Sumlime text 2 插件: Eval Sel


前言

Sublime text 2 確實是很不錯的編輯器,用了挺長一段時間。我認為是我等用不慣 Vim/Emacs 的凡人的最佳選擇。最近經常向周圍同事推薦。

正在學習 Scheme ,用不慣 DrRacket ,而且不太習慣用命令行形式的 REPL 。 於是准備自己開發一個簡單的插件,目的是運行當前選中的語句,並顯示其輸出。

此插件的代碼保存在 github 上, 有興趣的同學可以看一看 Eval Sel。 插件本身還有不少問題,今后會逐漸改進。

開發步驟

Sublime text 2 的插件開發使用的是 Python 。具體接口可以參考 API Reference。而 How to Create a Sublime Text 2 Plugin 提供了一個很好插件開發例子。

使用插件模板

使用 Sublime 菜單 Tools->New Plugin... ,即可創建新的插件:

        import sublime, sublime_plugin

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

Sublime的插件中含有一個或多個命令(Command)。每個命令的具體實現在 run 函數中。 現在此插件功能為在當前視圖開始處插入 "Hello, World!" 字符串。

保存並修改

在 Sublime 的 Packages 文件夾中, 創建新的文件夾 eval_sel 。 Packages 文件夾可以通過菜單 Preferences->Browse Packages 打開。

將已生成的文件保存在 eval_sel 文件中,命名為 eval_sel.py 。 將

 class ExampleCommand(sublime_plugin.TextCommand): 

重命名為:

 class evalselCommand(sublime_plugin.TextCommand): 

快捷鍵配置

在 eval_sel 文件夾下面建立文件:

  • Default (Linux).sublime-keymap
  • Default (OSX).sublime-keymap
  • Default (Windows).sublime-keymap

可以在這些文件中以json格式定義快捷鍵映射:

 [ { "keys": ["ctrl+alt+e"], "command": "evalsel" } ] 

這樣每次按 ctrl + alt + e 時,就會執行 evalsel 命令。

具體實現

獲取選中文本

view.sel() 能夠返回選中的區域集合(有可能存在多個選中區域)。獲取第一個選中區域。

 sel = self.view.sel()[0] 

view.substr 則能獲取區域所包含的文本

 expression = self.view.substr(sel) 
傳遞給解釋器

在 Sublime 中,可以使用 Python 的大部分標准類庫。這種情況可以使用 subprocess 啟動一個子進程,傳遞字符串到子進程的 stdin ,並從子進程的 stdout 獲取結果。

1. 啟動子進程

self.process = subprocess.Popen(evaluator, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) 

evaluator 是用來啟動解釋器的參數列表,一般是解釋器的路徑,比如使用 Racket 時為 ["racket"] (racket.exe 已經加入系統路徑)。 但這里需要注意一點,使用某些解釋器的時候,需要加入額外的參數,讓其采用交互模式,比如使用 Python 時為 ["python", "-u", "-i"]

stdin/stdout 設置為 subprocess.PIPE ,則表明打開指向 stdin/stdout 管道。

2. 將表達式傳遞給子進程

子進程的 stdin/stdout 可以當做標准的文件對象進行讀寫。 采用交互模式時,在寫入后,要注意調用 flush 刷新緩存。

self.process.stdin.write(expression + "\n") self.process.stdin.flush() 

3. 從子進程獲取結果

stdout 讀取內容時,需注意讀取時會被阻塞,所以要在另一個線程中讀取。這里實現了簡單的讀取線程。

    class readThread(threading.Thread):  
        def __init__(self, process, file_io, output):  
            self.file_io = file_io
            self.output = output
            self.process = process
            threading.Thread.__init__(self)

        def run(self):
            if not self.file_io:
                return

            while True:
                line = self.file_io.readline()

                if len(line) == 0:
                    break;

                sublime.set_timeout(functools.partial(self.output, 
                            "%s" % (line)), 0)
輸出結果

Sublime 為插件提供了 output_panel ,相當一個特殊的 view 對象。 需要通過 window 對象的接口,獲取 output_panel 對象。

        def show_output_view(self):
            if not self.output_view:
                self.output_view = self.view.window().get_output_panel("evalsel")
            self.view.window().run_command('show_panel', {'panel': 'output.evalsel'})

 

插入文本:

    def output(self, info):
        self.output_view.set_read_only(False)
        edit = self.output_view.begin_edit()
        
        self.output_view.insert(edit, self.output_view.size(), info)
        self.scroll_to_view_end()

        self.output_view.end_edit(edit)
        self.output_view.set_read_only(True)

發布

最簡單的方法是將插件發布到網上,讓用戶自己下載到 Packages 文件夾中。

但有更方便的方法就是,通過 Packages control 發布。參考 Submitting a Package 介紹,只需要簡單地幾步即可。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM