zoukankan      html  css  js  c++  java
  • Sublime插件开发——简单的代码模板插件

        最近一段一直使用sublime进行golang开发,整体感觉很不错,虽然比不上eclipse之类IDE强大,但是用起来很轻巧便捷,开发golang完全做够了。由于有一部分代码复用率很高,经常要用到,而自己记性特别差也懒得每次自己敲,就希望能够像其他IDE的插件那样能直接插入代码模板,于是就研究了下sublime的插件开发(网上有很多人推荐Gist,但是发现由于网络原因适用Gist插件很慢,每次都要等很长时间)。
        装过插件的都知道sublime的插件采用python开发的,所以如果想要开发需要对python有初步的掌握。之所以说初步是因为sublime插件开发实际上是使用python调用subline提供的接口进行开发,就像MFC那样,你并不需要去关注每个动作底层是如何实现的(看了下应该 ),只需要调用这些动作接口完成一套操作即可。
        入门开发过程这里不再赘述,这里有一篇入门教程已经讲得很好了,在加上官方接口文档,应该还是比较简单的:

        下边就主要介绍一下我的这个小插件的开发

    一、功能确定

        还是老规矩,工欲善其事,必先利其器,我们先来确定下插件的功能。由于第一次开发,所以只要满足基本需求就行,不打算开发的太复杂,就确定了一下功能:

    • 将选中的代码添加到模板库里边
    • 从模板库里边选择指定代码插入到当前位置
    • 可以完成一些变量替换,如将模板中的{{date}}替换成当前日期


    二、功能设计

        我们来逐一分析这三个功能。首先第一个实现方式有很多,我们可以将所有模板都存在同一个文件中,适用分界符进行取分,但是如果这样的话我们无论删除修改添加时多要把所有模板遍历一遍进行判断,会变得很麻烦。所以可以直接将每个模板存一个文件,文件名直接以模板名命名,这样处理起来非常方便,可能有人说这样岂不是会生成一大堆文件,多了之后查找会不会很慢?我一直觉得任何程序设计要兼顾平衡实现的复杂度和性能才行,而不是一味偏激的只追求一方面。如sublime中我们平时常用的代码模板其实很有限,一般几十个而已(多了估计也记不住),对此直接单独写文件完全没问题,反而如果为了高效再去搞套索引,那就有点杀鸡用宰牛刀了。当然,其实为了方便使用,我们这里按照文件夹分组存放更合理些,不过目前懒得弄了,先这样吧。
        插入代码就很简单了,先遍历模板文件夹读出所有文件名供选择,然后读取对应文件插入到光标位置即可。
        变量替换就更简单了,插入前变量替换即可。当然,为了实现自定义变量需要添加一个配置文件。

    三、代码实现

        代码不细讲了,之前的教程文档看过的话下边代码就很简单了。    
        首先看下代码结构:

    template  #模板文件夹
    codemanage.py #插件代码
    Default (XXX).sublime-keymap #快捷键配置文件,XXX值平台
    var-map.conf  #替换变量配置文件,key=value

        codemanage.py代码如下:

    #-*- coding: UTF-8 -*-
    import sublime, sublime_plugin
    import os
    import os.path
    import time
    import sys
    
    reload(sys)   
    sys.setdefaultencoding('utf8')
    
    #写入模板,如果是新模板按照模板名创建一个文件,如果是旧模板则覆盖写原文件
    class CodeTplAddCommand(sublime_plugin.TextCommand):
        def run(self,edit):
            #获取当前选中内容
            selstr = ''
            sels = self.view.sel()
            for sel in sels:
                value = self.view.substr(sel)
                if value == '':
                    continue
                selstr = selstr + value + '
    '
    
            if selstr == '':
                sublime.message_dialog("Select content is empty.")
                return
    
            def on_done(name):
                if name=='':
                    sublime.message_dialog("Template name is empty.")
                    return
                #写入文件
                path = os.path.join(sublime.packages_path(),"CodeManage","template",name+".ctpl")
                try:
                    f = open(path, 'w')
                    print selstr
                    selstr.encode("gbk")
                    f.write(selstr)
                except Exception, e:
                    print e
                    sublime.message_dialog("Write template file fail:"+str(e))
                    return
                finally:
                    f.close()
    
            def on_change(name):
                return
    
            def on_cancel():
                return
    
            #输入模板名
            self.view.window().show_input_panel('Plese input the code template name','template',on_done,on_change,on_cancel)
    
    #将对应模板插入当前位置
    class CodeTplInsertCommand(sublime_plugin.TextCommand):
        def run(self,edit):
            filenames = []
            rootdir= os.path.join(sublime.packages_path(),"CodeManage","template")
            for p,d,files in os.walk(rootdir):
                filenames = files
    
            def on_sel_done(selvalue):
                if selvalue==-1:
                    return
                filename = filenames[selvalue]
                content = ''
    
                if filename=='':
                    sublime.message_dialog("Template is not exist.")
                    return
                path = os.path.join(sublime.packages_path(),"CodeManage","template",filename)
    
                try:
                    f =  open(path, 'r')
                    content = f.read()
                    if content=='':
                        sublime.message_dialog("Template file is empty")
                        return
                    content = ReplaceVar(content)
                except Exception, e:
                    sublime.message_dialog("Open template file fail:"+str(e))
                    return
                finally:
                    f.close()
                
                #把内容插入当前位置
                sels = self.view.sel()
                for sel in sels:
                    self.view.insert(edit,sel.begin(),content)
    
            #打开选择列表
            self.view.window().show_quick_panel(filenames,on_sel_done)
    
    #处理一些模板替换变量
    #将模板中{{XXX}}的变量替换成配置文件中的变量({{data}}等信息直接替换)
    def ReplaceVar(content):
        varmap = {
            '{{date}}':time.strftime('%Y-%m-%d',time.localtime(time.time()))
        }
        #读取变量
        try:
            path = os.path.join(sublime.packages_path(),"CodeManage","var-map.conf")
            f =  open(path, 'r')
            for line in f.readlines():
                if line=='':
                    continue
                value = line.split("=")
                varmap["{{"+value[0]+"}}"] = value[1]
        except Exception, e:
            sublime.message_dialog("Open var-map file fail:"+str(e))
            return
        finally:
            f.close()
        
        for (k,v) in varmap.items():
            content = content.replace(k,v)
        return content

        懂python应该可以看出来非常简单。

    四、总结

        现在虽然功能还不算完善,但是使用起来已经很方便了。可以看出sublime插件开发还是比较简单的,入门之后就可以很轻松的定制自己的轻量级IDE了。
        插件地址: github


  • 相关阅读:
    LeetCode 623. Add One Row to Tree
    LeetCode 894. All Possible Full Binary Trees
    LeetCode 988. Smallest String Starting From Leaf
    LeetCode 979. Distribute Coins in Binary Tree
    LeetCode 814. Binary Tree Pruning
    LeetCode 951. Flip Equivalent Binary Trees
    LeetCode 426. Convert Binary Search Tree to Sorted Doubly Linked List
    LeetCode 889. Construct Binary Tree from Preorder and Postorder Traversal
    LeetCode 687. Longest Univalue Path
    LeetCode 428. Serialize and Deserialize N-ary Tree
  • 原文地址:https://www.cnblogs.com/good-temper/p/3871304.html
Copyright © 2011-2022 走看看