原文地址:http://code-tech.diandian.com/post/2012-11-16/40042306130
Sublime插件的开发,可以首先参考How to Create a Sublime Text 2 Plugin 和
如何开发Sublime插件 还有Sublime中文手册 ,还有个非官方的文档,没有翻译完,希望有志之士发扬开源精神,继续完成,地址https://github.com/yangweijie/sublime-text-unofficial-documentation--cn
虽然看了前面两篇文章,但是对于没有任何python基础的人还是有点困难,本人主攻语言php,看了2星期的python电子书。隔了几个月又基本还回去了,推荐一个网站可以将常用php函数找到对应python版,说起来还真的很像的: http://www.php2python.com PS:Ruby和python都能跨界,什么时候出个php的就好了O(∩_∩)O~
废话不多说了,先说一下开发插件流程:
1.按照上面的文章开发出Example插件
2.在此插件上添加自己的功能
3.完善菜单、快捷键和配置文件等
注意点:善用调试面板 ctrl+~,多读其他插件的源码,他山之石可以攻玉,借助度娘和谷姐的力量
先粘上本插件的源码
# -*- coding: utf-8 -*- import sublime, sublime_plugin import os,httplib,urllib,urllib2,json,webbrowser,codecs def fs_reader(path): return codecs.open(path, mode='r', encoding='utf8').read() def fs_writer(path, raw): codecs.open(path, mode='w', encoding='utf8').write(raw) def out_tpl(new,sub=''): if sub == '': return tpl.replace('{%s}',new) else: return tpl2.replace('{%s}',new) def get_tpl_fullpath(filename,parent_dir=''): return packages_path + '\\manual\\' + parent_dir + filename+'.html' def write_tpl(filename,content,parent_dir=''): if not os.path.isfile(get_tpl_fullpath(filename,parent_dir)): fs_writer(get_tpl_fullpath(filename,parent_dir),content) def open_tab(url): webbrowser.open_new_tab(url) def get_content(id,parent_dir=0): conn = httplib.HTTPConnection("doc.thinkphp.cn") conn.request("GET", "/api/view/"+id) r1 = conn.getresponse() data1 = r1.read() data1 = json.loads(data1) data = data1['data'] content = '' for i in data: content= content + i['content'] if parent_dir == 0: return out_tpl(content) else: return out_tpl(content,1) settings = sublime.load_settings('Thinkphp.sublime-settings') packages_path = sublime.packages_path() + '\\Thinkphp' manual_dir = settings.get('manual_dir') tpl = fs_reader(os.path.join(packages_path + '\\'+ manual_dir +'\\public', 'book.tpl')) tpl2 = fs_reader(os.path.join(packages_path + '\\'+ manual_dir +'\\public', 'book_sub.tpl')) class ThinkphpCommand(sublime_plugin.TextCommand): def see(self,id,name,parent_dir=''): #url = 'http://doc.thinkphp.cn/manual/' + self.data[arg]['name'] content = get_content(id,parent_dir) write_tpl(name,content,parent_dir) url = 'file://'+get_tpl_fullpath(name,parent_dir) open_tab(url) def build(self,id,name,parent_dir=''): content = get_content(id,parent_dir) write_tpl(name,content,parent_dir) def run(self, edit): data = self._init() self.data = data chapter = [] tree = [] sort_data = [] k = 0 for i in data: chapter.insert(int(i['id']),i['title']) sort_data.insert(k,i['name']) state = i.get('_child', None) if state: tree.insert(k,i['_child']) else: tree.insert(k,None) k = k+1 # print chapter self.chapter = chapter self.sort_data = sort_data self.tree = tree self.view.window().show_quick_panel(chapter, self.panel_done) def panel_done(self,arg): if arg == -1: pass else: self.tree_key = arg if self.tree[arg] == None: self.see(self.data[arg]['id'],self.data[arg]['name']) else: if not os.path.isdir(packages_path + '\\'+ manual_dir +'\\'+self.sort_data[arg]): os.mkdir(packages_path + '\\'+ manual_dir +'\\'+self.sort_data[arg]) child =[] k = 0 for i in self.tree[arg]: child.insert(k,i['title']) k +=1 self.view.window().show_quick_panel(child, self.child_done) def child_done(self,arg): if arg == -1: self.view.window().show_quick_panel(self.chapter, self.panel_done) else: self.see(self.tree[self.tree_key][arg]['id'],self.tree[self.tree_key][arg]['name'],self.sort_data[self.tree_key]+'\\') def _init(self): conn = httplib.HTTPConnection("doc.thinkphp.cn") conn.request("GET", "/api") r1 = conn.getresponse() data1 = r1.read() data1 = json.loads(data1) return data1['data'] def update_manual(self): data = self._init() for j in data: if not j.get('_child', None): self.build(j['id'], j['name']) else: parent_dir = j['name'] if not os.path.isdir(packages_path + '\\'+ manual_dir +'\\'+j['name']): os.mkdir(packages_path + '\\'+ manual_dir +'\\'+j['name']) for t in j['_child']: sublime.set_timeout(self.build(t['id'],t['name'],parent_dir+'\\'),100) sublime.status_message('the manual has been generated') def search_panel(self): self.view.window().show_input_panel('search in thinkphp manual?', '', self.search_done, self.search_change, self.search_cancel) def search_done(self,arg): data = {'keywords' : arg} f = urllib2.urlopen(url = 'http://doc.thinkphp.cn/api/search',data = urllib.urlencode(data)) data = f.read() data = json.loads(data) if data['data'] == []: sublime.error_message('No Search result !') else: chapter = [] data = data['data'] self.search_list = data for i in data: chapter.insert(int(i['id']),i['title']) self.view.window().show_quick_panel(chapter, self.manual_search_done) def manual_search_done(self,arg): if arg == -1: pass else: choose = self.search_list[arg] data = self._init() for i in data: if i['id'] == choose['id']: self.see(choose['id'], choose['name']) else: state = i.get('_child', None) if state: for j in i['_child']: if j['id'] == choose['id']: if not os.path.isdir(packages_path + '\\'+ manual_dir +'\\'+i['name']): os.mkdir(packages_path + '\\'+ manual_dir +'\\'+i['name']) self.see(choose['id'], choose['name'], i['name']+'\\') def search_change(self,arg): pass def search_cancel(self): pass class update_thinkphp_manual(ThinkphpCommand,sublime_plugin.TextCommand): def run(self, edit): self.update_manual() class search_word_thinkphp_manual(ThinkphpCommand,sublime_plugin.TextCommand): def run(self, edit): region = self.view.sel()[0] if region.begin() != region.end(): self.search_done(self.view.substr(region)) else: self.search_panel() class search_thinkphp_manual(ThinkphpCommand,sublime_plugin.TextCommand): def run(self, edit): self.search_panel()
# -*- coding: utf-8 -*-
这行注释防止代码有中文导致的乱码显示
self
.view.window().show_quick_panel
这行里的self.view.window()获得window类,之后就可以调用window类的所有方法了,比如show_quick_panel显示下拉列表
sublime.packages_path()
这个是获取当前插件包的路径,根据安装版和绿色版返回的地址不同,前者win的是在用户文档目录下,后者是在Sublime软件安装的Data\Packages里
class
ThinkphpCommand(sublime_plugin.TextCommand):
这个才是开始插件命令的定义,注意Thinkphp一定要和插件目录名一致,当我们保存插件py文件时,st会重新加载所有插件一次,这时在终端面板里可以通过view.runCommand('thinkphp')来运行它看效果,命令名要用小写了
sublime.error_message()
Sublime类的方法可以直接调用
class
update_thinkphp_manual(ThinkphpCommand,sublime_plugin.TextCommand):
def
run(
self
, edit):
self
.update_manual()
这个是前面2篇文档没讲的,我是在gist插件的源码里看到的,如何在一个插件里扩展多条命令,并且可以使用当前插件的方法
settings = sublime.load_settings('Thinkphp.sublime-settings')
manual_dir = settings.get('manual_dir')
这两句是读取配置和获取配置的值,当然还有自己去更新配置
region = self.view.sel()[0] if region.begin() != region.end(): self.search_done(self.view.substr(region))
这个是最简单的获取选区的判断后使用的例子
接下来时菜单Main.sublime-menu:
[ { "id": "tools", "children": [ { "caption": "ThinkPHP manual", "id": "ThinkPHP manual", "command": "thinkphp" }, { "caption": "ThinkPHP manual: search", "id": "ThinkPHP manual: search", "command": "search_thinkphp_manual" }, { "caption": "ThinkPHP manual: build book", "id": "ThinkPHP manual: build book", "command": "update_thinkphp_manual" } ] }, { "caption": "Preferences", "mnemonic": "n", "id": "preferences", "children": [ { "caption": "Package Settings", "mnemonic": "P", "id": "package-settings", "children": [ { "caption": "ThinkPHP", "children": [ { "command": "open_file", "args": {"file": "${packages}/Gist/ThinkPHP.sublime-settings"}, "caption": "Settings – Default" }, { "command": "open_file", "args": {"file": "${packages}/User/ThinkPHP.sublime-settings"}, "caption": "Settings – User" }, { "command": "open_file", "args": { "file": "${packages}/ThinkPHP/Default (Windows).sublime-keymap", "platform": "Windows" }, "caption": "Key Bindings – Default" }, { "command": "open_file", "args": { "file": "${packages}/User/Default (Windows).sublime-keymap", "platform": "Windows" }, "caption": "Key Bindings – User" }, { "caption": "-" } ] } ] } ] } ]
这里注意的是"${packages}
"代表当前插件目录,还有就是顺序,tools在preferences
前面,放到后面可能不起作用了
Thinkphp.sublime-commands
[ { "caption": "ThinkPHP manual: view list", "command": "thinkphp" }, { "caption": "ThinkPHP manual: build book", "command": "update_thinkphp_manual" }, { "caption": "ThinkPHP manual: search", "command": "search_thinkphp_manual" } ]
只有在命令文件里写过的命令才会在ctrl+shift+p的命令列表中显示
右键 Context.sublime-menu:
[ { "command": "search_word_thinkphp_manual", "caption": "search_thinkphp_manual here" } ]
菜单文件配了选项在菜单中会出现,但是只有在对应命令存在可执行,方会显示可点击的状态,而不是灰色
插件命名最好使用首字母大写的驼峰法命名如Thinkphp,最好不要带_ 空格等。
希望大家能从这篇文章中得到一些帮助,然后投入到轰轰烈烈的Sublime插件开发队伍中去。。