发布时间:2023-08-15
浏览次数:0
作者|
喜欢使用Text的同事都知道,Text相当于Linux上的Vim。 它们都具有扩展性强、功能丰富、速度快等特点。 它们对于处理大文件和项目非常高效,所以如果不是很复杂的项目,我通常使用 Text 来编译和编译它们。
但在使用Text进行开发的过程中,我发现了一个问题:Text本身的手动补全功能只搜索当前视图中正在编辑文件的功能。 当我想在其他文件中使用自定义函数时,没有手动补全功能。 的。 而且当自定义功能过多时,效率会大大提高,于是我开始寻找具有相关功能的插件。
一开始我用的是非常流行的“”插件,确实很好用。 不幸的是,这个插件不支持C/C++,而且占用大量空间。 我必须寻找另一种方式来追求简单和轻盈。 后来我发现了一个“All”插件。 该插件扩展了Text默认的手动补全功能。 它可以搜索当前视图中打开的所有文件中定义的函数和变量。 虽然效果很好,但也存在很多问题。 显然,必须同时打开多个文件,极其不方便,所以我又放弃了。
在网上找了半天,没有找到我想要的插件,于是我开始考虑自己写一个这样的插件,正好利用这个机会入门。 这时我就想到是否可以使用CTags,它可以提取当前项目中的所有自定义函数,生成.tags文件,并提供符号跳转功能,只需提取.tags文件上的信息,使用正则匹配,然后添加到Text的手动补全功能还不够。
为了完成这个插件,我在网上查找了相关资料,找到了相关资料并重新思考,同时参考了All插件的源码。
需要提到的是,Text下安装CTags的方法这里就不说了,请自行查看。
插件的想法
◈
读取设置,设置中添加的语言禁用了插件功能
◈
检查.tag文件是否存在,如果不存在,则直接
◈
读取当前文件夹中的.tag文件
◈
正则匹配函数名
◈
正则匹配函数体
◈
添加到手动完成的套接字
动笔
新插件
刚开始写Text插件的时候,其实需要了解Text提供的各种。 于是,我去Text的官网查找相关文档:[1]、Text[2]。
首先,在Text中选择“Tools->->New”,创建一个基本的插件文档:
import sublime
import sublime_plugin
class ExampleCommand(sublime_plugin.TextCommand):
def run(self, edit):
self.view.insert(edit, 0, "Hello, World!")
这里 和 是需要的模块,具体的类和方法可以参考官方API[3]。
接下来sublime text 安装插件,将此文件保存到文件夹(默认保存位置User文件夹的上层)中的文件夹(新建)中,并命名为.py。 虽然命名没有限制,但是最好使用插件的名字来统一命名。
然后回到Text,通过快捷键Ctrl+`输入Text,然后进入view.(''),如果底部显示“Hello World”,则说明插件已正常加载。
这里之所以直接使用'',是因为命令名是按照小写字符分割的。
文本中的术语
◈
:Text的当前窗口对象
◈
View:当前窗口中打开的文本视图对象
◈
:Text中快捷键Ctrl+Shift+P打开的交互列表
确定插头插座类型
Text 下的插件命令有 3 种命令类型(均来自模块):
◈
Class[4]:通过 View 对象提供对所选文件/缓冲区内容的访问。
◈
Class[5]:通过对象提供对当前窗口的引用
◈
Class[6]:该类不引用任何特定的窗口或文件/缓冲区,因此很少使用
2种风暴窃听:
◈
Class[7]:窃听Text中的各种干扰并执行命令
◈
Class[8]:提供类似于风暴处理的类sublime text 安装插件,但绑定到特定视图。
2 个输入处理程序:
◈
Class[9]:可用于接受文本输入。
◈
Class[10]:可用于接受来自列表项的选择输入。
因为我要实现的功能比较简单,只需要监听输入风暴并触发手动补全功能,所以需要使用Class。 在这个类下,我们找到了一种方法来处理触发手动完成时执行的命令。 然后把刚才的代码改一下:
import sublime
import sublime_plugin
class CTagsAutoComplete(sublime_plugin.EventListener):
def on_query_completions(self, view, prefix, locations):
◈
视图:当前视图
◈
:触发手动完成时输入的文本
◈
:触发手动完成时,输入缓冲区中的位置。 您可以使用该参数来确定执行不同命令的语言
◈
返回类型:
◈无
◈[["\\thint",""]...],其中\\thint是可选的,为手动完成的函数名称添加提示
◈(,flag),这是一个包含手动完成的句子的列表,如上所述; flag是一个附加参数,可以用来控制是否显示Text自带的手动补全功能
读取CTags文件
为了读取.tag文件,首先要判断当前项目是否打开以及.tag文件是否存在,然后读取.tag文件中的所有内容:
import sublime
import sublime_plugin
import os
import re
class CTagsAutoComplete(sublime_plugin.EventListener):
def on_query_completions(self, view, prefix, locations):
results = []
ctags_paths = [folder + '\\.tags' for folder in view.window().folders()]
ctags_rows = []
for ctags_path in ctags_paths:
if not is_file_exist(view, ctags_path):
return []
ctags_path = str(ctags_path)
ctags_file = open(ctags_path, encoding = 'utf-8')
ctags_rows += ctags_file.readlines()
ctags_file.close()
def is_file_exist(view, file):
if (not view.window().folders() or not os.path.exists(file)):
return False
return True
通过以上操作,可以读取当前项目下所有.tag文件的内容。
分析 CTags 文件
第一个是获取 .tags 文件中包含的行:
for rows in ctags_rows:
target = re.findall('^' + prefix + '.*', rows)
一旦找到,该行数据就会通过正则表达式进行处理:
if target:
matched = re.split('\\t', str(target[0]))
trigger = matched[0] # 返回的第一个参数,函数名称
trigger += '\\t(%s)' % 'CTags' # 给函数名称后加上标识 'CTags'
contents = re.findall(prefix + '[0-9a-zA-Z_]*\\(.*\\)', str(matched[2])) # 返回的第二个参数,函数的具体定义
if (len(matched) > 1 and contents):
results.append((trigger, contents[0]))
results = list(set(results)) # 去除重复的函数
results.sort() # 排序
处理完成后即可返回。 考虑到最好只显示.tags中的函数,我不需要显示Text自带的手动补全函数(提取当前页面的变量和函数),所以我的返回结果如下:
return (results, sublime.INHIBIT_WORD_COMPLETIONS | sublime.INHIBIT_EXPLICIT_COMPLETIONS)
添加配置文件
考虑到插件的功能只能关闭,所以需要添加一个配置文件来指定不启用插件功能的语言。 这里我参考“All”的代码:
def plugin_loaded():
global settings
settings = sublime.load_settings('CTagsAutoComplete.sublime-settings')
def is_disabled_in(scope):
excluded_scopes = settings.get("exclude_from_completion", [])
for excluded_scope in excluded_scopes:
if scope.find(excluded_scope) != -1:
return True
return False
if is_disabled_in(view.scope_name(locations[0])):
return []
这里使用的配置文件需要添加到插件所在文件夹中,名称为.-,内容为:
{
// An array of syntax names to exclude from being autocompleted.
"exclude_from_completion": [
"css",
"html"
]
}
添加设置文件
有了配置文件,还需要在Text的“->”下添加相应的设置,同样放在插件所在文件夹下,名称为Main.-menu:
[
{
"caption": "Preferences",
"mnemonic": "n",
"id": "preferences",
"children": [
{
"caption": "Package Settings",
"mnemonic": "P",
"id": "package-settings",
"children": [
{
"caption": "CTagsAutoComplete",
"children": [
{
"command": "open_file",
"args": {
"file": "${packages}/CTagsAutoComplete/CTagsAutoComplete.sublime-settings"
},
"caption": "Settings"
}
]
}
]
}
]
}
]
总结
首先给出插件的完整源码:
import sublime
import sublime_plugin
import os
import re
def plugin_loaded():
global settings
settings = sublime.load_settings('CTagsAutoComplete.sublime-settings')
class CTagsAutoComplete(sublime_plugin.EventListener):
def on_query_completions(self, view, prefix, locations):
if is_disabled_in(view.scope_name(locations[0])):
return []
results = []
ctags_paths = [folder + '\\.tags' for folder in view.window().folders()]
ctags_rows = []
for ctags_path in ctags_paths:
if not is_file_exist(view, ctags_path):
return []
ctags_path = str(ctags_path)
ctags_file = open(ctags_path, encoding = 'utf-8')
ctags_rows += ctags_file.readlines()
ctags_file.close()
for rows in ctags_rows:
target = re.findall('^' + prefix + '.*', rows)
if target:
matched = re.split('\\t', str(target[0]))
trigger = matched[0]
trigger += '\\t(%s)' % 'CTags'
contents = re.findall(prefix + '[0-9a-zA-Z_]*\\(.*\\)', str(matched[2]))
if (len(matched) > 1 and contents):
results.append((trigger, contents[0]))
results = list(set(results))
results.sort()
return (results, sublime.INHIBIT_WORD_COMPLETIONS | sublime.INHIBIT_EXPLICIT_COMPLETIONS)
def is_disabled_in(scope):
excluded_scopes = settings.get("exclude_from_completion", [])
for excluded_scope in excluded_scopes:
if scope.find(excluded_scope) != -1:
return True
return False
def is_file_exist(view, file):
if (not view.window().folders() or not os.path.exists(file)):
return False
return True
plugin_loaded()
然后我会把这个插件集成起来并上传到网站上,让更多的人可以更方便的使用。 通过这个条目,我尝到了甜头。 在未来的发展过程中,可能会出现各种奇特的需求。 如果现有的插件无法提供帮助,那就自己动手吧。
如有侵权请联系删除!
Copyright © 2023 江苏优软数字科技有限公司 All Rights Reserved.正版sublime text、Codejock、IntelliJ IDEA、sketch、Mestrenova、DNAstar服务提供商
13262879759
微信二维码