本身動手開發sublime插件(1)

最近對sublime的親密度不斷增長,之前只是用它來寫WEB,如今發現用它來寫C++也很方便,特別是它的免打擾模式太好用了,因而我乾脆弄了一個C++的sublime build system,這樣在sublime中也能編譯C++了,除了不能調試,已經算是一個開發環境。html

 

可是,昨天發現,我習慣用的Visual Assist在sublime中找不到類似的插件。尤爲是 alt + up, alt+ down 快捷鍵,在VC中是跳轉到類或函數定義,是我最經常使用的快捷鍵之一。好吧,既然找不到,咱就本身作一個。python

 

其實爲sublime作插件並不難,sublime是用python作爲腳本驅動的,插件一般也是用python。在網上看了點資料,再看看sublime3\package\default目錄裏面幾個py,就大概明白插件的思路了。正則表達式

 

首先,在 sublime3安裝目錄 \Data\Packages目錄下新建一個目錄,名字能夠隨意,我取名爲JumpTag。json

 

而後,由於我要捕捉快捷鍵,就要有.sublime-keymap文件;要用python,必須有.py文件。因此在這個JumpTag目錄下新建幾個文件:Default (Linux).sublime-keymap、Default (OSX).sublime-keymap、Default (Windows).sublime-keymap 和 JumpTag.pyapi

 

其中,三個.sublime-keymap文件都是同樣:async

[
  { "keys": ["alt+up"], "command": "jump_tag_prev"},
  { "keys": ["alt+down"], "command": "jump_tag_next"}
]

實際上是json格式,意思是說按下 alt+up 就調用命令 jump_tag_prev,alt+down 調用 jump_tag_next函數

 

那麼,在哪裏實現jump_tag_prev、jump_tag_next 命令呢?固然是在.py文件裏啦:ui

 1 import sublime, sublime_plugin
 2 import re
 3 
 4 
 5 _datas = {"view_id":0,"recorder":None}
 6 
 7 class JumpTagRecorder(sublime_plugin.EventListener):
 8     def on_modified_async(self, view):
 9         _datas["view_id"] = view.id();
10         _datas["recorder"]= None;
11 
12     def on_activated_async(self, view):
13         _datas["view_id"] = 0;
14         _datas["recorder"]= None;
15 
16 
17 def gen_recorder(view):
18     if (_datas["recorder"] is None or _datas["view_id"] != view.id()):
19         _datas["view_id"] = view.id()
20         _datas["recorder"]= view.find_all(r"(^(?![ \t]*?\b(if|while|for|try)\b)[\w \t*&]*?\([^()]*?\)(?=[\w\s]*?\{))|(\bclass\b|\bstruct\b)[\w \t:,<>]+?(?=[\s]*?\{)")
21 
22     return _datas["recorder"]
23 
24 
25 class JumpTagPrevCommand(sublime_plugin.TextCommand): #注意看類的名字,對應了 jump_tag_prev_command 命令
26     def run(self, edit):
27         reg_list = gen_recorder(self.view)
28 
29         if reg_list is None:
30             return
31 
32         for region in self.view.sel():
33             pt = region
34             break
35 
36         closest_num = 999999999
37         closest_region = sublime.Region(0,0)
38 
39         for region in reg_list:
40             if region.end() < pt.begin():
41                 n = pt.begin() - region.end() 
42                 if n < closest_num:
43                     closest_num = n
44                     closest_region = region
45 
46         if closest_region.empty():
47             return
48 
49         self.view.sel().clear()
50         self.view.sel().add(closest_region)
51 
52         self.view.show(closest_region.begin())
53 
54 class JumpTagNextCommand(sublime_plugin.TextCommand):  #這個類的名字對應了 jump_tag_next_command 命令
55     def run(self, edit):
56 
57         reg_list = gen_recorder(self.view)
58 
59         if reg_list is None:
60             return
61 
62         for region in self.view.sel():
63             pt = region
64             break
65 
66         closest_num = 999999999
67         closest_region = sublime.Region(0,0)
68 
69         for region in reg_list:
70             if region.begin() > pt.end():
71                 n = region.begin() - pt.end() 
72                 if n < closest_num:
73                     closest_num = n
74                     closest_region = region
75 
76         if closest_region.empty():
77             return
78 
79         self.view.sel().clear()
80         self.view.sel().add(closest_region)
81 
82         self.view.show(closest_region.begin())

稍微講一下這代碼:由於咱們要在函數定義、類定義之間跳轉,因此就得先把這些定義的位置找出來,函數gen_recorder就是幹這工做的,我認可函數名起的不咋滴。它調用了sublime的一個API:find_all,按正則表達式找出全部函數定義和類定義的位置,我這正則表達式也不知道是否是最優,總之功能是實現了。spa

如今有了找出定義位置的函數了,那麼,咱們何時才須要去找這些定義的位置呢?應該知道全文查找是個相對耗時的操做,不該該在每次按快捷鍵時調用。咱們能夠把定義的位置保存起來,在文檔發生改變時再從新查找。所以,就須要監聽文檔的修改事件了。定義一個監聽器也是很簡單的:插件

class JumpTagRecorder(sublime_plugin.EventListener):   #注意括號裏必須是sublime_plugin.EventListener

    def on_modified_async(self, view):        #注意函數的名字
        _datas["view_id"] = view.id();
        _datas["recorder"]= None;

    def on_activated_async(self, view):
        _datas["view_id"] = 0;
        _datas["recorder"]= None;

上面這個類的名字是隨意的,可是要注意括號裏面,必須是 sublime_plugin.EventListener,類的方法必須按照api文檔http://www.sublimetext.com/docs/3/api_reference.html 

最後,就是實現 jump_tag_prev、jump_tag_next命令了,代碼十分的簡單,相信沒有人看不懂的。要注意的是命令對應的類,不能隨意取名,必定要把命令名改爲「駝峯式」,還得加上Command,並且必需要有run方法。

 

簡簡單單,就實現一個小插件啦!對了,讓我影響比較深的是sublime是熱加載插件代碼的,也就是說插件代碼一旦被修改,sublime中當即從新加載,這真的很方便。

相關文章
相關標籤/搜索