2012年6月30日 星期六

Sublime Text 2 - 同步捲動檔案視窗 Part.2

 

上一篇「Sublime Text 2 - 同步捲動檔案視窗 Part.1」的最後有提到,

因為「Synchronized File Scrolling」只有提供鍵盤操作的功能,並沒有提供滑鼠的操作,

所以必須要用另外一種方法來解決,這一篇文章就是要來介紹這個方法,不多廢話就直接看下去!

 


這一個要讓 Sublime Text 2 可以用滑鼠來操作多個文件的同步捲動,在「Community Sublime Packages」是找不到的,

其實我有點忘了我是怎麼找到這個方法的,好像是先看到 Youtube 的一段影片才知道有這麼一個方法,

所以就先把這個 Youtube 影片給貼出來,讓大家看一看,在看過之後也就應該知道怎麼操作。

 

Sublime Text 2 :: Scroll Multiple Files

 

我想很多人在看過影片之後就應該要怎麼操作讓 Sublime Text 2 能有滑鼠同步捲動多文件的功能,

但是呢…… 有些地方還是要特別的說明,如果不說的話一定會有很多人是不明白的,

首先我們就照著影片裡的說明到作者放在 bitbucket 的原始碼位置,

https://bitbucket.org/theblacklion/sublime_plugins/changeset/3ea0c9e35d2f

image

 

這時候還不用把這個原始碼的程式內容給複製下來,這時候應該要做的是開啟 Sublime Text 2 先……

開啟之後,我們要做的就是去開啟一個「New Plugin」的新檔案,

SNAGHTML7aeecb6

選擇「Tools > New Plugin…」之後就會有建立一個新的 Plugin 檔案

SNAGHTML7b040ee

接者把這個 New Plugin 檔案的 Line 3 ~ Line 5 給刪除,或是等一下把原始檔複製貼過來時給覆蓋上去也可以,

 

再來就是把原始檔程式碼從 Line 30 以後的程式內容給複製起來……

image

if 'views' not in globals():
    views = []
if 'active_syncer' not in globals():
    active_syncer = 0
 
 
class GlueViewsAddCommand(sublime_plugin.TextCommand):
 
    def run(self, edit):
        for view in views:
            if view.id() == self.view.id():
                sublime.status_message('View already in glued group.')
                return
        views.append(self.view)
        sublime.status_message('Added view to glued group.')
        syncer.timeout = syncer.timeout_min
 
 
class GlueViewsRemoveCommand(sublime_plugin.TextCommand):
 
    def run(self, edit):
        id = self.view.id()
        for view in views:
            if view.id() == id:
                views.remove(view)
                sublime.status_message('Removed view from glued group.')
                return
        sublime.status_message('View not in glued group.')
 
 
class GlueViewsClearCommand(sublime_plugin.TextCommand):
 
    def run(self, edit):
        global views
        views = []
        sublime.status_message('Removed all views from glued group.')
 
 
class ViewSynchronizer(object):
 
    def __init__(self, id):
        self.id = id
        self.timeout_min = 10
        self.timeout_max = 1000
        self.timeout = self.timeout_max
        self.timeout_inc_step = 10
 
    def prune_views(self):
        for view in views[:]:
            if not view.window():
                print 'remove view', view.id()
                views.remove(view)
        if len(views) == 0:
            self.timeout = self.timeout_max
 
    def get_active_view(self):
        for view in views:
            window = view.window()
            if window:
                if window.active_view().id() == view.id():
                    return view
        return None
 
    def get_other_views(self):
        active_view = self.get_active_view()
        other_views = []
        for view in views:
            if view.id() == active_view.id():
                continue
            other_views.append(view)
        return other_views
 
    def run(self):
        global active_syncer
        if active_syncer != self.id:
            return
        # print '---', self.id, len(views), self.timeout
        self.prune_views()
        active_view = self.get_active_view()
        if active_view:
            settings = active_view.settings()
            last_row = settings.get('glue_views_last_row', None)
            cur_row, _ = active_view.rowcol(active_view.visible_region().begin())
            if last_row is not None:
                if last_row != cur_row:
                    self.timeout = self.timeout_min
                    diff = cur_row - last_row
                    # print 'active view', active_view.id(), 'diff', diff
                    for view in self.get_other_views():
                        row, _ = view.rowcol(view.visible_region().begin())
                        # print 'view', view.id(), 'currently at row', row
                        view.run_command('scroll_lines', dict(amount=-diff))
                        sels = view.sel()
                        if sels:
                            row, col = view.rowcol(sels[0].end())
                            sels.clear()
                            row += diff
                            sels.add(sublime.Region(view.text_point(int(row), col)))
                        view.settings().set('glue_views_last_row', None)
            settings.set('glue_views_last_row', cur_row)
        sublime.set_timeout(self.run, self.timeout)
        self.timeout += self.timeout_inc_step
        self.timeout = min(self.timeout, self.timeout_max)
 
 
active_syncer += 1
syncer = ViewSynchronizer(active_syncer)
syncer.run()
 
 
class GlueViewsListener(sublime_plugin.EventListener):
 
    def on_activated(self, view):
        view.settings().set('glue_views_last_row', None)

 

接著就是把複製起來的程式碼給貼到剛才所建立的 New Plugin 中…

SNAGHTML7b403a0

 

貼上去之後就可以進行存檔,直接輸入快速鍵「Ctrl + S」就可以存檔,

檔案存放的位置在 Sublime Text 2 > Packafes > User 目錄下,

image

而要存的檔案名稱就直接使用作者所命名的名稱「glue_views.py

檔案儲存完成之後,在「Sublime Text 2 > Packafes > User」目錄下就可以看到建立好的 Plugin 檔案,

image

 

而接下來要做的就是建立 Keymap 定義,點選「Preferences > Key Bindings – User」的選項,

image

 

開啟「Default.sublime-keymap」檔案,這個檔案的名稱會隨著你的作業系統不同而有不同的名稱,

SNAGHTML7bba24f

 

如果照著影片裡的作法,應該是要把原本在原始碼程式中前面所註解的地方,把定義 keymap 的資料給貼上去,

image

作業系統是使用 Windows 的朋友,如果是直接貼這三個定義資料的話,一定會有問題,

 

如果是看著影片中的設定資料而自行做調整然後輸入的話,也一定會遇到問題,

image

因為這是給 OSX 作業系統下所使用的設定,如果是 Windows 作業系統用這樣的設定,就會跟原本的預設 Keymap 衝突,

所以我建議可以採用我的定義內容:

[
    { "keys": ["ctrl+alt+g"], "command": "glue_views_add"},
    { "keys": ["ctrl+alt+r"], "command": "glue_views_remove"},
    { "keys": ["ctrl+alt+c"], "command": "glue_views_clear"}
]

當我們要把需要同步捲動的文件給加入到 Glue Views 時,只需要輸入「Ctrl + Alt + G」就好,

如果是要解除某個文件的同步捲動時,就輸入「Ctrl + Alt + R」,

如果是要解除全部的 Glue Views 內容,就輸入「Ctrl + Alt + C」,

只要去聯想到 Group, Remove, Clear 的字首就可以了。

 

PS.

這邊建議各位一定要調整你的 Keymap 設定值,因為每個人的電腦使用設定都不盡相同,

所以有可能我這樣的 Keymap 設定在你的電腦上是無法順利執行或是與其他的快速鍵設定衝突。

一定要自己再調整過這個 Keymap 設定內容!

 

 

程式與資料都建立完成之後,接下來就是要來試試看這個功能要怎麼用啦!

使用兩個橫列(或是直行)開啟兩個檔案,

SNAGHTML7ce0d03

 

要讓這兩個橫列可以使用滑鼠同步捲動,就先分別 Focus 在自己的文件上然後輸入「Ctrl + Alt + G

SNAGHTML7d8a108

SNAGHTML7dabb8a

都分別操作加入 Glue Views 之後就可以試著用滑鼠來拖曳文件的 Scroll Bar 或是在 MiniMap 移動文件,

就應該可以看到兩份文件同時地移動文件內容,

SNAGHTML7df2ac0

 

如果你要解除某個文件的 Glue View,只要先 Focus 在文件上然後輸入「Ctrl + Alt + R」就可以了

SNAGHTML7e461e6

 

如果你是要清除全部的 Glue Views 內容的話,輸入「Ctrl + Alt  + C」就可以清除了。

SNAGHTML7e91be2

 

最後再來個實際操作影片來讓大家更清楚了解…


(建議解析度選擇 720P 然後以全螢幕觀看)

 

以上

7 則留言:

  1. 你好,請問你圖的 " 符號會反白,是如何做的,謝謝。 PS. 看其他網頁的圖,有的 { } 也會反白。

    回覆刪除
    回覆
    1. BracketHighlighter
      http://kevintsengtw.blogspot.tw/2012/03/sublime-text-2-part8-package.html#.VIHb7DGUepQ

      刪除
    2. 你好,有裝BracketHighlighter。
      我的 OS 是 Win7-32bit,ST2/3 install 版和 portable 版都試過了,還是無法有括號反白,只有行號左邊的顯示。

      刪除
    3. 這你要去做一些設定上的調整,在 BracketHighlighter 的 Github Repository 裡都有說明。
      因為每個人所做的設定都有不同,如果真的有問題的話,建議你去 BracketHighlighter 的 Github 裡去問,
      或是直接再去 Google 相關的資料,因為在這邊問我並不會得到答案的。

      刪除
    4. BracketHighlighter 對於 C/C++ 是 default 是 underline,按照底下步驟改就可以顯示 hightlight。
      1. Menu->Preferences->Package Settings->Bracket Highlighter->Bracket Settings-Default
      2. Copy part of "bracket_systles{...}" to Bracket Settings-User
      3. Search "default{...style...}"
      4. Modify "style:underline" to "style:hightlight"
      5. Modify "color:brackethighlighter.default" to "color:entity.name.class"

      刪除
    5. 貼出我的設定供參考...
      {
      // Define region highlight styles
      "bracket_styles": {
      "default": {
      "icon": "dot",
      // BH1's original default color for reference
      "color": "entity.name.class",
      // "color": "brackethighlighter.default",
      "style": "hightlight"
      },
      ......
      }

      刪除

提醒

千萬不要使用 Google Talk (Hangouts) 或 Facebook 及時通訊與我聯繫、提問,因為會掉訊息甚至我是過了好幾天之後才發現到你曾經傳給我訊息過,請多多使用「詢問與建議」(在左邊,就在左邊),另外比較深入的問題討論,或是有牽涉到你實作程式碼的內容,不適合在留言板裡留言討論,請務必使用「詢問與建議」功能(可以夾帶檔案),謝謝。