自己动手开发sublime插件(1)

最近对sublime的亲密度不断增加,以前只是用它来写WEB,现在发现用它来写C++也很方便,特别是它的免打扰模式太好用了,于是我干脆弄了一个C++的sublime build system,这样在sublime中也能编译C++了,除了不能调试,已经算是一个开发环境。

但是,昨天发现,我习惯用的Visual Assist在sublime中找不到相似的插件。尤其是 alt + up, alt+ down 快捷键,在VC中是跳转到类或函数定义,是我最常用的快捷键之一。好吧,既然找不到,咱就自己做一个。

其实为sublime做插件并不难,sublime是用python做为脚本驱动的,插件通常也是用python。在网上看了点资料,再看看sublime3\package\default目录里面几个py,就大概明白插件的思路了。

首先,在 sublime3安装目录 \Data\Packages目录下新建一个目录,名字可以随意,我取名为JumpTag。

然后,因为我要捕捉快捷键,就要有.sublime-keymap文件;要用python,必须有.py文件。所以在这个JumpTag目录下新建几个文件:Default (Linux).sublime-keymap、Default (OSX).sublime-keymap、Default (Windows).sublime-keymap 和 JumpTag.py

其中,三个.sublime-keymap文件都是一样:

[
  { "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文件里啦:

 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,按正则表达式找出所有函数定义和类定义的位置,我这正则表达式也不知道是不是最优,总之功能是实现了。

现在有了找出定义位置的函数了,那么,我们什么时候才需要去找这些定义的位置呢?应该知道全文查找是个相对耗时的操作,不应该在每次按快捷键时调用。我们可以把定义的位置保存起来,在文档发生改变时再重新查找。因此,就需要监听文档的修改事件了。定义一个监听器也是很简单的:

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中立即重新加载,这真的很方便。

时间: 2024-12-15 01:53:09

自己动手开发sublime插件(1)的相关文章

Sublime插件库新成员基于APICloud快速开发跨平台App

互联网时代强调用户体验,那什么是HTML5跨平台App开发者的编程体验?"不剥夺.不替换开发者喜欢的开发工具,就是人性化的用户体验",APICloud给出了这样的答案! 重磅发布"多开发工具支持策略" "如果,你以为此次分享会APICloud只是讲解Eclipse开源插件代码经验,那就大错特错了!"APICloud CEO刘鑫以调侃的话进行了开场. 经过一年的上线摸索,APICloud团队充分的认识到"剥夺开发者已经习惯的开发工具,替换

【自己动手】sublime text插件开发

今天是五四青年节,在此先祝大家节日快乐!!! --------------------------------------------华丽的分界线--------------------------------------------------- 从使用ST开始,就觉得使用起来很顺手,在加上各种各样的插件,做起开发来还真可以省不少事儿.以前做.net一直用vs,不过说实话vs是最好用的IDE,没有之一:现在呢,入了前端的行,用起vs总是觉得太过笨重,于是就用起了同事推荐的ST,从此哥开发js和

sublime 插件(侧重JavaScript)

Sublime Text几乎是任何开发者在其工具箱的必备应用程序.Sublime Text是一款跨平台的,高度可定制的,高级的文本编辑器,既适合全功能的IDE(出了名的资源匮乏),又可匹配命令行编辑器,例如Vim和Emacs(具有陡峭的学习曲线). Sublime Text如此受欢迎的其中一个原因就是它的可扩展插件架构.这使得开发人员可以轻松使用新功能,例如代码完成,或远程API文档嵌入,来扩展Sublime的核心功能.Sublime Text的插件并不是开箱即用的--通常需要通过一个叫Pack

Notepad++前端开发常用插件介绍

Notepad++前端开发常用插件介绍 Notepad++除了自身的功能强大之外,更是有许多非常的优秀的插件,下面就总结一下前端开发过程一些比较常用的插件. Emmet Emmet的前身是Zen Coding,一款使用仿CSS选择器的语法来快速开发HTML和CSS的插件,是前端开发神器.它无视了编辑器的自动提示和自动完成,秒杀了你自定义的各种快捷键或者 AHK 的热字符串,以智能简洁高效的缩短输入,带给你超快速地书写各种复杂而枯燥的 HTML 和 CSS 代码的体验.现在可以在Notepad++

我使用的Sublime插件及配置

我使用的Sublime插件及配置 增强型插件 Package Control 快捷键ctrl+~,调出命令行,运行: import urllib.request,os,hashlib; h = '2915d1851351e5ee549c20394736b442' + '8bc59f460fa1548d1514676163dafc88'; pf = 'Package Control.sublime-package'; ipp = sublime.installed_packages_path();

atitit.自己动手开发编译器and解释器(1) ------词法分析--attilax总结

atitit.自己动手开发编译器and解释器(1) ------词法分析--attilax总结 1.   应用场景:::DSL 大大提升开发效率 1 2. 2. 流程如下::: 词法分析(生成token流) >>>>语法分析(生成ast) >>解释执行... 2 3. 如何进行词法分析?Fsm状态机(自动机) 2 4. 使用状态模式构建FSM  (简单,易用..推荐首选) 2 5. ---代码( 状态模式构建FSM ) 3 6. 词法分析概念 3 6.1. 词法分析(英

atitit.自己动手开发编译器and解释器(2) ------语法分析,语义分析,代码生成--attilax总结

atitit.自己动手开发编译器and解释器(2) ------语法分析,语义分析,代码生成--attilax总结 1. 建立AST 抽象语法树 Abstract Syntax Tree,AST) 1 2. 建立AST 语法树----递归下降(recursive descent)法 2 3. 语法分析概念 2 3.1. 上下文无关语言,非终结符(nonterminal symbol),终结符(terminal symbol).注 2 3.2. 最左推导.当然也有最右推导 3 3.3. 分支预测的

C#开发BHO插件UrlTrack

最近忽然突发奇想,想统计一下我最经常上的网站是哪些,并且在这些网站上都停留了多久.为此决定写一个BHO插件来做这件事. BHO(Browser Help Objects)是实现了特定接口(IObjectWithSite)的COM组件.开发好的BHO插件除了要在注册表中注册为COM Server外,还必须将它的CLSID在HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Browser Helper Objects下注册为子键.每当浏览

Qt5的插件机制(6)--开发Qt插件时几个重要的宏

怎样开发Qt插件,能够在Qt Assistant 中搜索"Qt Plugins"或"How to Create Qt Plugins",看看那篇manual中的介绍. 当中涉及到了几个宏 Q_DECLARE_INTERFACE( ClassName, Identifier) This macro associates the given Identifier (a string literal) to the interface class called Class