我编写了一个交互式函数,它将“点上方的字符”插入当前行。例如,给定一行包含“12345”后跟一行“abcdef”并且该点位于字母“c”,复制将使第二行变为“ab3cdef”。再次复制会使第二行变为“ab34cdef”。
我的功能失败(在Windows 7下使用GNU Emacs 23.3.1)第二次通过插入第一次调用的文本而不是正确推进来调用它。如果我在调用之间放置任何emacs“操作”,它就可以正常工作。 (例如,如果我执行复制,“向左箭头”,“向右箭头”,则复制它对两个调用都可以正常工作。)
这是我的功能:
(defun copy-down ()
"Grab the character in the line above and insert at the current location."
(interactive)
(let ((beg (progn (previous-line 1) (point)))
(end (progn (forward-char) (point))))
(backward-char)
(next-line 1)
(insert-buffer-substring (current-buffer) beg end)))
如果重要,我通常将我的功能绑定到一个键:(global-set-key [f5]'copy-down)
PS。我习惯在多年前切换到emacs之前使用的编辑器中使用此功能,我在GNU Emacs中想念它。 : - (
答案 0 :(得分:2)
你的工作对我来说很好。也就是说,previous-line
与其他设置(特别是goal-column
)有交互,通常在编写elisp时不应使用。相反,您应该使用(forward-line -1)
。但是,当然,您的代码依赖于goal-column
...您可以通过在没有其他配置的情况下运行Emacs来测试这一点,例如emacs -q
。
以下是您的代码略有不同的版本,不依赖于goal-column
:
(defun copy-down ()
"Grab the character in the line above and insert at the current location."
(interactive)
(let* ((col (current-column))
(to-insert (save-excursion
(forward-line -1)
(move-to-column col)
(buffer-substring-no-properties (point) (1+ (point))))))
(insert to-insert)))
如果问题不在于使用previous-line
,那么我认为我的代码不会产生太大的影响。
您拥有的另一个选择是尝试在调试器中运行它以查看代码中断的位置。将defun
内的点移动到copy-down
并输入 M-x edebug-defun ,下次运行它时,您将能够单步执行代码。可以找到edebug
的文档here。
答案 1 :(得分:0)
您需要使用let*
代替let
。前者允许您在同一语句中使用后面表单中的早期值。
编辑: 嘿,有人完全重新安排了你的功能!它现在可能会奏效。
答案 2 :(得分:0)
尝试
(defun copy-down (arg)
(interactive "p")
(let ((p (+ (current-column) (point-at-bol 0))))
(insert-buffer-substring (current-buffer) p (+ p arg))))
其附加功能是使用前缀参数来复制n(默认为1)个字符。