我为一个区域编写了一个简单的defun,即使没有区域我想要应用它 - 也就是说它根本没有选择。我以为我可以做以下事情:
(defun region-study (strt end)
(interactive "r")
(if (= strt end)
(progn ....) ;; then
(progn ....))) ;; else
但它不起作用。事实证明,当您在没有区域的情况下调用(interactive "r")
时,它不仅仅将边界设置为相等。试试这个:
(defun region-study (strt end)
(interactive "r")
(message "strt=%d; end=%d" strt end))
所以我的问题是:“如何编写一个对区域起作用的defun,但如果没有区域则作用于点?”
修改
所以我想把选择放在括号中或只是插入括号和(backward-char 1)
。这是一个解决方案:
(defun put-in-lft-rit (lft rit)
(interactive "k")
(if (use-region-p) ;; act on region
(progn
(setq pP (point))
(setq strt (region-beginning))
(setq end (region-end))
(setq meat (buffer-substring-no-properties strt end))
(setq news (concat lft meat rit))
(delete-region strt end)
(goto-char strt)
(insert news)
(if (= pP strt)
(goto-char strt) ; then
(goto-char (+ end 1)))) ; else
(progn ;; act on point
(insert lft rit)
(backward-char 1))))
(defun bk-put-in-braces ()
(interactive)
(put-in-lft-rit "(" ")"))
(defun bk-put-in-curly-braces ()
(interactive)
(put-in-lft-rit "{" "}"))
(defun bk-put-in-quotes ()
(interactive)
(put-in-lft-rit "'" "'"))
(defun bk-put-in-double-quotes ()
(interactive)
(put-in-lft-rit "\"" "\""))
(defun bk-put-in-square-brackes ()
(interactive)
(put-in-lft-rit "[" "]"))
然后你绑定.emacs:
(global-set-key (kbd "C-<f9>") 'bk-put-in-square-brackes)
(global-set-key (kbd "<f9>") 'bk-put-in-curly-braces)
(global-set-key (kbd "S-<f7>") 'bk-put-in-quotes)
(global-set-key (kbd "S-<f8>") 'bk-put-in-double-quotes)
(global-set-key (kbd "S-<f9>") 'bk-put-in-braces)
就是这样!应该在所有模式下工作。
EDIT2 :
@phils 谢谢。你是完全正确的。但有一点 - 我的代码还有一个额外的功能,即将点留在区域的开头或结尾 - 取决于它在选择中的位置。这是您添加此功能的代码:
(defun put-in-lft-rit (lft rit)
(interactive "k")
(if (use-region-p) ;; act on region
(let ((strt (region-beginning))
(end (region-end))
(pP (point)))
(save-excursion
(goto-char end)
(insert rit)
(goto-char strt)
(insert lft))
(if (= pP strt)
(goto-char strt) ; then
(goto-char (+ end 1)))) ; else
(progn ;; act on point
(insert lft rit)
(backward-char 1))))
答案 0 :(得分:8)
关于你的解决方案的几点说明......
避免不必要的全局范围setq
是一种好习惯。请改用(let)
来定义变量的临时范围。
你做的工作比要求多得多。而不是复制区域,将该副本和分隔符连接成“新闻”变量,删除该区域,然后插入“新闻”,您需要做的就是在区域的开头和结尾插入分隔符字符。 / p>
(一般来说,如果你在编写elisp时尝试“像编辑器一样思考”,并专注于操纵缓冲区而不是变量,那么通常会使用更高效的代码。)
save-excursion
非常有用(以及其他几种save-
和with-
表单)。
(defun put-in-lft-rit (lft rit)
(interactive "k")
(if (use-region-p) ;; act on region
(let ((strt (region-beginning))
(end (region-end)))
(save-excursion
(goto-char end)
(insert rit)
(goto-char strt)
(insert lft)))
(progn ;; act on point
(insert lft rit)
(backward-char 1))))
答案 1 :(得分:6)
use-region-p
如果您的函数应该在该区域而不是某个点上执行,则应返回t
。
答案 2 :(得分:2)
您可能希望使用在thingatpt + .el
中定义的区域或单词功能。