-
Notifications
You must be signed in to change notification settings - Fork 5
/
choosy_single_selection.py
121 lines (91 loc) · 3.64 KB
/
choosy_single_selection.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
"""
The method for writing this was inspired from writing store_selections,
which has code based off of (and taken from) https://github.com/colinta/SublimeMarkAndMove,
but the idea (and I think all the code) in this is mine.
This is hereby released completely and irrevocably into the Public Domain.
store_selections has it's own licensing, so remember to look there as well.
- Joshua Landau <[email protected]>
"""
import sublime, sublime_plugin
from .store_selections import get_id, store_selections
# Dict of id: settings pairs for KeepStoredSelectionsClear
# Used to remove all relevant reagions and remake with unchanged settings
to_clear = {}
class ChoosySingleSelectionCommand(sublime_plugin.TextCommand):
"""
Remove all but one selection, keeping the choice from "index",
default 0 (first). Negative indexes also work.
Adds other selections to a visible cache, which you can cycle
though with choosy_selection_select.
"""
def run(self, edit, index=0, **settings):
to_clear[get_id(settings)] = settings
selections = self.view.sel()
old_selections = list(selections)
store_selections(self.view, old_selections, **settings)
selections.clear()
self.view.show(old_selections[index])
selections.add(old_selections[index])
class ChoosySelectionSelectCommand(sublime_plugin.TextCommand):
"""
Cycles through the cache created by choosy_single_selection.
"""
def run(self, edit, forward=True, **settings):
id = get_id(settings)
to_clear[id] = settings
stored_selections = self.view.get_regions(id)
# This can happen due to unwanted fallback in the keybindings,
# just ignore it
if not stored_selections:
return
# Remove the current cursor
selections = self.view.sel()
[old_selection] = selections
selections.clear()
# Move (index, shift, wrap)
index = stored_selections.index(old_selection)
index += 1 if forward else -1
index %= len(stored_selections)
# Add back in new position
self.view.show(stored_selections[index])
selections.add(stored_selections[index])
class KeepStoredSelectionsClear(sublime_plugin.EventListener):
"""
Gets rid of the cache created by choosy_single_selection in a greedy
but intelligent way.
"""
def on_selection_modified(self, view):
"""
If the selection is modified by anything other than us, remove the
cache.
"""
command, args, repeat_count = view.command_history(0)
if command not in ("choosy_single_selection", "choosy_selection_select"):
for id in to_clear:
store_selections(view, [], replace=True, id=id)
def on_deactivated(self, view):
"""
If we move away, on_selection_modified does not work. We have to add a cache
which will let us check whether the selection has changed manually.
Also, hide the cache, because it's silly to see it during, say, a find dialogue.
"""
for id in to_clear:
# Move the stored selections to a hidden buffer
selections = view.get_regions(id)
store_selections(view, selections, replace=True, id=id+" <cache>")
# Remove from view
store_selections(view, [], replace=True, id=id)
# Add the current selections to a buffer to check whether we can resume the stored selections
store_selections(view, view.sel(), replace=True, id="<check>")
def on_activated(self, view):
"""
If the selection has changed since the last look, clear the cache. Otherwise, restore it.
"""
selection_check = view.get_regions("<check>")
# Check if the selection has changed from cache
if view.sel() == selection_check:
for id in to_clear:
selections = view.get_regions(id+" <cache>")
# Add the region back
# "to_clear[id]" is its original settings dict
store_selections(view, selections, replace=True, **to_clear[id])