手机版
你好,游客 登录 注册
背景:
阅读新闻

如何开发 Sublime Text 2 的插件

[日期:2013-09-13] 来源:oschina.net  作者:青崖白鹿 [字体: ]

第三步 - 选定文本

Sublime最有用的功能之一就是具备多行选定的功能

现在,我们已经正式命名了我们的插件,可以开始从当前的buffer中获取CSS并且发送到Prefixr API上了。Sublime最有用的功能之一就是具备多行选定的功能。由于要获取选定的文件,我们需要把所有选定的行放入我们的插件中处理,而不仅仅是第一个选定的。

由于我们写的是一个文本命令,所以可以通过self.view访问当前view。view对象的self()方法将返回一个当前选定内容的iterable Region集合,我们可以通过花括号扫描到这些内容。若找不到花括号,可以扩大选定内容到周围的括号,以保证整个块有一个括号前缀。选定内容中是否包含花括号还将有利于我们后面对Prefixr API返回的内容作空白调整和格式调整。

 

braces = False
sels = self.view.sel()
for sel in sels:
    if self.view.substr(sel).find('{') != -1:
        braces = True
 

用这几行代码替换框架中的run()方法中的代码。

若未找到任何的花括号,我们需要循环检测每一个选定区段,把每一个区段和后括弧关联起来。之后,用带有to参数设置为 brackets的内建命令 expand_selectionl来确保获取了每个CSS块的完整内容。

if not braces:
    new_sels = []
    for sel in sels:
        new_sels.append(self.view.find('\}', sel.end()))
    sels.clear()
    for sel in new_sels:
        sels.add(sel)
    self.view.run_command("expand_selection", {"to": "brackets"})

若果你想再检查一次你的代码,你可以和源代码zip文件中的Prefixr1.py文件对比一下。

第四步 - 线程

为防止糟糕的连接破坏其他正常工作,我们需要确保在后台完成Prefixr API调用。

此时,选定的文本已经扩展到了能抓取每个CSS块的完整内容。现在,我们需要把他们发送打牌Prefixr API上。这只需要一个简单的HTTP请求,用urllib和urllib2模块就可以实现。但是,在发起请求之前,需要想想一个潜在的web请求延迟会对编辑器性能造成的影响。如因为某些原因,用户处在一个很慢的连接环境下,对Prefixr API的请求很可能需要好几秒钟乃至更多。

为防止糟糕的连接破坏其他正常工作,我们需要确保在后台完成Prefixr API调用。若你不了解线程,很基础的一种解释就是,线程是使你的程序的多个代码块在同一时间运行的机制。这在我们的插件环境中是很重要的,因为这样做可以避免在向Prefixr发送数据和等待响应的过程中Sublime处于不可用状态。

第五步 - 创建线程

我们将使用Python threading 模块来创建线程。要使用该模块,需要创建一个继承threading的新类。Thread包含一个所有线程代码都在其中执行的run()方法。

class PrefixrApiCall(threading.Thread):
    def __init__(self, sel, string, timeout):
        self.sel = sel
        self.original = string
        self.timeout = timeout
        self.result = None
        threading.Thread.__init__(self)

    def run(self):
        try:
            data = urllib.urlencode({'css': self.original})
            request = urllib2.Request('http://prefixr.com/api/index.php', data,
                headers={"User-Agent": "Sublime Prefixr"})
            http_file = urllib2.urlopen(request, timeout=self.timeout)
            self.result = http_file.read()
            return

        except (urllib2.HTTPError) as (e):
            err = '%s: HTTP error %s contacting API' % (__name__, str(e.code))
        except (urllib2.URLError) as (e):
            err = '%s: URL error %s contacting API' % (__name__, str(e.reason))

        sublime.error_message(err)
        self.result = False

这里,我们使用thread的__init__()方法来设置所有的在web请求中需要的数据变量。run()方法包含所有的设置代码和执行向Prefixr API 的http请求的代码。由于线程并发的执行,所以直接返回值是不可行的,取而代之的我们设置self.result作为调用的结果。

鉴于我们在我们的插件中开始使用其他一些模块,我们必须在程序顶端增加import语句。

import urllib
import urllib2
import threading

现在我们有了一个线程类来执行HTTP请求,我们需要为每一个selection块创建一个线程。为此,回到我们的PrefixrCommand类的run方法中,使用下面的循环:

threads = []
for sel in sels:
    string = self.view.substr(sel)
    thread = PrefixrApiCall(sel, string, 5)
    threads.append(thread)
    thread.start()

我们记录了每一个我们创建的线程,然后调用start()方法开启每一个线程。如果想再次检查你的工作,对比源代码文件zip文件中的filePrefixr1.py文件。

第六步 - 准备结果

现在,我们已经开始了实际的Prefixr API请求,在处理HTTP相应之前,我们需要处理最后几个问题。

首先,我们清楚所有的selection,因为之前我们修改了他们。稍后将把他们设置成一个更合理的状态。

self.view.sel().clear()

此外,我们开启一个新的Edit对象,把undo和redo操作组织在一起。我们指定我们在为prefix命令创建一个这样的组。

edit = self.view.begin_edit('prefixr')

作为最后一步,我们调用下面的方法来处理API的相应结果。

第七步 - 处理线程

此时,我们的线程已经在运行了,认知已经运行结束了。下一次,我们需要完成刚刚调用的handle_threads()方法。这一方法将循环处理线程列表并且寻找不再运行的线程。

def handle_threads(self, edit, threads, braces, offset=0, i=0, dir=1):
    next_threads = []
    for thread in threads:
        if thread.is_alive():
            next_threads.append(thread)
            continue
        if thread.result == False:
            continue
        offset = self.replace(edit, thread, braces, offset)
    threads = next_threads

如果线程仍然运行着,我们将其加入线程列表一遍后面再检测。如果result是False,则忽略它。然后,对于返回正确的结果,再调用一个马上就要说到的replace()方法。

linux
相关资讯       Sublime Text  Sublime Text 2 
本文评论   查看全部评论 (0)
表情: 表情 姓名: 字数

       

评论声明
  • 尊重网上道德,遵守中华人民共和国的各项有关法律法规
  • 承担一切因您的行为而直接或间接导致的民事或刑事法律责任
  • 本站管理人员有权保留或删除其管辖留言中的任意内容
  • 本站有权在网站内转载或引用您的评论
  • 参与本评论即表明您已经阅读并接受上述条款