如何在elisp中设置标记并进行班次选择?


9

Emacs在瞬态标记模式处于活动状态时的正常行为是,当您进行换档选择时,如果下一个命令是非换档运动,则会取消激活该标记。例如,在命令M-l(用下面的功能标记当前行)和之后C-f,该标记被禁用。之后如何模仿elisp的行为(set-mark-command nil)

例如:

(defun my-mark-current-line ()
  (interactive)
  (beginning-of-line)
  (set-mark-command nil)
  (end-of-line)
  (forward-char))

(global-set-key (kbd "M-l") 'my-mark-current-line)

现在做M1 Cf,区域将增长,但是,我希望使用默认行为,即在Cf时停用区域,并随CSf一起增长。

编辑:应该使用与set-mark-command不同的功能来允许此操作吗?我找不到。


我相信这是不可能的(我可能是错的)。只要区域处于活动状态,导航命令就会更改选择。使用进行移位选择C-S-f类似于C-SPC(激活区域)+ C-f(导航)。您可以通过绑定C-f 到包装器函数来获得所需的信息,该包装器函数首先将激活的区域取消激活,然后继续执行C-fforward-char);并C-S-f直接绑定到forward-char。请注意,如果你使用emacs的终端模式,C-fC-S-f都将表现为C-f作为终端无法区分这两个。
Kaushal Modi

同样,您所做的包装和绑定也C-f将应用于您使用的所有其他导航命令。
Kaushal Modi

C-f之后的btw M-l不会扩展该区域,因为的末尾没有活动区域M-ldowncase-word默认情况下绑定到该区域)。
Kaushal Modi

1
@KaushalModi我认为M-lOP 所引用的不是默认绑定(downcase-word),而是my-mark-current-line
nispio

确实是@nispio。
mikl

Answers:


8

由于移位转换和标记的临时激活是由命令循环处理的,因此您将需要调用移动功能的交互式版本,以便从它们中获取适当的移位选择行为:

;; (source: http://emacs.stackexchange.com/a/22166/93)
(defun my-mark-current-line ()
  (interactive)
  (beginning-of-line)
  (setq this-command-keys-shift-translated t)
  (call-interactively 'end-of-line)
  (call-interactively 'forward-char))

(global-set-key (kbd "M-l") 'my-mark-current-line)

更新:

自编写上述答案以来,我花了一些时间来了解有关换挡选择真正如何工作的更多信息。它将的符号值设置transient-mark-mode为形式的cons单元(only . OLDVAL),其中OLDVAL是移位选择之前的值。

下面的解决方案call-interactively通过根据需要激活标记并设置的适当值来避免使用transient-mark-mode。基本上,我认为此解决方案比第一个解决方案要小。

作为奖励,它现在具有可选的重复计数,并且如果标记已处于活动状态,它将在任一方向上扩展当前选择。

;; (source: http://emacs.stackexchange.com/a/22166/93)
(defun my-mark-current-line (&optional arg)
  "Uses shift selection to select the current line.
When there is an existing shift selection, extends the selection
in the appropriate direction to include current line."
  (interactive "p")
  (let ((oldval (or (cdr-safe transient-mark-mode) transient-mark-mode))
        (backwards (and mark-active (> (mark) (point))))
        (beg (and mark-active (mark-marker))))
    (unless beg
      (if backwards (end-of-line) (beginning-of-line))
      (setq beg (point-marker)))
    (if backwards (end-of-line (- 1 arg)) (beginning-of-line (+ 1 arg)))
    (unless mark-active
      (push-mark beg nil t))
    (setq transient-mark-mode (cons 'only oldval))))

1
两者都能正常工作,旧的东西非常有用!非常感谢!
mikl '16
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.