在 Evil-mode Emacs 中组合两个运算符

在 Evil-mode Emacs 中组合两个运算符

在 vim 中,我将可视模式下的>和分别重新映射到和,如下所示:<>gv<gv

vnoremap > >gv
vnoremap < <gv

由于我针对这个问题的问题是熟悉 emacs 而不是 vim 的人,所以>和的<作用是缩进/去缩进可视选择的文本。和的作用gv是重新选择之前选择的文本。这些映射导致><缩进/去缩进,然后重新选择之前选择的文本。

我正在尝试使用 evil-mode 的 emacs,我想做同样的事情,但我遇到了一些困难,不知道如何才能实现自动重新选择。

看起来我需要以某种方式按顺序调用evil-shift-rightevil-visual-restore,但我不知道如何创建一个可以同时执行这两项操作的映射,因此我尝试创建自己的函数,该函数将按顺序调用两者并进行映射,但是它不起作用,可能是因为它们两者都不是作为带有的函数defun而是作为带有的运算符定义的evil-define-operator

我尝试创建自己的运算符:

(evil-define-operator shift-left-reselect (beg end)
    (evil-shift-left beg end)
    (evil-visual-restore))

(evil-define-operator shift-right-reselect (beg end)
    (evil-shift-right beg end)
    (evil-visual-restore))

但这并没有像预期的那样恢复视觉效果。我摸索了一下,得到了这个:

(evil-define-operator shift-left-reselect (beg end)
    (evil-shift-left beg end)
    ('evil-visual-restore))

(evil-define-operator shift-right-reselect (beg end)
    (evil-shift-right beg end)
    ('evil-visual-restore))

但每当需要重新选择时,都会选择一条额外的线路。

目前我一直在使用以下方法,它只存在在<操作员中重新选择附加行的问题。

(evil-define-operator shift-right-reselect (beg end)
  (evil-shift-right beg end)
  (evil-visual-make-selection beg end))

(evil-define-operator shift-left-reselect (beg end)
  (evil-shift-left beg end)
  (evil-visual-make-selection beg end))

我把它们绘制成了地图:

(define-key evil-visual-state-map ">" 'shift-right-reselect)
(define-key evil-visual-state-map "<" 'shift-left-reselect)

如能得到任何帮助/指点/提示我将非常感激。

提前致谢。

编辑:

我希望能够基本上做到这一点:

(define-key evil-visual-state-map ">" (kbd ">gv"))
(define-key evil-visual-state-map "<" (kbd "<gv"))

但由于没有默认映射><递归映射的想法没有任何意义,并且这具有您对此类映射所期望的所有问题。但是,下面的方法可以工作,但它很丑陋,因为它需要添加两个丢弃的映射。有什么方法可以避免这样做吗?

(define-key evil-visual-state-map "g>" 'evil-shift-right)
(define-key evil-visual-state-map "g<" 'evil-shift-left)
(define-key evil-visual-state-map ">" (kbd "g>gv"))
(define-key evil-visual-state-map "<" (kbd "g<gv"))

如果时间足够长,我会接受这个问题,创建一个答案,并接受它,以便其他发现这个问题的人可以轻松地找到/使用它。

答案1

evil-shift-right命令需要一个开始和结束参数,并且要求开始参数小于结束参数。实现此目的的一种方法如下:

(define-key evil-visual-state-map ">" (lambda ()
    (interactive)
    ; ensure mark is less than point
    (when (> (mark) (point)) 
        (exchange-point-and-mark)
    )
    (evil-normal-state)
    (evil-shift-right (mark) (point))
    (evil-visual-restore) ; re-select last visual-mode selection
))

(define-key evil-visual-state-map "<" (lambda ()
    (interactive)
    ; ensure mark is less than point
    (when (> (mark) (point)) 
        (exchange-point-and-mark)
    )
    (evil-normal-state)
    (evil-shift-left (mark) (point))
    (evil-visual-restore) ; re-select last visual-mode selection
))

答案2

我最终使用了以下内容:

(define-key evil-visual-state-map (kbd "<") (lambda ()
  (interactive)
  (evil-shift-left (region-beginning) (region-end))
  (evil-normal-state)
  (evil-visual-restore)))
(define-key evil-visual-state-map (kbd ">") (lambda ()
  (interactive)
  (evil-shift-right (region-beginning) (region-end))
  (evil-normal-state)
  (evil-visual-restore)))

相关内容