網頁

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"
      },
      ......
      }

      刪除