【问题标题】:Emacs equivalent of Vim's yy10p?Emacs 相当于 Vim 的 yy10p?
【发布时间】:2008-09-16 13:06:39
【问题描述】:

如何在 Emacs 中轻松复制一行 10 次?我找不到复制行快捷方式或功能。我可以使用 C-aC-spcC-eM-w 费力地复制该行,但我怎样才能将其粘贴多次?

在我编写自己的函数之前的任何想法。

【问题讨论】:

    标签: emacs editor shortcut


    【解决方案1】:

    您可以为此使用键盘宏:-

    C-a C-k C-x ( C-y C-j C-x ) C-u 9 C-x e

    说明:-

    • C-a : 转到行首
    • C-k : 杀戮线
    • C-x ( : 开始录制键盘宏
    • C-y : Yank 杀线
    • C-j : 移到下一行
    • C-x ) : 停止录制键盘宏
    • C-u 9 : 重复 9 次
    • C-x e : 执行键盘宏

    【讨论】:

    • 请注意,自从 Emacs 22.1 发布以来,您实际上可以使用 <C-S-backspace>,它运行 kill-whole-line,相当于 vi 中的 dd。因此,每当您发现自己在做C-a C-k C-k 时,您只需<C-S-backspace>
    • 以上工作正常,但在 Emacs 25 中仅供参考(可能还有更早的版本?)而不是 C-x (C-x ) 您可以分别键入 F3F4 键。 See emacs manual for more info
    【解决方案2】:

    复制

    如果您经常使用线条,您可能希望在未选择区域时对线条进行复制 (kill-ring-save) 和剪切 (kill-region):

    (defadvice kill-ring-save (before slickcopy activate compile)
      "When called interactively with no active region, copy a single line instead."
      (interactive
       (if mark-active (list (region-beginning) (region-end))
         (list (line-beginning-position)
               (line-beginning-position 2)))))
    (defadvice kill-region (before slickcut activate compile)
      "When called interactively with no active region, kill a single line instead."
      (interactive
       (if mark-active (list (region-beginning) (region-end))
         (list (line-beginning-position)
               (line-beginning-position 2)))))
    

    然后你可以只用 M-w 复制该行。

    粘贴

    通常前缀参数只是多次执行一个动作,所以你希望 C-u 10 C-y 起作用,但在这种情况下 C-y 使用它的参数来表示要“拉”(粘贴)的 kill-ring 的哪个元素。我能想到的唯一解决方案是 kronoz 所说的:用 C-x ( C-y C-x ) 记录一个宏,然后让 C-u 的参数转到 kmacro-end-and-call-macro ( 那是 C-u 9 C-x e 甚至只是 C-9 C-x e 或 M -9 C-x e)。

    另一种方式: 您也可以留在M-x viper-mode 并使用 yy10p :)

    【讨论】:

    【解决方案3】:

    您可能知道这一点,但是对于 许多 命令,“C-u 10”前缀就可以解决问题。不幸的是,对于 C-y yank 命令,“C-u”被重新定义为“返回杀伤环中的那么多物品,然后猛拉该物品”。

    我认为您可以将复制注册和插入注册命令与 C-u 前缀命令一起使用,但显然这也不起作用。

    还有 C-x z,“重复上一个命令”似乎对 C-u 免疫。

    另一个想法是使用 M-: 来获得 Eval 提示并输入一些 elisp。我认为像 (dotimes '10 'yank) 这样的东西可能会这样做,但似乎没有。

    所以看起来在宏上使用 C-u 可能确实是你能做的最好的事情,而不是编写自己的小函数。

    如果我投票,我会投票给 kronoz 答案。

    【讨论】:

    • I 秒 C-u(最小字符限制欺骗)。
    【解决方案4】:

    在此示例中,您不需要同时使用 C-x ) 和 C-x e。

    您可以直接将重复参数直接提供给 C-x )。这将停止录制并在一个步骤中重复宏。或者您可以跳过 C-x ) 并直接转到 C-x e,因为 C-x e 将在重复之前结束录制。

    选择哪种方式取决于您希望重复计数的工作方式。对于 C-x )你说你总共想要多少次重复(在这种情况下是 10 次)。对于 C-x e,您需要说明还剩下多少重复(即 9)。


    C-a C-k C-k 也会杀死尾随的换行符,所以你以后不必自己放回去。它比使用标记更快,并且不需要您更改任何变量。

    更好的是(除非你在终端中),你可以使用 C-S-Backspace* 来杀死整行,无论你在哪里。

    [* 如果您使用的是 X windows,请确保输入 shift(not alt),否则您可能会终止会话!]

    说到终端,如果您发现无法键入 C-9,M-9 是一个不错的选择。


    在 Emacs 22 及更高版本中,默认情况下 F3 启动一个宏,F4 结束/重复一个宏。您只需按 F3 开始录制,完成后按 F4,然后再次按 F4 重复宏。 (F4 也接受一个参数。)


    将这些放在一起,得到当前行的 10 个副本:

    • C-S-Backspace : 终止这一行
    • F3 : 启动宏
    • C-y : 拉线
    • C-1 C-0 F4 : 10 次猛拉

    不像y y 10 p那么短,但非常接近。 :)

    【讨论】:

      【解决方案5】:

      这是我从 Emacs 的 OS/2 端口获取的函数。 (是的,我使用 Emacs 已经有一段时间了。)

      ;; Author: Eberhard Mattes <mattes@azu.informatik.uni-stuttgart.de>
      (defun emx-dup-line (arg)
        "Duplicate current line.
      Set mark to the beginning of the new line.
      With argument, do this that many times."
        (interactive "*p")
        (setq last-command 'identity) ; Don't append to kill ring
        (let ((s (point)))
          (beginning-of-line)
          (let ((b (point)))
            (forward-line)
            (if (not (eq (preceding-char) ?\n)) (insert ?\n))
            (copy-region-as-kill b (point))
          (while (> arg 0)
            (yank)
            (setq arg (1- arg)))
          (goto-char s))))
      

      我已经绑定到 F9 d:

      (global-set-key [f9 ?d]    'emx-dup-line)
      

      然后我会使用 C-u 10 F9 d 将一行复制 10 次。

      【讨论】:

        【解决方案6】:

        我知道重复任意命令的唯一方法是使用键盘宏的“按参数重复”功能。

        C-a C-空格向下 M-w C-x ( C-y C-x ) C-9 C-x e

        • C-a : 转到行首
        • C 空间:设置标记
        • down : 转到下一行的开头
        • M-w : 复制区域
        • C-x ( : 启动键盘宏
        • C-y : Yank 复制行
        • C-x ) : 结束键盘宏
        • C-9 C-x e : 执行键盘宏九次。

        与 vim 相比,这有点弱。但这只是因为 vim 在这类事情上的效率惊人。

        如果您真的很喜欢模态 vi 类交互,您可以使用 vi 仿真模式之一,例如 viper 模式。查看在线 emacs 手册的“仿真”部分。

        【讨论】:

        • 嘿嘿,这是 8 次击键,而 10 次只是 C-y 十次。我保证我输入 C-y 的速度比我输入所有内容的速度快十倍。
        【解决方案7】:

        你会想要终止这条线:C-a C-k,然后是 C-y 或 ?

        【讨论】:

        • 呃..问题是如何做十次,而不是一次。
        【解决方案8】:

        我不知道直接等效(C-y 10 次是我所知道的最好的),但您可能对 Viper 感兴趣,它是 emacs 的 vi 仿真包。它是标准 emacs 发行版的一部分。

        【讨论】:

          【解决方案9】:

          根据 Baxissimo 的回答,我取消了这个:

          (defun yank-n-times (arg)
            "yank prefix-arg number of times. Not safe in any way."
            (interactive "*p")
            (dotimes 'arg (yank)))
          

          将其设置为某个键,使用前缀参数调用它,然后就可以使用了。

          edit(还修改了上面的交互调用,使其不那么糟糕)

          或者,这是一个可以替代 yank-pop 的版本:

          (defun yank-n-times (&optional arg)
            "yank prefix-arg number of times. Call yank-pop if last command was yank."
            (interactive "*p")
            (if (or (string= last-command "yank")
                (string= last-command "yank-pop"))
                (yank-pop arg)
              (if (> arg 1)
              (dotimes 'arg (yank))
                (message "Previous arg was not a yank, and called without a prefix."))))
          

          这个消息有点像谎言,但无论如何你都不应该在没有大于 1 的前缀的情况下调用它,所以。

          不确定这是否是个好主意,但我用这个替换了 M-y,我会看看结果如何。

          【讨论】:

            【解决方案10】:

            你用 C-k 得到该行,用 C-u 10 使下一个命令发生十次,然后用 C-y 粘贴该行。很简单。

            如果你总是希望 C-k 做整行,你可以将 kill-whole-line 设置为 t。不用再摆弄 C-a 或 C-e。

            你可以用花哨的杀戮环、寄存器和宏做很多事情,我鼓励你学习它们,但拉线十次并不一定很难或奇怪。

            【讨论】:

            • 不错的猜测,但你真的尝试过吗? C-u 前缀命令在与 C-y 组合使用时从杀伤环中选择要拉出的元素。它不会重复该命令 10 次。
            猜你喜欢
            • 1970-01-01
            • 2010-12-03
            • 2010-10-01
            • 1970-01-01
            • 2010-09-27
            • 1970-01-01
            • 2010-11-29
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多