7

sublime Text 3 以下简称ST3是一个非常性感的文本编辑器,很多前端开发者在使用它。无插件,不神器,插件的使用可以使开发更方便快捷。目前社区里提供了各种各样的插件,在搜索里一搜就是各类插件的使用推荐,即使有这么多的插件,有时也不能满足我们的开发需要,今天就跟大家聊一下前段时间实现的(QcmsAux)插件的开发过程,希望给打算写插件的小伙伴们提供参考。

前期知识了解

1.了解Python

ST3是通过C++开发的,它的插件系统是通过Python来编写的,所以你一定要会Python,不一定非常精通,但是一定要了解,用到哪块儿知道去哪儿查。

推荐:Python基础教程 做为入门了解。

2. Python控制台

Sublime Text中内嵌了Python解释器。ST3中的Python和系统中的python是相互独立的。

我使用的是OSX系统,系统中的pythone版本是

python -V // Python2.7.10
打开Python控制台
  • 快捷键:Ctrl + `
  • 菜单: View -> Show Console

在这个控制台中查看,当前ST3中sublime的信息

sublime.version() // '3126'
sublime.platform() // 'osx'

查看ST3中python的版本

platform.python_version() //'3.3.6'

3. 重要的几个目录

Data目录

ST3几乎所有需要的文件都保存在Data目录下,不同的操作系统路径不同:

  • Windows: %APPDATA%Sublime Text 3
  • OS X: ~/Library/Application Support/Sublime Text 3
  • Linux: ~/.config/sublime-text-3

删除这个目录之前使用的插件和自定义的一些配置都会被同时删除,再次打开ST3,这个目录会被自动创建。

Packages目录

Data目录下的Packages目录是一个非常重要的目录,关于编程和标记语言的所有支持都保存在这里。

通过Sublime Text -> Preferences -> Browse Packages…可以打开该目录。

User 目录

User目录在Packages目录下,用于保存自定义plugins,snippets, macros(宏)。插件配置等都存在这个目录下。插件更新时,这个目录里的内容不会被修改。

准备工作

一个简单的插件示例

Tools -> Developer -> New Plugin, 使用这个命令可以创建一个插件示例,保存该文件,默认会保存在User目录下,默认文件名是 untitled.py

插件保存的位置

通过Package Control 安装的插件有的以源码的形式存入Packages目录,有的则以.sublime-package结尾的压缩包存在在上层目录的Installed Packages文件夹下。

ST3将会3个地方依次加载插件:

  1. Installed Pacages(only .sublime-package files)
  2. Packages
  3. Packages/User

根据约定,不会加载更深层次嵌套的文件,也就是说如果把 untitled.py 放在packages目录下会生效,但是如果放在User/new/下就不会生效。下面我直接放Packages/Example/下,文件名称改为Example.py,这里建议文件名和目录名保持一致。

我本机的目录/Users/rongl/Library/Application Support/Sublime Text 3/Packages/Example/

打开控制台,看到reloading plugin example.Example,说明插件已经被自动加载了,然后运行view.run_command('example'),如下会在第一行插入Hello, World! ,这样这个简单的插件就执行成功了。

Hello, World!import sublime
import sublime_plugin

class ExampleCommand(sublime_plugin.TextCommand):

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

到目前为止已经完成了简单的插件的编写执行。在上面的示例中:

  • sublime_plugin.TextCommand:这是文本编辑相关的基类,文本编辑相关的命令都继承于这个基类。
  • ExampleCommand: 类名以Command结尾,之前的部分为命令名,其中首字母要大写。执行命令时则采用下划线风格的拼写,view.run_command中传入example,如果为MyExampleCommand,则传入my_example
  • run(self,edit): 执行命令时会执行这个函数,这是固定格式。edit为API中提供的edit对象,在编辑时会用到。self,代表类ExampleCommand的实例。
  • self.view.insert(edit,point,content): point是init类型,指定编辑器中的一个坐标。所有插入,删除,选取等操作都通过self.view调用。

示例的效果就是在point位置插入content.

QcmsAux的开发过程

插件的主要功能

  1. 获取当前文件的路径,分析文件路径和文件名后缀,判断是否符合配置中指定的条件
  2. 如果未在qcms创建,调用qcms接口,在qcms创建文件,并返回新建文件的pid
  3. 已提交git,已在qcms创建,调用OBQ接口,发布到测试或上线
  4. 已提交git,调用OBQ接口,查看当前文件操作信息
  5. 调用验证接口,进行代码验证
  6. 跳转到OBQ平台,查看当前模板对应的query
  7. 跳转到OBQ平台,解锁当前模板
  8. 支持在SideBar中文件上右键弹出菜单上传到测试或上线

核心功能的实现

  1. QCMS创建页面查看QCMSAPI

sublime.load_settins加载插件的配置文件,配置文件内容格式为jsop,分User和default两种,分别位于Packages/User/<setting-name>Packages/<package-name>/<setting-name>中,前者覆盖后者。

# 获取配置信息

settings = sublime.load_settins("QcmsAux.sublime-settings")

settings.get('key')

# 获取页面内容

content = view.substr(sublime.Region(0, view.size()))

# 往接口post信息,urllib发送数据和header伪代码

import urllib.parse
import urllib.request

url = 'http://localhost/login.php'
user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
values = {
    'act' : 'login',
    'login[email]' : xx@xx.com',
    'login[password]' : '123456'
}
headers = { 'User-Agent' : user_agent }

data = urllib.parse.urlencode(values)
req = urllib.request.Request(url, data, headers)
response = urllib.request.urlopen(req)
the_page = response.read()

print(the_page.decode("utf8"))

2.指定浏览器打开url

# MacOS
CHROME_PATH = 'open -a /Applications/Google\ Chrome.app %s'

# Windows
# chrome_path = 'C:\Program Files (x86)\Google\Chrome\Application\chrome.exe %s'
# 
# Windows
# chrome_path = 'C:\Program Files (x86)\Google\Chrome\Application\chrome.exe %s' 
url = "http://www.so.com"
webbrowser.get(CHROME_PATH).open(url,new=1)

耗时任务阻塞主线程

ST3已经提供了非常方便的异步执行耗时任务的方法set_timeout_async

快捷键

sublime大部分的配置都可以通过json文件来完成,键盘绑定也一样。不过它的键盘绑定是区分系统的,所以基本上要建立3个文件,而且命名为Default (Windows).sublime-keymap, Default (Linux).sublime-keymapDefault (OSX).sublime-keymap

菜单项

  • Main.sublime-menu 控制了程序的主菜单
  • Side Bar.sublime-menu 控制侧边栏文件或者目录的右键菜单
  • Context.sublime-menu 控制处于编辑状态的文件右键菜单

通过console打印

print xxxx

弹出式的窗口

sublime.error_message("hello world")

几个常见概念

Window:

打开的 sublime text 窗口

View

表示一个文本缓冲的视图,可以认为是打开的一个 tab。

Edit

继承自 sublime_plugin.TextCommand 的命令, Edit 为第一个参数。 打开一个 view 以后必须要指定 Edit 才能真正的 insert 字符。需要 view.begin_edit 开始使用编辑区,使用完要 end_edit 。根据 sublime 3 API 的说法,只能继承,不能被创建。

Region

表示缓冲区的一个区域。有两个init类型的属性a和b。Region.a表示区域开始的点,Region.b表示区域结束的点。

view 的 find_all 等可以匹配一系列的 region 出来

Selection(RegionSet)

表示选择的区域。函数sublime.View.sel()返回的类型就是Selection,表示目前选中的所有区域。Selection.add(Region)方法可以添加选择区域。

Point概念

int类型,代表缓冲区的一个位置。可以通过sublime.View.rowcol(point)将point转化为行列信息(int,int)。或通过sublime.View.text_point(row,col)将行列信息转化为point。

  • Point 是跟文本开头位置的偏移量
  • 获得当前光标位置的 point: view.sel()[0].a
  • 一个 region 的属性 a b 为起始的俩个 point

line:

这里看到 line 返回的是鼠标所在行的起始字符数,从文件头开始,算 UTF8 字符,一个中文也是一个字符,无论光标在何处,都是这样的结构(行开始字符数, 行结束字符)

mark = self.view.sel()[0]
line = self.view.line(mark.a)
sublime.status_message("hickdebug "  + time.strftime("%Y-%m-%d %X - ") + str(line))
        

内置命令

expand_selection

用内置的expand_selection命令,to参数设置为brackets 每个css规则区域内容就可以选中了

self.view.run_command("expand_selection", {"to": "brackets"})

python中执行shell命令的四种方式

  1. os.system()

这个方法得不到shell命令的输出

import os
os.system('ls')
# 执行ls命令
  1. popen()

这个方法能得到命令执行后的结果是一个字符串,要自行处理才能得到想要的信息

import os
str = os.popen("ls").read()
a = str.split('\n')
for b in a:
    print b
  1. commands模块

可以很方便的取得命令的输出(包括标准和错误输出)和执行状态位

commands.getstatusoutput(cmd) 返回(status,output)

import commands
a,b = commands.getstatusoutput('ls')
print a
# a是退出的状态
# 0 
print b
# b是输出结果
# 执行ls命令

commands.getoutput(cmd) 只返回输出结果

import commands
b = commands.getoutput('ls')
# 执行ls命令

commands.getstatus(file) 待补充

  1. subprocess模块

使用subprocess模块可以创建新的进程,可以与新建进程的输入/输出/错误管道连通,并可以获得新建进程执行的返回状态。使用subprocess模块的目的是替代os.system(),os.popen(),commands*等旧的函数和模块。

subprocess.call(command,shell=True)

import subprocess
subprocess.call('ls',shell=True)
# 执行ls命令

subprocess.Popen(command,shell=True)

import subprocess
subprocess.Popen('ls',shell=True)
# 执行ls命令

subprocess.Popen(command,stdout=subprocess.PIPE,shell=True)待补充

如果command不是一个可执行文件,shell=True是不可省略的。
shell=True表示在shell下执行command

常用语句功能

view.settings().get('syntax')

返回当前文件格式,常见的有

  • [tpl,inc,html] : Packages/HTML/HTML.sublime-syntax
  • css: Packages/CSS/CSS.sublime-syntax
  • php: Packages/PHP/PHP.sublime-syntax
  • js:Packages/JavaScript/JavaScript.sublime-syntax
  • py:Packages/Python/Python.sublime-syntax
if int(sublime.version()) > 3000
    print("sublime3")

判断sublime的版本信息

命令的拼写

['node', '/Users/guopeipei/Library/Application Support/Sublime Text 3/Packages/JSLint/linter.js', '--bitwise', '--browser', '--es6', '--eval', '--for', '--fudge', '--node', '--this', '/Users/guopeipei/project/M_so_com/m_so/resource/js/result/scrollTab.js']

Running node /Users/guopeipei/Library/Application Support/Sublime Text 3/Packages/JSLint/linter.js --bitwise --browser --es6 --eval --for --fudge --node --this /Users/guopeipei/project/M_so_com/m_so/resource/js/result/scrollTab.js

sublime.View类重要方法

sublime.View.find_by_class(point, forward, classes, <separators>)

通过Class查找,sublime提供的Class

  • sublime.CLASS_WORD_START
  • sublime.CLASS_WORD_END
  • sublime.CLASS_PUNCTUATION_START
  • sublime.CLASS_PUNCTUATION_END
  • sublime.CLASS_SUB_WORD_START
  • sublime.CLASS_SUB_WORD_END
  • sublime.CLASS_LINE_START
  • sublime.CLASS_LINE_END
  • sublime.CLASS_EMPTY_LINE
sublime.View.find_by_selector(selector)

根据语法选择器查找 ,selector是一个字符串。Scope Naming

sublime.py文件位置

/Applications/Sublime Text.app/Contents/MacOS/sublime.py

参考

  1. sublime插件开发从0到1
  2. 为sublime text 3开发插件
  3. Sublime Text非官方文档
  4. 非官方文档的翻译整理
  5. Sublime Text 3.0 API文档
  6. Sublime Text 3.0 API 中文版

冰果
99 声望5 粉丝