Emacs:为键绑定指定一个功能,重复按下后,撤消最后一次按下并在更宽的设置下重做

use*_*309 5 emacs elisp

这是我正在尝试做的更大的图景:

使用按键,它将在最里面的关闭/打开分隔符(括号,括号,括号,等等)之后/之前插入一个左右括号.

但是如果在之后立即按下它,它将撤消最后一次插入,找出下一个结束分隔符,并在之后放置,依此类推.

我有第一部分的工作版本,但我正在寻找第二部分的"最佳实践"(它撤消并向外移动)

作为一个激励因素和具体的例子,这是用Python编码的典型场景.我经常使用列表推导,并且经常构造列表,然后决定我要总结所有元素等等.所以我先输入:

[x*x for x in some_lst if is_prime(x)]
Run Code Online (Sandbox Code Playgroud)

然后我想用"sum"命令封装这个列表:

sum([x*x for x in some_lst if is_prime(x)])
Run Code Online (Sandbox Code Playgroud)

我不想继续将光标移动到开头和结尾只是为了插入括号.我宁愿在列表中找到要点,按一下键,让它找出分隔符,然后将标记放在开头插入的括号之前,这样我就可以输入"sum".我的下面的功能似乎工作(捎带在"扩展区域"包):

(defun add-paren ()
  (interactive)
  (er/mark-outside-pairs)
  (exchange-point-and-mark)
  (insert-string ")")
  (exchange-point-and-mark)
  (insert-string "(")
  (left-char 1)
  )
Run Code Online (Sandbox Code Playgroud)

第二步的最佳做法是什么?

(对上述内容的任何建议/改进也将不胜感激.这是我在Elisp中的第一个"真实"功能.)

谢谢.

更新:感谢大家的提示.我可能会在最终解决方案中使用其中一些.我的原始问题仍然存在:是否存在"大规模撤消和重做"的标准模式,或者每个问题都有自己的自定义解决方案?假设我smartparens按照建议使用在一次击键中完成所有操作,但我希望它在第3级出现.我想要的是按下击键3次并将括号放在那里.

所以在第一次击键后,它将括号放在最里面.再次按下它应该删除插入的括号,并将它们放在下一级,依此类推......

(顺便说一句,不要试图重新发明轮子.我怀疑列出的一些软件包可能正是我需要的 - 我只想在Elisp中练习编码).

更新2: 我想这没有最好的做法?无论如何,我用expand-region和解决了这个问题smartparens:

(defun add-paren ()
  (interactive)
  (if (eq last-command 'add-paren)
      ;; (message "AAAA")
      (delete-paren)
    )
  (setq currpoint (point))
  (er/mark-outside-pairs)
  (if (eq currpoint (point))
      (er/mark-outside-pairs)
    )
  (sp-wrap-with-pair "(")
  (left-char 1)
)

(global-set-key (kbd "<f5>") 'add-paren)

(defun delete-paren ()
  (interactive)
  (setq currloc (point))
  (sp-unwrap-sexp)
  (goto-char currloc)
  (left-char 1)
)
Run Code Online (Sandbox Code Playgroud)

use*_*309 1

我想这没有最佳实践吗?无论如何,我使用 Expand-Region 和 smartparens 解决了这个问题:

(defun add-paren ()
  (interactive)
  (if (eq last-command 'add-paren)
      ;; (message "AAAA")
      (delete-paren)
    )
  (setq currpoint (point))
  (er/mark-outside-pairs)
  (if (eq currpoint (point))
      (er/mark-outside-pairs)
    )
  (sp-wrap-with-pair "(")
  (left-char 1)
)

(global-set-key (kbd "<f5>") 'add-paren)

(defun delete-paren ()
  (interactive)
  (setq currloc (point))
  (sp-unwrap-sexp)
  (goto-char currloc)
  (left-char 1)
)
Run Code Online (Sandbox Code Playgroud)