Clojure

结构化编辑

什么是结构化编辑?

文本编辑器将文件视为字符行。常见的功能包括:输入新字符,按行(上/下)或字符(右/左)导航,选择/复制/粘贴文本,删除或替换文本等。所有这些操作都在字符或行级别进行。

当我们检查 Clojure 代码时,我们会注意到它可以被视为嵌套形式集,其中每个嵌套级别都是一个具有开始和结束定界符的集合:( …​ )[ …​ ]{ …​ } 等。这种规律的结构形成了一棵树,结构化编辑是一套新的操作,用于在节点/树级别而不是字符/行级别操作我们的代码。

结构化编辑在 Lisp 语言编辑方面有着悠久的历史,与 Emacs 以及 Emacs paredit 模式最为密切相关。但这些思想比 Lisp 或 Emacs 更通用,实际上,在几乎所有为支持 Clojure 而设计的编辑器中都能找到结构化编辑。

与基于字符的编辑类似,结构化编辑也提供创建新形式、导航、选择、复制/粘贴、删除等方式,但所有这些都以嵌套表达式而不是字符或行来表示。本页面旨在向您介绍结构化编辑中的一些高级术语和概念,而不是涵盖任何特定的编辑器或键,因为具体细节因编辑器而异(并且通常也是可自定义的)。

入门时,重点记住一小部分命令(以下都已涵盖):kill、向前吸入、向前吐出、拼接和提升。当你遇到其他情况时,找到合适的结构化编辑命令并将其添加到你的工具箱中。

平衡形式

结构化编辑的一般原则是在任何时候都确保所有形式都是平衡的。这在你的代码中创建新形式时立即显而易见。如果你输入一个集合的起始定界符,你的编辑器也会插入结束定界符。如果你输入 (,你的编辑器会插入 (),并将你的光标放在中间,这样你就可以在形式内部继续输入。大多数编辑器还会提供一些视觉反馈,在你移动到它们时匹配开始和结束定界符,或者甚至可能根据这种结构支持代码折叠和展开。

你可能会遇到的一个常见问题(尤其是在学习期间)是意外使用破坏你的代码结构的行编辑命令。例如,如果你有一个多行嵌套表达式,从中间删除一行很可能会删除左括号,但不会删除后一行上的匹配右括号。不要惊慌!

一些修复这种情况的常见方法

  • 撤销 - 通常,你只需撤销该行命令,然后使用结构化编辑命令即可

  • 关闭结构化编辑,修复问题,然后重新启用结构化编辑 - 在一些编辑器中,页脚或其他位置有一个按钮可以切换结构化编辑,这比较容易,而在其他编辑器中则比较难。

  • 使用字符编辑命令进行修复 - 在某些情况下,例如要删除的悬空左括号,你可以选择左括号并使用字符删除来删除它(在结构化编辑之外)

  • 使用注释和字符编辑 - 如果你要关闭悬空的左括号,你可以插入一个 Clojure 注释 ;,这允许你键入 ),然后选择 ; 并使用字符编辑删除它

导航和选择

导航(以及选择,通常作为修饰符)是对你已经拥有的字符和行导航和选择的扩展。除了选择下一个单词之外,你还可以选择下一个表达式或通过选择包含的表达式(向上移动树)来扩展选择范围。并且不要忘记,如果你觉得更方便,你仍然可以使用鼠标来选择。

剪切/粘贴又称 kill/yank

在 Emacs 中,剪切文本称为 "kill",粘贴称为 "yank"。在 Emacs 中,kill 将剪切的文本块放入 "kill ring" 中,实际上是一个堆栈。默认情况下,"yank" 将文本粘贴到堆栈的顶部并将其从 kill ring 中删除。你的编辑器是否支持所有这些功能将取决于编辑器,但重要的是,当你查看键绑定时,"kill" 表示 "剪切"。

默认情况下,大多数结构化编辑器会从当前位置剪切到当前集合的末尾。大多数编辑器都有各种其他选项,但仅使用默认的 kill 和选择对于你大多数工作来说已经足够了。

吸入和吐出

"向前吸入" 命令将当前集合之后的表达式吸入集合中,作为最后一个项目。"向前吐出" 做相反的事情,将集合的最后一个项目移到当前集合之外,并在其之后。"向后吸入" 命令操作集合中的第一个元素,但它并不常见。

拼接和提升

一个常见的场景是将当前集合的内容拼接到父集合中。这样做时,可以选择在 "向后拼接杀" 之前或在 "向前拼接杀" 之后放置这些项目。你可能还想用光标处的元素的值来替换父元素,这被称为 "提升"。

Parinfer

几年前,一个名为 Parinfer 的 Paredit 新替代方案被开发出来。Parinfer 将缩进与嵌套相关联,因此你可以通过缩进代码来插入子表达式。许多编辑器支持 Parinfer 作为 Paredit 的替代方案。如果你刚接触结构化编辑,你应该尝试一下,看看它是否适合你!总的来说,这似乎是一个个人偏好的问题。

资源

以下资源可能对你有所帮助,作为学习 paredit 命令或如何在特定编辑器中使用结构化编辑的额外步骤。总的来说,大多数核心命令集是相似的,并且具有可配置的键绑定。通常,默认的键绑定可以追溯到 Emacs 中的 Paredit,但不要被它限制,自定义这些键绑定很常见。

原作者:Alex Miller