写一个Sublime Text 2插件(CSS文件里px单位替换成rem单位)

三年前我就知道了sublime text 不过那时候用DW还是很爽的样子,后来有天想为难自己了,于是用了两年的vim和五笔,最近又觉得这么好编辑器也可以试试,改变一下自己,用一下的,不过由于工作的原因,没有坚持下来,有时候顺手似乎比先进更重要一些。
最近工作都是做一些移动端的页面,而微信的长按出现二维码有个bug,在ios里缩放的页面长按是不会出现“识别二维码”的。所以需要转换一下,不要让页面缩放,要自适应,这个时候就用rem单位来做的会比较好一些,而我的同事之前开发了一个px to  rem的工具https://github.com/stormtea123/viewtorem。用他的工具就可以搞定的。奈何我这等懒人,把这个工具给到别人还要和别人说的,觉得累。于是就想写个sublime text 插件算了。
很简单的一个需求:找到CSS文件里px单位改成rem单位。
第一步搜百度
凡事问百度,结果全是 How to Create a Sublime Text 2 Plugin 这篇文章的翻译,还不全,不会英语的要哭倒了。当然也有一些收获:Sublime Text 接口的中文文档 http://www.oschina.net/translate/sublime-text-plugin-api-reference 和 英文文档:http://www.sublimetext.com/docs/2/api_reference.html 。没有想到这个编辑器不同的版本借口命名还有差异,顶,好吧,不会的地方记得要看英文的。
第二步设置插件
先找到插件的目录,通过Tools -> New Plugin...来打开一个初始化的插件编辑文件,它会有这样的内容:
import sublime, sublime_plugin

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

然后Ctrl+s,来保存这个文件,这个时候电脑就会打开到要保存的目录(一般是:安装目录\Data\Packages\User)了,我们可以建一个目录pxtorem,也可以直接在打开的目录保存。保存为任何你喜欢的名字,关键是以.py为拓展名就可以了(你知道的,sublime text用的是python来写的),我们这里命名为text.py。
保存好了,现在我们要运行sublime text 给我们的哪个初始化插件例子啦,输入 ctrl+`打开Sublime的控制台,它是一个可以访问API的Python控制台。输入下面的Python代码来测试这个例子插件:
view.run_command('example')
这个时候注意观察当前的文件开头插入了“Hello,World”,当前文件也变成待保存的状态,好了,测试成功,我们按ctrl+z,
让它回到开始的状态的吧。
等等,为什么是“example”?
它是从前面插件例子里 class ExampleCommand 来的,你需要换一个属于你自己插件的名字,把ExampleCommand里的‘Example’改一下。这一改,然后有的人发现运行自己的插件名称运行不了了,原来这里的设置有个规则,你用驼峰命名,例如PxToRemCommand 你运行的时候需要是view.run_command(px_to_rem),即用下划线隔开,否则像例子那样好了,开头大写后面全是小写。
第三步设置快捷键
每次都要输入一下命令行,这个得烦死吧,我们先建立一个快捷键吧,这个也是sublime text 所擅长的。在你插件的目录下,新建一个文件,命名为Default (Windows).sublime-keymap然后内容为
[
    {
        "command": "px_to_rem",
        "keys": [
            "ctrl+alt+k"
        ]
    }
]
这个快捷键是 ctrl+alt+k,按下就会运行px_to_rem命令,相当与按下快捷键执行view.run_command(px_to_rem),你可以改成不会冲突的别的按键,试试看看生效了没。
第四步就是编写程序
1、从设置文件里读取信息,之前同事写的是json格式的,很熟悉呀
{
     "files": ["./test/style.css"],
    "root_value": 20,
    "unit_precision": 5,
    "prop_white_list": ["width", "height", "padding", "padding-top", "padding-right", "padding-bottom", "padding-left", "margin", "margin-top", "margin-right", "margin-bottom", "margin-left"],
    "replace": false,
    "media_query": false
}
保存。然后我们到之前我们建的插件文件text.py里去试试看能不能获取到我们的设置信息。
import sublime, sublime_plugin

SETTINGS_FILE = "px_to_rem.sublime-settings"

class PxToRemCommand(sublime_plugin.TextCommand):
     def run(self, edit):
          #load config
          settings = sublime.load_settings(SETTINGS_FILE)
          #file
          files = settings.get("files");
          print files

我们先用sublime.load_settings()把设置文件引入,然后用settings.get()去取我们想要的属性。最后用print 打印到控制台。然后我们用crtl+`打开控制台,然后我们运行我们的插件ctrl+alt+k,看看打印出我们想要的东西没。
2、我们在设置文件里有一个白名单,只有这个白名单里的属性我们才会去更改它的值单位px为rem。
取得设置文件白名单
<pre name="code" class="python">prop_white_list = settings.get("prop_white_list",[])


然后去找当前文件里(样式文件)白名单里的属性,这个时候用到sublime text 接口self.view.find_all() 如下:
for text in prop_white_list:
               matches[text] = self.view.find_all(text+r":(\s*(auto)?([+-]?\d*\.?\d+(px)?)?)+")

我这个正则写得不太好的,汗。这里取得了,sublime text编辑器里的Region集合,就是匹配区域的集合。这个Region 有begin()和end()等方法。详情看文档。
3、我们要把我们找到的区域集合里的“数值px”替换成“数值rem”,先取得数值计算成跟相对与跟rem的值,然后再替换px为rem,开始我想用的是replace替换,不过python里replace做不到,只能用的sub,匹配到值然后调用自己定义的函数replaceToRem处理,要用到replace要引入re这个库,用到的一些数学方法要用到math,要在页面顶部引入。
for text in prop_white_list:
               for i in matches[text]:
                    reStr = self.view.substr(i)
                    replaced = re.sub("(?P<number>([+-]?)\d*\.?\d+)",replaceToRem,reStr)
                    replaced = str(replaced).replace("px","rem")
                    #self.view.replace(edit, i, replaced)
                    print replaced
                    self.view.insert(edit, i.end(), ";"+replaced)

其中的函数replaceToRem 如下:
def replaceToRem(replaceString):
               #
               intStr = replaceString.group("number")
               intValue = float(intStr)
               #
               newValue = intValue / root_value
               #
               newValue = round(newValue,unit_precision)
               newValueStr = str(newValue)
               #
               newValueStr = re.sub("\.[0]+$","",newValueStr)
               return newValueStr
到这里一个sublime text插件算是差不多完成了。

第五步添加到设置菜单里
第六步发布
后面两步我就省略啦,可以参考这篇文章:http://www.welefen.com/how-to-develop-sublime-text-plugin.html 人家写得不错的。我写这个文章就是想大家学会如何从设置文件里获取设置,另外知道replace不能调用函数,而sub可以,最后sublime text不同版本的接口有一些有一点点的区别,sublime text的插件还是很容易写的,我几乎不用sublime text也不会python也可以写出来的哦。最后附上所有代码:
text.py文件
import sublime, sublime_plugin, re
import math

SETTINGS_FILE = "px_to_rem.sublime-settings"

class PxToRemCommand(sublime_plugin.TextCommand):
     def run(self, edit):
          #load config
          settings = sublime.load_settings(SETTINGS_FILE)
          #file
          files = settings.get("files");
          #get rootValue (int)
          root_value = int(settings.get("root_value",20))
          # toFixed the value (int)
          unit_precision = int(settings.get("unit_precision",5))
          #replace prop list (list)
          prop_white_list = settings.get("prop_white_list",[])
          # relpace or append to end
          replace = settings.get("replace",True)
          #
          media_query = settings.get("media_query",True)

          #self.view.insert(edit, 0, root_value)
          #content = self.view.substr(sublime.Region(0,self.view.size()-1))
          #
          matches ={}
          def replaceToRem(replaceString):
               #
               intStr = replaceString.group("number")
               intValue = float(intStr)
               #
               newValue = intValue / root_value
               #
               newValue = round(newValue,unit_precision)
               newValueStr = str(newValue)
               #
               newValueStr = re.sub("\.[0]+$","",newValueStr)
               return newValueStr


          for text in prop_white_list:
               matches[text] = self.view.find_all(text+r":(\s*(auto)?([+-]?\d*\.?\d+(px)?)?)+")


          for text in prop_white_list:
               for i in matches[text]:
                    reStr = self.view.substr(i)
                    replaced = re.sub("(?P<number>([+-]?)\d*\.?\d+)",replaceToRem,reStr)
                    replaced = str(replaced).replace("px","rem")
                    #self.view.replace(edit, i, replaced)
                    print replaced
                    self.view.insert(edit, i.end(), ";"+replaced)


          print matches
          #self.view.insert(edit, 0, matches)

px_to_rem.sublime-settings文件
{
     "files": ["./test/style.css"],
    "root_value": 20,
    "unit_precision": 5,
    "prop_white_list": ["width", "height", "padding", "padding-top", "padding-right", "padding-bottom", "padding-left", "margin", "margin-top", "margin-right", "margin-bottom", "margin-left"],
    "replace": false,
    "media_query": false
}

Default (Windows).sublime-keymap 文件
[
    {
        "command": "px_to_rem",
        "keys": [
            "ctrl+alt+k"
        ]
    }
]
Main.sublime-menu 文件
[
    {
        "id": "view",
        "children":
        [
            {
                "caption": "pxToRem",
                "id": "px-to-rem",
                "command": "px_to_rem"
            }
        ]
    }
]






郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。