Sublime Text 插件开发笔记

一直想写几个小插件满足一下自己的需求, 终于动笔啦!

运行 sublime 后, 会运行 python. sublime 中进行的一系列操作均是由python的函数完成的. 当然这里的函数是 sublime 自己实现的.

所以我们写的插件, 本质上是对调用命令的"自动化".

放在 Packages 下的任意位置即可. 当然可以创建文件夹使得我们的插件更容易被找到.

在 sublime 中按 Ctrl + ~ 呼出 python 交互窗口, 可以看到加载插件的信息.

Tools $\to$ Developer $\to$ New Plugin...

然后他会新建一个文件如下:

1
2
3
4
5
6
import sublime
import sublime_plugin

class ExampleCommand(sublime_plugin.TextCommand):
	def run(self, edit):
		self.view.insert(edit, 0, "Hello, World!")

保存至插件目录即可.

官网, 请

建一个类, 类名为 YourCommandNameCommand, 继承 sublime_plugin.TextCommand, 如:

1
2
3
class ExampleCommand(sublime_plugin.TextCommand):
	def run(self, edit):
		self.view.insert(edit, 0, "Hello, World!")

根据sublime的命令规则, 这条命令可以被 view.run_command('example') 调用.

可以发现, 就是类名Command之前的前缀. 把驼峰换成小写字母下划线分割的形式就是命令.

监听分为事件监听(EventListener)和更精确一点的视图事件监听(ViewEventListener).

视图事件监听直接对应了当前视图(View), 有 self.view 成员变量, 在一些情况下比较方便, 比如监听事件以后需要调用文本命令.

建一个类, 继承 sublime_plugin.EventListener 或者 sublime_plugin.ViewEventListener, 重写监听函数, 如:

1
2
3
class SaveListener(sublime_plugin.ViewEventListener):
	def on_pre_save(self):
		self.view.run_command("replace_punctuations")
  1. View.find(pattern, start_point, <flags>) -> Region

start_point 位置开始查找正则 pattern, 返回区域(Region).

  1. View.find_all(pattern, <flags>, <format>, <extractions>) -> [Region]

查找所有正则 pattern, 返回区域列表

参数目前没用到, 先不记录.

View.replace(edit, region, string)

editsublime.Edit类, 在 sublime_plugin.TextCommandrun() 传入, 直接调用就行.

把区域 region 中的内容替换成 string.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
import sublime
import sublime_plugin

class SaveListener(sublime_plugin.ViewEventListener):
	def on_pre_save(self):
		self.view.run_command("replace_punctuations")

class ReplacePunctuationsCommand(sublime_plugin.TextCommand):
	def run(self, edit):
		self.replace(edit, '. ', '. ')		 前面其实是中文
		self.replace(edit, ': ', ': ')		 句号, 冒号, 逗号, 顿号
		self.replace(edit, ', ', ', ')		 保存文件后他被替换掉了
		self.replace(edit, ', ', ', ')		 哈哈哈
	def replace(self, edit, src, dst):
		regions = self.view.find_all(src)
		for region in reversed(regions):
			self.view.replace(edit, region, dst)
		if len(regions):
			print(len(regions), src, 'replaced!')
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import sublime
import sublime_plugin
import datetime

class SaveListener(sublime_plugin.ViewEventListener):
	def on_pre_save(self):
		self.view.run_command("auto_fill_lastmod")

class AutoFillLastmodCommand(sublime_plugin.TextCommand):
	def run(self, edit):
		filename = self.view.file_name()
		if filename[-3:] == '.md':
			print('The view is markdown')
			region = self.view.find('lastmod: .{19}', 0)
			if not region.empty():
				print('\"lastmod\" has been found')
				region = sublime.Region(region.a + 9, region.b)
				self.view.replace(edit, region, getCurrentTime())
				print('Updated lastmod time')

def getCurrentTime():
	time = datetime.datetime.now()
	time_str = time.strftime("%Y-%m-%dT%H:%M:%S")
	return time_str