有方言意识的s-表达式缩进器
yasi的Python项目详细描述
yasi-又一个s表达式缩进器
- 简介
- 安装
- 功能
- 命令行参数
- 挂起缩进
- 定制
- 关于默认缩进
- Yasi不处理的内容
- 对Lispindent的修改
- 编辑集成
- Lispindent2问题
- lispindent2命令行 选项
简介
yasi是一个方言识别的s-表达式缩进器,它试图改进 多赖的压头 和vim的 内置压头。它可以处理 公共lisp , clojure , scheme 和 newlisp 代码及其独特的语法。
它主要是一个批处理模式的压头,灵感来自Dorai's lispindent.lisp 它首先用 python 编写,然后翻译成 newlisp
它的缩进方式非常接近于lispindent.lisp和 尝试遵循这些风格 指导原则在合理的情况下。
对于使用其他任何编辑器的程序员来说,它应该是最有用的 而emacs则为类似lisp的表单和 开箱即用的S-表达式。
我做这个是因为没有足够好的工具 可以缩进我从教程中复制/粘贴并运行的代码 从Lisp开始。
安装
来自PYPI:
pip install --upgrade yasi
功能
yasi的 缩进在很大程度上依赖于给出它的正则表达式 与对应的lispindent.lisp相比的边。其功能包括:
- 支持不同的主流语言 根据方言的正确缩进 语法/语义。例如, do 关键字是一个循环构造 在 common lisp 中,在 clojure 中执行顺序。关键词 在两种方言中应该是这样的:
;; In Common Lisp(do((j0(+j1)))(nil);Do forever.(formatt"~%Input ~D:"j)(let((item(read)))(if(nullitem)(return);Process items until NIL seen.(formatt"~&Output ~D: ~S"jitem))))
;; In Clojure(do(println "LOG: Computing...")(+ 11))
- 能够修剪无关的空白和压缩代码
- 对代码中可能出现的错误(如不匹配的括号)发出警告 和未闭合的字符串
- 用户定义宏的正确缩进
- 通过当前或中的配置文件支持其他关键字 主目录
- 正确缩进 flets 和 标签 即使在Emacs中也不会出现
- 从标准输入缩进
- python版本可以输出初始和 缩进代码
命令行参数
usage: yasi [-h] [-nc] [-nb] [-nm] [--diff] [-nw] [-nr] [--no-output] [-c] [-ne] [-o OUTPUT_FILE] [--tab TAB_SIZE] [--dialect DIALECT] [-v] [-suffix BACKUP_SUFFIX] [-bd BACKUP_DIR] [-is INDENT_SIZE] [-di DEFAULT_INDENT] [-ic] [-uni] [files [files ...]] Dialect-aware s-expression indenter positional arguments: files List of files to be indented. Will indent from standard input if no files are specified optional arguments: -h, --help show this help message and exit -nc, --no-compact, --nc Do not compact the code, just indent -nb, --no-backup, --nb Do not create a backup file even if --backup-dir is specified -nm, --no-modify, --nm Do not modify the file --diff, -diff Prints unified diff of the initial and final result -nw, --no-warning, --nw Do not display warnings -nr, --no-rc, --nr Ignore any rc files in the current or home folder --no-output, -no-output Suppress output of the indented code -c, --color, -color Display diff text in color -ne, --no-exit, --ne Instructs the program not to exit when a warning is raised. -o OUTPUT_FILE Path/name of output file --tab TAB_SIZE, -tab TAB_SIZE Indent with tabs using the specified tabwidth. A tab is assumed equal to 4 spaces by default when expanding the tabs in the input file --dialect DIALECT, -dialect DIALECT Use Scheme keywords -v, --version Prints script version -suffix BACKUP_SUFFIX, --suffix BACKUP_SUFFIX Backup file suffix -bd BACKUP_DIR, --backup-dir BACKUP_DIR, --bd BACKUP_DIR, -backup-dir BACKUP_DIR The directory where the backup file is to be written -is INDENT_SIZE, --indent-size INDENT_SIZE, --is INDENT_SIZE The number of spaces per indent -di DEFAULT_INDENT, --default-indent DEFAULT_INDENT, --di DEFAULT_INDENT The indent level to be used in case a function's argument is in the next line. Vim uses 2, the most common being 1. -ic, --indent-comments, --ic If true, comment lines will be indented possibly messing with any deliberate comment layout -uni, --uniform, -uniform, --uni Dictates whether the if-clause and else-clause of an if-likeblock should have the same indent level.
悬挂缩进
这是缩进的代码块与左边距不齐的地方。 Lispindent默认情况下会这样做,尽管它与 在Yasi实施。通过 获得效果–不紧凑 到剧本里去。下面是Lispindent和Yasi的悬挂凹痕 不同:
初始代码:
;; Comment(if(not(empty?macro-name))(push(listmacro-nameKEYWORD1)keyword-lst)nil)(if(not(empty?macro-name))(push(listmacro-nameKEYWORD1)keyword-lst)nil)(exit)
使用 调用文件上的yasi–不压缩 :
;; Comment(if(not(empty?macro-name))(push(listmacro-nameKEYWORD1)keyword-lst)nil)(if(not(empty?macro-name))(push(listmacro-nameKEYWORD1)keyword-lst)nil)(exit)
Lispindent是如何做到的(第一个块开头的空格数 定义文件中其余块的开始位置:
;; Comment(if(not(empty?macro-name))(push(listmacro-nameKEYWORD1)keyword-lst)nil)(if(not(empty?macro-name))(push(listmacro-nameKEYWORD1)keyword-lst)nil)(exit)
定制
定制的方式与Lispindent中的类似- 关键字与决定下一行的数字相关联 缩进水平。
附加关键字定义在 主文件夹中的当前工作目录。如果有 两个目录中的配置文件当前工作目录中的配置文件 首选目录。
典型的配置文件如下:
{"scheme":{"do":2,"if":2},"lisp":{"do":2,"if":2},"clojure":{"do":2,"if":2},"newlisp":{"do":2,"if":2}}
数字如下所述(假设标准压痕尺寸为2 空间):
- 0 -将关键字与零关联会将其转换为普通关键字 函数即删除关键字
(do-the-boogie(=1244)(print"if clause")(print"else clause"))
- 1 -使函数的子窗体均匀缩进 按单位缩进大小(可以更改)
pip install --upgrade yasi0
- 2 -通过赋予第一个子窗体更大的 缩进比其他子窗体的缩进方式与标准相同 如果表达式缩进。第一个子窗体的 压痕尺寸与其余尺寸相同。
pip install --upgrade yasi1
- 3 -子窗体将均匀缩进两倍缩进 大小<LI>
pip install --upgrade yasi2
- 4 -按单位缩进,如1-关键字,但也按其局部缩进 功能
pip install --upgrade yasi3
标准缩进(假设 letfn 只是另一个函数) 将是:
pip install --upgrade yasi4
关于默认缩进
–默认缩进 出现在其子窗体通常为 从后面几行开始。就像在a cond 表达式中一样:
pip install --upgrade yasi5
上述结果将是标准/预期缩进。然而 人们可能更希望子窗体开始于超过头部的两个空格 这样的表达式。
pip install --upgrade yasi6
这是vim的默认缩进样式。这个选项使您能够 指定所需的数量,例如,要实现上述样式,可以 像这样传递参数:
pip install --upgrade yasi7
Yasi不处理的内容
在某些方言中,有些语法似乎并不适用。 值得努力实施。例如 mzscheme 和 gauche 对正则表达式使用 .// 或 .[] 。
对Lispindent的修改
我对 lispindent.lisp 做了一些修改,并将其重命名为 lispindent2.lisp 。更改包括:
- 为程序的某些部分添加了注释 理解
- 它现在可以从命令行缩进文件而无需 将文件内容重定向到程序。T他最初的那个是纯粹的 仅用作从标准缩进的筛选脚本 输入.
- lispindent2.lisp 更好地缩进clojure的向量和集合。 即压痕水平为1,但不影响Lisp的 scheme的缩进 。它使用文件的扩展名来确定 它正在查看clojure代码。例如
pip install --upgrade yasi8
pip install --upgrade yasi9
- lispindent2.lisp 忽略多行注释中的任何代码,并且不会 受到评论中任何未关闭的括号的影响,如 原版。不幸的是,它的多行检测方法 注释相当幼稚,并在代码中引入了一个bug。参照 其问题如下。
- lispindent2.lisp 默认使用行尾来写入文件。 它比通常在 烦人的方式在 vim
编辑器集成
Yasi从标准输入格式化代码的能力使它成为一个合适的 VIM中的 equalprg 设置的候选者。将此添加到 .vimrc 你很好去。
;; In Common Lisp(do((j0(+j1)))(nil);Do forever.(formatt"~%Input ~D:"j)(let((item(read)))(if(nullitem)(return);Process items until NIL seen.(formatt"~&Output ~D: ~S"jitem))))0
然后,您可以通过在 = 符号,例如 =%
您还可以签出这些其他项目以进行适当的集成 不将其作为筛选脚本外部调用,例如:
- vim插件:https://github.com/nkmathew/vim-newlisp-yasi" rel="nofollow">https://github.com/nkmathew/vim newlisp yasi
- Sublime Text 2/3插件:https://github.com/nkmathew/sublime-yasi" rel="nofollow">https://github.com/nkmathew/sublime yasi
Lispindent2问题
我无意中添加了一个bug,试图阻止它评估 公共lisp中多行注释内的括号和符号 scheme中的空格。
它使用管道字符()跟踪注释是否仍然 在多行注释中,表示多行中奇数个管道 注释将产生错误的缩进,例如:
;; In Common Lisp(do((j0(+j1)))(nil);Do forever.(formatt"~%Input ~D:"j)(let((item(read)))(if(nullitem)(return);Process items until NIL seen.(formatt"~&Output ~D: ~S"jitem))))1
我不认为这是个大问题,因为多行注释是 很少使用,常见的用例是注释掉代码区域 调试时。
lispindent2.lisp 使用 lisp reader函数从字符串中读取 从读取字符串中获取lisp形式和原子。
其缺点是当 字符串中的代码"格式不正确"。例如,如果它发现 用于在 common lisp 中考虑的运算符在打开后出现 括号,它将引发致命错误。这意味着任何 clojure 代码 尝试使用点运算符访问类方法的 由于错误而缩进。例如,此代码:
;; In Common Lisp(do((j0(+j1)))(nil);Do forever.(formatt"~%Input ~D:"j)(let((item(read)))(if(nullitem)(return);Process items until NIL seen.(formatt"~&Output ~D: ~S"jitem))))2
lispindent2.lisp 使用忽略错误宏作为解决方法。 这样做意味着它不能在gnu common lisp中运行,因为它 没有宏。
lispindent2命令行选项
;; In Common Lisp(do((j0(+j1)))(nil);Do forever.(formatt"~%Input ~D:"j)(let((item(read)))(if(nullitem)(return);Process items until NIL seen.(formatt"~&Output ~D: ~S"jitem))))3