Skip to content

Commit c255455

Browse files
committed
Merge pull request #25 from r-stein/selection_fields_add
Improved and emphasized selection fields `add` functionality
2 parents ffd0d31 + 97c54d0 commit c255455

4 files changed

Lines changed: 78 additions & 19 deletions

File tree

Default.sublime-commands

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
{ "command": "jump_to_last_region", "caption" : "MultiEditUtils: Jump to last region" },
33
{ "command": "add_last_selection", "caption" : "MultiEditUtils: Add last selection" },
44
{ "command": "selection_fields", "caption": "MultiEditUtils: Selection as Fields", "args": {"mode": "toggle"} },
5+
{ "command": "selection_fields", "caption": "MultiEditUtils: Selection as Fields - Add Selections to Fields", "args": {"mode": "add"} },
56
{ "command": "cycle_through_regions", "caption" : "MultiEditUtils: Cycle through regions" },
67
{ "command": "normalize_region_ends", "caption" : "MultiEditUtils: Normalize region ends" },
78
{ "command": "split_selection", "caption" : "MultiEditUtils: Split selection" },

MultiEditUtils.sublime-settings

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
{
22
"live_split_selection" : true,
3+
// the highlighting scope of fields
4+
"selection_fields.scope.fields": "comment",
5+
// the highlighting scope of fields added via the `add` mode
6+
"selection_fields.scope.added_fields": "none",
7+
// whether the add command of selection fields should add separated field,
8+
// such that the special keybindings are not enabled via the add command
9+
"selection_fields.add_separated": true,
310
// whether the tab key should jump to the next field during the selection field mode
411
"selection_fields_tab_enabled": true,
512
// whether the escape key should cancel the selection field mode

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,12 @@ Arguments:
101101
- `only_other` (`false`) ignores the current selection for pop and go next actions.
102102

103103
Suggestion for more keybindings based on the arguments:
104+
104105
``` js
105106
// default use of selection_fields
106107
{ "keys": ["alt+d"], "command": "selection_fields" },
108+
// add the current selections as a fields
109+
{ "keys": ["alt+a"], "command": "selection_fields", "args": {"mode": "add"} },
107110
// jump and remove current selection in selection_fields
108111
{ "keys": ["ctrl+alt+d"], "command": "selection_fields",
109112
"args": {"mode": "smart", "only_other": true} },

selection_fields.py

Lines changed: 67 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,53 @@
99
else:
1010
_FLAGS = sublime.DRAW_EMPTY | sublime.DRAW_OUTLINED
1111

12-
_SCOPE = "comment"
1312

14-
def _set_fields(view, regions):
13+
def get_settings(key, default=None):
14+
"""Get the setting specified by the key."""
15+
settings = sublime.load_settings("MultiEditUtils.sublime-settings")
16+
return settings.get(key, default)
17+
18+
19+
def _get_settings(key, default=None):
20+
"""
21+
Get the setting specified by the key,
22+
with the prefix `selection_fields.`.
23+
"""
24+
return get_settings("selection_fields.{0}".format(key), default)
25+
26+
27+
def _set_fields(view, regions, added_fields=False):
1528
"""Set the fields as regions in the view."""
1629
# push the fields to the view, kwargs for ST3 and pos args for ST2
30+
if not added_fields:
31+
reg_name = "meu_sf_stored_selections"
32+
scope_setting = "scope.fields"
33+
else:
34+
reg_name = "meu_sf_added_selections"
35+
scope_setting = "scope.added_fields"
36+
scope = _get_settings(scope_setting, "comment")
1737
if _ST3:
18-
view.add_regions("meu_sf_stored_selections", regions, scope=_SCOPE,
19-
flags=_FLAGS)
38+
view.add_regions(reg_name, regions, scope=scope, flags=_FLAGS)
2039
else:
21-
view.add_regions("meu_sf_stored_selections", regions, _SCOPE, _FLAGS)
40+
view.add_regions(reg_name, regions, scope, _FLAGS)
41+
42+
43+
def _get_fields(view, added_fields=True):
44+
fields = view.get_regions("meu_sf_stored_selections")
45+
if added_fields:
46+
fields.extend(view.get_regions("meu_sf_added_selections"))
47+
return fields
48+
49+
50+
def _erase_added_fields(view):
51+
view.erase_regions("meu_sf_added_selections")
52+
53+
54+
def _erase_fields(view):
55+
view.erase_regions("meu_sf_stored_selections")
56+
view.erase_regions("meu_sf_added_selections")
57+
view.erase_status("meu_field_message")
58+
2259

2360
def _change_selection(view, regions, pos):
2461
"""Extract the next selection, push all other fields."""
@@ -41,11 +78,10 @@ def _change_selection(view, regions, pos):
4178

4279
def _restore_selection(view, only_other):
4380
"""Restore the selection from the pushed fields."""
44-
sel_regions = view.get_regions("meu_sf_stored_selections")
81+
sel_regions = _get_fields(view)
4582
if not only_other:
4683
sel_regions.extend(view.sel())
47-
view.erase_regions("meu_sf_stored_selections")
48-
view.erase_status("meu_field_message")
84+
_erase_fields(view)
4985
return sel_regions
5086

5187

@@ -54,7 +90,7 @@ def _execute_jump(view, jump_forward, only_other):
5490
Add the selection to the fields and move the selection to the
5591
next field.
5692
"""
57-
regions = view.get_regions("meu_sf_stored_selections")
93+
regions = _get_fields(view)
5894

5995
try:
6096
# search for the first field, which is behind the last selection
@@ -80,6 +116,7 @@ def _execute_jump(view, jump_forward, only_other):
80116
pos = pos + delta
81117
return regions, pos
82118

119+
83120
def _subtract_selection(pushed_regions, sel_regions):
84121
"""Subtract the selections from the pushed fields."""
85122
for reg in pushed_regions:
@@ -121,14 +158,16 @@ def run(self, edit, mode="smart", jump_forward=True, only_other=False):
121158
)
122159
return
123160
view = self.view
124-
has_regions = bool(view.get_regions("meu_sf_stored_selections"))
161+
has_fields = bool(_get_fields(view))
162+
has_only_added_fields = (not _get_fields(view, added_fields=False) and
163+
_get_settings("add_separated", True))
125164
do_push = {
126165
"pop": False,
127166
"remove": False,
128167
"push": True,
129168
"subtract": False,
130169
"add": False # add is specially handled
131-
}.get(mode, not has_regions)
170+
}.get(mode, not has_fields)
132171
# the regions, which should be selected after executing this command
133172
sel_regions = None
134173

@@ -138,18 +177,23 @@ def run(self, edit, mode="smart", jump_forward=True, only_other=False):
138177
sel_regions = _change_selection(view, sels, border_pos)
139178
elif mode == "subtract": # subtract selections from the pushed fields
140179
sel_regions = list(view.sel())
141-
pushed_regions = view.get_regions("meu_sf_stored_selections")
180+
pushed_regions = _get_fields(view)
142181
regions = list(_subtract_selection(pushed_regions, sel_regions))
143-
_set_fields(view, regions)
182+
_erase_added_fields(view)
183+
_set_fields(view, regions, added_fields=has_only_added_fields)
144184
elif mode == "add": # add selections to the pushed fields
145-
pushed_regions = view.get_regions("meu_sf_stored_selections")
185+
pushed_regions = _get_fields(view)
146186
sel_regions = list(view.sel())
147-
_set_fields(view, sel_regions + pushed_regions)
187+
_set_fields(view, sel_regions + pushed_regions,
188+
added_fields=has_only_added_fields)
148189
elif mode == "remove": # remove pushed fields
149190
pop_regions = _restore_selection(view, only_other)
150191
sel_regions = list(view.sel()) if not only_other else pop_regions
151192
elif mode not in ["smart", "cycle"]: # pop or toggle with region
152193
sel_regions = _restore_selection(view, only_other)
194+
# pop added fields instead of jumping
195+
elif mode == "smart" and has_only_added_fields:
196+
sel_regions = _restore_selection(view, only_other)
153197
else: # smart or cycle
154198
# execute the jump
155199
regions, pos = _execute_jump(view, jump_forward, only_other)
@@ -179,17 +223,21 @@ def run(self, edit, mode="smart", jump_forward=True, only_other=False):
179223

180224
class SelectionFieldsContext(sublime_plugin.EventListener):
181225
def on_query_context(self, view, key, operator, operand, match_all):
182-
if key not in ["is_selection_field", "selection_fields_tab_enabled",
226+
if key not in ["is_selection_field", "is_selection_field.added_fields",
227+
"selection_fields_tab_enabled",
183228
"selection_fields_escape_enabled"]:
184229
return False
185230

186231
if key == "is_selection_field":
187232
# selection field is active if the regions are pushed to the view
188-
result = bool(view.get_regions("meu_sf_stored_selections"))
233+
result = bool(_get_fields(view, added_fields=False))
234+
elif key == "is_selection_field.added_fields":
235+
# selection field is active if the regions are pushed to the view
236+
# also if added fields are pushed
237+
result = bool(_get_fields(view))
189238
else:
190239
# the *_enabled key has the same name in the settings
191-
settings = sublime.load_settings("MultiEditUtils.sublime-settings")
192-
result = settings.get(key, False)
240+
result = get_settings(key, False)
193241

194242
if operator == sublime.OP_EQUAL:
195243
result = result == operand

0 commit comments

Comments
 (0)