我想像expand-region一样,再选择字符的时候临时使用一套案件绑定,比如y -> kill-ring-save
。
具体实现比较头疼,expand-region有明确的启动函数,只要在那个函数里设置就好了。普适性再region-active的时候启动临时transient-map的要怎么搞呢?
给push-mark
加advise吗?有没有更好的方法?
我想像expand-region一样,再选择字符的时候临时使用一套案件绑定,比如y -> kill-ring-save
。
具体实现比较头疼,expand-region有明确的启动函数,只要在那个函数里设置就好了。普适性再region-active的时候启动临时transient-map的要怎么搞呢?
给push-mark
加advise吗?有没有更好的方法?
给set mark加吧 用Emacs加advice是家常便饭
可以给某个region设置key map,比如macrostep就会在expand出来的部分加map,buffer里其他部分不受影响
或许可以试试 activate-mark-hook
(defun activate-mark-hook@set-transient-map ()
(set-transient-map
(let ((map (make-sparse-keymap)))
(define-key map "n" #'next-line)
(define-key map "p" #'previous-line)
(define-key map "q" #'keyboard-quit)
(define-key map "y" (lambda (b e)
(interactive "r")
(kill-new (buffer-substring b e))
(message "Region saved")))
map)
#'region-active-p))
(add-hook 'activate-mark-hook #'activate-mark-hook@set-transient-map)
;; 卸载
;; (remove-hook 'activate-mark-hook activate-mark-hook@set-transient-map)
注意上面没有直接绑定你提到的 kill-ring-save
,因为这个命令会取消选中区域。
另外也可以考虑下 Hydra,它有一套专门的方案。具体怎么实现不清楚,我几乎没怎么用过 expand-region 和 Hydra。
是这样,但是我觉得的这个方法要求有一个明确的启动函数,我想我的设置能零修改适用所有场景。
@xuchunyang 我现在有个问题……
我把y绑定到kill-ring-save
(把Y绑定到你的自制函数)。但是还是有一点问题。我每次按y(或者其他命令)以后 transient map 还会起效。一开始我发现kill-region
以后region-active-p
还会返回t
,所以我吧kill-ring-save
改成(lambda (beg end) (interactive "r") (kill-ring-save beg end) (deactivate-mark t))
,然而还是不行。之后我试了其他命令比如keyboard-quit
,结果是一样的,执行以后transient map没有失效,依然可以激活绑定的命令。
测试代码:
(defun activate-mark-hook@set-transient-map ()
(set-transient-map
(let ((map (make-sparse-keymap)))
(define-key map "y" (lambda (beg end) (interactive "r") (kill-ring-save beg end) (deactivate-mark t)))
(define-key map "i" (lambda () (interactive) (message "OMG region-activate-p is %s" (prin1-to-string (region-active-p)))))
map)
#'region-active-p))
(add-hook 'activate-mark-hook #'activate-mark-hook@set-transient-map)
按y后再按i,lambda函数会运行。
P.S. 我把(lambda () (print (region-active-p))
绑定到post-command-hook
,按y运行我的加强版kill-ring-save
和其他命令后打印出来的是nil
。你可以试试:
(add-hook 'post-command-hook (lambda () (print (region-active-p)))
上个月解决了我楼上说的那个问题,今天想起来贴出来:
(我在stackvoerflow上看到的解决办法,具体链接我忘了……)
一个有意思的地方:用这个方法我可以把复制和粘贴绑定到一个按键上(C-y
),非常实用。
(defconst angel-transient-mode-map-alist
`((mark-active
,@(let ((map (make-sparse-keymap)))
;; operations
(define-key map "p" (lambda (b e)
(interactive "r") (delete-region b e) (yank)))
(define-key map (kbd "M-p") #'counsel-yank-pop)
(define-key map "x" #'exchange-point-and-mark)
(define-key map ";" #'comment-dwim)
(define-key map "y" #'kill-ring-save)
(define-key map (kbd "C-y") #'kill-ring-save)
(define-key map "Y" (lambda
(b e)
(interactive "r")
(kill-new (buffer-substring b e))
(message "Region saved")))
;; isolate
(define-key map "s" #'isolate-quick-add)
(define-key map "S" #'isolate-long-add)
(define-key map "d" #'isolate-quick-delete)
(define-key map "D" #'isolate-long-delete)
(define-key map "c" #'isolate-quick-change)
(define-key map "C" #'isolate-long-change)
;; mark things
(define-key map "f" #'er/mark-defun)
(define-key map "w" #'er/mark-word)
(define-key map "W" #'er/mark-symbol)
(define-key map "P" #'mark-paragraph)
;; inner & outer
;; (define-key map "C-i" inner-map)
;; (define-key map "C-a" outer-map)
;; (define-key inner-map "q" #'er/mark-inside-quotes)
;; (define-key outer-map "q" #'er/mark-outside-quotes)
;; (define-key inner-map "b" #'er/mark-inside-pairs)
;; (define-key outer-map "b" #'er/mark-outside-pairs)
(define-key map "q" #'er/mark-inside-quotes)
(define-key map "b" #'er/mark-inside-pairs)
;; expand-region
(define-key map (kbd "C--") #'er/contract-region)
(define-key map (kbd "C-=") #'er/expand-region)
map))))
(add-to-list 'emulation-mode-map-alists
'angel-transient-mode-map-alist t)
大师的最新配置
;;; Transient map in region (y p)
;; Unlike `emulation-mode-map-alists', luna-def-key allows more
;; flexibility for the predicate.
(luna-def-key
:when (lambda ()
(and mark-active (not (derived-mode-p 'magit-status-mode))))
:keymaps 'override
"p" '("override-paste" . (lambda (b e)
(interactive "r")
(delete-region b e) (yank)))
"x" #'exchange-point-and-mark
";" #'comment-dwim
"y" #'kill-ring-save
"C-y" #'kill-ring-save
"Y" '("copy-&-keep-region" .
(lambda
(b e)
(interactive "r")
(kill-new (buffer-substring b e))
(message "Region saved")))
"r" #'query-replace+
"R" #'query-replace+delete)