在Vim for Common Lisp中自定义自动格式化/自动缩进的最佳方法

wb1gzix0  于 2022-11-11  发布在  其他
关注(0)|答案(4)|浏览(123)

我想知道在Vim for Common Lisp中自定义自动格式化/自动缩进的最佳方法。
自动格式化(我通常通过在命令模式下每行输入'=='来完成)对于vim中的基本lisp语言(例如defmacro、defun、lambda、if、with-output-to-string)非常有效,但是每当定义新的语言结构(例如使用宏)时,我发现新结构的格式通常不是我希望的那样。
例如,下面是vim如何格式化'when(标准lisp结构)和'awhen('when的常用回指形式;不是lisp标准的一部分)

(when 'this
  (process 'this))

(awhen 'this
       (process it))

我想用“awhen”自动格式化为“when”。有什么想法吗?
编辑:感谢Gilligan和Tamas对Slimv的推荐。作为测试,我下载了MacVim(将需要它与终端vim一起工作,但这是一个不同的问题)和slimv,将slimv下载到~/.vim中,启动MacVim,并加载了一个.lisp文件。
然后,我启动了lisp服务器(通过MacVim的GUI完成),它加载了我的默认lisp可执行文件和核心文件。

  • 由于我的核心文件已经加载了我常用的语言扩展(a当是其中之一时),a当格式正确时,开箱即用。

我真的很喜欢这个解决方案。不用[1]学习如何告诉vim正确地缩进特定的函数,[2]为我定义的每个语言扩展显式地编写代码,[3]每次添加新的语言结构时都更新代码。相反,我利用slimv来为我做格式化。而且slimv可以“学习”新的语言扩展。只要这些宏已经被加载到服务器会话正在使用的lisp核心中。
我发现这对于特定的语言扩展类很有效。通常是定义为宏的扩展,使用&body关键字。这似乎在大多数情况下都是正确的,但是我使用的宏仍然不能正确地自动格式化。尽管我想说这更可能是宏的编写方式(非标准语言扩展)的问题,而不是其他问题。
所以,这个解决方案对我来说在大多数情况下都很好用,而且我不需要编码(和维护)任何东西。

g52tjvyc

g52tjvyc1#

这可能不是一个直接回答你的问题,但我强烈建议你安装slimv插件:http://www.vim.org/scripts/script.php?script_id=2531
这是一个很棒的插件,它将SLIME功能集成到vim中,除了许多其他的东西之外,它还为clisp和clojure提供了一个改进的缩进。

qjp7pelc

qjp7pelc2#

对于那些正在寻找这个主题,但不想运行Slimv的人,因为他们不使用Common Lisp或其他原因,这里有一个独家新闻。
Vim的Lisp缩进与其他语言的缩进不同;它有一个特殊的“Lisp模式”。这个模式是由

:set lisp

这是针对.lisp文件自动完成的。Lisp模式不是Vim的发明;经典的Vi实现使用:set lisp打开Lisp模式(不幸的是,POSIX没有描述它)。
Vim的Lisp模式有一个简单的机制来识别需要操作符样式缩进的表单:也就是说,存在一个称为lispwords的参数,它保存一个逗号分隔的标识符列表。
你可以向自己证明这就是所使用的标识符列表,即使你在编辑一个Common Lisp .lisp文件时使用了语法高亮等功能。简单地执行:set listwords[TAB]并编辑列表,从列表中删除一些内容,例如defun。然后尝试重新标识一个defun:您将看到函数样式的缩进而不是操作符样式的缩进。
对Common Lisp的语法突出显示支持与Lisp模式的lispwords参数是分开的;它有自己的标识符列表。例如,在Vim 7.3中,如果输入以下内容:

(symbol-macrolet ((foo bar))
                 you get indented out to here!)

尽管symbol-macrolet被识别并着色了,但这是为什么?因为symbol-macrolet没有出现在相当少的lispwords列表中,而它 * 确实 * 出现在lisp.vim语法突出显示定义文件中。
结果是,您可以将一些脚本组合在一起,这些脚本扫描您的.lisp文件目录以查找宏,并生成一个set lispwords=...命令,该命令被放置在.vimrc目录中。
或者,如果您正在处理一个自定义Lisp方言,则可以在加载时使其Vim语法高亮文件自定义lispwords

以下是一个实施疏忽:lispwords选项没有本地值;您不能使用setlocal lispwords ...为它指定特定于缓冲区的值。换句话说,看来(至少在我在Ubuntu下使用的Vim 7.3中)你不能打开两个或更多的缓冲区来存放不同的Lisp方言,这些方言带有不同的缩进标识符。“一刀切”的解决方案。

m528fe3b

m528fe3b3#

如果您的文件类型是“lisp”,那么我认为您需要在“/vim 7 x/indent”目录下的“lisp.vim”文件中添加特殊情况下的缩进规则。您可以在:h indent-expr:h indentexpr的帮助中找到更多信息。
也许有人能告诉你更好的,但我相信默认的lisp.vim indent文件基本上什么也不做,因为内置函数lispindent()被用来获取indent值。
(1)将用于获取缩进值(即indentexpr)的函数设置为您自己的indent/lisp.vim文件中的函数,例如GetLispIndent()。
(2)在你的GetLispIndent()函数中,你将使用lispindent()来获取所有行的缩进值,除了你的特殊情况。2查看其他语言的缩进文件和阅读文档来了解indentexpr是如何工作的,例如java. vim。

umuewwlo

umuewwlo4#

@Kaz的答案是完全正确的,但是他们并没有完全回答原来的问题。当lispwords中的任何单词出现在S表达式的开头时,Vim会改变S表达式的缩进方式。换句话说,它定义了OP引用的“标准lisp结构”。如果你查看当前的lispwords配置,你会看到“when”被包含,而“awhen”没有,结果如下:

(when 'this
  (process 'this))

(awhen 'this
       (process it))

要解决这个问题,只需在config中的某个位置将“awhen”添加到config字符串中,如下所示:

set lispwords+=awhen,

结尾的逗号并不是绝对必要的,但是默认值包含了它,如果你或其他插件修改器在其他地方使用它,这可能是明智的。

(when 'this
  (process 'this))

(awhen 'this
  (process it))

(在我当前安装的Vim 9.0上测试)
注意,正如@Kaz指出的,这个配置字符串是通用的,所以如果你有不同方言的lisp,它们的缩进都将由这个设置来控制。Vim在自动检测lisp方面相当不错,但是如果它不能识别你的文件类型或方言,你可能需要:set lisp

相关问题