sublime插件开发

在写前端代码的时候, vs虽然有比较完美的智能提示和格式化, 但是字体太大和占用内存太大, 而且比起纯代码编辑器还是卡了一点, 所以一般还是习惯使用sublime来写html等前端代码. 但是最近有一点用得很不舒服的就是代码格式化.

sublime是没有自己的代码格式化的, 需要格式化都需要使用插件来完成, 而我目前使用的有HTML-CSS-JS Prettify, 格式化出来的效果还是比较好的, 唯一有一点不舒服的就是会有一点点卡顿的感觉, 在js文件比较大的时候更明显.

而有时候在复制一些代码时, 特别是使用ESLint格式化的代码, 在粘贴到sublime里面的时候, 由于ESLint默认的缩进是2行, 而项目组里面的代码都是4行缩进的, 贴进来以后就显得很不协调, 即使是用带格式的粘贴ctrl + shift + v也不能解决这个问题, 只能默认缩进到当前行, 但是里面的缩进还是2行. 而每次粘贴完成代码以后使用一次格式化又感觉有点卡和不爽, 所以想自己写个小插件来解决这个问题.

首先新建一个plugins, 点击Tool -> New Plugin...会出现一个默认的Hello World文件, 能发现它的语法是python. 然后用ctrl + ~打开控制台, 保存该文件到Packagesdemo目录, 文件名为demo.py. 保存的时候就能看到控制台出现提示, reloading plugin ..., 表示插件读取到了. 既然是python, 那么测试一下, 发现不支持print 'a'这种语法可知python版本为3.x.

运行方式, 在.py文件中, 主函数名为xAxBxCommand, 那么在控制台中输入view.run_command('x_ax_bx')即可运行该插件. 剩下的就是开发python了. 打开vs, 建个python工程, 写好转换函数, 贴进来就可以使用了.

首先是获取剪切板内容, 查API可得使用函数sublime.get_clipboard()即可获取当前剪切板内容. 剩下就是简单的修改字符串函数了.

1
clipboardStr = sublime.get_clipboard()

首先是把\t转换成空格, clipboardStr = clipboardStr.expandtabs(4).
然后是把行分割成数组, 这里有个问题是window中, 行结尾符可能是\r\n也可能是\n, 这里处理方法是如果有\r\n即使用\r\n做分隔符.

1
2
3
4
split_symbol = '\n'
if clipboardStr.find('\r\n') > -1:
split_symbol = '\r\n'
s_list = clipboardStr.split(split_symbol)

如果当前剪切板只有一行, 那么就直接调用paste_and_indent(ctrl + shift + v)粘贴即可.

1
2
if len(s_list) == 1:
self.view.run_command('paste_and_indent')

如果超过一行, 那么先将每行都往前缩进最小的空格数量, 即去掉多余的空格, 按本来的缩进排列, 这里存在一个问题是, 可能在复制的时候第一行是没有复制到空格而是直接复制得代码, 所以需要特殊处理一下.
再计算每行的最小前置空格差, 如果最小相差为2, 那么说明这段代码的原始tab占空格为2个, 否则为4个. 如果tab占空格为2的话, 那么将每行的前置空格数量翻倍即可.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
preIndent = 0
if len(s_list) == 1:
self.view.run_command('paste_and_indent')
else:
preIndent = self.getLeftSpace(s_list[0])
if preIndent == 0:
preIndent = 1000
leftSpaceList = [0]
for s in s_list[1:]:
leftSpace = self.getLeftSpace(s)
leftSpaceList.append(leftSpace)
preIndent = leftSpace if leftSpace < preIndent else preIndent
s_list[0] = s_list[0].lstrip()
minPreIndentSpace = 1000
leftSpaceList.sort()
for i in range(1, len(leftSpaceList)):
leftSpaceSplit = leftSpaceList[i] - leftSpaceList[i-1]
if leftSpaceSplit > 0 and leftSpaceSplit < minPreIndentSpace:
minPreIndentSpace = leftSpaceSplit
if preIndent > 0:
for index in range(1, len(s_list)):
s = s_list[index]
if self.getLeftSpace(s) >= preIndent and len(s.strip()) > 0:
s_list[index] = s[preIndent:]
if minPreIndentSpace == 2:
for index in range(0, len(s_list)):
if self.getLeftSpace(s_list[index]) >= minPreIndentSpace:
s_list[index] = s_list[index].replace(' ', ' ')
clipboardStr = split_symbol.join(s_list)
def getLeftSpace(self, s):
return len(s) - len(s.lstrip())

然后将值设置到剪切板中, 调用paste_and_indent即可.

1
2
sublime.set_clipboard(clipboardStr)
self.view.run_command('paste_and_indent')

然后去设置一个快捷键, 建立一个Default (Windows).sublime-keymap文件, 内容为:

1
2
3
[
{ "keys": ["ctrl+shift+v"], "command": "paste_with_tab" }
]

这里直接覆盖了原始的ctrl + shift + v命令. commandPasteWithTabCommand的驼峰转换小写形式. 再加一个菜单文件Main.sublime-menu, 内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[
{
"id": "edit",
"children":
[
{ "caption": "-", "id": "clipboard" },
{
"caption": "带缩进的粘贴",
"command": "paste_with_tab"
},

]
}
]

所有代码见git

作者

Mosby

发布于

2017-03-06

许可协议

评论