Skip to content

Commit 343baac

Browse files
committed
cursor can now only go to all query results from rerun previous command
refactor for more reusability of components don't show results from previous valid query in quick panel when the xpath query expression being typed is invalid
1 parent 1ffc692 commit 343baac

File tree

7 files changed

+241
-180
lines changed

7 files changed

+241
-180
lines changed

Default.sublime-commands

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
"command": "show_xpath_query_history"
4747
}, {
4848
"caption": "XPath: Re-run last query and select all results",
49-
"command": "rerun_last_xpath_query", "args": { "show_query_results": false }
49+
"command": "rerun_last_xpath_query_and_select_results"
5050
}, {
5151
"caption": "XPath: Clean tag soup",
5252
"command": "clean_tag_soup"

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ See [default settings](https://github.com/rosshadden/sublime-xpath/blob/master/x
2828
- `attributes_to_include` - Specific attributes or namespaces to include in the XPath.
2929
- `show_attributes_in_hierarchy` - Whether or not to include attributes when in hierarchy mode. (If `show_all_attributes` is false and the `attributes_to_include` whitelist is empty, this will have no effect.)
3030
- `live_mode` - whether to show the results of the xpath query while it is being typed. If false, will only show the results after the user presses enter in the input box.
31-
- `show_query_results` - whether or not to show the results of the xpath query. If false, the cursor will move directly to all results. If the xpath query does not return a nodeset, the results are always displayed, regardless of this setting.
3231
- `default_namespace_prefix` - the prefix to use when the xml document contains a default namespace with no prefix. e.g. `<test xmlns="http://uri/">` XPath 1.0 doesn't support blank prefixes, so, for convenience, this plugin can set one for you.
3332
- `show_namespace_prefixes_from_query` - in case of blank namespace prefixes (see `default_namespace_prefix`) or multiple namespace URIs being referenced from the same prefix, the plugin will automatically make them unique, so that you can easily use them in a query. If this is turned on, the xpaths that are shown in the status bar and copied to the clipboard will be directly queryable by this plugin. If this is turned off, element names in the path will reflect those in the source document.
3433
- `only_show_xpath_if_saved` - whether or not to only show the current xpath in the status bar if the view is not dirty. This could be useful to save wasting CPU cycles (from constant parsing) when editing a document, for example.

sublime_input.py

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import sublime
2+
import sublime_plugin
3+
4+
class RequestInputCommand(sublime_plugin.TextCommand): # example usage from python console: sublime.active_window().active_view().run_command('request_input', { 'label': 'Enter text here:', 'initial_value': 'Hello World' })
5+
input_panel = None
6+
pending_value = None
7+
current_value = None
8+
live_mode = None
9+
timeout_active = None
10+
arguments = None
11+
12+
def run(self, edit, **args):
13+
self.input_panel = None
14+
self.pending_value = None
15+
self.current_value = None
16+
self.timeout_active = False
17+
self.set_args(**args)
18+
self.parse_args()
19+
20+
self.input_panel = self.view.window().show_input_panel(self.get_value_from_args('label', ''), self.get_value_from_args('initial_value', ''), self.input_done, self.input_changed, self.input_cancelled)
21+
syntax = self.get_value_from_args('syntax', None)
22+
if syntax is not None:
23+
self.input_panel.set_syntax_file(syntax)
24+
self.input_panel.settings().set('gutter', False)
25+
26+
def set_args(self, **args):
27+
self.arguments = args or {}
28+
29+
def parse_args(self):
30+
self.live_mode = self.get_value_from_args('live_mode', True)
31+
32+
def get_value_from_args(self, key, default):
33+
if key in self.arguments:
34+
if self.arguments[key] is not None:
35+
return self.arguments[key]
36+
return default
37+
38+
def close_input_panel(self):
39+
sublime.active_window().run_command('hide_panel', { 'cancel': True }) # close input panel
40+
self.input_panel = None
41+
42+
def compare_to_previous(self):
43+
"""Compare the pending_value with the current_value and process it if it is different."""
44+
self.timeout_active = False
45+
if self.pending_value != self.current_value: # no point reporting the same input again
46+
self.current_value = self.pending_value
47+
self.process_current_input()
48+
49+
def input_changed(self, value):
50+
"""When the input is changed in live mode, after a short delay (so that it doesn't report unnecessarily while the text is still being typed), report the current value."""
51+
self.pending_value = value
52+
53+
if self.live_mode:
54+
use_delay = self.get_value_from_args('delay', 0)
55+
if self.current_value is None: # if this is the initial input, report it immediately
56+
use_delay = 0
57+
58+
if not self.timeout_active:
59+
self.timeout_active = True
60+
if self.get_value_from_args('async', True):
61+
sublime.set_timeout_async(lambda: self.compare_to_previous(), use_delay)
62+
else:
63+
sublime.set_timeout(lambda: self.compare_to_previous(), use_delay)
64+
65+
def input_cancelled(self):
66+
self.input_panel = None
67+
68+
def input_done(self, value):
69+
"""When input is completed, if the current value hasn't already been processed, process it now."""
70+
self.input_panel = None
71+
self.pending_value = value
72+
self.compare_to_previous()
73+
74+
def process_current_input(self):
75+
pass

sublime_input_quickpanel.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import sublime
2+
import sublime_plugin
3+
from .sublime_input import RequestInputCommand
4+
5+
class QuickPanelFromInputCommand(RequestInputCommand): # example usage from python console: sublime.active_window().active_view().run_command('quick_panel_from_input', { 'label': 'Enter text here:', 'initial_value': 'Hello World' })
6+
items = None
7+
8+
def run(self, edit, **args):
9+
super().run(edit, **args)
10+
self.items = None
11+
12+
def close_quick_panel(self):
13+
"""Close existing quick panel."""
14+
sublime.active_window().run_command('hide_overlay', { 'cancel': True })
15+
16+
def input_cancelled(self):
17+
self.close_quick_panel()
18+
super().input_cancelled()
19+
20+
def input_done(self, value):
21+
if self.live_mode:
22+
self.close_quick_panel()
23+
super().input_done(value)
24+
self.commit_input()
25+
26+
def process_current_input(self):
27+
items = self.get_items_from_input()
28+
if items is not None:
29+
self.items = items
30+
else:
31+
if self.get_value_from_args('use_previous_when_none', False):
32+
return
33+
else:
34+
self.items = None
35+
36+
self.close_quick_panel()
37+
if items is not None:
38+
self.view.window().show_quick_panel(self.get_items_to_show_in_quickpanel(), self.quickpanel_selection_done, sublime.KEEP_OPEN_ON_FOCUS_LOST, -1, self.quickpanel_selection_changed)
39+
if self.input_panel is not None:
40+
self.input_panel.window().focus_view(self.input_panel)
41+
42+
def get_items_from_input(self):
43+
return None
44+
45+
def get_items_to_show_in_quickpanel(self):
46+
return self.items
47+
48+
def quickpanel_selection_changed(self, selected_index):
49+
pass
50+
51+
def quickpanel_selection_done(self, selected_index):
52+
if selected_index > -1: # if it wasn't cancelled
53+
self.close_input_panel()
54+
if self.live_mode:
55+
self.commit_input()
56+
57+
def commit_input(self):
58+
pass

sublime_lxml.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ def move_cursors_to_nodes(view, nodes, position_type):
142142

143143
view.show(cursors[0]) # scroll to show the first selection, if it is not already visible
144144

145-
return (len(cursors) == len(nodes), len(cursors))
145+
return (len(cursors), len(nodes))
146146

147147
def getElementXMLPreview(view, node, maxlen):
148148
"""Generate the xml string for the given node, up to the specified number of characters."""

0 commit comments

Comments
 (0)