你好,欢迎进入江苏优软数字科技有限公司官网!

诚信、勤奋、创新、卓越

友好定价、专业客服支持、正版软件一站式服务提供

13262879759

工作日:9:00-22:00

利用 CTags 开发一个 Sublime Text 代码补完插件

发布时间:2025-01-27

浏览次数:0

作者|

喜欢使用文本的朋友知道文本等同于Linux上的VIM。它们都具有强大的可伸缩函数,具有多种功能和快速速度。对于小型文件和项目效率,它特别有效,因此,如果不是特别的,它不是专门用于复杂项目,我通常使用文本和编译。

但是,在使用文本的过程中,我发现了一个问题:文本本身的自动完成功能搜索当前视图中正在编辑的文件的功能。当我想在其他文件中使用自定义功能时,没有自动完成功能。的。当自定义功能太多时,效率将大大降低,因此我开始寻找具有相关功能的插头。

一开始,我使用了一个非常流行的“”插头-in。尝试它真的很容易,但是不幸的是,此插头不支持C/C ++,并且所占用的空间很大。我必须采取不同的方法来追求简单和轻巧的方法。后来,发现了一个“全”插头。此插头扩展了文本的默认自动完成功能。您可以在当前视图中打开的所有文件中找到定义函数和变量。尽管它运行良好,但显然它的问题也很好,但有必要同时打开多个文件,这非常不便,所以我再次放弃。

在寻找很长一段时间之后,我找不到想要的插头,所以我开始考虑我不妨写下这样的插头sublime text 查看插件,只需借此机会开始即可。目前,我只是想知道我是否可以使用CTAG。它可以在当前项目中提取所有自定义功能,生成.tags文件并提供符号跳跃功能。添加文本的自动完成功能还不够。

为了完成此插头,我在线搜索了相关信息,找到了相关的材料并重新考虑了它。同时,我参考了所有插件的源代码。

应该提到的是,在此处不会提及在文本下安装CTAG的方法,因此请询问自己。

插件的想法

苍凉

读取设置并设置在设置中添加的语言禁用插件函数

苍凉

检测.tag文件是否存在,如果没有存在,它将直接

苍凉

在当前文件夹中读取.tag文件

苍凉

常规匹配功能名称名称

苍凉

常规匹配功能主体

苍凉

添加到自动完成界面

动笔

新插头-in

当然,在撰写文本插件的开始时,您需要首先了解文本提供的各种接口。为此,我去了Text的官方网站查找相关文档:如何进行文本[1]和文本[2]。

插件substitute_sublime text 查看插件_插件查看群成员退出

首先,在文本中选择“工具 - > - > new”以创建新的最基本的插件-in文档:

  1. import sublime

  2. import sublime_plugin

  3. class ExampleCommand(sublime_plugin.TextCommand):

  4.    def run(self, edit):

  5.        self.view.insert(edit, 0, "Hello, World!")

这里的和谐是必要的模块,特定类别和方法可以指官方API [3]。

然后,将此文件保存到文件夹的文件夹(用户文件夹的上一层的第一层)(默认保存的位置),然后将其命名为.py。尽管命名没有限制,但最好以插件的名称统一命名。

然后返回文本,通过快捷键Ctrl+`输入文本,然后输入视图。 ('')。如果下面显示“ Hello World”,则意味着插头 - 已正常加载。

“”此处“”的原因是因为该命令的名称是根据资本角色拆分的。该示例是“”,也可以直接访问。

文本中的术语

苍凉

:文字的当前窗口对象

苍凉

查看:在文本文本中打开的查看对象

苍凉

:文本交互式列表由快捷方式Ctrl+Shift+p在文本中打开

确定插头-in接口类型

文本下的插件-in命令中有3种类型的命令(全部来自模块):

苍凉

类[4]:通过查看对象提供对所选文件/缓冲区的内容的访问。

苍凉

类[5]:通过对象提供对当前窗口的引用

苍凉

类[6]:此类不引用任何特定的窗口或文件/缓冲区,因此很少使用

两种类型的事件监控类型:

苍凉

插件查看群成员退出_sublime text 查看插件_插件substitute

类[7]:监视文本中的各种事件并执行命令

苍凉

类[8]:提供类似事件但绑定到特定视图的类。

2个输入处理程序:

苍凉

类[9]:可用于接受中的文本输入。

苍凉

类[10]:可用于从列表项接收选择输入。

因为我要实现的功能相对简单,所以我只需要监视输入事件并触发自动完成功能,因此需要使用类。在此类下方找到该方法,以处理触发器自动完成时执行的命令。然后刚刚修改代码:

  1. import sublime

  2. import sublime_plugin

  3. class CTagsAutoComplete(sublime_plugin.EventListener):

  4.    def on_query_completions(self, view, prefix, locations):

苍凉

查看:当前视图

苍凉

:触发​​自动完成时输入的文本

苍凉

:当触发器自动完成时,输入在缓存区域的位置。您可以使用此参数确定以执行不同命令的语言

苍凉

返回类型:

◈没有

h [[“ \ t提示”,“”,其中\ t提示是可选的,请在自动函数名称中添加提示

)(,标志),其中包含自动完成语句的列表,如上所述;标志是一个附加参数,可用于控制文本随附的自动完成功能是否随附

读取CTAGS文件

为了读取.tag文件,您必须首先确定是否打开了当前项目。同时,是否存在.tag文件,然后读取.tag文件的所有内容:

  1. import sublime

  2. import sublime_plugin

  3. import os

  4. import re

  5. class CTagsAutoComplete(sublime_plugin.EventListener):

  6.    def on_query_completions(self, view, prefix, locations):

  7.        results = []

  8.        ctags_paths = [folder + '\.tags' for folder in view.window().folders()]

  9.        ctags_rows  = []

  10.        for ctags_path in ctags_paths:

  11.            if not is_file_exist(view, ctags_path):

  12.                return []

  13.            ctags_path = str(ctags_path)

  14.            ctags_file = open(ctags_path, encoding = 'utf-8')

  15.            ctags_rows += ctags_file.readlines()

  16.            ctags_file.close()

  17. def is_file_exist(view, file):

  18.    if (not view.window().folders() or not os.path.exists(file)):

  19.        return False

  20.    return True

通过上述操作,您可以在当前项目下的所有.TAG文件中读取内容。

分析CTAGS文件

首先是在.tags文件中获取行:

  1. for rows in ctags_rows:

  2.    target = re.findall('^' + prefix + '.*', rows)

找到一旦找到,通过正则表达式处理线的数据:

  1. if target:

  2.    matched = re.split('\t', str(target[0]))

  3.    trigger = matched[0] # 返回的第一个参数,函数名称

  4.    trigger += '\t(%s)' % 'CTags' # 给函数名称后加上标识 'CTags'

  5.    contents = re.findall(prefix + '[0-9a-zA-Z_]*\(.*\)', str(matched[2])) # 返回的第二个参数,函数的具体定义

  6.    if (len(matched) > 1 and contents):

  7.        results.append((trigger, contents[0]))

  8.        results = list(set(results)) # 去除重复的函数

  9.        results.sort() # 排序

处理完成后,可以将其返回。考虑到最好在.tags中显示该函数。我不需要显示文本随附的自动完成功能(当前页面中的变量和功能提取)。因此,我的返回结果如下:

  1. return (results, sublime.INHIBIT_WORD_COMPLETIONS | sublime.INHIBIT_EXPLICIT_COMPLETIONS)

添加配置文件

考虑到能够关闭插件的功能,您需要添加配置文件以指定不打开插件函数的语言。在这里,我指的是“全部”的代码:

  1. def plugin_loaded():

  2.    global settings

  3.    settings = sublime.load_settings('CTagsAutoComplete.sublime-settings')

  4. def is_disabled_in(scope):

  5.    excluded_scopes = settings.get("exclude_from_completion", [])

  6.    for excluded_scope in excluded_scopes:

  7.        if scope.find(excluded_scope) != -1:

  8.            return True

  9.    return False

  10. if is_disabled_in(view.scope_name(locations[0])):

  11.    return []

此处使用的配置文件需要添加到插件所在的文件夹中。名称为.-,内容为:

  1. {

  2.    // An array of syntax names to exclude from being autocompleted.

  3.    "exclude_from_completion": [

  4.        "css",

  5.        "html"

  6.    ]

  7. }

添加设置文件

使用配置文件,您还需要在文本的“ - >”下添加相应的设置。它也放在插件所在的文件夹中。名称是主要的。 -菜单:

  1. [

  2.    {

  3.        "caption": "Preferences",

  4.        "mnemonic": "n",

  5.        "id": "preferences",

  6.        "children": [

  7.            {

  8.                "caption": "Package Settings",

  9.                "mnemonic": "P",

  10.                "id": "package-settings",

  11.                "children": [

  12.                    {

  13.                        "caption": "CTagsAutoComplete",

  14.                        "children": [

  15.                            {

  16.                                "command": "open_file",

  17.                                "args": {

  18.                                    "file": "${packages}/CTagsAutoComplete/CTagsAutoComplete.sublime-settings"

  19.                                },

  20.                                "caption": "Settings"

  21.                            }

  22.                        ]

  23.                    }

  24.                ]

  25.            }

  26.        ]

  27.    }

  28. ]

总结

首先给出插件的完整源代码:

  1. import sublime

  2. import sublime_plugin

  3. import os

  4. import re

  5. def plugin_loaded():

  6.    global settings

  7.    settings = sublime.load_settings('CTagsAutoComplete.sublime-settings')

  8. class CTagsAutoComplete(sublime_plugin.EventListener):

  9.    def on_query_completions(self, view, prefix, locations):

  10.        if is_disabled_in(view.scope_name(locations[0])):

  11.            return []

  12.        results = []

  13.        ctags_paths = [folder + '\.tags' for folder in view.window().folders()]

  14.        ctags_rows  = []

  15.        for ctags_path in ctags_paths:

  16.            if not is_file_exist(view, ctags_path):

  17.                return []

  18.            ctags_path = str(ctags_path)

  19.            ctags_file = open(ctags_path, encoding = 'utf-8')

  20.            ctags_rows += ctags_file.readlines()

  21.            ctags_file.close()

  22.        for rows in ctags_rows:

  23.            target = re.findall('^' + prefix + '.*', rows)

  24.            if target:

  25.                matched = re.split('\t', str(target[0]))

  26.                trigger = matched[0]

  27.                trigger += '\t(%s)' % 'CTags'

  28.                contents = re.findall(prefix + '[0-9a-zA-Z_]*\(.*\)', str(matched[2]))

  29.                if (len(matched) > 1 and contents):

  30.                    results.append((trigger, contents[0]))

  31.                    results = list(set(results))

  32.                    results.sort()

  33.        return (results, sublime.INHIBIT_WORD_COMPLETIONS | sublime.INHIBIT_EXPLICIT_COMPLETIONS)

  34. def is_disabled_in(scope):

  35.    excluded_scopes = settings.get("exclude_from_completion", [])

  36.    for excluded_scope in excluded_scopes:

  37.        if scope.find(excluded_scope) != -1:

  38.            return True

  39.    return False

  40. def is_file_exist(view, file):

  41.    if (not view.window().folders() or not os.path.exists(file)):

  42.        return False

  43.    return True

  44. plugin_loaded()

之后,我将集成此插头,然后将其上传到顶部,以促进更多的人使用。通过这个条目sublime text 查看插件,我品尝了甜味。在未来的开发过程中,可能会出现各种独特的需求。如果现有的插件无法提供帮助,请继续使用。

如有侵权请联系删除!

13262879759

微信二维码