From 62f1ec05bb49666cf22bcfed049182e126df4340 Mon Sep 17 00:00:00 2001 From: Allen Bierbaum Date: Tue, 11 Nov 2014 09:30:16 -0600 Subject: [PATCH 1/5] Add support for opening file in adjacent group if win is split. --- find_results.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/find_results.py b/find_results.py index 852e244..6fb95e0 100644 --- a/find_results.py +++ b/find_results.py @@ -5,14 +5,26 @@ class FindInFilesOpenFileCommand(sublime_plugin.TextCommand): def run(self, edit): view = self.view + window = self.view.window() + + # If we have multiple groups, then select the next one in layout + # to open the new file. + start_group = window.active_group() + dest_group = (start_group + 1) % window.num_groups() + set_group = (start_group != dest_group) + if view.name() == "Find Results": line_no = self.get_line_no() file_name = self.get_file() + print ("BetterFind: Opening file: %s" % file_name) + + window.focus_group(dest_group) if line_no is not None and file_name is not None: file_loc = "%s:%s" % (file_name, line_no) view.window().open_file(file_loc, sublime.ENCODED_POSITION) elif file_name is not None: view.window().open_file(file_name) + window.focus_group(start_group) def get_line_no(self): view = self.view @@ -36,9 +48,9 @@ def get_file(self): line = view.line(line.begin() - 1) return None - class FindInFilesJumpFileCommand(sublime_plugin.TextCommand): def run(self, edit, forward=True): + print("BetterFind: jumping") v = self.view files = v.find_by_selector("entity.name.filename.find-in-files") caret = v.sel()[0] From 9a2ebfd79fc09d6a8f1917a57d96b3f59ec15996 Mon Sep 17 00:00:00 2001 From: Allen Bierbaum Date: Tue, 11 Nov 2014 11:25:59 -0600 Subject: [PATCH 2/5] Add support for previewing in a transient window in a split. --- Default.sublime-keymap | 4 +-- find_results.py | 57 ++++++++++++++++++++++++++++++++++-------- 2 files changed, 48 insertions(+), 13 deletions(-) diff --git a/Default.sublime-keymap b/Default.sublime-keymap index 2df2259..fbf92b1 100644 --- a/Default.sublime-keymap +++ b/Default.sublime-keymap @@ -23,14 +23,14 @@ }, { "keys": ["j"], - "command": "find_next", + "command": "find_in_files_find_next", "context": [ {"key": "selector", "operator": "equal", "operand": "text.find-in-files" } ] }, { "keys": ["k"], - "command": "find_prev", + "command": "find_in_files_find_next", "args": { "forward": false }, "context": [ {"key": "selector", "operator": "equal", "operand": "text.find-in-files" } diff --git a/find_results.py b/find_results.py index 6fb95e0..411c4c8 100644 --- a/find_results.py +++ b/find_results.py @@ -2,29 +2,46 @@ import sublime_plugin import re, os, shutil -class FindInFilesOpenFileCommand(sublime_plugin.TextCommand): - def run(self, edit): - view = self.view +# TODO: +# - Add line highlighting +# - Clean up the logic in open_file + +class FileOpeningSupport(object): + def open_file(self, transient = False): + view = self.view window = self.view.window() # If we have multiple groups, then select the next one in layout - # to open the new file. + # to open the new file. We only do transient if we have a + # split layout. start_group = window.active_group() - dest_group = (start_group + 1) % window.num_groups() - set_group = (start_group != dest_group) + dest_group = (start_group + 1) % window.num_groups() + should_open = (not transient) or (start_group != dest_group) + open_flags = sublime.TRANSIENT if transient else 0 - if view.name() == "Find Results": + if (view.name() == "Find Results") and should_open: line_no = self.get_line_no() file_name = self.get_file() - print ("BetterFind: Opening file: %s" % file_name) + print ("BetterFind: Opening file: %s - %s" % (file_name, transient)) + new_view = None window.focus_group(dest_group) if line_no is not None and file_name is not None: + open_flags = open_flags | sublime.ENCODED_POSITION file_loc = "%s:%s" % (file_name, line_no) - view.window().open_file(file_loc, sublime.ENCODED_POSITION) + new_view = view.window().open_file(file_loc, open_flags) elif file_name is not None: - view.window().open_file(file_name) - window.focus_group(start_group) + print("Opening transient window") + new_view = view.window().open_file(file_name, open_flags) + + # Transient windows may not respect the focus group, so we move + # them manually + if new_view and transient: + window.set_view_index(new_view, dest_group, 0) + + # If transient, then jump back over to find view + if transient: + window.focus_group(start_group) def get_line_no(self): view = self.view @@ -48,6 +65,11 @@ def get_file(self): line = view.line(line.begin() - 1) return None +class FindInFilesOpenFileCommand(sublime_plugin.TextCommand, FileOpeningSupport): + def run(self, edit): + self.open_file(transient = False) + + class FindInFilesJumpFileCommand(sublime_plugin.TextCommand): def run(self, edit, forward=True): print("BetterFind: jumping") @@ -66,6 +88,19 @@ def run(self, edit, forward=True): top_offset = v.text_to_layout(region.begin())[1] - v.line_height() v.set_viewport_position((0, top_offset), True) +class FindInFilesFindNextCommand(sublime_plugin.TextCommand, FileOpeningSupport): + def run(self, edit, forward=True): + print("BetterFind: find next: %s " % forward) + v = self.view + window = v.window() + + if forward: + window.run_command("find_next",) + else: + window.run_command("find_prev", {"forward": False}) + + # If we want to support transient preview + self.open_file(transient = True) class FindInFilesSetReadOnly(sublime_plugin.EventListener): def is_find_results(self, view): From f0ea82e0a8e8646ee6f0cbe0f122b9fa4b6b3f46 Mon Sep 17 00:00:00 2001 From: Allen Bierbaum Date: Tue, 11 Nov 2014 16:33:16 -0600 Subject: [PATCH 3/5] Clean up transient logic and add highlighting. - Add code to delay view processing until it is loaded - Highlight the find term in the transient view --- find_results.py | 71 ++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 59 insertions(+), 12 deletions(-) diff --git a/find_results.py b/find_results.py index 411c4c8..1125b6d 100644 --- a/find_results.py +++ b/find_results.py @@ -2,11 +2,9 @@ import sublime_plugin import re, os, shutil -# TODO: -# - Add line highlighting -# - Clean up the logic in open_file class FileOpeningSupport(object): + """ Base class for plugins that need file opening support. """ def open_file(self, transient = False): view = self.view window = self.view.window() @@ -14,16 +12,24 @@ def open_file(self, transient = False): # If we have multiple groups, then select the next one in layout # to open the new file. We only do transient if we have a # split layout. + # todo: move this to a config option + use_transient_preview = True + if transient and not use_transient_preview: + return + start_group = window.active_group() dest_group = (start_group + 1) % window.num_groups() should_open = (not transient) or (start_group != dest_group) - open_flags = sublime.TRANSIENT if transient else 0 if (view.name() == "Find Results") and should_open: - line_no = self.get_line_no() + line_no = self.get_line_no() file_name = self.get_file() - print ("BetterFind: Opening file: %s - %s" % (file_name, transient)) + find_term = self.get_find_term() + open_flags = sublime.TRANSIENT if transient else 0 + print ("BetterFind: file: [%s] trans: [%s] term: [%s]" % (file_name, + transient, + find_term)) new_view = None window.focus_group(dest_group) if line_no is not None and file_name is not None: @@ -31,22 +37,49 @@ def open_file(self, transient = False): file_loc = "%s:%s" % (file_name, line_no) new_view = view.window().open_file(file_loc, open_flags) elif file_name is not None: - print("Opening transient window") new_view = view.window().open_file(file_name, open_flags) + window.focus_group(start_group) - # Transient windows may not respect the focus group, so we move - # them manually + # Transient views don't respect the focus group, move explicitly + # XXX: Not sure if we can do this before view is loaded. if new_view and transient: window.set_view_index(new_view, dest_group, 0) - # If transient, then jump back over to find view - if transient: - window.focus_group(start_group) + def finish_open(): + # delay until view is done loading + if new_view.is_loading(): + sublime.set_timeout(finish_open, 50) + + # Find and highlight the current result in transient window + new_view.erase_regions("bfb_key") + if transient: + row_num = 0 if (line_no is None) else int(line_no) - 1 + line_start_pos = new_view.text_point(row_num, 0) + + ##print("line: %s pos: %s" % (line_no, line_start_pos)) + ##print(" : %s" % new_view.substr(line_start_pos)) + ##print(" : %s" % new_view.substr(new_view.line(line_start_pos))) + + # XXX: Don't have active find settings, so use most generic options + region = new_view.find(find_term, line_start_pos, flags = sublime.IGNORECASE) + if region is not None: + new_view.add_regions("bfb_key", [region], + scope="string", flags = sublime.DRAW_NO_OUTLINE) + + # Transient views don't respect the focus group, move explicitly + window.set_view_index(new_view, dest_group, 0) + + # Adding regions can change group focus, so set back + window.focus_group(start_group) + + if new_view: + finish_open() def get_line_no(self): view = self.view if len(view.sel()) == 1: line_text = view.substr(view.line(view.sel()[0])) + print("line_text: %s" % line_text) match = re.match(r"\s*(\d+).+", line_text) if match: return match.group(1) @@ -65,6 +98,20 @@ def get_file(self): line = view.line(line.begin() - 1) return None + def get_find_term(self): + # Scan back in view for current search term for selected result + view = self.view + if len(view.sel()) == 1: + line = view.line(view.sel()[0]) + while line.begin() > 0: + line_text = view.substr(line) + match = re.match(r"^Searching.*?\"(.*)\".*?$", line_text) + if match: + term = match.group(1) + return term + line = view.line(line.begin() - 1) + return None + class FindInFilesOpenFileCommand(sublime_plugin.TextCommand, FileOpeningSupport): def run(self, edit): self.open_file(transient = False) From b6a752b4ee0935dac6b990dae86ab43209abe3e9 Mon Sep 17 00:00:00 2001 From: Allen Bierbaum Date: Tue, 11 Nov 2014 16:59:50 -0600 Subject: [PATCH 4/5] Remove some debug output. --- find_results.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/find_results.py b/find_results.py index 1125b6d..6b75a2b 100644 --- a/find_results.py +++ b/find_results.py @@ -79,7 +79,6 @@ def get_line_no(self): view = self.view if len(view.sel()) == 1: line_text = view.substr(view.line(view.sel()[0])) - print("line_text: %s" % line_text) match = re.match(r"\s*(\d+).+", line_text) if match: return match.group(1) @@ -119,7 +118,6 @@ def run(self, edit): class FindInFilesJumpFileCommand(sublime_plugin.TextCommand): def run(self, edit, forward=True): - print("BetterFind: jumping") v = self.view files = v.find_by_selector("entity.name.filename.find-in-files") caret = v.sel()[0] @@ -137,7 +135,6 @@ def run(self, edit, forward=True): class FindInFilesFindNextCommand(sublime_plugin.TextCommand, FileOpeningSupport): def run(self, edit, forward=True): - print("BetterFind: find next: %s " % forward) v = self.view window = v.window() From 6d5edbde586667e0a1cc6527b5a05bcd21004c0c Mon Sep 17 00:00:00 2001 From: Allen Bierbaum Date: Thu, 13 Nov 2014 15:56:52 -0600 Subject: [PATCH 5/5] Fix off-by-one error when searching back through find buffer. The previous code would fail if the line being searched for was on the first line of the buffer. --- find_results.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/find_results.py b/find_results.py index 6b75a2b..a31fc02 100644 --- a/find_results.py +++ b/find_results.py @@ -88,7 +88,7 @@ def get_file(self): view = self.view if len(view.sel()) == 1: line = view.line(view.sel()[0]) - while line.begin() > 0: + while line.begin() >= 0: line_text = view.substr(line) match = re.match(r"(.+):$", line_text) if match: @@ -102,7 +102,7 @@ def get_find_term(self): view = self.view if len(view.sel()) == 1: line = view.line(view.sel()[0]) - while line.begin() > 0: + while line.begin() >= 0: line_text = view.substr(line) match = re.match(r"^Searching.*?\"(.*)\".*?$", line_text) if match: