PageRenderTime 52ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/glue_views.py

https://bitbucket.org/theblacklion/sublime_plugins/
Python | 144 lines | 126 code | 5 blank | 13 comment | 0 complexity | d2459472bab0b1c847a7e6734c8319c5 MD5 | raw file
Possible License(s): MIT
  1. '''
  2. A text command which takes multiple views and enables an event listener to
  3. monitor them. If the visible region of the active view changes, the other views
  4. get moved by the same amount either up or down.
  5. Example use cases:
  6. - Opening two or more files side by side in order to diff them.
  7. - Opening a file and it's clone side by side to diff it.
  8. Known limitations:
  9. - Scrolling of slaves is row-wise. I don't get pixel-wise values.
  10. - Hiding a view which is glued drops it from the list. This is due to Sublime
  11. returning None on view.window() if it's not visible anymore.
  12. For use add something like this to your user definable key bindings file:
  13. { "keys": ["alt+plus"], "command": "glue_views_add"},
  14. { "keys": ["alt+minus"], "command": "glue_views_remove"},
  15. { "keys": ["alt+#"], "command": "glue_views_clear"}
  16. @author: Oktay Acikalin <ok@ryotic.de>
  17. @license: MIT (http://www.opensource.org/licenses/mit-license.php)
  18. @since: 2011-04-08
  19. '''
  20. import sublime
  21. import sublime_plugin
  22. if 'views' not in globals():
  23. views = []
  24. if 'active_syncer' not in globals():
  25. active_syncer = 0
  26. class GlueViewsAddCommand(sublime_plugin.TextCommand):
  27. def run(self, edit):
  28. for view in views:
  29. if view.id() == self.view.id():
  30. sublime.status_message('View already in glued group.')
  31. return
  32. views.append(self.view)
  33. sublime.status_message('Added view to glued group.')
  34. syncer.timeout = syncer.timeout_min
  35. class GlueViewsRemoveCommand(sublime_plugin.TextCommand):
  36. def run(self, edit):
  37. id = self.view.id()
  38. for view in views:
  39. if view.id() == id:
  40. views.remove(view)
  41. sublime.status_message('Removed view from glued group.')
  42. return
  43. sublime.status_message('View not in glued group.')
  44. class GlueViewsClearCommand(sublime_plugin.TextCommand):
  45. def run(self, edit):
  46. global views
  47. views = []
  48. sublime.status_message('Removed all views from glued group.')
  49. class ViewSynchronizer(object):
  50. def __init__(self, id):
  51. self.id = id
  52. self.timeout_min = 10
  53. self.timeout_max = 1000
  54. self.timeout = self.timeout_max
  55. self.timeout_inc_step = 10
  56. def prune_views(self):
  57. for view in views[:]:
  58. if not view.window():
  59. print 'remove view', view.id()
  60. views.remove(view)
  61. if len(views) == 0:
  62. self.timeout = self.timeout_max
  63. def get_active_view(self):
  64. for view in views:
  65. window = view.window()
  66. if window:
  67. if window.active_view().id() == view.id():
  68. return view
  69. return None
  70. def get_other_views(self):
  71. active_view = self.get_active_view()
  72. other_views = []
  73. for view in views:
  74. if view.id() == active_view.id():
  75. continue
  76. other_views.append(view)
  77. return other_views
  78. def run(self):
  79. global active_syncer
  80. if active_syncer != self.id:
  81. return
  82. # print '---', self.id, len(views), self.timeout
  83. self.prune_views()
  84. active_view = self.get_active_view()
  85. if active_view:
  86. settings = active_view.settings()
  87. last_row = settings.get('glue_views_last_row', None)
  88. cur_row, _ = active_view.rowcol(active_view.visible_region().begin())
  89. if last_row is not None:
  90. if last_row != cur_row:
  91. self.timeout = self.timeout_min
  92. diff = cur_row - last_row
  93. # print 'active view', active_view.id(), 'diff', diff
  94. for view in self.get_other_views():
  95. row, _ = view.rowcol(view.visible_region().begin())
  96. # print 'view', view.id(), 'currently at row', row
  97. view.run_command('scroll_lines', dict(amount=-diff))
  98. sels = view.sel()
  99. if sels:
  100. row, col = view.rowcol(sels[0].end())
  101. sels.clear()
  102. row += diff
  103. sels.add(sublime.Region(view.text_point(int(row), col)))
  104. view.settings().set('glue_views_last_row', None)
  105. settings.set('glue_views_last_row', cur_row)
  106. sublime.set_timeout(self.run, self.timeout)
  107. self.timeout += self.timeout_inc_step
  108. self.timeout = min(self.timeout, self.timeout_max)
  109. active_syncer += 1
  110. syncer = ViewSynchronizer(active_syncer)
  111. syncer.run()
  112. class GlueViewsListener(sublime_plugin.EventListener):
  113. def on_activated(self, view):
  114. view.settings().set('glue_views_last_row', None)