为 Clojure 模式的 TAB 添加新功能



我知道TAB想在Emacs中变得聪明。 然而,它对我的口味来说还不够聪明。 而且因为它是"智能"的,所以扩展起来似乎很复杂。

我希望 Clojure 模式下的 TAB 完全按照它的行为行事,除了当我在 defn, defmacro 的第一个括号处时,等等,它位于第 0 列。

当它在那里时,我希望它从 hs 次要模式调用 hs 切换隐藏

然而,我正在疯狂地试图让它工作。

我首先尝试修改分配给 TAB 的快捷方式,以便仅在 Clojure 模式下时,它会首先调用我的函数,然后调用缩进 for-tab-命令,但更改 TAB 快捷方式似乎非常复杂。 由于Emacs已经计划了模式可以在lisp-indent-function中注册其TAB函数的情况,我希望修改clojure-indent-function,它说:

(defun clojure-indent-function (indent-point state)
  "This function is the normal value of the variable `lisp-indent-function'.

但是,此函数显然仅在光标位于函数内部时才调用。 当光标位于"("的第一个"("上时,则不会。

如何让 TAB 在 Clojure 模式下和指向括号上的第 0 列时调用hs-toggle-hiding

我不希望这影响组织模式或任何其他模式。 只是Clojure模式。

一般的答案是:

(eval-after-load 'clojure-mode
  '(define-key clojure-mode-map [tab] 'my-tab-command))

以及定义,如您所描述的:

(defun my-tab-command (&optional arg)
  (interactive "P")
  (if (and (zerop (current-column)) (eq (char-after) ?())
      (hs-toggle-hiding)
    (indent-for-tab-command arg)))
clojure-indent-function

lisp-indent-function的实现,它不应该缩进,而是计算缩进。它可以随时被任何对可能的缩进感兴趣的代码调用,所以我们当然不想将我们想要的 TAB 行为挂接到这个地方。

鉴于 TAB 的智能性可能不是您想要的,因此最好重新绑定TAB将我们的逻辑放在所有可能的智能之前:

(defun clojure-hs-tab (arg)
  (interactive "P")
  (if (and (<= (current-column) 1)
           (save-excursion
             (beginning-of-line)
             (looking-at "(")))
      (hs-toggle-hiding)
    (indent-for-tab-command arg)))
(define-key clojure-mode-map (kbd "TAB") 'clojure-hs-tab)    

我冒昧地修改了您的要求并允许第 1 列,因为这是HS切换隐藏后放置点的地方。您不想通过第二次 TAB 键取消隐藏吗?

下一个级别的"标签智能"是indent-line-function变量。这就是完成或缩进选项卡时调用的内容决心缩而不是完成。有一个强大的不在这里使用它的原因:indent-line-function可能被称为多次缩进区域。即使我们决定我们想要仅覆盖缩进和完成的缩进行为TAB,最好建议indent-for-tab-command(在全球范围内提供建议并检查major-mode只做我们想做的事在该模式下)。

最新更新