From 18dc0d630250c3d3b8cb4139bed53327aa4fed50 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 26 Jan 2022 11:14:35 +0800 Subject: [PATCH 001/365] fix issue #871 add "--case-insensitive" --- README.md | 1 + autoload/leaderf/Any.vim | 1 + autoload/leaderf/python/leaderf/cli.py | 26 +++++++++++++++++----- autoload/leaderf/python/leaderf/manager.py | 1 + 4 files changed, 24 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 3e570b3b..55517bf7 100644 --- a/README.md +++ b/README.md @@ -108,6 +108,7 @@ optional arguments: --popup-width specifies the width of popup window, only available in popup mode. --no-sort do not sort the result. + --case-insensitive fuzzy search case insensitively. subcommands: diff --git a/autoload/leaderf/Any.vim b/autoload/leaderf/Any.vim index cec62d01..9c8db872 100644 --- a/autoload/leaderf/Any.vim +++ b/autoload/leaderf/Any.vim @@ -223,6 +223,7 @@ let g:Lf_CommonArguments = [ \ {"name": ["--popup-height"], "nargs": 1, "help": "specifies the maximum height of popup window, only available in popup mode."}, \ {"name": ["--popup-width"], "nargs": 1, "help": "specifies the width of popup window, only available in popup mode."}, \ {"name": ["--no-sort"], "nargs": 0, "help": "do not sort the result."}, + \ {"name": ["--case-insensitive"], "nargs": 0, "help": "fuzzy search case insensitively."}, \] " arguments is something like g:Lf_CommonArguments diff --git a/autoload/leaderf/python/leaderf/cli.py b/autoload/leaderf/python/leaderf/cli.py index db2b6729..b9bc9c72 100644 --- a/autoload/leaderf/python/leaderf/cli.py +++ b/autoload/leaderf/python/leaderf/cli.py @@ -63,13 +63,16 @@ def __init__(self): self._spin_symbols = lfEval("get(g:, 'Lf_SpinSymbols', [])") if not self._spin_symbols: if platform.system() == "Linux": - self._spin_symbols = ['△', '▲', '▷', '▶', '▽', '▼', '◁', '◀'] + self._spin_symbols = ['✵', '⋆', '✶','✷','✸','✹', '✺'] else: self._spin_symbols = ['🌘', '🌗', '🌖', '🌕', '🌔', '🌓', '🌒', '🌑'] def setInstance(self, instance): self._instance = instance + def setArguments(self, arguments): + self._arguments = arguments + def _setDefaultMode(self): mode = lfEval("g:Lf_DefaultMode") if mode == 'NameOnly': # nameOnly mode @@ -369,11 +372,17 @@ def _buildPrompt(self): lfCmd("redraw") def _buildPattern(self): + case_insensitive = "--case-insensitive" in self._arguments if self._is_fuzzy: if self._and_delimiter in ''.join(self._cmdline).lstrip(self._and_delimiter) \ and self._delimiter not in self._cmdline: self._is_and_mode = True - patterns = re.split(r'['+self._and_delimiter+']+', ''.join(self._cmdline).strip(self._and_delimiter)) + if case_insensitive: + patterns = re.split(r'['+self._and_delimiter+']+', + ''.join(self._cmdline).strip(self._and_delimiter).lower()) + else: + patterns = re.split(r'['+self._and_delimiter+']+', + ''.join(self._cmdline).strip(self._and_delimiter)) pattern_dict = OrderedDict([]) for p in patterns: if p in pattern_dict: @@ -391,13 +400,20 @@ def _buildPattern(self): self._supports_refine) and self._delimiter in self._cmdline): self._refine = True idx = self._cmdline.index(self._delimiter) - self._pattern = (''.join(self._cmdline[:idx]), - ''.join(self._cmdline[idx+1:])) + if case_insensitive: + self._pattern = (''.join(self._cmdline[:idx]).lower(), + ''.join(self._cmdline[idx+1:]).lower()) + else: + self._pattern = (''.join(self._cmdline[:idx]), + ''.join(self._cmdline[idx+1:])) if self._pattern == ('', ''): self._pattern = None else: self._refine = False - self._pattern = ''.join(self._cmdline) + if case_insensitive: + self._pattern = ''.join(self._cmdline).lower() + else: + self._pattern = ''.join(self._cmdline) else: self._is_and_mode = False self._pattern = ''.join(self._cmdline) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 90a2d275..a90ab8bb 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -2167,6 +2167,7 @@ def startExplorer(self, win_pos, *args, **kwargs): self._arguments["--next"] = arguments_dict["--next"] else: self.setArguments(arguments_dict) + self._cli.setArguments(arguments_dict) self._cli.setNameOnlyFeature(self._getExplorer().supportsNameOnly()) self._cli.setRefineFeature(self._supportsRefine()) self._orig_line = '' From 58ef474453717efa9b700a22fc004756bf2ea5b9 Mon Sep 17 00:00:00 2001 From: leoatchina Date: Mon, 7 Mar 2022 10:01:18 +0800 Subject: [PATCH 002/365] =?UTF-8?q?fixed=20vim.error:=20Vim:E118:=20?= =?UTF-8?q?=E5=87=BD=E6=95=B0=E7=9A=84=E5=8F=82=E6=95=B0=E8=BF=87=E5=A4=9A?= =?UTF-8?q?:=20getcwd=20in=20vim=207.4.629=20(#876)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- autoload/leaderf/python/leaderf/manager.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index a90ab8bb..ba6393b9 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -145,7 +145,7 @@ def _defineMaps(self): def _defineCommonMaps(self): normal_map = lfEval("get(g:, 'Lf_NormalMap', {})") - if "_" not in normal_map: + if "_" not in normal_map: return for [lhs, rhs] in normal_map["_"]: @@ -1872,7 +1872,7 @@ def accept(self, mode=''): self._getInstance().exitBuffer() # https://github.com/Yggdroot/LeaderF/issues/257 - win_local_cwd = lfEval("getcwd(winnr())") + win_local_cwd = lfEval("getcwd()") if cwd != win_local_cwd: chdir(cwd) @@ -1909,7 +1909,7 @@ def accept(self, mode=''): self._getInstance().exitBuffer() # https://github.com/Yggdroot/LeaderF/issues/257 - win_local_cwd = lfEval("getcwd(winnr())") + win_local_cwd = lfEval("getcwd()") if cwd != win_local_cwd: chdir(cwd) @@ -2244,7 +2244,7 @@ def startExplorer(self, win_pos, *args, **kwargs): self._bang_count = 0 self._getInstance().buffer.vars['Lf_category'] = self._getExplorer().getStlCategory() - + self._read_content_exception = None if isinstance(content, list): self._is_content_list = True @@ -2283,7 +2283,7 @@ def startExplorer(self, win_pos, *args, **kwargs): if not remember_last_status and not self._cli.pattern and empty_query: self._gotoFirstLine() self._guessSearch(self._content) - if self._result_content: # self._result_content is [] only if + if self._result_content: # self._result_content is [] only if # self._cur_buffer.name == '' or self._cur_buffer.options["buftype"] not in [b'', '']: self._getInstance().appendBuffer(self._result_content[self._initial_count:]) else: @@ -2419,7 +2419,7 @@ def _workInIdle(self, content=None, bang=False): elif self._empty_query and self._getExplorer().getStlCategory() in ["File"]: self._guessSearch(self._content) if bang: - if self._result_content: # self._result_content is [] only if + if self._result_content: # self._result_content is [] only if # self._cur_buffer.name == '' or self._cur_buffer.options["buftype"] != b'': self._getInstance().appendBuffer(self._result_content[self._initial_count:]) else: From 60e14a5bbd52a22578d6335c606d0539067b9327 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Tue, 22 Mar 2022 12:16:19 +0800 Subject: [PATCH 003/365] fix a bug --- autoload/leaderf/fuzzyMatch_C/fuzzyEngine.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/autoload/leaderf/fuzzyMatch_C/fuzzyEngine.c b/autoload/leaderf/fuzzyMatch_C/fuzzyEngine.c index 24e391e3..4b50a15d 100644 --- a/autoload/leaderf/fuzzyMatch_C/fuzzyEngine.c +++ b/autoload/leaderf/fuzzyMatch_C/fuzzyEngine.c @@ -1983,6 +1983,7 @@ static void rg_getDigest(char** str, uint32_t* length, RgParameter* param) { if ( *p == ':' ) { + minus = 0; ++colon; if ( (colon == 2 && !param->has_column) || colon == 3 ) { @@ -1993,6 +1994,7 @@ static void rg_getDigest(char** str, uint32_t* length, RgParameter* param) } else if ( *p == '-' ) { + colon = 0; ++minus; if ( minus == 2 ) { @@ -2001,6 +2003,11 @@ static void rg_getDigest(char** str, uint32_t* length, RgParameter* param) return; } } + else if ( !isdigit(*p) && colon + minus > 0 ) + { + colon = 0; + minus = 0; + } } } } @@ -2019,6 +2026,10 @@ static void rg_getDigest(char** str, uint32_t* length, RgParameter* param) return; } } + else if ( !isdigit(*p) && colon > 0 ) + { + colon = 0; + } } } } From 9c642cfd2bf96029caee57a8d76ed13e65d7f265 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Fri, 1 Apr 2022 16:43:34 +0800 Subject: [PATCH 004/365] fix issue #881 --- autoload/leaderf/python/leaderf/gtagsExpl.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gtagsExpl.py b/autoload/leaderf/python/leaderf/gtagsExpl.py index 6ef9b881..4b71e6af 100644 --- a/autoload/leaderf/python/leaderf/gtagsExpl.py +++ b/autoload/leaderf/python/leaderf/gtagsExpl.py @@ -119,7 +119,10 @@ def getContent(self, *args, **kwargs): auto_jump = False self._last_result_format = self._result_format - self._result_format = None + self._result_format = 'ctags-mod' + if "--result" in arguments_dict: + self._result_format = arguments_dict["--result"][0] + if "-d" in arguments_dict: pattern = arguments_dict["-d"][0] pattern_option = "-d -e %s " % pattern @@ -241,9 +244,10 @@ def getContent(self, *args, **kwargs): env = os.environ env["GTAGSROOT"] = root env["GTAGSDBPATH"] = dbpath - cmd = 'global {}--gtagslabel={} {} {}{}{}{}--color=never --result=ctags-mod'.format( + cmd = 'global {}--gtagslabel={} {} {}{}{}{}--color=never --result={}'.format( '--gtagsconf %s ' % self._gtagsconf if self._gtagsconf else "", - self._gtagslabel, pattern_option, path_style, scope, literal, ignorecase) + self._gtagslabel, pattern_option, path_style, scope, literal, + ignorecase, self._result_format) executor = AsyncExecutor() self._executor.append(executor) @@ -263,9 +267,10 @@ def getContent(self, *args, **kwargs): if path_style == "--path-style abslib ": path_style = "--path-style absolute " - cmd = 'global {}--gtagslabel={} {} {}{}{}{}--color=never --result=ctags-mod -q'.format( + cmd = 'global {}--gtagslabel={} {} {}{}{}{}--color=never --result={} -q'.format( '--gtagsconf %s ' % self._gtagsconf if self._gtagsconf else "", - self._gtagslabel, pattern_option, path_style, scope, literal, ignorecase) + self._gtagslabel, pattern_option, path_style, scope, literal, + ignorecase, self._result_format) executor = AsyncExecutor() self._executor.append(executor) From 24ae93f358686d3d6d35f2a995fd37ff8c754c3a Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Fri, 1 Apr 2022 21:27:36 +0800 Subject: [PATCH 005/365] fix issue #828 add support for Horizontal Preview --- autoload/leaderf/python/leaderf/cli.py | 2 +- autoload/leaderf/python/leaderf/manager.py | 50 +++++++++++++++++++++- doc/leaderf.txt | 2 + 3 files changed, 51 insertions(+), 3 deletions(-) diff --git a/autoload/leaderf/python/leaderf/cli.py b/autoload/leaderf/python/leaderf/cli.py index b9bc9c72..cacfd7ab 100644 --- a/autoload/leaderf/python/leaderf/cli.py +++ b/autoload/leaderf/python/leaderf/cli.py @@ -241,7 +241,7 @@ def _buildPopupPrompt(self): sep, part3, sep_width=len(sep), - part1_width=part1_width, + part1_width=max(0, part1_width), part2_width=len(part2), part3_width=len(part3)) if self._instance.getWinPos() == 'popup': diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index ba6393b9..9f30494d 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -447,7 +447,7 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): self._is_previewed = True if lfEval("has('nvim')") == '1': width = int(lfEval("get(g:, 'Lf_PreviewPopupWidth', 0)")) - if width == 0: + if width <= 0: maxwidth = int(lfEval("&columns"))//2 else: maxwidth = min(width, int(lfEval("&columns"))) @@ -468,6 +468,8 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): float_window = self._getInstance().window float_win_row = int(float(lfEval("nvim_win_get_config(%d).row" % float_window.id))) float_win_col = int(float(lfEval("nvim_win_get_config(%d).col" % float_window.id))) + float_win_height = int(float(lfEval("nvim_win_get_config(%d).height" % float_window.id))) + float_win_width= int(float(lfEval("nvim_win_get_config(%d).width" % float_window.id))) preview_pos = lfEval("get(g:, 'Lf_PopupPreviewPosition', 'top')") if preview_pos.lower() == 'bottom': anchor = "NW" @@ -489,6 +491,26 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): if height < 1: return width = float_window.width + elif preview_pos.lower() == 'right': + anchor = "NW" + row = float_win_row - 1 + col = float_win_col + float_window.width + height = float_win_height + 1 + if lfEval("get(g:, 'Lf_PopupShowStatusline', 1)") == '1': + height += 1 + if width == 0: + width = float_win_width + width = min(width, int(lfEval("&columns")) - col) + elif preview_pos.lower() == 'left': + anchor = "NE" + row = float_win_row - 1 + col = float_win_col + height = float_win_height + 1 + if lfEval("get(g:, 'Lf_PopupShowStatusline', 1)") == '1': + height += 1 + if width == 0: + width = float_win_width + width = min(width, col) else: anchor = "SW" start = int(lfEval("line('w0')")) - 1 @@ -543,7 +565,7 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): popup_pos = lfEval("popup_getpos(%d)" % popup_window.id) width = int(lfEval("get(g:, 'Lf_PreviewPopupWidth', 0)")) - if width == 0: + if width <= 0: maxwidth = int(lfEval("&columns"))//2 - 1 else: maxwidth = min(width, int(lfEval("&columns"))) @@ -587,6 +609,30 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): pos = "botleft" line = maxheight + 1 + elif preview_pos.lower() == 'right': + col = int(popup_pos["col"]) + int(popup_pos["width"]) + line = int(popup_pos["line"]) - 1 + maxheight = int(popup_pos["height"]) + if lfEval("get(g:, 'Lf_PopupShowStatusline', 1)") == '1': + maxheight += 1 + pos = "topleft" + if width == 0: + maxwidth = int(popup_pos["width"]) + if buffer_len >= maxheight: # scrollbar appear + maxwidth -= 1 + maxwidth = min(maxwidth, int(lfEval("&columns")) - col + 1) + elif preview_pos.lower() == 'left': + col = int(popup_pos["col"]) - 1 + line = int(popup_pos["line"]) - 1 + maxheight = int(popup_pos["height"]) + if lfEval("get(g:, 'Lf_PopupShowStatusline', 1)") == '1': + maxheight += 1 + pos = "topright" + if width == 0: + maxwidth = int(popup_pos["width"]) + if buffer_len >= maxheight: # scrollbar appear + maxwidth -= 1 + maxwidth = min(maxwidth, col) else: # cursor lfCmd("""call win_execute(%d, "let numberwidth = &numberwidth")""" % popup_window.id) col = int(popup_pos["core_col"]) + int(lfEval("numberwidth")) + popup_window.cursor[1] diff --git a/doc/leaderf.txt b/doc/leaderf.txt index fd161cec..dadeaeda 100644 --- a/doc/leaderf.txt +++ b/doc/leaderf.txt @@ -807,6 +807,8 @@ g:Lf_PopupPreviewPosition *g:Lf_PopupPreviewPosition* The value can be one of the following: 'top': the preview window is on the top of the main LeaderF window. 'bottom': the preview window is at the bottom of the main LeaderF window. + 'left': the preview window is on the left of the main LeaderF window. + 'right': the preview window is on the right of the main LeaderF window. 'cursor': the preview window is at the cursor position in the main LeaderF window. From 9b94b195f51cb0557839b3526f6bc07a42b51ab1 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Sat, 2 Apr 2022 12:43:42 +0800 Subject: [PATCH 006/365] auto set the position of popup window --- autoload/leaderf/python/leaderf/instance.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/autoload/leaderf/python/leaderf/instance.py b/autoload/leaderf/python/leaderf/instance.py index c13c5374..856a1904 100644 --- a/autoload/leaderf/python/leaderf/instance.py +++ b/autoload/leaderf/python/leaderf/instance.py @@ -396,7 +396,17 @@ def _createPopupWindow(self, clear): line = min(line, int(lfEval("&lines")) - maxheight) if col == 0: - col = (int(lfEval("&columns")) - maxwidth) // 2 + preview_pos = lfEval("get(g:, 'Lf_PopupPreviewPosition', 'top')") + if preview_pos.lower() == 'right': + col = max(0, (int(lfEval("&columns")) - maxwidth*2) // 2) + elif preview_pos.lower() == 'left': + col = (int(lfEval("&columns")) - maxwidth*2) // 2 + if col < 0: + col = int(lfEval("&columns")) // 2 + else: + col += maxwidth + else: + col = (int(lfEval("&columns")) - maxwidth) // 2 else: col = min(col, int(lfEval("&columns")) - maxwidth) From eb85e4ea96276258abe5177b4de39d23b3edbaff Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Sun, 3 Apr 2022 15:12:08 +0800 Subject: [PATCH 007/365] add g:Lf_PopupAutoAjustHeight --- autoload/leaderf/python/leaderf/instance.py | 13 ++++++++++++- doc/leaderf.txt | 5 +++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/autoload/leaderf/python/leaderf/instance.py b/autoload/leaderf/python/leaderf/instance.py index 856a1904..9e46ec0f 100644 --- a/autoload/leaderf/python/leaderf/instance.py +++ b/autoload/leaderf/python/leaderf/instance.py @@ -420,7 +420,10 @@ def _createPopupWindow(self, clear): if lfEval("has('nvim')") == '1': self._win_pos = "floatwin" - floatwin_height = 1 + if lfEval("get(g:, 'Lf_PopupAutoAjustHeight', 1)") == '1': + floatwin_height = 1 + else: + floatwin_height = self._popup_maxheight config = { "relative": "editor", @@ -549,11 +552,16 @@ def getWindow(number): lfCmd("augroup END") else: self._win_pos = "popup" + if lfEval("get(g:, 'Lf_PopupAutoAjustHeight', 1)") == '1': + minheight = 1 + else: + minheight = self._popup_maxheight options = { "maxwidth": maxwidth, "minwidth": maxwidth, "maxheight": self._popup_maxheight, + "minheight": minheight, "zindex": 20480, "pos": "topleft", "line": line + 1, # there is an input window above @@ -1199,6 +1207,9 @@ def setBuffer(self, content, need_copy=False): self.buffer.options['modifiable'] = False def refreshPopupStatusline(self): + if lfEval("get(g:, 'Lf_PopupAutoAjustHeight', 1)") == '0': + return + statusline_win = self._popup_instance.statusline_win buffer_len = len(self._buffer_object) if self._win_pos == 'popup': diff --git a/doc/leaderf.txt b/doc/leaderf.txt index dadeaeda..55dfe47e 100644 --- a/doc/leaderf.txt +++ b/doc/leaderf.txt @@ -869,6 +869,11 @@ g:Lf_PopupShowFoldcolumn *g:Lf_PopupShowFoldcolumn* Default value is 1. +g:Lf_PopupAutoAjustHeight *g:Lf_PopupAutoAjustHeight* + Specifies whether to adjust the height of popup window automatically. + + Default value is 1. + g:Lf_AutoResize *g:Lf_AutoResize* Auto resize the LeaderF window height automatically. From cc21177618270255e4181dfa1ade52abebb71c23 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Sun, 3 Apr 2022 15:31:08 +0800 Subject: [PATCH 008/365] fix the height of preview window --- autoload/leaderf/python/leaderf/instance.py | 6 ++++++ autoload/leaderf/python/leaderf/manager.py | 16 ++++------------ 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/autoload/leaderf/python/leaderf/instance.py b/autoload/leaderf/python/leaderf/instance.py index 9e46ec0f..6409dd36 100644 --- a/autoload/leaderf/python/leaderf/instance.py +++ b/autoload/leaderf/python/leaderf/instance.py @@ -1438,4 +1438,10 @@ def getPopupWinId(self): def getPopupInstance(self): return self._popup_instance + def getPopupHeight(self): + if lfEval("get(g:, 'Lf_PopupShowStatusline', 1)") == '1': + return self._popup_maxheight + 1 + else: + return self._popup_maxheight + # vim: set ts=4 sw=4 tw=0 et : diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 9f30494d..f0d815d7 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -495,9 +495,7 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): anchor = "NW" row = float_win_row - 1 col = float_win_col + float_window.width - height = float_win_height + 1 - if lfEval("get(g:, 'Lf_PopupShowStatusline', 1)") == '1': - height += 1 + height = self._getInstance().getPopupHeight() if width == 0: width = float_win_width width = min(width, int(lfEval("&columns")) - col) @@ -505,9 +503,7 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): anchor = "NE" row = float_win_row - 1 col = float_win_col - height = float_win_height + 1 - if lfEval("get(g:, 'Lf_PopupShowStatusline', 1)") == '1': - height += 1 + height = self._getInstance().getPopupHeight() if width == 0: width = float_win_width width = min(width, col) @@ -612,9 +608,7 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): elif preview_pos.lower() == 'right': col = int(popup_pos["col"]) + int(popup_pos["width"]) line = int(popup_pos["line"]) - 1 - maxheight = int(popup_pos["height"]) - if lfEval("get(g:, 'Lf_PopupShowStatusline', 1)") == '1': - maxheight += 1 + maxheight = self._getInstance().getPopupHeight() pos = "topleft" if width == 0: maxwidth = int(popup_pos["width"]) @@ -624,9 +618,7 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): elif preview_pos.lower() == 'left': col = int(popup_pos["col"]) - 1 line = int(popup_pos["line"]) - 1 - maxheight = int(popup_pos["height"]) - if lfEval("get(g:, 'Lf_PopupShowStatusline', 1)") == '1': - maxheight += 1 + maxheight = self._getInstance().getPopupHeight() pos = "topright" if width == 0: maxwidth = int(popup_pos["width"]) From be58cc3f27704a4e34f350f2c3a15d7f961bc16a Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Mon, 4 Apr 2022 17:35:12 +0800 Subject: [PATCH 009/365] fix issue #524 add g:Lf_PopupShowBorder --- .../leaderf/colorscheme/popup/default.vim | 2 + .../colorscheme/popup/gruvbox_default.vim | 2 + .../colorscheme/popup/gruvbox_material.vim | 2 + autoload/leaderf/python/leaderf/cli.py | 2 + autoload/leaderf/python/leaderf/instance.py | 62 ++++++++++++++++--- autoload/leaderf/python/leaderf/manager.py | 51 +++++++++++++-- doc/leaderf.txt | 5 ++ syntax/leaderf.vim | 1 + 8 files changed, 115 insertions(+), 12 deletions(-) diff --git a/autoload/leaderf/colorscheme/popup/default.vim b/autoload/leaderf/colorscheme/popup/default.vim index 33639ccd..f8dd13e9 100644 --- a/autoload/leaderf/colorscheme/popup/default.vim +++ b/autoload/leaderf/colorscheme/popup/default.vim @@ -115,6 +115,7 @@ if &background ==? 'dark' highlight def Lf_hl_gtagsHighlight guifg=#000000 guibg=#cccc66 gui=NONE ctermfg=16 ctermbg=185 cterm=NONE highlight def link Lf_hl_previewTitle Statusline + highlight def link Lf_hl_popupBorder VertSplit highlight def link Lf_hl_winNumber Constant highlight def link Lf_hl_winIndicators Statement @@ -229,6 +230,7 @@ else highlight def Lf_hl_gtagsHighlight guifg=#4d4d4d guibg=#cccc66 gui=NONE ctermfg=239 ctermbg=185 cterm=NONE highlight def link Lf_hl_previewTitle Statusline + highlight def link Lf_hl_popupBorder VertSplit highlight def link Lf_hl_winNumber Constant highlight def link Lf_hl_winIndicators Statement diff --git a/autoload/leaderf/colorscheme/popup/gruvbox_default.vim b/autoload/leaderf/colorscheme/popup/gruvbox_default.vim index b15a6537..8838b2a2 100644 --- a/autoload/leaderf/colorscheme/popup/gruvbox_default.vim +++ b/autoload/leaderf/colorscheme/popup/gruvbox_default.vim @@ -114,6 +114,7 @@ if &background ==? 'dark' highlight def Lf_hl_gtagsHighlight guifg=#000000 guibg=#cccc66 gui=NONE ctermfg=16 ctermbg=185 cterm=NONE highlight def link Lf_hl_previewTitle Statusline + highlight def link Lf_hl_popupBorder VertSplit highlight def link Lf_hl_winNumber Constant highlight def link Lf_hl_winIndicators Statement @@ -228,6 +229,7 @@ else highlight def Lf_hl_gtagsHighlight guifg=#4d4d4d guibg=#cccc66 gui=NONE ctermfg=239 ctermbg=185 cterm=NONE highlight def link Lf_hl_previewTitle Statusline + highlight def link Lf_hl_popupBorder VertSplit highlight def link Lf_hl_winNumber Constant highlight def link Lf_hl_winIndicators Statement diff --git a/autoload/leaderf/colorscheme/popup/gruvbox_material.vim b/autoload/leaderf/colorscheme/popup/gruvbox_material.vim index 948f8e4d..9538810d 100644 --- a/autoload/leaderf/colorscheme/popup/gruvbox_material.vim +++ b/autoload/leaderf/colorscheme/popup/gruvbox_material.vim @@ -112,6 +112,7 @@ if &background ==# 'dark' highlight def Lf_hl_gtagsHighlight guifg=#000000 guibg=#cccc66 gui=NONE ctermfg=16 ctermbg=185 cterm=NONE highlight def link Lf_hl_previewTitle Statusline + highlight def link Lf_hl_popupBorder VertSplit highlight def link Lf_hl_winNumber Constant highlight def link Lf_hl_winIndicators Statement @@ -229,6 +230,7 @@ else highlight def Lf_hl_gtagsHighlight guifg=#000000 guibg=#cccc66 gui=NONE ctermfg=16 ctermbg=185 cterm=NONE highlight def link Lf_hl_previewTitle Statusline + highlight def link Lf_hl_popupBorder VertSplit highlight def link Lf_hl_winNumber Constant highlight def link Lf_hl_winIndicators Statement diff --git a/autoload/leaderf/python/leaderf/cli.py b/autoload/leaderf/python/leaderf/cli.py index cacfd7ab..27cad675 100644 --- a/autoload/leaderf/python/leaderf/cli.py +++ b/autoload/leaderf/python/leaderf/cli.py @@ -205,6 +205,8 @@ def _buildPopupPrompt(self): input_window = self._instance.getPopupInstance().input_win content_winid = self._instance.getPopupInstance().content_win.id input_win_width = input_window.width + if lfEval("get(g:, 'Lf_PopupShowBorder', 0)") == '1' and lfEval("has('nvim')") == '0': + input_win_width -= 2 if self._instance.getWinPos() == 'popup': lfCmd("""call win_execute(%d, 'let line_num = line(".")')""" % content_winid) line_num = lfEval("line_num") diff --git a/autoload/leaderf/python/leaderf/instance.py b/autoload/leaderf/python/leaderf/instance.py index 6409dd36..e4518c0a 100644 --- a/autoload/leaderf/python/leaderf/instance.py +++ b/autoload/leaderf/python/leaderf/instance.py @@ -433,10 +433,19 @@ def _createPopupWindow(self, clear): "row" : line + 1, "col" : col } + + if lfEval("get(g:, 'Lf_PopupShowBorder', 0)") == '1': + if lfEval("get(g:, 'Lf_PopupShowStatusline', 1)") == '1': + config["border"] = ['','','','|','','','','|'] + else: + config["border"] = ['','','','|','+','-','+','|'] + config["row"] += 1 + config["width"] -= 2 + lfCmd("noautocmd silent noswapfile let winid = nvim_open_win(%d, 1, %s)" % (buf_number, str(config))) self._popup_winid = int(lfEval("winid")) self._setAttributes() - if lfEval("get(g:, 'Lf_PopupShowFoldcolumn', 1)") == '0': + if lfEval("get(g:, 'Lf_PopupShowFoldcolumn', 1)") == '0' or lfEval("get(g:, 'Lf_PopupShowBorder', 0)") == '1': try: lfCmd("call nvim_win_set_option(%d, 'foldcolumn', 0)" % self._popup_winid) except vim.error: @@ -451,7 +460,7 @@ def _createPopupWindow(self, clear): self._tabpage_object = vim.current.tabpage self._buffer_object = vim.buffers[buf_number] - self._window_object = FloatWindow(self._popup_winid, vim.current.window, self._buffer_object, self._tabpage_object, line + 1) + self._window_object = FloatWindow(self._popup_winid, vim.current.window, self._buffer_object, self._tabpage_object, config["row"]) self._popup_instance.content_win = self._window_object input_win_config = { @@ -463,6 +472,10 @@ def _createPopupWindow(self, clear): "col" : col } + if lfEval("get(g:, 'Lf_PopupShowBorder', 0)") == '1': + input_win_config["border"] = ['+','-','+','|','','','','|'] + input_win_config["width"] -= 2 + if self._input_buffer_number == -1: self._input_buffer_number = int(lfEval("bufadd('')")) @@ -507,10 +520,14 @@ def getWindow(number): "anchor" : "NW", "height" : 1, "width" : maxwidth, - "row" : line + 1 + floatwin_height, + "row" : config["row"] + floatwin_height, "col" : col } + if lfEval("get(g:, 'Lf_PopupShowBorder', 0)") == '1': + stl_win_config["border"] = ['','','','|','+','-','+','|'] + stl_win_config["width"] -= 2 + if self._stl_buffer_number == -1: self._stl_buffer_number = int(lfEval("bufadd('')")) @@ -539,7 +556,7 @@ def getWindow(number): lfCmd("call nvim_win_set_option(%d, 'cursorlineopt', 'both')" % winid) lfCmd("call nvim_win_set_option(%d, 'colorcolumn', '')" % winid) lfCmd("call nvim_win_set_option(%d, 'winhighlight', 'Normal:Lf_hl_popup_blank')" % winid) - self._popup_instance.statusline_win = FloatWindow(winid, getWindow(int(lfEval("win_id2win(%d)" % winid))), vim.buffers[buf_number], vim.current.tabpage, line + 1 + floatwin_height) + self._popup_instance.statusline_win = FloatWindow(winid, getWindow(int(lfEval("win_id2win(%d)" % winid))), vim.buffers[buf_number], vim.current.tabpage, stl_win_config["row"]) if "--recall" in self._arguments: self.refreshPopupStatusline() @@ -569,9 +586,22 @@ def getWindow(number): "padding": [0, 0, 0, 0], "scrollbar": 0, "mapping": 0, + "borderhighlight": ["Lf_hl_previewTitle"], "filter": "leaderf#PopupFilter", } + borderchars = ['-','|','-','|','+','+','+','+'] + if lfEval("get(g:, 'Lf_PopupShowBorder', 0)") == '1': + if lfEval("get(g:, 'Lf_PopupShowStatusline', 1)") == '1': + options["border"] = [0, 1, 0, 1] + else: + options["border"] = [0, 1, 1, 1] + options["borderchars"] = borderchars + options["maxwidth"] -= 2 + options["minwidth"] -= 2 + options["line"] += 1 + options["borderhighlight"] = ["Lf_hl_popupBorder"] + lfCmd("noautocmd silent noswapfile let winid = popup_create(%d, %s)" % (buf_number, str(options))) self._popup_winid = int(lfEval("winid")) lfCmd("call win_execute(%d, 'setlocal nobuflisted')" % self._popup_winid) @@ -588,7 +618,7 @@ def getWindow(number): lfCmd("call win_execute(%d, 'setlocal cursorline')" % self._popup_winid) if lfEval("exists('+cursorlineopt')") == '1': lfCmd("call win_execute(%d, 'setlocal cursorlineopt=both')" % self._popup_winid) - if lfEval("get(g:, 'Lf_PopupShowFoldcolumn', 1)") == '0': + if lfEval("get(g:, 'Lf_PopupShowFoldcolumn', 1)") == '0' or lfEval("get(g:, 'Lf_PopupShowBorder', 0)") == '1': lfCmd("call win_execute(%d, 'setlocal foldcolumn=0')" % self._popup_winid) else: lfCmd("call win_execute(%d, 'setlocal foldcolumn=1')" % self._popup_winid) @@ -599,7 +629,7 @@ def getWindow(number): self._tabpage_object = vim.current.tabpage self._buffer_object = vim.buffers[buf_number] - self._window_object = PopupWindow(self._popup_winid, self._buffer_object, self._tabpage_object, line+1) + self._window_object = PopupWindow(self._popup_winid, self._buffer_object, self._tabpage_object, options["line"]) self._popup_instance.content_win = self._window_object input_win_options = { @@ -612,8 +642,16 @@ def getWindow(number): "col": col, "scrollbar": 0, "mapping": 0, + "borderhighlight": ["Lf_hl_previewTitle"], } + if lfEval("get(g:, 'Lf_PopupShowBorder', 0)") == '1': + input_win_options["border"] = [1, 1, 0, 1] + input_win_options["borderchars"] = borderchars + input_win_options["maxwidth"] -= 2 + input_win_options["minwidth"] -= 2 + input_win_options["borderhighlight"] = ["Lf_hl_popupBorder"] + if self._input_buffer_number == -1: self._input_buffer_number = int(lfEval("bufadd('')")) @@ -646,12 +684,20 @@ def getWindow(number): "maxheight": 1, "zindex": 20480, "pos": "topleft", - "line": line + 1 + self._window_object.height, + "line": options["line"] + self._window_object.height, "col": col, "scrollbar": 0, "mapping": 0, + "borderhighlight": ["Lf_hl_previewTitle"], } + if lfEval("get(g:, 'Lf_PopupShowBorder', 0)") == '1': + statusline_win_options["border"] = [0, 1, 1, 1] + statusline_win_options["borderchars"] = borderchars + statusline_win_options["maxwidth"] -= 2 + statusline_win_options["minwidth"] -= 2 + statusline_win_options["borderhighlight"] = ["Lf_hl_popupBorder"] + if self._stl_buffer_number == -1: self._stl_buffer_number = int(lfEval("bufadd('')")) @@ -675,7 +721,7 @@ def getWindow(number): lfCmd("call win_execute(%d, 'setlocal colorcolumn=')" % winid) lfCmd("call win_execute(%d, 'setlocal wincolor=Lf_hl_popup_blank')" % winid) - self._popup_instance.statusline_win = PopupWindow(winid, vim.buffers[buf_number], vim.current.tabpage, line + 1 + self._window_object.height) + self._popup_instance.statusline_win = PopupWindow(winid, vim.buffers[buf_number], vim.current.tabpage, statusline_win_options["line"]) lfCmd("call leaderf#ResetPopupOptions(%d, 'callback', function('leaderf#PopupClosed', [%s, %d]))" % (self._popup_winid, str(self._popup_instance.getWinIdList()), id(self._manager))) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index f0d815d7..76ecb3f2 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -471,6 +471,7 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): float_win_height = int(float(lfEval("nvim_win_get_config(%d).height" % float_window.id))) float_win_width= int(float(lfEval("nvim_win_get_config(%d).width" % float_window.id))) preview_pos = lfEval("get(g:, 'Lf_PopupPreviewPosition', 'top')") + borderchars = ['+','-','+','|','+','-','+','|'] if preview_pos.lower() == 'bottom': anchor = "NW" if self._getInstance().getPopupInstance().statusline_win: @@ -483,19 +484,26 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): if height < 1: return width = float_window.width + borderchars = ['','','','|','+','-','+','|'] elif preview_pos.lower() == 'top': anchor = "SW" row = float_win_row - 1 + if lfEval("get(g:, 'Lf_PopupShowBorder', 0)") == '1': + row -= 1 col = float_win_col height = row if height < 1: return width = float_window.width + borderchars = ['+','-','+','|','','','','|'] elif preview_pos.lower() == 'right': anchor = "NW" row = float_win_row - 1 col = float_win_col + float_window.width - height = self._getInstance().getPopupHeight() + if lfEval("get(g:, 'Lf_PopupShowBorder', 0)") == '1': + row -= 1 + col += 2 + height = self._getInstance().getPopupHeight() + 1 if width == 0: width = float_win_width width = min(width, int(lfEval("&columns")) - col) @@ -503,7 +511,10 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): anchor = "NE" row = float_win_row - 1 col = float_win_col - height = self._getInstance().getPopupHeight() + if lfEval("get(g:, 'Lf_PopupShowBorder', 0)") == '1': + row -= 1 + col -= 2 + height = self._getInstance().getPopupHeight() + 1 if width == 0: width = float_win_width width = min(width, col) @@ -524,8 +535,13 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): "height" : height, "width" : width, "row" : row, - "col" : col + "col" : col, + "noautocmd": 1 } + + if lfEval("get(g:, 'Lf_PopupShowBorder', 0)") == '1': + config["border"] = borderchars + if isinstance(source, int): self._preview_winid = int(lfEval("nvim_open_win(%d, 0, %s)" % (source, str(config)))) else: @@ -544,6 +560,8 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): lfCmd("call nvim_win_set_option(%d, 'relativenumber', v:false)" % self._preview_winid) lfCmd("call nvim_win_set_option(%d, 'cursorline', v:true)" % self._preview_winid) lfCmd("call nvim_win_set_option(%d, 'foldmethod', 'manual')" % self._preview_winid) + lfCmd("call nvim_win_set_option(%d, 'foldcolumn', '0')" % self._preview_winid) + lfCmd("call nvim_win_set_option(%d, 'signcolumn', 'no')" % self._preview_winid) if lfEval("exists('+cursorlineopt')") == '1': lfCmd("call nvim_win_set_option(%d, 'cursorlineopt', 'both')" % self._preview_winid) lfCmd("call nvim_win_set_option(%d, 'colorcolumn', '')" % self._preview_winid) @@ -657,9 +675,34 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): "filter": "leaderf#popupModePreviewFilter", } + if lfEval("get(g:, 'Lf_PopupShowBorder', 0)") == '1': + options["borderchars"] = ['-','|','-','|','+','+','+','+'] + options["maxwidth"] -= 2 + options["minwidth"] -= 2 + options["borderhighlight"] = ["Lf_hl_popupBorder"] + if preview_pos.lower() == 'bottom': del options["title"] options["border"] = [0, 0, 1, 0] + if lfEval("get(g:, 'Lf_PopupShowBorder', 0)") == '1': + options["border"] = [0, 1, 1, 1] + elif preview_pos.lower() == 'top': + if lfEval("get(g:, 'Lf_PopupShowBorder', 0)") == '1': + options["border"] = [1, 1, 0, 1] + elif preview_pos.lower() == 'right': + if lfEval("get(g:, 'Lf_PopupShowBorder', 0)") == '1': + options["border"] = [1, 1, 1, 1] + options["line"] -= 1 + # options["col"] += 1 + options["maxheight"] += 1 + options["minheight"] += 1 + elif preview_pos.lower() == 'left': + if lfEval("get(g:, 'Lf_PopupShowBorder', 0)") == '1': + options["border"] = [1, 1, 1, 1] + options["line"] -= 1 + # options["col"] -= 1 + options["maxheight"] += 1 + options["minheight"] += 1 elif preview_pos.lower() == 'cursor' and maxheight < int(lfEval("&lines"))//2 - 2: maxheight = int(lfEval("&lines")) - maxheight - 5 del options["title"] @@ -683,7 +726,7 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): if lfEval("exists('+cursorlineopt')") == '1': lfCmd("call win_execute(%d, 'setlocal cursorlineopt=both')" % self._preview_winid) lfCmd("call win_execute(%d, 'setlocal wincolor=Lf_hl_popup_window')" % self._preview_winid) - if lfEval("get(g:, 'Lf_PopupShowFoldcolumn', 1)") == '0': + if lfEval("get(g:, 'Lf_PopupShowFoldcolumn', 1)") == '0' or lfEval("get(g:, 'Lf_PopupShowBorder', 0)") == '1': lfCmd("call win_execute(%d, 'setlocal foldcolumn=0')" % self._preview_winid) else: lfCmd("call win_execute(%d, 'setlocal foldcolumn=1')" % self._preview_winid) diff --git a/doc/leaderf.txt b/doc/leaderf.txt index 55dfe47e..4ba9b3cf 100644 --- a/doc/leaderf.txt +++ b/doc/leaderf.txt @@ -874,6 +874,11 @@ g:Lf_PopupAutoAjustHeight *g:Lf_PopupAutoAjustHeight* Default value is 1. +g:Lf_PopupShowBorder *g:Lf_PopupShowBorder* + Specifies whether to show border for popup window. + + Default value is 0. + g:Lf_AutoResize *g:Lf_AutoResize* Auto resize the LeaderF window height automatically. diff --git a/syntax/leaderf.vim b/syntax/leaderf.vim index f7bf89ec..e78b5c8f 100644 --- a/syntax/leaderf.vim +++ b/syntax/leaderf.vim @@ -107,6 +107,7 @@ function! g:LfDefineDefaultColors() abort highlight def Lf_hl_gtagsHighlight guifg=#000000 guibg=#cccc66 gui=NONE ctermfg=16 ctermbg=185 cterm=NONE highlight def link Lf_hl_previewTitle Statusline + highlight def link Lf_hl_popupBorder VertSplit highlight def link Lf_hl_winNumber Constant highlight def link Lf_hl_winIndicators Statement From 8d143ac26dfc8c857ef47c0d57949b894035b1d4 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Mon, 4 Apr 2022 20:30:38 +0800 Subject: [PATCH 010/365] add `--auto-preview` as per #882 --- README.md | 1 + autoload/leaderf/Any.vim | 1 + autoload/leaderf/python/leaderf/manager.py | 3 +++ 3 files changed, 5 insertions(+) diff --git a/README.md b/README.md index 55517bf7..480ae490 100644 --- a/README.md +++ b/README.md @@ -109,6 +109,7 @@ optional arguments: specifies the width of popup window, only available in popup mode. --no-sort do not sort the result. --case-insensitive fuzzy search case insensitively. + --auto-preview open preview window automatically. subcommands: diff --git a/autoload/leaderf/Any.vim b/autoload/leaderf/Any.vim index 9c8db872..6ae4b25c 100644 --- a/autoload/leaderf/Any.vim +++ b/autoload/leaderf/Any.vim @@ -224,6 +224,7 @@ let g:Lf_CommonArguments = [ \ {"name": ["--popup-width"], "nargs": 1, "help": "specifies the width of popup window, only available in popup mode."}, \ {"name": ["--no-sort"], "nargs": 0, "help": "do not sort the result."}, \ {"name": ["--case-insensitive"], "nargs": 0, "help": "fuzzy search case insensitively."}, + \ {"name": ["--auto-preview"], "nargs": 0, "help": "open preview window automatically."}, \] " arguments is something like g:Lf_CommonArguments diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 76ecb3f2..529698da 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -896,6 +896,9 @@ def _needPreview(self, preview): preview: if True, always preview the result no matter what `g:Lf_PreviewResult` is. """ + if "--auto-preview" in self._arguments: + return True + preview_dict = {k.lower(): v for k, v in lfEval("g:Lf_PreviewResult").items()} category = self._getExplorer().getStlCategory() if not preview and int(preview_dict.get(category.lower(), 0)) == 0: From 1a8a80a416649853b936f763f6ae35f2e494f72e Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Mon, 4 Apr 2022 22:10:38 +0800 Subject: [PATCH 011/365] update arguments when `--recall` --- autoload/leaderf/python/leaderf/manager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 529698da..a13f0db7 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -2244,7 +2244,7 @@ def _readFinished(self): def startExplorer(self, win_pos, *args, **kwargs): arguments_dict = kwargs.get("arguments", {}) if "--recall" in arguments_dict: - self._arguments["--recall"] = arguments_dict["--recall"] + self._arguments.update(arguments_dict) elif "--previous" in arguments_dict: self._arguments["--previous"] = arguments_dict["--previous"] elif "--next" in arguments_dict: From fbdd4a93da7913fb0fdf357ce64cfcad0e61163c Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Tue, 5 Apr 2022 15:57:51 +0800 Subject: [PATCH 012/365] ensure popup window is above statusline --- autoload/leaderf/python/leaderf/instance.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/autoload/leaderf/python/leaderf/instance.py b/autoload/leaderf/python/leaderf/instance.py index e4518c0a..3dc9c862 100644 --- a/autoload/leaderf/python/leaderf/instance.py +++ b/autoload/leaderf/python/leaderf/instance.py @@ -387,11 +387,13 @@ def _createPopupWindow(self, clear): maxheight = 1 else: height = int(height) - maxheight = min(height, int(lfEval("&lines"))) + maxheight = min(height, int(lfEval("&lines")) - 2) + if lfEval("get(g:, 'Lf_PopupShowBorder', 0)") == '1': + maxheight -= 2 line, col = [int(i) for i in lfEval("get(g:, 'Lf_PopupPosition', [0, 0])")] if line == 0: - line = (int(lfEval("&lines")) - maxheight) // 2 + line = (int(lfEval("&lines")) - 2 - maxheight) // 2 else: line = min(line, int(lfEval("&lines")) - maxheight) From 6a2ad813fc2936f87db13abdd14901c91e42798d Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Tue, 5 Apr 2022 17:24:19 +0800 Subject: [PATCH 013/365] add g:Lf_PopupBorders --- autoload/leaderf.vim | 1 + autoload/leaderf/python/leaderf/instance.py | 13 ++++++++----- autoload/leaderf/python/leaderf/manager.py | 14 ++++++++++---- doc/leaderf.txt | 17 +++++++++++++++++ 4 files changed, 36 insertions(+), 9 deletions(-) diff --git a/autoload/leaderf.vim b/autoload/leaderf.vim index aaa5996d..e1595e91 100644 --- a/autoload/leaderf.vim +++ b/autoload/leaderf.vim @@ -137,6 +137,7 @@ call s:InitDict('g:Lf_GtagsfilesCmd', { \ 'default': 'rg --no-messages --files' \}) call s:InitVar('g:Lf_HistoryEditPromptIfEmpty', 1) +call s:InitVar('g:Lf_PopupBorders', ['-','|','-','|','+','+','+','+']) let s:Lf_CommandMap = { \ '': [''], diff --git a/autoload/leaderf/python/leaderf/instance.py b/autoload/leaderf/python/leaderf/instance.py index 3dc9c862..890ff2c1 100644 --- a/autoload/leaderf/python/leaderf/instance.py +++ b/autoload/leaderf/python/leaderf/instance.py @@ -436,11 +436,14 @@ def _createPopupWindow(self, clear): "col" : col } + popup_borders = lfEval("g:Lf_PopupBorders") + borderchars = [popup_borders[4], popup_borders[0], popup_borders[5], popup_borders[1], + popup_borders[6], popup_borders[2], popup_borders[7], popup_borders[3]] if lfEval("get(g:, 'Lf_PopupShowBorder', 0)") == '1': if lfEval("get(g:, 'Lf_PopupShowStatusline', 1)") == '1': - config["border"] = ['','','','|','','','','|'] + config["border"] = ['','','',borderchars[3],'','','',borderchars[7]] else: - config["border"] = ['','','','|','+','-','+','|'] + config["border"] = ['','',''] + borderchars[3:] config["row"] += 1 config["width"] -= 2 @@ -475,7 +478,7 @@ def _createPopupWindow(self, clear): } if lfEval("get(g:, 'Lf_PopupShowBorder', 0)") == '1': - input_win_config["border"] = ['+','-','+','|','','','','|'] + input_win_config["border"] = borderchars[:4] + ['','','', borderchars[7]] input_win_config["width"] -= 2 if self._input_buffer_number == -1: @@ -527,7 +530,7 @@ def getWindow(number): } if lfEval("get(g:, 'Lf_PopupShowBorder', 0)") == '1': - stl_win_config["border"] = ['','','','|','+','-','+','|'] + stl_win_config["border"] = ['','',''] + borderchars[3:] stl_win_config["width"] -= 2 if self._stl_buffer_number == -1: @@ -592,7 +595,7 @@ def getWindow(number): "filter": "leaderf#PopupFilter", } - borderchars = ['-','|','-','|','+','+','+','+'] + borderchars = lfEval("g:Lf_PopupBorders") if lfEval("get(g:, 'Lf_PopupShowBorder', 0)") == '1': if lfEval("get(g:, 'Lf_PopupShowStatusline', 1)") == '1': options["border"] = [0, 1, 0, 1] diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index a13f0db7..b9d7f7a7 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -471,7 +471,9 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): float_win_height = int(float(lfEval("nvim_win_get_config(%d).height" % float_window.id))) float_win_width= int(float(lfEval("nvim_win_get_config(%d).width" % float_window.id))) preview_pos = lfEval("get(g:, 'Lf_PopupPreviewPosition', 'top')") - borderchars = ['+','-','+','|','+','-','+','|'] + popup_borders = lfEval("g:Lf_PopupBorders") + borderchars = [popup_borders[4], popup_borders[0], popup_borders[5], popup_borders[1], + popup_borders[6], popup_borders[2], popup_borders[7], popup_borders[3]] if preview_pos.lower() == 'bottom': anchor = "NW" if self._getInstance().getPopupInstance().statusline_win: @@ -484,7 +486,9 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): if height < 1: return width = float_window.width - borderchars = ['','','','|','+','-','+','|'] + borderchars[0] = '' + borderchars[1] = '' + borderchars[2] = '' elif preview_pos.lower() == 'top': anchor = "SW" row = float_win_row - 1 @@ -495,7 +499,9 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): if height < 1: return width = float_window.width - borderchars = ['+','-','+','|','','','','|'] + borderchars[4] = '' + borderchars[5] = '' + borderchars[6] = '' elif preview_pos.lower() == 'right': anchor = "NW" row = float_win_row - 1 @@ -676,7 +682,7 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): } if lfEval("get(g:, 'Lf_PopupShowBorder', 0)") == '1': - options["borderchars"] = ['-','|','-','|','+','+','+','+'] + options["borderchars"] = lfEval("g:Lf_PopupBorders") options["maxwidth"] -= 2 options["minwidth"] -= 2 options["borderhighlight"] = ["Lf_hl_popupBorder"] diff --git a/doc/leaderf.txt b/doc/leaderf.txt index 4ba9b3cf..632f80c7 100644 --- a/doc/leaderf.txt +++ b/doc/leaderf.txt @@ -879,6 +879,23 @@ g:Lf_PopupShowBorder *g:Lf_PopupShowBorder* Default value is 0. +g:Lf_PopupBorders *g:Lf_PopupBorders* + Specifies a list of characters, defining the character to use for the + top/right/bottom/left border, followed by the character to use for the + topleft/topright/botright/botleft corner. + Example: > + let g:Lf_PopupBorders = ["─","│","─","│","╭","╮","╯","╰"] + let g:Lf_PopupBorders = ["─","│","─","│","┌","┐","┘","└"] + let g:Lf_PopupBorders = ["━","┃","━","┃","┏","┓","┛","┗"] + let g:Lf_PopupBorders = ["═","║","═","║","╔","╗","╝","╚"] +< + For some terminals, the non-ascii characters can not be displayed + properly for borders, see https://github.com/neovim/neovim/issues/17996. + To have a good display for non-ascii characters, perhaps you need to set + the value of |ambiwidth| as "single". + + Default value is ["-","|","-","|","+","+","+","+"]. + g:Lf_AutoResize *g:Lf_AutoResize* Auto resize the LeaderF window height automatically. From 7292967624ba89e2c3ab2f374959d5a25d5c9d9f Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Tue, 5 Apr 2022 22:40:51 +0800 Subject: [PATCH 014/365] fix a bug --- autoload/leaderf/python/leaderf/instance.py | 7 +++++-- autoload/leaderf/python/leaderf/manager.py | 22 +++++++++------------ 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/autoload/leaderf/python/leaderf/instance.py b/autoload/leaderf/python/leaderf/instance.py index 890ff2c1..b46e870b 100644 --- a/autoload/leaderf/python/leaderf/instance.py +++ b/autoload/leaderf/python/leaderf/instance.py @@ -404,9 +404,9 @@ def _createPopupWindow(self, clear): elif preview_pos.lower() == 'left': col = (int(lfEval("&columns")) - maxwidth*2) // 2 if col < 0: - col = int(lfEval("&columns")) // 2 + col = int(lfEval("&columns")) - maxwidth + 1 else: - col += maxwidth + col += maxwidth + 1 else: col = (int(lfEval("&columns")) - maxwidth) // 2 else: @@ -418,6 +418,9 @@ def _createPopupWindow(self, clear): if col <= 0: col = 1 + if lfEval("has('nvim')") == '1': + col -= 1 + self._popup_maxheight = max(maxheight - 2, 1) # there is an input window above if lfEval("has('nvim')") == '1': diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index b9d7f7a7..e679a798 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -466,6 +466,7 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): lfCmd("call nvim_buf_set_option(scratch_buffer, 'bufhidden', 'wipe')") float_window = self._getInstance().window + # row and col start from 0 float_win_row = int(float(lfEval("nvim_win_get_config(%d).row" % float_window.id))) float_win_col = int(float(lfEval("nvim_win_get_config(%d).col" % float_window.id))) float_win_height = int(float(lfEval("nvim_win_get_config(%d).height" % float_window.id))) @@ -505,14 +506,17 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): elif preview_pos.lower() == 'right': anchor = "NW" row = float_win_row - 1 - col = float_win_col + float_window.width + col = float_win_col + float_win_width if lfEval("get(g:, 'Lf_PopupShowBorder', 0)") == '1': row -= 1 col += 2 height = self._getInstance().getPopupHeight() + 1 - if width == 0: + if width <= 0: width = float_win_width - width = min(width, int(lfEval("&columns")) - col) + if lfEval("get(g:, 'Lf_PopupShowBorder', 0)") == '1': + width = min(width, int(lfEval("&columns")) - col - 2) + else: + width = min(width, int(lfEval("&columns")) - col) elif preview_pos.lower() == 'left': anchor = "NE" row = float_win_row - 1 @@ -521,7 +525,7 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): row -= 1 col -= 2 height = self._getInstance().getPopupHeight() + 1 - if width == 0: + if width <= 0: width = float_win_width width = min(width, col) else: @@ -614,8 +618,6 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): if maxheight < 1: return - if buffer_len >= maxheight: # scrollbar appear - maxwidth -= 1 elif preview_pos.lower() == 'top': maxwidth = int(popup_pos["width"]) col = int(popup_pos["col"]) @@ -624,9 +626,6 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): if maxheight < 1: return - if buffer_len >= maxheight: # scrollbar appear - maxwidth -= 1 - pos = "botleft" line = maxheight + 1 elif preview_pos.lower() == 'right': @@ -636,8 +635,6 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): pos = "topleft" if width == 0: maxwidth = int(popup_pos["width"]) - if buffer_len >= maxheight: # scrollbar appear - maxwidth -= 1 maxwidth = min(maxwidth, int(lfEval("&columns")) - col + 1) elif preview_pos.lower() == 'left': col = int(popup_pos["col"]) - 1 @@ -646,8 +643,6 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): pos = "topright" if width == 0: maxwidth = int(popup_pos["width"]) - if buffer_len >= maxheight: # scrollbar appear - maxwidth -= 1 maxwidth = min(maxwidth, col) else: # cursor lfCmd("""call win_execute(%d, "let numberwidth = &numberwidth")""" % popup_window.id) @@ -674,6 +669,7 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): "pos": pos, "line": line, "col": col, + "scrollbar": 0, "padding": [0, 0, 0, 0], "border": [1, 0, 0, 0], "borderchars": [' '], From 6ae2ba208936542acb6fc0144033b3c34640daa4 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 6 Apr 2022 10:27:05 +0800 Subject: [PATCH 015/365] fix the flicker issue for nvim if `set lastatus=0` --- autoload/leaderf/python/leaderf/manager.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index e679a798..dd0d7fd5 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -250,6 +250,8 @@ def _setStlMode(self, **kwargs): def _beforeEnter(self): self._resetAutochdir() self._cur_buffer = vim.current.buffer + self._laststatus = lfEval("&laststatus") + lfCmd("set laststatus=2") def _afterEnter(self): if self._vim_file_autoloaded == False: @@ -313,7 +315,7 @@ def _beforeExit(self): self._match_ids = [] def _afterExit(self): - pass + lfCmd("set laststatus=%s" % self._laststatus) def _bangEnter(self): self._preview_open = False From 0f19c3c19e793b7af0a889f3949ba1c681f94bff Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 6 Apr 2022 10:47:58 +0800 Subject: [PATCH 016/365] fix the flicker issue for nvim if `set lastatus=0` --- autoload/leaderf/python/leaderf/manager.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index dd0d7fd5..3c16a16e 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -251,7 +251,8 @@ def _beforeEnter(self): self._resetAutochdir() self._cur_buffer = vim.current.buffer self._laststatus = lfEval("&laststatus") - lfCmd("set laststatus=2") + if self._laststatus == '0': + lfCmd("set laststatus=2") def _afterEnter(self): if self._vim_file_autoloaded == False: @@ -315,7 +316,8 @@ def _beforeExit(self): self._match_ids = [] def _afterExit(self): - lfCmd("set laststatus=%s" % self._laststatus) + if self._laststatus == '0': + lfCmd("set laststatus=%s" % self._laststatus) def _bangEnter(self): self._preview_open = False From 6897a6605492e48b6ce0f37adf8b1f7051ac17be Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Mon, 11 Apr 2022 12:50:11 +0800 Subject: [PATCH 017/365] optimize the algorithm when matching a very long line --- autoload/leaderf/fuzzyMatch_C/fuzzyMatch.c | 9 +++++++++ autoload/leaderf/fuzzyMatch_C/fuzzyMatch.h | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/autoload/leaderf/fuzzyMatch_C/fuzzyMatch.c b/autoload/leaderf/fuzzyMatch_C/fuzzyMatch.c index c4b7a7ca..71129242 100644 --- a/autoload/leaderf/fuzzyMatch_C/fuzzyMatch.c +++ b/autoload/leaderf/fuzzyMatch_C/fuzzyMatch.c @@ -538,8 +538,13 @@ ValueElements* evaluate(TextContext* pText_ctxt, score = prefix_score + pVal->score - 0.3f * (pVal->beg - i); end_pos = pVal->end; } + else + { + break; + } } } + if ( score > max_score ) { max_score = score; @@ -1268,6 +1273,10 @@ HighlightGroup* evaluateHighlights(TextContext* pText_ctxt, memcpy(cur_highlights.positions + 1, pGroup->positions, pGroup->end_index * sizeof(HighlightPos)); cur_highlights.end_index = pGroup->end_index + 1; } + else + { + break; + } } } } diff --git a/autoload/leaderf/fuzzyMatch_C/fuzzyMatch.h b/autoload/leaderf/fuzzyMatch_C/fuzzyMatch.h index 575b2984..daddb33f 100644 --- a/autoload/leaderf/fuzzyMatch_C/fuzzyMatch.h +++ b/autoload/leaderf/fuzzyMatch_C/fuzzyMatch.h @@ -19,7 +19,7 @@ #include "mystdint.h" -#define MIN_WEIGHT (-10000.0f) +#define MIN_WEIGHT (-1000000.0f) typedef struct PatternContext { From e33c9128893a69808b8a1aa077ebeeb86fd9e9b3 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Tue, 12 Apr 2022 14:23:23 +0800 Subject: [PATCH 018/365] optimize the fuzzy matching algorithm --- autoload/leaderf/fuzzyMatch_C/fuzzyMatch.c | 30 ++++++++++------------ 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/autoload/leaderf/fuzzyMatch_C/fuzzyMatch.c b/autoload/leaderf/fuzzyMatch_C/fuzzyMatch.c index 71129242..d6e0fc19 100644 --- a/autoload/leaderf/fuzzyMatch_C/fuzzyMatch.c +++ b/autoload/leaderf/fuzzyMatch_C/fuzzyMatch.c @@ -428,7 +428,6 @@ ValueElements* evaluate(TextContext* pText_ctxt, } if ( bits == 0 ) { - memset(val, 0, sizeof(ValueElements)); return val; } else @@ -1260,23 +1259,20 @@ HighlightGroup* evaluateHighlights(TextContext* pText_ctxt, max_prefix_score = prefix_score; pText_ctxt->offset = i; HighlightGroup* pGroup = evaluateHighlights(pText_ctxt, pPattern_ctxt, k + n, groups); - if ( pGroup ) + if ( pGroup && pGroup->end ) { - if ( pGroup->end ) - { - score = prefix_score + pGroup->score - 0.3f * (pGroup->beg - i); - cur_highlights.score = score; - cur_highlights.beg = i - n; - cur_highlights.end = pGroup->end; - cur_highlights.positions[0].col = i - n + 1; - cur_highlights.positions[0].len = n; - memcpy(cur_highlights.positions + 1, pGroup->positions, pGroup->end_index * sizeof(HighlightPos)); - cur_highlights.end_index = pGroup->end_index + 1; - } - else - { - break; - } + score = prefix_score + pGroup->score - 0.3f * (pGroup->beg - i); + cur_highlights.score = score; + cur_highlights.beg = i - n; + cur_highlights.end = pGroup->end; + cur_highlights.positions[0].col = i - n + 1; + cur_highlights.positions[0].len = n; + memcpy(cur_highlights.positions + 1, pGroup->positions, pGroup->end_index * sizeof(HighlightPos)); + cur_highlights.end_index = pGroup->end_index + 1; + } + else + { + break; } } } From 1ced441e5c6e9aeebf1ce35a107a6a5a645b8894 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 13 Apr 2022 11:35:21 +0800 Subject: [PATCH 019/365] fix issue #10 and #885 --- autoload/leaderf/Any.vim | 2 +- autoload/leaderf/python/leaderf/fileExpl.py | 48 ++++++++++++++++++++- plugin/leaderf.vim | 4 +- 3 files changed, 49 insertions(+), 5 deletions(-) diff --git a/autoload/leaderf/Any.vim b/autoload/leaderf/Any.vim index 6ae4b25c..c25c7abd 100644 --- a/autoload/leaderf/Any.vim +++ b/autoload/leaderf/Any.vim @@ -60,7 +60,7 @@ let g:Lf_Helps = { let g:Lf_Arguments = { \ "file":[ \ [ - \ {"name": ["directory"], "nargs": "?", "help": "serarch files under "}, + \ {"name": ["directory"], "nargs": "*", "help": "serarch files under "}, \ {"name": ["--file"], "nargs": "+", "help": "read file list from the specified file."}, \ ], \ {"name": ["--no-ignore"], "nargs": 0, "help": "don't respect ignore files (.gitignore, .ignore, etc.)."}, diff --git a/autoload/leaderf/python/leaderf/fileExpl.py b/autoload/leaderf/python/leaderf/fileExpl.py index ba5691e6..4be4f64d 100644 --- a/autoload/leaderf/python/leaderf/fileExpl.py +++ b/autoload/leaderf/python/leaderf/fileExpl.py @@ -580,6 +580,48 @@ def setContent(self, content): if lfEval("g:Lf_UseCache") == '1': self._writeCache(content) + def getContentFromMultiDirs(self, dirs, **kwargs): + no_ignore = kwargs.get("arguments", {}).get("--no-ignore") + if no_ignore != self._no_ignore: + self._no_ignore = no_ignore + arg_changes = True + else: + arg_changes = False + + dirs = { os.path.abspath(os.path.expanduser(lfDecode(dir.strip('"').rstrip('\\/')))) for dir in dirs } + if arg_changes or lfEval("g:Lf_UseMemoryCache") == '0' or dirs != self._cur_dir or \ + not self._content: + self._cur_dir = dirs + + cmd = '' + for dir in dirs: + if not os.path.exists(dir): + lfCmd("echoe ' Unknown directory `%s`'" % dir) + return None + + command = self._buildCmd(dir, **kwargs) + if command: + if cmd == '': + cmd = command + else: + cmd += ' && ' + command + + if cmd: + executor = AsyncExecutor() + self._executor.append(executor) + if cmd.split(None, 1)[0] == "dir": + content = executor.execute(cmd, format_line) + else: + if lfEval("get(g:, 'Lf_ShowDevIcons', 1)") == "1": + content = executor.execute(cmd, encoding=lfEval("&encoding"), format_line=format_line) + else: + content = executor.execute(cmd, encoding=lfEval("&encoding")) + self._cmd_start_time = time.time() + return content + + return self._content + + def getContent(self, *args, **kwargs): files = kwargs.get("arguments", {}).get("--file", []) if files: @@ -589,6 +631,9 @@ def getContent(self, *args, **kwargs): self._cmd_work_dir = "" directory = kwargs.get("arguments", {}).get("directory") + if directory and len(directory) > 1: + return self.getContentFromMultiDirs(directory, **kwargs) + if directory and directory[0] not in ['""', "''"]: dir = directory[0].strip('"').rstrip('\\/') if os.path.exists(os.path.expanduser(lfDecode(dir))): @@ -599,8 +644,7 @@ def getContent(self, *args, **kwargs): dir = os.path.abspath(os.path.expanduser(lfDecode(dir))) self._cmd_work_dir = dir else: - lfCmd("echohl ErrorMsg | redraw | echon " - "'Unknown directory `%s`' | echohl NONE" % dir) + lfCmd("echoe ' Unknown directory `%s`'" % dir) return None no_ignore = kwargs.get("arguments", {}).get("--no-ignore") diff --git a/plugin/leaderf.vim b/plugin/leaderf.vim index 891be636..7a367cbb 100644 --- a/plugin/leaderf.vim +++ b/plugin/leaderf.vim @@ -176,8 +176,8 @@ vnoremap LeaderfGtagsReference :=leaderf#Gtags#startCmd vnoremap LeaderfGtagsSymbol :=leaderf#Gtags#startCmdline(2, 1, 's') vnoremap LeaderfGtagsGrep :=leaderf#Gtags#startCmdline(2, 1, 'g') -command! -bar -nargs=? -complete=dir LeaderfFile Leaderf file -command! -bar -nargs=? -complete=dir LeaderfFileFullScreen Leaderf file --fullScreen +command! -bar -nargs=* -complete=dir LeaderfFile Leaderf file +command! -bar -nargs=* -complete=dir LeaderfFileFullScreen Leaderf file --fullScreen command! -bar -nargs=1 LeaderfFilePattern Leaderf file --input command! -bar -nargs=0 LeaderfFileCword Leaderf file --cword From fe8b6b0216c27d6f7f27a3ae49fff39b5963db73 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 13 Apr 2022 14:52:05 +0800 Subject: [PATCH 020/365] fix issue #830 add g:Lf_Global and g:Lf_Gtags --- autoload/leaderf/python/leaderf/gtagsExpl.py | 37 +++++++++++--------- doc/leaderf.txt | 12 +++++++ 2 files changed, 32 insertions(+), 17 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gtagsExpl.py b/autoload/leaderf/python/leaderf/gtagsExpl.py index 4b71e6af..bdd12b62 100644 --- a/autoload/leaderf/python/leaderf/gtagsExpl.py +++ b/autoload/leaderf/python/leaderf/gtagsExpl.py @@ -44,6 +44,8 @@ def __init__(self): self._last_command = "" self._content = [] self._with_gutentags = lfEval("get(g:, 'Lf_GtagsGutentags', 0)") != '0' + self._global = lfEval("get(g:, 'Lf_Global', 'global')") + self._gtags = lfEval("get(g:, 'Lf_Gtags', 'gtags')") self._is_debug = False self._cmd = '' @@ -174,12 +176,13 @@ def getContent(self, *args, **kwargs): env["GTAGSDBPATH"] = dbpath if pattern_option is None: # '--all' or empty means the whole project - cmd = 'global -P | global -L- -f {}--gtagslabel={} {}--color=never --result={}'.format( + cmd = '{} -P | {} -L- -f {}--gtagslabel={} {}--color=never --result={}'.format( + self._global, self._global, '--gtagsconf %s ' % self._gtagsconf if self._gtagsconf else "", self._gtagslabel, path_style, self._result_format) else: - cmd = 'global {}--gtagslabel={} {} {}--color=never --result={}'.format( - '--gtagsconf %s ' % self._gtagsconf if self._gtagsconf else "", + cmd = '{} {}--gtagslabel={} {} {}--color=never --result={}'.format( + self._global, '--gtagsconf %s ' % self._gtagsconf if self._gtagsconf else "", self._gtagslabel, pattern_option, path_style, self._result_format) if not self._isDBModified(os.path.join(dbpath, 'GTAGS')) and self._content \ @@ -244,8 +247,8 @@ def getContent(self, *args, **kwargs): env = os.environ env["GTAGSROOT"] = root env["GTAGSDBPATH"] = dbpath - cmd = 'global {}--gtagslabel={} {} {}{}{}{}--color=never --result={}'.format( - '--gtagsconf %s ' % self._gtagsconf if self._gtagsconf else "", + cmd = '{} {}--gtagslabel={} {} {}{}{}{}--color=never --result={}'.format( + self._global, '--gtagsconf %s ' % self._gtagsconf if self._gtagsconf else "", self._gtagslabel, pattern_option, path_style, scope, literal, ignorecase, self._result_format) @@ -267,8 +270,8 @@ def getContent(self, *args, **kwargs): if path_style == "--path-style abslib ": path_style = "--path-style absolute " - cmd = 'global {}--gtagslabel={} {} {}{}{}{}--color=never --result={} -q'.format( - '--gtagsconf %s ' % self._gtagsconf if self._gtagsconf else "", + cmd = '{} {}--gtagslabel={} {} {}{}{}{}--color=never --result={} -q'.format( + self._global, '--gtagsconf %s ' % self._gtagsconf if self._gtagsconf else "", self._gtagslabel, pattern_option, path_style, scope, literal, ignorecase, self._result_format) @@ -507,8 +510,8 @@ def _update(self, filename, single_update, auto): self._updateLibGtags(root, dbpath) if single_update: if exists: - cmd = 'cd {}"{}" && gtags {}{}{}{}--gtagslabel {} --single-update "{}" "{}"'.format(self._cd_option, root, - self._accept_dotfiles, self._skip_unreadable, self._skip_symlink, + cmd = 'cd {}"{}" && {} {}{}{}{}--gtagslabel {} --single-update "{}" "{}"'.format(self._cd_option, root, + self._gtags, self._accept_dotfiles, self._skip_unreadable, self._skip_symlink, '--gtagsconf %s ' % self._gtagsconf if self._gtagsconf else "", self._gtagslabel, filename, dbpath) env = os.environ @@ -545,8 +548,8 @@ def _updateLibGtags(self, root, dbpath): libdbpath = self._generateDbpath(path) if not os.path.exists(libdbpath): os.makedirs(libdbpath) - cmd = 'cd {}"{}" && gtags -i {}{}{}{}--gtagslabel {} "{}"'.format(self._cd_option, path, - self._accept_dotfiles, self._skip_unreadable, self._skip_symlink, + cmd = 'cd {}"{}" && {} -i {}{}{}{}--gtagslabel {} "{}"'.format(self._cd_option, path, + self._gtags, self._accept_dotfiles, self._skip_unreadable, self._skip_symlink, '--gtagsconf %s ' % self._gtagsconf if self._gtagsconf else "", self._gtagslabel, libdbpath) @@ -836,18 +839,18 @@ def _executeCmd(self, root, dbpath): cmd = self._file_list_cmd(root) if cmd: if os.name == 'nt': - cmd = 'cd {}"{}" && ( {} ) | gtags -i {}{}{}{}--gtagslabel {} -f- "{}"'.format(self._cd_option, root, cmd, - self._accept_dotfiles, self._skip_unreadable, self._skip_symlink, + cmd = 'cd {}"{}" && ( {} ) | {} -i {}{}{}{}--gtagslabel {} -f- "{}"'.format(self._cd_option, root, cmd, + self._gtags, self._accept_dotfiles, self._skip_unreadable, self._skip_symlink, '--gtagsconf %s ' % self._gtagsconf if self._gtagsconf else "", self._gtagslabel, dbpath) else: - cmd = 'cd {}"{}" && {{ {}; }} | gtags -i {}{}{}{}--gtagslabel {} -f- "{}"'.format(self._cd_option, root, cmd, - self._accept_dotfiles, self._skip_unreadable, self._skip_symlink, + cmd = 'cd {}"{}" && {{ {}; }} | {} -i {}{}{}{}--gtagslabel {} -f- "{}"'.format(self._cd_option, root, cmd, + self._gtags, self._accept_dotfiles, self._skip_unreadable, self._skip_symlink, '--gtagsconf %s ' % self._gtagsconf if self._gtagsconf else "", self._gtagslabel, dbpath) else: - cmd = 'cd {}"{}" && gtags -i {}{}{}{}--gtagslabel {} "{}"'.format(self._cd_option, root, - self._accept_dotfiles, self._skip_unreadable, self._skip_symlink, + cmd = 'cd {}"{}" && {} -i {}{}{}{}--gtagslabel {} "{}"'.format(self._cd_option, root, + self._gtags, self._accept_dotfiles, self._skip_unreadable, self._skip_symlink, '--gtagsconf %s ' % self._gtagsconf if self._gtagsconf else "", self._gtagslabel, dbpath) diff --git a/doc/leaderf.txt b/doc/leaderf.txt index 632f80c7..8a03c681 100644 --- a/doc/leaderf.txt +++ b/doc/leaderf.txt @@ -622,6 +622,18 @@ g:Lf_NoChdir *g:Lf_NoChdir* to `dir`. Default value is 1. +g:Lf_Global *g:Lf_Global* + Use this option to customize the global executable to use. e.g., > + let g:Lf_Global = "/bin/global" +< + Default value is "global". + +g:Lf_Gtags *g:Lf_Gtags* + Use this option to customize the global executable to use. e.g., > + let g:Lf_Gtags = "/bin/gtags" +< + Default value is "gtags". + g:Lf_GtagsAutoGenerate *g:Lf_GtagsAutoGenerate* If the value is 1 and there is a rootmark defined by |g:Lf_RootMarkers| under the project root directory, gtags files will be generated From ecd38845d65ffbe4b080cc3c2c1c7f0bfe835bb3 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Tue, 19 Apr 2022 20:54:51 +0800 Subject: [PATCH 021/365] add --absolute-path for `Leaderf mru` --- autoload/leaderf/Any.vim | 1 + autoload/leaderf/python/leaderf/mruExpl.py | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/autoload/leaderf/Any.vim b/autoload/leaderf/Any.vim index c25c7abd..031f7fa8 100644 --- a/autoload/leaderf/Any.vim +++ b/autoload/leaderf/Any.vim @@ -72,6 +72,7 @@ let g:Lf_Arguments = { \ "mru":[ \ {"name": ["--cwd"], "nargs": 0, "help": "search MRU in current working directory"}, \ {"name": ["--no-split-path"], "nargs": 0, "help": "do not split the path"}, + \ {"name": ["--absolute-path"], "nargs": 0, "help": "show absolute path"}, \ ], \ "tag":[], \ "bufTag":[ diff --git a/autoload/leaderf/python/leaderf/mruExpl.py b/autoload/leaderf/python/leaderf/mruExpl.py index 36dc7050..6761defe 100644 --- a/autoload/leaderf/python/leaderf/mruExpl.py +++ b/autoload/leaderf/python/leaderf/mruExpl.py @@ -71,8 +71,9 @@ def getContent(self, *args, **kwargs): self._max_bufname_len = max(int(lfEval("strdisplaywidth('%s')" % escQuote(getBasename(line)))) for line in lines) + show_absolute = "--absolute-path" in kwargs.get("arguments", {}) for i, line in enumerate(lines): - if lfEval("g:Lf_ShowRelativePath") == '1': + if lfEval("g:Lf_ShowRelativePath") == '1' and show_absolute == False: line = lfRelpath(line) basename = getBasename(line) dirname = getDirname(line) From 4eb2c41e394353b10497725a49154bd564176b8f Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Fri, 22 Apr 2022 12:52:01 +0800 Subject: [PATCH 022/365] update the default width and height of popup window --- autoload/leaderf/python/leaderf/instance.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/autoload/leaderf/python/leaderf/instance.py b/autoload/leaderf/python/leaderf/instance.py index b46e870b..1dc43581 100644 --- a/autoload/leaderf/python/leaderf/instance.py +++ b/autoload/leaderf/python/leaderf/instance.py @@ -361,12 +361,16 @@ def _createPopupWindow(self, clear): buf_number = int(lfEval("bufadd('{}')".format(escQuote(self._buffer_name)))) + preview_pos = lfEval("get(g:, 'Lf_PopupPreviewPosition', 'top')") width = lfEval("get(g:, 'Lf_PopupWidth', 0)") width = self._arguments.get("--popup-width", [width])[0] width = width.strip('"').strip("'") width = float(lfEval(width)) if width <= 0: - maxwidth = int(int(lfEval("&columns")) * 2 // 3) + if preview_pos.lower() in ('right', 'left'): + maxwidth = int(int(lfEval("&columns")) * 2 // 5) + else: + maxwidth = int(int(lfEval("&columns")) * 2 // 3) elif width < 1: maxwidth = int(int(lfEval("&columns")) * width) maxwidth = max(20, maxwidth) @@ -380,7 +384,10 @@ def _createPopupWindow(self, clear): height = height.strip('"').strip("'") height = float(lfEval(height)) if height <= 0: - maxheight = int(int(lfEval("&lines")) * 0.4) + if preview_pos.lower() in ('right', 'left'): + maxheight = int(int(lfEval("&lines")) * 0.7) + else: + maxheight = int(int(lfEval("&lines")) * 0.4) elif height < 1: maxheight = int(int(lfEval("&lines")) * height) if maxheight < 1: @@ -398,7 +405,6 @@ def _createPopupWindow(self, clear): line = min(line, int(lfEval("&lines")) - maxheight) if col == 0: - preview_pos = lfEval("get(g:, 'Lf_PopupPreviewPosition', 'top')") if preview_pos.lower() == 'right': col = max(0, (int(lfEval("&columns")) - maxwidth*2) // 2) elif preview_pos.lower() == 'left': From 2817a561495f19a37369c72a1685e3e1e4c3c09d Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Tue, 26 Apr 2022 13:56:14 +0800 Subject: [PATCH 023/365] fix the highlight issue of vimL function with # --- autoload/leaderf/python/leaderf/functionExpl.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/autoload/leaderf/python/leaderf/functionExpl.py b/autoload/leaderf/python/leaderf/functionExpl.py index 2eb4527d..2c792e80 100644 --- a/autoload/leaderf/python/leaderf/functionExpl.py +++ b/autoload/leaderf/python/leaderf/functionExpl.py @@ -293,7 +293,7 @@ def _afterEnter(self): % self._getInstance().getPopupWinId()) id = int(lfEval("matchid")) self._match_ids.append(id) - lfCmd("""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_funcReturnType'', ''^\w\t\zs.\{-}\ze\s*[~]\=\w\+\W\{-}[(\[]'')')""" + lfCmd("""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_funcReturnType'', ''^\w\t\zs.\{-}\ze\s*[~]\=\(\w\|[#:]\)\+\W\{-}[(\[]'')')""" % self._getInstance().getPopupWinId()) id = int(lfEval("matchid")) self._match_ids.append(id) @@ -301,7 +301,7 @@ def _afterEnter(self): % self._getInstance().getPopupWinId()) id = int(lfEval("matchid")) self._match_ids.append(id) - lfCmd("""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_funcName'', ''^\w\t.\{-}\s*\zs[~]\=\w\+\W\{-}\ze[(\[]'')')""" + lfCmd("""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_funcName'', ''^\w\t.\{-}\s*\zs[~]\=\(\w\|[#:]\)\+\W\{-}\ze[(\[]'')')""" % self._getInstance().getPopupWinId()) id = int(lfEval("matchid")) self._match_ids.append(id) @@ -316,11 +316,11 @@ def _afterEnter(self): else: id = int(lfEval('''matchadd('Lf_hl_funcKind', '^\w')''')) self._match_ids.append(id) - id = int(lfEval('''matchadd('Lf_hl_funcReturnType', '^\w\t\zs.\{-}\ze\s*[~]\=\w\+\W\{-}[(\[]')''')) + id = int(lfEval('''matchadd('Lf_hl_funcReturnType', '^\w\t\zs.\{-}\ze\s*[~]\=\(\w\|[#:]\)\+\W\{-}[(\[]')''')) self._match_ids.append(id) id = int(lfEval('''matchadd('Lf_hl_funcScope', '\w*\(<[^>]*>\)\=::')''')) self._match_ids.append(id) - id = int(lfEval('''matchadd('Lf_hl_funcName', '^\w\t.\{-}\s*\zs[~]\=\w\+\W\{-}\ze[(\[]')''')) + id = int(lfEval('''matchadd('Lf_hl_funcName', '^\w\t.\{-}\s*\zs[~]\=\(\w\|[#:]\)\+\W\{-}\ze[(\[]')''')) self._match_ids.append(id) id = int(lfEval('''matchadd('Lf_hl_funcDirname', '\t\zs\[.*:\d\+ \d\+]$')''')) self._match_ids.append(id) From 9ec61062b1e2e55412f28028557c6f970a7e41c6 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Mon, 9 May 2022 11:09:29 +0800 Subject: [PATCH 024/365] fix issue #874 --- autoload/leaderf/Gtags.vim | 2 +- autoload/leaderf/Rg.vim | 2 +- plugin/leaderf.vim | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/autoload/leaderf/Gtags.vim b/autoload/leaderf/Gtags.vim index 3f08b02b..7622c971 100644 --- a/autoload/leaderf/Gtags.vim +++ b/autoload/leaderf/Gtags.vim @@ -66,7 +66,7 @@ function! leaderf#Gtags#getPattern(type) if a:type == 0 return expand('') elseif a:type == 1 - return escape(expand('')) + return '"' . escape(expand(''), '"') . '"' elseif a:type == 2 return leaderf#Gtags#visual() else diff --git a/autoload/leaderf/Rg.vim b/autoload/leaderf/Rg.vim index 6f14125d..36d48350 100644 --- a/autoload/leaderf/Rg.vim +++ b/autoload/leaderf/Rg.vim @@ -73,7 +73,7 @@ function! leaderf#Rg#getPattern(type) if a:type == 0 return expand('') elseif a:type == 1 - return escape(expand('')) + return '"' . escape(expand(''), '"') . '"' elseif a:type == 2 return leaderf#Rg#visual() else diff --git a/plugin/leaderf.vim b/plugin/leaderf.vim index 7a367cbb..54d28b46 100644 --- a/plugin/leaderf.vim +++ b/plugin/leaderf.vim @@ -152,7 +152,7 @@ noremap LeaderfRgBangCwordRegexNoBoundary :=leaderf#Rg#startCm noremap LeaderfRgBangCwordRegexBoundary :=leaderf#Rg#startCmdline(0, 1, 1, 1) noremap LeaderfRgWORDLiteralNoBoundary :=leaderf#Rg#startCmdline(1, 0, 0, 0) -noremap LeaderfRgWORDLiteralBoundary :=leaderf#Rg#startCmdline(1, 0, 0, 1) +noremap LeaderfRgWORDLiteralBoundary :=leaderf#Rg#startCmdline(1, 0, 0, 0) noremap LeaderfRgWORDRegexNoBoundary :=leaderf#Rg#startCmdline(1, 0, 1, 0) noremap LeaderfRgWORDRegexBoundary :=leaderf#Rg#startCmdline(1, 0, 1, 1) From 44c730cb290d5527cb73c4ccf3055b53a0b35240 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Tue, 10 May 2022 22:59:33 +0800 Subject: [PATCH 025/365] fix issue #896 --- autoload/leaderf/python/leaderf/manager.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 3c16a16e..1f5911f8 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -113,7 +113,6 @@ def __init__(self): self._highlight_refine_pos = [] self._highlight_ids = [] self._orig_line = '' - self._ctrlp_pressed = False self._fuzzy_engine = None self._result_content = [] self._reader_thread = None @@ -903,6 +902,7 @@ def _needPreview(self, preview): if True, always preview the result no matter what `g:Lf_PreviewResult` is. """ if "--auto-preview" in self._arguments: + self._orig_line = self._getInstance().currentLine return True preview_dict = {k.lower(): v for k, v in lfEval("g:Lf_PreviewResult").items()} @@ -922,7 +922,7 @@ def _needPreview(self, preview): vim.current.buffer != self._getInstance().buffer): return False - if self._ctrlp_pressed == True: + if preview: return True line = self._getInstance().currentLine @@ -2759,9 +2759,7 @@ def input(self): elif equal(cmd, ''): self.clearSelections() elif equal(cmd, ''): - self._ctrlp_pressed = True self._previewResult(True) - self._ctrlp_pressed = False elif equal(cmd, ''): self._pageUp() self._previewResult(False) From f1da1ca2a4a71e79f4a625f62d8973de5cd2fab9 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 11 May 2022 10:39:57 +0800 Subject: [PATCH 026/365] fix issue #895 --- autoload/leaderf/python/leaderf/instance.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/autoload/leaderf/python/leaderf/instance.py b/autoload/leaderf/python/leaderf/instance.py index 1dc43581..20690313 100644 --- a/autoload/leaderf/python/leaderf/instance.py +++ b/autoload/leaderf/python/leaderf/instance.py @@ -512,7 +512,7 @@ def _createPopupWindow(self, clear): lfCmd("call nvim_win_set_option(%d, 'foldcolumn', 0)" % winid) except vim.error: lfCmd("call nvim_win_set_option(%d, 'foldcolumn', '0')" % winid) - # lfCmd("call nvim_win_set_option(%d, 'signcolumn', 'no')" % winid) + lfCmd("call nvim_win_set_option(%d, 'signcolumn', 'no')" % winid) lfCmd("call nvim_win_set_option(%d, 'cursorline', v:false)" % winid) if lfEval("exists('+cursorlineopt')") == '1': lfCmd("call nvim_win_set_option(%d, 'cursorlineopt', 'both')" % winid) @@ -564,7 +564,7 @@ def getWindow(number): lfCmd("call nvim_win_set_option(%d, 'foldcolumn', 0)" % winid) except vim.error: lfCmd("call nvim_win_set_option(%d, 'foldcolumn', '0')" % winid) - # lfCmd("call nvim_win_set_option(%d, 'signcolumn', 'no')" % winid) + lfCmd("call nvim_win_set_option(%d, 'signcolumn', 'no')" % winid) lfCmd("call nvim_win_set_option(%d, 'cursorline', v:false)" % winid) if lfEval("exists('+cursorlineopt')") == '1': lfCmd("call nvim_win_set_option(%d, 'cursorlineopt', 'both')" % winid) From 6792bddf02d536a5555fd0dc5ac2de94b2539e14 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Fri, 20 May 2022 09:56:41 +0800 Subject: [PATCH 027/365] fix issue #890 --- autoload/leaderf/python/leaderf/manager.py | 1 + 1 file changed, 1 insertion(+) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 1f5911f8..98190347 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -1884,6 +1884,7 @@ def toggleHelp(self): self.clearSelections() self._resetHighlights() + @ignoreEvent('BufUnload') def _accept(self, file, mode, *args, **kwargs): if file: if self._getExplorer().getStlCategory() != "Jumps": From f55c96bf3725db9b817e8cfcdc9ec3efa4c15b95 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Sat, 25 Jun 2022 08:53:03 +0800 Subject: [PATCH 028/365] fix issue #910 --- autoload/leaderf/Any.vim | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/autoload/leaderf/Any.vim b/autoload/leaderf/Any.vim index 031f7fa8..b1125cbd 100644 --- a/autoload/leaderf/Any.vim +++ b/autoload/leaderf/Any.vim @@ -27,6 +27,18 @@ function! leaderf#Any#Maps(category) nnoremap i :exec g:Lf_py b:Lf_AnyExplManager."input()" nnoremap :exec g:Lf_py b:Lf_AnyExplManager."input()" nnoremap :exec g:Lf_py b:Lf_AnyExplManager."toggleHelp()" + nnoremap p :exec g:Lf_py b:Lf_AnyExplManager."_previewResult(True)" + nnoremap j j:exec g:Lf_py b:Lf_AnyExplManager."_previewResult(False)" + nnoremap k k:exec g:Lf_py b:Lf_AnyExplManager."_previewResult(False)" + nnoremap :exec g:Lf_py b:Lf_AnyExplManager."_previewResult(False)" + nnoremap :exec g:Lf_py b:Lf_AnyExplManager."_previewResult(False)" + nnoremap :exec g:Lf_py b:Lf_AnyExplManager."_previewResult(False)" + nnoremap :exec g:Lf_py b:Lf_AnyExplManager."_previewResult(False)" + if has("nvim") + nnoremap :exec g:Lf_py b:Lf_AnyExplManager."_toUpInPopup()" + nnoremap :exec g:Lf_py b:Lf_AnyExplManager."_toDownInPopup()" + nnoremap :exec g:Lf_py b:Lf_AnyExplManager."_closePreviewPopup()" + endif if has_key(g:Lf_NormalMap, a:category) for i in g:Lf_NormalMap[a:category] exec 'nnoremap '.i[0].' '.i[1] From ec37183a3ad41dc3cb58bde8693ad355488fda53 Mon Sep 17 00:00:00 2001 From: qx220 Date: Tue, 28 Jun 2022 21:14:46 -0400 Subject: [PATCH 029/365] fix issue #913 (#918) Co-authored-by: qx --- autoload/leaderf/python/leaderf/manager.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 98190347..6cc8d196 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -719,6 +719,7 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): lfCmd("noautocmd silent! let winid = popup_create(%d, %s)" % (source, json.dumps(options))) else: lfCmd("silent! let winid = popup_create(content, %s)" % json.dumps(options)) + lfCmd("call win_execute(winid, 'setlocal nomodeline')") lfCmd("call win_execute(winid, 'doautocmd filetypedetect BufNewFile %s')" % escQuote(source)) self._preview_winid = int(lfEval("winid")) @@ -880,6 +881,7 @@ def _createPopupPreview(self, title, source, line_nr, jump_cmd=''): lfPrintError(e) return lfCmd("silent! let winid = popup_create(content, %s)" % json.dumps(options)) + lfCmd("call win_execute(winid, 'setlocal nomodeline')") lfCmd("call win_execute(winid, 'doautocmd filetypedetect BufNewFile %s')" % escQuote(source)) self._preview_winid = int(lfEval("winid")) From d914e12c9a5226c831d5a4e732a678ee8d791e0b Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 7 Jul 2022 08:01:23 +0800 Subject: [PATCH 030/365] fix issue #922 --- autoload/leaderf/python/leaderf/bufTagExpl.py | 1 + autoload/leaderf/python/leaderf/functionExpl.py | 1 + autoload/leaderf/python/leaderf/manager.py | 1 + 3 files changed, 3 insertions(+) diff --git a/autoload/leaderf/python/leaderf/bufTagExpl.py b/autoload/leaderf/python/leaderf/bufTagExpl.py index 501e53a4..b12e2b91 100644 --- a/autoload/leaderf/python/leaderf/bufTagExpl.py +++ b/autoload/leaderf/python/leaderf/bufTagExpl.py @@ -488,6 +488,7 @@ def _previewResult(self, preview): if lfEval("get(g:, 'Lf_PreviewInPopup', 0)") == '1': self._previewInPopup(line, self._getInstance().buffer, line_nr) + lfCmd("redraw") return orig_pos = self._getInstance().getOriginalPos() diff --git a/autoload/leaderf/python/leaderf/functionExpl.py b/autoload/leaderf/python/leaderf/functionExpl.py index 2c792e80..80da2acc 100644 --- a/autoload/leaderf/python/leaderf/functionExpl.py +++ b/autoload/leaderf/python/leaderf/functionExpl.py @@ -359,6 +359,7 @@ def _previewResult(self, preview): line = self._getInstance().currentLine if lfEval("get(g:, 'Lf_PreviewInPopup', 0)") == '1': self._previewInPopup(line) + lfCmd("redraw") return orig_pos = self._getInstance().getOriginalPos() diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 6cc8d196..934a2164 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -391,6 +391,7 @@ def _previewResult(self, preview): if lfEval("get(g:, 'Lf_PreviewInPopup', 0)") == '1': line_nr = self._getInstance().window.cursor[0] self._previewInPopup(line, self._getInstance().buffer, line_nr) + lfCmd("redraw") return orig_pos = self._getInstance().getOriginalPos() From d7f0c677ca73239aaef08de25d68451b597a3bdb Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 7 Jul 2022 10:02:03 +0800 Subject: [PATCH 031/365] fix issue #922 --- autoload/leaderf/python/leaderf/bufTagExpl.py | 1 + autoload/leaderf/python/leaderf/functionExpl.py | 1 + autoload/leaderf/python/leaderf/jumpsExpl.py | 1 + 3 files changed, 3 insertions(+) diff --git a/autoload/leaderf/python/leaderf/bufTagExpl.py b/autoload/leaderf/python/leaderf/bufTagExpl.py index b12e2b91..b310b1d3 100644 --- a/autoload/leaderf/python/leaderf/bufTagExpl.py +++ b/autoload/leaderf/python/leaderf/bufTagExpl.py @@ -516,6 +516,7 @@ def _bangEnter(self): self._relocateCursor() def _bangReadFinished(self): + super(BufTagExplManager, self)._bangReadFinished() self._relocateCursor() def _relocateCursor(self): diff --git a/autoload/leaderf/python/leaderf/functionExpl.py b/autoload/leaderf/python/leaderf/functionExpl.py index 80da2acc..55ba9feb 100644 --- a/autoload/leaderf/python/leaderf/functionExpl.py +++ b/autoload/leaderf/python/leaderf/functionExpl.py @@ -387,6 +387,7 @@ def _bangEnter(self): self._relocateCursor() def _bangReadFinished(self): + super(FunctionExplManager, self)._bangReadFinished() self._relocateCursor() def _relocateCursor(self): diff --git a/autoload/leaderf/python/leaderf/jumpsExpl.py b/autoload/leaderf/python/leaderf/jumpsExpl.py index 1802847b..4809f669 100644 --- a/autoload/leaderf/python/leaderf/jumpsExpl.py +++ b/autoload/leaderf/python/leaderf/jumpsExpl.py @@ -176,6 +176,7 @@ def _readFinished(self): break def _bangReadFinished(self): + super(JumpsExplManager, self)._bangReadFinished() self._readFinished() def _previewInPopup(self, *args, **kwargs): From c81ffb908e8011620f371295fdde557aac95e555 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 7 Jul 2022 10:42:52 +0800 Subject: [PATCH 032/365] fix issue #904 #921 --- install.sh | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/install.sh b/install.sh index 43f75ec5..145c66ac 100755 --- a/install.sh +++ b/install.sh @@ -18,17 +18,13 @@ cd autoload/leaderf/fuzzyMatch_C if command -v python2 > /dev/null 2>&1; then no_python=false echo "Begin to compile C extension of Python2 ..." - python2 setup.py build + python2 setup.py build --build-lib ../python if [ $? -eq 0 ] then - cp build/lib*2.*/* ../python - if [ $? -eq 0 ] - then - echo - echo ================================================= - echo ^_^ C extension of Python2 installed sucessfully! - echo ================================================= - fi + echo + echo ================================================= + echo ^_^ C extension of Python2 installed sucessfully! + echo ================================================= fi fi @@ -37,17 +33,13 @@ if command -v python3 > /dev/null 2>&1; then no_python=false echo "Begin to compile C extension of Python3 ..." - python3 setup.py build + python3 setup.py build --build-lib ../python if [ $? -eq 0 ] then - cp build/lib*3.*/* ../python - if [ $? -eq 0 ] - then - echo - echo ================================================= - echo ^_^ C extension of Python3 installed sucessfully! - echo ================================================= - fi + echo + echo ================================================= + echo ^_^ C extension of Python3 installed sucessfully! + echo ================================================= fi fi From 41263eb9c34748d1f9a0f36e83de0ec4c3fcf19e Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Sun, 10 Jul 2022 10:46:50 +0800 Subject: [PATCH 033/365] fix issue #923 --- autoload/leaderf/python/leaderf/mruExpl.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/autoload/leaderf/python/leaderf/mruExpl.py b/autoload/leaderf/python/leaderf/mruExpl.py index 6761defe..5c31193a 100644 --- a/autoload/leaderf/python/leaderf/mruExpl.py +++ b/autoload/leaderf/python/leaderf/mruExpl.py @@ -58,20 +58,20 @@ def getContent(self, *args, **kwargs): self.show_icon = True self._prefix_length = webDevIconsStrLen() + show_absolute = "--absolute-path" in kwargs.get("arguments", {}) if "--no-split-path" in kwargs.get("arguments", {}): - if lfEval("get(g:, 'Lf_ShowDevIcons', 1)") == "0": - return lines - - for line in lines: - return [ + if lfEval("g:Lf_ShowRelativePath") == '1' and show_absolute == False: + lines = [lfRelpath(line) for line in lines] + if lfEval("get(g:, 'Lf_ShowDevIcons', 1)") == "1": + lines = [ webDevIconsGetFileTypeSymbol(getBasename(line)) + line for line in lines ] + return lines self._max_bufname_len = max(int(lfEval("strdisplaywidth('%s')" % escQuote(getBasename(line)))) for line in lines) - show_absolute = "--absolute-path" in kwargs.get("arguments", {}) for i, line in enumerate(lines): if lfEval("g:Lf_ShowRelativePath") == '1' and show_absolute == False: line = lfRelpath(line) From fcfa675f28e097206079b7ce24899c73daeb97f1 Mon Sep 17 00:00:00 2001 From: tcx4c70 Date: Fri, 15 Jul 2022 08:16:44 +0800 Subject: [PATCH 034/365] Fix issure #924 (#926) * make sure that preview window is on top of search window (#924) * show preview below or above cursor automatically in neovim Signed-off-by: Adam Tao --- autoload/leaderf/python/leaderf/manager.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 934a2164..439e995b 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -533,14 +533,20 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): width = float_win_width width = min(width, col) else: - anchor = "SW" start = int(lfEval("line('w0')")) - 1 end = int(lfEval("line('.')")) - 1 col_width = float_window.width - int(lfEval("&numberwidth")) - 1 delta_height = lfActualLineCount(self._getInstance().buffer, start, end, col_width) - row = float_win_row + delta_height + win_height = int(lfEval("&lines")) + if float_win_row + delta_height < win_height // 2: + anchor = "NW" + row = float_win_row + delta_height + 1 + height = win_height - int(lfEval("&cmdheight")) - row + else: + anchor = "SW" + row = float_win_row + delta_height + height = row col = float_win_col + int(lfEval("&numberwidth")) + 1 + float_window.cursor[1] - height = row width = maxwidth config = { @@ -548,6 +554,7 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): "anchor" : anchor, "height" : height, "width" : width, + "zindex" : 20481, "row" : row, "col" : col, "noautocmd": 1 @@ -804,6 +811,7 @@ def _createPopupPreview(self, title, source, line_nr, jump_cmd=''): "anchor" : anchor, "height" : height, "width" : width, + "zindex" : 20480, "row" : row, "col" : col } From 7dc648448e5de788e0498c8c789a980e19dda722 Mon Sep 17 00:00:00 2001 From: tcx4c70 Date: Fri, 15 Jul 2022 08:17:16 +0800 Subject: [PATCH 035/365] Fix g:Lf_PopupPosition in neovim (#927) If set g:Lf_PopupPosition to [1, 0], then the search window will not show from the first line in neovim. Fix it. Signed-off-by: Adam Tao --- autoload/leaderf/python/leaderf/instance.py | 1 + 1 file changed, 1 insertion(+) diff --git a/autoload/leaderf/python/leaderf/instance.py b/autoload/leaderf/python/leaderf/instance.py index 20690313..3cdfa9f0 100644 --- a/autoload/leaderf/python/leaderf/instance.py +++ b/autoload/leaderf/python/leaderf/instance.py @@ -425,6 +425,7 @@ def _createPopupWindow(self, clear): col = 1 if lfEval("has('nvim')") == '1': + line -= 1 col -= 1 self._popup_maxheight = max(maxheight - 2, 1) # there is an input window above From aef58eaa7f328d6f5713a04198c80590bbc4ecba Mon Sep 17 00:00:00 2001 From: Zimin Cai Date: Wed, 20 Jul 2022 09:01:40 +0800 Subject: [PATCH 036/365] fixe issue #928 (#929) Co-authored-by: Zimin Cai --- autoload/leaderf/python/leaderf/gtagsExpl.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autoload/leaderf/python/leaderf/gtagsExpl.py b/autoload/leaderf/python/leaderf/gtagsExpl.py index bdd12b62..8b816a26 100644 --- a/autoload/leaderf/python/leaderf/gtagsExpl.py +++ b/autoload/leaderf/python/leaderf/gtagsExpl.py @@ -862,7 +862,7 @@ def _executeCmd(self, root, dbpath): def print_log(args): print(args) - if error: + if proc.returncode != 0: if self._has_nvim: vim.async_call(print_log, cmd) vim.async_call(print_log, error) From 1137327cf3b3e357c308ee7a459599f7ccfcb4eb Mon Sep 17 00:00:00 2001 From: Shihao Qiu Date: Thu, 1 Sep 2022 10:42:48 +0800 Subject: [PATCH 037/365] Fix issue #948 (#950) --- autoload/leaderf/python/leaderf/rgExpl.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/autoload/leaderf/python/leaderf/rgExpl.py b/autoload/leaderf/python/leaderf/rgExpl.py index 476e4744..a2d2668c 100644 --- a/autoload/leaderf/python/leaderf/rgExpl.py +++ b/autoload/leaderf/python/leaderf/rgExpl.py @@ -952,13 +952,13 @@ def _previewInPopup(self, *args, **kwargs): def outputToQflist(self, *args, **kwargs): items = self._getFormatedContents() - lfCmd("call setqflist(%s, 'r')" % json.dumps(items)) + lfCmd("call setqflist(%s, 'r')" % json.dumps(items, ensure_ascii=False)) lfCmd("echohl WarningMsg | redraw | echo ' Output result to quickfix list.' | echohl NONE") def outputToLoclist(self, *args, **kwargs): items = self._getFormatedContents() winnr = lfEval('bufwinnr(%s)' % self._cur_buffer.number) - lfCmd("call setloclist(%d, %s, 'r')" % (int(winnr), json.dumps(items))) + lfCmd("call setloclist(%d, %s, 'r')" % (int(winnr), json.dumps(items, ensure_ascii=False))) lfCmd("echohl WarningMsg | redraw | echo ' Output result to location list.' | echohl NONE") def _getFormatedContents(self): From 404d7726d097ce1ec64449021dadcc8ae7c181ee Mon Sep 17 00:00:00 2001 From: fhopecc Date: Thu, 15 Sep 2022 11:19:15 +0800 Subject: [PATCH 038/365] =?UTF-8?q?=E6=9F=A5=E6=89=BE=E6=AA=94=E6=A1=88?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E6=96=B0=E5=A2=9E=E6=A0=B9=E6=93=9A=E5=89=AF?= =?UTF-8?q?=E6=AA=94=E5=90=8D=E8=87=AA=E8=A8=82=E8=99=95=E7=90=86=E5=91=BD?= =?UTF-8?q?=E4=BB=A4=20#947=20(#952)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 查找檔案功能新增根據副檔名自訂處理命令 #947 增加g:Lf_FileActions --- autoload/leaderf/python/leaderf/fileExpl.py | 12 +++++++++++- doc/leaderf.txt | 18 ++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/autoload/leaderf/python/leaderf/fileExpl.py b/autoload/leaderf/python/leaderf/fileExpl.py index 4be4f64d..d4124893 100644 --- a/autoload/leaderf/python/leaderf/fileExpl.py +++ b/autoload/leaderf/python/leaderf/fileExpl.py @@ -911,7 +911,17 @@ def _acceptSelection(self, *args, **kwargs): and not vim.current.buffer.options["modified"]): lfCmd("setlocal bufhidden=wipe") - lfCmd("hide edit %s" % escSpecial(file)) + m=lfEval("get(g:, 'Lf_FileActions', {})") + if m != {}: + try: + from os.path import splitext + extension = splitext(file)[-1] + filecmd = m[extension] + lfCmd(f"{filecmd} %s" % escSpecial(file)) + except KeyError: + lfCmd("hide edit %s" % escSpecial(file)) + else: + lfCmd("hide edit %s" % escSpecial(file)) except vim.error: # E37 lfPrintTraceback() diff --git a/doc/leaderf.txt b/doc/leaderf.txt index 8a03c681..05989cbf 100644 --- a/doc/leaderf.txt +++ b/doc/leaderf.txt @@ -1001,6 +1001,24 @@ g:Lf_SpinSymbols *g:Lf_SpinSymbols* For Linux platform, the default value is ['△', '▲', '▷', '▶', '▽', '▼', '◁', '◀'], for Windows and MacOS, the default value is ['🌘', '🌗', '🌖', '🌕', '🌔', '🌓', '🌒', '🌑'] +g:Lf_FileActions *g:Lf_FileActions* + Specify the command to handle the user seleted file instead the default + vim edit command. + + e.g.: > + " _vimrc or .vimrc adding the following code + let g:Lf_FileActions = { '.pdf': '!start' + \,'.doc':'!start' + \,'.docx':'!start' + \,'.odt':'!start' + \,'.xlsx':'!start' + \,'.jpg':'!start' + \} +< + then if the user select "da\db\c.pdf", leaderf will execute command as following: > + :!start da\db\c.pdf +< + to open "da\db\c.pdf" with pdfreader in Windows OS. ============================================================================== USAGE *leaderf-usage* From f090cb40eacdce71c406e466d02e3b41c03312c8 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 15 Sep 2022 17:45:48 +0800 Subject: [PATCH 039/365] fix issue #954 --- autoload/leaderf/python/leaderf/fileExpl.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/autoload/leaderf/python/leaderf/fileExpl.py b/autoload/leaderf/python/leaderf/fileExpl.py index d4124893..fa7ebef9 100644 --- a/autoload/leaderf/python/leaderf/fileExpl.py +++ b/autoload/leaderf/python/leaderf/fileExpl.py @@ -911,13 +911,12 @@ def _acceptSelection(self, *args, **kwargs): and not vim.current.buffer.options["modified"]): lfCmd("setlocal bufhidden=wipe") - m=lfEval("get(g:, 'Lf_FileActions', {})") + m = lfEval("get(g:, 'Lf_FileActions', {})") if m != {}: try: - from os.path import splitext - extension = splitext(file)[-1] + extension = os.path.splitext(file)[-1] filecmd = m[extension] - lfCmd(f"{filecmd} %s" % escSpecial(file)) + lfCmd("%s %s" % (filecmd, escSpecial(file))) except KeyError: lfCmd("hide edit %s" % escSpecial(file)) else: From b7bf04eaeae846168efd86ef0136394a2d128b72 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Mon, 10 Oct 2022 13:32:32 +0800 Subject: [PATCH 040/365] fix issue #958 add `--binary` for `Leaderf rg` --- autoload/leaderf/Any.vim | 1 + autoload/leaderf/python/leaderf/rgExpl.py | 2 ++ 2 files changed, 3 insertions(+) diff --git a/autoload/leaderf/Any.vim b/autoload/leaderf/Any.vim index b1125cbd..2008b5d1 100644 --- a/autoload/leaderf/Any.vim +++ b/autoload/leaderf/Any.vim @@ -117,6 +117,7 @@ let g:Lf_Arguments = { \ {"name": ["-v", "--invert-match"], "nargs": 0, "help": "Invert matching. Show lines that do not match the given patterns."}, \ {"name": ["-w", "--word-regexp"], "nargs": 0, "help": "Only show matches surrounded by word boundaries. This is roughly equivalent to putting \\b before and after all of the search patterns."}, \ {"name": ["-x", "--line-regexp"], "nargs": 0, "help": "Only show matches surrounded by line boundaries."}, + \ {"name": ["--binary"], "nargs": 0, "help": "Enabling this flag will cause ripgrep to search binary files."}, \ {"name": ["--hidden"], "nargs": 0, "help": "Search hidden files and directories. By default, hidden files and directories are skipped."}, \ {"name": ["--heading"], "nargs": 0, "help": "Prints the file path above clusters of matches from each file instead of printing the file path as a prefix for each matched line."}, \ {"name": ["--no-config"], "nargs": 0, "help": "Never read configuration files. When this flag is present, rg will not respect the RIPGREP_CONFIG_PATH environment variable."}, diff --git a/autoload/leaderf/python/leaderf/rgExpl.py b/autoload/leaderf/python/leaderf/rgExpl.py index a2d2668c..b6ac0647 100644 --- a/autoload/leaderf/python/leaderf/rgExpl.py +++ b/autoload/leaderf/python/leaderf/rgExpl.py @@ -105,6 +105,8 @@ def getContent(self, *args, **kwargs): is_perl = False if "-v" in arguments_dict: zero_args_options += "-v " + if "--binary" in arguments_dict: + zero_args_options += "--binary " if "--hidden" in arguments_dict: zero_args_options += "--hidden " if "--no-config" in arguments_dict: From 8c8e625c63a0386e65adcd7d8472a826a26d9615 Mon Sep 17 00:00:00 2001 From: Guangqing Chen Date: Thu, 13 Oct 2022 17:46:25 +0800 Subject: [PATCH 041/365] add solarized colorscheme (#960) --- .../leaderf/colorscheme/popup/solarized.vim | 59 +++++++++++++++++++ autoload/leaderf/colorscheme/solarized.vim | 45 ++++++++++++++ 2 files changed, 104 insertions(+) create mode 100644 autoload/leaderf/colorscheme/popup/solarized.vim create mode 100644 autoload/leaderf/colorscheme/solarized.vim diff --git a/autoload/leaderf/colorscheme/popup/solarized.vim b/autoload/leaderf/colorscheme/popup/solarized.vim new file mode 100644 index 00000000..58cc8557 --- /dev/null +++ b/autoload/leaderf/colorscheme/popup/solarized.vim @@ -0,0 +1,59 @@ +if &background ==? 'dark' + highlight def Lf_hl_popup_inputText guifg=#839496 ctermfg=102 guibg=#002b36 ctermbg=17 + highlight def Lf_hl_popup_window guifg=#839496 ctermfg=102 guibg=#002b36 ctermbg=17 + highlight def Lf_hl_popup_blank guibg=#073642 ctermbg=23 + highlight def Lf_hl_popup_cursor guifg=#657b83 ctermfg=66 guibg=#93a1a1 ctermbg=109 + highlight def Lf_hl_popup_prompt guifg=#b58900 ctermfg=136 guibg=#002b36 ctermbg=17 gui=bold cterm=bold + highlight def Lf_hl_popup_spin guifg=#fdf6e3 ctermfg=230 guibg=#002b36 ctermbg=17 + highlight def Lf_hl_popup_normalMode guifg=#fdf6e3 ctermfg=230 guibg=#93a1a1 ctermbg=109 gui=bold cterm=bold + highlight def Lf_hl_popup_inputMode guifg=#fdf6e3 ctermfg=230 guibg=#b58900 ctermbg=136 gui=bold cterm=bold + highlight def Lf_hl_popup_category guifg=#eee8d5 ctermfg=224 guibg=#657b83 ctermbg=66 + highlight def Lf_hl_popup_nameOnlyMode guifg=#eee8d5 ctermfg=224 guibg=#268bd2 ctermbg=32 + highlight def Lf_hl_popup_fullPathMode guifg=#eee8d5 ctermfg=224 guibg=#586e75 ctermbg=60 + highlight def Lf_hl_popup_fuzzyMode guifg=#eee8d5 ctermfg=224 guibg=#586e75 ctermbg=60 + highlight def Lf_hl_popup_regexMode guifg=#eee8d5 ctermfg=224 guibg=#dc322f ctermbg=166 + highlight def Lf_hl_popup_cwd guifg=#93a1a1 ctermfg=109 guibg=#073642 ctermbg=23 + highlight def Lf_hl_popup_lineInfo guifg=#eee8d5 ctermfg=224 guibg=#657b83 ctermbg=66 + highlight def Lf_hl_popup_total guifg=#fdf6e3 ctermfg=230 guibg=#93a1a1 ctermbg=109 + + highlight def link Lf_hl_popupBorder Normal + + highlight def Lf_hl_cursorline guifg=#fdf6e3 ctermfg=230 + + highlight def Lf_hl_match guifg=#b58900 ctermfg=136 guibg=NONE ctermbg=NONE gui=bold cterm=bold + highlight def Lf_hl_match0 guifg=#d33682 ctermfg=168 guibg=NONE ctermbg=NONE gui=bold cterm=bold + highlight def Lf_hl_match1 guifg=#6c71c4 ctermfg=62 guibg=NONE ctermbg=NONE gui=bold cterm=bold + highlight def Lf_hl_match2 guifg=#268bd2 ctermfg=32 guibg=NONE ctermbg=NONE gui=bold cterm=bold + highlight def Lf_hl_match3 guifg=#2aa198 ctermfg=36 guibg=NONE ctermbg=NONE gui=bold cterm=bold + highlight def Lf_hl_match4 guifg=#859900 ctermfg=100 guibg=NONE ctermbg=NONE gui=bold cterm=bold + highlight def Lf_hl_matchRefine guifg=#cb4b16 ctermfg=166 +else + highlight def Lf_hl_popup_inputText guifg=#657b83 ctermfg=66 guibg=#fdf6e3 ctermbg=230 + highlight def Lf_hl_popup_window guifg=#657b83 ctermfg=66 guibg=#fdf6e3 ctermbg=230 + highlight def Lf_hl_popup_blank guibg=#eee8d5 ctermbg=224 + highlight def Lf_hl_popup_cursor guifg=#b58900 ctermfg=136 guibg=#586e75 ctermbg=60 + highlight def Lf_hl_popup_prompt guifg=#073642 ctermfg=23 guibg=#fdf6e3 ctermbg=230 gui=bold cterm=bold + highlight def Lf_hl_popup_spin guifg=#002b36 ctermfg=17 guibg=#fdf6e3 ctermbg=230 + highlight def Lf_hl_popup_normalMode guifg=#fdf6e3 ctermfg=230 guibg=#586e75 ctermbg=60 gui=bold cterm=bold + highlight def Lf_hl_popup_inputMode guifg=#fdf6e3 ctermfg=230 guibg=#b58900 ctermbg=136 gui=bold cterm=bold + highlight def Lf_hl_popup_category guifg=#eee8d5 ctermfg=224 guibg=#839496 ctermbg=102 + highlight def Lf_hl_popup_nameOnlyMode guifg=#eee8d5 ctermfg=224 guibg=#268bd2 ctermbg=32 + highlight def Lf_hl_popup_fullPathMode guifg=#eee8d5 ctermfg=224 guibg=#93a1a1 ctermbg=109 + highlight def Lf_hl_popup_fuzzyMode guifg=#eee8d5 ctermfg=224 guibg=#93a1a1 ctermbg=109 + highlight def Lf_hl_popup_regexMode guifg=#eee8d5 ctermfg=224 guibg=#dc322f ctermbg=166 + highlight def Lf_hl_popup_cwd guifg=#586e75 ctermfg=60 guibg=#eee8d5 ctermbg=224 + highlight def Lf_hl_popup_lineInfo guifg=#eee8d5 ctermfg=224 guibg=#839496 ctermbg=102 + highlight def Lf_hl_popup_total guifg=#fdf6e3 ctermfg=230 guibg=#586e75 ctermbg=60 + + highlight def link Lf_hl_popupBorder Normal + + highlight def Lf_hl_cursorline guifg=#002b36 ctermfg=17 + + highlight def Lf_hl_match guifg=#b58900 ctermfg=136 guibg=NONE ctermbg=NONE gui=bold cterm=bold + highlight def Lf_hl_match0 guifg=#d33682 ctermfg=168 guibg=NONE ctermbg=NONE gui=bold cterm=bold + highlight def Lf_hl_match1 guifg=#6c71c4 ctermfg=62 guibg=NONE ctermbg=NONE gui=bold cterm=bold + highlight def Lf_hl_match2 guifg=#268bd2 ctermfg=32 guibg=NONE ctermbg=NONE gui=bold cterm=bold + highlight def Lf_hl_match3 guifg=#2aa198 ctermfg=36 guibg=NONE ctermbg=NONE gui=bold cterm=bold + highlight def Lf_hl_match4 guifg=#859900 ctermfg=100 guibg=NONE ctermbg=NONE gui=bold cterm=bold + highlight def Lf_hl_matchRefine guifg=#cb4b16 ctermfg=166 guibg=NONE ctermbg=NONE gui=bold cterm=bold +endif diff --git a/autoload/leaderf/colorscheme/solarized.vim b/autoload/leaderf/colorscheme/solarized.vim new file mode 100644 index 00000000..e184d186 --- /dev/null +++ b/autoload/leaderf/colorscheme/solarized.vim @@ -0,0 +1,45 @@ +if &background ==? 'dark' + let s:palette = { + \ 'match': { 'guifg': '#b58900', 'ctermfg': '136' }, + \ 'match0': { 'guifg': '#d33682', 'ctermfg': '168' }, + \ 'match1': { 'guifg': '#6c71c4', 'ctermfg': '62' }, + \ 'match2': { 'guifg': '#268bd2', 'ctermfg': '32' }, + \ 'match3': { 'guifg': '#2aa198', 'ctermfg': '36' }, + \ 'match4': { 'guifg': '#859900', 'ctermfg': '100' }, + \ 'matchRefine': { 'guifg': '#cb4b16', 'ctermfg': '166' }, + \ 'cursorline': { 'guifg': '#fdf6e3', 'ctermfg': '230' }, + \ 'stlName': { 'guifg': '#fdf6e3', 'ctermfg': '230', 'guibg': '#b58900', 'ctermbg': '136', 'gui': 'bold', 'cterm': 'bold' }, + \ 'stlCategory': { 'guifg': '#eee8d5', 'ctermfg': '224', 'guibg': '#657b83', 'ctermbg': '66', 'gui': 'NONE', 'cterm': 'NONE' }, + \ 'stlNameOnlyMode': { 'guifg': '#eee8d5', 'ctermfg': '224', 'guibg': '#268bd2', 'ctermbg': '32', 'gui': 'NONE', 'cterm': 'NONE' }, + \ 'stlFullPathMode': { 'guifg': '#eee8d5', 'ctermfg': '224', 'guibg': '#586e75', 'ctermbg': '60', 'gui': 'NONE', 'cterm': 'NONE' }, + \ 'stlFuzzyMode': { 'guifg': '#eee8d5', 'ctermfg': '224', 'guibg': '#586e75', 'ctermbg': '60', 'gui': 'NONE', 'cterm': 'NONE' }, + \ 'stlRegexMode': { 'guifg': '#eee8d5', 'ctermfg': '224', 'guibg': '#dc322f', 'ctermbg': '166', 'gui': 'NONE', 'cterm': 'NONE' }, + \ 'stlCwd': { 'guifg': '#93a1a1', 'ctermfg': '109', 'guibg': '#073642', 'ctermbg': '23', 'gui': 'NONE', 'cterm': 'NONE' }, + \ 'stlBlank': { 'guifg': '#93a1a1', 'ctermfg': '109', 'guibg': '#073642', 'ctermbg': '23', 'gui': 'NONE', 'cterm': 'NONE' }, + \ 'stlLineInfo': { 'guifg': '#eee8d5', 'ctermfg': '224', 'guibg': '#657b83', 'ctermbg': '66', 'gui': 'NONE', 'cterm': 'NONE' }, + \ 'stlTotal': { 'guifg': '#fdf6e3', 'ctermfg': '230', 'guibg': '#93a1a1', 'ctermbg': '109', 'gui': 'NONE', 'cterm': 'NONE' }, + \ } +else + let s:palette = { + \ 'match': { 'guifg': '#b58900', 'ctermfg': '136' }, + \ 'match0': { 'guifg': '#d33682', 'ctermfg': '168' }, + \ 'match1': { 'guifg': '#6c71c4', 'ctermfg': '62' }, + \ 'match2': { 'guifg': '#268bd2', 'ctermfg': '32' }, + \ 'match3': { 'guifg': '#2aa198', 'ctermfg': '36' }, + \ 'match4': { 'guifg': '#859900', 'ctermfg': '100' }, + \ 'matchRefine': { 'guifg': '#cb4b16', 'ctermfg': '166' }, + \ 'cursorline': { 'guifg': '#002b36', 'ctermfg': '17' }, + \ 'stlName': { 'guifg': '#fdf6e3', 'ctermfg': '230', 'guibg': '#b58900', 'ctermbg': '136', 'gui': 'bold', 'cterm': 'bold' }, + \ 'stlCategory': { 'guifg': '#eee8d5', 'ctermfg': '224', 'guibg': '#839496', 'ctermbg': '102', 'gui': 'NONE', 'cterm': 'NONE' }, + \ 'stlNameOnlyMode': { 'guifg': '#eee8d5', 'ctermfg': '224', 'guibg': '#268bd2', 'ctermbg': '32', 'gui': 'NONE', 'cterm': 'NONE' }, + \ 'stlFullPathMode': { 'guifg': '#eee8d5', 'ctermfg': '224', 'guibg': '#93a1a1', 'ctermbg': '109', 'gui': 'NONE', 'cterm': 'NONE' }, + \ 'stlFuzzyMode': { 'guifg': '#eee8d5', 'ctermfg': '224', 'guibg': '#93a1a1', 'ctermbg': '109', 'gui': 'NONE', 'cterm': 'NONE' }, + \ 'stlRegexMode': { 'guifg': '#eee8d5', 'ctermfg': '224', 'guibg': '#dc322f', 'ctermbg': '166', 'gui': 'NONE', 'cterm': 'NONE' }, + \ 'stlCwd': { 'guifg': '#586e75', 'ctermfg': '60', 'guibg': '#eee8d5', 'ctermbg': '224', 'gui': 'NONE', 'cterm': 'NONE' }, + \ 'stlBlank': { 'guifg': '#586e75', 'ctermfg': '60', 'guibg': '#eee8d5', 'ctermbg': '224', 'gui': 'NONE', 'cterm': 'NONE' }, + \ 'stlLineInfo': { 'guifg': '#eee8d5', 'ctermfg': '224', 'guibg': '#839496', 'ctermbg': '102', 'gui': 'NONE', 'cterm': 'NONE' }, + \ 'stlTotal': { 'guifg': '#fdf6e3', 'ctermfg': '230', 'guibg': '#586e75', 'ctermbg': '60', 'gui': 'NONE', 'cterm': 'NONE' }, + \ } +endif + +let g:leaderf#colorscheme#solarized#palette = leaderf#colorscheme#mergePalette(s:palette) From ebb1f3a20b83a950938c59200434a4e66b69612d Mon Sep 17 00:00:00 2001 From: Guangqing Chen Date: Thu, 13 Oct 2022 20:35:01 +0800 Subject: [PATCH 042/365] scroll more in preview window (#961) --- autoload/leaderf/python/leaderf/manager.py | 10 ++++++---- doc/leaderf.txt | 5 +++++ 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 439e995b..b75f6b13 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -1042,25 +1042,27 @@ def _setAutochdir(self): def _toUpInPopup(self): if self._preview_winid > 0 and int(lfEval("winbufnr(%d)" % self._preview_winid)) != -1: + scroll_step_size = int(lfEval("get(g:, 'Lf_PreviewScrollStepSize', 1)")) if lfEval("has('nvim')") == '1': cur_winid = lfEval("win_getid()") lfCmd("noautocmd call win_gotoid(%d)" % self._preview_winid) - lfCmd("norm! k") + lfCmd("norm! %dk" % (scroll_step_size)) lfCmd("redraw") lfCmd("noautocmd call win_gotoid(%s)" % cur_winid) else: - lfCmd("call win_execute(%d, 'norm! k')" % (self._preview_winid)) + lfCmd("call win_execute(%d, 'norm! %dk')" % (self._preview_winid, scroll_step_size)) def _toDownInPopup(self): if self._preview_winid > 0 and int(lfEval("winbufnr(%d)" % self._preview_winid)) != -1: + scroll_step_size = int(lfEval("get(g:, 'Lf_PreviewScrollStepSize', 1)")) if lfEval("has('nvim')") == '1': cur_winid = lfEval("win_getid()") lfCmd("noautocmd call win_gotoid(%d)" % self._preview_winid) - lfCmd("norm! j") + lfCmd("norm! %dj" % (scroll_step_size)) lfCmd("redraw") lfCmd("noautocmd call win_gotoid(%s)" % cur_winid) else: - lfCmd("call win_execute(%d, 'norm! j')" % (self._preview_winid)) + lfCmd("call win_execute(%d, 'norm! %dj')" % (self._preview_winid, scroll_step_size)) def _toUp(self): if self._getInstance().getWinPos() == 'popup': diff --git a/doc/leaderf.txt b/doc/leaderf.txt index 05989cbf..cc68bfad 100644 --- a/doc/leaderf.txt +++ b/doc/leaderf.txt @@ -759,6 +759,11 @@ g:Lf_PreviewPopupWidth *g:Lf_PreviewPopupWidth* Default value is 0. +g:Lf_PreviewScrollStepSize *g:Lf_PreviewScrollStepSize* + Specify how many rows will be scrolled at once in the preview window. + + Default value is 1. + g:Lf_PopupWidth *g:Lf_PopupWidth* Specify the width of the popup window or floating window when LeaderF is in popup mode. `Popup mode` is when |g:Lf_WindowPosition| is 'popup' or '--popup' From 1326f60715adf6c434c0a6287e071af02d13dc26 Mon Sep 17 00:00:00 2001 From: zlbruce Date: Tue, 6 Dec 2022 14:46:38 +0800 Subject: [PATCH 043/365] use --build-lib instead of copy file (#972) same as the install.sh way --- install.bat | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/install.bat b/install.bat index 495cc796..35af7c8f 100644 --- a/install.bat +++ b/install.bat @@ -11,31 +11,22 @@ if /i "%1" equ "--reverse" ( ) echo Begin to compile C extension of Python2 ... cd autoload\leaderf\fuzzyMatch_C -py -2 setup.py build -if %errorlevel% neq 0 goto second -pushd build\lib*2.* -xcopy /y *.pyd ..\..\..\python\ +py -2 setup.py build --build-lib ..\python if %errorlevel% equ 0 ( echo= echo =============================================== echo C extension of Python2 installed sucessfully! echo =============================================== ) -popd -:second echo= echo Begin to compile C extension of Python3 ... -py -3 setup.py build -if %errorlevel% neq 0 goto end -pushd build\lib*3.* -xcopy /y *.pyd ..\..\..\python\ +py -3 setup.py build --build-lib ..\python if %errorlevel% equ 0 ( echo= echo =============================================== echo C extension of Python3 installed sucessfully! echo =============================================== ) -popd :end From 3ce1a63f85128beea8d74a52baacea11c105bf0f Mon Sep 17 00:00:00 2001 From: zlbruce Date: Fri, 9 Dec 2022 14:44:31 +0800 Subject: [PATCH 044/365] add onedark colorscheme (#973) --- autoload/leaderf/colorscheme/onedark.vim | 25 +++++++++++++++ .../leaderf/colorscheme/popup/onedark.vim | 32 +++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 autoload/leaderf/colorscheme/onedark.vim create mode 100644 autoload/leaderf/colorscheme/popup/onedark.vim diff --git a/autoload/leaderf/colorscheme/onedark.vim b/autoload/leaderf/colorscheme/onedark.vim new file mode 100644 index 00000000..3f079f1f --- /dev/null +++ b/autoload/leaderf/colorscheme/onedark.vim @@ -0,0 +1,25 @@ +if &background ==? 'dark' + let s:palette = { + \ 'match': { 'guifg': '#E06C75', 'ctermfg': '204' }, + \ 'match0': { 'guifg': '#E06C75', 'ctermfg': '204' }, + \ 'match1': { 'guifg': '#D19A66', 'ctermfg': '173' }, + \ 'match2': { 'guifg': '#61AFEF', 'ctermfg': '39' }, + \ 'match3': { 'guifg': '#98C379', 'ctermfg': '114' }, + \ 'match4': { 'guifg': '#56B6C2', 'ctermfg': '38' }, + \ 'matchRefine': { 'guifg': '#D19A66', 'ctermfg': '173' }, + \ 'cursorline': { 'guifg': '#ABB2BF', 'ctermfg': '145' }, + \ 'stlName': { 'guifg': '#2C323C', 'ctermfg': '236', 'guibg': '#98C379', 'ctermbg': '114', 'gui': 'bold', 'cterm': 'bold' }, + \ 'stlCategory': { 'guifg': '#2C323C', 'ctermfg': '236', 'guibg': '#ABB2BF', 'ctermbg': '145', 'gui': 'NONE', 'cterm': 'NONE' }, + \ 'stlNameOnlyMode': { 'guifg': '#2C323C', 'ctermfg': '236', 'guibg': '#C678DD', 'ctermbg': '170', 'gui': 'NONE', 'cterm': 'NONE' }, + \ 'stlFullPathMode': { 'guifg': '#2C323C', 'ctermfg': '236', 'guibg': '#E5C07B', 'ctermbg': '180', 'gui': 'NONE', 'cterm': 'NONE' }, + \ 'stlFuzzyMode': { 'guifg': '#2C323C', 'ctermfg': '236', 'guibg': '#56B6C2', 'ctermbg': '38', 'gui': 'NONE', 'cterm': 'NONE' }, + \ 'stlRegexMode': { 'guifg': '#2C323C', 'ctermfg': '236', 'guibg': '#E06C75', 'ctermbg': '204', 'gui': 'NONE', 'cterm': 'NONE' }, + \ 'stlCwd': { 'guifg': '#ABB2BF', 'ctermfg': '145', 'guibg': '#3E4452', 'ctermbg': '237', 'gui': 'NONE', 'cterm': 'NONE' }, + \ 'stlBlank': { 'guifg': '#ABB2BF', 'ctermfg': '145', 'guibg': '#282C34', 'ctermbg': '235', 'gui': 'NONE', 'cterm': 'NONE' }, + \ 'stlLineInfo': { 'guifg': '#ABB2BF', 'ctermfg': '145', 'guibg': '#3E4452', 'ctermbg': '237', 'gui': 'NONE', 'cterm': 'NONE' }, + \ 'stlTotal': { 'guifg': '#2C323C', 'ctermfg': '236', 'guibg': '#98C379', 'ctermbg': '114', 'gui': 'NONE', 'cterm': 'NONE' }, + \ 'stlSpin': { 'guifg': '#ABB2BF', 'ctermfg': '145', 'guibg': '#282C34', 'ctermbg': '235', 'gui': 'NONE', 'cterm': 'NONE' }, + \ } +endif + +let g:leaderf#colorscheme#onedark#palette = leaderf#colorscheme#mergePalette(s:palette) diff --git a/autoload/leaderf/colorscheme/popup/onedark.vim b/autoload/leaderf/colorscheme/popup/onedark.vim new file mode 100644 index 00000000..d139cfca --- /dev/null +++ b/autoload/leaderf/colorscheme/popup/onedark.vim @@ -0,0 +1,32 @@ +if &background ==? 'dark' + highlight def Lf_hl_popup_inputText guifg=#ABB2BF ctermfg=145 guibg=#3B4048 ctermbg=238 + highlight def Lf_hl_popup_window guifg=#ABB2BF ctermfg=145 guibg=#3B4048 ctermbg=238 + highlight def Lf_hl_popup_blank guibg=#3E4452 ctermbg=237 + highlight def Lf_hl_popup_cursor guifg=#657b83 ctermfg=66 guibg=#98C379 ctermbg=114 + highlight def Lf_hl_popup_prompt guifg=#D19A66 ctermfg=173 guibg=#3B4048 ctermbg=238 gui=bold cterm=bold + highlight def Lf_hl_popup_spin guifg=#ABB2BF ctermfg=145 guibg=#3B4048 ctermbg=238 + highlight def Lf_hl_popup_normalMode guifg=#2C323C ctermfg=236 guibg=#98C379 ctermbg=114 gui=bold cterm=bold + highlight def Lf_hl_popup_inputMode guifg=#2C323C ctermfg=236 guibg=#61AFEF ctermbg=39 gui=bold cterm=bold + highlight def Lf_hl_popup_category guifg=#2C323C ctermfg=236 guibg=#ABB2BF ctermbg=145 + highlight def Lf_hl_popup_nameOnlyMode guifg=#2C323C ctermfg=236 guibg=#C678DD ctermbg=170 + highlight def Lf_hl_popup_fullPathMode guifg=#2C323C ctermfg=236 guibg=#E5C07B ctermbg=180 + highlight def Lf_hl_popup_fuzzyMode guifg=#2C323C ctermfg=236 guibg=#56B6C2 ctermbg=38 + highlight def Lf_hl_popup_regexMode guifg=#2C323C ctermfg=236 guibg=#E06C75 ctermbg=204 + highlight def Lf_hl_popup_cwd guifg=#ABB2BF ctermfg=145 guibg=#3E4452 ctermbg=237 + highlight def Lf_hl_popup_lineInfo guifg=#ABB2BF ctermfg=145 guibg=#3E4452 ctermbg=237 + highlight def Lf_hl_popup_total guifg=#2C323C ctermfg=236 guibg=#ABB2BF ctermbg=145 + + highlight def link Lf_hl_popupBorder Default + + highlight def Lf_hl_cursorline guifg=#ABB2BF ctermfg=145 guibg=NONE ctermbg=NONE + + highlight def Lf_hl_match guifg=#E06C75 ctermfg=204 guibg=NONE ctermbg=NONE gui=bold cterm=bold + highlight def Lf_hl_match0 guifg=#E06C75 ctermfg=204 guibg=NONE ctermbg=NONE gui=bold cterm=bold + highlight def Lf_hl_match1 guifg=#D19A66 ctermfg=173 guibg=NONE ctermbg=NONE gui=bold cterm=bold + highlight def Lf_hl_match2 guifg=#61AFEF ctermfg=39 guibg=NONE ctermbg=NONE gui=bold cterm=bold + highlight def Lf_hl_match3 guifg=#98C379 ctermfg=114 guibg=NONE ctermbg=NONE gui=bold cterm=bold + highlight def Lf_hl_match4 guifg=#56B6C2 ctermfg=38 guibg=NONE ctermbg=NONE gui=bold cterm=bold + highlight def Lf_hl_matchRefine guifg=#D19A66 ctermfg=173 + + highlight def Lf_hl_selection guifg=#2C323C ctermfg=236 guibg=#E5C07B ctermbg=180 gui=NONE cterm=NONE +endif From 43433aa8dad1601acf923d3c25fa3325799508aa Mon Sep 17 00:00:00 2001 From: fhopecc Date: Sun, 18 Dec 2022 21:16:16 +0800 Subject: [PATCH 045/365] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E4=B8=AD=E6=96=87?= =?UTF-8?q?=E6=AA=94=E5=90=8D=E7=84=A1=E6=B3=95=E5=AF=AB=E5=85=A5mruCache?= =?UTF-8?q?=E5=95=8F=E9=A1=8C=20(#976)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- autoload/leaderf/python/leaderf/mru.py | 2 +- autoload/leaderf/python/leaderf/mruExpl.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/autoload/leaderf/python/leaderf/mru.py b/autoload/leaderf/python/leaderf/mru.py index aa13e21d..5256e43c 100644 --- a/autoload/leaderf/python/leaderf/mru.py +++ b/autoload/leaderf/python/leaderf/mru.py @@ -60,7 +60,7 @@ def saveToCache(self, buf_name_list): if not buf_names: return - with lfOpen(self._cache_file, 'r+', errors='ignore') as f: + with lfOpen(self._cache_file, 'r+', errors='ignore', encoding='utf-8') as f: lines = f.readlines() for name in buf_names: nocase = False diff --git a/autoload/leaderf/python/leaderf/mruExpl.py b/autoload/leaderf/python/leaderf/mruExpl.py index 5c31193a..339106b3 100644 --- a/autoload/leaderf/python/leaderf/mruExpl.py +++ b/autoload/leaderf/python/leaderf/mruExpl.py @@ -31,7 +31,7 @@ def getContent(self, *args, **kwargs): mru.saveToCache(lfEval("readfile(lfMru#CacheFileName())")) lfCmd("call writefile([], lfMru#CacheFileName())") - with lfOpen(mru.getCacheFileName(), 'r+', errors='ignore') as f: + with lfOpen(mru.getCacheFileName(), 'r+', errors='ignore', encoding='utf8') as f: lines = f.readlines() lines = [name for name in lines if os.path.exists(lfDecode(name.rstrip()))] f.seek(0) @@ -102,7 +102,7 @@ def supportsNameOnly(self): return True def delFromCache(self, name): - with lfOpen(mru.getCacheFileName(), 'r+', errors='ignore') as f: + with lfOpen(mru.getCacheFileName(), 'r+', errors='ignore', encoding='utf8') as f: lines = f.readlines() lines.remove(lfEncode(os.path.abspath(lfDecode(name))) + '\n') f.seek(0) From e48b140fb9132cc26cc82c7464e473b8f0af65db Mon Sep 17 00:00:00 2001 From: Jiang Yinzuo <40995042+jiangyinzuo@users.noreply.github.com> Date: Sun, 5 Feb 2023 17:39:08 +0800 Subject: [PATCH 046/365] fix bug in bufExpl.py and rgExpl.py (#984) --- autoload/leaderf/python/leaderf/bufExpl.py | 2 ++ autoload/leaderf/python/leaderf/rgExpl.py | 2 ++ 2 files changed, 4 insertions(+) diff --git a/autoload/leaderf/python/leaderf/bufExpl.py b/autoload/leaderf/python/leaderf/bufExpl.py index 20d578c8..0cae21c5 100644 --- a/autoload/leaderf/python/leaderf/bufExpl.py +++ b/autoload/leaderf/python/leaderf/bufExpl.py @@ -290,6 +290,8 @@ def deleteBuffer(self, wipe=0): def _previewInPopup(self, *args, **kwargs): line = args[0] + if line == '': + return buf_number = int(re.sub(r"^.*?(\d+).*$", r"\1", line)) self._createPopupPreview(vim.buffers[buf_number].name, buf_number, 0) diff --git a/autoload/leaderf/python/leaderf/rgExpl.py b/autoload/leaderf/python/leaderf/rgExpl.py index b6ac0647..c9afdc27 100644 --- a/autoload/leaderf/python/leaderf/rgExpl.py +++ b/autoload/leaderf/python/leaderf/rgExpl.py @@ -496,6 +496,8 @@ def _getFileInfo(self, args): file, line_num = m.group(1, 3) else: m = re.match(r'^(.+?):(\d+):', line) + if m is None: + return (None, None) file, line_num = m.group(1, 2) if not re.search(r"\d+_'No_Name_(\d+)'", file): if not os.path.isabs(file): From 86db2ec0d332c125c6c7d726721c613380978e2e Mon Sep 17 00:00:00 2001 From: zoumi Date: Fri, 17 Feb 2023 09:29:01 +0800 Subject: [PATCH 047/365] set bufname to look like a valid file system path may misleading other vim plugins (#985) Co-authored-by: zoumi <> --- autoload/leaderf/python/leaderf/instance.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autoload/leaderf/python/leaderf/instance.py b/autoload/leaderf/python/leaderf/instance.py index 3cdfa9f0..1144c6fd 100644 --- a/autoload/leaderf/python/leaderf/instance.py +++ b/autoload/leaderf/python/leaderf/instance.py @@ -234,7 +234,7 @@ def __init__(self, manager, category, cli, self._tabpage_object = None self._window_object = None self._buffer_object = None - self._buffer_name = lfEval("expand('$VIMRUNTIME/')") + category + '/LeaderF' + self._buffer_name = 'Leaderf://' + category + '/LeaderF' self._input_buffer_number = -1 self._stl_buffer_number = -1 self._win_height = float(lfEval("g:Lf_WindowHeight")) From 0f9606ee3e7c0e2d3437b88b6aad77ed82609e97 Mon Sep 17 00:00:00 2001 From: zoumi Date: Tue, 21 Feb 2023 10:04:27 +0800 Subject: [PATCH 048/365] if the buffer is not loaded the preview will be empty in vim (#988) Co-authored-by: zoumi <> --- autoload/leaderf/python/leaderf/anyExpl.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autoload/leaderf/python/leaderf/anyExpl.py b/autoload/leaderf/python/leaderf/anyExpl.py index 259189f4..0acd2317 100644 --- a/autoload/leaderf/python/leaderf/anyExpl.py +++ b/autoload/leaderf/python/leaderf/anyExpl.py @@ -380,7 +380,7 @@ def _previewInPopup(self, *args, **kwargs): filename, line_num, jump_cmd = result # for backward compatibility if isinstance(filename, int): # it is a buffer number - pass + lfCmd("call bufload(%d)" % filename) elif lfEval("bufloaded('%s')" % escQuote(filename)) == '1': if not self._has_nvim: # py3 in nvim return str, in vim return bytes filename = lfBytes2Str(filename) From f052e13282149d3ac49540284d1f618ad4cabb56 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 2 Mar 2023 17:27:43 +0800 Subject: [PATCH 049/365] refactor the code about nearestAncestor --- autoload/leaderf/python/leaderf/fileExpl.py | 29 ++-------------- autoload/leaderf/python/leaderf/gtagsExpl.py | 35 +++----------------- autoload/leaderf/python/leaderf/rgExpl.py | 29 ++-------------- autoload/leaderf/python/leaderf/utils.py | 25 ++++++++++++++ 4 files changed, 34 insertions(+), 84 deletions(-) diff --git a/autoload/leaderf/python/leaderf/fileExpl.py b/autoload/leaderf/python/leaderf/fileExpl.py index fa7ebef9..8b0b9e47 100644 --- a/autoload/leaderf/python/leaderf/fileExpl.py +++ b/autoload/leaderf/python/leaderf/fileExpl.py @@ -743,31 +743,6 @@ def _createHelp(self): help.append('" ---------------------------------------------------------') return help - def _nearestAncestor(self, markers, path): - """ - return the nearest ancestor path(including itself) of `path` that contains - one of files or directories in `markers`. - `markers` is a list of file or directory names. - """ - if os.name == 'nt': - # e.g. C:\\ - root = os.path.splitdrive(os.path.abspath(path))[0] + os.sep - else: - root = '/' - - path = os.path.abspath(path) - while path != root: - for name in markers: - if os.path.exists(os.path.join(path, name)): - return path - path = os.path.abspath(os.path.join(path, "..")) - - for name in markers: - if os.path.exists(os.path.join(path, name)): - return path - - return "" - def _afterEnter(self): super(FileExplManager, self)._afterEnter() lfCmd("augroup Lf_File") @@ -824,14 +799,14 @@ def startExplorer(self, win_pos, *args, **kwargs): cur_buf_name = lfDecode(vim.current.buffer.name) fall_back = False if 'a' in mode: - working_dir = self._nearestAncestor(root_markers, self._orig_cwd) + working_dir = nearestAncestor(root_markers, self._orig_cwd) if working_dir: # there exists a root marker in nearest ancestor path chdir(working_dir) else: fall_back = True elif 'A' in mode: if cur_buf_name: - working_dir = self._nearestAncestor(root_markers, os.path.dirname(cur_buf_name)) + working_dir = nearestAncestor(root_markers, os.path.dirname(cur_buf_name)) else: working_dir = "" if working_dir: # there exists a root marker in nearest ancestor path diff --git a/autoload/leaderf/python/leaderf/gtagsExpl.py b/autoload/leaderf/python/leaderf/gtagsExpl.py index 8b816a26..a463101b 100644 --- a/autoload/leaderf/python/leaderf/gtagsExpl.py +++ b/autoload/leaderf/python/leaderf/gtagsExpl.py @@ -373,36 +373,11 @@ def translateRegex(self, regex, is_perl=False): return r'\v' + vim_regex - def _nearestAncestor(self, markers, path): - """ - return the nearest ancestor path(including itself) of `path` that contains - one of files or directories in `markers`. - `markers` is a list of file or directory names. - """ - if os.name == 'nt': - # e.g. C:\\ - root = os.path.splitdrive(os.path.abspath(path))[0] + os.sep - else: - root = '/' - - path = os.path.abspath(path) - while path != root: - for name in markers: - if os.path.exists(os.path.join(path, name)): - return path - path = os.path.abspath(os.path.join(path, "..")) - - for name in markers: - if os.path.exists(os.path.join(path, name)): - return path - - return "" - def _isVersionControl(self, filename): if self._project_root and filename.startswith(self._project_root): return True - ancestor = self._nearestAncestor(self._root_markers, os.path.dirname(filename)) + ancestor = nearestAncestor(self._root_markers, os.path.dirname(filename)) if ancestor: self._project_root = ancestor return True @@ -440,12 +415,12 @@ def _root_dbpath(self, filename): if self._project_root and filename.startswith(self._project_root): root = self._project_root else: - ancestor = self._nearestAncestor(self._root_markers, os.path.dirname(filename)) + ancestor = nearestAncestor(self._root_markers, os.path.dirname(filename)) if ancestor: self._project_root = ancestor root = self._project_root else: - ancestor = self._nearestAncestor(self._root_markers, lfGetCwd()) + ancestor = nearestAncestor(self._root_markers, lfGetCwd()) if ancestor: self._project_root = ancestor root = self._project_root @@ -1200,9 +1175,9 @@ def startExplorer(self, win_pos, *args, **kwargs): else: path = lfGetCwd() root_markers = lfEval("g:Lf_RootMarkers") - project_root = self._getExplorer()._nearestAncestor(root_markers, path) + project_root = nearestAncestor(root_markers, path) if project_root == "" and path != lfGetCwd(): - project_root = self._getExplorer()._nearestAncestor(root_markers, lfGetCwd()) + project_root = nearestAncestor(root_markers, lfGetCwd()) if project_root: chdir(project_root) diff --git a/autoload/leaderf/python/leaderf/rgExpl.py b/autoload/leaderf/python/leaderf/rgExpl.py index c9afdc27..3047c482 100644 --- a/autoload/leaderf/python/leaderf/rgExpl.py +++ b/autoload/leaderf/python/leaderf/rgExpl.py @@ -806,31 +806,6 @@ def _bangEnter(self): else: instance.window.options["cursorline"] = True - def _nearestAncestor(self, markers, path): - """ - return the nearest ancestor path(including itself) of `path` that contains - one of files or directories in `markers`. - `markers` is a list of file or directory names. - """ - if os.name == 'nt': - # e.g. C:\\ - root = os.path.splitdrive(os.path.abspath(path))[0] + os.sep - else: - root = '/' - - path = os.path.abspath(path) - while path != root: - for name in markers: - if os.path.exists(os.path.join(path, name)): - return path - path = os.path.abspath(os.path.join(path, "..")) - - for name in markers: - if os.path.exists(os.path.join(path, name)): - return path - - return "" - def startExplorer(self, win_pos, *args, **kwargs): arguments_dict = kwargs.get("arguments", {}) if "--heading" in arguments_dict: @@ -860,14 +835,14 @@ def startExplorer(self, win_pos, *args, **kwargs): cur_buf_name = lfDecode(vim.current.buffer.name) fall_back = False if 'a' in mode: - working_dir = self._nearestAncestor(root_markers, self._orig_cwd) + working_dir = nearestAncestor(root_markers, self._orig_cwd) if working_dir: # there exists a root marker in nearest ancestor path chdir(working_dir) else: fall_back = True elif 'A' in mode: if cur_buf_name: - working_dir = self._nearestAncestor(root_markers, os.path.dirname(cur_buf_name)) + working_dir = nearestAncestor(root_markers, os.path.dirname(cur_buf_name)) else: working_dir = "" if working_dir: # there exists a root marker in nearest ancestor path diff --git a/autoload/leaderf/python/leaderf/utils.py b/autoload/leaderf/python/leaderf/utils.py index 9bb4d662..e882a59a 100644 --- a/autoload/leaderf/python/leaderf/utils.py +++ b/autoload/leaderf/python/leaderf/utils.py @@ -221,3 +221,28 @@ def lfDrop(type, file_name, line_num=None): lfCmd("hide edit +%d %s" % (line_num, escSpecial(file_name))) else: lfCmd("hide edit %s" % escSpecial(file_name)) + +def nearestAncestor(markers, path): + """ + return the nearest ancestor path(including itself) of `path` that contains + one of files or directories in `markers`. + `markers` is a list of file or directory names. + """ + if os.name == 'nt': + # e.g. C:\\ + root = os.path.splitdrive(os.path.abspath(path))[0] + os.sep + else: + root = '/' + + path = os.path.abspath(path) + while path != root: + for name in markers: + if os.path.exists(os.path.join(path, name)): + return path + path = os.path.abspath(os.path.join(path, "..")) + + for name in markers: + if os.path.exists(os.path.join(path, name)): + return path + + return "" From 44badee0f1aa5ec72b570634d18985fd70c68983 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 2 Mar 2023 17:38:46 +0800 Subject: [PATCH 050/365] fix issue #990 add `--project` for :Leaderf mru --- autoload/leaderf/Any.vim | 5 ++++- autoload/leaderf/python/leaderf/mruExpl.py | 14 +++++++++++--- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/autoload/leaderf/Any.vim b/autoload/leaderf/Any.vim index 2008b5d1..852244a3 100644 --- a/autoload/leaderf/Any.vim +++ b/autoload/leaderf/Any.vim @@ -82,7 +82,10 @@ let g:Lf_Arguments = { \ {"name": ["--tabpage"], "nargs": 0, "help": "search buffers in current tabpage"}, \ ], \ "mru":[ - \ {"name": ["--cwd"], "nargs": 0, "help": "search MRU in current working directory"}, + \ [ + \ {"name": ["--cwd"], "nargs": 0, "help": "search MRU in current working directory"}, + \ {"name": ["--project"], "nargs": 0, "help": "search MRU in the project"}, + \ ], \ {"name": ["--no-split-path"], "nargs": 0, "help": "do not split the path"}, \ {"name": ["--absolute-path"], "nargs": 0, "help": "show absolute path"}, \ ], diff --git a/autoload/leaderf/python/leaderf/mruExpl.py b/autoload/leaderf/python/leaderf/mruExpl.py index 339106b3..b228917a 100644 --- a/autoload/leaderf/python/leaderf/mruExpl.py +++ b/autoload/leaderf/python/leaderf/mruExpl.py @@ -26,6 +26,7 @@ class MruExplorer(Explorer): def __init__(self): self._prefix_length = 0 self._max_bufname_len = 0 + self._root_markers = lfEval("g:Lf_RootMarkers") def getContent(self, *args, **kwargs): mru.saveToCache(lfEval("readfile(lfMru#CacheFileName())")) @@ -38,8 +39,15 @@ def getContent(self, *args, **kwargs): f.truncate(0) f.writelines(lines) - if "--cwd" in kwargs.get("arguments", {}): + arguments_dict = kwargs.get("arguments", {}) + if "--cwd" in arguments_dict: lines = [name for name in lines if lfDecode(name).startswith(lfGetCwd())] + elif "--project" in arguments_dict: + project_root = lfGetCwd() + ancestor = nearestAncestor(self._root_markers, project_root) + if ancestor != "": + project_root = ancestor + lines = [name for name in lines if lfDecode(name).startswith(project_root)] lines = [line.rstrip() for line in lines] # remove the '\n' wildignore = lfEval("g:Lf_MruWildIgnore") @@ -58,8 +66,8 @@ def getContent(self, *args, **kwargs): self.show_icon = True self._prefix_length = webDevIconsStrLen() - show_absolute = "--absolute-path" in kwargs.get("arguments", {}) - if "--no-split-path" in kwargs.get("arguments", {}): + show_absolute = "--absolute-path" in arguments_dict + if "--no-split-path" in arguments_dict: if lfEval("g:Lf_ShowRelativePath") == '1' and show_absolute == False: lines = [lfRelpath(line) for line in lines] if lfEval("get(g:, 'Lf_ShowDevIcons', 1)") == "1": From 1319824e2cbbb8471f7da56a8d787a664bb8faae Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Mon, 20 Mar 2023 14:15:21 +0800 Subject: [PATCH 051/365] fix issue #974 --- autoload/leaderf/python/leaderf/fileExpl.py | 5 +++-- autoload/leaderf/python/leaderf/gtagsExpl.py | 5 +++-- autoload/leaderf/python/leaderf/mruExpl.py | 5 +++-- autoload/leaderf/python/leaderf/qfloclistExpl.py | 5 +++-- autoload/leaderf/python/leaderf/rgExpl.py | 5 +++-- autoload/leaderf/python/leaderf/tagExpl.py | 5 +++-- 6 files changed, 18 insertions(+), 12 deletions(-) diff --git a/autoload/leaderf/python/leaderf/fileExpl.py b/autoload/leaderf/python/leaderf/fileExpl.py index 8b0b9e47..2e582d74 100644 --- a/autoload/leaderf/python/leaderf/fileExpl.py +++ b/autoload/leaderf/python/leaderf/fileExpl.py @@ -896,8 +896,9 @@ def _acceptSelection(self, *args, **kwargs): lfCmd("hide edit %s" % escSpecial(file)) else: lfCmd("hide edit %s" % escSpecial(file)) - except vim.error: # E37 - lfPrintTraceback() + except vim.error as e: # E37 + if 'E325' not in str(e).split(':'): + lfPrintTraceback() #***************************************************** # fileExplManager is a singleton diff --git a/autoload/leaderf/python/leaderf/gtagsExpl.py b/autoload/leaderf/python/leaderf/gtagsExpl.py index a463101b..c6bb045e 100644 --- a/autoload/leaderf/python/leaderf/gtagsExpl.py +++ b/autoload/leaderf/python/leaderf/gtagsExpl.py @@ -932,8 +932,9 @@ def _acceptSelection(self, *args, **kwargs): self._cursorline_dict[vim.current.window] = vim.current.window.options["cursorline"] lfCmd("setlocal cursorline") - except vim.error: - lfPrintTraceback() + except vim.error as e: # E37 + if 'E325' not in str(e).split(':'): + lfPrintTraceback() def updateGtags(self, filename, single_update, auto=True): self._getExplorer().updateGtags(filename, single_update, auto) diff --git a/autoload/leaderf/python/leaderf/mruExpl.py b/autoload/leaderf/python/leaderf/mruExpl.py index b228917a..1ab7bbec 100644 --- a/autoload/leaderf/python/leaderf/mruExpl.py +++ b/autoload/leaderf/python/leaderf/mruExpl.py @@ -191,8 +191,9 @@ def _acceptSelection(self, *args, **kwargs): lfCmd("setlocal bufhidden=wipe") lfCmd("hide edit %s" % escSpecial(file)) - except vim.error: # E37 - lfPrintTraceback() + except vim.error as e: # E37 + if 'E325' not in str(e).split(':'): + lfPrintTraceback() def _getDigest(self, line, mode): """ diff --git a/autoload/leaderf/python/leaderf/qfloclistExpl.py b/autoload/leaderf/python/leaderf/qfloclistExpl.py index edcfcc3f..0582ca96 100644 --- a/autoload/leaderf/python/leaderf/qfloclistExpl.py +++ b/autoload/leaderf/python/leaderf/qfloclistExpl.py @@ -82,8 +82,9 @@ def _acceptSelection(self, *args, **kwargs): lfCmd("call cursor(%s, %s)" % (line_num, col)) lfCmd("norm! zv") lfCmd("norm! zz") - except vim.error: # E37 - lfPrintTraceback() + except vim.error as e: # E37 + if 'E325' not in str(e).split(':'): + lfPrintTraceback() def _getDigest(self, line, mode): """ diff --git a/autoload/leaderf/python/leaderf/rgExpl.py b/autoload/leaderf/python/leaderf/rgExpl.py index 3047c482..417b2ad1 100644 --- a/autoload/leaderf/python/leaderf/rgExpl.py +++ b/autoload/leaderf/python/leaderf/rgExpl.py @@ -558,8 +558,9 @@ def _acceptSelection(self, *args, **kwargs): self._cursorline_dict[vim.current.window] = vim.current.window.options["cursorline"] lfCmd("setlocal cursorline") - except vim.error: - lfPrintTraceback() + except vim.error as e: # E37 + if 'E325' not in str(e).split(':'): + lfPrintTraceback() def setArguments(self, arguments): self._arguments = arguments diff --git a/autoload/leaderf/python/leaderf/tagExpl.py b/autoload/leaderf/python/leaderf/tagExpl.py index 7cb72f40..e768936b 100644 --- a/autoload/leaderf/python/leaderf/tagExpl.py +++ b/autoload/leaderf/python/leaderf/tagExpl.py @@ -87,8 +87,9 @@ def _acceptSelection(self, *args, **kwargs): lfDrop('', tagfile) else: lfCmd("hide edit %s" % escSpecial(tagfile)) - except vim.error: # E37 - lfPrintTraceback() + except vim.error as e: # E37 + if 'E325' not in str(e).split(':'): + lfPrintTraceback() if tagaddress[0] not in '/?': lfCmd(tagaddress) From 4b8f537dadf5f9abbdd1554584bec9c04843909c Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Mon, 20 Mar 2023 14:47:47 +0800 Subject: [PATCH 052/365] fix issue #955 --- autoload/leaderf/python/leaderf/manager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index b75f6b13..0e80ee49 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -785,7 +785,7 @@ def _createPopupPreview(self, title, source, line_nr, jump_cmd=''): lfCmd("let scratch_buffer = nvim_create_buf(0, 1)") lfCmd("call setbufline(scratch_buffer, 1, content)") lfCmd("call nvim_buf_set_option(scratch_buffer, 'bufhidden', 'wipe')") - height = min(maxheight, buffer_len) + height = max(1, min(maxheight, buffer_len)) preview_pos = lfEval("get(g:, 'Lf_PreviewHorizontalPosition', 'right')") if preview_pos.lower() == 'center': col = (int(lfEval("&columns")) - width) // 2 From 45911fd6b436976ae9e83eb0a1968d3b8e72276b Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Fri, 24 Mar 2023 17:36:08 +0800 Subject: [PATCH 053/365] fix issue #999 --- autoload/leaderf/python/leaderf/mruExpl.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autoload/leaderf/python/leaderf/mruExpl.py b/autoload/leaderf/python/leaderf/mruExpl.py index 1ab7bbec..d330789d 100644 --- a/autoload/leaderf/python/leaderf/mruExpl.py +++ b/autoload/leaderf/python/leaderf/mruExpl.py @@ -47,7 +47,7 @@ def getContent(self, *args, **kwargs): ancestor = nearestAncestor(self._root_markers, project_root) if ancestor != "": project_root = ancestor - lines = [name for name in lines if lfDecode(name).startswith(project_root)] + lines = [name for name in lines if lfDecode(name).startswith(os.path.join(project_root, ''))] lines = [line.rstrip() for line in lines] # remove the '\n' wildignore = lfEval("g:Lf_MruWildIgnore") From 4f1fc63ef0ed1f923f306631edd680ea294cc400 Mon Sep 17 00:00:00 2001 From: Zhizhen He Date: Tue, 2 May 2023 14:51:20 +0800 Subject: [PATCH 054/365] Update font name for Droid Sans Mono Nerd Font Mono (#1005) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 480ae490..2181ec52 100644 --- a/README.md +++ b/README.md @@ -295,7 +295,7 @@ Customization " Show icons, icons are shown by default let g:Lf_ShowDevIcons = 1 " For GUI vim, the icon font can be specify like this, for example - let g:Lf_DevIconsFont = "DroidSansMono Nerd Font Mono" + let g:Lf_DevIconsFont = "DroidSansM Nerd Font Mono" " If needs set ambiwidth=double ``` From 81e6e90c212e600d288d45c7e07c379ff445e298 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Sat, 6 May 2023 10:06:56 +0800 Subject: [PATCH 055/365] fix issue #1006 add g:Lf_MruEnable --- doc/leaderf.txt | 4 ++++ plugin/leaderf.vim | 10 ++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/doc/leaderf.txt b/doc/leaderf.txt index cc68bfad..f3f7bbda 100644 --- a/doc/leaderf.txt +++ b/doc/leaderf.txt @@ -1024,6 +1024,10 @@ g:Lf_FileActions *g:Lf_FileActions* :!start da\db\c.pdf < to open "da\db\c.pdf" with pdfreader in Windows OS. + +g:Lf_MruEnable *g:Lf_MruEnable* + Enable `Leaderf mru` or not. + Default value is 1. ============================================================================== USAGE *leaderf-usage* diff --git a/plugin/leaderf.vim b/plugin/leaderf.vim index 54d28b46..d267ed82 100644 --- a/plugin/leaderf.vim +++ b/plugin/leaderf.vim @@ -107,10 +107,12 @@ function! s:Normalize(filename) endif endfunction -augroup LeaderF_Mru - autocmd BufAdd,BufEnter,BufWritePost * call lfMru#record(s:Normalize(expand(':p'))) | - \ call lfMru#recordBuffer(expand('')) -augroup END +if get(g:, 'Lf_MruEnable', 1) == 1 + augroup LeaderF_Mru + autocmd BufAdd,BufEnter,BufWritePost * call lfMru#record(s:Normalize(expand(':p'))) | + \ call lfMru#recordBuffer(expand('')) + augroup END +endif augroup LeaderF_Gtags autocmd! From ada80ec869446d46a8b595ea913507f7d5928f60 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 18 May 2023 15:44:17 +0800 Subject: [PATCH 056/365] fix typos --- autoload/leaderf/fuzzyMatch_C/fuzzyEngine.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/autoload/leaderf/fuzzyMatch_C/fuzzyEngine.c b/autoload/leaderf/fuzzyMatch_C/fuzzyEngine.c index 4b50a15d..bd9764bc 100644 --- a/autoload/leaderf/fuzzyMatch_C/fuzzyEngine.c +++ b/autoload/leaderf/fuzzyMatch_C/fuzzyEngine.c @@ -689,7 +689,7 @@ static PyObject* createWeights(void* weights) * fuzzyMatch(engine, source, pattern, is_name_only=False, sort_results=True) * * `is_name_only` is optional, it defaults to `False`, which indicates using the full path matching algorithm. - * `sort_results` is optional, it defineds to `True`, which indicates whether to sort the results. + * `sort_results` is optional, it defaults to `True`, which indicates whether to sort the results. * * return a tuple, (a list of corresponding weight, a sorted list of items from `source` that match `pattern`). */ @@ -2134,7 +2134,7 @@ static void line_getDigest(char** str, uint32_t* length, Parameter* param) * fuzzyMatchPart(engine, source, pattern, category, param, is_name_only=False, sort_results=True) * * `is_name_only` is optional, it defaults to `False`, which indicates using the full path matching algorithm. - * `sort_results` is optional, it defineds to `True`, which indicates whether to sort the results. + * `sort_results` is optional, it defaults to `True`, which indicates whether to sort the results. * * return a tuple, (a list of corresponding weight, a sorted list of items from `source` that match `pattern`). */ From 50430a7d67dc7e48498509cb85afdae021796bf3 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Fri, 26 May 2023 11:45:23 +0800 Subject: [PATCH 057/365] set proirity of Lf_hl_cursorline to -100 --- autoload/leaderf/python/leaderf/manager.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 0e80ee49..90beb285 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -280,10 +280,10 @@ def _afterEnter(self): self._defineMaps() self._defineCommonMaps() - id = int(lfEval("matchadd('Lf_hl_cursorline', '.*\%#.*', 9)")) + id = int(lfEval("matchadd('Lf_hl_cursorline', '.*\%#.*', -100)")) self._match_ids.append(id) else: - lfCmd("""call win_execute({}, 'let matchid = matchadd(''Lf_hl_cursorline'', ''.*\%#.*'', 9)')""" + lfCmd("""call win_execute({}, 'let matchid = matchadd(''Lf_hl_cursorline'', ''.*\%#.*'', -100)')""" .format(self._getInstance().getPopupWinId())) id = int(lfEval("matchid")) self._match_ids.append(id) From 070923974f288c532d792acffb11f4896650efca Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Mon, 29 May 2023 15:48:27 +0800 Subject: [PATCH 058/365] add `--crlf` for Leaderf rg --- autoload/leaderf/Any.vim | 1 + autoload/leaderf/python/leaderf/rgExpl.py | 2 ++ 2 files changed, 3 insertions(+) diff --git a/autoload/leaderf/Any.vim b/autoload/leaderf/Any.vim index 852244a3..ecc4b798 100644 --- a/autoload/leaderf/Any.vim +++ b/autoload/leaderf/Any.vim @@ -109,6 +109,7 @@ let g:Lf_Arguments = { \ {"name": ["-B", "--before-context"], "nargs": 1, "metavar": "", "help": "Show NUM lines before each match."}, \ {"name": ["-C", "--context"], "nargs": 1, "metavar": "", "help": "Show NUM lines before and after each match."}, \ {"name": ["--context-separator"], "nargs": 1, "metavar": "", "help": "The string used to separate non-contiguous context lines in the output."}, + \ {"name": ["--crlf"], "nargs": 0, "help": "ripgrep will treat CRLF ('\r\n') as a line terminator instead of just '\n'."}, \ {"name": ["-e", "--regexp"], "action": "append", "metavar": "...", \ "help": "A pattern to search for. This option can be provided multiple times, where all patterns given are searched."}, \ {"name": ["-F", "--fixed-strings"], "nargs": 0, "help": "Treat the pattern as a literal string instead of a regular expression."}, diff --git a/autoload/leaderf/python/leaderf/rgExpl.py b/autoload/leaderf/python/leaderf/rgExpl.py index 417b2ad1..476688e4 100644 --- a/autoload/leaderf/python/leaderf/rgExpl.py +++ b/autoload/leaderf/python/leaderf/rgExpl.py @@ -127,6 +127,8 @@ def getContent(self, *args, **kwargs): zero_args_options += "-U " if "--multiline-dotall" in arguments_dict: zero_args_options += "--multiline-dotall " + if "--crlf" in arguments_dict: + zero_args_options += "--crlf " one_args_options = '' if "--context-separator" in arguments_dict: From 0ca6c053847fa8f1a67e27c6b372755380b8f022 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Tue, 30 May 2023 17:20:34 +0800 Subject: [PATCH 059/365] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2181ec52..0a1c3592 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ An efficient fuzzy finder that helps to locate files, buffers, mrus, gtags, etc. - Written in Python. - Support fuzzy and regex searching. - Full-featured. - - [Well-designed fuzzy matching algorithm](https://github.com/Yggdroot/testFuzzyMatch). + - Well-designed fuzzy matching algorithm. - [Extensible](https://github.com/Yggdroot/LeaderF/wiki/Extensions). Changelog From 5746281bb6467522e959f75939976e98da277f1e Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Tue, 30 May 2023 22:24:37 +0800 Subject: [PATCH 060/365] add "--column" for `Leaderf rg` --- autoload/leaderf/Any.vim | 1 + autoload/leaderf/python/leaderf/rgExpl.py | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/autoload/leaderf/Any.vim b/autoload/leaderf/Any.vim index ecc4b798..e50c328a 100644 --- a/autoload/leaderf/Any.vim +++ b/autoload/leaderf/Any.vim @@ -122,6 +122,7 @@ let g:Lf_Arguments = { \ {"name": ["-w", "--word-regexp"], "nargs": 0, "help": "Only show matches surrounded by word boundaries. This is roughly equivalent to putting \\b before and after all of the search patterns."}, \ {"name": ["-x", "--line-regexp"], "nargs": 0, "help": "Only show matches surrounded by line boundaries."}, \ {"name": ["--binary"], "nargs": 0, "help": "Enabling this flag will cause ripgrep to search binary files."}, + \ {"name": ["--column"], "nargs": 0, "help": "Show column numbers (1-based). This only shows the column numbers for the first match on each line."}, \ {"name": ["--hidden"], "nargs": 0, "help": "Search hidden files and directories. By default, hidden files and directories are skipped."}, \ {"name": ["--heading"], "nargs": 0, "help": "Prints the file path above clusters of matches from each file instead of printing the file path as a prefix for each matched line."}, \ {"name": ["--no-config"], "nargs": 0, "help": "Never read configuration files. When this flag is present, rg will not respect the RIPGREP_CONFIG_PATH environment variable."}, diff --git a/autoload/leaderf/python/leaderf/rgExpl.py b/autoload/leaderf/python/leaderf/rgExpl.py index 476688e4..a6d30195 100644 --- a/autoload/leaderf/python/leaderf/rgExpl.py +++ b/autoload/leaderf/python/leaderf/rgExpl.py @@ -107,6 +107,8 @@ def getContent(self, *args, **kwargs): zero_args_options += "-v " if "--binary" in arguments_dict: zero_args_options += "--binary " + if "--column" in arguments_dict: + zero_args_options += "--column " if "--hidden" in arguments_dict: zero_args_options += "--hidden " if "--no-config" in arguments_dict: @@ -567,7 +569,7 @@ def _acceptSelection(self, *args, **kwargs): def setArguments(self, arguments): self._arguments = arguments self._match_path = "--match-path" in arguments - self._has_column = "--column" in lfEval("get(g:, 'Lf_RgConfig', [])") + self._has_column = "--column" in lfEval("get(g:, 'Lf_RgConfig', [])") or "--column" in self._arguments def _getDigest(self, line, mode): """ From 124bcbf036c44ec33e4e6e4b356811b2c086faf0 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 7 Jun 2023 22:20:17 +0800 Subject: [PATCH 061/365] make error message more clear --- autoload/leaderf/python/leaderf/asyncExecutor.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/autoload/leaderf/python/leaderf/asyncExecutor.py b/autoload/leaderf/python/leaderf/asyncExecutor.py index d3566949..55b85c05 100644 --- a/autoload/leaderf/python/leaderf/asyncExecutor.py +++ b/autoload/leaderf/python/leaderf/asyncExecutor.py @@ -102,7 +102,7 @@ def read(source): err = b"".join(iter(self._errQueue.get, None)) if err and raise_except: - raise Exception(lfBytes2Str(err, encoding)) + raise Exception(lfBytes2Str(err) + lfBytes2Str(err, encoding)) except ValueError: pass finally: @@ -150,7 +150,7 @@ def read(source): err = b"".join(iter(self._errQueue.get, None)) if err and raise_except: - raise Exception(err) + raise Exception(lfEncode(err) + err) except ValueError: pass finally: From 86013dd6208609e51c722e91e8faa6c4597ed83a Mon Sep 17 00:00:00 2001 From: leoatchina Date: Fri, 9 Jun 2023 12:51:40 +0800 Subject: [PATCH 062/365] add leader#execute func if execute() function not exists (#1010) --- autoload/leaderf.vim | 11 +++++++++++ autoload/leaderf/python/leaderf/commandExpl.py | 4 ++-- autoload/leaderf/python/leaderf/jumpsExpl.py | 2 +- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/autoload/leaderf.vim b/autoload/leaderf.vim index e1595e91..9123e812 100644 --- a/autoload/leaderf.vim +++ b/autoload/leaderf.vim @@ -327,6 +327,17 @@ endfunction call s:InitCommandMap('g:Lf_CommandMap', s:Lf_CommandMap) +function! leaderf#execute(cmd) + if exists('*execute') + return execute(a:cmd) + else + redir => l:output + silent! execute a:cmd + redir END + return l:output + endif +endfunction + function! leaderf#versionCheck() if g:Lf_PythonVersion == 2 && pyeval("sys.version_info < (2, 7)") echohl Error diff --git a/autoload/leaderf/python/leaderf/commandExpl.py b/autoload/leaderf/python/leaderf/commandExpl.py index 8760b7f6..3f308cac 100644 --- a/autoload/leaderf/python/leaderf/commandExpl.py +++ b/autoload/leaderf/python/leaderf/commandExpl.py @@ -12,7 +12,7 @@ RE_USER_DEFINED_COMMAND = re.compile(r"^.{4}(\w+)") # index.txt line -# "|:silent| :sil[ent] ..." +# "|:silent| :sil[ent] ..." # ^^^^^^ RE_BUILT_IN_COMMAND = re.compile(r"^\|:([^|]+)\|") @@ -33,7 +33,7 @@ def getFreshContent(self, *args, **kwargs): result_list = [] # user-defined Ex commands - result = lfEval("execute('command')") + result = lfEval("leaderf#execute('command')") for line in result.splitlines()[2:]: match = RE_USER_DEFINED_COMMAND.match(line) diff --git a/autoload/leaderf/python/leaderf/jumpsExpl.py b/autoload/leaderf/python/leaderf/jumpsExpl.py index 4809f669..18a3af1f 100644 --- a/autoload/leaderf/python/leaderf/jumpsExpl.py +++ b/autoload/leaderf/python/leaderf/jumpsExpl.py @@ -21,7 +21,7 @@ def getContent(self, *args, **kwargs): return self.getFreshContent(*args, **kwargs) def getFreshContent(self, *args, **kwargs): - content = lfEval("split(execute('jumps'), '\n')") + content = lfEval("split(leaderf#execute('jumps'), '\n')") flag = ' ' self._content = [] From 27bd938a422fc6fcfc453fa88fe2ad453a012074 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Tue, 13 Jun 2023 13:51:48 +0800 Subject: [PATCH 063/365] optimize the performance of preview --- autoload/leaderf.vim | 137 +- autoload/leaderf/Buffer.vim | 93 +- autoload/leaderf/Command.vim | 86 +- autoload/leaderf/File.vim | 101 +- autoload/leaderf/Gtags.vim | 105 +- autoload/leaderf/History.vim | 86 +- autoload/leaderf/Line.vim | 99 +- autoload/leaderf/Mru.vim | 99 +- autoload/leaderf/QfLocList.vim | 92 +- autoload/leaderf/Rg.vim | 96 +- autoload/leaderf/Window.vim | 94 +- autoload/leaderf/python/leaderf/anyExpl.py | 2 +- autoload/leaderf/python/leaderf/bufExpl.py | 3 + autoload/leaderf/python/leaderf/bufTagExpl.py | 34 - autoload/leaderf/python/leaderf/cli.py | 63 +- .../leaderf/python/leaderf/colorschemeExpl.py | 1 - .../leaderf/python/leaderf/functionExpl.py | 32 - autoload/leaderf/python/leaderf/instance.py | 14 +- autoload/leaderf/python/leaderf/manager.py | 198 ++- autoload/leaderf/python/leaderf/rgExpl.py | 2 + autoload/leaderf/python/leaderf/utils.py | 1158 +++++++++++++++++ doc/leaderf.txt | 2 +- 22 files changed, 1472 insertions(+), 1125 deletions(-) diff --git a/autoload/leaderf.vim b/autoload/leaderf.vim index 9123e812..6e484f95 100644 --- a/autoload/leaderf.vim +++ b/autoload/leaderf.vim @@ -11,9 +11,11 @@ if !exists("g:Lf_PythonVersion") if has("python3") let g:Lf_PythonVersion = 3 let g:Lf_py = "py3 " + let g:Lf_PyEval = function("py3eval") elseif has("python") let g:Lf_PythonVersion = 2 let g:Lf_py = "py " + let g:Lf_PyEval = function("pyeval") else echoe "Error: LeaderF requires vim compiled with +python or +python3" finish @@ -22,6 +24,7 @@ else if g:Lf_PythonVersion == 2 if has("python") let g:Lf_py = "py " + let g:Lf_PyEval = function("pyeval") else echoe 'LeaderF Error: has("python") == 0' finish @@ -29,6 +32,7 @@ else else if has("python3") let g:Lf_py = "py3 " + let g:Lf_PyEval = function("py3eval") else echoe 'LeaderF Error: has("python3") == 0' finish @@ -117,13 +121,13 @@ call s:InitVar('g:Lf_WorkingDirectoryMode', 'c') call s:InitVar('g:Lf_WorkingDirectory', '') call s:InitVar('g:Lf_ShowHidden', 0) call s:InitDict('g:Lf_PreviewResult', { - \ 'File': 0, - \ 'Buffer': 0, - \ 'Mru': 0, - \ 'Tag': 0, + \ 'File': 1, + \ 'Buffer': 1, + \ 'Mru': 1, + \ 'Tag': 1, \ 'BufTag': 1, \ 'Function': 1, - \ 'Line': 0, + \ 'Line': 1, \ 'Colorscheme': 0, \ 'Jumps': 1 \}) @@ -137,7 +141,7 @@ call s:InitDict('g:Lf_GtagsfilesCmd', { \ 'default': 'rg --no-messages --files' \}) call s:InitVar('g:Lf_HistoryEditPromptIfEmpty', 1) -call s:InitVar('g:Lf_PopupBorders', ['-','|','-','|','+','+','+','+']) +call s:InitVar('g:Lf_PopupBorders', ["─","│","─","│","╭","╮","╯","╰"]) let s:Lf_CommandMap = { \ '': [''], @@ -375,21 +379,17 @@ function! leaderf#visual() abort endfunction function! leaderf#popupModePreviewFilter(winid, key) abort - let key = get(g:Lf_KeyDict, get(g:Lf_KeyMap, a:key, a:key), a:key) + let key = get(g:Lf_KeyMap, a:key, a:key) if key ==? "" noautocmd call popup_close(a:winid) redraw return 0 - elseif key ==? "" - noautocmd call popup_close(a:winid) - " https://github.com/vim/vim/issues/5216 - "redraw - return 0 elseif key ==? "" if exists("*getmousepos") let pos = getmousepos() if pos.winid == a:winid call win_execute(pos.winid, "call cursor([pos.line, pos.column])") + redraw return 1 endif elseif has('patch-8.1.2266') @@ -415,50 +415,56 @@ function! leaderf#popupModePreviewFilter(winid, key) abort return 1 endif endif - elseif key ==? "" - call win_execute(a:winid, "norm! 3k") - redraw - return 1 - elseif key ==? "" - call win_execute(a:winid, "norm! 3j") - redraw - return 1 + elseif key ==? "" && exists("*getmousepos") + let pos = getmousepos() + if pos.winid == a:winid + call win_execute(a:winid, "norm! 3\") + redraw + return 1 + endif + elseif key ==? "" && exists("*getmousepos") + let pos = getmousepos() + if pos.winid == a:winid + call win_execute(a:winid, "norm! 3\") + redraw + return 1 + endif endif return 0 endfunction -function! leaderf#normalModePreviewFilter(id, winid, key) abort - let key = get(g:Lf_KeyDict, get(g:Lf_KeyMap, a:key, a:key), a:key) +function! leaderf#normalModePreviewFilter(id, lf_winid, winid, key) abort + let key = get(g:Lf_KeyMap, a:key, a:key) if key ==? "" noautocmd call popup_close(a:winid) redraw return 1 - elseif key ==? "" - noautocmd call popup_close(a:winid) - " https://github.com/vim/vim/issues/5216 - "redraw - return 0 elseif key ==? "" && has('patch-8.1.2266') let pos = getmousepos() if pos.winid == a:winid call win_execute(pos.winid, "call cursor([pos.line, pos.column])") - return 1 - else - noautocmd call popup_close(a:winid) redraw + return 1 + elseif pos.winid == a:lf_winid call win_execute(pos.winid, "call cursor([pos.line, pos.column])") exec g:Lf_py "import ctypes" exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value._previewResult(False)", a:id) + return 0 + endif + elseif key ==? "" && exists("*getmousepos") + let pos = getmousepos() + if pos.winid == a:winid + call win_execute(a:winid, "norm! 3\") + "redraw + return 1 + endif + elseif key ==? "" && exists("*getmousepos") + let pos = getmousepos() + if pos.winid == a:winid + call win_execute(a:winid, "norm! 3\") + "redraw return 1 endif - elseif key ==? "" - call win_execute(a:winid, "norm! 3k") - redraw - return 1 - elseif key ==? "" - call win_execute(a:winid, "norm! 3j") - redraw - return 1 elseif key ==? "" call win_execute(a:winid, "norm! k") redraw @@ -478,7 +484,7 @@ endfunction function! leaderf#NormalModeFilter(id, winid, key) abort exec g:Lf_py "import ctypes" - let key = get(g:Lf_KeyDict, get(g:Lf_KeyMap, a:key, a:key), a:key) + let key = get(g:Lf_KeyMap, a:key, a:key) if key !=# "g" call win_execute(a:winid, printf("let g:Lf_%d_is_g_pressed = 0", a:id)) @@ -530,10 +536,15 @@ function! leaderf#NormalModeFilter(id, winid, key) abort elseif key ==? "" if exists("*getmousepos") let pos = getmousepos() - call win_execute(pos.winid, "call cursor([pos.line, pos.column])") - exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value._cli._buildPopupPrompt()", a:id) - redraw - exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value._previewResult(False)", a:id) + if pos.winid == a:winid + call win_execute(pos.winid, "call cursor([pos.line, pos.column])") + exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value._cli._buildPopupPrompt()", a:id) + exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value._previewResult(False)", a:id) + redraw + return 1 + else + return 0 + endif elseif has('patch-8.1.2266') call win_execute(a:winid, "exec v:mouse_lnum") call win_execute(a:winid, "exec 'norm!'.v:mouse_col.'|'") @@ -541,16 +552,30 @@ function! leaderf#NormalModeFilter(id, winid, key) abort redraw exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value._previewResult(False)", a:id) endif - elseif key ==? "" - call win_execute(a:winid, "norm! 3k") - exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value._cli._buildPopupPrompt()", a:id) - redraw - exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value._getInstance().refreshPopupStatusline()", a:id) - elseif key ==? "" - call win_execute(a:winid, "norm! 3j") - exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value._cli._buildPopupPrompt()", a:id) - redraw - exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value._getInstance().refreshPopupStatusline()", a:id) + elseif key ==? "" && exists("*getmousepos") + let pos = getmousepos() + if pos.winid == a:winid + call win_execute(a:winid, "norm! 3\") + exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value._cli._buildPopupPrompt()", a:id) + exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value._getInstance().refreshPopupStatusline()", a:id) + exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value._previewResult(False)", a:id) + redraw + return 1 + else + return 0 + endif + elseif key ==? "" && exists("*getmousepos") + let pos = getmousepos() + if pos.winid == a:winid + call win_execute(a:winid, "norm! 3\") + exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value._cli._buildPopupPrompt()", a:id) + exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value._getInstance().refreshPopupStatusline()", a:id) + exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value._previewResult(False)", a:id) + redraw + return 1 + else + return 0 + endif elseif key ==# "q" || key ==? "" exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value.quit()", a:id) elseif key ==# "i" || key ==? "" @@ -564,12 +589,6 @@ function! leaderf#NormalModeFilter(id, winid, key) abort exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value.accept('v')", a:id) elseif key ==# "t" exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value.accept('t')", a:id) - elseif key ==# "s" - exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value.addSelections()", a:id) - elseif key ==# "a" - exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value.selectAll()", a:id) - elseif key ==# "c" - exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value.clearSelections()", a:id) elseif key ==# "p" exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value._previewResult(True)", a:id) elseif key ==? "" diff --git a/autoload/leaderf/Buffer.vim b/autoload/leaderf/Buffer.vim index 7675139c..04293b9f 100644 --- a/autoload/leaderf/Buffer.vim +++ b/autoload/leaderf/Buffer.vim @@ -41,98 +41,13 @@ function! leaderf#Buffer#Maps() endfunction function! leaderf#Buffer#NormalModeFilter(winid, key) abort - let key = get(g:Lf_KeyDict, get(g:Lf_KeyMap, a:key, a:key), a:key) - - if key !=# "g" - call win_execute(a:winid, "let g:Lf_Buffer_is_g_pressed = 0") - endif - - if key ==# "j" || key ==? "" - call win_execute(a:winid, "norm! j") - exec g:Lf_py "bufExplManager._cli._buildPopupPrompt()" - "redraw - exec g:Lf_py "bufExplManager._getInstance().refreshPopupStatusline()" - elseif key ==# "k" || key ==? "" - call win_execute(a:winid, "norm! k") - exec g:Lf_py "bufExplManager._cli._buildPopupPrompt()" - "redraw - exec g:Lf_py "bufExplManager._getInstance().refreshPopupStatusline()" - elseif key ==? "" || key ==? "" - call win_execute(a:winid, "norm! \") - exec g:Lf_py "bufExplManager._cli._buildPopupPrompt()" - exec g:Lf_py "bufExplManager._getInstance().refreshPopupStatusline()" - elseif key ==? "" || key ==? "" - call win_execute(a:winid, "norm! \") - exec g:Lf_py "bufExplManager._cli._buildPopupPrompt()" - exec g:Lf_py "bufExplManager._getInstance().refreshPopupStatusline()" - elseif key ==# "g" - if get(g:, "Lf_Buffer_is_g_pressed", 0) == 0 - let g:Lf_Buffer_is_g_pressed = 1 - else - let g:Lf_Buffer_is_g_pressed = 0 - call win_execute(a:winid, "norm! gg") - exec g:Lf_py "bufExplManager._cli._buildPopupPrompt()" - redraw - endif - elseif key ==# "G" - call win_execute(a:winid, "norm! G") - exec g:Lf_py "bufExplManager._cli._buildPopupPrompt()" - redraw - elseif key ==? "" - call win_execute(a:winid, "norm! \") - exec g:Lf_py "bufExplManager._cli._buildPopupPrompt()" - redraw - elseif key ==? "" - call win_execute(a:winid, "norm! \") - exec g:Lf_py "bufExplManager._cli._buildPopupPrompt()" - redraw - elseif key ==? "" - if exists("*getmousepos") - let pos = getmousepos() - call win_execute(pos.winid, "call cursor([pos.line, pos.column])") - exec g:Lf_py "bufExplManager._cli._buildPopupPrompt()" - redraw - elseif has('patch-8.1.2266') - call win_execute(a:winid, "exec v:mouse_lnum") - call win_execute(a:winid, "exec 'norm!'.v:mouse_col.'|'") - exec g:Lf_py "bufExplManager._cli._buildPopupPrompt()" - redraw - endif - elseif key ==? "" - call win_execute(a:winid, "norm! 3k") - exec g:Lf_py "bufExplManager._cli._buildPopupPrompt()" - redraw - exec g:Lf_py "bufExplManager._getInstance().refreshPopupStatusline()" - elseif key ==? "" - call win_execute(a:winid, "norm! 3j") - exec g:Lf_py "bufExplManager._cli._buildPopupPrompt()" - redraw - exec g:Lf_py "bufExplManager._getInstance().refreshPopupStatusline()" - elseif key ==# "q" || key ==? "" - exec g:Lf_py "bufExplManager.quit()" - elseif key ==# "i" || key ==? "" - call leaderf#ResetPopupOptions(a:winid, 'filter', 'leaderf#PopupFilter') - exec g:Lf_py "bufExplManager.input()" - elseif key ==# "o" || key ==? "" || key ==? "<2-LeftMouse>" - exec g:Lf_py "bufExplManager.accept()" - elseif key ==# "x" - exec g:Lf_py "bufExplManager.accept('h')" - elseif key ==# "v" - exec g:Lf_py "bufExplManager.accept('v')" - elseif key ==# "t" - exec g:Lf_py "bufExplManager.accept('t')" - elseif key ==# "p" - exec g:Lf_py "bufExplManager._previewResult(True)" - elseif key ==? "" - exec g:Lf_py "bufExplManager.toggleHelp()" - elseif key ==# "d" + let key = get(g:Lf_KeyMap, a:key, a:key) + if key ==# "d" exec g:Lf_py "bufExplManager.deleteBuffer(1)" elseif key ==# "D" exec g:Lf_py "bufExplManager.deleteBuffer()" - elseif key ==? "" - exec g:Lf_py "bufExplManager._toUpInPopup()" - elseif key ==? "" - exec g:Lf_py "bufExplManager._toDownInPopup()" + else + return leaderf#NormalModeFilter(g:Lf_PyEval("id(bufExplManager)"), a:winid, a:key) endif return 1 diff --git a/autoload/leaderf/Command.vim b/autoload/leaderf/Command.vim index d2ab6916..6a7d82f0 100644 --- a/autoload/leaderf/Command.vim +++ b/autoload/leaderf/Command.vim @@ -30,84 +30,18 @@ function! leaderf#Command#Maps() endfunction function! leaderf#Command#NormalModeFilter(winid, key) abort - let key = get(g:Lf_KeyDict, get(g:Lf_KeyMap, a:key, a:key), a:key) + let key = get(g:Lf_KeyMap, a:key, a:key) - if key !=# "g" - call win_execute(a:winid, "let g:Lf_Command_is_g_pressed = 0") - endif - - if key ==# "j" || key ==? "" - call win_execute(a:winid, "norm! j") - exec g:Lf_py "commandExplManager._cli._buildPopupPrompt()" - "redraw - exec g:Lf_py "commandExplManager._getInstance().refreshPopupStatusline()" - elseif key ==# "k" || key ==? "" - call win_execute(a:winid, "norm! k") - exec g:Lf_py "commandExplManager._cli._buildPopupPrompt()" - "redraw - exec g:Lf_py "commandExplManager._getInstance().refreshPopupStatusline()" - elseif key ==? "" || key ==? "" - call win_execute(a:winid, "norm! \") - exec g:Lf_py "commandExplManager._cli._buildPopupPrompt()" - exec g:Lf_py "commandExplManager._getInstance().refreshPopupStatusline()" - elseif key ==? "" || key ==? "" - call win_execute(a:winid, "norm! \") - exec g:Lf_py "commandExplManager._cli._buildPopupPrompt()" - exec g:Lf_py "commandExplManager._getInstance().refreshPopupStatusline()" - elseif key ==# "g" - if get(g:, "Lf_Command_is_g_pressed", 0) == 0 - let g:Lf_Command_is_g_pressed = 1 - else - let g:Lf_Command_is_g_pressed = 0 - call win_execute(a:winid, "norm! gg") - exec g:Lf_py "commandExplManager._cli._buildPopupPrompt()" - redraw - endif - elseif key ==# "G" - call win_execute(a:winid, "norm! G") - exec g:Lf_py "commandExplManager._cli._buildPopupPrompt()" - redraw - elseif key ==? "" - call win_execute(a:winid, "norm! \") - exec g:Lf_py "commandExplManager._cli._buildPopupPrompt()" - redraw - elseif key ==? "" - call win_execute(a:winid, "norm! \") - exec g:Lf_py "commandExplManager._cli._buildPopupPrompt()" - redraw - elseif key ==? "" - if exists("*getmousepos") - let pos = getmousepos() - call win_execute(pos.winid, "call cursor([pos.line, pos.column])") - exec g:Lf_py "commandExplManager._cli._buildPopupPrompt()" - redraw - elseif has('patch-8.1.2266') - call win_execute(a:winid, "exec v:mouse_lnum") - call win_execute(a:winid, "exec 'norm!'.v:mouse_col.'|'") - exec g:Lf_py "commandExplManager._cli._buildPopupPrompt()" - redraw - endif - elseif key ==? "" - call win_execute(a:winid, "norm! 3k") - exec g:Lf_py "commandExplManager._cli._buildPopupPrompt()" - redraw - exec g:Lf_py "commandExplManager._getInstance().refreshPopupStatusline()" - elseif key ==? "" - call win_execute(a:winid, "norm! 3j") - exec g:Lf_py "commandExplManager._cli._buildPopupPrompt()" - redraw - exec g:Lf_py "commandExplManager._getInstance().refreshPopupStatusline()" - elseif key ==# "q" || key ==? "" - exec g:Lf_py "commandExplManager.quit()" - elseif key ==# "i" || key ==? "" - call leaderf#ResetPopupOptions(a:winid, 'filter', 'leaderf#PopupFilter') - exec g:Lf_py "commandExplManager.input()" - elseif key ==# "o" || key ==? "" || key ==? "<2-LeftMouse>" - exec g:Lf_py "commandExplManager.accept()" - elseif key ==? "" - exec g:Lf_py "commandExplManager.toggleHelp()" - elseif key ==? "e" + if key ==# "x" + elseif key ==# "v" + elseif key ==# "t" + elseif key ==# "p" + elseif key ==? "" + elseif key ==? "" + elseif key ==# "e" exec g:Lf_py "commandExplManager.editCommand()" + else + return leaderf#NormalModeFilter(g:Lf_PyEval("id(commandExplManager)"), a:winid, a:key) endif return 1 diff --git a/autoload/leaderf/File.vim b/autoload/leaderf/File.vim index 912390b0..a2a6b402 100644 --- a/autoload/leaderf/File.vim +++ b/autoload/leaderf/File.vim @@ -58,108 +58,17 @@ function! leaderf#File#TimerCallback(id) endfunction function! leaderf#File#NormalModeFilter(winid, key) abort - let key = get(g:Lf_KeyDict, get(g:Lf_KeyMap, a:key, a:key), a:key) - - if key !=# "g" - call win_execute(a:winid, "let g:Lf_File_is_g_pressed = 0") - endif - - if key ==# "j" || key ==? "" - call win_execute(a:winid, "norm! j") - exec g:Lf_py "fileExplManager._cli._buildPopupPrompt()" - "redraw - exec g:Lf_py "fileExplManager._getInstance().refreshPopupStatusline()" - exec g:Lf_py "fileExplManager._previewResult(False)" - elseif key ==# "k" || key ==? "" - call win_execute(a:winid, "norm! k") - exec g:Lf_py "fileExplManager._cli._buildPopupPrompt()" - "redraw - exec g:Lf_py "fileExplManager._getInstance().refreshPopupStatusline()" - exec g:Lf_py "fileExplManager._previewResult(False)" - elseif key ==? "" || key ==? "" - call win_execute(a:winid, "norm! \") - exec g:Lf_py "fileExplManager._cli._buildPopupPrompt()" - exec g:Lf_py "fileExplManager._getInstance().refreshPopupStatusline()" - exec g:Lf_py "fileExplManager._previewResult(False)" - elseif key ==? "" || key ==? "" - call win_execute(a:winid, "norm! \") - exec g:Lf_py "fileExplManager._cli._buildPopupPrompt()" - exec g:Lf_py "fileExplManager._getInstance().refreshPopupStatusline()" - exec g:Lf_py "fileExplManager._previewResult(False)" - elseif key ==# "g" - if get(g:, "Lf_File_is_g_pressed", 0) == 0 - let g:Lf_File_is_g_pressed = 1 - else - let g:Lf_File_is_g_pressed = 0 - call win_execute(a:winid, "norm! gg") - exec g:Lf_py "fileExplManager._cli._buildPopupPrompt()" - redraw - endif - elseif key ==# "G" - call win_execute(a:winid, "norm! G") - exec g:Lf_py "fileExplManager._cli._buildPopupPrompt()" - redraw - elseif key ==? "" - call win_execute(a:winid, "norm! \") - exec g:Lf_py "fileExplManager._cli._buildPopupPrompt()" - redraw - elseif key ==? "" - call win_execute(a:winid, "norm! \") - exec g:Lf_py "fileExplManager._cli._buildPopupPrompt()" - redraw - elseif key ==? "" - if exists("*getmousepos") - let pos = getmousepos() - call win_execute(pos.winid, "call cursor([pos.line, pos.column])") - exec g:Lf_py "fileExplManager._cli._buildPopupPrompt()" - redraw - exec g:Lf_py "fileExplManager._previewResult(False)" - elseif has('patch-8.1.2266') - call win_execute(a:winid, "exec v:mouse_lnum") - call win_execute(a:winid, "exec 'norm!'.v:mouse_col.'|'") - exec g:Lf_py "fileExplManager._cli._buildPopupPrompt()" - redraw - exec g:Lf_py "fileExplManager._previewResult(False)" - endif - elseif key ==? "" - call win_execute(a:winid, "norm! 3k") - exec g:Lf_py "fileExplManager._cli._buildPopupPrompt()" - redraw - exec g:Lf_py "fileExplManager._getInstance().refreshPopupStatusline()" - elseif key ==? "" - call win_execute(a:winid, "norm! 3j") - exec g:Lf_py "fileExplManager._cli._buildPopupPrompt()" - redraw - exec g:Lf_py "fileExplManager._getInstance().refreshPopupStatusline()" - elseif key ==# "q" || key ==? "" - exec g:Lf_py "fileExplManager.quit()" - elseif key ==# "i" || key ==? "" - call leaderf#ResetPopupOptions(a:winid, 'filter', 'leaderf#PopupFilter') - exec g:Lf_py "fileExplManager.input()" - elseif key ==# "o" || key ==? "" || key ==? "<2-LeftMouse>" - exec g:Lf_py "fileExplManager.accept()" - elseif key ==# "x" - exec g:Lf_py "fileExplManager.accept('h')" - elseif key ==# "v" - exec g:Lf_py "fileExplManager.accept('v')" - elseif key ==# "t" - exec g:Lf_py "fileExplManager.accept('t')" + let key = get(g:Lf_KeyMap, a:key, a:key) + if key ==? "" + exec g:Lf_py "fileExplManager.refresh()" elseif key ==# "s" exec g:Lf_py "fileExplManager.addSelections()" elseif key ==# "a" exec g:Lf_py "fileExplManager.selectAll()" elseif key ==# "c" exec g:Lf_py "fileExplManager.clearSelections()" - elseif key ==# "p" - exec g:Lf_py "fileExplManager._previewResult(True)" - elseif key ==? "" - exec g:Lf_py "fileExplManager.toggleHelp()" - elseif key ==? "" - exec g:Lf_py "fileExplManager.refresh()" - elseif key ==? "" - exec g:Lf_py "fileExplManager._toUpInPopup()" - elseif key ==? "" - exec g:Lf_py "fileExplManager._toDownInPopup()" + else + return leaderf#NormalModeFilter(g:Lf_PyEval("id(fileExplManager)"), a:winid, a:key) endif return 1 diff --git a/autoload/leaderf/Gtags.vim b/autoload/leaderf/Gtags.vim index 7622c971..8d02eeae 100644 --- a/autoload/leaderf/Gtags.vim +++ b/autoload/leaderf/Gtags.vim @@ -107,102 +107,17 @@ EOF endfunction function! leaderf#Gtags#NormalModeFilter(winid, key) abort - let key = get(g:Lf_KeyDict, get(g:Lf_KeyMap, a:key, a:key), a:key) - - if key !=# "g" - call win_execute(a:winid, "let g:Lf_Gtags_is_g_pressed = 0") - endif - - if key ==# "j" || key ==? "" - call win_execute(a:winid, "norm! j") - exec g:Lf_py "gtagsExplManager._cli._buildPopupPrompt()" - "redraw - exec g:Lf_py "gtagsExplManager._getInstance().refreshPopupStatusline()" - exec g:Lf_py "gtagsExplManager._previewResult(False)" - elseif key ==# "k" || key ==? "" - call win_execute(a:winid, "norm! k") - exec g:Lf_py "gtagsExplManager._cli._buildPopupPrompt()" - "redraw - exec g:Lf_py "gtagsExplManager._getInstance().refreshPopupStatusline()" - exec g:Lf_py "gtagsExplManager._previewResult(False)" - elseif key ==? "" || key ==? "" - call win_execute(a:winid, "norm! \") - exec g:Lf_py "gtagsExplManager._cli._buildPopupPrompt()" - exec g:Lf_py "gtagsExplManager._getInstance().refreshPopupStatusline()" - exec g:Lf_py "gtagsExplManager._previewResult(False)" - elseif key ==? "" || key ==? "" - call win_execute(a:winid, "norm! \") - exec g:Lf_py "gtagsExplManager._cli._buildPopupPrompt()" - exec g:Lf_py "gtagsExplManager._getInstance().refreshPopupStatusline()" - exec g:Lf_py "gtagsExplManager._previewResult(False)" - elseif key ==# "g" - if get(g:, "Lf_Gtags_is_g_pressed", 0) == 0 - let g:Lf_Gtags_is_g_pressed = 1 - else - let g:Lf_Gtags_is_g_pressed = 0 - call win_execute(a:winid, "norm! gg") - exec g:Lf_py "gtagsExplManager._cli._buildPopupPrompt()" - redraw - endif - elseif key ==# "G" - call win_execute(a:winid, "norm! G") - exec g:Lf_py "gtagsExplManager._cli._buildPopupPrompt()" - redraw - elseif key ==? "" - call win_execute(a:winid, "norm! \") - exec g:Lf_py "gtagsExplManager._cli._buildPopupPrompt()" - redraw - elseif key ==? "" - call win_execute(a:winid, "norm! \") - exec g:Lf_py "gtagsExplManager._cli._buildPopupPrompt()" - redraw - elseif key ==? "" - if exists("*getmousepos") - let pos = getmousepos() - call win_execute(pos.winid, "call cursor([pos.line, pos.column])") - exec g:Lf_py "gtagsExplManager._cli._buildPopupPrompt()" - redraw - exec g:Lf_py "gtagsExplManager._previewResult(False)" - elseif has('patch-8.1.2266') - call win_execute(a:winid, "exec v:mouse_lnum") - call win_execute(a:winid, "exec 'norm!'.v:mouse_col.'|'") - exec g:Lf_py "gtagsExplManager._cli._buildPopupPrompt()" - redraw - exec g:Lf_py "gtagsExplManager._previewResult(False)" - endif - elseif key ==? "" - call win_execute(a:winid, "norm! 3k") - exec g:Lf_py "gtagsExplManager._cli._buildPopupPrompt()" - redraw - exec g:Lf_py "gtagsExplManager._getInstance().refreshPopupStatusline()" - elseif key ==? "" - call win_execute(a:winid, "norm! 3j") - exec g:Lf_py "gtagsExplManager._cli._buildPopupPrompt()" - redraw - exec g:Lf_py "gtagsExplManager._getInstance().refreshPopupStatusline()" - elseif key ==# "q" || key ==? "" - exec g:Lf_py "gtagsExplManager.quit()" - elseif key ==# "i" || key ==? "" - call leaderf#ResetPopupOptions(a:winid, 'filter', 'leaderf#PopupFilter') - exec g:Lf_py "gtagsExplManager.input()" - elseif key ==# "o" || key ==? "" || key ==? "<2-LeftMouse>" - exec g:Lf_py "gtagsExplManager.accept()" - elseif key ==# "x" - exec g:Lf_py "gtagsExplManager.accept('h')" - elseif key ==# "v" - exec g:Lf_py "gtagsExplManager.accept('v')" - elseif key ==# "t" - exec g:Lf_py "gtagsExplManager.accept('t')" - elseif key ==# "p" - exec g:Lf_py "gtagsExplManager._previewResult(True)" - elseif key ==? "" - exec g:Lf_py "gtagsExplManager.toggleHelp()" - elseif key ==# "d" + let key = get(g:Lf_KeyMap, a:key, a:key) + if key ==# "d" exec g:Lf_py "gtagsExplManager.deleteCurrentLine()" - elseif key ==? "" - exec g:Lf_py "gtagsExplManager._toUpInPopup()" - elseif key ==? "" - exec g:Lf_py "gtagsExplManager._toDownInPopup()" + elseif key ==# "s" + exec g:Lf_py "gtagsExplManager.addSelections()" + elseif key ==# "a" + exec g:Lf_py "gtagsExplManager.selectAll()" + elseif key ==# "c" + exec g:Lf_py "gtagsExplManager.clearSelections()" + else + return leaderf#NormalModeFilter(g:Lf_PyEval("id(gtagsExplManager)"), a:winid, a:key) endif return 1 diff --git a/autoload/leaderf/History.vim b/autoload/leaderf/History.vim index 4316127f..d53d1a16 100644 --- a/autoload/leaderf/History.vim +++ b/autoload/leaderf/History.vim @@ -29,84 +29,18 @@ function! leaderf#History#Maps() endfunction function! leaderf#History#NormalModeFilter(winid, key) abort - let key = get(g:Lf_KeyDict, get(g:Lf_KeyMap, a:key, a:key), a:key) + let key = get(g:Lf_KeyMap, a:key, a:key) - if key !=# "g" - call win_execute(a:winid, "let g:Lf_History_is_g_pressed = 0") - endif - - if key ==# "j" || key ==? "" - call win_execute(a:winid, "norm! j") - exec g:Lf_py "historyExplManager._cli._buildPopupPrompt()" - "redraw - exec g:Lf_py "historyExplManager._getInstance().refreshPopupStatusline()" - elseif key ==# "k" || key ==? "" - call win_execute(a:winid, "norm! k") - exec g:Lf_py "historyExplManager._cli._buildPopupPrompt()" - "redraw - exec g:Lf_py "historyExplManager._getInstance().refreshPopupStatusline()" - elseif key ==? "" || key ==? "" - call win_execute(a:winid, "norm! \") - exec g:Lf_py "historyExplManager._cli._buildPopupPrompt()" - exec g:Lf_py "historyExplManager._getInstance().refreshPopupStatusline()" - elseif key ==? "" || key ==? "" - call win_execute(a:winid, "norm! \") - exec g:Lf_py "historyExplManager._cli._buildPopupPrompt()" - exec g:Lf_py "historyExplManager._getInstance().refreshPopupStatusline()" - elseif key ==# "g" - if get(g:, "Lf_History_is_g_pressed", 0) == 0 - let g:Lf_History_is_g_pressed = 1 - else - let g:Lf_History_is_g_pressed = 0 - call win_execute(a:winid, "norm! gg") - exec g:Lf_py "historyExplManager._cli._buildPopupPrompt()" - redraw - endif - elseif key ==# "G" - call win_execute(a:winid, "norm! G") - exec g:Lf_py "historyExplManager._cli._buildPopupPrompt()" - redraw - elseif key ==? "" - call win_execute(a:winid, "norm! \") - exec g:Lf_py "historyExplManager._cli._buildPopupPrompt()" - redraw - elseif key ==? "" - call win_execute(a:winid, "norm! \") - exec g:Lf_py "historyExplManager._cli._buildPopupPrompt()" - redraw - elseif key ==? "" - if exists("*getmousepos") - let pos = getmousepos() - call win_execute(pos.winid, "call cursor([pos.line, pos.column])") - exec g:Lf_py "historyExplManager._cli._buildPopupPrompt()" - redraw - elseif has('patch-8.1.2266') - call win_execute(a:winid, "exec v:mouse_lnum") - call win_execute(a:winid, "exec 'norm!'.v:mouse_col.'|'") - exec g:Lf_py "historyExplManager._cli._buildPopupPrompt()" - redraw - endif - elseif key ==? "" - call win_execute(a:winid, "norm! 3k") - exec g:Lf_py "historyExplManager._cli._buildPopupPrompt()" - redraw - exec g:Lf_py "historyExplManager._getInstance().refreshPopupStatusline()" - elseif key ==? "" - call win_execute(a:winid, "norm! 3j") - exec g:Lf_py "historyExplManager._cli._buildPopupPrompt()" - redraw - exec g:Lf_py "historyExplManager._getInstance().refreshPopupStatusline()" - elseif key ==# "q" || key ==? "" - exec g:Lf_py "historyExplManager.quit()" - elseif key ==# "i" || key ==? "" - call leaderf#ResetPopupOptions(a:winid, 'filter', 'leaderf#PopupFilter') - exec g:Lf_py "historyExplManager.input()" - elseif key ==# "o" || key ==? "" || key ==? "<2-LeftMouse>" - exec g:Lf_py "historyExplManager.accept()" - elseif key ==? "" - exec g:Lf_py "historyExplManager.toggleHelp()" - elseif key ==? "e" + if key ==# "x" + elseif key ==# "v" + elseif key ==# "t" + elseif key ==# "p" + elseif key ==? "" + elseif key ==? "" + elseif key ==# "e" exec g:Lf_py "historyExplManager.editHistory()" + else + return leaderf#NormalModeFilter(g:Lf_PyEval("id(historyExplManager)"), a:winid, a:key) endif return 1 diff --git a/autoload/leaderf/Line.vim b/autoload/leaderf/Line.vim index 8497591f..4a0bd601 100644 --- a/autoload/leaderf/Line.vim +++ b/autoload/leaderf/Line.vim @@ -48,104 +48,15 @@ function! leaderf#Line#Maps() endfunction function! leaderf#Line#NormalModeFilter(winid, key) abort - let key = get(g:Lf_KeyDict, get(g:Lf_KeyMap, a:key, a:key), a:key) - - if key !=# "g" - call win_execute(a:winid, "let g:Lf_Line_is_g_pressed = 0") - endif - - if key ==# "j" || key ==? "" - call win_execute(a:winid, "norm! j") - exec g:Lf_py "lineExplManager._cli._buildPopupPrompt()" - "redraw - exec g:Lf_py "lineExplManager._getInstance().refreshPopupStatusline()" - exec g:Lf_py "lineExplManager._previewResult(False)" - elseif key ==# "k" || key ==? "" - call win_execute(a:winid, "norm! k") - exec g:Lf_py "lineExplManager._cli._buildPopupPrompt()" - "redraw - exec g:Lf_py "lineExplManager._getInstance().refreshPopupStatusline()" - exec g:Lf_py "lineExplManager._previewResult(False)" - elseif key ==? "" || key ==? "" - call win_execute(a:winid, "norm! \") - exec g:Lf_py "lineExplManager._cli._buildPopupPrompt()" - exec g:Lf_py "lineExplManager._getInstance().refreshPopupStatusline()" - exec g:Lf_py "lineExplManager._previewResult(False)" - elseif key ==? "" || key ==? "" - call win_execute(a:winid, "norm! \") - exec g:Lf_py "lineExplManager._cli._buildPopupPrompt()" - exec g:Lf_py "lineExplManager._getInstance().refreshPopupStatusline()" - exec g:Lf_py "lineExplManager._previewResult(False)" - elseif key ==# "g" - if get(g:, "Lf_Line_is_g_pressed", 0) == 0 - let g:Lf_Line_is_g_pressed = 1 - else - let g:Lf_Line_is_g_pressed = 0 - call win_execute(a:winid, "norm! gg") - exec g:Lf_py "lineExplManager._cli._buildPopupPrompt()" - redraw - endif - elseif key ==# "G" - call win_execute(a:winid, "norm! G") - exec g:Lf_py "lineExplManager._cli._buildPopupPrompt()" - redraw - elseif key ==? "" - call win_execute(a:winid, "norm! \") - exec g:Lf_py "lineExplManager._cli._buildPopupPrompt()" - redraw - elseif key ==? "" - call win_execute(a:winid, "norm! \") - exec g:Lf_py "lineExplManager._cli._buildPopupPrompt()" - redraw - elseif key ==? "" - if exists("*getmousepos") - let pos = getmousepos() - call win_execute(pos.winid, "call cursor([pos.line, pos.column])") - exec g:Lf_py "lineExplManager._cli._buildPopupPrompt()" - redraw - exec g:Lf_py "lineExplManager._previewResult(False)" - elseif has('patch-8.1.2266') - call win_execute(a:winid, "exec v:mouse_lnum") - call win_execute(a:winid, "exec 'norm!'.v:mouse_col.'|'") - exec g:Lf_py "lineExplManager._cli._buildPopupPrompt()" - redraw - exec g:Lf_py "lineExplManager._previewResult(False)" - endif - elseif key ==? "" - call win_execute(a:winid, "norm! 3k") - exec g:Lf_py "lineExplManager._cli._buildPopupPrompt()" - redraw - exec g:Lf_py "lineExplManager._getInstance().refreshPopupStatusline()" - elseif key ==? "" - call win_execute(a:winid, "norm! 3j") - exec g:Lf_py "lineExplManager._cli._buildPopupPrompt()" - redraw - exec g:Lf_py "lineExplManager._getInstance().refreshPopupStatusline()" - elseif key ==# "q" || key ==? "" - exec g:Lf_py "lineExplManager.quit()" - elseif key ==# "i" || key ==? "" - call leaderf#ResetPopupOptions(a:winid, 'filter', 'leaderf#PopupFilter') - exec g:Lf_py "lineExplManager.input()" - elseif key ==# "o" || key ==? "" || key ==? "<2-LeftMouse>" - exec g:Lf_py "lineExplManager.accept()" - elseif key ==# "x" - exec g:Lf_py "lineExplManager.accept('h')" - elseif key ==# "v" - exec g:Lf_py "lineExplManager.accept('v')" - elseif key ==# "t" - exec g:Lf_py "lineExplManager.accept('t')" - elseif key ==# "p" - exec g:Lf_py "lineExplManager._previewResult(True)" - elseif key ==? "" - exec g:Lf_py "lineExplManager.toggleHelp()" - elseif key ==? "" - exec g:Lf_py "lineExplManager._toUpInPopup()" - elseif key ==? "" - exec g:Lf_py "lineExplManager._toDownInPopup()" + let key = get(g:Lf_KeyMap, a:key, a:key) + if key ==? "" + exec g:Lf_py "lineExplManager.refresh()" elseif key ==# "Q" exec g:Lf_py "lineExplManager.outputToQflist()" elseif key ==# "L" exec g:Lf_py "lineExplManager.outputToLoclist()" + else + return leaderf#NormalModeFilter(g:Lf_PyEval("id(lineExplManager)"), a:winid, a:key) endif return 1 diff --git a/autoload/leaderf/Mru.vim b/autoload/leaderf/Mru.vim index 82356f96..551d7994 100644 --- a/autoload/leaderf/Mru.vim +++ b/autoload/leaderf/Mru.vim @@ -50,93 +50,8 @@ function! leaderf#Mru#Maps() endfunction function! leaderf#Mru#NormalModeFilter(winid, key) abort - let key = get(g:Lf_KeyDict, get(g:Lf_KeyMap, a:key, a:key), a:key) - - if key !=# "g" - call win_execute(a:winid, "let g:Lf_Mru_is_g_pressed = 0") - endif - - if key ==# "j" || key ==? "" - call win_execute(a:winid, "norm! j") - exec g:Lf_py "mruExplManager._cli._buildPopupPrompt()" - "redraw - exec g:Lf_py "mruExplManager._getInstance().refreshPopupStatusline()" - exec g:Lf_py "mruExplManager._previewResult(False)" - elseif key ==# "k" || key ==? "" - call win_execute(a:winid, "norm! k") - exec g:Lf_py "mruExplManager._cli._buildPopupPrompt()" - "redraw - exec g:Lf_py "mruExplManager._getInstance().refreshPopupStatusline()" - exec g:Lf_py "mruExplManager._previewResult(False)" - elseif key ==? "" || key ==? "" - call win_execute(a:winid, "norm! \") - exec g:Lf_py "mruExplManager._cli._buildPopupPrompt()" - exec g:Lf_py "mruExplManager._getInstance().refreshPopupStatusline()" - exec g:Lf_py "mruExplManager._previewResult(False)" - elseif key ==? "" || key ==? "" - call win_execute(a:winid, "norm! \") - exec g:Lf_py "mruExplManager._cli._buildPopupPrompt()" - exec g:Lf_py "mruExplManager._getInstance().refreshPopupStatusline()" - exec g:Lf_py "mruExplManager._previewResult(False)" - elseif key ==# "g" - if get(g:, "Lf_Mru_is_g_pressed", 0) == 0 - let g:Lf_Mru_is_g_pressed = 1 - else - let g:Lf_Mru_is_g_pressed = 0 - call win_execute(a:winid, "norm! gg") - exec g:Lf_py "mruExplManager._cli._buildPopupPrompt()" - redraw - endif - elseif key ==# "G" - call win_execute(a:winid, "norm! G") - exec g:Lf_py "mruExplManager._cli._buildPopupPrompt()" - redraw - elseif key ==? "" - call win_execute(a:winid, "norm! \") - exec g:Lf_py "mruExplManager._cli._buildPopupPrompt()" - redraw - elseif key ==? "" - call win_execute(a:winid, "norm! \") - exec g:Lf_py "mruExplManager._cli._buildPopupPrompt()" - redraw - elseif key ==? "" - if exists("*getmousepos") - let pos = getmousepos() - call win_execute(pos.winid, "call cursor([pos.line, pos.column])") - exec g:Lf_py "mruExplManager._cli._buildPopupPrompt()" - redraw - exec g:Lf_py "mruExplManager._previewResult(False)" - elseif has('patch-8.1.2266') - call win_execute(a:winid, "exec v:mouse_lnum") - call win_execute(a:winid, "exec 'norm!'.v:mouse_col.'|'") - exec g:Lf_py "mruExplManager._cli._buildPopupPrompt()" - redraw - exec g:Lf_py "mruExplManager._previewResult(False)" - endif - elseif key ==? "" - call win_execute(a:winid, "norm! 3k") - exec g:Lf_py "mruExplManager._cli._buildPopupPrompt()" - redraw - exec g:Lf_py "mruExplManager._getInstance().refreshPopupStatusline()" - elseif key ==? "" - call win_execute(a:winid, "norm! 3j") - exec g:Lf_py "mruExplManager._cli._buildPopupPrompt()" - redraw - exec g:Lf_py "mruExplManager._getInstance().refreshPopupStatusline()" - elseif key ==# "q" || key ==? "" - exec g:Lf_py "mruExplManager.quit()" - elseif key ==# "i" || key ==? "" - call leaderf#ResetPopupOptions(a:winid, 'filter', 'leaderf#PopupFilter') - exec g:Lf_py "mruExplManager.input()" - elseif key ==# "o" || key ==? "" || key ==? "<2-LeftMouse>" - exec g:Lf_py "mruExplManager.accept()" - elseif key ==# "x" - exec g:Lf_py "mruExplManager.accept('h')" - elseif key ==# "v" - exec g:Lf_py "mruExplManager.accept('v')" - elseif key ==# "t" - exec g:Lf_py "mruExplManager.accept('t')" - elseif key ==# "d" + let key = get(g:Lf_KeyMap, a:key, a:key) + if key ==# "d" exec g:Lf_py "mruExplManager.deleteMru()" elseif key ==# "s" exec g:Lf_py "mruExplManager.addSelections()" @@ -144,14 +59,8 @@ function! leaderf#Mru#NormalModeFilter(winid, key) abort exec g:Lf_py "mruExplManager.selectAll()" elseif key ==# "c" exec g:Lf_py "mruExplManager.clearSelections()" - elseif key ==# "p" - exec g:Lf_py "mruExplManager._previewResult(True)" - elseif key ==? "" - exec g:Lf_py "mruExplManager.toggleHelp()" - elseif key ==? "" - exec g:Lf_py "mruExplManager._toUpInPopup()" - elseif key ==? "" - exec g:Lf_py "mruExplManager._toDownInPopup()" + else + return leaderf#NormalModeFilter(g:Lf_PyEval("id(mruExplManager)"), a:winid, a:key) endif return 1 diff --git a/autoload/leaderf/QfLocList.vim b/autoload/leaderf/QfLocList.vim index 5b3916d5..b956dd86 100644 --- a/autoload/leaderf/QfLocList.vim +++ b/autoload/leaderf/QfLocList.vim @@ -40,95 +40,5 @@ endfunction function! leaderf#QfLocList#NormalModeFilter(winid, key) abort - let key = get(g:Lf_KeyDict, get(g:Lf_KeyMap, a:key, a:key), a:key) - - if key !=# "g" - call win_execute(a:winid, "let g:Lf_QfLocList_is_g_pressed = 0") - endif - - if key ==# "j" || key ==? "" - call win_execute(a:winid, "norm! j") - exec g:Lf_py "qfloclistExplManager._cli._buildPopupPrompt()" - "redraw - exec g:Lf_py "qfloclistExplManager._getInstance().refreshPopupStatusline()" - elseif key ==# "k" || key ==? "" - call win_execute(a:winid, "norm! k") - exec g:Lf_py "qfloclistExplManager._cli._buildPopupPrompt()" - "redraw - exec g:Lf_py "qfloclistExplManager._getInstance().refreshPopupStatusline()" - elseif key ==? "" || key ==? "" - call win_execute(a:winid, "norm! \") - exec g:Lf_py "qfloclistExplManager._cli._buildPopupPrompt()" - exec g:Lf_py "qfloclistExplManager._getInstance().refreshPopupStatusline()" - elseif key ==? "" || key ==? "" - call win_execute(a:winid, "norm! \") - exec g:Lf_py "qfloclistExplManager._cli._buildPopupPrompt()" - exec g:Lf_py "qfloclistExplManager._getInstance().refreshPopupStatusline()" - elseif key ==# "g" - if get(g:, "Lf_QfLocList_is_g_pressed", 0) == 0 - let g:Lf_QfLocList_is_g_pressed = 1 - else - let g:Lf_QfLocList_is_g_pressed = 0 - call win_execute(a:winid, "norm! gg") - exec g:Lf_py "qfloclistExplManager._cli._buildPopupPrompt()" - redraw - endif - elseif key ==# "G" - call win_execute(a:winid, "norm! G") - exec g:Lf_py "qfloclistExplManager._cli._buildPopupPrompt()" - redraw - elseif key ==? "" - call win_execute(a:winid, "norm! \") - exec g:Lf_py "qfloclistExplManager._cli._buildPopupPrompt()" - redraw - elseif key ==? "" - call win_execute(a:winid, "norm! \") - exec g:Lf_py "qfloclistExplManager._cli._buildPopupPrompt()" - redraw - elseif key ==? "" - if exists("*getmousepos") - let pos = getmousepos() - call win_execute(pos.winid, "call cursor([pos.line, pos.column])") - exec g:Lf_py "qfloclistExplManager._cli._buildPopupPrompt()" - redraw - elseif has('patch-8.1.2266') - call win_execute(a:winid, "exec v:mouse_lnum") - call win_execute(a:winid, "exec 'norm!'.v:mouse_col.'|'") - exec g:Lf_py "qfloclistExplManager._cli._buildPopupPrompt()" - redraw - endif - elseif key ==? "" - call win_execute(a:winid, "norm! 3k") - exec g:Lf_py "qfloclistExplManager._cli._buildPopupPrompt()" - redraw - exec g:Lf_py "qfloclistExplManager._getInstance().refreshPopupStatusline()" - elseif key ==? "" - call win_execute(a:winid, "norm! 3j") - exec g:Lf_py "qfloclistExplManager._cli._buildPopupPrompt()" - redraw - exec g:Lf_py "qfloclistExplManager._getInstance().refreshPopupStatusline()" - elseif key ==# "q" || key ==? "" - exec g:Lf_py "qfloclistExplManager.quit()" - elseif key ==# "i" || key ==? "" - call leaderf#ResetPopupOptions(a:winid, 'filter', 'leaderf#PopupFilter') - exec g:Lf_py "qfloclistExplManager.input()" - elseif key ==# "o" || key ==? "" || key ==? "<2-LeftMouse>" - exec g:Lf_py "qfloclistExplManager.accept()" - elseif key ==# "x" - exec g:Lf_py "qfloclistExplManager.accept('h')" - elseif key ==# "v" - exec g:Lf_py "qfloclistExplManager.accept('v')" - elseif key ==# "t" - exec g:Lf_py "qfloclistExplManager.accept('t')" - elseif key ==# "p" - exec g:Lf_py "qfloclistExplManager._previewResult(True)" - elseif key ==? "" - exec g:Lf_py "qfloclistExplManager.toggleHelp()" - elseif key ==? "" - exec g:Lf_py "qfloclistExplManager._toUpInPopup()" - elseif key ==? "" - exec g:Lf_py "qfloclistExplManager._toDownInPopup()" - endif - - return 1 + return leaderf#NormalModeFilter(g:Lf_PyEval("id(qfloclistExplManager)"), a:winid, a:key) endfunction diff --git a/autoload/leaderf/Rg.vim b/autoload/leaderf/Rg.vim index 36d48350..b98ee408 100644 --- a/autoload/leaderf/Rg.vim +++ b/autoload/leaderf/Rg.vim @@ -182,82 +182,8 @@ endfunction function! leaderf#Rg#NormalModeFilter(winid, key) abort - let key = get(g:Lf_KeyDict, get(g:Lf_KeyMap, a:key, a:key), a:key) - - if key !=# "g" - call win_execute(a:winid, "let g:Lf_Rg_is_g_pressed = 0") - endif - - if key ==# "j" || key ==? "" - call win_execute(a:winid, "norm! j") - exec g:Lf_py "rgExplManager._cli._buildPopupPrompt()" - "redraw - exec g:Lf_py "rgExplManager._getInstance().refreshPopupStatusline()" - exec g:Lf_py "rgExplManager._previewResult(False)" - elseif key ==# "k" || key ==? "" - call win_execute(a:winid, "norm! k") - exec g:Lf_py "rgExplManager._cli._buildPopupPrompt()" - "redraw - exec g:Lf_py "rgExplManager._getInstance().refreshPopupStatusline()" - exec g:Lf_py "rgExplManager._previewResult(False)" - elseif key ==? "" || key ==? "" - call win_execute(a:winid, "norm! \") - exec g:Lf_py "rgExplManager._cli._buildPopupPrompt()" - exec g:Lf_py "rgExplManager._getInstance().refreshPopupStatusline()" - exec g:Lf_py "rgExplManager._previewResult(False)" - elseif key ==? "" || key ==? "" - call win_execute(a:winid, "norm! \") - exec g:Lf_py "rgExplManager._cli._buildPopupPrompt()" - exec g:Lf_py "rgExplManager._getInstance().refreshPopupStatusline()" - exec g:Lf_py "rgExplManager._previewResult(False)" - elseif key ==# "g" - if get(g:, "Lf_Rg_is_g_pressed", 0) == 0 - let g:Lf_Rg_is_g_pressed = 1 - else - let g:Lf_Rg_is_g_pressed = 0 - call win_execute(a:winid, "norm! gg") - exec g:Lf_py "rgExplManager._cli._buildPopupPrompt()" - redraw - endif - elseif key ==# "G" - call win_execute(a:winid, "norm! G") - exec g:Lf_py "rgExplManager._cli._buildPopupPrompt()" - redraw - elseif key ==? "" - call win_execute(a:winid, "norm! \") - exec g:Lf_py "rgExplManager._cli._buildPopupPrompt()" - redraw - elseif key ==? "" - call win_execute(a:winid, "norm! \") - exec g:Lf_py "rgExplManager._cli._buildPopupPrompt()" - redraw - elseif key ==? "" - if exists("*getmousepos") - let pos = getmousepos() - call win_execute(pos.winid, "call cursor([pos.line, pos.column])") - exec g:Lf_py "rgExplManager._cli._buildPopupPrompt()" - redraw - exec g:Lf_py "rgExplManager._previewResult(False)" - elseif has('patch-8.1.2266') - call win_execute(a:winid, "exec v:mouse_lnum") - call win_execute(a:winid, "exec 'norm!'.v:mouse_col.'|'") - exec g:Lf_py "rgExplManager._cli._buildPopupPrompt()" - redraw - exec g:Lf_py "rgExplManager._previewResult(False)" - endif - elseif key ==? "" - call win_execute(a:winid, "norm! 3k") - exec g:Lf_py "rgExplManager._cli._buildPopupPrompt()" - redraw - exec g:Lf_py "rgExplManager._getInstance().refreshPopupStatusline()" - elseif key ==? "" - call win_execute(a:winid, "norm! 3j") - exec g:Lf_py "rgExplManager._cli._buildPopupPrompt()" - redraw - exec g:Lf_py "rgExplManager._getInstance().refreshPopupStatusline()" - elseif key ==# "q" || key ==? "" - exec g:Lf_py "rgExplManager.quit()" - elseif key ==# "i" || key ==? "" + let key = get(g:Lf_KeyMap, a:key, a:key) + if key ==# "i" || key ==? "" if g:Lf_py == "py " let has_heading = pyeval("'--heading' in rgExplManager._arguments") else @@ -267,28 +193,14 @@ function! leaderf#Rg#NormalModeFilter(winid, key) abort call leaderf#ResetPopupOptions(a:winid, 'filter', 'leaderf#PopupFilter') exec g:Lf_py "rgExplManager.input()" endif - elseif key ==# "o" || key ==? "" || key ==? "<2-LeftMouse>" - exec g:Lf_py "rgExplManager.accept()" - elseif key ==# "x" - exec g:Lf_py "rgExplManager.accept('h')" - elseif key ==# "v" - exec g:Lf_py "rgExplManager.accept('v')" - elseif key ==# "t" - exec g:Lf_py "rgExplManager.accept('t')" - elseif key ==# "p" - exec g:Lf_py "rgExplManager._previewResult(True)" - elseif key ==? "" - exec g:Lf_py "rgExplManager.toggleHelp()" elseif key ==# "d" exec g:Lf_py "rgExplManager.deleteCurrentLine()" elseif key ==# "Q" exec g:Lf_py "rgExplManager.outputToQflist()" elseif key ==# "L" exec g:Lf_py "rgExplManager.outputToLoclist()" - elseif key ==? "" - exec g:Lf_py "rgExplManager._toUpInPopup()" - elseif key ==? "" - exec g:Lf_py "rgExplManager._toDownInPopup()" + else + return leaderf#NormalModeFilter(g:Lf_PyEval("id(rgExplManager)"), a:winid, a:key) endif return 1 diff --git a/autoload/leaderf/Window.vim b/autoload/leaderf/Window.vim index b6fab9fb..13bbae7e 100644 --- a/autoload/leaderf/Window.vim +++ b/autoload/leaderf/Window.vim @@ -32,90 +32,18 @@ function! leaderf#Window#Maps() endfunction function! leaderf#Window#NormalModeFilter(winid, key) abort - let key = get(g:Lf_KeyDict, get(g:Lf_KeyMap, a:key, a:key), a:key) - - if key !=# "g" - call win_execute(a:winid, "let g:Lf_Window_is_g_pressed = 0") - endif - - if key ==# "j" || key ==? "" - call win_execute(a:winid, "norm! j") - exec g:Lf_py "windowExplManager._cli._buildPopupPrompt()" - "redraw - exec g:Lf_py "windowExplManager._getInstance().refreshPopupStatusline()" - exec g:Lf_py "windowExplManager._previewResult(False)" - elseif key ==# "k" || key ==? "" - call win_execute(a:winid, "norm! k") - exec g:Lf_py "windowExplManager._cli._buildPopupPrompt()" - "redraw - exec g:Lf_py "windowExplManager._getInstance().refreshPopupStatusline()" - exec g:Lf_py "windowExplManager._previewResult(False)" - elseif key ==? "" || key ==? "" - call win_execute(a:winid, "norm! \") - exec g:Lf_py "windowExplManager._cli._buildPopupPrompt()" - exec g:Lf_py "windowExplManager._getInstance().refreshPopupStatusline()" - exec g:Lf_py "windowExplManager._previewResult(False)" - elseif key ==? "" || key ==? "" - call win_execute(a:winid, "norm! \") - exec g:Lf_py "windowExplManager._cli._buildPopupPrompt()" - exec g:Lf_py "windowExplManager._getInstance().refreshPopupStatusline()" - exec g:Lf_py "windowExplManager._previewResult(False)" - elseif key ==# "g" - if get(g:, "Lf_Window_is_g_pressed", 0) == 0 - let g:Lf_Window_is_g_pressed = 1 - else - let g:Lf_Window_is_g_pressed = 0 - call win_execute(a:winid, "norm! gg") - exec g:Lf_py "windowExplManager._cli._buildPopupPrompt()" - redraw - endif - elseif key ==# "G" - call win_execute(a:winid, "norm! G") - exec g:Lf_py "windowExplManager._cli._buildPopupPrompt()" - redraw - elseif key ==? "" - call win_execute(a:winid, "norm! \") - exec g:Lf_py "windowExplManager._cli._buildPopupPrompt()" - redraw - elseif key ==? "" - call win_execute(a:winid, "norm! \") - exec g:Lf_py "windowExplManager._cli._buildPopupPrompt()" - redraw - elseif key ==? "" - if exists("*getmousepos") - let pos = getmousepos() - call win_execute(pos.winid, "call cursor([pos.line, pos.column])") - exec g:Lf_py "windowExplManager._cli._buildPopupPrompt()" - redraw - exec g:Lf_py "windowExplManager._previewResult(False)" - elseif has('patch-8.1.2266') - call win_execute(a:winid, "exec v:mouse_lnum") - call win_execute(a:winid, "exec 'norm!'.v:mouse_col.'|'") - exec g:Lf_py "windowExplManager._cli._buildPopupPrompt()" - redraw - exec g:Lf_py "windowExplManager._previewResult(False)" - endif - elseif key ==? "" - call win_execute(a:winid, "norm! 3k") - exec g:Lf_py "windowExplManager._cli._buildPopupPrompt()" - redraw - exec g:Lf_py "windowExplManager._getInstance().refreshPopupStatusline()" - elseif key ==? "" - call win_execute(a:winid, "norm! 3j") - exec g:Lf_py "windowExplManager._cli._buildPopupPrompt()" - redraw - exec g:Lf_py "windowExplManager._getInstance().refreshPopupStatusline()" - elseif key ==# "q" || key ==? "" - exec g:Lf_py "windowExplManager.quit()" - elseif key ==# "i" || key ==? "" - call leaderf#ResetPopupOptions(a:winid, 'filter', 'leaderf#PopupFilter') - exec g:Lf_py "windowExplManager.input()" - elseif key ==# "o" || key ==? "" || key ==? "<2-LeftMouse>" - exec g:Lf_py "windowExplManager.accept()" - elseif key ==? "" - exec g:Lf_py "windowExplManager.toggleHelp()" - elseif key ==? "d" + let key = get(g:Lf_KeyMap, a:key, a:key) + + if key ==# "x" + elseif key ==# "v" + elseif key ==# "t" + elseif key ==# "p" + elseif key ==? "" + elseif key ==? "" + elseif key ==# "d" exec g:Lf_py "windowExplManager.deleteWindow()" + else + return leaderf#NormalModeFilter(g:Lf_PyEval("id(windowExplManager)"), a:winid, a:key) endif return 1 diff --git a/autoload/leaderf/python/leaderf/anyExpl.py b/autoload/leaderf/python/leaderf/anyExpl.py index 0acd2317..854cc925 100644 --- a/autoload/leaderf/python/leaderf/anyExpl.py +++ b/autoload/leaderf/python/leaderf/anyExpl.py @@ -380,7 +380,7 @@ def _previewInPopup(self, *args, **kwargs): filename, line_num, jump_cmd = result # for backward compatibility if isinstance(filename, int): # it is a buffer number - lfCmd("call bufload(%d)" % filename) + lfCmd("silent call bufload(%d)" % filename) elif lfEval("bufloaded('%s')" % escQuote(filename)) == '1': if not self._has_nvim: # py3 in nvim return str, in vim return bytes filename = lfBytes2Str(filename) diff --git a/autoload/leaderf/python/leaderf/bufExpl.py b/autoload/leaderf/python/leaderf/bufExpl.py index 0cae21c5..7ac3e071 100644 --- a/autoload/leaderf/python/leaderf/bufExpl.py +++ b/autoload/leaderf/python/leaderf/bufExpl.py @@ -293,6 +293,9 @@ def _previewInPopup(self, *args, **kwargs): if line == '': return buf_number = int(re.sub(r"^.*?(\d+).*$", r"\1", line)) + if lfEval("bufloaded(%d)" % buf_number) == '0': + lfCmd("silent call bufload(%d)" % buf_number) + self._createPopupPreview(vim.buffers[buf_number].name, buf_number, 0) diff --git a/autoload/leaderf/python/leaderf/bufTagExpl.py b/autoload/leaderf/python/leaderf/bufTagExpl.py index b310b1d3..e6a1e5b6 100644 --- a/autoload/leaderf/python/leaderf/bufTagExpl.py +++ b/autoload/leaderf/python/leaderf/bufTagExpl.py @@ -211,7 +211,6 @@ class BufTagExplManager(Manager): def __init__(self): super(BufTagExplManager, self).__init__() self._supports_preview = int(lfEval("g:Lf_PreviewCode")) - self._orig_line = '' def _getExplClass(self): return BufTagExplorer @@ -470,39 +469,6 @@ def _toDown(self): def removeCache(self, buf_number): self._getExplorer().removeCache(buf_number) - def _previewResult(self, preview): - if self._getInstance().getWinPos() == 'floatwin': - self._cli.buildPopupPrompt() - - if lfEval("get(g:, 'Lf_PreviewInPopup', 0)") == '1': - if self._orig_line != self._getInstance().currentLine: - self._closePreviewPopup() - else: - return - - if not self._needPreview(preview): - return - - line = self._getInstance().currentLine - line_nr = self._getInstance().window.cursor[0] - - if lfEval("get(g:, 'Lf_PreviewInPopup', 0)") == '1': - self._previewInPopup(line, self._getInstance().buffer, line_nr) - lfCmd("redraw") - return - - orig_pos = self._getInstance().getOriginalPos() - cur_pos = (vim.current.tabpage, vim.current.window, vim.current.buffer) - - saved_eventignore = vim.options['eventignore'] - vim.options['eventignore'] = 'BufLeave,WinEnter,BufEnter' - try: - vim.current.tabpage, vim.current.window, vim.current.buffer = orig_pos - self._acceptSelection(line, self._getInstance().buffer, line_nr, preview=True) - finally: - vim.current.tabpage, vim.current.window, vim.current.buffer = cur_pos - vim.options['eventignore'] = saved_eventignore - def _bangEnter(self): super(BufTagExplManager, self)._bangEnter() if "--all" in self._arguments and not self._is_content_list: diff --git a/autoload/leaderf/python/leaderf/cli.py b/autoload/leaderf/python/leaderf/cli.py index 27cad675..99d0b16b 100644 --- a/autoload/leaderf/python/leaderf/cli.py +++ b/autoload/leaderf/python/leaderf/cli.py @@ -18,11 +18,21 @@ def deco(*args, **kwargs): if lfEval("exists('g:lf_gcr_stack')") == '0': lfCmd("let g:lf_gcr_stack = []") lfCmd("call add(g:lf_gcr_stack, &gcr)") - lfCmd("set gcr=a:invisible") - if lfEval("exists('g:lf_t_ve_stack')") == '0': - lfCmd("let g:lf_t_ve_stack = []") - lfCmd("call add(g:lf_t_ve_stack, &t_ve)") - lfCmd("set t_ve=") + if lfEval("has('nvim')") == '1': + if lfEval("exists('g:lf_termgcr_stack')") == '0': + lfCmd("let g:lf_termgcr_stack = []") + lfCmd("call add(g:lf_termgcr_stack, &termguicolors)") + lfCmd("set termguicolors") + lfCmd("hi Cursor blend=100") + lfCmd("set guicursor+=a:Cursor/lCursor") + else: + lfCmd("set gcr=a:invisible") + + if lfEval("exists('g:lf_t_ve_stack')") == '0': + lfCmd("let g:lf_t_ve_stack = []") + lfCmd("call add(g:lf_t_ve_stack, &t_ve)") + lfCmd("set t_ve=") + lfCmd("let g:Lf_ttimeoutlen_orig = &ttimeoutlen") lfCmd("set ttimeoutlen=0") try: @@ -32,8 +42,13 @@ def deco(*args, **kwargs): lfCmd("let &ttimeoutlen = g:Lf_ttimeoutlen_orig") lfCmd("set gcr&") lfCmd("let &gcr = remove(g:lf_gcr_stack, -1)") - lfCmd("set t_ve&") - lfCmd("let &t_ve = remove(g:lf_t_ve_stack, -1)") + if lfEval("has('nvim')") == '1': + lfCmd("hi Cursor blend=0") + lfCmd("set termguicolors&") + lfCmd("let &termguicolors = remove(g:lf_termgcr_stack, -1)") + else: + lfCmd("set t_ve&") + lfCmd("let &t_ve = remove(g:lf_t_ve_stack, -1)") return deco @@ -168,28 +183,6 @@ def setPattern(self, pattern): self._cursor_pos = len(self._cmdline) self._buildPattern() - # https://github.com/neovim/neovim/issues/6538 - def _buildNvimPrompt(self): - lfCmd("redraw") - if self._is_fuzzy: - if self._is_full_path: - lfCmd("echohl Constant | echon '>F> {}' | echohl NONE".format(self._additional_prompt_string)) - else: - lfCmd("echohl Constant | echon '>>> {}' | echohl NONE".format(self._additional_prompt_string)) - else: - lfCmd("echohl Constant | echon 'R>> {}' | echohl NONE".format(self._additional_prompt_string)) - - lfCmd("echohl Normal | echon '%s' | echohl NONE" % - escQuote(''.join(self._cmdline[:self._cursor_pos]))) - if self._cursor_pos < len(self._cmdline): - lfCmd("hi! default link Lf_hl_cursor Cursor") - lfCmd("echohl Lf_hl_cursor | echon '%s' | echohl NONE" % - escQuote(''.join(self._cmdline[self._cursor_pos]))) - lfCmd("echohl Normal | echon '%s' | echohl NONE" % - escQuote(''.join(self._cmdline[self._cursor_pos+1:]))) - else: - lfCmd("hi! default link Lf_hl_cursor NONE") - def _buildPopupPrompt(self): self._instance.mimicCursor() @@ -328,10 +321,6 @@ def buildPopupPrompt(self): lfCmd("silent! redraw") def _buildPrompt(self): - if lfEval("has('nvim')") == '1' and self._instance.getWinPos() != 'floatwin': - self._buildNvimPrompt() - return - if self._idle and datetime.now() - self._start_time < timedelta(milliseconds=500): # 500ms return else: @@ -821,13 +810,9 @@ def input(self, callback): elif equal(cmd, ''): self._toRight() elif equal(cmd, ''): - yield '' - yield '' - yield '' + yield '' elif equal(cmd, ''): - yield '' - yield '' - yield '' + yield '' elif equal(cmd, ''): yield '' else: diff --git a/autoload/leaderf/python/leaderf/colorschemeExpl.py b/autoload/leaderf/python/leaderf/colorschemeExpl.py index 171418f2..0cd45086 100644 --- a/autoload/leaderf/python/leaderf/colorschemeExpl.py +++ b/autoload/leaderf/python/leaderf/colorschemeExpl.py @@ -71,7 +71,6 @@ def getStlCurDir(self): class ColorschemeExplManager(Manager): def __init__(self): super(ColorschemeExplManager, self).__init__() - self._orig_line = '' def _getExplClass(self): return ColorschemeExplorer diff --git a/autoload/leaderf/python/leaderf/functionExpl.py b/autoload/leaderf/python/leaderf/functionExpl.py index 55ba9feb..36096894 100644 --- a/autoload/leaderf/python/leaderf/functionExpl.py +++ b/autoload/leaderf/python/leaderf/functionExpl.py @@ -207,7 +207,6 @@ def cleanup(self): class FunctionExplManager(Manager): def __init__(self): super(FunctionExplManager, self).__init__() - self._orig_line = '' def _getExplClass(self): return FunctionExplorer @@ -343,37 +342,6 @@ def _supportsRefine(self): def removeCache(self, buf_number): self._getExplorer().removeCache(buf_number) - def _previewResult(self, preview): - if self._getInstance().getWinPos() == 'floatwin': - self._cli.buildPopupPrompt() - - if lfEval("get(g:, 'Lf_PreviewInPopup', 0)") == '1': - if self._orig_line != self._getInstance().currentLine: - self._closePreviewPopup() - else: - return - - if not self._needPreview(preview): - return - - line = self._getInstance().currentLine - if lfEval("get(g:, 'Lf_PreviewInPopup', 0)") == '1': - self._previewInPopup(line) - lfCmd("redraw") - return - - orig_pos = self._getInstance().getOriginalPos() - cur_pos = (vim.current.tabpage, vim.current.window, vim.current.buffer) - - saved_eventignore = vim.options['eventignore'] - vim.options['eventignore'] = 'BufLeave,WinEnter,BufEnter' - try: - vim.current.tabpage, vim.current.window, vim.current.buffer = orig_pos - self._acceptSelection(line, preview=True) - finally: - vim.current.tabpage, vim.current.window, vim.current.buffer = cur_pos - vim.options['eventignore'] = saved_eventignore - def _bangEnter(self): super(FunctionExplManager, self)._bangEnter() if "--all" in self._arguments and not self._is_content_list: diff --git a/autoload/leaderf/python/leaderf/instance.py b/autoload/leaderf/python/leaderf/instance.py index 1144c6fd..744fbce0 100644 --- a/autoload/leaderf/python/leaderf/instance.py +++ b/autoload/leaderf/python/leaderf/instance.py @@ -259,6 +259,7 @@ def __init__(self, manager, category, cli, self._win_pos = None self._stl_buf_namespace = None self._auto_resize = lfEval("get(g:, 'Lf_AutoResize', 0)") == '1' + self._window_id = 0 def _initStlVar(self): if int(lfEval("!exists('g:Lf_{}_StlCategory')".format(self._category))): @@ -459,6 +460,7 @@ def _createPopupWindow(self, clear): lfCmd("noautocmd silent noswapfile let winid = nvim_open_win(%d, 1, %s)" % (buf_number, str(config))) self._popup_winid = int(lfEval("winid")) + self._window_id = self._popup_winid self._setAttributes() if lfEval("get(g:, 'Lf_PopupShowFoldcolumn', 1)") == '0' or lfEval("get(g:, 'Lf_PopupShowBorder', 0)") == '1': try: @@ -619,6 +621,7 @@ def getWindow(number): lfCmd("noautocmd silent noswapfile let winid = popup_create(%d, %s)" % (buf_number, str(options))) self._popup_winid = int(lfEval("winid")) + self._window_id = self._popup_winid lfCmd("call win_execute(%d, 'setlocal nobuflisted')" % self._popup_winid) lfCmd("call win_execute(%d, 'setlocal buftype=nofile')" % self._popup_winid) lfCmd("call win_execute(%d, 'setlocal bufhidden=hide')" % self._popup_winid) @@ -818,6 +821,8 @@ def _createBufWindow(self, win_pos): lfCmd("doautocmd WinEnter") + if lfEval("exists('*win_getid')") == '1': + self._window_id = int(lfEval("win_getid()")) self._tabpage_object = vim.current.tabpage self._window_object = vim.current.window self._initial_win_height = self._window_object.height @@ -1421,16 +1426,17 @@ def tabpage(self): def window(self): return self._window_object + @property + def windowId(self): + return self._window_id + @property def buffer(self): return self._buffer_object @property def currentLine(self): - if self._win_pos in ('popup', 'floatwin'): - return self._buffer_object[self._window_object.cursor[0] - 1] - else: - return vim.current.line if self._buffer_object == vim.current.buffer else None + return self._buffer_object[self._window_object.cursor[0] - 1] def empty(self): return len(self._buffer_object) == 1 and self._buffer_object[0] == '' diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 90beb285..4a69ff2a 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -112,7 +112,7 @@ def __init__(self): self._highlight_pos_list = [] self._highlight_refine_pos = [] self._highlight_ids = [] - self._orig_line = '' + self._orig_line = None self._fuzzy_engine = None self._result_content = [] self._reader_thread = None @@ -127,6 +127,7 @@ def __init__(self): self._vim_file_autoloaded = False self._arguments = {} self._getExplClass() + self._preview_filetype = None #************************************************************** # abstract methods, in fact all the functions can be overridden @@ -373,25 +374,25 @@ def _closePreviewPopup(self): lfCmd("noautocmd call popup_close(%d)" % self._preview_winid) self._preview_winid = 0 - def _previewResult(self, preview): - if self._getInstance().getWinPos() == 'floatwin': - self._cli.buildPopupPrompt() + self._preview_filetype = None + def _previewResult(self, preview): if lfEval("get(g:, 'Lf_PreviewInPopup', 0)") == '1': - if self._orig_line != self._getInstance().currentLine: - self._closePreviewPopup() - else: + if preview == False and self._orig_line == self._getInstance().currentLine: return + self._orig_line = self._getInstance().currentLine + if not self._needPreview(preview): + if lfEval("get(g:, 'Lf_PreviewInPopup', 0)") == '1': + self._closePreviewPopup() return - line = self._getInstance().currentLine + line_nr = self._getInstance().window.cursor[0] + line = self._getInstance().buffer[line_nr - 1] if lfEval("get(g:, 'Lf_PreviewInPopup', 0)") == '1': - line_nr = self._getInstance().window.cursor[0] self._previewInPopup(line, self._getInstance().buffer, line_nr) - lfCmd("redraw") return orig_pos = self._getInstance().getOriginalPos() @@ -465,9 +466,9 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): lfPrintError(e) return buffer_len = int(lfEval("len(content)")) - lfCmd("let scratch_buffer = nvim_create_buf(0, 1)") - lfCmd("call setbufline(scratch_buffer, 1, content)") - lfCmd("call nvim_buf_set_option(scratch_buffer, 'bufhidden', 'wipe')") + lfCmd("noautocmd let g:Lf_preview_scratch_buffer = nvim_create_buf(0, 1)") + lfCmd("noautocmd call setbufline(g:Lf_preview_scratch_buffer, 1, content)") + lfCmd("noautocmd call nvim_buf_set_option(g:Lf_preview_scratch_buffer, 'bufhidden', 'wipe')") float_window = self._getInstance().window # row and col start from 0 @@ -566,7 +567,8 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): if isinstance(source, int): self._preview_winid = int(lfEval("nvim_open_win(%d, 0, %s)" % (source, str(config)))) else: - self._preview_winid = int(lfEval("nvim_open_win(scratch_buffer, 0, %s)" % str(config))) + self._preview_winid = int(lfEval("nvim_open_win(g:Lf_preview_scratch_buffer, 0, %s)" % str(config))) + self._preview_filetype = lfEval("getbufvar(winbufnr(%d), '&ft')" % self._preview_winid) lfCmd("let g:Lf_PreviewWindowID[%d] = %d" % (id(self), self._preview_winid)) if jump_cmd: @@ -594,7 +596,6 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): lfCmd("silent! %foldopen!") lfCmd("norm! zz") lfCmd("noautocmd call win_gotoid(%s)" % cur_winid) - # lfCmd("redraw!") # maybe we don't need it, it makes the preview slow else: popup_window = self._getInstance().window popup_pos = lfEval("popup_getpos(%d)" % popup_window.id) @@ -606,8 +607,11 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): maxwidth = min(width, int(lfEval("&columns"))) if isinstance(source, int): + lfCmd("let content = getbufline(%d, 1, '$')" % source) buffer_len = len(vim.buffers[source]) + filename = vim.buffers[source].name else: + filename = source try: lfCmd("let content = readfile('%s', '', 4096)" % escQuote(source)) except vim.error as e: @@ -723,18 +727,18 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): options["maxheight"] = maxheight options["minheight"] = maxheight - if isinstance(source, int): - lfCmd("noautocmd silent! let winid = popup_create(%d, %s)" % (source, json.dumps(options))) - else: - lfCmd("silent! let winid = popup_create(content, %s)" % json.dumps(options)) - lfCmd("call win_execute(winid, 'setlocal nomodeline')") - lfCmd("call win_execute(winid, 'doautocmd filetypedetect BufNewFile %s')" % escQuote(source)) + lfCmd("noautocmd silent! let winid = popup_create(content, %s)" % json.dumps(options)) + lfCmd("call win_execute(winid, 'setlocal nomodeline')") + lfCmd("call win_execute(winid, 'doautocmd filetypedetect BufNewFile %s')" % escQuote(filename)) self._preview_winid = int(lfEval("winid")) + self._preview_filetype = lfEval("getbufvar(winbufnr(winid), '&ft')") if jump_cmd: lfCmd("""call win_execute(%d, '%s')""" % (self._preview_winid, escQuote(jump_cmd))) + lfCmd("call win_execute(%d, 'norm! zz')" % self._preview_winid) elif line_nr > 0: lfCmd("""call win_execute(%d, "call cursor(%d, 1)")""" % (self._preview_winid, line_nr)) + lfCmd("call win_execute(%d, 'norm! zz')" % self._preview_winid) lfCmd("call win_execute(%d, 'setlocal cursorline number norelativenumber colorcolumn= ')" % self._preview_winid) lfCmd("call win_execute(%d, 'setlocal foldmethod=manual')" % self._preview_winid) if lfEval("exists('+cursorlineopt')") == '1': @@ -744,7 +748,53 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): lfCmd("call win_execute(%d, 'setlocal foldcolumn=0')" % self._preview_winid) else: lfCmd("call win_execute(%d, 'setlocal foldcolumn=1')" % self._preview_winid) + + def _useExistingWindow(self, title, source, line_nr, jump_cmd): + if lfEval("has('nvim')") == '1': + if isinstance(source, int): + lfCmd("noautocmd call nvim_win_set_buf(%d, %d)" % (self._preview_winid, source)) + else: + try: + lfCmd("let content = readfile('%s', '', 4096)" % escQuote(source)) + except vim.error as e: + lfPrintError(e) + return + if lfEval("!exists('g:Lf_preview_scratch_buffer') || !bufexists(g:Lf_preview_scratch_buffer)") == '1': + lfCmd("noautocmd let g:Lf_preview_scratch_buffer = nvim_create_buf(0, 1)") + lfCmd("noautocmd call nvim_buf_set_lines(g:Lf_preview_scratch_buffer, 0, -1, v:false, content)") + lfCmd("noautocmd call nvim_win_set_buf(%d, g:Lf_preview_scratch_buffer)" % self._preview_winid) + + cur_filetype = getExtension(source) + if cur_filetype != self._preview_filetype: + lfCmd("call win_execute(%d, 'doautocmd filetypedetect BufNewFile %s')" % (self._preview_winid, escQuote(source))) + self._preview_filetype = lfEval("getbufvar(winbufnr(%d), '&ft')" % self._preview_winid) + else: + lfCmd("noautocmd call leaderf#ResetPopupOptions(%d, 'title', '%s')" % (self._preview_winid, title)) + if isinstance(source, int): + lfCmd("noautocmd call popup_settext(%d, getbufline(%d, 1, '$'))" % (self._preview_winid, source) ) + filename = vim.buffers[source].name + else: + filename = source + try: + lfCmd("let content = readfile('%s', '', 4096)" % escQuote(filename)) + except vim.error as e: + lfPrintError(e) + return + lfCmd("noautocmd call popup_settext(%d, content)" % self._preview_winid ) + + cur_filetype = getExtension(filename) + if cur_filetype != self._preview_filetype: + lfCmd("call win_execute(%d, 'doautocmd filetypedetect BufNewFile %s')" % (self._preview_winid, escQuote(filename))) + self._preview_filetype = lfEval("getbufvar(winbufnr(%d), '&ft')" % self._preview_winid) + + if jump_cmd: + lfCmd("""call win_execute(%d, '%s')""" % (self._preview_winid, escQuote(jump_cmd))) + lfCmd("call win_execute(%d, 'norm! zz')" % self._preview_winid) + elif line_nr > 0: + lfCmd("""call win_execute(%d, "call cursor(%d, 1)")""" % (self._preview_winid, line_nr)) lfCmd("call win_execute(%d, 'norm! zz')" % self._preview_winid) + else: + lfCmd("call win_execute(%d, 'norm! gg')" % self._preview_winid) @ignoreEvent('BufRead,BufReadPre,BufReadPost') def _createPopupPreview(self, title, source, line_nr, jump_cmd=''): @@ -758,6 +808,10 @@ def _createPopupPreview(self, title, source, line_nr, jump_cmd=''): self._is_previewed = True line_nr = int(line_nr) + if self._preview_winid > 0 and int(lfEval("winbufnr(%d)" % self._preview_winid)) != -1: + self._useExistingWindow(title, source, line_nr, jump_cmd) + return + if self._getInstance().getWinPos() in ('popup', 'floatwin'): self._createPopupModePreview(title, source, line_nr, jump_cmd) return @@ -782,9 +836,9 @@ def _createPopupPreview(self, title, source, line_nr, jump_cmd=''): lfPrintError(e) return buffer_len = int(lfEval("len(content)")) - lfCmd("let scratch_buffer = nvim_create_buf(0, 1)") - lfCmd("call setbufline(scratch_buffer, 1, content)") - lfCmd("call nvim_buf_set_option(scratch_buffer, 'bufhidden', 'wipe')") + lfCmd("noautocmd let g:Lf_preview_scratch_buffer = nvim_create_buf(0, 1)") + lfCmd("noautocmd call setbufline(g:Lf_preview_scratch_buffer, 1, content)") + lfCmd("noautocmd call nvim_buf_set_option(g:Lf_preview_scratch_buffer, 'bufhidden', 'wipe')") height = max(1, min(maxheight, buffer_len)) preview_pos = lfEval("get(g:, 'Lf_PreviewHorizontalPosition', 'right')") if preview_pos.lower() == 'center': @@ -818,7 +872,8 @@ def _createPopupPreview(self, title, source, line_nr, jump_cmd=''): if isinstance(source, int): self._preview_winid = int(lfEval("nvim_open_win(%d, 0, %s)" % (source, str(config)))) else: - self._preview_winid = int(lfEval("nvim_open_win(scratch_buffer, 0, %s)" % str(config))) + self._preview_winid = int(lfEval("nvim_open_win(g:Lf_preview_scratch_buffer, 0, %s)" % str(config))) + self._preview_filetype = lfEval("getbufvar(winbufnr(%d), '&ft')" % self._preview_winid) if jump_cmd: cur_winid = lfEval("win_getid()") @@ -882,21 +937,25 @@ def _createPopupPreview(self, title, source, line_nr, jump_cmd=''): options["minheight"] = maxheight if isinstance(source, int): - lfCmd("noautocmd silent! let winid = popup_create(%d, %s)" % (source, json.dumps(options))) + lfCmd("let content = getbufline(%d, 1, '$')" % source) + filename = vim.buffers[source].name else: + filename = source try: lfCmd("let content = readfile('%s', '', 4096)" % escQuote(source)) except vim.error as e: lfPrintError(e) return - lfCmd("silent! let winid = popup_create(content, %s)" % json.dumps(options)) - lfCmd("call win_execute(winid, 'setlocal nomodeline')") - lfCmd("call win_execute(winid, 'doautocmd filetypedetect BufNewFile %s')" % escQuote(source)) + + lfCmd("silent! let winid = popup_create(content, %s)" % json.dumps(options)) + lfCmd("call win_execute(winid, 'setlocal nomodeline')") + lfCmd("call win_execute(winid, 'doautocmd filetypedetect BufNewFile %s')" % escQuote(filename)) self._preview_winid = int(lfEval("winid")) + self._preview_filetype = lfEval("getbufvar(winbufnr(winid), '&ft')") if self._current_mode == 'NORMAL': - lfCmd("call leaderf#ResetPopupOptions(%d, 'filter', function('leaderf#normalModePreviewFilter', [%d]))" - % (self._preview_winid, id(self))) + lfCmd("call leaderf#ResetPopupOptions(%d, 'filter', function('leaderf#normalModePreviewFilter', [%d, %d]))" + % (self._preview_winid, id(self), self._getInstance().windowId)) if jump_cmd: lfCmd("""call win_execute(%d, '%s')""" % (self._preview_winid, escQuote(jump_cmd))) elif line_nr > 0: @@ -912,36 +971,29 @@ def _needPreview(self, preview): preview: if True, always preview the result no matter what `g:Lf_PreviewResult` is. """ - if "--auto-preview" in self._arguments: - self._orig_line = self._getInstance().currentLine - return True - - preview_dict = {k.lower(): v for k, v in lfEval("g:Lf_PreviewResult").items()} - category = self._getExplorer().getStlCategory() - if not preview and int(preview_dict.get(category.lower(), 0)) == 0: - return False - if self._getInstance().isReverseOrder(): if self._getInstance().window.cursor[0] > len(self._getInstance().buffer) - self._help_length: - self._orig_line = self._getInstance().currentLine return False elif self._getInstance().window.cursor[0] <= self._help_length: - self._orig_line = self._getInstance().currentLine - return False - - if self._getInstance().empty() or (self._getInstance().getWinPos() != 'popup' and - vim.current.buffer != self._getInstance().buffer): return False if preview: return True - line = self._getInstance().currentLine - if self._orig_line == line and (self._getInstance().buffer.options['modifiable'] - or self._getInstance().getWinPos() in ('popup', 'floatwin')): + # # non popup mode does not support automatic preview + # if lfEval("get(g:, 'Lf_PreviewInPopup', 0)") == '0': + # return False + + if "--auto-preview" in self._arguments: + return True + + preview_dict = {k.lower(): v for k, v in lfEval("g:Lf_PreviewResult").items()} + category = self._getExplorer().getStlCategory() + if int(preview_dict.get(category.lower(), 0)) == 0: return False - self._orig_line = self._getInstance().currentLine + if self._getInstance().empty(): + return False return True @@ -1066,7 +1118,7 @@ def _toDownInPopup(self): def _toUp(self): if self._getInstance().getWinPos() == 'popup': - lfCmd("call win_execute(%d, 'norm! k')" % (self._getInstance().getPopupWinId())) + lfCmd("noautocmd call win_execute(%d, 'norm! k')" % (self._getInstance().getPopupWinId())) self._getInstance().refreshPopupStatusline() return @@ -1079,7 +1131,7 @@ def _toUp(self): and len(self._highlight_pos) < int(lfEval("g:Lf_NumberOfHighlight")): self._highlight_method() - lfCmd("norm! k") + lfCmd("noautocmd norm! k") if adjust: lfCmd("norm! zt") @@ -1090,7 +1142,7 @@ def _toUp(self): def _toDown(self): if self._getInstance().getWinPos() == 'popup': - lfCmd("call win_execute(%d, 'norm! j')" % (self._getInstance().getPopupWinId())) + lfCmd("noautocmd call win_execute(%d, 'norm! j')" % (self._getInstance().getPopupWinId())) self._getInstance().refreshPopupStatusline() return @@ -1098,7 +1150,7 @@ def _toDown(self): and self._getInstance().getCurrentPos()[0] == self._getInstance().window.height: self._setResultContent() - lfCmd("norm! j") + lfCmd("noautocmd norm! j") self._getInstance().setLineNumber() lfCmd("setlocal cursorline!") # these two help to redraw the statusline, lfCmd("setlocal cursorline!") # also fix a weird bug of vim @@ -1135,14 +1187,12 @@ def _pageDown(self): def _leftClick(self): if self._getInstance().getWinPos() == 'popup': - if int(lfEval("has('patch-8.1.2266')")) == 1: - if self._getInstance().getPopupWinId() == int(lfEval("v:mouse_winid")): - lfCmd("""call win_execute(%d, "exec v:mouse_lnum")""" - % (self._getInstance().getPopupWinId())) - lfCmd("""call win_execute(%d, "exec 'norm!'.v:mouse_col.'|'")""" - % (self._getInstance().getPopupWinId())) + if int(lfEval("has('patch-8.1.2292')")) == 1: + lfCmd("""call win_execute(v:mouse_winid, "exec v:mouse_lnum")""") + lfCmd("""call win_execute(v:mouse_winid, "exec 'norm!'.v:mouse_col.'|'")""") exit_loop = False elif self._getInstance().window.number == int(lfEval("v:mouse_win")): + lfCmd("noautocmd silent! call win_gotoid(v:mouse_winid)") lfCmd("exec v:mouse_lnum") lfCmd("exec 'norm!'.v:mouse_col.'|'") self._getInstance().setLineNumber() @@ -1150,20 +1200,28 @@ def _leftClick(self): exit_loop = False elif self._preview_winid == int(lfEval("v:mouse_winid")): if lfEval("has('nvim')") == '1': - lfCmd("call win_gotoid(%d)" % self._preview_winid) + lfCmd("noautocmd silent! call win_gotoid(v:mouse_winid)") lfCmd("exec v:mouse_lnum") lfCmd("exec 'norm!'.v:mouse_col.'|'") - self._current_mode = 'NORMAL' - lfCmd("call leaderf#colorscheme#popup#hiMode('%s', '%s')" - % (self._getExplorer().getStlCategory(), self._current_mode)) - self._getInstance().setPopupStl(self._current_mode) - exit_loop = True + exit_loop = False else: self.quit() exit_loop = True return exit_loop + def _scrollUp(self): + if lfEval('exists("*getmousepos")') == '1': + lfCmd("""call win_execute(getmousepos().winid, "norm! 3\")""") + else: + self._toUp() + + def _scrollDown(self): + if lfEval('exists("*getmousepos")') == '1': + lfCmd("""call win_execute(getmousepos().winid, "norm! 3\")""") + else: + self._toDown() + def _search(self, content, is_continue=False, step=0): if not is_continue: self.clearSelections() @@ -2274,7 +2332,7 @@ def startExplorer(self, win_pos, *args, **kwargs): self._cli.setArguments(arguments_dict) self._cli.setNameOnlyFeature(self._getExplorer().supportsNameOnly()) self._cli.setRefineFeature(self._supportsRefine()) - self._orig_line = '' + self._orig_line = None if self._getExplorer().getStlCategory() in ["Gtags"]: if "--update" in self._arguments or "--remove" in self._arguments: @@ -2784,6 +2842,12 @@ def input(self): self._toUpInPopup() elif equal(cmd, ''): self._toDownInPopup() + elif equal(cmd, ''): + self._scrollUp() + self._previewResult(False) + elif equal(cmd, ''): + self._scrollDown() + self._previewResult(False) else: if self._cmdExtension(cmd): break diff --git a/autoload/leaderf/python/leaderf/rgExpl.py b/autoload/leaderf/python/leaderf/rgExpl.py index a6d30195..745ebceb 100644 --- a/autoload/leaderf/python/leaderf/rgExpl.py +++ b/autoload/leaderf/python/leaderf/rgExpl.py @@ -891,6 +891,8 @@ def deleteCurrentLine(self): else: lfCmd("setlocal nomodifiable") + self._previewResult(False) + def _previewInPopup(self, *args, **kwargs): if len(args) == 0: return diff --git a/autoload/leaderf/python/leaderf/utils.py b/autoload/leaderf/python/leaderf/utils.py index e882a59a..ad31556d 100644 --- a/autoload/leaderf/python/leaderf/utils.py +++ b/autoload/leaderf/python/leaderf/utils.py @@ -246,3 +246,1161 @@ def nearestAncestor(markers, path): return path return "" + +extension_ft = { + ".8th" : "8th", + ".aap" : "aap", + ".abap" : "abap", + ".abc" : "abc", + ".abl" : "abel", + ".wrm" : "acedb", + ".adb" : "ada", + ".ads" : "ada", + ".ada" : "ada", + ".gpr" : "ada", + ".tdf" : "ahdl", + ".aidl" : "aidl", + ".run" : "ampl", + ".ino" : "arduino", + ".pde" : "arduino", + ".a65" : "a65", + ".scpt" : "applescript", + ".am" : "elf", + ".aml" : "aml", + ".art" : "art", + ".asciidoc" : "asciidoc", + ".adoc" : "asciidoc", + ".asn" : "asn", + ".asn1" : "asn", + ".demo" : "maxima", + ".wxm" : "maxima", + ".mar" : "vmasm", + ".astro" : "astro", + ".atl" : "atlas", + ".as" : "atlas", + ".atom" : "xml", + ".au3" : "autoit", + ".ahk" : "autohotkey", + ".at" : "m4", + ".ave" : "ave", + ".awk" : "awk", + ".gawk" : "awk", + ".mch" : "b", + ".ref" : "b", + ".imp" : "b", + ".bass" : "bass", + ".vb" : "vb", + ".vbs" : "vb", + ".dsm" : "vb", + ".ctl" : "vb", + ".iba" : "ibasic", + ".ibi" : "ibasic", + ".fb" : "freebasic", + ".bat" : "dosbatch", + ".bc" : "bc", + ".bdf" : "bdf", + ".beancount" : "beancount", + ".bib" : "bib", + ".bst" : "bst", + ".bicep" : "bicep", + ".bl" : "blank", + ".bb" : "bitbake", + ".bbappend" : "bitbake", + ".bbclass" : "bitbake", + ".bsd" : "bsdl", + ".bsdl" : "bsdl", + ".bzl" : "bzl", + ".bazel" : "bzl", + ".BUILD" : "bzl", + ".lpc" : "lpc", + ".ulpc" : "lpc", + ".cairo" : "cairo", + ".capnp" : "capnp", + ".cs" : "cs", + ".csx" : "cs", + ".csdl" : "csdl", + ".cabal" : "cabal", + ".toc" : "cdrtoc", + ".chai" : "chaiscript", + ".chatito" : "chatito", + ".cdl" : "cdl", + ".recipe" : "conaryrecipe", + ".cpon" : "cpon", + ".crm" : "crm", + ".cyn" : "cynpp", + ".c" : "c", + ".cc" : "cpp", + ".cpp" : "cpp", + ".cxx" : "cpp", + ".c++" : "cpp", + ".c++m" : "cpp", + ".h" : "cpp", + ".hh" : "cpp", + ".hxx" : "cpp", + ".hpp" : "cpp", + ".ipp" : "cpp", + ".moc" : "cpp", + ".tcc" : "cpp", + ".inl" : "cpp", + ".C" : "cpp", + ".H" : "cpp", + ".cppm" : "cpp", + ".ccm" : "cpp", + ".cxxm" : "cpp", + ".chf" : "ch", + ".tlh" : "cpp", + ".css" : "css", + ".con" : "cterm", + ".chopro" : "chordpro", + ".crd" : "chordpro", + ".cho" : "chordpro", + ".crdpro" : "chordpro", + ".chordpro" : "chordpro", + ".dcl" : "clean", + ".icl" : "clean", + ".eni" : "cl", + ".clj" : "clojure", + ".cljs" : "clojure", + ".cljx" : "clojure", + ".cljc" : "clojure", + ".cmake" : "cmake", + ".cbl" : "cobol", + ".cob" : "cobol", + ".lib" : "cobol", + ".atg" : "coco", + ".cfm" : "cf", + ".cfi" : "cf", + ".cfc" : "cf", + ".cook" : "cook", + ".cql" : "cqlang", + ".cr" : "crystal", + ".csv" : "csv", + ".cu" : "cuda", + ".cuh" : "cuda", + ".cue" : "cue", + ".dcd" : "dcd", + ".exs" : "elixir", + ".eex" : "eelixir", + ".leex" : "eelixir", + ".elv" : "elvish", + ".lrc" : "lyrics", + ".quake" : "m3quake", + ".qc" : "c", + ".feature" : "cucumber", + ".csp" : "csp", + ".fdr" : "csp", + ".pld" : "cupl", + ".si" : "cuplsim", + ".dart" : "dart", + ".drt" : "dart", + ".dhall" : "dhall", + ".desc" : "desc", + ".desktop" : "desktop", + ".directory" : "desktop", + ".diff" : "diff", + ".rej" : "diff", + ".dot" : "dot", + ".gv" : "dot", + ".lid" : "dylanlid", + ".intr" : "dylanintr", + ".dylan" : "dylan", + ".def" : "def", + ".drac" : "dracula", + ".drc" : "dracula", + ".ds" : "datascript", + ".dtd" : "dtd", + ".dts" : "dts", + ".dtsi" : "dts", + ".ecd" : "ecd", + ".erl" : "erlang", + ".hrl" : "erlang", + ".yaws" : "erlang", + ".elm" : "elm", + ".lc" : "elsa", + ".esdl" : "esdl", + ".ec" : "esqlc", + ".EC" : "esqlc", + ".strl" : "esterel", + ".csc" : "csc", + ".exp" : "expect", + ".fal" : "falcon", + ".fan" : "fan", + ".fwt" : "fan", + ".factor" : "factor", + ".fnl" : "fennel", + ".fir" : "firrtl", + ".fish" : "fish", + ".fex" : "focexec", + ".focexec" : "focexec", + ".mas" : "master", + ".master" : "master", + ".ft" : "forth", + ".fth" : "forth", + ".frt" : "reva", + ".F" : "fortran", + ".FOR" : "fortran", + ".FPP" : "fortran", + ".FTN" : "fortran", + ".F77" : "fortran", + ".F90" : "fortran", + ".F95" : "fortran", + ".F03" : "fortran", + ".F08" : "fortran", + ".f" : "fortran", + ".for" : "fortran", + ".fortran" : "fortran", + ".fpp" : "fortran", + ".ftn" : "fortran", + ".f77" : "fortran", + ".f90" : "fortran", + ".f95" : "fortran", + ".f03" : "fortran", + ".f08" : "fortran", + ".fsl" : "framescript", + ".fc" : "func", + ".fusion" : "fusion", + ".fsh" : "fsh", + ".fsi" : "fsharp", + ".fsx" : "fsharp", + ".gdb" : "gdb", + ".mo" : "gdmo", + ".gdmo" : "gdmo", + ".gd" : "gdscript", + ".tscn" : "gdresource", + ".tres" : "gdresource", + ".gdshader" : "gdshader", + ".shader" : "gdshader", + ".ged" : "gedcom", + ".gmi" : "gemtext", + ".gemini" : "gemtext", + ".gift" : "gift", + ".gleam" : "gleam", + ".glsl" : "glsl", + ".gp" : "gp", + ".gts" : "typescript.glimmer", + ".gjs" : "javascript.glimmer", + ".gpi" : "gnuplot", + ".go" : "go", + ".gs" : "grads", + ".graphql" : "graphql", + ".graphqls" : "graphql", + ".gql" : "graphql", + ".gretl" : "gretl", + ".gradle" : "groovy", + ".groovy" : "groovy", + ".gsp" : "gsp", + ".gyp" : "gyp", + ".gypi" : "gyp", + ".hack" : "hack", + ".hackpartial" : "hack", + ".haml" : "haml", + ".hsm" : "hamster", + ".hbs" : "handlebars", + ".ha" : "hare", + ".hs" : "haskell", + ".hsc" : "haskell", + ".hsig" : "haskell", + ".lhs" : "lhaskell", + ".chs" : "chaskell", + ".ht" : "haste", + ".htpp" : "hastepreproc", + ".hcl" : "hcl", + ".vc" : "hercules", + ".ev" : "hercules", + ".sum" : "hercules", + ".errsum" : "hercules", + ".heex" : "heex", + ".hex" : "hex", + ".h32" : "hex", + ".hjson" : "hjson", + ".m3u" : "hlsplaylist", + ".m3u8" : "hlsplaylist", + ".hws" : "hollywood", + ".hoon" : "hoon", + ".htm" : "html", + ".html" : "html", + ".shtml" : "html", + ".stm" : "html", + ".cshtml" : "html", + ".cshtml" : "html", + ".erb" : "eruby", + ".rhtml" : "eruby", + ".tmpl" : "template", + ".hb" : "hb", + ".htt" : "httest", + ".htb" : "httest", + ".icn" : "icon", + ".odl" : "msidl", + ".mof" : "msidl", + ".inf" : "inform", + ".INF" : "inform", + ".ii" : "initng", + ".4gl" : "fgl", + ".4gh" : "fgl", + ".m4gl" : "fgl", + ".ini" : "dosini", + ".iss" : "iss", + ".ijs" : "j", + ".jal" : "jal", + ".JAL" : "jal", + ".jpl" : "jam", + ".jpr" : "jam", + ".java" : "java", + ".jav" : "java", + ".jj" : "javacc", + ".jjt" : "javacc", + ".js" : "javascript", + ".jsm" : "javascript", + ".javascript" : "javascript", + ".es" : "javascript", + ".mjs" : "javascript", + ".cjs" : "javascript", + ".jsx" : "javascriptreact", + ".jsp" : "jsp", + ".properties" : "jproperties", + ".clp" : "jess", + ".jgr" : "jgraph", + ".jov" : "jovial", + ".j73" : "jovial", + ".jovial" : "jovial", + ".jq" : "jq", + ".json5" : "json5", + ".ipynb" : "json", + ".jsonc" : "jsonc", + ".json" : "json", + ".jsonp" : "json", + ".webmanifest" : "json", + ".jsonnet" : "jsonnet", + ".libsonnet" : "jsonnet", + ".jl" : "julia", + ".kdl" : "kdl", + ".kix" : "kix", + ".k" : "kwt", + ".kv" : "kivy", + ".kt" : "kotlin", + ".ktm" : "kotlin", + ".kts" : "kotlin", + ".ks" : "kscript", + ".ace" : "lace", + ".ACE" : "lace", + ".latte" : "latte", + ".lte" : "latte", + ".ldif" : "ldif", + ".ld" : "ld", + ".lean" : "lean", + ".ldg" : "ledger", + ".ledger" : "ledger", + ".journal" : "ledger", + ".less" : "less", + ".lex" : "lex", + ".l" : "lex", + ".lxx" : "lex", + ".ll" : "lifelines", + ".ly" : "lilypond", + ".ily" : "lilypond", + ".lsp" : "lisp", + ".lisp" : "lisp", + ".asd" : "lisp", + ".el" : "lisp", + ".cl" : "lisp", + ".L" : "lisp", + ".liquid" : "liquid", + ".lite" : "lite", + ".lt" : "lite", + ".livemd" : "livebook", + ".lgt" : "logtalk", + ".lot" : "lotos", + ".lotos" : "lotos", + ".lou" : "lout", + ".lout" : "lout", + ".lua" : "lua", + ".luau" : "luau", + ".rockspec" : "lua", + ".lss" : "lss", + ".mgp" : "mgp", + ".eml" : "mail", + ".mk" : "make", + ".mak" : "make", + ".dsp" : "make", + ".ist" : "ist", + ".mst" : "ist", + ".page" : "mallard", + ".man" : "man", + ".mv" : "maple", + ".mpl" : "maple", + ".mws" : "maple", + ".map" : "map", + ".markdown" : "markdown", + ".mdown" : "markdown", + ".mkd" : "markdown", + ".mkdn" : "markdown", + ".mdwn" : "markdown", + ".md" : "markdown", + ".mason" : "mason", + ".mhtml" : "mason", + ".comp" : "mason", + ".nb" : "mma", + ".mel" : "mel", + ".hgrc" : "cfg", + ".mmd" : "mermaid", + ".mmdc" : "mermaid", + ".mermaid" : "mermaid", + ".wrap" : "dosini", + ".mf" : "mf", + ".mp" : "mp", + ".mgl" : "mgl", + ".mix" : "mix", + ".mixal" : "mix", + ".mmp" : "mmp", + ".m2" : "modula2", + ".DEF" : "modula2", + ".mi" : "modula2", + ".lm3" : "modula3", + ".isc" : "monk", + ".monk" : "monk", + ".ssc" : "monk", + ".tsc" : "monk", + ".moo" : "moo", + ".moon" : "moonscript", + ".move" : "move", + ".mpd" : "xml", + ".s19" : "srec", + ".s28" : "srec", + ".s37" : "srec", + ".mot" : "srec", + ".srec" : "srec", + ".msql" : "msql", + ".mysql" : "mysql", + ".mu" : "mupad", + ".mush" : "mush", + ".n1ql" : "n1ql", + ".nql" : "n1ql", + ".nanorc" : "nanorc", + ".nginx" : "nginx", + ".nim" : "nim", + ".nims" : "nim", + ".nimble" : "nim", + ".ninja" : "ninja", + ".nix" : "nix", + ".ncf" : "ncf", + ".tr" : "nroff", + ".nr" : "nroff", + ".roff" : "nroff", + ".tmac" : "nroff", + ".mom" : "nroff", + ".nqc" : "nqc", + ".nse" : "lua", + ".nsi" : "nsis", + ".nsh" : "nsis", + ".obl" : "obse", + ".obse" : "obse", + ".oblivion" : "obse", + ".obscript" : "obse", + ".ml" : "ocaml", + ".mli" : "ocaml", + ".mll" : "ocaml", + ".mly" : "ocaml", + ".mlt" : "ocaml", + ".mlp" : "ocaml", + ".mlip" : "ocaml", + ".occ" : "occam", + ".odin" : "odin", + ".xom" : "omnimark", + ".xin" : "omnimark", + ".opam" : "opam", + ".or" : "openroad", + ".scad" : "openscad", + ".ora" : "ora", + ".org" : "org", + ".org_archive" : "org", + ".nmconnection": "confini", + ".papp" : "papp", + ".pxml" : "papp", + ".pxsl" : "papp", + ".pas" : "pascal", + ".dpr" : "pascal", + ".lpr" : "pascal", + ".fpc" : "fpcmake", + ".filter" : "poefilter", + ".pdf" : "pdf", + ".pcmk" : "pcmk", + ".plx" : "perl", + ".al" : "perl", + ".psgi" : "perl", + ".pod" : "pod", + ".php" : "php", + ".phtml" : "php", + ".ctp" : "php", + ".phpt" : "php", + ".theme" : "php", + ".pike" : "pike", + ".pmod" : "pike", + ".cmod" : "cmod", + ".rcp" : "pilrc", + ".pli" : "pli", + ".pl1" : "pli", + ".plm" : "plm", + ".p36" : "plm", + ".pac" : "plm", + ".pls" : "plsql", + ".plsql" : "plsql", + ".plp" : "plp", + ".po" : "po", + ".pot" : "po", + ".pony" : "pony", + ".ps" : "postscr", + ".pfa" : "postscr", + ".afm" : "postscr", + ".eps" : "postscr", + ".epsf" : "postscr", + ".epsi" : "postscr", + ".ai" : "postscr", + ".ppd" : "ppd", + ".pov" : "pov", + ".ps1" : "ps1", + ".psd1" : "ps1", + ".psm1" : "ps1", + ".pssc" : "ps1", + ".ps1xml" : "ps1xml", + ".cdxml" : "xml", + ".psc1" : "xml", + ".prisma" : "prisma", + ".g" : "pccts", + ".it" : "ppwiz", + ".ih" : "ppwiz", + ".pug" : "pug", + ".epp" : "epuppet", + ".obj" : "obj", + ".pc" : "proc", + ".action" : "privoxy", + ".psf" : "psf", + ".pdb" : "prolog", + ".pml" : "promela", + ".psl" : "psl", + ".proto" : "proto", + ".pbtxt" : "pbtxt", + ".pk" : "poke", + ".arr" : "pyret", + ".pyx" : "pyrex", + ".pxd" : "pyrex", + ".py" : "python", + ".pyw" : "python", + ".ptl" : "python", + ".pyi" : "python", + ".ql" : "ql", + ".qll" : "ql", + ".qmd" : "quarto", + ".rkt" : "racket", + ".rktd" : "racket", + ".rktl" : "racket", + ".rad" : "radiance", + ".mat" : "radiance", + ".pm6" : "raku", + ".p6" : "raku", + ".t6" : "raku", + ".pod6" : "raku", + ".raku" : "raku", + ".rakumod" : "raku", + ".rakudoc" : "raku", + ".rakutest" : "raku", + ".rib" : "rib", + ".rego" : "rego", + ".rex" : "rexx", + ".orx" : "rexx", + ".rxo" : "rexx", + ".rxj" : "rexx", + ".jrexx" : "rexx", + ".rexxj" : "rexx", + ".rexx" : "rexx", + ".testGroup" : "rexx", + ".testUnit" : "rexx", + ".rd" : "rhelp", + ".Rd" : "rhelp", + ".Rnw" : "rnoweb", + ".rnw" : "rnoweb", + ".Snw" : "rnoweb", + ".snw" : "rnoweb", + ".Rmd" : "rmd", + ".rmd" : "rmd", + ".Smd" : "rmd", + ".smd" : "rmd", + ".rss" : "xml", + ".Rrst" : "rrst", + ".rrst" : "rrst", + ".Srst" : "rrst", + ".srst" : "rrst", + ".remind" : "remind", + ".rem" : "remind", + ".res" : "rescript", + ".resi" : "rescript", + ".rnc" : "rnc", + ".rng" : "rng", + ".rpgle" : "rpgle", + ".rpgleinc" : "rpgle", + ".rpl" : "rpl", + ".robot" : "robot", + ".resource" : "robot", + ".ron" : "ron", + ".rsc" : "routeros", + ".x" : "rpcgen", + ".rst" : "rst", + ".rtf" : "rtf", + ".rb" : "ruby", + ".rbw" : "ruby", + ".gemspec" : "ruby", + ".rbs" : "rbs", + ".ru" : "ruby", + ".builder" : "ruby", + ".rxml" : "ruby", + ".rjs" : "ruby", + ".rant" : "ruby", + ".rake" : "ruby", + ".rs" : "rust", + ".sl" : "slang", + ".sage" : "sage", + ".sas" : "sas", + ".sass" : "sass", + ".sa" : "sather", + ".scala" : "scala", + ".sbt" : "sbt", + ".quark" : "supercollider", + ".sci" : "scilab", + ".sce" : "scilab", + ".scss" : "scss", + ".sd" : "sd", + ".sdl" : "sdl", + ".pr" : "sdl", + ".sed" : "sed", + ".srt" : "srt", + ".ass" : "ssa", + ".ssa" : "ssa", + ".svelte" : "svelte", + ".siv" : "sieve", + ".sieve" : "sieve", + ".zig" : "zig", + ".zir" : "zir", + ".zsh" : "zsh", + ".scm" : "scheme", + ".ss" : "scheme", + ".sld" : "scheme", + ".sexp" : "sexplib", + ".sim" : "simula", + ".sin" : "sinda", + ".s85" : "sinda", + ".sst" : "sisu", + ".ssm" : "sisu", + ".ssi" : "sisu", + "._sst" : "sisu", + ".il" : "skill", + ".ils" : "skill", + ".cdf" : "skill", + ".cdc" : "cdc", + ".score" : "slrnsc", + ".smali" : "smali", + ".st" : "st", + ".tpl" : "smarty", + ".smt" : "smith", + ".smith" : "smith", + ".smithy" : "smithy", + ".sno" : "snobol4", + ".spt" : "snobol4", + ".mib" : "mib", + ".my" : "mib", + ".hog" : "hog", + ".sol" : "solidity", + ".rq" : "sparql", + ".sparql" : "sparql", + ".spec" : "spec", + ".speedup" : "spup", + ".spdata" : "spup", + ".spd" : "spup", + ".ice" : "slice", + ".sln" : "solution", + ".slnf" : "json", + ".sp" : "spice", + ".spice" : "spice", + ".spy" : "spyce", + ".spi" : "spyce", + ".tyb" : "sql", + ".tyc" : "sql", + ".pkb" : "sql", + ".pks" : "sql", + ".sqlj" : "sqlj", + ".prql" : "prql", + ".sqr" : "sqr", + ".sqi" : "sqr", + ".nut" : "squirrel", + ".ipd" : "starlark", + ".star" : "starlark", + ".starlark" : "starlark", + ".ovpn" : "openvpn", + ".ado" : "stata", + ".do" : "stata", + ".imata" : "stata", + ".mata" : "stata", + ".hlp" : "smcl", + ".ihlp" : "smcl", + ".smcl" : "smcl", + ".stp" : "stp", + ".sml" : "sml", + ".cm" : "voscm", + ".swift" : "swift", + ".sdc" : "sdc", + ".svg" : "svg", + ".sface" : "surface", + ".td" : "tablegen", + ".tak" : "tak", + ".tal" : "tal", + ".task" : "taskedit", + ".tcl" : "tcl", + ".tm" : "tcl", + ".tk" : "tcl", + ".itcl" : "tcl", + ".itk" : "tcl", + ".jacl" : "tcl", + ".tl" : "teal", + ".tli" : "tli", + ".slt" : "tsalt", + ".ti" : "terminfo", + ".tfvars" : "terraform-vars", + ".latex" : "tex", + ".sty" : "tex", + ".dtx" : "tex", + ".ltx" : "tex", + ".bbl" : "tex", + ".mkii" : "context", + ".mkiv" : "context", + ".mkvi" : "context", + ".mkxl" : "context", + ".mklx" : "context", + ".texinfo" : "texinfo", + ".texi" : "texinfo", + ".txi" : "texinfo", + ".thrift" : "thrift", + ".tla" : "tla", + ".toml" : "toml", + ".tpp" : "tpp", + ".treetop" : "treetop", + ".tssgm" : "tssgm", + ".tssop" : "tssop", + ".tsscl" : "tsscl", + ".tsv" : "tsv", + ".twig" : "twig", + ".mts" : "typescript", + ".cts" : "typescript", + ".tsx" : "typescriptreact", + ".uit" : "uil", + ".uil" : "uil", + ".ungram" : "ungrammar", + ".uc" : "uc", + ".vala" : "vala", + ".vdf" : "vdf", + ".vdmpp" : "vdmpp", + ".vpp" : "vdmpp", + ".vdmrt" : "vdmrt", + ".vdmsl" : "vdmsl", + ".vdm" : "vdmsl", + ".vr" : "vera", + ".vri" : "vera", + ".vrh" : "vera", + ".va" : "verilogams", + ".vams" : "verilogams", + ".sv" : "systemverilog", + ".svh" : "systemverilog", + ".tape" : "vhs", + ".hdl" : "vhdl", + ".vhd" : "vhdl", + ".vhdl" : "vhdl", + ".vbe" : "vhdl", + ".vst" : "vhdl", + ".vho" : "vhdl", + ".vim" : "vim", + ".vba" : "vim", + ".sba" : "vb", + ".wrl" : "vrml", + ".vroom" : "vroom", + ".vue" : "vue", + ".wat" : "wat", + ".wast" : "wast", + ".wit" : "wit", + ".wm" : "webmacro", + ".wml" : "wml", + ".wbt" : "winbatch", + ".wsml" : "wsml", + ".wpl" : "xml", + ".xhtml" : "xhtml", + ".xht" : "xhtml", + ".xpm2" : "xpm2", + ".xs" : "xs", + ".ad" : "xdefaults", + ".msc" : "xmath", + ".msf" : "xmath", + ".xmi" : "xml", + ".csproj" : "xml", + ".fsproj" : "xml", + ".vbproj" : "xml", + ".ui" : "xml", + ".tpm" : "xml", + ".wsdl" : "xml", + ".wdl" : "wdl", + ".xlf" : "xml", + ".xliff" : "xml", + ".xul" : "xml", + ".xq" : "xquery", + ".xql" : "xquery", + ".xqm" : "xquery", + ".xquery" : "xquery", + ".xqy" : "xquery", + ".xsd" : "xsd", + ".xsl" : "xslt", + ".xslt" : "xslt", + ".yy" : "yacc", + ".yxx" : "yacc", + ".yaml" : "yaml", + ".yml" : "yaml", + ".raml" : "raml", + ".yang" : "yang", + ".yuck" : "yuck", + ".zu" : "zimbu", + ".zut" : "zimbutempl", + ".z8a" : "z8a", + ".text" : "text", + ".usda" : "usd", + ".usd" : "usd", + ".blp" : "blueprint", + ".dm1" : "maxima", + ".dm2" : "maxima", + ".dm3" : "maxima", + ".dmt" : "maxima", + ".dockerfile" : "dockerfile", + ".Dockerfile" : "dockerfile", + ".edf" : "edif", + ".edif" : "edif", + ".edo" : "edif", + ".hs-boot" : "haskell", + ".json-patch" : "json", + ".sub" : "krl", + ".l++" : "lex", + ".opl" : "opl", + ".-sst" : "sisu", + ".-sst.meta" : "sisu", + ".wsf" : "wsh", + ".wsc" : "wsh", + ".y++" : "yacc", + ".ebuild" : "sh", + ".sh" : "sh", + ".bash" : "sh", + ".env" : "sh", + ".eclass" : "sh", + ".ksh" : "ksh", + ".csh" : "csh", + ".tcsh" : "tcsh", + ".xml" : "xml", + ".csproj.user" : "xml", + ".fsproj.user" : "xml", + ".vbproj.user" : "xml", + ".cmake.in" : "cmake", + ".t.html" : "tilde", + ".html.m4" : "htmlm4", + ".upstream.dat" : "upstreamdat", + ".upstream.log" : "upstreamlog", + ".upstreaminstall.log": "upstreaminstalllog", + ".usserver.log" : "usserverlog", + ".usw2kagt.log" : "usw2kagtlog", + ".mli.cppo" : "ocaml", + ".ml.cppo" : "ocaml", + ".opam.template" : "opam", + ".sst.meta" : "sisu", + "._sst.meta" : "sisu", + ".swift.gyb" : "swiftgyb", +} + +name_ft = { + "a2psrc" : "a2ps", + ".a2psrc" : "a2ps", + "build.xml" : "ant", + ".htaccess" : "apache", + "makefile" : "make", + "Makefile" : "make", + "GNUmakefile" : "make", + "makefile.am" : "automake", + "Makefile.am" : "automake", + "GNUmakefile.am" : "automake", + ".asoundrc" : "alsaconf", + "apt.conf" : "aptconf", + ".arch-inventory" : "arch", + "=tagging-method" : "arch", + "maxima-init.mac" : "maxima", + "named.root" : "bindzone", + "WORKSPACE" : "bzl", + "WORKSPACE.bzlmod" : "bzl", + "BUILD" : "bzl", + ".busted" : "lua", + "calendar" : "calendar", + ".cdrdao" : "cdrdaoconf", + "cfengine.conf" : "cfengine", + "changelog.Debian" : "debchangelog", + "changelog.dch" : "debchangelog", + "NEWS.Debian" : "debchangelog", + "NEWS.dch" : "debchangelog", + ".clangd" : "yaml", + ".clang-format" : "yaml", + ".clang-tidy" : "yaml", + "CMakeLists.txt" : "cmake", + "configure.in" : "config", + "configure.ac" : "config", + "Containerfile" : "dockerfile", + "Dockerfile" : "dockerfile", + "dockerfile" : "dockerfile", + "mix.lock" : "elixir", + "lynx.cfg" : "lynx", + "cm3.cfg" : "m3quake", + "m3makefile" : "m3build", + "m3overrides" : "m3build", + "denyhosts.conf" : "denyhosts", + "dict.conf" : "dictconf", + ".dictrc" : "dictconf", + ".dir_colors" : "dircolors", + ".dircolors" : "dircolors", + "jbuild" : "dune", + "dune" : "dune", + "dune-project" : "dune", + "dune-workspace" : "dune", + ".editorconfig" : "editorconfig", + "elinks.conf" : "elinks", + "filter-rules" : "elmfilt", + "exim.conf" : "exim", + "exports" : "exports", + ".fetchmailrc" : "fetchmail", + "auto.master" : "conf", + "fstab" : "fstab", + "mtab" : "fstab", + ".gdbinit" : "gdb", + "gdbinit" : "gdb", + ".gdbearlyinit" : "gdb", + "gdbearlyinit" : "gdb", + "lltxxxxx.txt" : "gedcom", + "COMMIT_EDITMSG" : "gitcommit", + "MERGE_MSG" : "gitcommit", + "TAG_EDITMSG" : "gitcommit", + "NOTES_EDITMSG" : "gitcommit", + "EDIT_DESCRIPTION" : "gitcommit", + ".gitconfig" : "gitconfig", + ".gitmodules" : "gitconfig", + ".gitattributes" : "gitattributes", + ".gitignore" : "gitignore", + "git-rebase-todo" : "gitrebase", + "gkrellmrc" : "gkrellmrc", + ".gprc" : "gp", + "gnashrc" : "gnash", + ".gnashrc" : "gnash", + "gnashpluginrc" : "gnash", + ".gnashpluginrc" : "gnash", + "gitolite.conf" : "gitolite", + ".gitolite.rc" : "perl", + "example.gitolite.rc": "perl", + ".gnuplot" : "gnuplot", + "Gopkg.lock" : "toml", + "go.work" : "gowork", + "Jenkinsfile" : "groovy", + ".gtkrc" : "gtkrc", + "gtkrc" : "gtkrc", + "cabal.project" : "cabalproject", + "cabal.config" : "cabalconfig", + "go.sum" : "gosum", + "go.work.sum" : "gosum", + ".indent.pro" : "indent", + "indentrc" : "indent", + "upstream.dat" : "upstreamdat", + "fdrupstream.log" : "upstreamlog", + "upstream.log" : "upstreamlog", + "upstreaminstall.log": "upstreaminstalllog", + "usserver.log" : "usserverlog", + "usw2kagt.log" : "usw2kagtlog", + "ipf.conf" : "ipfilter", + "ipf6.conf" : "ipfilter", + "ipf.rules" : "ipfilter", + "inittab" : "inittab", + ".prettierrc" : "json", + ".firebaserc" : "json", + ".stylelintrc" : "json", + ".babelrc" : "jsonc", + ".eslintrc" : "jsonc", + ".jsfmtrc" : "jsonc", + ".jshintrc" : "jsonc", + ".hintrc" : "jsonc", + ".swrc" : "jsonc", + "Kconfig" : "kconfig", + "Kconfig.debug" : "kconfig", + ".latexmkrc" : "perl", + "latexmkrc" : "perl", + "lftp.conf" : "lftp", + ".lftprc" : "lftp", + "lilo.conf" : "lilo", + ".emacs" : "lisp", + ".sawfishrc" : "lisp", + "sbclrc" : "lisp", + ".sbclrc" : "lisp", + ".luacheckrc" : "lua", + ".letter" : "mail", + ".followup" : "mail", + ".article" : "mail", + ".mailcap" : "mailcap", + "mailcap" : "mailcap", + "man.config" : "manconf", + "meson.build" : "meson", + "meson_options.txt" : "meson", + "mplayer.conf" : "mplayerconf", + "mrxvtrc" : "mrxvtrc", + ".mrxvtrc" : "mrxvtrc", + "tclsh.rc" : "tcl", + "Neomuttrc" : "neomuttrc", + ".netrc" : "netrc", + "npmrc" : "dosini", + ".npmrc" : "dosini", + "env.nu" : "nu", + "config.nu" : "nu", + ".ocamlinit" : "ocaml", + "octave.conf" : "octave", + ".octaverc" : "octave", + "octaverc" : "octave", + "opam" : "opam", + "pf.conf" : "pf", + "mpv.conf" : "confini", + "pam_env.conf" : "pamenv", + ".pam_environment" : "pamenv", + ".pinerc" : "pine", + "pinerc" : "pine", + ".pinercex" : "pine", + "pinercex" : "pine", + "Pipfile" : "toml", + "Pipfile.lock" : "json", + "main.cf" : "pfmain", + "main.cf.proto" : "pfmain", + ".povrayrc" : "povini", + "Puppetfile" : "ruby", + ".procmail" : "procmail", + ".procmailrc" : "procmail", + ".pythonstartup" : "python", + ".pythonrc" : "python", + "SConstruct" : "python", + "qmldir" : "qmldir", + ".ratpoisonrc" : "ratpoison", + "ratpoisonrc" : "ratpoison", + ".inputrc" : "readline", + "inputrc" : "readline", + ".Rprofile" : "r", + "Rprofile" : "r", + "Rprofile.site" : "r", + ".reminders" : "remind", + "resolv.conf" : "resolv", + "robots.txt" : "robots", + ".irbrc" : "ruby", + "irbrc" : "ruby", + "Gemfile" : "ruby", + "rantfile" : "ruby", + "Rantfile" : "ruby", + "rakefile" : "ruby", + "Rakefile" : "ruby", + "Cargo.lock" : "toml", + "smb.conf" : "samba", + "sendmail.cf" : "sm", + "catalog" : "catalog", + ".zprofile" : "zsh", + ".zfbfmarks" : "zsh", + ".zshrc" : "zsh", + ".zshenv" : "zsh", + ".zlogin" : "zsh", + ".zlogout" : "zsh", + ".zcompdump" : "zsh", + ".screenrc" : "screen", + "screenrc" : "screen", + ".slrnrc" : "slrnrc", + "snort.conf" : "hog", + "vision.conf" : "hog", + "squid.conf" : "squid", + "ssh_config" : "sshconfig", + "sshd_config" : "sshdconfig", + "sudoers.tmp" : "sudoers", + "tags" : "tags", + "pending.data" : "taskdata", + "completed.data" : "taskdata", + "undo.data" : "taskdata", + ".tclshrc" : "tcl", + ".wishrc" : "tcl", + "texmf.cnf" : "texmf", + ".tidyrc" : "tidy", + "tidyrc" : "tidy", + "tidy.conf" : "tidy", + ".tfrc" : "tf", + "tfrc" : "tf", + "trustees.conf" : "trustees", + "Vagrantfile" : "ruby", + ".vimrc" : "vim", + "_vimrc" : "vim", + ".exrc" : "vim", + "_exrc" : "vim", + ".viminfo" : "viminfo", + "_viminfo" : "viminfo", + "vgrindefs" : "vgrindefs", + ".wgetrc" : "wget", + "wgetrc" : "wget", + ".wget2rc" : "wget2", + "wget2rc" : "wget2", + "wvdial.conf" : "wvdial", + ".wvdialrc" : "wvdial", + ".cvsrc" : "cvsrc", + ".Xdefaults" : "xdefaults", + ".Xpdefaults" : "xdefaults", + ".Xresources" : "xdefaults", + "xdm-config" : "xdefaults", + "fglrxrc" : "xml", + "README" : "text", + "LICENSE" : "text", + "COPYING" : "text", + "AUTHORS" : "text", + ".bashrc" : "sh", + "bashrc" : "sh", + "bash.bashrc" : "sh", + ".bash_profile" : "sh", + ".bash-profile" : "sh", + ".bash_logout" : "sh", + ".bash-logout" : "sh", + ".bash_aliases" : "sh", + ".bash-aliases" : "sh", + ".profile" : "sh", + "bash-fc-" : "sh", + "bash-fc." : "sh", + ".kshrc" : "ksh", + ".tcshrc" : "tcsh", + "tcsh.tcshrc" : "tcsh", + "tcsh.login" : "tcsh", + ".login" : "csh", + ".cshrc" : "csh", + "csh.cshrc" : "csh", + "csh.login" : "csh", + "csh.logout" : "csh", + ".alias" : "csh", + ".kshrc" : "ksh", + ".zshrc" : "zsh", +} + +def getExtension(path): + basename = os.path.basename(path) + if basename in name_ft: + return name_ft[basename] + else: + root, ext = os.path.splitext(basename) + if ext == '': + return None + + _, ext2 = os.path.splitext(root) + if ext2 != '': + extension = ext2 + ext + if extension in extension_ft: + return extension_ft[extension] + + if ext == '.txt' and os.path.dirname(path) == lfEval("expand('$VIMRUNTIME/doc')"): + return "help" + + return extension_ft.get(ext, None) diff --git a/doc/leaderf.txt b/doc/leaderf.txt index f3f7bbda..80d10ec5 100644 --- a/doc/leaderf.txt +++ b/doc/leaderf.txt @@ -911,7 +911,7 @@ g:Lf_PopupBorders *g:Lf_PopupBorders* To have a good display for non-ascii characters, perhaps you need to set the value of |ambiwidth| as "single". - Default value is ["-","|","-","|","+","+","+","+"]. + Default value is ["─","│","─","│","╭","╮","╯","╰"]. g:Lf_AutoResize *g:Lf_AutoResize* Auto resize the LeaderF window height automatically. From eda65fe024f33ad9ce355e3f724ea1eb4f6644fe Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Tue, 13 Jun 2023 16:11:29 +0800 Subject: [PATCH 064/365] nvim_win_set_buf() may have a bug --- autoload/leaderf/python/leaderf/manager.py | 1 + 1 file changed, 1 insertion(+) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 4a69ff2a..4d900ec8 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -753,6 +753,7 @@ def _useExistingWindow(self, title, source, line_nr, jump_cmd): if lfEval("has('nvim')") == '1': if isinstance(source, int): lfCmd("noautocmd call nvim_win_set_buf(%d, %d)" % (self._preview_winid, source)) + lfCmd("noautocmd call nvim_win_set_option(%d, 'cursorline', v:true)" % self._preview_winid) else: try: lfCmd("let content = readfile('%s', '', 4096)" % escQuote(source)) From 2a7a9bae98c4f91970799827f8f98c19a8670bae Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Tue, 13 Jun 2023 17:25:36 +0800 Subject: [PATCH 065/365] To use the popup mode, neovim 0.4.2+ or vim 8.1.1615+ are required --- README.md | 2 +- autoload/leaderf/python/leaderf/manager.py | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0a1c3592..2318d2e5 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ Requirements - vim7.3 or higher. Only support 7.4.1126+ after [v1.01](https://github.com/Yggdroot/LeaderF/releases/tag/v1.01). - Python2.7+ or Python3.1+. - - To use the popup mode, neovim 0.42+ or vim 8.1.1615+ are required. + - To use the popup mode, neovim 0.4.2+ or vim 8.1.1615+ are required. Installation ------------ diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 4d900ec8..fb6c050c 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -128,6 +128,9 @@ def __init__(self): self._arguments = {} self._getExplClass() self._preview_filetype = None + if lfEval("has('patch-8.1.1615') || has('nvim-0.4.2')") == '0': + lfCmd("let g:Lf_PreviewInPopup = 0") + #************************************************************** # abstract methods, in fact all the functions can be overridden From 1698cbbec5baabff0488f31b5c7fa89e25707d32 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Tue, 13 Jun 2023 22:57:13 +0800 Subject: [PATCH 066/365] preview result immediately --- .../leaderf/python/leaderf/asyncExecutor.py | 5 ++++- autoload/leaderf/python/leaderf/manager.py | 17 +++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/autoload/leaderf/python/leaderf/asyncExecutor.py b/autoload/leaderf/python/leaderf/asyncExecutor.py index 55b85c05..3442d8f9 100644 --- a/autoload/leaderf/python/leaderf/asyncExecutor.py +++ b/autoload/leaderf/python/leaderf/asyncExecutor.py @@ -201,7 +201,10 @@ def join_left(self, iterable): return self def __iter__(self): - return self._g + return self + + def __next__(self): + return next(self._g) if __name__ == "__main__": diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index fb6c050c..1338d4c1 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -2323,6 +2323,17 @@ def _gotoFirstLine(self): def _readFinished(self): pass + def _previewFirstLine(self, content): + try: + first_line = next(content) + content = itertools.chain([first_line], content) + self._getInstance().setBuffer([first_line]) + self._previewResult(False) + except StopIteration: + pass + + return content + def startExplorer(self, win_pos, *args, **kwargs): arguments_dict = kwargs.get("arguments", {}) if "--recall" in arguments_dict: @@ -2426,6 +2437,7 @@ def startExplorer(self, win_pos, *args, **kwargs): self._getInstance().setStlResultsCount(len(self._content)) if not empty_query: self._getInstance().setBuffer(self._content[:self._initial_count]) + self._previewResult(False) if lfEval("has('nvim')") == '1': lfCmd("redrawstatus") @@ -2467,6 +2479,7 @@ def startExplorer(self, win_pos, *args, **kwargs): self._callback = self._workInIdle if lfEval("get(g:, 'Lf_NoAsync', 0)") == '1': self._content = self._getInstance().initBuffer(content, self._getUnit(), self._getExplorer().setContent) + self._previewResult(False) self._read_finished = 1 self._offset_in_content = 0 else: @@ -2487,6 +2500,7 @@ def startExplorer(self, win_pos, *args, **kwargs): self._read_finished = 0 self._stop_reader_thread = False + content = self._previewFirstLine(content) self._reader_thread = threading.Thread(target=self._readContent, args=(content,)) self._reader_thread.daemon = True self._reader_thread.start() @@ -2500,9 +2514,11 @@ def startExplorer(self, win_pos, *args, **kwargs): self._getInstance().mimicCursor() else: self._is_content_list = False + content = self._previewFirstLine(content) self._callback = partial(self._workInIdle, content) if lfEval("get(g:, 'Lf_NoAsync', 0)") == '1': self._content = self._getInstance().initBuffer(content, self._getUnit(), self._getExplorer().setContent) + self._previewResult(False) self._read_finished = 1 self._offset_in_content = 0 else: @@ -2710,6 +2726,7 @@ def input(self): elif self._empty_query and self._getExplorer().getStlCategory() in ["File"] \ and "--recall" not in self._arguments: self._guessSearch(self._content) + self._previewResult(False) for cmd in self._cli.input(self._callback): cur_len = len(self._content) From e7d497e554a4743275557cc41acdd796d2783b3a Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 14 Jun 2023 14:03:56 +0800 Subject: [PATCH 067/365] fix typo --- autoload/leaderf/python/leaderf/instance.py | 6 +++--- doc/leaderf.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/autoload/leaderf/python/leaderf/instance.py b/autoload/leaderf/python/leaderf/instance.py index 744fbce0..7cd4de59 100644 --- a/autoload/leaderf/python/leaderf/instance.py +++ b/autoload/leaderf/python/leaderf/instance.py @@ -433,7 +433,7 @@ def _createPopupWindow(self, clear): if lfEval("has('nvim')") == '1': self._win_pos = "floatwin" - if lfEval("get(g:, 'Lf_PopupAutoAjustHeight', 1)") == '1': + if lfEval("get(g:, 'Lf_PopupAutoAdjustHeight', 1)") == '1': floatwin_height = 1 else: floatwin_height = self._popup_maxheight @@ -586,7 +586,7 @@ def getWindow(number): lfCmd("augroup END") else: self._win_pos = "popup" - if lfEval("get(g:, 'Lf_PopupAutoAjustHeight', 1)") == '1': + if lfEval("get(g:, 'Lf_PopupAutoAdjustHeight', 1)") == '1': minheight = 1 else: minheight = self._popup_maxheight @@ -1273,7 +1273,7 @@ def setBuffer(self, content, need_copy=False): self.buffer.options['modifiable'] = False def refreshPopupStatusline(self): - if lfEval("get(g:, 'Lf_PopupAutoAjustHeight', 1)") == '0': + if lfEval("get(g:, 'Lf_PopupAutoAdjustHeight', 1)") == '0': return statusline_win = self._popup_instance.statusline_win diff --git a/doc/leaderf.txt b/doc/leaderf.txt index 80d10ec5..4f5073f2 100644 --- a/doc/leaderf.txt +++ b/doc/leaderf.txt @@ -886,7 +886,7 @@ g:Lf_PopupShowFoldcolumn *g:Lf_PopupShowFoldcolumn* Default value is 1. -g:Lf_PopupAutoAjustHeight *g:Lf_PopupAutoAjustHeight* +g:Lf_PopupAutoAdjustHeight *g:Lf_PopupAutoAdjustHeight* Specifies whether to adjust the height of popup window automatically. Default value is 1. From a18838164299304209c0af2d90eebac4f81aab75 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 14 Jun 2023 14:58:47 +0800 Subject: [PATCH 068/365] fix a bug --- autoload/leaderf/python/leaderf/manager.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 1338d4c1..5afb3919 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -773,7 +773,8 @@ def _useExistingWindow(self, title, source, line_nr, jump_cmd): lfCmd("call win_execute(%d, 'doautocmd filetypedetect BufNewFile %s')" % (self._preview_winid, escQuote(source))) self._preview_filetype = lfEval("getbufvar(winbufnr(%d), '&ft')" % self._preview_winid) else: - lfCmd("noautocmd call leaderf#ResetPopupOptions(%d, 'title', '%s')" % (self._preview_winid, title)) + if lfEval("popup_getoptions(%d).title != ''" % self._preview_winid) == '1': + lfCmd("noautocmd call leaderf#ResetPopupOptions(%d, 'title', '%s')" % (self._preview_winid, title)) if isinstance(source, int): lfCmd("noautocmd call popup_settext(%d, getbufline(%d, 1, '$'))" % (self._preview_winid, source) ) filename = vim.buffers[source].name From 2144e40ac60782ea4ed779834daff3cf89317d66 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 14 Jun 2023 21:44:36 +0800 Subject: [PATCH 069/365] fix issue #1011 --- autoload/leaderf/python/leaderf/cli.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/autoload/leaderf/python/leaderf/cli.py b/autoload/leaderf/python/leaderf/cli.py index 99d0b16b..8b13a307 100644 --- a/autoload/leaderf/python/leaderf/cli.py +++ b/autoload/leaderf/python/leaderf/cli.py @@ -19,12 +19,8 @@ def deco(*args, **kwargs): lfCmd("let g:lf_gcr_stack = []") lfCmd("call add(g:lf_gcr_stack, &gcr)") if lfEval("has('nvim')") == '1': - if lfEval("exists('g:lf_termgcr_stack')") == '0': - lfCmd("let g:lf_termgcr_stack = []") - lfCmd("call add(g:lf_termgcr_stack, &termguicolors)") - lfCmd("set termguicolors") lfCmd("hi Cursor blend=100") - lfCmd("set guicursor+=a:Cursor/lCursor") + lfCmd("set gcr+=a:ver1-Cursor/lCursor") else: lfCmd("set gcr=a:invisible") @@ -44,8 +40,6 @@ def deco(*args, **kwargs): lfCmd("let &gcr = remove(g:lf_gcr_stack, -1)") if lfEval("has('nvim')") == '1': lfCmd("hi Cursor blend=0") - lfCmd("set termguicolors&") - lfCmd("let &termguicolors = remove(g:lf_termgcr_stack, -1)") else: lfCmd("set t_ve&") lfCmd("let &t_ve = remove(g:lf_t_ve_stack, -1)") From dfc01dcb1c3d14d6a1251531b4cc77c293d344d1 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 15 Jun 2023 10:22:08 +0800 Subject: [PATCH 070/365] in bang mode, first line is displayed twice --- autoload/leaderf/python/leaderf/manager.py | 1 + 1 file changed, 1 insertion(+) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 5afb3919..62fef592 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -2330,6 +2330,7 @@ def _previewFirstLine(self, content): content = itertools.chain([first_line], content) self._getInstance().setBuffer([first_line]) self._previewResult(False) + self._getInstance().clearBuffer() except StopIteration: pass From 6a48eca8a65799f7926f11131cd6b14e803720ec Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 15 Jun 2023 11:10:30 +0800 Subject: [PATCH 071/365] no color if preview after previewing a loaded buffer --- autoload/leaderf/Buffer.vim | 7 +++++++ autoload/leaderf/python/leaderf/manager.py | 1 + 2 files changed, 8 insertions(+) diff --git a/autoload/leaderf/Buffer.vim b/autoload/leaderf/Buffer.vim index 04293b9f..b6256654 100644 --- a/autoload/leaderf/Buffer.vim +++ b/autoload/leaderf/Buffer.vim @@ -28,6 +28,13 @@ function! leaderf#Buffer#Maps() nnoremap :exec g:Lf_py "bufExplManager.toggleHelp()" nnoremap d :exec g:Lf_py "bufExplManager.deleteBuffer(1)" nnoremap D :exec g:Lf_py "bufExplManager.deleteBuffer()" + nnoremap p :exec g:Lf_py "bufExplManager._previewResult(True)" + nnoremap j j:exec g:Lf_py "bufExplManager._previewResult(False)" + nnoremap k k:exec g:Lf_py "bufExplManager._previewResult(False)" + nnoremap :exec g:Lf_py "bufExplManager._previewResult(False)" + nnoremap :exec g:Lf_py "bufExplManager._previewResult(False)" + nnoremap :exec g:Lf_py "bufExplManager._previewResult(False)" + nnoremap :exec g:Lf_py "bufExplManager._previewResult(False)" if has("nvim") nnoremap :exec g:Lf_py "bufExplManager._toUpInPopup()" nnoremap :exec g:Lf_py "bufExplManager._toDownInPopup()" diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 62fef592..25d168bd 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -757,6 +757,7 @@ def _useExistingWindow(self, title, source, line_nr, jump_cmd): if isinstance(source, int): lfCmd("noautocmd call nvim_win_set_buf(%d, %d)" % (self._preview_winid, source)) lfCmd("noautocmd call nvim_win_set_option(%d, 'cursorline', v:true)" % self._preview_winid) + self._preview_filetype = '' else: try: lfCmd("let content = readfile('%s', '', 4096)" % escQuote(source)) From 4a574c1051ecac2e056780af9bf49354e471c904 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 15 Jun 2023 13:10:04 +0800 Subject: [PATCH 072/365] remove useless code --- autoload/leaderf/python/leaderf/manager.py | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 25d168bd..06f10f92 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -323,7 +323,6 @@ def _afterExit(self): lfCmd("set laststatus=%s" % self._laststatus) def _bangEnter(self): - self._preview_open = False self._current_mode = 'NORMAL' if self._getInstance().getWinPos() == 'popup': self._cli.hideCursor() @@ -341,9 +340,7 @@ def _bangEnter(self): self._getInstance().appendBuffer(self._result_content[self._initial_count:]) def _bangReadFinished(self): - if self._preview_open == False and self._getInstance().getWinPos() in ('popup', 'floatwin'): - self._previewResult(False) - self._preview_open = True + pass def _getList(self, pairs): """ @@ -2568,11 +2565,6 @@ def _workInIdle(self, content=None, bang=False): else: raise self._read_content_exception[1] - if bang == False and self._preview_open == False and lfEval("get(g:, 'Lf_PreviewInPopup', 0)") == '1' \ - and not self._getInstance().empty(): - self._previewResult(False) - self._preview_open = True - if self._is_content_list: if self._cli.pattern and (self._index < len(self._content) or len(self._cb_content) > 0): if self._fuzzy_engine: @@ -2702,7 +2694,6 @@ def _workInIdle(self, content=None, bang=False): @modifiableController def input(self): - self._preview_open = False self._current_mode = 'INPUT' self._getInstance().hideMimicCursor() if self._getInstance().getWinPos() in ('popup', 'floatwin'): From 452f6d7d2eeaf453ae2fe7e6affe277ba3dd0b3e Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 15 Jun 2023 17:40:52 +0800 Subject: [PATCH 073/365] make AsyncExecutor.Result a python2 iterator class --- autoload/leaderf/python/leaderf/asyncExecutor.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/autoload/leaderf/python/leaderf/asyncExecutor.py b/autoload/leaderf/python/leaderf/asyncExecutor.py index 3442d8f9..cf2c1419 100644 --- a/autoload/leaderf/python/leaderf/asyncExecutor.py +++ b/autoload/leaderf/python/leaderf/asyncExecutor.py @@ -206,6 +206,9 @@ def __iter__(self): def __next__(self): return next(self._g) + # for python2 + def next(self): + return next(self._g) if __name__ == "__main__": executor = AsyncExecutor() From 4c5335184b8c9a707b1651da07413895a8c9bc15 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 15 Jun 2023 22:06:30 +0800 Subject: [PATCH 074/365] move ignoreEvent() to utils.py --- autoload/leaderf/python/leaderf/manager.py | 14 ----------- autoload/leaderf/python/leaderf/utils.py | 28 ++++++++++++++++++++++ 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 06f10f92..d8d5d383 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -80,20 +80,6 @@ def deco(self, *args, **kwargs): self._timer_id = None return deco -def ignoreEvent(events): - def wrapper(func): - @wraps(func) - def deco(self, *args, **kwargs): - try: - saved_eventignore = vim.options['eventignore'] - vim.options['eventignore'] = events - - func(self, *args, **kwargs) - finally: - vim.options['eventignore'] = saved_eventignore - return deco - return wrapper - #***************************************************** # Manager #***************************************************** diff --git a/autoload/leaderf/python/leaderf/utils.py b/autoload/leaderf/python/leaderf/utils.py index ad31556d..f6dc3c30 100644 --- a/autoload/leaderf/python/leaderf/utils.py +++ b/autoload/leaderf/python/leaderf/utils.py @@ -6,11 +6,14 @@ import re import os import os.path +import time import locale import traceback import warnings warnings.filterwarnings("ignore", category=DeprecationWarning) +from functools import wraps + lfCmd = vim.command lfEval = vim.eval @@ -1404,3 +1407,28 @@ def getExtension(path): return "help" return extension_ft.get(ext, None) + +def ignoreEvent(events): + def wrapper(func): + @wraps(func) + def deco(self, *args, **kwargs): + try: + saved_eventignore = vim.options['eventignore'] + vim.options['eventignore'] = events + + func(self, *args, **kwargs) + finally: + vim.options['eventignore'] = saved_eventignore + return deco + return wrapper + +def printTime(func): + @wraps(func) + def deco(self, *args, **kwargs): + try: + start = time.time() + return func(self, *args, **kwargs) + finally: + print(func.__name__, time.time() - start) + + return deco From fc8f161eb278acda29c87d87175278c2939db3c6 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Sat, 17 Jun 2023 10:40:48 +0800 Subject: [PATCH 075/365] let g:Lf_PopupAutoAdjustHeight = 0 if g:Lf_PopupPreviewPosition is "bottom" --- autoload/leaderf/python/leaderf/manager.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index d8d5d383..baff24d5 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -116,6 +116,8 @@ def __init__(self): self._preview_filetype = None if lfEval("has('patch-8.1.1615') || has('nvim-0.4.2')") == '0': lfCmd("let g:Lf_PreviewInPopup = 0") + if lfEval("get(g:, 'Lf_PopupPreviewPosition', 'top')").lower() == 'bottom': + lfCmd("let g:Lf_PopupAutoAdjustHeight = 0") #************************************************************** From 8d494e37f73bfcd113c3b1856025d2555453dcc9 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Mon, 3 Jul 2023 10:40:27 +0800 Subject: [PATCH 076/365] fix issue #1013 --- autoload/leaderf/python/leaderf/manager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index baff24d5..36d98347 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -1658,7 +1658,7 @@ def _fuzzySearch(self, content, is_continue, step): self._highlight_method() if len(self._cli.pattern) > 1 and not is_continue: - lfCmd("redraw") + lfCmd("silent! redraw") def _guessFilter(self, filename, suffix, dirname, icon, iterable): """ From 96fd1910b2a2a9cfa5ad0b3a783bb9c0cbcc0d3d Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Mon, 3 Jul 2023 10:53:07 +0800 Subject: [PATCH 077/365] add '--live', '--no-fixed-strings' for Leaderf rg --- autoload/leaderf/Any.vim | 6 +- autoload/leaderf/Rg.vim | 2 +- autoload/leaderf/colorscheme.vim | 3 +- autoload/leaderf/colorscheme/popup.vim | 3 +- .../leaderf/python/leaderf/asyncExecutor.py | 1 + autoload/leaderf/python/leaderf/cli.py | 15 +- autoload/leaderf/python/leaderf/gtagsExpl.py | 30 +- autoload/leaderf/python/leaderf/instance.py | 2 +- autoload/leaderf/python/leaderf/manager.py | 26 +- autoload/leaderf/python/leaderf/rgExpl.py | 408 +++++++++++++++--- autoload/leaderf/python/leaderf/utils.py | 2 +- 11 files changed, 418 insertions(+), 80 deletions(-) diff --git a/autoload/leaderf/Any.vim b/autoload/leaderf/Any.vim index e50c328a..d1921d21 100644 --- a/autoload/leaderf/Any.vim +++ b/autoload/leaderf/Any.vim @@ -112,7 +112,10 @@ let g:Lf_Arguments = { \ {"name": ["--crlf"], "nargs": 0, "help": "ripgrep will treat CRLF ('\r\n') as a line terminator instead of just '\n'."}, \ {"name": ["-e", "--regexp"], "action": "append", "metavar": "...", \ "help": "A pattern to search for. This option can be provided multiple times, where all patterns given are searched."}, - \ {"name": ["-F", "--fixed-strings"], "nargs": 0, "help": "Treat the pattern as a literal string instead of a regular expression."}, + \ [ + \ {"name": ["-F", "--fixed-strings"], "nargs": 0, "help": "Treat the pattern as a literal string instead of a regular expression."}, + \ {"name": ["--no-fixed-strings"], "nargs": 0, "help": "Treat the pattern as a regular expression."}, + \ ], \ {"name": ["-i", "--ignore-case"], "nargs": 0, "help": "Searches case insensitively."}, \ {"name": ["-L", "--follow"], "nargs": 0, "help": "Follow symbolic links while traversing directories."}, \ {"name": ["-P", "--pcre2"], "nargs": 0, "help": "When this flag is present, rg will use the PCRE2 regex engine instead of its default regex engine."}, @@ -166,6 +169,7 @@ let g:Lf_Arguments = { \ {"name": ["--append"], "nargs": 0, "help": "Append to the previous search results."}, \ {"name": ["--match-path"], "nargs": 0, "help": "Match the file path when fuzzy searching."}, \ {"name": ["--wd-mode"], "nargs": 1, "metavar": "", "help": "Specify the working directory mode, value has the same meaning as g:Lf_WorkingDirectoryMode."}, + \ {"name": ["--live"], "nargs": 0, "help": "Perform the so called live grep. This option implies `-F`"}, \ ], \ "gtags":[ \ [ diff --git a/autoload/leaderf/Rg.vim b/autoload/leaderf/Rg.vim index b98ee408..406d6557 100644 --- a/autoload/leaderf/Rg.vim +++ b/autoload/leaderf/Rg.vim @@ -60,7 +60,7 @@ function! leaderf#Rg#visual() let x_save = getreg("x", 1) let type = getregtype("x") norm! gv"xy - return '"' . escape(@x, '"') . '"' + return '"' . escape(@x, '\"') . '"' finally call setreg("x", x_save, type) endtry diff --git a/autoload/leaderf/colorscheme.vim b/autoload/leaderf/colorscheme.vim index f1056f92..bc33f90d 100644 --- a/autoload/leaderf/colorscheme.vim +++ b/autoload/leaderf/colorscheme.vim @@ -15,7 +15,8 @@ let s:modeMap = { \ 'NameOnly': 'Lf_hl_stlNameOnlyMode', \ 'FullPath': 'Lf_hl_stlFullPathMode', \ 'Fuzzy': 'Lf_hl_stlFuzzyMode', - \ 'Regex': 'Lf_hl_stlRegexMode' + \ 'Regex': 'Lf_hl_stlRegexMode', + \ 'Live': 'Lf_hl_stlFuzzyMode' \ } let s:leftSep = { diff --git a/autoload/leaderf/colorscheme/popup.vim b/autoload/leaderf/colorscheme/popup.vim index 7a7a8c1e..c4052050 100644 --- a/autoload/leaderf/colorscheme/popup.vim +++ b/autoload/leaderf/colorscheme/popup.vim @@ -11,7 +11,8 @@ let s:matchModeMap = { \ 'NameOnly': 'Lf_hl_popup_nameOnlyMode', \ 'FullPath': 'Lf_hl_popup_fullPathMode', \ 'Fuzzy': 'Lf_hl_popup_fuzzyMode', - \ 'Regex': 'Lf_hl_popup_regexMode' + \ 'Regex': 'Lf_hl_popup_regexMode', + \ 'Live': 'Lf_hl_popup_fuzzyMode' \ } let s:leftSep = { diff --git a/autoload/leaderf/python/leaderf/asyncExecutor.py b/autoload/leaderf/python/leaderf/asyncExecutor.py index cf2c1419..c11cd66f 100644 --- a/autoload/leaderf/python/leaderf/asyncExecutor.py +++ b/autoload/leaderf/python/leaderf/asyncExecutor.py @@ -182,6 +182,7 @@ def killProcess(self): except OSError: pass + self._process.poll() self._process = None class Result(object): diff --git a/autoload/leaderf/python/leaderf/cli.py b/autoload/leaderf/python/leaderf/cli.py index 8b13a307..5f4f0f3f 100644 --- a/autoload/leaderf/python/leaderf/cli.py +++ b/autoload/leaderf/python/leaderf/cli.py @@ -68,6 +68,7 @@ def __init__(self): self._running_status = 0 self._input_buf_namespace = None self._setDefaultMode() + self._is_live = False self._additional_prompt_string = '' self._spin_symbols = lfEval("get(g:, 'Lf_SpinSymbols', [])") if not self._spin_symbols: @@ -107,6 +108,9 @@ def setCurrentMode(self, mode): elif mode == 'Fuzzy': # fuzzy mode self._is_fuzzy = True self._is_full_path = False + elif mode == 'Live': # live mode + self._is_fuzzy = False + self._is_live = True else: # regex mode self._is_fuzzy = False @@ -185,6 +189,8 @@ def _buildPopupPrompt(self): prompt = ' >F> {}'.format(self._additional_prompt_string) else: prompt = ' >>> {}'.format(self._additional_prompt_string) + elif self._is_live: + prompt = ' >>> {}'.format(self._additional_prompt_string) else: prompt = ' R>> {}'.format(self._additional_prompt_string) @@ -342,6 +348,8 @@ def _buildPrompt(self): lfCmd("echohl Constant | echon '>F> {}' | echohl NONE".format(self._additional_prompt_string)) else: lfCmd("echohl Constant | echon '>>> {}' | echohl NONE".format(self._additional_prompt_string)) + elif self._is_live: + lfCmd("echohl Constant | echon '>>> {}' | echohl NONE".format(self._additional_prompt_string)) else: lfCmd("echohl Constant | echon 'R>> {}' | echohl NONE".format(self._additional_prompt_string)) @@ -753,9 +761,10 @@ def input(self, callback): self._buildPattern() yield '' elif equal(cmd, ''): - self._is_fuzzy = not self._is_fuzzy - self._buildPattern() - yield '' + if not self._is_live: + self._is_fuzzy = not self._is_fuzzy + self._buildPattern() + yield '' elif equal(cmd, '') or equal(cmd, ''): if not self._pattern and self._refine == False: continue diff --git a/autoload/leaderf/python/leaderf/gtagsExpl.py b/autoload/leaderf/python/leaderf/gtagsExpl.py index c6bb045e..43b94a19 100644 --- a/autoload/leaderf/python/leaderf/gtagsExpl.py +++ b/autoload/leaderf/python/leaderf/gtagsExpl.py @@ -292,8 +292,20 @@ def translateRegex(self, regex, is_perl=False): """ copied from RgExplorer """ + + def replace(text, pattern, repl): + """ + only replace pattern with even number of \ preceding it + """ + result = '' + for s in re.split(r'((?:\\\\)+)', text): + result += re.sub(pattern, repl, s) + + return result + vim_regex = regex + vim_regex = vim_regex.replace(r"\\", "\\") vim_regex = re.sub(r'([%@&])', r'\\\1', vim_regex) # non-greedy pattern @@ -319,12 +331,12 @@ def translateRegex(self, regex, is_perl=False): vim_regex = re.sub(r'\(\?>(.+?)\)', r'(\1)@>', vim_regex) # this won't hurt although they are not the same - vim_regex = vim_regex.replace(r'\A', r'^') - vim_regex = vim_regex.replace(r'\z', r'$') - vim_regex = vim_regex.replace(r'\B', r'') + vim_regex = replace(vim_regex, r'\\A', r'^') + vim_regex = replace(vim_regex, r'\\z', r'$') + vim_regex = replace(vim_regex, r'\\B', r'') # word boundary - vim_regex = re.sub(r'\\b', r'(<|>)', vim_regex) + vim_regex = replace(vim_regex, r'\\b', r'(<|>)') # case-insensitive vim_regex = vim_regex.replace(r'(?i)', r'\c') @@ -339,19 +351,19 @@ def translateRegex(self, regex, is_perl=False): # \a bell (\x07) # \f form feed (\x0C) # \v vertical tab (\x0B) - vim_regex = vim_regex.replace(r'\a', r'%x07') - vim_regex = vim_regex.replace(r'\f', r'%x0C') - vim_regex = vim_regex.replace(r'\v', r'%x0B') + vim_regex = replace(vim_regex, r'\\a', r'%x07') + vim_regex = replace(vim_regex, r'\\f', r'%x0C') + vim_regex = replace(vim_regex, r'\\v', r'%x0B') # \123 octal character code (up to three digits) (when enabled) # \x7F hex character code (exactly two digits) - vim_regex = re.sub(r'\\(x[0-9A-Fa-f][0-9A-Fa-f])', r'%\1', vim_regex) + vim_regex = replace(vim_regex, r'\\(x[0-9A-Fa-f][0-9A-Fa-f])', r'%\1') # \x{10FFFF} any hex character code corresponding to a Unicode code point # \u007F hex character code (exactly four digits) # \u{7F} any hex character code corresponding to a Unicode code point # \U0000007F hex character code (exactly eight digits) # \U{7F} any hex character code corresponding to a Unicode code point - vim_regex = re.sub(r'\\([uU])', r'%\1', vim_regex) + vim_regex = replace(vim_regex, r'\\([uU])', r'%\1') vim_regex = re.sub(r'\[\[:ascii:\]\]', r'[\\x00-\\x7F]', vim_regex) vim_regex = re.sub(r'\[\[:word:\]\]', r'[0-9A-Za-z_]', vim_regex) diff --git a/autoload/leaderf/python/leaderf/instance.py b/autoload/leaderf/python/leaderf/instance.py index 7cd4de59..cd0f813c 100644 --- a/autoload/leaderf/python/leaderf/instance.py +++ b/autoload/leaderf/python/leaderf/instance.py @@ -281,7 +281,7 @@ def _initStlVar(self): stl += "%#Lf_hl_stlCwd# %<%{{g:Lf_{0}_StlCwd}} " stl += "%#Lf_hl_{0}_stlSeparator3#%{{g:Lf_StlSeparator.left}}" stl += "%#Lf_hl_{0}_stlBlank#%=" - stl += "%#Lf_hl_stlSpin#%{{g:Lf_{0}_StlRunning}}" + stl += "%#Lf_hl_stlSpin#%{{g:Lf_{0}_StlRunning}} " stl += "%#Lf_hl_{0}_stlSeparator4#%{{g:Lf_StlSeparator.right}}" if self._reverse_order: stl += "%#Lf_hl_stlLineInfo# %{{g:Lf_{0}_StlLineNumber}}/%{{g:Lf_{0}_StlResultsCount}} " diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 36d98347..c60a1880 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -212,10 +212,12 @@ def _setStlMode(self, **kwargs): mode = 'NameOnly' else: mode = 'Fuzzy' + elif self._cli._is_live: + mode = 'Fuzzy' else: mode = 'Regex' - modes = {"--nameOnly", "--fullPath", "--fuzzy", "--regexMode"} + modes = {"--live", "--nameOnly", "--fullPath", "--fuzzy", "--regexMode"} for opt in kwargs.get("arguments", {}): if opt in modes: if opt == "--regexMode": @@ -231,7 +233,9 @@ def _setStlMode(self, **kwargs): else: mode = 'NameOnly' elif opt in ("--nameOnly", "--fullPath", "--fuzzy"): - mode = 'Fuzzy' + mode = 'Fuzzy' + elif opt == "--live": + mode = 'Live' break @@ -795,17 +799,18 @@ def _createPopupPreview(self, title, source, line_nr, jump_cmd=''): if the type is int, it is a buffer number if the type is str, it is a file name + return False if use existing window, otherwise True """ self._is_previewed = True line_nr = int(line_nr) if self._preview_winid > 0 and int(lfEval("winbufnr(%d)" % self._preview_winid)) != -1: self._useExistingWindow(title, source, line_nr, jump_cmd) - return + return False if self._getInstance().getWinPos() in ('popup', 'floatwin'): self._createPopupModePreview(title, source, line_nr, jump_cmd) - return + return True if lfEval("has('nvim')") == '1': width = int(lfEval("get(g:, 'Lf_PreviewPopupWidth', 0)")) @@ -825,7 +830,7 @@ def _createPopupPreview(self, title, source, line_nr, jump_cmd=''): lfCmd("let content = readfile('%s', '', 4096)" % escQuote(source)) except vim.error as e: lfPrintError(e) - return + return False buffer_len = int(lfEval("len(content)")) lfCmd("noautocmd let g:Lf_preview_scratch_buffer = nvim_create_buf(0, 1)") lfCmd("noautocmd call setbufline(g:Lf_preview_scratch_buffer, 1, content)") @@ -936,7 +941,7 @@ def _createPopupPreview(self, title, source, line_nr, jump_cmd=''): lfCmd("let content = readfile('%s', '', 4096)" % escQuote(source)) except vim.error as e: lfPrintError(e) - return + return False lfCmd("silent! let winid = popup_create(content, %s)" % json.dumps(options)) lfCmd("call win_execute(winid, 'setlocal nomodeline')") @@ -956,6 +961,8 @@ def _createPopupPreview(self, title, source, line_nr, jump_cmd=''): if lfEval("exists('+cursorlineopt')") == '1': lfCmd("call win_execute(%d, 'setlocal cursorlineopt=both')" % self._preview_winid) + return True + def _needPreview(self, preview): """ Args: @@ -2372,7 +2379,7 @@ def startExplorer(self, win_pos, *args, **kwargs): return self._index = 0 - pattern = kwargs.get("pattern", "") or arguments_dict.get("--input", [""])[0] + pattern = arguments_dict.get("--input", [""])[0] if len(pattern) > 1 and (pattern[0] == '"' and pattern[-1] == '"' or pattern[0] == "'" and pattern[-1] == "'"): pattern = pattern[1:-1] @@ -2702,7 +2709,8 @@ def input(self): self._hideHelp() self._resetHighlights() - if self._cli.pattern: # --input xxx or from normal mode to input mode + # --input xxx or from normal mode to input mode + if self._cli.pattern and "--live" not in self._arguments: if self._index == 0: # --input xxx self._search(self._content) elif self._empty_query and self._getExplorer().getStlCategory() in ["File"] \ @@ -2735,7 +2743,7 @@ def input(self): else: self._gotoFirstLine() self._index = 0 # search from beginning - if self._cli.pattern: + if self._cli.pattern and "--live" not in self._arguments: self._search(cur_content) elif equal(cmd, ''): self._toUp() diff --git a/autoload/leaderf/python/leaderf/rgExpl.py b/autoload/leaderf/python/leaderf/rgExpl.py index 745ebceb..aa04224d 100644 --- a/autoload/leaderf/python/leaderf/rgExpl.py +++ b/autoload/leaderf/python/leaderf/rgExpl.py @@ -51,6 +51,10 @@ def getContent(self, *args, **kwargs): return [] self._cmd_work_dir = lfGetCwd() + + if "--live" in arguments_dict and "pattern" not in kwargs: + return AsyncExecutor.Result(iter([])) + rg_config = lfEval("get(g:, 'Lf_RgConfig', [])") extra_options = ' '.join(rg_config) for opt in rg_config: @@ -96,6 +100,8 @@ def getContent(self, *args, **kwargs): zero_args_options = '' if "-F" in arguments_dict: zero_args_options += "-F " + if "--no-fixed-strings" in arguments_dict: + zero_args_options += "--no-fixed-strings " if "-L" in arguments_dict: zero_args_options += "-L " if "-P" in arguments_dict: @@ -183,20 +189,30 @@ def getContent(self, *args, **kwargs): repeatable_options += "-T %s " % " -T ".join(arguments_dict["-T"]) is_literal = "-F" in arguments_dict - pattern = '' + if "--append" not in arguments_dict: self._pattern_regex = [] path_list = arguments_dict.get("PATH", []) path = ' '.join(path_list) - pattern_list = arguments_dict.get("-e", []) + if "--live" in arguments_dict: + pattern_list = [kwargs["pattern"]] + no_error_message = " 2>/dev/null" + # --live implies -F + if "-F" not in arguments_dict and "--no-fixed-strings" not in arguments_dict: + zero_args_options += "-F " + is_literal = True + else: + pattern_list = arguments_dict.get("-e", []) + no_error_message = "" + + pattern = '' for i in pattern_list or path_list[:1]: if len(pattern_list) == 0: # treat the first PATH as pattern path = ' '.join(path_list[1:]) - pattern += r'-e %s ' % i if case_flag == '-i': case_pattern = r'\c' elif case_flag == '-s': @@ -207,21 +223,22 @@ def getContent(self, *args, **kwargs): else: case_pattern = r'\C' - if len(i) > 1 and (i[0] == i[-1] == '"' or i[0] == i[-1] == "'"): - p = i[1:-1] + if "--live" in arguments_dict: + p = i.replace('\\', r'\\').replace('"', r'\"') + pattern += r'-e "%s" ' % p else: - p = i + if len(i) > 1 and (i[0] == i[-1] == '"' or i[0] == i[-1] == "'"): + p = i[1:-1] + else: + p = i - # -e "" - if p == '': - continue + # -e "" + if p == '': + continue - if is_literal: - if len(i) > 1 and i[0] == i[-1] == '"': - p = re.sub(r'\\(?!")', r'\\\\', p) - else: - p = p.replace('\\', r'\\') + pattern += r'-e "%s" ' % p + if is_literal: if word_or_line == '-w ': p = r'\<' + p + r'\>' @@ -310,15 +327,27 @@ def removeFiles(names): heading = "--no-heading" cmd = '''{} {} --no-config --no-ignore-messages {} --with-filename --color never --line-number '''\ - '''{} {}{}{}{}{}{}'''.format(self._rg, extra_options, heading, case_flag, word_or_line, zero_args_options, - one_args_options, repeatable_options, lfDecode(pattern), path) + '''{} {}{}{}{}{}{}{}'''.format(self._rg, extra_options, heading, case_flag, word_or_line, zero_args_options, + one_args_options, repeatable_options, lfDecode(pattern), path, no_error_message) lfCmd("let g:Lf_Debug_RgCmd = '%s'" % escQuote(cmd)) content = executor.execute(cmd, encoding=lfEval("&encoding"), cleanup=partial(removeFiles, tmpfilenames)) return content def translateRegex(self, regex, is_perl=False): + + def replace(text, pattern, repl): + """ + only replace pattern with even number of \ preceding it + """ + result = '' + for s in re.split(r'((?:\\\\)+)', text): + result += re.sub(pattern, repl, s) + + return result + vim_regex = regex + vim_regex = vim_regex.replace(r"\\", "\\") vim_regex = re.sub(r'([%@&])', r'\\\1', vim_regex) # non-greedy pattern @@ -344,12 +373,12 @@ def translateRegex(self, regex, is_perl=False): vim_regex = re.sub(r'\(\?>(.+?)\)', r'(\1)@>', vim_regex) # this won't hurt although they are not the same - vim_regex = vim_regex.replace(r'\A', r'^') - vim_regex = vim_regex.replace(r'\z', r'$') - vim_regex = vim_regex.replace(r'\B', r'') + vim_regex = replace(vim_regex, r'\\A', r'^') + vim_regex = replace(vim_regex, r'\\z', r'$') + vim_regex = replace(vim_regex, r'\\B', r'') # word boundary - vim_regex = re.sub(r'\\b', r'(<|>)', vim_regex) + vim_regex = replace(vim_regex, r'\\b', r'(<|>)') # case-insensitive vim_regex = vim_regex.replace(r'(?i)', r'\c') @@ -364,19 +393,19 @@ def translateRegex(self, regex, is_perl=False): # \a bell (\x07) # \f form feed (\x0C) # \v vertical tab (\x0B) - vim_regex = vim_regex.replace(r'\a', r'%x07') - vim_regex = vim_regex.replace(r'\f', r'%x0C') - vim_regex = vim_regex.replace(r'\v', r'%x0B') + vim_regex = replace(vim_regex, r'\\a', r'%x07') + vim_regex = replace(vim_regex, r'\\f', r'%x0C') + vim_regex = replace(vim_regex, r'\\v', r'%x0B') # \123 octal character code (up to three digits) (when enabled) # \x7F hex character code (exactly two digits) - vim_regex = re.sub(r'\\(x[0-9A-Fa-f][0-9A-Fa-f])', r'%\1', vim_regex) + vim_regex = replace(vim_regex, r'\\(x[0-9A-Fa-f][0-9A-Fa-f])', r'%\1') # \x{10FFFF} any hex character code corresponding to a Unicode code point # \u007F hex character code (exactly four digits) # \u{7F} any hex character code corresponding to a Unicode code point # \U0000007F hex character code (exactly eight digits) # \U{7F} any hex character code corresponding to a Unicode code point - vim_regex = re.sub(r'\\([uU])', r'%\1', vim_regex) + vim_regex = replace(vim_regex, r'\\([uU])', r'%\1') vim_regex = re.sub(r'\[\[:ascii:\]\]', r'[\\x00-\\x7F]', vim_regex) vim_regex = re.sub(r'\[\[:word:\]\]', r'[0-9A-Za-z_]', vim_regex) @@ -432,6 +461,9 @@ def __init__(self): self._has_column = False self._orig_buffer = [] self._buf_number_dict = {} + self._pattern_changed = False + self._pattern_match_ids = [] + self._preview_match_ids = [] def _getExplClass(self): return RgExplorer @@ -718,10 +750,16 @@ def _afterEnter(self): if "--multiline-dotall" in self._arguments: i = i.replace('.', r'\_.') - lfCmd("""call win_execute(%d, "let matchid = matchadd('Lf_hl_rgHighlight', '%s', 9)")""" - % (self._getInstance().getPopupWinId(), re.sub(r'\\(?!")', r'\\\\', escQuote(i)))) - id = int(lfEval("matchid")) - self._match_ids.append(id) + if "--live" in self._arguments: + lfCmd("""call win_execute(%d, "let matchid = matchadd('Lf_hl_match', '%s', 9)")""" + % (self._getInstance().getPopupWinId(), re.sub(r'\\(?!")', r'\\\\', escQuote(i)))) + id = int(lfEval("matchid")) + self._pattern_match_ids.append(id) + else: + lfCmd("""call win_execute(%d, "let matchid = matchadd('Lf_hl_rgHighlight', '%s', 9)")""" + % (self._getInstance().getPopupWinId(), re.sub(r'\\(?!")', r'\\\\', escQuote(i)))) + id = int(lfEval("matchid")) + self._match_ids.append(id) except vim.error: pass else: @@ -764,8 +802,12 @@ def _afterEnter(self): if "--multiline-dotall" in self._arguments: i = i.replace('.', r'\_.') - id = int(lfEval("matchadd('Lf_hl_rgHighlight', '%s', 9)" % escQuote(i))) - self._match_ids.append(id) + if "--live" in self._arguments: + id = int(lfEval("matchadd('Lf_hl_match', '%s', 9)" % escQuote(i))) + self._pattern_match_ids.append(id) + else: + id = int(lfEval("matchadd('Lf_hl_rgHighlight', '%s', 9)" % escQuote(i))) + self._match_ids.append(id) except vim.error: pass @@ -779,6 +821,16 @@ def _beforeExit(self): k.options["cursorline"] = v self._cursorline_dict.clear() + if self._getInstance().getWinPos() == 'popup': + for i in self._pattern_match_ids: + lfCmd("silent! call matchdelete(%d, %d)" % (i, self._getInstance().getPopupWinId())) + else: + for i in self._pattern_match_ids: + lfCmd("silent! call matchdelete(%d)" % i) + self._pattern_match_ids = [] + + self._clearPreviewHighlights() + reg = lfEval("get(g:, 'Lf_RgStorePattern', '')") if reg == '': return @@ -811,8 +863,152 @@ def _bangEnter(self): else: instance.window.options["cursorline"] = True + def _highlightMatch(self): + if self._getInstance().getWinPos() == 'popup': + # clear the highlight first + for i in self._pattern_match_ids: + lfCmd("silent! call matchdelete(%d, %d)" % (i, self._getInstance().getPopupWinId())) + + self._pattern_match_ids = [] + + try: + for i in self._getExplorer().getPatternRegex(): + if "-U" in self._arguments: + if self._has_column: + i = i.replace(r'\n', r'\n.{-}\d+:\d+:') + else: + i = i.replace(r'\n', r'\n.{-}\d+:') + if "--multiline-dotall" in self._arguments: + i = i.replace('.', r'\_.') + + lfCmd("""call win_execute(%d, "let matchid = matchadd('Lf_hl_match', '%s', 9)")""" + % (self._getInstance().getPopupWinId(), re.sub(r'\\(?!")', r'\\\\', escQuote(i)))) + id = int(lfEval("matchid")) + self._pattern_match_ids.append(id) + except vim.error: + pass + else: + # clear the highlight first + for i in self._pattern_match_ids: + lfCmd("silent! call matchdelete(%d)" % i) + + self._pattern_match_ids = [] + + try: + for i in self._getExplorer().getPatternRegex(): + if "-U" in self._arguments: + if self._has_column: + i = i.replace(r'\n', r'\n.{-}\d+:\d+:') + else: + i = i.replace(r'\n', r'\n.{-}\d+:') + if "--multiline-dotall" in self._arguments: + i = i.replace('.', r'\_.') + + id = int(lfEval("matchadd('Lf_hl_match', '%s', 9)" % escQuote(i))) + self._pattern_match_ids.append(id) + except vim.error: + pass + + def startLiveGrep(self, win_pos, *args, **kwargs): + arguments_dict = kwargs.get("arguments", {}) + if "--recall" in arguments_dict: + self._arguments.update(arguments_dict) + elif "--previous" in arguments_dict: + self._arguments["--previous"] = arguments_dict["--previous"] + elif "--next" in arguments_dict: + self._arguments["--next"] = arguments_dict["--next"] + else: + self.setArguments(arguments_dict) + self._cli.setArguments(arguments_dict) + self._cli.setNameOnlyFeature(self._getExplorer().supportsNameOnly()) + self._cli.setRefineFeature(self._supportsRefine()) + self._orig_line = None + + if "--next" in arguments_dict: + if self._jumpNext() == False: + lfCmd("echohl Error | redraw | echo 'Error, no content!' | echohl NONE") + return + elif "--previous" in arguments_dict: + if self._jumpPrevious() == False: + lfCmd("echohl Error | redraw | echo 'Error, no content!' | echohl NONE") + return + + self._cleanup() + + # lfCmd("echohl WarningMsg | redraw | echo ' searching ...' | echohl NONE") + self._getInstance().setArguments(self._arguments) + + self._getInstance().setCwd(lfGetCwd()) + + pattern = arguments_dict.get("--input", [""])[0] + if len(pattern) > 1 and (pattern[0] == '"' and pattern[-1] == '"' + or pattern[0] == "'" and pattern[-1] == "'"): + pattern = pattern[1:-1] + + self._cli.setPattern(pattern) + + if pattern: + content = self._getExplorer().getContent(*args, **kwargs, pattern=self._cli.pattern) + else: + content = self._getExplorer().getContent(*args, **kwargs) + + # clear the buffer only when the content is not a list + self._getInstance().enterBuffer(win_pos, not isinstance(content, list)) + self._initial_count = self._getInstance().getInitialWinHeight() + + self._getInstance().setStlCategory(self._getExplorer().getStlCategory()) + self._setStlMode(**kwargs) + self._getInstance().setStlCwd(self._getExplorer().getStlCurDir()) + + if kwargs.get('bang', 0): + self._current_mode = 'NORMAL' + else: + self._current_mode = 'INPUT' + lfCmd("call leaderf#colorscheme#popup#hiMode('%s', '%s')" + % (self._getExplorer().getStlCategory(), self._current_mode)) + + self._getInstance().setPopupStl(self._current_mode) + self._getInstance().setStlResultsCount(0) + self._getInstance().setStlTotal(0) + self._getInstance().setStlRunning(False) + + self._start_time = time.time() + self._bang_start_time = self._start_time + self._bang_count = 0 + + self._getInstance().buffer.vars['Lf_category'] = self._getExplorer().getStlCategory() + + self._read_content_exception = None + + self._callback = self._writeBuffer + if lfEval("get(g:, 'Lf_NoAsync', 0)") == '1': + self._content = self._getInstance().initBuffer(content, self._getUnit(), self._getExplorer().setContent) + self._previewResult(False) + self._read_finished = 1 + self._offset_in_content = 0 + else: + self._getInstance().clearBuffer() + self._content = [] + self._offset_in_content = 0 + + self._read_finished = 0 + + self._stop_reader_thread = False + content = self._previewFirstLine(content) + self._reader_thread = threading.Thread(target=self._readContent, args=(content,)) + self._reader_thread.daemon = True + self._reader_thread.start() + + self.input() + def startExplorer(self, win_pos, *args, **kwargs): arguments_dict = kwargs.get("arguments", {}) + if "--live" in arguments_dict: + for arg in ("--nameOnly", "--fullPath", "--fuzzy", "--regexMode"): + if arg in arguments_dict: + lfPrintError("error: argument --live: not allowed with argument %s" % arg) + return + if "--heading" in arguments_dict: kwargs["bang"] = 1 @@ -865,7 +1061,10 @@ def startExplorer(self, win_pos, *args, **kwargs): if cur_buf_name and not os.path.dirname(cur_buf_name).startswith(self._orig_cwd): chdir(os.path.dirname(cur_buf_name)) - super(RgExplManager, self).startExplorer(win_pos, *args, **kwargs) + if "--live" in arguments_dict: + self.startLiveGrep(win_pos, *args, **kwargs) + else: + super(RgExplManager, self).startExplorer(win_pos, *args, **kwargs) def deleteCurrentLine(self): instance = self._getInstance() @@ -893,6 +1092,50 @@ def deleteCurrentLine(self): self._previewResult(False) + def _clearPreviewHighlights(self): + for i in self._preview_match_ids: + lfCmd("silent! call matchdelete(%d, %d)" % (i, self._preview_winid)) + + def _highlightInPreview(self): + if lfEval("has('nvim')") != '1': + try: + for i in self._getExplorer().getPatternRegex(): + lfCmd("""call win_execute(%d, "let matchid = matchadd('Lf_hl_rgHighlight', '%s', 9)")""" + % (self._preview_winid, re.sub(r'\\(?!")', r'\\\\', escQuote(i)))) + id = int(lfEval("matchid")) + self._preview_match_ids.append(id) + except vim.error: + pass + else: + cur_winid = lfEval("win_getid()") + lfCmd("noautocmd call win_gotoid(%d)" % self._preview_winid) + if lfEval("win_getid()") != cur_winid: + try: + for i in self._getExplorer().getPatternRegex(): + id = int(lfEval("matchadd('Lf_hl_rgHighlight', '%s', 9)" % escQuote(i))) + self._preview_match_ids.append(id) + except vim.error: + pass + lfCmd("noautocmd call win_gotoid(%s)" % cur_winid) + + def _createPopupPreview(self, title, source, line_nr, jump_cmd=''): + """ + Args: + source: + if the type is int, it is a buffer number + if the type is str, it is a file name + + return False if use existing window, otherwise True + """ + + if (super(RgExplManager, self)._createPopupPreview(title, source, line_nr, jump_cmd) + and lfEval("get(g:, 'Lf_RgHighlightInPreview', 1)") == '1'): + + self._highlightInPreview() + return True + + return False + def _previewInPopup(self, *args, **kwargs): if len(args) == 0: return @@ -915,27 +1158,6 @@ def _previewInPopup(self, *args, **kwargs): self._createPopupPreview("", source, line_num) - if lfEval("get(g:, 'Lf_RgHighlightInPreview', 1)") == '1': - if lfEval("has('nvim')") != '1': - try: - for i in self._getExplorer().getPatternRegex(): - lfCmd("""call win_execute(%d, "let matchid = matchadd('Lf_hl_rgHighlight', '%s', 9)")""" - % (self._preview_winid, re.sub(r'\\(?!")', r'\\\\', escQuote(i)))) - id = int(lfEval("matchid")) - self._match_ids.append(id) - except vim.error: - pass - else: - cur_winid = lfEval("win_getid()") - lfCmd("noautocmd call win_gotoid(%d)" % self._preview_winid) - try: - for i in self._getExplorer().getPatternRegex(): - id = int(lfEval("matchadd('Lf_hl_rgHighlight', '%s', 9)" % escQuote(i))) - self._match_ids.append(id) - except vim.error: - pass - lfCmd("noautocmd call win_gotoid(%s)" % cur_winid) - def outputToQflist(self, *args, **kwargs): items = self._getFormatedContents() lfCmd("call setqflist(%s, 'r')" % json.dumps(items, ensure_ascii=False)) @@ -1200,6 +1422,86 @@ def quit(self): lfCmd("silent! autocmd! Lf_Rg_ReplaceMode") + def _writeBuffer(self): + if not self._cli.pattern: # e.g., when or is typed + return + + if self._read_content_exception is not None: + raise self._read_content_exception[1] + + if self._read_finished > 0: + if self._read_finished == 1: + self._read_finished += 1 + self._getExplorer().setContent(self._content) + self._getInstance().setStlTotal(len(self._content)//self._getUnit()) + self._getInstance().setStlRunning(False) + + self._getInstance().setBuffer(self._content[:self._initial_count]) + self._previewResult(False) + + self._getInstance().setStlResultsCount(len(self._content)) + + if self._getInstance().getWinPos() not in ('popup', 'floatwin'): + lfCmd("redrawstatus") + else: + cur_len = len(self._content) + if time.time() - self._start_time > 0.1: + self._start_time = time.time() + self._getInstance().setStlTotal(cur_len//self._getUnit()) + self._getInstance().setStlRunning(True) + self._getInstance().setStlResultsCount(cur_len) + + if self._getInstance().getWinPos() not in ('popup', 'floatwin'): + lfCmd("redrawstatus") + + if self._pattern_changed or len(self._getInstance().buffer) < min(cur_len, self._initial_count): + self._pattern_changed = False + self._getInstance().setBuffer(self._content[:self._initial_count]) + if not self._getInstance().empty(): + self._previewResult(False) + + def _killThread(self, executors): + for exe in executors: + exe.killProcess() + + def _search(self, content, is_continue=False, step=0): + if "--live" not in self._arguments: + super(RgExplManager, self)._search(content, is_continue, step) + return + + if self._reader_thread and self._reader_thread.is_alive(): + self._stop_reader_thread = True + self._reader_thread.join() + + # kill process in a thread + kill_thread = threading.Thread(target=self._killThread, args=(self._getExplorer()._executor,)) + self._getExplorer()._executor = [] + kill_thread.daemon = True + kill_thread.start() + + if not self._cli.pattern: # e.g., when or is typed + self._getInstance().clearBuffer() + self._content = [] + self._getInstance().setStlResultsCount(0) + self._getInstance().setStlTotal(len(self._content)//self._getUnit()) + self._getInstance().setStlRunning(False) + self._previewResult(False) + return + + self._clearPreviewHighlights() + self._stop_reader_thread = False + self._read_finished = 0 + self._content = [] + self._pattern_changed = True + content = self._getExplorer().getContent(arguments=self._arguments, pattern=self._cli.pattern) + self._reader_thread = threading.Thread(target=self._readContent, args=(content,)) + self._reader_thread.daemon = True + self._reader_thread.start() + + self._highlightMatch() + self._highlightInPreview() + + #***************************************************** # rgExplManager is a singleton #***************************************************** diff --git a/autoload/leaderf/python/leaderf/utils.py b/autoload/leaderf/python/leaderf/utils.py index f6dc3c30..b6b9bdc0 100644 --- a/autoload/leaderf/python/leaderf/utils.py +++ b/autoload/leaderf/python/leaderf/utils.py @@ -1416,7 +1416,7 @@ def deco(self, *args, **kwargs): saved_eventignore = vim.options['eventignore'] vim.options['eventignore'] = events - func(self, *args, **kwargs) + return func(self, *args, **kwargs) finally: vim.options['eventignore'] = saved_eventignore return deco From 6f159ae9bcfb8e2abdf516698795277d8ce13bf0 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Mon, 3 Jul 2023 11:12:50 +0800 Subject: [PATCH 078/365] fix issue #1012 add `--no-auto-preview` and update the doc --- README.md | 4 +++- autoload/leaderf/Any.vim | 5 ++++- autoload/leaderf/python/leaderf/manager.py | 3 +++ doc/leaderf.txt | 20 ++++++++++++-------- 4 files changed, 22 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 2318d2e5..48680e13 100644 --- a/README.md +++ b/README.md @@ -75,7 +75,8 @@ Usage usage: Leaderf[!] [-h] [--reverse] [--stayOpen] [--input | --cword] [--top | --bottom | --left | --right | --belowright | --aboveleft | --fullScreen | --popup] [--nameOnly | --fullPath | --fuzzy | --regexMode] [--nowrap] [--next | --previous] - [--recall] [--popup-height ] [--popup-width ] + [--recall] [--popup-height ] [--popup-width ] [--no-sort] + [--case-insensitive] [--auto-preview | --no-auto-preview] {file,tag,function,mru,searchHistory,cmdHistory,help,line,colorscheme,gtags, self,bufTag,buffer,rg,filetype,command,window,quickfix,loclist,jumps} @@ -110,6 +111,7 @@ optional arguments: --no-sort do not sort the result. --case-insensitive fuzzy search case insensitively. --auto-preview open preview window automatically. + --no-auto-preview don't open preview window automatically. subcommands: diff --git a/autoload/leaderf/Any.vim b/autoload/leaderf/Any.vim index d1921d21..458e629a 100644 --- a/autoload/leaderf/Any.vim +++ b/autoload/leaderf/Any.vim @@ -247,7 +247,10 @@ let g:Lf_CommonArguments = [ \ {"name": ["--popup-width"], "nargs": 1, "help": "specifies the width of popup window, only available in popup mode."}, \ {"name": ["--no-sort"], "nargs": 0, "help": "do not sort the result."}, \ {"name": ["--case-insensitive"], "nargs": 0, "help": "fuzzy search case insensitively."}, - \ {"name": ["--auto-preview"], "nargs": 0, "help": "open preview window automatically."}, + \ [ + \ {"name": ["--auto-preview"], "nargs": 0, "help": "open preview window automatically."}, + \ {"name": ["--no-auto-preview"], "nargs": 0, "help": "don't open preview window automatically."}, + \ ], \] " arguments is something like g:Lf_CommonArguments diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index c60a1880..478eaca8 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -985,6 +985,9 @@ def _needPreview(self, preview): if "--auto-preview" in self._arguments: return True + if "--no-auto-preview" in self._arguments: + return False + preview_dict = {k.lower(): v for k, v in lfEval("g:Lf_PreviewResult").items()} category = self._getExplorer().getStlCategory() if int(preview_dict.get(category.lower(), 0)) == 0: diff --git a/doc/leaderf.txt b/doc/leaderf.txt index 4f5073f2..5dbe627c 100644 --- a/doc/leaderf.txt +++ b/doc/leaderf.txt @@ -416,21 +416,25 @@ g:Lf_PreviewResult *g:Lf_PreviewResult* This is a dictionary, indicates whether to enable the preview of the result. Default value is: > let g:Lf_PreviewResult = { - \ 'File': 0, - \ 'Buffer': 0, - \ 'Mru': 0, - \ 'Tag': 0, + \ 'File': 1, + \ 'Buffer': 1, + \ 'Mru': 1, + \ 'Tag': 1, \ 'BufTag': 1, \ 'Function': 1, - \ 'Line': 0, - \ 'Colorscheme': 0, - \ 'Rg': 0, - \ 'Gtags': 0 + \ 'Line': 1, + \ 'Colorscheme': 1, + \ 'Rg': 1, + \ 'Gtags': 1 \} < e.g., if you want to disable the preview of BufTag explorer: > let g:Lf_PreviewResult = { 'BufTag': 0 } < + You can also specify `--auto-preview` or `--no-auto-preview` for the specific + command to override this option. + e.g., `Leaderf file --no-auto-preview` + g:Lf_RememberLastSearch *g:Lf_RememberLastSearch* This option specifies whether to remember the last search. If the value is 1, the search string you typed during last search is still there when From 4457231b3dc8fa1ddbcae19a04c0dcf378536fe2 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Mon, 3 Jul 2023 16:52:25 +0800 Subject: [PATCH 079/365] let --recall work well with --live --- autoload/leaderf/python/leaderf/manager.py | 13 +++++---- autoload/leaderf/python/leaderf/rgExpl.py | 33 +++++++++++++--------- 2 files changed, 27 insertions(+), 19 deletions(-) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 478eaca8..f850f7f8 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -203,7 +203,7 @@ def _getDigestStartPos(self, line, mode): def _createHelp(self): return [] - def _setStlMode(self, **kwargs): + def _setStlMode(self, the_mode=None, **kwargs): if self._cli.isFuzzy: if self._getExplorer().supportsNameOnly(): if self._cli.isFullPath: @@ -212,12 +212,10 @@ def _setStlMode(self, **kwargs): mode = 'NameOnly' else: mode = 'Fuzzy' - elif self._cli._is_live: - mode = 'Fuzzy' else: mode = 'Regex' - modes = {"--live", "--nameOnly", "--fullPath", "--fuzzy", "--regexMode"} + modes = {"--nameOnly", "--fullPath", "--fuzzy", "--regexMode"} for opt in kwargs.get("arguments", {}): if opt in modes: if opt == "--regexMode": @@ -234,11 +232,12 @@ def _setStlMode(self, **kwargs): mode = 'NameOnly' elif opt in ("--nameOnly", "--fullPath", "--fuzzy"): mode = 'Fuzzy' - elif opt == "--live": - mode = 'Live' break + if the_mode is not None: + mode = the_mode + self._getInstance().setStlMode(mode) self._cli.setCurrentMode(mode) @@ -2436,6 +2435,8 @@ def startExplorer(self, win_pos, *args, **kwargs): if not empty_query: self._getInstance().setBuffer(self._content[:self._initial_count]) self._previewResult(False) + else: + self._previewResult(False) if lfEval("has('nvim')") == '1': lfCmd("redrawstatus") diff --git a/autoload/leaderf/python/leaderf/rgExpl.py b/autoload/leaderf/python/leaderf/rgExpl.py index aa04224d..99d20e37 100644 --- a/autoload/leaderf/python/leaderf/rgExpl.py +++ b/autoload/leaderf/python/leaderf/rgExpl.py @@ -47,7 +47,7 @@ def __init__(self): def getContent(self, *args, **kwargs): arguments_dict = kwargs.get("arguments", {}) - if "--recall" in arguments_dict: + if "--recall" in arguments_dict and "--live" not in arguments_dict: return [] self._cmd_work_dir = lfGetCwd() @@ -938,26 +938,33 @@ def startLiveGrep(self, win_pos, *args, **kwargs): # lfCmd("echohl WarningMsg | redraw | echo ' searching ...' | echohl NONE") self._getInstance().setArguments(self._arguments) - self._getInstance().setCwd(lfGetCwd()) + remember_last_status = "--recall" in self._arguments \ + or lfEval("g:Lf_RememberLastSearch") == '1' and self._cli.pattern + if remember_last_status: + content = iter(self._content) + self._getInstance().useLastReverseOrder() + win_pos = self._getInstance().getWinPos() + else: + self._getInstance().setCwd(lfGetCwd()) - pattern = arguments_dict.get("--input", [""])[0] - if len(pattern) > 1 and (pattern[0] == '"' and pattern[-1] == '"' - or pattern[0] == "'" and pattern[-1] == "'"): - pattern = pattern[1:-1] + pattern = arguments_dict.get("--input", [""])[0] + if len(pattern) > 1 and (pattern[0] == '"' and pattern[-1] == '"' + or pattern[0] == "'" and pattern[-1] == "'"): + pattern = pattern[1:-1] - self._cli.setPattern(pattern) + self._cli.setPattern(pattern) - if pattern: - content = self._getExplorer().getContent(*args, **kwargs, pattern=self._cli.pattern) - else: - content = self._getExplorer().getContent(*args, **kwargs) + if pattern: + content = self._getExplorer().getContent(*args, **kwargs, pattern=self._cli.pattern) + else: + content = self._getExplorer().getContent(*args, **kwargs) # clear the buffer only when the content is not a list self._getInstance().enterBuffer(win_pos, not isinstance(content, list)) self._initial_count = self._getInstance().getInitialWinHeight() self._getInstance().setStlCategory(self._getExplorer().getStlCategory()) - self._setStlMode(**kwargs) + self._setStlMode(the_mode="Live", **kwargs) self._getInstance().setStlCwd(self._getExplorer().getStlCurDir()) if kwargs.get('bang', 0): @@ -1061,7 +1068,7 @@ def startExplorer(self, win_pos, *args, **kwargs): if cur_buf_name and not os.path.dirname(cur_buf_name).startswith(self._orig_cwd): chdir(os.path.dirname(cur_buf_name)) - if "--live" in arguments_dict: + if "--live" in arguments_dict or ("--recall" in arguments_dict and "--live" in self._arguments): self.startLiveGrep(win_pos, *args, **kwargs) else: super(RgExplManager, self).startExplorer(win_pos, *args, **kwargs) From 5ac6e1f03a68c717eb6d8d90190e9701dd85a418 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Tue, 4 Jul 2023 15:46:44 +0800 Subject: [PATCH 080/365] update line number when move in normal mode (nvim) --- autoload/leaderf/Any.vim | 12 ++++++------ autoload/leaderf/BufTag.vim | 12 ++++++------ autoload/leaderf/Buffer.vim | 12 ++++++------ autoload/leaderf/Colors.vim | 12 ++++++------ autoload/leaderf/File.vim | 12 ++++++------ autoload/leaderf/Function.vim | 12 ++++++------ autoload/leaderf/Gtags.vim | 12 ++++++------ autoload/leaderf/Jumps.vim | 12 ++++++------ autoload/leaderf/Line.vim | 12 ++++++------ autoload/leaderf/Mru.vim | 12 ++++++------ autoload/leaderf/Rg.vim | 12 ++++++------ autoload/leaderf/Tag.vim | 12 ++++++------ autoload/leaderf/python/leaderf/manager.py | 18 ++++++++++++++++-- 13 files changed, 88 insertions(+), 74 deletions(-) diff --git a/autoload/leaderf/Any.vim b/autoload/leaderf/Any.vim index 458e629a..e982e68f 100644 --- a/autoload/leaderf/Any.vim +++ b/autoload/leaderf/Any.vim @@ -28,12 +28,12 @@ function! leaderf#Any#Maps(category) nnoremap :exec g:Lf_py b:Lf_AnyExplManager."input()" nnoremap :exec g:Lf_py b:Lf_AnyExplManager."toggleHelp()" nnoremap p :exec g:Lf_py b:Lf_AnyExplManager."_previewResult(True)" - nnoremap j j:exec g:Lf_py b:Lf_AnyExplManager."_previewResult(False)" - nnoremap k k:exec g:Lf_py b:Lf_AnyExplManager."_previewResult(False)" - nnoremap :exec g:Lf_py b:Lf_AnyExplManager."_previewResult(False)" - nnoremap :exec g:Lf_py b:Lf_AnyExplManager."_previewResult(False)" - nnoremap :exec g:Lf_py b:Lf_AnyExplManager."_previewResult(False)" - nnoremap :exec g:Lf_py b:Lf_AnyExplManager."_previewResult(False)" + nnoremap j :exec g:Lf_py b:Lf_AnyExplManager.moveAndPreview('j')" + nnoremap k :exec g:Lf_py b:Lf_AnyExplManager.moveAndPreview('k')" + nnoremap :exec g:Lf_py b:Lf_AnyExplManager.moveAndPreview('Up')" + nnoremap :exec g:Lf_py b:Lf_AnyExplManager.moveAndPreview('Down')" + nnoremap :exec g:Lf_py b:Lf_AnyExplManager.moveAndPreview('PageUp')" + nnoremap :exec g:Lf_py b:Lf_AnyExplManager.moveAndPreview('PageDown')" if has("nvim") nnoremap :exec g:Lf_py b:Lf_AnyExplManager."_toUpInPopup()" nnoremap :exec g:Lf_py b:Lf_AnyExplManager."_toDownInPopup()" diff --git a/autoload/leaderf/BufTag.vim b/autoload/leaderf/BufTag.vim index 96f5eb4a..0d1407b0 100644 --- a/autoload/leaderf/BufTag.vim +++ b/autoload/leaderf/BufTag.vim @@ -27,12 +27,12 @@ function! leaderf#BufTag#Maps() nnoremap :exec g:Lf_py "bufTagExplManager.input()" nnoremap :exec g:Lf_py "bufTagExplManager.toggleHelp()" nnoremap p :exec g:Lf_py "bufTagExplManager._previewResult(True)" - nnoremap j j:exec g:Lf_py "bufTagExplManager._previewResult(False)" - nnoremap k k:exec g:Lf_py "bufTagExplManager._previewResult(False)" - nnoremap :exec g:Lf_py "bufTagExplManager._previewResult(False)" - nnoremap :exec g:Lf_py "bufTagExplManager._previewResult(False)" - nnoremap :exec g:Lf_py "bufTagExplManager._previewResult(False)" - nnoremap :exec g:Lf_py "bufTagExplManager._previewResult(False)" + nnoremap j :exec g:Lf_py "bufTagExplManager.moveAndPreview('j')" + nnoremap k :exec g:Lf_py "bufTagExplManager.moveAndPreview('k')" + nnoremap :exec g:Lf_py "bufTagExplManager.moveAndPreview('Up')" + nnoremap :exec g:Lf_py "bufTagExplManager.moveAndPreview('Down')" + nnoremap :exec g:Lf_py "bufTagExplManager.moveAndPreview('PageUp')" + nnoremap :exec g:Lf_py "bufTagExplManager.moveAndPreview('PageDown')" if has("nvim") nnoremap :exec g:Lf_py "bufTagExplManager._toUpInPopup()" nnoremap :exec g:Lf_py "bufTagExplManager._toDownInPopup()" diff --git a/autoload/leaderf/Buffer.vim b/autoload/leaderf/Buffer.vim index b6256654..de2b7fab 100644 --- a/autoload/leaderf/Buffer.vim +++ b/autoload/leaderf/Buffer.vim @@ -29,12 +29,12 @@ function! leaderf#Buffer#Maps() nnoremap d :exec g:Lf_py "bufExplManager.deleteBuffer(1)" nnoremap D :exec g:Lf_py "bufExplManager.deleteBuffer()" nnoremap p :exec g:Lf_py "bufExplManager._previewResult(True)" - nnoremap j j:exec g:Lf_py "bufExplManager._previewResult(False)" - nnoremap k k:exec g:Lf_py "bufExplManager._previewResult(False)" - nnoremap :exec g:Lf_py "bufExplManager._previewResult(False)" - nnoremap :exec g:Lf_py "bufExplManager._previewResult(False)" - nnoremap :exec g:Lf_py "bufExplManager._previewResult(False)" - nnoremap :exec g:Lf_py "bufExplManager._previewResult(False)" + nnoremap j :exec g:Lf_py "bufExplManager.moveAndPreview('j')" + nnoremap k :exec g:Lf_py "bufExplManager.moveAndPreview('k')" + nnoremap :exec g:Lf_py "bufExplManager.moveAndPreview('Up')" + nnoremap :exec g:Lf_py "bufExplManager.moveAndPreview('Down')" + nnoremap :exec g:Lf_py "bufExplManager.moveAndPreview('PageUp')" + nnoremap :exec g:Lf_py "bufExplManager.moveAndPreview('PageDown')" if has("nvim") nnoremap :exec g:Lf_py "bufExplManager._toUpInPopup()" nnoremap :exec g:Lf_py "bufExplManager._toDownInPopup()" diff --git a/autoload/leaderf/Colors.vim b/autoload/leaderf/Colors.vim index 6f443c9a..d4f35d83 100644 --- a/autoload/leaderf/Colors.vim +++ b/autoload/leaderf/Colors.vim @@ -24,12 +24,12 @@ function! leaderf#Colors#Maps() nnoremap :exec g:Lf_py "colorschemeExplManager.input()" nnoremap :exec g:Lf_py "colorschemeExplManager.toggleHelp()" nnoremap p :exec g:Lf_py "colorschemeExplManager._previewResult(True)" - nnoremap j j:exec g:Lf_py "colorschemeExplManager._previewResult(False)" - nnoremap k k:exec g:Lf_py "colorschemeExplManager._previewResult(False)" - nnoremap :exec g:Lf_py "colorschemeExplManager._previewResult(False)" - nnoremap :exec g:Lf_py "colorschemeExplManager._previewResult(False)" - nnoremap :exec g:Lf_py "colorschemeExplManager._previewResult(False)" - nnoremap :exec g:Lf_py "colorschemeExplManager._previewResult(False)" + nnoremap j :exec g:Lf_py "colorschemeExplManager.moveAndPreview('j')" + nnoremap k :exec g:Lf_py "colorschemeExplManager.moveAndPreview('k')" + nnoremap :exec g:Lf_py "colorschemeExplManager.moveAndPreview('Up')" + nnoremap :exec g:Lf_py "colorschemeExplManager.moveAndPreview('Down')" + nnoremap :exec g:Lf_py "colorschemeExplManager.moveAndPreview('PageUp')" + nnoremap :exec g:Lf_py "colorschemeExplManager.moveAndPreview('PageDown')" if has_key(g:Lf_NormalMap, "Colorscheme") for i in g:Lf_NormalMap["Colorscheme"] exec 'nnoremap '.i[0].' '.i[1] diff --git a/autoload/leaderf/File.vim b/autoload/leaderf/File.vim index a2a6b402..c62cb0da 100644 --- a/autoload/leaderf/File.vim +++ b/autoload/leaderf/File.vim @@ -31,12 +31,12 @@ function! leaderf#File#Maps() nnoremap a :exec g:Lf_py "fileExplManager.selectAll()" nnoremap c :exec g:Lf_py "fileExplManager.clearSelections()" nnoremap p :exec g:Lf_py "fileExplManager._previewResult(True)" - nnoremap j j:exec g:Lf_py "fileExplManager._previewResult(False)" - nnoremap k k:exec g:Lf_py "fileExplManager._previewResult(False)" - nnoremap :exec g:Lf_py "fileExplManager._previewResult(False)" - nnoremap :exec g:Lf_py "fileExplManager._previewResult(False)" - nnoremap :exec g:Lf_py "fileExplManager._previewResult(False)" - nnoremap :exec g:Lf_py "fileExplManager._previewResult(False)" + nnoremap j :exec g:Lf_py "fileExplManager.moveAndPreview('j')" + nnoremap k :exec g:Lf_py "fileExplManager.moveAndPreview('k')" + nnoremap :exec g:Lf_py "fileExplManager.moveAndPreview('Up')" + nnoremap :exec g:Lf_py "fileExplManager.moveAndPreview('Down')" + nnoremap :exec g:Lf_py "fileExplManager.moveAndPreview('PageUp')" + nnoremap :exec g:Lf_py "fileExplManager.moveAndPreview('PageDown')" if has("nvim") nnoremap :exec g:Lf_py "fileExplManager._toUpInPopup()" nnoremap :exec g:Lf_py "fileExplManager._toDownInPopup()" diff --git a/autoload/leaderf/Function.vim b/autoload/leaderf/Function.vim index 6948adbd..80c6b749 100644 --- a/autoload/leaderf/Function.vim +++ b/autoload/leaderf/Function.vim @@ -27,12 +27,12 @@ function! leaderf#Function#Maps() nnoremap :exec g:Lf_py "functionExplManager.input()" nnoremap :exec g:Lf_py "functionExplManager.toggleHelp()" nnoremap p :exec g:Lf_py "functionExplManager._previewResult(True)" - nnoremap j j:exec g:Lf_py "functionExplManager._previewResult(False)" - nnoremap k k:exec g:Lf_py "functionExplManager._previewResult(False)" - nnoremap :exec g:Lf_py "functionExplManager._previewResult(False)" - nnoremap :exec g:Lf_py "functionExplManager._previewResult(False)" - nnoremap :exec g:Lf_py "functionExplManager._previewResult(False)" - nnoremap :exec g:Lf_py "functionExplManager._previewResult(False)" + nnoremap j :exec g:Lf_py "functionExplManager.moveAndPreview('j')" + nnoremap k :exec g:Lf_py "functionExplManager.moveAndPreview('k')" + nnoremap :exec g:Lf_py "functionExplManager.moveAndPreview('Up')" + nnoremap :exec g:Lf_py "functionExplManager.moveAndPreview('Down')" + nnoremap :exec g:Lf_py "functionExplManager.moveAndPreview('PageUp')" + nnoremap :exec g:Lf_py "functionExplManager.moveAndPreview('PageDown')" if has("nvim") nnoremap :exec g:Lf_py "functionExplManager._toUpInPopup()" nnoremap :exec g:Lf_py "functionExplManager._toDownInPopup()" diff --git a/autoload/leaderf/Gtags.vim b/autoload/leaderf/Gtags.vim index 8d02eeae..d189ae9a 100644 --- a/autoload/leaderf/Gtags.vim +++ b/autoload/leaderf/Gtags.vim @@ -23,12 +23,12 @@ function! leaderf#Gtags#Maps() nnoremap v :exec g:Lf_py "gtagsExplManager.accept('v')" nnoremap t :exec g:Lf_py "gtagsExplManager.accept('t')" nnoremap p :exec g:Lf_py "gtagsExplManager._previewResult(True)" - nnoremap j j:exec g:Lf_py "gtagsExplManager._previewResult(False)" - nnoremap k k:exec g:Lf_py "gtagsExplManager._previewResult(False)" - nnoremap :exec g:Lf_py "gtagsExplManager._previewResult(False)" - nnoremap :exec g:Lf_py "gtagsExplManager._previewResult(False)" - nnoremap :exec g:Lf_py "gtagsExplManager._previewResult(False)" - nnoremap :exec g:Lf_py "gtagsExplManager._previewResult(False)" + nnoremap j :exec g:Lf_py "gtagsExplManager.moveAndPreview('j')" + nnoremap k :exec g:Lf_py "gtagsExplManager.moveAndPreview('k')" + nnoremap :exec g:Lf_py "gtagsExplManager.moveAndPreview('Up')" + nnoremap :exec g:Lf_py "gtagsExplManager.moveAndPreview('Down')" + nnoremap :exec g:Lf_py "gtagsExplManager.moveAndPreview('PageUp')" + nnoremap :exec g:Lf_py "gtagsExplManager.moveAndPreview('PageDown')" nnoremap q :exec g:Lf_py "gtagsExplManager.quit()" " nnoremap :exec g:Lf_py "gtagsExplManager.quit()" nnoremap i :exec g:Lf_py "gtagsExplManager.input()" diff --git a/autoload/leaderf/Jumps.vim b/autoload/leaderf/Jumps.vim index 9f2f6af4..345d5280 100644 --- a/autoload/leaderf/Jumps.vim +++ b/autoload/leaderf/Jumps.vim @@ -28,12 +28,12 @@ function! leaderf#Jumps#Maps() nnoremap :exec g:Lf_py "jumpsExplManager.toggleHelp()" nnoremap :exec g:Lf_py "jumpsExplManager.refresh()" nnoremap p :exec g:Lf_py "jumpsExplManager._previewResult(True)" - nnoremap j j:exec g:Lf_py "jumpsExplManager._previewResult(False)" - nnoremap k k:exec g:Lf_py "jumpsExplManager._previewResult(False)" - nnoremap :exec g:Lf_py "jumpsExplManager._previewResult(False)" - nnoremap :exec g:Lf_py "jumpsExplManager._previewResult(False)" - nnoremap :exec g:Lf_py "jumpsExplManager._previewResult(False)" - nnoremap :exec g:Lf_py "jumpsExplManager._previewResult(False)" + nnoremap j :exec g:Lf_py "jumpsExplManager.moveAndPreview('j')" + nnoremap k :exec g:Lf_py "jumpsExplManager.moveAndPreview('k')" + nnoremap :exec g:Lf_py "jumpsExplManager.moveAndPreview('Up')" + nnoremap :exec g:Lf_py "jumpsExplManager.moveAndPreview('Down')" + nnoremap :exec g:Lf_py "jumpsExplManager.moveAndPreview('PageUp')" + nnoremap :exec g:Lf_py "jumpsExplManager.moveAndPreview('PageDown')" if has("nvim") nnoremap :exec g:Lf_py "jumpsExplManager._toUpInPopup()" nnoremap :exec g:Lf_py "jumpsExplManager._toDownInPopup()" diff --git a/autoload/leaderf/Line.vim b/autoload/leaderf/Line.vim index 4a0bd601..f064aa21 100644 --- a/autoload/leaderf/Line.vim +++ b/autoload/leaderf/Line.vim @@ -27,12 +27,12 @@ function! leaderf#Line#Maps() nnoremap :exec g:Lf_py "lineExplManager.input()" nnoremap :exec g:Lf_py "lineExplManager.toggleHelp()" nnoremap p :exec g:Lf_py "lineExplManager._previewResult(True)" - nnoremap j j:exec g:Lf_py "lineExplManager._previewResult(False)" - nnoremap k k:exec g:Lf_py "lineExplManager._previewResult(False)" - nnoremap :exec g:Lf_py "lineExplManager._previewResult(False)" - nnoremap :exec g:Lf_py "lineExplManager._previewResult(False)" - nnoremap :exec g:Lf_py "lineExplManager._previewResult(False)" - nnoremap :exec g:Lf_py "lineExplManager._previewResult(False)" + nnoremap j :exec g:Lf_py "lineExplManager.moveAndPreview('j')" + nnoremap k :exec g:Lf_py "lineExplManager.moveAndPreview('k')" + nnoremap :exec g:Lf_py "lineExplManager.moveAndPreview('Up')" + nnoremap :exec g:Lf_py "lineExplManager.moveAndPreview('Down')" + nnoremap :exec g:Lf_py "lineExplManager.moveAndPreview('PageUp')" + nnoremap :exec g:Lf_py "lineExplManager.moveAndPreview('PageDown')" nnoremap Q :exec g:Lf_py "lineExplManager.outputToQflist()" nnoremap L :exec g:Lf_py "lineExplManager.outputToLoclist()" if has("nvim") diff --git a/autoload/leaderf/Mru.vim b/autoload/leaderf/Mru.vim index 551d7994..8a80b90a 100644 --- a/autoload/leaderf/Mru.vim +++ b/autoload/leaderf/Mru.vim @@ -31,12 +31,12 @@ function! leaderf#Mru#Maps() nnoremap a :exec g:Lf_py "mruExplManager.selectAll()" nnoremap c :exec g:Lf_py "mruExplManager.clearSelections()" nnoremap p :exec g:Lf_py "mruExplManager._previewResult(True)" - nnoremap j j:exec g:Lf_py "mruExplManager._previewResult(False)" - nnoremap k k:exec g:Lf_py "mruExplManager._previewResult(False)" - nnoremap :exec g:Lf_py "mruExplManager._previewResult(False)" - nnoremap :exec g:Lf_py "mruExplManager._previewResult(False)" - nnoremap :exec g:Lf_py "mruExplManager._previewResult(False)" - nnoremap :exec g:Lf_py "mruExplManager._previewResult(False)" + nnoremap j :exec g:Lf_py "mruExplManager.moveAndPreview('j')" + nnoremap k :exec g:Lf_py "mruExplManager.moveAndPreview('k')" + nnoremap :exec g:Lf_py "mruExplManager.moveAndPreview('Up')" + nnoremap :exec g:Lf_py "mruExplManager.moveAndPreview('Down')" + nnoremap :exec g:Lf_py "mruExplManager.moveAndPreview('PageUp')" + nnoremap :exec g:Lf_py "mruExplManager.moveAndPreview('PageDown')" if has("nvim") nnoremap :exec g:Lf_py "mruExplManager._toUpInPopup()" nnoremap :exec g:Lf_py "mruExplManager._toDownInPopup()" diff --git a/autoload/leaderf/Rg.vim b/autoload/leaderf/Rg.vim index 406d6557..e469bb5a 100644 --- a/autoload/leaderf/Rg.vim +++ b/autoload/leaderf/Rg.vim @@ -22,12 +22,12 @@ function! leaderf#Rg#Maps(heading) nnoremap v :exec g:Lf_py "rgExplManager.accept('v')" nnoremap t :exec g:Lf_py "rgExplManager.accept('t')" nnoremap p :exec g:Lf_py "rgExplManager._previewResult(True)" - nnoremap j j:exec g:Lf_py "rgExplManager._previewResult(False)" - nnoremap k k:exec g:Lf_py "rgExplManager._previewResult(False)" - nnoremap :exec g:Lf_py "rgExplManager._previewResult(False)" - nnoremap :exec g:Lf_py "rgExplManager._previewResult(False)" - nnoremap :exec g:Lf_py "rgExplManager._previewResult(False)" - nnoremap :exec g:Lf_py "rgExplManager._previewResult(False)" + nnoremap j :exec g:Lf_py "rgExplManager.moveAndPreview('j')" + nnoremap k :exec g:Lf_py "rgExplManager.moveAndPreview('k')" + nnoremap :exec g:Lf_py "rgExplManager.moveAndPreview('Up')" + nnoremap :exec g:Lf_py "rgExplManager.moveAndPreview('Down')" + nnoremap :exec g:Lf_py "rgExplManager.moveAndPreview('PageUp')" + nnoremap :exec g:Lf_py "rgExplManager.moveAndPreview('PageDown')" nnoremap q :exec g:Lf_py "rgExplManager.quit()" " nnoremap :exec g:Lf_py "rgExplManager.quit()" if a:heading == 0 diff --git a/autoload/leaderf/Tag.vim b/autoload/leaderf/Tag.vim index 7156a991..2ec58825 100644 --- a/autoload/leaderf/Tag.vim +++ b/autoload/leaderf/Tag.vim @@ -28,12 +28,12 @@ function! leaderf#Tag#Maps() nnoremap :exec g:Lf_py "tagExplManager.toggleHelp()" nnoremap :exec g:Lf_py "tagExplManager.refresh()" nnoremap p :exec g:Lf_py "tagExplManager._previewResult(True)" - nnoremap j j:exec g:Lf_py "tagExplManager._previewResult(False)" - nnoremap k k:exec g:Lf_py "tagExplManager._previewResult(False)" - nnoremap :exec g:Lf_py "tagExplManager._previewResult(False)" - nnoremap :exec g:Lf_py "tagExplManager._previewResult(False)" - nnoremap :exec g:Lf_py "tagExplManager._previewResult(False)" - nnoremap :exec g:Lf_py "tagExplManager._previewResult(False)" + nnoremap j :exec g:Lf_py "tagExplManager.moveAndPreview('j')" + nnoremap k :exec g:Lf_py "tagExplManager.moveAndPreview('k')" + nnoremap :exec g:Lf_py "tagExplManager.moveAndPreview('Up')" + nnoremap :exec g:Lf_py "tagExplManager.moveAndPreview('Down')" + nnoremap :exec g:Lf_py "tagExplManager.moveAndPreview('PageUp')" + nnoremap :exec g:Lf_py "tagExplManager.moveAndPreview('PageDown')" if has("nvim") nnoremap :exec g:Lf_py "tagExplManager._toUpInPopup()" nnoremap :exec g:Lf_py "tagExplManager._toDownInPopup()" diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index f850f7f8..ec81e26e 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -1116,6 +1116,20 @@ def _toDownInPopup(self): else: lfCmd("call win_execute(%d, 'norm! %dj')" % (self._preview_winid, scroll_step_size)) + def moveAndPreview(self, direction): + """ + direction is in {'j', 'k', 'Down', 'Up', 'PageDown', 'PageUp'} + """ + if len(direction) > 1: + lfCmd('noautocmd exec "norm! \<{}>"'.format(direction)) + else: + lfCmd('noautocmd exec "norm! {}"'.format(direction)) + + if self._getInstance().getWinPos() == 'floatwin': + self._cli.buildPopupPrompt() + + self._previewResult(False) + def _toUp(self): if self._getInstance().getWinPos() == 'popup': lfCmd("noautocmd call win_execute(%d, 'norm! k')" % (self._getInstance().getPopupWinId())) @@ -1168,7 +1182,7 @@ def _pageUp(self): and len(self._highlight_pos) < int(lfEval("g:Lf_NumberOfHighlight")): self._highlight_method() - lfCmd('exec "norm! \"') + lfCmd('noautocmd exec "norm! \"') self._getInstance().setLineNumber() @@ -1181,7 +1195,7 @@ def _pageDown(self): if not self._getInstance().isReverseOrder(): self._setResultContent() - lfCmd('exec "norm! \"') + lfCmd('noautocmd exec "norm! \"') self._getInstance().setLineNumber() From e9287c46952a9c434fee71538e5addd5e632f4cb Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Tue, 4 Jul 2023 16:09:26 +0800 Subject: [PATCH 081/365] fix a bug when do replace using Leaderf rg --- autoload/leaderf/python/leaderf/rgExpl.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/autoload/leaderf/python/leaderf/rgExpl.py b/autoload/leaderf/python/leaderf/rgExpl.py index 99d20e37..07ae5b68 100644 --- a/autoload/leaderf/python/leaderf/rgExpl.py +++ b/autoload/leaderf/python/leaderf/rgExpl.py @@ -1234,13 +1234,13 @@ def replace(self): string = lfEval("input('Replace with: ')") flags = lfEval("input('flags: ', 'gc')") if "--heading" in self._arguments: - lfCmd('%d;$s/\(^\d\+[:-].\{-}\)\@<=%s/%s/%s' - % (self._getInstance().helpLength + 1, escQuote(pattern.replace('/', '\/')), - escQuote(string.replace('/', '\/')), escQuote(flags))) + lfCmd("""%d;$s/\%%(^\d\+[:-].\{-}\)\@<=%s/%s/%s""" + % (self._getInstance().helpLength + 1, pattern.replace('/', '\/'), + string.replace('/', '\/'), flags)) else: - lfCmd('%d;$s/\(^.\+\(:\d\+:\|-\d\+-\).\{-}\)\@<=%s/%s/%s' - % (self._getInstance().helpLength + 1, escQuote(pattern.replace('/', '\/')), - escQuote(string.replace('/', '\/')), escQuote(flags))) + lfCmd("""%d;$s/\%%(^.\+\%%(:\d\+:\|-\d\+-\).\{-}\)\@<=%s/%s/%s""" + % (self._getInstance().helpLength + 1, pattern.replace('/', '\/'), + string.replace('/', '\/'), flags)) lfCmd("call histdel('search', -1)") lfCmd("let @/ = histget('search', -1)") lfCmd("nohlsearch") From ea95b143db9b9c85db5fa37fc7b0c60d7a49c5ab Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 5 Jul 2023 11:22:35 +0800 Subject: [PATCH 082/365] restore the view of Float window when --recall --- autoload/leaderf/python/leaderf/instance.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/autoload/leaderf/python/leaderf/instance.py b/autoload/leaderf/python/leaderf/instance.py index cd0f813c..f14374ba 100644 --- a/autoload/leaderf/python/leaderf/instance.py +++ b/autoload/leaderf/python/leaderf/instance.py @@ -260,6 +260,7 @@ def __init__(self, manager, category, cli, self._stl_buf_namespace = None self._auto_resize = lfEval("get(g:, 'Lf_AutoResize', 0)") == '1' self._window_id = 0 + self._float_win_view = None def _initStlVar(self): if int(lfEval("!exists('g:Lf_{}_StlCategory')".format(self._category))): @@ -584,6 +585,9 @@ def getWindow(number): self._popup_instance.statusline_win.id if show_stl else -1, show_stl, id(self._manager))) lfCmd("augroup END") + + if self._float_win_view is not None: + lfCmd("call winrestview(%s)" % self._float_win_view) else: self._win_pos = "popup" if lfEval("get(g:, 'Lf_PopupAutoAdjustHeight', 1)") == '1': @@ -1124,6 +1128,7 @@ def exitBuffer(self): lfCmd("let &gcr = remove(g:lf_gcr_stack, -1)") lfCmd("set t_ve&") lfCmd("let &t_ve = remove(g:lf_t_ve_stack, -1)") + self._float_win_view = lfEval("winsaveview()") self._popup_instance.close() if self._orig_win_id is not None: lfCmd("call win_gotoid(%d)" % self._orig_win_id) From 7c8d82b56cdc4e83e24a782ea9b5590fc75f98ad Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 5 Jul 2023 14:07:03 +0800 Subject: [PATCH 083/365] don't redraw --- autoload/leaderf/python/leaderf/manager.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index ec81e26e..971de648 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -1126,7 +1126,7 @@ def moveAndPreview(self, direction): lfCmd('noautocmd exec "norm! {}"'.format(direction)) if self._getInstance().getWinPos() == 'floatwin': - self._cli.buildPopupPrompt() + self._cli._buildPopupPrompt() self._previewResult(False) @@ -1161,7 +1161,7 @@ def _toDown(self): return if not self._getInstance().isReverseOrder() \ - and self._getInstance().getCurrentPos()[0] == self._getInstance().window.height: + and self._getInstance().getCurrentPos()[0] == self._initial_count: self._setResultContent() lfCmd("noautocmd norm! j") From 988019b4b6f5633ee93ec8372f2d00a51b72d994 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 5 Jul 2023 23:26:38 +0800 Subject: [PATCH 084/365] let g:Lf_PopupShowBorder be 1 by default update some colors of colorschemes --- autoload/leaderf/colorscheme/popup.vim | 53 +++++++++++++++++++ .../leaderf/colorscheme/popup/default.vim | 12 ++--- .../colorscheme/popup/gruvbox_default.vim | 12 ++--- .../colorscheme/popup/gruvbox_material.vim | 20 ++++--- .../leaderf/colorscheme/popup/onedark.vim | 6 +-- .../leaderf/colorscheme/popup/solarized.vim | 12 ++--- autoload/leaderf/python/leaderf/cli.py | 2 +- autoload/leaderf/python/leaderf/instance.py | 30 +++++++---- autoload/leaderf/python/leaderf/manager.py | 34 +++++++----- doc/leaderf.txt | 4 +- 10 files changed, 129 insertions(+), 56 deletions(-) diff --git a/autoload/leaderf/colorscheme/popup.vim b/autoload/leaderf/colorscheme/popup.vim index c4052050..b0fc39db 100644 --- a/autoload/leaderf/colorscheme/popup.vim +++ b/autoload/leaderf/colorscheme/popup.vim @@ -129,6 +129,59 @@ function! leaderf#colorscheme#popup#link_no_reverse(from, to) abort exec hiCmd endfunction +" link to bg's background color and fg's foreground color +function! leaderf#colorscheme#popup#link_two(from, bg, fg, no_attr) abort + let bg_sid = synIDtrans(hlID(a:bg)) + if synIDattr(bg_sid, "reverse") || synIDattr(bg_sid, "inverse") + let guibg = synIDattr(bg_sid, "fg", "gui") + let ctermbg = synIDattr(bg_sid, "fg", "cterm") + else + let guibg = synIDattr(bg_sid, "bg", "gui") + let ctermbg = synIDattr(bg_sid, "bg", "cterm") + endif + + let fg_sid = synIDtrans(hlID(a:fg)) + if synIDattr(fg_sid, "reverse") || synIDattr(fg_sid, "inverse") + let guifg = synIDattr(fg_sid, "bg", "gui") + if guifg == guibg + let guifg = synIDattr(fg_sid, "fg", "gui") + endif + let ctermfg = synIDattr(fg_sid, "bg", "cterm") + if ctermfg == ctermbg + let ctermfg = synIDattr(fg_sid, "fg", "cterm") + endif + else + let guifg = synIDattr(fg_sid, "fg", "gui") + if guifg == guibg + let guifg = synIDattr(fg_sid, "bg", "gui") + endif + let ctermfg = synIDattr(fg_sid, "fg", "cterm") + if ctermfg == ctermbg + let ctermfg = synIDattr(fg_sid, "bg", "cterm") + endif + endif + + if a:no_attr + let attr = "gui=NONE cterm=NONE" + else + let bold = synIDattr(fg_sid, "bold") ? "bold" : "" + let italic = synIDattr(fg_sid, "italic") ? "italic" : "" + if bold == "" && italic == "" + let attr = "gui=NONE cterm=NONE" + elseif bold == "bold" && italic == "italic" + let attr = "gui=bold,italic cterm=bold,italic" + elseif bold == "bold" + let attr = "gui=bold cterm=bold" + else + let attr = "gui=italic cterm=italic" + endif + endif + let hiCmd = printf("hi def %s %s", a:from, attr) + let hiCmd .= printf(" guifg=%s guibg=%s", guifg == '' ? 'NONE': guifg, guibg == '' ? 'NONE': guibg) + let hiCmd .= printf(" ctermfg=%s ctermbg=%s", ctermfg == '' ? 'NONE': ctermfg, ctermbg == '' ? 'NONE': ctermbg) + exec hiCmd +endfunction + " mode can be: " 1. INPUT mode " 2. NORMAL mode diff --git a/autoload/leaderf/colorscheme/popup/default.vim b/autoload/leaderf/colorscheme/popup/default.vim index f8dd13e9..7da7819d 100644 --- a/autoload/leaderf/colorscheme/popup/default.vim +++ b/autoload/leaderf/colorscheme/popup/default.vim @@ -18,10 +18,10 @@ if &background ==? 'dark' highlight def Lf_hl_popup_inputText guifg=#87ceeb guibg=#4d4d4d gui=NONE ctermfg=117 ctermbg=239 cterm=NONE " Lf_hl_popup_window is the wincolor of content window - highlight def Lf_hl_popup_window guifg=#eeeeee guibg=#404040 gui=NONE ctermfg=255 ctermbg=237 cterm=NONE + call leaderf#colorscheme#popup#link_no_reverse("Lf_hl_popup_window", "Normal") " Lf_hl_popup_blank is the wincolor of statusline window - highlight def Lf_hl_popup_blank guifg=NONE guibg=#4b4e50 gui=NONE ctermbg=239 cterm=NONE + call leaderf#colorscheme#popup#link_no_reverse("Lf_hl_popup_blank", "StatusLineNC") highlight def link Lf_hl_popup_cursor Cursor highlight def Lf_hl_popup_prompt guifg=#ffcd4a guibg=NONE gui=NONE ctermfg=221 ctermbg=NONE cterm=NONE @@ -115,7 +115,7 @@ if &background ==? 'dark' highlight def Lf_hl_gtagsHighlight guifg=#000000 guibg=#cccc66 gui=NONE ctermfg=16 ctermbg=185 cterm=NONE highlight def link Lf_hl_previewTitle Statusline - highlight def link Lf_hl_popupBorder VertSplit + call leaderf#colorscheme#popup#link_two("Lf_hl_popupBorder", "Normal", "VertSplit", 1) highlight def link Lf_hl_winNumber Constant highlight def link Lf_hl_winIndicators Statement @@ -133,10 +133,10 @@ else highlight def Lf_hl_popup_inputText guifg=#525252 guibg=#f4f3d7 gui=NONE ctermfg=239 ctermbg=230 cterm=NONE " Lf_hl_popup_window is the wincolor of content window - highlight def Lf_hl_popup_window guifg=#4d4d4d guibg=#fafbff gui=NONE ctermfg=239 ctermbg=231 cterm=NONE + call leaderf#colorscheme#popup#link_no_reverse("Lf_hl_popup_window", "Normal") " Lf_hl_popup_blank is the wincolor of statusline window - highlight def Lf_hl_popup_blank guifg=NONE guibg=#eeecc1 gui=NONE ctermbg=230 cterm=NONE + call leaderf#colorscheme#popup#link_no_reverse("Lf_hl_popup_blank", "StatusLineNC") highlight def link Lf_hl_popup_cursor Cursor highlight def Lf_hl_popup_prompt guifg=#c77400 guibg=NONE gui=NONE ctermfg=172 cterm=NONE @@ -230,7 +230,7 @@ else highlight def Lf_hl_gtagsHighlight guifg=#4d4d4d guibg=#cccc66 gui=NONE ctermfg=239 ctermbg=185 cterm=NONE highlight def link Lf_hl_previewTitle Statusline - highlight def link Lf_hl_popupBorder VertSplit + call leaderf#colorscheme#popup#link_two("Lf_hl_popupBorder", "Normal", "VertSplit", 1) highlight def link Lf_hl_winNumber Constant highlight def link Lf_hl_winIndicators Statement diff --git a/autoload/leaderf/colorscheme/popup/gruvbox_default.vim b/autoload/leaderf/colorscheme/popup/gruvbox_default.vim index 8838b2a2..dd9b0ceb 100644 --- a/autoload/leaderf/colorscheme/popup/gruvbox_default.vim +++ b/autoload/leaderf/colorscheme/popup/gruvbox_default.vim @@ -18,10 +18,10 @@ if &background ==? 'dark' highlight def Lf_hl_popup_inputText guifg=#dfebb2 guibg=#413d39 gui=NONE ctermfg=187 ctermbg=237 cterm=NONE " Lf_hl_popup_window is the wincolor of content window - highlight def Lf_hl_popup_window guifg=#ebdbb2 guibg=#323232 gui=NONE ctermfg=187 ctermbg=236 cterm=NONE + call leaderf#colorscheme#popup#link_no_reverse("Lf_hl_popup_window", "Normal") " Lf_hl_popup_blank is the wincolor of statusline window - highlight def Lf_hl_popup_blank guifg=NONE guibg=#413d39 gui=NONE ctermbg=237 cterm=NONE + call leaderf#colorscheme#popup#link_no_reverse("Lf_hl_popup_blank", "StatusLineNC") highlight def link Lf_hl_popup_cursor Cursor highlight def Lf_hl_popup_prompt guifg=#fabd2f guibg=NONE gui=NONE ctermfg=214 ctermbg=NONE cterm=NONE @@ -114,7 +114,7 @@ if &background ==? 'dark' highlight def Lf_hl_gtagsHighlight guifg=#000000 guibg=#cccc66 gui=NONE ctermfg=16 ctermbg=185 cterm=NONE highlight def link Lf_hl_previewTitle Statusline - highlight def link Lf_hl_popupBorder VertSplit + call leaderf#colorscheme#popup#link_two("Lf_hl_popupBorder", "Normal", "VertSplit", 1) highlight def link Lf_hl_winNumber Constant highlight def link Lf_hl_winIndicators Statement @@ -132,10 +132,10 @@ else highlight def Lf_hl_popup_inputText guifg=#504945 guibg=#faefb2 gui=NONE ctermfg=239 ctermbg=253 cterm=NONE " Lf_hl_popup_window is the wincolor of content window - highlight def Lf_hl_popup_window guifg=#665c54 guibg=#fcf4cf gui=NONE ctermfg=59 ctermbg=230 cterm=NONE + call leaderf#colorscheme#popup#link_no_reverse("Lf_hl_popup_window", "Normal") " Lf_hl_popup_blank is the wincolor of statusline window - highlight def Lf_hl_popup_blank guifg=NONE guibg=#faefb2 gui=NONE ctermbg=253 cterm=NONE + call leaderf#colorscheme#popup#link_no_reverse("Lf_hl_popup_blank", "StatusLineNC") highlight def link Lf_hl_popup_cursor Cursor highlight def Lf_hl_popup_prompt guifg=#c77400 guibg=NONE gui=NONE ctermfg=172 cterm=NONE @@ -229,7 +229,7 @@ else highlight def Lf_hl_gtagsHighlight guifg=#4d4d4d guibg=#cccc66 gui=NONE ctermfg=239 ctermbg=185 cterm=NONE highlight def link Lf_hl_previewTitle Statusline - highlight def link Lf_hl_popupBorder VertSplit + call leaderf#colorscheme#popup#link_two("Lf_hl_popupBorder", "Normal", "VertSplit", 1) highlight def link Lf_hl_winNumber Constant highlight def link Lf_hl_winIndicators Statement diff --git a/autoload/leaderf/colorscheme/popup/gruvbox_material.vim b/autoload/leaderf/colorscheme/popup/gruvbox_material.vim index 9538810d..88d8fbed 100644 --- a/autoload/leaderf/colorscheme/popup/gruvbox_material.vim +++ b/autoload/leaderf/colorscheme/popup/gruvbox_material.vim @@ -10,15 +10,17 @@ if &background ==# 'dark' if get(g:, 'gruvbox_material_background', 'medium') ==# 'hard' highlight Lf_hl_popup_inputText guifg=#ddc7a1 guibg=#3c3836 gui=NONE ctermfg=223 ctermbg=237 cterm=NONE - highlight Lf_hl_popup_window guifg=#ddc7a1 guibg=#3c3836 gui=NONE ctermfg=223 ctermbg=237 cterm=NONE + "highlight Lf_hl_popup_window guifg=#ddc7a1 guibg=#3c3836 gui=NONE ctermfg=223 ctermbg=237 cterm=NONE elseif get(g:, 'gruvbox_material_background', 'medium') ==# 'medium' highlight Lf_hl_popup_inputText guifg=#ddc7a1 guibg=#504945 gui=NONE ctermfg=223 ctermbg=239 cterm=NONE - highlight Lf_hl_popup_window guifg=#ddc7a1 guibg=#504945 gui=NONE ctermfg=223 ctermbg=239 cterm=NONE + "highlight Lf_hl_popup_window guifg=#ddc7a1 guibg=#504945 gui=NONE ctermfg=223 ctermbg=239 cterm=NONE elseif get(g:, 'gruvbox_material_background', 'medium') ==# 'soft' highlight Lf_hl_popup_inputText guifg=#ddc7a1 guibg=#504945 gui=NONE ctermfg=223 ctermbg=239 cterm=NONE - highlight Lf_hl_popup_window guifg=#ddc7a1 guibg=#504945 gui=NONE ctermfg=223 ctermbg=239 cterm=NONE + "highlight Lf_hl_popup_window guifg=#ddc7a1 guibg=#504945 gui=NONE ctermfg=223 ctermbg=239 cterm=NONE endif + call leaderf#colorscheme#popup#link_no_reverse("Lf_hl_popup_window", "Normal") + highlight Lf_hl_popup_prompt guifg=#89b482 ctermfg=108 highlight Lf_hl_popup_spin guifg=#d8a657 ctermfg=214 highlight Lf_hl_popup_normalMode guifg=#282828 guibg=#a89984 gui=bold ctermfg=235 ctermbg=246 cterm=bold @@ -112,7 +114,7 @@ if &background ==# 'dark' highlight def Lf_hl_gtagsHighlight guifg=#000000 guibg=#cccc66 gui=NONE ctermfg=16 ctermbg=185 cterm=NONE highlight def link Lf_hl_previewTitle Statusline - highlight def link Lf_hl_popupBorder VertSplit + call leaderf#colorscheme#popup#link_two("Lf_hl_popupBorder", "Normal", "VertSplit", 1) highlight def link Lf_hl_winNumber Constant highlight def link Lf_hl_winIndicators Statement @@ -128,15 +130,17 @@ if &background ==# 'dark' else if get(g:, 'gruvbox_material_background', 'medium') ==# 'hard' highlight Lf_hl_popup_inputText guifg=#4f3829 guibg=#f2e5bc gui=NONE ctermfg=237 ctermbg=228 cterm=NONE - highlight Lf_hl_popup_window guifg=#4f3829 guibg=#f2e5bc gui=NONE ctermfg=237 ctermbg=228 cterm=NONE + "highlight Lf_hl_popup_window guifg=#4f3829 guibg=#f2e5bc gui=NONE ctermfg=237 ctermbg=228 cterm=NONE elseif get(g:, 'gruvbox_material_background', 'medium') ==# 'medium' highlight Lf_hl_popup_inputText guifg=#4f3829 guibg=#ebdbb2 gui=NONE ctermfg=237 ctermbg=223 cterm=NONE - highlight Lf_hl_popup_window guifg=#4f3829 guibg=#ebdbb2 gui=NONE ctermfg=237 ctermbg=223 cterm=NONE + "highlight Lf_hl_popup_window guifg=#4f3829 guibg=#ebdbb2 gui=NONE ctermfg=237 ctermbg=223 cterm=NONE elseif get(g:, 'gruvbox_material_background', 'medium') ==# 'soft' highlight Lf_hl_popup_inputText guifg=#4f3829 guibg=#d5c4a1 gui=NONE ctermfg=237 ctermbg=250 cterm=NONE - highlight Lf_hl_popup_window guifg=#4f3829 guibg=#d5c4a1 gui=NONE ctermfg=237 ctermbg=250 cterm=NONE + "highlight Lf_hl_popup_window guifg=#4f3829 guibg=#d5c4a1 gui=NONE ctermfg=237 ctermbg=250 cterm=NONE endif + call leaderf#colorscheme#popup#link_no_reverse("Lf_hl_popup_window", "Normal") + highlight Lf_hl_popup_prompt guifg=#4c7a5d ctermfg=165 highlight Lf_hl_popup_spin guifg=#b47109 ctermfg=136 highlight Lf_hl_popup_normalMode guifg=#ebdbb2 guibg=#7c6f64 gui=bold ctermfg=235 ctermbg=243 cterm=bold @@ -230,7 +234,7 @@ else highlight def Lf_hl_gtagsHighlight guifg=#000000 guibg=#cccc66 gui=NONE ctermfg=16 ctermbg=185 cterm=NONE highlight def link Lf_hl_previewTitle Statusline - highlight def link Lf_hl_popupBorder VertSplit + call leaderf#colorscheme#popup#link_two("Lf_hl_popupBorder", "Normal", "VertSplit", 1) highlight def link Lf_hl_winNumber Constant highlight def link Lf_hl_winIndicators Statement diff --git a/autoload/leaderf/colorscheme/popup/onedark.vim b/autoload/leaderf/colorscheme/popup/onedark.vim index d139cfca..c5fe17b1 100644 --- a/autoload/leaderf/colorscheme/popup/onedark.vim +++ b/autoload/leaderf/colorscheme/popup/onedark.vim @@ -1,7 +1,7 @@ if &background ==? 'dark' highlight def Lf_hl_popup_inputText guifg=#ABB2BF ctermfg=145 guibg=#3B4048 ctermbg=238 - highlight def Lf_hl_popup_window guifg=#ABB2BF ctermfg=145 guibg=#3B4048 ctermbg=238 - highlight def Lf_hl_popup_blank guibg=#3E4452 ctermbg=237 + call leaderf#colorscheme#popup#link_no_reverse("Lf_hl_popup_window", "Normal") + call leaderf#colorscheme#popup#link_no_reverse("Lf_hl_popup_blank", "StatusLineNC") highlight def Lf_hl_popup_cursor guifg=#657b83 ctermfg=66 guibg=#98C379 ctermbg=114 highlight def Lf_hl_popup_prompt guifg=#D19A66 ctermfg=173 guibg=#3B4048 ctermbg=238 gui=bold cterm=bold highlight def Lf_hl_popup_spin guifg=#ABB2BF ctermfg=145 guibg=#3B4048 ctermbg=238 @@ -16,7 +16,7 @@ if &background ==? 'dark' highlight def Lf_hl_popup_lineInfo guifg=#ABB2BF ctermfg=145 guibg=#3E4452 ctermbg=237 highlight def Lf_hl_popup_total guifg=#2C323C ctermfg=236 guibg=#ABB2BF ctermbg=145 - highlight def link Lf_hl_popupBorder Default + call leaderf#colorscheme#popup#link_two("Lf_hl_popupBorder", "Normal", "VertSplit", 1) highlight def Lf_hl_cursorline guifg=#ABB2BF ctermfg=145 guibg=NONE ctermbg=NONE diff --git a/autoload/leaderf/colorscheme/popup/solarized.vim b/autoload/leaderf/colorscheme/popup/solarized.vim index 58cc8557..4fd40744 100644 --- a/autoload/leaderf/colorscheme/popup/solarized.vim +++ b/autoload/leaderf/colorscheme/popup/solarized.vim @@ -1,7 +1,7 @@ if &background ==? 'dark' highlight def Lf_hl_popup_inputText guifg=#839496 ctermfg=102 guibg=#002b36 ctermbg=17 - highlight def Lf_hl_popup_window guifg=#839496 ctermfg=102 guibg=#002b36 ctermbg=17 - highlight def Lf_hl_popup_blank guibg=#073642 ctermbg=23 + call leaderf#colorscheme#popup#link_no_reverse("Lf_hl_popup_window", "Normal") + call leaderf#colorscheme#popup#link_no_reverse("Lf_hl_popup_blank", "StatusLineNC") highlight def Lf_hl_popup_cursor guifg=#657b83 ctermfg=66 guibg=#93a1a1 ctermbg=109 highlight def Lf_hl_popup_prompt guifg=#b58900 ctermfg=136 guibg=#002b36 ctermbg=17 gui=bold cterm=bold highlight def Lf_hl_popup_spin guifg=#fdf6e3 ctermfg=230 guibg=#002b36 ctermbg=17 @@ -16,7 +16,7 @@ if &background ==? 'dark' highlight def Lf_hl_popup_lineInfo guifg=#eee8d5 ctermfg=224 guibg=#657b83 ctermbg=66 highlight def Lf_hl_popup_total guifg=#fdf6e3 ctermfg=230 guibg=#93a1a1 ctermbg=109 - highlight def link Lf_hl_popupBorder Normal + call leaderf#colorscheme#popup#link_two("Lf_hl_popupBorder", "Normal", "VertSplit", 1) highlight def Lf_hl_cursorline guifg=#fdf6e3 ctermfg=230 @@ -29,8 +29,8 @@ if &background ==? 'dark' highlight def Lf_hl_matchRefine guifg=#cb4b16 ctermfg=166 else highlight def Lf_hl_popup_inputText guifg=#657b83 ctermfg=66 guibg=#fdf6e3 ctermbg=230 - highlight def Lf_hl_popup_window guifg=#657b83 ctermfg=66 guibg=#fdf6e3 ctermbg=230 - highlight def Lf_hl_popup_blank guibg=#eee8d5 ctermbg=224 + call leaderf#colorscheme#popup#link_no_reverse("Lf_hl_popup_window", "Normal") + call leaderf#colorscheme#popup#link_no_reverse("Lf_hl_popup_blank", "StatusLineNC") highlight def Lf_hl_popup_cursor guifg=#b58900 ctermfg=136 guibg=#586e75 ctermbg=60 highlight def Lf_hl_popup_prompt guifg=#073642 ctermfg=23 guibg=#fdf6e3 ctermbg=230 gui=bold cterm=bold highlight def Lf_hl_popup_spin guifg=#002b36 ctermfg=17 guibg=#fdf6e3 ctermbg=230 @@ -45,7 +45,7 @@ else highlight def Lf_hl_popup_lineInfo guifg=#eee8d5 ctermfg=224 guibg=#839496 ctermbg=102 highlight def Lf_hl_popup_total guifg=#fdf6e3 ctermfg=230 guibg=#586e75 ctermbg=60 - highlight def link Lf_hl_popupBorder Normal + call leaderf#colorscheme#popup#link_two("Lf_hl_popupBorder", "Normal", "VertSplit", 1) highlight def Lf_hl_cursorline guifg=#002b36 ctermfg=17 diff --git a/autoload/leaderf/python/leaderf/cli.py b/autoload/leaderf/python/leaderf/cli.py index 5f4f0f3f..5344b30a 100644 --- a/autoload/leaderf/python/leaderf/cli.py +++ b/autoload/leaderf/python/leaderf/cli.py @@ -198,7 +198,7 @@ def _buildPopupPrompt(self): input_window = self._instance.getPopupInstance().input_win content_winid = self._instance.getPopupInstance().content_win.id input_win_width = input_window.width - if lfEval("get(g:, 'Lf_PopupShowBorder', 0)") == '1' and lfEval("has('nvim')") == '0': + if lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1' and lfEval("has('nvim')") == '0': input_win_width -= 2 if self._instance.getWinPos() == 'popup': lfCmd("""call win_execute(%d, 'let line_num = line(".")')""" % content_winid) diff --git a/autoload/leaderf/python/leaderf/instance.py b/autoload/leaderf/python/leaderf/instance.py index f14374ba..0f53da72 100644 --- a/autoload/leaderf/python/leaderf/instance.py +++ b/autoload/leaderf/python/leaderf/instance.py @@ -397,7 +397,7 @@ def _createPopupWindow(self, clear): else: height = int(height) maxheight = min(height, int(lfEval("&lines")) - 2) - if lfEval("get(g:, 'Lf_PopupShowBorder', 0)") == '1': + if lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1': maxheight -= 2 line, col = [int(i) for i in lfEval("get(g:, 'Lf_PopupPosition', [0, 0])")] @@ -449,9 +449,17 @@ def _createPopupWindow(self, clear): } popup_borders = lfEval("g:Lf_PopupBorders") - borderchars = [popup_borders[4], popup_borders[0], popup_borders[5], popup_borders[1], - popup_borders[6], popup_borders[2], popup_borders[7], popup_borders[3]] - if lfEval("get(g:, 'Lf_PopupShowBorder', 0)") == '1': + borderchars = [ + [popup_borders[4], "Lf_hl_popupBorder"], + [popup_borders[0], "Lf_hl_popupBorder"], + [popup_borders[5], "Lf_hl_popupBorder"], + [popup_borders[1], "Lf_hl_popupBorder"], + [popup_borders[6], "Lf_hl_popupBorder"], + [popup_borders[2], "Lf_hl_popupBorder"], + [popup_borders[7], "Lf_hl_popupBorder"], + [popup_borders[3], "Lf_hl_popupBorder"] + ] + if lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1': if lfEval("get(g:, 'Lf_PopupShowStatusline', 1)") == '1': config["border"] = ['','','',borderchars[3],'','','',borderchars[7]] else: @@ -463,7 +471,7 @@ def _createPopupWindow(self, clear): self._popup_winid = int(lfEval("winid")) self._window_id = self._popup_winid self._setAttributes() - if lfEval("get(g:, 'Lf_PopupShowFoldcolumn', 1)") == '0' or lfEval("get(g:, 'Lf_PopupShowBorder', 0)") == '1': + if lfEval("get(g:, 'Lf_PopupShowFoldcolumn', 1)") == '0' or lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1': try: lfCmd("call nvim_win_set_option(%d, 'foldcolumn', 0)" % self._popup_winid) except vim.error: @@ -490,7 +498,7 @@ def _createPopupWindow(self, clear): "col" : col } - if lfEval("get(g:, 'Lf_PopupShowBorder', 0)") == '1': + if lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1': input_win_config["border"] = borderchars[:4] + ['','','', borderchars[7]] input_win_config["width"] -= 2 @@ -542,7 +550,7 @@ def getWindow(number): "col" : col } - if lfEval("get(g:, 'Lf_PopupShowBorder', 0)") == '1': + if lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1': stl_win_config["border"] = ['','',''] + borderchars[3:] stl_win_config["width"] -= 2 @@ -612,7 +620,7 @@ def getWindow(number): } borderchars = lfEval("g:Lf_PopupBorders") - if lfEval("get(g:, 'Lf_PopupShowBorder', 0)") == '1': + if lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1': if lfEval("get(g:, 'Lf_PopupShowStatusline', 1)") == '1': options["border"] = [0, 1, 0, 1] else: @@ -640,7 +648,7 @@ def getWindow(number): lfCmd("call win_execute(%d, 'setlocal cursorline')" % self._popup_winid) if lfEval("exists('+cursorlineopt')") == '1': lfCmd("call win_execute(%d, 'setlocal cursorlineopt=both')" % self._popup_winid) - if lfEval("get(g:, 'Lf_PopupShowFoldcolumn', 1)") == '0' or lfEval("get(g:, 'Lf_PopupShowBorder', 0)") == '1': + if lfEval("get(g:, 'Lf_PopupShowFoldcolumn', 1)") == '0' or lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1': lfCmd("call win_execute(%d, 'setlocal foldcolumn=0')" % self._popup_winid) else: lfCmd("call win_execute(%d, 'setlocal foldcolumn=1')" % self._popup_winid) @@ -667,7 +675,7 @@ def getWindow(number): "borderhighlight": ["Lf_hl_previewTitle"], } - if lfEval("get(g:, 'Lf_PopupShowBorder', 0)") == '1': + if lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1': input_win_options["border"] = [1, 1, 0, 1] input_win_options["borderchars"] = borderchars input_win_options["maxwidth"] -= 2 @@ -713,7 +721,7 @@ def getWindow(number): "borderhighlight": ["Lf_hl_previewTitle"], } - if lfEval("get(g:, 'Lf_PopupShowBorder', 0)") == '1': + if lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1': statusline_win_options["border"] = [0, 1, 1, 1] statusline_win_options["borderchars"] = borderchars statusline_win_options["maxwidth"] -= 2 diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 971de648..15e06525 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -469,8 +469,16 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): float_win_width= int(float(lfEval("nvim_win_get_config(%d).width" % float_window.id))) preview_pos = lfEval("get(g:, 'Lf_PopupPreviewPosition', 'top')") popup_borders = lfEval("g:Lf_PopupBorders") - borderchars = [popup_borders[4], popup_borders[0], popup_borders[5], popup_borders[1], - popup_borders[6], popup_borders[2], popup_borders[7], popup_borders[3]] + borderchars = [ + [popup_borders[4], "Lf_hl_popupBorder"], + [popup_borders[0], "Lf_hl_popupBorder"], + [popup_borders[5], "Lf_hl_popupBorder"], + [popup_borders[1], "Lf_hl_popupBorder"], + [popup_borders[6], "Lf_hl_popupBorder"], + [popup_borders[2], "Lf_hl_popupBorder"], + [popup_borders[7], "Lf_hl_popupBorder"], + [popup_borders[3], "Lf_hl_popupBorder"] + ] if preview_pos.lower() == 'bottom': anchor = "NW" if self._getInstance().getPopupInstance().statusline_win: @@ -489,7 +497,7 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): elif preview_pos.lower() == 'top': anchor = "SW" row = float_win_row - 1 - if lfEval("get(g:, 'Lf_PopupShowBorder', 0)") == '1': + if lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1': row -= 1 col = float_win_col height = row @@ -503,13 +511,13 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): anchor = "NW" row = float_win_row - 1 col = float_win_col + float_win_width - if lfEval("get(g:, 'Lf_PopupShowBorder', 0)") == '1': + if lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1': row -= 1 col += 2 height = self._getInstance().getPopupHeight() + 1 if width <= 0: width = float_win_width - if lfEval("get(g:, 'Lf_PopupShowBorder', 0)") == '1': + if lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1': width = min(width, int(lfEval("&columns")) - col - 2) else: width = min(width, int(lfEval("&columns")) - col) @@ -517,7 +525,7 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): anchor = "NE" row = float_win_row - 1 col = float_win_col - if lfEval("get(g:, 'Lf_PopupShowBorder', 0)") == '1': + if lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1': row -= 1 col -= 2 height = self._getInstance().getPopupHeight() + 1 @@ -552,7 +560,7 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): "noautocmd": 1 } - if lfEval("get(g:, 'Lf_PopupShowBorder', 0)") == '1': + if lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1': config["border"] = borderchars if isinstance(source, int): @@ -683,7 +691,7 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): "filter": "leaderf#popupModePreviewFilter", } - if lfEval("get(g:, 'Lf_PopupShowBorder', 0)") == '1': + if lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1': options["borderchars"] = lfEval("g:Lf_PopupBorders") options["maxwidth"] -= 2 options["minwidth"] -= 2 @@ -692,20 +700,20 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): if preview_pos.lower() == 'bottom': del options["title"] options["border"] = [0, 0, 1, 0] - if lfEval("get(g:, 'Lf_PopupShowBorder', 0)") == '1': + if lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1': options["border"] = [0, 1, 1, 1] elif preview_pos.lower() == 'top': - if lfEval("get(g:, 'Lf_PopupShowBorder', 0)") == '1': + if lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1': options["border"] = [1, 1, 0, 1] elif preview_pos.lower() == 'right': - if lfEval("get(g:, 'Lf_PopupShowBorder', 0)") == '1': + if lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1': options["border"] = [1, 1, 1, 1] options["line"] -= 1 # options["col"] += 1 options["maxheight"] += 1 options["minheight"] += 1 elif preview_pos.lower() == 'left': - if lfEval("get(g:, 'Lf_PopupShowBorder', 0)") == '1': + if lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1': options["border"] = [1, 1, 1, 1] options["line"] -= 1 # options["col"] -= 1 @@ -735,7 +743,7 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): if lfEval("exists('+cursorlineopt')") == '1': lfCmd("call win_execute(%d, 'setlocal cursorlineopt=both')" % self._preview_winid) lfCmd("call win_execute(%d, 'setlocal wincolor=Lf_hl_popup_window')" % self._preview_winid) - if lfEval("get(g:, 'Lf_PopupShowFoldcolumn', 1)") == '0' or lfEval("get(g:, 'Lf_PopupShowBorder', 0)") == '1': + if lfEval("get(g:, 'Lf_PopupShowFoldcolumn', 1)") == '0' or lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1': lfCmd("call win_execute(%d, 'setlocal foldcolumn=0')" % self._preview_winid) else: lfCmd("call win_execute(%d, 'setlocal foldcolumn=1')" % self._preview_winid) diff --git a/doc/leaderf.txt b/doc/leaderf.txt index 5dbe627c..4ddeab90 100644 --- a/doc/leaderf.txt +++ b/doc/leaderf.txt @@ -896,9 +896,9 @@ g:Lf_PopupAutoAdjustHeight *g:Lf_PopupAutoAdjustHeight* Default value is 1. g:Lf_PopupShowBorder *g:Lf_PopupShowBorder* - Specifies whether to show border for popup window. + Specifies whether to show borders for popup window. - Default value is 0. + Default value is 1. g:Lf_PopupBorders *g:Lf_PopupBorders* Specifies a list of characters, defining the character to use for the From 1a30a0d474a81a48668c637fee86c3e4ac260243 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 6 Jul 2023 12:40:20 +0800 Subject: [PATCH 085/365] nvim has a weird bug, if `hi Cursor cterm=reverse gui=reverse` and `hi def link Lf_hl_popup_cursor Cursor`, the bug occurs. --- autoload/leaderf/colorscheme/popup.vim | 15 +++++++++++++++ autoload/leaderf/colorscheme/popup/default.vim | 14 ++++++++++---- .../leaderf/colorscheme/popup/gruvbox_default.vim | 10 ++++++++-- .../colorscheme/popup/gruvbox_material.vim | 10 ++++++++-- 4 files changed, 41 insertions(+), 8 deletions(-) diff --git a/autoload/leaderf/colorscheme/popup.vim b/autoload/leaderf/colorscheme/popup.vim index b0fc39db..2c5d1c0a 100644 --- a/autoload/leaderf/colorscheme/popup.vim +++ b/autoload/leaderf/colorscheme/popup.vim @@ -182,6 +182,21 @@ function! leaderf#colorscheme#popup#link_two(from, bg, fg, no_attr) abort exec hiCmd endfunction +" nvim has a weird bug, if `hi Cursor cterm=reverse gui=reverse` +" and `hi def link Lf_hl_popup_cursor Cursor`, the bug occurs. +function! leaderf#colorscheme#popup#link_cursor(from) abort + if has("nvim") + let sid = synIDtrans(hlID("Cursor")) + if synIDattr(sid, "reverse") || synIDattr(sid, "inverse") + exec printf("hi %s gui=reverse guifg=NONE guibg=NONE cterm=reverse ctermfg=NONE ctermbg=NONE", a:from) + else + exec printf("hi def link %s Cursor", a:from) + endif + else + exec printf("hi def link %s Cursor", a:from) + endif +endfunction + " mode can be: " 1. INPUT mode " 2. NORMAL mode diff --git a/autoload/leaderf/colorscheme/popup/default.vim b/autoload/leaderf/colorscheme/popup/default.vim index 7da7819d..720e548b 100644 --- a/autoload/leaderf/colorscheme/popup/default.vim +++ b/autoload/leaderf/colorscheme/popup/default.vim @@ -23,7 +23,10 @@ if &background ==? 'dark' " Lf_hl_popup_blank is the wincolor of statusline window call leaderf#colorscheme#popup#link_no_reverse("Lf_hl_popup_blank", "StatusLineNC") - highlight def link Lf_hl_popup_cursor Cursor + " nvim has a weird bug, if `hi Cursor cterm=reverse gui=reverse` + " and `hi def link Lf_hl_popup_cursor Cursor`, the bug occurs. + call leaderf#colorscheme#popup#link_cursor("Lf_hl_popup_cursor") + highlight def Lf_hl_popup_prompt guifg=#ffcd4a guibg=NONE gui=NONE ctermfg=221 ctermbg=NONE cterm=NONE highlight def Lf_hl_popup_spin guifg=#e6e666 guibg=NONE gui=NONE ctermfg=185 ctermbg=NONE cterm=NONE highlight def Lf_hl_popup_normalMode guifg=#333300 guibg=#c1ce96 gui=bold ctermfg=58 ctermbg=187 cterm=bold @@ -42,10 +45,10 @@ if &background ==? 'dark' highlight def Lf_hl_cursorline guifg=Yellow guibg=NONE gui=NONE ctermfg=226 ctermbg=NONE cterm=NONE " the color of matching character - highlight def Lf_hl_match guifg=SpringGreen guibg=NONE gui=bold ctermfg=85 ctermbg=NONE cterm=bold + highlight def Lf_hl_match guifg=#afff5f guibg=NONE gui=bold ctermfg=155 ctermbg=NONE cterm=bold " the color of matching character in `And mode` - highlight def Lf_hl_match0 guifg=SpringGreen guibg=NONE gui=bold ctermfg=85 ctermbg=NONE cterm=bold + highlight def Lf_hl_match0 guifg=#afff5f guibg=NONE gui=bold ctermfg=155 ctermbg=NONE cterm=bold highlight def Lf_hl_match1 guifg=#fe8019 guibg=NONE gui=bold ctermfg=208 ctermbg=NONE cterm=bold highlight def Lf_hl_match2 guifg=#3ff5d1 guibg=NONE gui=bold ctermfg=50 ctermbg=NONE cterm=bold highlight def Lf_hl_match3 guifg=#ff7272 guibg=NONE gui=bold ctermfg=203 ctermbg=NONE cterm=bold @@ -138,7 +141,10 @@ else " Lf_hl_popup_blank is the wincolor of statusline window call leaderf#colorscheme#popup#link_no_reverse("Lf_hl_popup_blank", "StatusLineNC") - highlight def link Lf_hl_popup_cursor Cursor + " nvim has a weird bug, if `hi Cursor cterm=reverse gui=reverse` + " and `hi def link Lf_hl_popup_cursor Cursor`, the bug occurs. + call leaderf#colorscheme#popup#link_cursor("Lf_hl_popup_cursor") + highlight def Lf_hl_popup_prompt guifg=#c77400 guibg=NONE gui=NONE ctermfg=172 cterm=NONE highlight def Lf_hl_popup_spin guifg=#f12d2d guibg=NONE gui=NONE ctermfg=196 cterm=NONE highlight def Lf_hl_popup_normalMode guifg=#808000 guibg=#ccc88e gui=bold ctermfg=100 ctermbg=186 cterm=bold diff --git a/autoload/leaderf/colorscheme/popup/gruvbox_default.vim b/autoload/leaderf/colorscheme/popup/gruvbox_default.vim index dd9b0ceb..73679106 100644 --- a/autoload/leaderf/colorscheme/popup/gruvbox_default.vim +++ b/autoload/leaderf/colorscheme/popup/gruvbox_default.vim @@ -23,7 +23,10 @@ if &background ==? 'dark' " Lf_hl_popup_blank is the wincolor of statusline window call leaderf#colorscheme#popup#link_no_reverse("Lf_hl_popup_blank", "StatusLineNC") - highlight def link Lf_hl_popup_cursor Cursor + " nvim has a weird bug, if `hi Cursor cterm=reverse gui=reverse` + " and `hi def link Lf_hl_popup_cursor Cursor`, the bug occurs. + call leaderf#colorscheme#popup#link_cursor("Lf_hl_popup_cursor") + highlight def Lf_hl_popup_prompt guifg=#fabd2f guibg=NONE gui=NONE ctermfg=214 ctermbg=NONE cterm=NONE highlight def Lf_hl_popup_spin guifg=#e6e666 guibg=NONE gui=NONE ctermfg=185 ctermbg=NONE cterm=NONE highlight def Lf_hl_popup_normalMode guifg=#282828 guibg=#a89984 gui=bold ctermfg=235 ctermbg=137 cterm=bold @@ -137,7 +140,10 @@ else " Lf_hl_popup_blank is the wincolor of statusline window call leaderf#colorscheme#popup#link_no_reverse("Lf_hl_popup_blank", "StatusLineNC") - highlight def link Lf_hl_popup_cursor Cursor + " nvim has a weird bug, if `hi Cursor cterm=reverse gui=reverse` + " and `hi def link Lf_hl_popup_cursor Cursor`, the bug occurs. + call leaderf#colorscheme#popup#link_cursor("Lf_hl_popup_cursor") + highlight def Lf_hl_popup_prompt guifg=#c77400 guibg=NONE gui=NONE ctermfg=172 cterm=NONE highlight def Lf_hl_popup_spin guifg=#f12d2d guibg=NONE gui=NONE ctermfg=196 cterm=NONE highlight def Lf_hl_popup_normalMode guifg=#fbf1c7 guibg=#a89984 gui=bold ctermfg=230 ctermbg=137 cterm=bold diff --git a/autoload/leaderf/colorscheme/popup/gruvbox_material.vim b/autoload/leaderf/colorscheme/popup/gruvbox_material.vim index 88d8fbed..93a1520c 100644 --- a/autoload/leaderf/colorscheme/popup/gruvbox_material.vim +++ b/autoload/leaderf/colorscheme/popup/gruvbox_material.vim @@ -36,7 +36,10 @@ if &background ==# 'dark' highlight Lf_hl_popup_lineInfo guifg=#ddc7a1 guibg=#665c54 gui=NONE ctermfg=223 ctermbg=241 cterm=NONE highlight Lf_hl_popup_total guifg=#282828 guibg=#a89984 gui=NONE ctermfg=235 ctermbg=246 cterm=NONE - highlight def link Lf_hl_popup_cursor Cursor + " nvim has a weird bug, if `hi Cursor cterm=reverse gui=reverse` + " and `hi def link Lf_hl_popup_cursor Cursor`, the bug occurs. + call leaderf#colorscheme#popup#link_cursor("Lf_hl_popup_cursor") + " the color of the cursorline highlight def Lf_hl_cursorline guifg=#d4be98 guibg=NONE gui=NONE ctermfg=223 ctermbg=NONE cterm=NONE @@ -156,7 +159,10 @@ else highlight Lf_hl_popup_lineInfo guifg=#4f3829 guibg=#bdae93 gui=NONE ctermfg=237 ctermbg=248 cterm=NONE highlight Lf_hl_popup_total guifg=#ebdbb2 guibg=#7c6f64 gui=NONE ctermfg=235 ctermbg=243 cterm=NONE - highlight def link Lf_hl_popup_cursor Cursor + " nvim has a weird bug, if `hi Cursor cterm=reverse gui=reverse` + " and `hi def link Lf_hl_popup_cursor Cursor`, the bug occurs. + call leaderf#colorscheme#popup#link_cursor("Lf_hl_popup_cursor") + " the color of the cursorline highlight def Lf_hl_cursorline guifg=#654735 guibg=NONE gui=NONE ctermfg=237 ctermbg=NONE cterm=NONE From 37dd4972bd8412cbbc32eed83566dac5d71173cc Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 6 Jul 2023 13:02:49 +0800 Subject: [PATCH 086/365] let popup preview window not cover the statusline if let g:Lf_PopupPreviewPosition = 'bottom' --- autoload/leaderf/python/leaderf/manager.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 15e06525..f2f63787 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -487,7 +487,7 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): statusline_height = 0 row = float_win_row + float_window.height + statusline_height col = float_win_col - height = int(lfEval("&lines")) - row - 2 + height = int(lfEval("&lines")) - row - 3 if height < 1: return width = float_window.width @@ -628,7 +628,7 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): statusline_height = 0 line = int(popup_pos["line"]) + int(popup_pos["height"]) + statusline_height pos = "topleft" - maxheight = int(lfEval("&lines")) - line + maxheight = int(lfEval("&lines")) - line - 2 if maxheight < 1: return From 6dfa00b5ad4e842e0ca76754e1f27fc29200320e Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 6 Jul 2023 14:01:06 +0800 Subject: [PATCH 087/365] update color --- autoload/leaderf/colorscheme/popup.vim | 4 ++-- syntax/leaderf.vim | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/autoload/leaderf/colorscheme/popup.vim b/autoload/leaderf/colorscheme/popup.vim index 2c5d1c0a..b9f062a6 100644 --- a/autoload/leaderf/colorscheme/popup.vim +++ b/autoload/leaderf/colorscheme/popup.vim @@ -187,8 +187,8 @@ endfunction function! leaderf#colorscheme#popup#link_cursor(from) abort if has("nvim") let sid = synIDtrans(hlID("Cursor")) - if synIDattr(sid, "reverse") || synIDattr(sid, "inverse") - exec printf("hi %s gui=reverse guifg=NONE guibg=NONE cterm=reverse ctermfg=NONE ctermbg=NONE", a:from) + if synIDattr(sid, "bg") == '' || synIDattr(sid, "fg") == '' + exec printf("hi def %s gui=reverse guifg=NONE guibg=NONE cterm=reverse ctermfg=NONE ctermbg=NONE", a:from) else exec printf("hi def link %s Cursor", a:from) endif diff --git a/syntax/leaderf.vim b/syntax/leaderf.vim index e78b5c8f..58409fc9 100644 --- a/syntax/leaderf.vim +++ b/syntax/leaderf.vim @@ -34,10 +34,10 @@ function! g:LfDefineDefaultColors() abort highlight def Lf_hl_cursorline guifg=Yellow guibg=NONE gui=NONE ctermfg=226 ctermbg=NONE cterm=NONE " the color of matching character - highlight def Lf_hl_match guifg=SpringGreen guibg=NONE gui=bold ctermfg=85 ctermbg=NONE cterm=bold + highlight def Lf_hl_match guifg=#afff5f guibg=NONE gui=bold ctermfg=155 ctermbg=NONE cterm=bold " the color of matching character in `And mode` - highlight def Lf_hl_match0 guifg=SpringGreen guibg=NONE gui=bold ctermfg=85 ctermbg=NONE cterm=bold + highlight def Lf_hl_match0 guifg=#afff5f guibg=NONE gui=bold ctermfg=155 ctermbg=NONE cterm=bold highlight def Lf_hl_match1 guifg=#fe8019 guibg=NONE gui=bold ctermfg=208 ctermbg=NONE cterm=bold highlight def Lf_hl_match2 guifg=#3ff5d1 guibg=NONE gui=bold ctermfg=50 ctermbg=NONE cterm=bold highlight def Lf_hl_match3 guifg=#ff7272 guibg=NONE gui=bold ctermfg=203 ctermbg=NONE cterm=bold From dd45011f87e9fc9bb6b3e78eb018b992c240be1b Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 6 Jul 2023 14:20:13 +0800 Subject: [PATCH 088/365] hybrid has `hi Cursor guifg=bg guibg=fg` --- autoload/leaderf/colorscheme/popup.vim | 10 +++------- autoload/leaderf/python/leaderf/cli.py | 5 +---- syntax/leaderf.vim | 2 +- 3 files changed, 5 insertions(+), 12 deletions(-) diff --git a/autoload/leaderf/colorscheme/popup.vim b/autoload/leaderf/colorscheme/popup.vim index b9f062a6..6023ed77 100644 --- a/autoload/leaderf/colorscheme/popup.vim +++ b/autoload/leaderf/colorscheme/popup.vim @@ -185,13 +185,9 @@ endfunction " nvim has a weird bug, if `hi Cursor cterm=reverse gui=reverse` " and `hi def link Lf_hl_popup_cursor Cursor`, the bug occurs. function! leaderf#colorscheme#popup#link_cursor(from) abort - if has("nvim") - let sid = synIDtrans(hlID("Cursor")) - if synIDattr(sid, "bg") == '' || synIDattr(sid, "fg") == '' - exec printf("hi def %s gui=reverse guifg=NONE guibg=NONE cterm=reverse ctermfg=NONE ctermbg=NONE", a:from) - else - exec printf("hi def link %s Cursor", a:from) - endif + let sid = synIDtrans(hlID("Cursor")) + if synIDattr(sid, "bg") == '' || synIDattr(sid, "fg") == '' + exec printf("hi def %s gui=reverse guifg=NONE guibg=NONE cterm=reverse ctermfg=NONE ctermbg=NONE", a:from) else exec printf("hi def link %s Cursor", a:from) endif diff --git a/autoload/leaderf/python/leaderf/cli.py b/autoload/leaderf/python/leaderf/cli.py index 5344b30a..e37c9248 100644 --- a/autoload/leaderf/python/leaderf/cli.py +++ b/autoload/leaderf/python/leaderf/cli.py @@ -326,10 +326,7 @@ def _buildPrompt(self): else: self._start_time = datetime.now() if self._blinkon: - if self._instance.getWinPos() in ('popup', 'floatwin'): - lfCmd("hi! default link Lf_hl_cursor Lf_hl_popup_cursor") - else: - lfCmd("hi! default link Lf_hl_cursor Cursor") + lfCmd("hi! default link Lf_hl_cursor Lf_hl_popup_cursor") else: lfCmd("hi! default link Lf_hl_cursor NONE") diff --git a/syntax/leaderf.vim b/syntax/leaderf.vim index 58409fc9..bd44ab01 100644 --- a/syntax/leaderf.vim +++ b/syntax/leaderf.vim @@ -30,7 +30,7 @@ endif let b:current_syntax = "leaderf" function! g:LfDefineDefaultColors() abort - highlight def link Lf_hl_popup_cursor Cursor + call leaderf#colorscheme#popup#link_cursor("Lf_hl_popup_cursor") highlight def Lf_hl_cursorline guifg=Yellow guibg=NONE gui=NONE ctermfg=226 ctermbg=NONE cterm=NONE " the color of matching character From 94108fc48164e4fb61e14e56a4aa37b36f458587 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 6 Jul 2023 16:00:04 +0800 Subject: [PATCH 089/365] update colorscheme --- .../leaderf/colorscheme/popup/default.vim | 10 ++ .../colorscheme/popup/gruvbox_default.vim | 10 ++ .../colorscheme/popup/gruvbox_material.vim | 10 ++ .../leaderf/colorscheme/popup/onedark.vim | 75 +++++++- .../leaderf/colorscheme/popup/solarized.vim | 164 +++++++++++++++++- syntax/leaderf.vim | 105 +---------- 6 files changed, 271 insertions(+), 103 deletions(-) diff --git a/autoload/leaderf/colorscheme/popup/default.vim b/autoload/leaderf/colorscheme/popup/default.vim index 720e548b..3b6ca4e4 100644 --- a/autoload/leaderf/colorscheme/popup/default.vim +++ b/autoload/leaderf/colorscheme/popup/default.vim @@ -131,6 +131,11 @@ if &background ==? 'dark' highlight def link Lf_hl_loclistFileName Directory highlight def link Lf_hl_loclistLineNumber Constant highlight def link Lf_hl_loclistColumnNumber Constant + + highlight def link Lf_hl_jumpsTitle Title + highlight def link Lf_hl_jumpsNumber Number + highlight def link Lf_hl_jumpsLineCol String + highlight def link Lf_hl_jumpsIndicator Type else " Lf_hl_popup_inputText is the wincolor of input window highlight def Lf_hl_popup_inputText guifg=#525252 guibg=#f4f3d7 gui=NONE ctermfg=239 ctermbg=230 cterm=NONE @@ -249,4 +254,9 @@ else highlight def link Lf_hl_loclistFileName Directory highlight def link Lf_hl_loclistLineNumber Constant highlight def link Lf_hl_loclistColumnNumber Constant + + highlight def link Lf_hl_jumpsTitle Title + highlight def link Lf_hl_jumpsNumber Number + highlight def link Lf_hl_jumpsLineCol String + highlight def link Lf_hl_jumpsIndicator Type endif diff --git a/autoload/leaderf/colorscheme/popup/gruvbox_default.vim b/autoload/leaderf/colorscheme/popup/gruvbox_default.vim index 73679106..f5f97b7b 100644 --- a/autoload/leaderf/colorscheme/popup/gruvbox_default.vim +++ b/autoload/leaderf/colorscheme/popup/gruvbox_default.vim @@ -130,6 +130,11 @@ if &background ==? 'dark' highlight def link Lf_hl_loclistFileName Directory highlight def link Lf_hl_loclistLineNumber Constant highlight def link Lf_hl_loclistColumnNumber Constant + + highlight def link Lf_hl_jumpsTitle Title + highlight def link Lf_hl_jumpsNumber Number + highlight def link Lf_hl_jumpsLineCol String + highlight def link Lf_hl_jumpsIndicator Type else " Lf_hl_popup_inputText is the wincolor of input window highlight def Lf_hl_popup_inputText guifg=#504945 guibg=#faefb2 gui=NONE ctermfg=239 ctermbg=253 cterm=NONE @@ -248,4 +253,9 @@ else highlight def link Lf_hl_loclistFileName Directory highlight def link Lf_hl_loclistLineNumber Constant highlight def link Lf_hl_loclistColumnNumber Constant + + highlight def link Lf_hl_jumpsTitle Title + highlight def link Lf_hl_jumpsNumber Number + highlight def link Lf_hl_jumpsLineCol String + highlight def link Lf_hl_jumpsIndicator Type endif diff --git a/autoload/leaderf/colorscheme/popup/gruvbox_material.vim b/autoload/leaderf/colorscheme/popup/gruvbox_material.vim index 93a1520c..7157c5af 100644 --- a/autoload/leaderf/colorscheme/popup/gruvbox_material.vim +++ b/autoload/leaderf/colorscheme/popup/gruvbox_material.vim @@ -130,6 +130,11 @@ if &background ==# 'dark' highlight def link Lf_hl_loclistFileName Directory highlight def link Lf_hl_loclistLineNumber Constant highlight def link Lf_hl_loclistColumnNumber Constant + + highlight def link Lf_hl_jumpsTitle Title + highlight def link Lf_hl_jumpsNumber Number + highlight def link Lf_hl_jumpsLineCol String + highlight def link Lf_hl_jumpsIndicator Type else if get(g:, 'gruvbox_material_background', 'medium') ==# 'hard' highlight Lf_hl_popup_inputText guifg=#4f3829 guibg=#f2e5bc gui=NONE ctermfg=237 ctermbg=228 cterm=NONE @@ -253,5 +258,10 @@ else highlight def link Lf_hl_loclistFileName Directory highlight def link Lf_hl_loclistLineNumber Constant highlight def link Lf_hl_loclistColumnNumber Constant + + highlight def link Lf_hl_jumpsTitle Title + highlight def link Lf_hl_jumpsNumber Number + highlight def link Lf_hl_jumpsLineCol String + highlight def link Lf_hl_jumpsIndicator Type endif diff --git a/autoload/leaderf/colorscheme/popup/onedark.vim b/autoload/leaderf/colorscheme/popup/onedark.vim index c5fe17b1..6d76d9f4 100644 --- a/autoload/leaderf/colorscheme/popup/onedark.vim +++ b/autoload/leaderf/colorscheme/popup/onedark.vim @@ -16,8 +16,6 @@ if &background ==? 'dark' highlight def Lf_hl_popup_lineInfo guifg=#ABB2BF ctermfg=145 guibg=#3E4452 ctermbg=237 highlight def Lf_hl_popup_total guifg=#2C323C ctermfg=236 guibg=#ABB2BF ctermbg=145 - call leaderf#colorscheme#popup#link_two("Lf_hl_popupBorder", "Normal", "VertSplit", 1) - highlight def Lf_hl_cursorline guifg=#ABB2BF ctermfg=145 guibg=NONE ctermbg=NONE highlight def Lf_hl_match guifg=#E06C75 ctermfg=204 guibg=NONE ctermbg=NONE gui=bold cterm=bold @@ -29,4 +27,77 @@ if &background ==? 'dark' highlight def Lf_hl_matchRefine guifg=#D19A66 ctermfg=173 highlight def Lf_hl_selection guifg=#2C323C ctermfg=236 guibg=#E5C07B ctermbg=180 gui=NONE cterm=NONE + + " the color of `Leaderf buffer` + highlight def link Lf_hl_bufNumber Constant + highlight def link Lf_hl_bufIndicators Statement + highlight def link Lf_hl_bufModified String + highlight def link Lf_hl_bufNomodifiable Comment + highlight def link Lf_hl_bufDirname Directory + + " the color of `Leaderf tag` + highlight def link Lf_hl_tagFile Directory + highlight def link Lf_hl_tagType Type + highlight def link Lf_hl_tagKeyword Keyword + + " the color of `Leaderf bufTag` + highlight def link Lf_hl_buftagKind Title + highlight def link Lf_hl_buftagScopeType Keyword + highlight def link Lf_hl_buftagScope Type + highlight def link Lf_hl_buftagDirname Directory + highlight def link Lf_hl_buftagLineNum Constant + highlight def link Lf_hl_buftagCode Comment + + " the color of `Leaderf function` + highlight def link Lf_hl_funcKind Title + highlight def link Lf_hl_funcReturnType Type + highlight def link Lf_hl_funcScope Keyword + highlight def link Lf_hl_funcName Function + highlight def link Lf_hl_funcDirname Directory + highlight def link Lf_hl_funcLineNum Constant + + " the color of `Leaderf line` + highlight def link Lf_hl_lineLocation Comment + + " the color of `Leaderf self` + highlight def link Lf_hl_selfIndex Constant + highlight def link Lf_hl_selfDescription Comment + + " the color of `Leaderf help` + highlight def link Lf_hl_helpTagfile Comment + + " the color of `Leaderf rg` + highlight def link Lf_hl_rgFileName Directory + highlight def link Lf_hl_rgLineNumber Constant + " the color of line number if '-A' or '-B' or '-C' is in the options list + " of `Leaderf rg` + highlight def link Lf_hl_rgLineNumber2 Folded + " the color of column number if '--column' in g:Lf_RgConfig + highlight def link Lf_hl_rgColumnNumber Constant + highlight def Lf_hl_rgHighlight guifg=#000000 guibg=#cccc66 gui=NONE ctermfg=16 ctermbg=185 cterm=NONE + + " the color of `Leaderf gtags` + highlight def link Lf_hl_gtagsFileName Directory + highlight def link Lf_hl_gtagsLineNumber Constant + highlight def Lf_hl_gtagsHighlight guifg=#000000 guibg=#cccc66 gui=NONE ctermfg=16 ctermbg=185 cterm=NONE + + highlight def link Lf_hl_previewTitle Statusline + call leaderf#colorscheme#popup#link_two("Lf_hl_popupBorder", "Normal", "VertSplit", 1) + + highlight def link Lf_hl_winNumber Constant + highlight def link Lf_hl_winIndicators Statement + highlight def link Lf_hl_winModified String + highlight def link Lf_hl_winNomodifiable Comment + highlight def link Lf_hl_winDirname Directory + highlight def link Lf_hl_quickfixFileName Directory + highlight def link Lf_hl_quickfixLineNumber Constant + highlight def link Lf_hl_quickfixColumnNumber Constant + highlight def link Lf_hl_loclistFileName Directory + highlight def link Lf_hl_loclistLineNumber Constant + highlight def link Lf_hl_loclistColumnNumber Constant + + highlight def link Lf_hl_jumpsTitle Title + highlight def link Lf_hl_jumpsNumber Number + highlight def link Lf_hl_jumpsLineCol String + highlight def link Lf_hl_jumpsIndicator Type endif diff --git a/autoload/leaderf/colorscheme/popup/solarized.vim b/autoload/leaderf/colorscheme/popup/solarized.vim index 4fd40744..1ffba146 100644 --- a/autoload/leaderf/colorscheme/popup/solarized.vim +++ b/autoload/leaderf/colorscheme/popup/solarized.vim @@ -16,8 +16,6 @@ if &background ==? 'dark' highlight def Lf_hl_popup_lineInfo guifg=#eee8d5 ctermfg=224 guibg=#657b83 ctermbg=66 highlight def Lf_hl_popup_total guifg=#fdf6e3 ctermfg=230 guibg=#93a1a1 ctermbg=109 - call leaderf#colorscheme#popup#link_two("Lf_hl_popupBorder", "Normal", "VertSplit", 1) - highlight def Lf_hl_cursorline guifg=#fdf6e3 ctermfg=230 highlight def Lf_hl_match guifg=#b58900 ctermfg=136 guibg=NONE ctermbg=NONE gui=bold cterm=bold @@ -27,6 +25,86 @@ if &background ==? 'dark' highlight def Lf_hl_match3 guifg=#2aa198 ctermfg=36 guibg=NONE ctermbg=NONE gui=bold cterm=bold highlight def Lf_hl_match4 guifg=#859900 ctermfg=100 guibg=NONE ctermbg=NONE gui=bold cterm=bold highlight def Lf_hl_matchRefine guifg=#cb4b16 ctermfg=166 + + " the color of help in normal mode when is pressed + highlight def link Lf_hl_help Comment + highlight def link Lf_hl_helpCmd Identifier + + " the color when select multiple lines + highlight def Lf_hl_selection guifg=#4d4d4d guibg=#a5eb84 gui=NONE ctermfg=239 ctermbg=156 cterm=NONE + + " the color of `Leaderf buffer` + highlight def link Lf_hl_bufNumber Constant + highlight def link Lf_hl_bufIndicators Statement + highlight def link Lf_hl_bufModified String + highlight def link Lf_hl_bufNomodifiable Comment + highlight def link Lf_hl_bufDirname Directory + + " the color of `Leaderf tag` + highlight def link Lf_hl_tagFile Directory + highlight def link Lf_hl_tagType Type + highlight def link Lf_hl_tagKeyword Keyword + + " the color of `Leaderf bufTag` + highlight def link Lf_hl_buftagKind Title + highlight def link Lf_hl_buftagScopeType Keyword + highlight def link Lf_hl_buftagScope Type + highlight def link Lf_hl_buftagDirname Directory + highlight def link Lf_hl_buftagLineNum Constant + highlight def link Lf_hl_buftagCode Comment + + " the color of `Leaderf function` + highlight def link Lf_hl_funcKind Title + highlight def link Lf_hl_funcReturnType Type + highlight def link Lf_hl_funcScope Keyword + highlight def link Lf_hl_funcName Function + highlight def link Lf_hl_funcDirname Directory + highlight def link Lf_hl_funcLineNum Constant + + " the color of `Leaderf line` + highlight def link Lf_hl_lineLocation Comment + + " the color of `Leaderf self` + highlight def link Lf_hl_selfIndex Constant + highlight def link Lf_hl_selfDescription Comment + + " the color of `Leaderf help` + highlight def link Lf_hl_helpTagfile Comment + + " the color of `Leaderf rg` + highlight def link Lf_hl_rgFileName Directory + highlight def link Lf_hl_rgLineNumber Constant + " the color of line number if '-A' or '-B' or '-C' is in the options list + " of `Leaderf rg` + highlight def link Lf_hl_rgLineNumber2 Folded + " the color of column number if '--column' in g:Lf_RgConfig + highlight def link Lf_hl_rgColumnNumber Constant + highlight def Lf_hl_rgHighlight guifg=#4d4d4d guibg=#cccc66 gui=NONE ctermfg=239 ctermbg=185 cterm=NONE + + " the color of `Leaderf gtags` + highlight def link Lf_hl_gtagsFileName Directory + highlight def link Lf_hl_gtagsLineNumber Constant + highlight def Lf_hl_gtagsHighlight guifg=#4d4d4d guibg=#cccc66 gui=NONE ctermfg=239 ctermbg=185 cterm=NONE + + highlight def link Lf_hl_previewTitle Statusline + call leaderf#colorscheme#popup#link_two("Lf_hl_popupBorder", "Normal", "VertSplit", 1) + + highlight def link Lf_hl_winNumber Constant + highlight def link Lf_hl_winIndicators Statement + highlight def link Lf_hl_winModified String + highlight def link Lf_hl_winNomodifiable Comment + highlight def link Lf_hl_winDirname Directory + highlight def link Lf_hl_quickfixFileName Directory + highlight def link Lf_hl_quickfixLineNumber Constant + highlight def link Lf_hl_quickfixColumnNumber Constant + highlight def link Lf_hl_loclistFileName Directory + highlight def link Lf_hl_loclistLineNumber Constant + highlight def link Lf_hl_loclistColumnNumber Constant + + highlight def link Lf_hl_jumpsTitle Title + highlight def link Lf_hl_jumpsNumber Number + highlight def link Lf_hl_jumpsLineCol String + highlight def link Lf_hl_jumpsIndicator Type else highlight def Lf_hl_popup_inputText guifg=#657b83 ctermfg=66 guibg=#fdf6e3 ctermbg=230 call leaderf#colorscheme#popup#link_no_reverse("Lf_hl_popup_window", "Normal") @@ -45,8 +123,6 @@ else highlight def Lf_hl_popup_lineInfo guifg=#eee8d5 ctermfg=224 guibg=#839496 ctermbg=102 highlight def Lf_hl_popup_total guifg=#fdf6e3 ctermfg=230 guibg=#586e75 ctermbg=60 - call leaderf#colorscheme#popup#link_two("Lf_hl_popupBorder", "Normal", "VertSplit", 1) - highlight def Lf_hl_cursorline guifg=#002b36 ctermfg=17 highlight def Lf_hl_match guifg=#b58900 ctermfg=136 guibg=NONE ctermbg=NONE gui=bold cterm=bold @@ -56,4 +132,84 @@ else highlight def Lf_hl_match3 guifg=#2aa198 ctermfg=36 guibg=NONE ctermbg=NONE gui=bold cterm=bold highlight def Lf_hl_match4 guifg=#859900 ctermfg=100 guibg=NONE ctermbg=NONE gui=bold cterm=bold highlight def Lf_hl_matchRefine guifg=#cb4b16 ctermfg=166 guibg=NONE ctermbg=NONE gui=bold cterm=bold + + " the color of help in normal mode when is pressed + highlight def link Lf_hl_help Comment + highlight def link Lf_hl_helpCmd Identifier + + " the color when select multiple lines + highlight def Lf_hl_selection guifg=#4d4d4d guibg=#a5eb84 gui=NONE ctermfg=239 ctermbg=156 cterm=NONE + + " the color of `Leaderf buffer` + highlight def link Lf_hl_bufNumber Constant + highlight def link Lf_hl_bufIndicators Statement + highlight def link Lf_hl_bufModified String + highlight def link Lf_hl_bufNomodifiable Comment + highlight def link Lf_hl_bufDirname Directory + + " the color of `Leaderf tag` + highlight def link Lf_hl_tagFile Directory + highlight def link Lf_hl_tagType Type + highlight def link Lf_hl_tagKeyword Keyword + + " the color of `Leaderf bufTag` + highlight def link Lf_hl_buftagKind Title + highlight def link Lf_hl_buftagScopeType Keyword + highlight def link Lf_hl_buftagScope Type + highlight def link Lf_hl_buftagDirname Directory + highlight def link Lf_hl_buftagLineNum Constant + highlight def link Lf_hl_buftagCode Comment + + " the color of `Leaderf function` + highlight def link Lf_hl_funcKind Title + highlight def link Lf_hl_funcReturnType Type + highlight def link Lf_hl_funcScope Keyword + highlight def link Lf_hl_funcName Function + highlight def link Lf_hl_funcDirname Directory + highlight def link Lf_hl_funcLineNum Constant + + " the color of `Leaderf line` + highlight def link Lf_hl_lineLocation Comment + + " the color of `Leaderf self` + highlight def link Lf_hl_selfIndex Constant + highlight def link Lf_hl_selfDescription Comment + + " the color of `Leaderf help` + highlight def link Lf_hl_helpTagfile Comment + + " the color of `Leaderf rg` + highlight def link Lf_hl_rgFileName Directory + highlight def link Lf_hl_rgLineNumber Constant + " the color of line number if '-A' or '-B' or '-C' is in the options list + " of `Leaderf rg` + highlight def link Lf_hl_rgLineNumber2 Folded + " the color of column number if '--column' in g:Lf_RgConfig + highlight def link Lf_hl_rgColumnNumber Constant + highlight def Lf_hl_rgHighlight guifg=#4d4d4d guibg=#cccc66 gui=NONE ctermfg=239 ctermbg=185 cterm=NONE + + " the color of `Leaderf gtags` + highlight def link Lf_hl_gtagsFileName Directory + highlight def link Lf_hl_gtagsLineNumber Constant + highlight def Lf_hl_gtagsHighlight guifg=#4d4d4d guibg=#cccc66 gui=NONE ctermfg=239 ctermbg=185 cterm=NONE + + highlight def link Lf_hl_previewTitle Statusline + call leaderf#colorscheme#popup#link_two("Lf_hl_popupBorder", "Normal", "VertSplit", 1) + + highlight def link Lf_hl_winNumber Constant + highlight def link Lf_hl_winIndicators Statement + highlight def link Lf_hl_winModified String + highlight def link Lf_hl_winNomodifiable Comment + highlight def link Lf_hl_winDirname Directory + highlight def link Lf_hl_quickfixFileName Directory + highlight def link Lf_hl_quickfixLineNumber Constant + highlight def link Lf_hl_quickfixColumnNumber Constant + highlight def link Lf_hl_loclistFileName Directory + highlight def link Lf_hl_loclistLineNumber Constant + highlight def link Lf_hl_loclistColumnNumber Constant + + highlight def link Lf_hl_jumpsTitle Title + highlight def link Lf_hl_jumpsNumber Number + highlight def link Lf_hl_jumpsLineCol String + highlight def link Lf_hl_jumpsIndicator Type endif diff --git a/syntax/leaderf.vim b/syntax/leaderf.vim index bd44ab01..f35bc8c7 100644 --- a/syntax/leaderf.vim +++ b/syntax/leaderf.vim @@ -29,102 +29,13 @@ endif let b:current_syntax = "leaderf" +" define the highlight groups +" new highlight groups will be defined in autoload/leaderf/colorscheme/popup/default.vim +" there are also duplicates defined here so that other colorschemes can also +" own these highlight groups function! g:LfDefineDefaultColors() abort - call leaderf#colorscheme#popup#link_cursor("Lf_hl_popup_cursor") - highlight def Lf_hl_cursorline guifg=Yellow guibg=NONE gui=NONE ctermfg=226 ctermbg=NONE cterm=NONE - - " the color of matching character - highlight def Lf_hl_match guifg=#afff5f guibg=NONE gui=bold ctermfg=155 ctermbg=NONE cterm=bold - - " the color of matching character in `And mode` - highlight def Lf_hl_match0 guifg=#afff5f guibg=NONE gui=bold ctermfg=155 ctermbg=NONE cterm=bold - highlight def Lf_hl_match1 guifg=#fe8019 guibg=NONE gui=bold ctermfg=208 ctermbg=NONE cterm=bold - highlight def Lf_hl_match2 guifg=#3ff5d1 guibg=NONE gui=bold ctermfg=50 ctermbg=NONE cterm=bold - highlight def Lf_hl_match3 guifg=#ff7272 guibg=NONE gui=bold ctermfg=203 ctermbg=NONE cterm=bold - highlight def Lf_hl_match4 guifg=#43b9f0 guibg=NONE gui=bold ctermfg=74 ctermbg=NONE cterm=bold - - " the color of matching character in nameOnly mode when ';' is typed - highlight def Lf_hl_matchRefine gui=bold guifg=Magenta cterm=bold ctermfg=201 - - " the color of help in normal mode when is pressed - highlight def link Lf_hl_help Comment - highlight def link Lf_hl_helpCmd Identifier - - " the color when select multiple lines - highlight def Lf_hl_selection guifg=Black guibg=#a5eb84 gui=NONE ctermfg=Black ctermbg=156 cterm=NONE - - " the color of `Leaderf buffer` - highlight def link Lf_hl_bufNumber Constant - highlight def link Lf_hl_bufIndicators Statement - highlight def link Lf_hl_bufModified String - highlight def link Lf_hl_bufNomodifiable Comment - highlight def link Lf_hl_bufDirname Directory - - " the color of `Leaderf tag` - highlight def link Lf_hl_tagFile Directory - highlight def link Lf_hl_tagType Type - highlight def link Lf_hl_tagKeyword Keyword - - " the color of `Leaderf bufTag` - highlight def link Lf_hl_buftagKind Title - highlight def link Lf_hl_buftagScopeType Keyword - highlight def link Lf_hl_buftagScope Type - highlight def link Lf_hl_buftagDirname Directory - highlight def link Lf_hl_buftagLineNum Constant - highlight def link Lf_hl_buftagCode Comment - - " the color of `Leaderf function` - highlight def link Lf_hl_funcKind Title - highlight def link Lf_hl_funcReturnType Type - highlight def link Lf_hl_funcScope Keyword - highlight def link Lf_hl_funcName Function - highlight def link Lf_hl_funcDirname Directory - highlight def link Lf_hl_funcLineNum Constant - - " the color of `Leaderf line` - highlight def link Lf_hl_lineLocation Comment - - " the color of `Leaderf self` - highlight def link Lf_hl_selfIndex Constant - highlight def link Lf_hl_selfDescription Comment - - " the color of `Leaderf help` - highlight def link Lf_hl_helpTagfile Comment - - " the color of `Leaderf rg` - highlight def link Lf_hl_rgFileName Directory - highlight def link Lf_hl_rgLineNumber Constant - " the color of line number if '-A' or '-B' or '-C' is in the options list - " of `Leaderf rg` - highlight def link Lf_hl_rgLineNumber2 Folded - " the color of column number if '--column' in g:Lf_RgConfig - highlight def link Lf_hl_rgColumnNumber Constant - highlight def Lf_hl_rgHighlight guifg=#000000 guibg=#cccc66 gui=NONE ctermfg=16 ctermbg=185 cterm=NONE - - " the color of `Leaderf gtags` - highlight def link Lf_hl_gtagsFileName Directory - highlight def link Lf_hl_gtagsLineNumber Constant - highlight def Lf_hl_gtagsHighlight guifg=#000000 guibg=#cccc66 gui=NONE ctermfg=16 ctermbg=185 cterm=NONE - - highlight def link Lf_hl_previewTitle Statusline - highlight def link Lf_hl_popupBorder VertSplit - - highlight def link Lf_hl_winNumber Constant - highlight def link Lf_hl_winIndicators Statement - highlight def link Lf_hl_winModified String - highlight def link Lf_hl_winNomodifiable Comment - highlight def link Lf_hl_winDirname Directory - - highlight def link Lf_hl_quickfixFileName Directory - highlight def link Lf_hl_quickfixLineNumber Constant - highlight def link Lf_hl_quickfixColumnNumber Constant - - highlight def link Lf_hl_loclistFileName Directory - highlight def link Lf_hl_loclistLineNumber Constant - highlight def link Lf_hl_loclistColumnNumber Constant - - highlight def link Lf_hl_jumpsTitle Title - highlight def link Lf_hl_jumpsNumber Number - highlight def link Lf_hl_jumpsLineCol String - highlight def link Lf_hl_jumpsIndicator Type + "highlight def link Lf_hl_jumpsTitle Title + "highlight def link Lf_hl_jumpsNumber Number + "highlight def link Lf_hl_jumpsLineCol String + "highlight def link Lf_hl_jumpsIndicator Type endfunction From a87d0a303a3c3705277daedd8c5a6ce34f045993 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 6 Jul 2023 18:02:48 +0800 Subject: [PATCH 090/365] change the default value of g:Lf_PopupPreviewPosition to 'right' --- autoload/leaderf/python/leaderf/instance.py | 14 +++++++++++--- autoload/leaderf/python/leaderf/manager.py | 7 +++---- doc/leaderf.txt | 2 +- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/autoload/leaderf/python/leaderf/instance.py b/autoload/leaderf/python/leaderf/instance.py index 0f53da72..2c6675e1 100644 --- a/autoload/leaderf/python/leaderf/instance.py +++ b/autoload/leaderf/python/leaderf/instance.py @@ -363,7 +363,7 @@ def _createPopupWindow(self, clear): buf_number = int(lfEval("bufadd('{}')".format(escQuote(self._buffer_name)))) - preview_pos = lfEval("get(g:, 'Lf_PopupPreviewPosition', 'top')") + preview_pos = lfEval("get(g:, 'Lf_PopupPreviewPosition', 'right')") width = lfEval("get(g:, 'Lf_PopupWidth', 0)") width = self._arguments.get("--popup-width", [width])[0] width = width.strip('"').strip("'") @@ -372,7 +372,7 @@ def _createPopupWindow(self, clear): if preview_pos.lower() in ('right', 'left'): maxwidth = int(int(lfEval("&columns")) * 2 // 5) else: - maxwidth = int(int(lfEval("&columns")) * 2 // 3) + maxwidth = int(int(lfEval("&columns")) * 0.618) elif width < 1: maxwidth = int(int(lfEval("&columns")) * width) maxwidth = max(20, maxwidth) @@ -402,7 +402,12 @@ def _createPopupWindow(self, clear): line, col = [int(i) for i in lfEval("get(g:, 'Lf_PopupPosition', [0, 0])")] if line == 0: - line = (int(lfEval("&lines")) - 2 - maxheight) // 2 + if preview_pos.lower() == 'top': + line = (int(lfEval("&lines")) - 2 - maxheight) * 4 // 5 + elif preview_pos.lower() == 'bottom': + line = (int(lfEval("&lines")) - 2 - maxheight) // 5 + else: + line = (int(lfEval("&lines")) - 2 - maxheight) // 2 else: line = min(line, int(lfEval("&lines")) - maxheight) @@ -417,6 +422,9 @@ def _createPopupWindow(self, clear): col += maxwidth + 1 else: col = (int(lfEval("&columns")) - maxwidth) // 2 + + # to the left a bit + col -= 3 else: col = min(col, int(lfEval("&columns")) - maxwidth) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index f2f63787..e856e3f8 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -116,7 +116,7 @@ def __init__(self): self._preview_filetype = None if lfEval("has('patch-8.1.1615') || has('nvim-0.4.2')") == '0': lfCmd("let g:Lf_PreviewInPopup = 0") - if lfEval("get(g:, 'Lf_PopupPreviewPosition', 'top')").lower() == 'bottom': + if lfEval("get(g:, 'Lf_PopupPreviewPosition', 'right')").lower() == 'bottom': lfCmd("let g:Lf_PopupAutoAdjustHeight = 0") @@ -467,7 +467,7 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): float_win_col = int(float(lfEval("nvim_win_get_config(%d).col" % float_window.id))) float_win_height = int(float(lfEval("nvim_win_get_config(%d).height" % float_window.id))) float_win_width= int(float(lfEval("nvim_win_get_config(%d).width" % float_window.id))) - preview_pos = lfEval("get(g:, 'Lf_PopupPreviewPosition', 'top')") + preview_pos = lfEval("get(g:, 'Lf_PopupPreviewPosition', 'right')") popup_borders = lfEval("g:Lf_PopupBorders") borderchars = [ [popup_borders[4], "Lf_hl_popupBorder"], @@ -527,7 +527,6 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): col = float_win_col if lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1': row -= 1 - col -= 2 height = self._getInstance().getPopupHeight() + 1 if width <= 0: width = float_win_width @@ -618,7 +617,7 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): return buffer_len = int(lfEval("len(content)")) - preview_pos = lfEval("get(g:, 'Lf_PopupPreviewPosition', 'top')") + preview_pos = lfEval("get(g:, 'Lf_PopupPreviewPosition', 'right')") if preview_pos.lower() == 'bottom': maxwidth = int(popup_pos["width"]) col = int(popup_pos["col"]) diff --git a/doc/leaderf.txt b/doc/leaderf.txt index 4ddeab90..2d3e1956 100644 --- a/doc/leaderf.txt +++ b/doc/leaderf.txt @@ -833,7 +833,7 @@ g:Lf_PopupPreviewPosition *g:Lf_PopupPreviewPosition* 'cursor': the preview window is at the cursor position in the main LeaderF window. - Default value is 'top'. + Default value is 'right'. g:Lf_PopupColorscheme *g:Lf_PopupColorscheme* You can configure the colorscheme of LeaderF in popup mode. From 7415344a1c865afb31ecb2d20d6dc2ad1900a9a7 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 6 Jul 2023 22:42:09 +0800 Subject: [PATCH 091/365] fix issue #1012 non popup preview does not support automatic preview --- .../leaderf/python/leaderf/colorschemeExpl.py | 2 +- autoload/leaderf/python/leaderf/manager.py | 26 ++++++++++++------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/autoload/leaderf/python/leaderf/colorschemeExpl.py b/autoload/leaderf/python/leaderf/colorschemeExpl.py index 0cd45086..b60f3c42 100644 --- a/autoload/leaderf/python/leaderf/colorschemeExpl.py +++ b/autoload/leaderf/python/leaderf/colorschemeExpl.py @@ -123,7 +123,7 @@ def _beforeExit(self): super(ColorschemeExplManager, self)._beforeExit() def _previewResult(self, preview): - if not self._needPreview(preview): + if not self._needPreview(preview, True): return self._acceptSelection(self._getInstance().currentLine) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index e856e3f8..5394c08d 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -368,21 +368,23 @@ def _closePreviewPopup(self): self._preview_filetype = None def _previewResult(self, preview): - if lfEval("get(g:, 'Lf_PreviewInPopup', 0)") == '1': - if preview == False and self._orig_line == self._getInstance().currentLine: - return + preview_in_popup = (lfEval("get(g:, 'Lf_PreviewInPopup', 0)") == '1' + or self._getInstance().getWinPos() in ('popup', 'floatwin')) + + if preview == False and self._orig_line == self._getInstance().currentLine: + return self._orig_line = self._getInstance().currentLine - if not self._needPreview(preview): - if lfEval("get(g:, 'Lf_PreviewInPopup', 0)") == '1': + if not self._needPreview(preview, preview_in_popup): + if preview_in_popup: self._closePreviewPopup() return line_nr = self._getInstance().window.cursor[0] line = self._getInstance().buffer[line_nr - 1] - if lfEval("get(g:, 'Lf_PreviewInPopup', 0)") == '1': + if preview_in_popup: self._previewInPopup(line, self._getInstance().buffer, line_nr) return @@ -969,11 +971,15 @@ def _createPopupPreview(self, title, source, line_nr, jump_cmd=''): return True - def _needPreview(self, preview): + def _needPreview(self, preview, preview_in_popup): """ Args: preview: if True, always preview the result no matter what `g:Lf_PreviewResult` is. + + preview_in_popup: + whether preview in popup, if value is true, it means + (lfEval("get(g:, 'Lf_PreviewInPopup', 0)") == '1' or self._getInstance().getWinPos() in ('popup', 'floatwin')) """ if self._getInstance().isReverseOrder(): if self._getInstance().window.cursor[0] > len(self._getInstance().buffer) - self._help_length: @@ -984,9 +990,9 @@ def _needPreview(self, preview): if preview: return True - # # non popup mode does not support automatic preview - # if lfEval("get(g:, 'Lf_PreviewInPopup', 0)") == '0': - # return False + # non popup preview does not support automatic preview + if not preview_in_popup: + return False if "--auto-preview" in self._arguments: return True From 34b1f0fe417ccb133500840639d34f667161473d Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Fri, 7 Jul 2023 13:39:05 +0800 Subject: [PATCH 092/365] change the default value of g:Lf_PreviewInPopup to 1 --- README.md | 7 ------- autoload/leaderf/python/leaderf/anyExpl.py | 3 +++ autoload/leaderf/python/leaderf/manager.py | 4 ++-- doc/leaderf.txt | 2 +- 4 files changed, 6 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 48680e13..48eac37b 100644 --- a/README.md +++ b/README.md @@ -235,12 +235,6 @@ or add `--popup` after each subcommand, e.g., Leaderf file --popup ``` -It's better to set -```vim -let g:Lf_PreviewInPopup = 1 -``` -, so that you can also preview the result in a popup window. - Customization ------------- @@ -314,7 +308,6 @@ let g:Lf_UseVersionControlTool = 0 let g:Lf_IgnoreCurrentBufferName = 1 " popup mode let g:Lf_WindowPosition = 'popup' -let g:Lf_PreviewInPopup = 1 let g:Lf_StlSeparator = { 'left': "\ue0b0", 'right': "\ue0b2", 'font': "DejaVu Sans Mono for Powerline" } let g:Lf_PreviewResult = {'Function': 0, 'BufTag': 0 } diff --git a/autoload/leaderf/python/leaderf/anyExpl.py b/autoload/leaderf/python/leaderf/anyExpl.py index 854cc925..2a43511e 100644 --- a/autoload/leaderf/python/leaderf/anyExpl.py +++ b/autoload/leaderf/python/leaderf/anyExpl.py @@ -744,6 +744,9 @@ def _default_action(self, category, positional_args, arguments, *args, **kwargs) kwargs["arguments"] = arguments kwargs["positional_args"] = positional_args + if lfEval("has('patch-8.1.1615') || has('nvim-0.4.2')") == '0': + win_pos = "--bottom" + manager.startExplorer(win_pos[2:], *args, **kwargs) def start(self, arg_line, *args, **kwargs): diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 5394c08d..d0776cf9 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -368,7 +368,7 @@ def _closePreviewPopup(self): self._preview_filetype = None def _previewResult(self, preview): - preview_in_popup = (lfEval("get(g:, 'Lf_PreviewInPopup', 0)") == '1' + preview_in_popup = (lfEval("get(g:, 'Lf_PreviewInPopup', 1)") == '1' or self._getInstance().getWinPos() in ('popup', 'floatwin')) if preview == False and self._orig_line == self._getInstance().currentLine: @@ -979,7 +979,7 @@ def _needPreview(self, preview, preview_in_popup): preview_in_popup: whether preview in popup, if value is true, it means - (lfEval("get(g:, 'Lf_PreviewInPopup', 0)") == '1' or self._getInstance().getWinPos() in ('popup', 'floatwin')) + (lfEval("get(g:, 'Lf_PreviewInPopup', 1)") == '1' or self._getInstance().getWinPos() in ('popup', 'floatwin')) """ if self._getInstance().isReverseOrder(): if self._getInstance().window.cursor[0] > len(self._getInstance().buffer) - self._help_length: diff --git a/doc/leaderf.txt b/doc/leaderf.txt index 2d3e1956..20c48d0b 100644 --- a/doc/leaderf.txt +++ b/doc/leaderf.txt @@ -745,7 +745,7 @@ g:Lf_IgnoreCurrentBufferName *g:Lf_IgnoreCurrentBufferName* g:Lf_PreviewInPopup *g:Lf_PreviewInPopup* This option specifies whether to preview the result in a popup window. - Default value is 0. + Default value is 1. g:Lf_PreviewHorizontalPosition *g:Lf_PreviewHorizontalPosition* Specify where to locate the preview window horizontally. The value can be From edbadfdd99416d433cdb311ae4ce4b295556c791 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Fri, 7 Jul 2023 14:41:38 +0800 Subject: [PATCH 093/365] Using "2> NUL" redirection on Windows --- autoload/leaderf/python/leaderf/rgExpl.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/autoload/leaderf/python/leaderf/rgExpl.py b/autoload/leaderf/python/leaderf/rgExpl.py index 07ae5b68..2fc947bf 100644 --- a/autoload/leaderf/python/leaderf/rgExpl.py +++ b/autoload/leaderf/python/leaderf/rgExpl.py @@ -198,7 +198,10 @@ def getContent(self, *args, **kwargs): if "--live" in arguments_dict: pattern_list = [kwargs["pattern"]] - no_error_message = " 2>/dev/null" + if os.name == 'nt': + no_error_message = " 2>NUL" + else: + no_error_message = " 2>/dev/null" # --live implies -F if "-F" not in arguments_dict and "--no-fixed-strings" not in arguments_dict: zero_args_options += "-F " @@ -955,9 +958,9 @@ def startLiveGrep(self, win_pos, *args, **kwargs): self._cli.setPattern(pattern) if pattern: - content = self._getExplorer().getContent(*args, **kwargs, pattern=self._cli.pattern) - else: - content = self._getExplorer().getContent(*args, **kwargs) + kwargs['pattern'] = self._cli.pattern + + content = self._getExplorer().getContent(*args, **kwargs) # clear the buffer only when the content is not a list self._getInstance().enterBuffer(win_pos, not isinstance(content, list)) From 5d94b8ce87c8e9eff7d3b9476b2657c081d0e853 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Fri, 7 Jul 2023 18:04:40 +0800 Subject: [PATCH 094/365] fix a bug --- autoload/leaderf/python/leaderf/cli.py | 1 + autoload/leaderf/python/leaderf/manager.py | 2 ++ 2 files changed, 3 insertions(+) diff --git a/autoload/leaderf/python/leaderf/cli.py b/autoload/leaderf/python/leaderf/cli.py index e37c9248..d4526b9f 100644 --- a/autoload/leaderf/python/leaderf/cli.py +++ b/autoload/leaderf/python/leaderf/cli.py @@ -99,6 +99,7 @@ def _setDefaultMode(self): self._is_full_path = True def setCurrentMode(self, mode): + self._is_live = False if mode == 'NameOnly': # nameOnly mode self._is_fuzzy = True self._is_full_path = False diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index d0776cf9..3887c30e 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -237,6 +237,8 @@ def _setStlMode(self, the_mode=None, **kwargs): if the_mode is not None: mode = the_mode + elif self._cli._is_live: + mode = 'Fuzzy' self._getInstance().setStlMode(mode) self._cli.setCurrentMode(mode) From fa396ccecdd4e774d3a516a866d21f9faec7683c Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Mon, 10 Jul 2023 10:33:44 +0800 Subject: [PATCH 095/365] preview first line may take too long --- autoload/leaderf/python/leaderf/instance.py | 55 ++++++++++++++------- autoload/leaderf/python/leaderf/manager.py | 37 +++++++------- autoload/leaderf/python/leaderf/rgExpl.py | 6 ++- 3 files changed, 60 insertions(+), 38 deletions(-) diff --git a/autoload/leaderf/python/leaderf/instance.py b/autoload/leaderf/python/leaderf/instance.py index 2c6675e1..a48362a4 100644 --- a/autoload/leaderf/python/leaderf/instance.py +++ b/autoload/leaderf/python/leaderf/instance.py @@ -210,6 +210,20 @@ def statusline_win(self, statusline_win): def getWinIdList(self): return [win.id for win in self._popup_wins.values() if win is not None] + @property + def tabpage(self): + if self._popup_wins["input_win"] is None: + return None + else: + return self._popup_wins["input_win"].tabpage + + def valid(self): + for win in self._popup_wins.values(): + if win is None or not win.valid: + return False + + return True + #***************************************************** # LfInstance #***************************************************** @@ -339,24 +353,14 @@ def _setStatusline(self): .format(self.buffer.number, self._stl)) lfCmd("augroup END") - def _createPopupWindow(self, clear): - # `type(self._window_object) != type(vim.current.window)` is necessary, error occurs if - # `Leaderf file --popup` after `Leaderf file` without it. - if self._window_object is not None and type(self._window_object) != type(vim.current.window)\ - and isinstance(self._window_object, PopupWindow): # type is PopupWindow - if self._window_object.tabpage == vim.current.tabpage and lfEval("get(g:, 'Lf_Popup_VimResized', 0)") == '0' \ + def _createPopupWindow(self): + if lfEval("has('nvim')") == '0' and self._popup_instance.valid(): + if self._popup_instance.tabpage == vim.current.tabpage and lfEval("get(g:, 'Lf_Popup_VimResized', 0)") == '0' \ and "--popup-width" not in self._arguments and "--popup-height" not in self._arguments: - if self._popup_winid > 0 and self._window_object.valid: # invalid if cleared by popup_clear() - # clear the buffer first to avoid a flash - if clear and lfEval("g:Lf_RememberLastSearch") == '0' \ - and "--append" not in self._arguments \ - and "--recall" not in self._arguments: - self.buffer.options['modifiable'] = True - del self._buffer_object[:] - self.refreshPopupStatusline() - - self._popup_instance.show() - return + self._win_pos = "popup" + self._window_object = self._popup_instance.content_win + self._popup_instance.show() + return else: lfCmd("let g:Lf_Popup_VimResized = 0") self._popup_instance.close() @@ -1076,6 +1080,18 @@ def setStlRunning(self, running): self._running_status = 0 lfCmd("let g:Lf_{}_StlRunning = ''".format(self._category)) + def clearBufferObject(self): + """ + https://github.com/vim/vim/issues/1737 + https://github.com/vim/vim/issues/1738 + """ + if (self._buffer_object is not None and self._buffer_object.valid + and lfEval("g:Lf_RememberLastSearch") == '0' + and "--append" not in self._arguments + and "--recall" not in self._arguments): + self.buffer.options['modifiable'] = True + del self._buffer_object[:] + def enterBuffer(self, win_pos, clear): if self._enterOpeningBuffer(): return @@ -1093,6 +1109,9 @@ def enterBuffer(self, win_pos, clear): self._before_enter() + if clear: + self.clearBufferObject() + if win_pos in ('popup', 'floatwin'): if lfEval("exists('g:lf_gcr_stack')") == '0': lfCmd("let g:lf_gcr_stack = []") @@ -1104,7 +1123,7 @@ def enterBuffer(self, win_pos, clear): lfCmd("set t_ve=") self._orig_win_nr = vim.current.window.number self._orig_win_id = lfWinId(self._orig_win_nr) - self._createPopupWindow(clear) + self._createPopupWindow() self._arguments["popup_winid"] = self._popup_winid elif win_pos == 'fullScreen': self._orig_tabpage = vim.current.tabpage diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 3887c30e..474602be 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -751,6 +751,9 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): else: lfCmd("call win_execute(%d, 'setlocal foldcolumn=1')" % self._preview_winid) + def isPreviewWindowOpen(self): + return self._preview_winid > 0 and int(lfEval("winbufnr(%d)" % self._preview_winid)) != -1 + def _useExistingWindow(self, title, source, line_nr, jump_cmd): if lfEval("has('nvim')") == '1': if isinstance(source, int): @@ -814,7 +817,7 @@ def _createPopupPreview(self, title, source, line_nr, jump_cmd=''): self._is_previewed = True line_nr = int(line_nr) - if self._preview_winid > 0 and int(lfEval("winbufnr(%d)" % self._preview_winid)) != -1: + if self.isPreviewWindowOpen(): self._useExistingWindow(title, source, line_nr, jump_cmd) return False @@ -983,10 +986,7 @@ def _needPreview(self, preview, preview_in_popup): whether preview in popup, if value is true, it means (lfEval("get(g:, 'Lf_PreviewInPopup', 1)") == '1' or self._getInstance().getWinPos() in ('popup', 'floatwin')) """ - if self._getInstance().isReverseOrder(): - if self._getInstance().window.cursor[0] > len(self._getInstance().buffer) - self._help_length: - return False - elif self._getInstance().window.cursor[0] <= self._help_length: + if self._inHelpLines(): return False if preview: @@ -1108,7 +1108,7 @@ def _setAutochdir(self): lfCmd("set autochdir") def _toUpInPopup(self): - if self._preview_winid > 0 and int(lfEval("winbufnr(%d)" % self._preview_winid)) != -1: + if self.isPreviewWindowOpen(): scroll_step_size = int(lfEval("get(g:, 'Lf_PreviewScrollStepSize', 1)")) if lfEval("has('nvim')") == '1': cur_winid = lfEval("win_getid()") @@ -1120,7 +1120,7 @@ def _toUpInPopup(self): lfCmd("call win_execute(%d, 'norm! %dk')" % (self._preview_winid, scroll_step_size)) def _toDownInPopup(self): - if self._preview_winid > 0 and int(lfEval("winbufnr(%d)" % self._preview_winid)) != -1: + if self.isPreviewWindowOpen(): scroll_step_size = int(lfEval("get(g:, 'Lf_PreviewScrollStepSize', 1)")) if lfEval("has('nvim')") == '1': cur_winid = lfEval("win_getid()") @@ -2348,17 +2348,13 @@ def _gotoFirstLine(self): def _readFinished(self): pass - def _previewFirstLine(self, content): - try: - first_line = next(content) - content = itertools.chain([first_line], content) + def _previewFirstLine(self): + time.sleep(0.005) + if len(self._content) > 0: + first_line = self._content[0] self._getInstance().setBuffer([first_line]) self._previewResult(False) self._getInstance().clearBuffer() - except StopIteration: - pass - - return content def startExplorer(self, win_pos, *args, **kwargs): arguments_dict = kwargs.get("arguments", {}) @@ -2518,7 +2514,6 @@ def startExplorer(self, win_pos, *args, **kwargs): self._getInstance().setBuffer(self._content, need_copy=False) self._createHelpHint() else: - self._getInstance().clearBuffer() self._content = [] self._offset_in_content = 0 else: @@ -2528,10 +2523,10 @@ def startExplorer(self, win_pos, *args, **kwargs): self._read_finished = 0 self._stop_reader_thread = False - content = self._previewFirstLine(content) self._reader_thread = threading.Thread(target=self._readContent, args=(content,)) self._reader_thread.daemon = True self._reader_thread.start() + self._previewFirstLine() if not kwargs.get('bang', 0): self.input() @@ -2542,7 +2537,6 @@ def startExplorer(self, win_pos, *args, **kwargs): self._getInstance().mimicCursor() else: self._is_content_list = False - content = self._previewFirstLine(content) self._callback = partial(self._workInIdle, content) if lfEval("get(g:, 'Lf_NoAsync', 0)") == '1': self._content = self._getInstance().initBuffer(content, self._getUnit(), self._getExplorer().setContent) @@ -2661,6 +2655,9 @@ def _workInIdle(self, content=None, bang=False): self._getInstance().setStlResultsCount(len(self._content)) + if not self.isPreviewWindowOpen(): + self._previewResult(False) + if self._getInstance().getWinPos() not in ('popup', 'floatwin'): lfCmd("redrawstatus") @@ -2720,6 +2717,10 @@ def _workInIdle(self, content=None, bang=False): elif len(self._getInstance().buffer) < min(cur_len, self._initial_count): self._getInstance().setBuffer(self._content[:self._initial_count]) + if not self.isPreviewWindowOpen(): + self._previewResult(False) + + @modifiableController def input(self): self._current_mode = 'INPUT' diff --git a/autoload/leaderf/python/leaderf/rgExpl.py b/autoload/leaderf/python/leaderf/rgExpl.py index 2fc947bf..1474a489 100644 --- a/autoload/leaderf/python/leaderf/rgExpl.py +++ b/autoload/leaderf/python/leaderf/rgExpl.py @@ -159,6 +159,8 @@ def getContent(self, *args, **kwargs): one_args_options += "-E %s " % arguments_dict["-E"][0] if "-M" in arguments_dict: one_args_options += "-M %s " % arguments_dict["-M"][0] + else: + one_args_options += "-M 512 " if "-m" in arguments_dict: one_args_options += "-m %s " % arguments_dict["-m"][0] if "--max-depth" in arguments_dict: @@ -997,17 +999,17 @@ def startLiveGrep(self, win_pos, *args, **kwargs): self._read_finished = 1 self._offset_in_content = 0 else: - self._getInstance().clearBuffer() self._content = [] self._offset_in_content = 0 self._read_finished = 0 self._stop_reader_thread = False - content = self._previewFirstLine(content) self._reader_thread = threading.Thread(target=self._readContent, args=(content,)) self._reader_thread.daemon = True self._reader_thread.start() + # for the case of --input + self._previewFirstLine() self.input() From 92bbe71f0ffa1a1d8c6b871ae4841a1b9e3af079 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Mon, 10 Jul 2023 11:59:07 +0800 Subject: [PATCH 096/365] put the popup window in the center of screen if g:Lf_PopupPreviewPosition in ('top', 'bottom') --- autoload/leaderf/python/leaderf/instance.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/autoload/leaderf/python/leaderf/instance.py b/autoload/leaderf/python/leaderf/instance.py index a48362a4..5560ac8e 100644 --- a/autoload/leaderf/python/leaderf/instance.py +++ b/autoload/leaderf/python/leaderf/instance.py @@ -406,12 +406,7 @@ def _createPopupWindow(self): line, col = [int(i) for i in lfEval("get(g:, 'Lf_PopupPosition', [0, 0])")] if line == 0: - if preview_pos.lower() == 'top': - line = (int(lfEval("&lines")) - 2 - maxheight) * 4 // 5 - elif preview_pos.lower() == 'bottom': - line = (int(lfEval("&lines")) - 2 - maxheight) // 5 - else: - line = (int(lfEval("&lines")) - 2 - maxheight) // 2 + line = (int(lfEval("&lines")) - 2 - maxheight) // 2 else: line = min(line, int(lfEval("&lines")) - maxheight) From 1ff12814d13ad375074e3ee0252b1a874fc309c4 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Mon, 10 Jul 2023 23:06:33 +0800 Subject: [PATCH 097/365] window local option should be set again if nvim_win_set_buf() --- autoload/leaderf/python/leaderf/manager.py | 30 +++++++++++++--------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 474602be..32c07c33 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -435,6 +435,18 @@ def getArguments(self): #************************************************************** + def _setWinOptions(self, winid): + lfCmd("call nvim_win_set_option(%d, 'number', v:true)" % winid) + lfCmd("call nvim_win_set_option(%d, 'relativenumber', v:false)" % winid) + lfCmd("call nvim_win_set_option(%d, 'cursorline', v:true)" % winid) + lfCmd("call nvim_win_set_option(%d, 'foldmethod', 'manual')" % winid) + lfCmd("call nvim_win_set_option(%d, 'foldcolumn', '0')" % winid) + lfCmd("call nvim_win_set_option(%d, 'signcolumn', 'no')" % winid) + if lfEval("exists('+cursorlineopt')") == '1': + lfCmd("call nvim_win_set_option(%d, 'cursorlineopt', 'both')" % winid) + lfCmd("call nvim_win_set_option(%d, 'colorcolumn', '')" % winid) + lfCmd("call nvim_win_set_option(%d, 'winhighlight', 'Normal:Lf_hl_popup_window')" % winid) + @ignoreEvent('BufWinEnter,BufEnter') def _createPopupModePreview(self, title, source, line_nr, jump_cmd): """ @@ -464,6 +476,7 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): lfCmd("noautocmd let g:Lf_preview_scratch_buffer = nvim_create_buf(0, 1)") lfCmd("noautocmd call setbufline(g:Lf_preview_scratch_buffer, 1, content)") lfCmd("noautocmd call nvim_buf_set_option(g:Lf_preview_scratch_buffer, 'bufhidden', 'wipe')") + lfCmd("noautocmd call nvim_buf_set_option(g:Lf_preview_scratch_buffer, 'undolevels', -1)") float_window = self._getInstance().window # row and col start from 0 @@ -581,16 +594,8 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): if buffer_len >= line_nr > 0: lfCmd("""call nvim_win_set_cursor(%d, [%d, 1])""" % (self._preview_winid, line_nr)) - lfCmd("call nvim_win_set_option(%d, 'number', v:true)" % self._preview_winid) - lfCmd("call nvim_win_set_option(%d, 'relativenumber', v:false)" % self._preview_winid) - lfCmd("call nvim_win_set_option(%d, 'cursorline', v:true)" % self._preview_winid) - lfCmd("call nvim_win_set_option(%d, 'foldmethod', 'manual')" % self._preview_winid) - lfCmd("call nvim_win_set_option(%d, 'foldcolumn', '0')" % self._preview_winid) - lfCmd("call nvim_win_set_option(%d, 'signcolumn', 'no')" % self._preview_winid) - if lfEval("exists('+cursorlineopt')") == '1': - lfCmd("call nvim_win_set_option(%d, 'cursorlineopt', 'both')" % self._preview_winid) - lfCmd("call nvim_win_set_option(%d, 'colorcolumn', '')" % self._preview_winid) - lfCmd("call nvim_win_set_option(%d, 'winhighlight', 'Normal:Lf_hl_popup_window')" % self._preview_winid) + self._setWinOptions(self._preview_winid) + cur_winid = lfEval("win_getid()") lfCmd("noautocmd call win_gotoid(%d)" % self._preview_winid) if not isinstance(source, int): @@ -758,7 +763,7 @@ def _useExistingWindow(self, title, source, line_nr, jump_cmd): if lfEval("has('nvim')") == '1': if isinstance(source, int): lfCmd("noautocmd call nvim_win_set_buf(%d, %d)" % (self._preview_winid, source)) - lfCmd("noautocmd call nvim_win_set_option(%d, 'cursorline', v:true)" % self._preview_winid) + self._setWinOptions(self._preview_winid) self._preview_filetype = '' else: try: @@ -768,6 +773,7 @@ def _useExistingWindow(self, title, source, line_nr, jump_cmd): return if lfEval("!exists('g:Lf_preview_scratch_buffer') || !bufexists(g:Lf_preview_scratch_buffer)") == '1': lfCmd("noautocmd let g:Lf_preview_scratch_buffer = nvim_create_buf(0, 1)") + lfCmd("noautocmd call nvim_buf_set_option(g:Lf_preview_scratch_buffer, 'undolevels', -1)") lfCmd("noautocmd call nvim_buf_set_lines(g:Lf_preview_scratch_buffer, 0, -1, v:false, content)") lfCmd("noautocmd call nvim_win_set_buf(%d, g:Lf_preview_scratch_buffer)" % self._preview_winid) @@ -2349,7 +2355,7 @@ def _readFinished(self): pass def _previewFirstLine(self): - time.sleep(0.005) + time.sleep(0.002) if len(self._content) > 0: first_line = self._content[0] self._getInstance().setBuffer([first_line]) From 7823fb6625cce19780967c97af33b74d31f884a9 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Mon, 10 Jul 2023 23:33:43 +0800 Subject: [PATCH 098/365] rg -M 512 -M 512 "" report error --- autoload/leaderf/python/leaderf/rgExpl.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/autoload/leaderf/python/leaderf/rgExpl.py b/autoload/leaderf/python/leaderf/rgExpl.py index 1474a489..5f53f06f 100644 --- a/autoload/leaderf/python/leaderf/rgExpl.py +++ b/autoload/leaderf/python/leaderf/rgExpl.py @@ -160,7 +160,11 @@ def getContent(self, *args, **kwargs): if "-M" in arguments_dict: one_args_options += "-M %s " % arguments_dict["-M"][0] else: - one_args_options += "-M 512 " + for opt in rg_config: + if opt.lstrip().startswith("--max-columns=") or opt.lstrip().startswith("-M "): + break + else: + one_args_options += "-M 512 " if "-m" in arguments_dict: one_args_options += "-m %s " % arguments_dict["-m"][0] if "--max-depth" in arguments_dict: From d27943998851ef8097d791724917d0094c661d41 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Mon, 10 Jul 2023 23:39:36 +0800 Subject: [PATCH 099/365] update doc --- doc/leaderf.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/leaderf.txt b/doc/leaderf.txt index 20c48d0b..93d6ab3e 100644 --- a/doc/leaderf.txt +++ b/doc/leaderf.txt @@ -587,7 +587,7 @@ g:Lf_RgConfig *g:Lf_RgConfig* Specify a list of ripgrep configurations. For example, > let g:Lf_RgConfig = [ \ "--max-columns=150", - \ "--type-add web:*.{html,css,js}*", + \ '--type-add "web:*.{html,css,js}*"', \ "--glob=!git/*", \ "--hidden" \ ] From 49af82180b22c3c2ff8d9d1e82a7ab1486cd052b Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Tue, 11 Jul 2023 16:25:50 +0800 Subject: [PATCH 100/365] fix a bug when using everforest colorscheme --- autoload/leaderf/colorscheme/popup.vim | 6 +++++- autoload/leaderf/colorscheme/popup/default.vim | 6 ++++-- autoload/leaderf/colorscheme/popup/gruvbox_default.vim | 6 ++++-- autoload/leaderf/colorscheme/popup/gruvbox_material.vim | 6 ++++-- autoload/leaderf/colorscheme/popup/onedark.vim | 2 +- autoload/leaderf/colorscheme/popup/solarized.vim | 4 ++-- syntax/leaderf.vim | 8 -------- 7 files changed, 20 insertions(+), 18 deletions(-) diff --git a/autoload/leaderf/colorscheme/popup.vim b/autoload/leaderf/colorscheme/popup.vim index 6023ed77..4b4e9515 100644 --- a/autoload/leaderf/colorscheme/popup.vim +++ b/autoload/leaderf/colorscheme/popup.vim @@ -288,10 +288,14 @@ endfunction function! leaderf#colorscheme#popup#load(category, name) exec 'runtime autoload/leaderf/colorscheme/popup/'.a:name.'.vim' + " in case a:name does not exist + if a:name != "default" + exec 'runtime autoload/leaderf/colorscheme/popup/default.vim' + endif + if !has("nvim") call s:AddPropType() endif call s:LoadFromPalette() call s:HighlightSeperator(a:category) - call g:LfDefineDefaultColors() endfunction diff --git a/autoload/leaderf/colorscheme/popup/default.vim b/autoload/leaderf/colorscheme/popup/default.vim index 3b6ca4e4..2172d80e 100644 --- a/autoload/leaderf/colorscheme/popup/default.vim +++ b/autoload/leaderf/colorscheme/popup/default.vim @@ -27,6 +27,8 @@ if &background ==? 'dark' " and `hi def link Lf_hl_popup_cursor Cursor`, the bug occurs. call leaderf#colorscheme#popup#link_cursor("Lf_hl_popup_cursor") + call leaderf#colorscheme#popup#link_two("Lf_hl_popupBorder", "Normal", "VertSplit", 1) + highlight def Lf_hl_popup_prompt guifg=#ffcd4a guibg=NONE gui=NONE ctermfg=221 ctermbg=NONE cterm=NONE highlight def Lf_hl_popup_spin guifg=#e6e666 guibg=NONE gui=NONE ctermfg=185 ctermbg=NONE cterm=NONE highlight def Lf_hl_popup_normalMode guifg=#333300 guibg=#c1ce96 gui=bold ctermfg=58 ctermbg=187 cterm=bold @@ -118,7 +120,6 @@ if &background ==? 'dark' highlight def Lf_hl_gtagsHighlight guifg=#000000 guibg=#cccc66 gui=NONE ctermfg=16 ctermbg=185 cterm=NONE highlight def link Lf_hl_previewTitle Statusline - call leaderf#colorscheme#popup#link_two("Lf_hl_popupBorder", "Normal", "VertSplit", 1) highlight def link Lf_hl_winNumber Constant highlight def link Lf_hl_winIndicators Statement @@ -150,6 +151,8 @@ else " and `hi def link Lf_hl_popup_cursor Cursor`, the bug occurs. call leaderf#colorscheme#popup#link_cursor("Lf_hl_popup_cursor") + call leaderf#colorscheme#popup#link_two("Lf_hl_popupBorder", "Normal", "VertSplit", 1) + highlight def Lf_hl_popup_prompt guifg=#c77400 guibg=NONE gui=NONE ctermfg=172 cterm=NONE highlight def Lf_hl_popup_spin guifg=#f12d2d guibg=NONE gui=NONE ctermfg=196 cterm=NONE highlight def Lf_hl_popup_normalMode guifg=#808000 guibg=#ccc88e gui=bold ctermfg=100 ctermbg=186 cterm=bold @@ -241,7 +244,6 @@ else highlight def Lf_hl_gtagsHighlight guifg=#4d4d4d guibg=#cccc66 gui=NONE ctermfg=239 ctermbg=185 cterm=NONE highlight def link Lf_hl_previewTitle Statusline - call leaderf#colorscheme#popup#link_two("Lf_hl_popupBorder", "Normal", "VertSplit", 1) highlight def link Lf_hl_winNumber Constant highlight def link Lf_hl_winIndicators Statement diff --git a/autoload/leaderf/colorscheme/popup/gruvbox_default.vim b/autoload/leaderf/colorscheme/popup/gruvbox_default.vim index f5f97b7b..f20d23ac 100644 --- a/autoload/leaderf/colorscheme/popup/gruvbox_default.vim +++ b/autoload/leaderf/colorscheme/popup/gruvbox_default.vim @@ -27,6 +27,8 @@ if &background ==? 'dark' " and `hi def link Lf_hl_popup_cursor Cursor`, the bug occurs. call leaderf#colorscheme#popup#link_cursor("Lf_hl_popup_cursor") + call leaderf#colorscheme#popup#link_two("Lf_hl_popupBorder", "Normal", "VertSplit", 1) + highlight def Lf_hl_popup_prompt guifg=#fabd2f guibg=NONE gui=NONE ctermfg=214 ctermbg=NONE cterm=NONE highlight def Lf_hl_popup_spin guifg=#e6e666 guibg=NONE gui=NONE ctermfg=185 ctermbg=NONE cterm=NONE highlight def Lf_hl_popup_normalMode guifg=#282828 guibg=#a89984 gui=bold ctermfg=235 ctermbg=137 cterm=bold @@ -117,7 +119,6 @@ if &background ==? 'dark' highlight def Lf_hl_gtagsHighlight guifg=#000000 guibg=#cccc66 gui=NONE ctermfg=16 ctermbg=185 cterm=NONE highlight def link Lf_hl_previewTitle Statusline - call leaderf#colorscheme#popup#link_two("Lf_hl_popupBorder", "Normal", "VertSplit", 1) highlight def link Lf_hl_winNumber Constant highlight def link Lf_hl_winIndicators Statement @@ -149,6 +150,8 @@ else " and `hi def link Lf_hl_popup_cursor Cursor`, the bug occurs. call leaderf#colorscheme#popup#link_cursor("Lf_hl_popup_cursor") + call leaderf#colorscheme#popup#link_two("Lf_hl_popupBorder", "Normal", "VertSplit", 1) + highlight def Lf_hl_popup_prompt guifg=#c77400 guibg=NONE gui=NONE ctermfg=172 cterm=NONE highlight def Lf_hl_popup_spin guifg=#f12d2d guibg=NONE gui=NONE ctermfg=196 cterm=NONE highlight def Lf_hl_popup_normalMode guifg=#fbf1c7 guibg=#a89984 gui=bold ctermfg=230 ctermbg=137 cterm=bold @@ -240,7 +243,6 @@ else highlight def Lf_hl_gtagsHighlight guifg=#4d4d4d guibg=#cccc66 gui=NONE ctermfg=239 ctermbg=185 cterm=NONE highlight def link Lf_hl_previewTitle Statusline - call leaderf#colorscheme#popup#link_two("Lf_hl_popupBorder", "Normal", "VertSplit", 1) highlight def link Lf_hl_winNumber Constant highlight def link Lf_hl_winIndicators Statement diff --git a/autoload/leaderf/colorscheme/popup/gruvbox_material.vim b/autoload/leaderf/colorscheme/popup/gruvbox_material.vim index 7157c5af..f617d5d7 100644 --- a/autoload/leaderf/colorscheme/popup/gruvbox_material.vim +++ b/autoload/leaderf/colorscheme/popup/gruvbox_material.vim @@ -40,6 +40,8 @@ if &background ==# 'dark' " and `hi def link Lf_hl_popup_cursor Cursor`, the bug occurs. call leaderf#colorscheme#popup#link_cursor("Lf_hl_popup_cursor") + call leaderf#colorscheme#popup#link_two("Lf_hl_popupBorder", "Normal", "VertSplit", 1) + " the color of the cursorline highlight def Lf_hl_cursorline guifg=#d4be98 guibg=NONE gui=NONE ctermfg=223 ctermbg=NONE cterm=NONE @@ -117,7 +119,6 @@ if &background ==# 'dark' highlight def Lf_hl_gtagsHighlight guifg=#000000 guibg=#cccc66 gui=NONE ctermfg=16 ctermbg=185 cterm=NONE highlight def link Lf_hl_previewTitle Statusline - call leaderf#colorscheme#popup#link_two("Lf_hl_popupBorder", "Normal", "VertSplit", 1) highlight def link Lf_hl_winNumber Constant highlight def link Lf_hl_winIndicators Statement @@ -168,6 +169,8 @@ else " and `hi def link Lf_hl_popup_cursor Cursor`, the bug occurs. call leaderf#colorscheme#popup#link_cursor("Lf_hl_popup_cursor") + call leaderf#colorscheme#popup#link_two("Lf_hl_popupBorder", "Normal", "VertSplit", 1) + " the color of the cursorline highlight def Lf_hl_cursorline guifg=#654735 guibg=NONE gui=NONE ctermfg=237 ctermbg=NONE cterm=NONE @@ -245,7 +248,6 @@ else highlight def Lf_hl_gtagsHighlight guifg=#000000 guibg=#cccc66 gui=NONE ctermfg=16 ctermbg=185 cterm=NONE highlight def link Lf_hl_previewTitle Statusline - call leaderf#colorscheme#popup#link_two("Lf_hl_popupBorder", "Normal", "VertSplit", 1) highlight def link Lf_hl_winNumber Constant highlight def link Lf_hl_winIndicators Statement diff --git a/autoload/leaderf/colorscheme/popup/onedark.vim b/autoload/leaderf/colorscheme/popup/onedark.vim index 6d76d9f4..56381f66 100644 --- a/autoload/leaderf/colorscheme/popup/onedark.vim +++ b/autoload/leaderf/colorscheme/popup/onedark.vim @@ -3,6 +3,7 @@ if &background ==? 'dark' call leaderf#colorscheme#popup#link_no_reverse("Lf_hl_popup_window", "Normal") call leaderf#colorscheme#popup#link_no_reverse("Lf_hl_popup_blank", "StatusLineNC") highlight def Lf_hl_popup_cursor guifg=#657b83 ctermfg=66 guibg=#98C379 ctermbg=114 + call leaderf#colorscheme#popup#link_two("Lf_hl_popupBorder", "Normal", "VertSplit", 1) highlight def Lf_hl_popup_prompt guifg=#D19A66 ctermfg=173 guibg=#3B4048 ctermbg=238 gui=bold cterm=bold highlight def Lf_hl_popup_spin guifg=#ABB2BF ctermfg=145 guibg=#3B4048 ctermbg=238 highlight def Lf_hl_popup_normalMode guifg=#2C323C ctermfg=236 guibg=#98C379 ctermbg=114 gui=bold cterm=bold @@ -82,7 +83,6 @@ if &background ==? 'dark' highlight def Lf_hl_gtagsHighlight guifg=#000000 guibg=#cccc66 gui=NONE ctermfg=16 ctermbg=185 cterm=NONE highlight def link Lf_hl_previewTitle Statusline - call leaderf#colorscheme#popup#link_two("Lf_hl_popupBorder", "Normal", "VertSplit", 1) highlight def link Lf_hl_winNumber Constant highlight def link Lf_hl_winIndicators Statement diff --git a/autoload/leaderf/colorscheme/popup/solarized.vim b/autoload/leaderf/colorscheme/popup/solarized.vim index 1ffba146..e860b91f 100644 --- a/autoload/leaderf/colorscheme/popup/solarized.vim +++ b/autoload/leaderf/colorscheme/popup/solarized.vim @@ -3,6 +3,7 @@ if &background ==? 'dark' call leaderf#colorscheme#popup#link_no_reverse("Lf_hl_popup_window", "Normal") call leaderf#colorscheme#popup#link_no_reverse("Lf_hl_popup_blank", "StatusLineNC") highlight def Lf_hl_popup_cursor guifg=#657b83 ctermfg=66 guibg=#93a1a1 ctermbg=109 + call leaderf#colorscheme#popup#link_two("Lf_hl_popupBorder", "Normal", "VertSplit", 1) highlight def Lf_hl_popup_prompt guifg=#b58900 ctermfg=136 guibg=#002b36 ctermbg=17 gui=bold cterm=bold highlight def Lf_hl_popup_spin guifg=#fdf6e3 ctermfg=230 guibg=#002b36 ctermbg=17 highlight def Lf_hl_popup_normalMode guifg=#fdf6e3 ctermfg=230 guibg=#93a1a1 ctermbg=109 gui=bold cterm=bold @@ -87,7 +88,6 @@ if &background ==? 'dark' highlight def Lf_hl_gtagsHighlight guifg=#4d4d4d guibg=#cccc66 gui=NONE ctermfg=239 ctermbg=185 cterm=NONE highlight def link Lf_hl_previewTitle Statusline - call leaderf#colorscheme#popup#link_two("Lf_hl_popupBorder", "Normal", "VertSplit", 1) highlight def link Lf_hl_winNumber Constant highlight def link Lf_hl_winIndicators Statement @@ -110,6 +110,7 @@ else call leaderf#colorscheme#popup#link_no_reverse("Lf_hl_popup_window", "Normal") call leaderf#colorscheme#popup#link_no_reverse("Lf_hl_popup_blank", "StatusLineNC") highlight def Lf_hl_popup_cursor guifg=#b58900 ctermfg=136 guibg=#586e75 ctermbg=60 + call leaderf#colorscheme#popup#link_two("Lf_hl_popupBorder", "Normal", "VertSplit", 1) highlight def Lf_hl_popup_prompt guifg=#073642 ctermfg=23 guibg=#fdf6e3 ctermbg=230 gui=bold cterm=bold highlight def Lf_hl_popup_spin guifg=#002b36 ctermfg=17 guibg=#fdf6e3 ctermbg=230 highlight def Lf_hl_popup_normalMode guifg=#fdf6e3 ctermfg=230 guibg=#586e75 ctermbg=60 gui=bold cterm=bold @@ -194,7 +195,6 @@ else highlight def Lf_hl_gtagsHighlight guifg=#4d4d4d guibg=#cccc66 gui=NONE ctermfg=239 ctermbg=185 cterm=NONE highlight def link Lf_hl_previewTitle Statusline - call leaderf#colorscheme#popup#link_two("Lf_hl_popupBorder", "Normal", "VertSplit", 1) highlight def link Lf_hl_winNumber Constant highlight def link Lf_hl_winIndicators Statement diff --git a/syntax/leaderf.vim b/syntax/leaderf.vim index f35bc8c7..9f885323 100644 --- a/syntax/leaderf.vim +++ b/syntax/leaderf.vim @@ -31,11 +31,3 @@ let b:current_syntax = "leaderf" " define the highlight groups " new highlight groups will be defined in autoload/leaderf/colorscheme/popup/default.vim -" there are also duplicates defined here so that other colorschemes can also -" own these highlight groups -function! g:LfDefineDefaultColors() abort - "highlight def link Lf_hl_jumpsTitle Title - "highlight def link Lf_hl_jumpsNumber Number - "highlight def link Lf_hl_jumpsLineCol String - "highlight def link Lf_hl_jumpsIndicator Type -endfunction From 9c2b1c673bd9471449c00b7dacd411c06cfbed49 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 12 Jul 2023 16:37:41 +0800 Subject: [PATCH 101/365] preview result by default --- autoload/leaderf.vim | 1 + autoload/leaderf/python/leaderf/manager.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/autoload/leaderf.vim b/autoload/leaderf.vim index 6e484f95..0910343b 100644 --- a/autoload/leaderf.vim +++ b/autoload/leaderf.vim @@ -129,6 +129,7 @@ call s:InitDict('g:Lf_PreviewResult', { \ 'Function': 1, \ 'Line': 1, \ 'Colorscheme': 0, + \ 'Rg': 1, \ 'Jumps': 1 \}) call s:InitDict('g:Lf_NormalMap', {}) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 32c07c33..71371198 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -1010,7 +1010,7 @@ def _needPreview(self, preview, preview_in_popup): preview_dict = {k.lower(): v for k, v in lfEval("g:Lf_PreviewResult").items()} category = self._getExplorer().getStlCategory() - if int(preview_dict.get(category.lower(), 0)) == 0: + if int(preview_dict.get(category.lower(), 1)) == 0: return False if self._getInstance().empty(): From ed13a2ff5fd6dfbbc9fdc15bea43ec03a6e8dbb6 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Sun, 16 Jul 2023 18:38:35 +0800 Subject: [PATCH 102/365] optimize the code --- autoload/leaderf/python/leaderf/rgExpl.py | 59 ++++++++++++++--------- 1 file changed, 36 insertions(+), 23 deletions(-) diff --git a/autoload/leaderf/python/leaderf/rgExpl.py b/autoload/leaderf/python/leaderf/rgExpl.py index 5f53f06f..9e77c59c 100644 --- a/autoload/leaderf/python/leaderf/rgExpl.py +++ b/autoload/leaderf/python/leaderf/rgExpl.py @@ -918,6 +918,21 @@ def _highlightMatch(self): except vim.error: pass + def _resume(self, bang): + if self._getInstance().getWinPos() == 'popup': + self._cli.hideCursor() + if lfEval("exists('*leaderf#%s#NormalModeFilter')" % self._getExplorer().getStlCategory()) == '1': + lfCmd("call leaderf#ResetPopupOptions(%d, 'filter', '%s')" % (self._getInstance().getPopupWinId(), + 'leaderf#%s#NormalModeFilter' % self._getExplorer().getStlCategory())) + else: + lfCmd("call leaderf#ResetPopupOptions(%d, 'filter', function('leaderf#NormalModeFilter', [%d]))" + % (self._getInstance().getPopupWinId(), id(self))) + + self._previewResult(False) + + if not bang: + self.input() + def startLiveGrep(self, win_pos, *args, **kwargs): arguments_dict = kwargs.get("arguments", {}) if "--recall" in arguments_dict: @@ -950,7 +965,7 @@ def startLiveGrep(self, win_pos, *args, **kwargs): remember_last_status = "--recall" in self._arguments \ or lfEval("g:Lf_RememberLastSearch") == '1' and self._cli.pattern if remember_last_status: - content = iter(self._content) + content = self._content self._getInstance().useLastReverseOrder() win_pos = self._getInstance().getWinPos() else: @@ -984,36 +999,33 @@ def startLiveGrep(self, win_pos, *args, **kwargs): % (self._getExplorer().getStlCategory(), self._current_mode)) self._getInstance().setPopupStl(self._current_mode) - self._getInstance().setStlResultsCount(0) - self._getInstance().setStlTotal(0) - self._getInstance().setStlRunning(False) - - self._start_time = time.time() - self._bang_start_time = self._start_time - self._bang_count = 0 self._getInstance().buffer.vars['Lf_category'] = self._getExplorer().getStlCategory() + if remember_last_status: + self._resume(kwargs.get('bang', 0)) + return + + self._start_time = time.time() + self._read_content_exception = None + self._getInstance().setStlResultsCount(0) + self._getInstance().setStlTotal(0) + self._getInstance().setStlRunning(False) + self._callback = self._writeBuffer - if lfEval("get(g:, 'Lf_NoAsync', 0)") == '1': - self._content = self._getInstance().initBuffer(content, self._getUnit(), self._getExplorer().setContent) - self._previewResult(False) - self._read_finished = 1 - self._offset_in_content = 0 - else: - self._content = [] - self._offset_in_content = 0 + self._content = [] + self._offset_in_content = 0 - self._read_finished = 0 + self._read_finished = 0 - self._stop_reader_thread = False - self._reader_thread = threading.Thread(target=self._readContent, args=(content,)) - self._reader_thread.daemon = True - self._reader_thread.start() - # for the case of --input - self._previewFirstLine() + self._stop_reader_thread = False + self._reader_thread = threading.Thread(target=self._readContent, args=(content,)) + self._reader_thread.daemon = True + self._reader_thread.start() + # for the case of --input + self._previewFirstLine() self.input() @@ -1501,6 +1513,7 @@ def _search(self, content, is_continue=False, step=0): self._getInstance().setStlResultsCount(0) self._getInstance().setStlTotal(len(self._content)//self._getUnit()) self._getInstance().setStlRunning(False) + self._getInstance().refreshPopupStatusline() self._previewResult(False) return From 65740651731c01363c2dad0c528102bc0c7876fe Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 20 Jul 2023 00:07:13 +0800 Subject: [PATCH 103/365] deprecate g:Lf_PreviewHorizontalPosition add g:Lf_PreviewPosition --- autoload/leaderf/python/leaderf/instance.py | 3 +- autoload/leaderf/python/leaderf/manager.py | 374 +++++++++----------- doc/leaderf.txt | 32 +- 3 files changed, 199 insertions(+), 210 deletions(-) diff --git a/autoload/leaderf/python/leaderf/instance.py b/autoload/leaderf/python/leaderf/instance.py index 5560ac8e..dfe50c53 100644 --- a/autoload/leaderf/python/leaderf/instance.py +++ b/autoload/leaderf/python/leaderf/instance.py @@ -322,8 +322,7 @@ def _setAttributes(self): lfCmd("setlocal cursorline") if lfEval("exists('+cursorlineopt')") == '1': lfCmd("setlocal cursorlineopt=both") - if lfEval("has('nvim')") == '1': - lfCmd("silent! setlocal signcolumn=no") # make vim flicker + lfCmd("silent! setlocal signcolumn=no") # make vim flicker lfCmd("setlocal colorcolumn=") if self._reverse_order: lfCmd("setlocal nonumber") diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 71371198..39ec9ddb 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -447,6 +447,77 @@ def _setWinOptions(self, winid): lfCmd("call nvim_win_set_option(%d, 'colorcolumn', '')" % winid) lfCmd("call nvim_win_set_option(%d, 'winhighlight', 'Normal:Lf_hl_popup_window')" % winid) + def _createPreviewWindow(self, config, source, line_nr, jump_cmd): + if lfEval("has('nvim')") == '1': + if isinstance(source, int): + buffer_len = len(vim.buffers[source]) + self._preview_winid = int(lfEval("nvim_open_win(%d, 0, %s)" % (source, str(config)))) + else: + try: + lfCmd("let content = readfile('%s', '', 4096)" % escQuote(source)) + except vim.error as e: + lfPrintError(e) + return + buffer_len = int(lfEval("len(content)")) + lfCmd("noautocmd let g:Lf_preview_scratch_buffer = nvim_create_buf(0, 1)") + lfCmd("noautocmd call setbufline(g:Lf_preview_scratch_buffer, 1, content)") + lfCmd("noautocmd call nvim_buf_set_option(g:Lf_preview_scratch_buffer, 'bufhidden', 'wipe')") + lfCmd("noautocmd call nvim_buf_set_option(g:Lf_preview_scratch_buffer, 'undolevels', -1)") + + self._preview_winid = int(lfEval("nvim_open_win(g:Lf_preview_scratch_buffer, 0, %s)" % str(config))) + self._preview_filetype = lfEval("getbufvar(winbufnr(%d), '&ft')" % self._preview_winid) + + if jump_cmd: + cur_winid = lfEval("win_getid()") + lfCmd("noautocmd call win_gotoid(%d)" % self._preview_winid) + lfCmd(jump_cmd) + lfCmd("noautocmd call win_gotoid(%s)" % cur_winid) + if buffer_len >= line_nr > 0: + lfCmd("""call nvim_win_set_cursor(%d, [%d, 1])""" % (self._preview_winid, line_nr)) + + self._setWinOptions(self._preview_winid) + + cur_winid = lfEval("win_getid()") + lfCmd("noautocmd call win_gotoid(%d)" % self._preview_winid) + if not isinstance(source, int): + lfCmd("doautocmd filetypedetect BufNewFile %s" % source) + lfCmd("silent! %foldopen!") + lfCmd("norm! zz") + lfCmd("noautocmd call win_gotoid(%s)" % cur_winid) + else: + if isinstance(source, int): + lfCmd("let content = getbufline(%d, 1, '$')" % source) + filename = vim.buffers[source].name + else: + filename = source + try: + lfCmd("let content = readfile('%s', '', 4096)" % escQuote(source)) + except vim.error as e: + lfPrintError(e) + return + + lfCmd("noautocmd silent! let winid = popup_create(content, %s)" % json.dumps(config)) + lfCmd("call win_execute(winid, 'setlocal nomodeline')") + lfCmd("call win_execute(winid, 'doautocmd filetypedetect BufNewFile %s')" % escQuote(filename)) + + self._preview_winid = int(lfEval("winid")) + self._preview_filetype = lfEval("getbufvar(winbufnr(winid), '&ft')") + if jump_cmd: + lfCmd("""call win_execute(%d, '%s')""" % (self._preview_winid, escQuote(jump_cmd))) + lfCmd("call win_execute(%d, 'norm! zz')" % self._preview_winid) + elif line_nr > 0: + lfCmd("""call win_execute(%d, "call cursor(%d, 1)")""" % (self._preview_winid, line_nr)) + lfCmd("call win_execute(%d, 'norm! zz')" % self._preview_winid) + lfCmd("call win_execute(%d, 'setlocal cursorline number norelativenumber colorcolumn= ')" % self._preview_winid) + lfCmd("call win_execute(%d, 'setlocal foldmethod=manual')" % self._preview_winid) + if lfEval("exists('+cursorlineopt')") == '1': + lfCmd("call win_execute(%d, 'setlocal cursorlineopt=both')" % self._preview_winid) + lfCmd("call win_execute(%d, 'setlocal wincolor=Lf_hl_popup_window')" % self._preview_winid) + if lfEval("get(g:, 'Lf_PopupShowFoldcolumn', 1)") == '0' or lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1': + lfCmd("call win_execute(%d, 'setlocal foldcolumn=0')" % self._preview_winid) + else: + lfCmd("call win_execute(%d, 'setlocal foldcolumn=1')" % self._preview_winid) + @ignoreEvent('BufWinEnter,BufEnter') def _createPopupModePreview(self, title, source, line_nr, jump_cmd): """ @@ -457,26 +528,15 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): """ self._is_previewed = True + + show_borders = lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1' + if lfEval("has('nvim')") == '1': width = int(lfEval("get(g:, 'Lf_PreviewPopupWidth', 0)")) if width <= 0: maxwidth = int(lfEval("&columns"))//2 else: maxwidth = min(width, int(lfEval("&columns"))) - relative = 'editor' - if isinstance(source, int): - buffer_len = len(vim.buffers[source]) - else: - try: - lfCmd("let content = readfile('%s', '', 4096)" % escQuote(source)) - except vim.error as e: - lfPrintError(e) - return - buffer_len = int(lfEval("len(content)")) - lfCmd("noautocmd let g:Lf_preview_scratch_buffer = nvim_create_buf(0, 1)") - lfCmd("noautocmd call setbufline(g:Lf_preview_scratch_buffer, 1, content)") - lfCmd("noautocmd call nvim_buf_set_option(g:Lf_preview_scratch_buffer, 'bufhidden', 'wipe')") - lfCmd("noautocmd call nvim_buf_set_option(g:Lf_preview_scratch_buffer, 'undolevels', -1)") float_window = self._getInstance().window # row and col start from 0 @@ -496,6 +556,8 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): [popup_borders[7], "Lf_hl_popupBorder"], [popup_borders[3], "Lf_hl_popupBorder"] ] + + relative = 'editor' if preview_pos.lower() == 'bottom': anchor = "NW" if self._getInstance().getPopupInstance().statusline_win: @@ -514,7 +576,7 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): elif preview_pos.lower() == 'top': anchor = "SW" row = float_win_row - 1 - if lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1': + if show_borders: row -= 1 col = float_win_col height = row @@ -528,13 +590,13 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): anchor = "NW" row = float_win_row - 1 col = float_win_col + float_win_width - if lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1': + if show_borders: row -= 1 col += 2 height = self._getInstance().getPopupHeight() + 1 if width <= 0: width = float_win_width - if lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1': + if show_borders: width = min(width, int(lfEval("&columns")) - col - 2) else: width = min(width, int(lfEval("&columns")) - col) @@ -542,7 +604,7 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): anchor = "NE" row = float_win_row - 1 col = float_win_col - if lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1': + if show_borders: row -= 1 height = self._getInstance().getPopupHeight() + 1 if width <= 0: @@ -576,33 +638,13 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): "noautocmd": 1 } - if lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1': + if show_borders: config["border"] = borderchars + config["title"] = " Preview " + config["title_pos"] = "center" - if isinstance(source, int): - self._preview_winid = int(lfEval("nvim_open_win(%d, 0, %s)" % (source, str(config)))) - else: - self._preview_winid = int(lfEval("nvim_open_win(g:Lf_preview_scratch_buffer, 0, %s)" % str(config))) - self._preview_filetype = lfEval("getbufvar(winbufnr(%d), '&ft')" % self._preview_winid) + self._createPreviewWindow(config, source, line_nr, jump_cmd) lfCmd("let g:Lf_PreviewWindowID[%d] = %d" % (id(self), self._preview_winid)) - - if jump_cmd: - cur_winid = lfEval("win_getid()") - lfCmd("noautocmd call win_gotoid(%d)" % self._preview_winid) - lfCmd(jump_cmd) - lfCmd("noautocmd call win_gotoid(%s)" % cur_winid) - if buffer_len >= line_nr > 0: - lfCmd("""call nvim_win_set_cursor(%d, [%d, 1])""" % (self._preview_winid, line_nr)) - - self._setWinOptions(self._preview_winid) - - cur_winid = lfEval("win_getid()") - lfCmd("noautocmd call win_gotoid(%d)" % self._preview_winid) - if not isinstance(source, int): - lfCmd("doautocmd filetypedetect BufNewFile %s" % source) - lfCmd("silent! %foldopen!") - lfCmd("norm! zz") - lfCmd("noautocmd call win_gotoid(%s)" % cur_winid) else: popup_window = self._getInstance().window popup_pos = lfEval("popup_getpos(%d)" % popup_window.id) @@ -613,19 +655,6 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): else: maxwidth = min(width, int(lfEval("&columns"))) - if isinstance(source, int): - lfCmd("let content = getbufline(%d, 1, '$')" % source) - buffer_len = len(vim.buffers[source]) - filename = vim.buffers[source].name - else: - filename = source - try: - lfCmd("let content = readfile('%s', '', 4096)" % escQuote(source)) - except vim.error as e: - lfPrintError(e) - return - buffer_len = int(lfEval("len(content)")) - preview_pos = lfEval("get(g:, 'Lf_PopupPreviewPosition', 'right')") if preview_pos.lower() == 'bottom': maxwidth = int(popup_pos["width"]) @@ -699,7 +728,7 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): "filter": "leaderf#popupModePreviewFilter", } - if lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1': + if show_borders: options["borderchars"] = lfEval("g:Lf_PopupBorders") options["maxwidth"] -= 2 options["minwidth"] -= 2 @@ -708,20 +737,20 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): if preview_pos.lower() == 'bottom': del options["title"] options["border"] = [0, 0, 1, 0] - if lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1': + if show_borders: options["border"] = [0, 1, 1, 1] elif preview_pos.lower() == 'top': - if lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1': + if show_borders: options["border"] = [1, 1, 0, 1] elif preview_pos.lower() == 'right': - if lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1': + if show_borders: options["border"] = [1, 1, 1, 1] options["line"] -= 1 # options["col"] += 1 options["maxheight"] += 1 options["minheight"] += 1 elif preview_pos.lower() == 'left': - if lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1': + if show_borders: options["border"] = [1, 1, 1, 1] options["line"] -= 1 # options["col"] -= 1 @@ -734,27 +763,8 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): options["maxheight"] = maxheight options["minheight"] = maxheight - lfCmd("noautocmd silent! let winid = popup_create(content, %s)" % json.dumps(options)) - lfCmd("call win_execute(winid, 'setlocal nomodeline')") - lfCmd("call win_execute(winid, 'doautocmd filetypedetect BufNewFile %s')" % escQuote(filename)) + self._createPreviewWindow(options, source, line_nr, jump_cmd) - self._preview_winid = int(lfEval("winid")) - self._preview_filetype = lfEval("getbufvar(winbufnr(winid), '&ft')") - if jump_cmd: - lfCmd("""call win_execute(%d, '%s')""" % (self._preview_winid, escQuote(jump_cmd))) - lfCmd("call win_execute(%d, 'norm! zz')" % self._preview_winid) - elif line_nr > 0: - lfCmd("""call win_execute(%d, "call cursor(%d, 1)")""" % (self._preview_winid, line_nr)) - lfCmd("call win_execute(%d, 'norm! zz')" % self._preview_winid) - lfCmd("call win_execute(%d, 'setlocal cursorline number norelativenumber colorcolumn= ')" % self._preview_winid) - lfCmd("call win_execute(%d, 'setlocal foldmethod=manual')" % self._preview_winid) - if lfEval("exists('+cursorlineopt')") == '1': - lfCmd("call win_execute(%d, 'setlocal cursorlineopt=both')" % self._preview_winid) - lfCmd("call win_execute(%d, 'setlocal wincolor=Lf_hl_popup_window')" % self._preview_winid) - if lfEval("get(g:, 'Lf_PopupShowFoldcolumn', 1)") == '0' or lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1': - lfCmd("call win_execute(%d, 'setlocal foldcolumn=0')" % self._preview_winid) - else: - lfCmd("call win_execute(%d, 'setlocal foldcolumn=1')" % self._preview_winid) def isPreviewWindowOpen(self): return self._preview_winid > 0 and int(lfEval("winbufnr(%d)" % self._preview_winid)) != -1 @@ -831,49 +841,37 @@ def _createPopupPreview(self, title, source, line_nr, jump_cmd=''): self._createPopupModePreview(title, source, line_nr, jump_cmd) return True + show_borders = lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1' + preview_pos = lfEval("get(g:, 'Lf_PreviewPosition', 'top')") if lfEval("has('nvim')") == '1': - width = int(lfEval("get(g:, 'Lf_PreviewPopupWidth', 0)")) - if width == 0: - width = int(lfEval("&columns"))//2 - else: - width = min(width, int(lfEval("&columns"))) - maxheight = int(lfEval("&lines - (line('w$') - line('.')) - 3")) - maxheight -= int(self._getInstance().window.height) - int(lfEval("(line('w$') - line('w0') + 1)")) - relative = 'editor' - anchor = "SW" - row = maxheight - if isinstance(source, int): - buffer_len = len(vim.buffers[source]) - else: - try: - lfCmd("let content = readfile('%s', '', 4096)" % escQuote(source)) - except vim.error as e: - lfPrintError(e) - return False - buffer_len = int(lfEval("len(content)")) - lfCmd("noautocmd let g:Lf_preview_scratch_buffer = nvim_create_buf(0, 1)") - lfCmd("noautocmd call setbufline(g:Lf_preview_scratch_buffer, 1, content)") - lfCmd("noautocmd call nvim_buf_set_option(g:Lf_preview_scratch_buffer, 'bufhidden', 'wipe')") - height = max(1, min(maxheight, buffer_len)) - preview_pos = lfEval("get(g:, 'Lf_PreviewHorizontalPosition', 'right')") - if preview_pos.lower() == 'center': - col = (int(lfEval("&columns")) - width) // 2 - elif preview_pos.lower() == 'left': + if preview_pos.lower() == 'topleft': + relative = 'editor' + anchor = "SW" + width = self._getInstance().window.width // 2 + height = self._getInstance().window.row + row = self._getInstance().window.row col = 0 + elif preview_pos.lower() == 'topright': + relative = 'editor' + anchor = "SW" + width = self._getInstance().window.width // 2 + height = self._getInstance().window.row + row = self._getInstance().window.row + col = self._getInstance().window.width - width elif preview_pos.lower() == 'right': - col = int(lfEval("&columns")) - width - else: - relative = 'cursor' - row = 0 - col = 0 - - if maxheight < int(lfEval("&lines"))//2 - 2: + relative = 'editor' anchor = "NW" - if relative == 'cursor': - row = 1 - else: - row = maxheight + 1 - height = min(int(lfEval("&lines")) - maxheight - 3, buffer_len) + width = self._getInstance().window.width // 2 + height = self._getInstance().window.height + row = self._getInstance().window.row + col = self._getInstance().window.width - width + else: # preview_pos.lower() == 'top' + relative = 'editor' + anchor = "SW" + width = self._getInstance().window.width + height = self._getInstance().window.row + row = self._getInstance().window.row + col = 0 config = { "relative": relative, @@ -882,51 +880,54 @@ def _createPopupPreview(self, title, source, line_nr, jump_cmd=''): "width" : width, "zindex" : 20480, "row" : row, - "col" : col + "col" : col, + "noautocmd": 1 } - if isinstance(source, int): - self._preview_winid = int(lfEval("nvim_open_win(%d, 0, %s)" % (source, str(config)))) - else: - self._preview_winid = int(lfEval("nvim_open_win(g:Lf_preview_scratch_buffer, 0, %s)" % str(config))) - self._preview_filetype = lfEval("getbufvar(winbufnr(%d), '&ft')" % self._preview_winid) - if jump_cmd: - cur_winid = lfEval("win_getid()") - lfCmd("noautocmd call win_gotoid(%d)" % self._preview_winid) - lfCmd(jump_cmd) - lfCmd("noautocmd call win_gotoid(%s)" % cur_winid) - if buffer_len >= line_nr > 0: - lfCmd("""call nvim_win_set_cursor(%d, [%d, 1])""" % (self._preview_winid, line_nr)) - lfCmd("call nvim_win_set_option(%d, 'number', v:true)" % self._preview_winid) - lfCmd("call nvim_win_set_option(%d, 'relativenumber', v:false)" % self._preview_winid) - lfCmd("call nvim_win_set_option(%d, 'cursorline', v:true)" % self._preview_winid) - lfCmd("call nvim_win_set_option(%d, 'foldmethod', 'manual')" % self._preview_winid) - if lfEval("exists('+cursorlineopt')") == '1': - lfCmd("call nvim_win_set_option(%d, 'cursorlineopt', 'both')" % self._preview_winid) - lfCmd("call nvim_win_set_option(%d, 'colorcolumn', '')" % self._preview_winid) - cur_winid = lfEval("win_getid()") - lfCmd("noautocmd call win_gotoid(%d)" % self._preview_winid) - if not isinstance(source, int): - lfCmd("doautocmd filetypedetect BufNewFile %s" % source) - lfCmd("silent! %foldopen!") - lfCmd("noautocmd call win_gotoid(%s)" % cur_winid) + if show_borders: + popup_borders = lfEval("g:Lf_PopupBorders") + borderchars = [ + [popup_borders[4], "Lf_hl_popupBorder"], + [popup_borders[0], "Lf_hl_popupBorder"], + [popup_borders[5], "Lf_hl_popupBorder"], + [popup_borders[1], "Lf_hl_popupBorder"], + [popup_borders[6], "Lf_hl_popupBorder"], + [popup_borders[2], "Lf_hl_popupBorder"], + [popup_borders[7], "Lf_hl_popupBorder"], + [popup_borders[3], "Lf_hl_popupBorder"] + ] + config["border"] = borderchars + config["height"] -= 2 + config["width"] -= 2 + config["title"] = " Preview " + config["title_pos"] = "center" + + self._createPreviewWindow(config, source, line_nr, jump_cmd) else: - preview_pos = lfEval("get(g:, 'Lf_PreviewHorizontalPosition', 'right')") - if preview_pos.lower() == 'center': - col = 0 - elif preview_pos.lower() == 'left': + if preview_pos.lower() == 'topleft': + maxwidth = self._getInstance().window.width // 2 + maxheight = self._getInstance().window.row - 1 + pos = "botleft" + line = self._getInstance().window.row col = 1 + elif preview_pos.lower() == 'topright': + maxwidth = self._getInstance().window.width // 2 + maxheight = self._getInstance().window.row - 1 + pos = "botleft" + line = self._getInstance().window.row + col = self._getInstance().window.width - maxwidth + 1 elif preview_pos.lower() == 'right': - col = int(lfEval("&columns"))//2 + 2 - else: - col = "cursor" - width = int(lfEval("get(g:, 'Lf_PreviewPopupWidth', 0)")) - if width == 0: - maxwidth = int(lfEval("&columns"))//2 - 1 - else: - maxwidth = min(width, int(lfEval("&columns"))) - maxheight = int(lfEval("&lines - (line('w$') - line('.')) - 4")) - maxheight -= int(self._getInstance().window.height) - int(lfEval("(line('w$') - line('w0') + 1)")) + maxwidth = self._getInstance().window.width // 2 + maxheight = self._getInstance().window.height - 1 + pos = "topleft" + line = self._getInstance().window.row + 1 + col = self._getInstance().window.width - maxwidth + 1 + else: # preview_pos.lower() == 'top' + maxwidth = self._getInstance().window.width + maxheight = self._getInstance().window.row - 1 + pos = "botleft" + line = self._getInstance().window.row + col = 1 options = { "title": title, @@ -934,51 +935,26 @@ def _createPopupPreview(self, title, source, line_nr, jump_cmd=''): "minwidth": maxwidth, "maxheight": maxheight, "minheight": maxheight, - "zindex": 20481, - "pos": "botleft", - "line": "cursor-1", + "zindex": 20480, + "pos": pos, + "line": line, "col": col, - "padding": [0, 0, 0, 1], - "border": [1, 0, 0, 0], - "borderchars": [' '], + "scrollbar": 0, + "padding": [0, 0, 0, 0], "borderhighlight": ["Lf_hl_previewTitle"], - "filter": "leaderf#popupModePreviewFilter", + "filter": "leaderf#popupModePreviewFilter", } - if maxheight < int(lfEval("&lines"))//2 - 2: - maxheight = int(lfEval("&lines")) - maxheight - 5 - del options["title"] - options["border"] = [0, 0, 1, 0] - options["maxheight"] = maxheight - options["minheight"] = maxheight - - if isinstance(source, int): - lfCmd("let content = getbufline(%d, 1, '$')" % source) - filename = vim.buffers[source].name - else: - filename = source - try: - lfCmd("let content = readfile('%s', '', 4096)" % escQuote(source)) - except vim.error as e: - lfPrintError(e) - return False - lfCmd("silent! let winid = popup_create(content, %s)" % json.dumps(options)) - lfCmd("call win_execute(winid, 'setlocal nomodeline')") - lfCmd("call win_execute(winid, 'doautocmd filetypedetect BufNewFile %s')" % escQuote(filename)) + if show_borders: + options["border"] = [] + options["borderchars"] = lfEval("g:Lf_PopupBorders") + options["maxwidth"] -= 2 + options["minwidth"] -= 2 + options["maxheight"] -= 1 + options["minheight"] -= 1 + options["borderhighlight"] = ["Lf_hl_popupBorder"] - self._preview_winid = int(lfEval("winid")) - self._preview_filetype = lfEval("getbufvar(winbufnr(winid), '&ft')") - if self._current_mode == 'NORMAL': - lfCmd("call leaderf#ResetPopupOptions(%d, 'filter', function('leaderf#normalModePreviewFilter', [%d, %d]))" - % (self._preview_winid, id(self), self._getInstance().windowId)) - if jump_cmd: - lfCmd("""call win_execute(%d, '%s')""" % (self._preview_winid, escQuote(jump_cmd))) - elif line_nr > 0: - lfCmd("""call win_execute(%d, "exec 'norm! %dG'")""" % (self._preview_winid, line_nr)) - lfCmd("call win_execute(%d, 'setlocal cursorline number norelativenumber')" % self._preview_winid) - lfCmd("call win_execute(%d, 'setlocal foldmethod=manual')" % self._preview_winid) - if lfEval("exists('+cursorlineopt')") == '1': - lfCmd("call win_execute(%d, 'setlocal cursorlineopt=both')" % self._preview_winid) + self._createPreviewWindow(options, source, line_nr, jump_cmd) return True diff --git a/doc/leaderf.txt b/doc/leaderf.txt index 93d6ab3e..1cdd5524 100644 --- a/doc/leaderf.txt +++ b/doc/leaderf.txt @@ -59,11 +59,11 @@ g:Lf_WindowPosition *g:Lf_WindowPosition* Setting this option can change the position of the LeaderF window. The value can be 'fullScreen', 'top', 'bottom', 'left', 'right'. 'fullScreen' - the LeaderF window take up the full screen - 'top' - the LeaderF window is at the top of the screen. + 'top' - the LeaderF window is at the top of the screen. 'bottom' - the LeaderF window is at the bottom of the screen. - 'left' - the LeaderF window is at the left of the screen. - 'right' - the LeaderF window is at the right of the screen. - 'popup' - the LeaderF window is a popup window or floating window. + 'left' - the LeaderF window is at the left of the screen. + 'right' - the LeaderF window is at the right of the screen. + 'popup' - the LeaderF window is a popup window or floating window. Default value is 'bottom'. g:Lf_WindowHeight *g:Lf_WindowHeight* @@ -748,6 +748,10 @@ g:Lf_PreviewInPopup *g:Lf_PreviewInPopup* Default value is 1. g:Lf_PreviewHorizontalPosition *g:Lf_PreviewHorizontalPosition* + [[This option is deprecated. Use |g:Lf_PreviewPosition| instead.]] + [[This option is deprecated. Use |g:Lf_PreviewPosition| instead.]] + [[This option is deprecated. Use |g:Lf_PreviewPosition| instead.]] + Specify where to locate the preview window horizontally. The value can be one of the following: 'left': the preview window is on the left side of the screen. @@ -758,8 +762,9 @@ g:Lf_PreviewHorizontalPosition *g:Lf_PreviewHorizontalPosition* Default value is 'right'. g:Lf_PreviewPopupWidth *g:Lf_PreviewPopupWidth* - Specify the width of preview popup window, the value should be a non-negative - integer. If the value is 0, the width is half of the screen's width. + Specify the width of preview window, the value should be a non-negative + integer. If the value is 0, the width of preview window is the same as the + width of the main LeaderF window. Default value is 0. @@ -822,7 +827,7 @@ g:Lf_PopupShowStatusline *g:Lf_PopupShowStatusline* Default value is 1. g:Lf_PopupPreviewPosition *g:Lf_PopupPreviewPosition* - Specify where to locate the preview window when LeaderF is in popup mode. + Specify where to place the preview window when LeaderF is in popup mode. `Popup mode` is when |g:Lf_WindowPosition| is 'popup' or '--popup' is in the options list of `Leaderf` command. The value can be one of the following: @@ -830,11 +835,20 @@ g:Lf_PopupPreviewPosition *g:Lf_PopupPreviewPosition* 'bottom': the preview window is at the bottom of the main LeaderF window. 'left': the preview window is on the left of the main LeaderF window. 'right': the preview window is on the right of the main LeaderF window. - 'cursor': the preview window is at the cursor position in the main LeaderF - window. Default value is 'right'. +g:Lf_PreviewPosition *g:Lf_PreviewPosition* + Specify where to place the preview window when LeaderF is in non-popup mode. + + The value can be one of the following: + 'top': the preview window is on the top of the main LeaderF window. + 'topleft': the preview window is on the topleft of the main LeaderF window. + 'topright': the preview window is on the topright of the main LeaderF window. + 'right': the preview window is on the right of the main LeaderF window. + + Default value is 'top'. + g:Lf_PopupColorscheme *g:Lf_PopupColorscheme* You can configure the colorscheme of LeaderF in popup mode. e.g. > From 2b35dd797d02d320dba43abec5223e41aa163865 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 20 Jul 2023 10:57:08 +0800 Subject: [PATCH 104/365] display title as "Preview" --- autoload/leaderf/python/leaderf/manager.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 39ec9ddb..98227b58 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -711,7 +711,7 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): line = maxheight + 1 options = { - "title": title, + "title": " Preview ", "maxwidth": maxwidth, "minwidth": maxwidth, "maxheight": maxheight, @@ -792,8 +792,6 @@ def _useExistingWindow(self, title, source, line_nr, jump_cmd): lfCmd("call win_execute(%d, 'doautocmd filetypedetect BufNewFile %s')" % (self._preview_winid, escQuote(source))) self._preview_filetype = lfEval("getbufvar(winbufnr(%d), '&ft')" % self._preview_winid) else: - if lfEval("popup_getoptions(%d).title != ''" % self._preview_winid) == '1': - lfCmd("noautocmd call leaderf#ResetPopupOptions(%d, 'title', '%s')" % (self._preview_winid, title)) if isinstance(source, int): lfCmd("noautocmd call popup_settext(%d, getbufline(%d, 1, '$'))" % (self._preview_winid, source) ) filename = vim.buffers[source].name @@ -930,7 +928,7 @@ def _createPopupPreview(self, title, source, line_nr, jump_cmd=''): col = 1 options = { - "title": title, + "title": " Preview ", "maxwidth": maxwidth, "minwidth": maxwidth, "maxheight": maxheight, From 12074baabc525ac15bf8cd89ac922e992fdb7bdd Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 20 Jul 2023 17:58:09 +0800 Subject: [PATCH 105/365] 1. fix issue #913 again, use 'silent!', because we need 'modeline' to be set, if not set, vim help file will have no syntax highlight 2. add support for instant preview for 'Leaderf help' --- autoload/leaderf/Help.vim | 7 +++++++ autoload/leaderf/python/leaderf/helpExpl.py | 17 ++++++++++++++++- autoload/leaderf/python/leaderf/manager.py | 14 ++++++++------ 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/autoload/leaderf/Help.vim b/autoload/leaderf/Help.vim index 808d2749..c6ed1986 100644 --- a/autoload/leaderf/Help.vim +++ b/autoload/leaderf/Help.vim @@ -21,6 +21,13 @@ function! leaderf#Help#Maps() nnoremap x :exec g:Lf_py "helpExplManager.accept('h')" nnoremap v :exec g:Lf_py "helpExplManager.accept('v')" nnoremap t :exec g:Lf_py "helpExplManager.accept('t')" + nnoremap p :exec g:Lf_py "helpExplManager._previewResult(True)" + nnoremap j :exec g:Lf_py "helpExplManager.moveAndPreview('j')" + nnoremap k :exec g:Lf_py "helpExplManager.moveAndPreview('k')" + nnoremap :exec g:Lf_py "helpExplManager.moveAndPreview('Up')" + nnoremap :exec g:Lf_py "helpExplManager.moveAndPreview('Down')" + nnoremap :exec g:Lf_py "helpExplManager.moveAndPreview('PageUp')" + nnoremap :exec g:Lf_py "helpExplManager.moveAndPreview('PageDown')" nnoremap q :exec g:Lf_py "helpExplManager.quit()" " nnoremap :exec g:Lf_py "helpExplManager.quit()" nnoremap i :exec g:Lf_py "helpExplManager.input()" diff --git a/autoload/leaderf/python/leaderf/helpExpl.py b/autoload/leaderf/python/leaderf/helpExpl.py index c8c88bc8..fb21bf9d 100644 --- a/autoload/leaderf/python/leaderf/helpExpl.py +++ b/autoload/leaderf/python/leaderf/helpExpl.py @@ -16,6 +16,7 @@ class HelpExplorer(Explorer): def __init__(self): self._content = [] + self._file_ids = {} def getContent(self, *args, **kwargs): if self._content: @@ -26,6 +27,7 @@ def getContent(self, *args, **kwargs): def getFreshContent(self, *args, **kwargs): self._content = [] lfCmd("silent! helptags ALL") + file_id = 0 for dir in lfEval("&rtp").split(','): tags_file = os.path.join(dir, "doc", "tags") try: @@ -33,10 +35,13 @@ def getFreshContent(self, *args, **kwargs): lines = f.readlines() for line in lines: tag, file = line.split()[:2] - self._content.append("{:<40} {}".format(tag, file)) + self._content.append("{:<40} {} {}".format(tag, file, file_id)) except IOError: pass + self._file_ids[file_id] = os.path.dirname(tags_file) + file_id += 1 + return self._content def getStlCategory(self): @@ -134,6 +139,16 @@ def _beforeExit(self): def _supportsRefine(self): return True + def _previewInPopup(self, *args, **kwargs): + if len(args) == 0: + return + + line = args[0] + tagname, tagfile, file_id = line.split(None, 2) + tagfile = os.path.join(self._getExplorer()._file_ids[int(file_id)], tagfile) + jump_cmd = "call search('\m\*%s\*', 'w')" % escQuote(tagname) + self._createPopupPreview("", tagfile, 0, jump_cmd) + #***************************************************** # helpExplManager is a singleton diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 98227b58..d63e9ca7 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -463,9 +463,9 @@ def _createPreviewWindow(self, config, source, line_nr, jump_cmd): lfCmd("noautocmd call setbufline(g:Lf_preview_scratch_buffer, 1, content)") lfCmd("noautocmd call nvim_buf_set_option(g:Lf_preview_scratch_buffer, 'bufhidden', 'wipe')") lfCmd("noautocmd call nvim_buf_set_option(g:Lf_preview_scratch_buffer, 'undolevels', -1)") + lfCmd("noautocmd call nvim_buf_set_option(g:Lf_preview_scratch_buffer, 'modeline', v:true)") self._preview_winid = int(lfEval("nvim_open_win(g:Lf_preview_scratch_buffer, 0, %s)" % str(config))) - self._preview_filetype = lfEval("getbufvar(winbufnr(%d), '&ft')" % self._preview_winid) if jump_cmd: cur_winid = lfEval("win_getid()") @@ -480,10 +480,11 @@ def _createPreviewWindow(self, config, source, line_nr, jump_cmd): cur_winid = lfEval("win_getid()") lfCmd("noautocmd call win_gotoid(%d)" % self._preview_winid) if not isinstance(source, int): - lfCmd("doautocmd filetypedetect BufNewFile %s" % source) + lfCmd("silent! doautocmd filetypedetect BufNewFile %s" % source) lfCmd("silent! %foldopen!") lfCmd("norm! zz") lfCmd("noautocmd call win_gotoid(%s)" % cur_winid) + self._preview_filetype = lfEval("getbufvar(winbufnr(%d), '&ft')" % self._preview_winid) else: if isinstance(source, int): lfCmd("let content = getbufline(%d, 1, '$')" % source) @@ -497,8 +498,8 @@ def _createPreviewWindow(self, config, source, line_nr, jump_cmd): return lfCmd("noautocmd silent! let winid = popup_create(content, %s)" % json.dumps(config)) - lfCmd("call win_execute(winid, 'setlocal nomodeline')") - lfCmd("call win_execute(winid, 'doautocmd filetypedetect BufNewFile %s')" % escQuote(filename)) + lfCmd("call win_execute(winid, 'setlocal modeline')") + lfCmd("call win_execute(winid, 'silent! doautocmd filetypedetect BufNewFile %s')" % escQuote(filename)) self._preview_winid = int(lfEval("winid")) self._preview_filetype = lfEval("getbufvar(winbufnr(winid), '&ft')") @@ -784,12 +785,13 @@ def _useExistingWindow(self, title, source, line_nr, jump_cmd): if lfEval("!exists('g:Lf_preview_scratch_buffer') || !bufexists(g:Lf_preview_scratch_buffer)") == '1': lfCmd("noautocmd let g:Lf_preview_scratch_buffer = nvim_create_buf(0, 1)") lfCmd("noautocmd call nvim_buf_set_option(g:Lf_preview_scratch_buffer, 'undolevels', -1)") + lfCmd("noautocmd call nvim_buf_set_option(g:Lf_preview_scratch_buffer, 'modeline', v:true)") lfCmd("noautocmd call nvim_buf_set_lines(g:Lf_preview_scratch_buffer, 0, -1, v:false, content)") lfCmd("noautocmd call nvim_win_set_buf(%d, g:Lf_preview_scratch_buffer)" % self._preview_winid) cur_filetype = getExtension(source) if cur_filetype != self._preview_filetype: - lfCmd("call win_execute(%d, 'doautocmd filetypedetect BufNewFile %s')" % (self._preview_winid, escQuote(source))) + lfCmd("call win_execute(%d, 'silent! doautocmd filetypedetect BufNewFile %s')" % (self._preview_winid, escQuote(source))) self._preview_filetype = lfEval("getbufvar(winbufnr(%d), '&ft')" % self._preview_winid) else: if isinstance(source, int): @@ -806,7 +808,7 @@ def _useExistingWindow(self, title, source, line_nr, jump_cmd): cur_filetype = getExtension(filename) if cur_filetype != self._preview_filetype: - lfCmd("call win_execute(%d, 'doautocmd filetypedetect BufNewFile %s')" % (self._preview_winid, escQuote(filename))) + lfCmd("call win_execute(%d, 'silent! doautocmd filetypedetect BufNewFile %s')" % (self._preview_winid, escQuote(filename))) self._preview_filetype = lfEval("getbufvar(winbufnr(%d), '&ft')" % self._preview_winid) if jump_cmd: From 88c913a52fdbd0bd96a0e8b431425ae09e7519eb Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 20 Jul 2023 19:13:03 +0800 Subject: [PATCH 106/365] (nvim) reset highlight wrong if cursor is in the preview window --- autoload/leaderf/python/leaderf/manager.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index d63e9ca7..2a4925c2 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -80,6 +80,21 @@ def deco(self, *args, **kwargs): self._timer_id = None return deco +def windo(func): + if lfEval("has('nvim')") == '0': + return func + + @wraps(func) + def deco(self, *args, **kwargs): + try: + cur_winid = lfEval("win_getid()") + lfCmd("noautocmd call win_gotoid(%d)" % self._getInstance().window.id) + return func(self, *args, **kwargs) + finally: + lfCmd("noautocmd call win_gotoid(%s)" % cur_winid) + + return deco + #***************************************************** # Manager #***************************************************** @@ -1743,6 +1758,7 @@ def _clearHighlightsPos(self): self._highlight_pos_list = [] self._highlight_refine_pos = [] + @windo def _resetHighlights(self): self._clearHighlights() From 32d1c53728acfdc465dc307ec1cb1acf3ac15926 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Fri, 21 Jul 2023 09:56:14 +0800 Subject: [PATCH 107/365] fix issue #1018 --- autoload/leaderf/python/leaderf/instance.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/autoload/leaderf/python/leaderf/instance.py b/autoload/leaderf/python/leaderf/instance.py index dfe50c53..6053e1b2 100644 --- a/autoload/leaderf/python/leaderf/instance.py +++ b/autoload/leaderf/python/leaderf/instance.py @@ -420,9 +420,6 @@ def _createPopupWindow(self): col += maxwidth + 1 else: col = (int(lfEval("&columns")) - maxwidth) // 2 - - # to the left a bit - col -= 3 else: col = min(col, int(lfEval("&columns")) - maxwidth) From de62b4e196b1f2891acf8147e580f28ed3a9f907 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Fri, 21 Jul 2023 12:29:49 +0800 Subject: [PATCH 108/365] fix a bug https://github.com/Yggdroot/LeaderF/commit/88c913a52fdbd0bd96a0e8b431425ae09e7519eb#commitcomment-122257340 --- autoload/leaderf/python/leaderf/manager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 2a4925c2..0a1fc15d 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -88,7 +88,7 @@ def windo(func): def deco(self, *args, **kwargs): try: cur_winid = lfEval("win_getid()") - lfCmd("noautocmd call win_gotoid(%d)" % self._getInstance().window.id) + lfCmd("noautocmd call win_gotoid(%d)" % self._getInstance().windowId) return func(self, *args, **kwargs) finally: lfCmd("noautocmd call win_gotoid(%s)" % cur_winid) From 5f2e49bcfdeaf0e6f4f8261a8291b824bb7aeda7 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Fri, 21 Jul 2023 16:59:37 +0800 Subject: [PATCH 109/365] update doc --- doc/leaderf.txt | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/doc/leaderf.txt b/doc/leaderf.txt index 1cdd5524..ff89a69c 100644 --- a/doc/leaderf.txt +++ b/doc/leaderf.txt @@ -502,9 +502,9 @@ g:Lf_WorkingDirectoryMode *g:Lf_WorkingDirectoryMode* g:Lf_WorkingDirectory *g:Lf_WorkingDirectory* Set LeaderF's working directory. It will ignore the |g:Lf_RootMarkers| and - |g:Lf_WorkingDirectoryMode| option set. - e.g., > - let g:Lf_WorkingDirectory = finddir('.git', '.;') + |g:Lf_WorkingDirectoryMode| option set. + e.g., > + let g:Lf_WorkingDirectory = finddir('.git', '.;') < g:Lf_CommandMap *g:Lf_CommandMap* Use this option to customize the mappings inside LeaderF's @@ -646,12 +646,12 @@ g:Lf_GtagsAutoGenerate *g:Lf_GtagsAutoGenerate* generated manually by using `Leaderf gtags --update` . Default value is 0. -g:Lf_GtagsGutentags *g:Lf_GtagsGutentags* - if you use https://github.com/ludovicchabant/vim-gutentags to generate - gtags; Firstly, you should let g:Lf_GtagsAutoGenerate = 0 and let g:Lf_GtagsGutentags = 1. - Then, you should config gutentags like this: g:Lf_CacheDirectory = - expand('~') and g:gutentags_cache_dir = expand(g:Lf_CacheDirectory.'/.LfCache/gtags') - Default value is 0 +g:Lf_GtagsGutentags *g:Lf_GtagsGutentags* + if you use https://github.com/ludovicchabant/vim-gutentags to generate + gtags; Firstly, you should let g:Lf_GtagsAutoGenerate = 0 and let g:Lf_GtagsGutentags = 1. + Then, you should config gutentags like this: g:Lf_CacheDirectory = expand('~') + and g:gutentags_cache_dir = expand(g:Lf_CacheDirectory.'/.LfCache/gtags') + Default value is 0 g:Lf_GtagsAutoUpdate *g:Lf_GtagsAutoUpdate* If the value is 1 and the gtags database already exists, gtags database From 55778f0ba8d909dbe5a04e1f2f44ce6558b29a5c Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Fri, 21 Jul 2023 17:33:57 +0800 Subject: [PATCH 110/365] don't fold in preview window --- autoload/leaderf/python/leaderf/manager.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 0a1fc15d..4fd8680c 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -514,10 +514,12 @@ def _createPreviewWindow(self, config, source, line_nr, jump_cmd): lfCmd("noautocmd silent! let winid = popup_create(content, %s)" % json.dumps(config)) lfCmd("call win_execute(winid, 'setlocal modeline')") + lfCmd("call win_execute(winid, 'setlocal nofoldenable')") lfCmd("call win_execute(winid, 'silent! doautocmd filetypedetect BufNewFile %s')" % escQuote(filename)) self._preview_winid = int(lfEval("winid")) self._preview_filetype = lfEval("getbufvar(winbufnr(winid), '&ft')") + if jump_cmd: lfCmd("""call win_execute(%d, '%s')""" % (self._preview_winid, escQuote(jump_cmd))) lfCmd("call win_execute(%d, 'norm! zz')" % self._preview_winid) From 987f043c6f22dc016b407d17db67944ffc1edd7b Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Sat, 22 Jul 2023 22:34:24 +0800 Subject: [PATCH 111/365] refactor the code --- autoload/leaderf/python/leaderf/instance.py | 218 ++++++++++---------- autoload/leaderf/python/leaderf/manager.py | 25 +-- 2 files changed, 117 insertions(+), 126 deletions(-) diff --git a/autoload/leaderf/python/leaderf/instance.py b/autoload/leaderf/python/leaderf/instance.py index 6053e1b2..7a1fd94b 100644 --- a/autoload/leaderf/python/leaderf/instance.py +++ b/autoload/leaderf/python/leaderf/instance.py @@ -352,6 +352,48 @@ def _setStatusline(self): .format(self.buffer.number, self._stl)) lfCmd("augroup END") + def _nvim_set_options(self, buf_number, winid): + lfCmd("call nvim_buf_set_option(%d, 'buflisted', v:false)" % buf_number) + lfCmd("call nvim_buf_set_option(%d, 'buftype', 'nofile')" % buf_number) + lfCmd("call nvim_buf_set_option(%d, 'bufhidden', 'hide')" % buf_number) + lfCmd("call nvim_buf_set_option(%d, 'undolevels', -1)" % buf_number) + lfCmd("call nvim_buf_set_option(%d, 'swapfile', v:false)" % buf_number) + + lfCmd("call nvim_win_set_option(%d, 'list', v:false)" % winid) + lfCmd("call nvim_win_set_option(%d, 'number', v:false)" % winid) + lfCmd("call nvim_win_set_option(%d, 'relativenumber', v:false)" % winid) + lfCmd("call nvim_win_set_option(%d, 'spell', v:false)" % winid) + lfCmd("call nvim_win_set_option(%d, 'foldenable', v:false)" % winid) + lfCmd("call nvim_win_set_option(%d, 'foldmethod', 'manual')" % winid) + try: + lfCmd("call nvim_win_set_option(%d, 'foldcolumn', 0)" % winid) + except vim.error: + lfCmd("call nvim_win_set_option(%d, 'foldcolumn', '0')" % winid) + lfCmd("call nvim_win_set_option(%d, 'signcolumn', 'no')" % winid) + lfCmd("call nvim_win_set_option(%d, 'cursorline', v:false)" % winid) + if lfEval("exists('+cursorlineopt')") == '1': + lfCmd("call nvim_win_set_option(%d, 'cursorlineopt', 'both')" % winid) + lfCmd("call nvim_win_set_option(%d, 'colorcolumn', '')" % winid) + + def _vim_set_options(self, winid): + lfCmd("call win_execute(%d, 'setlocal nobuflisted')" % winid) + lfCmd("call win_execute(%d, 'setlocal buftype=nofile')" % winid) + lfCmd("call win_execute(%d, 'setlocal bufhidden=hide')" % winid) + lfCmd("call win_execute(%d, 'setlocal undolevels=-1')" % winid) + lfCmd("call win_execute(%d, 'setlocal noswapfile')" % winid) + lfCmd("call win_execute(%d, 'setlocal nolist')" % winid) + lfCmd("call win_execute(%d, 'setlocal nonumber norelativenumber')" % winid) + lfCmd("call win_execute(%d, 'setlocal nospell')" % winid) + lfCmd("call win_execute(%d, 'setlocal nofoldenable')" % winid) + lfCmd("call win_execute(%d, 'setlocal foldmethod=manual')" % winid) + lfCmd("call win_execute(%d, 'setlocal shiftwidth=4')" % winid) + lfCmd("call win_execute(%d, 'setlocal nocursorline')" % winid) + lfCmd("call win_execute(%d, 'setlocal foldcolumn=0')" % winid) + lfCmd("call win_execute(%d, 'silent! setlocal signcolumn=no')" % winid) + if lfEval("exists('+cursorlineopt')") == '1': + lfCmd("call win_execute(%d, 'setlocal cursorlineopt=both')" % winid) + lfCmd("call win_execute(%d, 'setlocal colorcolumn=')" % winid) + def _createPopupWindow(self): if lfEval("has('nvim')") == '0' and self._popup_instance.valid(): if self._popup_instance.tabpage == vim.current.tabpage and lfEval("get(g:, 'Lf_Popup_VimResized', 0)") == '0' \ @@ -489,7 +531,8 @@ def _createPopupWindow(self): self._tabpage_object = vim.current.tabpage self._buffer_object = vim.buffers[buf_number] - self._window_object = FloatWindow(self._popup_winid, vim.current.window, self._buffer_object, self._tabpage_object, config["row"]) + self._window_object = FloatWindow(self._popup_winid, vim.current.window, + self._buffer_object, self._tabpage_object, config["row"]) self._popup_instance.content_win = self._window_object input_win_config = { @@ -511,35 +554,17 @@ def _createPopupWindow(self): buf_number = self._input_buffer_number lfCmd("noautocmd silent let winid = nvim_open_win(%d, 0, %s)" % (buf_number, str(input_win_config))) winid = int(lfEval("winid")) - lfCmd("call nvim_buf_set_option(%d, 'buflisted', v:false)" % buf_number) - lfCmd("call nvim_buf_set_option(%d, 'buftype', 'nofile')" % buf_number) - lfCmd("call nvim_buf_set_option(%d, 'bufhidden', 'hide')" % buf_number) - lfCmd("call nvim_buf_set_option(%d, 'undolevels', -1)" % buf_number) - lfCmd("call nvim_buf_set_option(%d, 'swapfile', v:false)" % buf_number) - - lfCmd("call nvim_win_set_option(%d, 'list', v:false)" % winid) - lfCmd("call nvim_win_set_option(%d, 'number', v:false)" % winid) - lfCmd("call nvim_win_set_option(%d, 'relativenumber', v:false)" % winid) - lfCmd("call nvim_win_set_option(%d, 'spell', v:false)" % winid) - lfCmd("call nvim_win_set_option(%d, 'foldenable', v:false)" % winid) - lfCmd("call nvim_win_set_option(%d, 'foldmethod', 'manual')" % winid) - try: - lfCmd("call nvim_win_set_option(%d, 'foldcolumn', 0)" % winid) - except vim.error: - lfCmd("call nvim_win_set_option(%d, 'foldcolumn', '0')" % winid) - lfCmd("call nvim_win_set_option(%d, 'signcolumn', 'no')" % winid) - lfCmd("call nvim_win_set_option(%d, 'cursorline', v:false)" % winid) - if lfEval("exists('+cursorlineopt')") == '1': - lfCmd("call nvim_win_set_option(%d, 'cursorlineopt', 'both')" % winid) - lfCmd("call nvim_win_set_option(%d, 'colorcolumn', '')" % winid) + self._nvim_set_options(buf_number, winid) lfCmd("call nvim_win_set_option(%d, 'winhighlight', 'Normal:Lf_hl_popup_inputText')" % winid) + def getWindow(number): for w in vim.windows: if number == w.number: return w return vim.current.window - self._popup_instance.input_win = FloatWindow(winid, getWindow(int(lfEval("win_id2win(%d)" % winid))), vim.buffers[buf_number], vim.current.tabpage, line) + self._popup_instance.input_win = FloatWindow(winid, getWindow(int(lfEval("win_id2win(%d)" % winid))), + vim.buffers[buf_number], vim.current.tabpage, line) show_stl = 0 if lfEval("get(g:, 'Lf_PopupShowStatusline', 1)") == '1': @@ -563,38 +588,23 @@ def getWindow(number): buf_number = self._stl_buffer_number lfCmd("noautocmd silent let winid = nvim_open_win(%d, 0, %s)" % (buf_number, str(stl_win_config))) winid = int(lfEval("winid")) - lfCmd("call nvim_buf_set_option(%d, 'buflisted', v:false)" % buf_number) - lfCmd("call nvim_buf_set_option(%d, 'buftype', 'nofile')" % buf_number) - lfCmd("call nvim_buf_set_option(%d, 'bufhidden', 'hide')" % buf_number) - lfCmd("call nvim_buf_set_option(%d, 'undolevels', -1)" % buf_number) - lfCmd("call nvim_buf_set_option(%d, 'swapfile', v:false)" % buf_number) - - lfCmd("call nvim_win_set_option(%d, 'list', v:false)" % winid) - lfCmd("call nvim_win_set_option(%d, 'number', v:false)" % winid) - lfCmd("call nvim_win_set_option(%d, 'relativenumber', v:false)" % winid) - lfCmd("call nvim_win_set_option(%d, 'spell', v:false)" % winid) - lfCmd("call nvim_win_set_option(%d, 'foldenable', v:false)" % winid) - lfCmd("call nvim_win_set_option(%d, 'foldmethod', 'manual')" % winid) - try: - lfCmd("call nvim_win_set_option(%d, 'foldcolumn', 0)" % winid) - except vim.error: - lfCmd("call nvim_win_set_option(%d, 'foldcolumn', '0')" % winid) - lfCmd("call nvim_win_set_option(%d, 'signcolumn', 'no')" % winid) - lfCmd("call nvim_win_set_option(%d, 'cursorline', v:false)" % winid) - if lfEval("exists('+cursorlineopt')") == '1': - lfCmd("call nvim_win_set_option(%d, 'cursorlineopt', 'both')" % winid) - lfCmd("call nvim_win_set_option(%d, 'colorcolumn', '')" % winid) + self._nvim_set_options(buf_number, winid) lfCmd("call nvim_win_set_option(%d, 'winhighlight', 'Normal:Lf_hl_popup_blank')" % winid) - self._popup_instance.statusline_win = FloatWindow(winid, getWindow(int(lfEval("win_id2win(%d)" % winid))), vim.buffers[buf_number], vim.current.tabpage, stl_win_config["row"]) + self._popup_instance.statusline_win = FloatWindow(winid, + getWindow(int(lfEval("win_id2win(%d)" % winid))), + vim.buffers[buf_number], + vim.current.tabpage, + stl_win_config["row"]) if "--recall" in self._arguments: self.refreshPopupStatusline() lfCmd("augroup Lf_Floatwin_Close") - lfCmd("autocmd! WinEnter * call leaderf#closeAllFloatwin(%d, %d, %d, %d, %d)" % (self._popup_instance.input_win.id, - self._popup_instance.content_win.id, - self._popup_instance.statusline_win.id if show_stl else -1, - show_stl, id(self._manager))) + lfCmd("autocmd! WinEnter * call leaderf#closeAllFloatwin(%d, %d, %d, %d, %d)" + % (self._popup_instance.input_win.id, + self._popup_instance.content_win.id, + self._popup_instance.statusline_win.id if show_stl else -1, + show_stl, id(self._manager))) lfCmd("augroup END") if self._float_win_view is not None: @@ -637,26 +647,13 @@ def getWindow(number): lfCmd("noautocmd silent noswapfile let winid = popup_create(%d, %s)" % (buf_number, str(options))) self._popup_winid = int(lfEval("winid")) self._window_id = self._popup_winid - lfCmd("call win_execute(%d, 'setlocal nobuflisted')" % self._popup_winid) - lfCmd("call win_execute(%d, 'setlocal buftype=nofile')" % self._popup_winid) - lfCmd("call win_execute(%d, 'setlocal bufhidden=hide')" % self._popup_winid) - lfCmd("call win_execute(%d, 'setlocal undolevels=-1')" % self._popup_winid) - lfCmd("call win_execute(%d, 'setlocal noswapfile')" % self._popup_winid) - lfCmd("call win_execute(%d, 'setlocal nolist')" % self._popup_winid) - lfCmd("call win_execute(%d, 'setlocal number norelativenumber')" % self._popup_winid) - lfCmd("call win_execute(%d, 'setlocal nospell')" % self._popup_winid) - lfCmd("call win_execute(%d, 'setlocal nofoldenable')" % self._popup_winid) - lfCmd("call win_execute(%d, 'setlocal foldmethod=manual')" % self._popup_winid) - lfCmd("call win_execute(%d, 'setlocal shiftwidth=4')" % self._popup_winid) + self._vim_set_options(self._popup_winid) + lfCmd("call win_execute(%d, 'setlocal number')" % self._popup_winid) lfCmd("call win_execute(%d, 'setlocal cursorline')" % self._popup_winid) - if lfEval("exists('+cursorlineopt')") == '1': - lfCmd("call win_execute(%d, 'setlocal cursorlineopt=both')" % self._popup_winid) if lfEval("get(g:, 'Lf_PopupShowFoldcolumn', 1)") == '0' or lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1': lfCmd("call win_execute(%d, 'setlocal foldcolumn=0')" % self._popup_winid) else: lfCmd("call win_execute(%d, 'setlocal foldcolumn=1')" % self._popup_winid) - # lfCmd("call win_execute(%d, 'silent! setlocal signcolumn=no')" % self._popup_winid) - lfCmd("call win_execute(%d, 'setlocal colorcolumn=')" % self._popup_winid) lfCmd("call win_execute(%d, 'setlocal wincolor=Lf_hl_popup_window')" % self._popup_winid) lfCmd("call win_execute(%d, 'silent! setlocal filetype=leaderf')" % self._popup_winid) @@ -691,21 +688,7 @@ def getWindow(number): buf_number = self._input_buffer_number lfCmd("noautocmd silent let winid = popup_create(%d, %s)" % (buf_number, str(input_win_options))) winid = int(lfEval("winid")) - lfCmd("call win_execute(%d, 'setlocal nobuflisted')" % winid) - lfCmd("call win_execute(%d, 'setlocal buftype=nofile')" % winid) - lfCmd("call win_execute(%d, 'setlocal bufhidden=hide')" % winid) - lfCmd("call win_execute(%d, 'setlocal undolevels=-1')" % winid) - lfCmd("call win_execute(%d, 'setlocal noswapfile')" % winid) - lfCmd("call win_execute(%d, 'setlocal nolist')" % winid) - lfCmd("call win_execute(%d, 'setlocal nonumber norelativenumber')" % winid) - lfCmd("call win_execute(%d, 'setlocal nospell')" % winid) - lfCmd("call win_execute(%d, 'setlocal nofoldenable')" % winid) - lfCmd("call win_execute(%d, 'setlocal foldmethod=manual')" % winid) - lfCmd("call win_execute(%d, 'setlocal shiftwidth=4')" % winid) - lfCmd("call win_execute(%d, 'setlocal nocursorline')" % winid) - lfCmd("call win_execute(%d, 'setlocal foldcolumn=0')" % winid) - # lfCmd("call win_execute(%d, 'silent! setlocal signcolumn=no')" % winid) - lfCmd("call win_execute(%d, 'setlocal colorcolumn=')" % winid) + self._vim_set_options(winid) lfCmd("call win_execute(%d, 'setlocal wincolor=Lf_hl_popup_inputText')" % winid) self._popup_instance.input_win = PopupWindow(winid, vim.buffers[buf_number], vim.current.tabpage, line) @@ -737,31 +720,21 @@ def getWindow(number): buf_number = self._stl_buffer_number lfCmd("noautocmd silent let winid = popup_create(%d, %s)" % (buf_number, str(statusline_win_options))) winid = int(lfEval("winid")) - lfCmd("call win_execute(%d, 'setlocal nobuflisted')" % winid) - lfCmd("call win_execute(%d, 'setlocal buftype=nofile')" % winid) - lfCmd("call win_execute(%d, 'setlocal bufhidden=hide')" % winid) - lfCmd("call win_execute(%d, 'setlocal undolevels=-1')" % winid) - lfCmd("call win_execute(%d, 'setlocal noswapfile')" % winid) - lfCmd("call win_execute(%d, 'setlocal nolist')" % winid) - lfCmd("call win_execute(%d, 'setlocal nonumber norelativenumber')" % winid) - lfCmd("call win_execute(%d, 'setlocal nospell')" % winid) - lfCmd("call win_execute(%d, 'setlocal nofoldenable')" % winid) - lfCmd("call win_execute(%d, 'setlocal foldmethod=manual')" % winid) - lfCmd("call win_execute(%d, 'setlocal shiftwidth=4')" % winid) - lfCmd("call win_execute(%d, 'setlocal nocursorline')" % winid) - lfCmd("call win_execute(%d, 'setlocal foldcolumn=0')" % winid) - # lfCmd("call win_execute(%d, 'silent! setlocal signcolumn=no')" % winid) - lfCmd("call win_execute(%d, 'setlocal colorcolumn=')" % winid) + self._vim_set_options(winid) lfCmd("call win_execute(%d, 'setlocal wincolor=Lf_hl_popup_blank')" % winid) - self._popup_instance.statusline_win = PopupWindow(winid, vim.buffers[buf_number], vim.current.tabpage, statusline_win_options["line"]) + self._popup_instance.statusline_win = PopupWindow(winid, + vim.buffers[buf_number], + vim.current.tabpage, + statusline_win_options["line"]) lfCmd("call leaderf#ResetPopupOptions(%d, 'callback', function('leaderf#PopupClosed', [%s, %d]))" % (self._popup_winid, str(self._popup_instance.getWinIdList()), id(self._manager))) if not self._is_popup_colorscheme_autocmd_set: self._is_popup_colorscheme_autocmd_set = True - lfCmd("call leaderf#colorscheme#popup#load('{}', '{}')".format(self._category, lfEval("get(g:, 'Lf_PopupColorscheme', 'default')"))) + lfCmd("call leaderf#colorscheme#popup#load('{}', '{}')".format(self._category, + lfEval("get(g:, 'Lf_PopupColorscheme', 'default')"))) lfCmd("augroup Lf_Popup_{}_Colorscheme".format(self._category)) lfCmd("autocmd ColorScheme * call leaderf#colorscheme#popup#load('{}', '{}')".format(self._category, lfEval("get(g:, 'Lf_PopupColorscheme', 'default')"))) @@ -851,11 +824,13 @@ def _createBufWindow(self, win_pos): if not self._is_colorscheme_autocmd_set: self._is_colorscheme_autocmd_set = True - lfCmd("call leaderf#colorscheme#popup#load('{}', '{}')".format(self._category, lfEval("get(g:, 'Lf_PopupColorscheme', 'default')"))) + lfCmd("call leaderf#colorscheme#popup#load('{}', '{}')".format(self._category, + lfEval("get(g:, 'Lf_PopupColorscheme', 'default')"))) lfCmd("call leaderf#colorscheme#highlight('{}', {})".format(self._category, self._buffer_object.number)) lfCmd("augroup Lf_{}_Colorscheme".format(self._category)) lfCmd("autocmd!") - lfCmd("autocmd ColorScheme * call leaderf#colorscheme#highlight('{}', {})".format(self._category, self._buffer_object.number)) + lfCmd("autocmd ColorScheme * call leaderf#colorscheme#highlight('{}', {})".format(self._category, + self._buffer_object.number)) lfCmd("autocmd ColorScheme * call leaderf#colorscheme#highlightMode('{0}', g:Lf_{0}_StlMode)".format(self._category)) lfCmd("autocmd ColorScheme doautocmd syntax") lfCmd("autocmd CursorMoved let g:Lf_{}_StlLineNumber = 1 + line('$') - line('.')".format(self._category)) @@ -913,7 +888,8 @@ def mimicCursor(self): if self._popup_winid > 0 and self._window_object.valid: self.hideMimicCursor() lfCmd("""call win_execute(%d, "let cursor_pos = getcurpos()[1:2]")""" % (self._popup_winid)) - lfCmd("""silent! call win_execute(%d, 'let g:Lf_mimicedCursorId = matchaddpos("Cursor", [cursor_pos])')""" % (self._popup_winid)) + lfCmd("""silent! call win_execute(%d, 'let g:Lf_mimicedCursorId = matchaddpos("Cursor", [cursor_pos])')""" + % (self._popup_winid)) def setPopupStl(self, current_mode): statusline_win = self._popup_instance.statusline_win @@ -949,30 +925,36 @@ def setPopupStl(self, current_mode): if self._win_pos == 'popup': lfCmd("""call popup_settext(%d, '%s')""" % (statusline_win.id, escQuote(text))) - lfCmd("""call win_execute(%d, "call prop_remove({'type': 'Lf_hl_popup_%s_mode'})")""" % (statusline_win.id, self._category)) + lfCmd("""call win_execute(%d, "call prop_remove({'type': 'Lf_hl_popup_%s_mode'})")""" + % (statusline_win.id, self._category)) lfCmd("""call win_execute(%d, "call prop_add(1, 1, {'length': %d, 'type': 'Lf_hl_popup_%s_mode'})")""" % (statusline_win.id, lfBytesLen(current_mode) + 2, self._category)) if sep != "": - lfCmd("""call win_execute(%d, "call prop_remove({'type': 'Lf_hl_popup_%s_sep0'})")""" % (statusline_win.id, self._category)) + lfCmd("""call win_execute(%d, "call prop_remove({'type': 'Lf_hl_popup_%s_sep0'})")""" + % (statusline_win.id, self._category)) lfCmd("""call win_execute(%d, "call prop_add(1, %d, {'length': %d, 'type': 'Lf_hl_popup_%s_sep0'})")""" % (statusline_win.id, sep0_start, sep_len, self._category)) - lfCmd("""call win_execute(%d, "call prop_remove({'type': 'Lf_hl_popup_category'})")""" % (statusline_win.id)) + lfCmd("""call win_execute(%d, "call prop_remove({'type': 'Lf_hl_popup_category'})")""" + % (statusline_win.id)) lfCmd("""call win_execute(%d, "call prop_add(1, %d, {'length': %d, 'type': 'Lf_hl_popup_category'})")""" % (statusline_win.id, category_start, category_len)) if sep != "": - lfCmd("""call win_execute(%d, "call prop_remove({'type': 'Lf_hl_popup_%s_sep1'})")""" % (statusline_win.id, self._category)) + lfCmd("""call win_execute(%d, "call prop_remove({'type': 'Lf_hl_popup_%s_sep1'})")""" + % (statusline_win.id, self._category)) lfCmd("""call win_execute(%d, "call prop_add(1, %d, {'length': %d, 'type': 'Lf_hl_popup_%s_sep1'})")""" - % (statusline_win.id, sep1_start, sep_len, self._category)) + % (statusline_win.id, sep1_start, sep_len, self._category)) - lfCmd("""call win_execute(%d, "call prop_remove({'type': 'Lf_hl_popup_%s_matchMode'})")""" % (statusline_win.id, self._category)) + lfCmd("""call win_execute(%d, "call prop_remove({'type': 'Lf_hl_popup_%s_matchMode'})")""" + % (statusline_win.id, self._category)) lfCmd("""call win_execute(%d, "call prop_add(1, %d, {'length': %d, 'type': 'Lf_hl_popup_%s_matchMode'})")""" % (statusline_win.id, match_mode_start, match_mode_len, self._category)) if sep != "": - lfCmd("""call win_execute(%d, "call prop_remove({'type': 'Lf_hl_popup_%s_sep2'})")""" % (statusline_win.id, self._category)) + lfCmd("""call win_execute(%d, "call prop_remove({'type': 'Lf_hl_popup_%s_sep2'})")""" + % (statusline_win.id, self._category)) lfCmd("""call win_execute(%d, "call prop_add(1, %d, {'length': %d, 'type': 'Lf_hl_popup_%s_sep2'})")""" % (statusline_win.id, sep2_start, sep_len, self._category)) @@ -981,7 +963,8 @@ def setPopupStl(self, current_mode): % (statusline_win.id, cwd_start, cwd_len)) if sep != "": - lfCmd("""call win_execute(%d, "call prop_remove({'type': 'Lf_hl_popup_%s_sep3'})")""" % (statusline_win.id, self._category)) + lfCmd("""call win_execute(%d, "call prop_remove({'type': 'Lf_hl_popup_%s_sep3'})")""" + % (statusline_win.id, self._category)) lfCmd("""call win_execute(%d, "call prop_add(1, %d, {'length': %d, 'type': 'Lf_hl_popup_%s_sep3'})")""" % (statusline_win.id, sep3_start, sep_len, self._category)) elif self._win_pos == 'floatwin': @@ -1206,7 +1189,8 @@ def exitBuffer(self): orig_win = vim.current.window for w in vim.windows: vim.current.window = w - if lfEval("exists('w:lf_win_view')") != '0' and lfEval("has_key(w:lf_win_view, '%s')" % self._category) != '0': + if (lfEval("exists('w:lf_win_view')") != '0' + and lfEval("has_key(w:lf_win_view, '%s')" % self._category) != '0'): lfCmd("call winrestview(w:lf_win_view['%s'])" % self._category) finally: vim.current.window = orig_win @@ -1223,7 +1207,8 @@ def _actualLength(self, buffer): try: num += (int(lfEval("strdisplaywidth('%s')" % escQuote(i))) + columns - 1)// columns except: - num += (int(lfEval("strdisplaywidth('%s')" % escQuote(i).replace('\x00', '\x01'))) + columns - 1)// columns + num += (int(lfEval("strdisplaywidth('%s')" + % escQuote(i).replace('\x00', '\x01'))) + columns - 1)// columns return num def setBuffer(self, content, need_copy=False): @@ -1261,7 +1246,8 @@ def setBuffer(self, content, need_copy=False): buffer_len = len(self._buffer_object) if buffer_len < self._initial_win_height: if "--nowrap" not in self._arguments: - self._window_object.height = min(self._initial_win_height, self._actualLength(self._buffer_object)) + self._window_object.height = min(self._initial_win_height, + self._actualLength(self._buffer_object)) else: self._window_object.height = buffer_len elif self._window_object.height < self._initial_win_height: @@ -1284,7 +1270,8 @@ def setBuffer(self, content, need_copy=False): buffer_len = len(self._buffer_object) if buffer_len < self._initial_win_height: if "--nowrap" not in self._arguments: - self._window_object.height = min(self._initial_win_height, self._actualLength(self._buffer_object)) + self._window_object.height = min(self._initial_win_height, + self._actualLength(self._buffer_object)) else: self._window_object.height = buffer_len elif self._window_object.height < self._initial_win_height: @@ -1314,7 +1301,8 @@ def refreshPopupStatusline(self): lfCmd("call leaderf#ResetPopupOptions(%d, 'minheight', %d)" % (self._popup_winid, min(self._popup_maxheight, self._actualLength(self._buffer_object[:self._popup_maxheight])))) else: - lfCmd("call leaderf#ResetPopupOptions(%d, 'minheight', %d)" % (self._popup_winid, min(self._popup_maxheight, buffer_len))) + lfCmd("call leaderf#ResetPopupOptions(%d, 'minheight', %d)" % (self._popup_winid, + min(self._popup_maxheight, buffer_len))) if statusline_win: expected_line = self._window_object.initialLine + self._window_object.height @@ -1358,7 +1346,8 @@ def appendBuffer(self, content): buffer_len = len(self._buffer_object) if buffer_len < self._initial_win_height: if "--nowrap" not in self._arguments: - self._window_object.height = min(self._initial_win_height, self._actualLength(self._buffer_object)) + self._window_object.height = min(self._initial_win_height, + self._actualLength(self._buffer_object)) else: self._window_object.height = buffer_len elif self._window_object.height < self._initial_win_height: @@ -1384,7 +1373,8 @@ def appendBuffer(self, content): buffer_len = len(self._buffer_object) if buffer_len < self._initial_win_height: if "--nowrap" not in self._arguments: - self._window_object.height = min(self._initial_win_height, self._actualLength(self._buffer_object)) + self._window_object.height = min(self._initial_win_height, + self._actualLength(self._buffer_object)) else: self._window_object.height = buffer_len elif self._window_object.height < self._initial_win_height: diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 4fd8680c..278370b9 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -454,6 +454,7 @@ def _setWinOptions(self, winid): lfCmd("call nvim_win_set_option(%d, 'number', v:true)" % winid) lfCmd("call nvim_win_set_option(%d, 'relativenumber', v:false)" % winid) lfCmd("call nvim_win_set_option(%d, 'cursorline', v:true)" % winid) + lfCmd("call nvim_win_set_option(%d, 'foldenable', v:false)" % winid) lfCmd("call nvim_win_set_option(%d, 'foldmethod', 'manual')" % winid) lfCmd("call nvim_win_set_option(%d, 'foldcolumn', '0')" % winid) lfCmd("call nvim_win_set_option(%d, 'signcolumn', 'no')" % winid) @@ -482,6 +483,8 @@ def _createPreviewWindow(self, config, source, line_nr, jump_cmd): self._preview_winid = int(lfEval("nvim_open_win(g:Lf_preview_scratch_buffer, 0, %s)" % str(config))) + self._setWinOptions(self._preview_winid) + if jump_cmd: cur_winid = lfEval("win_getid()") lfCmd("noautocmd call win_gotoid(%d)" % self._preview_winid) @@ -490,13 +493,10 @@ def _createPreviewWindow(self, config, source, line_nr, jump_cmd): if buffer_len >= line_nr > 0: lfCmd("""call nvim_win_set_cursor(%d, [%d, 1])""" % (self._preview_winid, line_nr)) - self._setWinOptions(self._preview_winid) - cur_winid = lfEval("win_getid()") lfCmd("noautocmd call win_gotoid(%d)" % self._preview_winid) if not isinstance(source, int): lfCmd("silent! doautocmd filetypedetect BufNewFile %s" % source) - lfCmd("silent! %foldopen!") lfCmd("norm! zz") lfCmd("noautocmd call win_gotoid(%s)" % cur_winid) self._preview_filetype = lfEval("getbufvar(winbufnr(%d), '&ft')" % self._preview_winid) @@ -513,8 +513,18 @@ def _createPreviewWindow(self, config, source, line_nr, jump_cmd): return lfCmd("noautocmd silent! let winid = popup_create(content, %s)" % json.dumps(config)) + lfCmd("call win_execute(winid, 'setlocal wincolor=Lf_hl_popup_window')") lfCmd("call win_execute(winid, 'setlocal modeline')") + lfCmd("call win_execute(winid, 'setlocal cursorline number norelativenumber colorcolumn=')") lfCmd("call win_execute(winid, 'setlocal nofoldenable')") + lfCmd("call win_execute(winid, 'setlocal foldmethod=manual')") + if lfEval("exists('+cursorlineopt')") == '1': + lfCmd("call win_execute(winid, 'setlocal cursorlineopt=both')") + if lfEval("get(g:, 'Lf_PopupShowFoldcolumn', 1)") == '0' or lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1': + lfCmd("call win_execute(winid, 'setlocal foldcolumn=0')") + else: + lfCmd("call win_execute(winid, 'setlocal foldcolumn=1')") + lfCmd("call win_execute(winid, 'silent! doautocmd filetypedetect BufNewFile %s')" % escQuote(filename)) self._preview_winid = int(lfEval("winid")) @@ -526,15 +536,6 @@ def _createPreviewWindow(self, config, source, line_nr, jump_cmd): elif line_nr > 0: lfCmd("""call win_execute(%d, "call cursor(%d, 1)")""" % (self._preview_winid, line_nr)) lfCmd("call win_execute(%d, 'norm! zz')" % self._preview_winid) - lfCmd("call win_execute(%d, 'setlocal cursorline number norelativenumber colorcolumn= ')" % self._preview_winid) - lfCmd("call win_execute(%d, 'setlocal foldmethod=manual')" % self._preview_winid) - if lfEval("exists('+cursorlineopt')") == '1': - lfCmd("call win_execute(%d, 'setlocal cursorlineopt=both')" % self._preview_winid) - lfCmd("call win_execute(%d, 'setlocal wincolor=Lf_hl_popup_window')" % self._preview_winid) - if lfEval("get(g:, 'Lf_PopupShowFoldcolumn', 1)") == '0' or lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1': - lfCmd("call win_execute(%d, 'setlocal foldcolumn=0')" % self._preview_winid) - else: - lfCmd("call win_execute(%d, 'setlocal foldcolumn=1')" % self._preview_winid) @ignoreEvent('BufWinEnter,BufEnter') def _createPopupModePreview(self, title, source, line_nr, jump_cmd): From cd91b8190f017852954ae0ef906baa0670d4c1f3 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Sat, 22 Jul 2023 23:10:28 +0800 Subject: [PATCH 112/365] fix an issue that `--cword` is broken --- autoload/leaderf/python/leaderf/anyExpl.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autoload/leaderf/python/leaderf/anyExpl.py b/autoload/leaderf/python/leaderf/anyExpl.py index 2a43511e..9f4b2aa8 100644 --- a/autoload/leaderf/python/leaderf/anyExpl.py +++ b/autoload/leaderf/python/leaderf/anyExpl.py @@ -739,7 +739,7 @@ def _default_action(self, category, positional_args, arguments, *args, **kwargs) arguments["win_pos"] = win_pos[2:] if "--cword" in arguments: - kwargs["pattern"] = lfEval("expand('')") + arguments["--input"]= [lfEval("expand('')")] kwargs["arguments"] = arguments kwargs["positional_args"] = positional_args From b7482f15e44a8cb351add8f4cd8ea1d7e0937f57 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Mon, 24 Jul 2023 16:33:14 +0800 Subject: [PATCH 113/365] update the default value of `g:Lf_CacheDirectory` to support XDG Base Directory --- autoload/leaderf/python/leaderf/cli.py | 6 +++--- autoload/leaderf/python/leaderf/fileExpl.py | 2 +- autoload/leaderf/python/leaderf/gtagsExpl.py | 2 +- autoload/leaderf/python/leaderf/mru.py | 2 +- autoload/lfMru.vim | 6 +++--- doc/leaderf.txt | 6 ++++-- plugin/leaderf.vim | 14 +++++++++++++- 7 files changed, 26 insertions(+), 12 deletions(-) diff --git a/autoload/leaderf/python/leaderf/cli.py b/autoload/leaderf/python/leaderf/cli.py index d4526b9f..5967e1d0 100644 --- a/autoload/leaderf/python/leaderf/cli.py +++ b/autoload/leaderf/python/leaderf/cli.py @@ -530,7 +530,7 @@ def writeHistory(self, category): else: pattern = self._pattern - history_dir = os.path.join(lfEval("g:Lf_CacheDirectory"), '.LfCache', 'history', category) + history_dir = os.path.join(lfEval("g:Lf_CacheDirectory"), 'LeaderF', 'history', category) if self._is_fuzzy: history_file = os.path.join(history_dir, 'fuzzy.txt') else: @@ -560,7 +560,7 @@ def writeHistory(self, category): f.writelines(lines) def previousHistory(self, category): - history_dir = os.path.join(lfEval("g:Lf_CacheDirectory"), '.LfCache', 'history', category) + history_dir = os.path.join(lfEval("g:Lf_CacheDirectory"), 'LeaderF', 'history', category) if self._is_fuzzy: history_file = os.path.join(history_dir, 'fuzzy.txt') else: @@ -583,7 +583,7 @@ def previousHistory(self, category): return True def nextHistory(self, category): - history_dir = os.path.join(lfEval("g:Lf_CacheDirectory"), '.LfCache', 'history', category) + history_dir = os.path.join(lfEval("g:Lf_CacheDirectory"), 'LeaderF', 'history', category) if self._is_fuzzy: history_file = os.path.join(history_dir, 'fuzzy.txt') else: diff --git a/autoload/leaderf/python/leaderf/fileExpl.py b/autoload/leaderf/python/leaderf/fileExpl.py index 2e582d74..013f692c 100644 --- a/autoload/leaderf/python/leaderf/fileExpl.py +++ b/autoload/leaderf/python/leaderf/fileExpl.py @@ -58,7 +58,7 @@ def __init__(self): self._cur_dir = '' self._content = [] self._cache_dir = os.path.join(lfEval("g:Lf_CacheDirectory"), - '.LfCache', + 'LeaderF', 'python' + lfEval("g:Lf_PythonVersion"), 'file') self._cache_index = os.path.join(self._cache_dir, 'cacheIndex') diff --git a/autoload/leaderf/python/leaderf/gtagsExpl.py b/autoload/leaderf/python/leaderf/gtagsExpl.py index 43b94a19..50e4eb6b 100644 --- a/autoload/leaderf/python/leaderf/gtagsExpl.py +++ b/autoload/leaderf/python/leaderf/gtagsExpl.py @@ -30,7 +30,7 @@ def __init__(self): self._cd_option = '' self._root_markers = lfEval("g:Lf_RootMarkers") self._db_location = os.path.join(lfEval("g:Lf_CacheDirectory"), - '.LfCache', + 'LeaderF', 'gtags') self._store_in_project = lfEval("get(g:, 'Lf_GtagsStoreInProject', 0)") == '1' self._store_in_rootmarker = lfEval("get(g:, 'Lf_GtagsStoreInRootMarker', 0)") == '1' diff --git a/autoload/leaderf/python/leaderf/mru.py b/autoload/leaderf/python/leaderf/mru.py index 5256e43c..542a1317 100644 --- a/autoload/leaderf/python/leaderf/mru.py +++ b/autoload/leaderf/python/leaderf/mru.py @@ -15,7 +15,7 @@ class Mru(object): def __init__(self): self._cache_dir = os.path.join(lfEval("g:Lf_CacheDirectory"), - '.LfCache', + 'LeaderF', 'python' + lfEval("g:Lf_PythonVersion"), 'mru') self._cache_file = os.path.join(self._cache_dir, 'mruCache') diff --git a/autoload/lfMru.vim b/autoload/lfMru.vim index 9728462a..5c817194 100644 --- a/autoload/lfMru.vim +++ b/autoload/lfMru.vim @@ -13,11 +13,11 @@ if !isdirectory(g:Lf_CacheDirectory) call mkdir(g:Lf_CacheDirectory, "p") endif -if !isdirectory(g:Lf_CacheDirectory . '/.LfCache') - call mkdir(g:Lf_CacheDirectory . '/.LfCache', "p") +if !isdirectory(g:Lf_CacheDirectory . '/LeaderF') + call mkdir(g:Lf_CacheDirectory . '/LeaderF', "p") endif -let g:Lf_MruCacheFileName = g:Lf_CacheDirectory . '/.LfCache/tempMru' +let g:Lf_MruCacheFileName = g:Lf_CacheDirectory . '/LeaderF/tempMru' if !filereadable(g:Lf_MruCacheFileName) call writefile([], g:Lf_MruCacheFileName) diff --git a/doc/leaderf.txt b/doc/leaderf.txt index ff89a69c..f2d67aed 100644 --- a/doc/leaderf.txt +++ b/doc/leaderf.txt @@ -108,7 +108,9 @@ g:Lf_CacheDirectory *g:Lf_CacheDirectory* e.g. > let g:Lf_CacheDirectory = '/root' < - Default value is $HOME. + On Windows, default value is '%APPDATA%'. + On Linux, default value is '$XDG_CACHE_HOME' if $XDG_CACHE_HOME is defined, + otherwise, default value is '$HOME/.cache'. g:Lf_NeedCacheTime *g:Lf_NeedCacheTime* This option set a threshold, if the time of indexing files is greater than @@ -650,7 +652,7 @@ g:Lf_GtagsGutentags *g:Lf_GtagsGutentags* if you use https://github.com/ludovicchabant/vim-gutentags to generate gtags; Firstly, you should let g:Lf_GtagsAutoGenerate = 0 and let g:Lf_GtagsGutentags = 1. Then, you should config gutentags like this: g:Lf_CacheDirectory = expand('~') - and g:gutentags_cache_dir = expand(g:Lf_CacheDirectory.'/.LfCache/gtags') + and g:gutentags_cache_dir = expand(g:Lf_CacheDirectory.'/LeaderF/gtags') Default value is 0 g:Lf_GtagsAutoUpdate *g:Lf_GtagsAutoUpdate* diff --git a/plugin/leaderf.vim b/plugin/leaderf.vim index d267ed82..15b35443 100644 --- a/plugin/leaderf.vim +++ b/plugin/leaderf.vim @@ -32,11 +32,23 @@ endfunction call s:InitVar('g:Lf_ShortcutF', 'f') call s:InitVar('g:Lf_ShortcutB', 'b') call s:InitVar('g:Lf_WindowPosition', 'bottom') -call s:InitVar('g:Lf_CacheDirectory', $HOME) call s:InitVar('g:Lf_MruBufnrs', []) call s:InitVar('g:Lf_PythonExtensions', {}) call s:InitVar('g:Lf_PreviewWindowID', {}) +if has('win32') || has('win64') + let s:cache_dir = $APPDATA + if s:cache_dir == '' + let s:cache_dir = $HOME + endif +else + let s:cache_dir = $XDG_CACHE_HOME + if s:cache_dir == '' + let s:cache_dir = $HOME . '/.cache' + endif +endif +call s:InitVar('g:Lf_CacheDirectory', s:cache_dir) + function! g:LfNoErrMsgMatch(expr, pat) try return match(a:expr, a:pat) From 4c5290e277d2a50d83222dacba35aec42c096875 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Mon, 24 Jul 2023 17:08:25 +0800 Subject: [PATCH 114/365] highlight wrong when using `Leaderf rg` to replace --- autoload/leaderf/python/leaderf/instance.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/autoload/leaderf/python/leaderf/instance.py b/autoload/leaderf/python/leaderf/instance.py index 7a1fd94b..f87dbeff 100644 --- a/autoload/leaderf/python/leaderf/instance.py +++ b/autoload/leaderf/python/leaderf/instance.py @@ -296,7 +296,7 @@ def _initStlVar(self): stl += "%#Lf_hl_stlCwd# %<%{{g:Lf_{0}_StlCwd}} " stl += "%#Lf_hl_{0}_stlSeparator3#%{{g:Lf_StlSeparator.left}}" stl += "%#Lf_hl_{0}_stlBlank#%=" - stl += "%#Lf_hl_stlSpin#%{{g:Lf_{0}_StlRunning}} " + stl += "%#Lf_hl_stlSpin#%{{g:Lf_{0}_StlRunning}}" stl += "%#Lf_hl_{0}_stlSeparator4#%{{g:Lf_StlSeparator.right}}" if self._reverse_order: stl += "%#Lf_hl_stlLineInfo# %{{g:Lf_{0}_StlLineNumber}}/%{{g:Lf_{0}_StlResultsCount}} " @@ -1047,7 +1047,7 @@ def setStlRunning(self, running): return if running: - spin = "{}".format(self._cli._spin_symbols[self._running_status]) + spin = "{} ".format(self._cli._spin_symbols[self._running_status]) self._running_status = (self._running_status + 1) % len(self._cli._spin_symbols) lfCmd("let g:Lf_{}_StlRunning = '{}'".format(self._category, spin)) else: From 8d51a3512fa318393df2bc092e458fd7d6c8e75b Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Tue, 25 Jul 2023 00:35:29 -0500 Subject: [PATCH 115/365] fix issue #1020 --- README.md | 2 +- autoload/leaderf/python/leaderf/anyExpl.py | 2 +- autoload/leaderf/python/leaderf/instance.py | 31 +++++++++++++-------- autoload/leaderf/python/leaderf/manager.py | 12 ++++---- 4 files changed, 28 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 48eac37b..b0cdc1ac 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ Requirements - vim7.3 or higher. Only support 7.4.1126+ after [v1.01](https://github.com/Yggdroot/LeaderF/releases/tag/v1.01). - Python2.7+ or Python3.1+. - - To use the popup mode, neovim 0.4.2+ or vim 8.1.1615+ are required. + - To use the popup mode, neovim 0.5.0+ or vim 8.1.1615+ are required. Installation ------------ diff --git a/autoload/leaderf/python/leaderf/anyExpl.py b/autoload/leaderf/python/leaderf/anyExpl.py index 9f4b2aa8..800f173f 100644 --- a/autoload/leaderf/python/leaderf/anyExpl.py +++ b/autoload/leaderf/python/leaderf/anyExpl.py @@ -744,7 +744,7 @@ def _default_action(self, category, positional_args, arguments, *args, **kwargs) kwargs["arguments"] = arguments kwargs["positional_args"] = positional_args - if lfEval("has('patch-8.1.1615') || has('nvim-0.4.2')") == '0': + if lfEval("has('patch-8.1.1615') || has('nvim-0.5.0')") == '0': win_pos = "--bottom" manager.startExplorer(win_pos[2:], *args, **kwargs) diff --git a/autoload/leaderf/python/leaderf/instance.py b/autoload/leaderf/python/leaderf/instance.py index f87dbeff..ade9ae9e 100644 --- a/autoload/leaderf/python/leaderf/instance.py +++ b/autoload/leaderf/python/leaderf/instance.py @@ -426,6 +426,7 @@ def _createPopupWindow(self): maxwidth = min(width, int(lfEval("&columns"))) maxwidth = max(20, maxwidth) + show_borders = lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1' height = lfEval("get(g:, 'Lf_PopupHeight', 0)") height = self._arguments.get("--popup-height", [height])[0] height = height.strip('"').strip("'") @@ -442,7 +443,7 @@ def _createPopupWindow(self): else: height = int(height) maxheight = min(height, int(lfEval("&lines")) - 2) - if lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1': + if show_borders: maxheight -= 2 line, col = [int(i) for i in lfEval("get(g:, 'Lf_PopupPosition', [0, 0])")] @@ -489,8 +490,10 @@ def _createPopupWindow(self): "anchor" : "NW", "height" : floatwin_height, "width" : maxwidth, + "zindex" : 20480, "row" : line + 1, - "col" : col + "col" : col, + "noautocmd": 1 } popup_borders = lfEval("g:Lf_PopupBorders") @@ -504,7 +507,7 @@ def _createPopupWindow(self): [popup_borders[7], "Lf_hl_popupBorder"], [popup_borders[3], "Lf_hl_popupBorder"] ] - if lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1': + if show_borders: if lfEval("get(g:, 'Lf_PopupShowStatusline', 1)") == '1': config["border"] = ['','','',borderchars[3],'','','',borderchars[7]] else: @@ -516,7 +519,7 @@ def _createPopupWindow(self): self._popup_winid = int(lfEval("winid")) self._window_id = self._popup_winid self._setAttributes() - if lfEval("get(g:, 'Lf_PopupShowFoldcolumn', 1)") == '0' or lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1': + if lfEval("get(g:, 'Lf_PopupShowFoldcolumn', 1)") == '0' or show_borders: try: lfCmd("call nvim_win_set_option(%d, 'foldcolumn', 0)" % self._popup_winid) except vim.error: @@ -540,11 +543,13 @@ def _createPopupWindow(self): "anchor" : "NW", "height" : 1, "width" : maxwidth, + "zindex" : 20480, "row" : line, - "col" : col + "col" : col, + "noautocmd": 1 } - if lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1': + if show_borders: input_win_config["border"] = borderchars[:4] + ['','','', borderchars[7]] input_win_config["width"] -= 2 @@ -574,11 +579,13 @@ def getWindow(number): "anchor" : "NW", "height" : 1, "width" : maxwidth, + "zindex" : 20480, "row" : config["row"] + floatwin_height, - "col" : col + "col" : col, + "noautocmd": 1 } - if lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1': + if show_borders: stl_win_config["border"] = ['','',''] + borderchars[3:] stl_win_config["width"] -= 2 @@ -633,7 +640,7 @@ def getWindow(number): } borderchars = lfEval("g:Lf_PopupBorders") - if lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1': + if show_borders: if lfEval("get(g:, 'Lf_PopupShowStatusline', 1)") == '1': options["border"] = [0, 1, 0, 1] else: @@ -650,7 +657,7 @@ def getWindow(number): self._vim_set_options(self._popup_winid) lfCmd("call win_execute(%d, 'setlocal number')" % self._popup_winid) lfCmd("call win_execute(%d, 'setlocal cursorline')" % self._popup_winid) - if lfEval("get(g:, 'Lf_PopupShowFoldcolumn', 1)") == '0' or lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1': + if lfEval("get(g:, 'Lf_PopupShowFoldcolumn', 1)") == '0' or show_borders: lfCmd("call win_execute(%d, 'setlocal foldcolumn=0')" % self._popup_winid) else: lfCmd("call win_execute(%d, 'setlocal foldcolumn=1')" % self._popup_winid) @@ -675,7 +682,7 @@ def getWindow(number): "borderhighlight": ["Lf_hl_previewTitle"], } - if lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1': + if show_borders: input_win_options["border"] = [1, 1, 0, 1] input_win_options["borderchars"] = borderchars input_win_options["maxwidth"] -= 2 @@ -707,7 +714,7 @@ def getWindow(number): "borderhighlight": ["Lf_hl_previewTitle"], } - if lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1': + if show_borders: statusline_win_options["border"] = [0, 1, 1, 1] statusline_win_options["borderchars"] = borderchars statusline_win_options["maxwidth"] -= 2 diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 278370b9..6a7ef867 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -129,7 +129,7 @@ def __init__(self): self._arguments = {} self._getExplClass() self._preview_filetype = None - if lfEval("has('patch-8.1.1615') || has('nvim-0.4.2')") == '0': + if lfEval("has('patch-8.1.1615') || has('nvim-0.5.0')") == '0': lfCmd("let g:Lf_PreviewInPopup = 0") if lfEval("get(g:, 'Lf_PopupPreviewPosition', 'right')").lower() == 'bottom': lfCmd("let g:Lf_PopupAutoAdjustHeight = 0") @@ -659,8 +659,9 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): if show_borders: config["border"] = borderchars - config["title"] = " Preview " - config["title_pos"] = "center" + if lfEval("has('nvim-0.9.0')") == '1': + config["title"] = " Preview " + config["title_pos"] = "center" self._createPreviewWindow(config, source, line_nr, jump_cmd) lfCmd("let g:Lf_PreviewWindowID[%d] = %d" % (id(self), self._preview_winid)) @@ -917,8 +918,9 @@ def _createPopupPreview(self, title, source, line_nr, jump_cmd=''): config["border"] = borderchars config["height"] -= 2 config["width"] -= 2 - config["title"] = " Preview " - config["title_pos"] = "center" + if lfEval("has('nvim-0.9.0')") == '1': + config["title"] = " Preview " + config["title_pos"] = "center" self._createPreviewWindow(config, source, line_nr, jump_cmd) else: From 84a9e0160df51dce9218efe5a1e3e6c6af28874e Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Fri, 4 Aug 2023 17:53:57 +0800 Subject: [PATCH 116/365] add support for cyclic scroll --- autoload/leaderf.vim | 4 ++-- autoload/leaderf/python/leaderf/manager.py | 22 +++++++++++++++++++--- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/autoload/leaderf.vim b/autoload/leaderf.vim index 0910343b..2e9cda8a 100644 --- a/autoload/leaderf.vim +++ b/autoload/leaderf.vim @@ -492,13 +492,13 @@ function! leaderf#NormalModeFilter(id, winid, key) abort endif if key ==# "j" || key ==? "" - call win_execute(a:winid, "norm! j") + exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value.move('j')", a:id) exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value._cli._buildPopupPrompt()", a:id) "redraw exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value._getInstance().refreshPopupStatusline()", a:id) exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value._previewResult(False)", a:id) elseif key ==# "k" || key ==? "" - call win_execute(a:winid, "norm! k") + exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value.move('k')", a:id) exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value._cli._buildPopupPrompt()", a:id) "redraw exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value._getInstance().refreshPopupStatusline()", a:id) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 6a7ef867..d6d7d181 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -1133,14 +1133,30 @@ def _toDownInPopup(self): else: lfCmd("call win_execute(%d, 'norm! %dj')" % (self._preview_winid, scroll_step_size)) + def move(self, direction): + """ + direction is in {'j', 'k'} + """ + if direction == 'j' and self._getInstance().window.cursor[0] == len(self._getInstance().buffer): + lfCmd("noautocmd call win_execute(%d, 'norm! gg')" % (self._getInstance().getPopupWinId())) + elif direction == 'k' and self._getInstance().window.cursor[0] == 1: + lfCmd("noautocmd call win_execute(%d, 'norm! G')" % (self._getInstance().getPopupWinId())) + else: + lfCmd("noautocmd call win_execute(%d, 'norm! %s')" % (self._getInstance().getPopupWinId(), direction)) + def moveAndPreview(self, direction): """ direction is in {'j', 'k', 'Down', 'Up', 'PageDown', 'PageUp'} """ - if len(direction) > 1: - lfCmd('noautocmd exec "norm! \<{}>"'.format(direction)) + if direction in ("j", "Down") and self._getInstance().window.cursor[0] == len(self._getInstance().buffer): + lfCmd('noautocmd exec "norm! gg"') + elif direction in ("k", "Up") and self._getInstance().window.cursor[0] == 1: + lfCmd('noautocmd exec "norm! G"') else: - lfCmd('noautocmd exec "norm! {}"'.format(direction)) + if len(direction) > 1: + lfCmd('noautocmd exec "norm! \<{}>"'.format(direction)) + else: + lfCmd('noautocmd exec "norm! {}"'.format(direction)) if self._getInstance().getWinPos() == 'floatwin': self._cli._buildPopupPrompt() From 6a4e01d85337c781cf6fe37e19f87e41869adfad Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Fri, 4 Aug 2023 20:18:55 +0800 Subject: [PATCH 117/365] add support for cyclic scroll --- autoload/leaderf/python/leaderf/manager.py | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index d6d7d181..c72502f1 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -1165,7 +1165,10 @@ def moveAndPreview(self, direction): def _toUp(self): if self._getInstance().getWinPos() == 'popup': - lfCmd("noautocmd call win_execute(%d, 'norm! k')" % (self._getInstance().getPopupWinId())) + if self._getInstance().window.cursor[0] == 1: + lfCmd("noautocmd call win_execute(%d, 'norm! G')" % (self._getInstance().getPopupWinId())) + else: + lfCmd("noautocmd call win_execute(%d, 'norm! k')" % (self._getInstance().getPopupWinId())) self._getInstance().refreshPopupStatusline() return @@ -1178,7 +1181,10 @@ def _toUp(self): and len(self._highlight_pos) < int(lfEval("g:Lf_NumberOfHighlight")): self._highlight_method() - lfCmd("noautocmd norm! k") + if self._getInstance().window.cursor[0] == 1: + lfCmd("noautocmd norm! G") + else: + lfCmd("noautocmd norm! k") if adjust: lfCmd("norm! zt") @@ -1189,7 +1195,10 @@ def _toUp(self): def _toDown(self): if self._getInstance().getWinPos() == 'popup': - lfCmd("noautocmd call win_execute(%d, 'norm! j')" % (self._getInstance().getPopupWinId())) + if self._getInstance().window.cursor[0] == len(self._getInstance().buffer): + lfCmd("noautocmd call win_execute(%d, 'norm! gg')" % (self._getInstance().getPopupWinId())) + else: + lfCmd("noautocmd call win_execute(%d, 'norm! j')" % (self._getInstance().getPopupWinId())) self._getInstance().refreshPopupStatusline() return @@ -1197,7 +1206,10 @@ def _toDown(self): and self._getInstance().getCurrentPos()[0] == self._initial_count: self._setResultContent() - lfCmd("noautocmd norm! j") + if self._getInstance().window.cursor[0] == len(self._getInstance().buffer): + lfCmd("noautocmd norm! gg") + else: + lfCmd("noautocmd norm! j") self._getInstance().setLineNumber() lfCmd("setlocal cursorline!") # these two help to redraw the statusline, lfCmd("setlocal cursorline!") # also fix a weird bug of vim From 3ded37f92807d8c6ad831d5af2c4ff22bfd32fc8 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Mon, 21 Aug 2023 17:17:54 +0800 Subject: [PATCH 118/365] fix issue #1023 add g:Lf_NormalCommandMap --- autoload/leaderf.vim | 90 ++++++++++------------ autoload/leaderf/Any.vim | 8 +- autoload/leaderf/BufTag.vim | 8 +- autoload/leaderf/Buffer.vim | 11 ++- autoload/leaderf/Command.vim | 2 +- autoload/leaderf/File.vim | 11 ++- autoload/leaderf/Function.vim | 8 +- autoload/leaderf/Gtags.vim | 11 ++- autoload/leaderf/History.vim | 2 +- autoload/leaderf/Jumps.vim | 8 +- autoload/leaderf/Line.vim | 11 ++- autoload/leaderf/Mru.vim | 11 ++- autoload/leaderf/QfLocList.vim | 8 +- autoload/leaderf/Rg.vim | 11 ++- autoload/leaderf/Tag.vim | 8 +- autoload/leaderf/Window.vim | 2 +- autoload/leaderf/python/leaderf/manager.py | 18 +++++ doc/leaderf.txt | 37 +++++++++ 18 files changed, 148 insertions(+), 117 deletions(-) diff --git a/autoload/leaderf.vim b/autoload/leaderf.vim index 2e9cda8a..c13cc6e2 100644 --- a/autoload/leaderf.vim +++ b/autoload/leaderf.vim @@ -381,11 +381,7 @@ endfunction function! leaderf#popupModePreviewFilter(winid, key) abort let key = get(g:Lf_KeyMap, a:key, a:key) - if key ==? "" - noautocmd call popup_close(a:winid) - redraw - return 0 - elseif key ==? "" + if key ==? "" if exists("*getmousepos") let pos = getmousepos() if pos.winid == a:winid @@ -434,58 +430,54 @@ function! leaderf#popupModePreviewFilter(winid, key) abort return 0 endfunction -function! leaderf#normalModePreviewFilter(id, lf_winid, winid, key) abort - let key = get(g:Lf_KeyMap, a:key, a:key) - if key ==? "" - noautocmd call popup_close(a:winid) - redraw - return 1 - elseif key ==? "" && has('patch-8.1.2266') - let pos = getmousepos() - if pos.winid == a:winid - call win_execute(pos.winid, "call cursor([pos.line, pos.column])") - redraw - return 1 - elseif pos.winid == a:lf_winid - call win_execute(pos.winid, "call cursor([pos.line, pos.column])") - exec g:Lf_py "import ctypes" - exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value._previewResult(False)", a:id) - return 0 +function! leaderf#PopupFilter(winid, key) abort + return 0 +endfunction + +function! leaderf#RemapKey(id, key) abort + exec g:Lf_py "import ctypes" + + let normal_map = get(g:, 'Lf_NormalCommandMap', {}) + let key_map = get(normal_map, '*', {}) + let category = g:Lf_PyEval(printf("ctypes.cast(%d, ctypes.py_object).value._getExplorer().getStlCategory()", a:id)) + for [old, new] in items(get(normal_map, category, {})) + let has_key = 0 + for [k, v] in items(key_map) + if old =~ '\m<.\{-}>' && old ==? k + let key_map[k] = new + let has_key = 1 + break + endif + endfor + if has_key == 0 + let key_map[old] = new endif - elseif key ==? "" && exists("*getmousepos") - let pos = getmousepos() - if pos.winid == a:winid - call win_execute(a:winid, "norm! 3\") - "redraw - return 1 + endfor + + let key = a:key + let is_old = 0 + let is_new = 0 + for [old, new] in items(key_map) + if key =~ '\m<.\{-}>' && key ==? new || key ==# new + let key = old + let is_new = 1 endif - elseif key ==? "" && exists("*getmousepos") - let pos = getmousepos() - if pos.winid == a:winid - call win_execute(a:winid, "norm! 3\") - "redraw - return 1 + if key =~ '\m<.\{-}>' && key ==? old || key ==# old + let is_old = 1 endif - elseif key ==? "" - call win_execute(a:winid, "norm! k") - redraw - return 1 - elseif key ==? "" - call win_execute(a:winid, "norm! j") - redraw - return 1 + endfor + + if is_old && is_new == 0 + let key = '' endif - return 0 -endfunction -function! leaderf#PopupFilter(winid, key) abort - return 0 + return key endfunction function! leaderf#NormalModeFilter(id, winid, key) abort exec g:Lf_py "import ctypes" - let key = get(g:Lf_KeyMap, a:key, a:key) + let key = leaderf#RemapKey(a:id, get(g:Lf_KeyMap, a:key, a:key)) if key !=# "g" call win_execute(a:winid, printf("let g:Lf_%d_is_g_pressed = 0", a:id)) @@ -577,7 +569,7 @@ function! leaderf#NormalModeFilter(id, winid, key) abort else return 0 endif - elseif key ==# "q" || key ==? "" + elseif key ==# "q" exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value.quit()", a:id) elseif key ==# "i" || key ==? "" call leaderf#ResetPopupOptions(a:winid, 'filter', 'leaderf#PopupFilter') @@ -598,6 +590,8 @@ function! leaderf#NormalModeFilter(id, winid, key) abort exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value._toUpInPopup()", a:id) elseif key ==? "" exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value._toDownInPopup()", a:id) + elseif key ==? "" + exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value._closePreviewPopup()", a:id) endif return 1 diff --git a/autoload/leaderf/Any.vim b/autoload/leaderf/Any.vim index e982e68f..a2e4bdb7 100644 --- a/autoload/leaderf/Any.vim +++ b/autoload/leaderf/Any.vim @@ -34,11 +34,9 @@ function! leaderf#Any#Maps(category) nnoremap :exec g:Lf_py b:Lf_AnyExplManager.moveAndPreview('Down')" nnoremap :exec g:Lf_py b:Lf_AnyExplManager.moveAndPreview('PageUp')" nnoremap :exec g:Lf_py b:Lf_AnyExplManager.moveAndPreview('PageDown')" - if has("nvim") - nnoremap :exec g:Lf_py b:Lf_AnyExplManager."_toUpInPopup()" - nnoremap :exec g:Lf_py b:Lf_AnyExplManager."_toDownInPopup()" - nnoremap :exec g:Lf_py b:Lf_AnyExplManager."_closePreviewPopup()" - endif + nnoremap :exec g:Lf_py b:Lf_AnyExplManager."_toUpInPopup()" + nnoremap :exec g:Lf_py b:Lf_AnyExplManager."_toDownInPopup()" + nnoremap :exec g:Lf_py b:Lf_AnyExplManager."_closePreviewPopup()" if has_key(g:Lf_NormalMap, a:category) for i in g:Lf_NormalMap[a:category] exec 'nnoremap '.i[0].' '.i[1] diff --git a/autoload/leaderf/BufTag.vim b/autoload/leaderf/BufTag.vim index 0d1407b0..a14961c2 100644 --- a/autoload/leaderf/BufTag.vim +++ b/autoload/leaderf/BufTag.vim @@ -33,11 +33,9 @@ function! leaderf#BufTag#Maps() nnoremap :exec g:Lf_py "bufTagExplManager.moveAndPreview('Down')" nnoremap :exec g:Lf_py "bufTagExplManager.moveAndPreview('PageUp')" nnoremap :exec g:Lf_py "bufTagExplManager.moveAndPreview('PageDown')" - if has("nvim") - nnoremap :exec g:Lf_py "bufTagExplManager._toUpInPopup()" - nnoremap :exec g:Lf_py "bufTagExplManager._toDownInPopup()" - nnoremap :exec g:Lf_py "bufTagExplManager._closePreviewPopup()" - endif + nnoremap :exec g:Lf_py "bufTagExplManager._toUpInPopup()" + nnoremap :exec g:Lf_py "bufTagExplManager._toDownInPopup()" + nnoremap :exec g:Lf_py "bufTagExplManager._closePreviewPopup()" if has_key(g:Lf_NormalMap, "BufTag") for i in g:Lf_NormalMap["BufTag"] exec 'nnoremap '.i[0].' '.i[1] diff --git a/autoload/leaderf/Buffer.vim b/autoload/leaderf/Buffer.vim index de2b7fab..6924bf23 100644 --- a/autoload/leaderf/Buffer.vim +++ b/autoload/leaderf/Buffer.vim @@ -35,11 +35,9 @@ function! leaderf#Buffer#Maps() nnoremap :exec g:Lf_py "bufExplManager.moveAndPreview('Down')" nnoremap :exec g:Lf_py "bufExplManager.moveAndPreview('PageUp')" nnoremap :exec g:Lf_py "bufExplManager.moveAndPreview('PageDown')" - if has("nvim") - nnoremap :exec g:Lf_py "bufExplManager._toUpInPopup()" - nnoremap :exec g:Lf_py "bufExplManager._toDownInPopup()" - nnoremap :exec g:Lf_py "bufExplManager._closePreviewPopup()" - endif + nnoremap :exec g:Lf_py "bufExplManager._toUpInPopup()" + nnoremap :exec g:Lf_py "bufExplManager._toDownInPopup()" + nnoremap :exec g:Lf_py "bufExplManager._closePreviewPopup()" if has_key(g:Lf_NormalMap, "Buffer") for i in g:Lf_NormalMap["Buffer"] exec 'nnoremap '.i[0].' '.i[1] @@ -48,7 +46,8 @@ function! leaderf#Buffer#Maps() endfunction function! leaderf#Buffer#NormalModeFilter(winid, key) abort - let key = get(g:Lf_KeyMap, a:key, a:key) + let key = leaderf#RemapKey(g:Lf_PyEval("id(bufExplManager)"), get(g:Lf_KeyMap, a:key, a:key)) + if key ==# "d" exec g:Lf_py "bufExplManager.deleteBuffer(1)" elseif key ==# "D" diff --git a/autoload/leaderf/Command.vim b/autoload/leaderf/Command.vim index 6a7d82f0..ab5007ab 100644 --- a/autoload/leaderf/Command.vim +++ b/autoload/leaderf/Command.vim @@ -30,7 +30,7 @@ function! leaderf#Command#Maps() endfunction function! leaderf#Command#NormalModeFilter(winid, key) abort - let key = get(g:Lf_KeyMap, a:key, a:key) + let key = leaderf#RemapKey(g:Lf_PyEval("id(commandExplManager)"), get(g:Lf_KeyMap, a:key, a:key)) if key ==# "x" elseif key ==# "v" diff --git a/autoload/leaderf/File.vim b/autoload/leaderf/File.vim index c62cb0da..99523a0c 100644 --- a/autoload/leaderf/File.vim +++ b/autoload/leaderf/File.vim @@ -37,11 +37,9 @@ function! leaderf#File#Maps() nnoremap :exec g:Lf_py "fileExplManager.moveAndPreview('Down')" nnoremap :exec g:Lf_py "fileExplManager.moveAndPreview('PageUp')" nnoremap :exec g:Lf_py "fileExplManager.moveAndPreview('PageDown')" - if has("nvim") - nnoremap :exec g:Lf_py "fileExplManager._toUpInPopup()" - nnoremap :exec g:Lf_py "fileExplManager._toDownInPopup()" - nnoremap :exec g:Lf_py "fileExplManager._closePreviewPopup()" - endif + nnoremap :exec g:Lf_py "fileExplManager._toUpInPopup()" + nnoremap :exec g:Lf_py "fileExplManager._toDownInPopup()" + nnoremap :exec g:Lf_py "fileExplManager._closePreviewPopup()" if has_key(g:Lf_NormalMap, "File") for i in g:Lf_NormalMap["File"] exec 'nnoremap '.i[0].' '.i[1] @@ -58,7 +56,8 @@ function! leaderf#File#TimerCallback(id) endfunction function! leaderf#File#NormalModeFilter(winid, key) abort - let key = get(g:Lf_KeyMap, a:key, a:key) + let key = leaderf#RemapKey(g:Lf_PyEval("id(fileExplManager)"), get(g:Lf_KeyMap, a:key, a:key)) + if key ==? "" exec g:Lf_py "fileExplManager.refresh()" elseif key ==# "s" diff --git a/autoload/leaderf/Function.vim b/autoload/leaderf/Function.vim index 80c6b749..9d135723 100644 --- a/autoload/leaderf/Function.vim +++ b/autoload/leaderf/Function.vim @@ -33,11 +33,9 @@ function! leaderf#Function#Maps() nnoremap :exec g:Lf_py "functionExplManager.moveAndPreview('Down')" nnoremap :exec g:Lf_py "functionExplManager.moveAndPreview('PageUp')" nnoremap :exec g:Lf_py "functionExplManager.moveAndPreview('PageDown')" - if has("nvim") - nnoremap :exec g:Lf_py "functionExplManager._toUpInPopup()" - nnoremap :exec g:Lf_py "functionExplManager._toDownInPopup()" - nnoremap :exec g:Lf_py "functionExplManager._closePreviewPopup()" - endif + nnoremap :exec g:Lf_py "functionExplManager._toUpInPopup()" + nnoremap :exec g:Lf_py "functionExplManager._toDownInPopup()" + nnoremap :exec g:Lf_py "functionExplManager._closePreviewPopup()" if has_key(g:Lf_NormalMap, "Function") for i in g:Lf_NormalMap["Function"] exec 'nnoremap '.i[0].' '.i[1] diff --git a/autoload/leaderf/Gtags.vim b/autoload/leaderf/Gtags.vim index d189ae9a..6c17d269 100644 --- a/autoload/leaderf/Gtags.vim +++ b/autoload/leaderf/Gtags.vim @@ -35,11 +35,9 @@ function! leaderf#Gtags#Maps() nnoremap :exec g:Lf_py "gtagsExplManager.input()" nnoremap :exec g:Lf_py "gtagsExplManager.toggleHelp()" nnoremap d :exec g:Lf_py "gtagsExplManager.deleteCurrentLine()" - if has("nvim") - nnoremap :exec g:Lf_py "gtagsExplManager._toUpInPopup()" - nnoremap :exec g:Lf_py "gtagsExplManager._toDownInPopup()" - nnoremap :exec g:Lf_py "gtagsExplManager._closePreviewPopup()" - endif + nnoremap :exec g:Lf_py "gtagsExplManager._toUpInPopup()" + nnoremap :exec g:Lf_py "gtagsExplManager._toDownInPopup()" + nnoremap :exec g:Lf_py "gtagsExplManager._closePreviewPopup()" if has_key(g:Lf_NormalMap, "Gtags") for i in g:Lf_NormalMap["Gtags"] exec 'nnoremap '.i[0].' '.i[1] @@ -107,7 +105,8 @@ EOF endfunction function! leaderf#Gtags#NormalModeFilter(winid, key) abort - let key = get(g:Lf_KeyMap, a:key, a:key) + let key = leaderf#RemapKey(g:Lf_PyEval("id(gtagsExplManager)"), get(g:Lf_KeyMap, a:key, a:key)) + if key ==# "d" exec g:Lf_py "gtagsExplManager.deleteCurrentLine()" elseif key ==# "s" diff --git a/autoload/leaderf/History.vim b/autoload/leaderf/History.vim index d53d1a16..a9794af4 100644 --- a/autoload/leaderf/History.vim +++ b/autoload/leaderf/History.vim @@ -29,7 +29,7 @@ function! leaderf#History#Maps() endfunction function! leaderf#History#NormalModeFilter(winid, key) abort - let key = get(g:Lf_KeyMap, a:key, a:key) + let key = leaderf#RemapKey(g:Lf_PyEval("id(historyExplManager)"), get(g:Lf_KeyMap, a:key, a:key)) if key ==# "x" elseif key ==# "v" diff --git a/autoload/leaderf/Jumps.vim b/autoload/leaderf/Jumps.vim index 345d5280..430a9ebc 100644 --- a/autoload/leaderf/Jumps.vim +++ b/autoload/leaderf/Jumps.vim @@ -34,11 +34,9 @@ function! leaderf#Jumps#Maps() nnoremap :exec g:Lf_py "jumpsExplManager.moveAndPreview('Down')" nnoremap :exec g:Lf_py "jumpsExplManager.moveAndPreview('PageUp')" nnoremap :exec g:Lf_py "jumpsExplManager.moveAndPreview('PageDown')" - if has("nvim") - nnoremap :exec g:Lf_py "jumpsExplManager._toUpInPopup()" - nnoremap :exec g:Lf_py "jumpsExplManager._toDownInPopup()" - nnoremap :exec g:Lf_py "jumpsExplManager._closePreviewPopup()" - endif + nnoremap :exec g:Lf_py "jumpsExplManager._toUpInPopup()" + nnoremap :exec g:Lf_py "jumpsExplManager._toDownInPopup()" + nnoremap :exec g:Lf_py "jumpsExplManager._closePreviewPopup()" if has_key(g:Lf_NormalMap, "Jumps") for i in g:Lf_NormalMap["Jumps"] exec 'nnoremap '.i[0].' '.i[1] diff --git a/autoload/leaderf/Line.vim b/autoload/leaderf/Line.vim index f064aa21..e23f83a2 100644 --- a/autoload/leaderf/Line.vim +++ b/autoload/leaderf/Line.vim @@ -35,11 +35,9 @@ function! leaderf#Line#Maps() nnoremap :exec g:Lf_py "lineExplManager.moveAndPreview('PageDown')" nnoremap Q :exec g:Lf_py "lineExplManager.outputToQflist()" nnoremap L :exec g:Lf_py "lineExplManager.outputToLoclist()" - if has("nvim") - nnoremap :exec g:Lf_py "lineExplManager._toUpInPopup()" - nnoremap :exec g:Lf_py "lineExplManager._toDownInPopup()" - nnoremap :exec g:Lf_py "lineExplManager._closePreviewPopup()" - endif + nnoremap :exec g:Lf_py "lineExplManager._toUpInPopup()" + nnoremap :exec g:Lf_py "lineExplManager._toDownInPopup()" + nnoremap :exec g:Lf_py "lineExplManager._closePreviewPopup()" if has_key(g:Lf_NormalMap, "Line") for i in g:Lf_NormalMap["Line"] exec 'nnoremap '.i[0].' '.i[1] @@ -48,7 +46,8 @@ function! leaderf#Line#Maps() endfunction function! leaderf#Line#NormalModeFilter(winid, key) abort - let key = get(g:Lf_KeyMap, a:key, a:key) + let key = leaderf#RemapKey(g:Lf_PyEval("id(lineExplManager)"), get(g:Lf_KeyMap, a:key, a:key)) + if key ==? "" exec g:Lf_py "lineExplManager.refresh()" elseif key ==# "Q" diff --git a/autoload/leaderf/Mru.vim b/autoload/leaderf/Mru.vim index 8a80b90a..f9e1739b 100644 --- a/autoload/leaderf/Mru.vim +++ b/autoload/leaderf/Mru.vim @@ -37,11 +37,9 @@ function! leaderf#Mru#Maps() nnoremap :exec g:Lf_py "mruExplManager.moveAndPreview('Down')" nnoremap :exec g:Lf_py "mruExplManager.moveAndPreview('PageUp')" nnoremap :exec g:Lf_py "mruExplManager.moveAndPreview('PageDown')" - if has("nvim") - nnoremap :exec g:Lf_py "mruExplManager._toUpInPopup()" - nnoremap :exec g:Lf_py "mruExplManager._toDownInPopup()" - nnoremap :exec g:Lf_py "mruExplManager._closePreviewPopup()" - endif + nnoremap :exec g:Lf_py "mruExplManager._toUpInPopup()" + nnoremap :exec g:Lf_py "mruExplManager._toDownInPopup()" + nnoremap :exec g:Lf_py "mruExplManager._closePreviewPopup()" if has_key(g:Lf_NormalMap, "Mru") for i in g:Lf_NormalMap["Mru"] exec 'nnoremap '.i[0].' '.i[1] @@ -50,7 +48,8 @@ function! leaderf#Mru#Maps() endfunction function! leaderf#Mru#NormalModeFilter(winid, key) abort - let key = get(g:Lf_KeyMap, a:key, a:key) + let key = leaderf#RemapKey(g:Lf_PyEval("id(mruExplManager)"), get(g:Lf_KeyMap, a:key, a:key)) + if key ==# "d" exec g:Lf_py "mruExplManager.deleteMru()" elseif key ==# "s" diff --git a/autoload/leaderf/QfLocList.vim b/autoload/leaderf/QfLocList.vim index b956dd86..a7923095 100644 --- a/autoload/leaderf/QfLocList.vim +++ b/autoload/leaderf/QfLocList.vim @@ -26,11 +26,9 @@ function! leaderf#QfLocList#Maps() nnoremap i :exec g:Lf_py "qfloclistExplManager.input()" nnoremap :exec g:Lf_py "qfloclistExplManager.input()" nnoremap :exec g:Lf_py "qfloclistExplManager.toggleHelp()" - if has("nvim") - nnoremap :exec g:Lf_py "qfloclistExplManager._toUpInPopup()" - nnoremap :exec g:Lf_py "qfloclistExplManager._toDownInPopup()" - nnoremap :exec g:Lf_py "qfloclistExplManager._closePreviewPopup()" - endif + nnoremap :exec g:Lf_py "qfloclistExplManager._toUpInPopup()" + nnoremap :exec g:Lf_py "qfloclistExplManager._toDownInPopup()" + nnoremap :exec g:Lf_py "qfloclistExplManager._closePreviewPopup()" if has_key(g:Lf_NormalMap, "QfLocList") for i in g:Lf_NormalMap["QfLocList"] exec 'nnoremap '.i[0].' '.i[1] diff --git a/autoload/leaderf/Rg.vim b/autoload/leaderf/Rg.vim index e469bb5a..c7774ae9 100644 --- a/autoload/leaderf/Rg.vim +++ b/autoload/leaderf/Rg.vim @@ -42,11 +42,9 @@ function! leaderf#Rg#Maps(heading) nnoremap w :call leaderf#Rg#ApplyChangesAndSave(0) nnoremap W :call leaderf#Rg#ApplyChangesAndSave(1) nnoremap U :call leaderf#Rg#UndoLastChange() - if has("nvim") - nnoremap :exec g:Lf_py "rgExplManager._toUpInPopup()" - nnoremap :exec g:Lf_py "rgExplManager._toDownInPopup()" - nnoremap :exec g:Lf_py "rgExplManager._closePreviewPopup()" - endif + nnoremap :exec g:Lf_py "rgExplManager._toUpInPopup()" + nnoremap :exec g:Lf_py "rgExplManager._toDownInPopup()" + nnoremap :exec g:Lf_py "rgExplManager._closePreviewPopup()" if has_key(g:Lf_NormalMap, "Rg") for i in g:Lf_NormalMap["Rg"] exec 'nnoremap '.i[0].' '.i[1] @@ -182,7 +180,8 @@ endfunction function! leaderf#Rg#NormalModeFilter(winid, key) abort - let key = get(g:Lf_KeyMap, a:key, a:key) + let key = leaderf#RemapKey(g:Lf_PyEval("id(rgExplManager)"), get(g:Lf_KeyMap, a:key, a:key)) + if key ==# "i" || key ==? "" if g:Lf_py == "py " let has_heading = pyeval("'--heading' in rgExplManager._arguments") diff --git a/autoload/leaderf/Tag.vim b/autoload/leaderf/Tag.vim index 2ec58825..f676b23a 100644 --- a/autoload/leaderf/Tag.vim +++ b/autoload/leaderf/Tag.vim @@ -34,11 +34,9 @@ function! leaderf#Tag#Maps() nnoremap :exec g:Lf_py "tagExplManager.moveAndPreview('Down')" nnoremap :exec g:Lf_py "tagExplManager.moveAndPreview('PageUp')" nnoremap :exec g:Lf_py "tagExplManager.moveAndPreview('PageDown')" - if has("nvim") - nnoremap :exec g:Lf_py "tagExplManager._toUpInPopup()" - nnoremap :exec g:Lf_py "tagExplManager._toDownInPopup()" - nnoremap :exec g:Lf_py "tagExplManager._closePreviewPopup()" - endif + nnoremap :exec g:Lf_py "tagExplManager._toUpInPopup()" + nnoremap :exec g:Lf_py "tagExplManager._toDownInPopup()" + nnoremap :exec g:Lf_py "tagExplManager._closePreviewPopup()" if has_key(g:Lf_NormalMap, "Tag") for i in g:Lf_NormalMap["Tag"] exec 'nnoremap '.i[0].' '.i[1] diff --git a/autoload/leaderf/Window.vim b/autoload/leaderf/Window.vim index 13bbae7e..9716ee34 100644 --- a/autoload/leaderf/Window.vim +++ b/autoload/leaderf/Window.vim @@ -32,7 +32,7 @@ function! leaderf#Window#Maps() endfunction function! leaderf#Window#NormalModeFilter(winid, key) abort - let key = get(g:Lf_KeyMap, a:key, a:key) + let key = leaderf#RemapKey(g:Lf_PyEval("id(windowExplManager)"), get(g:Lf_KeyMap, a:key, a:key)) if key ==# "x" elseif key ==# "v" diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index c72502f1..819735e3 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -149,6 +149,23 @@ def _getExplClass(self): def _defineMaps(self): pass + def _defineNormalCommandMaps(self): + normal_map = lfEval("get(g:, 'Lf_NormalCommandMap', {})") + if not normal_map: + return + + command_map = normal_map.get("*", {}) + command_map.update(normal_map.get(self._getExplorer().getStlCategory(), {})) + new_commands = set(i.lower() if i.startswith('<') else i for i in command_map.values()) + map_rhs = {k: lfEval("maparg('{}', 'n', 0, 1)".format(k)) for k in command_map} + for old, new in command_map.items(): + maparg = map_rhs[old] + if maparg and maparg["buffer"] == '1': + lfCmd("silent! nnoremap {} {}".format(new, maparg["rhs"])) + old_cmd = old.lower() if old.startswith('<') else old + if old_cmd not in new_commands: + lfCmd("silent! nunmap {}".format(old)) + def _defineCommonMaps(self): normal_map = lfEval("get(g:, 'Lf_NormalMap', {})") if "_" not in normal_map: @@ -291,6 +308,7 @@ def _afterEnter(self): if self._getInstance().getWinPos() != 'popup': self._defineMaps() self._defineCommonMaps() + self._defineNormalCommandMaps() id = int(lfEval("matchadd('Lf_hl_cursorline', '.*\%#.*', -100)")) self._match_ids.append(id) diff --git a/doc/leaderf.txt b/doc/leaderf.txt index f2d67aed..6970104f 100644 --- a/doc/leaderf.txt +++ b/doc/leaderf.txt @@ -451,6 +451,8 @@ g:Lf_UseCache *g:Lf_UseCache* Default value is 1. g:Lf_NormalMap *g:Lf_NormalMap* + This option is deprecated in favor of |g:Lf_NormalCommandMap|. + Use this option to customize the mappings in normal mode. The mapping with the key `"_"` applies to all categories. Also, `"_"` is overridden by the mapping of each category. @@ -515,6 +517,41 @@ g:Lf_CommandMap *g:Lf_CommandMap* change the default command to and : > let g:Lf_CommandMap = {'': [''], '': ['', '']} < + Note: The key of the dictionary is the old command, the value of the + dictionary is the new command. + +g:Lf_NormalCommandMap *g:Lf_NormalCommandMap* + Use this option to customize the mappings in normal mode. + The mapping with the key `"*"` applies to all categories. + Also, `"*"` is overridden by the mapping of each category. + + Note: The key of the dictionary is the old command, the value of the + dictionary is the new command. + + e.g., > + let g:Lf_NormalCommandMap = { + \ "*": { + \ "": "", + \ "": "" + \ }, + \ "File": { + \ "q": "", + \ "a": "", + \ "": "", + \ }, + \ "Buffer": {}, + \ "Mru": {}, + \ "Tag": {}, + \ "BufTag": {}, + \ "Function": {}, + \ "Line": {}, + \ "History":{}, + \ "Help": {}, + \ "Rg": {}, + \ "Gtags": {}, + \ "Colorscheme": {} + \} + g:Lf_HideHelp *g:Lf_HideHelp* To specify whether to show the hint "Press for help" in normal mode. You can set the value to 1 to hide the hint. From 5be44034a3a5a31e12074f287bedd670297c52ee Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 6 Sep 2023 22:38:03 +0800 Subject: [PATCH 119/365] fix issue #1031 --- autoload/leaderf/python/leaderf/manager.py | 149 ++++++++++++++++----- doc/leaderf.txt | 2 + 2 files changed, 118 insertions(+), 33 deletions(-) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 819735e3..27ecda8f 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -878,37 +878,82 @@ def _createPopupPreview(self, title, source, line_nr, jump_cmd=''): self._createPopupModePreview(title, source, line_nr, jump_cmd) return True + win_pos = self._getInstance().getWinPos() show_borders = lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1' preview_pos = lfEval("get(g:, 'Lf_PreviewPosition', 'top')") if lfEval("has('nvim')") == '1': - if preview_pos.lower() == 'topleft': + if win_pos == 'bottom': + if preview_pos.lower() == 'topleft': + relative = 'editor' + anchor = "SW" + width = self._getInstance().window.width // 2 + height = self._getInstance().window.row + row = self._getInstance().window.row + col = 0 + elif preview_pos.lower() == 'topright': + relative = 'editor' + anchor = "SW" + width = self._getInstance().window.width // 2 + height = self._getInstance().window.row + row = self._getInstance().window.row + col = self._getInstance().window.width - width + elif preview_pos.lower() == 'right': + relative = 'editor' + anchor = "NW" + width = self._getInstance().window.width // 2 + height = self._getInstance().window.height + row = self._getInstance().window.row + col = self._getInstance().window.width - width + else: # preview_pos.lower() == 'top' + relative = 'editor' + anchor = "SW" + width = self._getInstance().window.width + height = self._getInstance().window.row + row = self._getInstance().window.row + col = 0 + elif win_pos == 'top': + if preview_pos.lower() == 'bottom': + relative = 'editor' + anchor = "NW" + width = self._getInstance().window.width + height = int(lfEval("&lines")) - self._getInstance().window.height - 2 + row = self._getInstance().window.height + col = 0 + else: # preview_pos.lower() == 'right' + relative = 'editor' + anchor = "NW" + width = self._getInstance().window.width // 2 + height = self._getInstance().window.height + row = self._getInstance().window.row + col = self._getInstance().window.width - width + elif win_pos == 'left': relative = 'editor' - anchor = "SW" - width = self._getInstance().window.width // 2 - height = self._getInstance().window.row + anchor = "NW" + width = int(lfEval("&columns")) - 1 - self._getInstance().window.width + height = self._getInstance().window.height row = self._getInstance().window.row - col = 0 - elif preview_pos.lower() == 'topright': + col = self._getInstance().window.width + 1 + elif win_pos == 'right': relative = 'editor' - anchor = "SW" - width = self._getInstance().window.width // 2 - height = self._getInstance().window.row + anchor = "NW" + width = int(lfEval("&columns")) - 1 - self._getInstance().window.width + height = self._getInstance().window.height row = self._getInstance().window.row - col = self._getInstance().window.width - width - elif preview_pos.lower() == 'right': + col = 0 + elif win_pos == 'fullScreen': relative = 'editor' anchor = "NW" width = self._getInstance().window.width // 2 height = self._getInstance().window.height row = self._getInstance().window.row col = self._getInstance().window.width - width - else: # preview_pos.lower() == 'top' + else: relative = 'editor' - anchor = "SW" - width = self._getInstance().window.width - height = self._getInstance().window.row + anchor = "NW" + width = self._getInstance().window.width // 2 + height = self._getInstance().window.height row = self._getInstance().window.row - col = 0 + col = self._getInstance().window.col + self._getInstance().window.width - width config = { "relative": relative, @@ -942,30 +987,68 @@ def _createPopupPreview(self, title, source, line_nr, jump_cmd=''): self._createPreviewWindow(config, source, line_nr, jump_cmd) else: - if preview_pos.lower() == 'topleft': - maxwidth = self._getInstance().window.width // 2 - maxheight = self._getInstance().window.row - 1 - pos = "botleft" - line = self._getInstance().window.row + if win_pos == 'bottom': + if preview_pos.lower() == 'topleft': + maxwidth = self._getInstance().window.width // 2 + maxheight = self._getInstance().window.row - 1 + pos = "botleft" + line = self._getInstance().window.row + col = 1 + elif preview_pos.lower() == 'topright': + maxwidth = self._getInstance().window.width // 2 + maxheight = self._getInstance().window.row - 1 + pos = "botleft" + line = self._getInstance().window.row + col = self._getInstance().window.width - maxwidth + 1 + elif preview_pos.lower() == 'right': + maxwidth = self._getInstance().window.width // 2 + maxheight = self._getInstance().window.height - 1 + pos = "topleft" + line = self._getInstance().window.row + 1 + col = self._getInstance().window.width - maxwidth + 1 + else: # preview_pos.lower() == 'top' + maxwidth = self._getInstance().window.width + maxheight = self._getInstance().window.row - 1 + pos = "botleft" + line = self._getInstance().window.row + col = 1 + elif win_pos == 'top': + if preview_pos.lower() == 'bottom': + maxwidth = self._getInstance().window.width + maxheight = int(lfEval("&lines")) - self._getInstance().window.height - 3 + pos = "topleft" + line = self._getInstance().window.height + 1 + col = 1 + else: # preview_pos.lower() == 'right' + maxwidth = self._getInstance().window.width // 2 + maxheight = self._getInstance().window.height - 1 + pos = "topleft" + line = self._getInstance().window.row + 1 + col = self._getInstance().window.width - maxwidth + 1 + elif win_pos == 'left': + maxwidth = int(lfEval("&columns")) - 1 - self._getInstance().window.width + maxheight = self._getInstance().window.height - 1 + pos = "topleft" + line = self._getInstance().window.row + 1 + col = self._getInstance().window.width + 2 + elif win_pos == 'right': + maxwidth = int(lfEval("&columns")) - 1 - self._getInstance().window.width + maxheight = self._getInstance().window.height - 1 + pos = "topleft" + line = self._getInstance().window.row + 1 col = 1 - elif preview_pos.lower() == 'topright': + elif win_pos == 'fullScreen': maxwidth = self._getInstance().window.width // 2 - maxheight = self._getInstance().window.row - 1 - pos = "botleft" - line = self._getInstance().window.row + maxheight = self._getInstance().window.height - 1 + pos = "topleft" + line = self._getInstance().window.row + 1 col = self._getInstance().window.width - maxwidth + 1 - elif preview_pos.lower() == 'right': + else: maxwidth = self._getInstance().window.width // 2 maxheight = self._getInstance().window.height - 1 pos = "topleft" line = self._getInstance().window.row + 1 - col = self._getInstance().window.width - maxwidth + 1 - else: # preview_pos.lower() == 'top' - maxwidth = self._getInstance().window.width - maxheight = self._getInstance().window.row - 1 - pos = "botleft" - line = self._getInstance().window.row - col = 1 + col = self._getInstance().window.col + self._getInstance().window.width - maxwidth + 1 options = { "title": " Preview ", diff --git a/doc/leaderf.txt b/doc/leaderf.txt index 6970104f..9bc6e84c 100644 --- a/doc/leaderf.txt +++ b/doc/leaderf.txt @@ -885,6 +885,8 @@ g:Lf_PreviewPosition *g:Lf_PreviewPosition* 'topleft': the preview window is on the topleft of the main LeaderF window. 'topright': the preview window is on the topright of the main LeaderF window. 'right': the preview window is on the right of the main LeaderF window. + 'bottom': the preview window is at the bottom of the main LeaderF window. + (only available when LeaderF window is on the top) Default value is 'top'. From 80edadb7b1e44f1ed3f0009b59f9424e98050119 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 7 Sep 2023 10:18:22 +0800 Subject: [PATCH 120/365] fix issue #1032 --- autoload/leaderf/python/leaderf/devicons.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autoload/leaderf/python/leaderf/devicons.py b/autoload/leaderf/python/leaderf/devicons.py index 29d595fa..a866faf5 100644 --- a/autoload/leaderf/python/leaderf/devicons.py +++ b/autoload/leaderf/python/leaderf/devicons.py @@ -48,7 +48,7 @@ 'Rmd' : '', 'es' : '', 'less' : '', 'rej' : '', 'Smd' : '', 'ex' : '', 'lhs' : '', 'rlib' : '', 'ai' : '', 'exs' : '', 'lisp' : '', 'rmd' : '', - 'awk' : '', 'f#' : '', 'lock' : '', 'rmeta' : '', + 'awk' : '', 'f#' : '', 'lock' : '', 'rmeta' : '', 'bash' : '', 'fish' : '', 'log' : '', 'rs' : '', 'bat' : '', 'fs' : '', 'lsp' : '', 'rss' : '', 'bin' : '', 'fsi' : '', 'lua' : '', 'sass' : '', From 712da0e4ebe9376d52be0e60eff72e8411ea5992 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 7 Sep 2023 17:36:48 +0800 Subject: [PATCH 121/365] fix issue #1029 add support for quick-select mode --- autoload/leaderf/Any.vim | 1 + autoload/leaderf/python/leaderf/cli.py | 18 +++++++++- autoload/leaderf/python/leaderf/manager.py | 38 ++++++++++++++++++++-- doc/leaderf.txt | 23 +++++++++++++ 4 files changed, 76 insertions(+), 4 deletions(-) diff --git a/autoload/leaderf/Any.vim b/autoload/leaderf/Any.vim index a2e4bdb7..7f69c46a 100644 --- a/autoload/leaderf/Any.vim +++ b/autoload/leaderf/Any.vim @@ -249,6 +249,7 @@ let g:Lf_CommonArguments = [ \ {"name": ["--auto-preview"], "nargs": 0, "help": "open preview window automatically."}, \ {"name": ["--no-auto-preview"], "nargs": 0, "help": "don't open preview window automatically."}, \ ], + \ {"name": ["--quick-select"], "nargs": "?", "choices":[0, 1], "metavar": "", "help": "Enable quick-select mode or not. can be '1' or '0', which means 'true' or 'false' respectively. If is omitted, it means enable quick-select mode."}, \] " arguments is something like g:Lf_CommonArguments diff --git a/autoload/leaderf/python/leaderf/cli.py b/autoload/leaderf/python/leaderf/cli.py index 5967e1d0..6325a8bf 100644 --- a/autoload/leaderf/python/leaderf/cli.py +++ b/autoload/leaderf/python/leaderf/cli.py @@ -70,6 +70,8 @@ def __init__(self): self._setDefaultMode() self._is_live = False self._additional_prompt_string = '' + self._quick_select = False + self.last_char = '' self._spin_symbols = lfEval("get(g:, 'Lf_SpinSymbols', [])") if not self._spin_symbols: if platform.system() == "Linux": @@ -82,6 +84,14 @@ def setInstance(self, instance): def setArguments(self, arguments): self._arguments = arguments + quick_select = self._arguments.get("--quick-select", [0]) + if len(quick_select) == 0: + quick_select_value = 1 + else: + quick_select_value = int(quick_select[0]) + self._quick_select = (not self._instance.isReverseOrder() + and (bool(quick_select_value) + or bool(int(lfEval("get(g:, 'Lf_QuickSelect', 0)"))))) def _setDefaultMode(self): mode = lfEval("g:Lf_DefaultMode") @@ -725,11 +735,17 @@ def input(self, callback): self._blinkon = True if lfEval("!type(nr) && nr >= 0x20") == '1': + char = lfEval("ch") + if self._quick_select and char in "0123456789": + self.last_char = char + yield '' + continue + if update == False: update = True prefix = ''.join(self._cmdline) - self._insert(lfEval("ch")) + self._insert(char) self._buildPattern() if self._pattern is None or (self._refine and self._pattern[1] == ''): # e.g. abc; continue diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 27ecda8f..93992c43 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -1382,6 +1382,33 @@ def _scrollDown(self): else: self._toDown() + def _quickSelect(self): + selection = int(self._cli.last_char) + if selection == 0: + selection = 10 + + line_num = self._help_length + selection + if line_num > len(self._getInstance().buffer): + return False + + if self._getInstance().isReverseOrder(): + pass + else: + if self._getInstance().getWinPos() == 'popup': + lfCmd("""call win_execute(%d, "exec %d")""" % (self._getInstance().getPopupWinId(), line_num)) + else: + lfCmd("exec %d" % line_num) + + action = lfEval("get(g:, 'Lf_QuickSelectAction', 'c')") + if action != '' and action in "hvtc": + if action == 'c': + action = '' + self.accept(action) + return True + else: + self._previewResult(False) + return False + def _search(self, content, is_continue=False, step=0): if not is_continue: self.clearSelections() @@ -2498,7 +2525,9 @@ def startExplorer(self, win_pos, *args, **kwargs): self._arguments["--next"] = arguments_dict["--next"] else: self.setArguments(arguments_dict) - self._cli.setArguments(arguments_dict) + + self._getInstance().setArguments(self._arguments) + self._cli.setArguments(self._arguments) self._cli.setNameOnlyFeature(self._getExplorer().supportsNameOnly()) self._cli.setRefineFeature(self._supportsRefine()) self._orig_line = None @@ -2520,7 +2549,6 @@ def startExplorer(self, win_pos, *args, **kwargs): self._cleanup() # lfCmd("echohl WarningMsg | redraw | echo ' searching ...' | echohl NONE") - self._getInstance().setArguments(self._arguments) empty_query = self._empty_query and self._getExplorer().getStlCategory() in ["File"] remember_last_status = "--recall" in self._arguments \ or lfEval("g:Lf_RememberLastSearch") == '1' and self._cli.pattern @@ -2658,7 +2686,8 @@ def startExplorer(self, win_pos, *args, **kwargs): self._reader_thread = threading.Thread(target=self._readContent, args=(content,)) self._reader_thread.daemon = True self._reader_thread.start() - self._previewFirstLine() + if not self._getInstance().isReverseOrder(): + self._previewFirstLine() if not kwargs.get('bang', 0): self.input() @@ -3025,6 +3054,9 @@ def input(self): elif equal(cmd, ''): self._scrollDown() self._previewResult(False) + elif equal(cmd, ''): + if self._quickSelect(): + break else: if self._cmdExtension(cmd): break diff --git a/doc/leaderf.txt b/doc/leaderf.txt index 9bc6e84c..6adedf68 100644 --- a/doc/leaderf.txt +++ b/doc/leaderf.txt @@ -1087,6 +1087,29 @@ g:Lf_FileActions *g:Lf_FileActions* g:Lf_MruEnable *g:Lf_MruEnable* Enable `Leaderf mru` or not. Default value is 1. + +g:Lf_QuickSelect *g:Lf_QuickSelect* + Enable quick-select mode or not. When enabled, characters [0-9] are not + treated as literal characters, but are used to select the [0-9]th entry. 0 + means the 10th entry. + NOTE: Appending '--quick-select' in the arguments list of `Leaderf` command + will override this option. + + Default value is 0. + +g:Lf_QuickSelectAction *g:Lf_QuickSelectAction* + This option specify what action to do when quick-select mode is enabled + and an entry is seleted. + + The value can be one of the following: + '': do nothing. + 'c': open the seleted entry in the current window. + 'h': open the seleted entry in a horizontal split window. + 'v': open the seleted entry in a vertical split window. + 't': open the seleted entry in a new tabpage. + + Default value is 'c'. + ============================================================================== USAGE *leaderf-usage* From 9ea48853ca8c923e807e42d2d8b5f3568d9c85b3 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 7 Sep 2023 18:01:55 +0800 Subject: [PATCH 122/365] fix issue #1029 --- autoload/leaderf/python/leaderf/cli.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/autoload/leaderf/python/leaderf/cli.py b/autoload/leaderf/python/leaderf/cli.py index 6325a8bf..5449d584 100644 --- a/autoload/leaderf/python/leaderf/cli.py +++ b/autoload/leaderf/python/leaderf/cli.py @@ -89,9 +89,12 @@ def setArguments(self, arguments): quick_select_value = 1 else: quick_select_value = int(quick_select[0]) - self._quick_select = (not self._instance.isReverseOrder() - and (bool(quick_select_value) - or bool(int(lfEval("get(g:, 'Lf_QuickSelect', 0)"))))) + + if "--quick-select" in self._arguments: + self._quick_select = not self._instance.isReverseOrder() and bool(quick_select_value) + else: + self._quick_select = (not self._instance.isReverseOrder() + and bool(int(lfEval("get(g:, 'Lf_QuickSelect', 0)")))) def _setDefaultMode(self): mode = lfEval("g:Lf_DefaultMode") From 7088babc96bc35b5a5a0b5ad12e3d2e7430b1a38 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Fri, 8 Sep 2023 11:16:44 +0800 Subject: [PATCH 123/365] use to close popup preview window if the window is open or quit otherwise --- autoload/leaderf.vim | 2 +- autoload/leaderf/Any.vim | 2 +- autoload/leaderf/BufTag.vim | 2 +- autoload/leaderf/Buffer.vim | 2 +- autoload/leaderf/File.vim | 2 +- autoload/leaderf/Function.vim | 2 +- autoload/leaderf/Gtags.vim | 2 +- autoload/leaderf/Jumps.vim | 2 +- autoload/leaderf/Line.vim | 2 +- autoload/leaderf/Mru.vim | 2 +- autoload/leaderf/QfLocList.vim | 2 +- autoload/leaderf/Rg.vim | 2 +- autoload/leaderf/Tag.vim | 2 +- autoload/leaderf/python/leaderf/manager.py | 8 ++++++++ 14 files changed, 21 insertions(+), 13 deletions(-) diff --git a/autoload/leaderf.vim b/autoload/leaderf.vim index c13cc6e2..6049c3d8 100644 --- a/autoload/leaderf.vim +++ b/autoload/leaderf.vim @@ -591,7 +591,7 @@ function! leaderf#NormalModeFilter(id, winid, key) abort elseif key ==? "" exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value._toDownInPopup()", a:id) elseif key ==? "" - exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value._closePreviewPopup()", a:id) + exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value.closePreviewPopupOrQuit()", a:id) endif return 1 diff --git a/autoload/leaderf/Any.vim b/autoload/leaderf/Any.vim index 7f69c46a..88fc7120 100644 --- a/autoload/leaderf/Any.vim +++ b/autoload/leaderf/Any.vim @@ -36,7 +36,7 @@ function! leaderf#Any#Maps(category) nnoremap :exec g:Lf_py b:Lf_AnyExplManager.moveAndPreview('PageDown')" nnoremap :exec g:Lf_py b:Lf_AnyExplManager."_toUpInPopup()" nnoremap :exec g:Lf_py b:Lf_AnyExplManager."_toDownInPopup()" - nnoremap :exec g:Lf_py b:Lf_AnyExplManager."_closePreviewPopup()" + nnoremap :exec g:Lf_py b:Lf_AnyExplManager."closePreviewPopupOrQuit()" if has_key(g:Lf_NormalMap, a:category) for i in g:Lf_NormalMap[a:category] exec 'nnoremap '.i[0].' '.i[1] diff --git a/autoload/leaderf/BufTag.vim b/autoload/leaderf/BufTag.vim index a14961c2..929ce13a 100644 --- a/autoload/leaderf/BufTag.vim +++ b/autoload/leaderf/BufTag.vim @@ -35,7 +35,7 @@ function! leaderf#BufTag#Maps() nnoremap :exec g:Lf_py "bufTagExplManager.moveAndPreview('PageDown')" nnoremap :exec g:Lf_py "bufTagExplManager._toUpInPopup()" nnoremap :exec g:Lf_py "bufTagExplManager._toDownInPopup()" - nnoremap :exec g:Lf_py "bufTagExplManager._closePreviewPopup()" + nnoremap :exec g:Lf_py "bufTagExplManager.closePreviewPopupOrQuit()" if has_key(g:Lf_NormalMap, "BufTag") for i in g:Lf_NormalMap["BufTag"] exec 'nnoremap '.i[0].' '.i[1] diff --git a/autoload/leaderf/Buffer.vim b/autoload/leaderf/Buffer.vim index 6924bf23..be3fe410 100644 --- a/autoload/leaderf/Buffer.vim +++ b/autoload/leaderf/Buffer.vim @@ -37,7 +37,7 @@ function! leaderf#Buffer#Maps() nnoremap :exec g:Lf_py "bufExplManager.moveAndPreview('PageDown')" nnoremap :exec g:Lf_py "bufExplManager._toUpInPopup()" nnoremap :exec g:Lf_py "bufExplManager._toDownInPopup()" - nnoremap :exec g:Lf_py "bufExplManager._closePreviewPopup()" + nnoremap :exec g:Lf_py "bufExplManager.closePreviewPopupOrQuit()" if has_key(g:Lf_NormalMap, "Buffer") for i in g:Lf_NormalMap["Buffer"] exec 'nnoremap '.i[0].' '.i[1] diff --git a/autoload/leaderf/File.vim b/autoload/leaderf/File.vim index 99523a0c..36f8a62b 100644 --- a/autoload/leaderf/File.vim +++ b/autoload/leaderf/File.vim @@ -39,7 +39,7 @@ function! leaderf#File#Maps() nnoremap :exec g:Lf_py "fileExplManager.moveAndPreview('PageDown')" nnoremap :exec g:Lf_py "fileExplManager._toUpInPopup()" nnoremap :exec g:Lf_py "fileExplManager._toDownInPopup()" - nnoremap :exec g:Lf_py "fileExplManager._closePreviewPopup()" + nnoremap :exec g:Lf_py "fileExplManager.closePreviewPopupOrQuit()" if has_key(g:Lf_NormalMap, "File") for i in g:Lf_NormalMap["File"] exec 'nnoremap '.i[0].' '.i[1] diff --git a/autoload/leaderf/Function.vim b/autoload/leaderf/Function.vim index 9d135723..db6638b4 100644 --- a/autoload/leaderf/Function.vim +++ b/autoload/leaderf/Function.vim @@ -35,7 +35,7 @@ function! leaderf#Function#Maps() nnoremap :exec g:Lf_py "functionExplManager.moveAndPreview('PageDown')" nnoremap :exec g:Lf_py "functionExplManager._toUpInPopup()" nnoremap :exec g:Lf_py "functionExplManager._toDownInPopup()" - nnoremap :exec g:Lf_py "functionExplManager._closePreviewPopup()" + nnoremap :exec g:Lf_py "functionExplManager.closePreviewPopupOrQuit()" if has_key(g:Lf_NormalMap, "Function") for i in g:Lf_NormalMap["Function"] exec 'nnoremap '.i[0].' '.i[1] diff --git a/autoload/leaderf/Gtags.vim b/autoload/leaderf/Gtags.vim index 6c17d269..73030c68 100644 --- a/autoload/leaderf/Gtags.vim +++ b/autoload/leaderf/Gtags.vim @@ -37,7 +37,7 @@ function! leaderf#Gtags#Maps() nnoremap d :exec g:Lf_py "gtagsExplManager.deleteCurrentLine()" nnoremap :exec g:Lf_py "gtagsExplManager._toUpInPopup()" nnoremap :exec g:Lf_py "gtagsExplManager._toDownInPopup()" - nnoremap :exec g:Lf_py "gtagsExplManager._closePreviewPopup()" + nnoremap :exec g:Lf_py "gtagsExplManager.closePreviewPopupOrQuit()" if has_key(g:Lf_NormalMap, "Gtags") for i in g:Lf_NormalMap["Gtags"] exec 'nnoremap '.i[0].' '.i[1] diff --git a/autoload/leaderf/Jumps.vim b/autoload/leaderf/Jumps.vim index 430a9ebc..7d9f5efe 100644 --- a/autoload/leaderf/Jumps.vim +++ b/autoload/leaderf/Jumps.vim @@ -36,7 +36,7 @@ function! leaderf#Jumps#Maps() nnoremap :exec g:Lf_py "jumpsExplManager.moveAndPreview('PageDown')" nnoremap :exec g:Lf_py "jumpsExplManager._toUpInPopup()" nnoremap :exec g:Lf_py "jumpsExplManager._toDownInPopup()" - nnoremap :exec g:Lf_py "jumpsExplManager._closePreviewPopup()" + nnoremap :exec g:Lf_py "jumpsExplManager.closePreviewPopupOrQuit()" if has_key(g:Lf_NormalMap, "Jumps") for i in g:Lf_NormalMap["Jumps"] exec 'nnoremap '.i[0].' '.i[1] diff --git a/autoload/leaderf/Line.vim b/autoload/leaderf/Line.vim index e23f83a2..a758bf86 100644 --- a/autoload/leaderf/Line.vim +++ b/autoload/leaderf/Line.vim @@ -37,7 +37,7 @@ function! leaderf#Line#Maps() nnoremap L :exec g:Lf_py "lineExplManager.outputToLoclist()" nnoremap :exec g:Lf_py "lineExplManager._toUpInPopup()" nnoremap :exec g:Lf_py "lineExplManager._toDownInPopup()" - nnoremap :exec g:Lf_py "lineExplManager._closePreviewPopup()" + nnoremap :exec g:Lf_py "lineExplManager.closePreviewPopupOrQuit()" if has_key(g:Lf_NormalMap, "Line") for i in g:Lf_NormalMap["Line"] exec 'nnoremap '.i[0].' '.i[1] diff --git a/autoload/leaderf/Mru.vim b/autoload/leaderf/Mru.vim index f9e1739b..bd6e064d 100644 --- a/autoload/leaderf/Mru.vim +++ b/autoload/leaderf/Mru.vim @@ -39,7 +39,7 @@ function! leaderf#Mru#Maps() nnoremap :exec g:Lf_py "mruExplManager.moveAndPreview('PageDown')" nnoremap :exec g:Lf_py "mruExplManager._toUpInPopup()" nnoremap :exec g:Lf_py "mruExplManager._toDownInPopup()" - nnoremap :exec g:Lf_py "mruExplManager._closePreviewPopup()" + nnoremap :exec g:Lf_py "mruExplManager.closePreviewPopupOrQuit()" if has_key(g:Lf_NormalMap, "Mru") for i in g:Lf_NormalMap["Mru"] exec 'nnoremap '.i[0].' '.i[1] diff --git a/autoload/leaderf/QfLocList.vim b/autoload/leaderf/QfLocList.vim index a7923095..656683d2 100644 --- a/autoload/leaderf/QfLocList.vim +++ b/autoload/leaderf/QfLocList.vim @@ -28,7 +28,7 @@ function! leaderf#QfLocList#Maps() nnoremap :exec g:Lf_py "qfloclistExplManager.toggleHelp()" nnoremap :exec g:Lf_py "qfloclistExplManager._toUpInPopup()" nnoremap :exec g:Lf_py "qfloclistExplManager._toDownInPopup()" - nnoremap :exec g:Lf_py "qfloclistExplManager._closePreviewPopup()" + nnoremap :exec g:Lf_py "qfloclistExplManager.closePreviewPopupOrQuit()" if has_key(g:Lf_NormalMap, "QfLocList") for i in g:Lf_NormalMap["QfLocList"] exec 'nnoremap '.i[0].' '.i[1] diff --git a/autoload/leaderf/Rg.vim b/autoload/leaderf/Rg.vim index c7774ae9..409ef046 100644 --- a/autoload/leaderf/Rg.vim +++ b/autoload/leaderf/Rg.vim @@ -44,7 +44,7 @@ function! leaderf#Rg#Maps(heading) nnoremap U :call leaderf#Rg#UndoLastChange() nnoremap :exec g:Lf_py "rgExplManager._toUpInPopup()" nnoremap :exec g:Lf_py "rgExplManager._toDownInPopup()" - nnoremap :exec g:Lf_py "rgExplManager._closePreviewPopup()" + nnoremap :exec g:Lf_py "rgExplManager.closePreviewPopupOrQuit()" if has_key(g:Lf_NormalMap, "Rg") for i in g:Lf_NormalMap["Rg"] exec 'nnoremap '.i[0].' '.i[1] diff --git a/autoload/leaderf/Tag.vim b/autoload/leaderf/Tag.vim index f676b23a..506ed37c 100644 --- a/autoload/leaderf/Tag.vim +++ b/autoload/leaderf/Tag.vim @@ -36,7 +36,7 @@ function! leaderf#Tag#Maps() nnoremap :exec g:Lf_py "tagExplManager.moveAndPreview('PageDown')" nnoremap :exec g:Lf_py "tagExplManager._toUpInPopup()" nnoremap :exec g:Lf_py "tagExplManager._toDownInPopup()" - nnoremap :exec g:Lf_py "tagExplManager._closePreviewPopup()" + nnoremap :exec g:Lf_py "tagExplManager.closePreviewPopupOrQuit()" if has_key(g:Lf_NormalMap, "Tag") for i in g:Lf_NormalMap["Tag"] exec 'nnoremap '.i[0].' '.i[1] diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 93992c43..e01092cb 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -389,6 +389,14 @@ def _supportsRefine(self): def _previewInPopup(self, *args, **kwargs): pass + def closePreviewPopupOrQuit(self): + if self._getInstance().getWinPos() in ('popup', 'floatwin'): + self.quit() + elif self._preview_winid: + self._closePreviewPopup() + else: + self.quit() + def _closePreviewPopup(self): if lfEval("has('nvim')") == '1': if self._preview_winid: From fb467cf489250f3d5efdba7205bfafc5f9ce8d45 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Fri, 8 Sep 2023 14:10:02 +0800 Subject: [PATCH 124/365] update doc --- doc/leaderf.txt | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/doc/leaderf.txt b/doc/leaderf.txt index 6adedf68..c91acc8d 100644 --- a/doc/leaderf.txt +++ b/doc/leaderf.txt @@ -1089,24 +1089,24 @@ g:Lf_MruEnable *g:Lf_MruEnable* Default value is 1. g:Lf_QuickSelect *g:Lf_QuickSelect* - Enable quick-select mode or not. When enabled, characters [0-9] are not + Enable or disable quick-select mode. If enabled, the characters [0-9] are not treated as literal characters, but are used to select the [0-9]th entry. 0 means the 10th entry. - NOTE: Appending '--quick-select' in the arguments list of `Leaderf` command + NOTE: Appending '--quick-select' to the arguments list of the `Leaderf` command will override this option. Default value is 0. g:Lf_QuickSelectAction *g:Lf_QuickSelectAction* - This option specify what action to do when quick-select mode is enabled - and an entry is seleted. + This option specifies what action to be taken when quick-select mode is enabled + and an entry is selected. The value can be one of the following: '': do nothing. - 'c': open the seleted entry in the current window. - 'h': open the seleted entry in a horizontal split window. - 'v': open the seleted entry in a vertical split window. - 't': open the seleted entry in a new tabpage. + 'c': open the selected entry in the current window. + 'h': open the selected entry in a horizontally split window. + 'v': open the selected entry in a vertically split window. + 't': open the selected entry in a new tabpage. Default value is 'c'. From b198bdffe5a84d76c1544ee681dffeadd1a5c0c2 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Sun, 10 Sep 2023 22:48:55 +0800 Subject: [PATCH 125/365] fix issue #1034 --- autoload/leaderf/python/leaderf/jumpsExpl.py | 2 ++ autoload/leaderf/python/leaderf/manager.py | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/autoload/leaderf/python/leaderf/jumpsExpl.py b/autoload/leaderf/python/leaderf/jumpsExpl.py index 18a3af1f..95eaa9f3 100644 --- a/autoload/leaderf/python/leaderf/jumpsExpl.py +++ b/autoload/leaderf/python/leaderf/jumpsExpl.py @@ -75,6 +75,8 @@ def _acceptSelection(self, *args, **kwargs): file_text = file_text[:-1] orig_buf_num = self._getInstance().getOriginalPos()[2].number orig_buf = vim.buffers[orig_buf_num] + if self._preview_winid: + self._closePreviewPopup() # it's text if int(line) <= len(orig_buf) and orig_buf[int(line) - 1].lstrip().startswith(file_text): self._getInstance().gotoOriginalWindow() diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index e01092cb..c370659e 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -2223,6 +2223,8 @@ def accept(self, mode=''): self._getInstance().cursorRow = self._getInstance().window.cursor[0] self._getInstance().helpLength = self._help_length try: + if self._preview_winid: + self._closePreviewPopup() vim.current.tabpage, vim.current.window, vim.current.buffer = self._getInstance().getOriginalPos() except vim.error: # error if original buffer is an No Name buffer pass @@ -2260,6 +2262,8 @@ def accept(self, mode=''): self._getInstance().cursorRow = self._getInstance().window.cursor[0] self._getInstance().helpLength = self._help_length try: + if self._preview_winid: + self._closePreviewPopup() vim.current.tabpage, vim.current.window, vim.current.buffer = self._getInstance().getOriginalPos() except vim.error: # error if original buffer is an No Name buffer pass From 6aebb6c6b1019499aed2815e86b59b831915af82 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 13 Sep 2023 17:45:40 +0800 Subject: [PATCH 126/365] fix issue #1030 add `--frecency` and g:Lf_MruEnableFrecency for `Leaderf mru` --- autoload/leaderf/Any.vim | 1 + autoload/leaderf/python/leaderf/mru.py | 39 +++++++++------- autoload/leaderf/python/leaderf/mruExpl.py | 54 ++++++++++++++++++++-- autoload/lfMru.vim | 25 +++++++--- doc/leaderf.txt | 5 ++ plugin/leaderf.vim | 2 +- 6 files changed, 98 insertions(+), 28 deletions(-) diff --git a/autoload/leaderf/Any.vim b/autoload/leaderf/Any.vim index 88fc7120..981622f3 100644 --- a/autoload/leaderf/Any.vim +++ b/autoload/leaderf/Any.vim @@ -86,6 +86,7 @@ let g:Lf_Arguments = { \ ], \ {"name": ["--no-split-path"], "nargs": 0, "help": "do not split the path"}, \ {"name": ["--absolute-path"], "nargs": 0, "help": "show absolute path"}, + \ {"name": ["--frecency"], "nargs": 0, "help": "enable the frecency algorithm"}, \ ], \ "tag":[], \ "bufTag":[ diff --git a/autoload/leaderf/python/leaderf/mru.py b/autoload/leaderf/python/leaderf/mru.py index 542a1317..a78639fe 100644 --- a/autoload/leaderf/python/leaderf/mru.py +++ b/autoload/leaderf/python/leaderf/mru.py @@ -18,7 +18,8 @@ def __init__(self): 'LeaderF', 'python' + lfEval("g:Lf_PythonVersion"), 'mru') - self._cache_file = os.path.join(self._cache_dir, 'mruCache') + self._cache_file = os.path.join(self._cache_dir, 'frecency') + self._old_cache_file = os.path.join(self._cache_dir, 'mruCache') self._initCache() self._mru_bufnrs = { b.number: 0 for b in vim.buffers } self._timestamp = 0 @@ -33,6 +34,9 @@ def _initCache(self): def getCacheFileName(self): return self._cache_file + def getOldCacheFileName(self): + return self._old_cache_file + def normalize(self, name): if '~' in name: name = os.path.expanduser(name) @@ -48,37 +52,40 @@ def normalize(self, name): name = name[:11].lower() + name[11:] return name - def saveToCache(self, buf_name_list): - buf_names = [] - for name in buf_name_list: - name = self.normalize(name) + def filename(self, line): + return line.rstrip().split(maxsplit=2)[2] + + def saveToCache(self, data_list): + frecency_list = [] + for item in data_list: + name = self.normalize(self.filename(item)) if True in (fnmatch.fnmatch(name, i) for i in lfEval("g:Lf_MruFileExclude")): continue - buf_names.append(name) + frecency_list.append(item) - if not buf_names: + if not frecency_list: return with lfOpen(self._cache_file, 'r+', errors='ignore', encoding='utf-8') as f: lines = f.readlines() - for name in buf_names: + for item in frecency_list: nocase = False - compare = name + compare = self.filename(item) if sys.platform[:3] == 'win' or sys.platform in ('cygwin', 'msys'): nocase = True - compare = name.lower() + compare = compare.lower() for i, line in enumerate(lines): - text = line.rstrip() + text = self.filename(line) if (compare == text) or (nocase and compare == text.lower()): - del lines[i] + time1, rank1, filename = item.split(maxsplit=2) + time2, rank2, _ = lines[i].split(maxsplit=2) + lines[i] = "{} {} {}\n".format(time1, int(rank1) + int(rank2), filename) break + else: + lines.append(item + '\n') - lines = [name + '\n' for name in buf_names] + lines - max_files = int(lfEval("g:Lf_MruMaxFiles")) - if len(lines) > max_files: - del lines[max_files:] f.seek(0) f.truncate(0) f.writelines(lines) diff --git a/autoload/leaderf/python/leaderf/mruExpl.py b/autoload/leaderf/python/leaderf/mruExpl.py index d330789d..fe5a2777 100644 --- a/autoload/leaderf/python/leaderf/mruExpl.py +++ b/autoload/leaderf/python/leaderf/mruExpl.py @@ -4,7 +4,10 @@ import vim import os import os.path +import time +import operator from fnmatch import fnmatch +from functools import partial from .utils import * from .explorer import * from .manager import * @@ -28,18 +31,60 @@ def __init__(self): self._max_bufname_len = 0 self._root_markers = lfEval("g:Lf_RootMarkers") + def getFrecency(self, current_time, item): + """ + item is [time, rank, filename] + """ + rank = int(item[1]) + delta_time = int(current_time) - int(item[0]) + frecency = 0 + if delta_time < 3600: + frecency = rank * 4 + elif delta_time < 86400: + frecency = rank * 2 + elif delta_time < 604800: + frecency = rank * 0.5 + else: + frecency = rank * 0.25 + + return frecency + def getContent(self, *args, **kwargs): mru.saveToCache(lfEval("readfile(lfMru#CacheFileName())")) lfCmd("call writefile([], lfMru#CacheFileName())") with lfOpen(mru.getCacheFileName(), 'r+', errors='ignore', encoding='utf8') as f: - lines = f.readlines() - lines = [name for name in lines if os.path.exists(lfDecode(name.rstrip()))] + data_list = [] + for line in f.readlines(): + data = line.split(maxsplit=2) + if os.path.exists(lfDecode(data[2].rstrip())): + data[0] = int(data[0]) + data_list.append(data) + + if len(data_list) == 0: + # import old data + with lfOpen(mru.getOldCacheFileName(), 'r+', errors='ignore', encoding='utf8') as old_f: + current_time = time.time() + data_list = [[int(current_time), 1, filename] for filename in old_f.readlines() + if os.path.exists(lfDecode(filename.rstrip())) + ] + + arguments_dict = kwargs.get("arguments", {}) + if "--frecency" in arguments_dict or lfEval("get(g:, 'Lf_MruEnableFrecency', 0)") == '1': + data_list.sort(key=partial(self.getFrecency, time.time()), reverse=True) + else: + data_list.sort(key=operator.itemgetter(0), reverse=True) + + max_files = int(lfEval("g:Lf_MruMaxFiles")) + if len(data_list) > max_files: + del data_list[max_files:] + f.seek(0) f.truncate(0) - f.writelines(lines) + f.writelines(["{} {} {}".format(data[0], data[1], data[2]) for data in data_list]) + + lines = [data[2].rstrip() for data in data_list] - arguments_dict = kwargs.get("arguments", {}) if "--cwd" in arguments_dict: lines = [name for name in lines if lfDecode(name).startswith(lfGetCwd())] elif "--project" in arguments_dict: @@ -49,7 +94,6 @@ def getContent(self, *args, **kwargs): project_root = ancestor lines = [name for name in lines if lfDecode(name).startswith(os.path.join(project_root, ''))] - lines = [line.rstrip() for line in lines] # remove the '\n' wildignore = lfEval("g:Lf_MruWildIgnore") lines = [name for name in lines if True not in (fnmatch(name, j) for j in wildignore.get('file', [])) and True not in (fnmatch(name, "*/" + j + "/*") for j in wildignore.get('dir', []))] diff --git a/autoload/lfMru.vim b/autoload/lfMru.vim index 5c817194..a843c485 100644 --- a/autoload/lfMru.vim +++ b/autoload/lfMru.vim @@ -17,7 +17,7 @@ if !isdirectory(g:Lf_CacheDirectory . '/LeaderF') call mkdir(g:Lf_CacheDirectory . '/LeaderF', "p") endif -let g:Lf_MruCacheFileName = g:Lf_CacheDirectory . '/LeaderF/tempMru' +let g:Lf_MruCacheFileName = g:Lf_CacheDirectory . '/LeaderF/frecency' if !filereadable(g:Lf_MruCacheFileName) call writefile([], g:Lf_MruCacheFileName) @@ -31,13 +31,26 @@ function! lfMru#record(name) if a:name == '' || !filereadable(a:name) || strpart(a:name, 0, 2) == '\\' return endif + let file_list = readfile(g:Lf_MruCacheFileName) - if empty(file_list) - call writefile([a:name], g:Lf_MruCacheFileName) - elseif a:name != file_list[0] - call filter(file_list, 'v:val != a:name') - call writefile([a:name] + file_list, g:Lf_MruCacheFileName) + let found = 0 + let i = 0 + for item in file_list + let t = split(item, ' ') + if t[2] ==# a:name + let found = 1 + let t[1] += 1 + let file_list[i] = printf("%s %s %s", localtime(), t[1], t[2]) + break + endif + let i += 1 + endfor + + if found == 0 + call add(file_list, printf("%s 1 %s", localtime(), a:name)) endif + + call writefile(file_list, g:Lf_MruCacheFileName) endfunction function! lfMru#recordBuffer(bufNum) diff --git a/doc/leaderf.txt b/doc/leaderf.txt index c91acc8d..bd71e5bc 100644 --- a/doc/leaderf.txt +++ b/doc/leaderf.txt @@ -1088,6 +1088,11 @@ g:Lf_MruEnable *g:Lf_MruEnable* Enable `Leaderf mru` or not. Default value is 1. +g:Lf_MruEnableFrecency *g:Lf_MruEnableFrecency* + This option specifies whether `Leaderf mru` uses frecency algorithm. + `--frecency` can override this option. + Default value is 0. + g:Lf_QuickSelect *g:Lf_QuickSelect* Enable or disable quick-select mode. If enabled, the characters [0-9] are not treated as literal characters, but are used to select the [0-9]th entry. 0 diff --git a/plugin/leaderf.vim b/plugin/leaderf.vim index 15b35443..556178ca 100644 --- a/plugin/leaderf.vim +++ b/plugin/leaderf.vim @@ -121,7 +121,7 @@ endfunction if get(g:, 'Lf_MruEnable', 1) == 1 augroup LeaderF_Mru - autocmd BufAdd,BufEnter,BufWritePost * call lfMru#record(s:Normalize(expand(':p'))) | + autocmd BufEnter,BufWritePost * call lfMru#record(s:Normalize(expand(':p'))) | \ call lfMru#recordBuffer(expand('')) augroup END endif From 044ac6ab2b172f5542d7c849ad10a1b9a65b9042 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 14 Sep 2023 13:47:15 +0800 Subject: [PATCH 127/365] some options should be set again in case modeline has changed them --- autoload/leaderf/python/leaderf/manager.py | 51 ++++++++++++---------- 1 file changed, 28 insertions(+), 23 deletions(-) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index c370659e..ceb6966d 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -477,17 +477,29 @@ def getArguments(self): #************************************************************** def _setWinOptions(self, winid): - lfCmd("call nvim_win_set_option(%d, 'number', v:true)" % winid) - lfCmd("call nvim_win_set_option(%d, 'relativenumber', v:false)" % winid) - lfCmd("call nvim_win_set_option(%d, 'cursorline', v:true)" % winid) - lfCmd("call nvim_win_set_option(%d, 'foldenable', v:false)" % winid) - lfCmd("call nvim_win_set_option(%d, 'foldmethod', 'manual')" % winid) - lfCmd("call nvim_win_set_option(%d, 'foldcolumn', '0')" % winid) - lfCmd("call nvim_win_set_option(%d, 'signcolumn', 'no')" % winid) - if lfEval("exists('+cursorlineopt')") == '1': - lfCmd("call nvim_win_set_option(%d, 'cursorlineopt', 'both')" % winid) - lfCmd("call nvim_win_set_option(%d, 'colorcolumn', '')" % winid) - lfCmd("call nvim_win_set_option(%d, 'winhighlight', 'Normal:Lf_hl_popup_window')" % winid) + if lfEval("has('nvim')") == '1': + lfCmd("call nvim_win_set_option(%d, 'number', v:true)" % winid) + lfCmd("call nvim_win_set_option(%d, 'relativenumber', v:false)" % winid) + lfCmd("call nvim_win_set_option(%d, 'cursorline', v:true)" % winid) + lfCmd("call nvim_win_set_option(%d, 'foldenable', v:false)" % winid) + lfCmd("call nvim_win_set_option(%d, 'foldmethod', 'manual')" % winid) + lfCmd("call nvim_win_set_option(%d, 'foldcolumn', '0')" % winid) + lfCmd("call nvim_win_set_option(%d, 'signcolumn', 'no')" % winid) + if lfEval("exists('+cursorlineopt')") == '1': + lfCmd("call nvim_win_set_option(%d, 'cursorlineopt', 'both')" % winid) + lfCmd("call nvim_win_set_option(%d, 'colorcolumn', '')" % winid) + lfCmd("call nvim_win_set_option(%d, 'winhighlight', 'Normal:Lf_hl_popup_window')" % winid) + else: + lfCmd("call win_execute(%d, 'setlocal number norelativenumber cursorline')" % winid) + lfCmd("call win_execute(%d, 'setlocal nofoldenable foldmethod=manual')" % winid) + if lfEval("get(g:, 'Lf_PopupShowFoldcolumn', 1)") == '0' or lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1': + lfCmd("call win_execute(%d, 'setlocal foldcolumn=0')" % winid) + else: + lfCmd("call win_execute(%d, 'setlocal foldcolumn=1')" % winid) + if lfEval("exists('+cursorlineopt')") == '1': + lfCmd("call win_execute(%d, 'setlocal cursorlineopt=both')" % winid) + lfCmd("call win_execute(%d, 'setlocal colorcolumn=')" % winid) + lfCmd("call win_execute(%d, 'setlocal wincolor=Lf_hl_popup_window')" % winid) def _createPreviewWindow(self, config, source, line_nr, jump_cmd): if lfEval("has('nvim')") == '1': @@ -509,8 +521,6 @@ def _createPreviewWindow(self, config, source, line_nr, jump_cmd): self._preview_winid = int(lfEval("nvim_open_win(g:Lf_preview_scratch_buffer, 0, %s)" % str(config))) - self._setWinOptions(self._preview_winid) - if jump_cmd: cur_winid = lfEval("win_getid()") lfCmd("noautocmd call win_gotoid(%d)" % self._preview_winid) @@ -525,6 +535,8 @@ def _createPreviewWindow(self, config, source, line_nr, jump_cmd): lfCmd("silent! doautocmd filetypedetect BufNewFile %s" % source) lfCmd("norm! zz") lfCmd("noautocmd call win_gotoid(%s)" % cur_winid) + + self._setWinOptions(self._preview_winid) self._preview_filetype = lfEval("getbufvar(winbufnr(%d), '&ft')" % self._preview_winid) else: if isinstance(source, int): @@ -539,21 +551,12 @@ def _createPreviewWindow(self, config, source, line_nr, jump_cmd): return lfCmd("noautocmd silent! let winid = popup_create(content, %s)" % json.dumps(config)) - lfCmd("call win_execute(winid, 'setlocal wincolor=Lf_hl_popup_window')") lfCmd("call win_execute(winid, 'setlocal modeline')") - lfCmd("call win_execute(winid, 'setlocal cursorline number norelativenumber colorcolumn=')") - lfCmd("call win_execute(winid, 'setlocal nofoldenable')") - lfCmd("call win_execute(winid, 'setlocal foldmethod=manual')") - if lfEval("exists('+cursorlineopt')") == '1': - lfCmd("call win_execute(winid, 'setlocal cursorlineopt=both')") - if lfEval("get(g:, 'Lf_PopupShowFoldcolumn', 1)") == '0' or lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1': - lfCmd("call win_execute(winid, 'setlocal foldcolumn=0')") - else: - lfCmd("call win_execute(winid, 'setlocal foldcolumn=1')") lfCmd("call win_execute(winid, 'silent! doautocmd filetypedetect BufNewFile %s')" % escQuote(filename)) self._preview_winid = int(lfEval("winid")) + self._setWinOptions(self._preview_winid) self._preview_filetype = lfEval("getbufvar(winbufnr(winid), '&ft')") if jump_cmd: @@ -856,6 +859,8 @@ def _useExistingWindow(self, title, source, line_nr, jump_cmd): lfCmd("call win_execute(%d, 'silent! doautocmd filetypedetect BufNewFile %s')" % (self._preview_winid, escQuote(filename))) self._preview_filetype = lfEval("getbufvar(winbufnr(%d), '&ft')" % self._preview_winid) + self._setWinOptions(self._preview_winid) + if jump_cmd: lfCmd("""call win_execute(%d, '%s')""" % (self._preview_winid, escQuote(jump_cmd))) lfCmd("call win_execute(%d, 'norm! zz')" % self._preview_winid) From 85bddb794fdfe007ebae92bd3410e0ff8363dcb4 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 14 Sep 2023 14:22:53 +0800 Subject: [PATCH 128/365] update code --- autoload/leaderf/python/leaderf/anyExpl.py | 30 ++--- autoload/leaderf/python/leaderf/bufTagExpl.py | 30 ++--- .../leaderf/python/leaderf/functionExpl.py | 20 +-- autoload/leaderf/python/leaderf/instance.py | 16 +-- autoload/leaderf/python/leaderf/lineExpl.py | 12 +- autoload/leaderf/python/leaderf/manager.py | 125 +++++++++--------- autoload/leaderf/python/leaderf/rgExpl.py | 4 +- autoload/leaderf/python/leaderf/tagExpl.py | 8 +- 8 files changed, 122 insertions(+), 123 deletions(-) diff --git a/autoload/leaderf/python/leaderf/anyExpl.py b/autoload/leaderf/python/leaderf/anyExpl.py index 800f173f..f39b7063 100644 --- a/autoload/leaderf/python/leaderf/anyExpl.py +++ b/autoload/leaderf/python/leaderf/anyExpl.py @@ -28,13 +28,13 @@ \ "format_list": funcref ([], arguments), \ "need_exit": funcref (line, arguments), \ "accept": funcref (line, arguments), - \ "preview": funcref (orig_buf_nr, orig_cursor, arguments), + \ "preview": funcref (orig_buf_num, orig_cursor, arguments), \ "supports_name_only": 0, \ "get_digest": funcref (line, mode), \ "before_enter": funcref (arguments), - \ "after_enter": funcref (orig_buf_nr, orig_cursor, arguments), - \ "bang_enter": funcref (orig_buf_nr, orig_cursor, arguments), - \ "before_exit": funcref (orig_buf_nr, orig_cursor, arguments), + \ "after_enter": funcref (orig_buf_num, orig_cursor, arguments), + \ "bang_enter": funcref (orig_buf_num, orig_cursor, arguments), + \ "before_exit": funcref (orig_buf_num, orig_cursor, arguments), \ "after_exit": funcref (arguments), \ "highlights_def": { \ "Lf_hl_apple": '^\s*\zs\d\+', @@ -275,15 +275,15 @@ def _afterEnter(self): super(AnyExplManager, self)._afterEnter() after_enter = self._config.get("after_enter") if after_enter: - orig_buf_nr = self._getInstance().getOriginalPos()[2].number + orig_buf_num = self._getInstance().getOriginalPos()[2].number line, col = self._getInstance().getOriginalCursor() try: if self._getInstance().getWinPos() == 'popup': lfCmd("""call win_execute(%d, "call %s(%d, [%d, %d], %s)")""" - % (self._getInstance().getPopupWinId(), after_enter, orig_buf_nr, line, col+1, str(self._arguments))) + % (self._getInstance().getPopupWinId(), after_enter, orig_buf_num, line, col+1, str(self._arguments))) else: after_enter = lfFunction(after_enter) - after_enter(orig_buf_nr, [line, col+1], self._arguments) + after_enter(orig_buf_num, [line, col+1], self._arguments) except vim.error as err: raise Exception("Error occurred in user defined %s: %s" % (str(after_enter), err)) @@ -321,15 +321,15 @@ def _bangEnter(self): super(AnyExplManager, self)._bangEnter() bang_enter = self._config.get("bang_enter") if bang_enter: - orig_buf_nr = self._getInstance().getOriginalPos()[2].number + orig_buf_num = self._getInstance().getOriginalPos()[2].number line, col = self._getInstance().getOriginalCursor() try: if self._getInstance().getWinPos() == 'popup': lfCmd("""call win_execute(%d, "call %s(%d, [%d, %d], %s)")""" - % (self._getInstance().getPopupWinId(), bang_enter, orig_buf_nr, line, col+1, str(self._arguments))) + % (self._getInstance().getPopupWinId(), bang_enter, orig_buf_num, line, col+1, str(self._arguments))) else: bang_enter = lfFunction(bang_enter) - bang_enter(orig_buf_nr, [line, col+1], self._arguments) + bang_enter(orig_buf_num, [line, col+1], self._arguments) except vim.error as err: raise Exception("Error occurred in user defined %s: %s" % (str(bang_enter), err)) @@ -337,15 +337,15 @@ def _beforeExit(self): super(AnyExplManager, self)._beforeExit() before_exit = self._config.get("before_exit") if before_exit: - orig_buf_nr = self._getInstance().getOriginalPos()[2].number + orig_buf_num = self._getInstance().getOriginalPos()[2].number line, col = self._getInstance().getOriginalCursor() try: if self._getInstance().getWinPos() == 'popup': lfCmd("""call win_execute(%d, "call %s(%d, [%d, %d], %s)")""" - % (self._getInstance().getPopupWinId(), before_exit, orig_buf_nr, line, col+1, str(self._arguments))) + % (self._getInstance().getPopupWinId(), before_exit, orig_buf_num, line, col+1, str(self._arguments))) else: before_exit = lfFunction(before_exit) - before_exit(orig_buf_nr, [line, col+1], self._arguments) + before_exit(orig_buf_num, [line, col+1], self._arguments) except vim.error as err: raise Exception("Error occurred in user defined %s: %s" % (str(before_exit), err)) @@ -371,11 +371,11 @@ def _previewInPopup(self, *args, **kwargs): preview = self._config.get("preview") if preview: - orig_buf_nr = self._getInstance().getOriginalPos()[2].number + orig_buf_num = self._getInstance().getOriginalPos()[2].number l, c = self._getInstance().getOriginalCursor() try: preview = lfFunction(preview) - result = preview(orig_buf_nr, [l, c+1], line, self._arguments) + result = preview(orig_buf_num, [l, c+1], line, self._arguments) if result: filename, line_num, jump_cmd = result # for backward compatibility diff --git a/autoload/leaderf/python/leaderf/bufTagExpl.py b/autoload/leaderf/python/leaderf/bufTagExpl.py index e6a1e5b6..c5149e2c 100644 --- a/autoload/leaderf/python/leaderf/bufTagExpl.py +++ b/autoload/leaderf/python/leaderf/bufTagExpl.py @@ -224,21 +224,21 @@ def _acceptSelection(self, *args, **kwargs): line = args[0] if line[0].isspace(): # if g:Lf_PreviewCode == 1 buffer = args[1] - line_nr = args[2] + line_num = args[2] if self._getInstance().isReverseOrder(): - line = buffer[line_nr] + line = buffer[line_num] else: - line = buffer[line_nr - 2] + line = buffer[line_num - 2] # {tag} {kind} {scope} {file}:{line} {buf_number} items = re.split(" *\t *", line) tagname = items[0] - line_nr = items[3].rsplit(":", 1)[1] + line_num = items[3].rsplit(":", 1)[1] buf_number = items[4] if kwargs.get("mode", '') == 't': buf_name = lfEval("bufname(%s)" % buf_number) - lfDrop('tab', buf_name, line_nr) + lfDrop('tab', buf_name, line_num) else: - lfCmd("hide buffer +%s %s" % (line_nr, buf_number)) + lfCmd("hide buffer +%s %s" % (line_num, buf_number)) if "preview" not in kwargs: lfCmd("norm! ^") lfCmd("call search('\V%s', 'Wc', line('.'))" % escQuote(tagname)) @@ -494,7 +494,7 @@ def _relocateCursor(self): inst = self._getInstance() if inst.empty(): return - orig_buf_nr = inst.getOriginalPos()[2].number + orig_buf_num = inst.getOriginalPos()[2].number orig_line = inst.getOriginalCursor()[0] tags = [] for index, line in enumerate(inst.buffer, 1): @@ -505,10 +505,10 @@ def _relocateCursor(self): elif index & 1 == 0: continue items = re.split(" *\t *", line) - line_nr = int(items[3].rsplit(":", 1)[1]) + line_num = int(items[3].rsplit(":", 1)[1]) buf_number = int(items[4]) - if orig_buf_nr == buf_number: - tags.append((index, buf_number, line_nr)) + if orig_buf_num == buf_number: + tags.append((index, buf_number, line_num)) if self._getInstance().isReverseOrder(): tags = tags[::-1] @@ -542,18 +542,18 @@ def _previewInPopup(self, *args, **kwargs): line = args[0] if line[0].isspace(): # if g:Lf_PreviewCode == 1 buffer = args[1] - line_nr = args[2] + line_num = args[2] if self._getInstance().isReverseOrder(): - line = buffer[line_nr] + line = buffer[line_num] else: - line = buffer[line_nr - 2] + line = buffer[line_num - 2] # {tag} {kind} {scope} {file}:{line} {buf_number} items = re.split(" *\t *", line) tagname = items[0] - line_nr = items[3].rsplit(":", 1)[1] + line_num = items[3].rsplit(":", 1)[1] buf_number = int(items[4]) - self._createPopupPreview(tagname, buf_number, line_nr) + self._createPopupPreview(tagname, buf_number, line_num) #***************************************************** diff --git a/autoload/leaderf/python/leaderf/functionExpl.py b/autoload/leaderf/python/leaderf/functionExpl.py index 36096894..4082dcf5 100644 --- a/autoload/leaderf/python/leaderf/functionExpl.py +++ b/autoload/leaderf/python/leaderf/functionExpl.py @@ -220,12 +220,12 @@ def _acceptSelection(self, *args, **kwargs): line = args[0] # {kind} {code} {file} {line} line = line.rsplit("\t", 1)[1][1:-1] # file:line buf_number - line_nr, buf_number = line.rsplit(":", 1)[1].split() + line_num, buf_number = line.rsplit(":", 1)[1].split() if kwargs.get("mode", '') == 't': buf_name = lfEval("bufname(%s)" % buf_number) - lfDrop('tab', buf_name, line_nr) + lfDrop('tab', buf_name, line_num) else: - lfCmd("hide buffer +%s %s" % (line_nr, buf_number)) + lfCmd("hide buffer +%s %s" % (line_num, buf_number)) lfCmd("norm! ^zv") lfCmd("norm! zz") @@ -367,15 +367,15 @@ def _relocateCursor(self): inst = self._getInstance() if inst.empty(): return - orig_buf_nr = inst.getOriginalPos()[2].number + orig_buf_num = inst.getOriginalPos()[2].number orig_line = inst.getOriginalCursor()[0] tags = [] for index, line in enumerate(inst.buffer, 1): line = line.rsplit("\t", 1)[1][1:-1] - line_nr, buf_number = line.rsplit(":", 1)[1].split() - line_nr, buf_number = int(line_nr), int(buf_number) - if orig_buf_nr == buf_number: - tags.append((index, buf_number, line_nr)) + line_num, buf_number = line.rsplit(":", 1)[1].split() + line_num, buf_number = int(line_num), int(buf_number) + if orig_buf_num == buf_number: + tags.append((index, buf_number, line_num)) if self._getInstance().isReverseOrder(): tags = tags[::-1] @@ -409,10 +409,10 @@ def _previewInPopup(self, *args, **kwargs): line = args[0] # {kind} {code} {file} {line} line = line.rsplit("\t", 1)[1][1:-1] # file:line buf_number - line_nr, buf_number = line.rsplit(":", 1)[1].split() + line_num, buf_number = line.rsplit(":", 1)[1].split() buf_number = int(buf_number) - self._createPopupPreview("", buf_number, line_nr) + self._createPopupPreview("", buf_number, line_num) #***************************************************** diff --git a/autoload/leaderf/python/leaderf/instance.py b/autoload/leaderf/python/leaderf/instance.py index ade9ae9e..f38128cd 100644 --- a/autoload/leaderf/python/leaderf/instance.py +++ b/autoload/leaderf/python/leaderf/instance.py @@ -1102,8 +1102,8 @@ def enterBuffer(self, win_pos, clear): lfCmd("let g:lf_t_ve_stack = []") lfCmd("call add(g:lf_t_ve_stack, &t_ve)") lfCmd("set t_ve=") - self._orig_win_nr = vim.current.window.number - self._orig_win_id = lfWinId(self._orig_win_nr) + self._orig_win_num = vim.current.window.number + self._orig_win_id = lfWinId(self._orig_win_num) self._createPopupWindow() self._arguments["popup_winid"] = self._popup_winid elif win_pos == 'fullScreen': @@ -1112,8 +1112,8 @@ def enterBuffer(self, win_pos, clear): lfCmd("set showtabline=0") self._createBufWindow(win_pos) else: - self._orig_win_nr = vim.current.window.number - self._orig_win_id = lfWinId(self._orig_win_nr) + self._orig_win_num = vim.current.window.number + self._orig_win_id = lfWinId(self._orig_win_num) self._createBufWindow(win_pos) if not self._is_icon_colorscheme_autocmd_set: @@ -1178,7 +1178,7 @@ def exitBuffer(self): lfCmd("call win_gotoid(%d)" % self._orig_win_id) else: # 'silent!' is used to skip error E16. - lfCmd("silent! exec '%d wincmd w'" % self._orig_win_nr) + lfCmd("silent! exec '%d wincmd w'" % self._orig_win_num) if lfEval("get(g:, 'Lf_VimResized', 0)") == '0' \ and self._orig_win_count == len(vim.windows): lfCmd(self._restore_sizes) # why this line does not take effect? @@ -1492,8 +1492,8 @@ def isLastReverseOrder(self): def setLineNumber(self): if self._reverse_order: - line_nr = 1 + len(self._buffer_object) - self._window_object.cursor[0] - lfCmd("let g:Lf_{}_StlLineNumber = '{}'".format(self._category, line_nr)) + line_num = 1 + len(self._buffer_object) - self._window_object.cursor[0] + lfCmd("let g:Lf_{}_StlLineNumber = '{}'".format(self._category, line_num)) def setCwd(self, cwd): self._current_working_directory = cwd @@ -1522,7 +1522,7 @@ def gotoOriginalWindow(self): lfCmd("keepj call win_gotoid(%d)" % self._orig_win_id) else: # 'silent!' is used to skip error E16. - lfCmd("keepj silent! exec '%d wincmd w'" % self._orig_win_nr) + lfCmd("keepj silent! exec '%d wincmd w'" % self._orig_win_num) def getWinPos(self): return self._win_pos diff --git a/autoload/leaderf/python/leaderf/lineExpl.py b/autoload/leaderf/python/leaderf/lineExpl.py index 0b9a136c..1d0efb0a 100644 --- a/autoload/leaderf/python/leaderf/lineExpl.py +++ b/autoload/leaderf/python/leaderf/lineExpl.py @@ -65,8 +65,8 @@ def _acceptSelection(self, *args, **kwargs): return line = args[0] line = line.rsplit("\t", 1)[1][1:-1] # file:line buf_number - line_nr, buf_number = line.rsplit(":", 1)[1].split() - lfCmd("hide buffer +%s %s" % (line_nr, buf_number)) + line_num, buf_number = line.rsplit(":", 1)[1].split() + lfCmd("hide buffer +%s %s" % (line_num, buf_number)) lfCmd("norm! ^zv") lfCmd("norm! zz") @@ -136,9 +136,9 @@ def _previewInPopup(self, *args, **kwargs): line = args[0] line = line.rsplit("\t", 1)[1][1:-1] # file:line buf_number - line_nr, buf_number = line.rsplit(":", 1)[1].split() + line_num, buf_number = line.rsplit(":", 1)[1].split() buf_number = int(buf_number) - self._createPopupPreview(vim.buffers[int(buf_number)].name, buf_number, line_nr) + self._createPopupPreview(vim.buffers[int(buf_number)].name, buf_number, line_num) def outputToQflist(self, *args, **kwargs): items = self._getFormatedContents() @@ -156,10 +156,10 @@ def _getFormatedContents(self): for line in self._instance._buffer_object[self._help_length:]: text, info = line.rsplit("\t", 1) info = info[1:-1] # file:line buf_number - line_nr, buf_number = info.rsplit(":", 1)[1].split() + line_num, buf_number = info.rsplit(":", 1)[1].split() items.append({ "filename": lfEval("getbufinfo(%d)[0]['name']" % int(buf_number)), - "lnum": line_nr, + "lnum": line_num, "col": 1, "text": text, }) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index ceb6966d..4beeedf0 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -424,11 +424,11 @@ def _previewResult(self, preview): self._closePreviewPopup() return - line_nr = self._getInstance().window.cursor[0] - line = self._getInstance().buffer[line_nr - 1] + line_num = self._getInstance().window.cursor[0] + line = self._getInstance().buffer[line_num - 1] if preview_in_popup: - self._previewInPopup(line, self._getInstance().buffer, line_nr) + self._previewInPopup(line, self._getInstance().buffer, line_num) return orig_pos = self._getInstance().getOriginalPos() @@ -438,8 +438,8 @@ def _previewResult(self, preview): vim.options['eventignore'] = 'BufLeave,WinEnter,BufEnter' try: vim.current.tabpage, vim.current.window = orig_pos[:2] - line_nr = self._getInstance().window.cursor[0] - self._acceptSelection(line, self._getInstance().buffer, line_nr, preview=True) + line_num = self._getInstance().window.cursor[0] + self._acceptSelection(line, self._getInstance().buffer, line_num, preview=True) lfCmd("augroup Lf_Cursorline") lfCmd("autocmd! BufwinEnter setlocal cursorline<") lfCmd("augroup END") @@ -501,7 +501,7 @@ def _setWinOptions(self, winid): lfCmd("call win_execute(%d, 'setlocal colorcolumn=')" % winid) lfCmd("call win_execute(%d, 'setlocal wincolor=Lf_hl_popup_window')" % winid) - def _createPreviewWindow(self, config, source, line_nr, jump_cmd): + def _createPreviewWindow(self, config, source, line_num, jump_cmd): if lfEval("has('nvim')") == '1': if isinstance(source, int): buffer_len = len(vim.buffers[source]) @@ -521,23 +521,22 @@ def _createPreviewWindow(self, config, source, line_nr, jump_cmd): self._preview_winid = int(lfEval("nvim_open_win(g:Lf_preview_scratch_buffer, 0, %s)" % str(config))) - if jump_cmd: - cur_winid = lfEval("win_getid()") - lfCmd("noautocmd call win_gotoid(%d)" % self._preview_winid) - lfCmd(jump_cmd) - lfCmd("noautocmd call win_gotoid(%s)" % cur_winid) - if buffer_len >= line_nr > 0: - lfCmd("""call nvim_win_set_cursor(%d, [%d, 1])""" % (self._preview_winid, line_nr)) - cur_winid = lfEval("win_getid()") lfCmd("noautocmd call win_gotoid(%d)" % self._preview_winid) if not isinstance(source, int): lfCmd("silent! doautocmd filetypedetect BufNewFile %s" % source) - lfCmd("norm! zz") lfCmd("noautocmd call win_gotoid(%s)" % cur_winid) self._setWinOptions(self._preview_winid) self._preview_filetype = lfEval("getbufvar(winbufnr(%d), '&ft')" % self._preview_winid) + + lfCmd("noautocmd call win_gotoid(%d)" % self._preview_winid) + if jump_cmd: + lfCmd(jump_cmd) + if buffer_len >= line_num > 0: + lfCmd("""call nvim_win_set_cursor(%d, [%d, 1])""" % (self._preview_winid, line_num)) + lfCmd("norm! zz") + lfCmd("noautocmd call win_gotoid(%s)" % cur_winid) else: if isinstance(source, int): lfCmd("let content = getbufline(%d, 1, '$')" % source) @@ -562,12 +561,12 @@ def _createPreviewWindow(self, config, source, line_nr, jump_cmd): if jump_cmd: lfCmd("""call win_execute(%d, '%s')""" % (self._preview_winid, escQuote(jump_cmd))) lfCmd("call win_execute(%d, 'norm! zz')" % self._preview_winid) - elif line_nr > 0: - lfCmd("""call win_execute(%d, "call cursor(%d, 1)")""" % (self._preview_winid, line_nr)) + elif line_num > 0: + lfCmd("""call win_execute(%d, "call cursor(%d, 1)")""" % (self._preview_winid, line_num)) lfCmd("call win_execute(%d, 'norm! zz')" % self._preview_winid) @ignoreEvent('BufWinEnter,BufEnter') - def _createPopupModePreview(self, title, source, line_nr, jump_cmd): + def _createPopupModePreview(self, title, source, line_num, jump_cmd): """ Args: source: @@ -692,7 +691,7 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): config["title"] = " Preview " config["title_pos"] = "center" - self._createPreviewWindow(config, source, line_nr, jump_cmd) + self._createPreviewWindow(config, source, line_num, jump_cmd) lfCmd("let g:Lf_PreviewWindowID[%d] = %d" % (id(self), self._preview_winid)) else: popup_window = self._getInstance().window @@ -812,13 +811,13 @@ def _createPopupModePreview(self, title, source, line_nr, jump_cmd): options["maxheight"] = maxheight options["minheight"] = maxheight - self._createPreviewWindow(options, source, line_nr, jump_cmd) + self._createPreviewWindow(options, source, line_num, jump_cmd) def isPreviewWindowOpen(self): return self._preview_winid > 0 and int(lfEval("winbufnr(%d)" % self._preview_winid)) != -1 - def _useExistingWindow(self, title, source, line_nr, jump_cmd): + def _useExistingWindow(self, title, source, line_num, jump_cmd): if lfEval("has('nvim')") == '1': if isinstance(source, int): lfCmd("noautocmd call nvim_win_set_buf(%d, %d)" % (self._preview_winid, source)) @@ -864,14 +863,14 @@ def _useExistingWindow(self, title, source, line_nr, jump_cmd): if jump_cmd: lfCmd("""call win_execute(%d, '%s')""" % (self._preview_winid, escQuote(jump_cmd))) lfCmd("call win_execute(%d, 'norm! zz')" % self._preview_winid) - elif line_nr > 0: - lfCmd("""call win_execute(%d, "call cursor(%d, 1)")""" % (self._preview_winid, line_nr)) + elif line_num > 0: + lfCmd("""call win_execute(%d, "call cursor(%d, 1)")""" % (self._preview_winid, line_num)) lfCmd("call win_execute(%d, 'norm! zz')" % self._preview_winid) else: lfCmd("call win_execute(%d, 'norm! gg')" % self._preview_winid) @ignoreEvent('BufRead,BufReadPre,BufReadPost') - def _createPopupPreview(self, title, source, line_nr, jump_cmd=''): + def _createPopupPreview(self, title, source, line_num, jump_cmd=''): """ Args: source: @@ -881,14 +880,14 @@ def _createPopupPreview(self, title, source, line_nr, jump_cmd=''): return False if use existing window, otherwise True """ self._is_previewed = True - line_nr = int(line_nr) + line_num = int(line_num) if self.isPreviewWindowOpen(): - self._useExistingWindow(title, source, line_nr, jump_cmd) + self._useExistingWindow(title, source, line_num, jump_cmd) return False if self._getInstance().getWinPos() in ('popup', 'floatwin'): - self._createPopupModePreview(title, source, line_nr, jump_cmd) + self._createPopupModePreview(title, source, line_num, jump_cmd) return True win_pos = self._getInstance().getWinPos() @@ -998,7 +997,7 @@ def _createPopupPreview(self, title, source, line_nr, jump_cmd=''): config["title"] = " Preview " config["title_pos"] = "center" - self._createPreviewWindow(config, source, line_nr, jump_cmd) + self._createPreviewWindow(config, source, line_num, jump_cmd) else: if win_pos == 'bottom': if preview_pos.lower() == 'topleft': @@ -1088,7 +1087,7 @@ def _createPopupPreview(self, title, source, line_nr, jump_cmd=''): options["minheight"] -= 1 options["borderhighlight"] = ["Lf_hl_popupBorder"] - self._createPreviewWindow(options, source, line_nr, jump_cmd) + self._createPreviewWindow(options, source, line_num, jump_cmd) return True @@ -2259,7 +2258,7 @@ def accept(self, mode=''): need_exit = True else: file = self._getInstance().currentLine - line_nr = self._getInstance().window.cursor[0] + line_num = self._getInstance().window.cursor[0] need_exit = self._needExit(file, self._arguments) if need_exit: if "--stayOpen" in self._arguments: @@ -2281,7 +2280,7 @@ def accept(self, mode=''): chdir(cwd) orig_cwd = lfGetCwd() - self._accept(file, mode, self._getInstance().buffer, line_nr) # for bufTag + self._accept(file, mode, self._getInstance().buffer, line_num) # for bufTag if lfGetCwd() != orig_cwd: dir_changed_by_autocmd = True else: @@ -2313,20 +2312,20 @@ def _jumpNext(self): instance.window.options["cursorline"] = True instance.gotoOriginalWindow() - line_nr = self._getInstance().window.cursor[0] - self._accept(instance.buffer[instance.window.cursor[0] - 1], "", self._getInstance().buffer, line_nr) + line_num = self._getInstance().window.cursor[0] + self._accept(instance.buffer[instance.window.cursor[0] - 1], "", self._getInstance().buffer, line_num) else: if instance.cursorRow > len(instance.buffer) - instance.helpLength: instance.cursorRow = len(instance.buffer) - instance.helpLength - line_nr = instance.cursorRow + line_num = instance.cursorRow elif instance.cursorRow == 1: # at the last line - line_nr = instance.cursorRow + line_num = instance.cursorRow instance.cursorRow = len(instance.buffer) - instance.helpLength else: - line_nr = instance.cursorRow + line_num = instance.cursorRow instance.cursorRow -= 1 - self._accept(instance.buffer[instance.cursorRow - 1], "", self._getInstance().buffer, line_nr) + self._accept(instance.buffer[instance.cursorRow - 1], "", self._getInstance().buffer, line_num) lfCmd("echohl WarningMsg | redraw | echo ' (%d of %d)' | echohl NONE" % (len(instance.buffer) - instance.cursorRow - instance.helpLength + 1, len(instance.buffer) - instance.helpLength)) @@ -2341,20 +2340,20 @@ def _jumpNext(self): instance.window.options["cursorline"] = True instance.gotoOriginalWindow() - line_nr = self._getInstance().window.cursor[0] - self._accept(instance.buffer[instance.window.cursor[0] - 1], "", self._getInstance().buffer, line_nr) + line_num = self._getInstance().window.cursor[0] + self._accept(instance.buffer[instance.window.cursor[0] - 1], "", self._getInstance().buffer, line_num) else: if instance.cursorRow <= instance.helpLength: instance.cursorRow = instance.helpLength + 1 - line_nr = instance.cursorRow + line_num = instance.cursorRow elif instance.cursorRow == len(instance.buffer): # at the last line - line_nr = instance.cursorRow + line_num = instance.cursorRow instance.cursorRow = instance.helpLength + 1 else: - line_nr = instance.cursorRow + line_num = instance.cursorRow instance.cursorRow += 1 - self._accept(instance.buffer[instance.cursorRow - 1], "", self._getInstance().buffer, line_nr) + self._accept(instance.buffer[instance.cursorRow - 1], "", self._getInstance().buffer, line_num) lfCmd("echohl WarningMsg | redraw | echo ' (%d of %d)' | echohl NONE" % \ (instance.cursorRow - instance.helpLength, len(instance.buffer) - instance.helpLength)) @@ -2374,17 +2373,17 @@ def _jumpPrevious(self): instance.window.options["cursorline"] = True instance.gotoOriginalWindow() - line_nr = self._getInstance().window.cursor[0] - self._accept(instance.buffer[instance.window.cursor[0] - 1], "", self._getInstance().buffer, line_nr) + line_num = self._getInstance().window.cursor[0] + self._accept(instance.buffer[instance.window.cursor[0] - 1], "", self._getInstance().buffer, line_num) else: if instance.cursorRow >= len(instance.buffer) - instance.helpLength: instance.cursorRow = 1 - line_nr = instance.cursorRow + line_num = instance.cursorRow else: - line_nr = instance.cursorRow + line_num = instance.cursorRow instance.cursorRow += 1 - self._accept(instance.buffer[instance.cursorRow - 1], "", self._getInstance().buffer, line_nr) + self._accept(instance.buffer[instance.cursorRow - 1], "", self._getInstance().buffer, line_num) lfCmd("echohl WarningMsg | redraw | echo ' (%d of %d)' | echohl NONE" % (len(instance.buffer) - instance.cursorRow - instance.helpLength + 1, len(instance.buffer) - instance.helpLength)) @@ -2397,17 +2396,17 @@ def _jumpPrevious(self): instance.window.options["cursorline"] = True instance.gotoOriginalWindow() - line_nr = self._getInstance().window.cursor[0] - self._accept(instance.buffer[instance.window.cursor[0] - 1], "", self._getInstance().buffer, line_nr) + line_num = self._getInstance().window.cursor[0] + self._accept(instance.buffer[instance.window.cursor[0] - 1], "", self._getInstance().buffer, line_num) else: if instance.cursorRow <= instance.helpLength + 1: instance.cursorRow = len(instance.buffer) - line_nr = instance.cursorRow + line_num = instance.cursorRow else: - line_nr = instance.cursorRow + line_num = instance.cursorRow instance.cursorRow -= 1 - self._accept(instance.buffer[instance.cursorRow - 1], "", self._getInstance().buffer, line_nr) + self._accept(instance.buffer[instance.cursorRow - 1], "", self._getInstance().buffer, line_num) lfCmd("echohl WarningMsg | redraw | echo ' (%d of %d)' | echohl NONE" % \ (instance.cursorRow - instance.helpLength, len(instance.buffer) - instance.helpLength)) @@ -2453,13 +2452,13 @@ def addSelections(self): lfCmd("exec v:mouse_lnum") lfCmd("exec 'norm!'.v:mouse_col.'|'") - line_nr = self._getInstance().window.cursor[0] + line_num = self._getInstance().window.cursor[0] if self._getInstance().isReverseOrder(): - if line_nr > len(self._getInstance().buffer) - self._help_length: + if line_num > len(self._getInstance().buffer) - self._help_length: lfCmd("norm! k") return else: - if line_nr <= self._help_length: + if line_num <= self._help_length: if self._getInstance().getWinPos() == 'popup': lfCmd("call win_execute({}, 'norm! j')".format(self._getInstance().getPopupWinId())) else: @@ -2470,20 +2469,20 @@ def addSelections(self): return - if line_nr in self._selections: + if line_num in self._selections: if self._getInstance().getWinPos() == 'popup': - lfCmd("call matchdelete(%d, %d)" % (self._selections[line_nr], self._getInstance().getPopupWinId())) + lfCmd("call matchdelete(%d, %d)" % (self._selections[line_num], self._getInstance().getPopupWinId())) else: - lfCmd("call matchdelete(%d)" % self._selections[line_nr]) - del self._selections[line_nr] + lfCmd("call matchdelete(%d)" % self._selections[line_num]) + del self._selections[line_num] else: if self._getInstance().getWinPos() == 'popup': lfCmd("""call win_execute(%d, "let matchid = matchadd('Lf_hl_selection', '\\\\%%%dl.')")""" - % (self._getInstance().getPopupWinId(), line_nr)) + % (self._getInstance().getPopupWinId(), line_num)) id = int(lfEval("matchid")) else: - id = int(lfEval("matchadd('Lf_hl_selection', '\%%%dl.')" % line_nr)) - self._selections[line_nr] = id + id = int(lfEval("matchadd('Lf_hl_selection', '\%%%dl.')" % line_num)) + self._selections[line_num] = id def selectMulti(self): orig_line = self._getInstance().window.cursor[0] diff --git a/autoload/leaderf/python/leaderf/rgExpl.py b/autoload/leaderf/python/leaderf/rgExpl.py index 9e77c59c..99ccf287 100644 --- a/autoload/leaderf/python/leaderf/rgExpl.py +++ b/autoload/leaderf/python/leaderf/rgExpl.py @@ -1146,7 +1146,7 @@ def _highlightInPreview(self): pass lfCmd("noautocmd call win_gotoid(%s)" % cur_winid) - def _createPopupPreview(self, title, source, line_nr, jump_cmd=''): + def _createPopupPreview(self, title, source, line_num, jump_cmd=''): """ Args: source: @@ -1156,7 +1156,7 @@ def _createPopupPreview(self, title, source, line_nr, jump_cmd=''): return False if use existing window, otherwise True """ - if (super(RgExplManager, self)._createPopupPreview(title, source, line_nr, jump_cmd) + if (super(RgExplManager, self)._createPopupPreview(title, source, line_num, jump_cmd) and lfEval("get(g:, 'Lf_RgHighlightInPreview', 1)") == '1'): self._highlightInPreview() diff --git a/autoload/leaderf/python/leaderf/tagExpl.py b/autoload/leaderf/python/leaderf/tagExpl.py index e768936b..97d95139 100644 --- a/autoload/leaderf/python/leaderf/tagExpl.py +++ b/autoload/leaderf/python/leaderf/tagExpl.py @@ -100,8 +100,8 @@ def _acceptSelection(self, *args, **kwargs): if len(res) > 1: result = re.search('(?<=\t)line:\d+', res[1]) if result: - line_nr = result.group(0).split(':')[1] - lfCmd(line_nr) + line_num = result.group(0).split(':')[1] + lfCmd(line_num) else: # for c, c++ keyword = "(class|enum|struct|union)" result = re.search('(?<=\t)%s:\S+' % keyword, res[1]) @@ -225,8 +225,8 @@ def _previewInPopup(self, *args, **kwargs): if len(res) > 1: result = re.search('(?<=\t)line:\d+', res[1]) if result: - line_nr = result.group(0).split(':')[1] - self._createPopupPreview("", tagfile, line_nr) + line_num = result.group(0).split(':')[1] + self._createPopupPreview("", tagfile, line_num) else: # for c, c++ keyword = "(class|enum|struct|union)" result = re.search('(?<=\t)%s:\S+' % keyword, res[1]) From 27be0e9ba72141f643ff4b752b093fee86074b12 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 14 Sep 2023 17:27:29 +0800 Subject: [PATCH 129/365] detect binary file --- autoload/leaderf/python/leaderf/manager.py | 35 +++++++++++++++++++--- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 4beeedf0..f5a576b6 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -508,7 +508,10 @@ def _createPreviewWindow(self, config, source, line_num, jump_cmd): self._preview_winid = int(lfEval("nvim_open_win(%d, 0, %s)" % (source, str(config)))) else: try: - lfCmd("let content = readfile('%s', '', 4096)" % escQuote(source)) + if self._isBinaryFile(source): + lfCmd("""let content = map(range(128), '"^@"')""") + else: + lfCmd("let content = readfile('%s', '', 4096)" % escQuote(source)) except vim.error as e: lfPrintError(e) return @@ -544,7 +547,10 @@ def _createPreviewWindow(self, config, source, line_num, jump_cmd): else: filename = source try: - lfCmd("let content = readfile('%s', '', 4096)" % escQuote(source)) + if self._isBinaryFile(filename): + lfCmd("""let content = map(range(128), '"^@"')""") + else: + lfCmd("let content = readfile('%s', '', 4096)" % escQuote(filename)) except vim.error as e: lfPrintError(e) return @@ -817,6 +823,21 @@ def _createPopupModePreview(self, title, source, line_num, jump_cmd): def isPreviewWindowOpen(self): return self._preview_winid > 0 and int(lfEval("winbufnr(%d)" % self._preview_winid)) != -1 + def _isBinaryFile(self, filename): + try: + is_binary = False + with lfOpen(filename, 'r', encoding='utf-8', errors='ignore') as f: + data = f.read(128) + for i in data: + if i == '\0': + is_binary = True + break + + return is_binary + except Exception as e: + lfPrintError(e) + return True + def _useExistingWindow(self, title, source, line_num, jump_cmd): if lfEval("has('nvim')") == '1': if isinstance(source, int): @@ -825,7 +846,10 @@ def _useExistingWindow(self, title, source, line_num, jump_cmd): self._preview_filetype = '' else: try: - lfCmd("let content = readfile('%s', '', 4096)" % escQuote(source)) + if self._isBinaryFile(source): + lfCmd("""let content = map(range(128), '"^@"')""") + else: + lfCmd("let content = readfile('%s', '', 4096)" % escQuote(source)) except vim.error as e: lfPrintError(e) return @@ -847,7 +871,10 @@ def _useExistingWindow(self, title, source, line_num, jump_cmd): else: filename = source try: - lfCmd("let content = readfile('%s', '', 4096)" % escQuote(filename)) + if self._isBinaryFile(filename): + lfCmd("""let content = map(range(128), '"^@"')""") + else: + lfCmd("let content = readfile('%s', '', 4096)" % escQuote(filename)) except vim.error as e: lfPrintError(e) return From 31f8fb269ac284b2b75cbea300027f11ab820d2c Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Fri, 15 Sep 2023 10:38:07 +0800 Subject: [PATCH 130/365] fix FileNotFoundError --- autoload/leaderf/python/leaderf/mruExpl.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/autoload/leaderf/python/leaderf/mruExpl.py b/autoload/leaderf/python/leaderf/mruExpl.py index fe5a2777..cb0f1963 100644 --- a/autoload/leaderf/python/leaderf/mruExpl.py +++ b/autoload/leaderf/python/leaderf/mruExpl.py @@ -63,11 +63,14 @@ def getContent(self, *args, **kwargs): if len(data_list) == 0: # import old data - with lfOpen(mru.getOldCacheFileName(), 'r+', errors='ignore', encoding='utf8') as old_f: - current_time = time.time() - data_list = [[int(current_time), 1, filename] for filename in old_f.readlines() - if os.path.exists(lfDecode(filename.rstrip())) - ] + try: + with lfOpen(mru.getOldCacheFileName(), 'r+', errors='ignore', encoding='utf8') as old_f: + current_time = time.time() + data_list = [[int(current_time), 1, filename] for filename in old_f.readlines() + if os.path.exists(lfDecode(filename.rstrip())) + ] + except FileNotFoundError: + pass arguments_dict = kwargs.get("arguments", {}) if "--frecency" in arguments_dict or lfEval("get(g:, 'Lf_MruEnableFrecency', 0)") == '1': From eeacb5b7bce21a0bf1d9604d386c27bdc44c7e6d Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Fri, 15 Sep 2023 11:05:06 +0800 Subject: [PATCH 131/365] fix issue #1031 --- autoload/leaderf/python/leaderf/anyExpl.py | 3 +++ autoload/leaderf/python/leaderf/bufExpl.py | 5 +++-- autoload/leaderf/python/leaderf/bufTagExpl.py | 2 +- autoload/leaderf/python/leaderf/fileExpl.py | 3 +++ autoload/leaderf/python/leaderf/functionExpl.py | 2 +- autoload/leaderf/python/leaderf/gtagsExpl.py | 2 +- autoload/leaderf/python/leaderf/helpExpl.py | 2 +- autoload/leaderf/python/leaderf/jumpsExpl.py | 3 ++- autoload/leaderf/python/leaderf/lineExpl.py | 2 +- autoload/leaderf/python/leaderf/mruExpl.py | 2 +- autoload/leaderf/python/leaderf/qfloclistExpl.py | 2 +- autoload/leaderf/python/leaderf/rgExpl.py | 2 +- autoload/leaderf/python/leaderf/tagExpl.py | 3 ++- 13 files changed, 21 insertions(+), 12 deletions(-) diff --git a/autoload/leaderf/python/leaderf/anyExpl.py b/autoload/leaderf/python/leaderf/anyExpl.py index f39b7063..9a4a9567 100644 --- a/autoload/leaderf/python/leaderf/anyExpl.py +++ b/autoload/leaderf/python/leaderf/anyExpl.py @@ -367,6 +367,9 @@ def startExplorer(self, win_pos, *args, **kwargs): super(AnyExplManager, self).startExplorer(win_pos, *args, **kwargs) def _previewInPopup(self, *args, **kwargs): + if len(args) == 0 or args[0] == '': + return + line = args[0] preview = self._config.get("preview") diff --git a/autoload/leaderf/python/leaderf/bufExpl.py b/autoload/leaderf/python/leaderf/bufExpl.py index 7ac3e071..dee2e5b3 100644 --- a/autoload/leaderf/python/leaderf/bufExpl.py +++ b/autoload/leaderf/python/leaderf/bufExpl.py @@ -289,9 +289,10 @@ def deleteBuffer(self, wipe=0): lfCmd("setlocal nomodifiable") def _previewInPopup(self, *args, **kwargs): - line = args[0] - if line == '': + if len(args) == 0 or args[0] == '': return + + line = args[0] buf_number = int(re.sub(r"^.*?(\d+).*$", r"\1", line)) if lfEval("bufloaded(%d)" % buf_number) == '0': lfCmd("silent call bufload(%d)" % buf_number) diff --git a/autoload/leaderf/python/leaderf/bufTagExpl.py b/autoload/leaderf/python/leaderf/bufTagExpl.py index c5149e2c..e4254ce5 100644 --- a/autoload/leaderf/python/leaderf/bufTagExpl.py +++ b/autoload/leaderf/python/leaderf/bufTagExpl.py @@ -536,7 +536,7 @@ def _relocateCursor(self): lfCmd("norm! zz") def _previewInPopup(self, *args, **kwargs): - if len(args) == 0: + if len(args) == 0 or args[0] == '': return line = args[0] diff --git a/autoload/leaderf/python/leaderf/fileExpl.py b/autoload/leaderf/python/leaderf/fileExpl.py index 013f692c..17f379e3 100644 --- a/autoload/leaderf/python/leaderf/fileExpl.py +++ b/autoload/leaderf/python/leaderf/fileExpl.py @@ -828,6 +828,9 @@ def startExplorer(self, win_pos, *args, **kwargs): @removeDevIcons def _previewInPopup(self, *args, **kwargs): + if len(args) == 0 or args[0] == '': + return + line = args[0] if not os.path.isabs(line): if self._getExplorer()._cmd_work_dir: diff --git a/autoload/leaderf/python/leaderf/functionExpl.py b/autoload/leaderf/python/leaderf/functionExpl.py index 4082dcf5..c2e6fea1 100644 --- a/autoload/leaderf/python/leaderf/functionExpl.py +++ b/autoload/leaderf/python/leaderf/functionExpl.py @@ -403,7 +403,7 @@ def _relocateCursor(self): lfCmd("norm! zz") def _previewInPopup(self, *args, **kwargs): - if len(args) == 0: + if len(args) == 0 or args[0] == '': return line = args[0] diff --git a/autoload/leaderf/python/leaderf/gtagsExpl.py b/autoload/leaderf/python/leaderf/gtagsExpl.py index 50e4eb6b..7c0c95fe 100644 --- a/autoload/leaderf/python/leaderf/gtagsExpl.py +++ b/autoload/leaderf/python/leaderf/gtagsExpl.py @@ -1197,7 +1197,7 @@ def startExplorer(self, win_pos, *args, **kwargs): super(GtagsExplManager, self).startExplorer(win_pos, *args, **kwargs) def _previewInPopup(self, *args, **kwargs): - if len(args) == 0: + if len(args) == 0 or args[0] == '': return line = args[0] diff --git a/autoload/leaderf/python/leaderf/helpExpl.py b/autoload/leaderf/python/leaderf/helpExpl.py index fb21bf9d..77425965 100644 --- a/autoload/leaderf/python/leaderf/helpExpl.py +++ b/autoload/leaderf/python/leaderf/helpExpl.py @@ -140,7 +140,7 @@ def _supportsRefine(self): return True def _previewInPopup(self, *args, **kwargs): - if len(args) == 0: + if len(args) == 0 or args[0] == '': return line = args[0] diff --git a/autoload/leaderf/python/leaderf/jumpsExpl.py b/autoload/leaderf/python/leaderf/jumpsExpl.py index 95eaa9f3..07a5ab01 100644 --- a/autoload/leaderf/python/leaderf/jumpsExpl.py +++ b/autoload/leaderf/python/leaderf/jumpsExpl.py @@ -182,8 +182,9 @@ def _bangReadFinished(self): self._readFinished() def _previewInPopup(self, *args, **kwargs): - if len(args) == 0: + if len(args) == 0 or args[0] == '': return + line = args[0] # title diff --git a/autoload/leaderf/python/leaderf/lineExpl.py b/autoload/leaderf/python/leaderf/lineExpl.py index 1d0efb0a..7f21e5bf 100644 --- a/autoload/leaderf/python/leaderf/lineExpl.py +++ b/autoload/leaderf/python/leaderf/lineExpl.py @@ -131,7 +131,7 @@ def _beforeExit(self): self._cursorline_dict.clear() def _previewInPopup(self, *args, **kwargs): - if len(args) == 0: + if len(args) == 0 or args[0] == '': return line = args[0] diff --git a/autoload/leaderf/python/leaderf/mruExpl.py b/autoload/leaderf/python/leaderf/mruExpl.py index cb0f1963..c9627c45 100644 --- a/autoload/leaderf/python/leaderf/mruExpl.py +++ b/autoload/leaderf/python/leaderf/mruExpl.py @@ -371,7 +371,7 @@ def deleteMru(self): lfCmd("setlocal nomodifiable") def _previewInPopup(self, *args, **kwargs): - if len(args) == 0: + if len(args) == 0 or args[0] == '': return line = args[0] diff --git a/autoload/leaderf/python/leaderf/qfloclistExpl.py b/autoload/leaderf/python/leaderf/qfloclistExpl.py index 0582ca96..c034a01e 100644 --- a/autoload/leaderf/python/leaderf/qfloclistExpl.py +++ b/autoload/leaderf/python/leaderf/qfloclistExpl.py @@ -188,7 +188,7 @@ def _createHelp(self): return help def _previewInPopup(self, *args, **kwargs): - if len(args) == 0: + if len(args) == 0 or args[0] == '': return line = args[0] diff --git a/autoload/leaderf/python/leaderf/rgExpl.py b/autoload/leaderf/python/leaderf/rgExpl.py index 99ccf287..ef2ec751 100644 --- a/autoload/leaderf/python/leaderf/rgExpl.py +++ b/autoload/leaderf/python/leaderf/rgExpl.py @@ -1165,7 +1165,7 @@ def _createPopupPreview(self, title, source, line_num, jump_cmd=''): return False def _previewInPopup(self, *args, **kwargs): - if len(args) == 0: + if len(args) == 0 or args[0] == '': return if args[0] == self._getExplorer().getContextSeparator(): diff --git a/autoload/leaderf/python/leaderf/tagExpl.py b/autoload/leaderf/python/leaderf/tagExpl.py index 97d95139..329c4f89 100644 --- a/autoload/leaderf/python/leaderf/tagExpl.py +++ b/autoload/leaderf/python/leaderf/tagExpl.py @@ -211,8 +211,9 @@ def _bangEnter(self): instance.window.options["cursorline"] = True def _previewInPopup(self, *args, **kwargs): - if len(args) == 0: + if len(args) == 0 or args[0] == '': return + line = args[0] # {tagname}{tagfile}{tagaddress}[;"{tagfield}..] tagname, tagfile, right = line.split('\t', 2) From 5dfa9355bbb819ae6597a947c39a2a96235568da Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Fri, 15 Sep 2023 14:15:20 +0800 Subject: [PATCH 132/365] line number is not right --- autoload/leaderf/python/leaderf/functionExpl.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/autoload/leaderf/python/leaderf/functionExpl.py b/autoload/leaderf/python/leaderf/functionExpl.py index c2e6fea1..66b8069c 100644 --- a/autoload/leaderf/python/leaderf/functionExpl.py +++ b/autoload/leaderf/python/leaderf/functionExpl.py @@ -398,10 +398,15 @@ def _relocateCursor(self): else: lfCmd("call leaderf#ResetPopupOptions(%d, 'filter', function('leaderf#NormalModeFilter', [%d]))" % (self._getInstance().getPopupWinId(), id(self))) + self._cli._buildPopupPrompt() else: lfCmd(str(index)) + if self._getInstance().getWinPos() == 'floatwin': + self._cli._buildPopupPrompt() lfCmd("norm! zz") + self._previewResult(False) + def _previewInPopup(self, *args, **kwargs): if len(args) == 0 or args[0] == '': return From 9c4451d2c1a6ea1f32e39fe52d58f6f5655b231d Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Fri, 15 Sep 2023 17:54:04 +0800 Subject: [PATCH 133/365] add support for `--preview-position` --- autoload/leaderf/Any.vim | 1 + autoload/leaderf/python/leaderf/instance.py | 24 +++++++++++++++------ autoload/leaderf/python/leaderf/manager.py | 13 +++++------ 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/autoload/leaderf/Any.vim b/autoload/leaderf/Any.vim index 981622f3..421e1555 100644 --- a/autoload/leaderf/Any.vim +++ b/autoload/leaderf/Any.vim @@ -251,6 +251,7 @@ let g:Lf_CommonArguments = [ \ {"name": ["--no-auto-preview"], "nargs": 0, "help": "don't open preview window automatically."}, \ ], \ {"name": ["--quick-select"], "nargs": "?", "choices":[0, 1], "metavar": "", "help": "Enable quick-select mode or not. can be '1' or '0', which means 'true' or 'false' respectively. If is omitted, it means enable quick-select mode."}, + \ {"name": ["--preview-position"], "nargs": 1, "choices": ["top", "topleft", "topright", "right", "bottom", "left"], "metavar": "", "help": "Specify where to place the preview window."}, \] " arguments is something like g:Lf_CommonArguments diff --git a/autoload/leaderf/python/leaderf/instance.py b/autoload/leaderf/python/leaderf/instance.py index f38128cd..a44a4da1 100644 --- a/autoload/leaderf/python/leaderf/instance.py +++ b/autoload/leaderf/python/leaderf/instance.py @@ -275,6 +275,8 @@ def __init__(self, manager, category, cli, self._auto_resize = lfEval("get(g:, 'Lf_AutoResize', 0)") == '1' self._window_id = 0 self._float_win_view = None + self._auto_adjust_height = lfEval("get(g:, 'Lf_PopupAutoAdjustHeight', 1)") == '1' + self._preview_position = None def _initStlVar(self): if int(lfEval("!exists('g:Lf_{}_StlCategory')".format(self._category))): @@ -395,9 +397,16 @@ def _vim_set_options(self, winid): lfCmd("call win_execute(%d, 'setlocal colorcolumn=')" % winid) def _createPopupWindow(self): + preview_pos = self._arguments.get("--preview-position", [""])[0] + if preview_pos == "": + preview_pos = lfEval("get(g:, 'Lf_PopupPreviewPosition', 'right')") + if lfEval("has('nvim')") == '0' and self._popup_instance.valid(): - if self._popup_instance.tabpage == vim.current.tabpage and lfEval("get(g:, 'Lf_Popup_VimResized', 0)") == '0' \ - and "--popup-width" not in self._arguments and "--popup-height" not in self._arguments: + if (self._popup_instance.tabpage == vim.current.tabpage + and lfEval("get(g:, 'Lf_Popup_VimResized', 0)") == '0' + and "--popup-width" not in self._arguments + and "--popup-height" not in self._arguments + and preview_pos == self._preview_position): self._win_pos = "popup" self._window_object = self._popup_instance.content_win self._popup_instance.show() @@ -408,7 +417,10 @@ def _createPopupWindow(self): buf_number = int(lfEval("bufadd('{}')".format(escQuote(self._buffer_name)))) - preview_pos = lfEval("get(g:, 'Lf_PopupPreviewPosition', 'right')") + self._preview_position = preview_pos + if preview_pos == "bottom": + self._auto_adjust_height = False + width = lfEval("get(g:, 'Lf_PopupWidth', 0)") width = self._arguments.get("--popup-width", [width])[0] width = width.strip('"').strip("'") @@ -480,7 +492,7 @@ def _createPopupWindow(self): if lfEval("has('nvim')") == '1': self._win_pos = "floatwin" - if lfEval("get(g:, 'Lf_PopupAutoAdjustHeight', 1)") == '1': + if self._auto_adjust_height: floatwin_height = 1 else: floatwin_height = self._popup_maxheight @@ -618,7 +630,7 @@ def getWindow(number): lfCmd("call winrestview(%s)" % self._float_win_view) else: self._win_pos = "popup" - if lfEval("get(g:, 'Lf_PopupAutoAdjustHeight', 1)") == '1': + if self._auto_adjust_height: minheight = 1 else: minheight = self._popup_maxheight @@ -1298,7 +1310,7 @@ def setBuffer(self, content, need_copy=False): self.buffer.options['modifiable'] = False def refreshPopupStatusline(self): - if lfEval("get(g:, 'Lf_PopupAutoAdjustHeight', 1)") == '0': + if not self._auto_adjust_height: return statusline_win = self._popup_instance.statusline_win diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index f5a576b6..424ec171 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -131,9 +131,6 @@ def __init__(self): self._preview_filetype = None if lfEval("has('patch-8.1.1615') || has('nvim-0.5.0')") == '0': lfCmd("let g:Lf_PreviewInPopup = 0") - if lfEval("get(g:, 'Lf_PopupPreviewPosition', 'right')").lower() == 'bottom': - lfCmd("let g:Lf_PopupAutoAdjustHeight = 0") - #************************************************************** # abstract methods, in fact all the functions can be overridden @@ -583,6 +580,9 @@ def _createPopupModePreview(self, title, source, line_num, jump_cmd): self._is_previewed = True show_borders = lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1' + preview_pos = self._arguments.get("--preview-position", [""])[0] + if preview_pos == "": + preview_pos = lfEval("get(g:, 'Lf_PopupPreviewPosition', 'right')") if lfEval("has('nvim')") == '1': width = int(lfEval("get(g:, 'Lf_PreviewPopupWidth', 0)")) @@ -597,7 +597,6 @@ def _createPopupModePreview(self, title, source, line_num, jump_cmd): float_win_col = int(float(lfEval("nvim_win_get_config(%d).col" % float_window.id))) float_win_height = int(float(lfEval("nvim_win_get_config(%d).height" % float_window.id))) float_win_width= int(float(lfEval("nvim_win_get_config(%d).width" % float_window.id))) - preview_pos = lfEval("get(g:, 'Lf_PopupPreviewPosition', 'right')") popup_borders = lfEval("g:Lf_PopupBorders") borderchars = [ [popup_borders[4], "Lf_hl_popupBorder"], @@ -709,7 +708,6 @@ def _createPopupModePreview(self, title, source, line_num, jump_cmd): else: maxwidth = min(width, int(lfEval("&columns"))) - preview_pos = lfEval("get(g:, 'Lf_PopupPreviewPosition', 'right')") if preview_pos.lower() == 'bottom': maxwidth = int(popup_pos["width"]) col = int(popup_pos["col"]) @@ -919,7 +917,10 @@ def _createPopupPreview(self, title, source, line_num, jump_cmd=''): win_pos = self._getInstance().getWinPos() show_borders = lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1' - preview_pos = lfEval("get(g:, 'Lf_PreviewPosition', 'top')") + preview_pos = self._arguments.get("--preview-position", [""])[0] + if preview_pos == "": + preview_pos = lfEval("get(g:, 'Lf_PreviewPosition', 'top')") + if lfEval("has('nvim')") == '1': if win_pos == 'bottom': if preview_pos.lower() == 'topleft': From 44c1b4b7d285b1eccda5544fad476dfa58690b8e Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Mon, 18 Sep 2023 10:17:56 +0800 Subject: [PATCH 134/365] fix issue #1038 --- autoload/leaderf/python/leaderf/manager.py | 7 ++++++- autoload/leaderf/python/leaderf/rgExpl.py | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 424ec171..e3c60d2c 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -101,9 +101,14 @@ def deco(self, *args, **kwargs): class Manager(object): def __init__(self): self._autochdir = 0 - self._instance = None self._cli = LfCli() self._explorer = None + self._instance = LfInstance(self, self._getExplorer().getStlCategory(), + self._cli, + self._beforeEnter, + self._afterEnter, + self._beforeExit, + self._afterExit) self._content = [] self._index = 0 self._help_length = 0 diff --git a/autoload/leaderf/python/leaderf/rgExpl.py b/autoload/leaderf/python/leaderf/rgExpl.py index ef2ec751..e707c6ec 100644 --- a/autoload/leaderf/python/leaderf/rgExpl.py +++ b/autoload/leaderf/python/leaderf/rgExpl.py @@ -943,6 +943,7 @@ def startLiveGrep(self, win_pos, *args, **kwargs): self._arguments["--next"] = arguments_dict["--next"] else: self.setArguments(arguments_dict) + self._getInstance().setArguments(self._arguments) self._cli.setArguments(arguments_dict) self._cli.setNameOnlyFeature(self._getExplorer().supportsNameOnly()) self._cli.setRefineFeature(self._supportsRefine()) @@ -960,7 +961,6 @@ def startLiveGrep(self, win_pos, *args, **kwargs): self._cleanup() # lfCmd("echohl WarningMsg | redraw | echo ' searching ...' | echohl NONE") - self._getInstance().setArguments(self._arguments) remember_last_status = "--recall" in self._arguments \ or lfEval("g:Lf_RememberLastSearch") == '1' and self._cli.pattern From 85ae520e732cd51f54971e57b5d4275f0dad38e3 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Mon, 18 Sep 2023 11:01:04 +0800 Subject: [PATCH 135/365] fix issue #1038 --- autoload/leaderf/python/leaderf/manager.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index e3c60d2c..687c9549 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -1161,13 +1161,6 @@ def _needPreview(self, preview, preview_in_popup): return True def _getInstance(self): - if self._instance is None: - self._instance = LfInstance(self, self._getExplorer().getStlCategory(), - self._cli, - self._beforeEnter, - self._afterEnter, - self._beforeExit, - self._afterExit) return self._instance def _createHelpHint(self): From c632d20218ddd9ad4758586b89debd08ae43a6bd Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Mon, 18 Sep 2023 13:22:36 +0800 Subject: [PATCH 136/365] fix issue #1039 --- autoload/leaderf/python/leaderf/manager.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 687c9549..2adbcad3 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -103,12 +103,7 @@ def __init__(self): self._autochdir = 0 self._cli = LfCli() self._explorer = None - self._instance = LfInstance(self, self._getExplorer().getStlCategory(), - self._cli, - self._beforeEnter, - self._afterEnter, - self._beforeExit, - self._afterExit) + self._instance = None self._content = [] self._index = 0 self._help_length = 0 @@ -1161,6 +1156,13 @@ def _needPreview(self, preview, preview_in_popup): return True def _getInstance(self): + if self._instance is None: + self._instance = LfInstance(self, self._getExplorer().getStlCategory(), + self._cli, + self._beforeEnter, + self._afterEnter, + self._beforeExit, + self._afterExit) return self._instance def _createHelpHint(self): From 191acc11311aacac2a0c5bef15f3326ac3381c8c Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 20 Sep 2023 22:01:57 +0800 Subject: [PATCH 137/365] fix issue #1034 --- autoload/leaderf/Any.vim | 2 +- autoload/leaderf/python/leaderf/manager.py | 96 ++++++++++++++++------ doc/leaderf.txt | 1 + 3 files changed, 75 insertions(+), 24 deletions(-) diff --git a/autoload/leaderf/Any.vim b/autoload/leaderf/Any.vim index 421e1555..d4376cd0 100644 --- a/autoload/leaderf/Any.vim +++ b/autoload/leaderf/Any.vim @@ -251,7 +251,7 @@ let g:Lf_CommonArguments = [ \ {"name": ["--no-auto-preview"], "nargs": 0, "help": "don't open preview window automatically."}, \ ], \ {"name": ["--quick-select"], "nargs": "?", "choices":[0, 1], "metavar": "", "help": "Enable quick-select mode or not. can be '1' or '0', which means 'true' or 'false' respectively. If is omitted, it means enable quick-select mode."}, - \ {"name": ["--preview-position"], "nargs": 1, "choices": ["top", "topleft", "topright", "right", "bottom", "left"], "metavar": "", "help": "Specify where to place the preview window."}, + \ {"name": ["--preview-position"], "nargs": 1, "choices": ["top", "topleft", "topright", "right", "bottom", "left", "cursor"], "metavar": "", "help": "Specify where to place the preview window."}, \] " arguments is something like g:Lf_CommonArguments diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 2adbcad3..139d12a9 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -129,6 +129,7 @@ def __init__(self): self._arguments = {} self._getExplClass() self._preview_filetype = None + self._preview_config = {} if lfEval("has('patch-8.1.1615') || has('nvim-0.5.0')") == '0': lfCmd("let g:Lf_PreviewInPopup = 0") @@ -499,6 +500,8 @@ def _setWinOptions(self, winid): lfCmd("call win_execute(%d, 'setlocal wincolor=Lf_hl_popup_window')" % winid) def _createPreviewWindow(self, config, source, line_num, jump_cmd): + self._preview_config = config + if lfEval("has('nvim')") == '1': if isinstance(source, int): buffer_len = len(vim.buffers[source]) @@ -837,6 +840,20 @@ def _isBinaryFile(self, filename): return True def _useExistingWindow(self, title, source, line_num, jump_cmd): + preview_pos = self._arguments.get("--preview-position", [""])[0] + if preview_pos == "": + preview_pos = lfEval("get(g:, 'Lf_PreviewPosition', 'top')") + + if preview_pos == "cursor" and self._getInstance().getWinPos() not in ('popup', 'floatwin'): + show_borders = lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1' + self._updateOptions(preview_pos, show_borders, self._preview_config) + if lfEval("has('nvim')") == '1': + if 'noautocmd' in self._preview_config: + del self._preview_config['noautocmd'] + lfCmd("call nvim_win_set_config(%d, %s)" % (self._preview_winid, str(self._preview_config))) + else: + lfCmd("call popup_setoptions(%d, %s)" % (self._preview_winid, str(self._preview_config))) + if lfEval("has('nvim')") == '1': if isinstance(source, int): lfCmd("noautocmd call nvim_win_set_buf(%d, %d)" % (self._preview_winid, source)) @@ -1006,25 +1023,7 @@ def _createPopupPreview(self, title, source, line_num, jump_cmd=''): "noautocmd": 1 } - if show_borders: - popup_borders = lfEval("g:Lf_PopupBorders") - borderchars = [ - [popup_borders[4], "Lf_hl_popupBorder"], - [popup_borders[0], "Lf_hl_popupBorder"], - [popup_borders[5], "Lf_hl_popupBorder"], - [popup_borders[1], "Lf_hl_popupBorder"], - [popup_borders[6], "Lf_hl_popupBorder"], - [popup_borders[2], "Lf_hl_popupBorder"], - [popup_borders[7], "Lf_hl_popupBorder"], - [popup_borders[3], "Lf_hl_popupBorder"] - ] - config["border"] = borderchars - config["height"] -= 2 - config["width"] -= 2 - if lfEval("has('nvim-0.9.0')") == '1': - config["title"] = " Preview " - config["title_pos"] = "center" - + self._updateOptions(preview_pos, show_borders, config) self._createPreviewWindow(config, source, line_num, jump_cmd) else: if win_pos == 'bottom': @@ -1106,6 +1105,61 @@ def _createPopupPreview(self, title, source, line_num, jump_cmd=''): "filter": "leaderf#popupModePreviewFilter", } + self._updateOptions(preview_pos, show_borders, options) + self._createPreviewWindow(options, source, line_num, jump_cmd) + + return True + + def _updateOptions(self, preview_pos, show_borders, options): + if lfEval("has('nvim')") == '1': + if preview_pos.lower() == 'cursor': + options["anchor"] = "NW" + options["width"] = self._getInstance().window.width + row = int(lfEval("screenpos(%d, line('.'), 1)" % self._getInstance().windowId)['row']) + height = int(lfEval("&lines")) - 2 - row + + if height * 2 < int(lfEval("&lines")) - 2: + height = row - 1 + row = 0 + + options["height"] = height + options["row"] = row + options["col"] = self._getInstance().window.col + + if show_borders: + popup_borders = lfEval("g:Lf_PopupBorders") + borderchars = [ + [popup_borders[4], "Lf_hl_popupBorder"], + [popup_borders[0], "Lf_hl_popupBorder"], + [popup_borders[5], "Lf_hl_popupBorder"], + [popup_borders[1], "Lf_hl_popupBorder"], + [popup_borders[6], "Lf_hl_popupBorder"], + [popup_borders[2], "Lf_hl_popupBorder"], + [popup_borders[7], "Lf_hl_popupBorder"], + [popup_borders[3], "Lf_hl_popupBorder"] + ] + options["border"] = borderchars + options["height"] -= 2 + options["width"] -= 2 + if lfEval("has('nvim-0.9.0')") == '1': + options["title"] = " Preview " + options["title_pos"] = "center" + else: + if preview_pos.lower() == 'cursor': + options["maxwidth"] = self._getInstance().window.width + options["minwidth"] = self._getInstance().window.width + row = int(lfEval("screenpos(%d, line('.'), 1)" % self._getInstance().windowId)['row']) + maxheight = int(lfEval("&lines")) - 2 - row - 1 + + if maxheight * 2 < int(lfEval("&lines")) - 3: + maxheight = int(lfEval("&lines")) - maxheight - 5 + + options["maxheight"] = maxheight + options["minheight"] = maxheight + options["pos"] = "botleft" + options["line"] = "cursor-1" + options["col"] = self._getInstance().window.col + 1 + if show_borders: options["border"] = [] options["borderchars"] = lfEval("g:Lf_PopupBorders") @@ -1115,10 +1169,6 @@ def _createPopupPreview(self, title, source, line_num, jump_cmd=''): options["minheight"] -= 1 options["borderhighlight"] = ["Lf_hl_popupBorder"] - self._createPreviewWindow(options, source, line_num, jump_cmd) - - return True - def _needPreview(self, preview, preview_in_popup): """ Args: diff --git a/doc/leaderf.txt b/doc/leaderf.txt index bd71e5bc..2e357cc7 100644 --- a/doc/leaderf.txt +++ b/doc/leaderf.txt @@ -887,6 +887,7 @@ g:Lf_PreviewPosition *g:Lf_PreviewPosition* 'right': the preview window is on the right of the main LeaderF window. 'bottom': the preview window is at the bottom of the main LeaderF window. (only available when LeaderF window is on the top) + 'cursor': the preview window is at the cursorline of the main LeaderF window. Default value is 'top'. From a77f45791edeaa82fa75c5959ca73a59d7549549 Mon Sep 17 00:00:00 2001 From: sheeaza Date: Mon, 25 Sep 2023 10:12:40 +0800 Subject: [PATCH 138/365] simplify argdelete and prefix path to multi file selection (#1042) * use %argdelete to delete all to simplify the origin 'silent! argdelete *' code, and '%argdelete' will not raise any error * file: prefix path for multi selection if there is path arg to 'Leaderf file' cmd like 'Leaderf file path/to/files', and multi files are selected, those files except first one will use the wrong path. in this situation we need to prefix the path with cwd, like the first one Signed-off-by: sheeaza --------- Signed-off-by: sheeaza --- autoload/leaderf/python/leaderf/manager.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 139d12a9..ee806539 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -184,9 +184,16 @@ def _cmdExtension(self, cmd): @removeDevIcons def _argaddFiles(self, files): - # It will raise E480 without 'silent!' - lfCmd("silent! argdelete *") + # simply delete all, without err print + lfCmd("%argdelete") for file in files: + if not os.path.isabs(file): + if self._getExplorer()._cmd_work_dir: + file = os.path.join(self._getExplorer()._cmd_work_dir, lfDecode(file)) + else: + file = os.path.join(self._getInstance().getCwd(), lfDecode(file)) + file = os.path.normpath(lfEncode(file)) + lfCmd("argadd %s" % escSpecial(file)) def _issue_422_set_option(self): From 2c85c8b160fb13d8af4fac3efbd6d48badf146cf Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Tue, 17 Oct 2023 15:33:01 +0800 Subject: [PATCH 139/365] fix a bug ':Leaderf rg --live --no-fixed-strings' has no output if input \bint on Windows --- autoload/leaderf/python/leaderf/rgExpl.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/autoload/leaderf/python/leaderf/rgExpl.py b/autoload/leaderf/python/leaderf/rgExpl.py index e707c6ec..de4b17b0 100644 --- a/autoload/leaderf/python/leaderf/rgExpl.py +++ b/autoload/leaderf/python/leaderf/rgExpl.py @@ -204,17 +204,14 @@ def getContent(self, *args, **kwargs): if "--live" in arguments_dict: pattern_list = [kwargs["pattern"]] - if os.name == 'nt': - no_error_message = " 2>NUL" - else: - no_error_message = " 2>/dev/null" + raise_except = False # --live implies -F if "-F" not in arguments_dict and "--no-fixed-strings" not in arguments_dict: zero_args_options += "-F " is_literal = True else: pattern_list = arguments_dict.get("-e", []) - no_error_message = "" + raise_except = True pattern = '' for i in pattern_list or path_list[:1]: @@ -233,7 +230,10 @@ def getContent(self, *args, **kwargs): case_pattern = r'\C' if "--live" in arguments_dict: - p = i.replace('\\', r'\\').replace('"', r'\"') + if "--no-fixed-strings" in arguments_dict: + p = i.replace('"', r'\"') + else: + p = i.replace('\\', r'\\').replace('"', r'\"') pattern += r'-e "%s" ' % p else: if len(i) > 1 and (i[0] == i[-1] == '"' or i[0] == i[-1] == "'"): @@ -336,10 +336,10 @@ def removeFiles(names): heading = "--no-heading" cmd = '''{} {} --no-config --no-ignore-messages {} --with-filename --color never --line-number '''\ - '''{} {}{}{}{}{}{}{}'''.format(self._rg, extra_options, heading, case_flag, word_or_line, zero_args_options, - one_args_options, repeatable_options, lfDecode(pattern), path, no_error_message) + '''{} {}{}{}{}{}{}'''.format(self._rg, extra_options, heading, case_flag, word_or_line, zero_args_options, + one_args_options, repeatable_options, lfDecode(pattern), path) lfCmd("let g:Lf_Debug_RgCmd = '%s'" % escQuote(cmd)) - content = executor.execute(cmd, encoding=lfEval("&encoding"), cleanup=partial(removeFiles, tmpfilenames)) + content = executor.execute(cmd, encoding=lfEval("&encoding"), cleanup=partial(removeFiles, tmpfilenames), raise_except=raise_except) return content def translateRegex(self, regex, is_perl=False): From 31f1d4fb32fc9f3e0f373c29b2423e90ec527a03 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 25 Oct 2023 15:05:56 +0800 Subject: [PATCH 140/365] python2 reports errors TypeError: split() takes no keyword arguments --- autoload/leaderf/python/leaderf/mru.py | 6 +++--- autoload/leaderf/python/leaderf/mruExpl.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/autoload/leaderf/python/leaderf/mru.py b/autoload/leaderf/python/leaderf/mru.py index a78639fe..0fb315c6 100644 --- a/autoload/leaderf/python/leaderf/mru.py +++ b/autoload/leaderf/python/leaderf/mru.py @@ -53,7 +53,7 @@ def normalize(self, name): return name def filename(self, line): - return line.rstrip().split(maxsplit=2)[2] + return line.rstrip().split(None, 2)[2] def saveToCache(self, data_list): frecency_list = [] @@ -79,8 +79,8 @@ def saveToCache(self, data_list): for i, line in enumerate(lines): text = self.filename(line) if (compare == text) or (nocase and compare == text.lower()): - time1, rank1, filename = item.split(maxsplit=2) - time2, rank2, _ = lines[i].split(maxsplit=2) + time1, rank1, filename = item.split(None, 2) + time2, rank2, _ = lines[i].split(None, 2) lines[i] = "{} {} {}\n".format(time1, int(rank1) + int(rank2), filename) break else: diff --git a/autoload/leaderf/python/leaderf/mruExpl.py b/autoload/leaderf/python/leaderf/mruExpl.py index c9627c45..a86cc241 100644 --- a/autoload/leaderf/python/leaderf/mruExpl.py +++ b/autoload/leaderf/python/leaderf/mruExpl.py @@ -56,7 +56,7 @@ def getContent(self, *args, **kwargs): with lfOpen(mru.getCacheFileName(), 'r+', errors='ignore', encoding='utf8') as f: data_list = [] for line in f.readlines(): - data = line.split(maxsplit=2) + data = line.split(None, 2) if os.path.exists(lfDecode(data[2].rstrip())): data[0] = int(data[0]) data_list.append(data) From ab810656f787a387189d8a1ce4002ce38007f7b2 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 25 Oct 2023 15:12:56 +0800 Subject: [PATCH 141/365] add support to highlight in preview window for Leaderf gtags --- autoload/leaderf/python/leaderf/gtagsExpl.py | 29 ++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/autoload/leaderf/python/leaderf/gtagsExpl.py b/autoload/leaderf/python/leaderf/gtagsExpl.py index 7c0c95fe..15a05e6b 100644 --- a/autoload/leaderf/python/leaderf/gtagsExpl.py +++ b/autoload/leaderf/python/leaderf/gtagsExpl.py @@ -898,6 +898,7 @@ class GtagsExplManager(Manager): def __init__(self): super(GtagsExplManager, self).__init__() self._match_path = False + self._preview_match_ids = [] def _getExplClass(self): return GtagsExplorer @@ -1118,6 +1119,7 @@ def _beforeExit(self): if k.valid: k.options["cursorline"] = v self._cursorline_dict.clear() + self._clearPreviewHighlights() def _bangEnter(self): super(GtagsExplManager, self)._bangEnter() @@ -1196,6 +1198,32 @@ def startExplorer(self, win_pos, *args, **kwargs): super(GtagsExplManager, self).startExplorer(win_pos, *args, **kwargs) + def _clearPreviewHighlights(self): + for i in self._preview_match_ids: + lfCmd("silent! call matchdelete(%d, %d)" % (i, self._preview_winid)) + + def _highlightInPreview(self): + if lfEval("has('nvim')") != '1': + try: + for i in self._getExplorer().getPatternRegex(): + lfCmd("""call win_execute(%d, "let matchid = matchadd('Lf_hl_gtagsHighlight', '%s', 9)")""" + % (self._preview_winid, re.sub(r'\\(?!")', r'\\\\', escQuote(i)))) + id = int(lfEval("matchid")) + self._preview_match_ids.append(id) + except vim.error: + pass + else: + cur_winid = lfEval("win_getid()") + lfCmd("noautocmd call win_gotoid(%d)" % self._preview_winid) + if lfEval("win_getid()") != cur_winid: + try: + for i in self._getExplorer().getPatternRegex(): + id = int(lfEval("matchadd('Lf_hl_gtagsHighlight', '%s', 9)" % escQuote(i))) + self._preview_match_ids.append(id) + except vim.error: + pass + lfCmd("noautocmd call win_gotoid(%s)" % cur_winid) + def _previewInPopup(self, *args, **kwargs): if len(args) == 0 or args[0] == '': return @@ -1219,6 +1247,7 @@ def _previewInPopup(self, *args, **kwargs): else: source = file self._createPopupPreview("", source, line_num) + self._highlightInPreview() #***************************************************** From 59bf3ccc33bcf7010a06521fd3ac9be912261bd3 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Mon, 30 Oct 2023 13:29:46 +0800 Subject: [PATCH 142/365] close preview window if quit by using :q --- autoload/leaderf.vim | 5 +++++ autoload/leaderf/python/leaderf/instance.py | 1 + 2 files changed, 6 insertions(+) diff --git a/autoload/leaderf.vim b/autoload/leaderf.vim index 6049c3d8..67fd7dca 100644 --- a/autoload/leaderf.vim +++ b/autoload/leaderf.vim @@ -610,6 +610,11 @@ function! leaderf#PopupClosed(id_list, manager_id, winid, result) abort endif endfunction +function! leaderf#Quit(manager_id) abort + exec g:Lf_py "import ctypes" + exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value.quit()", a:manager_id) +endfunction + function! leaderf#ResetPopupOptions(winid, option, value) abort let opts = popup_getoptions(a:winid) " https://github.com/vim/vim/issues/5081 diff --git a/autoload/leaderf/python/leaderf/instance.py b/autoload/leaderf/python/leaderf/instance.py index a44a4da1..80cf83c0 100644 --- a/autoload/leaderf/python/leaderf/instance.py +++ b/autoload/leaderf/python/leaderf/instance.py @@ -854,6 +854,7 @@ def _createBufWindow(self, win_pos): lfCmd("autocmd ColorScheme doautocmd syntax") lfCmd("autocmd CursorMoved let g:Lf_{}_StlLineNumber = 1 + line('$') - line('.')".format(self._category)) lfCmd("autocmd VimResized * let g:Lf_VimResized = 1") + lfCmd("autocmd BufHidden call leaderf#Quit({})".format(id(self._manager))) lfCmd("augroup END") saved_eventignore = vim.options['eventignore'] From 7b3055fe77b47349333722851f7557e130a954e5 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Mon, 27 Nov 2023 21:01:31 +0800 Subject: [PATCH 143/365] add g:Lf_SpacesAfterIcon --- autoload/leaderf/python/leaderf/devicons.py | 18 ++++++++++++------ doc/leaderf.txt | 5 +++++ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/autoload/leaderf/python/leaderf/devicons.py b/autoload/leaderf/python/leaderf/devicons.py index a866faf5..a2469a27 100644 --- a/autoload/leaderf/python/leaderf/devicons.py +++ b/autoload/leaderf/python/leaderf/devicons.py @@ -353,10 +353,13 @@ devicons_palette["dark"].update(lfEval("get(get(g:, 'Lf_DevIconsPalette', {}), 'dark', {})")) devicons_palette["light"].update(lfEval("get(get(g:, 'Lf_DevIconsPalette', {}), 'light', {})")) -if os.name == 'nt' or lfEval('&ambiwidth') == "double": - _spaces = ' ' +if os.name == "nt" or lfEval('&ambiwidth') == "double": + _spaces = lfEval("get(g:, 'Lf_SpacesAfterIcon', ' ')") else: - _spaces = ' ' + _spaces = lfEval("get(g:, 'Lf_SpacesAfterIcon', ' ')") + +if _spaces == "": + _spaces = ' ' _default_palette = { "gui": "NONE", @@ -420,10 +423,13 @@ def _getExt(file): def setAmbiwidth(val): global _spaces - if os.name == 'nt' or val == "double": - _spaces = ' ' + if os.name == "nt" or val == "double": + _spaces = lfEval("get(g:, 'Lf_SpacesAfterIcon', ' ')") else: - _spaces = ' ' + _spaces = lfEval("get(g:, 'Lf_SpacesAfterIcon', ' ')") + + if _spaces == "": + _spaces = ' ' # To use asynchronously def webDevIconsGetFileTypeSymbol(file, isdir=False): diff --git a/doc/leaderf.txt b/doc/leaderf.txt index 2e357cc7..03e134fb 100644 --- a/doc/leaderf.txt +++ b/doc/leaderf.txt @@ -1116,6 +1116,11 @@ g:Lf_QuickSelectAction *g:Lf_QuickSelectAction* Default value is 'c'. +g:Lf_SpacesAfterIcon *g:Lf_SpacesAfterIcon* + Specifies the spaces after the icon if |g:Lf_ShowDevIcons| is 1. + + Default value is ' '. + ============================================================================== USAGE *leaderf-usage* From 1e9dab0e0424fe7cc1f741b1a38df87cedc72981 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 29 Nov 2023 14:14:35 +0800 Subject: [PATCH 144/365] fix issue #1025 add g:Lf_EnableCircularScroll --- autoload/leaderf/python/leaderf/manager.py | 19 +++++++++++-------- doc/leaderf.txt | 5 +++++ 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index ee806539..56524159 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -130,6 +130,7 @@ def __init__(self): self._getExplClass() self._preview_filetype = None self._preview_config = {} + self._circular_scroll = lfEval("get(g:, 'Lf_EnableCircularScroll', 0)") == '1' if lfEval("has('patch-8.1.1615') || has('nvim-0.5.0')") == '0': lfCmd("let g:Lf_PreviewInPopup = 0") @@ -1335,9 +1336,10 @@ def move(self, direction): """ direction is in {'j', 'k'} """ - if direction == 'j' and self._getInstance().window.cursor[0] == len(self._getInstance().buffer): + if (direction == 'j' and self._getInstance().window.cursor[0] == len(self._getInstance().buffer) + and self._circular_scroll): lfCmd("noautocmd call win_execute(%d, 'norm! gg')" % (self._getInstance().getPopupWinId())) - elif direction == 'k' and self._getInstance().window.cursor[0] == 1: + elif direction == 'k' and self._getInstance().window.cursor[0] == 1 and self._circular_scroll: lfCmd("noautocmd call win_execute(%d, 'norm! G')" % (self._getInstance().getPopupWinId())) else: lfCmd("noautocmd call win_execute(%d, 'norm! %s')" % (self._getInstance().getPopupWinId(), direction)) @@ -1346,9 +1348,10 @@ def moveAndPreview(self, direction): """ direction is in {'j', 'k', 'Down', 'Up', 'PageDown', 'PageUp'} """ - if direction in ("j", "Down") and self._getInstance().window.cursor[0] == len(self._getInstance().buffer): + if (direction in ("j", "Down") and self._getInstance().window.cursor[0] == len(self._getInstance().buffer) + and self._circular_scroll): lfCmd('noautocmd exec "norm! gg"') - elif direction in ("k", "Up") and self._getInstance().window.cursor[0] == 1: + elif direction in ("k", "Up") and self._getInstance().window.cursor[0] == 1 and self._circular_scroll: lfCmd('noautocmd exec "norm! G"') else: if len(direction) > 1: @@ -1363,7 +1366,7 @@ def moveAndPreview(self, direction): def _toUp(self): if self._getInstance().getWinPos() == 'popup': - if self._getInstance().window.cursor[0] == 1: + if self._getInstance().window.cursor[0] == 1 and self._circular_scroll: lfCmd("noautocmd call win_execute(%d, 'norm! G')" % (self._getInstance().getPopupWinId())) else: lfCmd("noautocmd call win_execute(%d, 'norm! k')" % (self._getInstance().getPopupWinId())) @@ -1379,7 +1382,7 @@ def _toUp(self): and len(self._highlight_pos) < int(lfEval("g:Lf_NumberOfHighlight")): self._highlight_method() - if self._getInstance().window.cursor[0] == 1: + if self._getInstance().window.cursor[0] == 1 and self._circular_scroll: lfCmd("noautocmd norm! G") else: lfCmd("noautocmd norm! k") @@ -1393,7 +1396,7 @@ def _toUp(self): def _toDown(self): if self._getInstance().getWinPos() == 'popup': - if self._getInstance().window.cursor[0] == len(self._getInstance().buffer): + if self._getInstance().window.cursor[0] == len(self._getInstance().buffer) and self._circular_scroll: lfCmd("noautocmd call win_execute(%d, 'norm! gg')" % (self._getInstance().getPopupWinId())) else: lfCmd("noautocmd call win_execute(%d, 'norm! j')" % (self._getInstance().getPopupWinId())) @@ -1404,7 +1407,7 @@ def _toDown(self): and self._getInstance().getCurrentPos()[0] == self._initial_count: self._setResultContent() - if self._getInstance().window.cursor[0] == len(self._getInstance().buffer): + if self._getInstance().window.cursor[0] == len(self._getInstance().buffer) and self._circular_scroll: lfCmd("noautocmd norm! gg") else: lfCmd("noautocmd norm! j") diff --git a/doc/leaderf.txt b/doc/leaderf.txt index 03e134fb..f27996f4 100644 --- a/doc/leaderf.txt +++ b/doc/leaderf.txt @@ -1121,6 +1121,11 @@ g:Lf_SpacesAfterIcon *g:Lf_SpacesAfterIcon* Default value is ' '. +g:Lf_EnableCircularScroll *g:Lf_EnableCircularScroll* + Enable circular scroll in the result window. + + Default value is 0. + ============================================================================== USAGE *leaderf-usage* From 001b12c022babbe433bc53f8ecdac1c202c57977 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 30 Nov 2023 16:34:58 +0800 Subject: [PATCH 145/365] restore the cursor line of popup window when --recall --- autoload/leaderf/python/leaderf/instance.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/autoload/leaderf/python/leaderf/instance.py b/autoload/leaderf/python/leaderf/instance.py index 80cf83c0..67490c35 100644 --- a/autoload/leaderf/python/leaderf/instance.py +++ b/autoload/leaderf/python/leaderf/instance.py @@ -275,6 +275,7 @@ def __init__(self, manager, category, cli, self._auto_resize = lfEval("get(g:, 'Lf_AutoResize', 0)") == '1' self._window_id = 0 self._float_win_view = None + self._popup_cursor_line = 1 self._auto_adjust_height = lfEval("get(g:, 'Lf_PopupAutoAdjustHeight', 1)") == '1' self._preview_position = None @@ -675,6 +676,7 @@ def getWindow(number): lfCmd("call win_execute(%d, 'setlocal foldcolumn=1')" % self._popup_winid) lfCmd("call win_execute(%d, 'setlocal wincolor=Lf_hl_popup_window')" % self._popup_winid) lfCmd("call win_execute(%d, 'silent! setlocal filetype=leaderf')" % self._popup_winid) + lfCmd("call win_execute(%d, 'norm! %dG')" % (self._popup_winid, self._popup_cursor_line)) self._tabpage_object = vim.current.tabpage self._buffer_object = vim.buffers[buf_number] @@ -1149,6 +1151,7 @@ def exitBuffer(self): lfCmd("let &gcr = remove(g:lf_gcr_stack, -1)") lfCmd("set t_ve&") lfCmd("let &t_ve = remove(g:lf_t_ve_stack, -1)") + self._popup_cursor_line = self._window_object.cursor[0] self._popup_instance.hide() self._after_exit() return From ee827173e5a3977ef764302083a4df07b4568cf3 Mon Sep 17 00:00:00 2001 From: Adam Tao Date: Sun, 3 Dec 2023 14:17:56 +0800 Subject: [PATCH 146/365] fix: Fix SyntaxWarning in python3.12 (#1047) Signed-off-by: Adam Tao --- autoload/leaderf/python/leaderf/anyExpl.py | 2 +- autoload/leaderf/python/leaderf/bufExpl.py | 20 +++---- autoload/leaderf/python/leaderf/bufTagExpl.py | 26 ++++----- autoload/leaderf/python/leaderf/cli.py | 20 +++---- autoload/leaderf/python/leaderf/devicons.py | 8 +-- autoload/leaderf/python/leaderf/fileExpl.py | 10 ++-- .../leaderf/python/leaderf/functionExpl.py | 24 ++++----- autoload/leaderf/python/leaderf/gtagsExpl.py | 18 +++---- autoload/leaderf/python/leaderf/helpExpl.py | 6 +-- autoload/leaderf/python/leaderf/jumpsExpl.py | 18 +++---- autoload/leaderf/python/leaderf/lineExpl.py | 4 +- autoload/leaderf/python/leaderf/manager.py | 26 ++++----- autoload/leaderf/python/leaderf/mruExpl.py | 4 +- autoload/leaderf/python/leaderf/rgExpl.py | 54 +++++++++---------- autoload/leaderf/python/leaderf/selfExpl.py | 8 +-- autoload/leaderf/python/leaderf/tagExpl.py | 30 +++++------ 16 files changed, 139 insertions(+), 139 deletions(-) diff --git a/autoload/leaderf/python/leaderf/anyExpl.py b/autoload/leaderf/python/leaderf/anyExpl.py index 9a4a9567..0de1bf76 100644 --- a/autoload/leaderf/python/leaderf/anyExpl.py +++ b/autoload/leaderf/python/leaderf/anyExpl.py @@ -16,7 +16,7 @@ from .asyncExecutor import AsyncExecutor -""" +r""" let g:Lf_Extensions = { \ "apple": { \ "source": [], "grep -r '%s' *", funcref (arguments), {"command": "ls" or funcref(arguments)} diff --git a/autoload/leaderf/python/leaderf/bufExpl.py b/autoload/leaderf/python/leaderf/bufExpl.py index dee2e5b3..25660bd2 100644 --- a/autoload/leaderf/python/leaderf/bufExpl.py +++ b/autoload/leaderf/python/leaderf/bufExpl.py @@ -220,37 +220,37 @@ def _afterEnter(self): winid = None if self._getInstance().getWinPos() == 'popup': - lfCmd("""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_bufNumber'', ''^\s*\zs\d\+'')')""" + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_bufNumber'', ''^\s*\zs\d\+'')')""" % self._getInstance().getPopupWinId()) id = int(lfEval("matchid")) self._match_ids.append(id) - lfCmd("""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_bufIndicators'', ''^\s*\d\+\s*\zsu\=\s*[#%%]\=...'')')""" + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_bufIndicators'', ''^\s*\d\+\s*\zsu\=\s*[#%%]\=...'')')""" % self._getInstance().getPopupWinId()) id = int(lfEval("matchid")) self._match_ids.append(id) - lfCmd("""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_bufModified'', ''^\s*\d\+\s*u\=\s*[#%%]\=.+\s*\zs.*$'')')""" + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_bufModified'', ''^\s*\d\+\s*u\=\s*[#%%]\=.+\s*\zs.*$'')')""" % self._getInstance().getPopupWinId()) id = int(lfEval("matchid")) self._match_ids.append(id) - lfCmd("""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_bufNomodifiable'', ''^\s*\d\+\s*u\=\s*[#%%]\=..-\s*\zs.*$'')')""" + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_bufNomodifiable'', ''^\s*\d\+\s*u\=\s*[#%%]\=..-\s*\zs.*$'')')""" % self._getInstance().getPopupWinId()) id = int(lfEval("matchid")) self._match_ids.append(id) - lfCmd("""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_bufDirname'', '' \zs".*"$'')')""" + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_bufDirname'', '' \zs".*"$'')')""" % self._getInstance().getPopupWinId()) id = int(lfEval("matchid")) self._match_ids.append(id) winid = self._getInstance().getPopupWinId() else: - id = int(lfEval("matchadd('Lf_hl_bufNumber', '^\s*\zs\d\+')")) + id = int(lfEval(r"matchadd('Lf_hl_bufNumber', '^\s*\zs\d\+')")) self._match_ids.append(id) - id = int(lfEval("matchadd('Lf_hl_bufIndicators', '^\s*\d\+\s*\zsu\=\s*[#%]\=...')")) + id = int(lfEval(r"matchadd('Lf_hl_bufIndicators', '^\s*\d\+\s*\zsu\=\s*[#%]\=...')")) self._match_ids.append(id) - id = int(lfEval("matchadd('Lf_hl_bufModified', '^\s*\d\+\s*u\=\s*[#%]\=.+\s*\zs.*$')")) + id = int(lfEval(r"matchadd('Lf_hl_bufModified', '^\s*\d\+\s*u\=\s*[#%]\=.+\s*\zs.*$')")) self._match_ids.append(id) - id = int(lfEval("matchadd('Lf_hl_bufNomodifiable', '^\s*\d\+\s*u\=\s*[#%]\=..-\s*\zs.*$')")) + id = int(lfEval(r"matchadd('Lf_hl_bufNomodifiable', '^\s*\d\+\s*u\=\s*[#%]\=..-\s*\zs.*$')")) self._match_ids.append(id) - id = int(lfEval('''matchadd('Lf_hl_bufDirname', ' \zs".*"$')''')) + id = int(lfEval(r'''matchadd('Lf_hl_bufDirname', ' \zs".*"$')''')) self._match_ids.append(id) # devicons diff --git a/autoload/leaderf/python/leaderf/bufTagExpl.py b/autoload/leaderf/python/leaderf/bufTagExpl.py index e4254ce5..3217fd6c 100644 --- a/autoload/leaderf/python/leaderf/bufTagExpl.py +++ b/autoload/leaderf/python/leaderf/bufTagExpl.py @@ -241,7 +241,7 @@ def _acceptSelection(self, *args, **kwargs): lfCmd("hide buffer +%s %s" % (line_num, buf_number)) if "preview" not in kwargs: lfCmd("norm! ^") - lfCmd("call search('\V%s', 'Wc', line('.'))" % escQuote(tagname)) + lfCmd(r"call search('\V%s', 'Wc', line('.'))" % escQuote(tagname)) lfCmd("norm! zv") lfCmd("norm! zz") @@ -304,42 +304,42 @@ def _afterEnter(self): lfCmd("autocmd VimLeavePre * call leaderf#BufTag#cleanup()") lfCmd("augroup END") if self._getInstance().getWinPos() == 'popup': - lfCmd("""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_buftagKind'', ''^[^\t]*\t\zs\S\+'')')""" + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_buftagKind'', ''^[^\t]*\t\zs\S\+'')')""" % self._getInstance().getPopupWinId()) id = int(lfEval("matchid")) self._match_ids.append(id) - lfCmd("""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_buftagScopeType'', ''[^\t]*\t\S\+\s*\zs\w\+:'')')""" + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_buftagScopeType'', ''[^\t]*\t\S\+\s*\zs\w\+:'')')""" % self._getInstance().getPopupWinId()) id = int(lfEval("matchid")) self._match_ids.append(id) - lfCmd("""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_buftagScope'', ''^[^\t]*\t\S\+\s*\(\w\+:\)\=\zs\S\+'')')""" + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_buftagScope'', ''^[^\t]*\t\S\+\s*\(\w\+:\)\=\zs\S\+'')')""" % self._getInstance().getPopupWinId()) id = int(lfEval("matchid")) self._match_ids.append(id) - lfCmd("""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_buftagDirname'', ''[^\t]*\t\S\+\s*\S\+\s*\zs[^\t]\+'')')""" + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_buftagDirname'', ''[^\t]*\t\S\+\s*\S\+\s*\zs[^\t]\+'')')""" % self._getInstance().getPopupWinId()) id = int(lfEval("matchid")) self._match_ids.append(id) - lfCmd("""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_buftagLineNum'', ''\d\+\t\ze\d\+$'')')""" + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_buftagLineNum'', ''\d\+\t\ze\d\+$'')')""" % self._getInstance().getPopupWinId()) id = int(lfEval("matchid")) self._match_ids.append(id) - lfCmd("""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_buftagCode'', ''^\s\+.*'')')""" + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_buftagCode'', ''^\s\+.*'')')""" % self._getInstance().getPopupWinId()) id = int(lfEval("matchid")) self._match_ids.append(id) else: - id = int(lfEval('''matchadd('Lf_hl_buftagKind', '^[^\t]*\t\zs\S\+')''')) + id = int(lfEval(r'''matchadd('Lf_hl_buftagKind', '^[^\t]*\t\zs\S\+')''')) self._match_ids.append(id) - id = int(lfEval('''matchadd('Lf_hl_buftagScopeType', '[^\t]*\t\S\+\s*\zs\w\+:')''')) + id = int(lfEval(r'''matchadd('Lf_hl_buftagScopeType', '[^\t]*\t\S\+\s*\zs\w\+:')''')) self._match_ids.append(id) - id = int(lfEval('''matchadd('Lf_hl_buftagScope', '^[^\t]*\t\S\+\s*\(\w\+:\)\=\zs\S\+')''')) + id = int(lfEval(r'''matchadd('Lf_hl_buftagScope', '^[^\t]*\t\S\+\s*\(\w\+:\)\=\zs\S\+')''')) self._match_ids.append(id) - id = int(lfEval('''matchadd('Lf_hl_buftagDirname', '[^\t]*\t\S\+\s*\S\+\s*\zs[^\t]\+')''')) + id = int(lfEval(r'''matchadd('Lf_hl_buftagDirname', '[^\t]*\t\S\+\s*\S\+\s*\zs[^\t]\+')''')) self._match_ids.append(id) - id = int(lfEval('''matchadd('Lf_hl_buftagLineNum', '\d\+\t\ze\d\+$')''')) + id = int(lfEval(r'''matchadd('Lf_hl_buftagLineNum', '\d\+\t\ze\d\+$')''')) self._match_ids.append(id) - id = int(lfEval('''matchadd('Lf_hl_buftagCode', '^\s\+.*')''')) + id = int(lfEval(r'''matchadd('Lf_hl_buftagCode', '^\s\+.*')''')) self._match_ids.append(id) def _beforeExit(self): diff --git a/autoload/leaderf/python/leaderf/cli.py b/autoload/leaderf/python/leaderf/cli.py index 5449d584..039a9017 100644 --- a/autoload/leaderf/python/leaderf/cli.py +++ b/autoload/leaderf/python/leaderf/cli.py @@ -425,7 +425,7 @@ def _buildPattern(self): def _join(self, cmdline): if not cmdline: return '' - cmd = ['%s\[^%s]\{-}' % (c, c) for c in cmdline[0:-1]] + cmd = [r'%s\[^%s]\{-}' % (c, c) for c in cmdline[0:-1]] cmd.append(cmdline[-1]) regex = ''.join(cmd) return regex @@ -447,31 +447,31 @@ def highlightMatches(self): cmdline = [r'\/' if c == '/' else r'\\' if c == '\\' else c for c in self._cmdline] # \/ for syn match if self._is_full_path: - regex = '\c\V' + self._join(cmdline) + regex = r'\c\V' + self._join(cmdline) lfCmd("syn match Lf_hl_match display /%s/ containedin=" "Lf_hl_nonHelp, Lf_hl_dirname, Lf_hl_filename contained" % regex) else: if self._refine: idx = self._cmdline.index(self._delimiter) - regex = ('\c\V' + self._join(cmdline[:idx]), - '\c\V' + self._join(cmdline[idx+1:])) - if regex[0] == '\c\V' and regex[1] == '\c\V': + regex = (r'\c\V' + self._join(cmdline[:idx]), + r'\c\V' + self._join(cmdline[idx+1:])) + if regex[0] == r'\c\V' and regex[1] == r'\c\V': pass - elif regex[0] == '\c\V': + elif regex[0] == r'\c\V': lfCmd("syn match Lf_hl_match display /%s/ " "containedin=Lf_hl_dirname, Lf_hl_filename " "contained" % regex[1]) - elif regex[1] == '\c\V': + elif regex[1] == r'\c\V': lfCmd("syn match Lf_hl_match display /%s/ " "containedin=Lf_hl_filename contained" % regex[0]) else: lfCmd("syn match Lf_hl_match display /%s/ " "containedin=Lf_hl_filename contained" % regex[0]) lfCmd("syn match Lf_hl_match_refine display " - "/%s\(\.\*\[\/]\)\@=/ containedin=" + r"/%s\(\.\*\[\/]\)\@=/ containedin=" "Lf_hl_dirname contained" % regex[1]) else: - regex = '\c\V' + self._join(cmdline) + regex = r'\c\V' + self._join(cmdline) lfCmd("syn match Lf_hl_match display /%s/ " "containedin=Lf_hl_filename contained" % regex) else: @@ -762,7 +762,7 @@ def input(self, callback): else: cmd = '' for (key, value) in self._key_dict.items(): - if lfEval('ch ==# "\%s"' % key) == '1': + if lfEval(r'ch ==# "\%s"' % key) == '1': cmd = value break if equal(cmd, ''): diff --git a/autoload/leaderf/python/leaderf/devicons.py b/autoload/leaderf/python/leaderf/devicons.py index a2469a27..7c86b98d 100644 --- a/autoload/leaderf/python/leaderf/devicons.py +++ b/autoload/leaderf/python/leaderf/devicons.py @@ -454,7 +454,7 @@ def _normalize_name(val): return RE_CANNOT_USE_FOR_HIGHLIGHT.sub('__', val) def _matchadd(icons, pattern, priority, winid): - """ + r""" Enable ignore case (\c flag) """ ids = [] @@ -478,7 +478,7 @@ def _matchadd(icons, pattern, priority, winid): return ids def matchaddDevIconsDefault(pattern, winid=None): - """ + r""" pattern: It will be converted to the following __icon__ => icon @@ -492,7 +492,7 @@ def convertor(pattern, _, glyph): return _matchadd({'default': fileNodesDefaultSymbol}, pattern, 9, winid) def matchaddDevIconsExact(pattern, winid=None): - """ + r""" pattern: It will be converted to the following __icon__ => icon @@ -504,7 +504,7 @@ def matchaddDevIconsExact(pattern, winid=None): return _matchadd(fileNodesExactSymbols, pattern, 8, winid) def matchaddDevIconsExtension(pattern, winid=None): - """ + r""" pattern: It will be converted to the following __icon__ => icon diff --git a/autoload/leaderf/python/leaderf/fileExpl.py b/autoload/leaderf/python/leaderf/fileExpl.py index 17f379e3..3930e9d2 100644 --- a/autoload/leaderf/python/leaderf/fileExpl.py +++ b/autoload/leaderf/python/leaderf/fileExpl.py @@ -107,7 +107,7 @@ def _getFileList(self, dir): target = i if target != -1: - lines[target] = re.sub('^\S*', + lines[target] = re.sub(r'^\S*', '%.3f' % time.time(), lines[target]) f.seek(0) @@ -185,7 +185,7 @@ def _refresh(self): target = i if target != -1: - lines[target] = re.sub('^\S*', '%.3f' % time.time(), lines[target]) + lines[target] = re.sub(r'^\S*', '%.3f' % time.time(), lines[target]) f.seek(0) f.truncate(0) f.writelines(lines) @@ -433,7 +433,7 @@ def _buildCmd(self, dir, **kwargs): followlinks = "" if lfEval("g:Lf_ShowRelativePath") == '1': - strip = "| sed 's#^\./##'" + strip = r"| sed 's#^\./##'" else: strip = "" @@ -490,7 +490,7 @@ def _writeCache(self, content): return # update the time - lines[target] = re.sub('^\S*', + lines[target] = re.sub(r'^\S*', '%.3f' % time.time(), lines[target]) f.seek(0) @@ -545,7 +545,7 @@ def _getFilesFromCache(self): if target != -1: # already cached # update the time - lines[target] = re.sub('^\S*', + lines[target] = re.sub(r'^\S*', '%.3f' % time.time(), lines[target]) f.seek(0) diff --git a/autoload/leaderf/python/leaderf/functionExpl.py b/autoload/leaderf/python/leaderf/functionExpl.py index 66b8069c..b93c019f 100644 --- a/autoload/leaderf/python/leaderf/functionExpl.py +++ b/autoload/leaderf/python/leaderf/functionExpl.py @@ -288,42 +288,42 @@ def _afterEnter(self): lfCmd("autocmd VimLeavePre * call leaderf#Function#cleanup()") lfCmd("augroup END") if self._getInstance().getWinPos() == 'popup': - lfCmd("""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_funcKind'', ''^\w'')')""" + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_funcKind'', ''^\w'')')""" % self._getInstance().getPopupWinId()) id = int(lfEval("matchid")) self._match_ids.append(id) - lfCmd("""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_funcReturnType'', ''^\w\t\zs.\{-}\ze\s*[~]\=\(\w\|[#:]\)\+\W\{-}[(\[]'')')""" + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_funcReturnType'', ''^\w\t\zs.\{-}\ze\s*[~]\=\(\w\|[#:]\)\+\W\{-}[(\[]'')')""" % self._getInstance().getPopupWinId()) id = int(lfEval("matchid")) self._match_ids.append(id) - lfCmd("""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_funcScope'', ''\w*\(<[^>]*>\)\=::'')')""" + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_funcScope'', ''\w*\(<[^>]*>\)\=::'')')""" % self._getInstance().getPopupWinId()) id = int(lfEval("matchid")) self._match_ids.append(id) - lfCmd("""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_funcName'', ''^\w\t.\{-}\s*\zs[~]\=\(\w\|[#:]\)\+\W\{-}\ze[(\[]'')')""" + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_funcName'', ''^\w\t.\{-}\s*\zs[~]\=\(\w\|[#:]\)\+\W\{-}\ze[(\[]'')')""" % self._getInstance().getPopupWinId()) id = int(lfEval("matchid")) self._match_ids.append(id) - lfCmd("""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_funcDirname'', ''\t\zs\[.*:\d\+ \d\+]$'')')""" + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_funcDirname'', ''\t\zs\[.*:\d\+ \d\+]$'')')""" % self._getInstance().getPopupWinId()) id = int(lfEval("matchid")) self._match_ids.append(id) - lfCmd("""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_funcLineNum'', '':\zs\d\+\ze \d\+]$'')')""" + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_funcLineNum'', '':\zs\d\+\ze \d\+]$'')')""" % self._getInstance().getPopupWinId()) id = int(lfEval("matchid")) self._match_ids.append(id) else: - id = int(lfEval('''matchadd('Lf_hl_funcKind', '^\w')''')) + id = int(lfEval(r'''matchadd('Lf_hl_funcKind', '^\w')''')) self._match_ids.append(id) - id = int(lfEval('''matchadd('Lf_hl_funcReturnType', '^\w\t\zs.\{-}\ze\s*[~]\=\(\w\|[#:]\)\+\W\{-}[(\[]')''')) + id = int(lfEval(r'''matchadd('Lf_hl_funcReturnType', '^\w\t\zs.\{-}\ze\s*[~]\=\(\w\|[#:]\)\+\W\{-}[(\[]')''')) self._match_ids.append(id) - id = int(lfEval('''matchadd('Lf_hl_funcScope', '\w*\(<[^>]*>\)\=::')''')) + id = int(lfEval(r'''matchadd('Lf_hl_funcScope', '\w*\(<[^>]*>\)\=::')''')) self._match_ids.append(id) - id = int(lfEval('''matchadd('Lf_hl_funcName', '^\w\t.\{-}\s*\zs[~]\=\(\w\|[#:]\)\+\W\{-}\ze[(\[]')''')) + id = int(lfEval(r'''matchadd('Lf_hl_funcName', '^\w\t.\{-}\s*\zs[~]\=\(\w\|[#:]\)\+\W\{-}\ze[(\[]')''')) self._match_ids.append(id) - id = int(lfEval('''matchadd('Lf_hl_funcDirname', '\t\zs\[.*:\d\+ \d\+]$')''')) + id = int(lfEval(r'''matchadd('Lf_hl_funcDirname', '\t\zs\[.*:\d\+ \d\+]$')''')) self._match_ids.append(id) - id = int(lfEval('''matchadd('Lf_hl_funcLineNum', ':\zs\d\+\ze \d\+]$')''')) + id = int(lfEval(r'''matchadd('Lf_hl_funcLineNum', ':\zs\d\+\ze \d\+]$')''')) self._match_ids.append(id) def _beforeExit(self): diff --git a/autoload/leaderf/python/leaderf/gtagsExpl.py b/autoload/leaderf/python/leaderf/gtagsExpl.py index 15a05e6b..e286cebe 100644 --- a/autoload/leaderf/python/leaderf/gtagsExpl.py +++ b/autoload/leaderf/python/leaderf/gtagsExpl.py @@ -294,7 +294,7 @@ def translateRegex(self, regex, is_perl=False): """ def replace(text, pattern, repl): - """ + r""" only replace pattern with even number of \ preceding it """ result = '' @@ -1084,24 +1084,24 @@ def _afterEnter(self): pass else: if self._getExplorer().getResultFormat() is None: - id = int(lfEval("""matchadd('Lf_hl_gtagsFileName', '^.\{-}\ze\t')""")) + id = int(lfEval(r"""matchadd('Lf_hl_gtagsFileName', '^.\{-}\ze\t')""")) self._match_ids.append(id) - id = int(lfEval("""matchadd('Lf_hl_gtagsLineNumber', '\t\zs\d\+\ze\t')""")) + id = int(lfEval(r"""matchadd('Lf_hl_gtagsLineNumber', '\t\zs\d\+\ze\t')""")) self._match_ids.append(id) elif self._getExplorer().getResultFormat() == "ctags": - id = int(lfEval("""matchadd('Lf_hl_gtagsFileName', '\t\zs.\{-}\ze\t')""")) + id = int(lfEval(r"""matchadd('Lf_hl_gtagsFileName', '\t\zs.\{-}\ze\t')""")) self._match_ids.append(id) - id = int(lfEval("""matchadd('Lf_hl_gtagsLineNumber', '\t\zs\d\+$')""")) + id = int(lfEval(r"""matchadd('Lf_hl_gtagsLineNumber', '\t\zs\d\+$')""")) self._match_ids.append(id) elif self._getExplorer().getResultFormat() == "ctags-x": - id = int(lfEval("""matchadd('Lf_hl_gtagsFileName', '^\S\+\s\+\d\+\s\+\zs\S\+')""")) + id = int(lfEval(r"""matchadd('Lf_hl_gtagsFileName', '^\S\+\s\+\d\+\s\+\zs\S\+')""")) self._match_ids.append(id) - id = int(lfEval("""matchadd('Lf_hl_gtagsLineNumber', '^\S\+\s\+\zs\d\+')""")) + id = int(lfEval(r"""matchadd('Lf_hl_gtagsLineNumber', '^\S\+\s\+\zs\d\+')""")) self._match_ids.append(id) else: # ctags-mod - id = int(lfEval("""matchadd('Lf_hl_gtagsFileName', '^.\{-}\ze\t')""")) + id = int(lfEval(r"""matchadd('Lf_hl_gtagsFileName', '^.\{-}\ze\t')""")) self._match_ids.append(id) - id = int(lfEval("""matchadd('Lf_hl_gtagsLineNumber', '\t\zs\d\+\ze\t')""")) + id = int(lfEval(r"""matchadd('Lf_hl_gtagsLineNumber', '\t\zs\d\+\ze\t')""")) self._match_ids.append(id) try: for i in self._getExplorer().getPatternRegex(): diff --git a/autoload/leaderf/python/leaderf/helpExpl.py b/autoload/leaderf/python/leaderf/helpExpl.py index 77425965..a76de389 100644 --- a/autoload/leaderf/python/leaderf/helpExpl.py +++ b/autoload/leaderf/python/leaderf/helpExpl.py @@ -125,12 +125,12 @@ def _createHelp(self): def _afterEnter(self): super(HelpExplManager, self)._afterEnter() if self._getInstance().getWinPos() == 'popup': - lfCmd("""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_helpTagfile'', '' \zs.*$'')')""" + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_helpTagfile'', '' \zs.*$'')')""" % self._getInstance().getPopupWinId()) id = int(lfEval("matchid")) self._match_ids.append(id) else: - id = int(lfEval('''matchadd('Lf_hl_helpTagfile', ' \zs.*$')''')) + id = int(lfEval(r'''matchadd('Lf_hl_helpTagfile', ' \zs.*$')''')) self._match_ids.append(id) def _beforeExit(self): @@ -146,7 +146,7 @@ def _previewInPopup(self, *args, **kwargs): line = args[0] tagname, tagfile, file_id = line.split(None, 2) tagfile = os.path.join(self._getExplorer()._file_ids[int(file_id)], tagfile) - jump_cmd = "call search('\m\*%s\*', 'w')" % escQuote(tagname) + jump_cmd = r"call search('\m\*%s\*', 'w')" % escQuote(tagname) self._createPopupPreview("", tagfile, 0, jump_cmd) diff --git a/autoload/leaderf/python/leaderf/jumpsExpl.py b/autoload/leaderf/python/leaderf/jumpsExpl.py index 07a5ab01..af49558a 100644 --- a/autoload/leaderf/python/leaderf/jumpsExpl.py +++ b/autoload/leaderf/python/leaderf/jumpsExpl.py @@ -86,9 +86,9 @@ def _acceptSelection(self, *args, **kwargs): else: number = line.split(None, 1)[0] if line.endswith('\t'): - lfCmd(':exec "norm! %s\"' % number) + lfCmd(r':exec "norm! %s\"' % number) else: - lfCmd(':exec "norm! %s\"' % number) + lfCmd(r':exec "norm! %s\"' % number) if "preview" not in kwargs: lfCmd("setlocal cursorline! | redraw | sleep 150m | setlocal cursorline!") @@ -132,28 +132,28 @@ def _createHelp(self): def _afterEnter(self): super(JumpsExplManager, self)._afterEnter() if self._getInstance().getWinPos() == 'popup': - lfCmd("""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_jumpsTitle'', ''^ \D\+'')')""" + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_jumpsTitle'', ''^ \D\+'')')""" % self._getInstance().getPopupWinId()) id = int(lfEval("matchid")) self._match_ids.append(id) - lfCmd("""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_jumpsNumber'', ''^>\?\s*\zs\d\+'')')""" + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_jumpsNumber'', ''^>\?\s*\zs\d\+'')')""" % self._getInstance().getPopupWinId()) id = int(lfEval("matchid")) self._match_ids.append(id) - lfCmd("""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_jumpsLineCol'', ''^>\?\s*\d\+\s*\zs\d\+\s*\d\+'')')""" + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_jumpsLineCol'', ''^>\?\s*\d\+\s*\zs\d\+\s*\d\+'')')""" % self._getInstance().getPopupWinId()) id = int(lfEval("matchid")) self._match_ids.append(id) - lfCmd("""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_jumpsIndicator'', ''^>'')')""" + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_jumpsIndicator'', ''^>'')')""" % self._getInstance().getPopupWinId()) id = int(lfEval("matchid")) self._match_ids.append(id) else: - id = int(lfEval('''matchadd('Lf_hl_jumpsTitle', '^ \D\+')''')) + id = int(lfEval(r'''matchadd('Lf_hl_jumpsTitle', '^ \D\+')''')) self._match_ids.append(id) - id = int(lfEval('''matchadd('Lf_hl_jumpsNumber', '^>\?\s*\zs\d\+')''')) + id = int(lfEval(r'''matchadd('Lf_hl_jumpsNumber', '^>\?\s*\zs\d\+')''')) self._match_ids.append(id) - id = int(lfEval('''matchadd('Lf_hl_jumpsLineCol', '^>\?\s*\d\+\s*\zs\d\+\s*\d\+')''')) + id = int(lfEval(r'''matchadd('Lf_hl_jumpsLineCol', '^>\?\s*\d\+\s*\zs\d\+\s*\d\+')''')) self._match_ids.append(id) id = int(lfEval('''matchadd('Lf_hl_jumpsIndicator', '^>')''')) self._match_ids.append(id) diff --git a/autoload/leaderf/python/leaderf/lineExpl.py b/autoload/leaderf/python/leaderf/lineExpl.py index 7f21e5bf..c26cedee 100644 --- a/autoload/leaderf/python/leaderf/lineExpl.py +++ b/autoload/leaderf/python/leaderf/lineExpl.py @@ -115,12 +115,12 @@ def _createHelp(self): def _afterEnter(self): super(LineExplManager, self)._afterEnter() if self._getInstance().getWinPos() == 'popup': - lfCmd("""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_lineLocation'', ''\t\zs\[.*:\d\+ \d\+]$'')')""" + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_lineLocation'', ''\t\zs\[.*:\d\+ \d\+]$'')')""" % self._getInstance().getPopupWinId()) id = int(lfEval("matchid")) self._match_ids.append(id) else: - id = int(lfEval('''matchadd('Lf_hl_lineLocation', '\t\zs\[.*:\d\+ \d\+]$')''')) + id = int(lfEval(r'''matchadd('Lf_hl_lineLocation', '\t\zs\[.*:\d\+ \d\+]$')''')) self._match_ids.append(id) def _beforeExit(self): diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 56524159..dfbb5667 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -316,10 +316,10 @@ def _afterEnter(self): self._defineCommonMaps() self._defineNormalCommandMaps() - id = int(lfEval("matchadd('Lf_hl_cursorline', '.*\%#.*', -100)")) + id = int(lfEval(r"matchadd('Lf_hl_cursorline', '.*\%#.*', -100)")) self._match_ids.append(id) else: - lfCmd("""call win_execute({}, 'let matchid = matchadd(''Lf_hl_cursorline'', ''.*\%#.*'', -100)')""" + lfCmd(r"""call win_execute({}, 'let matchid = matchadd(''Lf_hl_cursorline'', ''.*\%#.*'', -100)')""" .format(self._getInstance().getPopupWinId())) id = int(lfEval("matchid")) self._match_ids.append(id) @@ -1355,7 +1355,7 @@ def moveAndPreview(self, direction): lfCmd('noautocmd exec "norm! G"') else: if len(direction) > 1: - lfCmd('noautocmd exec "norm! \<{}>"'.format(direction)) + lfCmd(r'noautocmd exec "norm! \<{}>"'.format(direction)) else: lfCmd('noautocmd exec "norm! {}"'.format(direction)) @@ -1417,7 +1417,7 @@ def _toDown(self): def _pageUp(self): if self._getInstance().getWinPos() == 'popup': - lfCmd("""call win_execute(%d, 'exec "norm! \"')""" % (self._getInstance().getPopupWinId())) + lfCmd(r"""call win_execute(%d, 'exec "norm! \"')""" % (self._getInstance().getPopupWinId())) self._getInstance().refreshPopupStatusline() return @@ -1428,20 +1428,20 @@ def _pageUp(self): and len(self._highlight_pos) < int(lfEval("g:Lf_NumberOfHighlight")): self._highlight_method() - lfCmd('noautocmd exec "norm! \"') + lfCmd(r'noautocmd exec "norm! \"') self._getInstance().setLineNumber() def _pageDown(self): if self._getInstance().getWinPos() == 'popup': - lfCmd("""call win_execute(%d, 'exec "norm! \"')""" % (self._getInstance().getPopupWinId())) + lfCmd(r"""call win_execute(%d, 'exec "norm! \"')""" % (self._getInstance().getPopupWinId())) self._getInstance().refreshPopupStatusline() return if not self._getInstance().isReverseOrder(): self._setResultContent() - lfCmd('noautocmd exec "norm! \"') + lfCmd(r'noautocmd exec "norm! \"') self._getInstance().setLineNumber() @@ -1472,13 +1472,13 @@ def _leftClick(self): def _scrollUp(self): if lfEval('exists("*getmousepos")') == '1': - lfCmd("""call win_execute(getmousepos().winid, "norm! 3\")""") + lfCmd(r"""call win_execute(getmousepos().winid, "norm! 3\")""") else: self._toUp() def _scrollDown(self): if lfEval('exists("*getmousepos")') == '1': - lfCmd("""call win_execute(getmousepos().winid, "norm! 3\")""") + lfCmd(r"""call win_execute(getmousepos().winid, "norm! 3\")""") else: self._toDown() @@ -2569,7 +2569,7 @@ def addSelections(self): % (self._getInstance().getPopupWinId(), line_num)) id = int(lfEval("matchid")) else: - id = int(lfEval("matchadd('Lf_hl_selection', '\%%%dl.')" % line_num)) + id = int(lfEval(r"matchadd('Lf_hl_selection', '\%%%dl.')" % line_num)) self._selections[line_num] = id def selectMulti(self): @@ -2583,7 +2583,7 @@ def selectMulti(self): self.clearSelections() for i in range(min(orig_line, cur_line), max(orig_line, cur_line)+1): if i > self._help_length and i not in self._selections: - id = int(lfEval("matchadd('Lf_hl_selection', '\%%%dl.')" % (i))) + id = int(lfEval(r"matchadd('Lf_hl_selection', '\%%%dl.')" % (i))) self._selections[i] = id def selectAll(self): @@ -2599,7 +2599,7 @@ def selectAll(self): % (self._getInstance().getPopupWinId(), i+1)) id = int(lfEval("matchid")) else: - id = int(lfEval("matchadd('Lf_hl_selection', '\%%%dl.')" % (i+1))) + id = int(lfEval(r"matchadd('Lf_hl_selection', '\%%%dl.')" % (i+1))) self._selections[i+1] = id def _gotoFirstLine(self): @@ -3086,7 +3086,7 @@ def input(self): elif equal(cmd, ''): if self.accept('t') is None: break - elif equal(cmd, ''): + elif equal(cmd, r''): actions = ['', 'h', 'v', 't', 'dr'] action_count = len(actions) selection = int( vim.eval( diff --git a/autoload/leaderf/python/leaderf/mruExpl.py b/autoload/leaderf/python/leaderf/mruExpl.py index a86cc241..ca10d10d 100644 --- a/autoload/leaderf/python/leaderf/mruExpl.py +++ b/autoload/leaderf/python/leaderf/mruExpl.py @@ -323,12 +323,12 @@ def _afterEnter(self): if "--no-split-path" not in self._arguments: if self._getInstance().getWinPos() == 'popup': - lfCmd("""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_bufDirname'', '' \zs".*"$'')')""" + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_bufDirname'', '' \zs".*"$'')')""" % self._getInstance().getPopupWinId()) id = int(lfEval("matchid")) self._match_ids.append(id) else: - id = int(lfEval('''matchadd('Lf_hl_bufDirname', ' \zs".*"$')''')) + id = int(lfEval(r'''matchadd('Lf_hl_bufDirname', ' \zs".*"$')''')) self._match_ids.append(id) if lfEval("get(g:, 'Lf_ShowDevIcons', 1)") == '1': diff --git a/autoload/leaderf/python/leaderf/rgExpl.py b/autoload/leaderf/python/leaderf/rgExpl.py index de4b17b0..bc23f614 100644 --- a/autoload/leaderf/python/leaderf/rgExpl.py +++ b/autoload/leaderf/python/leaderf/rgExpl.py @@ -345,7 +345,7 @@ def removeFiles(names): def translateRegex(self, regex, is_perl=False): def replace(text, pattern, repl): - """ + r""" only replace pattern with even number of \ preceding it """ result = '' @@ -705,47 +705,47 @@ def _afterEnter(self): if self._getInstance().getWinPos() == 'popup': if "--heading" in self._arguments: if "-A" in self._arguments or "-B" in self._arguments or "-C" in self._arguments: - lfCmd("""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_rgFileName'', ''\(^\d\+[:-].*\)\@ 1: - result = re.search('(?<=\t)line:\d+', res[1]) + result = re.search(r'(?<=\t)line:\d+', res[1]) if result: line_num = result.group(0).split(':')[1] lfCmd(line_num) else: # for c, c++ keyword = "(class|enum|struct|union)" - result = re.search('(?<=\t)%s:\S+' % keyword, res[1]) + result = re.search(r'(?<=\t)%s:\S+' % keyword, res[1]) if result: tagfield = result.group(0).split(":") name = tagfield[0] value = tagfield[-1] - lfCmd("call search('\m%s\_s\+%s\_[^;{]*{', 'w')" % (name, value)) + lfCmd(r"call search('\m%s\_s\+%s\_[^;{]*{', 'w')" % (name, value)) - pattern = "\M" + tagaddress[1:-1] + pattern = r"\M" + tagaddress[1:-1] lfCmd("call search('%s', 'w')" % escQuote(pattern)) - if lfEval("search('\V%s', 'wc')" % escQuote(tagname)) == '0': + if lfEval(r"search('\V%s', 'wc')" % escQuote(tagname)) == '0': lfCmd("norm! ^") lfCmd("norm! zv") lfCmd("norm! zz") @@ -163,28 +163,28 @@ def _createHelp(self): def _afterEnter(self): super(TagExplManager, self)._afterEnter() if self._getInstance().getWinPos() == 'popup': - lfCmd("""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_tagFile'', ''^.\{-}\t\zs.\{-}\ze\t'')')""" + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_tagFile'', ''^.\{-}\t\zs.\{-}\ze\t'')')""" % self._getInstance().getPopupWinId()) id = int(lfEval("matchid")) self._match_ids.append(id) - lfCmd("""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_tagType'', '';"\t\zs[cdefFgmpstuv]\ze\(\t\|$\)'')')""" + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_tagType'', '';"\t\zs[cdefFgmpstuv]\ze\(\t\|$\)'')')""" % self._getInstance().getPopupWinId()) id = int(lfEval("matchid")) self._match_ids.append(id) keyword = ["namespace", "class", "enum", "file", "function", "kind", "struct", "union"] for i in keyword: - lfCmd("""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_tagKeyword'', ''\(;"\t.\{-}\)\@<=%s:'')')""" + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_tagKeyword'', ''\(;"\t.\{-}\)\@<=%s:'')')""" % (self._getInstance().getPopupWinId(), i)) id = int(lfEval("matchid")) self._match_ids.append(id) else: - id = int(lfEval('''matchadd('Lf_hl_tagFile', '^.\{-}\t\zs.\{-}\ze\t')''')) + id = int(lfEval(r'''matchadd('Lf_hl_tagFile', '^.\{-}\t\zs.\{-}\ze\t')''')) self._match_ids.append(id) - id = int(lfEval('''matchadd('Lf_hl_tagType', ';"\t\zs[cdefFgmpstuv]\ze\(\t\|$\)')''')) + id = int(lfEval(r'''matchadd('Lf_hl_tagType', ';"\t\zs[cdefFgmpstuv]\ze\(\t\|$\)')''')) self._match_ids.append(id) keyword = ["namespace", "class", "enum", "file", "function", "kind", "struct", "union"] for i in keyword: - id = int(lfEval('''matchadd('Lf_hl_tagKeyword', '\(;"\t.\{-}\)\@<=%s:')''' % i)) + id = int(lfEval(r'''matchadd('Lf_hl_tagKeyword', '\(;"\t.\{-}\)\@<=%s:')''' % i)) self._match_ids.append(id) def _beforeExit(self): @@ -224,21 +224,21 @@ def _previewInPopup(self, *args, **kwargs): else: # In case there are mutiple matches. if len(res) > 1: - result = re.search('(?<=\t)line:\d+', res[1]) + result = re.search(r'(?<=\t)line:\d+', res[1]) if result: line_num = result.group(0).split(':')[1] self._createPopupPreview("", tagfile, line_num) else: # for c, c++ keyword = "(class|enum|struct|union)" - result = re.search('(?<=\t)%s:\S+' % keyword, res[1]) + result = re.search(r'(?<=\t)%s:\S+' % keyword, res[1]) jump_cmd = 'exec "norm! gg"' if result: tagfield = result.group(0).split(":") name = tagfield[0] value = tagfield[-1] - jump_cmd += " | call search('\m%s\_s\+%s\_[^;{]*{', 'w')" % (name, value) + jump_cmd += r" | call search('\m%s\_s\+%s\_[^;{]*{', 'w')" % (name, value) - pattern = "\M" + tagaddress[1:-1] + pattern = r"\M" + tagaddress[1:-1] jump_cmd += " | call search('%s', 'w')" % escQuote(pattern) self._createPopupPreview("", tagfile, 0, jump_cmd) From d8bd4a5b7d5975543b62c44cd06fd46bb1d83a9e Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Mon, 25 Dec 2023 11:24:11 +0800 Subject: [PATCH 147/365] fix issue #1049 --- autoload/leaderf/Any.vim | 12 ++++++------ autoload/leaderf/BufTag.vim | 12 ++++++------ autoload/leaderf/Buffer.vim | 12 ++++++------ autoload/leaderf/Colors.vim | 12 ++++++------ autoload/leaderf/File.vim | 12 ++++++------ autoload/leaderf/Function.vim | 12 ++++++------ autoload/leaderf/Gtags.vim | 12 ++++++------ autoload/leaderf/Help.vim | 12 ++++++------ autoload/leaderf/Jumps.vim | 12 ++++++------ autoload/leaderf/Line.vim | 12 ++++++------ autoload/leaderf/Mru.vim | 12 ++++++------ autoload/leaderf/Rg.vim | 12 ++++++------ autoload/leaderf/Tag.vim | 12 ++++++------ autoload/leaderf/python/leaderf/manager.py | 6 ++++-- 14 files changed, 82 insertions(+), 80 deletions(-) diff --git a/autoload/leaderf/Any.vim b/autoload/leaderf/Any.vim index d4376cd0..66ffe93d 100644 --- a/autoload/leaderf/Any.vim +++ b/autoload/leaderf/Any.vim @@ -28,12 +28,12 @@ function! leaderf#Any#Maps(category) nnoremap :exec g:Lf_py b:Lf_AnyExplManager."input()" nnoremap :exec g:Lf_py b:Lf_AnyExplManager."toggleHelp()" nnoremap p :exec g:Lf_py b:Lf_AnyExplManager."_previewResult(True)" - nnoremap j :exec g:Lf_py b:Lf_AnyExplManager.moveAndPreview('j')" - nnoremap k :exec g:Lf_py b:Lf_AnyExplManager.moveAndPreview('k')" - nnoremap :exec g:Lf_py b:Lf_AnyExplManager.moveAndPreview('Up')" - nnoremap :exec g:Lf_py b:Lf_AnyExplManager.moveAndPreview('Down')" - nnoremap :exec g:Lf_py b:Lf_AnyExplManager.moveAndPreview('PageUp')" - nnoremap :exec g:Lf_py b:Lf_AnyExplManager.moveAndPreview('PageDown')" + nnoremap j :exec g:Lf_py b:Lf_AnyExplManager.moveAndPreview('j')" + nnoremap k :exec g:Lf_py b:Lf_AnyExplManager.moveAndPreview('k')" + nnoremap :exec g:Lf_py b:Lf_AnyExplManager.moveAndPreview('Up')" + nnoremap :exec g:Lf_py b:Lf_AnyExplManager.moveAndPreview('Down')" + nnoremap :exec g:Lf_py b:Lf_AnyExplManager.moveAndPreview('PageUp')" + nnoremap :exec g:Lf_py b:Lf_AnyExplManager.moveAndPreview('PageDown')" nnoremap :exec g:Lf_py b:Lf_AnyExplManager."_toUpInPopup()" nnoremap :exec g:Lf_py b:Lf_AnyExplManager."_toDownInPopup()" nnoremap :exec g:Lf_py b:Lf_AnyExplManager."closePreviewPopupOrQuit()" diff --git a/autoload/leaderf/BufTag.vim b/autoload/leaderf/BufTag.vim index 929ce13a..fdbbf10e 100644 --- a/autoload/leaderf/BufTag.vim +++ b/autoload/leaderf/BufTag.vim @@ -27,12 +27,12 @@ function! leaderf#BufTag#Maps() nnoremap :exec g:Lf_py "bufTagExplManager.input()" nnoremap :exec g:Lf_py "bufTagExplManager.toggleHelp()" nnoremap p :exec g:Lf_py "bufTagExplManager._previewResult(True)" - nnoremap j :exec g:Lf_py "bufTagExplManager.moveAndPreview('j')" - nnoremap k :exec g:Lf_py "bufTagExplManager.moveAndPreview('k')" - nnoremap :exec g:Lf_py "bufTagExplManager.moveAndPreview('Up')" - nnoremap :exec g:Lf_py "bufTagExplManager.moveAndPreview('Down')" - nnoremap :exec g:Lf_py "bufTagExplManager.moveAndPreview('PageUp')" - nnoremap :exec g:Lf_py "bufTagExplManager.moveAndPreview('PageDown')" + nnoremap j :exec g:Lf_py "bufTagExplManager.moveAndPreview('j')" + nnoremap k :exec g:Lf_py "bufTagExplManager.moveAndPreview('k')" + nnoremap :exec g:Lf_py "bufTagExplManager.moveAndPreview('Up')" + nnoremap :exec g:Lf_py "bufTagExplManager.moveAndPreview('Down')" + nnoremap :exec g:Lf_py "bufTagExplManager.moveAndPreview('PageUp')" + nnoremap :exec g:Lf_py "bufTagExplManager.moveAndPreview('PageDown')" nnoremap :exec g:Lf_py "bufTagExplManager._toUpInPopup()" nnoremap :exec g:Lf_py "bufTagExplManager._toDownInPopup()" nnoremap :exec g:Lf_py "bufTagExplManager.closePreviewPopupOrQuit()" diff --git a/autoload/leaderf/Buffer.vim b/autoload/leaderf/Buffer.vim index be3fe410..3f1d5462 100644 --- a/autoload/leaderf/Buffer.vim +++ b/autoload/leaderf/Buffer.vim @@ -29,12 +29,12 @@ function! leaderf#Buffer#Maps() nnoremap d :exec g:Lf_py "bufExplManager.deleteBuffer(1)" nnoremap D :exec g:Lf_py "bufExplManager.deleteBuffer()" nnoremap p :exec g:Lf_py "bufExplManager._previewResult(True)" - nnoremap j :exec g:Lf_py "bufExplManager.moveAndPreview('j')" - nnoremap k :exec g:Lf_py "bufExplManager.moveAndPreview('k')" - nnoremap :exec g:Lf_py "bufExplManager.moveAndPreview('Up')" - nnoremap :exec g:Lf_py "bufExplManager.moveAndPreview('Down')" - nnoremap :exec g:Lf_py "bufExplManager.moveAndPreview('PageUp')" - nnoremap :exec g:Lf_py "bufExplManager.moveAndPreview('PageDown')" + nnoremap j :exec g:Lf_py "bufExplManager.moveAndPreview('j')" + nnoremap k :exec g:Lf_py "bufExplManager.moveAndPreview('k')" + nnoremap :exec g:Lf_py "bufExplManager.moveAndPreview('Up')" + nnoremap :exec g:Lf_py "bufExplManager.moveAndPreview('Down')" + nnoremap :exec g:Lf_py "bufExplManager.moveAndPreview('PageUp')" + nnoremap :exec g:Lf_py "bufExplManager.moveAndPreview('PageDown')" nnoremap :exec g:Lf_py "bufExplManager._toUpInPopup()" nnoremap :exec g:Lf_py "bufExplManager._toDownInPopup()" nnoremap :exec g:Lf_py "bufExplManager.closePreviewPopupOrQuit()" diff --git a/autoload/leaderf/Colors.vim b/autoload/leaderf/Colors.vim index d4f35d83..07f63b59 100644 --- a/autoload/leaderf/Colors.vim +++ b/autoload/leaderf/Colors.vim @@ -24,12 +24,12 @@ function! leaderf#Colors#Maps() nnoremap :exec g:Lf_py "colorschemeExplManager.input()" nnoremap :exec g:Lf_py "colorschemeExplManager.toggleHelp()" nnoremap p :exec g:Lf_py "colorschemeExplManager._previewResult(True)" - nnoremap j :exec g:Lf_py "colorschemeExplManager.moveAndPreview('j')" - nnoremap k :exec g:Lf_py "colorschemeExplManager.moveAndPreview('k')" - nnoremap :exec g:Lf_py "colorschemeExplManager.moveAndPreview('Up')" - nnoremap :exec g:Lf_py "colorschemeExplManager.moveAndPreview('Down')" - nnoremap :exec g:Lf_py "colorschemeExplManager.moveAndPreview('PageUp')" - nnoremap :exec g:Lf_py "colorschemeExplManager.moveAndPreview('PageDown')" + nnoremap j :exec g:Lf_py "colorschemeExplManager.moveAndPreview('j')" + nnoremap k :exec g:Lf_py "colorschemeExplManager.moveAndPreview('k')" + nnoremap :exec g:Lf_py "colorschemeExplManager.moveAndPreview('Up')" + nnoremap :exec g:Lf_py "colorschemeExplManager.moveAndPreview('Down')" + nnoremap :exec g:Lf_py "colorschemeExplManager.moveAndPreview('PageUp')" + nnoremap :exec g:Lf_py "colorschemeExplManager.moveAndPreview('PageDown')" if has_key(g:Lf_NormalMap, "Colorscheme") for i in g:Lf_NormalMap["Colorscheme"] exec 'nnoremap '.i[0].' '.i[1] diff --git a/autoload/leaderf/File.vim b/autoload/leaderf/File.vim index 36f8a62b..e901c1e9 100644 --- a/autoload/leaderf/File.vim +++ b/autoload/leaderf/File.vim @@ -31,12 +31,12 @@ function! leaderf#File#Maps() nnoremap a :exec g:Lf_py "fileExplManager.selectAll()" nnoremap c :exec g:Lf_py "fileExplManager.clearSelections()" nnoremap p :exec g:Lf_py "fileExplManager._previewResult(True)" - nnoremap j :exec g:Lf_py "fileExplManager.moveAndPreview('j')" - nnoremap k :exec g:Lf_py "fileExplManager.moveAndPreview('k')" - nnoremap :exec g:Lf_py "fileExplManager.moveAndPreview('Up')" - nnoremap :exec g:Lf_py "fileExplManager.moveAndPreview('Down')" - nnoremap :exec g:Lf_py "fileExplManager.moveAndPreview('PageUp')" - nnoremap :exec g:Lf_py "fileExplManager.moveAndPreview('PageDown')" + nnoremap j :exec g:Lf_py "fileExplManager.moveAndPreview('j')" + nnoremap k :exec g:Lf_py "fileExplManager.moveAndPreview('k')" + nnoremap :exec g:Lf_py "fileExplManager.moveAndPreview('Up')" + nnoremap :exec g:Lf_py "fileExplManager.moveAndPreview('Down')" + nnoremap :exec g:Lf_py "fileExplManager.moveAndPreview('PageUp')" + nnoremap :exec g:Lf_py "fileExplManager.moveAndPreview('PageDown')" nnoremap :exec g:Lf_py "fileExplManager._toUpInPopup()" nnoremap :exec g:Lf_py "fileExplManager._toDownInPopup()" nnoremap :exec g:Lf_py "fileExplManager.closePreviewPopupOrQuit()" diff --git a/autoload/leaderf/Function.vim b/autoload/leaderf/Function.vim index db6638b4..151eccd4 100644 --- a/autoload/leaderf/Function.vim +++ b/autoload/leaderf/Function.vim @@ -27,12 +27,12 @@ function! leaderf#Function#Maps() nnoremap :exec g:Lf_py "functionExplManager.input()" nnoremap :exec g:Lf_py "functionExplManager.toggleHelp()" nnoremap p :exec g:Lf_py "functionExplManager._previewResult(True)" - nnoremap j :exec g:Lf_py "functionExplManager.moveAndPreview('j')" - nnoremap k :exec g:Lf_py "functionExplManager.moveAndPreview('k')" - nnoremap :exec g:Lf_py "functionExplManager.moveAndPreview('Up')" - nnoremap :exec g:Lf_py "functionExplManager.moveAndPreview('Down')" - nnoremap :exec g:Lf_py "functionExplManager.moveAndPreview('PageUp')" - nnoremap :exec g:Lf_py "functionExplManager.moveAndPreview('PageDown')" + nnoremap j :exec g:Lf_py "functionExplManager.moveAndPreview('j')" + nnoremap k :exec g:Lf_py "functionExplManager.moveAndPreview('k')" + nnoremap :exec g:Lf_py "functionExplManager.moveAndPreview('Up')" + nnoremap :exec g:Lf_py "functionExplManager.moveAndPreview('Down')" + nnoremap :exec g:Lf_py "functionExplManager.moveAndPreview('PageUp')" + nnoremap :exec g:Lf_py "functionExplManager.moveAndPreview('PageDown')" nnoremap :exec g:Lf_py "functionExplManager._toUpInPopup()" nnoremap :exec g:Lf_py "functionExplManager._toDownInPopup()" nnoremap :exec g:Lf_py "functionExplManager.closePreviewPopupOrQuit()" diff --git a/autoload/leaderf/Gtags.vim b/autoload/leaderf/Gtags.vim index 73030c68..89fddc96 100644 --- a/autoload/leaderf/Gtags.vim +++ b/autoload/leaderf/Gtags.vim @@ -23,12 +23,12 @@ function! leaderf#Gtags#Maps() nnoremap v :exec g:Lf_py "gtagsExplManager.accept('v')" nnoremap t :exec g:Lf_py "gtagsExplManager.accept('t')" nnoremap p :exec g:Lf_py "gtagsExplManager._previewResult(True)" - nnoremap j :exec g:Lf_py "gtagsExplManager.moveAndPreview('j')" - nnoremap k :exec g:Lf_py "gtagsExplManager.moveAndPreview('k')" - nnoremap :exec g:Lf_py "gtagsExplManager.moveAndPreview('Up')" - nnoremap :exec g:Lf_py "gtagsExplManager.moveAndPreview('Down')" - nnoremap :exec g:Lf_py "gtagsExplManager.moveAndPreview('PageUp')" - nnoremap :exec g:Lf_py "gtagsExplManager.moveAndPreview('PageDown')" + nnoremap j :exec g:Lf_py "gtagsExplManager.moveAndPreview('j')" + nnoremap k :exec g:Lf_py "gtagsExplManager.moveAndPreview('k')" + nnoremap :exec g:Lf_py "gtagsExplManager.moveAndPreview('Up')" + nnoremap :exec g:Lf_py "gtagsExplManager.moveAndPreview('Down')" + nnoremap :exec g:Lf_py "gtagsExplManager.moveAndPreview('PageUp')" + nnoremap :exec g:Lf_py "gtagsExplManager.moveAndPreview('PageDown')" nnoremap q :exec g:Lf_py "gtagsExplManager.quit()" " nnoremap :exec g:Lf_py "gtagsExplManager.quit()" nnoremap i :exec g:Lf_py "gtagsExplManager.input()" diff --git a/autoload/leaderf/Help.vim b/autoload/leaderf/Help.vim index c6ed1986..568f6cd8 100644 --- a/autoload/leaderf/Help.vim +++ b/autoload/leaderf/Help.vim @@ -22,12 +22,12 @@ function! leaderf#Help#Maps() nnoremap v :exec g:Lf_py "helpExplManager.accept('v')" nnoremap t :exec g:Lf_py "helpExplManager.accept('t')" nnoremap p :exec g:Lf_py "helpExplManager._previewResult(True)" - nnoremap j :exec g:Lf_py "helpExplManager.moveAndPreview('j')" - nnoremap k :exec g:Lf_py "helpExplManager.moveAndPreview('k')" - nnoremap :exec g:Lf_py "helpExplManager.moveAndPreview('Up')" - nnoremap :exec g:Lf_py "helpExplManager.moveAndPreview('Down')" - nnoremap :exec g:Lf_py "helpExplManager.moveAndPreview('PageUp')" - nnoremap :exec g:Lf_py "helpExplManager.moveAndPreview('PageDown')" + nnoremap j :exec g:Lf_py "helpExplManager.moveAndPreview('j')" + nnoremap k :exec g:Lf_py "helpExplManager.moveAndPreview('k')" + nnoremap :exec g:Lf_py "helpExplManager.moveAndPreview('Up')" + nnoremap :exec g:Lf_py "helpExplManager.moveAndPreview('Down')" + nnoremap :exec g:Lf_py "helpExplManager.moveAndPreview('PageUp')" + nnoremap :exec g:Lf_py "helpExplManager.moveAndPreview('PageDown')" nnoremap q :exec g:Lf_py "helpExplManager.quit()" " nnoremap :exec g:Lf_py "helpExplManager.quit()" nnoremap i :exec g:Lf_py "helpExplManager.input()" diff --git a/autoload/leaderf/Jumps.vim b/autoload/leaderf/Jumps.vim index 7d9f5efe..8566bf0d 100644 --- a/autoload/leaderf/Jumps.vim +++ b/autoload/leaderf/Jumps.vim @@ -28,12 +28,12 @@ function! leaderf#Jumps#Maps() nnoremap :exec g:Lf_py "jumpsExplManager.toggleHelp()" nnoremap :exec g:Lf_py "jumpsExplManager.refresh()" nnoremap p :exec g:Lf_py "jumpsExplManager._previewResult(True)" - nnoremap j :exec g:Lf_py "jumpsExplManager.moveAndPreview('j')" - nnoremap k :exec g:Lf_py "jumpsExplManager.moveAndPreview('k')" - nnoremap :exec g:Lf_py "jumpsExplManager.moveAndPreview('Up')" - nnoremap :exec g:Lf_py "jumpsExplManager.moveAndPreview('Down')" - nnoremap :exec g:Lf_py "jumpsExplManager.moveAndPreview('PageUp')" - nnoremap :exec g:Lf_py "jumpsExplManager.moveAndPreview('PageDown')" + nnoremap j :exec g:Lf_py "jumpsExplManager.moveAndPreview('j')" + nnoremap k :exec g:Lf_py "jumpsExplManager.moveAndPreview('k')" + nnoremap :exec g:Lf_py "jumpsExplManager.moveAndPreview('Up')" + nnoremap :exec g:Lf_py "jumpsExplManager.moveAndPreview('Down')" + nnoremap :exec g:Lf_py "jumpsExplManager.moveAndPreview('PageUp')" + nnoremap :exec g:Lf_py "jumpsExplManager.moveAndPreview('PageDown')" nnoremap :exec g:Lf_py "jumpsExplManager._toUpInPopup()" nnoremap :exec g:Lf_py "jumpsExplManager._toDownInPopup()" nnoremap :exec g:Lf_py "jumpsExplManager.closePreviewPopupOrQuit()" diff --git a/autoload/leaderf/Line.vim b/autoload/leaderf/Line.vim index a758bf86..21ac937b 100644 --- a/autoload/leaderf/Line.vim +++ b/autoload/leaderf/Line.vim @@ -27,12 +27,12 @@ function! leaderf#Line#Maps() nnoremap :exec g:Lf_py "lineExplManager.input()" nnoremap :exec g:Lf_py "lineExplManager.toggleHelp()" nnoremap p :exec g:Lf_py "lineExplManager._previewResult(True)" - nnoremap j :exec g:Lf_py "lineExplManager.moveAndPreview('j')" - nnoremap k :exec g:Lf_py "lineExplManager.moveAndPreview('k')" - nnoremap :exec g:Lf_py "lineExplManager.moveAndPreview('Up')" - nnoremap :exec g:Lf_py "lineExplManager.moveAndPreview('Down')" - nnoremap :exec g:Lf_py "lineExplManager.moveAndPreview('PageUp')" - nnoremap :exec g:Lf_py "lineExplManager.moveAndPreview('PageDown')" + nnoremap j :exec g:Lf_py "lineExplManager.moveAndPreview('j')" + nnoremap k :exec g:Lf_py "lineExplManager.moveAndPreview('k')" + nnoremap :exec g:Lf_py "lineExplManager.moveAndPreview('Up')" + nnoremap :exec g:Lf_py "lineExplManager.moveAndPreview('Down')" + nnoremap :exec g:Lf_py "lineExplManager.moveAndPreview('PageUp')" + nnoremap :exec g:Lf_py "lineExplManager.moveAndPreview('PageDown')" nnoremap Q :exec g:Lf_py "lineExplManager.outputToQflist()" nnoremap L :exec g:Lf_py "lineExplManager.outputToLoclist()" nnoremap :exec g:Lf_py "lineExplManager._toUpInPopup()" diff --git a/autoload/leaderf/Mru.vim b/autoload/leaderf/Mru.vim index bd6e064d..0a9070dc 100644 --- a/autoload/leaderf/Mru.vim +++ b/autoload/leaderf/Mru.vim @@ -31,12 +31,12 @@ function! leaderf#Mru#Maps() nnoremap a :exec g:Lf_py "mruExplManager.selectAll()" nnoremap c :exec g:Lf_py "mruExplManager.clearSelections()" nnoremap p :exec g:Lf_py "mruExplManager._previewResult(True)" - nnoremap j :exec g:Lf_py "mruExplManager.moveAndPreview('j')" - nnoremap k :exec g:Lf_py "mruExplManager.moveAndPreview('k')" - nnoremap :exec g:Lf_py "mruExplManager.moveAndPreview('Up')" - nnoremap :exec g:Lf_py "mruExplManager.moveAndPreview('Down')" - nnoremap :exec g:Lf_py "mruExplManager.moveAndPreview('PageUp')" - nnoremap :exec g:Lf_py "mruExplManager.moveAndPreview('PageDown')" + nnoremap j :exec g:Lf_py "mruExplManager.moveAndPreview('j')" + nnoremap k :exec g:Lf_py "mruExplManager.moveAndPreview('k')" + nnoremap :exec g:Lf_py "mruExplManager.moveAndPreview('Up')" + nnoremap :exec g:Lf_py "mruExplManager.moveAndPreview('Down')" + nnoremap :exec g:Lf_py "mruExplManager.moveAndPreview('PageUp')" + nnoremap :exec g:Lf_py "mruExplManager.moveAndPreview('PageDown')" nnoremap :exec g:Lf_py "mruExplManager._toUpInPopup()" nnoremap :exec g:Lf_py "mruExplManager._toDownInPopup()" nnoremap :exec g:Lf_py "mruExplManager.closePreviewPopupOrQuit()" diff --git a/autoload/leaderf/Rg.vim b/autoload/leaderf/Rg.vim index 409ef046..436155d0 100644 --- a/autoload/leaderf/Rg.vim +++ b/autoload/leaderf/Rg.vim @@ -22,12 +22,12 @@ function! leaderf#Rg#Maps(heading) nnoremap v :exec g:Lf_py "rgExplManager.accept('v')" nnoremap t :exec g:Lf_py "rgExplManager.accept('t')" nnoremap p :exec g:Lf_py "rgExplManager._previewResult(True)" - nnoremap j :exec g:Lf_py "rgExplManager.moveAndPreview('j')" - nnoremap k :exec g:Lf_py "rgExplManager.moveAndPreview('k')" - nnoremap :exec g:Lf_py "rgExplManager.moveAndPreview('Up')" - nnoremap :exec g:Lf_py "rgExplManager.moveAndPreview('Down')" - nnoremap :exec g:Lf_py "rgExplManager.moveAndPreview('PageUp')" - nnoremap :exec g:Lf_py "rgExplManager.moveAndPreview('PageDown')" + nnoremap j :exec g:Lf_py "rgExplManager.moveAndPreview('j')" + nnoremap k :exec g:Lf_py "rgExplManager.moveAndPreview('k')" + nnoremap :exec g:Lf_py "rgExplManager.moveAndPreview('Up')" + nnoremap :exec g:Lf_py "rgExplManager.moveAndPreview('Down')" + nnoremap :exec g:Lf_py "rgExplManager.moveAndPreview('PageUp')" + nnoremap :exec g:Lf_py "rgExplManager.moveAndPreview('PageDown')" nnoremap q :exec g:Lf_py "rgExplManager.quit()" " nnoremap :exec g:Lf_py "rgExplManager.quit()" if a:heading == 0 diff --git a/autoload/leaderf/Tag.vim b/autoload/leaderf/Tag.vim index 506ed37c..8538e2d3 100644 --- a/autoload/leaderf/Tag.vim +++ b/autoload/leaderf/Tag.vim @@ -28,12 +28,12 @@ function! leaderf#Tag#Maps() nnoremap :exec g:Lf_py "tagExplManager.toggleHelp()" nnoremap :exec g:Lf_py "tagExplManager.refresh()" nnoremap p :exec g:Lf_py "tagExplManager._previewResult(True)" - nnoremap j :exec g:Lf_py "tagExplManager.moveAndPreview('j')" - nnoremap k :exec g:Lf_py "tagExplManager.moveAndPreview('k')" - nnoremap :exec g:Lf_py "tagExplManager.moveAndPreview('Up')" - nnoremap :exec g:Lf_py "tagExplManager.moveAndPreview('Down')" - nnoremap :exec g:Lf_py "tagExplManager.moveAndPreview('PageUp')" - nnoremap :exec g:Lf_py "tagExplManager.moveAndPreview('PageDown')" + nnoremap j :exec g:Lf_py "tagExplManager.moveAndPreview('j')" + nnoremap k :exec g:Lf_py "tagExplManager.moveAndPreview('k')" + nnoremap :exec g:Lf_py "tagExplManager.moveAndPreview('Up')" + nnoremap :exec g:Lf_py "tagExplManager.moveAndPreview('Down')" + nnoremap :exec g:Lf_py "tagExplManager.moveAndPreview('PageUp')" + nnoremap :exec g:Lf_py "tagExplManager.moveAndPreview('PageDown')" nnoremap :exec g:Lf_py "tagExplManager._toUpInPopup()" nnoremap :exec g:Lf_py "tagExplManager._toDownInPopup()" nnoremap :exec g:Lf_py "tagExplManager.closePreviewPopupOrQuit()" diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index dfbb5667..014059b8 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -1348,6 +1348,8 @@ def moveAndPreview(self, direction): """ direction is in {'j', 'k', 'Down', 'Up', 'PageDown', 'PageUp'} """ + count = int(lfEval("v:count")) + if (direction in ("j", "Down") and self._getInstance().window.cursor[0] == len(self._getInstance().buffer) and self._circular_scroll): lfCmd('noautocmd exec "norm! gg"') @@ -1355,9 +1357,9 @@ def moveAndPreview(self, direction): lfCmd('noautocmd exec "norm! G"') else: if len(direction) > 1: - lfCmd(r'noautocmd exec "norm! \<{}>"'.format(direction)) + lfCmd(r'noautocmd exec "norm! {}\<{}>"'.format(count, direction)) else: - lfCmd('noautocmd exec "norm! {}"'.format(direction)) + lfCmd('noautocmd exec "norm! {}{}"'.format(count, direction)) if self._getInstance().getWinPos() == 'floatwin': self._cli._buildPopupPrompt() From 5ad91dc63c6f70ae0a8e392a1d905444eaa9aa80 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Tue, 9 Jan 2024 20:44:03 +0800 Subject: [PATCH 148/365] jump to the concrete position --- autoload/leaderf/python/leaderf/rgExpl.py | 1 + 1 file changed, 1 insertion(+) diff --git a/autoload/leaderf/python/leaderf/rgExpl.py b/autoload/leaderf/python/leaderf/rgExpl.py index bc23f614..7f7ba804 100644 --- a/autoload/leaderf/python/leaderf/rgExpl.py +++ b/autoload/leaderf/python/leaderf/rgExpl.py @@ -594,6 +594,7 @@ def _acceptSelection(self, *args, **kwargs): else: lfCmd("hide buffer +%s %s" % (line_num, buf_number)) lfCmd("norm! ^zv") + lfCmd("call search('%s', 'zW', line('.'))" % escQuote(self._getExplorer().getPatternRegex()[0])) lfCmd("norm! zz") if "preview" not in kwargs: From fb00bfdc9da86fbb43ca5f784a86958bfc7c7fc2 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Tue, 16 Jan 2024 22:16:06 +0800 Subject: [PATCH 149/365] Leaderf rg can grep modified buffer --- autoload/leaderf/python/leaderf/rgExpl.py | 75 ++++++++++++++++++----- 1 file changed, 58 insertions(+), 17 deletions(-) diff --git a/autoload/leaderf/python/leaderf/rgExpl.py b/autoload/leaderf/python/leaderf/rgExpl.py index 7f7ba804..c71cbd45 100644 --- a/autoload/leaderf/python/leaderf/rgExpl.py +++ b/autoload/leaderf/python/leaderf/rgExpl.py @@ -274,6 +274,22 @@ def removeFiles(names): except: pass + buffer_names = { b.number: lfRelpath(b.name) for b in vim.buffers } + + def formatLine(line): + try: + if "@LeaderF@" not in line: + return line + + _, line = line.split("@LeaderF@", 1) + buf_number = line.split(":", 1)[0] + buf_name = buffer_names[int(buf_number)] + return line.replace(buf_number, buf_name, 1) + except: + return line + + format_line = None + if sys.version_info >= (3, 0): tmp_file = partial(tempfile.NamedTemporaryFile, encoding=lfEval("&encoding")) else: @@ -282,44 +298,65 @@ def removeFiles(names): if "--current-buffer" in arguments_dict: path = '' # omit the option if vim.current.buffer.name: - try: - path = '"%s"' % os.path.relpath(lfDecode(vim.current.buffer.name)) - except ValueError: - path = '"%s"' % lfDecode(vim.current.buffer.name) + if vim.current.buffer.options["modified"] == False: + try: + path = '"%s"' % os.path.relpath(lfDecode(vim.current.buffer.name)) + except ValueError: + path = '"%s"' % lfDecode(vim.current.buffer.name) + else: + with tmp_file(mode='w', suffix='@LeaderF@'+str(vim.current.buffer.number), + delete=False) as f: + file_name = lfDecode(f.name) + for line in vim.current.buffer: + f.write(line + '\n') + + path = '"' + file_name + '"' + tmpfilenames.append(file_name) + format_line = formatLine else: file_name = "%d_'No_Name_%d'" % (os.getpid(), vim.current.buffer.number) try: with lfOpen(file_name, 'w', errors='ignore') as f: - for line in vim.current.buffer[:]: + for line in vim.current.buffer: f.write(line + '\n') except IOError: with tmp_file(mode='w', suffix='_'+file_name, delete=False) as f: file_name = lfDecode(f.name) - for line in vim.current.buffer[:]: + for line in vim.current.buffer: f.write(line + '\n') path = '"' + file_name + '"' tmpfilenames.append(file_name) - - if "--all-buffers" in arguments_dict: + elif "--all-buffers" in arguments_dict: path = '' # omit the option for b in vim.buffers: if lfEval("buflisted(%d)" % b.number) == '1': if b.name: - try: - path += '"' + os.path.relpath(lfDecode(b.name)) + '" ' - except ValueError: - path += '"' + lfDecode(b.name) + '" ' + if b.options["modified"] == False: + try: + path += '"' + os.path.relpath(lfDecode(b.name)) + '" ' + except ValueError: + path += '"' + lfDecode(b.name) + '" ' + else: + with tmp_file(mode='w', suffix='@LeaderF@'+str(b.number), + delete=False) as f: + file_name = lfDecode(f.name) + for line in b: + f.write(line + '\n') + + path += '"' + file_name + '" ' + tmpfilenames.append(file_name) + format_line = formatLine else: file_name = "%d_'No_Name_%d'" % (os.getpid(), b.number) try: with lfOpen(file_name, 'w', errors='ignore') as f: - for line in b[:]: + for line in b: f.write(line + '\n') except IOError: with tmp_file(mode='w', suffix='_'+file_name, delete=False) as f: file_name = lfDecode(f.name) - for line in b[:]: + for line in b: f.write(line + '\n') path += '"' + file_name + '" ' @@ -336,10 +373,14 @@ def removeFiles(names): heading = "--no-heading" cmd = '''{} {} --no-config --no-ignore-messages {} --with-filename --color never --line-number '''\ - '''{} {}{}{}{}{}{}'''.format(self._rg, extra_options, heading, case_flag, word_or_line, zero_args_options, - one_args_options, repeatable_options, lfDecode(pattern), path) + '''{} {}{}{}{}{}{}'''.format(self._rg, extra_options, heading, case_flag, + word_or_line, zero_args_options, one_args_options, + repeatable_options, lfDecode(pattern), path) lfCmd("let g:Lf_Debug_RgCmd = '%s'" % escQuote(cmd)) - content = executor.execute(cmd, encoding=lfEval("&encoding"), cleanup=partial(removeFiles, tmpfilenames), raise_except=raise_except) + content = executor.execute(cmd, encoding=lfEval("&encoding"), + cleanup=partial(removeFiles, tmpfilenames), + raise_except=raise_except, + format_line=format_line) return content def translateRegex(self, regex, is_perl=False): From de8bb02024b2c4d89006d51b896b2808ddece527 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 17 Jan 2024 13:50:18 +0800 Subject: [PATCH 150/365] fix issue #1050 --- autoload/leaderf/python/leaderf/rgExpl.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/autoload/leaderf/python/leaderf/rgExpl.py b/autoload/leaderf/python/leaderf/rgExpl.py index c71cbd45..3cecb75e 100644 --- a/autoload/leaderf/python/leaderf/rgExpl.py +++ b/autoload/leaderf/python/leaderf/rgExpl.py @@ -635,7 +635,8 @@ def _acceptSelection(self, *args, **kwargs): else: lfCmd("hide buffer +%s %s" % (line_num, buf_number)) lfCmd("norm! ^zv") - lfCmd("call search('%s', 'zW', line('.'))" % escQuote(self._getExplorer().getPatternRegex()[0])) + if self._getExplorer().getPatternRegex(): + lfCmd("call search('%s', 'zW', line('.'))" % escQuote(self._getExplorer().getPatternRegex()[0])) lfCmd("norm! zz") if "preview" not in kwargs: From 597b7b717936ba0ff186f1371125c114629f253c Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 18 Jan 2024 15:22:31 +0800 Subject: [PATCH 151/365] optimize the preview --- autoload/leaderf/python/leaderf/manager.py | 84 ++++++++++++---------- 1 file changed, 45 insertions(+), 39 deletions(-) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 014059b8..d4dc455e 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -129,6 +129,7 @@ def __init__(self): self._arguments = {} self._getExplClass() self._preview_filetype = None + self._orig_source = None self._preview_config = {} self._circular_scroll = lfEval("get(g:, 'Lf_EnableCircularScroll', 0)") == '1' if lfEval("has('patch-8.1.1615') || has('nvim-0.5.0')") == '0': @@ -862,53 +863,56 @@ def _useExistingWindow(self, title, source, line_num, jump_cmd): else: lfCmd("call popup_setoptions(%d, %s)" % (self._preview_winid, str(self._preview_config))) - if lfEval("has('nvim')") == '1': - if isinstance(source, int): - lfCmd("noautocmd call nvim_win_set_buf(%d, %d)" % (self._preview_winid, source)) - self._setWinOptions(self._preview_winid) - self._preview_filetype = '' - else: - try: - if self._isBinaryFile(source): - lfCmd("""let content = map(range(128), '"^@"')""") - else: - lfCmd("let content = readfile('%s', '', 4096)" % escQuote(source)) - except vim.error as e: - lfPrintError(e) - return - if lfEval("!exists('g:Lf_preview_scratch_buffer') || !bufexists(g:Lf_preview_scratch_buffer)") == '1': - lfCmd("noautocmd let g:Lf_preview_scratch_buffer = nvim_create_buf(0, 1)") - lfCmd("noautocmd call nvim_buf_set_option(g:Lf_preview_scratch_buffer, 'undolevels', -1)") - lfCmd("noautocmd call nvim_buf_set_option(g:Lf_preview_scratch_buffer, 'modeline', v:true)") - lfCmd("noautocmd call nvim_buf_set_lines(g:Lf_preview_scratch_buffer, 0, -1, v:false, content)") - lfCmd("noautocmd call nvim_win_set_buf(%d, g:Lf_preview_scratch_buffer)" % self._preview_winid) + if self._orig_source != source: + self._orig_source = source - cur_filetype = getExtension(source) - if cur_filetype != self._preview_filetype: - lfCmd("call win_execute(%d, 'silent! doautocmd filetypedetect BufNewFile %s')" % (self._preview_winid, escQuote(source))) - self._preview_filetype = lfEval("getbufvar(winbufnr(%d), '&ft')" % self._preview_winid) - else: - if isinstance(source, int): - lfCmd("noautocmd call popup_settext(%d, getbufline(%d, 1, '$'))" % (self._preview_winid, source) ) - filename = vim.buffers[source].name + if lfEval("has('nvim')") == '1': + if isinstance(source, int): + lfCmd("noautocmd call nvim_win_set_buf(%d, %d)" % (self._preview_winid, source)) + self._setWinOptions(self._preview_winid) + self._preview_filetype = '' + else: + try: + if self._isBinaryFile(source): + lfCmd("""let content = map(range(128), '"^@"')""") + else: + lfCmd("let content = readfile('%s', '', 4096)" % escQuote(source)) + except vim.error as e: + lfPrintError(e) + return + if lfEval("!exists('g:Lf_preview_scratch_buffer') || !bufexists(g:Lf_preview_scratch_buffer)") == '1': + lfCmd("noautocmd let g:Lf_preview_scratch_buffer = nvim_create_buf(0, 1)") + lfCmd("noautocmd call nvim_buf_set_option(g:Lf_preview_scratch_buffer, 'undolevels', -1)") + lfCmd("noautocmd call nvim_buf_set_option(g:Lf_preview_scratch_buffer, 'modeline', v:true)") + lfCmd("noautocmd call nvim_buf_set_lines(g:Lf_preview_scratch_buffer, 0, -1, v:false, content)") + lfCmd("noautocmd call nvim_win_set_buf(%d, g:Lf_preview_scratch_buffer)" % self._preview_winid) + + cur_filetype = getExtension(source) + if cur_filetype != self._preview_filetype: + lfCmd("call win_execute(%d, 'silent! doautocmd filetypedetect BufNewFile %s')" % (self._preview_winid, escQuote(source))) + self._preview_filetype = lfEval("getbufvar(winbufnr(%d), '&ft')" % self._preview_winid) else: - filename = source - try: - if self._isBinaryFile(filename): - lfCmd("""let content = map(range(128), '"^@"')""") - else: - lfCmd("let content = readfile('%s', '', 4096)" % escQuote(filename)) - except vim.error as e: - lfPrintError(e) - return - lfCmd("noautocmd call popup_settext(%d, content)" % self._preview_winid ) + if isinstance(source, int): + lfCmd("noautocmd call popup_settext(%d, getbufline(%d, 1, '$'))" % (self._preview_winid, source)) + filename = vim.buffers[source].name + else: + filename = source + try: + if self._isBinaryFile(filename): + lfCmd("""let content = map(range(128), '"^@"')""") + else: + lfCmd("let content = readfile('%s', '', 4096)" % escQuote(filename)) + except vim.error as e: + lfPrintError(e) + return + lfCmd("noautocmd call popup_settext(%d, content)" % self._preview_winid) cur_filetype = getExtension(filename) if cur_filetype != self._preview_filetype: lfCmd("call win_execute(%d, 'silent! doautocmd filetypedetect BufNewFile %s')" % (self._preview_winid, escQuote(filename))) self._preview_filetype = lfEval("getbufvar(winbufnr(%d), '&ft')" % self._preview_winid) - self._setWinOptions(self._preview_winid) + self._setWinOptions(self._preview_winid) if jump_cmd: lfCmd("""call win_execute(%d, '%s')""" % (self._preview_winid, escQuote(jump_cmd))) @@ -1116,6 +1120,8 @@ def _createPopupPreview(self, title, source, line_num, jump_cmd=''): self._updateOptions(preview_pos, show_borders, options) self._createPreviewWindow(options, source, line_num, jump_cmd) + self._orig_source = source + return True def _updateOptions(self, preview_pos, show_borders, options): From 43e6c0467ef73107f9f6f02ac967dbc359a8d438 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Fri, 19 Jan 2024 10:06:52 +0800 Subject: [PATCH 152/365] fix issue #1051 introduced by 597b7b7 --- autoload/leaderf/python/leaderf/manager.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index d4dc455e..e714e357 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -907,10 +907,10 @@ def _useExistingWindow(self, title, source, line_num, jump_cmd): return lfCmd("noautocmd call popup_settext(%d, content)" % self._preview_winid) - cur_filetype = getExtension(filename) - if cur_filetype != self._preview_filetype: - lfCmd("call win_execute(%d, 'silent! doautocmd filetypedetect BufNewFile %s')" % (self._preview_winid, escQuote(filename))) - self._preview_filetype = lfEval("getbufvar(winbufnr(%d), '&ft')" % self._preview_winid) + cur_filetype = getExtension(filename) + if cur_filetype != self._preview_filetype: + lfCmd("call win_execute(%d, 'silent! doautocmd filetypedetect BufNewFile %s')" % (self._preview_winid, escQuote(filename))) + self._preview_filetype = lfEval("getbufvar(winbufnr(%d), '&ft')" % self._preview_winid) self._setWinOptions(self._preview_winid) From ed30de54a43ffa2e02b41b86efaa30b8ec8556ff Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Fri, 26 Jan 2024 11:28:16 +0800 Subject: [PATCH 153/365] $ should be escaped in linux shell --- autoload/leaderf/python/leaderf/rgExpl.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/autoload/leaderf/python/leaderf/rgExpl.py b/autoload/leaderf/python/leaderf/rgExpl.py index 3cecb75e..a6a13322 100644 --- a/autoload/leaderf/python/leaderf/rgExpl.py +++ b/autoload/leaderf/python/leaderf/rgExpl.py @@ -232,9 +232,16 @@ def getContent(self, *args, **kwargs): if "--live" in arguments_dict: if "--no-fixed-strings" in arguments_dict: p = i.replace('"', r'\"') + if os.name != 'nt': + pattern += r'-e "%s" ' % p.replace(r'\$', r'\\$').replace('$', r'\$') + else: + pattern += r'-e "%s" ' % p else: p = i.replace('\\', r'\\').replace('"', r'\"') - pattern += r'-e "%s" ' % p + if os.name != 'nt': + pattern += r'-e "%s" ' % p.replace('$', r'\$') + else: + pattern += r'-e "%s" ' % p else: if len(i) > 1 and (i[0] == i[-1] == '"' or i[0] == i[-1] == "'"): p = i[1:-1] @@ -245,7 +252,13 @@ def getContent(self, *args, **kwargs): if p == '': continue - pattern += r'-e "%s" ' % p + if os.name != 'nt': + if "-F" in arguments_dict: + pattern += r'-e "%s" ' % p.replace('$', r'\$') + else: + pattern += r'-e "%s" ' % p.replace(r'\$', r'\\$').replace('$', r'\$') + else: + pattern += r'-e "%s" ' % p if is_literal: if word_or_line == '-w ': From 9cf165b444b961f019d3b1a87f38788f9c314100 Mon Sep 17 00:00:00 2001 From: Niko Zhong <26323326+NasdaqGodzilla@users.noreply.github.com> Date: Fri, 2 Feb 2024 12:22:56 +0800 Subject: [PATCH 154/365] =?UTF-8?q?=E6=96=B0=E5=A2=9Eg:Lf=5FRg=5FBackend?= =?UTF-8?q?=E7=94=A8=E4=BA=8E=E6=8C=87=E5=AE=9Abin=E6=A1=A3=E4=BD=9C?= =?UTF-8?q?=E4=B8=BA=E6=90=9C=E7=B4=A2=E5=90=8E=E7=AB=AF=E5=AE=9E=E7=8E=B0?= =?UTF-8?q?.=20(#1055)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: NasdaqGodzilla <6323326+NasdaqGodzilla@users.noreply.github.com> --- autoload/leaderf/python/leaderf/rgExpl.py | 18 ++++++++++++++---- doc/leaderf.txt | 8 ++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/autoload/leaderf/python/leaderf/rgExpl.py b/autoload/leaderf/python/leaderf/rgExpl.py index a6a13322..f2b11416 100644 --- a/autoload/leaderf/python/leaderf/rgExpl.py +++ b/autoload/leaderf/python/leaderf/rgExpl.py @@ -44,6 +44,7 @@ def __init__(self): self._display_multi = False self._cmd_work_dir = "" self._rg = lfEval("get(g:, 'Lf_Rg', 'rg')") + self._rg_backend = lfEval("get(g:, 'Lf_Rg_Backend', '')") def getContent(self, *args, **kwargs): arguments_dict = kwargs.get("arguments", {}) @@ -219,6 +220,11 @@ def getContent(self, *args, **kwargs): # treat the first PATH as pattern path = ' '.join(path_list[1:]) + if lfEval("get(g:, 'Lf_Rg_Backend', '')") == '': + pattern += r'-e %s ' % i + else: + pattern += r'%s ' % i + if case_flag == '-i': case_pattern = r'\c' elif case_flag == '-s': @@ -385,10 +391,14 @@ def formatLine(line): else: heading = "--no-heading" - cmd = '''{} {} --no-config --no-ignore-messages {} --with-filename --color never --line-number '''\ - '''{} {}{}{}{}{}{}'''.format(self._rg, extra_options, heading, case_flag, - word_or_line, zero_args_options, one_args_options, - repeatable_options, lfDecode(pattern), path) + if lfEval("get(g:, 'Lf_Rg_Backend', '')") == '': + cmd = '''{} {} --no-config --no-ignore-messages {} --with-filename --color never --line-number '''\ + '''{} {}{}{}{}{}{}'''.format(self._rg, extra_options, heading, case_flag, word_or_line, zero_args_options, + one_args_options, repeatable_options, lfDecode(pattern), path) + else: + cmd = '''{} {} {}'''.format(self._rg_backend, lfDecode(pattern), path) + + lfCmd("echohl WarningMsg | redraw | echo 'Running: %s'" % escQuote(cmd)) lfCmd("let g:Lf_Debug_RgCmd = '%s'" % escQuote(cmd)) content = executor.execute(cmd, encoding=lfEval("&encoding"), cleanup=partial(removeFiles, tmpfilenames), diff --git a/doc/leaderf.txt b/doc/leaderf.txt index f27996f4..06a60b91 100644 --- a/doc/leaderf.txt +++ b/doc/leaderf.txt @@ -622,6 +622,14 @@ g:Lf_Rg *g:Lf_Rg* < Default value is "rg". +g:Lf_Rg_Backend *g:Lf_Rg_Backend* + Specify the search backend. When this option is set, use this backend to + perform search and will ignore g:Lf_Rg. You can select your own customized + searching bin or wrapper by this option. e.g., > + let g:Lf_Rg_Backend = '/PATH/MyRgWrapper.sh' +< + Default value is "". + g:Lf_RgConfig *g:Lf_RgConfig* Specify a list of ripgrep configurations. For example, > let g:Lf_RgConfig = [ From f166222d21995f23417df604b3d500636d63d99a Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Sun, 25 Feb 2024 14:03:52 +0800 Subject: [PATCH 155/365] =?UTF-8?q?Revert=20"=E6=96=B0=E5=A2=9Eg:Lf=5FRg?= =?UTF-8?q?=5FBackend=E7=94=A8=E4=BA=8E=E6=8C=87=E5=AE=9Abin=E6=A1=A3?= =?UTF-8?q?=E4=BD=9C=E4=B8=BA=E6=90=9C=E7=B4=A2=E5=90=8E=E7=AB=AF=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0.=20(#1055)"=20This=20PR=20introduced=20a=20bug.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- autoload/leaderf/python/leaderf/rgExpl.py | 18 ++++-------------- doc/leaderf.txt | 8 -------- 2 files changed, 4 insertions(+), 22 deletions(-) diff --git a/autoload/leaderf/python/leaderf/rgExpl.py b/autoload/leaderf/python/leaderf/rgExpl.py index f2b11416..a6a13322 100644 --- a/autoload/leaderf/python/leaderf/rgExpl.py +++ b/autoload/leaderf/python/leaderf/rgExpl.py @@ -44,7 +44,6 @@ def __init__(self): self._display_multi = False self._cmd_work_dir = "" self._rg = lfEval("get(g:, 'Lf_Rg', 'rg')") - self._rg_backend = lfEval("get(g:, 'Lf_Rg_Backend', '')") def getContent(self, *args, **kwargs): arguments_dict = kwargs.get("arguments", {}) @@ -220,11 +219,6 @@ def getContent(self, *args, **kwargs): # treat the first PATH as pattern path = ' '.join(path_list[1:]) - if lfEval("get(g:, 'Lf_Rg_Backend', '')") == '': - pattern += r'-e %s ' % i - else: - pattern += r'%s ' % i - if case_flag == '-i': case_pattern = r'\c' elif case_flag == '-s': @@ -391,14 +385,10 @@ def formatLine(line): else: heading = "--no-heading" - if lfEval("get(g:, 'Lf_Rg_Backend', '')") == '': - cmd = '''{} {} --no-config --no-ignore-messages {} --with-filename --color never --line-number '''\ - '''{} {}{}{}{}{}{}'''.format(self._rg, extra_options, heading, case_flag, word_or_line, zero_args_options, - one_args_options, repeatable_options, lfDecode(pattern), path) - else: - cmd = '''{} {} {}'''.format(self._rg_backend, lfDecode(pattern), path) - - lfCmd("echohl WarningMsg | redraw | echo 'Running: %s'" % escQuote(cmd)) + cmd = '''{} {} --no-config --no-ignore-messages {} --with-filename --color never --line-number '''\ + '''{} {}{}{}{}{}{}'''.format(self._rg, extra_options, heading, case_flag, + word_or_line, zero_args_options, one_args_options, + repeatable_options, lfDecode(pattern), path) lfCmd("let g:Lf_Debug_RgCmd = '%s'" % escQuote(cmd)) content = executor.execute(cmd, encoding=lfEval("&encoding"), cleanup=partial(removeFiles, tmpfilenames), diff --git a/doc/leaderf.txt b/doc/leaderf.txt index 06a60b91..f27996f4 100644 --- a/doc/leaderf.txt +++ b/doc/leaderf.txt @@ -622,14 +622,6 @@ g:Lf_Rg *g:Lf_Rg* < Default value is "rg". -g:Lf_Rg_Backend *g:Lf_Rg_Backend* - Specify the search backend. When this option is set, use this backend to - perform search and will ignore g:Lf_Rg. You can select your own customized - searching bin or wrapper by this option. e.g., > - let g:Lf_Rg_Backend = '/PATH/MyRgWrapper.sh' -< - Default value is "". - g:Lf_RgConfig *g:Lf_RgConfig* Specify a list of ripgrep configurations. For example, > let g:Lf_RgConfig = [ From fd05ba47004f36f78325fb2a205cf4f4849e9605 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Tue, 5 Mar 2024 14:39:58 +0800 Subject: [PATCH 156/365] add `Leaderf git` many commands are available for elevating your Git collaboration experience, such as: Leaderf git Leaderf git diff Leaderf git diff --side-by-side Leaderf git diff --side-by-side --current-file Leaderf git diff --directly Leaderf git diff --directly --position right Leaderf git diff --cached Leaderf git diff --cached --side-by-side Leaderf git diff --cached --directly Leaderf git diff --cached --directly --position right Leaderf git diff HEAD Leaderf git diff HEAD --side-by-side Leaderf git diff HEAD --directly Leaderf git diff HEAD --directly --position right Leaderf git log Leaderf git log --directly Leaderf git log --explorer Leaderf git log --explorer --navigation-position bottom Leaderf git log --current-file --- autoload/leaderf.vim | 6 +- autoload/leaderf/Any.vim | 42 + autoload/leaderf/Git.vim | 319 +++ .../leaderf/colorscheme/popup/default.vim | 50 + autoload/leaderf/python/leaderf/anyExpl.py | 25 +- .../leaderf/python/leaderf/asyncExecutor.py | 3 +- autoload/leaderf/python/leaderf/gitExpl.py | 2308 +++++++++++++++++ autoload/leaderf/python/leaderf/instance.py | 2 +- autoload/leaderf/python/leaderf/manager.py | 17 +- autoload/leaderf/python/leaderf/rgExpl.py | 1 - autoload/leaderf/python/leaderf/utils.py | 9 + doc/leaderf.txt | 57 +- 12 files changed, 2815 insertions(+), 24 deletions(-) create mode 100644 autoload/leaderf/Git.vim create mode 100644 autoload/leaderf/python/leaderf/gitExpl.py diff --git a/autoload/leaderf.vim b/autoload/leaderf.vim index 67fd7dca..0843d60d 100644 --- a/autoload/leaderf.vim +++ b/autoload/leaderf.vim @@ -71,7 +71,7 @@ function! s:InitDict(var, dict) endfunction call s:InitVar('g:Lf_WindowHeight', '0.5') -call s:InitVar('g:Lf_TabpagePosition', 2) +call s:InitVar('g:Lf_TabpagePosition', 3) call s:InitVar('g:Lf_ShowRelativePath', 1) call s:InitVar('g:Lf_DefaultMode', 'FullPath') call s:InitVar('g:Lf_CursorBlink', 1) @@ -143,6 +143,10 @@ call s:InitDict('g:Lf_GtagsfilesCmd', { \}) call s:InitVar('g:Lf_HistoryEditPromptIfEmpty', 1) call s:InitVar('g:Lf_PopupBorders', ["─","│","─","│","╭","╮","╯","╰"]) +call s:InitVar('g:Lf_GitFolderIcons', { + \ 'open': '', + \ 'closed': '', + \}) let s:Lf_CommandMap = { \ '': [''], diff --git a/autoload/leaderf/Any.vim b/autoload/leaderf/Any.vim index 66ffe93d..25a4357b 100644 --- a/autoload/leaderf/Any.vim +++ b/autoload/leaderf/Any.vim @@ -65,6 +65,10 @@ let g:Lf_Helps = { \ "quickfix": "navigate quickfix", \ "loclist": "navigate location list", \ "jumps": "navigate jumps list", + \ "git": "use git", + \ "git-log": "show the commit logs", + \ "git-diff": "show changes between commits, commit and working tree, etc", + \ "git-blame": "show what revision and author last modified each line of a file", \ } let g:Lf_Arguments = { @@ -211,6 +215,35 @@ let g:Lf_Arguments = { \ "quickfix": [], \ "loclist": [], \ "jumps": [], + \ "git":{ + \ "log": [ + \ {"name": ["--current-file"], "nargs": 0, "help": "show logs of current file"}, + \ {"name": ["extra"], "nargs": "*", "help": "extra arguments of git log"}, + \ [ + \ {"name": ["--directly"], "nargs": 0, "help": "output the logs directly"}, + \ {"name": ["--explorer"], "nargs": 0, "help": "view changed files of one commit in a tree explorer"}, + \ ], + \ {"name": ["--position"], "nargs": 1, "choices": ["top", "right", "bottom", "left"], "metavar": "", + \ "help": "specifies the position of the logs window"}, + \ {"name": ["--navigation-position"], "nargs": 1, "choices": ["top", "right", "bottom", "left"], "metavar": "", + \ "help": "specifies the position of the navigation panel"}, + \ ], + \ "diff": [ + \ {"name": ["--cached", "--staged"], "nargs": 0, "help": "run 'git diff --cached'"}, + \ [ + \ {"name": ["--directly"], "nargs": 0, "help": "output the diffs directly"}, + \ {"name": ["--explorer"], "nargs": 0, "help": "view changed files in a tree explorer"}, + \ ], + \ {"name": ["--position"], "nargs": 1, "choices": ["top", "right", "bottom", "left"], "metavar": "", + \ "help": "specifies the position of the diffs window"}, + \ {"name": ["-s", "--side-by-side"], "nargs": 0, "help": "show diffs in a side-by-side view"}, + \ {"name": ["--current-file"], "nargs": 0, "help": "show diffs of current file"}, + \ {"name": ["extra"], "nargs": "*", "help": "extra arguments of git diff"}, + \ ], + \ "blame": [ + \ {"name": ["--abc"], "nargs": 0, "help": ""}, + \ ], + \ }, \} let g:Lf_CommonArguments = [ @@ -346,6 +379,15 @@ function! leaderf#Any#parseArguments(argLead, cmdline, cursorPos) abort else let arguments = [] endif + + if type(arguments) == type({}) + if argNum == 2 || argNum == 3 && a:argLead != "" + return filter(keys(arguments), "s:Lf_FuzzyMatch(a:argLead, v:val)") + else + let arguments = arguments[argList[2]] + endif + endif + let argDict = s:Lf_GenDict(arguments + g:Lf_CommonArguments) for opt in s:Lf_Refine(arguments + g:Lf_CommonArguments) if type(opt) == type([]) diff --git a/autoload/leaderf/Git.vim b/autoload/leaderf/Git.vim new file mode 100644 index 00000000..381bd77a --- /dev/null +++ b/autoload/leaderf/Git.vim @@ -0,0 +1,319 @@ +" ============================================================================ +" File: Git.vim +" Description: +" Author: Yggdroot +" Website: https://github.com/Yggdroot +" Note: +" License: Apache License, Version 2.0 +" ============================================================================ + +if leaderf#versionCheck() == 0 " this check is necessary + finish +endif + +exec g:Lf_py "from leaderf.gitExpl import *" + +function! leaderf#Git#Maps(id) + nmapclear + exec g:Lf_py "import ctypes" + let manager = printf("ctypes.cast(%d, ctypes.py_object).value", a:id) + exec printf('nnoremap :exec g:Lf_py "%s.accept()"', manager) + exec printf('nnoremap o :exec g:Lf_py "%s.accept()"', manager) + exec printf('nnoremap <2-LeftMouse> :exec g:Lf_py "%s.accept()"', manager) + exec printf('nnoremap x :exec g:Lf_py "%s.accept(''h'')"', manager) + exec printf('nnoremap v :exec g:Lf_py "%s.accept(''v'')"', manager) + exec printf('nnoremap t :exec g:Lf_py "%s.accept(''t'')"', manager) + exec printf('nnoremap p :exec g:Lf_py "%s._previewResult(True)"', manager) + exec printf('nnoremap j :exec g:Lf_py "%s.moveAndPreview(''j'')"', manager) + exec printf('nnoremap k :exec g:Lf_py "%s.moveAndPreview(''k'')"', manager) + exec printf('nnoremap :exec g:Lf_py "%s.moveAndPreview(''Up'')"', manager) + exec printf('nnoremap :exec g:Lf_py "%s.moveAndPreview(''Down'')"', manager) + exec printf('nnoremap :exec g:Lf_py "%s.moveAndPreview(''PageUp'')"', manager) + exec printf('nnoremap :exec g:Lf_py "%s.moveAndPreview(''PageDown'')"', manager) + exec printf('nnoremap q :exec g:Lf_py "%s.quit()"', manager) + exec printf('nnoremap i :exec g:Lf_py "%s.input()"', manager) + exec printf('nnoremap :exec g:Lf_py "%s.input()"', manager) + exec printf('nnoremap :exec g:Lf_py "%s.toggleHelp()"', manager) + exec printf('nnoremap :exec g:Lf_py "%s._toUpInPopup()"', manager) + exec printf('nnoremap :exec g:Lf_py "%s._toDownInPopup()"', manager) + exec printf('nnoremap :exec g:Lf_py "%s.closePreviewPopupOrQuit()"', manager) +endfunction + +" direction: +" 0, backward +" 1, forward +function! leaderf#Git#OuterIndent(direction) + let spaces = substitute(getline('.'), '^\(\s*\).*', '\1', '') + let width = strdisplaywidth(spaces) + if width == 0 + return 0 + endif + if a:direction == 0 + let flags = 'sbW' + else + let flags = 'sW' + endif + return search(printf('^\s\{,%d}\zs\S', width-1), flags) +endfunction + +" direction: +" 0, backward +" 1, forward +function! leaderf#Git#SameIndent(direction) + let spaces = substitute(getline('.'), '^\(\s*\).*', '\1', '') + let width = strdisplaywidth(spaces) + if a:direction == 0 + let flags = 'sbW' + else + let flags = 'sW' + endif + if width == 0 + let stopline = 0 + else + let stopline = search(printf('^\s\{,%d}\zs\S', width-1), flags[1:].'n') + endif + + noautocmd norm! ^ + call search(printf('^\s\{%d}\zs\S', width), flags, stopline) +endfunction + +function! leaderf#Git#SpecificMaps(id) + exec g:Lf_py "import ctypes" + let manager = printf("ctypes.cast(%d, ctypes.py_object).value", a:id) + exec printf('nnoremap e :exec g:Lf_py "%s.editCommand()"', manager) +endfunction + +" direction: +" 0, backward +" 1, forward +function! leaderf#Git#OuterBlock(direction) + let column = col('.') + if column >= match(getline('.'), '\S') + 1 + noautocmd norm! ^ + let column = col('.') - 1 + endif + let width = (column - 1) / 2 * 2 + if a:direction == 0 + let flags = 'sbW' + else + let flags = 'sW' + endif + call search(printf('^\s\{%d}\zs\S', width), flags) +endfunction + +let s:help = [ + \ "o: open the folder or open the diffs of current file", + \ ": open the folder or open the diffs of current file", + \ "<2-LeftMouse>: open the folder or open the diffs of current file", + \ "O: open the folder recursively", + \ "t: open the diffs in a new tabpage", + \ "p: preview the diffs, i.e., like 'o', but leave the cursor in the current panel", + \ "x: collapse the parent folder", + \ "X: collapse all the children of the current folder", + \ "f: fuzzy search files", + \ "F: resume the previous fuzzy searching", + \ "-: go to the parent folder", + \ "+: go to the next sibling of the parent folder", + \ ": go to the next sibling of the current folder", + \ ": go to the previous sibling of the current folder", + \ "(: go to the start of the current indent level", + \ "): go to the end of the current indent level", + \] + +function s:HelpFilter(winid, key) + if a:key == "\" || a:key == "\" + call popup_close(a:winid) + return 1 + endif + return 1 +endfunction + +function! s:GetRowCol(width, height) + let win_width = &columns + let win_height = &lines + + let row = (win_height - a:height) / 2 - 1 + let col = (win_width - a:width) / 2 + + return {'row': row, 'col': col} +endfunction + +function! leaderf#Git#ShowHelp() + if has("nvim") + let borderchars = [ + \ [g:Lf_PopupBorders[4], "Lf_hl_popupBorder"], + \ [g:Lf_PopupBorders[0], "Lf_hl_popupBorder"], + \ [g:Lf_PopupBorders[5], "Lf_hl_popupBorder"], + \ [g:Lf_PopupBorders[1], "Lf_hl_popupBorder"], + \ [g:Lf_PopupBorders[6], "Lf_hl_popupBorder"], + \ [g:Lf_PopupBorders[2], "Lf_hl_popupBorder"], + \ [g:Lf_PopupBorders[7], "Lf_hl_popupBorder"], + \ [g:Lf_PopupBorders[3], "Lf_hl_popupBorder"] + \] + let width = 100 + let height = len(s:help) + let row_col = s:GetRowCol(width, height) + let options = { + \ "title": " Help ", + \ "title_pos": "center", + \ "relative": "editor", + \ "row": row_col["row"], + \ "col": row_col["col"], + \ "width": width, + \ "height": height, + \ "zindex": 20482, + \ "noautocmd": 1, + \ "border": borderchars, + \ "style": "minimal", + \} + let scratch_buffer = nvim_create_buf(v:false, v:true) + call nvim_buf_set_option(scratch_buffer, 'bufhidden', 'wipe') + call nvim_buf_set_lines(scratch_buffer, 0, -1, v:false, s:help) + call nvim_buf_set_option(scratch_buffer, 'modifiable', v:false) + let id = nvim_open_win(scratch_buffer, 1, options) + call nvim_win_set_option(id, 'winhighlight', 'Normal:Lf_hl_popup_window') + call win_execute(id, 'call matchadd("Special", ''^.\{-}\(:\)\@='')') + call win_execute(id, 'call matchadd("Comment", ''\(^.\{-}:\s*\)\@<=.*'')') + call win_execute(id, 'nnoremap c') + call win_execute(id, 'nnoremap c') + else + let options = { + \ "title": " Help ", + \ "zindex": 20482, + \ "scrollbar": 1, + \ "padding": [0, 0, 0, 0], + \ "border": [1, 1, 1, 1], + \ "borderchars": g:Lf_PopupBorders, + \ "borderhighlight": ["Lf_hl_popupBorder"], + \ "filter": "s:HelpFilter", + \ "mapping": 0, + \} + + let id = popup_create(s:help, options) + call win_execute(id, 'setlocal wincolor=Lf_hl_popup_window') + call win_execute(id, 'call matchadd("Special", ''^.\{-}\(:\)\@='')') + call win_execute(id, 'call matchadd("Comment", ''\(^.\{-}:\s*\)\@<=.*'')') + endif +endfunction + +function! leaderf#Git#TreeViewMaps(id) + exec g:Lf_py "import ctypes" + let tree_view = printf("ctypes.cast(%d, ctypes.py_object).value", a:id) + exec printf('nnoremap X :exec g:Lf_py "%s.collapseChildren()"', tree_view) + nnoremap :call leaderf#Git#ShowHelp() + nnoremap - :call leaderf#Git#OuterIndent(0) + nnoremap + :call leaderf#Git#OuterIndent(1) + nnoremap :call leaderf#Git#SameIndent(0) + nnoremap :call leaderf#Git#SameIndent(1) + nnoremap ( :call leaderf#Git#OuterBlock(0) + nnoremap ) :call leaderf#Git#OuterBlock(1) +endfunction + +function! leaderf#Git#CollapseParent(explorer_page) + if leaderf#Git#OuterIndent(0) != 0 + exec g:Lf_py printf("%s.open(False)", a:explorer_page) + endif +endfunction + +function! leaderf#Git#ExplorerMaps(id) + exec g:Lf_py "import ctypes" + let explorer_page = printf("ctypes.cast(%d, ctypes.py_object).value", a:id) + exec printf('nnoremap o :exec g:Lf_py "%s.open(False)"', explorer_page) + exec printf('nnoremap <2-LeftMouse> :exec g:Lf_py "%s.open(False)"', explorer_page) + exec printf('nnoremap :exec g:Lf_py "%s.open(False)"', explorer_page) + exec printf('nnoremap O :exec g:Lf_py "%s.open(True)"', explorer_page) + exec printf('nnoremap t :exec g:Lf_py "%s.open(False, mode=''t'')"', explorer_page) + exec printf('nnoremap p :exec g:Lf_py "%s.open(False, preview=True)"', explorer_page) + exec printf('nnoremap x :call leaderf#Git#CollapseParent("%s")', explorer_page) + exec printf('nnoremap f :exec g:Lf_py "%s.fuzzySearch()"', explorer_page) + exec printf('nnoremap F :exec g:Lf_py "%s.fuzzySearch(True)"', explorer_page) + nnoremap q :q +endfunction + +function! leaderf#Git#TimerCallback(manager_id, id) + exec g:Lf_py "import ctypes" + exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value._callback(bang=True)", a:manager_id) +endfunction + +function! leaderf#Git#WriteBuffer(view_id, id) + exec g:Lf_py "import ctypes" + exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value.writeBuffer()", a:view_id) +endfunction + +function! leaderf#Git#Cleanup(owner_id, id) + exec g:Lf_py "import ctypes" + exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value.cleanup()", a:owner_id) +endfunction + +function! leaderf#Git#Suicide(view_id) + exec g:Lf_py "import ctypes" + exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value.suicide()", a:view_id) +endfunction + +function! leaderf#Git#Bufhidden(view_id) + exec g:Lf_py "import ctypes" + exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value.bufHidden()", a:view_id) +endfunction + +function! leaderf#Git#CleanupExplorerPage(view_id) + exec g:Lf_py "import ctypes" + exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value.cleanupExplorerPage()", a:view_id) +endfunction + +function! leaderf#Git#Commands() + if !exists("g:Lf_GitCommands") + let g:Lf_GitCommands = [ + \ {"Leaderf git diff": "fuzzy search and view the diffs"}, + \ {"Leaderf git diff --side-by-side": "fuzzy search and view the side-by-side diffs"}, + \ {"Leaderf git diff --side-by-side --current-file":"view the side-by-side diffs of the current file"}, + \ {"Leaderf git diff --directly": "view the diffs directly"}, + \ {"Leaderf git diff --directly --position right":"view the diffs in the right split window"}, + \ {"Leaderf git diff --cached": "fuzzy search and view `git diff --cached`"}, + \ {"Leaderf git diff --cached --side-by-side": "fuzzy search and view the side-by-side diffs of `git diff --cached`"}, + \ {"Leaderf git diff --cached --directly": "view `git diff --cached` directly"}, + \ {"Leaderf git diff --cached --directly --position right": "view `git diff --cached` directly in the right split window"}, + \ {"Leaderf git diff HEAD": "fuzzy search and view `git diff HEAD`"}, + \ {"Leaderf git diff HEAD --side-by-side": "fuzzy search and view the side-by-side diffs of `git diff HEAD`"}, + \ {"Leaderf git diff HEAD --directly": "view `git diff HEAD` directly"}, + \ {"Leaderf git diff HEAD --directly --position right": "view `git diff HEAD` directly in the right split window"}, + \ {"Leaderf git log": "fuzzy search and view the log"}, + \ {"Leaderf git log --directly": "view the logs directly"}, + \ {"Leaderf git log --explorer": "fuzzy search and view the logs of in an explorer tabpage"}, + \ {"Leaderf git log --explorer --navigation-position bottom": "specify the position of navigation panel in explorer tabpage"}, + \ {"Leaderf git log --current-file": "fuzzy search and view the logs of current file"}, + \ ] + endif + + return g:Lf_GitCommands +endfunction + +function! leaderf#Git#NormalModeFilter(winid, key) abort + let key = leaderf#RemapKey(g:Lf_PyEval("id(gitExplManager)"), get(g:Lf_KeyMap, a:key, a:key)) + + if key ==# "e" + exec g:Lf_py "gitExplManager.editCommand()" + else + return leaderf#NormalModeFilter(g:Lf_PyEval("id(gitExplManager)"), a:winid, a:key) + endif + + return 1 +endfunction + +function! leaderf#Git#DefineSyntax() abort + syntax region Lf_hl_gitStat start=/^---$/ end=/^ \d\+ files\? changed,/ + syn match Lf_hl_gitStatPath /^ \S*\%(\s*|\s*\d\+\s*+*-*$\)\@=/ display containedin=Lf_hl_gitStat contained + syn match Lf_hl_gitStatPath /^ \S*\%(\s*|\s*Bin \d\+ -> \d\+ bytes\?$\)\@=/ display containedin=Lf_hl_gitStat contained + syn match Lf_hl_gitStatPath /^ \S*\%( => \S*\s*|\s*\d\+\s*+*-*$\)\@=/ display containedin=Lf_hl_gitStat contained + syn match Lf_hl_gitStatPath /\%(^ \S* => \)\@<=\S*\%(\s*|\s*\d\+\s*+*-*$\)\@=/ display containedin=Lf_hl_gitStat contained + syn match Lf_hl_gitStatNumber /\%(^ \S*\%( => \S*\)\?\s*|\s*\)\@<=\d\+\%(\s*+*-*$\)\@=/ display containedin=Lf_hl_gitStat contained + syn match Lf_hl_gitStatNumber /\%(^ \S*\%( => \S*\)\?\s*|\s*Bin \)\@<=\d\+ -> \d\+\%( bytes\?$\)\@=/ display containedin=Lf_hl_gitStat contained + syn match Lf_hl_gitStatPlus /\%(^ \S*\%( => \S*\)\?\s*|\s*\d\+\s*\)\@<=+*\%(-*$\)\@=/ display containedin=Lf_hl_gitStat contained + syn match Lf_hl_gitStatMinus /\%(^ \S*\%( => \S*\)\?\s*|\s*\d\+\s*+*\)\@<=-*$/ display containedin=Lf_hl_gitStat contained + syn match gitIdentityHeader /^Committer:/ contained containedin=gitHead nextgroup=gitIdentity skipwhite contains=@NoSpell +endfunction + +function! leaderf#Git#DiffOff(win_ids) abort + for id in a:win_ids + call win_execute(id, "diffoff") + endfor +endfunction diff --git a/autoload/leaderf/colorscheme/popup/default.vim b/autoload/leaderf/colorscheme/popup/default.vim index 2172d80e..60b43a07 100644 --- a/autoload/leaderf/colorscheme/popup/default.vim +++ b/autoload/leaderf/colorscheme/popup/default.vim @@ -137,6 +137,31 @@ if &background ==? 'dark' highlight def link Lf_hl_jumpsNumber Number highlight def link Lf_hl_jumpsLineCol String highlight def link Lf_hl_jumpsIndicator Type + + highlight def Lf_hl_gitDiffModification guifg=#ffa500 guibg=NONE gui=NONE ctermfg=214 ctermbg=NONE cterm=NONE + highlight def Lf_hl_gitDiffAddition guifg=#a8e332 guibg=NONE gui=NONE ctermfg=148 ctermbg=NONE cterm=NONE + highlight def Lf_hl_gitDiffDeletion guifg=#ff477e guibg=NONE gui=NONE ctermfg=204 ctermbg=NONE cterm=NONE + highlight def link Lf_hl_gitHash Identifier + highlight def link Lf_hl_gitRefNames Special + highlight def link Lf_hl_gitFolder Directory + highlight def link Lf_hl_gitFolderIcon Special + highlight def link Lf_hl_gitAddIcon Lf_hl_gitDiffAddition + highlight def link Lf_hl_gitCopyIcon Lf_hl_gitDiffAddition + highlight def link Lf_hl_gitDelIcon Lf_hl_gitDiffDeletion + highlight def link Lf_hl_gitModificationIcon Lf_hl_gitDiffModification + highlight def link Lf_hl_gitRenameIcon Lf_hl_gitDiffAddition + highlight def link Lf_hl_gitNumStatAdd Lf_hl_gitDiffAddition + highlight def link Lf_hl_gitNumStatDel Lf_hl_gitDiffDeletion + highlight def link Lf_hl_gitNumStatBinary Constant + highlight def link Lf_hl_gitHelp Comment + call leaderf#colorscheme#popup#link_two("Lf_hl_gitStlChangedNum", "StatusLine", "Number", 1) + highlight def link Lf_hl_gitStlFileChanged StatusLine + call leaderf#colorscheme#popup#link_two("Lf_hl_gitStlAdd", "StatusLine", "Lf_hl_gitDiffAddition", 1) + call leaderf#colorscheme#popup#link_two("Lf_hl_gitStlDel", "StatusLine", "Lf_hl_gitDiffDeletion", 1) + highlight def link Lf_hl_gitStatPath Directory + highlight def link Lf_hl_gitStatNumber Number + highlight def link Lf_hl_gitStatPlus Lf_hl_gitNumStatAdd + highlight def link Lf_hl_gitStatMinus Lf_hl_gitNumStatDel else " Lf_hl_popup_inputText is the wincolor of input window highlight def Lf_hl_popup_inputText guifg=#525252 guibg=#f4f3d7 gui=NONE ctermfg=239 ctermbg=230 cterm=NONE @@ -261,4 +286,29 @@ else highlight def link Lf_hl_jumpsNumber Number highlight def link Lf_hl_jumpsLineCol String highlight def link Lf_hl_jumpsIndicator Type + + highlight def Lf_hl_gitDiffModification guifg=#df5f00 guibg=NONE gui=NONE ctermfg=166 ctermbg=NONE cterm=NONE + highlight def Lf_hl_gitDiffAddition guifg=#008700 guibg=NONE gui=NONE ctermfg=28 ctermbg=NONE cterm=NONE + highlight def Lf_hl_gitDiffDeletion guifg=#df0000 guibg=NONE gui=NONE ctermfg=160 ctermbg=NONE cterm=NONE + highlight def link Lf_hl_gitHash Identifier + highlight def link Lf_hl_gitRefNames Special + highlight def link Lf_hl_gitFolder Directory + highlight def link Lf_hl_gitFolderIcon Special + highlight def link Lf_hl_gitAddIcon Lf_hl_gitDiffAddition + highlight def link Lf_hl_gitCopyIcon Lf_hl_gitDiffAddition + highlight def link Lf_hl_gitDelIcon Lf_hl_gitDiffDeletion + highlight def link Lf_hl_gitModificationIcon Lf_hl_gitDiffModification + highlight def link Lf_hl_gitRenameIcon Lf_hl_gitDiffAddition + highlight def link Lf_hl_gitNumStatAdd Lf_hl_gitDiffAddition + highlight def link Lf_hl_gitNumStatDel Lf_hl_gitDiffDeletion + highlight def link Lf_hl_gitNumStatBinary Constant + highlight def link Lf_hl_gitHelp Comment + call leaderf#colorscheme#popup#link_two("Lf_hl_gitStlChangedNum", "StatusLine", "Number", 1) + highlight def link Lf_hl_gitStlFileChanged StatusLine + call leaderf#colorscheme#popup#link_two("Lf_hl_gitStlAdd", "StatusLine", "Lf_hl_gitDiffAddition", 1) + call leaderf#colorscheme#popup#link_two("Lf_hl_gitStlDel", "StatusLine", "Lf_hl_gitDiffDeletion", 1) + highlight def link Lf_hl_gitStatPath Directory + highlight def link Lf_hl_gitStatNumber Number + highlight def link Lf_hl_gitStatPlus Lf_hl_gitNumStatAdd + highlight def link Lf_hl_gitStatMinus Lf_hl_gitNumStatDel endif diff --git a/autoload/leaderf/python/leaderf/anyExpl.py b/autoload/leaderf/python/leaderf/anyExpl.py index 0de1bf76..dd14722c 100644 --- a/autoload/leaderf/python/leaderf/anyExpl.py +++ b/autoload/leaderf/python/leaderf/anyExpl.py @@ -719,6 +719,9 @@ def _default_action(self, category, positional_args, arguments, *args, **kwargs) elif category == "jumps": from .jumpsExpl import jumpsExplManager manager = jumpsExplManager + elif category == "git": + from .gitExpl import gitExplManager + manager = gitExplManager else: import ctypes manager_id = lfFunction(lfEval("g:Lf_PythonExtensions['%s'].manager_id" % category))() @@ -775,11 +778,25 @@ def start(self, arg_line, *args, **kwargs): parser = subparsers.add_parser(category, usage=gtags_usage, formatter_class=LfHelpFormatter, help=help, epilog="If [!] is given, enter normal mode directly.") else: parser = subparsers.add_parser(category, help=help, formatter_class=LfHelpFormatter, epilog="If [!] is given, enter normal mode directly.") - group = parser.add_argument_group('specific arguments') - self._add_argument(group, arg_def, positional_args) - group = parser.add_argument_group("common arguments") - self._add_argument(group, lfEval("g:Lf_CommonArguments"), positional_args) + if isinstance(arg_def, dict): + subsubparsers = parser.add_subparsers(title="subcommands", description="", help="") + group = parser.add_argument_group("common arguments") + self._add_argument(group, lfEval("g:Lf_CommonArguments"), positional_args) + for command, args in arg_def.items(): + help = lfEval("g:Lf_Helps").get(category + "-" + command, "") + subparser = subsubparsers.add_parser(command, help=help, formatter_class=LfHelpFormatter) + group = subparser.add_argument_group('specific arguments') + self._add_argument(group, args, positional_args) + + group = subparser.add_argument_group("common arguments") + self._add_argument(group, lfEval("g:Lf_CommonArguments"), positional_args) + else: + group = parser.add_argument_group('specific arguments') + self._add_argument(group, arg_def, positional_args) + + group = parser.add_argument_group("common arguments") + self._add_argument(group, lfEval("g:Lf_CommonArguments"), positional_args) parser.set_defaults(start=partial(self._default_action, category, positional_args)) diff --git a/autoload/leaderf/python/leaderf/asyncExecutor.py b/autoload/leaderf/python/leaderf/asyncExecutor.py index c11cd66f..eca42c9b 100644 --- a/autoload/leaderf/python/leaderf/asyncExecutor.py +++ b/autoload/leaderf/python/leaderf/asyncExecutor.py @@ -21,7 +21,7 @@ class AsyncExecutor(object): read the output asynchronously. """ def __init__(self): - self._errQueue = Queue.Queue() + self._errQueue = None self._process = None self._finished = False self._max_count = int(lfEval("g:Lf_MaxCount")) @@ -54,6 +54,7 @@ def execute(self, cmd, encoding=None, cleanup=None, env=None, raise_except=True, env=env, universal_newlines=False) + self._errQueue = Queue.Queue() self._finished = False stderr_thread = threading.Thread(target=self._readerThread, diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py new file mode 100644 index 00000000..65cf5881 --- /dev/null +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -0,0 +1,2308 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import vim +import re +import os +import sys +import os.path +import json +import bisect +import itertools +if sys.version_info >= (3, 0): + import queue as Queue +else: + import Queue +from enum import Enum +from collections import OrderedDict +from .utils import * +from .explorer import * +from .manager import * +from .devicons import ( + webDevIconsGetFileTypeSymbol, + removeDevIcons, + matchaddDevIconsDefault, + matchaddDevIconsExact, + matchaddDevIconsExtension, +) + +def lfGetFilePath(source): + """ + source is a tuple like (b90f76fc1, bad07e644, R099, src/version.c, src/version2.c) + """ + return source[3] if source[4] == "" else source[4] + +#***************************************************** +# GitExplorer +#***************************************************** +class GitExplorer(Explorer): + def __init__(self): + self._executor = [] + self._display_multi = False + self._show_icon = lfEval("get(g:, 'Lf_ShowDevIcons', 1)") == "1" + + def getContent(self, *args, **kwargs): + commands = lfEval("leaderf#Git#Commands()") + return [list(item)[0] for item in commands] + + def formatLine(self, line): + pass + + def getStlCategory(self): + return 'Git' + + def getStlCurDir(self): + return escQuote(lfEncode(lfGetCwd())) + + def supportsNameOnly(self): + return False + + def cleanup(self): + for exe in self._executor: + exe.killProcess() + self._executor = [] + + def getPatternRegex(self): + return self._pattern_regex + + def getContextSeparator(self): + return self._context_separator + + def displayMulti(self): + return self._display_multi + + +class GitDiffExplorer(GitExplorer): + def __init__(self): + super(GitDiffExplorer, self).__init__() + self._source_info = {} + + def getContent(self, *args, **kwargs): + arguments_dict = kwargs.get("arguments", {}) + + if "content" in arguments_dict: + return arguments_dict["content"] + + executor = AsyncExecutor() + self._executor.append(executor) + + self._source_info = {} + + cmd = "git diff --no-color --raw --no-abbrev" + if "--cached" in arguments_dict: + cmd += " --cached" + if "extra" in arguments_dict: + cmd += " " + " ".join(arguments_dict["extra"]) + content = executor.execute(cmd, encoding=lfEval("&encoding"), format_line=self.formatLine) + return content + + def formatLine(self, line): + """ + :000000 100644 000000000 5b01d33aa A runtime/syntax/json5.vim + :100644 100644 671b269c0 ef52cddf4 M runtime/syntax/nix.vim + :100644 100644 69671c59c 084f8cdb4 M runtime/syntax/zsh.vim + :100644 100644 b90f76fc1 bad07e644 R099 src/version.c src/version2.c + :100644 000000 b5825eb19 000000000 D src/testdir/dumps + + ':100644 100644 72943a1 dbee026 R050\thello world.txt\thello world2.txt' + """ + tmp = line.split(sep='\t') + file_names = (tmp[1], tmp[2] if len(tmp) == 3 else "") + blob_status = tmp[0].split() + self._source_info[file_names] = (blob_status[2], blob_status[3], blob_status[4], + file_names[0], file_names[1]) + icon = webDevIconsGetFileTypeSymbol(file_names[0]) if self._show_icon else "" + return "{:<4} {}{}{}".format(blob_status[4], icon, file_names[0], + "" if file_names[1] == "" else "\t=>\t" + file_names[1] ) + + def getStlCategory(self): + return 'Git_diff' + + def getSourceInfo(self): + return self._source_info + + +class GitLogExplorer(GitExplorer): + def getContent(self, *args, **kwargs): + arguments_dict = kwargs.get("arguments", {}) + + executor = AsyncExecutor() + self._executor.append(executor) + + cmd = 'git log --pretty=format:"%h%d %s"' + if "--current-file" in arguments_dict and "current_file" in arguments_dict: + cmd += " -- {}".format(arguments_dict["current_file"]) + + if "extra" in arguments_dict: + cmd += " " + " ".join(arguments_dict["extra"]) + content = executor.execute(cmd, encoding=lfEval("&encoding"), format_line=self.formatLine) + return content + + def formatLine(self, line): + return line + + def getStlCategory(self): + return 'Git_log' + + +class GitCommand(object): + def __init__(self, arguments_dict, source): + self._arguments = arguments_dict + self._source = source + self._cmd = "" + self._file_type = "" + self._file_type_cmd = "" + self._buffer_name = "" + self.buildCommandAndBufferName() + + def buildCommandAndBufferName(self): + pass + + def getCommand(self): + return self._cmd + + def getFileType(self): + return self._file_type + + def getFileTypeCommand(self): + return self._file_type_cmd + + def getBufferName(self): + return self._buffer_name + + def getArguments(self): + return self._arguments + + def getSource(self): + return self._source + + +class GitDiffCommand(GitCommand): + def __init__(self, arguments_dict, source): + super(GitDiffCommand, self).__init__(arguments_dict, source) + + def buildCommandAndBufferName(self): + self._cmd = "git diff --no-color" + extra_options = "" + if "--cached" in self._arguments: + extra_options += " --cached" + + if "extra" in self._arguments: + extra_options += " " + " ".join(self._arguments["extra"]) + + if self._source is not None: + file_name = lfGetFilePath(self._source) + if " " in file_name: + file_name = file_name.replace(' ', r'\ ') + extra_options += " -- {}".format(file_name) + elif "--current-file" in self._arguments and "current_file" in self._arguments: + extra_options += " -- {}".format(self._arguments["current_file"]) + + self._cmd += extra_options + self._buffer_name = "LeaderF://git diff" + extra_options + self._file_type = "diff" + self._file_type_cmd = "silent! doautocmd filetypedetect BufNewFile *.diff" + + +class GitLogDiffCommand(GitCommand): + def __init__(self, arguments_dict, source): + super(GitLogDiffCommand, self).__init__(arguments_dict, source) + + def buildCommandAndBufferName(self): + # fuzzy search in navigation panel + if not self._arguments["parent"].startswith("0000000"): + self._cmd = "git diff --no-color {}..{} -- {}".format(self._arguments["parent"], + self._arguments["commit_id"], + lfGetFilePath(self._source) + ) + else: + self._cmd = "git show --pretty= --no-color {} -- {}".format(self._arguments["commit_id"], + lfGetFilePath(self._source) + ) + self._buffer_name = "LeaderF://" + self._cmd + self._file_type = "diff" + self._file_type_cmd = "silent! doautocmd filetypedetect BufNewFile *.diff" + + +class GitCatFileCommand(GitCommand): + def __init__(self, arguments_dict, source, commit_id): + """ + source is a tuple like (b90f76fc1, R099, src/version.c) + """ + self._commit_id = commit_id + super(GitCatFileCommand, self).__init__(arguments_dict, source) + + @staticmethod + def buildBufferName(commit_id, source): + """ + source is a tuple like (b90f76fc1, R099, src/version.c) + """ + return "{}:{}:{}".format(commit_id[:7], source[0][:9], source[2]) + + def buildCommandAndBufferName(self): + self._cmd = "git cat-file -p {}".format(self._source[0]) + if self._source[0].startswith("0000000"): + if self._source[1] == "M": + if os.name == 'nt': + self._cmd = "type {}".format(self._source[2]) + else: + self._cmd = "cat {}".format(self._source[2]) + else: + self._cmd = "" + + self._buffer_name = GitCatFileCommand.buildBufferName(self._commit_id, self._source) + self._file_type_cmd = "silent! doautocmd filetypedetect BufNewFile {}".format(self._source[2]) + + +class GitLogCommand(GitCommand): + def __init__(self, arguments_dict, source): + super(GitLogCommand, self).__init__(arguments_dict, source) + + def buildCommandAndBufferName(self): + if "--directly" in self._arguments: + self._cmd = "git log" + + if "extra" in self._arguments: + self._cmd += " " + " ".join(self._arguments["extra"]) + + if "--current-file" in self._arguments and "current_file" in self._arguments: + self._cmd += " -- {}".format(self._arguments["current_file"]) + + self._buffer_name = "LeaderF://" + self._cmd + else: + sep = ' ' if os.name == 'nt' else '' + self._cmd = ('git show {} --pretty=format:"commit %H%nparent %P%n' + 'Author: %an <%ae>%nAuthorDate: %ad%nCommitter: %cn <%ce>%nCommitDate:' + ' %cd{}%n%n%s%n%n%b%n" --stat=70 --stat-graph-width=10 -p --no-color' + ).format(self._source, sep) + + if "--recall" in self._arguments and "current_file" in self._arguments: + self._cmd += " -- {}".format(self._arguments["current_file"]) + elif "--current-file" in self._arguments and "current_file" in self._arguments: + self._cmd += " -- {}".format(self._arguments["current_file"]) + + self._buffer_name = "LeaderF://" + self._source + + self._file_type = "git" + self._file_type_cmd = "setlocal filetype=git" + + +class GitDiffExplCommand(GitCommand): + def __init__(self, arguments_dict, source): + super(GitDiffExplCommand, self).__init__(arguments_dict, source) + + def buildCommandAndBufferName(self): + self._cmd = 'git diff --raw -C --numstat --shortstat --no-abbrev' + extra_options = "" + if "--cached" in self._arguments: + extra_options += " --cached" + + if "extra" in self._arguments: + extra_options += " " + " ".join(self._arguments["extra"]) + + self._cmd += extra_options + + self._buffer_name = "LeaderF://navigation/" + self._source + self._file_type_cmd = "" + + +class GitLogExplCommand(GitCommand): + def __init__(self, arguments_dict, source): + super(GitLogExplCommand, self).__init__(arguments_dict, source) + + def buildCommandAndBufferName(self): + self._cmd = ('git show -m --raw -C --numstat --shortstat ' + '--pretty=format:"# %P" --no-abbrev {}').format(self._source) + + self._buffer_name = "LeaderF://navigation/" + self._source + self._file_type_cmd = "" + + +class ParallelExecutor(object): + @staticmethod + def run(*cmds): + outputs = [[] for _ in range(len(cmds))] + stop_thread = False + + def readContent(content, output): + try: + for line in content: + output.append(line) + if stop_thread: + break + except Exception: + traceback.print_exc() + traceback.print_stack() + + + executors = [AsyncExecutor() for _ in range(len(cmds))] + workers = [] + for i, (exe, cmd) in enumerate(zip(executors, cmds)): + content = exe.execute(cmd, encoding=lfEval("&encoding")) + worker = threading.Thread(target=readContent, args=(content, outputs[i])) + worker.daemon = True + worker.start() + workers.append(worker) + + for w in workers: + w.join(5) # I think 5s is enough for git cat-file + + stop_thread = True + + for e in executors: + e.killProcess() + + return outputs + + +class GitCommandView(object): + def __init__(self, owner, cmd): + self._owner = owner + self._cmd = cmd + self._executor = AsyncExecutor() + self._buffer = None + self._window_id = -1 + self._bufhidden = 'wipe' + self.init() + owner.register(self) + + def init(self): + self._content = [] + self._timer_id = None + self._reader_thread = None + self._offset_in_content = 0 + self._read_finished = 0 + self._stop_reader_thread = False + + def getBufferName(self): + return self._cmd.getBufferName() + + def getWindowId(self): + if lfEval("win_id2tabwin({})".format(self._window_id)) == ['0', '0']: + self._window_id = int(lfEval("bufwinid('{}')".format(escQuote(self._buffer.name)))) + return self._window_id + + def setWindowId(self, winid): + self._window_id = winid + + def getContent(self): + return self._content + + def setContent(self, content): + try: + self._buffer.options['modifiable'] = True + self._buffer[:] = content + finally: + self._buffer.options['modifiable'] = False + + def getSource(self): + return self._cmd.getSource() + + def start(self): + # start a timer and thread + self._timer_id = lfEval("timer_start(100, function('leaderf#Git#WriteBuffer', [%d]), {'repeat': -1})" % id(self)) + + self._reader_thread = threading.Thread(target=self._readContent, args=(lfEval("&encoding"),)) + self._reader_thread.daemon = True + self._reader_thread.start() + + def setOptions(self, winid, bufhidden): + lfCmd("call win_execute({}, 'setlocal nobuflisted')".format(winid)) + lfCmd("call win_execute({}, 'setlocal buftype=nofile')".format(winid)) + lfCmd("call win_execute({}, 'setlocal bufhidden={}')".format(winid, bufhidden)) + lfCmd("call win_execute({}, 'setlocal undolevels=-1')".format(winid)) + lfCmd("call win_execute({}, 'setlocal noswapfile')".format(winid)) + lfCmd("call win_execute({}, 'setlocal nospell')".format(winid)) + lfCmd("call win_execute({}, 'setlocal nomodifiable')".format(winid)) + if lfEval("getbufvar(winbufnr(%d), '&ft')" % winid) != self._cmd.getFileType(): + lfCmd("call win_execute({}, '{}')".format(winid, self._cmd.getFileTypeCommand())) + + def initBuffer(self): + pass + + def defineMaps(self, winid): + pass + + def enableColor(self, winid): + pass + + def create(self, winid, bufhidden='wipe', buf_content=None): + self._bufhidden = bufhidden + + if self._buffer is not None: + self._buffer.options['modifiable'] = True + del self._buffer[:] + self._buffer.options['modifiable'] = False + self.cleanup() + lfCmd("call win_gotoid({})".format(self.getWindowId())) + + self.init() + + if self._buffer is None: + self.defineMaps(winid) + self.setOptions(winid, bufhidden) + lfCmd("augroup Lf_Git | augroup END") + lfCmd("call win_execute({}, 'autocmd! Lf_Git BufWipeout call leaderf#Git#Suicide({})')" + .format(winid, id(self))) + lfCmd("call win_execute({}, 'autocmd! Lf_Git BufHidden call leaderf#Git#Bufhidden({})')" + .format(winid, id(self))) + + self._buffer = vim.buffers[int(lfEval("winbufnr({})".format(winid)))] + self._window_id = winid + + self.enableColor(self.getWindowId()) + + if buf_content is not None: + # cache the content if buf_content is the result of ParallelExecutor.run() + self._content = buf_content + self._owner.readFinished(self) + + self._read_finished = 2 + + self._buffer.options['modifiable'] = True + self._buffer[:] = buf_content + self._buffer.options['modifiable'] = False + + self._owner.writeFinished(self.getWindowId()) + + return + + if self._cmd.getCommand() == "": + self._read_finished = 2 + self._owner.writeFinished(self.getWindowId()) + return + + self.initBuffer() + self.start() + + def writeBuffer(self): + if self._read_finished == 2: + return + + if not self._buffer.valid: + self.stopTimer() + return + + self._buffer.options['modifiable'] = True + try: + cur_len = len(self._content) + if cur_len > self._offset_in_content: + if self._offset_in_content == 0: + self._buffer[:] = self._content[:cur_len] + else: + self._buffer.append(self._content[self._offset_in_content:cur_len]) + + self._offset_in_content = cur_len + lfCmd("redraw") + finally: + self._buffer.options['modifiable'] = False + + if self._read_finished == 1 and self._offset_in_content == len(self._content): + self._read_finished = 2 + self._owner.writeFinished(self.getWindowId()) + self.stopTimer() + + def _readContent(self, encoding): + try: + content = self._executor.execute(self._cmd.getCommand(), encoding=encoding) + for line in content: + self._content.append(line) + if self._stop_reader_thread: + break + else: + self._read_finished = 1 + self._owner.readFinished(self) + except Exception: + traceback.print_exc() + traceback.print_stack() + self._read_finished = 1 + + def stopThread(self): + if self._reader_thread and self._reader_thread.is_alive(): + self._stop_reader_thread = True + self._reader_thread.join(0.01) + + def stopTimer(self): + if self._timer_id is not None: + lfCmd("call timer_stop(%s)" % self._timer_id) + self._timer_id = None + + def cleanup(self, wipe=True): + self.stopTimer() + self.stopThread() + # must do this at last + self._executor.killProcess() + + if self._bufhidden == "hide" and wipe == True: + lfCmd("noautocmd bwipe! {}".format(self._buffer.number)) + + def suicide(self): + self._owner.deregister(self) + + def bufHidden(self): + self._owner.bufHidden(self) + + def valid(self): + return self._buffer is not None and self._buffer.valid + + +class LfOrderedDict(OrderedDict): + def last_key(self): + return next(reversed(self.keys())) + + def last_value(self): + return next(reversed(self.values())) + + def last_key_value(self): + return next(reversed(self.items())) + + def first_key(self): + return next(iter(self.keys())) + + def first_value(self): + return next(iter(self.values())) + + def first_key_value(self): + return next(iter(self.items())) + +class FolderStatus(Enum): + CLOSED = 0 + OPEN = 1 + + +class TreeNode(object): + def __init__(self, status=FolderStatus.OPEN): + self.status = status + # key is the directory name, value is a TreeNode + self.dirs = LfOrderedDict() + # key is the file name, + # value is a tuple like (b90f76fc1, bad07e644, R099, src/version.c, src/version2.c) + self.files = LfOrderedDict() + + +class MetaInfo(object): + def __init__(self, level, is_dir, name, info, path): + """ + info is TreeNode if is_dir is true or source otherwise. + """ + self.level = level + self.is_dir = is_dir + self.name = name + self.info = info + self.path = path + + +class KeyWrapper(object): + def __init__(self, iterable, key): + self._list = iterable + self._key = key + + def __getitem__(self, i): + return self._key(self._list[i]) + + def __len__(self): + return len(self._list) + + +class Bisect(object): + @staticmethod + def bisect_left(a, x, lo=0, hi=None, *, key=None): + if hi is None: + hi = len(a) + + if sys.version_info >= (3, 10): + pos = bisect.bisect_left(a, x, lo, hi, key=key) + else: + pos = bisect.bisect_left(KeyWrapper(a, key), x, lo, hi) + return pos + + @staticmethod + def bisect_right(a, x, lo=0, hi=None, *, key=None): + if hi is None: + hi = len(a) + + if sys.version_info >= (3, 10): + pos = bisect.bisect_right(a, x, lo, hi, key=key) + else: + pos = bisect.bisect_right(KeyWrapper(a, key), x, lo, hi) + return pos + + +class TreeView(GitCommandView): + def __init__(self, owner, cmd, project_root): + super(TreeView, self).__init__(owner, cmd) + self._project_root = project_root + # key is the parent hash, value is a TreeNode + self._trees = LfOrderedDict() + # key is the parent hash, value is a list of MetaInfo + self._file_structures = {} + # to protect self._file_structures + self._lock = threading.Lock() + self._file_list = {} + self._cur_parent = None + self._short_stat = {} + self._num_stat = {} + self._first_source = {} + self._left_most_file = set() + self._source_queue = Queue.Queue() + folder_icons = lfEval("g:Lf_GitFolderIcons") + self._closed_folder_icon = folder_icons["closed"] + self._open_folder_icon = folder_icons["open"] + self._preopen_num = int(lfEval("get(g:, 'Lf_GitPreopenNum', 100)")) + self._add_icon = lfEval("get(g:, 'Lf_GitAddIcon', '')") #   + self._copy_icon = lfEval("get(g:, 'Lf_GitCopyIcon', '')") + self._del_icon = lfEval("get(g:, 'Lf_GitDelIcon', '')") #   + self._modification_icon = lfEval("get(g:, 'Lf_GitModifyIcon', '')") + self._rename_icon = lfEval("get(g:, 'Lf_GitRenameIcon', '')") + self._status_icons = { + "A": self._add_icon, + "C": self._copy_icon, + "D": self._del_icon, + "M": self._modification_icon, + "R": self._rename_icon, + } + self._head = [ + '" Press for help', + '', + self._project_root + "/", + ] + self._match_ids = [] + + def enableColor(self, winid): + if lfEval("hlexists('Lf_hl_help')") == '0': + lfCmd("call leaderf#colorscheme#popup#load('{}', '{}')".format("git", + lfEval("get(g:, 'Lf_PopupColorscheme', 'default')"))) + + lfCmd(r"""call win_execute({}, 'let matchid = matchadd(''Lf_hl_gitHelp'', ''^".*'', -100)')""" + .format(winid)) + id = int(lfEval("matchid")) + self._match_ids.append(id) + lfCmd(r"""call win_execute({}, 'let matchid = matchadd(''Lf_hl_gitFolder'', ''\S*/'', -100)')""" + .format(winid)) + id = int(lfEval("matchid")) + self._match_ids.append(id) + lfCmd(r"""call win_execute({}, 'let matchid = matchadd(''Lf_hl_gitFolderIcon'', ''^\s*\zs[{}{}]'', -100)')""" + .format(winid, self._closed_folder_icon, self._open_folder_icon)) + id = int(lfEval("matchid")) + self._match_ids.append(id) + lfCmd(r"""call win_execute({}, 'let matchid = matchadd(''Lf_hl_gitAddIcon'', ''^\s*\zs{}'', -100)')""" + .format(winid, self._add_icon)) + id = int(lfEval("matchid")) + self._match_ids.append(id) + lfCmd(r"""call win_execute({}, 'let matchid = matchadd(''Lf_hl_gitCopyIcon'', ''^\s*\zs{}'', -100)')""" + .format(winid, self._copy_icon)) + id = int(lfEval("matchid")) + self._match_ids.append(id) + lfCmd(r"""call win_execute({}, 'let matchid = matchadd(''Lf_hl_gitDelIcon'', ''^\s*\zs{}'', -100)')""" + .format(winid, self._del_icon)) + id = int(lfEval("matchid")) + self._match_ids.append(id) + lfCmd(r"""call win_execute({}, 'let matchid = matchadd(''Lf_hl_gitModificationIcon'', ''^\s*\zs{}'', -100)')""" + .format(winid, self._modification_icon)) + id = int(lfEval("matchid")) + self._match_ids.append(id) + lfCmd(r"""call win_execute({}, 'let matchid = matchadd(''Lf_hl_gitRenameIcon'', ''^\s*\zs{}'', -100)')""" + .format(winid, self._rename_icon)) + id = int(lfEval("matchid")) + lfCmd(r"""call win_execute({}, 'let matchid = matchadd(''Lf_hl_gitRenameIcon'', '' \zs=>\ze '', -100)')""" + .format(winid)) + id = int(lfEval("matchid")) + self._match_ids.append(id) + lfCmd(r"""call win_execute({}, 'let matchid = matchadd(''Lf_hl_gitNumStatAdd'', ''\t\zs+\d\+'', -100)')""" + .format(winid)) + id = int(lfEval("matchid")) + self._match_ids.append(id) + lfCmd(r"""call win_execute({}, 'let matchid = matchadd(''Lf_hl_gitNumStatDel'', ''\t+\d\+\s\+\zs-\d\+'', -100)')""" + .format(winid)) + id = int(lfEval("matchid")) + self._match_ids.append(id) + lfCmd(r"""call win_execute({}, 'let matchid = matchadd(''Lf_hl_gitNumStatBinary'', ''\t\zs(Bin)'', -100)')""" + .format(winid)) + id = int(lfEval("matchid")) + self._match_ids.append(id) + + def defineMaps(self, winid): + lfCmd("call win_execute({}, 'call leaderf#Git#TreeViewMaps({})')" + .format(winid, id(self))) + + def getFirstSource(self): + if self._cur_parent in self._first_source: + return self._first_source[self._cur_parent] + else: + parent = "" + while(parent != self._cur_parent): + parent, source = self._source_queue.get() + self._first_source[parent] = source + + return source + + def getCurrentParent(self): + return self._cur_parent + + def getFileList(self): + return self._file_list[self._cur_parent] + + @staticmethod + def generateSource(line): + """ + :000000 100644 000000000 5b01d33aa A runtime/syntax/json5.vim + :100644 100644 671b269c0 ef52cddf4 M runtime/syntax/nix.vim + :100644 100644 69671c59c 084f8cdb4 M runtime/syntax/zsh.vim + :100644 100644 b90f76fc1 bad07e644 R099 src/version.c src/version2.c + :100644 000000 b5825eb19 000000000 D src/testdir/dumps + + ':100644 100644 72943a1 dbee026 R050\thello world.txt\thello world2.txt' + + return a tuple like (100644, (b90f76fc1, bad07e644, R099, src/version.c, src/version2.c)) + (100644, (69671c59c, 084f8cdb4, M, runtime/syntax/zsh.vim, "")) + """ + tmp = line.split(sep='\t') + file_names = (tmp[1], tmp[2] if len(tmp) == 3 else "") + blob_status = tmp[0].split() + return (blob_status[1], + (blob_status[2], blob_status[3], blob_status[4], + file_names[0], file_names[1]) + ) + + def buildFileStructure(self, parent, level, name, tree_node, path): + if len(tree_node.dirs) == 1 and len(tree_node.files) == 0: + if tree_node.status == FolderStatus.CLOSED: + self._file_structures[parent].append( + MetaInfo(level, True, name, tree_node, path) + ) + else: + dir_name, node = tree_node.dirs.last_key_value() + self.buildFileStructure(parent, level, "{}/{}".format(name, dir_name), + node, "{}{}/".format(path, dir_name) + ) + else: + self._file_structures[parent].append( + MetaInfo(level, True, name, tree_node, path) + ) + + if tree_node.status == FolderStatus.OPEN: + for dir_name, node in tree_node.dirs.items(): + self.buildFileStructure(parent, level + 1, dir_name, node, + "{}{}/".format(path, dir_name)) + + self.appendFiles(parent, level + 1, tree_node) + + def appendRemainingFiles(self, parent, tree_node): + if len(tree_node.dirs) == 0: + return + + dir_name, node = tree_node.dirs.last_key_value() + if len(node.dirs) > 1: + if node.status == FolderStatus.OPEN: + child_dir_name, child_node = node.dirs.last_key_value() + self.buildFileStructure(parent, 1, child_dir_name, child_node, + "{}/{}/".format(dir_name, child_dir_name)) + + self.appendFiles(parent, 1, node) + else: + self.buildFileStructure(parent, 0, dir_name, node, dir_name + "/") + + def appendFiles(self, parent, level, tree_node): + for k, v in tree_node.files.items(): + self._file_structures[parent].append( + MetaInfo(level, False, k, v, lfGetFilePath(v)) + ) + + def getLeftMostFile(self, tree_node): + for node in tree_node.dirs.values(): + result = self.getLeftMostFile(node) + if result is not None: + return result + + for i in tree_node.files.values(): + return i + + return None + + def enqueueLeftMostFile(self, parent): + self._left_most_file.add(parent) + + tree_node = self._trees[parent] + self._source_queue.put((parent, self.getLeftMostFile(tree_node))) + + def buildTree(self, line): + """ + command output is something as follows: + + # 9d0ccb54c743424109751a82a742984699e365fe 63aa0c07bcd16ddac52d5275b9513712b780bc25 + :100644 100644 0cbabf4 d641678 M src/a.txt + 2 0 src/a.txt + 1 file changed, 2 insertions(+) + + # 9d0ccb54c743424109751a82a742984699e365fe 63aa0c07bcd16ddac52d5275b9513712b780bc25 + :100644 100644 acc5824 d641678 M src/a.txt + 3 0 src/a.txt + 1 file changed, 3 insertions(+) + """ + if line.startswith("#"): + size = len(self._trees) + parents = line.split() + if len(parents) == 1: # first commit + parent = "0000000" + else: + parent = parents[size + 1] + if self._cur_parent is None: + self._cur_parent = parent + self._trees[parent] = TreeNode() + self._file_structures[parent] = [] + self._file_list[parent] = [] + elif line.startswith(":"): + if self._cur_parent is None: + parent = "0000000" + self._cur_parent = parent + self._trees[parent] = TreeNode() + self._file_structures[parent] = [] + self._file_list[parent] = [] + + parent, tree_node = self._trees.last_key_value() + mode, source = TreeView.generateSource(line) + file_path = lfGetFilePath(source) + self._file_list[parent].append("{:<4} {}{}" + .format(source[2], source[3], + "" if source[4] == "" + else "\t=>\t" + source[4]) + ) + if mode == "160000": # gitlink + directories = file_path.split("/") + else: + *directories, file = file_path.split("/") + with self._lock: + for i, d in enumerate(directories, 0): + if i == 0: + level0_dir_name = d + + if d not in tree_node.dirs: + # not first directory + if len(tree_node.dirs) > 0: + if i == 1: + if len(tree_node.dirs) == 1: + self._file_structures[parent].append( + MetaInfo(0, True, level0_dir_name, + tree_node, level0_dir_name + "/") + ) + + if tree_node.status == FolderStatus.OPEN: + dir_name, node = tree_node.dirs.last_key_value() + self.buildFileStructure(parent, 1, dir_name, node, + "{}/{}/".format(level0_dir_name, + dir_name) + ) + + if parent not in self._left_most_file: + self.enqueueLeftMostFile(parent) + elif i == 0: + self.appendRemainingFiles(parent, tree_node) + + if len(self._file_structures[parent]) >= self._preopen_num: + status = FolderStatus.CLOSED + else: + status = FolderStatus.OPEN + tree_node.dirs[d] = TreeNode(status) + + tree_node = tree_node.dirs[d] + + if mode != "160000": + tree_node.files[file] = source + elif line.startswith(" "): + parent, tree_node = self._trees.last_key_value() + self._short_stat[parent] = line + self.appendRemainingFiles(parent, tree_node) + self.appendFiles(parent, 0, tree_node) + if parent not in self._left_most_file: + self.enqueueLeftMostFile(parent) + elif line == "": + pass + else: + parent = self._trees.last_key() + if parent not in self._num_stat: + self._num_stat[parent] = {} + + #'3\t1\tarch/{i386 => x86}/Makefile' + added, deleted, pathname = line.split("\t") + if "=>" in pathname: + if "{" in pathname: + pathname = re.sub(r'{.*?=> (.*?)}', r'\1', pathname) + else: + pathname = pathname.split(" => ")[1] + if added == "-" and deleted == "-": + self._num_stat[parent][pathname] = "(Bin)" + else: + self._num_stat[parent][pathname] = "+{:3} -{}".format(added, deleted) + + def metaInfoGenerator(self, meta_info, recursive, level): + meta_info.info.status = FolderStatus.OPEN + + tree_node = meta_info.info + if len(tree_node.dirs) == 1 and len(tree_node.files) == 0 and level != -1: + node = tree_node + while len(node.dirs) == 1 and len(node.files) == 0: + dir_name, node = node.dirs.last_key_value() + meta_info.name = "{}/{}".format(meta_info.name, dir_name) + meta_info.path = "{}{}/".format(meta_info.path, dir_name) + meta_info.info = node + if level == 0: + node.status = FolderStatus.OPEN + + if recursive == True or node.status == FolderStatus.OPEN: + yield from self.metaInfoGenerator(meta_info, recursive, level + 1) + + return + + for dir_name, node in tree_node.dirs.items(): + cur_path = "{}{}/".format(meta_info.path, dir_name) + info = MetaInfo(meta_info.level + 1, True, dir_name, node, cur_path) + yield info + if recursive == True or node.status == FolderStatus.OPEN: + yield from self.metaInfoGenerator(info, recursive, level + 1) + + for k, v in tree_node.files.items(): + yield MetaInfo(meta_info.level + 1, False, k, v, lfGetFilePath(v)) + + def expandOrCollapseFolder(self, recursive=False): + with self._lock: + line_num = vim.current.window.cursor[0] + index = line_num - len(self._head) - 1 + # the root + if index == -1 and recursive == True: + self.expandRoot(line_num) + return None + + structure = self._file_structures[self._cur_parent] + if index < 0 or index >= len(structure): + return None + + meta_info = structure[index] + if meta_info.is_dir: + if meta_info.info.status == FolderStatus.CLOSED: + self.expandFolder(line_num, index, meta_info, recursive) + elif recursive == True: + self.collapseFolder(line_num, index, meta_info, recursive) + self.expandFolder(line_num, index, meta_info, recursive) + else: + self.collapseFolder(line_num, index, meta_info, recursive) + return None + else: + return meta_info.info + + def collapseChildren(self): + with self._lock: + line_num = vim.current.window.cursor[0] + index = line_num - len(self._head) - 1 + structure = self._file_structures[self._cur_parent] + if index < -1 or index >= len(structure): + return + + # the root + if index == -1: + level = -1 + else: + meta_info = structure[index] + if not meta_info.is_dir: + return + + level = meta_info.level + + index += 1 + line_num += 1 + while index < len(structure) and structure[index].level > level and structure[index].is_dir: + if structure[index].info.status == FolderStatus.OPEN: + self.collapseFolder(line_num, index, structure[index], False) + index += 1 + line_num += 1 + + def expandRoot(self, line_num): + meta_info = MetaInfo(-1, True, "", self._trees[self._cur_parent], "") + self._file_structures[self._cur_parent] = list(self.metaInfoGenerator(meta_info, True, -1)) + self._buffer.options['modifiable'] = True + structure = self._file_structures[self._cur_parent] + try: + increment = len(structure) + self._buffer[line_num:] = [self.buildLine(info) for info in structure] + self._offset_in_content = increment + finally: + self._buffer.options['modifiable'] = False + + return increment + + def expandFolder(self, line_num, index, meta_info, recursive): + structure = self._file_structures[self._cur_parent] + size = len(structure) + structure[index + 1 : index + 1] = self.metaInfoGenerator(meta_info, recursive, 0) + self._buffer.options['modifiable'] = True + try: + increment = len(structure) - size + if index >= 0: + self._buffer[line_num - 1] = self.buildLine(structure[index]) + self._buffer.append([self.buildLine(info) + for info in structure[index + 1 : index + 1 + increment]], + line_num) + self._offset_in_content += increment + finally: + self._buffer.options['modifiable'] = False + + return increment + + def collapseFolder(self, line_num, index, meta_info, recursive): + meta_info.info.status = FolderStatus.CLOSED + # # Should all the status be set as CLOSED ? + # # No. + # if "/" in meta_info.name: + # prefix = meta_info.path[:len(meta_info.path) - len(meta_info.name) - 2] + # tree_node = self._trees[self._cur_parent] + # for d in prefix.split("/"): + # tree_node = tree_node.dirs[d] + + # for d in meta_info.name.split("/"): + # tree_node = tree_node.dirs[d] + # tree_node.status = FolderStatus.CLOSED + + structure = self._file_structures[self._cur_parent] + cur_node = meta_info.info + children_num = len(cur_node.dirs) + len(cur_node.files) + if (index + children_num + 1 == len(structure) + or not structure[index + children_num + 1].path.startswith(meta_info.path)): + decrement = children_num + else: + pos = Bisect.bisect_right(structure, False, lo=index + children_num + 1, + key=lambda info: not info.path.startswith(meta_info.path)) + decrement = pos - 1 - index + + del structure[index + 1 : index + 1 + decrement] + self._buffer.options['modifiable'] = True + try: + self._buffer[line_num - 1] = self.buildLine(structure[index]) + del self._buffer[line_num:line_num + decrement] + self._offset_in_content -= decrement + finally: + self._buffer.options['modifiable'] = False + + def inFileStructure(self, path): + *directories, file = path.split("/") + tree_node = self._trees[self._cur_parent] + for d in directories: + if d not in tree_node.dirs: + return False + tree_node = tree_node.dirs[d] + + return file in tree_node.files + + def locateFile(self, path): + with self._lock: + self._locateFile(lfRelpath(path)) + + @staticmethod + def getDirName(path): + if path.endswith("/"): + return path + else: + path = os.path.dirname(path) + if path != "": + path += "/" + return path + + def _locateFile(self, path): + def getKey(info): + if info.path == path: + return 0 + else: + info_path_dir = TreeView.getDirName(info.path) + path_dir = TreeView.getDirName(path) + if ((info.path > path + and not (info_path_dir.startswith(path_dir) and info_path_dir != path_dir) + ) + or + (info.path < path and info.is_dir == False + and (path_dir.startswith(info_path_dir) and info_path_dir != path_dir) + ) + ): + return 1 + else: + return -1 + + structure = self._file_structures[self._cur_parent] + index = Bisect.bisect_left(structure, 0, key=getKey) + if index < len(structure) and structure[index].path == path: + # lfCmd("call win_gotoid({})" .format(self.getWindowId())) + # lfCmd("{} | norm! 0zz" .format(index + 1 + len(self._head))) + lfCmd("call win_execute({}, 'norm! {}Gzz')" + .format(self.getWindowId(), index + 1 + len(self._head))) + else: + if not self.inFileStructure(path): + lfPrintError("File can't be found!") + return + + meta_info = structure[index-1] + prefix_len = len(meta_info.path) + tree_node = meta_info.info + *directories, file = path[prefix_len:].split("/") + node = tree_node + node.status = FolderStatus.OPEN + for d in directories: + node = node.dirs[d] + node.status = FolderStatus.OPEN + + line_num = index + len(self._head) + increment = self.expandFolder(line_num, index - 1, meta_info, False) + + index = Bisect.bisect_left(structure, 0, index, index + increment, key=getKey) + if index < len(structure) and structure[index].path == path: + lfCmd("call win_execute({}, 'norm! {}Gzz')" + .format(self.getWindowId(), index + 1 + len(self._head))) + # lfCmd("call win_gotoid({})" .format(self.getWindowId())) + # lfCmd("{} | norm! 0zz" .format(index + 1 + len(self._head))) + else: + lfPrintError("BUG: File can't be found!") + + def buildLine(self, meta_info): + if meta_info.is_dir: + if meta_info.info.status == FolderStatus.CLOSED: + icon = self._closed_folder_icon + else: + icon = self._open_folder_icon + return "{}{} {}/".format(" " * meta_info.level, icon, meta_info.name) + else: + num_stat = self._num_stat.get(self._cur_parent, {}).get(meta_info.path, "") + icon = self._status_icons.get(meta_info.info[2][0], self._modification_icon) + + orig_name = "" + if meta_info.info[2][0] in ("R", "C"): + head, tail = os.path.split(meta_info.info[3]) + orig_name = "{} => ".format(lfRelpath(meta_info.info[3], + os.path.dirname(meta_info.info[4]))) + + return "{}{} {}{}\t{}".format(" " * meta_info.level, + icon, + orig_name, + meta_info.name, + num_stat + ) + + def setOptions(self, winid, bufhidden): + super(TreeView, self).setOptions(winid, bufhidden) + lfCmd(r"""call win_execute({}, 'let &l:stl="%#Lf_hl_gitStlChangedNum# 0 %#Lf_hl_gitStlFileChanged#file changed, %#Lf_hl_gitStlAdd#0 (+), %#Lf_hl_gitStlDel#0 (-)"')""" + .format(winid)) + if lfEval("has('nvim')") == '1': + lfCmd("call nvim_win_set_option(%d, 'cursorline', v:true)" % winid) + lfCmd("call nvim_win_set_option(%d, 'number', v:false)" % winid) + else: + lfCmd("call win_execute({}, 'setlocal cursorline')".format(winid)) + lfCmd("call win_execute({}, 'setlocal nonumber')".format(winid)) + lfCmd("call win_execute({}, 'noautocmd setlocal sw=2 tabstop=4')".format(winid)) + lfCmd("call win_execute({}, 'setlocal signcolumn=no')".format(winid)) + lfCmd("call win_execute({}, 'setlocal foldmethod=indent')".format(winid)) + lfCmd("call win_execute({}, 'setlocal foldcolumn=1')".format(winid)) + lfCmd("call win_execute({}, 'setlocal conceallevel=0')".format(winid)) + lfCmd("call win_execute({}, 'setlocal winfixwidth')".format(winid)) + lfCmd("call win_execute({}, 'setlocal winfixheight')".format(winid)) + try: + lfCmd(r"call win_execute({}, 'setlocal list lcs=leadmultispace:¦\ ,tab:\ \ ')" + .format(winid)) + except vim.error: + lfCmd("call win_execute({}, 'setlocal nolist')".format(winid)) + lfCmd("augroup Lf_Git_Colorscheme | augroup END") + lfCmd("autocmd Lf_Git_Colorscheme ColorScheme * call leaderf#colorscheme#popup#load('Git', '{}')" + .format(lfEval("get(g:, 'Lf_PopupColorscheme', 'default')"))) + + def initBuffer(self): + self._buffer.options['modifiable'] = True + try: + self._buffer[:] = self._head + finally: + self._buffer.options['modifiable'] = False + + def writeBuffer(self): + if self._cur_parent is None: + return + + if self._read_finished == 2: + return + + if not self._buffer.valid: + self.stopTimer() + return + + with self._lock: + self._buffer.options['modifiable'] = True + try: + structure = self._file_structures[self._cur_parent] + cur_len = len(structure) + if cur_len > self._offset_in_content: + cursor_line = int(lfEval("getcurpos({})[1]".format(self.getWindowId()))) + init_line = len(self._head) + + if cursor_line <= init_line: + lfCmd("call win_execute({}, 'norm! {}G')".format(self.getWindowId(), init_line)) + cursor_line = int(lfEval("getcurpos({})[1]".format(self.getWindowId()))) + + for info in structure[self._offset_in_content:cur_len]: + self._buffer.append(self.buildLine(info)) + if cursor_line == init_line and not info.is_dir: + cursor_line = len(self._buffer) + lfCmd("call win_execute({}, 'norm! {}G')".format(self.getWindowId(), cursor_line)) + + self._offset_in_content = cur_len + lfCmd("redraw") + finally: + self._buffer.options['modifiable'] = False + + if self._read_finished == 1 and self._offset_in_content == len(structure): + shortstat = re.sub(r"( \d+)( files? changed)", + r"%#Lf_hl_gitStlChangedNum#\1%#Lf_hl_gitStlFileChanged#\2", + self._short_stat[self._cur_parent]) + shortstat = re.sub(r"(\d+) insertions?", r"%#Lf_hl_gitStlAdd#\1 ",shortstat) + shortstat = re.sub(r"(\d+) deletions?", r"%#Lf_hl_gitStlDel#\1 ", shortstat) + lfCmd(r"""call win_execute({}, 'let &l:stl="{}"')""" + .format(self.getWindowId(), shortstat)) + self._read_finished = 2 + self._owner.writeFinished(self.getWindowId()) + self.stopTimer() + + def _readContent(self, encoding): + try: + content = self._executor.execute(self._cmd.getCommand(), encoding=encoding) + for line in content: + self.buildTree(line) + if self._stop_reader_thread: + break + else: + self._read_finished = 1 + self._owner.readFinished(self) + + # if content is empty, getFirstSource() will hang + if self._cur_parent is None: + self._first_source[self._cur_parent] = None + self._source_queue.put((None, None)) + except Exception: + traceback.print_exc() + traceback.print_stack() + self._read_finished = 1 + + def cleanup(self): + super(TreeView, self).cleanup() + + self._match_ids = [] + + +class Panel(object): + def __init__(self): + pass + + def register(self, view): + pass + + def deregister(self, view): + pass + + def bufHidden(self, view): + pass + + def cleanup(self): + pass + + def writeBuffer(self): + pass + + def readFinished(self, view): + pass + + def writeFinished(self, winid): + pass + + +class ResultPanel(Panel): + def __init__(self): + self._views = {} + self._sources = set() + + def register(self, view): + self._views[view.getBufferName()] = view + self._sources.add(view.getSource()) + + def deregister(self, view): + name = view.getBufferName() + if name in self._views: + self._sources.discard(self._views[name].getSource()) + self._views[name].cleanup() + del self._views[name] + + def getSources(self): + return self._sources + + def _createWindow(self, win_pos, buffer_name): + if win_pos == 'tab': + lfCmd("silent! keepa keepj hide edit {}".format(buffer_name)) + elif win_pos == 'top': + lfCmd("silent! noa keepa keepj abo sp {}".format(buffer_name)) + elif win_pos == 'bottom': + lfCmd("silent! noa keepa keepj bel sp {}".format(buffer_name)) + elif win_pos == 'left': + lfCmd("silent! noa keepa keepj abo vsp {}".format(buffer_name)) + elif win_pos == 'right': + lfCmd("silent! noa keepa keepj bel vsp {}".format(buffer_name)) + else: + lfCmd("silent! keepa keepj hide edit {}".format(buffer_name)) + + return int(lfEval("win_getid()")) + + def create(self, cmd, content=None): + buffer_name = cmd.getBufferName() + if buffer_name in self._views and self._views[buffer_name].valid(): + self._views[buffer_name].create(-1, buf_content=content) + else: + arguments = cmd.getArguments() + if arguments.get("mode") == 't': + win_pos = 'tab' + else: + win_pos = arguments.get("--position", ["top"])[0] + winid = self._createWindow(win_pos, buffer_name) + GitCommandView(self, cmd).create(winid, buf_content=content) + + def writeBuffer(self): + for v in self._views.values(): + v.writeBuffer() + + +class PreviewPanel(Panel): + def __init__(self): + self._view = None + self._buffer_contents = {} + self._preview_winid = 0 + + def register(self, view): + if self._view is not None: + self._view.cleanup() + self._view = view + + def deregister(self, view): + if self._view is view: + self._view.cleanup() + self._view = None + + def create(self, cmd, config): + if lfEval("has('nvim')") == '1': + lfCmd("noautocmd let scratch_buffer = nvim_create_buf(0, 1)") + self._preview_winid = int(lfEval("nvim_open_win(scratch_buffer, 0, %s)" + % json.dumps(config))) + else: + lfCmd("noautocmd silent! let winid = popup_create([], %s)" % json.dumps(config)) + self._preview_winid = int(lfEval("winid")) + + GitCommandView(self, cmd).create(self._preview_winid) + + def createView(self, cmd): + if self._preview_winid > 0: + GitCommandView(self, cmd).create(self._preview_winid) + + def writeBuffer(self): + if self._view is not None: + self._view.writeBuffer() + + def getPreviewWinId(self): + return self._preview_winid + + def cleanup(self): + if self._view is not None: + # may never run here + self._view.cleanup() + self._view = None + self._buffer_contents = {} + self._preview_winid = 0 + + def readFinished(self, view): + self._buffer_contents[view.getSource()] = view.getContent() + + def getContent(self, source): + return self._buffer_contents.get(source) + + def setContent(self, content): + if self._view: + self._view.setContent(content) + + +class DiffViewPanel(Panel): + def __init__(self, bufhidden_callback=None, commit_id=""): + self._commit_id = commit_id + self._views = {} + self._hidden_views = {} + # key is current tabpage + self._buffer_names = {} + self._bufhidden_cb = bufhidden_callback + + def setCommitId(self, commit_id): + self._commit_id = commit_id + + def register(self, view): + self._views[view.getBufferName()] = view + + def deregister(self, view): + # :bw + name = view.getBufferName() + if name in self._views: + self._views[name].cleanup(wipe=False) + del self._views[name] + + if name in self._hidden_views: + self._hidden_views[name].cleanup(wipe=False) + del self._hidden_views[name] + + def bufHidden(self, view): + name = view.getBufferName() + del self._views[name] + self._hidden_views[name] = view + lfCmd("call win_execute({}, 'diffoff')".format(view.getWindowId())) + + if self._bufhidden_cb is not None: + self._bufhidden_cb() + + def bufShown(self, buffer_name, winid): + view = self._hidden_views[buffer_name] + view.setWindowId(winid) + del self._hidden_views[buffer_name] + self._views[buffer_name] = view + lfCmd("call win_execute({}, 'diffthis')".format(winid)) + + def cleanup(self): + for view in self._hidden_views.values(): + view.cleanup() + self._hidden_views = {} + + self._buffer_names = {} + + def writeFinished(self, winid): + lfCmd("call win_execute({}, 'diffthis')".format(winid)) + + def getValidWinIDs(self, win_ids): + if win_ids == [-1, -1]: + # won't happen + pass + elif win_ids[0] == -1: + lfCmd("call win_gotoid({})".format(win_ids[1])) + lfCmd("noautocmd leftabove vertical new") + win_ids[0] = int(lfEval("win_getid()")) + elif win_ids[1] == -1: + lfCmd("call win_gotoid({})".format(win_ids[0])) + lfCmd("noautocmd rightbelow vertical new") + win_ids[1] = int(lfEval("win_getid()")) + + return win_ids + + def hasView(self): + return vim.current.tabpage in self._buffer_names + + def isAllHidden(self): + return len(self._views) == 0 + + def create(self, arguments_dict, source, **kwargs): + """ + source is a tuple like (b90f76fc1, bad07e644, R099, src/version.c, src/version2.c) + """ + file_path = lfGetFilePath(source) + sources = ((source[0], source[2], source[3]), + (source[1], source[2], file_path)) + buffer_names = (GitCatFileCommand.buildBufferName(self._commit_id, sources[0]), + GitCatFileCommand.buildBufferName(self._commit_id, sources[1])) + if buffer_names[0] in self._views and buffer_names[1] in self._views: + win_ids = (self._views[buffer_names[0]].getWindowId(), + self._views[buffer_names[1]].getWindowId()) + lfCmd("call win_gotoid({})".format(win_ids[0])) + elif buffer_names[0] in self._views: + lfCmd("call win_gotoid({})".format(self._views[buffer_names[0]].getWindowId())) + cmd = GitCatFileCommand(arguments_dict, sources[1], self._commit_id) + lfCmd("rightbelow vsp {}".format(cmd.getBufferName())) + if buffer_names[1] in self._hidden_views: + self.bufShown(buffer_names[1], int(lfEval("win_getid()"))) + else: + GitCommandView(self, cmd).create(int(lfEval("win_getid()")), bufhidden='hide') + lfCmd("call win_gotoid({})".format(self._views[buffer_names[0]].getWindowId())) + elif buffer_names[1] in self._views: + lfCmd("call win_gotoid({})".format(self._views[buffer_names[1]].getWindowId())) + cmd = GitCatFileCommand(arguments_dict, sources[0], self._commit_id) + lfCmd("leftabove vsp {}".format(cmd.getBufferName())) + if buffer_names[0] in self._hidden_views: + self.bufShown(buffer_names[0], int(lfEval("win_getid()"))) + else: + GitCommandView(self, cmd).create(int(lfEval("win_getid()")), bufhidden='hide') + else: + if kwargs.get("mode", '') == 't': + lfCmd("noautocmd tabnew | vsp") + tabmove() + win_ids = [int(lfEval("win_getid({})".format(w.number))) + for w in vim.current.tabpage.windows] + elif "winid" in kwargs: # --explorer + win_ids = [kwargs["winid"], 0] + lfCmd("call win_gotoid({})".format(win_ids[0])) + lfCmd("noautocmd bel vsp") + win_ids[1] = int(lfEval("win_getid()")) + lfCmd("call win_gotoid({})".format(win_ids[0])) + elif vim.current.tabpage not in self._buffer_names: # Leaderf git diff -s + lfCmd("noautocmd tabnew | vsp") + tabmove() + win_ids = [int(lfEval("win_getid({})".format(w.number))) + for w in vim.current.tabpage.windows] + else: + buffer_names = self._buffer_names[vim.current.tabpage] + win_ids = [int(lfEval("bufwinid('{}')".format(escQuote(name)))) for name in buffer_names] + win_ids = self.getValidWinIDs(win_ids) + + cat_file_cmds = [GitCatFileCommand(arguments_dict, s, self._commit_id) for s in sources] + outputs = [None, None] + if (cat_file_cmds[0].getBufferName() not in self._hidden_views + and cat_file_cmds[1].getBufferName() not in self._hidden_views): + outputs = ParallelExecutor.run(*[cmd.getCommand() for cmd in cat_file_cmds]) + + if vim.current.tabpage not in self._buffer_names: + self._buffer_names[vim.current.tabpage] = [None, None] + + for i, (cmd, winid) in enumerate(zip(cat_file_cmds, win_ids)): + if (lfEval("bufname(winbufnr({}))".format(winid)) == "" + and int(lfEval("bufnr('{}')".format(escQuote(cmd.getBufferName())))) != -1): + lfCmd("call win_execute({}, 'setlocal bufhidden=wipe')".format(winid)) + + buffer_name = lfEval("bufname(winbufnr({}))".format(winid)) + lfCmd("call win_execute({}, 'diffoff | hide edit {}')".format(winid, cmd.getBufferName())) + + # if the buffer also in another tabpage, BufHidden is not triggerd + # should run this code + if buffer_name in self._views: + self.bufHidden(self._views[buffer_name]) + + self._buffer_names[vim.current.tabpage][i] = cmd.getBufferName() + if cmd.getBufferName() in self._hidden_views: + self.bufShown(cmd.getBufferName(), winid) + else: + GitCommandView(self, cmd).create(winid, bufhidden='hide', buf_content=outputs[i]) + + lfCmd("call win_gotoid({})".format(win_ids[0])) + + +class NavigationPanel(Panel): + def __init__(self, bufhidden_callback=None): + self.tree_view = None + self._bufhidden_cb = bufhidden_callback + self._is_hidden = False + + def register(self, view): + self.tree_view = view + + def bufHidden(self, view): + self._is_hidden = True + if self._bufhidden_cb is not None: + self._bufhidden_cb() + + def isHidden(self): + return self._is_hidden + + def cleanup(self): + if self.tree_view is not None: + self.tree_view.cleanup() + self.tree_view = None + + def create(self, cmd, winid, project_root): + TreeView(self, cmd, project_root).create(winid, bufhidden="hide") + + def writeBuffer(self): + # called in idle + if self.tree_view is not None: + self.tree_view.writeBuffer() + + def getFirstSource(self): + return self.tree_view.getFirstSource() + + def getWindowId(self): + return self.tree_view.getWindowId() + + +class ExplorerPage(object): + def __init__(self, project_root, commit_id, owner): + self._project_root = project_root + self._navigation_panel = NavigationPanel(self.afterBufhidden) + self._diff_view_panel = DiffViewPanel(self.afterBufhidden, commit_id) + self._commit_id = commit_id + self._owner = owner + self._arguments = {} + self._win_pos = None + self.tabpage = None + self._git_diff_manager = None + + def _createWindow(self, win_pos, buffer_name): + self._win_pos = win_pos + if win_pos == 'top': + height = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelHeight', &lines * 0.3)"))) + lfCmd("silent! noa keepa keepj abo {}sp {}".format(height, buffer_name)) + elif win_pos == 'bottom': + height = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelHeight', &lines * 0.3)"))) + lfCmd("silent! noa keepa keepj bel {}sp {}".format(height, buffer_name)) + elif win_pos == 'left': + width = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelWidth', &columns * 0.2)"))) + lfCmd("silent! noa keepa keepj abo {}vsp {}".format(width, buffer_name)) + elif win_pos == 'right': + width = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelWidth', &columns * 0.2)"))) + lfCmd("silent! noa keepa keepj bel {}vsp {}".format(width, buffer_name)) + else: # left + width = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelWidth', &columns * 0.2)"))) + lfCmd("silent! noa keepa keepj abo {}vsp {}".format(width, buffer_name)) + + return int(lfEval("win_getid()")) + + def splitWindow(self, win_pos): + if win_pos == 'top': + height = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelHeight', &lines * 0.3)"))) + height = int(lfEval("&lines")) - height - 4 + lfCmd("silent! noa keepa keepj bel {}sp".format(height)) + elif win_pos == 'bottom': + height = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelHeight', &lines * 0.3)"))) + height = int(lfEval("&lines")) - height - 4 + lfCmd("silent! noa keepa keepj abo {}sp".format(height)) + elif win_pos == 'left': + width = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelWidth', &columns * 0.2)"))) + width = int(lfEval("&columns")) - width + 1 + lfCmd("silent! noa keepa keepj bel {}vsp".format(width)) + elif win_pos == 'right': + width = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelWidth', &columns * 0.2)"))) + width = int(lfEval("&columns")) - width - 1 + lfCmd("silent! noa keepa keepj abo {}vsp".format(width)) + else: # left + width = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelWidth', &columns * 0.2)"))) + width = int(lfEval("&columns")) - width + 1 + lfCmd("silent! noa keepa keepj bel {}vsp".format(width)) + + return int(lfEval("win_getid()")) + + def defineMaps(self, winid): + lfCmd("call win_execute({}, 'call leaderf#Git#ExplorerMaps({})')" + .format(winid, id(self))) + + def create(self, arguments_dict, cmd): + self._arguments = arguments_dict + lfCmd("noautocmd tabnew") + + self.tabpage = vim.current.tabpage + diff_view_winid = int(lfEval("win_getid()")) + + win_pos = arguments_dict.get("--navigation-position", ["left"])[0] + winid = self._createWindow(win_pos, cmd.getBufferName()) + + self._navigation_panel.create(cmd, winid, self._project_root) + self.defineMaps(self._navigation_panel.getWindowId()) + + source = self._navigation_panel.getFirstSource() + if source is not None: + self._diff_view_panel.create(arguments_dict, source, winid=diff_view_winid) + lfCmd("call win_gotoid({})".format(self._navigation_panel.getWindowId())) + + def afterBufhidden(self): + if self._navigation_panel.isHidden() and self._diff_view_panel.isAllHidden(): + lfCmd("call timer_start(1, function('leaderf#Git#Cleanup', [{}]))".format(id(self))) + + def cleanup(self): + self._navigation_panel.cleanup() + self._diff_view_panel.cleanup() + + def open(self, recursive, **kwargs): + source = self._navigation_panel.tree_view.expandOrCollapseFolder(recursive) + if source is not None: + if kwargs.get("mode", '') == 't': + tabpage_count = len(vim.tabpages) + self._diff_view_panel.create(self._arguments, source, mode='t') + if len(vim.tabpages) > tabpage_count: + tabmove() + elif len(vim.current.tabpage.windows) == 1: + win_pos = self._arguments.get("--navigation-position", ["left"])[0] + diff_view_winid = self.splitWindow(win_pos) + self._diff_view_panel.create(self._arguments, source, winid=diff_view_winid) + elif not self._diff_view_panel.hasView(): + if self._win_pos in ["top", "left"]: + lfCmd("wincmd w") + else: + lfCmd("wincmd W") + lfCmd("noautocmd leftabove sp") + diff_view_winid = int(lfEval("win_getid()")) + self._diff_view_panel.create(self._arguments, source, winid=diff_view_winid) + else: + self._diff_view_panel.create(self._arguments, source) + + if kwargs.get("preview", False) == True: + lfCmd("call win_gotoid({})".format(self._navigation_panel.getWindowId())) + + def locateFile(self, path): + self._navigation_panel.tree_view.locateFile(path) + self.open(False, preview=True) + + def fuzzySearch(self, recall=False): + if self._git_diff_manager is None: + self._git_diff_manager = GitDiffExplManager() + + kwargs = {} + kwargs["arguments"] = { + "owner": self._owner, + "commit_id": self._commit_id, + "parent": self._navigation_panel.tree_view.getCurrentParent(), + "content": self._navigation_panel.tree_view.getFileList(), + "accept": self.locateFile + } + + if recall == True: + kwargs["arguments"]["--recall"] = [] + + self._git_diff_manager.startExplorer("popup", **kwargs) + + +#***************************************************** +# GitExplManager +#***************************************************** +class GitExplManager(Manager): + def __init__(self): + super(GitExplManager, self).__init__() + self._show_icon = lfEval("get(g:, 'Lf_ShowDevIcons', 1)") == "1" + self._result_panel = ResultPanel() + self._preview_panel = PreviewPanel() + self._git_diff_manager = None + self._git_log_manager = None + self._selected_content = None + self._project_root = "" + + def _getExplClass(self): + return GitExplorer + + def _defineMaps(self): + lfCmd("call leaderf#Git#Maps({})".format(id(self))) + if type(self) is GitExplManager: + lfCmd("call leaderf#Git#SpecificMaps({})".format(id(self))) + + def _createHelp(self): + help = [] + help.append('" //o : execute command under cursor') + help.append('" i/ : switch to input mode') + if type(self) is GitExplManager: + help.append('" e : edit command under cursor') + help.append('" p : preview the help information') + help.append('" q : quit') + help.append('" : toggle this help') + help.append('" : close the preview window or quit') + help.append('" ---------------------------------------------------------') + return help + + def _workInIdle(self, content=None, bang=False): + self._result_panel.writeBuffer() + self._preview_panel.writeBuffer() + + super(GitExplManager, self)._workInIdle(content, bang) + + def _beforeExit(self): + super(GitExplManager, self)._beforeExit() + self._preview_panel.cleanup() + + def getExplManager(self, subcommand): + if subcommand == "diff": + if self._git_diff_manager is None: + self._git_diff_manager = GitDiffExplManager() + return self._git_diff_manager + elif subcommand == "log": + if self._git_log_manager is None: + self._git_log_manager = GitLogExplManager() + return self._git_log_manager + else: + return super(GitExplManager, self) + + def checkWorkingDirectory(self): + self._orig_cwd = lfGetCwd() + self._project_root = nearestAncestor([".git"], self._orig_cwd) + if self._project_root: # there exists a root marker in nearest ancestor path + # https://github.com/neovim/neovim/issues/8336 + if lfEval("has('nvim')") == '1': + chdir = vim.chdir + else: + chdir = os.chdir + chdir(self._project_root) + else: + lfPrintError("Not a git repository (or any of the parent directories): .git") + return False + + return True + + def startExplorer(self, win_pos, *args, **kwargs): + arguments_dict = kwargs.get("arguments", {}) + if "--recall" in arguments_dict: + self._arguments.update(arguments_dict) + else: + self.setArguments(arguments_dict) + + arg_list = self._arguments.get("arg_line", 'git').split() + arg_list = [item for item in arg_list if not item.startswith('-')] + if len(arg_list) == 1: + subcommand = "" + else: + subcommand = arg_list[1] + self.getExplManager(subcommand).startExplorer(win_pos, *args, **kwargs) + + def accept(self, mode=''): + source = self.getSource(self._getInstance().currentLine) + self._selected_content = self._preview_panel.getContent(source) + + return super(GitExplManager, self).accept(mode) + + def _accept(self, file, mode, *args, **kwargs): + self._acceptSelection(file, *args, **kwargs) + + def _acceptSelection(self, *args, **kwargs): + if len(args) == 0: + return + + line = args[0] + cmd = line + try: + lfCmd(cmd) + except vim.error: + lfPrintTraceback() + + def _bangEnter(self): + super(GitExplManager, self)._bangEnter() + + if lfEval("exists('*timer_start')") == '0': + lfCmd("echohl Error | redraw | echo ' E117: Unknown function: timer_start' | echohl NONE") + return + + self._callback(bang=True) + if self._read_finished < 2: + self._timer_id = lfEval("timer_start(10, function('leaderf#Git#TimerCallback', [%d]), {'repeat': -1})" % id(self)) + + def getSource(self, line): + commands = lfEval("leaderf#Git#Commands()") + for cmd in commands: + if line in cmd: + return cmd[line] + + return None + + def _previewInPopup(self, *args, **kwargs): + if len(args) == 0 or args[0] == '': + return + + line = args[0] + source = self.getSource(line) + + self._createPopupPreview("", source, 0) + + def _createPreviewWindow(self, config, source, line_num, jump_cmd): + if lfEval("has('nvim')") == '1': + lfCmd("noautocmd let scratch_buffer = nvim_create_buf(0, 1)") + lfCmd("noautocmd call setbufline(scratch_buffer, 1, '{}')".format(escQuote(source))) + lfCmd("noautocmd call nvim_buf_set_option(scratch_buffer, 'bufhidden', 'wipe')") + lfCmd("noautocmd call nvim_buf_set_option(scratch_buffer, 'undolevels', -1)") + + self._preview_winid = int(lfEval("nvim_open_win(scratch_buffer, 0, {})" + .format(json.dumps(config)))) + else: + lfCmd("noautocmd let winid = popup_create('{}', {})" + .format(escQuote(source), json.dumps(config))) + self._preview_winid = int(lfEval("winid")) + + self._setWinOptions(self._preview_winid) + + def createGitCommand(self, arguments_dict, source): + pass + + def _useExistingWindow(self, title, source, line_num, jump_cmd): + self.setOptionsForCursor() + + if lfEval("has('nvim')") == '1': + lfCmd("""call win_execute({}, "call nvim_buf_set_lines(0, 0, -1, v:false, ['{}'])")""" + .format(self._preview_winid, escQuote(source))) + else: + lfCmd("noautocmd call popup_settext({}, '{}')" + .format(self._preview_winid, escQuote(source))) + + def _cmdExtension(self, cmd): + if type(self) is GitExplManager: + if equal(cmd, ''): + self.editCommand() + return True + + def editCommand(self): + instance = self._getInstance() + line = instance.currentLine + instance.exitBuffer() + lfCmd("call feedkeys(':%s', 'n')" % escQuote(line)) + + +class GitDiffExplManager(GitExplManager): + def __init__(self): + super(GitDiffExplManager, self).__init__() + self._diff_view_panel = DiffViewPanel(self.afterBufhidden) + self._pages = set() + + def _getExplorer(self): + if self._explorer is None: + self._explorer = GitDiffExplorer() + return self._explorer + + def _getDigest(self, line, mode): + return line.split(None, 1)[1] + + def _getDigestStartPos(self, line, mode): + return 5 + + def afterBufhidden(self): + if self._diff_view_panel.isAllHidden(): + lfCmd("call timer_start(1, function('leaderf#Git#Cleanup', [{}]))".format(id(self))) + + def getSource(self, line): + """ + return a tuple like (b90f76fc1, bad07e644, R099, src/version.c, src/version2.c) + """ + if line == '': + return None + + file_name2 = "" + if "\t=>\t" in line: + # 'R050 hello world.txt\t=>\thello world2.txt' + # 'R050  hello world.txt\t=>\thello world2.txt' + tmp = line.split("\t=>\t") + file_name1 = tmp[0].split(None, 2 if self._show_icon else 1)[-1] + file_name2 = tmp[1] + else: + # 'M  runtime/syntax/nix.vim' + file_name1 = line.split()[-1] + + return self._getExplorer().getSourceInfo().get((file_name1, file_name2), + ("", "", "", file_name1, file_name2)) + + def _createPreviewWindow(self, config, source, line_num, jump_cmd): + self._preview_panel.create(self.createGitCommand(self._arguments, source), config) + self._preview_winid = self._preview_panel.getPreviewWinId() + self._setWinOptions(self._preview_winid) + + def getPreviewCommand(self, arguments_dict, source): + arguments_dict.update(self._arguments) + return GitDiffCommand(arguments_dict, source) + + def createGitCommand(self, arguments_dict, source): + if "owner" in arguments_dict: + return arguments_dict["owner"].getPreviewCommand(arguments_dict, source) + else: + return GitDiffCommand(arguments_dict, source) + + def _useExistingWindow(self, title, source, line_num, jump_cmd): + self.setOptionsForCursor() + + content = self._preview_panel.getContent(source) + if content is None: + self._preview_panel.createView(self.createGitCommand(self._arguments, source)) + else: + self._preview_panel.setContent(content) + + def vsplitDiff(self): + if "--cached" not in self._arguments: + if "extra" in self._arguments: + cmd = "git diff {} --raw -- {}".format(" ".join(self._arguments["extra"]), + self._arguments["current_file"]) + + outputs = ParallelExecutor.run(cmd) + if len(outputs[0]) == 0: + lfPrintError("No diffs!") + return + + blob = outputs[0][0].split()[2] + cmd = "git cat-file -p {}".format(blob) + file_name = "LeaderF://{}:{}".format(blob, self._arguments["current_file"]) + else: + cmd = "git show :{}".format(self._arguments["current_file"]) + file_name = "LeaderF://:{}".format(self._arguments["current_file"]) + + win_ids = [int(lfEval("win_getid()")), 0] + lfCmd("keepa keepj abo vsp {}".format(file_name)) + win_ids[1] = int(lfEval("win_getid()")) + lfCmd("augroup Lf_Git | augroup END") + lfCmd("autocmd! Lf_Git BufWipeout call leaderf#Git#DiffOff({})".format(win_ids)) + lfCmd("call win_execute({}, 'autocmd! Lf_Git BufHidden,BufWipeout call leaderf#Git#DiffOff({})')" + .format(win_ids[0], win_ids)) + lfCmd("setlocal nobuflisted") + lfCmd("setlocal buftype=nofile") + lfCmd("setlocal bufhidden=wipe") + lfCmd("setlocal undolevels=-1") + lfCmd("setlocal noswapfile") + lfCmd("setlocal nospell") + + outputs = ParallelExecutor.run(cmd) + vim.current.buffer[:] = outputs[0] + lfCmd("setlocal nomodifiable") + + for winid in win_ids: + lfCmd("call win_execute({}, 'diffthis')".format(winid)) + else: + if "extra" in self._arguments: + extra = " ".join(self._arguments["extra"]) + else: + extra = "" + + cmd = "git diff {} --cached --raw -- {}".format(extra, + self._arguments["current_file"]) + outputs = ParallelExecutor.run(cmd) + if len(outputs[0]) > 0: + _, source = TreeView.generateSource(outputs[0][0]) + self._diff_view_panel.create(self._arguments, source, **{"mode": 't'}) + else: + lfPrintError("No diffs!") + + def startExplorer(self, win_pos, *args, **kwargs): + if self.checkWorkingDirectory() == False: + return + + arguments_dict = kwargs.get("arguments", {}) + if "--recall" not in arguments_dict: + self.setArguments(arguments_dict) + if ("--current-file" in arguments_dict + and vim.current.buffer.name + and not vim.current.buffer.options['bt'] + ): + file_name = vim.current.buffer.name + if " " in file_name: + file_name = file_name.replace(' ', r'\ ') + self._arguments["current_file"] = lfRelpath(file_name) + if "-s" in self._arguments: + self.vsplitDiff() + else: + self._accept(self._arguments["current_file"], "") + return + + if "--recall" in arguments_dict: + super(GitExplManager, self).startExplorer(win_pos, *args, **kwargs) + elif "--directly" in self._arguments: + self._result_panel.create(self.createGitCommand(self._arguments, None)) + self._restoreOrigCwd() + elif "--explorer" in self._arguments: + lfCmd("augroup Lf_Git | augroup END") + lfCmd("autocmd! Lf_Git TabClosed * call leaderf#Git#CleanupExplorerPage({})" + .format(id(self))) + + uid = str(int(time.time()))[-7:] + page = ExplorerPage(self._project_root, uid, self) + page.create(arguments_dict, GitDiffExplCommand(arguments_dict, uid)) + self._pages.add(page) + else: + super(GitExplManager, self).startExplorer(win_pos, *args, **kwargs) + + def _afterEnter(self): + super(GitExplManager, self)._afterEnter() + + if lfEval("get(g:, 'Lf_ShowDevIcons', 1)") == '1': + winid = self._getInstance().getPopupWinId() if self._getInstance().getWinPos() == 'popup' else None + icon_pattern = r'^\S*\s*\zs__icon__' + self._match_ids.extend(matchaddDevIconsExtension(icon_pattern, winid)) + self._match_ids.extend(matchaddDevIconsExact(icon_pattern, winid)) + self._match_ids.extend(matchaddDevIconsDefault(icon_pattern, winid)) + + if self._getInstance().getWinPos() == 'popup': + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_gitDiffModification'', ''^[MRT]\S*'')')""" + % self._getInstance().getPopupWinId()) + id = int(lfEval("matchid")) + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_gitDiffAddition'', ''^[AC]\S*'')')""" + % self._getInstance().getPopupWinId()) + id = int(lfEval("matchid")) + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_gitDiffDeletion'', ''^[DU]'')')""" + % self._getInstance().getPopupWinId()) + id = int(lfEval("matchid")) + else: + id = int(lfEval(r'''matchadd('Lf_hl_gitDiffModification', '^[MRT]\S*')''')) + self._match_ids.append(id) + id = int(lfEval(r'''matchadd('Lf_hl_gitDiffAddition', '^[AC]\S*')''')) + self._match_ids.append(id) + id = int(lfEval(r'''matchadd('Lf_hl_gitDiffDeletion', '^[DU]')''')) + self._match_ids.append(id) + + def _accept(self, file, mode, *args, **kwargs): + if "-s" in self._arguments: + kwargs["mode"] = mode + self._acceptSelection(file, *args, **kwargs) + else: + super(GitExplManager, self)._accept(file, mode, *args, **kwargs) + + def _acceptSelection(self, *args, **kwargs): + if len(args) == 0: + return + + line = args[0] + source = self.getSource(line) + + if "-s" in self._arguments: + self._diff_view_panel.create(self._arguments, source, **kwargs) + elif "accept" in self._arguments: + self._arguments["accept"](lfGetFilePath(source)) + else: + if kwargs.get("mode", '') == 't' and source not in self._result_panel.getSources(): + self._arguments["mode"] = 't' + lfCmd("tabnew") + else: + self._arguments["mode"] = '' + + tabpage_count = len(vim.tabpages) + + self._result_panel.create(self.createGitCommand(self._arguments, source), + self._selected_content) + + if kwargs.get("mode", '') == 't' and len(vim.tabpages) > tabpage_count: + tabmove() + + def cleanup(self): + self._diff_view_panel.cleanup() + + def cleanupExplorerPage(self): + for page in self._pages: + if page.tabpage not in vim.tabpages: + self._pages.discard(page) + return + + +class GitLogExplManager(GitExplManager): + def __init__(self): + super(GitLogExplManager, self).__init__() + lfCmd("augroup Lf_Git | augroup END") + lfCmd("autocmd! Lf_Git FileType git call leaderf#Git#DefineSyntax()") + self._diff_view_panel = None + # key is source, value is ExplorerPage + self._pages = {} + + def _getExplorer(self): + if self._explorer is None: + self._explorer = GitLogExplorer() + return self._explorer + + def afterBufhidden(self): + if self._diff_view_panel.isAllHidden(): + lfCmd("call timer_start(1, function('leaderf#Git#Cleanup', [{}]))".format(id(self))) + + def getSource(self, line): + """ + return the hash + """ + if line == '': + return None + + return line.split(None, 1)[0] + + def _createPreviewWindow(self, config, source, line_num, jump_cmd): + self._preview_panel.create(self.createGitCommand(self._arguments, source), config) + self._preview_winid = self._preview_panel.getPreviewWinId() + self._setWinOptions(self._preview_winid) + + def getPreviewCommand(self, arguments_dict, source): + return GitLogDiffCommand(arguments_dict, source) + + def createGitCommand(self, arguments_dict, source): + return GitLogCommand(arguments_dict, source) + + def _useExistingWindow(self, title, source, line_num, jump_cmd): + self.setOptionsForCursor() + + content = self._preview_panel.getContent(source) + if content is None: + self._preview_panel.createView(self.createGitCommand(self._arguments, source)) + else: + self._preview_panel.setContent(content) + + def startExplorer(self, win_pos, *args, **kwargs): + if self.checkWorkingDirectory() == False: + return + + arguments_dict = kwargs.get("arguments", {}) + if "--recall" not in arguments_dict: + self.setArguments(arguments_dict) + if ("--current-file" in arguments_dict + and vim.current.buffer.name + and not vim.current.buffer.options['bt'] + ): + file_name = vim.current.buffer.name + if " " in file_name: + file_name = file_name.replace(' ', r'\ ') + self._arguments["current_file"] = lfRelpath(file_name) + + if "--recall" in arguments_dict: + super(GitExplManager, self).startExplorer(win_pos, *args, **kwargs) + elif "--directly" in self._arguments: + self._result_panel.create(self.createGitCommand(self._arguments, None)) + self._restoreOrigCwd() + else: + super(GitExplManager, self).startExplorer(win_pos, *args, **kwargs) + + def _afterEnter(self): + super(GitExplManager, self)._afterEnter() + + if self._getInstance().getWinPos() == 'popup': + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_gitHash'', ''^[0-9A-Fa-f]\+'')')""" + % self._getInstance().getPopupWinId()) + id = int(lfEval("matchid")) + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_gitRefNames'', ''^[0-9A-Fa-f]\+\s*\zs(.\{-})'')')""" + % self._getInstance().getPopupWinId()) + id = int(lfEval("matchid")) + else: + id = int(lfEval(r'''matchadd('Lf_hl_gitHash', '^[0-9A-Fa-f]\+')''')) + self._match_ids.append(id) + id = int(lfEval(r'''matchadd('Lf_hl_gitRefNames', '^[0-9A-Fa-f]\+\s*\zs(.\{-})')''')) + self._match_ids.append(id) + + def _accept(self, file, mode, *args, **kwargs): + super(GitExplManager, self)._accept(file, mode, *args, **kwargs) + + def _acceptSelection(self, *args, **kwargs): + if len(args) == 0: + return + + line = args[0] + source = self.getSource(line) + + if "--current-file" in self._arguments and "current_file" in self._arguments: + if self._diff_view_panel is None: + self._diff_view_panel = DiffViewPanel(self.afterBufhidden) + + self._diff_view_panel.setCommitId(source) + cmd = "git show --pretty= --no-color --raw {} -- {}".format(source, + self._arguments["current_file"]) + outputs = ParallelExecutor.run(cmd) + if len(outputs[0]) > 0: + _, source = TreeView.generateSource(outputs[0][0]) + self._diff_view_panel.create(self._arguments, source, **kwargs) + elif "--explorer" in self._arguments: + if source in self._pages: + vim.current.tabpage = self._pages[source].tabpage + else: + lfCmd("augroup Lf_Git | augroup END") + lfCmd("autocmd! Lf_Git TabClosed * call leaderf#Git#CleanupExplorerPage({})" + .format(id(self))) + + self._pages[source] = ExplorerPage(self._project_root, source, self) + self._pages[source].create(self._arguments, + GitLogExplCommand(self._arguments, source)) + else: + if kwargs.get("mode", '') == 't' and source not in self._result_panel.getSources(): + lfCmd("tabnew") + + tabpage_count = len(vim.tabpages) + + self._result_panel.create(self.createGitCommand(self._arguments, source), + self._selected_content) + + if kwargs.get("mode", '') == 't' and len(vim.tabpages) > tabpage_count: + tabmove() + + def cleanup(self): + if self._diff_view_panel is not None: + self._diff_view_panel.cleanup() + + def cleanupExplorerPage(self): + for k, v in self._pages.items(): + if v.tabpage not in vim.tabpages: + del self._pages[k] + return + + +#***************************************************** +# gitExplManager is a singleton +#***************************************************** +gitExplManager = GitExplManager() + +__all__ = ['gitExplManager'] diff --git a/autoload/leaderf/python/leaderf/instance.py b/autoload/leaderf/python/leaderf/instance.py index 67490c35..71b4f165 100644 --- a/autoload/leaderf/python/leaderf/instance.py +++ b/autoload/leaderf/python/leaderf/instance.py @@ -248,7 +248,7 @@ def __init__(self, manager, category, cli, self._tabpage_object = None self._window_object = None self._buffer_object = None - self._buffer_name = 'Leaderf://' + category + '/LeaderF' + self._buffer_name = 'LeaderF://' + category + '/LeaderF' self._input_buffer_number = -1 self._stl_buffer_number = -1 self._win_height = float(lfEval("g:Lf_WindowHeight")) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index e714e357..44662c58 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -408,11 +408,11 @@ def _closePreviewPopup(self): if lfEval("has('nvim')") == '1': if self._preview_winid: if int(lfEval("nvim_win_is_valid(%d) == v:true" % self._preview_winid)): - lfCmd("noautocmd call nvim_win_close(%d, 1)" % self._preview_winid) + lfCmd("call nvim_win_close(%d, 1)" % self._preview_winid) self._preview_winid = 0 else: if self._preview_winid: - lfCmd("noautocmd call popup_close(%d)" % self._preview_winid) + lfCmd("call popup_close(%d)" % self._preview_winid) self._preview_winid = 0 self._preview_filetype = None @@ -848,7 +848,7 @@ def _isBinaryFile(self, filename): lfPrintError(e) return True - def _useExistingWindow(self, title, source, line_num, jump_cmd): + def setOptionsForCursor(self): preview_pos = self._arguments.get("--preview-position", [""])[0] if preview_pos == "": preview_pos = lfEval("get(g:, 'Lf_PreviewPosition', 'top')") @@ -863,6 +863,9 @@ def _useExistingWindow(self, title, source, line_num, jump_cmd): else: lfCmd("call popup_setoptions(%d, %s)" % (self._preview_winid, str(self._preview_config))) + def _useExistingWindow(self, title, source, line_num, jump_cmd): + self.setOptionsForCursor() + if self._orig_source != source: self._orig_source = source @@ -2274,13 +2277,7 @@ def _accept(self, file, mode, *args, **kwargs): self._cursorline_dict.clear() self._issue_422_set_option() if mode == 't' and len(vim.tabpages) > tabpage_count: - tab_pos = int(lfEval("g:Lf_TabpagePosition")) - if tab_pos == 0: - lfCmd("tabm 0") - elif tab_pos == 1: - lfCmd("tabm -1") - elif tab_pos == 3: - lfCmd("tabm") + tabmove() def accept(self, mode=''): if self._getInstance().isReverseOrder(): diff --git a/autoload/leaderf/python/leaderf/rgExpl.py b/autoload/leaderf/python/leaderf/rgExpl.py index a6a13322..e22eb477 100644 --- a/autoload/leaderf/python/leaderf/rgExpl.py +++ b/autoload/leaderf/python/leaderf/rgExpl.py @@ -11,7 +11,6 @@ from .utils import * from .explorer import * from .manager import * -from .mru import * def workingDirectory(func): @wraps(func) diff --git a/autoload/leaderf/python/leaderf/utils.py b/autoload/leaderf/python/leaderf/utils.py index b6b9bdc0..5cf61388 100644 --- a/autoload/leaderf/python/leaderf/utils.py +++ b/autoload/leaderf/python/leaderf/utils.py @@ -1432,3 +1432,12 @@ def deco(self, *args, **kwargs): print(func.__name__, time.time() - start) return deco + +def tabmove(): + tab_pos = int(lfEval("g:Lf_TabpagePosition")) + if tab_pos == 0: + lfCmd("tabm 0") + elif tab_pos == 1: + lfCmd("tabm -1") + elif tab_pos == 3: + lfCmd("tabm") diff --git a/doc/leaderf.txt b/doc/leaderf.txt index f27996f4..0ad19b7c 100644 --- a/doc/leaderf.txt +++ b/doc/leaderf.txt @@ -76,13 +76,13 @@ g:Lf_WindowHeight *g:Lf_WindowHeight* Default value is 0.5. g:Lf_TabpagePosition *g:Lf_TabpagePosition* - Specify where to put the newly opened tab page. + Specify where to put the newly opened tabpage. The value can be 0, 1, 2, ... - 0 - make the newly opened tab page the first one. - 1 - put the newly opened tab page before the current one. - 2 - put the newly opened tab page after the current one. - 3 - make the newly opened tab page the last one. - Default value is 2. + 0 - make the newly opened tabpage the first one. + 1 - put the newly opened tabpage before the current one. + 2 - put the newly opened tabpage after the current one. + 3 - make the newly opened tabpage the last one. + Default value is 3. g:Lf_ShowRelativePath *g:Lf_ShowRelativePath* Whether to show the relative path in the LeaderF window. @@ -1126,6 +1126,51 @@ g:Lf_EnableCircularScroll *g:Lf_EnableCircularScroll* Default value is 0. +g:Lf_GitCommands *g:Lf_GitCommands* + Define a list of commands you may want to use frequently. + The list is as follows: > + let g:Lf_GitCommands = [ + \ {"Leaderf git diff": "fuzzy search and view the diffs"}, + \ {"Leaderf git diff --cached": "fuzzy search and view `git diff --cached`"}, + \ {"Leaderf git diff HEAD": "fuzzy search and view `git diff HEAD`"}, + \ {"Leaderf git diff --side-by-side": "fuzzy search and view the side-by-side diffs"}, + \ ] +< + Open the commands panel using `:Leaderf git` . + +g:Lf_GitFolderIcons *g:Lf_GitFolderIcons* + To customize the folder icons in tree panel. + Default value is { 'open': '', 'closed': '' }. + +g:Lf_GitAddIcon *g:Lf_GitAddIcon* + To customize the icon of added file in tree panel. + Default value is ''. + +g:Lf_GitCopyIcon *g:Lf_GitCopyIcon* + To customize the icon of copied file in tree panel. + Default value is ''. + +g:Lf_GitDelIcon *g:Lf_GitDelIcon* + To customize the icon of deleted file in tree panel. + Default value is ''. + +g:Lf_GitModifyIcon *g:Lf_GitModifyIcon* + To customize the icon of modified file in tree panel. + Default value is ''. + +g:Lf_GitRenameIcon *g:Lf_GitRenameIcon* + To customize the icon of renamed file in tree panel. + Default value is ''. + +g:Lf_GitNavigationPanelHeight *g:Lf_GitNavigationPanelHeight* + To customize the height of navigation(tree) panel. + Default value is &lines * 0.3. + +g:Lf_GitNavigationPanelWidth *g:Lf_GitNavigationPanelWidth* + To customize the width of navigation(tree) panel. + Default value is &columns * 0.2. + + ============================================================================== USAGE *leaderf-usage* From a53c6d24d85a2780d5655a6b3d80073ccf2b4809 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 6 Mar 2024 14:54:16 +0800 Subject: [PATCH 157/365] update the menu of `Leaderf git` --- autoload/leaderf/Any.vim | 2 ++ autoload/leaderf/Git.vim | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/autoload/leaderf/Any.vim b/autoload/leaderf/Any.vim index 25a4357b..c4230dbf 100644 --- a/autoload/leaderf/Any.vim +++ b/autoload/leaderf/Any.vim @@ -236,6 +236,8 @@ let g:Lf_Arguments = { \ ], \ {"name": ["--position"], "nargs": 1, "choices": ["top", "right", "bottom", "left"], "metavar": "", \ "help": "specifies the position of the diffs window"}, + \ {"name": ["--navigation-position"], "nargs": 1, "choices": ["top", "right", "bottom", "left"], "metavar": "", + \ "help": "specifies the position of the navigation panel"}, \ {"name": ["-s", "--side-by-side"], "nargs": 0, "help": "show diffs in a side-by-side view"}, \ {"name": ["--current-file"], "nargs": 0, "help": "show diffs of current file"}, \ {"name": ["extra"], "nargs": "*", "help": "extra arguments of git diff"}, diff --git a/autoload/leaderf/Git.vim b/autoload/leaderf/Git.vim index 381bd77a..e965b802 100644 --- a/autoload/leaderf/Git.vim +++ b/autoload/leaderf/Git.vim @@ -266,19 +266,22 @@ function! leaderf#Git#Commands() \ {"Leaderf git diff": "fuzzy search and view the diffs"}, \ {"Leaderf git diff --side-by-side": "fuzzy search and view the side-by-side diffs"}, \ {"Leaderf git diff --side-by-side --current-file":"view the side-by-side diffs of the current file"}, + \ {"Leaderf git diff --explorer": "view the diffs in an explorer tabpage"}, \ {"Leaderf git diff --directly": "view the diffs directly"}, \ {"Leaderf git diff --directly --position right":"view the diffs in the right split window"}, \ {"Leaderf git diff --cached": "fuzzy search and view `git diff --cached`"}, \ {"Leaderf git diff --cached --side-by-side": "fuzzy search and view the side-by-side diffs of `git diff --cached`"}, + \ {"Leaderf git diff --cached --explorer": "view `git diff --cached` in an explorer tabpage"}, \ {"Leaderf git diff --cached --directly": "view `git diff --cached` directly"}, \ {"Leaderf git diff --cached --directly --position right": "view `git diff --cached` directly in the right split window"}, \ {"Leaderf git diff HEAD": "fuzzy search and view `git diff HEAD`"}, \ {"Leaderf git diff HEAD --side-by-side": "fuzzy search and view the side-by-side diffs of `git diff HEAD`"}, + \ {"Leaderf git diff HEAD --explorer": "view `git diff HEAD` in an explorer tabpage"}, \ {"Leaderf git diff HEAD --directly": "view `git diff HEAD` directly"}, \ {"Leaderf git diff HEAD --directly --position right": "view `git diff HEAD` directly in the right split window"}, \ {"Leaderf git log": "fuzzy search and view the log"}, \ {"Leaderf git log --directly": "view the logs directly"}, - \ {"Leaderf git log --explorer": "fuzzy search and view the logs of in an explorer tabpage"}, + \ {"Leaderf git log --explorer": "fuzzy search and view the log in an explorer tabpage"}, \ {"Leaderf git log --explorer --navigation-position bottom": "specify the position of navigation panel in explorer tabpage"}, \ {"Leaderf git log --current-file": "fuzzy search and view the logs of current file"}, \ ] From 5aca9ca85744ae9cf151bcdf199499885d6e52e0 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 6 Mar 2024 17:53:06 +0800 Subject: [PATCH 158/365] add support for '-n', '--max-count', '--skip', '--since', '--after' --- autoload/leaderf/Any.vim | 3 +++ autoload/leaderf/python/leaderf/gitExpl.py | 20 ++++++++++++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/autoload/leaderf/Any.vim b/autoload/leaderf/Any.vim index c4230dbf..279a4629 100644 --- a/autoload/leaderf/Any.vim +++ b/autoload/leaderf/Any.vim @@ -227,6 +227,9 @@ let g:Lf_Arguments = { \ "help": "specifies the position of the logs window"}, \ {"name": ["--navigation-position"], "nargs": 1, "choices": ["top", "right", "bottom", "left"], "metavar": "", \ "help": "specifies the position of the navigation panel"}, + \ {"name": ["-n", "--max-count"], "nargs": 1, "metavar": "", "help": "Limit the number of commits to output."}, + \ {"name": ["--skip"], "nargs": 1, "metavar": "", "help": "Skip number commits before starting to show the commit output."}, + \ {"name": ["--since", "--after"], "nargs": 1, "metavar": "", "help": "Show commits more recent than a specific date."}, \ ], \ "diff": [ \ {"name": ["--cached", "--staged"], "nargs": 0, "help": "run 'git diff --cached'"}, diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 65cf5881..81e41467 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -129,7 +129,8 @@ def getContent(self, *args, **kwargs): executor = AsyncExecutor() self._executor.append(executor) - cmd = 'git log --pretty=format:"%h%d %s"' + options = GitLogExplorer.generateOptions(arguments_dict) + cmd = 'git log {} --pretty=format:"%h%d %s"'.format(options) if "--current-file" in arguments_dict and "current_file" in arguments_dict: cmd += " -- {}".format(arguments_dict["current_file"]) @@ -144,6 +145,20 @@ def formatLine(self, line): def getStlCategory(self): return 'Git_log' + @staticmethod + def generateOptions(arguments_dict): + options = "" + if "-n" in arguments_dict: + options += "-n %s " % arguments_dict["-n"][0] + + if "--skip" in arguments_dict: + options += "--skip %s " % arguments_dict["--skip"][0] + + if "--since" in arguments_dict: + options += "--since %s " % arguments_dict["--since"][0] + + return options + class GitCommand(object): def __init__(self, arguments_dict, source): @@ -260,7 +275,8 @@ def __init__(self, arguments_dict, source): def buildCommandAndBufferName(self): if "--directly" in self._arguments: - self._cmd = "git log" + options = GitLogExplorer.generateOptions(self._arguments) + self._cmd = "git log {}".format(options) if "extra" in self._arguments: self._cmd += " " + " ".join(self._arguments["extra"]) From b9bce74481e4600c3c35bb34767346a997473764 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 6 Mar 2024 21:22:36 +0800 Subject: [PATCH 159/365] add support for '--until', '--before', '--author', '--committer', '--no-merges' --- autoload/leaderf/Any.vim | 4 ++++ autoload/leaderf/python/leaderf/gitExpl.py | 12 ++++++++++++ 2 files changed, 16 insertions(+) diff --git a/autoload/leaderf/Any.vim b/autoload/leaderf/Any.vim index 279a4629..6c04cfac 100644 --- a/autoload/leaderf/Any.vim +++ b/autoload/leaderf/Any.vim @@ -230,6 +230,10 @@ let g:Lf_Arguments = { \ {"name": ["-n", "--max-count"], "nargs": 1, "metavar": "", "help": "Limit the number of commits to output."}, \ {"name": ["--skip"], "nargs": 1, "metavar": "", "help": "Skip number commits before starting to show the commit output."}, \ {"name": ["--since", "--after"], "nargs": 1, "metavar": "", "help": "Show commits more recent than a specific date."}, + \ {"name": ["--until", "--before"], "nargs": 1, "metavar": "", "help": "Show commits older than a specific date."}, + \ {"name": ["--author"], "nargs": 1, "metavar": "", "help": "Limit the commits output to ones with author header lines that match the specified pattern (regular expression)."}, + \ {"name": ["--committer"], "nargs": 1, "metavar": "", "help": "Limit the commits output to ones with committer header lines that match the specified pattern (regular expression)."}, + \ {"name": ["--no-merges"], "nargs": 0, "help": "Do not print commits with more than one parent."}, \ ], \ "diff": [ \ {"name": ["--cached", "--staged"], "nargs": 0, "help": "run 'git diff --cached'"}, diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 81e41467..1e9f8698 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -157,6 +157,18 @@ def generateOptions(arguments_dict): if "--since" in arguments_dict: options += "--since %s " % arguments_dict["--since"][0] + if "--until" in arguments_dict: + options += "--until %s " % arguments_dict["--until"][0] + + if "--author" in arguments_dict: + options += "--author %s " % arguments_dict["--author"][0] + + if "--committer" in arguments_dict: + options += "--committer %s " % arguments_dict["--committer"][0] + + if "--no-merges" in arguments_dict: + options += "--no-merges " + return options From 0701f987107d4740f7bb5807c659057d80162a01 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 6 Mar 2024 23:13:16 +0800 Subject: [PATCH 160/365] add support for "--all" and "--graph" --- autoload/leaderf/Any.vim | 2 + .../leaderf/colorscheme/popup/default.vim | 10 ++++ autoload/leaderf/python/leaderf/gitExpl.py | 54 +++++++++++++++++-- 3 files changed, 62 insertions(+), 4 deletions(-) diff --git a/autoload/leaderf/Any.vim b/autoload/leaderf/Any.vim index 6c04cfac..57181f4c 100644 --- a/autoload/leaderf/Any.vim +++ b/autoload/leaderf/Any.vim @@ -234,6 +234,8 @@ let g:Lf_Arguments = { \ {"name": ["--author"], "nargs": 1, "metavar": "", "help": "Limit the commits output to ones with author header lines that match the specified pattern (regular expression)."}, \ {"name": ["--committer"], "nargs": 1, "metavar": "", "help": "Limit the commits output to ones with committer header lines that match the specified pattern (regular expression)."}, \ {"name": ["--no-merges"], "nargs": 0, "help": "Do not print commits with more than one parent."}, + \ {"name": ["--all"], "nargs": 0, "help": "Pretend as if all the refs in refs/, along with HEAD, are listed on the command line as ."}, + \ {"name": ["--graph"], "nargs": 0, "help": "Draw a text-based graphical representation of the commit history on the left hand side of the output."}, \ ], \ "diff": [ \ {"name": ["--cached", "--staged"], "nargs": 0, "help": "run 'git diff --cached'"}, diff --git a/autoload/leaderf/colorscheme/popup/default.vim b/autoload/leaderf/colorscheme/popup/default.vim index 60b43a07..7a00d867 100644 --- a/autoload/leaderf/colorscheme/popup/default.vim +++ b/autoload/leaderf/colorscheme/popup/default.vim @@ -162,6 +162,11 @@ if &background ==? 'dark' highlight def link Lf_hl_gitStatNumber Number highlight def link Lf_hl_gitStatPlus Lf_hl_gitNumStatAdd highlight def link Lf_hl_gitStatMinus Lf_hl_gitNumStatDel + highlight def link Lf_hl_gitGraph1 Statement + highlight def link Lf_hl_gitGraph2 String + highlight def link Lf_hl_gitGraph3 Special + highlight def link Lf_hl_gitGraph4 Lf_hl_gitGraph1 + highlight def link Lf_hl_gitGraphSlash Constant else " Lf_hl_popup_inputText is the wincolor of input window highlight def Lf_hl_popup_inputText guifg=#525252 guibg=#f4f3d7 gui=NONE ctermfg=239 ctermbg=230 cterm=NONE @@ -311,4 +316,9 @@ else highlight def link Lf_hl_gitStatNumber Number highlight def link Lf_hl_gitStatPlus Lf_hl_gitNumStatAdd highlight def link Lf_hl_gitStatMinus Lf_hl_gitNumStatDel + highlight def link Lf_hl_gitGraph1 Statement + highlight def link Lf_hl_gitGraph2 String + highlight def link Lf_hl_gitGraph3 Special + highlight def link Lf_hl_gitGraph4 Lf_hl_gitGraph1 + highlight def link Lf_hl_gitGraphSlash Constant endif diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 1e9f8698..3b17a67d 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -169,6 +169,12 @@ def generateOptions(arguments_dict): if "--no-merges" in arguments_dict: options += "--no-merges " + if "--all" in arguments_dict: + options += "--all " + + if "--graph" in arguments_dict: + options += "--graph " + return options @@ -2200,6 +2206,12 @@ def _getExplorer(self): self._explorer = GitLogExplorer() return self._explorer + def _getDigest(self, line, mode): + return line.lstrip(r"*\|/ ") + + def _getDigestStartPos(self, line, mode): + return len(line) - len(line.lstrip(r"*\|/ ")) + def afterBufhidden(self): if self._diff_view_panel.isAllHidden(): lfCmd("call timer_start(1, function('leaderf#Git#Cleanup', [{}]))".format(id(self))) @@ -2208,12 +2220,16 @@ def getSource(self, line): """ return the hash """ + line = line.lstrip(r"*\|/ ") if line == '': return None return line.split(None, 1)[0] def _createPreviewWindow(self, config, source, line_num, jump_cmd): + if source is None: + return + self._preview_panel.create(self.createGitCommand(self._arguments, source), config) self._preview_winid = self._preview_panel.getPreviewWinId() self._setWinOptions(self._preview_winid) @@ -2225,6 +2241,9 @@ def createGitCommand(self, arguments_dict, source): return GitLogCommand(arguments_dict, source) def _useExistingWindow(self, title, source, line_num, jump_cmd): + if source is None: + return + self.setOptionsForCursor() content = self._preview_panel.getContent(source) @@ -2261,16 +2280,41 @@ def _afterEnter(self): super(GitExplManager, self)._afterEnter() if self._getInstance().getWinPos() == 'popup': - lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_gitHash'', ''^[0-9A-Fa-f]\+'')')""" + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_gitGraph1'', ''^|'')')""" + % self._getInstance().getPopupWinId()) + id = int(lfEval("matchid")) + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_gitGraph2'', ''^[*\|/ ]\{2}\zs|'')')""" + % self._getInstance().getPopupWinId()) + id = int(lfEval("matchid")) + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_gitGraph3'', ''^[*\|/ ]\{4}\zs|'')')""" + % self._getInstance().getPopupWinId()) + id = int(lfEval("matchid")) + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_gitGraph4'', ''\(^[*\|/ ]\{6,}\)\@<=|'')')""" + % self._getInstance().getPopupWinId()) + id = int(lfEval("matchid")) + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_gitGraphSlash'', ''\(^[*\|/ ]\{-}\)\@<=[\/]'')')""" + % self._getInstance().getPopupWinId()) + id = int(lfEval("matchid")) + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_gitHash'', ''\(^[*\|/ ]*\)\@<=[0-9A-Fa-f]\+'')')""" % self._getInstance().getPopupWinId()) id = int(lfEval("matchid")) - lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_gitRefNames'', ''^[0-9A-Fa-f]\+\s*\zs(.\{-})'')')""" + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_gitRefNames'', ''^[*\|/ ]*[0-9A-Fa-f]\+\s*\zs(.\{-})'')')""" % self._getInstance().getPopupWinId()) id = int(lfEval("matchid")) else: - id = int(lfEval(r'''matchadd('Lf_hl_gitHash', '^[0-9A-Fa-f]\+')''')) + id = int(lfEval(r'''matchadd('Lf_hl_gitGraph1', '^|')''')) self._match_ids.append(id) - id = int(lfEval(r'''matchadd('Lf_hl_gitRefNames', '^[0-9A-Fa-f]\+\s*\zs(.\{-})')''')) + id = int(lfEval(r'''matchadd('Lf_hl_gitGraph2', '^[*\|/ ]\{2}\zs|')''')) + self._match_ids.append(id) + id = int(lfEval(r'''matchadd('Lf_hl_gitGraph3', '^[*\|/ ]\{4}\zs|')''')) + self._match_ids.append(id) + id = int(lfEval(r'''matchadd('Lf_hl_gitGraph4', '\(^[*\|/ ]\{6,}\)\@<=|')''')) + self._match_ids.append(id) + id = int(lfEval(r'''matchadd('Lf_hl_gitGraphSlash', '\(^[*\|/ ]\{-}\)\@<=[\/]')''')) + self._match_ids.append(id) + id = int(lfEval(r'''matchadd('Lf_hl_gitHash', '\(^[*\|/ ]*\)\@<=[0-9A-Fa-f]\+')''')) + self._match_ids.append(id) + id = int(lfEval(r'''matchadd('Lf_hl_gitRefNames', '^[*\|/ ]*[0-9A-Fa-f]\+\s*\zs(.\{-})')''')) self._match_ids.append(id) def _accept(self, file, mode, *args, **kwargs): @@ -2282,6 +2326,8 @@ def _acceptSelection(self, *args, **kwargs): line = args[0] source = self.getSource(line) + if source is None: + return if "--current-file" in self._arguments and "current_file" in self._arguments: if self._diff_view_panel is None: From 0aa25ef9ea8c4cf4a372a1d938d294cbd02053d6 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 7 Mar 2024 10:32:24 +0800 Subject: [PATCH 161/365] no need to split window in a tabpage --- autoload/leaderf/Any.vim | 2 +- autoload/leaderf/python/leaderf/gitExpl.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/autoload/leaderf/Any.vim b/autoload/leaderf/Any.vim index 57181f4c..d35aa6cd 100644 --- a/autoload/leaderf/Any.vim +++ b/autoload/leaderf/Any.vim @@ -218,7 +218,6 @@ let g:Lf_Arguments = { \ "git":{ \ "log": [ \ {"name": ["--current-file"], "nargs": 0, "help": "show logs of current file"}, - \ {"name": ["extra"], "nargs": "*", "help": "extra arguments of git log"}, \ [ \ {"name": ["--directly"], "nargs": 0, "help": "output the logs directly"}, \ {"name": ["--explorer"], "nargs": 0, "help": "view changed files of one commit in a tree explorer"}, @@ -236,6 +235,7 @@ let g:Lf_Arguments = { \ {"name": ["--no-merges"], "nargs": 0, "help": "Do not print commits with more than one parent."}, \ {"name": ["--all"], "nargs": 0, "help": "Pretend as if all the refs in refs/, along with HEAD, are listed on the command line as ."}, \ {"name": ["--graph"], "nargs": 0, "help": "Draw a text-based graphical representation of the commit history on the left hand side of the output."}, + \ {"name": ["extra"], "nargs": "*", "help": "extra arguments of git log"}, \ ], \ "diff": [ \ {"name": ["--cached", "--staged"], "nargs": 0, "help": "run 'git diff --cached'"}, diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 3b17a67d..4d8d86b3 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -2353,6 +2353,7 @@ def _acceptSelection(self, *args, **kwargs): GitLogExplCommand(self._arguments, source)) else: if kwargs.get("mode", '') == 't' and source not in self._result_panel.getSources(): + self._arguments["mode"] = 't' lfCmd("tabnew") tabpage_count = len(vim.tabpages) From 6305ce26a678470ab684e13a6c62483db623ee9b Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 7 Mar 2024 12:51:41 +0800 Subject: [PATCH 162/365] =?UTF-8?q?fix=20issue=20#1057=20add=20`nix:=20'?= =?UTF-8?q?=F3=B1=84=85'`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- autoload/leaderf/python/leaderf/devicons.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autoload/leaderf/python/leaderf/devicons.py b/autoload/leaderf/python/leaderf/devicons.py index 7c86b98d..7b7798c0 100644 --- a/autoload/leaderf/python/leaderf/devicons.py +++ b/autoload/leaderf/python/leaderf/devicons.py @@ -85,7 +85,7 @@ 'el' : '', 'jsonp' : '', 'pyw' : '', 'xml' : '', 'elm' : '', 'jsx' : '', 'rb' : '', 'xul' : '', 'yaml' : '', 'yaws' : '', 'yml' : '', 'zip' : '', - 'zsh' : '', + 'zsh' : '', 'nix' : '󱄅', } fileNodesExtensionSymbols.update(lfEval("get(g:, 'Lf_DevIconsExtensionSymbols', {})")) From e71acc48b03abcece1a85a206ff4e9e61619ab94 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Fri, 8 Mar 2024 16:50:30 +0800 Subject: [PATCH 163/365] adjust the fuzzy match score algorithm --- autoload/leaderf/fuzzyMatch_C/fuzzyMatch.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/autoload/leaderf/fuzzyMatch_C/fuzzyMatch.c b/autoload/leaderf/fuzzyMatch_C/fuzzyMatch.c index d6e0fc19..cc193541 100644 --- a/autoload/leaderf/fuzzyMatch_C/fuzzyMatch.c +++ b/autoload/leaderf/fuzzyMatch_C/fuzzyMatch.c @@ -468,13 +468,15 @@ ValueElements* evaluate(TextContext* pText_ctxt, #endif special = k == 0 ? 5 : 3; else if ( isupper(text[i]) ) - special = !isupper(text[i-1]) || (i+1 < text_len && islower(text[i+1])) ? 3 : 0; + special = (!isupper(text[i-1]) || (i+1 < text_len && islower(text[i+1])) ? + (i < 5 ? 5 : 3) : 0); /* else if ( text[i-1] == '_' || text[i-1] == '-' || text[i-1] == ' ' ) */ /* special = 3; */ /* else if ( text[i-1] == '.' ) */ /* special = 3; */ else if ( !isalnum(text[i-1]) ) - special = 3; + /* if there is an icon at the beginning, `if ( i == 0 )` won't meet */ + special = i < 5 ? 5 : 3; else special = 0; ++i; @@ -891,7 +893,7 @@ float getWeight(const char* text, uint16_t text_len, free(text_mask); - return score + (float)pattern_len/text_len + (float)(pattern_len << 1)/(text_len - beg); + return score + (float)(pattern_len<<1)/text_len + (float)pattern_len/(text_len - beg); } } From ef8ad13552d505ae8ae39e4327c029dafa34ade1 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Fri, 8 Mar 2024 17:05:23 +0800 Subject: [PATCH 164/365] show icon --- autoload/leaderf/python/leaderf/gitExpl.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 4d8d86b3..a8c5ba60 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -679,6 +679,7 @@ def __init__(self, owner, cmd, project_root): self._first_source = {} self._left_most_file = set() self._source_queue = Queue.Queue() + self._show_icon = lfEval("get(g:, 'Lf_ShowDevIcons', 1)") == "1" folder_icons = lfEval("g:Lf_GitFolderIcons") self._closed_folder_icon = folder_icons["closed"] self._open_folder_icon = folder_icons["open"] @@ -896,8 +897,9 @@ def buildTree(self, line): parent, tree_node = self._trees.last_key_value() mode, source = TreeView.generateSource(line) file_path = lfGetFilePath(source) - self._file_list[parent].append("{:<4} {}{}" - .format(source[2], source[3], + icon = webDevIconsGetFileTypeSymbol(file_path) if self._show_icon else "" + self._file_list[parent].append("{:<4} {}{}{}" + .format(source[2], icon, source[3], "" if source[4] == "" else "\t=>\t" + source[4]) ) From fc8a0ea4aa6341f6ee6c3004af6e92b7ee1d3863 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Fri, 8 Mar 2024 17:13:46 +0800 Subject: [PATCH 165/365] add "--reverse-order" --- autoload/leaderf/Any.vim | 1 + autoload/leaderf/python/leaderf/gitExpl.py | 3 +++ 2 files changed, 4 insertions(+) diff --git a/autoload/leaderf/Any.vim b/autoload/leaderf/Any.vim index d35aa6cd..207ba8c8 100644 --- a/autoload/leaderf/Any.vim +++ b/autoload/leaderf/Any.vim @@ -235,6 +235,7 @@ let g:Lf_Arguments = { \ {"name": ["--no-merges"], "nargs": 0, "help": "Do not print commits with more than one parent."}, \ {"name": ["--all"], "nargs": 0, "help": "Pretend as if all the refs in refs/, along with HEAD, are listed on the command line as ."}, \ {"name": ["--graph"], "nargs": 0, "help": "Draw a text-based graphical representation of the commit history on the left hand side of the output."}, + \ {"name": ["--reverse-order"], "nargs": 0, "help": "Output the commits chosen to be shown in reverse order."}, \ {"name": ["extra"], "nargs": "*", "help": "extra arguments of git log"}, \ ], \ "diff": [ diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index a8c5ba60..ab74b879 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -175,6 +175,9 @@ def generateOptions(arguments_dict): if "--graph" in arguments_dict: options += "--graph " + if "--reverse-order" in arguments_dict: + options += "--reverse " + return options From 2222c2e40ae81b2229f0f2b161fa03b5afd78784 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Tue, 12 Mar 2024 16:20:57 +0800 Subject: [PATCH 166/365] fix a bug to reproduce: Leaderf git log --explorer close a window, then edit a normal file, then open the diff --- autoload/leaderf/python/leaderf/gitExpl.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index ab74b879..6430c079 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -1517,8 +1517,10 @@ def writeFinished(self, winid): def getValidWinIDs(self, win_ids): if win_ids == [-1, -1]: - # won't happen - pass + lfCmd("wincmd w | leftabove new") + win_ids[1] = int(lfEval("win_getid()")) + lfCmd("noautocmd leftabove vertical new") + win_ids[0] = int(lfEval("win_getid()")) elif win_ids[0] == -1: lfCmd("call win_gotoid({})".format(win_ids[1])) lfCmd("noautocmd leftabove vertical new") From 1b1c9f21ed72a12fb7cc430edb1549e83f9b413b Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Tue, 12 Mar 2024 22:37:06 +0800 Subject: [PATCH 167/365] optimize the performance of `Leaderf git diff` --- autoload/leaderf/fuzzyMatch_C/fuzzyEngine.c | 27 +++++++++++++++++++++ autoload/leaderf/python/leaderf/gitExpl.py | 15 ++++++++++-- autoload/leaderf/python/leaderf/manager.py | 6 +++++ 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/autoload/leaderf/fuzzyMatch_C/fuzzyEngine.c b/autoload/leaderf/fuzzyMatch_C/fuzzyEngine.c index bd9764bc..d21b1685 100644 --- a/autoload/leaderf/fuzzyMatch_C/fuzzyEngine.c +++ b/autoload/leaderf/fuzzyMatch_C/fuzzyEngine.c @@ -1863,6 +1863,7 @@ enum Category_File, Category_Gtags, Category_Line, + Category_GitDiff, }; typedef struct RgParameter @@ -2130,6 +2131,18 @@ static void line_getDigest(char** str, uint32_t* length, Parameter* param) } } +static void gitdiff_getDigest(char** str, uint32_t* length, Parameter* param) +{ + if ( param->mode == 0 ) { + uint32_t len = 5; + *str += len; + *length -= len; + } + else { + file_getDigest(str, length, param); + } +} + /** * fuzzyMatchPart(engine, source, pattern, category, param, is_name_only=False, sort_results=True) * @@ -2314,6 +2327,9 @@ static PyObject* fuzzyEngine_fuzzyMatchPart(PyObject* self, PyObject* args, PyOb case Category_Line: line_getDigest(&s->str, &s->len, (Parameter*)PyCapsule_GetPointer(py_param, NULL)); break; + case Category_GitDiff: + gitdiff_getDigest(&s->str, &s->len, (Parameter*)PyCapsule_GetPointer(py_param, NULL)); + break; } } @@ -2567,6 +2583,12 @@ PyMODINIT_FUNC PyInit_fuzzyEngine(void) return NULL; } + if ( PyModule_AddObject(module, "Category_GitDiff", Py_BuildValue("I", Category_GitDiff)) ) + { + Py_DECREF(module); + return NULL; + } + return module; } @@ -2610,6 +2632,11 @@ PyMODINIT_FUNC initfuzzyEngine(void) return; } + if ( PyModule_AddObject(module, "Category_GitDiff", Py_BuildValue("I", Category_GitDiff)) ) + { + Py_DECREF(module); + return; + } } #endif diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 6430c079..b783a5dc 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -77,6 +77,9 @@ def __init__(self): super(GitDiffExplorer, self).__init__() self._source_info = {} + def supportsNameOnly(self): + return True + def getContent(self, *args, **kwargs): arguments_dict = kwargs.get("arguments", {}) @@ -1983,10 +1986,18 @@ def _getExplorer(self): return self._explorer def _getDigest(self, line, mode): - return line.split(None, 1)[1] + if mode == 0: + return line[5:] + elif mode == 1: + return getBasename(line) + else: + return getDirname(line[5:]) def _getDigestStartPos(self, line, mode): - return 5 + if mode == 0 or mode == 2: + return 5 + else: + return lfBytesLen(getDirname(line)) def afterBufhidden(self): if self._diff_view_panel.isAllHidden(): diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 44662c58..504e061d 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -1869,6 +1869,12 @@ def _fuzzySearch(self, content, is_continue, step): filter_method = partial(fuzzyEngine.fuzzyMatchPart, engine=self._fuzzy_engine, pattern=pattern, category=fuzzyEngine.Category_Line, param=fuzzyEngine.createParameter(1), is_name_only=True, sort_results=do_sort) + elif self._getExplorer().getStlCategory() == "Git_diff": + return_index = False + mode = 0 if self._cli.isFullPath else 1 + filter_method = partial(fuzzyEngine.fuzzyMatchPart, engine=self._fuzzy_engine, + pattern=pattern, category=fuzzyEngine.Category_GitDiff, + param=fuzzyEngine.createParameter(mode), is_name_only=False, sort_results=do_sort) elif self._getExplorer().getStlCategory() in ["Self", "Buffer", "Mru", "BufTag", "Function", "History", "Cmd_History", "Search_History", "Filetype", "Command", "Window", "QuickFix", "LocList"]: From 735a2f36d3a25e320182bf3f385f5530d674600e Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Fri, 29 Mar 2024 13:46:12 +0800 Subject: [PATCH 168/365] update the color of Lf_hl_gitDiffModification --- autoload/leaderf/colorscheme/popup/default.vim | 8 ++++---- autoload/leaderf/python/leaderf/gitExpl.py | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/autoload/leaderf/colorscheme/popup/default.vim b/autoload/leaderf/colorscheme/popup/default.vim index 7a00d867..89445ef7 100644 --- a/autoload/leaderf/colorscheme/popup/default.vim +++ b/autoload/leaderf/colorscheme/popup/default.vim @@ -138,7 +138,7 @@ if &background ==? 'dark' highlight def link Lf_hl_jumpsLineCol String highlight def link Lf_hl_jumpsIndicator Type - highlight def Lf_hl_gitDiffModification guifg=#ffa500 guibg=NONE gui=NONE ctermfg=214 ctermbg=NONE cterm=NONE + highlight def Lf_hl_gitDiffModification guifg=#87afff guibg=NONE gui=NONE ctermfg=111 ctermbg=NONE cterm=NONE highlight def Lf_hl_gitDiffAddition guifg=#a8e332 guibg=NONE gui=NONE ctermfg=148 ctermbg=NONE cterm=NONE highlight def Lf_hl_gitDiffDeletion guifg=#ff477e guibg=NONE gui=NONE ctermfg=204 ctermbg=NONE cterm=NONE highlight def link Lf_hl_gitHash Identifier @@ -148,7 +148,7 @@ if &background ==? 'dark' highlight def link Lf_hl_gitAddIcon Lf_hl_gitDiffAddition highlight def link Lf_hl_gitCopyIcon Lf_hl_gitDiffAddition highlight def link Lf_hl_gitDelIcon Lf_hl_gitDiffDeletion - highlight def link Lf_hl_gitModificationIcon Lf_hl_gitDiffModification + highlight def link Lf_hl_gitModifyIcon Lf_hl_gitDiffModification highlight def link Lf_hl_gitRenameIcon Lf_hl_gitDiffAddition highlight def link Lf_hl_gitNumStatAdd Lf_hl_gitDiffAddition highlight def link Lf_hl_gitNumStatDel Lf_hl_gitDiffDeletion @@ -292,7 +292,7 @@ else highlight def link Lf_hl_jumpsLineCol String highlight def link Lf_hl_jumpsIndicator Type - highlight def Lf_hl_gitDiffModification guifg=#df5f00 guibg=NONE gui=NONE ctermfg=166 ctermbg=NONE cterm=NONE + highlight def Lf_hl_gitDiffModification guifg=#5f87af guibg=NONE gui=NONE ctermfg=67 ctermbg=NONE cterm=NONE highlight def Lf_hl_gitDiffAddition guifg=#008700 guibg=NONE gui=NONE ctermfg=28 ctermbg=NONE cterm=NONE highlight def Lf_hl_gitDiffDeletion guifg=#df0000 guibg=NONE gui=NONE ctermfg=160 ctermbg=NONE cterm=NONE highlight def link Lf_hl_gitHash Identifier @@ -302,7 +302,7 @@ else highlight def link Lf_hl_gitAddIcon Lf_hl_gitDiffAddition highlight def link Lf_hl_gitCopyIcon Lf_hl_gitDiffAddition highlight def link Lf_hl_gitDelIcon Lf_hl_gitDiffDeletion - highlight def link Lf_hl_gitModificationIcon Lf_hl_gitDiffModification + highlight def link Lf_hl_gitModifyIcon Lf_hl_gitDiffModification highlight def link Lf_hl_gitRenameIcon Lf_hl_gitDiffAddition highlight def link Lf_hl_gitNumStatAdd Lf_hl_gitDiffAddition highlight def link Lf_hl_gitNumStatDel Lf_hl_gitDiffDeletion diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index b783a5dc..345aec4c 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -738,7 +738,7 @@ def enableColor(self, winid): .format(winid, self._del_icon)) id = int(lfEval("matchid")) self._match_ids.append(id) - lfCmd(r"""call win_execute({}, 'let matchid = matchadd(''Lf_hl_gitModificationIcon'', ''^\s*\zs{}'', -100)')""" + lfCmd(r"""call win_execute({}, 'let matchid = matchadd(''Lf_hl_gitModifyIcon'', ''^\s*\zs{}'', -100)')""" .format(winid, self._modification_icon)) id = int(lfEval("matchid")) self._match_ids.append(id) From 4947e13e7c02de84f6322ea6c2bbc418617e0109 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 11 Apr 2024 13:36:34 +0800 Subject: [PATCH 169/365] add support for `Leaderf git blame` --- autoload/leaderf/Any.vim | 2 +- autoload/leaderf/Git.vim | 57 ++- .../leaderf/colorscheme/popup/default.vim | 8 +- autoload/leaderf/python/leaderf/gitExpl.py | 415 +++++++++++++++--- 4 files changed, 384 insertions(+), 98 deletions(-) diff --git a/autoload/leaderf/Any.vim b/autoload/leaderf/Any.vim index 207ba8c8..9c9ae95a 100644 --- a/autoload/leaderf/Any.vim +++ b/autoload/leaderf/Any.vim @@ -253,7 +253,7 @@ let g:Lf_Arguments = { \ {"name": ["extra"], "nargs": "*", "help": "extra arguments of git diff"}, \ ], \ "blame": [ - \ {"name": ["--abc"], "nargs": 0, "help": ""}, + \ {"name": ["-w"], "nargs": 0, "help": "Ignore whitespace when comparing the parent’s version and the child’s to find where the lines came from."}, \ ], \ }, \} diff --git a/autoload/leaderf/Git.vim b/autoload/leaderf/Git.vim index e965b802..c8a0c63f 100644 --- a/autoload/leaderf/Git.vim +++ b/autoload/leaderf/Git.vim @@ -101,24 +101,26 @@ function! leaderf#Git#OuterBlock(direction) call search(printf('^\s\{%d}\zs\S', width), flags) endfunction -let s:help = [ - \ "o: open the folder or open the diffs of current file", - \ ": open the folder or open the diffs of current file", - \ "<2-LeftMouse>: open the folder or open the diffs of current file", - \ "O: open the folder recursively", - \ "t: open the diffs in a new tabpage", - \ "p: preview the diffs, i.e., like 'o', but leave the cursor in the current panel", - \ "x: collapse the parent folder", - \ "X: collapse all the children of the current folder", - \ "f: fuzzy search files", - \ "F: resume the previous fuzzy searching", - \ "-: go to the parent folder", - \ "+: go to the next sibling of the parent folder", - \ ": go to the next sibling of the current folder", - \ ": go to the previous sibling of the current folder", - \ "(: go to the start of the current indent level", - \ "): go to the end of the current indent level", - \] +let s:help = { + \ "tree": [ + \ "o: open the folder or open the diffs of current file", + \ ": open the folder or open the diffs of current file", + \ "<2-LeftMouse>: open the folder or open the diffs of current file", + \ "O: open the folder recursively", + \ "t: open the diffs in a new tabpage", + \ "p: preview the diffs, i.e., like 'o', but leave the cursor in the current panel", + \ "x: collapse the parent folder", + \ "X: collapse all the children of the current folder", + \ "f: fuzzy search files", + \ "F: resume the previous fuzzy searching", + \ "-: go to the parent folder", + \ "+: go to the next sibling of the parent folder", + \ ": go to the next sibling of the current folder", + \ ": go to the previous sibling of the current folder", + \ "(: go to the start of the current indent level", + \ "): go to the end of the current indent level", + \ ] + \} function s:HelpFilter(winid, key) if a:key == "\" || a:key == "\" @@ -138,7 +140,7 @@ function! s:GetRowCol(width, height) return {'row': row, 'col': col} endfunction -function! leaderf#Git#ShowHelp() +function! leaderf#Git#ShowHelp(type) if has("nvim") let borderchars = [ \ [g:Lf_PopupBorders[4], "Lf_hl_popupBorder"], @@ -151,7 +153,7 @@ function! leaderf#Git#ShowHelp() \ [g:Lf_PopupBorders[3], "Lf_hl_popupBorder"] \] let width = 100 - let height = len(s:help) + let height = len(s:help[a:type]) let row_col = s:GetRowCol(width, height) let options = { \ "title": " Help ", @@ -168,7 +170,7 @@ function! leaderf#Git#ShowHelp() \} let scratch_buffer = nvim_create_buf(v:false, v:true) call nvim_buf_set_option(scratch_buffer, 'bufhidden', 'wipe') - call nvim_buf_set_lines(scratch_buffer, 0, -1, v:false, s:help) + call nvim_buf_set_lines(scratch_buffer, 0, -1, v:false, s:help[a:type]) call nvim_buf_set_option(scratch_buffer, 'modifiable', v:false) let id = nvim_open_win(scratch_buffer, 1, options) call nvim_win_set_option(id, 'winhighlight', 'Normal:Lf_hl_popup_window') @@ -189,7 +191,7 @@ function! leaderf#Git#ShowHelp() \ "mapping": 0, \} - let id = popup_create(s:help, options) + let id = popup_create(s:help[a:type], options) call win_execute(id, 'setlocal wincolor=Lf_hl_popup_window') call win_execute(id, 'call matchadd("Special", ''^.\{-}\(:\)\@='')') call win_execute(id, 'call matchadd("Comment", ''\(^.\{-}:\s*\)\@<=.*'')') @@ -200,7 +202,7 @@ function! leaderf#Git#TreeViewMaps(id) exec g:Lf_py "import ctypes" let tree_view = printf("ctypes.cast(%d, ctypes.py_object).value", a:id) exec printf('nnoremap X :exec g:Lf_py "%s.collapseChildren()"', tree_view) - nnoremap :call leaderf#Git#ShowHelp() + nnoremap :call leaderf#Git#ShowHelp("tree") nnoremap - :call leaderf#Git#OuterIndent(0) nnoremap + :call leaderf#Git#OuterIndent(1) nnoremap :call leaderf#Git#SameIndent(0) @@ -230,6 +232,15 @@ function! leaderf#Git#ExplorerMaps(id) nnoremap q :q endfunction +function! leaderf#Git#BlameMaps(id) + exec g:Lf_py "import ctypes" + let explorer_page = printf("ctypes.cast(%d, ctypes.py_object).value", a:id) + exec printf('nnoremap o :exec g:Lf_py "%s.open()"', explorer_page) + exec printf('nnoremap <2-LeftMouse> :exec g:Lf_py "%s.open()"', explorer_page) + exec printf('nnoremap :exec g:Lf_py "%s.open()"', explorer_page) + nnoremap q :q +endfunction + function! leaderf#Git#TimerCallback(manager_id, id) exec g:Lf_py "import ctypes" exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value._callback(bang=True)", a:manager_id) diff --git a/autoload/leaderf/colorscheme/popup/default.vim b/autoload/leaderf/colorscheme/popup/default.vim index 89445ef7..f5aef20d 100644 --- a/autoload/leaderf/colorscheme/popup/default.vim +++ b/autoload/leaderf/colorscheme/popup/default.vim @@ -146,10 +146,10 @@ if &background ==? 'dark' highlight def link Lf_hl_gitFolder Directory highlight def link Lf_hl_gitFolderIcon Special highlight def link Lf_hl_gitAddIcon Lf_hl_gitDiffAddition - highlight def link Lf_hl_gitCopyIcon Lf_hl_gitDiffAddition + highlight def link Lf_hl_gitCopyIcon Number highlight def link Lf_hl_gitDelIcon Lf_hl_gitDiffDeletion highlight def link Lf_hl_gitModifyIcon Lf_hl_gitDiffModification - highlight def link Lf_hl_gitRenameIcon Lf_hl_gitDiffAddition + highlight def link Lf_hl_gitRenameIcon Constant highlight def link Lf_hl_gitNumStatAdd Lf_hl_gitDiffAddition highlight def link Lf_hl_gitNumStatDel Lf_hl_gitDiffDeletion highlight def link Lf_hl_gitNumStatBinary Constant @@ -300,10 +300,10 @@ else highlight def link Lf_hl_gitFolder Directory highlight def link Lf_hl_gitFolderIcon Special highlight def link Lf_hl_gitAddIcon Lf_hl_gitDiffAddition - highlight def link Lf_hl_gitCopyIcon Lf_hl_gitDiffAddition + highlight def link Lf_hl_gitCopyIcon Number highlight def link Lf_hl_gitDelIcon Lf_hl_gitDiffDeletion highlight def link Lf_hl_gitModifyIcon Lf_hl_gitDiffModification - highlight def link Lf_hl_gitRenameIcon Lf_hl_gitDiffAddition + highlight def link Lf_hl_gitRenameIcon Constant highlight def link Lf_hl_gitNumStatAdd Lf_hl_gitDiffAddition highlight def link Lf_hl_gitNumStatDel Lf_hl_gitDiffDeletion highlight def link Lf_hl_gitNumStatBinary Constant diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 345aec4c..846aeb37 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -13,6 +13,7 @@ import queue as Queue else: import Queue +from functools import partial from enum import Enum from collections import OrderedDict from .utils import * @@ -358,9 +359,35 @@ def buildCommandAndBufferName(self): self._file_type_cmd = "" +class GitBlameCommand(GitCommand): + def __init__(self, arguments_dict, source): + super(GitBlameCommand, self).__init__(arguments_dict, source) + + def buildCommandAndBufferName(self): + source = "" + if self._source is not None: + source = self._source + + extra_options = "" + if "-w" in self._arguments: + extra_options += " -w" + + self._cmd = "git blame -f -n {} {} -- ".format(extra_options, source) + + file_name = vim.current.buffer.name + if " " in file_name: + file_name = file_name.replace(' ', r'\ ') + file_name = lfRelpath(file_name) + + self._cmd += file_name + self._buffer_name = "LeaderF://git blame {} {}".format(source, file_name) + self._file_type = "" + self._file_type_cmd = "" + + class ParallelExecutor(object): @staticmethod - def run(*cmds): + def run(*cmds, format_line=None): outputs = [[] for _ in range(len(cmds))] stop_thread = False @@ -378,7 +405,7 @@ def readContent(content, output): executors = [AsyncExecutor() for _ in range(len(cmds))] workers = [] for i, (exe, cmd) in enumerate(zip(executors, cmds)): - content = exe.execute(cmd, encoding=lfEval("&encoding")) + content = exe.execute(cmd, encoding=lfEval("&encoding"), format_line=format_line) worker = threading.Thread(target=readContent, args=(content, outputs[i])) worker.daemon = True worker.start() @@ -403,6 +430,7 @@ def __init__(self, owner, cmd): self._buffer = None self._window_id = -1 self._bufhidden = 'wipe' + self._format_line = None self.init() owner.register(self) @@ -466,13 +494,11 @@ def defineMaps(self, winid): def enableColor(self, winid): pass - def create(self, winid, bufhidden='wipe', buf_content=None): + def create(self, winid, bufhidden='wipe', buf_content=None, format_line=None): self._bufhidden = bufhidden + self._format_line = format_line if self._buffer is not None: - self._buffer.options['modifiable'] = True - del self._buffer[:] - self._buffer.options['modifiable'] = False self.cleanup() lfCmd("call win_gotoid({})".format(self.getWindowId())) @@ -544,7 +570,10 @@ def writeBuffer(self): def _readContent(self, encoding): try: - content = self._executor.execute(self._cmd.getCommand(), encoding=encoding) + content = self._executor.execute(self._cmd.getCommand(), + encoding=encoding, + format_line=self._format_line + ) for line in content: self._content.append(line) if self._stop_reader_thread: @@ -586,6 +615,131 @@ def valid(self): return self._buffer is not None and self._buffer.valid +class GitBlameView(GitCommandView): + def __init__(self, owner, cmd): + super(GitBlameView, self).__init__(owner, cmd) + self._alternative_winid = None + self._alternative_win_options = {} + self._match_ids = [] + self._color_table = { + '0': '#000000', '1': '#800000', '2': '#008000', '3': '#808000', + '4': '#000080', '5': '#800080', '6': '#008080', '7': '#c0c0c0', + '8': '#808080', '9': '#ff0000', '10': '#00ff00', '11': '#ffff00', + '12': '#0000ff', '13': '#ff00ff', '14': '#00ffff', '15': '#ffffff', + '16': '#000000', '17': '#00005f', '18': '#000087', '19': '#0000af', + '20': '#0000d7', '21': '#0000ff', '22': '#005f00', '23': '#005f5f', + '24': '#005f87', '25': '#005faf', '26': '#005fd7', '27': '#005fff', + '28': '#008700', '29': '#00875f', '30': '#008787', '31': '#0087af', + '32': '#0087d7', '33': '#0087ff', '34': '#00af00', '35': '#00af5f', + '36': '#00af87', '37': '#00afaf', '38': '#00afd7', '39': '#00afff', + '40': '#00d700', '41': '#00d75f', '42': '#00d787', '43': '#00d7af', + '44': '#00d7d7', '45': '#00d7ff', '46': '#00ff00', '47': '#00ff5f', + '48': '#00ff87', '49': '#00ffaf', '50': '#00ffd7', '51': '#00ffff', + '52': '#5f0000', '53': '#5f005f', '54': '#5f0087', '55': '#5f00af', + '56': '#5f00d7', '57': '#5f00ff', '58': '#5f5f00', '59': '#5f5f5f', + '60': '#5f5f87', '61': '#5f5faf', '62': '#5f5fd7', '63': '#5f5fff', + '64': '#5f8700', '65': '#5f875f', '66': '#5f8787', '67': '#5f87af', + '68': '#5f87d7', '69': '#5f87ff', '70': '#5faf00', '71': '#5faf5f', + '72': '#5faf87', '73': '#5fafaf', '74': '#5fafd7', '75': '#5fafff', + '76': '#5fd700', '77': '#5fd75f', '78': '#5fd787', '79': '#5fd7af', + '80': '#5fd7d7', '81': '#5fd7ff', '82': '#5fff00', '83': '#5fff5f', + '84': '#5fff87', '85': '#5fffaf', '86': '#5fffd7', '87': '#5fffff', + '88': '#870000', '89': '#87005f', '90': '#870087', '91': '#8700af', + '92': '#8700d7', '93': '#8700ff', '94': '#875f00', '95': '#875f5f', + '96': '#875f87', '97': '#875faf', '98': '#875fd7', '99': '#875fff', + '100': '#878700', '101': '#87875f', '102': '#878787', '103': '#8787af', + '104': '#8787d7', '105': '#8787ff', '106': '#87af00', '107': '#87af5f', + '108': '#87af87', '109': '#87afaf', '110': '#87afd7', '111': '#87afff', + '112': '#87d700', '113': '#87d75f', '114': '#87d787', '115': '#87d7af', + '116': '#87d7d7', '117': '#87d7ff', '118': '#87ff00', '119': '#87ff5f', + '120': '#87ff87', '121': '#87ffaf', '122': '#87ffd7', '123': '#87ffff', + '124': '#af0000', '125': '#af005f', '126': '#af0087', '127': '#af00af', + '128': '#af00d7', '129': '#af00ff', '130': '#af5f00', '131': '#af5f5f', + '132': '#af5f87', '133': '#af5faf', '134': '#af5fd7', '135': '#af5fff', + '136': '#af8700', '137': '#af875f', '138': '#af8787', '139': '#af87af', + '140': '#af87d7', '141': '#af87ff', '142': '#afaf00', '143': '#afaf5f', + '144': '#afaf87', '145': '#afafaf', '146': '#afafd7', '147': '#afafff', + '148': '#afd700', '149': '#afd75f', '150': '#afd787', '151': '#afd7af', + '152': '#afd7d7', '153': '#afd7ff', '154': '#afff00', '155': '#afff5f', + '156': '#afff87', '157': '#afffaf', '158': '#afffd7', '159': '#afffff', + '160': '#d70000', '161': '#d7005f', '162': '#d70087', '163': '#d700af', + '164': '#d700d7', '165': '#d700ff', '166': '#d75f00', '167': '#d75f5f', + '168': '#d75f87', '169': '#d75faf', '170': '#d75fd7', '171': '#d75fff', + '172': '#d78700', '173': '#d7875f', '174': '#d78787', '175': '#d787af', + '176': '#d787d7', '177': '#d787ff', '178': '#d7af00', '179': '#d7af5f', + '180': '#d7af87', '181': '#d7afaf', '182': '#d7afd7', '183': '#d7afff', + '184': '#d7d700', '185': '#d7d75f', '186': '#d7d787', '187': '#d7d7af', + '188': '#d7d7d7', '189': '#d7d7ff', '190': '#d7ff00', '191': '#d7ff5f', + '192': '#d7ff87', '193': '#d7ffaf', '194': '#d7ffd7', '195': '#d7ffff', + '196': '#ff0000', '197': '#ff005f', '198': '#ff0087', '199': '#ff00af', + '200': '#ff00d7', '201': '#ff00ff', '202': '#ff5f00', '203': '#ff5f5f', + '204': '#ff5f87', '205': '#ff5faf', '206': '#ff5fd7', '207': '#ff5fff', + '208': '#ff8700', '209': '#ff875f', '210': '#ff8787', '211': '#ff87af', + '212': '#ff87d7', '213': '#ff87ff', '214': '#ffaf00', '215': '#ffaf5f', + '216': '#ffaf87', '217': '#ffafaf', '218': '#ffafd7', '219': '#ffafff', + '220': '#ffd700', '221': '#ffd75f', '222': '#ffd787', '223': '#ffd7af', + '224': '#ffd7d7', '225': '#ffd7ff', '226': '#ffff00', '227': '#ffff5f', + '228': '#ffff87', '229': '#ffffaf', '230': '#ffffd7', '231': '#ffffff', + '232': '#080808', '233': '#121212', '234': '#1c1c1c', '235': '#262626', + '236': '#303030', '237': '#3a3a3a', '238': '#444444', '239': '#4e4e4e', + '240': '#585858', '241': '#626262', '242': '#6c6c6c', '243': '#767676', + '244': '#808080', '245': '#8a8a8a', '246': '#949494', '247': '#9e9e9e', + '248': '#a8a8a8', '249': '#b2b2b2', '250': '#bcbcbc', '251': '#c6c6c6', + '252': '#d0d0d0', '253': '#dadada', '254': '#e4e4e4', '255': '#eeeeee' + } + + + def setOptions(self, winid, bufhidden): + super(GitBlameView, self).setOptions(winid, bufhidden) + lfCmd("call win_execute({}, 'setlocal nowrap')".format(winid)) + lfCmd("call win_execute({}, 'setlocal winfixwidth')".format(winid)) + lfCmd("call win_execute({}, 'setlocal fdc=0')".format(winid)) + lfCmd("call win_execute({}, 'setlocal number norelativenumber')".format(winid)) + lfCmd("call win_execute({}, 'setlocal nofoldenable')".format(winid)) + lfCmd("call win_execute({}, 'setlocal signcolumn=no')".format(winid)) + lfCmd("call win_execute({}, 'setlocal cursorline')".format(winid)) + + def saveAlternativeWinOptions(self, winid): + self._alternative_winid = winid + self._alternative_win_options = { + "foldenable": lfEval("getwinvar({}, '&foldenable')".format(winid)), + "scrollbind": lfEval("getwinvar({}, '&scrollbind')".format(winid)), + } + + def enableColor(self, winid): + if (lfEval("hlexists('Lf_hl_blame_255')") == '0' + or lfEval("exists('*hlget')") == '0' + or lfEval("hlget('Lf_hl_blame_255')[0]").get("cleared", False)): + for cterm_color, gui_color in self._color_table.items(): + lfCmd("hi def Lf_hl_blame_{} guifg={} guibg=NONE gui=NONE ctermfg={} ctermbg=NONE cterm=NONE" + .format(cterm_color, gui_color, cterm_color)) + + for i in range(256): + lfCmd(r"""call win_execute({}, 'let matchid = matchadd(''Lf_hl_blame_{}'', ''^\^\?{}\x\+'', -100)')""" + .format(winid, i, format(i, '02x'))) + id = int(lfEval("matchid")) + self._match_ids.append(id) + + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Number'', + ''\(^\^\?\x\+.*(.\{-}\s\)\@<=\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d [+-]\d\d\d\d'', -100)')""" % winid) + id = int(lfEval("matchid")) + self._match_ids.append(id) + + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''WarningMsg'', ''Not Committed Yet'', -100)')""" % winid) + id = int(lfEval("matchid")) + self._match_ids.append(id) + + def suicide(self): + super(GitBlameView, self).suicide() + if self._alternative_winid is not None: + for k, v in self._alternative_win_options.items(): + lfCmd("call setwinvar({}, '&{}', {})".format(self._alternative_winid, k, v)) + + for i in self._match_ids: + lfCmd("silent! call matchdelete(%d)" % i) + self._match_ids = [] + + class LfOrderedDict(OrderedDict): def last_key(self): return next(reversed(self.keys())) @@ -669,9 +823,13 @@ def bisect_right(a, x, lo=0, hi=None, *, key=None): class TreeView(GitCommandView): - def __init__(self, owner, cmd, project_root): + def __init__(self, owner, cmd, project_root, target_path, callback): super(TreeView, self).__init__(owner, cmd) self._project_root = project_root + self._target_path = target_path + # the argument is source, source is a tuple like + # (b90f76fc1, bad07e644, R099, src/version.c, src/version2.c) + self._callback = callback # key is the parent hash, value is a TreeNode self._trees = LfOrderedDict() # key is the parent hash, value is a list of MetaInfo @@ -683,8 +841,6 @@ def __init__(self, owner, cmd, project_root): self._short_stat = {} self._num_stat = {} self._first_source = {} - self._left_most_file = set() - self._source_queue = Queue.Queue() self._show_icon = lfEval("get(g:, 'Lf_ShowDevIcons', 1)") == "1" folder_icons = lfEval("g:Lf_GitFolderIcons") self._closed_folder_icon = folder_icons["closed"] @@ -766,17 +922,6 @@ def defineMaps(self, winid): lfCmd("call win_execute({}, 'call leaderf#Git#TreeViewMaps({})')" .format(winid, id(self))) - def getFirstSource(self): - if self._cur_parent in self._first_source: - return self._first_source[self._cur_parent] - else: - parent = "" - while(parent != self._cur_parent): - parent, source = self._source_queue.get() - self._first_source[parent] = source - - return source - def getCurrentParent(self): return self._cur_parent @@ -860,12 +1005,6 @@ def getLeftMostFile(self, tree_node): return None - def enqueueLeftMostFile(self, parent): - self._left_most_file.add(parent) - - tree_node = self._trees[parent] - self._source_queue.put((parent, self.getLeftMostFile(tree_node))) - def buildTree(self, line): """ command output is something as follows: @@ -901,6 +1040,7 @@ def buildTree(self, line): self._file_list[parent] = [] parent, tree_node = self._trees.last_key_value() + root_node = tree_node mode, source = TreeView.generateSource(line) file_path = lfGetFilePath(source) icon = webDevIconsGetFileTypeSymbol(file_path) if self._show_icon else "" @@ -934,9 +1074,6 @@ def buildTree(self, line): "{}/{}/".format(level0_dir_name, dir_name) ) - - if parent not in self._left_most_file: - self.enqueueLeftMostFile(parent) elif i == 0: self.appendRemainingFiles(parent, tree_node) @@ -948,6 +1085,13 @@ def buildTree(self, line): tree_node = tree_node.dirs[d] + if self._target_path == file_path: + node = root_node + node.status = FolderStatus.OPEN + for d in directories: + node = node.dirs[d] + node.status = FolderStatus.OPEN + if mode != "160000": tree_node.files[file] = source elif line.startswith(" "): @@ -955,8 +1099,6 @@ def buildTree(self, line): self._short_stat[parent] = line self.appendRemainingFiles(parent, tree_node) self.appendFiles(parent, 0, tree_node) - if parent not in self._left_most_file: - self.enqueueLeftMostFile(parent) elif line == "": pass else: @@ -1007,7 +1149,7 @@ def metaInfoGenerator(self, meta_info, recursive, level): def expandOrCollapseFolder(self, recursive=False): with self._lock: - line_num = vim.current.window.cursor[0] + line_num = int(lfEval("getcurpos({})[1]".format(self.getWindowId()))) index = line_num - len(self._head) - 1 # the root if index == -1 and recursive == True: @@ -1229,10 +1371,10 @@ def setOptions(self, winid, bufhidden): lfCmd(r"""call win_execute({}, 'let &l:stl="%#Lf_hl_gitStlChangedNum# 0 %#Lf_hl_gitStlFileChanged#file changed, %#Lf_hl_gitStlAdd#0 (+), %#Lf_hl_gitStlDel#0 (-)"')""" .format(winid)) if lfEval("has('nvim')") == '1': - lfCmd("call nvim_win_set_option(%d, 'cursorline', v:true)" % winid) + lfCmd("call nvim_win_set_option(%d, 'cursorline', v:false)" % winid) lfCmd("call nvim_win_set_option(%d, 'number', v:false)" % winid) else: - lfCmd("call win_execute({}, 'setlocal cursorline')".format(winid)) + lfCmd("call win_execute({}, 'setlocal nocursorline')".format(winid)) lfCmd("call win_execute({}, 'setlocal nonumber')".format(winid)) lfCmd("call win_execute({}, 'noautocmd setlocal sw=2 tabstop=4')".format(winid)) lfCmd("call win_execute({}, 'setlocal signcolumn=no')".format(winid)) @@ -1281,11 +1423,24 @@ def writeBuffer(self): lfCmd("call win_execute({}, 'norm! {}G')".format(self.getWindowId(), init_line)) cursor_line = int(lfEval("getcurpos({})[1]".format(self.getWindowId()))) + source = None for info in structure[self._offset_in_content:cur_len]: self._buffer.append(self.buildLine(info)) if cursor_line == init_line and not info.is_dir: - cursor_line = len(self._buffer) - lfCmd("call win_execute({}, 'norm! {}G')".format(self.getWindowId(), cursor_line)) + if self._target_path is None or info.path == self._target_path: + cursor_line = len(self._buffer) + source = info.info + + if source is not None: + self._callback(source) + if lfEval("has('nvim')") == '1': + lfCmd("call nvim_win_set_option({}, 'cursorline', v:true)".format(self.getWindowId())) + else: + lfCmd("call win_execute({}, 'setlocal cursorline')".format(self.getWindowId())) + lfCmd("call win_execute({}, 'norm! {}G0zz')".format(self.getWindowId(), cursor_line)) + + if self._target_path is None: + lfCmd("call win_gotoid({})".format(self.getWindowId())) self._offset_in_content = cur_len lfCmd("redraw") @@ -1314,11 +1469,6 @@ def _readContent(self, encoding): else: self._read_finished = 1 self._owner.readFinished(self) - - # if content is empty, getFirstSource() will hang - if self._cur_parent is None: - self._first_source[self._cur_parent] = None - self._source_queue.put((None, None)) except Exception: traceback.print_exc() traceback.print_stack() @@ -1326,7 +1476,6 @@ def _readContent(self, encoding): def cleanup(self): super(TreeView, self).cleanup() - self._match_ids = [] @@ -1550,10 +1699,12 @@ def create(self, arguments_dict, source, **kwargs): (source[1], source[2], file_path)) buffer_names = (GitCatFileCommand.buildBufferName(self._commit_id, sources[0]), GitCatFileCommand.buildBufferName(self._commit_id, sources[1])) + target_winid = None if buffer_names[0] in self._views and buffer_names[1] in self._views: win_ids = (self._views[buffer_names[0]].getWindowId(), self._views[buffer_names[1]].getWindowId()) - lfCmd("call win_gotoid({})".format(win_ids[0])) + lfCmd("call win_gotoid({})".format(win_ids[1])) + target_winid = win_ids[1] elif buffer_names[0] in self._views: lfCmd("call win_gotoid({})".format(self._views[buffer_names[0]].getWindowId())) cmd = GitCatFileCommand(arguments_dict, sources[1], self._commit_id) @@ -1562,7 +1713,7 @@ def create(self, arguments_dict, source, **kwargs): self.bufShown(buffer_names[1], int(lfEval("win_getid()"))) else: GitCommandView(self, cmd).create(int(lfEval("win_getid()")), bufhidden='hide') - lfCmd("call win_gotoid({})".format(self._views[buffer_names[0]].getWindowId())) + target_winid = int(lfEval("win_getid()")) elif buffer_names[1] in self._views: lfCmd("call win_gotoid({})".format(self._views[buffer_names[1]].getWindowId())) cmd = GitCatFileCommand(arguments_dict, sources[0], self._commit_id) @@ -1571,6 +1722,8 @@ def create(self, arguments_dict, source, **kwargs): self.bufShown(buffer_names[0], int(lfEval("win_getid()"))) else: GitCommandView(self, cmd).create(int(lfEval("win_getid()")), bufhidden='hide') + lfCmd("call win_gotoid({})".format(self._views[buffer_names[1]].getWindowId())) + target_winid = int(lfEval("win_getid()")) else: if kwargs.get("mode", '') == 't': lfCmd("noautocmd tabnew | vsp") @@ -1593,6 +1746,7 @@ def create(self, arguments_dict, source, **kwargs): win_ids = [int(lfEval("bufwinid('{}')".format(escQuote(name)))) for name in buffer_names] win_ids = self.getValidWinIDs(win_ids) + target_winid = win_ids[1] cat_file_cmds = [GitCatFileCommand(arguments_dict, s, self._commit_id) for s in sources] outputs = [None, None] if (cat_file_cmds[0].getBufferName() not in self._hidden_views @@ -1621,7 +1775,11 @@ def create(self, arguments_dict, source, **kwargs): else: GitCommandView(self, cmd).create(winid, bufhidden='hide', buf_content=outputs[i]) - lfCmd("call win_gotoid({})".format(win_ids[0])) + lfCmd("call win_gotoid({})".format(win_ids[1])) + + if kwargs.get("line_num", None) is not None: + lfCmd("call win_execute({}, 'norm! {}G0zbzz')".format(target_winid, kwargs["line_num"])) + class NavigationPanel(Panel): @@ -1646,21 +1804,70 @@ def cleanup(self): self.tree_view.cleanup() self.tree_view = None - def create(self, cmd, winid, project_root): - TreeView(self, cmd, project_root).create(winid, bufhidden="hide") + def create(self, cmd, winid, project_root, target_path, callback): + TreeView(self, cmd, project_root, target_path, callback).create(winid, bufhidden="hide") def writeBuffer(self): # called in idle if self.tree_view is not None: self.tree_view.writeBuffer() - def getFirstSource(self): - return self.tree_view.getFirstSource() - def getWindowId(self): return self.tree_view.getWindowId() +class BlamePanel(Panel): + def __init__(self, owner): + self._owner = owner + self._views = {} + + def register(self, view): + self._views[view.getBufferName()] = view + + def deregister(self, view): + name = view.getBufferName() + if name in self._views: + self._views[name].cleanup() + del self._views[name] + + def formatLine(self, line): + """ + 6817817e autoload/leaderf/manager.py 1 (Yggdroot 2014-02-26 00:37:26 +0800 1) #!/usr/bin/env python + """ + return re.sub(r'(^\^?\w+)\s+(.*?)\s+(\d+)\s+(\([^(]*?)\s+\d+\).*', r'\g<1> \g<4>)\t\g<3> \g<2>', line, 1) + + def create(self, cmd, content=None): + buffer_name = cmd.getBufferName() + outputs = ParallelExecutor.run(cmd.getCommand(), format_line=self.formatLine) + line_num_width = max(len(str(len(vim.current.buffer))) + 1, int(lfEval('&numberwidth'))) + if len(outputs[0]) > 0: + if buffer_name in self._views and self._views[buffer_name].valid(): + top_line = lfEval("line('w0')") + cursor_line = lfEval("line('.')") + line_width = outputs[0][0].rfind('\t') + self._views[buffer_name].create(-1, buf_content=outputs[0]) + lfCmd("vertical resize {}".format(line_width + line_num_width)) + lfCmd("norm! {}Gzt{}G0".format(top_line, cursor_line)) + else: + winid = int(lfEval("win_getid()")) + blame_view = GitBlameView(self, cmd) + blame_view.saveAlternativeWinOptions(winid) + lfCmd("setlocal nofoldenable") + top_line = lfEval("line('w0')") + cursor_line = lfEval("line('.')") + line_width = outputs[0][0].rfind('\t') + lfCmd("silent! noa keepa keepj abo {}vsp {}".format(line_width + line_num_width, + buffer_name)) + blame_winid = int(lfEval("win_getid()")) + blame_view.create(blame_winid, buf_content=outputs[0]) + self._owner.defineMaps(blame_winid) + lfCmd("norm! {}Gzt{}G0".format(top_line, cursor_line)) + lfCmd("call win_execute({}, 'setlocal scrollbind')".format(winid)) + lfCmd("setlocal scrollbind") + else: + lfPrintError("No need to blame!") + + class ExplorerPage(object): def __init__(self, project_root, commit_id, owner): self._project_root = project_root @@ -1721,7 +1928,7 @@ def defineMaps(self, winid): lfCmd("call win_execute({}, 'call leaderf#Git#ExplorerMaps({})')" .format(winid, id(self))) - def create(self, arguments_dict, cmd): + def create(self, arguments_dict, cmd, target_path=None, line_num=None): self._arguments = arguments_dict lfCmd("noautocmd tabnew") @@ -1731,14 +1938,13 @@ def create(self, arguments_dict, cmd): win_pos = arguments_dict.get("--navigation-position", ["left"])[0] winid = self._createWindow(win_pos, cmd.getBufferName()) - self._navigation_panel.create(cmd, winid, self._project_root) + callback = partial(self._diff_view_panel.create, + arguments_dict, + winid=diff_view_winid, + line_num=line_num) + self._navigation_panel.create(cmd, winid, self._project_root, target_path, callback) self.defineMaps(self._navigation_panel.getWindowId()) - source = self._navigation_panel.getFirstSource() - if source is not None: - self._diff_view_panel.create(arguments_dict, source, winid=diff_view_winid) - lfCmd("call win_gotoid({})".format(self._navigation_panel.getWindowId())) - def afterBufhidden(self): if self._navigation_panel.isHidden() and self._diff_view_panel.isAllHidden(): lfCmd("call timer_start(1, function('leaderf#Git#Cleanup', [{}]))".format(id(self))) @@ -1768,14 +1974,14 @@ def open(self, recursive, **kwargs): diff_view_winid = int(lfEval("win_getid()")) self._diff_view_panel.create(self._arguments, source, winid=diff_view_winid) else: - self._diff_view_panel.create(self._arguments, source) + self._diff_view_panel.create(self._arguments, source, **kwargs) if kwargs.get("preview", False) == True: lfCmd("call win_gotoid({})".format(self._navigation_panel.getWindowId())) - def locateFile(self, path): + def locateFile(self, path, line_num=None, preview=True): self._navigation_panel.tree_view.locateFile(path) - self.open(False, preview=True) + self.open(False, line_num=line_num, preview=preview) def fuzzySearch(self, recall=False): if self._git_diff_manager is None: @@ -1807,6 +2013,7 @@ def __init__(self): self._preview_panel = PreviewPanel() self._git_diff_manager = None self._git_log_manager = None + self._git_blame_manager = None self._selected_content = None self._project_root = "" @@ -1850,6 +2057,10 @@ def getExplManager(self, subcommand): if self._git_log_manager is None: self._git_log_manager = GitLogExplManager() return self._git_log_manager + elif subcommand == "blame": + if self._git_blame_manager is None: + self._git_blame_manager = GitBlameExplManager() + return self._git_blame_manager else: return super(GitExplManager, self) @@ -2069,9 +2280,9 @@ def vsplitDiff(self): win_ids = [int(lfEval("win_getid()")), 0] lfCmd("keepa keepj abo vsp {}".format(file_name)) win_ids[1] = int(lfEval("win_getid()")) - lfCmd("augroup Lf_Git | augroup END") - lfCmd("autocmd! Lf_Git BufWipeout call leaderf#Git#DiffOff({})".format(win_ids)) - lfCmd("call win_execute({}, 'autocmd! Lf_Git BufHidden,BufWipeout call leaderf#Git#DiffOff({})')" + lfCmd("augroup Lf_Git_Diff | augroup END") + lfCmd("autocmd! Lf_Git_Diff BufWipeout call leaderf#Git#DiffOff({})".format(win_ids)) + lfCmd("call win_execute({}, 'autocmd! Lf_Git_Diff BufHidden,BufWipeout call leaderf#Git#DiffOff({})')" .format(win_ids[0], win_ids)) lfCmd("setlocal nobuflisted") lfCmd("setlocal buftype=nofile") @@ -2128,8 +2339,8 @@ def startExplorer(self, win_pos, *args, **kwargs): self._result_panel.create(self.createGitCommand(self._arguments, None)) self._restoreOrigCwd() elif "--explorer" in self._arguments: - lfCmd("augroup Lf_Git | augroup END") - lfCmd("autocmd! Lf_Git TabClosed * call leaderf#Git#CleanupExplorerPage({})" + lfCmd("augroup Lf_Git_Diff | augroup END") + lfCmd("autocmd! Lf_Git_Diff TabClosed * call leaderf#Git#CleanupExplorerPage({})" .format(id(self))) uid = str(int(time.time()))[-7:] @@ -2213,8 +2424,8 @@ def cleanupExplorerPage(self): class GitLogExplManager(GitExplManager): def __init__(self): super(GitLogExplManager, self).__init__() - lfCmd("augroup Lf_Git | augroup END") - lfCmd("autocmd! Lf_Git FileType git call leaderf#Git#DefineSyntax()") + lfCmd("augroup Lf_Git_Log | augroup END") + lfCmd("autocmd! Lf_Git_Log FileType git call leaderf#Git#DefineSyntax()") self._diff_view_panel = None # key is source, value is ExplorerPage self._pages = {} @@ -2362,8 +2573,8 @@ def _acceptSelection(self, *args, **kwargs): if source in self._pages: vim.current.tabpage = self._pages[source].tabpage else: - lfCmd("augroup Lf_Git | augroup END") - lfCmd("autocmd! Lf_Git TabClosed * call leaderf#Git#CleanupExplorerPage({})" + lfCmd("augroup Lf_Git_Log | augroup END") + lfCmd("autocmd! Lf_Git_Log TabClosed * call leaderf#Git#CleanupExplorerPage({})" .format(id(self))) self._pages[source] = ExplorerPage(self._project_root, source, self) @@ -2393,6 +2604,70 @@ def cleanupExplorerPage(self): return +class GitBlameExplManager(GitExplManager): + def __init__(self): + super(GitBlameExplManager, self).__init__() + self._blame_panel = BlamePanel(self) + # key is source, value is ExplorerPage + self._pages = {} + + def createGitCommand(self, arguments_dict, source): + return GitBlameCommand(arguments_dict, source) + + def getPreviewCommand(self, arguments_dict, source): + return GitLogDiffCommand(arguments_dict, source) + + def defineMaps(self, winid): + lfCmd("call win_execute({}, 'call leaderf#Git#BlameMaps({})')" + .format(winid, id(self))) + + def open(self): + source = vim.current.line.lstrip('^').split(None, 1)[0] + if source.startswith('0000000'): + lfPrintError("Not Committed Yet!") + return + + line_num, file_name = vim.current.line.rsplit('\t', 1)[1].split(None, 1) + + if source in self._pages: + vim.current.tabpage = self._pages[source].tabpage + self._pages[source].locateFile(file_name, line_num, False) + else: + lfCmd("augroup Lf_Git_Blame | augroup END") + lfCmd("autocmd! Lf_Git_Blame TabClosed * call leaderf#Git#CleanupExplorerPage({})" + .format(id(self))) + + self._pages[source] = ExplorerPage(self._project_root, source, self) + self._pages[source].create(self._arguments, + GitLogExplCommand(self._arguments, source), + target_path=file_name, + line_num=line_num) + + def startExplorer(self, win_pos, *args, **kwargs): + if self.checkWorkingDirectory() == False: + return + + arguments_dict = kwargs.get("arguments", {}) + self.setArguments(arguments_dict) + + if vim.current.buffer.name and not vim.current.buffer.options['bt']: + if not vim.current.buffer.name.startswith(self._project_root): + lfPrintError("fatal: '{}' is outside repository at '{}'" + .format(lfRelpath(vim.current.buffer.name), self._project_root)) + else: + self._blame_panel.create(self.createGitCommand(self._arguments, None)) + else: + lfPrintError("fatal: no such path '{}' in HEAD".format(vim.current.buffer.name)) + + self._restoreOrigCwd() + + def cleanupExplorerPage(self): + for k, v in self._pages.items(): + if v.tabpage not in vim.tabpages: + del self._pages[k] + return + + #***************************************************** # gitExplManager is a singleton #***************************************************** From 7f3f78dc50c2faa6162f334ff8825bc930a0f749 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Fri, 12 Apr 2024 17:30:19 +0800 Subject: [PATCH 170/365] report error on neovim --- autoload/leaderf/python/leaderf/gitExpl.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 846aeb37..38670dab 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -720,8 +720,7 @@ def enableColor(self, winid): id = int(lfEval("matchid")) self._match_ids.append(id) - lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Number'', - ''\(^\^\?\x\+.*(.\{-}\s\)\@<=\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d [+-]\d\d\d\d'', -100)')""" % winid) + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Number'', ''\(^\^\?\x\+.*(.\{-}\s\)\@<=\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d [+-]\d\d\d\d'', -100)')""" % winid) id = int(lfEval("matchid")) self._match_ids.append(id) From a8afa6925f796156716b09c3cd30cda93098cc40 Mon Sep 17 00:00:00 2001 From: zoumi Date: Sun, 14 Apr 2024 13:18:53 +0800 Subject: [PATCH 171/365] check list length (#1062) check list length, before index it --- autoload/lfMru.vim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autoload/lfMru.vim b/autoload/lfMru.vim index a843c485..98888087 100644 --- a/autoload/lfMru.vim +++ b/autoload/lfMru.vim @@ -37,7 +37,7 @@ function! lfMru#record(name) let i = 0 for item in file_list let t = split(item, ' ') - if t[2] ==# a:name + if (len(t) > 2) && (t[2] ==# a:name) let found = 1 let t[1] += 1 let file_list[i] = printf("%s %s %s", localtime(), t[1], t[2]) From 3a2131249ee0d408d9cbcf98bcc4c4473602d8d8 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Sun, 14 Apr 2024 23:41:44 +0800 Subject: [PATCH 172/365] h: blame the parent commit, l: go to the previous blame status --- autoload/leaderf/Git.vim | 14 +- autoload/leaderf/python/leaderf/gitExpl.py | 194 +++++++++++++++++++-- 2 files changed, 192 insertions(+), 16 deletions(-) diff --git a/autoload/leaderf/Git.vim b/autoload/leaderf/Git.vim index c8a0c63f..9369e910 100644 --- a/autoload/leaderf/Git.vim +++ b/autoload/leaderf/Git.vim @@ -119,7 +119,14 @@ let s:help = { \ ": go to the previous sibling of the current folder", \ "(: go to the start of the current indent level", \ "): go to the end of the current indent level", - \ ] + \ ], + \ "blame": [ + \ "o: show the details of current commit in an explorer page", + \ ": show the details of current commit in an explorer page", + \ "<2-LeftMouse>: show the details of current commit in an explorer page", + \ "h: blame the parent commit", + \ "l: go to the previous blame status", + \ ], \} function s:HelpFilter(winid, key) @@ -238,7 +245,10 @@ function! leaderf#Git#BlameMaps(id) exec printf('nnoremap o :exec g:Lf_py "%s.open()"', explorer_page) exec printf('nnoremap <2-LeftMouse> :exec g:Lf_py "%s.open()"', explorer_page) exec printf('nnoremap :exec g:Lf_py "%s.open()"', explorer_page) - nnoremap q :q + exec printf('nnoremap h :exec g:Lf_py "%s.blamePrevious()"', explorer_page) + exec printf('nnoremap l :exec g:Lf_py "%s.blameNext()"', explorer_page) + nnoremap :call leaderf#Git#ShowHelp("blame") + nnoremap q :bwipe endfunction function! leaderf#Git#TimerCallback(manager_id, id) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 38670dab..704dce96 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -8,11 +8,6 @@ import os.path import json import bisect -import itertools -if sys.version_info >= (3, 0): - import queue as Queue -else: - import Queue from functools import partial from enum import Enum from collections import OrderedDict @@ -21,7 +16,6 @@ from .manager import * from .devicons import ( webDevIconsGetFileTypeSymbol, - removeDevIcons, matchaddDevIconsDefault, matchaddDevIconsExact, matchaddDevIconsExtension, @@ -619,6 +613,7 @@ class GitBlameView(GitCommandView): def __init__(self, owner, cmd): super(GitBlameView, self).__init__(owner, cmd) self._alternative_winid = None + self._alternative_buffer_num = None self._alternative_win_options = {} self._match_ids = [] self._color_table = { @@ -687,7 +682,9 @@ def __init__(self, owner, cmd): '248': '#a8a8a8', '249': '#b2b2b2', '250': '#bcbcbc', '251': '#c6c6c6', '252': '#d0d0d0', '253': '#dadada', '254': '#e4e4e4', '255': '#eeeeee' } - + self.blame_stack = [] + # key is commit id, value is (blame_buffer, alternative_buffer_num) + self.blame_dict = {} def setOptions(self, winid, bufhidden): super(GitBlameView, self).setOptions(winid, bufhidden) @@ -699,13 +696,18 @@ def setOptions(self, winid, bufhidden): lfCmd("call win_execute({}, 'setlocal signcolumn=no')".format(winid)) lfCmd("call win_execute({}, 'setlocal cursorline')".format(winid)) - def saveAlternativeWinOptions(self, winid): + def saveAlternativeWinOptions(self, winid, buffer_num): self._alternative_winid = winid + self._alternative_buffer_num = buffer_num + self._alternative_win_options = { "foldenable": lfEval("getwinvar({}, '&foldenable')".format(winid)), "scrollbind": lfEval("getwinvar({}, '&scrollbind')".format(winid)), } + def getAlternativeWinid(self): + return self._alternative_winid + def enableColor(self, winid): if (lfEval("hlexists('Lf_hl_blame_255')") == '0' or lfEval("exists('*hlget')") == '0' @@ -730,6 +732,10 @@ def enableColor(self, winid): def suicide(self): super(GitBlameView, self).suicide() + + lfCmd("call win_execute({}, 'buffer {}')".format(self._alternative_winid, + self._alternative_buffer_num)) + if self._alternative_winid is not None: for k, v in self._alternative_win_options.items(): lfCmd("call setwinvar({}, '&{}', {})".format(self._alternative_winid, k, v)) @@ -738,6 +744,14 @@ def suicide(self): lfCmd("silent! call matchdelete(%d)" % i) self._match_ids = [] + for item in self.blame_dict.values(): + buffer_num = int(item[1]) + # buftype is not empty + if vim.buffers[buffer_num].options["buftype"]: + lfCmd("bwipe {}".format(buffer_num)) + self.blame_dict = {} + self.blame_stack = [] + class LfOrderedDict(OrderedDict): def last_key(self): @@ -1354,7 +1368,6 @@ def buildLine(self, meta_info): orig_name = "" if meta_info.info[2][0] in ("R", "C"): - head, tail = os.path.split(meta_info.info[3]) orig_name = "{} => ".format(lfRelpath(meta_info.info[3], os.path.dirname(meta_info.info[4]))) @@ -1829,7 +1842,17 @@ def deregister(self, view): self._views[name].cleanup() del self._views[name] - def formatLine(self, line): + def getAlternativeWinid(self, buffer_name): + return self._views[buffer_name].getAlternativeWinid() + + def getBlameStack(self, buffer_name): + return self._views[buffer_name].blame_stack + + def getBlameDict(self, buffer_name): + return self._views[buffer_name].blame_dict + + @staticmethod + def formatLine(line): """ 6817817e autoload/leaderf/manager.py 1 (Yggdroot 2014-02-26 00:37:26 +0800 1) #!/usr/bin/env python """ @@ -1837,7 +1860,7 @@ def formatLine(self, line): def create(self, cmd, content=None): buffer_name = cmd.getBufferName() - outputs = ParallelExecutor.run(cmd.getCommand(), format_line=self.formatLine) + outputs = ParallelExecutor.run(cmd.getCommand(), format_line=BlamePanel.formatLine) line_num_width = max(len(str(len(vim.current.buffer))) + 1, int(lfEval('&numberwidth'))) if len(outputs[0]) > 0: if buffer_name in self._views and self._views[buffer_name].valid(): @@ -1846,11 +1869,11 @@ def create(self, cmd, content=None): line_width = outputs[0][0].rfind('\t') self._views[buffer_name].create(-1, buf_content=outputs[0]) lfCmd("vertical resize {}".format(line_width + line_num_width)) - lfCmd("norm! {}Gzt{}G0".format(top_line, cursor_line)) + lfCmd("noautocmd norm! {}Gzt{}G0".format(top_line, cursor_line)) else: winid = int(lfEval("win_getid()")) blame_view = GitBlameView(self, cmd) - blame_view.saveAlternativeWinOptions(winid) + blame_view.saveAlternativeWinOptions(winid, vim.current.buffer.number) lfCmd("setlocal nofoldenable") top_line = lfEval("line('w0')") cursor_line = lfEval("line('.')") @@ -1860,7 +1883,7 @@ def create(self, cmd, content=None): blame_winid = int(lfEval("win_getid()")) blame_view.create(blame_winid, buf_content=outputs[0]) self._owner.defineMaps(blame_winid) - lfCmd("norm! {}Gzt{}G0".format(top_line, cursor_line)) + lfCmd("noautocmd norm! {}Gzt{}G0".format(top_line, cursor_line)) lfCmd("call win_execute({}, 'setlocal scrollbind')".format(winid)) lfCmd("setlocal scrollbind") else: @@ -2620,7 +2643,150 @@ def defineMaps(self, winid): lfCmd("call win_execute({}, 'call leaderf#Git#BlameMaps({})')" .format(winid, id(self))) + def setOptions(self, winid): + lfCmd("call win_execute({}, 'setlocal nobuflisted')".format(winid)) + lfCmd("call win_execute({}, 'setlocal buftype=nofile')".format(winid)) + lfCmd("call win_execute({}, 'setlocal bufhidden=hide')".format(winid)) + lfCmd("call win_execute({}, 'setlocal undolevels=-1')".format(winid)) + lfCmd("call win_execute({}, 'setlocal noswapfile')".format(winid)) + lfCmd("call win_execute({}, 'setlocal nospell')".format(winid)) + + def blamePrevious(self): + if vim.current.line == "": + return + + if vim.current.line.startswith('^'): + lfPrintError("First commit!") + return + + commit_id = vim.current.line.lstrip('^').split(None, 1)[0] + if commit_id.startswith('0000000'): + lfPrintError("Not Committed Yet!") + return + + line_num, file_name = vim.current.line.rsplit('\t', 1)[1].split(None, 1) + alternative_winid = self._blame_panel.getAlternativeWinid(vim.current.buffer.name) + blame_winid = lfEval("win_getid()") + + if commit_id not in self._blame_panel.getBlameDict(vim.current.buffer.name): + cmd = ["git diff {}^ {} --name-status".format(commit_id, commit_id), + "git rev-parse {}^".format(commit_id) + ] + outputs = ParallelExecutor.run(*cmd) + orig_name = None + first_commit = False + for line in outputs[0]: + if line.endswith("\t" + file_name): + if line.startswith("A"): + first_commit = True + + if line.startswith("R"): + orig_name = line.split()[1] + else: + orig_name = file_name + break + + if first_commit == True: + lfPrintError("First commit of current file!") + return + + parent_commit_id = outputs[1][0] + + cmd = ["git blame -f -n {} -- {}".format(parent_commit_id, orig_name), + "git show {}:{}".format(parent_commit_id, orig_name) + ] + outputs = ParallelExecutor.run(*cmd) + + blame_win_width = vim.current.window.width + self._blame_panel.getBlameStack(vim.current.buffer.name).append( + ( + vim.current.buffer[:], + lfEval("winbufnr({})".format(alternative_winid)), + blame_win_width, + vim.current.window.cursor[0], + int(lfEval("line('w0')")) + ) + ) + + lfCmd("noautocmd call win_gotoid({})".format(alternative_winid)) + lfCmd("noautocmd enew") + self.setOptions(alternative_winid) + + vim.current.buffer[:] = outputs[1] + vim.current.buffer.name = "LeaderF://{}:{}".format(parent_commit_id[:7], orig_name) + lfCmd("doautocmd filetypedetect BufNewFile {}".format(orig_name)) + lfCmd("setlocal nomodifiable") + lfCmd("noautocmd norm! {}Gzz".format(line_num)) + alternative_buffer_num = vim.current.buffer.number + top_line = lfEval("line('w0')") + + lfCmd("noautocmd call win_gotoid({})".format(blame_winid)) + outputs[0] = [BlamePanel.formatLine(line) for line in outputs[0]] + lfCmd("setlocal modifiable") + vim.current.buffer[:] = outputs[0] + lfCmd("setlocal nomodifiable") + if len(outputs[0]) > 0: + line_width = outputs[0][0].rfind('\t') + line_num_width = max(len(str(len(vim.current.buffer))) + 1, int(lfEval('&numberwidth'))) + lfCmd("vertical resize {}".format(line_width + line_num_width)) + lfCmd("noautocmd norm! {}Gzt{}G0".format(top_line, line_num)) + lfCmd("call win_execute({}, 'setlocal scrollbind')".format(alternative_winid)) + + blame_win_width = vim.current.window.width + self._blame_panel.getBlameDict(vim.current.buffer.name)[commit_id] = ( + outputs[0], + alternative_buffer_num, + blame_win_width + ) + else: + self._blame_panel.getBlameStack(vim.current.buffer.name).append( + ( + vim.current.buffer[:], + lfEval("winbufnr({})".format(alternative_winid)), + vim.current.window.width, + vim.current.window.cursor[0], + int(lfEval("line('w0')")) + ) + ) + (blame_buffer, + alternative_buffer_num, + blame_win_width + ) = self._blame_panel.getBlameDict(vim.current.buffer.name)[commit_id] + lfCmd("noautocmd call win_gotoid({})".format(alternative_winid)) + lfCmd("buffer {}".format(alternative_buffer_num)) + lfCmd("noautocmd norm! {}Gzz".format(line_num)) + top_line = lfEval("line('w0')") + + lfCmd("noautocmd call win_gotoid({})".format(blame_winid)) + lfCmd("setlocal modifiable") + vim.current.buffer[:] = blame_buffer + lfCmd("setlocal nomodifiable") + lfCmd("vertical resize {}".format(blame_win_width)) + lfCmd("noautocmd norm! {}Gzt{}G0".format(top_line, line_num)) + + def blameNext(self): + blame_stack = self._blame_panel.getBlameStack(vim.current.buffer.name) + if len(blame_stack) == 0: + return + + blame_buffer, alternative_buffer_num, blame_win_width, cursor_line, top_line = blame_stack.pop() + blame_winid = lfEval("win_getid()") + alternative_winid = self._blame_panel.getAlternativeWinid(vim.current.buffer.name) + + lfCmd("noautocmd call win_gotoid({})".format(alternative_winid)) + lfCmd("buffer {}".format(alternative_buffer_num)) + + lfCmd("noautocmd call win_gotoid({})".format(blame_winid)) + lfCmd("setlocal modifiable") + vim.current.buffer[:] = blame_buffer + lfCmd("setlocal nomodifiable") + lfCmd("vertical resize {}".format(blame_win_width)) + lfCmd("noautocmd norm! {}Gzt{}G0".format(top_line, cursor_line)) + def open(self): + if vim.current.line == "": + return + source = vim.current.line.lstrip('^').split(None, 1)[0] if source.startswith('0000000'): lfPrintError("Not Committed Yet!") From b45fe98873c46d7a7d33617ecdef41b46eb535d1 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Mon, 15 Apr 2024 17:21:50 +0800 Subject: [PATCH 173/365] show cursorline in diff view window --- autoload/leaderf/python/leaderf/gitExpl.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 704dce96..da853a01 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -1726,6 +1726,8 @@ def create(self, arguments_dict, source, **kwargs): else: GitCommandView(self, cmd).create(int(lfEval("win_getid()")), bufhidden='hide') target_winid = int(lfEval("win_getid()")) + lfCmd("call win_execute({}, 'setlocal cursorlineopt=number')".format(target_winid)) + lfCmd("call win_execute({}, 'setlocal cursorline')".format(target_winid)) elif buffer_names[1] in self._views: lfCmd("call win_gotoid({})".format(self._views[buffer_names[1]].getWindowId())) cmd = GitCatFileCommand(arguments_dict, sources[0], self._commit_id) @@ -1734,6 +1736,8 @@ def create(self, arguments_dict, source, **kwargs): self.bufShown(buffer_names[0], int(lfEval("win_getid()"))) else: GitCommandView(self, cmd).create(int(lfEval("win_getid()")), bufhidden='hide') + lfCmd("call win_execute({}, 'setlocal cursorlineopt=number')".format(int(lfEval("win_getid()")))) + lfCmd("call win_execute({}, 'setlocal cursorline')".format(int(lfEval("win_getid()")))) lfCmd("call win_gotoid({})".format(self._views[buffer_names[1]].getWindowId())) target_winid = int(lfEval("win_getid()")) else: @@ -1775,6 +1779,8 @@ def create(self, arguments_dict, source, **kwargs): buffer_name = lfEval("bufname(winbufnr({}))".format(winid)) lfCmd("call win_execute({}, 'diffoff | hide edit {}')".format(winid, cmd.getBufferName())) + lfCmd("call win_execute({}, 'setlocal cursorlineopt=number')".format(winid)) + lfCmd("call win_execute({}, 'setlocal cursorline')".format(winid)) # if the buffer also in another tabpage, BufHidden is not triggerd # should run this code From 9cf2358cdd4ec4ade5d9fa4565d55b935735ceda Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Tue, 16 Apr 2024 00:25:51 +0800 Subject: [PATCH 174/365] add support to show commit message --- autoload/leaderf/Git.vim | 73 ++++++++++++++++++++++ autoload/leaderf/python/leaderf/gitExpl.py | 16 +++++ 2 files changed, 89 insertions(+) diff --git a/autoload/leaderf/Git.vim b/autoload/leaderf/Git.vim index 9369e910..a1bb5d64 100644 --- a/autoload/leaderf/Git.vim +++ b/autoload/leaderf/Git.vim @@ -113,6 +113,7 @@ let s:help = { \ "X: collapse all the children of the current folder", \ "f: fuzzy search files", \ "F: resume the previous fuzzy searching", + \ "m: show the commit message", \ "-: go to the parent folder", \ "+: go to the next sibling of the parent folder", \ ": go to the next sibling of the current folder", @@ -126,6 +127,7 @@ let s:help = { \ "<2-LeftMouse>: show the details of current commit in an explorer page", \ "h: blame the parent commit", \ "l: go to the previous blame status", + \ "m: show the commit message", \ ], \} @@ -133,7 +135,10 @@ function s:HelpFilter(winid, key) if a:key == "\" || a:key == "\" call popup_close(a:winid) return 1 + elseif a:key == "\" || a:key == "\" + return 0 endif + return 1 endfunction @@ -205,6 +210,72 @@ function! leaderf#Git#ShowHelp(type) endif endfunction +function s:CommitMessageFilter(winid, key) + if a:key == "\" || a:key == "m" + call popup_close(a:winid) + return 1 + elseif a:key == "\" || a:key == "\" + return 0 + endif + + return 1 +endfunction + +function! leaderf#Git#ShowCommitMessage(message) + if has("nvim") + let borderchars = [ + \ [g:Lf_PopupBorders[4], "Lf_hl_popupBorder"], + \ [g:Lf_PopupBorders[0], "Lf_hl_popupBorder"], + \ [g:Lf_PopupBorders[5], "Lf_hl_popupBorder"], + \ [g:Lf_PopupBorders[1], "Lf_hl_popupBorder"], + \ [g:Lf_PopupBorders[6], "Lf_hl_popupBorder"], + \ [g:Lf_PopupBorders[2], "Lf_hl_popupBorder"], + \ [g:Lf_PopupBorders[7], "Lf_hl_popupBorder"], + \ [g:Lf_PopupBorders[3], "Lf_hl_popupBorder"] + \] + let width = 100 + let height = len(a:message) + let row_col = s:GetRowCol(width, height) + let options = { + \ "title": " Commit Message ", + \ "title_pos": "center", + \ "relative": "editor", + \ "row": row_col["row"], + \ "col": row_col["col"], + \ "width": width, + \ "height": height, + \ "zindex": 20482, + \ "noautocmd": 1, + \ "border": borderchars, + \ "style": "minimal", + \} + let scratch_buffer = nvim_create_buf(v:false, v:true) + call nvim_buf_set_option(scratch_buffer, 'bufhidden', 'wipe') + call nvim_buf_set_lines(scratch_buffer, 0, -1, v:false, a:message) + call nvim_buf_set_option(scratch_buffer, 'modifiable', v:false) + let id = nvim_open_win(scratch_buffer, 1, options) + call nvim_win_set_option(id, 'winhighlight', 'Normal:Lf_hl_popup_window') + call win_execute(id, 'nnoremap c') + call win_execute(id, 'setlocal filetype=git') + else + let options = { + \ "title": " Commit Message ", + \ "zindex": 20482, + \ "scrollbar": 1, + \ "padding": [0, 0, 0, 0], + \ "border": [1, 1, 1, 1], + \ "borderchars": g:Lf_PopupBorders, + \ "borderhighlight": ["Lf_hl_popupBorder"], + \ "filter": "s:CommitMessageFilter", + \ "mapping": 0, + \} + + let id = popup_create(a:message, options) + call win_execute(id, 'setlocal wincolor=Lf_hl_popup_window') + call win_execute(id, 'setlocal filetype=git') + endif +endfunction + function! leaderf#Git#TreeViewMaps(id) exec g:Lf_py "import ctypes" let tree_view = printf("ctypes.cast(%d, ctypes.py_object).value", a:id) @@ -236,6 +307,7 @@ function! leaderf#Git#ExplorerMaps(id) exec printf('nnoremap x :call leaderf#Git#CollapseParent("%s")', explorer_page) exec printf('nnoremap f :exec g:Lf_py "%s.fuzzySearch()"', explorer_page) exec printf('nnoremap F :exec g:Lf_py "%s.fuzzySearch(True)"', explorer_page) + exec printf('nnoremap m :exec g:Lf_py "%s.showCommitMessage()"', explorer_page) nnoremap q :q endfunction @@ -247,6 +319,7 @@ function! leaderf#Git#BlameMaps(id) exec printf('nnoremap :exec g:Lf_py "%s.open()"', explorer_page) exec printf('nnoremap h :exec g:Lf_py "%s.blamePrevious()"', explorer_page) exec printf('nnoremap l :exec g:Lf_py "%s.blameNext()"', explorer_page) + exec printf('nnoremap m :exec g:Lf_py "%s.showCommitMessage()"', explorer_page) nnoremap :call leaderf#Git#ShowHelp("blame") nnoremap q :bwipe endfunction diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index da853a01..a73a2050 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -2029,6 +2029,10 @@ def fuzzySearch(self, recall=False): self._git_diff_manager.startExplorer("popup", **kwargs) + def showCommitMessage(self): + cmd = "git show {} -s --decorate --pretty=fuller".format(self._commit_id) + lfCmd("""call leaderf#Git#ShowCommitMessage(systemlist('{}'))""".format(cmd)) + #***************************************************** # GitExplManager @@ -2789,6 +2793,18 @@ def blameNext(self): lfCmd("vertical resize {}".format(blame_win_width)) lfCmd("noautocmd norm! {}Gzt{}G0".format(top_line, cursor_line)) + def showCommitMessage(self): + if vim.current.line == "": + return + + commit_id = vim.current.line.lstrip('^').split(None, 1)[0] + if commit_id.startswith('0000000'): + lfPrintError("Not Committed Yet!") + return + + cmd = "git show {} -s --decorate --pretty=fuller".format(commit_id) + lfCmd("""call leaderf#Git#ShowCommitMessage(systemlist('{}'))""".format(cmd)) + def open(self): if vim.current.line == "": return From 3f8df13641e296cb80e37512b7f339796346e2dc Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Tue, 16 Apr 2024 15:54:12 +0800 Subject: [PATCH 175/365] close commit message window when moving cursor by using j and k --- autoload/leaderf/Git.vim | 44 +++++++++++++++++++--- autoload/leaderf/python/leaderf/gitExpl.py | 5 ++- 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/autoload/leaderf/Git.vim b/autoload/leaderf/Git.vim index a1bb5d64..2351a1a0 100644 --- a/autoload/leaderf/Git.vim +++ b/autoload/leaderf/Git.vim @@ -210,10 +210,33 @@ function! leaderf#Git#ShowHelp(type) endif endfunction + +function! leaderf#Git#CloseCommitMessageWin() + if exists("b:blame_cursorline") && exists("*getmousepos") + let pos = getmousepos() + if pos.winid == b:blame_winid && b:blame_cursorline != pos["line"] + if exists("b:commit_msg_winid") && winbufnr(b:commit_msg_winid) != -1 + call nvim_win_close(b:commit_msg_winid, 1) + endif + endif + endif +endfunction + function s:CommitMessageFilter(winid, key) - if a:key == "\" || a:key == "m" + if a:key == "\" call popup_close(a:winid) return 1 + elseif a:key == "j" || a:key == "k" + call popup_close(a:winid) + return 0 + elseif a:key == "\" + if exists("b:blame_cursorline") && exists("*getmousepos") + let pos = getmousepos() + if pos.winid == b:blame_winid && b:blame_cursorline != pos["line"] + call popup_close(a:winid) + endif + endif + return 0 elseif a:key == "\" || a:key == "\" return 0 endif @@ -222,6 +245,8 @@ function s:CommitMessageFilter(winid, key) endfunction function! leaderf#Git#ShowCommitMessage(message) + let b:blame_cursorline = line('.') + let b:blame_winid = win_getid() if has("nvim") let borderchars = [ \ [g:Lf_PopupBorders[4], "Lf_hl_popupBorder"], @@ -253,10 +278,13 @@ function! leaderf#Git#ShowCommitMessage(message) call nvim_buf_set_option(scratch_buffer, 'bufhidden', 'wipe') call nvim_buf_set_lines(scratch_buffer, 0, -1, v:false, a:message) call nvim_buf_set_option(scratch_buffer, 'modifiable', v:false) - let id = nvim_open_win(scratch_buffer, 1, options) - call nvim_win_set_option(id, 'winhighlight', 'Normal:Lf_hl_popup_window') - call win_execute(id, 'nnoremap c') - call win_execute(id, 'setlocal filetype=git') + if exists("b:commit_msg_winid") && winbufnr(b:commit_msg_winid) != -1 + call nvim_win_close(b:commit_msg_winid, 1) + endif + let b:commit_msg_winid = nvim_open_win(scratch_buffer, 0, options) + call nvim_win_set_option(b:commit_msg_winid, 'winhighlight', 'Normal:Lf_hl_popup_window') + call win_execute(b:commit_msg_winid, 'nnoremap c') + call win_execute(b:commit_msg_winid, 'setlocal filetype=git') else let options = { \ "title": " Commit Message ", @@ -320,6 +348,12 @@ function! leaderf#Git#BlameMaps(id) exec printf('nnoremap h :exec g:Lf_py "%s.blamePrevious()"', explorer_page) exec printf('nnoremap l :exec g:Lf_py "%s.blameNext()"', explorer_page) exec printf('nnoremap m :exec g:Lf_py "%s.showCommitMessage()"', explorer_page) + if has("nvim") + nnoremap j :silent! call nvim_win_close(b:commit_msg_winid, 1)j + nnoremap k :silent! call nvim_win_close(b:commit_msg_winid, 1)k + nnoremap :silent! call nvim_win_close(b:commit_msg_winid, 1) + nnoremap :call leaderf#Git#CloseCommitMessageWin() + endif nnoremap :call leaderf#Git#ShowHelp("blame") nnoremap q :bwipe endfunction diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index a73a2050..3afeb49b 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -733,8 +733,9 @@ def enableColor(self, winid): def suicide(self): super(GitBlameView, self).suicide() - lfCmd("call win_execute({}, 'buffer {}')".format(self._alternative_winid, - self._alternative_buffer_num)) + lfCmd("call win_execute({}, 'buffer {} | norm! {}G0')".format(self._alternative_winid, + self._alternative_buffer_num, + vim.current.window.cursor[0])) if self._alternative_winid is not None: for k, v in self._alternative_win_options.items(): From f169fc73d06f5a10cbffdc2322c4c7462ca84b5c Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Tue, 16 Apr 2024 17:47:14 +0800 Subject: [PATCH 176/365] add Leaderf git blame --- autoload/leaderf/Git.vim | 2 ++ 1 file changed, 2 insertions(+) diff --git a/autoload/leaderf/Git.vim b/autoload/leaderf/Git.vim index 2351a1a0..b54c134c 100644 --- a/autoload/leaderf/Git.vim +++ b/autoload/leaderf/Git.vim @@ -412,6 +412,8 @@ function! leaderf#Git#Commands() \ {"Leaderf git log --explorer": "fuzzy search and view the log in an explorer tabpage"}, \ {"Leaderf git log --explorer --navigation-position bottom": "specify the position of navigation panel in explorer tabpage"}, \ {"Leaderf git log --current-file": "fuzzy search and view the logs of current file"}, + \ {"Leaderf git blame": "git blame current file"}, + \ {"Leaderf git blame -w": "ignore whitespace when git blame current file"}, \ ] endif From 7fbccd6f4e62b2c9ec493c3c32d2e4a63b9e95e5 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Tue, 16 Apr 2024 21:12:59 +0800 Subject: [PATCH 177/365] add command LeaderfGitSplitDiff --- plugin/leaderf.vim | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugin/leaderf.vim b/plugin/leaderf.vim index 556178ca..e35a8e65 100644 --- a/plugin/leaderf.vim +++ b/plugin/leaderf.vim @@ -257,6 +257,8 @@ command! -bar -nargs=0 LeaderfWindow Leaderf window command! -bar -nargs=0 LeaderfQuickFix Leaderf quickfix command! -bar -nargs=0 LeaderfLocList Leaderf loclist +command! -bar -nargs=0 LeaderfGitSplitDiff Leaderf git diff --current-file --side-by-side + try if g:Lf_ShortcutF != "" exec 'nnoremap ' g:Lf_ShortcutF ':LeaderfFile' From 76d170fbe8fe013cb5f2269e8ec215e88d2841b7 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Tue, 16 Apr 2024 23:11:15 +0800 Subject: [PATCH 178/365] add support for `Leaderf git log --current-file --explorer` --- autoload/leaderf/Git.vim | 3 +- autoload/leaderf/python/leaderf/gitExpl.py | 58 +++++++++++++--------- doc/leaderf.txt | 7 +++ plugin/leaderf.vim | 1 + 4 files changed, 44 insertions(+), 25 deletions(-) diff --git a/autoload/leaderf/Git.vim b/autoload/leaderf/Git.vim index b54c134c..ec897547 100644 --- a/autoload/leaderf/Git.vim +++ b/autoload/leaderf/Git.vim @@ -411,7 +411,8 @@ function! leaderf#Git#Commands() \ {"Leaderf git log --directly": "view the logs directly"}, \ {"Leaderf git log --explorer": "fuzzy search and view the log in an explorer tabpage"}, \ {"Leaderf git log --explorer --navigation-position bottom": "specify the position of navigation panel in explorer tabpage"}, - \ {"Leaderf git log --current-file": "fuzzy search and view the logs of current file"}, + \ {"Leaderf git log --current-file": "fuzzy search and view the log of current file"}, + \ {"Leaderf git log --current-file --explorer":"fuzzy search and view the log of current file in explorer tabpage"}, \ {"Leaderf git blame": "git blame current file"}, \ {"Leaderf git blame -w": "ignore whitespace when git blame current file"}, \ ] diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 3afeb49b..8fc6372c 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -311,10 +311,14 @@ def buildCommandAndBufferName(self): ' %cd{}%n%n%s%n%n%b%n" --stat=70 --stat-graph-width=10 -p --no-color' ).format(self._source, sep) - if "--recall" in self._arguments and "current_file" in self._arguments: - self._cmd += " -- {}".format(self._arguments["current_file"]) - elif "--current-file" in self._arguments and "current_file" in self._arguments: - self._cmd += " -- {}".format(self._arguments["current_file"]) + if (("--recall" in self._arguments or "--current-file" in self._arguments) + and "current_file" in self._arguments): + self._cmd = ('git show {} --pretty=format:"commit %H%nparent %P%n' + 'Author: %an <%ae>%nAuthorDate: %ad%nCommitter: %cn <%ce>%nCommitDate:' + ' %cd{}%n%n%s%n%n%b%n%x2d%x2d%x2d" --stat=70 --stat-graph-width=10 --no-color' + ' && git show {} --pretty=format:"%x20" --no-color -- {}' + ).format(self._source, sep, self._source, + self._arguments["current_file"]) self._buffer_name = "LeaderF://" + self._source @@ -1800,7 +1804,6 @@ def create(self, arguments_dict, source, **kwargs): lfCmd("call win_execute({}, 'norm! {}G0zbzz')".format(target_winid, kwargs["line_num"])) - class NavigationPanel(Panel): def __init__(self, bufhidden_callback=None): self.tree_view = None @@ -2582,6 +2585,19 @@ def _afterEnter(self): def _accept(self, file, mode, *args, **kwargs): super(GitExplManager, self)._accept(file, mode, *args, **kwargs) + def _createExplorerPage(self, source, target_path=None): + if source in self._pages: + vim.current.tabpage = self._pages[source].tabpage + else: + lfCmd("augroup Lf_Git_Log | augroup END") + lfCmd("autocmd! Lf_Git_Log TabClosed * call leaderf#Git#CleanupExplorerPage({})" + .format(id(self))) + + self._pages[source] = ExplorerPage(self._project_root, source, self) + self._pages[source].create(self._arguments, + GitLogExplCommand(self._arguments, source), + target_path=target_path) + def _acceptSelection(self, *args, **kwargs): if len(args) == 0: return @@ -2592,27 +2608,21 @@ def _acceptSelection(self, *args, **kwargs): return if "--current-file" in self._arguments and "current_file" in self._arguments: - if self._diff_view_panel is None: - self._diff_view_panel = DiffViewPanel(self.afterBufhidden) - - self._diff_view_panel.setCommitId(source) - cmd = "git show --pretty= --no-color --raw {} -- {}".format(source, - self._arguments["current_file"]) - outputs = ParallelExecutor.run(cmd) - if len(outputs[0]) > 0: - _, source = TreeView.generateSource(outputs[0][0]) - self._diff_view_panel.create(self._arguments, source, **kwargs) - elif "--explorer" in self._arguments: - if source in self._pages: - vim.current.tabpage = self._pages[source].tabpage + if "--explorer" in self._arguments: + self._createExplorerPage(source, self._arguments["current_file"]) else: - lfCmd("augroup Lf_Git_Log | augroup END") - lfCmd("autocmd! Lf_Git_Log TabClosed * call leaderf#Git#CleanupExplorerPage({})" - .format(id(self))) + if self._diff_view_panel is None: + self._diff_view_panel = DiffViewPanel(self.afterBufhidden) - self._pages[source] = ExplorerPage(self._project_root, source, self) - self._pages[source].create(self._arguments, - GitLogExplCommand(self._arguments, source)) + self._diff_view_panel.setCommitId(source) + cmd = "git show --pretty= --no-color --raw {} -- {}".format(source, + self._arguments["current_file"]) + outputs = ParallelExecutor.run(cmd) + if len(outputs[0]) > 0: + _, source = TreeView.generateSource(outputs[0][0]) + self._diff_view_panel.create(self._arguments, source, **kwargs) + elif "--explorer" in self._arguments: + self._createExplorerPage(source) else: if kwargs.get("mode", '') == 't' and source not in self._result_panel.getSources(): self._arguments["mode"] = 't' diff --git a/doc/leaderf.txt b/doc/leaderf.txt index 0ad19b7c..14081bdf 100644 --- a/doc/leaderf.txt +++ b/doc/leaderf.txt @@ -1246,6 +1246,13 @@ USAGE *leaderf-usage* :LeaderfRgRecall *LeaderfRgRecall* Recall last search of rg. +:LeaderfGit *LeaderfGit* + List some frequently used commands of Leaderf git. + +:LeaderfGitSplitDiff *LeaderfGitSplitDiff* + Show the diffs of current file in a vertical split window. + It is a shortcut of `:Leaderf git diff --current-file --side-by-side` + Some handy maps for `Leaderf rg`: | Map | Description diff --git a/plugin/leaderf.vim b/plugin/leaderf.vim index e35a8e65..70b60875 100644 --- a/plugin/leaderf.vim +++ b/plugin/leaderf.vim @@ -257,6 +257,7 @@ command! -bar -nargs=0 LeaderfWindow Leaderf window command! -bar -nargs=0 LeaderfQuickFix Leaderf quickfix command! -bar -nargs=0 LeaderfLocList Leaderf loclist +command! -bar -nargs=0 LeaderfGit Leaderf git command! -bar -nargs=0 LeaderfGitSplitDiff Leaderf git diff --current-file --side-by-side try From bfd5f20d9249cac9daf3fbf300dede9a3e194949 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 17 Apr 2024 10:05:32 +0800 Subject: [PATCH 179/365] go to first change --- autoload/leaderf/python/leaderf/gitExpl.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 8fc6372c..68dc5fb4 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -1802,6 +1802,8 @@ def create(self, arguments_dict, source, **kwargs): if kwargs.get("line_num", None) is not None: lfCmd("call win_execute({}, 'norm! {}G0zbzz')".format(target_winid, kwargs["line_num"])) + else: + lfCmd("call win_execute({}, 'norm! gg]c0')".format(target_winid)) class NavigationPanel(Panel): From 25fcf74d27e16470bbc5d79fb8859b7876764dc7 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 17 Apr 2024 18:35:06 +0800 Subject: [PATCH 180/365] optimize the code fix a bug that error occurs if two commits have the same parent --- autoload/leaderf/python/leaderf/gitExpl.py | 92 +++++++++++++--------- 1 file changed, 55 insertions(+), 37 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 68dc5fb4..66c06b94 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -689,6 +689,8 @@ def __init__(self, owner, cmd): self.blame_stack = [] # key is commit id, value is (blame_buffer, alternative_buffer_num) self.blame_dict = {} + # key is alternative buffer name, value is (blame_buffer, alternative_buffer_num) + self.blame_buffer_dict = {} def setOptions(self, winid, bufhidden): super(GitBlameView, self).setOptions(winid, bufhidden) @@ -752,10 +754,11 @@ def suicide(self): for item in self.blame_dict.values(): buffer_num = int(item[1]) # buftype is not empty - if vim.buffers[buffer_num].options["buftype"]: + if buffer_num in vim.buffers and vim.buffers[buffer_num].options["buftype"]: lfCmd("bwipe {}".format(buffer_num)) self.blame_dict = {} self.blame_stack = [] + self.blame_buffer_dict = {} class LfOrderedDict(OrderedDict): @@ -1863,6 +1866,9 @@ def getBlameStack(self, buffer_name): def getBlameDict(self, buffer_name): return self._views[buffer_name].blame_dict + def getBlameBufferDict(self, buffer_name): + return self._views[buffer_name].blame_buffer_dict + @staticmethod def formatLine(line): """ @@ -2692,33 +2698,28 @@ def blamePrevious(self): blame_winid = lfEval("win_getid()") if commit_id not in self._blame_panel.getBlameDict(vim.current.buffer.name): - cmd = ["git diff {}^ {} --name-status".format(commit_id, commit_id), - "git rev-parse {}^".format(commit_id) - ] - outputs = ParallelExecutor.run(*cmd) - orig_name = None - first_commit = False - for line in outputs[0]: - if line.endswith("\t" + file_name): - if line.startswith("A"): - first_commit = True - - if line.startswith("R"): - orig_name = line.split()[1] - else: - orig_name = file_name - break - - if first_commit == True: + cmd = 'git log -2 --pretty="%H" --name-status --follow {} -- {}'.format(commit_id, + file_name) + # output is as below: + + # a7cdd68e0f9e891e6f5def7b2b657d07d92a3675 + # + # R064 tui.py src/tui.py + # 5a0cd5103deba164a6fb33a5a3f67fb3a5dcf378 + # + # M tui.py + outputs = ParallelExecutor.run(cmd) + name_stat = outputs[0][2] + if name_stat.startswith("A"): lfPrintError("First commit of current file!") return + else: + if name_stat.startswith("R"): + orig_name = name_stat.split()[1] + else: + orig_name = file_name - parent_commit_id = outputs[1][0] - - cmd = ["git blame -f -n {} -- {}".format(parent_commit_id, orig_name), - "git show {}:{}".format(parent_commit_id, orig_name) - ] - outputs = ParallelExecutor.run(*cmd) + parent_commit_id = outputs[0][3] blame_win_width = vim.current.window.width self._blame_panel.getBlameStack(vim.current.buffer.name).append( @@ -2731,25 +2732,38 @@ def blamePrevious(self): ) ) + alternative_buffer_name = "LeaderF://{}:{}".format(parent_commit_id[:7], orig_name) + blame_buffer_dict = self._blame_panel.getBlameBufferDict(vim.current.buffer.name) + lfCmd("noautocmd call win_gotoid({})".format(alternative_winid)) - lfCmd("noautocmd enew") - self.setOptions(alternative_winid) + if alternative_buffer_name in blame_buffer_dict: + blame_buffer, alternative_buffer_num = blame_buffer_dict[alternative_buffer_name] + lfCmd("buffer {}".format(alternative_buffer_num)) + else: + cmd = ["git blame -f -n {} -- {}".format(parent_commit_id, orig_name), + "git show {}:{}".format(parent_commit_id, orig_name) + ] + outputs = ParallelExecutor.run(*cmd) + blame_buffer = [BlamePanel.formatLine(line) for line in outputs[0]] + + lfCmd("noautocmd enew") + self.setOptions(alternative_winid) + + vim.current.buffer[:] = outputs[1] + vim.current.buffer.name = alternative_buffer_name + lfCmd("doautocmd filetypedetect BufNewFile {}".format(orig_name)) + lfCmd("setlocal nomodifiable") + alternative_buffer_num = vim.current.buffer.number - vim.current.buffer[:] = outputs[1] - vim.current.buffer.name = "LeaderF://{}:{}".format(parent_commit_id[:7], orig_name) - lfCmd("doautocmd filetypedetect BufNewFile {}".format(orig_name)) - lfCmd("setlocal nomodifiable") lfCmd("noautocmd norm! {}Gzz".format(line_num)) - alternative_buffer_num = vim.current.buffer.number top_line = lfEval("line('w0')") lfCmd("noautocmd call win_gotoid({})".format(blame_winid)) - outputs[0] = [BlamePanel.formatLine(line) for line in outputs[0]] lfCmd("setlocal modifiable") - vim.current.buffer[:] = outputs[0] + vim.current.buffer[:] = blame_buffer lfCmd("setlocal nomodifiable") - if len(outputs[0]) > 0: - line_width = outputs[0][0].rfind('\t') + if len(blame_buffer) > 0: + line_width = blame_buffer[0].rfind('\t') line_num_width = max(len(str(len(vim.current.buffer))) + 1, int(lfEval('&numberwidth'))) lfCmd("vertical resize {}".format(line_width + line_num_width)) lfCmd("noautocmd norm! {}Gzt{}G0".format(top_line, line_num)) @@ -2757,10 +2771,14 @@ def blamePrevious(self): blame_win_width = vim.current.window.width self._blame_panel.getBlameDict(vim.current.buffer.name)[commit_id] = ( - outputs[0], + blame_buffer, alternative_buffer_num, blame_win_width ) + self._blame_panel.getBlameBufferDict(vim.current.buffer.name)[alternative_buffer_name] = ( + blame_buffer, + alternative_buffer_num, + ) else: self._blame_panel.getBlameStack(vim.current.buffer.name).append( ( From 226739922a1afb8a8d25421786085159c3743d2e Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 18 Apr 2024 13:25:35 +0800 Subject: [PATCH 181/365] update the code --- autoload/leaderf/python/leaderf/gitExpl.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 66c06b94..65165dcd 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -2775,10 +2775,7 @@ def blamePrevious(self): alternative_buffer_num, blame_win_width ) - self._blame_panel.getBlameBufferDict(vim.current.buffer.name)[alternative_buffer_name] = ( - blame_buffer, - alternative_buffer_num, - ) + blame_buffer_dict[alternative_buffer_name] = (blame_buffer, alternative_buffer_num) else: self._blame_panel.getBlameStack(vim.current.buffer.name).append( ( From 307899ee3aa6d07573afaa1d854b22baf0310b88 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 18 Apr 2024 16:29:15 +0800 Subject: [PATCH 182/365] let `Leaderf rg` support non-normal buffer(buftype not empty) --- autoload/leaderf/python/leaderf/rgExpl.py | 42 ++++++++++++++++++----- autoload/leaderf/python/leaderf/utils.py | 4 +++ 2 files changed, 37 insertions(+), 9 deletions(-) diff --git a/autoload/leaderf/python/leaderf/rgExpl.py b/autoload/leaderf/python/leaderf/rgExpl.py index e22eb477..83669f83 100644 --- a/autoload/leaderf/python/leaderf/rgExpl.py +++ b/autoload/leaderf/python/leaderf/rgExpl.py @@ -43,6 +43,8 @@ def __init__(self): self._display_multi = False self._cmd_work_dir = "" self._rg = lfEval("get(g:, 'Lf_Rg', 'rg')") + self.current_buffer_num = -1 + self.current_buffer_name_len = 0 def getContent(self, *args, **kwargs): arguments_dict = kwargs.get("arguments", {}) @@ -294,7 +296,7 @@ def formatLine(line): return line _, line = line.split("@LeaderF@", 1) - buf_number = line.split(":", 1)[0] + buf_number = re.split("[:-]", line, 1)[0] buf_name = buffer_names[int(buf_number)] return line.replace(buf_number, buf_name, 1) except: @@ -307,10 +309,13 @@ def formatLine(line): else: tmp_file = tempfile.NamedTemporaryFile + self.current_buffer_num = -1 + self.current_buffer_name_len = 0 if "--current-buffer" in arguments_dict: + self.current_buffer_num = vim.current.buffer.number path = '' # omit the option if vim.current.buffer.name: - if vim.current.buffer.options["modified"] == False: + if vim.current.buffer.options["modified"] == False and not vim.current.buffer.options["bt"]: try: path = '"%s"' % os.path.relpath(lfDecode(vim.current.buffer.name)) except ValueError: @@ -325,6 +330,7 @@ def formatLine(line): path = '"' + file_name + '"' tmpfilenames.append(file_name) format_line = formatLine + self.current_buffer_name_len = len(lfRelpath(vim.current.buffer.name)) else: file_name = "%d_'No_Name_%d'" % (os.getpid(), vim.current.buffer.number) try: @@ -537,12 +543,17 @@ def _getFileInfo(self, args): line = args[0] if "--heading" in self._arguments: + buffer_name_len = self._getExplorer().current_buffer_name_len buffer = args[1] cursor_line = args[2] if "-A" in self._arguments or "-B" in self._arguments or "-C" in self._arguments: if not re.match(r'^\d+[:-]', line): return (None, None) + if buffer_name_len > 0: + line_num = re.split("[:-]", line, 1)[0] + return (self._getExplorer().current_buffer_num, line_num) + for cur_line in reversed(buffer[:cursor_line]): if cur_line == self._getExplorer().getContextSeparator(): continue @@ -559,6 +570,10 @@ def _getFileInfo(self, args): if not re.match(r'^\d+:', line): return (None, None) + if buffer_name_len > 0: + line_num = line.split(":", 1)[0] + return (self._getExplorer().current_buffer_num, line_num) + for cur_line in reversed(buffer[:cursor_line]): if cur_line == self._getExplorer().getContextSeparator(): continue @@ -572,6 +587,11 @@ def _getFileInfo(self, args): file = os.path.join(self._getInstance().getCwd(), lfDecode(file)) line_num = line.split(':')[0] else: + buffer_name_len = self._getExplorer().current_buffer_name_len + if buffer_name_len > 0: + line_num = re.split("[:-]", line[buffer_name_len+1:], 1)[0] + return (self._getExplorer().current_buffer_num, line_num) + if "-A" in self._arguments or "-B" in self._arguments or "-C" in self._arguments: m = re.match(r'^(.+?)([:-])(\d+)\2', line) file, sep, line_num = m.group(1, 2, 3) @@ -586,6 +606,7 @@ def _getFileInfo(self, args): m = re.match(r'^(.+?)%s(\d+)%s' % (sep, sep), line) if m: file, line_num = m.group(1, 2) + if not re.search(r"\d+_'No_Name_(\d+)'", file): i = 1 while not os.path.exists(lfDecode(file)): @@ -596,8 +617,10 @@ def _getFileInfo(self, args): m = re.match(r'^(.+?):(\d+):', line) if m is None: return (None, None) + file, line_num = m.group(1, 2) - if not re.search(r"\d+_'No_Name_(\d+)'", file): + match = re.search(r"\d+_'No_Name_(\d+)'", file) + if not match: if not os.path.isabs(file): file = os.path.join(self._getInstance().getCwd(), lfDecode(file)) i = 1 @@ -607,6 +630,9 @@ def _getFileInfo(self, args): file, line_num = m.group(1, 2) if not os.path.isabs(file): file = os.path.join(self._getInstance().getCwd(), lfDecode(file)) + else: + buf_number = match.group(1) + return (int(buf_number), line_num) file = os.path.normpath(lfEncode(file)) @@ -624,9 +650,8 @@ def _acceptSelection(self, *args, **kwargs): if file is None: return - match = re.search(r"\d+_'No_Name_(\d+)'", file) - if match: - buf_number = match.group(1) + if isinstance(file, int): + buf_number = file else: buf_number = -1 @@ -1230,9 +1255,8 @@ def _previewInPopup(self, *args, **kwargs): if file is None: return - match = re.search(r"\d+_'No_Name_(\d+)'", file) - if match: - source = int(match.group(1)) + if isinstance(file, int): + source = file else: if lfEval("bufloaded('%s')" % escQuote(file)) == '1': source = int(lfEval("bufadd('%s')" % escQuote(file))) diff --git a/autoload/leaderf/python/leaderf/utils.py b/autoload/leaderf/python/leaderf/utils.py index 5cf61388..c4c84a9b 100644 --- a/autoload/leaderf/python/leaderf/utils.py +++ b/autoload/leaderf/python/leaderf/utils.py @@ -146,6 +146,10 @@ def equal(str1, str2, ignorecase=True): def lfRelpath(path, start=os.curdir): try: + # LeaderF://git diff + if not os.path.isabs(path): + return path + return lfEncode(os.path.relpath(lfDecode(path), start)) except ValueError: return path From 1bdd01ae8b050536e522dc98f63393ede529f9f0 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 18 Apr 2024 17:45:00 +0800 Subject: [PATCH 183/365] `buffer_num in vim.buffers` is always false --- autoload/leaderf/python/leaderf/gitExpl.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 65165dcd..0d3df72d 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -754,7 +754,8 @@ def suicide(self): for item in self.blame_dict.values(): buffer_num = int(item[1]) # buftype is not empty - if buffer_num in vim.buffers and vim.buffers[buffer_num].options["buftype"]: + if (lfEval("bufexists({})".format(buffer_num)) == "1" + and vim.buffers[buffer_num].options["buftype"]): lfCmd("bwipe {}".format(buffer_num)) self.blame_dict = {} self.blame_stack = [] From 393cbd1e60501f543297141a05f0e575c4c60077 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 18 Apr 2024 17:55:05 +0800 Subject: [PATCH 184/365] fix typos --- autoload/leaderf/python/leaderf/gitExpl.py | 80 +++++++++++----------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 0d3df72d..ea0c1cbe 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -616,9 +616,9 @@ def valid(self): class GitBlameView(GitCommandView): def __init__(self, owner, cmd): super(GitBlameView, self).__init__(owner, cmd) - self._alternative_winid = None - self._alternative_buffer_num = None - self._alternative_win_options = {} + self._alternate_winid = None + self._alternate_buffer_num = None + self._alternate_win_options = {} self._match_ids = [] self._color_table = { '0': '#000000', '1': '#800000', '2': '#008000', '3': '#808000', @@ -687,9 +687,9 @@ def __init__(self, owner, cmd): '252': '#d0d0d0', '253': '#dadada', '254': '#e4e4e4', '255': '#eeeeee' } self.blame_stack = [] - # key is commit id, value is (blame_buffer, alternative_buffer_num) + # key is commit id, value is (blame_buffer, alternate_buffer_num) self.blame_dict = {} - # key is alternative buffer name, value is (blame_buffer, alternative_buffer_num) + # key is alternate buffer name, value is (blame_buffer, alternate_buffer_num) self.blame_buffer_dict = {} def setOptions(self, winid, bufhidden): @@ -702,17 +702,17 @@ def setOptions(self, winid, bufhidden): lfCmd("call win_execute({}, 'setlocal signcolumn=no')".format(winid)) lfCmd("call win_execute({}, 'setlocal cursorline')".format(winid)) - def saveAlternativeWinOptions(self, winid, buffer_num): - self._alternative_winid = winid - self._alternative_buffer_num = buffer_num + def saveAlternateWinOptions(self, winid, buffer_num): + self._alternate_winid = winid + self._alternate_buffer_num = buffer_num - self._alternative_win_options = { + self._alternate_win_options = { "foldenable": lfEval("getwinvar({}, '&foldenable')".format(winid)), "scrollbind": lfEval("getwinvar({}, '&scrollbind')".format(winid)), } - def getAlternativeWinid(self): - return self._alternative_winid + def getAlternateWinid(self): + return self._alternate_winid def enableColor(self, winid): if (lfEval("hlexists('Lf_hl_blame_255')") == '0' @@ -739,13 +739,13 @@ def enableColor(self, winid): def suicide(self): super(GitBlameView, self).suicide() - lfCmd("call win_execute({}, 'buffer {} | norm! {}G0')".format(self._alternative_winid, - self._alternative_buffer_num, + lfCmd("call win_execute({}, 'buffer {} | norm! {}G0')".format(self._alternate_winid, + self._alternate_buffer_num, vim.current.window.cursor[0])) - if self._alternative_winid is not None: - for k, v in self._alternative_win_options.items(): - lfCmd("call setwinvar({}, '&{}', {})".format(self._alternative_winid, k, v)) + if self._alternate_winid is not None: + for k, v in self._alternate_win_options.items(): + lfCmd("call setwinvar({}, '&{}', {})".format(self._alternate_winid, k, v)) for i in self._match_ids: lfCmd("silent! call matchdelete(%d)" % i) @@ -1858,8 +1858,8 @@ def deregister(self, view): self._views[name].cleanup() del self._views[name] - def getAlternativeWinid(self, buffer_name): - return self._views[buffer_name].getAlternativeWinid() + def getAlternateWinid(self, buffer_name): + return self._views[buffer_name].getAlternateWinid() def getBlameStack(self, buffer_name): return self._views[buffer_name].blame_stack @@ -1892,7 +1892,7 @@ def create(self, cmd, content=None): else: winid = int(lfEval("win_getid()")) blame_view = GitBlameView(self, cmd) - blame_view.saveAlternativeWinOptions(winid, vim.current.buffer.number) + blame_view.saveAlternateWinOptions(winid, vim.current.buffer.number) lfCmd("setlocal nofoldenable") top_line = lfEval("line('w0')") cursor_line = lfEval("line('.')") @@ -2695,7 +2695,7 @@ def blamePrevious(self): return line_num, file_name = vim.current.line.rsplit('\t', 1)[1].split(None, 1) - alternative_winid = self._blame_panel.getAlternativeWinid(vim.current.buffer.name) + alternate_winid = self._blame_panel.getAlternateWinid(vim.current.buffer.name) blame_winid = lfEval("win_getid()") if commit_id not in self._blame_panel.getBlameDict(vim.current.buffer.name): @@ -2726,20 +2726,20 @@ def blamePrevious(self): self._blame_panel.getBlameStack(vim.current.buffer.name).append( ( vim.current.buffer[:], - lfEval("winbufnr({})".format(alternative_winid)), + lfEval("winbufnr({})".format(alternate_winid)), blame_win_width, vim.current.window.cursor[0], int(lfEval("line('w0')")) ) ) - alternative_buffer_name = "LeaderF://{}:{}".format(parent_commit_id[:7], orig_name) + alternate_buffer_name = "LeaderF://{}:{}".format(parent_commit_id[:7], orig_name) blame_buffer_dict = self._blame_panel.getBlameBufferDict(vim.current.buffer.name) - lfCmd("noautocmd call win_gotoid({})".format(alternative_winid)) - if alternative_buffer_name in blame_buffer_dict: - blame_buffer, alternative_buffer_num = blame_buffer_dict[alternative_buffer_name] - lfCmd("buffer {}".format(alternative_buffer_num)) + lfCmd("noautocmd call win_gotoid({})".format(alternate_winid)) + if alternate_buffer_name in blame_buffer_dict: + blame_buffer, alternate_buffer_num = blame_buffer_dict[alternate_buffer_name] + lfCmd("buffer {}".format(alternate_buffer_num)) else: cmd = ["git blame -f -n {} -- {}".format(parent_commit_id, orig_name), "git show {}:{}".format(parent_commit_id, orig_name) @@ -2748,13 +2748,13 @@ def blamePrevious(self): blame_buffer = [BlamePanel.formatLine(line) for line in outputs[0]] lfCmd("noautocmd enew") - self.setOptions(alternative_winid) + self.setOptions(alternate_winid) vim.current.buffer[:] = outputs[1] - vim.current.buffer.name = alternative_buffer_name + vim.current.buffer.name = alternate_buffer_name lfCmd("doautocmd filetypedetect BufNewFile {}".format(orig_name)) lfCmd("setlocal nomodifiable") - alternative_buffer_num = vim.current.buffer.number + alternate_buffer_num = vim.current.buffer.number lfCmd("noautocmd norm! {}Gzz".format(line_num)) top_line = lfEval("line('w0')") @@ -2768,31 +2768,31 @@ def blamePrevious(self): line_num_width = max(len(str(len(vim.current.buffer))) + 1, int(lfEval('&numberwidth'))) lfCmd("vertical resize {}".format(line_width + line_num_width)) lfCmd("noautocmd norm! {}Gzt{}G0".format(top_line, line_num)) - lfCmd("call win_execute({}, 'setlocal scrollbind')".format(alternative_winid)) + lfCmd("call win_execute({}, 'setlocal scrollbind')".format(alternate_winid)) blame_win_width = vim.current.window.width self._blame_panel.getBlameDict(vim.current.buffer.name)[commit_id] = ( blame_buffer, - alternative_buffer_num, + alternate_buffer_num, blame_win_width ) - blame_buffer_dict[alternative_buffer_name] = (blame_buffer, alternative_buffer_num) + blame_buffer_dict[alternate_buffer_name] = (blame_buffer, alternate_buffer_num) else: self._blame_panel.getBlameStack(vim.current.buffer.name).append( ( vim.current.buffer[:], - lfEval("winbufnr({})".format(alternative_winid)), + lfEval("winbufnr({})".format(alternate_winid)), vim.current.window.width, vim.current.window.cursor[0], int(lfEval("line('w0')")) ) ) (blame_buffer, - alternative_buffer_num, + alternate_buffer_num, blame_win_width ) = self._blame_panel.getBlameDict(vim.current.buffer.name)[commit_id] - lfCmd("noautocmd call win_gotoid({})".format(alternative_winid)) - lfCmd("buffer {}".format(alternative_buffer_num)) + lfCmd("noautocmd call win_gotoid({})".format(alternate_winid)) + lfCmd("buffer {}".format(alternate_buffer_num)) lfCmd("noautocmd norm! {}Gzz".format(line_num)) top_line = lfEval("line('w0')") @@ -2808,12 +2808,12 @@ def blameNext(self): if len(blame_stack) == 0: return - blame_buffer, alternative_buffer_num, blame_win_width, cursor_line, top_line = blame_stack.pop() + blame_buffer, alternate_buffer_num, blame_win_width, cursor_line, top_line = blame_stack.pop() blame_winid = lfEval("win_getid()") - alternative_winid = self._blame_panel.getAlternativeWinid(vim.current.buffer.name) + alternate_winid = self._blame_panel.getAlternateWinid(vim.current.buffer.name) - lfCmd("noautocmd call win_gotoid({})".format(alternative_winid)) - lfCmd("buffer {}".format(alternative_buffer_num)) + lfCmd("noautocmd call win_gotoid({})".format(alternate_winid)) + lfCmd("buffer {}".format(alternate_buffer_num)) lfCmd("noautocmd call win_gotoid({})".format(blame_winid)) lfCmd("setlocal modifiable") From 10558a429f9a405c63720abbb323497d1e83f4d8 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 18 Apr 2024 22:14:34 +0800 Subject: [PATCH 185/365] go to the original cursor line of blamed buffer --- autoload/leaderf/python/leaderf/gitExpl.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index ea0c1cbe..c8b49a67 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -739,9 +739,16 @@ def enableColor(self, winid): def suicide(self): super(GitBlameView, self).suicide() - lfCmd("call win_execute({}, 'buffer {} | norm! {}G0')".format(self._alternate_winid, - self._alternate_buffer_num, - vim.current.window.cursor[0])) + line_num = vim.current.window.cursor[0] + top_line = lfEval("line('w0')") + if len(self.blame_stack) > 0: + line_num = self.blame_stack[0][3] + top_line = self.blame_stack[0][4] + + lfCmd("call win_execute({}, 'buffer {} | norm! {}Gzt{}G0')".format(self._alternate_winid, + self._alternate_buffer_num, + top_line, + line_num)) if self._alternate_winid is not None: for k, v in self._alternate_win_options.items(): From 9f9985201d12880bfab65db83a75c0e537f7e582 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 18 Apr 2024 23:47:25 +0800 Subject: [PATCH 186/365] Leaderf git blame --date= --- autoload/leaderf/Any.vim | 8 ++ .../leaderf/colorscheme/popup/default.vim | 2 + autoload/leaderf/python/leaderf/gitExpl.py | 131 +++++++++++++----- 3 files changed, 104 insertions(+), 37 deletions(-) diff --git a/autoload/leaderf/Any.vim b/autoload/leaderf/Any.vim index 9c9ae95a..c5de0ebe 100644 --- a/autoload/leaderf/Any.vim +++ b/autoload/leaderf/Any.vim @@ -254,6 +254,8 @@ let g:Lf_Arguments = { \ ], \ "blame": [ \ {"name": ["-w"], "nargs": 0, "help": "Ignore whitespace when comparing the parent’s version and the child’s to find where the lines came from."}, + \ {"name": ["--date"], "nargs": 1, "choices": ["relative", "local", "iso", "iso-strict", "rfc", "short", "human", "default"], + \ "metavar": "", "help": "Specifies the format used to output dates. .i.e, git blame --date=. can be one of ['relative', 'local', 'iso', 'iso-strict', 'rfc', 'short', 'human', 'default']"}, \ ], \ }, \} @@ -400,6 +402,12 @@ function! leaderf#Any#parseArguments(argLead, cmdline, cursorPos) abort endif endif + if argNum > 3 && argList[1] == "git" && argList[2] == "blame" + if get(existingOptions, -1, "") == "--date" + return ["relative", "local", "iso", "iso-strict", "rfc", "short", "human", "default"] + endif + endif + let argDict = s:Lf_GenDict(arguments + g:Lf_CommonArguments) for opt in s:Lf_Refine(arguments + g:Lf_CommonArguments) if type(opt) == type([]) diff --git a/autoload/leaderf/colorscheme/popup/default.vim b/autoload/leaderf/colorscheme/popup/default.vim index f5aef20d..0f19e606 100644 --- a/autoload/leaderf/colorscheme/popup/default.vim +++ b/autoload/leaderf/colorscheme/popup/default.vim @@ -167,6 +167,7 @@ if &background ==? 'dark' highlight def link Lf_hl_gitGraph3 Special highlight def link Lf_hl_gitGraph4 Lf_hl_gitGraph1 highlight def link Lf_hl_gitGraphSlash Constant + highlight def link Lf_hl_gitBlameDate Number else " Lf_hl_popup_inputText is the wincolor of input window highlight def Lf_hl_popup_inputText guifg=#525252 guibg=#f4f3d7 gui=NONE ctermfg=239 ctermbg=230 cterm=NONE @@ -321,4 +322,5 @@ else highlight def link Lf_hl_gitGraph3 Special highlight def link Lf_hl_gitGraph4 Lf_hl_gitGraph1 highlight def link Lf_hl_gitGraphSlash Constant + highlight def link Lf_hl_gitBlameDate Number endif diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index c8b49a67..61a910a6 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -358,27 +358,32 @@ def buildCommandAndBufferName(self): class GitBlameCommand(GitCommand): - def __init__(self, arguments_dict, source): - super(GitBlameCommand, self).__init__(arguments_dict, source) - - def buildCommandAndBufferName(self): - source = "" - if self._source is not None: - source = self._source + def __init__(self, arguments_dict, commit_id): + super(GitBlameCommand, self).__init__(arguments_dict, commit_id) + @staticmethod + def buildCommand(arguments_dict, commit_id, file_name): extra_options = "" - if "-w" in self._arguments: + if "-w" in arguments_dict: extra_options += " -w" - self._cmd = "git blame -f -n {} {} -- ".format(extra_options, source) + if "--date" in arguments_dict: + extra_options += " --date={}".format(arguments_dict["--date"][0]) + + return "git blame -f -n {} {} -- {}".format(extra_options, commit_id, file_name) + + def buildCommandAndBufferName(self): + commit_id = "" + if self._source is not None: + commit_id = self._source file_name = vim.current.buffer.name if " " in file_name: file_name = file_name.replace(' ', r'\ ') file_name = lfRelpath(file_name) - self._cmd += file_name - self._buffer_name = "LeaderF://git blame {} {}".format(source, file_name) + self._cmd = GitBlameCommand.buildCommand(self._arguments, commit_id, file_name) + self._buffer_name = "LeaderF://git blame {} {}".format(commit_id, file_name) self._file_type = "" self._file_type_cmd = "" @@ -728,7 +733,24 @@ def enableColor(self, winid): id = int(lfEval("matchid")) self._match_ids.append(id) - lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Number'', ''\(^\^\?\x\+.*(.\{-}\s\)\@<=\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d [+-]\d\d\d\d'', -100)')""" % winid) + arguments_dict = self._cmd.getArguments() + date_format = arguments_dict.get("--date", [""])[0] + if date_format in ["", "iso", "short"]: + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_gitBlameDate'', ''\(^\^\?\x\+.*(.\{-}\s\)\@<=\d\{4}-\d\d-\d\d\( \d\d:\d\d:\d\d [+-]\d\d\d\d\)\?'', -100)')""" % winid) + elif date_format == "relative": + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_gitBlameDate'', ''\(^\^\?\x\+.*(.\{-}\s\)\@<=\d\+\s\+.\{-}ago'', -100)')""" % winid) + elif date_format == "local": + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_gitBlameDate'', ''\(^\^\?\x\+.*(.\{-}\s\)\@<=\(Mon\|Tue\|Wed\|Thu\|Fri\|Sat\|Sun\)\s\+\a\{3}\s\+\d\+.\{-}\(\s*)\)\@='', -100)')""" % winid) + elif date_format == "iso-strict": + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_gitBlameDate'', ''\(^\^\?\x\+.*(.\{-}\s\)\@<=\d\{4}-\d\d-\d\dT\d\d:\d\d:\d\d[+-]\d\d:\d\d'', -100)')""" % winid) + elif date_format == "rfc": + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_gitBlameDate'', ''\(^\^\?\x\+.*(.\{-}\s\)\@<=\(Mon\|Tue\|Wed\|Thu\|Fri\|Sat\|Sun\),\s\+\d\+.\{-}\(\s*)\)\@='', -100)')""" % winid) + elif date_format == "human": + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_gitBlameDate'', ''\(^\^\?\x\+.*(.\{-}\s\)\@<=\a\{3}\s\+\d\+\s\+\d\{4}\(\s*)\)\@='', -100)')""" % winid) + elif date_format == "default": + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_gitBlameDate'', ''\(^\^\?\x\+.*(.\{-}\s\)\@<=\(Mon\|Tue\|Wed\|Thu\|Fri\|Sat\|Sun\)\s\+\a\{3}\s\+\d\+.\{-}\(\s*)\)\@='', -100)')""" % winid) + else: + raise ValueError("impossible value of '--date'") id = int(lfEval("matchid")) self._match_ids.append(id) @@ -1878,16 +1900,48 @@ def getBlameBufferDict(self, buffer_name): return self._views[buffer_name].blame_buffer_dict @staticmethod - def formatLine(line): - """ - 6817817e autoload/leaderf/manager.py 1 (Yggdroot 2014-02-26 00:37:26 +0800 1) #!/usr/bin/env python - """ - return re.sub(r'(^\^?\w+)\s+(.*?)\s+(\d+)\s+(\([^(]*?)\s+\d+\).*', r'\g<1> \g<4>)\t\g<3> \g<2>', line, 1) + def formatLine(arguments_dict, line_num_width, line): + date_format = arguments_dict.get("--date", [""])[0] + if date_format in ["", "iso", "iso-strict", "short"]: + # 6817817e autoload/leaderf/manager.py 1 (Yggdroot 2014-02-26 00:37:26 +0800 1) #!/usr/bin/env python + return re.sub(r'(^\^?\w+)\s+(.*?)\s+(\d+)\s+(\([^(]*?)\s+\d+\).*', + r'\g<1> \g<4>)\t\g<3> \g<2>', line, 1) + elif date_format == "relative": + # c5c6d072 autoload/leaderf/python/leaderf/manager.py 63 (Yggdroot 4 years, 6 months ago 66) def catchException(func): + line = re.sub(r'(^.*?\d+\)).*', r'\g<1>', line, 1) + return re.sub(r'(^\^?\w+)\s+(.*?)\s+(\d+)\s+(\(.*)', + r'\g<1> \g<4>)\t\g<3> \g<2>', + line[:-(line_num_width + 1)], 1) + elif date_format == "local": + # 6817817e autoload/leaderf/manager.py 1 (Yggdroot Wed Feb 26 00:37:26 2014 1) #!/usr/bin/env python + line = re.sub(r'(^.*?\d+\)).*', r'\g<1>', line, 1) + return re.sub(r'(^\^?\w+)\s+(.*?)\s+(\d+)\s+(\(.*)', + r'\g<1> \g<4>)\t\g<3> \g<2>', + line[:-(line_num_width + 7)], 1) + elif date_format in ("rfc", "default"): + # 6817817e autoload/leaderf/manager.py 1 (Yggdroot Wed, 26 Feb 2014 00:37:26 +0800 1) #!/usr/bin/env python + # 6817817e autoload/leaderf/manager.py 1 (Yggdroot Wed Feb 26 00:37:26 2014 +0800 1) #!/usr/bin/env python + line = re.sub(r'(^.*?\d+\)).*', r'\g<1>', line, 1) + return re.sub(r'(^\^?\w+)\s+(.*?)\s+(\d+)\s+(\(.*)', + r'\g<1> \g<4>)\t\g<3> \g<2>', + line[:-(line_num_width + 1)], 1) + elif date_format == "human": + # 6817817e autoload/leaderf/manager.py 1 (Yggdroot Feb 26 2014 1) #!/usr/bin/env python + line = re.sub(r'(^.*?\d+\)).*', r'\g<1>', line, 1) + return re.sub(r'(^\^?\w+)\s+(.*?)\s+(\d+)\s+(\(.*)', + r'\g<1> \g<4>)\t\g<3> \g<2>', + line[:-(line_num_width + 6)], 1) + else: + return line - def create(self, cmd, content=None): + def create(self, arguments_dict, cmd, content=None): buffer_name = cmd.getBufferName() - outputs = ParallelExecutor.run(cmd.getCommand(), format_line=BlamePanel.formatLine) - line_num_width = max(len(str(len(vim.current.buffer))) + 1, int(lfEval('&numberwidth'))) + line_num_width = len(str(len(vim.current.buffer))) + 1 + outputs = ParallelExecutor.run(cmd.getCommand(), + format_line=partial(BlamePanel.formatLine, + arguments_dict, + line_num_width)) + line_num_width = max(line_num_width, int(lfEval('&numberwidth'))) if len(outputs[0]) > 0: if buffer_name in self._views and self._views[buffer_name].valid(): top_line = lfEval("line('w0')") @@ -2667,14 +2721,14 @@ class GitBlameExplManager(GitExplManager): def __init__(self): super(GitBlameExplManager, self).__init__() self._blame_panel = BlamePanel(self) - # key is source, value is ExplorerPage + # key is commit_id, value is ExplorerPage self._pages = {} - def createGitCommand(self, arguments_dict, source): - return GitBlameCommand(arguments_dict, source) + def createGitCommand(self, arguments_dict, commit_id): + return GitBlameCommand(arguments_dict, commit_id) - def getPreviewCommand(self, arguments_dict, source): - return GitLogDiffCommand(arguments_dict, source) + def getPreviewCommand(self, arguments_dict, commit_id): + return GitLogDiffCommand(arguments_dict, commit_id) def defineMaps(self, winid): lfCmd("call win_execute({}, 'call leaderf#Git#BlameMaps({})')" @@ -2748,11 +2802,14 @@ def blamePrevious(self): blame_buffer, alternate_buffer_num = blame_buffer_dict[alternate_buffer_name] lfCmd("buffer {}".format(alternate_buffer_num)) else: - cmd = ["git blame -f -n {} -- {}".format(parent_commit_id, orig_name), + cmd = [GitBlameCommand.buildCommand(self._arguments, parent_commit_id, orig_name), "git show {}:{}".format(parent_commit_id, orig_name) - ] + ] outputs = ParallelExecutor.run(*cmd) - blame_buffer = [BlamePanel.formatLine(line) for line in outputs[0]] + line_num_width = len(str(len(outputs[1]))) + 1 + blame_buffer = [BlamePanel.formatLine(self._arguments, line_num_width, line) + for line in outputs[0] + ] lfCmd("noautocmd enew") self.setOptions(alternate_winid) @@ -2845,24 +2902,24 @@ def open(self): if vim.current.line == "": return - source = vim.current.line.lstrip('^').split(None, 1)[0] - if source.startswith('0000000'): + commit_id = vim.current.line.lstrip('^').split(None, 1)[0] + if commit_id.startswith('0000000'): lfPrintError("Not Committed Yet!") return line_num, file_name = vim.current.line.rsplit('\t', 1)[1].split(None, 1) - if source in self._pages: - vim.current.tabpage = self._pages[source].tabpage - self._pages[source].locateFile(file_name, line_num, False) + if commit_id in self._pages: + vim.current.tabpage = self._pages[commit_id].tabpage + self._pages[commit_id].locateFile(file_name, line_num, False) else: lfCmd("augroup Lf_Git_Blame | augroup END") lfCmd("autocmd! Lf_Git_Blame TabClosed * call leaderf#Git#CleanupExplorerPage({})" .format(id(self))) - self._pages[source] = ExplorerPage(self._project_root, source, self) - self._pages[source].create(self._arguments, - GitLogExplCommand(self._arguments, source), + self._pages[commit_id] = ExplorerPage(self._project_root, commit_id, self) + self._pages[commit_id].create(self._arguments, + GitLogExplCommand(self._arguments, commit_id), target_path=file_name, line_num=line_num) @@ -2878,7 +2935,7 @@ def startExplorer(self, win_pos, *args, **kwargs): lfPrintError("fatal: '{}' is outside repository at '{}'" .format(lfRelpath(vim.current.buffer.name), self._project_root)) else: - self._blame_panel.create(self.createGitCommand(self._arguments, None)) + self._blame_panel.create(arguments_dict, self.createGitCommand(self._arguments, None)) else: lfPrintError("fatal: no such path '{}' in HEAD".format(vim.current.buffer.name)) From 27a211552b817bfb9d1460fc1927f631d35a51d0 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Fri, 19 Apr 2024 21:48:30 +0800 Subject: [PATCH 187/365] update comments --- autoload/leaderf/python/leaderf/gitExpl.py | 50 ++++++++++++++-------- 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 61a910a6..d2966a7e 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -213,6 +213,9 @@ def getSource(self): class GitDiffCommand(GitCommand): def __init__(self, arguments_dict, source): + """ + source is a tuple like (b90f76fc1, bad07e644, R099, src/version.c, src/version2.c) + """ super(GitDiffCommand, self).__init__(arguments_dict, source) def buildCommandAndBufferName(self): @@ -240,6 +243,9 @@ def buildCommandAndBufferName(self): class GitLogDiffCommand(GitCommand): def __init__(self, arguments_dict, source): + """ + source is a tuple like (b90f76fc1, bad07e644, R099, src/version.c, src/version2.c) + """ super(GitLogDiffCommand, self).__init__(arguments_dict, source) def buildCommandAndBufferName(self): @@ -290,6 +296,9 @@ def buildCommandAndBufferName(self): class GitLogCommand(GitCommand): def __init__(self, arguments_dict, source): + """ + source is a commit id + """ super(GitLogCommand, self).__init__(arguments_dict, source) def buildCommandAndBufferName(self): @@ -347,6 +356,9 @@ def buildCommandAndBufferName(self): class GitLogExplCommand(GitCommand): def __init__(self, arguments_dict, source): + """ + source is a commit id + """ super(GitLogExplCommand, self).__init__(arguments_dict, source) def buildCommandAndBufferName(self): @@ -2533,7 +2545,7 @@ def __init__(self): lfCmd("augroup Lf_Git_Log | augroup END") lfCmd("autocmd! Lf_Git_Log FileType git call leaderf#Git#DefineSyntax()") self._diff_view_panel = None - # key is source, value is ExplorerPage + # key is commit id, value is ExplorerPage self._pages = {} def _getExplorer(self): @@ -2572,8 +2584,8 @@ def _createPreviewWindow(self, config, source, line_num, jump_cmd): def getPreviewCommand(self, arguments_dict, source): return GitLogDiffCommand(arguments_dict, source) - def createGitCommand(self, arguments_dict, source): - return GitLogCommand(arguments_dict, source) + def createGitCommand(self, arguments_dict, commit_id): + return GitLogCommand(arguments_dict, commit_id) def _useExistingWindow(self, title, source, line_num, jump_cmd): if source is None: @@ -2655,17 +2667,17 @@ def _afterEnter(self): def _accept(self, file, mode, *args, **kwargs): super(GitExplManager, self)._accept(file, mode, *args, **kwargs) - def _createExplorerPage(self, source, target_path=None): - if source in self._pages: - vim.current.tabpage = self._pages[source].tabpage + def _createExplorerPage(self, commit_id, target_path=None): + if commit_id in self._pages: + vim.current.tabpage = self._pages[commit_id].tabpage else: lfCmd("augroup Lf_Git_Log | augroup END") lfCmd("autocmd! Lf_Git_Log TabClosed * call leaderf#Git#CleanupExplorerPage({})" .format(id(self))) - self._pages[source] = ExplorerPage(self._project_root, source, self) - self._pages[source].create(self._arguments, - GitLogExplCommand(self._arguments, source), + self._pages[commit_id] = ExplorerPage(self._project_root, commit_id, self) + self._pages[commit_id].create(self._arguments, + GitLogExplCommand(self._arguments, commit_id), target_path=target_path) def _acceptSelection(self, *args, **kwargs): @@ -2673,34 +2685,34 @@ def _acceptSelection(self, *args, **kwargs): return line = args[0] - source = self.getSource(line) - if source is None: + commit_id = self.getSource(line) + if commit_id is None: return if "--current-file" in self._arguments and "current_file" in self._arguments: if "--explorer" in self._arguments: - self._createExplorerPage(source, self._arguments["current_file"]) + self._createExplorerPage(commit_id, self._arguments["current_file"]) else: if self._diff_view_panel is None: self._diff_view_panel = DiffViewPanel(self.afterBufhidden) - self._diff_view_panel.setCommitId(source) - cmd = "git show --pretty= --no-color --raw {} -- {}".format(source, + self._diff_view_panel.setCommitId(commit_id) + cmd = "git show --pretty= --no-color --raw {} -- {}".format(commit_id, self._arguments["current_file"]) outputs = ParallelExecutor.run(cmd) if len(outputs[0]) > 0: _, source = TreeView.generateSource(outputs[0][0]) self._diff_view_panel.create(self._arguments, source, **kwargs) elif "--explorer" in self._arguments: - self._createExplorerPage(source) + self._createExplorerPage(commit_id) else: - if kwargs.get("mode", '') == 't' and source not in self._result_panel.getSources(): + if kwargs.get("mode", '') == 't' and commit_id not in self._result_panel.getSources(): self._arguments["mode"] = 't' lfCmd("tabnew") tabpage_count = len(vim.tabpages) - self._result_panel.create(self.createGitCommand(self._arguments, source), + self._result_panel.create(self.createGitCommand(self._arguments, commit_id), self._selected_content) if kwargs.get("mode", '') == 't' and len(vim.tabpages) > tabpage_count: @@ -2727,8 +2739,8 @@ def __init__(self): def createGitCommand(self, arguments_dict, commit_id): return GitBlameCommand(arguments_dict, commit_id) - def getPreviewCommand(self, arguments_dict, commit_id): - return GitLogDiffCommand(arguments_dict, commit_id) + def getPreviewCommand(self, arguments_dict, source): + return GitLogDiffCommand(arguments_dict, source) def defineMaps(self, winid): lfCmd("call win_execute({}, 'call leaderf#Git#BlameMaps({})')" From 4741d665a231f6e5b2512e9f09c0335c9acff21e Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Sat, 20 Apr 2024 11:32:20 +0800 Subject: [PATCH 188/365] add `abort` --- autoload/leaderf/Git.vim | 44 ++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/autoload/leaderf/Git.vim b/autoload/leaderf/Git.vim index ec897547..e9dfd2d3 100644 --- a/autoload/leaderf/Git.vim +++ b/autoload/leaderf/Git.vim @@ -13,7 +13,7 @@ endif exec g:Lf_py "from leaderf.gitExpl import *" -function! leaderf#Git#Maps(id) +function! leaderf#Git#Maps(id) abort nmapclear exec g:Lf_py "import ctypes" let manager = printf("ctypes.cast(%d, ctypes.py_object).value", a:id) @@ -42,7 +42,7 @@ endfunction " direction: " 0, backward " 1, forward -function! leaderf#Git#OuterIndent(direction) +function! leaderf#Git#OuterIndent(direction) abort let spaces = substitute(getline('.'), '^\(\s*\).*', '\1', '') let width = strdisplaywidth(spaces) if width == 0 @@ -59,7 +59,7 @@ endfunction " direction: " 0, backward " 1, forward -function! leaderf#Git#SameIndent(direction) +function! leaderf#Git#SameIndent(direction) abort let spaces = substitute(getline('.'), '^\(\s*\).*', '\1', '') let width = strdisplaywidth(spaces) if a:direction == 0 @@ -77,7 +77,7 @@ function! leaderf#Git#SameIndent(direction) call search(printf('^\s\{%d}\zs\S', width), flags, stopline) endfunction -function! leaderf#Git#SpecificMaps(id) +function! leaderf#Git#SpecificMaps(id) abort exec g:Lf_py "import ctypes" let manager = printf("ctypes.cast(%d, ctypes.py_object).value", a:id) exec printf('nnoremap e :exec g:Lf_py "%s.editCommand()"', manager) @@ -86,7 +86,7 @@ endfunction " direction: " 0, backward " 1, forward -function! leaderf#Git#OuterBlock(direction) +function! leaderf#Git#OuterBlock(direction) abort let column = col('.') if column >= match(getline('.'), '\S') + 1 noautocmd norm! ^ @@ -131,7 +131,7 @@ let s:help = { \ ], \} -function s:HelpFilter(winid, key) +function s:HelpFilter(winid, key) abort if a:key == "\" || a:key == "\" call popup_close(a:winid) return 1 @@ -142,7 +142,7 @@ function s:HelpFilter(winid, key) return 1 endfunction -function! s:GetRowCol(width, height) +function! s:GetRowCol(width, height) abort let win_width = &columns let win_height = &lines @@ -152,7 +152,7 @@ function! s:GetRowCol(width, height) return {'row': row, 'col': col} endfunction -function! leaderf#Git#ShowHelp(type) +function! leaderf#Git#ShowHelp(type) abort if has("nvim") let borderchars = [ \ [g:Lf_PopupBorders[4], "Lf_hl_popupBorder"], @@ -211,7 +211,7 @@ function! leaderf#Git#ShowHelp(type) endfunction -function! leaderf#Git#CloseCommitMessageWin() +function! leaderf#Git#CloseCommitMessageWin() abort if exists("b:blame_cursorline") && exists("*getmousepos") let pos = getmousepos() if pos.winid == b:blame_winid && b:blame_cursorline != pos["line"] @@ -222,7 +222,7 @@ function! leaderf#Git#CloseCommitMessageWin() endif endfunction -function s:CommitMessageFilter(winid, key) +function s:CommitMessageFilter(winid, key) abort if a:key == "\" call popup_close(a:winid) return 1 @@ -244,7 +244,7 @@ function s:CommitMessageFilter(winid, key) return 1 endfunction -function! leaderf#Git#ShowCommitMessage(message) +function! leaderf#Git#ShowCommitMessage(message) abort let b:blame_cursorline = line('.') let b:blame_winid = win_getid() if has("nvim") @@ -304,7 +304,7 @@ function! leaderf#Git#ShowCommitMessage(message) endif endfunction -function! leaderf#Git#TreeViewMaps(id) +function! leaderf#Git#TreeViewMaps(id) abort exec g:Lf_py "import ctypes" let tree_view = printf("ctypes.cast(%d, ctypes.py_object).value", a:id) exec printf('nnoremap X :exec g:Lf_py "%s.collapseChildren()"', tree_view) @@ -317,13 +317,13 @@ function! leaderf#Git#TreeViewMaps(id) nnoremap ) :call leaderf#Git#OuterBlock(1) endfunction -function! leaderf#Git#CollapseParent(explorer_page) +function! leaderf#Git#CollapseParent(explorer_page) abort if leaderf#Git#OuterIndent(0) != 0 exec g:Lf_py printf("%s.open(False)", a:explorer_page) endif endfunction -function! leaderf#Git#ExplorerMaps(id) +function! leaderf#Git#ExplorerMaps(id) abort exec g:Lf_py "import ctypes" let explorer_page = printf("ctypes.cast(%d, ctypes.py_object).value", a:id) exec printf('nnoremap o :exec g:Lf_py "%s.open(False)"', explorer_page) @@ -339,7 +339,7 @@ function! leaderf#Git#ExplorerMaps(id) nnoremap q :q endfunction -function! leaderf#Git#BlameMaps(id) +function! leaderf#Git#BlameMaps(id) abort exec g:Lf_py "import ctypes" let explorer_page = printf("ctypes.cast(%d, ctypes.py_object).value", a:id) exec printf('nnoremap o :exec g:Lf_py "%s.open()"', explorer_page) @@ -358,37 +358,37 @@ function! leaderf#Git#BlameMaps(id) nnoremap q :bwipe endfunction -function! leaderf#Git#TimerCallback(manager_id, id) +function! leaderf#Git#TimerCallback(manager_id, id) abort exec g:Lf_py "import ctypes" exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value._callback(bang=True)", a:manager_id) endfunction -function! leaderf#Git#WriteBuffer(view_id, id) +function! leaderf#Git#WriteBuffer(view_id, id) abort exec g:Lf_py "import ctypes" exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value.writeBuffer()", a:view_id) endfunction -function! leaderf#Git#Cleanup(owner_id, id) +function! leaderf#Git#Cleanup(owner_id, id) abort exec g:Lf_py "import ctypes" exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value.cleanup()", a:owner_id) endfunction -function! leaderf#Git#Suicide(view_id) +function! leaderf#Git#Suicide(view_id) abort exec g:Lf_py "import ctypes" exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value.suicide()", a:view_id) endfunction -function! leaderf#Git#Bufhidden(view_id) +function! leaderf#Git#Bufhidden(view_id) abort exec g:Lf_py "import ctypes" exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value.bufHidden()", a:view_id) endfunction -function! leaderf#Git#CleanupExplorerPage(view_id) +function! leaderf#Git#CleanupExplorerPage(view_id) abort exec g:Lf_py "import ctypes" exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value.cleanupExplorerPage()", a:view_id) endfunction -function! leaderf#Git#Commands() +function! leaderf#Git#Commands() abort if !exists("g:Lf_GitCommands") let g:Lf_GitCommands = [ \ {"Leaderf git diff": "fuzzy search and view the diffs"}, From db552a834ccc5308a244a3d8f375cd446c1eb230 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Sat, 20 Apr 2024 16:50:18 +0800 Subject: [PATCH 189/365] let `Leaderf git blame` support modified buffer --- autoload/leaderf/python/leaderf/bufTagExpl.py | 2 +- .../leaderf/python/leaderf/functionExpl.py | 2 +- autoload/leaderf/python/leaderf/gitExpl.py | 23 +++++++++++++++++-- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/autoload/leaderf/python/leaderf/bufTagExpl.py b/autoload/leaderf/python/leaderf/bufTagExpl.py index 3217fd6c..51df2ce1 100644 --- a/autoload/leaderf/python/leaderf/bufTagExpl.py +++ b/autoload/leaderf/python/leaderf/bufTagExpl.py @@ -108,7 +108,7 @@ def _getTagResult(self, buffer): tmp_file = tempfile.NamedTemporaryFile with tmp_file(mode='w+', suffix='_'+os.path.basename(buffer.name), delete=False) as f: - for line in buffer[:]: + for line in buffer: f.write(line + '\n') file_name = f.name # {tagname}{tagfile}{tagaddress}[;"{tagfield}..] diff --git a/autoload/leaderf/python/leaderf/functionExpl.py b/autoload/leaderf/python/leaderf/functionExpl.py index b93c019f..6b631dfe 100644 --- a/autoload/leaderf/python/leaderf/functionExpl.py +++ b/autoload/leaderf/python/leaderf/functionExpl.py @@ -127,7 +127,7 @@ def _getFunctionResult(self, buffer): tmp_file = tempfile.NamedTemporaryFile with tmp_file(mode='w+', suffix='_'+os.path.basename(buffer.name), delete=False) as f: - for line in buffer[:]: + for line in buffer: f.write(line + '\n') file_name = f.name # {tagname}{tagfile}{tagaddress};"{kind} diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index d2966a7e..8d86f901 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -8,6 +8,7 @@ import os.path import json import bisect +import tempfile from functools import partial from enum import Enum from collections import OrderedDict @@ -374,7 +375,7 @@ def __init__(self, arguments_dict, commit_id): super(GitBlameCommand, self).__init__(arguments_dict, commit_id) @staticmethod - def buildCommand(arguments_dict, commit_id, file_name): + def buildCommand(arguments_dict, commit_id, file_name, use_contents=False): extra_options = "" if "-w" in arguments_dict: extra_options += " -w" @@ -382,6 +383,9 @@ def buildCommand(arguments_dict, commit_id, file_name): if "--date" in arguments_dict: extra_options += " --date={}".format(arguments_dict["--date"][0]) + if use_contents and "--contents" in arguments_dict: + extra_options += " --contents {}".format(arguments_dict["--contents"][0]) + return "git blame -f -n {} {} -- {}".format(extra_options, commit_id, file_name) def buildCommandAndBufferName(self): @@ -394,7 +398,7 @@ def buildCommandAndBufferName(self): file_name = file_name.replace(' ', r'\ ') file_name = lfRelpath(file_name) - self._cmd = GitBlameCommand.buildCommand(self._arguments, commit_id, file_name) + self._cmd = GitBlameCommand.buildCommand(self._arguments, commit_id, file_name, True) self._buffer_name = "LeaderF://git blame {} {}".format(commit_id, file_name) self._file_type = "" self._file_type_cmd = "" @@ -2947,7 +2951,22 @@ def startExplorer(self, win_pos, *args, **kwargs): lfPrintError("fatal: '{}' is outside repository at '{}'" .format(lfRelpath(vim.current.buffer.name), self._project_root)) else: + tmp_file_name = None + if vim.current.buffer.options["modified"]: + if sys.version_info >= (3, 0): + tmp_file = partial(tempfile.NamedTemporaryFile, encoding=lfEval("&encoding")) + else: + tmp_file = tempfile.NamedTemporaryFile + + with tmp_file(mode='w+', delete=False) as f: + for line in vim.current.buffer: + f.write(line + '\n') + tmp_file_name = f.name + self._arguments["--contents"] = [tmp_file_name] + self._blame_panel.create(arguments_dict, self.createGitCommand(self._arguments, None)) + if tmp_file_name is not None: + os.remove(tmp_file_name) else: lfPrintError("fatal: no such path '{}' in HEAD".format(vim.current.buffer.name)) From d4eded0ab36ba60aa7e13893a2064a74d2cdb6bd Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Sat, 20 Apr 2024 21:19:14 +0800 Subject: [PATCH 190/365] add support for And mode and refine mode to `Leaderf rg` --- autoload/leaderf/colorscheme.vim | 2 ++ autoload/leaderf/colorscheme/popup.vim | 2 ++ autoload/leaderf/python/leaderf/gitExpl.py | 4 ---- autoload/leaderf/python/leaderf/manager.py | 9 ++++++--- autoload/leaderf/python/leaderf/rgExpl.py | 20 ++++++++++++++++---- 5 files changed, 26 insertions(+), 11 deletions(-) diff --git a/autoload/leaderf/colorscheme.vim b/autoload/leaderf/colorscheme.vim index bc33f90d..aab01aea 100644 --- a/autoload/leaderf/colorscheme.vim +++ b/autoload/leaderf/colorscheme.vim @@ -14,6 +14,8 @@ endfunction let s:modeMap = { \ 'NameOnly': 'Lf_hl_stlNameOnlyMode', \ 'FullPath': 'Lf_hl_stlFullPathMode', + \ 'Contents': 'Lf_hl_stlNameOnlyMode', + \ 'WholeLine': 'Lf_hl_stlFullPathMode', \ 'Fuzzy': 'Lf_hl_stlFuzzyMode', \ 'Regex': 'Lf_hl_stlRegexMode', \ 'Live': 'Lf_hl_stlFuzzyMode' diff --git a/autoload/leaderf/colorscheme/popup.vim b/autoload/leaderf/colorscheme/popup.vim index 4b4e9515..17b865d7 100644 --- a/autoload/leaderf/colorscheme/popup.vim +++ b/autoload/leaderf/colorscheme/popup.vim @@ -10,6 +10,8 @@ let s:matchModeMap = { \ 'NameOnly': 'Lf_hl_popup_nameOnlyMode', \ 'FullPath': 'Lf_hl_popup_fullPathMode', + \ 'Contents': 'Lf_hl_popup_nameOnlyMode', + \ 'WholeLine': 'Lf_hl_popup_fullPathMode', \ 'Fuzzy': 'Lf_hl_popup_fuzzyMode', \ 'Regex': 'Lf_hl_popup_regexMode', \ 'Live': 'Lf_hl_popup_fuzzyMode' diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 8d86f901..4763095d 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -34,7 +34,6 @@ def lfGetFilePath(source): class GitExplorer(Explorer): def __init__(self): self._executor = [] - self._display_multi = False self._show_icon = lfEval("get(g:, 'Lf_ShowDevIcons', 1)") == "1" def getContent(self, *args, **kwargs): @@ -64,9 +63,6 @@ def getPatternRegex(self): def getContextSeparator(self): return self._context_separator - def displayMulti(self): - return self._display_multi - class GitDiffExplorer(GitExplorer): def __init__(self): diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 504e061d..81dfccdc 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -279,9 +279,12 @@ def _setStlMode(self, the_mode=None, **kwargs): elif self._cli._is_live: mode = 'Fuzzy' - self._getInstance().setStlMode(mode) + self.setStlMode(mode) self._cli.setCurrentMode(mode) + def setStlMode(self, mode): + self._getInstance().setStlMode(mode) + def _beforeEnter(self): self._resetAutochdir() self._cur_buffer = vim.current.buffer @@ -1746,7 +1749,7 @@ def _fuzzySearch(self, content, is_continue, step): pattern=pattern, is_name_only=True, sort_results=do_sort) getHighlights = partial(fuzzyEngine.getHighlights, engine=self._fuzzy_engine, pattern=pattern, is_name_only=True) - highlight_method = partial(self._highlight, True, getHighlights, True) + highlight_method = partial(self._highlight, False, getHighlights, True) elif is_fuzzyMatch_C and isAscii(self._cli.pattern[0]): use_fuzzy_match_c = True pattern = fuzzyMatchC.initPattern(self._cli.pattern[0]) @@ -1838,7 +1841,7 @@ def _fuzzySearch(self, content, is_continue, step): is_name_only=True, sort_results=do_sort) elif self._getExplorer().getStlCategory() == "Rg": return_index = False - if "--match-path" in self._arguments: + if self._cli.isFullPath or "--match-path" in self._arguments: filter_method = partial(fuzzyEngine.fuzzyMatch, engine=self._fuzzy_engine, pattern=pattern, is_name_only=True, sort_results=do_sort) else: diff --git a/autoload/leaderf/python/leaderf/rgExpl.py b/autoload/leaderf/python/leaderf/rgExpl.py index 83669f83..86d96f7d 100644 --- a/autoload/leaderf/python/leaderf/rgExpl.py +++ b/autoload/leaderf/python/leaderf/rgExpl.py @@ -502,7 +502,7 @@ def getStlCurDir(self): return escQuote(lfEncode(self._cmd_work_dir)) def supportsNameOnly(self): - return False + return True def cleanup(self): for exe in self._executor: @@ -539,6 +539,13 @@ def _getExplClass(self): def _defineMaps(self): lfCmd("call leaderf#Rg#Maps(%d)" % int("--heading" in self._arguments)) + def setStlMode(self, mode): + if mode == "FullPath": + mode = "WholeLine" + elif mode == "NameOnly": + mode = "Contents" + super(RgExplManager, self).setStlMode(mode) + def _getFileInfo(self, args): line = args[0] @@ -700,9 +707,12 @@ def _getDigest(self, line, mode): 1, return the name only 2, return the directory name """ - if self._match_path: + if mode == 0 or self._match_path: return line - else: + elif mode == 1: + if mode == 0: + return line + if self._getExplorer().displayMulti(): if line == self._getExplorer().getContextSeparator(): return "" @@ -723,6 +733,8 @@ def _getDigest(self, line, mode): return line.split(":", 3)[-1] else: return line.split(":", 2)[-1] + else: + return line.split(":", 1)[0] def _getDigestStartPos(self, line, mode): """ @@ -732,7 +744,7 @@ def _getDigestStartPos(self, line, mode): 1, return the start postion of name only 2, return the start postion of directory name """ - if self._match_path: + if mode == 0 or mode == 2 or self._match_path: return 0 else: if self._getExplorer().displayMulti(): From 0d5277025e37eb623490c07f1a73fd5a5783c477 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Mon, 22 Apr 2024 00:01:41 +0800 Subject: [PATCH 191/365] if a file was renamed, 'Leaderf git log --current-file' can not open the diff --- .../leaderf/python/leaderf/asyncExecutor.py | 2 +- autoload/leaderf/python/leaderf/gitExpl.py | 47 +++++++++++++++---- 2 files changed, 38 insertions(+), 11 deletions(-) diff --git a/autoload/leaderf/python/leaderf/asyncExecutor.py b/autoload/leaderf/python/leaderf/asyncExecutor.py index eca42c9b..3f6acaf4 100644 --- a/autoload/leaderf/python/leaderf/asyncExecutor.py +++ b/autoload/leaderf/python/leaderf/asyncExecutor.py @@ -103,7 +103,7 @@ def read(source): err = b"".join(iter(self._errQueue.get, None)) if err and raise_except: - raise Exception(lfBytes2Str(err) + lfBytes2Str(err, encoding)) + raise Exception(cmd + "\n" + lfBytes2Str(err) + lfBytes2Str(err, encoding)) except ValueError: pass finally: diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 4763095d..55a31bfd 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -127,7 +127,7 @@ def getContent(self, *args, **kwargs): options = GitLogExplorer.generateOptions(arguments_dict) cmd = 'git log {} --pretty=format:"%h%d %s"'.format(options) if "--current-file" in arguments_dict and "current_file" in arguments_dict: - cmd += " -- {}".format(arguments_dict["current_file"]) + cmd += " --follow -- {}".format(arguments_dict["current_file"]) if "extra" in arguments_dict: cmd += " " + " ".join(arguments_dict["extra"]) @@ -307,7 +307,7 @@ def buildCommandAndBufferName(self): self._cmd += " " + " ".join(self._arguments["extra"]) if "--current-file" in self._arguments and "current_file" in self._arguments: - self._cmd += " -- {}".format(self._arguments["current_file"]) + self._cmd += " --follow -- {}".format(self._arguments["current_file"]) self._buffer_name = "LeaderF://" + self._cmd else: @@ -2677,8 +2677,37 @@ def _createExplorerPage(self, commit_id, target_path=None): self._pages[commit_id] = ExplorerPage(self._project_root, commit_id, self) self._pages[commit_id].create(self._arguments, - GitLogExplCommand(self._arguments, commit_id), - target_path=target_path) + GitLogExplCommand(self._arguments, commit_id), + target_path=target_path) + + def getOriginalName(self, commit_id, file_name): + cmd = 'git log --pretty="%H" --name-status --follow HEAD -- {}'.format(file_name) + # output is as below: + + # a7cdd68e0f9e891e6f5def7b2b657d07d92a3675 + # + # R064 tui.py src/tui.py + # 5a0cd5103deba164a6fb33a5a3f67fb3a5dcf378 + # + # M tui.py + outputs = ParallelExecutor.run(cmd) + for i, line in enumerate(outputs[0]): + if line.startswith(commit_id): + name_stat = outputs[0][i+2] + orig_name = name_stat.split()[1] + return orig_name + + return file_name + + def createDiffViewPanel(self, commit_id, file_name, **kwargs): + cmd = "git show --pretty= --no-color --raw {} -- {}".format(commit_id, file_name) + outputs = ParallelExecutor.run(cmd) + if len(outputs[0]) > 0: + _, source = TreeView.generateSource(outputs[0][0]) + self._diff_view_panel.create(self._arguments, source, **kwargs) + return True + else: + return False def _acceptSelection(self, *args, **kwargs): if len(args) == 0: @@ -2697,12 +2726,10 @@ def _acceptSelection(self, *args, **kwargs): self._diff_view_panel = DiffViewPanel(self.afterBufhidden) self._diff_view_panel.setCommitId(commit_id) - cmd = "git show --pretty= --no-color --raw {} -- {}".format(commit_id, - self._arguments["current_file"]) - outputs = ParallelExecutor.run(cmd) - if len(outputs[0]) > 0: - _, source = TreeView.generateSource(outputs[0][0]) - self._diff_view_panel.create(self._arguments, source, **kwargs) + file_name = self._arguments["current_file"] + status = self.createDiffViewPanel(commit_id, file_name, **kwargs) + if status == False: + self.createDiffViewPanel(commit_id, self.getOriginalName(commit_id, file_name), **kwargs) elif "--explorer" in self._arguments: self._createExplorerPage(commit_id) else: From 32a94c5cfd7b605a28b62c7bd89ff526ed2c55e4 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Mon, 22 Apr 2024 17:14:27 +0800 Subject: [PATCH 192/365] if a file was renamed, 'Leaderf git log --current-file --explorer' can not open the diff --- autoload/leaderf/python/leaderf/gitExpl.py | 45 ++++++++++++---------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 55a31bfd..ddd3d459 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -28,6 +28,24 @@ def lfGetFilePath(source): """ return source[3] if source[4] == "" else source[4] +def getOriginalName(commit_id, file_name): + cmd = 'git log --pretty=format:%H --name-status --follow HEAD -- {}'.format(file_name) + # output is as below: + + # a7cdd68e0f9e891e6f5def7b2b657d07d92a3675 + # R064 tui.py src/tui.py + # + # 5a0cd5103deba164a6fb33a5a3f67fb3a5dcf378 + # M tui.py + outputs = ParallelExecutor.run(cmd) + for i in range(0, len(outputs[0]), 3): + if outputs[0][i].startswith(commit_id): + name_stat = outputs[0][i+1] + orig_name = name_stat.split()[1] + return orig_name + + return file_name + #***************************************************** # GitExplorer #***************************************************** @@ -2680,25 +2698,6 @@ def _createExplorerPage(self, commit_id, target_path=None): GitLogExplCommand(self._arguments, commit_id), target_path=target_path) - def getOriginalName(self, commit_id, file_name): - cmd = 'git log --pretty="%H" --name-status --follow HEAD -- {}'.format(file_name) - # output is as below: - - # a7cdd68e0f9e891e6f5def7b2b657d07d92a3675 - # - # R064 tui.py src/tui.py - # 5a0cd5103deba164a6fb33a5a3f67fb3a5dcf378 - # - # M tui.py - outputs = ParallelExecutor.run(cmd) - for i, line in enumerate(outputs[0]): - if line.startswith(commit_id): - name_stat = outputs[0][i+2] - orig_name = name_stat.split()[1] - return orig_name - - return file_name - def createDiffViewPanel(self, commit_id, file_name, **kwargs): cmd = "git show --pretty= --no-color --raw {} -- {}".format(commit_id, file_name) outputs = ParallelExecutor.run(cmd) @@ -2720,7 +2719,9 @@ def _acceptSelection(self, *args, **kwargs): if "--current-file" in self._arguments and "current_file" in self._arguments: if "--explorer" in self._arguments: - self._createExplorerPage(commit_id, self._arguments["current_file"]) + file_name = self._arguments["current_file"] + # if the file was renamed, we should use the corresponding file name in commit_id + self._createExplorerPage(commit_id, getOriginalName(commit_id, file_name)) else: if self._diff_view_panel is None: self._diff_view_panel = DiffViewPanel(self.afterBufhidden) @@ -2729,7 +2730,9 @@ def _acceptSelection(self, *args, **kwargs): file_name = self._arguments["current_file"] status = self.createDiffViewPanel(commit_id, file_name, **kwargs) if status == False: - self.createDiffViewPanel(commit_id, self.getOriginalName(commit_id, file_name), **kwargs) + self.createDiffViewPanel(commit_id, + getOriginalName(commit_id, file_name), + **kwargs) elif "--explorer" in self._arguments: self._createExplorerPage(commit_id) else: From 71b114889874ee3890979250c9d5bce601d9dc08 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Mon, 22 Apr 2024 21:09:44 +0800 Subject: [PATCH 193/365] use getOriginalName() when necessary --- autoload/leaderf/python/leaderf/gitExpl.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index ddd3d459..5c4e6d2d 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -908,6 +908,7 @@ def __init__(self, owner, cmd, project_root, target_path, callback): super(TreeView, self).__init__(owner, cmd) self._project_root = project_root self._target_path = target_path + self._target_path_found = False # the argument is source, source is a tuple like # (b90f76fc1, bad07e644, R099, src/version.c, src/version2.c) self._callback = callback @@ -1512,6 +1513,8 @@ def writeBuffer(self): source = info.info if source is not None: + self._target_path_found = True + self._callback(source) if lfEval("has('nvim')") == '1': lfCmd("call nvim_win_set_option({}, 'cursorline', v:true)".format(self.getWindowId())) @@ -1528,6 +1531,11 @@ def writeBuffer(self): self._buffer.options['modifiable'] = False if self._read_finished == 1 and self._offset_in_content == len(structure): + if self._target_path is not None and self._target_path_found == False: + self.locateFile(getOriginalName(self._cmd.getSource(), self._target_path)) + structure = self._file_structures[self._cur_parent] + self._callback(structure[vim.current.window.cursor[0] - len(self._head) - 1].info) + shortstat = re.sub(r"( \d+)( files? changed)", r"%#Lf_hl_gitStlChangedNum#\1%#Lf_hl_gitStlFileChanged#\2", self._short_stat[self._cur_parent]) @@ -2720,8 +2728,7 @@ def _acceptSelection(self, *args, **kwargs): if "--current-file" in self._arguments and "current_file" in self._arguments: if "--explorer" in self._arguments: file_name = self._arguments["current_file"] - # if the file was renamed, we should use the corresponding file name in commit_id - self._createExplorerPage(commit_id, getOriginalName(commit_id, file_name)) + self._createExplorerPage(commit_id, file_name) else: if self._diff_view_panel is None: self._diff_view_panel = DiffViewPanel(self.afterBufhidden) From 8ab8687e80c5f41711aa7f69166ccf0d29aefb46 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Tue, 23 Apr 2024 14:18:31 +0800 Subject: [PATCH 194/365] revert to d4eded0 --- .../leaderf/python/leaderf/asyncExecutor.py | 2 +- autoload/leaderf/python/leaderf/gitExpl.py | 59 ++++--------------- 2 files changed, 12 insertions(+), 49 deletions(-) diff --git a/autoload/leaderf/python/leaderf/asyncExecutor.py b/autoload/leaderf/python/leaderf/asyncExecutor.py index 3f6acaf4..eca42c9b 100644 --- a/autoload/leaderf/python/leaderf/asyncExecutor.py +++ b/autoload/leaderf/python/leaderf/asyncExecutor.py @@ -103,7 +103,7 @@ def read(source): err = b"".join(iter(self._errQueue.get, None)) if err and raise_except: - raise Exception(cmd + "\n" + lfBytes2Str(err) + lfBytes2Str(err, encoding)) + raise Exception(lfBytes2Str(err) + lfBytes2Str(err, encoding)) except ValueError: pass finally: diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 5c4e6d2d..4763095d 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -28,24 +28,6 @@ def lfGetFilePath(source): """ return source[3] if source[4] == "" else source[4] -def getOriginalName(commit_id, file_name): - cmd = 'git log --pretty=format:%H --name-status --follow HEAD -- {}'.format(file_name) - # output is as below: - - # a7cdd68e0f9e891e6f5def7b2b657d07d92a3675 - # R064 tui.py src/tui.py - # - # 5a0cd5103deba164a6fb33a5a3f67fb3a5dcf378 - # M tui.py - outputs = ParallelExecutor.run(cmd) - for i in range(0, len(outputs[0]), 3): - if outputs[0][i].startswith(commit_id): - name_stat = outputs[0][i+1] - orig_name = name_stat.split()[1] - return orig_name - - return file_name - #***************************************************** # GitExplorer #***************************************************** @@ -145,7 +127,7 @@ def getContent(self, *args, **kwargs): options = GitLogExplorer.generateOptions(arguments_dict) cmd = 'git log {} --pretty=format:"%h%d %s"'.format(options) if "--current-file" in arguments_dict and "current_file" in arguments_dict: - cmd += " --follow -- {}".format(arguments_dict["current_file"]) + cmd += " -- {}".format(arguments_dict["current_file"]) if "extra" in arguments_dict: cmd += " " + " ".join(arguments_dict["extra"]) @@ -325,7 +307,7 @@ def buildCommandAndBufferName(self): self._cmd += " " + " ".join(self._arguments["extra"]) if "--current-file" in self._arguments and "current_file" in self._arguments: - self._cmd += " --follow -- {}".format(self._arguments["current_file"]) + self._cmd += " -- {}".format(self._arguments["current_file"]) self._buffer_name = "LeaderF://" + self._cmd else: @@ -908,7 +890,6 @@ def __init__(self, owner, cmd, project_root, target_path, callback): super(TreeView, self).__init__(owner, cmd) self._project_root = project_root self._target_path = target_path - self._target_path_found = False # the argument is source, source is a tuple like # (b90f76fc1, bad07e644, R099, src/version.c, src/version2.c) self._callback = callback @@ -1513,8 +1494,6 @@ def writeBuffer(self): source = info.info if source is not None: - self._target_path_found = True - self._callback(source) if lfEval("has('nvim')") == '1': lfCmd("call nvim_win_set_option({}, 'cursorline', v:true)".format(self.getWindowId())) @@ -1531,11 +1510,6 @@ def writeBuffer(self): self._buffer.options['modifiable'] = False if self._read_finished == 1 and self._offset_in_content == len(structure): - if self._target_path is not None and self._target_path_found == False: - self.locateFile(getOriginalName(self._cmd.getSource(), self._target_path)) - structure = self._file_structures[self._cur_parent] - self._callback(structure[vim.current.window.cursor[0] - len(self._head) - 1].info) - shortstat = re.sub(r"( \d+)( files? changed)", r"%#Lf_hl_gitStlChangedNum#\1%#Lf_hl_gitStlFileChanged#\2", self._short_stat[self._cur_parent]) @@ -2703,18 +2677,8 @@ def _createExplorerPage(self, commit_id, target_path=None): self._pages[commit_id] = ExplorerPage(self._project_root, commit_id, self) self._pages[commit_id].create(self._arguments, - GitLogExplCommand(self._arguments, commit_id), - target_path=target_path) - - def createDiffViewPanel(self, commit_id, file_name, **kwargs): - cmd = "git show --pretty= --no-color --raw {} -- {}".format(commit_id, file_name) - outputs = ParallelExecutor.run(cmd) - if len(outputs[0]) > 0: - _, source = TreeView.generateSource(outputs[0][0]) - self._diff_view_panel.create(self._arguments, source, **kwargs) - return True - else: - return False + GitLogExplCommand(self._arguments, commit_id), + target_path=target_path) def _acceptSelection(self, *args, **kwargs): if len(args) == 0: @@ -2727,19 +2691,18 @@ def _acceptSelection(self, *args, **kwargs): if "--current-file" in self._arguments and "current_file" in self._arguments: if "--explorer" in self._arguments: - file_name = self._arguments["current_file"] - self._createExplorerPage(commit_id, file_name) + self._createExplorerPage(commit_id, self._arguments["current_file"]) else: if self._diff_view_panel is None: self._diff_view_panel = DiffViewPanel(self.afterBufhidden) self._diff_view_panel.setCommitId(commit_id) - file_name = self._arguments["current_file"] - status = self.createDiffViewPanel(commit_id, file_name, **kwargs) - if status == False: - self.createDiffViewPanel(commit_id, - getOriginalName(commit_id, file_name), - **kwargs) + cmd = "git show --pretty= --no-color --raw {} -- {}".format(commit_id, + self._arguments["current_file"]) + outputs = ParallelExecutor.run(cmd) + if len(outputs[0]) > 0: + _, source = TreeView.generateSource(outputs[0][0]) + self._diff_view_panel.create(self._arguments, source, **kwargs) elif "--explorer" in self._arguments: self._createExplorerPage(commit_id) else: From 530a8e4f95dd8a68196e54a6b2fdbf09383d14ce Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Tue, 23 Apr 2024 14:12:31 +0800 Subject: [PATCH 195/365] if a file was renamed, 'Leaderf git log --current-file --explorer' can not open the diff 'Leaderf git log --current-file' can not open the diff --- .../leaderf/python/leaderf/asyncExecutor.py | 2 +- autoload/leaderf/python/leaderf/gitExpl.py | 39 +++++++++++++------ 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/autoload/leaderf/python/leaderf/asyncExecutor.py b/autoload/leaderf/python/leaderf/asyncExecutor.py index eca42c9b..3f6acaf4 100644 --- a/autoload/leaderf/python/leaderf/asyncExecutor.py +++ b/autoload/leaderf/python/leaderf/asyncExecutor.py @@ -103,7 +103,7 @@ def read(source): err = b"".join(iter(self._errQueue.get, None)) if err and raise_except: - raise Exception(lfBytes2Str(err) + lfBytes2Str(err, encoding)) + raise Exception(cmd + "\n" + lfBytes2Str(err) + lfBytes2Str(err, encoding)) except ValueError: pass finally: diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 4763095d..ca0aeae5 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -118,7 +118,19 @@ def getSourceInfo(self): class GitLogExplorer(GitExplorer): + def __init__(self): + super(GitLogExplorer, self).__init__() + self.orig_name = {} + + def generateContent(self, content): + for line1, line2, _ in itertools.zip_longest(content, content, content): + commit_id = line1.split(None, 1)[0] + self.orig_name[commit_id] = line2 + yield line1 + def getContent(self, *args, **kwargs): + self.orig_name.clear() + arguments_dict = kwargs.get("arguments", {}) executor = AsyncExecutor() @@ -127,15 +139,16 @@ def getContent(self, *args, **kwargs): options = GitLogExplorer.generateOptions(arguments_dict) cmd = 'git log {} --pretty=format:"%h%d %s"'.format(options) if "--current-file" in arguments_dict and "current_file" in arguments_dict: - cmd += " -- {}".format(arguments_dict["current_file"]) + cmd += " --name-only --follow -- {}".format(arguments_dict["current_file"]) if "extra" in arguments_dict: cmd += " " + " ".join(arguments_dict["extra"]) - content = executor.execute(cmd, encoding=lfEval("&encoding"), format_line=self.formatLine) - return content + content = executor.execute(cmd, encoding=lfEval("&encoding")) - def formatLine(self, line): - return line + if "--current-file" in arguments_dict and "current_file" in arguments_dict: + return self.generateContent(content) + + return content def getStlCategory(self): return 'Git_log' @@ -307,7 +320,7 @@ def buildCommandAndBufferName(self): self._cmd += " " + " ".join(self._arguments["extra"]) if "--current-file" in self._arguments and "current_file" in self._arguments: - self._cmd += " -- {}".format(self._arguments["current_file"]) + self._cmd += " --follow -- {}".format(self._arguments["current_file"]) self._buffer_name = "LeaderF://" + self._cmd else: @@ -324,7 +337,8 @@ def buildCommandAndBufferName(self): ' %cd{}%n%n%s%n%n%b%n%x2d%x2d%x2d" --stat=70 --stat-graph-width=10 --no-color' ' && git show {} --pretty=format:"%x20" --no-color -- {}' ).format(self._source, sep, self._source, - self._arguments["current_file"]) + self._arguments["orig_name"].get(self._source, + self._arguments["current_file"])) self._buffer_name = "LeaderF://" + self._source @@ -2614,6 +2628,7 @@ def startExplorer(self, win_pos, *args, **kwargs): if " " in file_name: file_name = file_name.replace(' ', r'\ ') self._arguments["current_file"] = lfRelpath(file_name) + self._arguments["orig_name"] = self._getExplorer().orig_name if "--recall" in arguments_dict: super(GitExplManager, self).startExplorer(win_pos, *args, **kwargs) @@ -2677,8 +2692,8 @@ def _createExplorerPage(self, commit_id, target_path=None): self._pages[commit_id] = ExplorerPage(self._project_root, commit_id, self) self._pages[commit_id].create(self._arguments, - GitLogExplCommand(self._arguments, commit_id), - target_path=target_path) + GitLogExplCommand(self._arguments, commit_id), + target_path=target_path) def _acceptSelection(self, *args, **kwargs): if len(args) == 0: @@ -2690,15 +2705,15 @@ def _acceptSelection(self, *args, **kwargs): return if "--current-file" in self._arguments and "current_file" in self._arguments: + file_name = self._getExplorer().orig_name[commit_id] if "--explorer" in self._arguments: - self._createExplorerPage(commit_id, self._arguments["current_file"]) + self._createExplorerPage(commit_id, file_name) else: if self._diff_view_panel is None: self._diff_view_panel = DiffViewPanel(self.afterBufhidden) self._diff_view_panel.setCommitId(commit_id) - cmd = "git show --pretty= --no-color --raw {} -- {}".format(commit_id, - self._arguments["current_file"]) + cmd = "git show --pretty= --no-color --raw {} -- {}".format(commit_id, file_name) outputs = ParallelExecutor.run(cmd) if len(outputs[0]) > 0: _, source = TreeView.generateSource(outputs[0][0]) From 4c1ec236c295eedc6872430c70f08e0d683da79d Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Tue, 23 Apr 2024 14:55:33 +0800 Subject: [PATCH 196/365] return AsyncExecutor.Result --- autoload/leaderf/python/leaderf/gitExpl.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index ca0aeae5..d55c9028 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -146,7 +146,7 @@ def getContent(self, *args, **kwargs): content = executor.execute(cmd, encoding=lfEval("&encoding")) if "--current-file" in arguments_dict and "current_file" in arguments_dict: - return self.generateContent(content) + return AsyncExecutor.Result(self.generateContent(content)) return content From 62015cfc6e01fbeb3b1270273435b5ea27411b2c Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Tue, 23 Apr 2024 15:12:27 +0800 Subject: [PATCH 197/365] fix issue "E28: No such highlight group name: Lf_hl_gitBlameDate" --- autoload/leaderf/python/leaderf/gitExpl.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index d55c9028..15526812 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -759,6 +759,10 @@ def enableColor(self, winid): id = int(lfEval("matchid")) self._match_ids.append(id) + if lfEval("hlexists('Lf_hl_gitBlameDate')") == '0': + lfCmd("call leaderf#colorscheme#popup#load('{}', '{}')" + .format("git", lfEval("get(g:, 'Lf_PopupColorscheme', 'default')"))) + arguments_dict = self._cmd.getArguments() date_format = arguments_dict.get("--date", [""])[0] if date_format in ["", "iso", "short"]: @@ -944,8 +948,8 @@ def __init__(self, owner, cmd, project_root, target_path, callback): def enableColor(self, winid): if lfEval("hlexists('Lf_hl_help')") == '0': - lfCmd("call leaderf#colorscheme#popup#load('{}', '{}')".format("git", - lfEval("get(g:, 'Lf_PopupColorscheme', 'default')"))) + lfCmd("call leaderf#colorscheme#popup#load('{}', '{}')" + .format("git", lfEval("get(g:, 'Lf_PopupColorscheme', 'default')"))) lfCmd(r"""call win_execute({}, 'let matchid = matchadd(''Lf_hl_gitHelp'', ''^".*'', -100)')""" .format(winid)) From 5bbe62f118f11351e0fbafc7619e3b3744fd265c Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Tue, 23 Apr 2024 16:11:35 +0800 Subject: [PATCH 198/365] enhance the regex of git blame --date --- autoload/leaderf/python/leaderf/gitExpl.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 15526812..7fa46ad9 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -1934,30 +1934,30 @@ def formatLine(arguments_dict, line_num_width, line): date_format = arguments_dict.get("--date", [""])[0] if date_format in ["", "iso", "iso-strict", "short"]: # 6817817e autoload/leaderf/manager.py 1 (Yggdroot 2014-02-26 00:37:26 +0800 1) #!/usr/bin/env python - return re.sub(r'(^\^?\w+)\s+(.*?)\s+(\d+)\s+(\([^(]*?)\s+\d+\).*', + return re.sub(r'(^\^?\w+)\s+(.*?)\s+(\d+)\s+(\(.*?\d\d)\s+\d+\).*', r'\g<1> \g<4>)\t\g<3> \g<2>', line, 1) elif date_format == "relative": # c5c6d072 autoload/leaderf/python/leaderf/manager.py 63 (Yggdroot 4 years, 6 months ago 66) def catchException(func): - line = re.sub(r'(^.*?\d+\)).*', r'\g<1>', line, 1) + line = re.sub(r'(^.*?\s\d+\)).*', r'\g<1>', line, 1) return re.sub(r'(^\^?\w+)\s+(.*?)\s+(\d+)\s+(\(.*)', r'\g<1> \g<4>)\t\g<3> \g<2>', line[:-(line_num_width + 1)], 1) elif date_format == "local": # 6817817e autoload/leaderf/manager.py 1 (Yggdroot Wed Feb 26 00:37:26 2014 1) #!/usr/bin/env python - line = re.sub(r'(^.*?\d+\)).*', r'\g<1>', line, 1) + line = re.sub(r'(^.*?\s\d+\)).*', r'\g<1>', line, 1) return re.sub(r'(^\^?\w+)\s+(.*?)\s+(\d+)\s+(\(.*)', r'\g<1> \g<4>)\t\g<3> \g<2>', line[:-(line_num_width + 7)], 1) elif date_format in ("rfc", "default"): # 6817817e autoload/leaderf/manager.py 1 (Yggdroot Wed, 26 Feb 2014 00:37:26 +0800 1) #!/usr/bin/env python # 6817817e autoload/leaderf/manager.py 1 (Yggdroot Wed Feb 26 00:37:26 2014 +0800 1) #!/usr/bin/env python - line = re.sub(r'(^.*?\d+\)).*', r'\g<1>', line, 1) + line = re.sub(r'(^.*?\s\d+\)).*', r'\g<1>', line, 1) return re.sub(r'(^\^?\w+)\s+(.*?)\s+(\d+)\s+(\(.*)', r'\g<1> \g<4>)\t\g<3> \g<2>', line[:-(line_num_width + 1)], 1) elif date_format == "human": # 6817817e autoload/leaderf/manager.py 1 (Yggdroot Feb 26 2014 1) #!/usr/bin/env python - line = re.sub(r'(^.*?\d+\)).*', r'\g<1>', line, 1) + line = re.sub(r'(^.*?\s\d+\)).*', r'\g<1>', line, 1) return re.sub(r'(^\^?\w+)\s+(.*?)\s+(\d+)\s+(\(.*)', r'\g<1> \g<4>)\t\g<3> \g<2>', line[:-(line_num_width + 6)], 1) From 974393c33860a2499107263b26c6671f24db5ce1 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Tue, 23 Apr 2024 23:48:22 +0800 Subject: [PATCH 199/365] add support for "--find-copies-harder" --- autoload/leaderf/Any.vim | 1 + autoload/leaderf/python/leaderf/gitExpl.py | 24 +++++++++++++++------- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/autoload/leaderf/Any.vim b/autoload/leaderf/Any.vim index c5de0ebe..85a1c6a6 100644 --- a/autoload/leaderf/Any.vim +++ b/autoload/leaderf/Any.vim @@ -236,6 +236,7 @@ let g:Lf_Arguments = { \ {"name": ["--all"], "nargs": 0, "help": "Pretend as if all the refs in refs/, along with HEAD, are listed on the command line as ."}, \ {"name": ["--graph"], "nargs": 0, "help": "Draw a text-based graphical representation of the commit history on the left hand side of the output."}, \ {"name": ["--reverse-order"], "nargs": 0, "help": "Output the commits chosen to be shown in reverse order."}, + \ {"name": ["--find-copies-harder"], "nargs": 0, "help": "This flag makes the command inspect unmodified files as candidates for the source of copy."}, \ {"name": ["extra"], "nargs": "*", "help": "extra arguments of git log"}, \ ], \ "diff": [ diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 7fa46ad9..52bba22f 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -325,18 +325,23 @@ def buildCommandAndBufferName(self): self._buffer_name = "LeaderF://" + self._cmd else: sep = ' ' if os.name == 'nt' else '' - self._cmd = ('git show {} --pretty=format:"commit %H%nparent %P%n' + if "--find-copies-harder" in self._arguments: + find_copies_harder = " -C" + else: + find_copies_harder = "" + + self._cmd = ('git show {} -C{} --pretty=format:"commit %H%nparent %P%n' 'Author: %an <%ae>%nAuthorDate: %ad%nCommitter: %cn <%ce>%nCommitDate:' ' %cd{}%n%n%s%n%n%b%n" --stat=70 --stat-graph-width=10 -p --no-color' - ).format(self._source, sep) + ).format(self._source, find_copies_harder, sep) if (("--recall" in self._arguments or "--current-file" in self._arguments) and "current_file" in self._arguments): - self._cmd = ('git show {} --pretty=format:"commit %H%nparent %P%n' + self._cmd = ('git show {} -C{} --pretty=format:"commit %H%nparent %P%n' 'Author: %an <%ae>%nAuthorDate: %ad%nCommitter: %cn <%ce>%nCommitDate:' ' %cd{}%n%n%s%n%n%b%n%x2d%x2d%x2d" --stat=70 --stat-graph-width=10 --no-color' ' && git show {} --pretty=format:"%x20" --no-color -- {}' - ).format(self._source, sep, self._source, + ).format(self._source, find_copies_harder, sep, self._source, self._arguments["orig_name"].get(self._source, self._arguments["current_file"])) @@ -373,8 +378,13 @@ def __init__(self, arguments_dict, source): super(GitLogExplCommand, self).__init__(arguments_dict, source) def buildCommandAndBufferName(self): - self._cmd = ('git show -m --raw -C --numstat --shortstat ' - '--pretty=format:"# %P" --no-abbrev {}').format(self._source) + if "--find-copies-harder" in self._arguments: + find_copies_harder = " -C" + else: + find_copies_harder = "" + + self._cmd = ('git show -m --raw -C{} --numstat --shortstat ' + '--pretty=format:"# %P" --no-abbrev {}').format(find_copies_harder, self._source) self._buffer_name = "LeaderF://navigation/" + self._source self._file_type_cmd = "" @@ -2803,7 +2813,7 @@ def blamePrevious(self): # M tui.py outputs = ParallelExecutor.run(cmd) name_stat = outputs[0][2] - if name_stat.startswith("A"): + if name_stat.startswith("A") or name_stat.startswith("C"): lfPrintError("First commit of current file!") return else: From 26654054e661fba38a054c651ed14c49537cb44c Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Mon, 22 Apr 2024 22:17:42 +0800 Subject: [PATCH 200/365] add support to preview the diffs when Leaderf git blame --- autoload/leaderf/Git.vim | 76 ++++++++-- autoload/leaderf/python/leaderf/gitExpl.py | 162 ++++++++++++++++++++- 2 files changed, 221 insertions(+), 17 deletions(-) diff --git a/autoload/leaderf/Git.vim b/autoload/leaderf/Git.vim index e9dfd2d3..3d290607 100644 --- a/autoload/leaderf/Git.vim +++ b/autoload/leaderf/Git.vim @@ -128,6 +128,7 @@ let s:help = { \ "h: blame the parent commit", \ "l: go to the previous blame status", \ "m: show the commit message", + \ "p: preview the diffs around the current line", \ ], \} @@ -211,7 +212,7 @@ function! leaderf#Git#ShowHelp(type) abort endfunction -function! leaderf#Git#CloseCommitMessageWin() abort +function! leaderf#Git#CloseFloatWinMouse() abort if exists("b:blame_cursorline") && exists("*getmousepos") let pos = getmousepos() if pos.winid == b:blame_winid && b:blame_cursorline != pos["line"] @@ -220,6 +221,14 @@ function! leaderf#Git#CloseCommitMessageWin() abort endif endif endif + if exists("b:blame_preview_cursorline") && exists("*getmousepos") + let pos = getmousepos() + if pos.winid == b:blame_winid && b:blame_preview_cursorline != pos["line"] + if exists("b:preview_winid") && winbufnr(b:preview_winid) != -1 + call nvim_win_close(b:preview_winid, 1) + endif + endif + endif endfunction function s:CommitMessageFilter(winid, key) abort @@ -304,6 +313,39 @@ function! leaderf#Git#ShowCommitMessage(message) abort endif endfunction +function leaderf#Git#PreviewFilter(winid, key) abort + if a:key == "\" + if exists("*getmousepos") + let pos = getmousepos() + if pos.winid != a:winid + call popup_close(a:winid) + endif + endif + endif + + if a:key == "\" + call popup_close(a:winid) + return 1 + elseif a:key == "j" || a:key == "k" + call popup_close(a:winid) + return 0 + elseif a:key == "\" + call popup_close(a:winid) + call feedkeys("\", 't') + return 1 + elseif a:key == "\" + call win_execute(a:winid, "norm! j") + return 1 + elseif a:key == "\" + call win_execute(a:winid, "norm! k") + return 1 + else + return leaderf#popupModePreviewFilter(a:winid, a:key) + endif + + return 1 +endfunction + function! leaderf#Git#TreeViewMaps(id) abort exec g:Lf_py "import ctypes" let tree_view = printf("ctypes.cast(%d, ctypes.py_object).value", a:id) @@ -339,20 +381,30 @@ function! leaderf#Git#ExplorerMaps(id) abort nnoremap q :q endfunction +function! leaderf#Git#CloseFloatWin() abort + if exists("b:commit_msg_winid") && winbufnr(b:commit_msg_winid) != -1 + call nvim_win_close(b:commit_msg_winid, 1) + endif + if exists("b:preview_winid") && winbufnr(b:preview_winid) != -1 + call nvim_win_close(b:preview_winid, 1) + endif +endfunction + function! leaderf#Git#BlameMaps(id) abort exec g:Lf_py "import ctypes" - let explorer_page = printf("ctypes.cast(%d, ctypes.py_object).value", a:id) - exec printf('nnoremap o :exec g:Lf_py "%s.open()"', explorer_page) - exec printf('nnoremap <2-LeftMouse> :exec g:Lf_py "%s.open()"', explorer_page) - exec printf('nnoremap :exec g:Lf_py "%s.open()"', explorer_page) - exec printf('nnoremap h :exec g:Lf_py "%s.blamePrevious()"', explorer_page) - exec printf('nnoremap l :exec g:Lf_py "%s.blameNext()"', explorer_page) - exec printf('nnoremap m :exec g:Lf_py "%s.showCommitMessage()"', explorer_page) + let blame_manager = printf("ctypes.cast(%d, ctypes.py_object).value", a:id) + exec printf('nnoremap o :exec g:Lf_py "%s.open()"', blame_manager) + exec printf('nnoremap <2-LeftMouse> :exec g:Lf_py "%s.open()"', blame_manager) + exec printf('nnoremap :exec g:Lf_py "%s.open()"', blame_manager) + exec printf('nnoremap h :exec g:Lf_py "%s.blamePrevious()"', blame_manager) + exec printf('nnoremap l :exec g:Lf_py "%s.blameNext()"', blame_manager) + exec printf('nnoremap m :exec g:Lf_py "%s.showCommitMessage()"', blame_manager) + exec printf('nnoremap p :exec g:Lf_py "%s.preview()"', blame_manager) if has("nvim") - nnoremap j :silent! call nvim_win_close(b:commit_msg_winid, 1)j - nnoremap k :silent! call nvim_win_close(b:commit_msg_winid, 1)k - nnoremap :silent! call nvim_win_close(b:commit_msg_winid, 1) - nnoremap :call leaderf#Git#CloseCommitMessageWin() + nnoremap j :call leaderf#Git#CloseFloatWin()j + nnoremap k :call leaderf#Git#CloseFloatWin()k + nnoremap :call leaderf#Git#CloseFloatWin() + nnoremap :call leaderf#Git#CloseFloatWinMouse() endif nnoremap :call leaderf#Git#ShowHelp("blame") nnoremap q :bwipe diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 52bba22f..ce6f1283 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -424,6 +424,26 @@ def buildCommandAndBufferName(self): self._file_type_cmd = "" +class GitShowCommand(GitCommand): + def __init__(self, arguments_dict, commit_id, file_name): + self._commit_id = commit_id + self._file_name = file_name + super(GitShowCommand, self).__init__(arguments_dict, None) + + def buildCommandAndBufferName(self): + self._cmd = "git show {} -- {}".format(self._commit_id, self._file_name) + self._file_type = "git" + self._file_type_cmd = "setlocal filetype=git" + + +class GitCustomizeCommand(GitCommand): + def __init__(self, arguments_dict, cmd, file_type, file_type_cmd): + super(GitCustomizeCommand, self).__init__(arguments_dict, None) + self._cmd = cmd + self._file_type = file_type + self._file_type_cmd = file_type_cmd + + class ParallelExecutor(object): @staticmethod def run(*cmds, format_line=None): @@ -1664,7 +1684,7 @@ def deregister(self, view): self._view.cleanup() self._view = None - def create(self, cmd, config): + def create(self, cmd, config, buf_content=None): if lfEval("has('nvim')") == '1': lfCmd("noautocmd let scratch_buffer = nvim_create_buf(0, 1)") self._preview_winid = int(lfEval("nvim_open_win(scratch_buffer, 0, %s)" @@ -1673,7 +1693,7 @@ def create(self, cmd, config): lfCmd("noautocmd silent! let winid = popup_create([], %s)" % json.dumps(config)) self._preview_winid = int(lfEval("winid")) - GitCommandView(self, cmd).create(self._preview_winid) + GitCommandView(self, cmd).create(self._preview_winid, buf_content=buf_content) def createView(self, cmd): if self._preview_winid > 0: @@ -1704,6 +1724,11 @@ def setContent(self, content): if self._view: self._view.setContent(content) + def getViewContent(self): + if self._view: + return self._view.getContent() + + return [] class DiffViewPanel(Panel): def __init__(self, bufhidden_callback=None, commit_id=""): @@ -2960,9 +2985,136 @@ def open(self): self._pages[commit_id] = ExplorerPage(self._project_root, commit_id, self) self._pages[commit_id].create(self._arguments, - GitLogExplCommand(self._arguments, commit_id), - target_path=file_name, - line_num=line_num) + GitLogExplCommand(self._arguments, commit_id), + target_path=file_name, + line_num=line_num) + + def generateConfig(self): + maxheight = int(lfEval("get(g:, 'Lf_GitBlamePreviewHeight', {})" + .format(vim.current.window.height // 3))) + if maxheight < 5: + maxheight = 5 + + alternate_winid = self._blame_panel.getAlternateWinid(vim.current.buffer.name) + screenpos = lfEval("screenpos({}, {}, {})".format(alternate_winid, + vim.current.window.cursor[0], + 1)) + col = int(screenpos["col"]) + maxwidth = int(lfEval("&columns")) - col + + if lfEval("has('nvim')") == '1': + row = int(screenpos["row"]) + + popup_borders = lfEval("g:Lf_PopupBorders") + borderchars = [ + [popup_borders[4], "Lf_hl_popupBorder"], + [popup_borders[0], "Lf_hl_popupBorder"], + [popup_borders[5], "Lf_hl_popupBorder"], + [popup_borders[1], "Lf_hl_popupBorder"], + [popup_borders[6], "Lf_hl_popupBorder"], + [popup_borders[2], "Lf_hl_popupBorder"], + [popup_borders[7], "Lf_hl_popupBorder"], + [popup_borders[3], "Lf_hl_popupBorder"] + ] + + if row > maxheight + 2: + anchor = "SW" + row -= 1 + else: + anchor = "NW" + + config = { + "title": " Preview ", + "title_pos": "center", + "relative": "editor", + "anchor": anchor, + "row": row, + "col": col - 1, + "width": maxwidth, + "height": maxheight, + "zindex": 20482, + "noautocmd": 1, + "border": borderchars, + "style": "minimal", + } + else: + config = { + "title": " Preview ", + "maxwidth": maxwidth, + "minwidth": maxwidth, + "maxheight": maxheight, + "minheight": maxheight, + "zindex": 20482, + "pos": "botleft", + "line": "cursor-1", + "col": col, + "scrollbar": 0, + "padding": [0, 0, 0, 0], + "border": [1, 1, 1, 1], + "borderchars": lfEval("g:Lf_PopupBorders"), + "borderhighlight": ["Lf_hl_popupBorder"], + "filter": "leaderf#Git#PreviewFilter", + "mapping": 0, + } + + return config + + def preview(self): + if vim.current.line == "": + return + + commit_id = vim.current.line.lstrip('^').split(None, 1)[0] + if commit_id.startswith('0000000'): + lfPrintError("Not Committed Yet!") + return + + line_num, file_name = vim.current.line.rsplit('\t', 1)[1].split(None, 1) + line_num = int(line_num) + + if lfEval("has('nvim')") == '1': + lfCmd("let b:blame_preview_cursorline = line('.')") + lfCmd("let b:blame_winid = win_getid()") + if lfEval("exists('b:preview_winid') && winbufnr(b:preview_winid) != -1") == '1': + lfCmd("call nvim_win_close(b:preview_winid, 1)") + + cmd = GitShowCommand(self._arguments, commit_id, file_name) + outputs = ParallelExecutor.run(cmd.getCommand()) + self._preview_panel.create(cmd, self.generateConfig(), outputs[0]) + preview_winid = self._preview_panel.getPreviewWinId() + self._setWinOptions(preview_winid) + if lfEval("has('nvim')") == '1': + lfCmd("let b:preview_winid = {}".format(preview_winid)) + lfCmd("call nvim_win_set_option(%d, 'number', v:false)" % preview_winid) + else: + lfCmd("call win_execute({}, 'setlocal nonumber')".format(preview_winid)) + + self.gotoLine(preview_winid, line_num) + + def gotoLine(self, winid, line_num): + found = False + current_line = 0 + view_content = self._preview_panel.getViewContent() + for i, line in enumerate(view_content, 1): + if found: + if not line.startswith("-"): + current_line += 1 + if current_line == line_num: + lfCmd("call win_execute({}, 'norm! {}Gzz')".format(winid, i)) + break + # @@ -2,11 +2,21 @@ + elif line.startswith("@@"): + line_numbers = line.split("+", 1)[1].split(None, 1)[0] + if "," in line_numbers: + start, count = line_numbers.split(",") + start = int(start) + count = int(count) + else: + start = int(line_numbers) + count = 0 + + if start + count > line_num: + found = True + current_line = start - 1 def startExplorer(self, win_pos, *args, **kwargs): if self.checkWorkingDirectory() == False: From 8972bedf6fc69b38d51922717395f0720cd83184 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Fri, 26 Apr 2024 22:24:13 +0800 Subject: [PATCH 201/365] replace s:CommitMessageFilter with leaderf#Git#PreviewFilter --- autoload/leaderf/Git.vim | 31 +++++++------------------------ 1 file changed, 7 insertions(+), 24 deletions(-) diff --git a/autoload/leaderf/Git.vim b/autoload/leaderf/Git.vim index 3d290607..fd8926e0 100644 --- a/autoload/leaderf/Git.vim +++ b/autoload/leaderf/Git.vim @@ -231,28 +231,6 @@ function! leaderf#Git#CloseFloatWinMouse() abort endif endfunction -function s:CommitMessageFilter(winid, key) abort - if a:key == "\" - call popup_close(a:winid) - return 1 - elseif a:key == "j" || a:key == "k" - call popup_close(a:winid) - return 0 - elseif a:key == "\" - if exists("b:blame_cursorline") && exists("*getmousepos") - let pos = getmousepos() - if pos.winid == b:blame_winid && b:blame_cursorline != pos["line"] - call popup_close(a:winid) - endif - endif - return 0 - elseif a:key == "\" || a:key == "\" - return 0 - endif - - return 1 -endfunction - function! leaderf#Git#ShowCommitMessage(message) abort let b:blame_cursorline = line('.') let b:blame_winid = win_getid() @@ -267,7 +245,7 @@ function! leaderf#Git#ShowCommitMessage(message) abort \ [g:Lf_PopupBorders[7], "Lf_hl_popupBorder"], \ [g:Lf_PopupBorders[3], "Lf_hl_popupBorder"] \] - let width = 100 + let width = 80 let height = len(a:message) let row_col = s:GetRowCol(width, height) let options = { @@ -295,15 +273,20 @@ function! leaderf#Git#ShowCommitMessage(message) abort call win_execute(b:commit_msg_winid, 'nnoremap c') call win_execute(b:commit_msg_winid, 'setlocal filetype=git') else + let maxheight = &lines / 3 let options = { \ "title": " Commit Message ", + \ "maxwidth": 80, + \ "minwidth": 80, + \ "maxheight": maxheight, + \ "minheight": maxheight, \ "zindex": 20482, \ "scrollbar": 1, \ "padding": [0, 0, 0, 0], \ "border": [1, 1, 1, 1], \ "borderchars": g:Lf_PopupBorders, \ "borderhighlight": ["Lf_hl_popupBorder"], - \ "filter": "s:CommitMessageFilter", + \ "filter": "leaderf#Git#PreviewFilter", \ "mapping": 0, \} From 5fbd9c9bf732553ec95c15b1b9298d55bf81d8d2 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Fri, 26 Apr 2024 22:44:29 +0800 Subject: [PATCH 202/365] show " Press for help." in statusline --- autoload/leaderf/Git.vim | 2 ++ autoload/leaderf/python/leaderf/gitExpl.py | 2 ++ 2 files changed, 4 insertions(+) diff --git a/autoload/leaderf/Git.vim b/autoload/leaderf/Git.vim index fd8926e0..3b24e7bb 100644 --- a/autoload/leaderf/Git.vim +++ b/autoload/leaderf/Git.vim @@ -122,6 +122,7 @@ let s:help = { \ "): go to the end of the current indent level", \ ], \ "blame": [ + \ ": toggle the help", \ "o: show the details of current commit in an explorer page", \ ": show the details of current commit in an explorer page", \ "<2-LeftMouse>: show the details of current commit in an explorer page", @@ -129,6 +130,7 @@ let s:help = { \ "l: go to the previous blame status", \ "m: show the commit message", \ "p: preview the diffs around the current line", + \ "q: quit the blame window", \ ], \} diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index ce6f1283..ad3fc59a 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -2031,6 +2031,8 @@ def create(self, arguments_dict, cmd, content=None): lfCmd("noautocmd norm! {}Gzt{}G0".format(top_line, cursor_line)) lfCmd("call win_execute({}, 'setlocal scrollbind')".format(winid)) lfCmd("setlocal scrollbind") + lfCmd(r"""call win_execute({}, 'let &l:stl=" Press for help."')""" + .format(blame_winid)) else: lfPrintError("No need to blame!") From 11fcefa0769361190c4020ca00812331619512d5 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Sat, 27 Apr 2024 10:30:33 +0800 Subject: [PATCH 203/365] add `Leaderf git blame --date relative` --- autoload/leaderf/Git.vim | 1 + 1 file changed, 1 insertion(+) diff --git a/autoload/leaderf/Git.vim b/autoload/leaderf/Git.vim index 3b24e7bb..7c6cc33d 100644 --- a/autoload/leaderf/Git.vim +++ b/autoload/leaderf/Git.vim @@ -452,6 +452,7 @@ function! leaderf#Git#Commands() abort \ {"Leaderf git log --current-file --explorer":"fuzzy search and view the log of current file in explorer tabpage"}, \ {"Leaderf git blame": "git blame current file"}, \ {"Leaderf git blame -w": "ignore whitespace when git blame current file"}, + \ {"Leaderf git blame --date relative": "show relative date when git blame current file"}, \ ] endif From e359cb3ae751be9582b620ef123e8f41ebb972a0 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Sun, 28 Apr 2024 14:37:37 +0800 Subject: [PATCH 204/365] fix issue that `:Leaderf git diff --explorer --side-by-side` crash --- autoload/leaderf/python/leaderf/gitExpl.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index ad3fc59a..b644da88 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -2565,10 +2565,10 @@ def _acceptSelection(self, *args, **kwargs): line = args[0] source = self.getSource(line) - if "-s" in self._arguments: - self._diff_view_panel.create(self._arguments, source, **kwargs) - elif "accept" in self._arguments: + if "accept" in self._arguments: self._arguments["accept"](lfGetFilePath(source)) + elif "-s" in self._arguments: + self._diff_view_panel.create(self._arguments, source, **kwargs) else: if kwargs.get("mode", '') == 't' and source not in self._result_panel.getSources(): self._arguments["mode"] = 't' From b73af2cbe778e560b723bc65eb385302257f44a4 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Tue, 30 Apr 2024 16:18:28 +0800 Subject: [PATCH 205/365] Leaderf git log --current-file if the file is renamed, the diffs is not correct --- autoload/leaderf/python/leaderf/gitExpl.py | 13 +++++++------ autoload/leaderf/python/leaderf/utils.py | 4 ---- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index b644da88..f7cc6ed4 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -261,10 +261,10 @@ def __init__(self, arguments_dict, source): def buildCommandAndBufferName(self): # fuzzy search in navigation panel if not self._arguments["parent"].startswith("0000000"): - self._cmd = "git diff --no-color {}..{} -- {}".format(self._arguments["parent"], - self._arguments["commit_id"], - lfGetFilePath(self._source) - ) + self._cmd = "git diff --follow --no-color {}..{} -- {}".format(self._arguments["parent"], + self._arguments["commit_id"], + lfGetFilePath(self._source) + ) else: self._cmd = "git show --pretty= --no-color {} -- {}".format(self._arguments["commit_id"], lfGetFilePath(self._source) @@ -340,7 +340,7 @@ def buildCommandAndBufferName(self): self._cmd = ('git show {} -C{} --pretty=format:"commit %H%nparent %P%n' 'Author: %an <%ae>%nAuthorDate: %ad%nCommitter: %cn <%ce>%nCommitDate:' ' %cd{}%n%n%s%n%n%b%n%x2d%x2d%x2d" --stat=70 --stat-graph-width=10 --no-color' - ' && git show {} --pretty=format:"%x20" --no-color -- {}' + ' && git log -1 -p --follow --pretty=format:"%x20" --no-color {} -- {}' ).format(self._source, find_copies_harder, sep, self._source, self._arguments["orig_name"].get(self._source, self._arguments["current_file"])) @@ -2754,7 +2754,8 @@ def _acceptSelection(self, *args, **kwargs): self._diff_view_panel = DiffViewPanel(self.afterBufhidden) self._diff_view_panel.setCommitId(commit_id) - cmd = "git show --pretty= --no-color --raw {} -- {}".format(commit_id, file_name) + cmd = "git log -1 --follow --pretty= --no-color --raw {} -- {}".format(commit_id, + file_name) outputs = ParallelExecutor.run(cmd) if len(outputs[0]) > 0: _, source = TreeView.generateSource(outputs[0][0]) diff --git a/autoload/leaderf/python/leaderf/utils.py b/autoload/leaderf/python/leaderf/utils.py index c4c84a9b..5cf61388 100644 --- a/autoload/leaderf/python/leaderf/utils.py +++ b/autoload/leaderf/python/leaderf/utils.py @@ -146,10 +146,6 @@ def equal(str1, str2, ignorecase=True): def lfRelpath(path, start=os.curdir): try: - # LeaderF://git diff - if not os.path.isabs(path): - return path - return lfEncode(os.path.relpath(lfDecode(path), start)) except ValueError: return path From de37c621a099a72d21e1731d4932d5b62cdc37bd Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Tue, 7 May 2024 11:08:01 +0800 Subject: [PATCH 206/365] fix a bug vim repo 1cae5a0 --- autoload/leaderf/python/leaderf/gitExpl.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index f7cc6ed4..40130217 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -287,6 +287,9 @@ def buildBufferName(commit_id, source): """ source is a tuple like (b90f76fc1, R099, src/version.c) """ + if source[1].startswith("C"): + return "{}:{}:{}:{}".format(commit_id[:7], source[0][:9], "C", source[2]) + return "{}:{}:{}".format(commit_id[:7], source[0][:9], source[2]) def buildCommandAndBufferName(self): From 04cbf95b456f57c3e58cc5b242ed49c51530fe3f Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Mon, 13 May 2024 11:27:03 +0800 Subject: [PATCH 207/365] setlocal scrolloff=0 --- autoload/leaderf/python/leaderf/gitExpl.py | 1 + 1 file changed, 1 insertion(+) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 40130217..56da0bac 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -765,6 +765,7 @@ def setOptions(self, winid, bufhidden): lfCmd("call win_execute({}, 'setlocal nofoldenable')".format(winid)) lfCmd("call win_execute({}, 'setlocal signcolumn=no')".format(winid)) lfCmd("call win_execute({}, 'setlocal cursorline')".format(winid)) + lfCmd("call win_execute({}, 'setlocal scrolloff=0')".format(winid)) def saveAlternateWinOptions(self, winid, buffer_num): self._alternate_winid = winid From 25218c5ff71e2569155a23a757fbc0d79b3a5608 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Mon, 13 May 2024 15:33:44 +0800 Subject: [PATCH 208/365] git command should be run in the project's root --- autoload/leaderf/python/leaderf/gitExpl.py | 35 +++++++++++++--------- autoload/leaderf/python/leaderf/utils.py | 5 ++++ 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 56da0bac..99a9f59b 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -449,7 +449,19 @@ def __init__(self, arguments_dict, cmd, file_type, file_type_cmd): class ParallelExecutor(object): @staticmethod - def run(*cmds, format_line=None): + def run(*cmds, format_line=None, directory=None): + try: + if directory is not None: + orig_cwd = lfGetCwd() + lfChdir(directory) + + return ParallelExecutor._run(*cmds, format_line=format_line) + finally: + if directory is not None: + lfChdir(orig_cwd) + + @staticmethod + def _run(*cmds, format_line=None): outputs = [[] for _ in range(len(cmds))] stop_thread = False @@ -2245,12 +2257,7 @@ def checkWorkingDirectory(self): self._orig_cwd = lfGetCwd() self._project_root = nearestAncestor([".git"], self._orig_cwd) if self._project_root: # there exists a root marker in nearest ancestor path - # https://github.com/neovim/neovim/issues/8336 - if lfEval("has('nvim')") == '1': - chdir = vim.chdir - else: - chdir = os.chdir - chdir(self._project_root) + lfChdir(self._project_root) else: lfPrintError("Not a git repository (or any of the parent directories): .git") return False @@ -2442,7 +2449,7 @@ def vsplitDiff(self): cmd = "git diff {} --raw -- {}".format(" ".join(self._arguments["extra"]), self._arguments["current_file"]) - outputs = ParallelExecutor.run(cmd) + outputs = ParallelExecutor.run(cmd, directory=self._project_root) if len(outputs[0]) == 0: lfPrintError("No diffs!") return @@ -2468,7 +2475,7 @@ def vsplitDiff(self): lfCmd("setlocal noswapfile") lfCmd("setlocal nospell") - outputs = ParallelExecutor.run(cmd) + outputs = ParallelExecutor.run(cmd, directory=self._project_root) vim.current.buffer[:] = outputs[0] lfCmd("setlocal nomodifiable") @@ -2482,7 +2489,7 @@ def vsplitDiff(self): cmd = "git diff {} --cached --raw -- {}".format(extra, self._arguments["current_file"]) - outputs = ParallelExecutor.run(cmd) + outputs = ParallelExecutor.run(cmd, directory=self._project_root) if len(outputs[0]) > 0: _, source = TreeView.generateSource(outputs[0][0]) self._diff_view_panel.create(self._arguments, source, **{"mode": 't'}) @@ -2760,7 +2767,7 @@ def _acceptSelection(self, *args, **kwargs): self._diff_view_panel.setCommitId(commit_id) cmd = "git log -1 --follow --pretty= --no-color --raw {} -- {}".format(commit_id, file_name) - outputs = ParallelExecutor.run(cmd) + outputs = ParallelExecutor.run(cmd, directory=self._project_root) if len(outputs[0]) > 0: _, source = TreeView.generateSource(outputs[0][0]) self._diff_view_panel.create(self._arguments, source, **kwargs) @@ -2843,7 +2850,7 @@ def blamePrevious(self): # 5a0cd5103deba164a6fb33a5a3f67fb3a5dcf378 # # M tui.py - outputs = ParallelExecutor.run(cmd) + outputs = ParallelExecutor.run(cmd, directory=self._project_root) name_stat = outputs[0][2] if name_stat.startswith("A") or name_stat.startswith("C"): lfPrintError("First commit of current file!") @@ -2878,7 +2885,7 @@ def blamePrevious(self): cmd = [GitBlameCommand.buildCommand(self._arguments, parent_commit_id, orig_name), "git show {}:{}".format(parent_commit_id, orig_name) ] - outputs = ParallelExecutor.run(*cmd) + outputs = ParallelExecutor.run(*cmd, directory=self._project_root) line_num_width = len(str(len(outputs[1]))) + 1 blame_buffer = [BlamePanel.formatLine(self._arguments, line_num_width, line) for line in outputs[0] @@ -3085,7 +3092,7 @@ def preview(self): lfCmd("call nvim_win_close(b:preview_winid, 1)") cmd = GitShowCommand(self._arguments, commit_id, file_name) - outputs = ParallelExecutor.run(cmd.getCommand()) + outputs = ParallelExecutor.run(cmd.getCommand(), directory=self._project_root) self._preview_panel.create(cmd, self.generateConfig(), outputs[0]) preview_winid = self._preview_panel.getPreviewWinId() self._setWinOptions(preview_winid) diff --git a/autoload/leaderf/python/leaderf/utils.py b/autoload/leaderf/python/leaderf/utils.py index 5cf61388..738c3f9b 100644 --- a/autoload/leaderf/python/leaderf/utils.py +++ b/autoload/leaderf/python/leaderf/utils.py @@ -17,6 +17,11 @@ lfCmd = vim.command lfEval = vim.eval +# https://github.com/neovim/neovim/issues/8336 +if lfEval("has('nvim')") == '1': + lfChdir = vim.chdir +else: + lfChdir = os.chdir lf_encoding = lfEval("&encoding") From 4f7da6d1289ef2ae2c31c851bdccfcee1c59293f Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Mon, 6 May 2024 17:58:15 +0800 Subject: [PATCH 209/365] add support for '--unified' to display the diffs in a unified view '--unified' should combine with '--explorer', for example: Leaderf git diff --explorer --unified Leaderf git log --explorer --unified --- autoload/leaderf/Any.vim | 9 +- autoload/leaderf/Git.vim | 58 ++ autoload/leaderf/colorscheme/popup.vim | 111 +++- .../leaderf/colorscheme/popup/default.vim | 8 + autoload/leaderf/python/leaderf/gitExpl.py | 499 +++++++++++++++++- doc/leaderf.txt | 56 +- 6 files changed, 677 insertions(+), 64 deletions(-) diff --git a/autoload/leaderf/Any.vim b/autoload/leaderf/Any.vim index 85a1c6a6..775f8bc3 100644 --- a/autoload/leaderf/Any.vim +++ b/autoload/leaderf/Any.vim @@ -226,6 +226,10 @@ let g:Lf_Arguments = { \ "help": "specifies the position of the logs window"}, \ {"name": ["--navigation-position"], "nargs": 1, "choices": ["top", "right", "bottom", "left"], "metavar": "", \ "help": "specifies the position of the navigation panel"}, + \ [ + \ {"name": ["-s", "--side-by-side"], "nargs": 0, "help": "show diffs in a side-by-side view"}, + \ {"name": ["-u", "--unified"], "nargs": 0, "help": "show diffs in a unified view"}, + \ ], \ {"name": ["-n", "--max-count"], "nargs": 1, "metavar": "", "help": "Limit the number of commits to output."}, \ {"name": ["--skip"], "nargs": 1, "metavar": "", "help": "Skip number commits before starting to show the commit output."}, \ {"name": ["--since", "--after"], "nargs": 1, "metavar": "", "help": "Show commits more recent than a specific date."}, @@ -249,7 +253,10 @@ let g:Lf_Arguments = { \ "help": "specifies the position of the diffs window"}, \ {"name": ["--navigation-position"], "nargs": 1, "choices": ["top", "right", "bottom", "left"], "metavar": "", \ "help": "specifies the position of the navigation panel"}, - \ {"name": ["-s", "--side-by-side"], "nargs": 0, "help": "show diffs in a side-by-side view"}, + \ [ + \ {"name": ["-s", "--side-by-side"], "nargs": 0, "help": "show diffs in a side-by-side view"}, + \ {"name": ["-u", "--unified"], "nargs": 0, "help": "show diffs in a unified view"}, + \ ], \ {"name": ["--current-file"], "nargs": 0, "help": "show diffs of current file"}, \ {"name": ["extra"], "nargs": "*", "help": "extra arguments of git diff"}, \ ], diff --git a/autoload/leaderf/Git.vim b/autoload/leaderf/Git.vim index 7c6cc33d..336a4e63 100644 --- a/autoload/leaderf/Git.vim +++ b/autoload/leaderf/Git.vim @@ -420,6 +420,16 @@ function! leaderf#Git#Bufhidden(view_id) abort exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value.bufHidden()", a:view_id) endfunction +function! leaderf#Git#ClearMatches() abort + for m in b:Leaderf_matches + call matchdelete(m.id) + endfor +endfunction + +function! leaderf#Git#SetMatches() abort + call setmatches(b:Leaderf_matches) +endfunction + function! leaderf#Git#CleanupExplorerPage(view_id) abort exec g:Lf_py "import ctypes" exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value.cleanupExplorerPage()", a:view_id) @@ -432,6 +442,7 @@ function! leaderf#Git#Commands() abort \ {"Leaderf git diff --side-by-side": "fuzzy search and view the side-by-side diffs"}, \ {"Leaderf git diff --side-by-side --current-file":"view the side-by-side diffs of the current file"}, \ {"Leaderf git diff --explorer": "view the diffs in an explorer tabpage"}, + \ {"Leaderf git diff --explorer --unified": "view the diffs in an explorer tabpage, the diffs is shown in unified view"}, \ {"Leaderf git diff --directly": "view the diffs directly"}, \ {"Leaderf git diff --directly --position right":"view the diffs in the right split window"}, \ {"Leaderf git diff --cached": "fuzzy search and view `git diff --cached`"}, @@ -447,6 +458,7 @@ function! leaderf#Git#Commands() abort \ {"Leaderf git log": "fuzzy search and view the log"}, \ {"Leaderf git log --directly": "view the logs directly"}, \ {"Leaderf git log --explorer": "fuzzy search and view the log in an explorer tabpage"}, + \ {"Leaderf git log --explorer --unified": "fuzzy search and view the log in an explorer tabpage, the diffs is shown in unified view"}, \ {"Leaderf git log --explorer --navigation-position bottom": "specify the position of navigation panel in explorer tabpage"}, \ {"Leaderf git log --current-file": "fuzzy search and view the log of current file"}, \ {"Leaderf git log --current-file --explorer":"fuzzy search and view the log of current file in explorer tabpage"}, @@ -489,3 +501,49 @@ function! leaderf#Git#DiffOff(win_ids) abort call win_execute(id, "diffoff") endfor endfunction + +function! leaderf#Git#FoldExpr() abort + return has_key(b:Leaderf_fold_ranges_dict, v:lnum) +endfunction + +function! leaderf#Git#SetLineNumberWin(line_num_content, buffer_num) + if len(a:line_num_content) == 0 + return + endif + + let line = a:line_num_content[0] + let line_len = strlen(line) + + let hi_line_num = get(g:, 'Lf_GitHightlightLineNumber', 0) + let delimiter = get(g:, 'Lf_GitDelimiter', '│') + let delimiter_len = len(delimiter) + let ns_id = nvim_create_namespace('LeaderF') + + for i in range(len(a:line_num_content)) + let line = a:line_num_content[i] + let last_part = strcharpart(line, line_len - (delimiter_len + 1), 2) + + if last_part[0] == '-' + if hi_line_num == 1 + let hl_group1 = "Lf_hl_gitDiffDelete" + else + let hl_group1 = "Lf_hl_LineNr" + endif + let hl_group2 = "Lf_hl_gitDiffDelete" + let first_part = strcharpart(line, 0, line_len - (delimiter_len + 1)) + call nvim_buf_set_extmark(a:buffer_num, ns_id, i, 0, {'virt_text': [[first_part, hl_group1], [last_part, hl_group2]], 'virt_text_pos': 'inline'}) + elseif last_part[0] == '+' + if hi_line_num == 1 + let hl_group1 = "Lf_hl_gitDiffAdd" + else + let hl_group1 = "Lf_hl_LineNr" + endif + let hl_group2 = "Lf_hl_gitDiffAdd" + let first_part = strcharpart(line, 0, line_len - (delimiter_len + 1)) + call nvim_buf_set_extmark(a:buffer_num, ns_id, i, 0, {'virt_text': [[first_part, hl_group1], [last_part, hl_group2]], 'virt_text_pos': 'inline'}) + else + let hl_group = "Lf_hl_LineNr" + call nvim_buf_set_extmark(a:buffer_num, ns_id, i, 0, {'virt_text': [[line, hl_group]], 'virt_text_pos': 'inline'}) + endif + endfor +endfunction diff --git a/autoload/leaderf/colorscheme/popup.vim b/autoload/leaderf/colorscheme/popup.vim index 17b865d7..61cbcb5a 100644 --- a/autoload/leaderf/colorscheme/popup.vim +++ b/autoload/leaderf/colorscheme/popup.vim @@ -99,6 +99,56 @@ function! s:HighlightSeperator(category) abort endfor endfunction +function! s:getSynAttr(sid) abort + let attr = "" + if synIDattr(a:sid, "bold") + let attr = "bold" + endif + if synIDattr(a:sid, "italic") + if attr == "" + let attr = "italic" + else + let attr = attr . ",italic" + endif + endif + if synIDattr(a:sid, "standout") + if attr == "" + let attr = "standout" + else + let attr = attr . ",standout" + endif + endif + if synIDattr(a:sid, "underline") + if attr == "" + let attr = "underline" + else + let attr = attr . ",underline" + endif + endif + if synIDattr(a:sid, "undercurl") + if attr == "" + let attr = "undercurl" + else + let attr = attr . ",undercurl" + endif + endif + if synIDattr(a:sid, "strike") + if attr == "" + let attr = "strike" + else + let attr = attr . ",strike" + endif + endif + if synIDattr(a:sid, "nocombine") + if attr == "" + let attr = "nocombine" + else + let attr = attr . ",nocombine" + endif + endif + return attr +endfunction + " https://github.com/vim/vim/issues/5227 " same as `hi link` but filter out the `reverse` attribute function! leaderf#colorscheme#popup#link_no_reverse(from, to) abort @@ -114,16 +164,12 @@ function! leaderf#colorscheme#popup#link_no_reverse(from, to) abort let ctermbg = synIDattr(sid, "bg", "cterm") let ctermfg = synIDattr(sid, "fg", "cterm") endif - let bold = synIDattr(sid, "bold") ? "bold" : "" - let italic = synIDattr(sid, "italic") ? "italic" : "" - if bold == "" && italic == "" + + let attr = s:getSynAttr(sid) + if attr == "" let attr = "gui=NONE cterm=NONE" - elseif bold == "bold" && italic == "italic" - let attr = "gui=bold,italic cterm=bold,italic" - elseif bold == "bold" - let attr = "gui=bold cterm=bold" else - let attr = "gui=italic cterm=italic" + let attr = "gui=" . attr . " cterm=" . attr endif let hiCmd = printf("hi def %s %s", a:from, attr) let hiCmd .= printf(" guifg=%s guibg=%s", guifg == '' ? 'NONE': guifg, guibg == '' ? 'NONE': guibg) @@ -166,16 +212,11 @@ function! leaderf#colorscheme#popup#link_two(from, bg, fg, no_attr) abort if a:no_attr let attr = "gui=NONE cterm=NONE" else - let bold = synIDattr(fg_sid, "bold") ? "bold" : "" - let italic = synIDattr(fg_sid, "italic") ? "italic" : "" - if bold == "" && italic == "" + let attr = s:getSynAttr(sid) + if attr == "" let attr = "gui=NONE cterm=NONE" - elseif bold == "bold" && italic == "italic" - let attr = "gui=bold,italic cterm=bold,italic" - elseif bold == "bold" - let attr = "gui=bold cterm=bold" else - let attr = "gui=italic cterm=italic" + let attr = "gui=" . attr . "cterm=" . attr endif endif let hiCmd = printf("hi def %s %s", a:from, attr) @@ -227,6 +268,38 @@ function! leaderf#colorscheme#popup#hiMatchMode(category, mode) abort exec printf("hi Lf_hl_popup_%s_sep2 ctermfg=%s", a:category, ctermbg == '' ? 'NONE': ctermbg) endfunction +" define Lf_hl_LineNr +function! s:hiDefineLineNr() abort + call leaderf#colorscheme#popup#link_no_reverse("Lf_hl_LineNr", "LineNr") + let sid = synIDtrans(hlID("Lf_hl_LineNr")) + if synIDattr(sid, "nocombine") == "" + let attr = s:getSynAttr(sid) + if attr == "" + let attr = "nocombine" + else + let attr = attr . ",nocombine" + endif + + let guibg = synIDattr(sid, "bg", "gui") + let ctermbg = synIDattr(sid, "bg", "cterm") + if guibg == "" + let guibg = synIDattr(synIDtrans(hlID("Normal")), "bg", "gui") + if guibg == "" + let guibg = "NONE" + endif + endif + if ctermbg == "" + let ctermbg = synIDattr(synIDtrans(hlID("Normal")), "bg", "cterm") + if ctermbg == "" + let ctermbg = "NONE" + endif + endif + + let hiCmd = printf("hi Lf_hl_LineNr cterm=%s ctermbg=%s gui=%s guibg=%s", attr, ctermbg, attr, guibg) + exec hiCmd + endif +endfunction + function! s:AddPropType() abort silent! highlight def link Lf_hl_cursor Cursor silent! call prop_type_add("Lf_hl_popup_cursor", {'highlight': "Lf_hl_cursor", 'priority': 20}) @@ -245,6 +318,11 @@ function! s:AddPropType() abort silent! call prop_type_add("Lf_hl_popup_blank", {'highlight': "Lf_hl_popup_blank", 'priority': 20}) silent! call prop_type_add("Lf_hl_popup_lineInfo", {'highlight': "Lf_hl_popup_lineInfo", 'priority': 20}) silent! call prop_type_add("Lf_hl_popup_total", {'highlight': "Lf_hl_popup_total", 'priority': 20}) + silent! call prop_type_add("Lf_hl_gitDiffAdd", {'highlight': "Lf_hl_gitDiffAdd", 'priority': 20}) + silent! call prop_type_add("Lf_hl_gitDiffDelete", {'highlight': "Lf_hl_gitDiffDelete", 'priority': 20}) + silent! call prop_type_add("Lf_hl_gitDiffChange", {'highlight': "Lf_hl_gitDiffChange", 'priority': 21}) + silent! call prop_type_add("Lf_hl_gitDiffText", {'highlight': "Lf_hl_gitDiffText", 'priority': 22}) + silent! call prop_type_add("Lf_hl_LineNr", {'highlight': "Lf_hl_LineNr", 'priority': 20}) endfunction " @@ -295,6 +373,7 @@ function! leaderf#colorscheme#popup#load(category, name) exec 'runtime autoload/leaderf/colorscheme/popup/default.vim' endif + call s:hiDefineLineNr() if !has("nvim") call s:AddPropType() endif diff --git a/autoload/leaderf/colorscheme/popup/default.vim b/autoload/leaderf/colorscheme/popup/default.vim index 0f19e606..ebab4563 100644 --- a/autoload/leaderf/colorscheme/popup/default.vim +++ b/autoload/leaderf/colorscheme/popup/default.vim @@ -168,6 +168,10 @@ if &background ==? 'dark' highlight def link Lf_hl_gitGraph4 Lf_hl_gitGraph1 highlight def link Lf_hl_gitGraphSlash Constant highlight def link Lf_hl_gitBlameDate Number + call leaderf#colorscheme#popup#link_no_reverse("Lf_hl_gitDiffAdd", "DiffAdd") + call leaderf#colorscheme#popup#link_no_reverse("Lf_hl_gitDiffDelete", "DiffDelete") + call leaderf#colorscheme#popup#link_no_reverse("Lf_hl_gitDiffChange", "DiffChange") + call leaderf#colorscheme#popup#link_no_reverse("Lf_hl_gitDiffText", "DiffText") else " Lf_hl_popup_inputText is the wincolor of input window highlight def Lf_hl_popup_inputText guifg=#525252 guibg=#f4f3d7 gui=NONE ctermfg=239 ctermbg=230 cterm=NONE @@ -323,4 +327,8 @@ else highlight def link Lf_hl_gitGraph4 Lf_hl_gitGraph1 highlight def link Lf_hl_gitGraphSlash Constant highlight def link Lf_hl_gitBlameDate Number + call leaderf#colorscheme#popup#link_no_reverse("Lf_hl_gitDiffAdd", "DiffAdd") + call leaderf#colorscheme#popup#link_no_reverse("Lf_hl_gitDiffDelete", "DiffDelete") + call leaderf#colorscheme#popup#link_no_reverse("Lf_hl_gitDiffChange", "DiffChange") + call leaderf#colorscheme#popup#link_no_reverse("Lf_hl_gitDiffText", "DiffText") endif diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 99a9f59b..aa211b72 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -9,6 +9,9 @@ import json import bisect import tempfile +import itertools +from difflib import Differ, SequenceMatcher +from itertools import islice from functools import partial from enum import Enum from collections import OrderedDict @@ -440,9 +443,10 @@ def buildCommandAndBufferName(self): class GitCustomizeCommand(GitCommand): - def __init__(self, arguments_dict, cmd, file_type, file_type_cmd): + def __init__(self, arguments_dict, cmd, buf_name, file_type, file_type_cmd): super(GitCustomizeCommand, self).__init__(arguments_dict, None) self._cmd = cmd + self._buffer_name = buf_name self._file_type = file_type self._file_type_cmd = file_type_cmd @@ -772,7 +776,7 @@ def setOptions(self, winid, bufhidden): super(GitBlameView, self).setOptions(winid, bufhidden) lfCmd("call win_execute({}, 'setlocal nowrap')".format(winid)) lfCmd("call win_execute({}, 'setlocal winfixwidth')".format(winid)) - lfCmd("call win_execute({}, 'setlocal fdc=0')".format(winid)) + lfCmd("call win_execute({}, 'setlocal foldcolumn=0')".format(winid)) lfCmd("call win_execute({}, 'setlocal number norelativenumber')".format(winid)) lfCmd("call win_execute({}, 'setlocal nofoldenable')".format(winid)) lfCmd("call win_execute({}, 'setlocal signcolumn=no')".format(winid)) @@ -1774,7 +1778,8 @@ def deregister(self, view): def bufHidden(self, view): name = view.getBufferName() - del self._views[name] + if name in self._views: + del self._views[name] self._hidden_views[name] = view lfCmd("call win_execute({}, 'diffoff')".format(view.getWindowId())) @@ -1798,9 +1803,13 @@ def cleanup(self): def writeFinished(self, winid): lfCmd("call win_execute({}, 'diffthis')".format(winid)) - def getValidWinIDs(self, win_ids): + def getValidWinIDs(self, win_ids, win_pos): if win_ids == [-1, -1]: - lfCmd("wincmd w | leftabove new") + if win_pos in ["top", "left"]: + lfCmd("wincmd w") + else: + lfCmd("wincmd W") + lfCmd("leftabove new") win_ids[1] = int(lfEval("win_getid()")) lfCmd("noautocmd leftabove vertical new") win_ids[0] = int(lfEval("win_getid()")) @@ -1815,9 +1824,6 @@ def getValidWinIDs(self, win_ids): return win_ids - def hasView(self): - return vim.current.tabpage in self._buffer_names - def isAllHidden(self): return len(self._views) == 0 @@ -1865,7 +1871,7 @@ def create(self, arguments_dict, source, **kwargs): tabmove() win_ids = [int(lfEval("win_getid({})".format(w.number))) for w in vim.current.tabpage.windows] - elif "winid" in kwargs: # --explorer + elif "winid" in kwargs: # --explorer create win_ids = [kwargs["winid"], 0] lfCmd("call win_gotoid({})".format(win_ids[0])) lfCmd("noautocmd bel vsp") @@ -1876,10 +1882,11 @@ def create(self, arguments_dict, source, **kwargs): tabmove() win_ids = [int(lfEval("win_getid({})".format(w.number))) for w in vim.current.tabpage.windows] - else: + else: # open buffer_names = self._buffer_names[vim.current.tabpage] win_ids = [int(lfEval("bufwinid('{}')".format(escQuote(name)))) for name in buffer_names] - win_ids = self.getValidWinIDs(win_ids) + win_pos = arguments_dict.get("--navigation-position", ["left"])[0] + win_ids = self.getValidWinIDs(win_ids, win_pos) target_winid = win_ids[1] cat_file_cmds = [GitCatFileCommand(arguments_dict, s, self._commit_id) for s in sources] @@ -1920,6 +1927,439 @@ def create(self, arguments_dict, source, **kwargs): lfCmd("call win_execute({}, 'norm! gg]c0')".format(target_winid)) +class UnifiedDiffViewPanel(Panel): + def __init__(self, bufhidden_callback=None, commit_id=""): + self._commit_id = commit_id + self._views = {} + self._hidden_views = {} + self._bufhidden_cb = bufhidden_callback + lfCmd("sign define Leaderf_diff_add linehl=Lf_hl_gitDiffAdd") + lfCmd("sign define Leaderf_diff_delete linehl=Lf_hl_gitDiffDelete") + lfCmd("sign define Leaderf_diff_change linehl=Lf_hl_gitDiffChange") + + def setCommitId(self, commit_id): + self._commit_id = commit_id + + def register(self, view): + self._views[view.getBufferName()] = view + + def deregister(self, view): + # :bw + name = view.getBufferName() + if name in self._views: + self._views[name].cleanup(wipe=False) + del self._views[name] + + if name in self._hidden_views: + self._hidden_views[name].cleanup(wipe=False) + del self._hidden_views[name] + + def bufHidden(self, view): + lfCmd("silent! call leaderf#Git#ClearMatches()") + name = view.getBufferName() + if name in self._views: + del self._views[name] + self._hidden_views[name] = view + + if self._bufhidden_cb is not None: + self._bufhidden_cb() + + def bufShown(self, buffer_name, winid): + view = self._hidden_views[buffer_name] + view.setWindowId(winid) + del self._hidden_views[buffer_name] + self._views[buffer_name] = view + lfCmd("call setmatches(b:Leaderf_matches, {})".format(winid)) + + def cleanup(self): + for view in self._hidden_views.values(): + view.cleanup() + self._hidden_views = {} + + def isAllHidden(self): + return len(self._views) == 0 + + def signPlace(self, added_line_nums, deleted_line_nums, buf_number): + for i in added_line_nums: + lfCmd("""call sign_place(0, "LeaderF", "Leaderf_diff_add", %d, {'lnum': %d})""" + % (buf_number, i)) + + for i in deleted_line_nums: + lfCmd("""call sign_place(0, "LeaderF", "Leaderf_diff_delete", %d, {'lnum': %d})""" + % (buf_number, i)) + + def setLineNumberWin(self, line_num_content, buffer_num): + if lfEval("has('nvim')") == '1': + self.nvim_setLineNumberWin(line_num_content, buffer_num) + return + + hi_line_num = int(lfEval("get(g:, 'Lf_GitHightlightLineNumber', 0)")) + for i, line in enumerate(line_num_content, 1): + if line[-2] == '-': + if hi_line_num == 1: + property_type = "Lf_hl_gitDiffDelete" + else: + property_type = "Lf_hl_LineNr" + lfCmd("call prop_add(%d, 1, {'type': '%s', 'text': '%s', 'bufnr': %d})" + % (i, property_type, line[:-2], buffer_num)) + property_type = "Lf_hl_gitDiffDelete" + lfCmd("call prop_add(%d, 1, {'type': '%s', 'text': '%s', 'bufnr': %d})" + % (i, property_type, line[-2:], buffer_num)) + elif line[-2] == '+': + if hi_line_num == 1: + property_type = "Lf_hl_gitDiffAdd" + else: + property_type = "Lf_hl_LineNr" + lfCmd("call prop_add(%d, 1, {'type': '%s', 'text': '%s', 'bufnr': %d})" + % (i, property_type, line[:-2], buffer_num)) + property_type = "Lf_hl_gitDiffAdd" + lfCmd("call prop_add(%d, 1, {'type': '%s', 'text': '%s', 'bufnr': %d})" + % (i, property_type, line[-2:], buffer_num)) + else: + property_type = "Lf_hl_LineNr" + lfCmd("call prop_add(%d, 1, {'type': '%s', 'text': '%s', 'bufnr': %d})" + % (i, property_type, line, buffer_num)) + + def nvim_setLineNumberWin(self, line_num_content, buffer_num): + lfCmd("call leaderf#Git#SetLineNumberWin({}, {})".format(str(line_num_content), + buffer_num)) + + def highlight(self, winid, status, content, line_num, line): + i = 0 + while i < len(line): + if line[i] == status or line[i] == '^': + c = line[i] + beg = i + i += 1 + while i < len(line) and line[i] == c: + i += 1 + end = i + col = lfBytesLen(content[line_num-1][:beg]) + 1 + length = lfBytesLen(content[line_num - 1][beg : end]) + if c == '^': + hl_group = "Lf_hl_gitDiffText" + elif c == '-': + hl_group = "Lf_hl_gitDiffText" + else: + hl_group = "Lf_hl_gitDiffText" + lfCmd("""call win_execute({}, "let matchid = matchaddpos('{}', [{}], -100)")""" + .format(winid, hl_group, str([line_num, col, length]))) + else: + i += 1 + + def highlightOneline(self, winid, content, minus_beg, plus_beg): + sm = SequenceMatcher(None, content[minus_beg-1], content[plus_beg-1]) + opcodes = sm.get_opcodes() + if len(opcodes) == 1 and opcodes[0][0] == "replace": + return + + hl_group = "Lf_hl_gitDiffChange" + lfCmd(r"""call win_execute({}, 'let matchid = matchadd(''{}'', ''\%{}l'', -101)')""" + .format(winid, hl_group, minus_beg)) + lfCmd(r"""call win_execute({}, 'let matchid = matchadd(''{}'', ''\%{}l'', -101)')""" + .format(winid, hl_group, plus_beg)) + + for tag, beg1, end1, beg2, end2 in sm.get_opcodes(): + if tag == "delete": + col = lfBytesLen(content[minus_beg-1][:beg1]) + 1 + length = lfBytesLen(content[minus_beg - 1][beg1 : end1]) + hl_group = "Lf_hl_gitDiffText" + lfCmd("""call win_execute({}, "let matchid = matchaddpos('{}', [{}], -100)")""" + .format(winid, hl_group, str([minus_beg, col, length]))) + elif tag == "insert": + col = lfBytesLen(content[plus_beg-1][:beg2]) + 1 + length = lfBytesLen(content[plus_beg - 1][beg2 : end2]) + hl_group = "Lf_hl_gitDiffText" + lfCmd("""call win_execute({}, "let matchid = matchaddpos('{}', [{}], -100)")""" + .format(winid, hl_group, str([plus_beg, col, length]))) + elif tag == "replace": + col = lfBytesLen(content[minus_beg-1][:beg1]) + 1 + length = lfBytesLen(content[minus_beg - 1][beg1 : end1]) + hl_group = "Lf_hl_gitDiffText" + lfCmd("""call win_execute({}, "let matchid = matchaddpos('{}', [{}], -100)")""" + .format(winid, hl_group, str([minus_beg, col, length]))) + + col = lfBytesLen(content[plus_beg-1][:beg2]) + 1 + length = lfBytesLen(content[plus_beg - 1][beg2 : end2]) + hl_group = "Lf_hl_gitDiffText" + lfCmd("""call win_execute({}, "let matchid = matchaddpos('{}', [{}], -100)")""" + .format(winid, hl_group, str([plus_beg, col, length]))) + + def highlightDiff(self, winid, content, minus_plus_lines): + for minus_beg, minus_end, plus_beg, plus_end in minus_plus_lines: + if minus_beg == minus_end and plus_beg == plus_end: + self.highlightOneline(winid, content, minus_beg, plus_beg) + continue + + minus_text = content[minus_beg - 1 : minus_end] + plus_text = content[plus_beg - 1 : plus_end] + minus_line_num = minus_beg - 1 + plus_line_num = plus_beg - 1 + status = ' ' + changed_line_num = 0 + for line in Differ().compare(minus_text, plus_text): + if line.startswith('- '): + status = '-' + minus_line_num += 1 + elif line.startswith('+ '): + status = '+' + plus_line_num += 1 + elif line.startswith('? '): + if status == '-': + hl_group = "Lf_hl_gitDiffChange" + changed_line_num = plus_line_num + 1 + lfCmd(r"""call win_execute({}, 'let matchid = matchadd(''{}'', ''\%{}l'', -101)')""" + .format(winid, hl_group, minus_line_num)) + lfCmd(r"""call win_execute({}, 'let matchid = matchadd(''{}'', ''\%{}l'', -101)')""" + .format(winid, hl_group, plus_line_num + 1)) + self.highlight(winid, status, content, minus_line_num, line[2:]) + elif status == '+': + hl_group = "Lf_hl_gitDiffChange" + if changed_line_num != plus_line_num: + lfCmd(r"""call win_execute({}, 'let matchid = matchadd(''{}'', ''\%{}l'', -101)')""" + .format(winid, hl_group, minus_line_num)) + lfCmd(r"""call win_execute({}, 'let matchid = matchadd(''{}'', ''\%{}l'', -101)')""" + .format(winid, hl_group, plus_line_num)) + self.highlight(winid, status, content, plus_line_num, line[2:]) + elif line.startswith(' '): + status = ' ' + minus_line_num += 1 + plus_line_num += 1 + + def setSomeOptions(self): + lfCmd("setlocal foldcolumn=1") + lfCmd("setlocal signcolumn=no") + lfCmd("setlocal nonumber") + lfCmd("setlocal conceallevel=0") + lfCmd("setlocal nowrap") + lfCmd("setlocal foldmethod=expr") + lfCmd("setlocal foldexpr=leaderf#Git#FoldExpr()") + lfCmd("setlocal foldlevel=0") + + def create(self, arguments_dict, source, **kwargs): + """ + source is a tuple like (b90f76fc1, bad07e644, R099, src/version.c, src/version2.c) + """ + buf_name = "LeaderF://{}:{}".format(self._commit_id, lfGetFilePath(source)) + if buf_name in self._views: + winid = self._views[buf_name].getWindowId() + lfCmd("call win_gotoid({})".format(winid)) + else: + if kwargs.get("mode", '') == 't': + lfCmd("noautocmd tabnew") + tabmove() + winid = int(lfEval("win_getid()")) + elif "winid" in kwargs: # --explorer + winid = kwargs["winid"] + else: + win_pos = arguments_dict.get("--navigation-position", ["left"])[0] + if win_pos in ["top", "left"]: + lfCmd("wincmd w") + else: + lfCmd("wincmd W") + winid = int(lfEval("win_getid()")) + + if buf_name not in self._hidden_views: + fold_ranges = [] + minus_plus_lines = [] + line_num_dict = {} + change_start_lines = [] + delimiter = lfEval("get(g:, 'Lf_GitDelimiter', '│')") + if source[0].startswith("0000000"): + git_cmd = "git show {}".format(source[1]) + outputs = ParallelExecutor.run(git_cmd) + line_num_width = len(str(len(outputs[0]))) + content = outputs[0] + line_num_content = ["{:>{}} +{}".format(i, line_num_width, delimiter) + for i in range(1, len(content) + 1)] + deleted_line_nums = [] + added_line_nums = range(1, len(outputs[0]) + 1) + elif source[1].startswith("0000000") and source[2] != 'M': + git_cmd = "git show {}".format(source[0]) + outputs = ParallelExecutor.run(git_cmd) + line_num_width = len(str(len(outputs[0]))) + content = outputs[0] + line_num_content = ["{:>{}} -{}".format(i, line_num_width, delimiter) + for i in range(1, len(content) + 1)] + deleted_line_nums = range(1, len(outputs[0]) + 1) + added_line_nums = [] + else: + if source[1].startswith("0000000"): + extra_options = "" + if "--cached" in arguments_dict: + extra_options += " --cached" + + if "extra" in arguments_dict: + extra_options += " " + " ".join(arguments_dict["extra"]) + git_cmd = "git diff -U999999 --no-color {} -- {}".format(extra_options, + source[3]) + else: + git_cmd = "git diff -U999999 --no-color {} {}".format(source[0], source[1]) + outputs = ParallelExecutor.run(git_cmd) + start = 0 + for i, line in enumerate(outputs[0], 1): + if line.startswith("@@"): + start = i + break + + line_num_width = len(str(len(outputs[0]) - start)) + + content = [] + line_num_content = [] + orig_line_num = 0 + line_num = 0 + + minus_beg = 0 + minus_end = 0 + plus_beg = 0 + plus_end = 0 + + change_start = 0 + deleted_line_nums = [] + added_line_nums = [] + context_num = int(lfEval("get(g:, 'Lf_GitContextNum', 6)")) + if context_num < 0: + context_num = 6 + beg = 1 + for i, line in enumerate(islice(outputs[0], start, None), 1): + content.append(line[1:]) + if line.startswith("-"): + # for fold + if beg != 0: + end = i - context_num - 1 + if end > beg: + fold_ranges.append([beg, end]) + beg = 0 + + # for highlight + if plus_beg != 0: + plus_end = i - 1 + minus_plus_lines.append((minus_beg, minus_end, plus_beg, plus_end)) + minus_beg = 0 + plus_beg = 0 + + if minus_beg == 0: + minus_beg = i + + if change_start == 0: + change_start = i + + deleted_line_nums.append(i) + orig_line_num += 1 + line_num_content.append("{:>{}} {:{}} -{}".format(orig_line_num, + line_num_width, + " ", + line_num_width, + delimiter)) + elif line.startswith("+"): + # for fold + if beg != 0: + end = i - context_num - 1 + if end > beg: + fold_ranges.append([beg, end]) + beg = 0 + + # for highlight + if minus_beg != 0 and plus_beg == 0: + minus_end = i - 1 + plus_beg = i + + if change_start == 0: + change_start = i + + added_line_nums.append(i) + line_num += 1 + line_num_dict[line_num] = i + line_num_content.append("{:{}} {:>{}} +{}".format(" ", + line_num_width, + line_num, + line_num_width, + delimiter)) + else: + # for fold + if beg == 0: + beg = i + context_num + + # for highlight + if plus_beg != 0: + plus_end = i - 1 + minus_plus_lines.append((minus_beg, minus_end, plus_beg, plus_end)) + plus_beg = 0 + + minus_beg = 0 + + if change_start != 0: + change_start_lines.append(change_start) + change_start = 0 + + orig_line_num += 1 + line_num += 1 + line_num_dict[line_num] = i + line_num_content.append("{:>{}} {:>{}} {}".format(orig_line_num, + line_num_width, + line_num, + line_num_width, + delimiter)) + else: + # for fold + end = len(outputs[0]) - start + if beg != 0 and end > beg: + fold_ranges.append([beg, end]) + + # for highlight + if plus_beg != 0: + plus_end = end + minus_plus_lines.append((minus_beg, minus_end, plus_beg, plus_end)) + + if change_start != 0: + change_start_lines.append(change_start) + + lfCmd("call win_gotoid({})".format(winid)) + if not vim.current.buffer.name: # buffer name is empty + lfCmd("setlocal bufhidden=wipe") + lfCmd("silent hide edit {}".format(buf_name)) + lfCmd("augroup Lf_Git_Log | augroup END") + lfCmd("autocmd! Lf_Git_Log BufWinEnter call leaderf#Git#SetMatches()") + ranges = (range(sublist[0], sublist[1] + 1) for sublist in fold_ranges) + fold_ranges_dict = {i: 0 for i in itertools.chain.from_iterable(ranges)} + lfCmd("let b:Leaderf_fold_ranges_dict = {}".format(str(fold_ranges_dict))) + lfCmd("silent! IndentLinesDisable") + self.setSomeOptions() + + cmd = GitCustomizeCommand(arguments_dict, "", buf_name, "", "") + view = GitCommandView(self, cmd) + view.line_num_dict = line_num_dict + view.change_start_lines = change_start_lines + view.create(winid, bufhidden='hide', buf_content=content) + + buffer_num = int(lfEval("winbufnr({})".format(winid))) + self.signPlace(added_line_nums, deleted_line_nums, buffer_num) + + self.setLineNumberWin(line_num_content, buffer_num) + self.highlightDiff(winid, content, minus_plus_lines) + lfCmd("let b:Leaderf_matches = getmatches()") + else: + lfCmd("call win_gotoid({})".format(winid)) + if not vim.current.buffer.name: # buffer name is empty + lfCmd("setlocal bufhidden=wipe") + lfCmd("silent hide edit {}".format(buf_name)) + self.bufShown(buf_name, winid) + self.setSomeOptions() + + target_line_num = kwargs.get("line_num", None) + if target_line_num is not None: + target_line_num = int(target_line_num) + line_num = self._views[buf_name].line_num_dict.get(target_line_num, target_line_num) + lfCmd("call win_execute({}, 'norm! {}G0zbzz')".format(winid, line_num)) + else: + change_start_lines = self._views[buf_name].change_start_lines + if len(change_start_lines) == 0: + first_change = 1 + else: + first_change = change_start_lines[0] + lfCmd("call win_execute({}, 'norm! {}G0zbzz')".format(winid, first_change)) + + class NavigationPanel(Panel): def __init__(self, bufhidden_callback=None): self.tree_view = None @@ -2058,15 +2498,14 @@ def __init__(self, project_root, commit_id, owner): self._project_root = project_root self._navigation_panel = NavigationPanel(self.afterBufhidden) self._diff_view_panel = DiffViewPanel(self.afterBufhidden, commit_id) + self._unified_diff_view_panel = UnifiedDiffViewPanel(self.afterBufhidden, commit_id) self._commit_id = commit_id self._owner = owner self._arguments = {} - self._win_pos = None self.tabpage = None self._git_diff_manager = None def _createWindow(self, win_pos, buffer_name): - self._win_pos = win_pos if win_pos == 'top': height = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelHeight', &lines * 0.3)"))) lfCmd("silent! noa keepa keepj abo {}sp {}".format(height, buffer_name)) @@ -2113,6 +2552,12 @@ def defineMaps(self, winid): lfCmd("call win_execute({}, 'call leaderf#Git#ExplorerMaps({})')" .format(winid, id(self))) + def getDiffViewPanel(self): + if self._diff_view_mode == "side_by_side": + return self._diff_view_panel + else: + return self._unified_diff_view_panel + def create(self, arguments_dict, cmd, target_path=None, line_num=None): self._arguments = arguments_dict lfCmd("noautocmd tabnew") @@ -2123,7 +2568,14 @@ def create(self, arguments_dict, cmd, target_path=None, line_num=None): win_pos = arguments_dict.get("--navigation-position", ["left"])[0] winid = self._createWindow(win_pos, cmd.getBufferName()) - callback = partial(self._diff_view_panel.create, + if "-u" in arguments_dict: + self._diff_view_mode = "unified" + elif "-s" in arguments_dict: + self._diff_view_mode = "side_by_side" + else: + self._diff_view_mode = lfEval("get(g:, 'Lf_GitDiffViewMode', 'side_by_side')") + + callback = partial(self.getDiffViewPanel().create, arguments_dict, winid=diff_view_winid, line_num=line_num) @@ -2131,35 +2583,30 @@ def create(self, arguments_dict, cmd, target_path=None, line_num=None): self.defineMaps(self._navigation_panel.getWindowId()) def afterBufhidden(self): - if self._navigation_panel.isHidden() and self._diff_view_panel.isAllHidden(): + if (self._navigation_panel.isHidden() and self._diff_view_panel.isAllHidden() + and self._unified_diff_view_panel.isAllHidden()): lfCmd("call timer_start(1, function('leaderf#Git#Cleanup', [{}]))".format(id(self))) def cleanup(self): self._navigation_panel.cleanup() self._diff_view_panel.cleanup() + self._unified_diff_view_panel.cleanup() def open(self, recursive, **kwargs): source = self._navigation_panel.tree_view.expandOrCollapseFolder(recursive) if source is not None: if kwargs.get("mode", '') == 't': tabpage_count = len(vim.tabpages) - self._diff_view_panel.create(self._arguments, source, mode='t') + self.getDiffViewPanel().create(self._arguments, source, **kwargs) if len(vim.tabpages) > tabpage_count: tabmove() elif len(vim.current.tabpage.windows) == 1: win_pos = self._arguments.get("--navigation-position", ["left"])[0] diff_view_winid = self.splitWindow(win_pos) - self._diff_view_panel.create(self._arguments, source, winid=diff_view_winid) - elif not self._diff_view_panel.hasView(): - if self._win_pos in ["top", "left"]: - lfCmd("wincmd w") - else: - lfCmd("wincmd W") - lfCmd("noautocmd leftabove sp") - diff_view_winid = int(lfEval("win_getid()")) - self._diff_view_panel.create(self._arguments, source, winid=diff_view_winid) + kwargs["winid"] = diff_view_winid + self.getDiffViewPanel().create(self._arguments, source, **kwargs) else: - self._diff_view_panel.create(self._arguments, source, **kwargs) + self.getDiffViewPanel().create(self._arguments, source, **kwargs) if kwargs.get("preview", False) == True: lfCmd("call win_gotoid({})".format(self._navigation_panel.getWindowId())) diff --git a/doc/leaderf.txt b/doc/leaderf.txt index 14081bdf..a7f94adc 100644 --- a/doc/leaderf.txt +++ b/doc/leaderf.txt @@ -1130,46 +1130,60 @@ g:Lf_GitCommands *g:Lf_GitCommands* Define a list of commands you may want to use frequently. The list is as follows: > let g:Lf_GitCommands = [ - \ {"Leaderf git diff": "fuzzy search and view the diffs"}, - \ {"Leaderf git diff --cached": "fuzzy search and view `git diff --cached`"}, - \ {"Leaderf git diff HEAD": "fuzzy search and view `git diff HEAD`"}, - \ {"Leaderf git diff --side-by-side": "fuzzy search and view the side-by-side diffs"}, + \ {"Leaderf git diff": "fuzzy search and view the diffs"}, + \ {"Leaderf git diff --cached": "fuzzy search and view `git diff --cached`"}, + \ {"Leaderf git diff HEAD": "fuzzy search and view `git diff HEAD`"}, + \ {"Leaderf git diff --side-by-side": "fuzzy search and view the side-by-side diffs"}, \ ] < Open the commands panel using `:Leaderf git` . g:Lf_GitFolderIcons *g:Lf_GitFolderIcons* - To customize the folder icons in tree panel. - Default value is { 'open': '', 'closed': '' }. + To customize the folder icons in tree panel. + Default value is { 'open': '', 'closed': '' }. g:Lf_GitAddIcon *g:Lf_GitAddIcon* - To customize the icon of added file in tree panel. - Default value is ''. + To customize the icon of added file in tree panel. + Default value is ''. g:Lf_GitCopyIcon *g:Lf_GitCopyIcon* - To customize the icon of copied file in tree panel. - Default value is ''. + To customize the icon of copied file in tree panel. + Default value is ''. g:Lf_GitDelIcon *g:Lf_GitDelIcon* - To customize the icon of deleted file in tree panel. - Default value is ''. + To customize the icon of deleted file in tree panel. + Default value is ''. g:Lf_GitModifyIcon *g:Lf_GitModifyIcon* - To customize the icon of modified file in tree panel. - Default value is ''. + To customize the icon of modified file in tree panel. + Default value is ''. g:Lf_GitRenameIcon *g:Lf_GitRenameIcon* - To customize the icon of renamed file in tree panel. - Default value is ''. + To customize the icon of renamed file in tree panel. + Default value is ''. g:Lf_GitNavigationPanelHeight *g:Lf_GitNavigationPanelHeight* - To customize the height of navigation(tree) panel. - Default value is &lines * 0.3. + To customize the height of navigation(tree) panel. + Default value is &lines * 0.3. g:Lf_GitNavigationPanelWidth *g:Lf_GitNavigationPanelWidth* - To customize the width of navigation(tree) panel. - Default value is &columns * 0.2. - + To customize the width of navigation(tree) panel. + Default value is &columns * 0.2. + +g:Lf_GitContextNum *g:Lf_GitContextNum* + Show diffs with g:Lf_GitContextNum lines of context. + Default value is 6. + +g:Lf_GitDiffViewMode *g:Lf_GitDiffViewMode* + Show diffs in a side by side view or in a unified view. + Value can be: 'side_by_side' or 'unified'. + Default value is 'side_by_side'. + +g:Lf_GitHightlightLineNumber *g:Lf_GitHightlightLineNumber* + Specify whether to highlight the line number when diff view is in + 'unified' mode. If enabled, the line numbers of changed lines are also + highlighted with 'DiffAdd' or 'DiffDelete'. + Default value is 0. ============================================================================== USAGE *leaderf-usage* From 51dacb7ccc6ef7d5fd455585599c6e52eb7c26d0 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Mon, 20 May 2024 12:47:38 +0800 Subject: [PATCH 210/365] optimize the code --- autoload/leaderf/Git.vim | 13 ++++++++++++- autoload/leaderf/python/leaderf/gitExpl.py | 10 +++------- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/autoload/leaderf/Git.vim b/autoload/leaderf/Git.vim index 336a4e63..1da5f443 100644 --- a/autoload/leaderf/Git.vim +++ b/autoload/leaderf/Git.vim @@ -506,7 +506,7 @@ function! leaderf#Git#FoldExpr() abort return has_key(b:Leaderf_fold_ranges_dict, v:lnum) endfunction -function! leaderf#Git#SetLineNumberWin(line_num_content, buffer_num) +function! leaderf#Git#SetLineNumberWin(line_num_content, buffer_num) abort if len(a:line_num_content) == 0 return endif @@ -547,3 +547,14 @@ function! leaderf#Git#SetLineNumberWin(line_num_content, buffer_num) endif endfor endfunction + + +function! leaderf#Git#SignPlace(added_line_nums, deleted_line_nums, buf_number) abort + for i in a:added_line_nums + call sign_place(0, "LeaderF", "Leaderf_diff_add", a:buf_number, {'lnum': i}) + endfor + + for i in a:deleted_line_nums + call sign_place(0, "LeaderF", "Leaderf_diff_delete", a:buf_number, {'lnum': i}) + endfor +endfunction diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index aa211b72..9e2a3ba5 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -1980,13 +1980,8 @@ def isAllHidden(self): return len(self._views) == 0 def signPlace(self, added_line_nums, deleted_line_nums, buf_number): - for i in added_line_nums: - lfCmd("""call sign_place(0, "LeaderF", "Leaderf_diff_add", %d, {'lnum': %d})""" - % (buf_number, i)) - - for i in deleted_line_nums: - lfCmd("""call sign_place(0, "LeaderF", "Leaderf_diff_delete", %d, {'lnum': %d})""" - % (buf_number, i)) + lfCmd("call leaderf#Git#SignPlace({}, {}, {})" + .format(str(added_line_nums), str(deleted_line_nums), buf_number)) def setLineNumberWin(self, line_num_content, buffer_num): if lfEval("has('nvim')") == '1': @@ -2195,6 +2190,7 @@ def create(self, arguments_dict, source, **kwargs): source[3]) else: git_cmd = "git diff -U999999 --no-color {} {}".format(source[0], source[1]) + outputs = ParallelExecutor.run(git_cmd) start = 0 for i, line in enumerate(outputs[0], 1): From 3a7d1c1eff1eace4503ab0e5107b89d469653b63 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Tue, 21 May 2024 17:37:36 +0800 Subject: [PATCH 211/365] fix issue #1066 add g:Lf_GitWorkingDirectoryMode --- autoload/leaderf/Git.vim | 14 +- .../leaderf/python/leaderf/asyncExecutor.py | 5 +- autoload/leaderf/python/leaderf/gitExpl.py | 176 ++++++++++++------ doc/leaderf.txt | 10 + 4 files changed, 142 insertions(+), 63 deletions(-) diff --git a/autoload/leaderf/Git.vim b/autoload/leaderf/Git.vim index 1da5f443..231e3e08 100644 --- a/autoload/leaderf/Git.vim +++ b/autoload/leaderf/Git.vim @@ -217,7 +217,7 @@ endfunction function! leaderf#Git#CloseFloatWinMouse() abort if exists("b:blame_cursorline") && exists("*getmousepos") let pos = getmousepos() - if pos.winid == b:blame_winid && b:blame_cursorline != pos["line"] + if pos.winid == b:lf_blame_winid && b:blame_cursorline != pos["line"] if exists("b:commit_msg_winid") && winbufnr(b:commit_msg_winid) != -1 call nvim_win_close(b:commit_msg_winid, 1) endif @@ -225,9 +225,9 @@ function! leaderf#Git#CloseFloatWinMouse() abort endif if exists("b:blame_preview_cursorline") && exists("*getmousepos") let pos = getmousepos() - if pos.winid == b:blame_winid && b:blame_preview_cursorline != pos["line"] - if exists("b:preview_winid") && winbufnr(b:preview_winid) != -1 - call nvim_win_close(b:preview_winid, 1) + if pos.winid == b:lf_blame_winid && b:blame_preview_cursorline != pos["line"] + if exists("b:lf_preview_winid") && winbufnr(b:lf_preview_winid) != -1 + call nvim_win_close(b:lf_preview_winid, 1) endif endif endif @@ -235,7 +235,7 @@ endfunction function! leaderf#Git#ShowCommitMessage(message) abort let b:blame_cursorline = line('.') - let b:blame_winid = win_getid() + let b:lf_blame_winid = win_getid() if has("nvim") let borderchars = [ \ [g:Lf_PopupBorders[4], "Lf_hl_popupBorder"], @@ -370,8 +370,8 @@ function! leaderf#Git#CloseFloatWin() abort if exists("b:commit_msg_winid") && winbufnr(b:commit_msg_winid) != -1 call nvim_win_close(b:commit_msg_winid, 1) endif - if exists("b:preview_winid") && winbufnr(b:preview_winid) != -1 - call nvim_win_close(b:preview_winid, 1) + if exists("b:lf_preview_winid") && winbufnr(b:lf_preview_winid) != -1 + call nvim_win_close(b:lf_preview_winid, 1) endif endfunction diff --git a/autoload/leaderf/python/leaderf/asyncExecutor.py b/autoload/leaderf/python/leaderf/asyncExecutor.py index 3f6acaf4..160fe8bb 100644 --- a/autoload/leaderf/python/leaderf/asyncExecutor.py +++ b/autoload/leaderf/python/leaderf/asyncExecutor.py @@ -35,13 +35,15 @@ def _readerThread(self, fd, queue): finally: queue.put(None) - def execute(self, cmd, encoding=None, cleanup=None, env=None, raise_except=True, format_line=None): + def execute(self, cmd, encoding=None, cleanup=None, env=None, + raise_except=True, format_line=None, cwd=None): if os.name == 'nt': self._process = subprocess.Popen(cmd, bufsize=-1, stdin=lfDEVNULL, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, + cwd=cwd, env=env, universal_newlines=False) else: @@ -51,6 +53,7 @@ def execute(self, cmd, encoding=None, cleanup=None, env=None, raise_except=True, stderr=subprocess.PIPE, preexec_fn=os.setsid, shell=True, + cwd=cwd, env=env, universal_newlines=False) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 9e2a3ba5..baeaa154 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -25,6 +25,23 @@ matchaddDevIconsExtension, ) +def ensureWorkingDirectory(func): + @wraps(func) + def deco(self, *args, **kwargs): + try: + orig_cwd = lfGetCwd() + changed = False + if self._project_root != orig_cwd: + changed = True + lfChdir(self._project_root) + + return func(self, *args, **kwargs) + finally: + if changed: + lfChdir(orig_cwd) + + return deco + def lfGetFilePath(source): """ source is a tuple like (b90f76fc1, bad07e644, R099, src/version.c, src/version2.c) @@ -454,18 +471,6 @@ def __init__(self, arguments_dict, cmd, buf_name, file_type, file_type_cmd): class ParallelExecutor(object): @staticmethod def run(*cmds, format_line=None, directory=None): - try: - if directory is not None: - orig_cwd = lfGetCwd() - lfChdir(directory) - - return ParallelExecutor._run(*cmds, format_line=format_line) - finally: - if directory is not None: - lfChdir(orig_cwd) - - @staticmethod - def _run(*cmds, format_line=None): outputs = [[] for _ in range(len(cmds))] stop_thread = False @@ -483,7 +488,10 @@ def readContent(content, output): executors = [AsyncExecutor() for _ in range(len(cmds))] workers = [] for i, (exe, cmd) in enumerate(zip(executors, cmds)): - content = exe.execute(cmd, encoding=lfEval("&encoding"), format_line=format_line) + content = exe.execute(cmd, + encoding=lfEval("&encoding"), + format_line=format_line, + cwd=directory) worker = threading.Thread(target=readContent, args=(content, outputs[i])) worker.daemon = True worker.start() @@ -650,7 +658,8 @@ def _readContent(self, encoding): try: content = self._executor.execute(self._cmd.getCommand(), encoding=encoding, - format_line=self._format_line + format_line=self._format_line, + cwd=self._owner.getProjectRoot() ) for line in content: self._content.append(line) @@ -1591,7 +1600,10 @@ def writeBuffer(self): def _readContent(self, encoding): try: - content = self._executor.execute(self._cmd.getCommand(), encoding=encoding) + content = self._executor.execute(self._cmd.getCommand(), + encoding=encoding, + cwd=self._project_root + ) for line in content: self.buildTree(line) if self._stop_reader_thread: @@ -1611,7 +1623,10 @@ def cleanup(self): class Panel(object): def __init__(self): - pass + self._project_root = None + + def getProjectRoot(self): + return self._project_root def register(self, view): pass @@ -1637,6 +1652,7 @@ def writeFinished(self, winid): class ResultPanel(Panel): def __init__(self): + super(ResultPanel, self).__init__() self._views = {} self._sources = set() @@ -1690,6 +1706,7 @@ def writeBuffer(self): class PreviewPanel(Panel): def __init__(self): + super(PreviewPanel, self).__init__() self._view = None self._buffer_contents = {} self._preview_winid = 0 @@ -1704,7 +1721,8 @@ def deregister(self, view): self._view.cleanup() self._view = None - def create(self, cmd, config, buf_content=None): + def create(self, cmd, config, buf_content=None, project_root=None): + self._project_root = project_root if lfEval("has('nvim')") == '1': lfCmd("noautocmd let scratch_buffer = nvim_create_buf(0, 1)") self._preview_winid = int(lfEval("nvim_open_win(scratch_buffer, 0, %s)" @@ -1752,6 +1770,7 @@ def getViewContent(self): class DiffViewPanel(Panel): def __init__(self, bufhidden_callback=None, commit_id=""): + super(DiffViewPanel, self).__init__() self._commit_id = commit_id self._views = {} self._hidden_views = {} @@ -1831,6 +1850,7 @@ def create(self, arguments_dict, source, **kwargs): """ source is a tuple like (b90f76fc1, bad07e644, R099, src/version.c, src/version2.c) """ + self._project_root = kwargs.get("project_root", None) file_path = lfGetFilePath(source) sources = ((source[0], source[2], source[3]), (source[1], source[2], file_path)) @@ -1893,7 +1913,8 @@ def create(self, arguments_dict, source, **kwargs): outputs = [None, None] if (cat_file_cmds[0].getBufferName() not in self._hidden_views and cat_file_cmds[1].getBufferName() not in self._hidden_views): - outputs = ParallelExecutor.run(*[cmd.getCommand() for cmd in cat_file_cmds]) + outputs = ParallelExecutor.run(*[cmd.getCommand() for cmd in cat_file_cmds], + directory=self._project_root) if vim.current.tabpage not in self._buffer_names: self._buffer_names[vim.current.tabpage] = [None, None] @@ -1929,6 +1950,7 @@ def create(self, arguments_dict, source, **kwargs): class UnifiedDiffViewPanel(Panel): def __init__(self, bufhidden_callback=None, commit_id=""): + super(UnifiedDiffViewPanel, self).__init__() self._commit_id = commit_id self._views = {} self._hidden_views = {} @@ -2135,6 +2157,7 @@ def create(self, arguments_dict, source, **kwargs): """ source is a tuple like (b90f76fc1, bad07e644, R099, src/version.c, src/version2.c) """ + self._project_root = kwargs.get("project_root", None) buf_name = "LeaderF://{}:{}".format(self._commit_id, lfGetFilePath(source)) if buf_name in self._views: winid = self._views[buf_name].getWindowId() @@ -2162,7 +2185,7 @@ def create(self, arguments_dict, source, **kwargs): delimiter = lfEval("get(g:, 'Lf_GitDelimiter', '│')") if source[0].startswith("0000000"): git_cmd = "git show {}".format(source[1]) - outputs = ParallelExecutor.run(git_cmd) + outputs = ParallelExecutor.run(git_cmd, directory=self._project_root) line_num_width = len(str(len(outputs[0]))) content = outputs[0] line_num_content = ["{:>{}} +{}".format(i, line_num_width, delimiter) @@ -2171,7 +2194,7 @@ def create(self, arguments_dict, source, **kwargs): added_line_nums = range(1, len(outputs[0]) + 1) elif source[1].startswith("0000000") and source[2] != 'M': git_cmd = "git show {}".format(source[0]) - outputs = ParallelExecutor.run(git_cmd) + outputs = ParallelExecutor.run(git_cmd, directory=self._project_root) line_num_width = len(str(len(outputs[0]))) content = outputs[0] line_num_content = ["{:>{}} -{}".format(i, line_num_width, delimiter) @@ -2191,7 +2214,7 @@ def create(self, arguments_dict, source, **kwargs): else: git_cmd = "git diff -U999999 --no-color {} {}".format(source[0], source[1]) - outputs = ParallelExecutor.run(git_cmd) + outputs = ParallelExecutor.run(git_cmd, directory=self._project_root) start = 0 for i, line in enumerate(outputs[0], 1): if line.startswith("@@"): @@ -2358,6 +2381,7 @@ def create(self, arguments_dict, source, **kwargs): class NavigationPanel(Panel): def __init__(self, bufhidden_callback=None): + super(NavigationPanel, self).__init__() self.tree_view = None self._bufhidden_cb = bufhidden_callback self._is_hidden = False @@ -2392,6 +2416,7 @@ def getWindowId(self): class BlamePanel(Panel): def __init__(self, owner): + super(BlamePanel, self).__init__() self._owner = owner self._views = {} @@ -2403,6 +2428,8 @@ def deregister(self, view): if name in self._views: self._views[name].cleanup() del self._views[name] + if len(self._views) == 0: + self._owner.discardPanel(self.getProjectRoot()) def getAlternateWinid(self, buffer_name): return self._views[buffer_name].getAlternateWinid() @@ -2451,13 +2478,16 @@ def formatLine(arguments_dict, line_num_width, line): else: return line - def create(self, arguments_dict, cmd, content=None): + def create(self, arguments_dict, cmd, project_root=None): + self._project_root = project_root buffer_name = cmd.getBufferName() line_num_width = len(str(len(vim.current.buffer))) + 1 outputs = ParallelExecutor.run(cmd.getCommand(), format_line=partial(BlamePanel.formatLine, arguments_dict, - line_num_width)) + line_num_width), + directory=self._project_root) + line_num_width = max(line_num_width, int(lfEval('&numberwidth'))) if len(outputs[0]) > 0: if buffer_name in self._views and self._views[buffer_name].valid(): @@ -2480,6 +2510,7 @@ def create(self, arguments_dict, cmd, content=None): blame_winid = int(lfEval("win_getid()")) blame_view.create(blame_winid, buf_content=outputs[0]) self._owner.defineMaps(blame_winid) + lfCmd("let b:lf_blame_project_root = '{}'".format(self._project_root)) lfCmd("noautocmd norm! {}Gzt{}G0".format(top_line, cursor_line)) lfCmd("call win_execute({}, 'setlocal scrollbind')".format(winid)) lfCmd("setlocal scrollbind") @@ -2574,7 +2605,8 @@ def create(self, arguments_dict, cmd, target_path=None, line_num=None): callback = partial(self.getDiffViewPanel().create, arguments_dict, winid=diff_view_winid, - line_num=line_num) + line_num=line_num, + project_root=self._project_root) self._navigation_panel.create(cmd, winid, self._project_root, target_path, callback) self.defineMaps(self._navigation_panel.getWindowId()) @@ -2589,6 +2621,7 @@ def cleanup(self): self._unified_diff_view_panel.cleanup() def open(self, recursive, **kwargs): + kwargs["project_root"] = self._project_root source = self._navigation_panel.tree_view.expandOrCollapseFolder(recursive) if source is not None: if kwargs.get("mode", '') == 't': @@ -2611,6 +2644,7 @@ def locateFile(self, path, line_num=None, preview=True): self._navigation_panel.tree_view.locateFile(path) self.open(False, line_num=line_num, preview=preview) + @ensureWorkingDirectory def fuzzySearch(self, recall=False): if self._git_diff_manager is None: self._git_diff_manager = GitDiffExplManager() @@ -2629,6 +2663,7 @@ def fuzzySearch(self, recall=False): self._git_diff_manager.startExplorer("popup", **kwargs) + @ensureWorkingDirectory def showCommitMessage(self): cmd = "git show {} -s --decorate --pretty=fuller".format(self._commit_id) lfCmd("""call leaderf#Git#ShowCommitMessage(systemlist('{}'))""".format(cmd)) @@ -2647,7 +2682,7 @@ def __init__(self): self._git_log_manager = None self._git_blame_manager = None self._selected_content = None - self._project_root = "" + self._project_root = None def _getExplClass(self): return GitExplorer @@ -2696,9 +2731,19 @@ def getExplManager(self, subcommand): else: return super(GitExplManager, self) + def getWorkingDirectory(self, orig_cwd): + wd_mode = lfEval("get(g:, 'Lf_GitWorkingDirectoryMode', 'f')") + if wd_mode == 'f': + cur_buf_name = lfDecode(vim.current.buffer.name) + if cur_buf_name: + return nearestAncestor([".git"], os.path.dirname(cur_buf_name)) + + return nearestAncestor([".git"], orig_cwd) + def checkWorkingDirectory(self): self._orig_cwd = lfGetCwd() - self._project_root = nearestAncestor([".git"], self._orig_cwd) + self._project_root = self.getWorkingDirectory(self._orig_cwd) + if self._project_root: # there exists a root marker in nearest ancestor path lfChdir(self._project_root) else: @@ -2863,7 +2908,9 @@ def getSource(self, line): ("", "", "", file_name1, file_name2)) def _createPreviewWindow(self, config, source, line_num, jump_cmd): - self._preview_panel.create(self.createGitCommand(self._arguments, source), config) + self._preview_panel.create(self.createGitCommand(self._arguments, source), + config, + project_root=self._project_root) self._preview_winid = self._preview_panel.getPreviewWinId() self._setWinOptions(self._preview_winid) @@ -2940,10 +2987,10 @@ def vsplitDiff(self): lfPrintError("No diffs!") def startExplorer(self, win_pos, *args, **kwargs): - if self.checkWorkingDirectory() == False: + arguments_dict = kwargs.get("arguments", {}) + if "--recall" not in arguments_dict and self.checkWorkingDirectory() == False: return - arguments_dict = kwargs.get("arguments", {}) if "--recall" not in arguments_dict: self.setArguments(arguments_dict) if ("--current-file" in arguments_dict @@ -3022,6 +3069,7 @@ def _acceptSelection(self, *args, **kwargs): if "accept" in self._arguments: self._arguments["accept"](lfGetFilePath(source)) elif "-s" in self._arguments: + kwargs["project_root"] = self._project_root self._diff_view_panel.create(self._arguments, source, **kwargs) else: if kwargs.get("mode", '') == 't' and source not in self._result_panel.getSources(): @@ -3086,7 +3134,9 @@ def _createPreviewWindow(self, config, source, line_num, jump_cmd): if source is None: return - self._preview_panel.create(self.createGitCommand(self._arguments, source), config) + self._preview_panel.create(self.createGitCommand(self._arguments, source), + config, + project_root=self._project_root) self._preview_winid = self._preview_panel.getPreviewWinId() self._setWinOptions(self._preview_winid) @@ -3109,10 +3159,10 @@ def _useExistingWindow(self, title, source, line_num, jump_cmd): self._preview_panel.setContent(content) def startExplorer(self, win_pos, *args, **kwargs): - if self.checkWorkingDirectory() == False: + arguments_dict = kwargs.get("arguments", {}) + if "--recall" not in arguments_dict and self.checkWorkingDirectory() == False: return - arguments_dict = kwargs.get("arguments", {}) if "--recall" not in arguments_dict: self.setArguments(arguments_dict) if ("--current-file" in arguments_dict @@ -3243,10 +3293,13 @@ def cleanupExplorerPage(self): class GitBlameExplManager(GitExplManager): def __init__(self): super(GitBlameExplManager, self).__init__() - self._blame_panel = BlamePanel(self) + self._blame_panels = {} # key is commit_id, value is ExplorerPage self._pages = {} + def discardPanel(self, project_root): + del self._blame_panels[project_root] + def createGitCommand(self, arguments_dict, commit_id): return GitBlameCommand(arguments_dict, commit_id) @@ -3279,10 +3332,12 @@ def blamePrevious(self): return line_num, file_name = vim.current.line.rsplit('\t', 1)[1].split(None, 1) - alternate_winid = self._blame_panel.getAlternateWinid(vim.current.buffer.name) + project_root = lfEval("b:lf_blame_project_root") + blame_panel = self._blame_panels[project_root] + alternate_winid = blame_panel.getAlternateWinid(vim.current.buffer.name) blame_winid = lfEval("win_getid()") - if commit_id not in self._blame_panel.getBlameDict(vim.current.buffer.name): + if commit_id not in blame_panel.getBlameDict(vim.current.buffer.name): cmd = 'git log -2 --pretty="%H" --name-status --follow {} -- {}'.format(commit_id, file_name) # output is as below: @@ -3293,7 +3348,7 @@ def blamePrevious(self): # 5a0cd5103deba164a6fb33a5a3f67fb3a5dcf378 # # M tui.py - outputs = ParallelExecutor.run(cmd, directory=self._project_root) + outputs = ParallelExecutor.run(cmd, directory=project_root) name_stat = outputs[0][2] if name_stat.startswith("A") or name_stat.startswith("C"): lfPrintError("First commit of current file!") @@ -3307,7 +3362,7 @@ def blamePrevious(self): parent_commit_id = outputs[0][3] blame_win_width = vim.current.window.width - self._blame_panel.getBlameStack(vim.current.buffer.name).append( + blame_panel.getBlameStack(vim.current.buffer.name).append( ( vim.current.buffer[:], lfEval("winbufnr({})".format(alternate_winid)), @@ -3318,7 +3373,7 @@ def blamePrevious(self): ) alternate_buffer_name = "LeaderF://{}:{}".format(parent_commit_id[:7], orig_name) - blame_buffer_dict = self._blame_panel.getBlameBufferDict(vim.current.buffer.name) + blame_buffer_dict = blame_panel.getBlameBufferDict(vim.current.buffer.name) lfCmd("noautocmd call win_gotoid({})".format(alternate_winid)) if alternate_buffer_name in blame_buffer_dict: @@ -3328,7 +3383,7 @@ def blamePrevious(self): cmd = [GitBlameCommand.buildCommand(self._arguments, parent_commit_id, orig_name), "git show {}:{}".format(parent_commit_id, orig_name) ] - outputs = ParallelExecutor.run(*cmd, directory=self._project_root) + outputs = ParallelExecutor.run(*cmd, directory=project_root) line_num_width = len(str(len(outputs[1]))) + 1 blame_buffer = [BlamePanel.formatLine(self._arguments, line_num_width, line) for line in outputs[0] @@ -3358,14 +3413,14 @@ def blamePrevious(self): lfCmd("call win_execute({}, 'setlocal scrollbind')".format(alternate_winid)) blame_win_width = vim.current.window.width - self._blame_panel.getBlameDict(vim.current.buffer.name)[commit_id] = ( + blame_panel.getBlameDict(vim.current.buffer.name)[commit_id] = ( blame_buffer, alternate_buffer_num, blame_win_width ) blame_buffer_dict[alternate_buffer_name] = (blame_buffer, alternate_buffer_num) else: - self._blame_panel.getBlameStack(vim.current.buffer.name).append( + blame_panel.getBlameStack(vim.current.buffer.name).append( ( vim.current.buffer[:], lfEval("winbufnr({})".format(alternate_winid)), @@ -3377,7 +3432,7 @@ def blamePrevious(self): (blame_buffer, alternate_buffer_num, blame_win_width - ) = self._blame_panel.getBlameDict(vim.current.buffer.name)[commit_id] + ) = blame_panel.getBlameDict(vim.current.buffer.name)[commit_id] lfCmd("noautocmd call win_gotoid({})".format(alternate_winid)) lfCmd("buffer {}".format(alternate_buffer_num)) lfCmd("noautocmd norm! {}Gzz".format(line_num)) @@ -3391,13 +3446,15 @@ def blamePrevious(self): lfCmd("noautocmd norm! {}Gzt{}G0".format(top_line, line_num)) def blameNext(self): - blame_stack = self._blame_panel.getBlameStack(vim.current.buffer.name) + project_root = lfEval("b:lf_blame_project_root") + blame_panel = self._blame_panels[project_root] + blame_stack = blame_panel.getBlameStack(vim.current.buffer.name) if len(blame_stack) == 0: return blame_buffer, alternate_buffer_num, blame_win_width, cursor_line, top_line = blame_stack.pop() blame_winid = lfEval("win_getid()") - alternate_winid = self._blame_panel.getAlternateWinid(vim.current.buffer.name) + alternate_winid = blame_panel.getAlternateWinid(vim.current.buffer.name) lfCmd("noautocmd call win_gotoid({})".format(alternate_winid)) lfCmd("buffer {}".format(alternate_buffer_num)) @@ -3418,7 +3475,8 @@ def showCommitMessage(self): lfPrintError("Not Committed Yet!") return - cmd = "git show {} -s --decorate --pretty=fuller".format(commit_id) + project_root = lfEval("b:lf_blame_project_root") + cmd = "cd {} && git show {} -s --decorate --pretty=fuller".format(project_root, commit_id) lfCmd("""call leaderf#Git#ShowCommitMessage(systemlist('{}'))""".format(cmd)) def open(self): @@ -3440,19 +3498,21 @@ def open(self): lfCmd("autocmd! Lf_Git_Blame TabClosed * call leaderf#Git#CleanupExplorerPage({})" .format(id(self))) - self._pages[commit_id] = ExplorerPage(self._project_root, commit_id, self) + project_root = lfEval("b:lf_blame_project_root") + self._pages[commit_id] = ExplorerPage(project_root, commit_id, self) self._pages[commit_id].create(self._arguments, GitLogExplCommand(self._arguments, commit_id), target_path=file_name, line_num=line_num) - def generateConfig(self): + def generateConfig(self, project_root): maxheight = int(lfEval("get(g:, 'Lf_GitBlamePreviewHeight', {})" .format(vim.current.window.height // 3))) if maxheight < 5: maxheight = 5 - alternate_winid = self._blame_panel.getAlternateWinid(vim.current.buffer.name) + blame_panel = self._blame_panels[project_root] + alternate_winid = blame_panel.getAlternateWinid(vim.current.buffer.name) screenpos = lfEval("screenpos({}, {}, {})".format(alternate_winid, vim.current.window.cursor[0], 1)) @@ -3530,17 +3590,18 @@ def preview(self): if lfEval("has('nvim')") == '1': lfCmd("let b:blame_preview_cursorline = line('.')") - lfCmd("let b:blame_winid = win_getid()") - if lfEval("exists('b:preview_winid') && winbufnr(b:preview_winid) != -1") == '1': - lfCmd("call nvim_win_close(b:preview_winid, 1)") + lfCmd("let b:lf_blame_winid = win_getid()") + if lfEval("exists('b:lf_preview_winid') && winbufnr(b:lf_preview_winid) != -1") == '1': + lfCmd("call nvim_win_close(b:lf_preview_winid, 1)") + project_root = lfEval("b:lf_blame_project_root") cmd = GitShowCommand(self._arguments, commit_id, file_name) - outputs = ParallelExecutor.run(cmd.getCommand(), directory=self._project_root) - self._preview_panel.create(cmd, self.generateConfig(), outputs[0]) + outputs = ParallelExecutor.run(cmd.getCommand(), directory=project_root) + self._preview_panel.create(cmd, self.generateConfig(project_root), outputs[0]) preview_winid = self._preview_panel.getPreviewWinId() self._setWinOptions(preview_winid) if lfEval("has('nvim')") == '1': - lfCmd("let b:preview_winid = {}".format(preview_winid)) + lfCmd("let b:lf_preview_winid = {}".format(preview_winid)) lfCmd("call nvim_win_set_option(%d, 'number', v:false)" % preview_winid) else: lfCmd("call win_execute({}, 'setlocal nonumber')".format(preview_winid)) @@ -3598,7 +3659,12 @@ def startExplorer(self, win_pos, *args, **kwargs): tmp_file_name = f.name self._arguments["--contents"] = [tmp_file_name] - self._blame_panel.create(arguments_dict, self.createGitCommand(self._arguments, None)) + if self._project_root not in self._blame_panels: + self._blame_panels[self._project_root] = BlamePanel(self) + + self._blame_panels[self._project_root].create(arguments_dict, + self.createGitCommand(self._arguments, None), + project_root=self._project_root) if tmp_file_name is not None: os.remove(tmp_file_name) else: diff --git a/doc/leaderf.txt b/doc/leaderf.txt index a7f94adc..fab44b43 100644 --- a/doc/leaderf.txt +++ b/doc/leaderf.txt @@ -1185,6 +1185,16 @@ g:Lf_GitHightlightLineNumber *g:Lf_GitHightlightLineNumber* highlighted with 'DiffAdd' or 'DiffDelete'. Default value is 0. +g:Lf_GitWorkingDirectoryMode *g:Lf_GitWorkingDirectoryMode* + Specify the working directory when launch Leaderf git command. The value + can be: + c - the nearest ancestor directory of current working directory that + contains '.git'. + f - the nearest ancestor directory of current file that contains '.git'. + Fall back to 'c' if no such ancestor directory found. + + Default value is 'f'. + ============================================================================== USAGE *leaderf-usage* From ef4952b0ee9ce57171ddfa2630a9d2b291288237 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 22 May 2024 09:01:27 +0800 Subject: [PATCH 212/365] add g:Lf_GitKeyMap add support for jumping to next and previous change --- autoload/leaderf.vim | 4 +++ autoload/leaderf/Git.vim | 41 ++++++++++++++++++++-- autoload/leaderf/python/leaderf/gitExpl.py | 6 +++- doc/leaderf.txt | 11 ++++++ 4 files changed, 59 insertions(+), 3 deletions(-) diff --git a/autoload/leaderf.vim b/autoload/leaderf.vim index 0843d60d..2662d74a 100644 --- a/autoload/leaderf.vim +++ b/autoload/leaderf.vim @@ -147,6 +147,10 @@ call s:InitVar('g:Lf_GitFolderIcons', { \ 'open': '', \ 'closed': '', \}) +call s:InitVar('g:Lf_GitKeyMap', { + \ 'previous_change': '[c', + \ 'next_change': ']c', + \}) let s:Lf_CommandMap = { \ '': [''], diff --git a/autoload/leaderf/Git.vim b/autoload/leaderf/Git.vim index 231e3e08..9d27f92b 100644 --- a/autoload/leaderf/Git.vim +++ b/autoload/leaderf/Git.vim @@ -223,9 +223,9 @@ function! leaderf#Git#CloseFloatWinMouse() abort endif endif endif - if exists("b:blame_preview_cursorline") && exists("*getmousepos") + if exists("b:lf_blame_preview_cursorline") && exists("*getmousepos") let pos = getmousepos() - if pos.winid == b:lf_blame_winid && b:blame_preview_cursorline != pos["line"] + if pos.winid == b:lf_blame_winid && b:lf_blame_preview_cursorline != pos["line"] if exists("b:lf_preview_winid") && winbufnr(b:lf_preview_winid) != -1 call nvim_win_close(b:lf_preview_winid, 1) endif @@ -558,3 +558,40 @@ function! leaderf#Git#SignPlace(added_line_nums, deleted_line_nums, buf_number) call sign_place(0, "LeaderF", "Leaderf_diff_delete", a:buf_number, {'lnum': i}) endfor endfunction + +function! leaderf#Git#PreviousChange() abort + let n = line('.') + let low = 0 + let high = len(b:lf_change_start_lines) + while low < high + let mid = (low + high)/2 + if b:lf_change_start_lines[mid] < n + let low = mid + 1 + else + let high = mid + endif + endwhile + + if low - 1 >= 0 + exec printf("norm! %dG0", b:lf_change_start_lines[low - 1]) + endif +endfunction + +function! leaderf#Git#NextChange() abort + let n = line('.') + let low = 0 + let size = len(b:lf_change_start_lines) + let high = size + while low < high + let mid = (low + high)/2 + if b:lf_change_start_lines[mid] <= n + let low = mid + 1 + else + let high = mid + endif + endwhile + + if high < size + exec printf("norm! %dG0", b:lf_change_start_lines[high]) + endif +endfunction diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index baeaa154..81eba2a0 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -2357,6 +2357,10 @@ def create(self, arguments_dict, source, **kwargs): self.setLineNumberWin(line_num_content, buffer_num) self.highlightDiff(winid, content, minus_plus_lines) lfCmd("let b:Leaderf_matches = getmatches()") + lfCmd("let b:lf_change_start_lines = {}".format(str(change_start_lines))) + blame_map = lfEval("g:Lf_GitKeyMap") + lfCmd("nnoremap {} :call leaderf#Git#PreviousChange()".format(blame_map["previous_change"])) + lfCmd("nnoremap {} :call leaderf#Git#NextChange()".format(blame_map["next_change"])) else: lfCmd("call win_gotoid({})".format(winid)) if not vim.current.buffer.name: # buffer name is empty @@ -3589,7 +3593,7 @@ def preview(self): line_num = int(line_num) if lfEval("has('nvim')") == '1': - lfCmd("let b:blame_preview_cursorline = line('.')") + lfCmd("let b:lf_blame_preview_cursorline = line('.')") lfCmd("let b:lf_blame_winid = win_getid()") if lfEval("exists('b:lf_preview_winid') && winbufnr(b:lf_preview_winid) != -1") == '1': lfCmd("call nvim_win_close(b:lf_preview_winid, 1)") diff --git a/doc/leaderf.txt b/doc/leaderf.txt index fab44b43..a916c797 100644 --- a/doc/leaderf.txt +++ b/doc/leaderf.txt @@ -1195,6 +1195,17 @@ g:Lf_GitWorkingDirectoryMode *g:Lf_GitWorkingDirectoryMode* Default value is 'f'. +g:Lf_GitKeyMap *g:Lf_GitKeyMap* + Customize the shortcut keys. + Default value is : > + let g:Lf_GitKeyMap = { + \ 'previous_change': '[c', + \ 'next_change': ']c', + \ } +< + it means you can use [c to jump backwards to the previous start of a change + and use ]c to jump forwards to the next start of a change. + ============================================================================== USAGE *leaderf-usage* From b79c6f02683b8f0a63ef7d69f6c40c562f67de5d Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 22 May 2024 23:45:30 +0800 Subject: [PATCH 213/365] add :LeaderfGitNavigationOpen command to open the navigation panel --- autoload/leaderf/Git.vim | 14 ++-- autoload/leaderf/python/leaderf/gitExpl.py | 94 +++++++++++++--------- doc/leaderf.txt | 3 + plugin/leaderf.vim | 1 + 4 files changed, 70 insertions(+), 42 deletions(-) diff --git a/autoload/leaderf/Git.vim b/autoload/leaderf/Git.vim index 9d27f92b..66f509d4 100644 --- a/autoload/leaderf/Git.vim +++ b/autoload/leaderf/Git.vim @@ -430,11 +430,6 @@ function! leaderf#Git#SetMatches() abort call setmatches(b:Leaderf_matches) endfunction -function! leaderf#Git#CleanupExplorerPage(view_id) abort - exec g:Lf_py "import ctypes" - exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value.cleanupExplorerPage()", a:view_id) -endfunction - function! leaderf#Git#Commands() abort if !exists("g:Lf_GitCommands") let g:Lf_GitCommands = [ @@ -595,3 +590,12 @@ function! leaderf#Git#NextChange() abort exec printf("norm! %dG0", b:lf_change_start_lines[high]) endif endfunction + +function! leaderf#Git#ExplorerPageDisplay() abort + if !exists("b:lf_explorer_page_id") || b:lf_explorer_page_id == 0 + return + endif + + exec g:Lf_py "import ctypes" + exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value.openNavigationPanel()", b:lf_explorer_page_id) +endfunction diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 81eba2a0..320bc72a 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -531,9 +531,14 @@ def init(self): def getBufferName(self): return self._cmd.getBufferName() + def getBufferNum(self): + if self._buffer is None: + return -1 + else: + return self._buffer.number + def getWindowId(self): - if lfEval("win_id2tabwin({})".format(self._window_id)) == ['0', '0']: - self._window_id = int(lfEval("bufwinid('{}')".format(escQuote(self._buffer.name)))) + self._window_id = int(lfEval("bufwinid('{}')".format(escQuote(self._buffer.name)))) return self._window_id def setWindowId(self, winid): @@ -1928,6 +1933,8 @@ def create(self, arguments_dict, source, **kwargs): lfCmd("call win_execute({}, 'diffoff | hide edit {}')".format(winid, cmd.getBufferName())) lfCmd("call win_execute({}, 'setlocal cursorlineopt=number')".format(winid)) lfCmd("call win_execute({}, 'setlocal cursorline')".format(winid)) + lfCmd("call win_execute({}, 'let b:lf_explorer_page_id = {}')" + .format(winid, kwargs.get("explorer_page_id", 0))) # if the buffer also in another tabpage, BufHidden is not triggerd # should run this code @@ -2358,6 +2365,7 @@ def create(self, arguments_dict, source, **kwargs): self.highlightDiff(winid, content, minus_plus_lines) lfCmd("let b:Leaderf_matches = getmatches()") lfCmd("let b:lf_change_start_lines = {}".format(str(change_start_lines))) + lfCmd("let b:lf_explorer_page_id = {}".format(kwargs.get("explorer_page_id", 0))) blame_map = lfEval("g:Lf_GitKeyMap") lfCmd("nnoremap {} :call leaderf#Git#PreviousChange()".format(blame_map["previous_change"])) lfCmd("nnoremap {} :call leaderf#Git#NextChange()".format(blame_map["next_change"])) @@ -2388,18 +2396,16 @@ def __init__(self, bufhidden_callback=None): super(NavigationPanel, self).__init__() self.tree_view = None self._bufhidden_cb = bufhidden_callback - self._is_hidden = False def register(self, view): self.tree_view = view def bufHidden(self, view): - self._is_hidden = True if self._bufhidden_cb is not None: self._bufhidden_cb() def isHidden(self): - return self._is_hidden + return lfEval("len(win_findbuf({})) == 0".format(self.tree_view.getBufferNum())) == "1" def cleanup(self): if self.tree_view is not None: @@ -2408,6 +2414,7 @@ def cleanup(self): def create(self, cmd, winid, project_root, target_path, callback): TreeView(self, cmd, project_root, target_path, callback).create(winid, bufhidden="hide") + lfCmd("call win_execute({}, 'let b:lf_navigation_matches = getmatches()')".format(winid)) def writeBuffer(self): # called in idle @@ -2528,14 +2535,44 @@ class ExplorerPage(object): def __init__(self, project_root, commit_id, owner): self._project_root = project_root self._navigation_panel = NavigationPanel(self.afterBufhidden) + self._navigation_buffer_name = None self._diff_view_panel = DiffViewPanel(self.afterBufhidden, commit_id) self._unified_diff_view_panel = UnifiedDiffViewPanel(self.afterBufhidden, commit_id) - self._commit_id = commit_id + self.commit_id = commit_id self._owner = owner self._arguments = {} self.tabpage = None self._git_diff_manager = None + def openNavigationPanel(self): + buffer_name = self._navigation_buffer_name + navigation_winid = int(lfEval("bufwinid('{}')".format(escQuote(buffer_name)))) + if navigation_winid != -1: + lfCmd("call win_gotoid({})".format(navigation_winid)) + return + + current_file_path = vim.current.buffer.name.rsplit(':', 1)[1] + win_pos = self._arguments.get("--navigation-position", ["left"])[0] + if win_pos == 'top': + height = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelHeight', &lines * 0.3)"))) + lfCmd("silent! noa keepa keepj topleft {}sp {}".format(height, buffer_name)) + elif win_pos == 'bottom': + height = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelHeight', &lines * 0.3)"))) + lfCmd("silent! noa keepa keepj botright {}sp {}".format(height, buffer_name)) + elif win_pos == 'left': + width = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelWidth', &columns * 0.2)"))) + lfCmd("silent! noa keepa keepj topleft {}vsp {}".format(width, buffer_name)) + elif win_pos == 'right': + width = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelWidth', &columns * 0.2)"))) + lfCmd("silent! noa keepa keepj botright {}vsp {}".format(width, buffer_name)) + else: # left + width = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelWidth', &columns * 0.2)"))) + lfCmd("silent! noa keepa keepj topleft {}vsp {}".format(width, buffer_name)) + + lfCmd("call setmatches(b:lf_navigation_matches)") + lfCmd("setlocal winfixwidth | wincmd =") + self._navigation_panel.tree_view.locateFile(current_file_path) + def _createWindow(self, win_pos, buffer_name): if win_pos == 'top': height = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelHeight', &lines * 0.3)"))) @@ -2597,7 +2634,8 @@ def create(self, arguments_dict, cmd, target_path=None, line_num=None): diff_view_winid = int(lfEval("win_getid()")) win_pos = arguments_dict.get("--navigation-position", ["left"])[0] - winid = self._createWindow(win_pos, cmd.getBufferName()) + self._navigation_buffer_name = cmd.getBufferName() + winid = self._createWindow(win_pos, self._navigation_buffer_name) if "-u" in arguments_dict: self._diff_view_mode = "unified" @@ -2610,7 +2648,8 @@ def create(self, arguments_dict, cmd, target_path=None, line_num=None): arguments_dict, winid=diff_view_winid, line_num=line_num, - project_root=self._project_root) + project_root=self._project_root, + explorer_page_id=id(self)) self._navigation_panel.create(cmd, winid, self._project_root, target_path, callback) self.defineMaps(self._navigation_panel.getWindowId()) @@ -2623,9 +2662,11 @@ def cleanup(self): self._navigation_panel.cleanup() self._diff_view_panel.cleanup() self._unified_diff_view_panel.cleanup() + self._owner.cleanupExplorerPage(self) def open(self, recursive, **kwargs): kwargs["project_root"] = self._project_root + kwargs["explorer_page_id"] = id(self) source = self._navigation_panel.tree_view.expandOrCollapseFolder(recursive) if source is not None: if kwargs.get("mode", '') == 't': @@ -2656,7 +2697,7 @@ def fuzzySearch(self, recall=False): kwargs = {} kwargs["arguments"] = { "owner": self._owner, - "commit_id": self._commit_id, + "commit_id": self.commit_id, "parent": self._navigation_panel.tree_view.getCurrentParent(), "content": self._navigation_panel.tree_view.getFileList(), "accept": self.locateFile @@ -2669,7 +2710,7 @@ def fuzzySearch(self, recall=False): @ensureWorkingDirectory def showCommitMessage(self): - cmd = "git show {} -s --decorate --pretty=fuller".format(self._commit_id) + cmd = "git show {} -s --decorate --pretty=fuller".format(self.commit_id) lfCmd("""call leaderf#Git#ShowCommitMessage(systemlist('{}'))""".format(cmd)) @@ -3017,10 +3058,6 @@ def startExplorer(self, win_pos, *args, **kwargs): self._result_panel.create(self.createGitCommand(self._arguments, None)) self._restoreOrigCwd() elif "--explorer" in self._arguments: - lfCmd("augroup Lf_Git_Diff | augroup END") - lfCmd("autocmd! Lf_Git_Diff TabClosed * call leaderf#Git#CleanupExplorerPage({})" - .format(id(self))) - uid = str(int(time.time()))[-7:] page = ExplorerPage(self._project_root, uid, self) page.create(arguments_dict, GitDiffExplCommand(arguments_dict, uid)) @@ -3093,11 +3130,8 @@ def _acceptSelection(self, *args, **kwargs): def cleanup(self): self._diff_view_panel.cleanup() - def cleanupExplorerPage(self): - for page in self._pages: - if page.tabpage not in vim.tabpages: - self._pages.discard(page) - return + def cleanupExplorerPage(self, page): + self._pages.discard(page) class GitLogExplManager(GitExplManager): @@ -3235,10 +3269,6 @@ def _createExplorerPage(self, commit_id, target_path=None): if commit_id in self._pages: vim.current.tabpage = self._pages[commit_id].tabpage else: - lfCmd("augroup Lf_Git_Log | augroup END") - lfCmd("autocmd! Lf_Git_Log TabClosed * call leaderf#Git#CleanupExplorerPage({})" - .format(id(self))) - self._pages[commit_id] = ExplorerPage(self._project_root, commit_id, self) self._pages[commit_id].create(self._arguments, GitLogExplCommand(self._arguments, commit_id), @@ -3287,11 +3317,8 @@ def cleanup(self): if self._diff_view_panel is not None: self._diff_view_panel.cleanup() - def cleanupExplorerPage(self): - for k, v in self._pages.items(): - if v.tabpage not in vim.tabpages: - del self._pages[k] - return + def cleanupExplorerPage(self, page): + del self._pages[page.commit_id] class GitBlameExplManager(GitExplManager): @@ -3498,10 +3525,6 @@ def open(self): vim.current.tabpage = self._pages[commit_id].tabpage self._pages[commit_id].locateFile(file_name, line_num, False) else: - lfCmd("augroup Lf_Git_Blame | augroup END") - lfCmd("autocmd! Lf_Git_Blame TabClosed * call leaderf#Git#CleanupExplorerPage({})" - .format(id(self))) - project_root = lfEval("b:lf_blame_project_root") self._pages[commit_id] = ExplorerPage(project_root, commit_id, self) self._pages[commit_id].create(self._arguments, @@ -3676,11 +3699,8 @@ def startExplorer(self, win_pos, *args, **kwargs): self._restoreOrigCwd() - def cleanupExplorerPage(self): - for k, v in self._pages.items(): - if v.tabpage not in vim.tabpages: - del self._pages[k] - return + def cleanupExplorerPage(self, page): + del self._pages[page.commit_id] #***************************************************** diff --git a/doc/leaderf.txt b/doc/leaderf.txt index a916c797..3439a385 100644 --- a/doc/leaderf.txt +++ b/doc/leaderf.txt @@ -1288,6 +1288,9 @@ USAGE *leaderf-usage* Show the diffs of current file in a vertical split window. It is a shortcut of `:Leaderf git diff --current-file --side-by-side` +:LeaderfGitNavigationOpen *LeaderfGitNavigationOpen* + Open the navigation panel. + Some handy maps for `Leaderf rg`: | Map | Description diff --git a/plugin/leaderf.vim b/plugin/leaderf.vim index 70b60875..0a963901 100644 --- a/plugin/leaderf.vim +++ b/plugin/leaderf.vim @@ -259,6 +259,7 @@ command! -bar -nargs=0 LeaderfLocList Leaderf loclist command! -bar -nargs=0 LeaderfGit Leaderf git command! -bar -nargs=0 LeaderfGitSplitDiff Leaderf git diff --current-file --side-by-side +command! -bar -nargs=0 LeaderfGitNavigationOpen call leaderf#Git#ExplorerPageDisplay() try if g:Lf_ShortcutF != "" From 5b14ca3e0b12ecdad19e845a31c22376e217835f Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 23 May 2024 15:18:43 +0800 Subject: [PATCH 214/365] get the winid of current tabpage first, if not exist, return the winid of another tabpage --- autoload/leaderf/python/leaderf/gitExpl.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 320bc72a..a281c879 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -538,7 +538,13 @@ def getBufferNum(self): return self._buffer.number def getWindowId(self): - self._window_id = int(lfEval("bufwinid('{}')".format(escQuote(self._buffer.name)))) + self._window_id = int(lfEval("bufwinid({})".format(self._buffer.number))) + # window not exist in current tabpage + if self._window_id == -1: + ids = lfEval("win_findbuf({})".format(self._buffer.number)) + if len(ids) > 0: + self._window_id = int(ids[0]) + return self._window_id def setWindowId(self, winid): From cec47ac91c2abc291a6c012102e9a32dcfbdac13 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 23 May 2024 17:12:13 +0800 Subject: [PATCH 215/365] update help message --- autoload/leaderf/Git.vim | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/autoload/leaderf/Git.vim b/autoload/leaderf/Git.vim index 66f509d4..6f5ba1c6 100644 --- a/autoload/leaderf/Git.vim +++ b/autoload/leaderf/Git.vim @@ -120,6 +120,9 @@ let s:help = { \ ": go to the previous sibling of the current folder", \ "(: go to the start of the current indent level", \ "): go to the end of the current indent level", + \ "q: quit the navigation window", + \ ":LeaderfGitNavigationOpen", + \ " open the navigation window", \ ], \ "blame": [ \ ": toggle the help", @@ -190,7 +193,9 @@ function! leaderf#Git#ShowHelp(type) abort let id = nvim_open_win(scratch_buffer, 1, options) call nvim_win_set_option(id, 'winhighlight', 'Normal:Lf_hl_popup_window') call win_execute(id, 'call matchadd("Special", ''^.\{-}\(:\)\@='')') - call win_execute(id, 'call matchadd("Comment", ''\(^.\{-}:\s*\)\@<=.*'')') + call win_execute(id, 'call matchadd("Special", ''^:\w\+'')') + call win_execute(id, 'call matchadd("Comment", ''\(^.\{-1,}:\s*\)\@<=.*'')') + call win_execute(id, 'call matchadd("Comment", ''\(^\s\+\)\@<=.*'')') call win_execute(id, 'nnoremap c') call win_execute(id, 'nnoremap c') else @@ -209,7 +214,9 @@ function! leaderf#Git#ShowHelp(type) abort let id = popup_create(s:help[a:type], options) call win_execute(id, 'setlocal wincolor=Lf_hl_popup_window') call win_execute(id, 'call matchadd("Special", ''^.\{-}\(:\)\@='')') - call win_execute(id, 'call matchadd("Comment", ''\(^.\{-}:\s*\)\@<=.*'')') + call win_execute(id, 'call matchadd("Special", ''^:\w\+'')') + call win_execute(id, 'call matchadd("Comment", ''\(^.\{-1,}:\s*\)\@<=.*'')') + call win_execute(id, 'call matchadd("Comment", ''\(^\s\+\)\@<=.*'')') endif endfunction From 4d3efa6fe5f95b74181f87e1749174254d803ee0 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Fri, 24 May 2024 14:03:57 +0800 Subject: [PATCH 216/365] add class LfDiffer --- autoload/leaderf/python/leaderf/diff.py | 99 ++++++++++++++++++++++ autoload/leaderf/python/leaderf/gitExpl.py | 5 +- 2 files changed, 102 insertions(+), 2 deletions(-) create mode 100644 autoload/leaderf/python/leaderf/diff.py diff --git a/autoload/leaderf/python/leaderf/diff.py b/autoload/leaderf/python/leaderf/diff.py new file mode 100644 index 00000000..197f4808 --- /dev/null +++ b/autoload/leaderf/python/leaderf/diff.py @@ -0,0 +1,99 @@ +from difflib import * + +class LfDiffer(Differ): + # copyed from https://github.com/python/cpython tag: v3.12.3 + # f6650f9ad73359051f3e558c2431a109bc016664 + def _fancy_replace(self, a, alo, ahi, b, blo, bhi): + r""" + When replacing one block of lines with another, search the blocks + for *similar* lines; the best-matching pair (if any) is used as a + synch point, and intraline difference marking is done on the + similar pair. Lots of work, but often worth it. + + Example: + + >>> d = Differ() + >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1, + ... ['abcdefGhijkl\n'], 0, 1) + >>> print(''.join(results), end="") + - abcDefghiJkl + ? ^ ^ ^ + + abcdefGhijkl + ? ^ ^ ^ + """ + + # don't synch up unless the lines have a similarity score of at + # least cutoff; best_ratio tracks the best score seen so far + best_ratio, cutoff = 0.54, 0.55 + cruncher = SequenceMatcher(self.charjunk) + eqi, eqj = None, None # 1st indices of equal lines (if any) + + # search for the pair that matches best without being identical + # (identical lines must be junk lines, & we don't want to synch up + # on junk -- unless we have to) + for j in range(blo, bhi): + bj = b[j] + cruncher.set_seq2(bj) + for i in range(alo, ahi): + ai = a[i] + if ai == bj: + if eqi is None: + eqi, eqj = i, j + continue + cruncher.set_seq1(ai) + # computing similarity is expensive, so use the quick + # upper bounds first -- have seen this speed up messy + # compares by a factor of 3. + # note that ratio() is only expensive to compute the first + # time it's called on a sequence pair; the expensive part + # of the computation is cached by cruncher + if cruncher.real_quick_ratio() > best_ratio and \ + cruncher.quick_ratio() > best_ratio and \ + cruncher.ratio() > best_ratio: + best_ratio, best_i, best_j = cruncher.ratio(), i, j + if best_ratio < cutoff: + # no non-identical "pretty close" pair + if eqi is None: + # no identical pair either -- treat it as a straight replace + yield from self._plain_replace(a, alo, ahi, b, blo, bhi) + return + # no close pair, but an identical pair -- synch up on that + best_i, best_j, best_ratio = eqi, eqj, 1.0 + else: + # there's a close pair, so forget the identical pair (if any) + eqi = None + + # a[best_i] very similar to b[best_j]; eqi is None iff they're not + # identical + + # pump out diffs from before the synch point + yield from self._fancy_helper(a, alo, best_i, b, blo, best_j) + + # do intraline marking on the synch pair + aelt, belt = a[best_i], b[best_j] + if eqi is None: + # pump out a '-', '?', '+', '?' quad for the synched lines + atags = btags = "" + cruncher.set_seqs(aelt, belt) + for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes(): + la, lb = ai2 - ai1, bj2 - bj1 + if tag == 'replace': + atags += '^' * la + btags += '^' * lb + elif tag == 'delete': + atags += '-' * la + elif tag == 'insert': + btags += '+' * lb + elif tag == 'equal': + atags += ' ' * la + btags += ' ' * lb + else: + raise ValueError('unknown tag %r' % (tag,)) + yield from self._qformat(aelt, belt, atags, btags) + else: + # the synch pair is identical + yield ' ' + aelt + + # pump out diffs from after the synch point + yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi) + diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index a281c879..d9df78f5 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -10,7 +10,7 @@ import bisect import tempfile import itertools -from difflib import Differ, SequenceMatcher +from difflib import SequenceMatcher from itertools import islice from functools import partial from enum import Enum @@ -18,6 +18,7 @@ from .utils import * from .explorer import * from .manager import * +from .diff import LfDiffer from .devicons import ( webDevIconsGetFileTypeSymbol, matchaddDevIconsDefault, @@ -2127,7 +2128,7 @@ def highlightDiff(self, winid, content, minus_plus_lines): plus_line_num = plus_beg - 1 status = ' ' changed_line_num = 0 - for line in Differ().compare(minus_text, plus_text): + for line in LfDiffer().compare(minus_text, plus_text): if line.startswith('- '): status = '-' minus_line_num += 1 From 85e6e7ea6a69f3d77a8c7948a1d6ba9424431adc Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Fri, 24 May 2024 16:39:32 +0800 Subject: [PATCH 217/365] git blame --date iso --- autoload/leaderf/python/leaderf/gitExpl.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index d9df78f5..a6b334ac 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -835,8 +835,8 @@ def enableColor(self, winid): .format("git", lfEval("get(g:, 'Lf_PopupColorscheme', 'default')"))) arguments_dict = self._cmd.getArguments() - date_format = arguments_dict.get("--date", [""])[0] - if date_format in ["", "iso", "short"]: + date_format = arguments_dict.get("--date", ["iso"])[0] + if date_format in ["iso", "short"]: lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_gitBlameDate'', ''\(^\^\?\x\+.*(.\{-}\s\)\@<=\d\{4}-\d\d-\d\d\( \d\d:\d\d:\d\d [+-]\d\d\d\d\)\?'', -100)')""" % winid) elif date_format == "relative": lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_gitBlameDate'', ''\(^\^\?\x\+.*(.\{-}\s\)\@<=\d\+\s\+.\{-}ago'', -100)')""" % winid) @@ -2463,8 +2463,8 @@ def getBlameBufferDict(self, buffer_name): @staticmethod def formatLine(arguments_dict, line_num_width, line): - date_format = arguments_dict.get("--date", [""])[0] - if date_format in ["", "iso", "iso-strict", "short"]: + date_format = arguments_dict.get("--date", ["iso"])[0] + if date_format in ["iso", "iso-strict", "short"]: # 6817817e autoload/leaderf/manager.py 1 (Yggdroot 2014-02-26 00:37:26 +0800 1) #!/usr/bin/env python return re.sub(r'(^\^?\w+)\s+(.*?)\s+(\d+)\s+(\(.*?\d\d)\s+\d+\).*', r'\g<1> \g<4>)\t\g<3> \g<2>', line, 1) From 7c60ba4c6f6803ade667f4b463dcdb1d169c7c54 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Fri, 24 May 2024 16:54:18 +0800 Subject: [PATCH 218/365] remove support for '--date human' --- autoload/leaderf/Any.vim | 6 +++--- autoload/leaderf/python/leaderf/gitExpl.py | 8 -------- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/autoload/leaderf/Any.vim b/autoload/leaderf/Any.vim index 775f8bc3..f72c2ea6 100644 --- a/autoload/leaderf/Any.vim +++ b/autoload/leaderf/Any.vim @@ -262,8 +262,8 @@ let g:Lf_Arguments = { \ ], \ "blame": [ \ {"name": ["-w"], "nargs": 0, "help": "Ignore whitespace when comparing the parent’s version and the child’s to find where the lines came from."}, - \ {"name": ["--date"], "nargs": 1, "choices": ["relative", "local", "iso", "iso-strict", "rfc", "short", "human", "default"], - \ "metavar": "", "help": "Specifies the format used to output dates. .i.e, git blame --date=. can be one of ['relative', 'local', 'iso', 'iso-strict', 'rfc', 'short', 'human', 'default']"}, + \ {"name": ["--date"], "nargs": 1, "choices": ["relative", "local", "iso", "iso-strict", "rfc", "short", "default"], + \ "metavar": "", "help": "Specifies the format used to output dates. .i.e, git blame --date=. can be one of ['relative', 'local', 'iso', 'iso-strict', 'rfc', 'short', 'default']"}, \ ], \ }, \} @@ -412,7 +412,7 @@ function! leaderf#Any#parseArguments(argLead, cmdline, cursorPos) abort if argNum > 3 && argList[1] == "git" && argList[2] == "blame" if get(existingOptions, -1, "") == "--date" - return ["relative", "local", "iso", "iso-strict", "rfc", "short", "human", "default"] + return ["relative", "local", "iso", "iso-strict", "rfc", "short", "default"] endif endif diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index a6b334ac..0e05febb 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -846,8 +846,6 @@ def enableColor(self, winid): lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_gitBlameDate'', ''\(^\^\?\x\+.*(.\{-}\s\)\@<=\d\{4}-\d\d-\d\dT\d\d:\d\d:\d\d[+-]\d\d:\d\d'', -100)')""" % winid) elif date_format == "rfc": lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_gitBlameDate'', ''\(^\^\?\x\+.*(.\{-}\s\)\@<=\(Mon\|Tue\|Wed\|Thu\|Fri\|Sat\|Sun\),\s\+\d\+.\{-}\(\s*)\)\@='', -100)')""" % winid) - elif date_format == "human": - lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_gitBlameDate'', ''\(^\^\?\x\+.*(.\{-}\s\)\@<=\a\{3}\s\+\d\+\s\+\d\{4}\(\s*)\)\@='', -100)')""" % winid) elif date_format == "default": lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_gitBlameDate'', ''\(^\^\?\x\+.*(.\{-}\s\)\@<=\(Mon\|Tue\|Wed\|Thu\|Fri\|Sat\|Sun\)\s\+\a\{3}\s\+\d\+.\{-}\(\s*)\)\@='', -100)')""" % winid) else: @@ -2487,12 +2485,6 @@ def formatLine(arguments_dict, line_num_width, line): return re.sub(r'(^\^?\w+)\s+(.*?)\s+(\d+)\s+(\(.*)', r'\g<1> \g<4>)\t\g<3> \g<2>', line[:-(line_num_width + 1)], 1) - elif date_format == "human": - # 6817817e autoload/leaderf/manager.py 1 (Yggdroot Feb 26 2014 1) #!/usr/bin/env python - line = re.sub(r'(^.*?\s\d+\)).*', r'\g<1>', line, 1) - return re.sub(r'(^\^?\w+)\s+(.*?)\s+(\d+)\s+(\(.*)', - r'\g<1> \g<4>)\t\g<3> \g<2>', - line[:-(line_num_width + 6)], 1) else: return line From a7270479cf65e76a1c400a6d4fe51bea8f14fbe1 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Mon, 27 May 2024 16:08:06 +0800 Subject: [PATCH 219/365] display dates from oldest to most recent using heat map colors --- autoload/leaderf/python/leaderf/gitExpl.py | 160 +++++++++++++++++---- 1 file changed, 135 insertions(+), 25 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 0e05febb..281c1eec 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -421,6 +421,9 @@ def __init__(self, arguments_dict, commit_id): @staticmethod def buildCommand(arguments_dict, commit_id, file_name, use_contents=False): extra_options = "" + if "-c" in arguments_dict: + extra_options += " -c" + if "-w" in arguments_dict: extra_options += " -w" @@ -489,9 +492,13 @@ def readContent(content, output): executors = [AsyncExecutor() for _ in range(len(cmds))] workers = [] for i, (exe, cmd) in enumerate(zip(executors, cmds)): + if isinstance(format_line, list): + format_line_cb = format_line[i] + else: + format_line_cb = format_line content = exe.execute(cmd, encoding=lfEval("&encoding"), - format_line=format_line, + format_line=format_line_cb, cwd=directory) worker = threading.Thread(target=readContent, args=(content, outputs[i])) worker.daemon = True @@ -787,6 +794,19 @@ def __init__(self, owner, cmd): '248': '#a8a8a8', '249': '#b2b2b2', '250': '#bcbcbc', '251': '#c6c6c6', '252': '#d0d0d0', '253': '#dadada', '254': '#e4e4e4', '255': '#eeeeee' } + + self._heat_colors = { + "dark": ['196', '202', '208', '214', '220', '226', '227', '191', '155', '119', + '83', '47', '42', '36', '30', '24', '244', '243', '242', '241', '240' + ], + "light": ['196', '202', '208', '214', '220', '226', '227', '191', '155', '119', + '83', '47', '42', '36', '30', '24', '244', '243', '242', '241', '240' + ] + } + + self._date_dict = {} + self._heat_seconds = [] + self.blame_stack = [] # key is commit id, value is (blame_buffer, alternate_buffer_num) self.blame_dict = {} @@ -824,6 +844,16 @@ def enableColor(self, winid): lfCmd("hi def Lf_hl_blame_{} guifg={} guibg=NONE gui=NONE ctermfg={} ctermbg=NONE cterm=NONE" .format(cterm_color, gui_color, cterm_color)) + stl = "" + for i, cterm_color in enumerate(self._heat_colors[lfEval("&bg")]): + lfCmd("hi def Lf_hl_blame_heat_{} guifg={} guibg=NONE gui=NONE ctermfg={} ctermbg=NONE cterm=NONE" + .format(i, self._color_table[cterm_color], cterm_color)) + lfCmd("call leaderf#colorscheme#popup#link_two('Lf_hl_blame_stl_heat_{}', 'StatusLine', 'Lf_hl_blame_heat_{}', 1)" + .format(i, i)) + stl = "%#Lf_hl_blame_stl_heat_{}#>".format(i) + stl + + lfCmd("let g:Lf_GitStlHeatLine = '{}'".format(stl)) + for i in range(256): lfCmd(r"""call win_execute({}, 'let matchid = matchadd(''Lf_hl_blame_{}'', ''^\^\?{}\x\+'', -100)')""" .format(winid, i, format(i, '02x'))) @@ -834,25 +864,6 @@ def enableColor(self, winid): lfCmd("call leaderf#colorscheme#popup#load('{}', '{}')" .format("git", lfEval("get(g:, 'Lf_PopupColorscheme', 'default')"))) - arguments_dict = self._cmd.getArguments() - date_format = arguments_dict.get("--date", ["iso"])[0] - if date_format in ["iso", "short"]: - lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_gitBlameDate'', ''\(^\^\?\x\+.*(.\{-}\s\)\@<=\d\{4}-\d\d-\d\d\( \d\d:\d\d:\d\d [+-]\d\d\d\d\)\?'', -100)')""" % winid) - elif date_format == "relative": - lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_gitBlameDate'', ''\(^\^\?\x\+.*(.\{-}\s\)\@<=\d\+\s\+.\{-}ago'', -100)')""" % winid) - elif date_format == "local": - lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_gitBlameDate'', ''\(^\^\?\x\+.*(.\{-}\s\)\@<=\(Mon\|Tue\|Wed\|Thu\|Fri\|Sat\|Sun\)\s\+\a\{3}\s\+\d\+.\{-}\(\s*)\)\@='', -100)')""" % winid) - elif date_format == "iso-strict": - lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_gitBlameDate'', ''\(^\^\?\x\+.*(.\{-}\s\)\@<=\d\{4}-\d\d-\d\dT\d\d:\d\d:\d\d[+-]\d\d:\d\d'', -100)')""" % winid) - elif date_format == "rfc": - lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_gitBlameDate'', ''\(^\^\?\x\+.*(.\{-}\s\)\@<=\(Mon\|Tue\|Wed\|Thu\|Fri\|Sat\|Sun\),\s\+\d\+.\{-}\(\s*)\)\@='', -100)')""" % winid) - elif date_format == "default": - lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_gitBlameDate'', ''\(^\^\?\x\+.*(.\{-}\s\)\@<=\(Mon\|Tue\|Wed\|Thu\|Fri\|Sat\|Sun\)\s\+\a\{3}\s\+\d\+.\{-}\(\s*)\)\@='', -100)')""" % winid) - else: - raise ValueError("impossible value of '--date'") - id = int(lfEval("matchid")) - self._match_ids.append(id) - lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''WarningMsg'', ''Not Committed Yet'', -100)')""" % winid) id = int(lfEval("matchid")) self._match_ids.append(id) @@ -889,6 +900,76 @@ def suicide(self): self.blame_stack = [] self.blame_buffer_dict = {} + def highlightHeatDate(self, normal_blame_list, unix_blame_list): + """ + normal_blame_list: + ["6817817e\t( Yggdroot\t10 years ago \t1)#!/usr/bin/env python", + ... + ] + + unix_blame_list: + ["6817817e\t( Yggdroot\t1393346246\t1)#!/usr/bin/env python", + ... + ] + """ + self._date_dict = {} + for i, line in enumerate(normal_blame_list): + commit_id, rest = line.split('\t', 1) + if commit_id not in self._date_dict: + date = rest.split('\t')[1].strip() + timestamp = int(unix_blame_list[i].split('\t')[2]) + self._date_dict[commit_id] = (date, timestamp) + + color_num = len(self._heat_colors[lfEval("&bg")]) + current_time = int(time.time()) + heat_seconds = sorted((current_time - timestamp for date, timestamp in self._date_dict.values())) + heat_seconds_len = len(heat_seconds) + if heat_seconds_len > color_num: + # 2h, 6h, 12h + special_heat_seconds = [7200, 21600, 43200] + index = Bisect.bisect_right(heat_seconds, special_heat_seconds[-1]) + step, remainder = divmod(heat_seconds_len - index, color_num - len(special_heat_seconds)) + if step == 0: + heat_seconds = special_heat_seconds + heat_seconds[index:] + else: + t = heat_seconds[index + step - 1 : heat_seconds_len - remainder : step] + if remainder > 0: + t[-1] = heat_seconds[-1] + heat_seconds = special_heat_seconds + t + + self._heat_seconds = heat_seconds + for date, timestamp in self._date_dict.values(): + index = Bisect.bisect_left(heat_seconds, current_time - timestamp) + id = int(lfEval(r'''matchadd('Lf_hl_blame_heat_{}', '\<{}\>', -100)'''.format(index, date))) + self._match_ids.append(id) + + def highlightRestHeatDate(self, normal_blame_list, unix_blame_list): + """ + normal_blame_list: + ["6817817e\t( Yggdroot\t10 years ago \t1)#!/usr/bin/env python", + ... + ] + + unix_blame_list: + ["6817817e\t( Yggdroot\t1393346246\t1)#!/usr/bin/env python", + ... + ] + """ + date_dict = {} + for i, line in enumerate(normal_blame_list): + commit_id, rest = line.split('\t', 1) + if commit_id not in self._date_dict: + date = rest.split('\t')[1].strip() + timestamp = int(unix_blame_list[i].split('\t')[2]) + self._date_dict[commit_id] = (date, timestamp) + date_dict[commit_id] = (date, timestamp) + + current_time = int(time.time()) + for date, timestamp in date_dict.values(): + index = Bisect.bisect_left(self._heat_seconds, current_time - timestamp) + id = int(lfEval(r'''matchadd('Lf_hl_blame_heat_{}', '\<{}\>', -100)'''.format(index, date))) + self._match_ids.append(id) + class LfOrderedDict(OrderedDict): def last_key(self): @@ -2447,6 +2528,9 @@ def deregister(self, view): if len(self._views) == 0: self._owner.discardPanel(self.getProjectRoot()) + def getBlameView(self, buffer_name): + return self._views[buffer_name] + def getAlternateWinid(self, buffer_name): return self._views[buffer_name].getAlternateWinid() @@ -2492,10 +2576,23 @@ def create(self, arguments_dict, cmd, project_root=None): self._project_root = project_root buffer_name = cmd.getBufferName() line_num_width = len(str(len(vim.current.buffer))) + 1 + + arguments_dict2 = arguments_dict.copy() + arguments_dict2["-c"] = [] + cmd2 = GitBlameCommand(arguments_dict2, None) + + arguments_dict3 = arguments_dict2.copy() + arguments_dict3["--date"] = ["unix"] + cmd3 = GitBlameCommand(arguments_dict3, None) + outputs = ParallelExecutor.run(cmd.getCommand(), - format_line=partial(BlamePanel.formatLine, - arguments_dict, - line_num_width), + cmd2.getCommand(), + cmd3.getCommand(), + format_line=[partial(BlamePanel.formatLine, + arguments_dict, + line_num_width), + None, + None], directory=self._project_root) line_num_width = max(line_num_width, int(lfEval('&numberwidth'))) @@ -2519,12 +2616,13 @@ def create(self, arguments_dict, cmd, project_root=None): buffer_name)) blame_winid = int(lfEval("win_getid()")) blame_view.create(blame_winid, buf_content=outputs[0]) + blame_view.highlightHeatDate(outputs[1], outputs[2]) self._owner.defineMaps(blame_winid) lfCmd("let b:lf_blame_project_root = '{}'".format(self._project_root)) lfCmd("noautocmd norm! {}Gzt{}G0".format(top_line, cursor_line)) lfCmd("call win_execute({}, 'setlocal scrollbind')".format(winid)) lfCmd("setlocal scrollbind") - lfCmd(r"""call win_execute({}, 'let &l:stl=" Press for help."')""" + lfCmd(r"""call win_execute({}, 'let &l:stl=" Press for help.%=".g:Lf_GitStlHeatLine')""" .format(blame_winid)) else: lfPrintError("No need to blame!") @@ -3410,9 +3508,18 @@ def blamePrevious(self): blame_buffer, alternate_buffer_num = blame_buffer_dict[alternate_buffer_name] lfCmd("buffer {}".format(alternate_buffer_num)) else: + arguments_dict2 = self._arguments.copy() + arguments_dict2["-c"] = [] + + arguments_dict3 = arguments_dict2.copy() + arguments_dict3["--date"] = ["unix"] + cmd = [GitBlameCommand.buildCommand(self._arguments, parent_commit_id, orig_name), - "git show {}:{}".format(parent_commit_id, orig_name) + "git show {}:{}".format(parent_commit_id, orig_name), + GitBlameCommand.buildCommand(arguments_dict2, parent_commit_id, orig_name), + GitBlameCommand.buildCommand(arguments_dict3, parent_commit_id, orig_name), ] + outputs = ParallelExecutor.run(*cmd, directory=project_root) line_num_width = len(str(len(outputs[1]))) + 1 blame_buffer = [BlamePanel.formatLine(self._arguments, line_num_width, line) @@ -3442,6 +3549,9 @@ def blamePrevious(self): lfCmd("noautocmd norm! {}Gzt{}G0".format(top_line, line_num)) lfCmd("call win_execute({}, 'setlocal scrollbind')".format(alternate_winid)) + blame_view = blame_panel.getBlameView(vim.current.buffer.name) + blame_view.highlightRestHeatDate(outputs[2], outputs[3]) + blame_win_width = vim.current.window.width blame_panel.getBlameDict(vim.current.buffer.name)[commit_id] = ( blame_buffer, From b301a3b1c1a8026303ae82f9ff7a53db61977220 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Mon, 27 May 2024 20:42:06 +0800 Subject: [PATCH 220/365] update colors --- autoload/leaderf/python/leaderf/gitExpl.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 281c1eec..af6c1d5d 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -796,11 +796,11 @@ def __init__(self, owner, cmd): } self._heat_colors = { - "dark": ['196', '202', '208', '214', '220', '226', '227', '191', '155', '119', - '83', '47', '42', '36', '30', '24', '244', '243', '242', '241', '240' + "dark": ['196', '202', '208', '214', '220', '226', '190', '154', '118', '46', + '47', '48', '49', '50', '51', '45', '39', '33', '27', '21', '243', '241' ], - "light": ['196', '202', '208', '214', '220', '226', '227', '191', '155', '119', - '83', '47', '42', '36', '30', '24', '244', '243', '242', '241', '240' + "light": ['196', '202', '208', '214', '220', '226', '190', '154', '118', '46', + '47', '48', '49', '50', '51', '45', '39', '33', '27', '21', '243', '241' ] } From ffe392d35d377d4655b8f7af2b24955af1d13433 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Tue, 28 May 2024 16:35:21 +0800 Subject: [PATCH 221/365] remove special_heat_seconds 2h, 6h, 12h --- autoload/leaderf/python/leaderf/gitExpl.py | 29 ++++++++++------------ 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index af6c1d5d..ad86ff26 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -796,11 +796,11 @@ def __init__(self, owner, cmd): } self._heat_colors = { - "dark": ['196', '202', '208', '214', '220', '226', '190', '154', '118', '46', - '47', '48', '49', '50', '51', '45', '39', '33', '27', '21', '243', '241' + "dark": ['160', '196', '202', '208', '214', '220', '226', '190', '154', '118', '46', + '47', '48', '49', '50', '51', '45', '39', '33', '27', '21', '244', '242', '240' ], - "light": ['196', '202', '208', '214', '220', '226', '190', '154', '118', '46', - '47', '48', '49', '50', '51', '45', '39', '33', '27', '21', '243', '241' + "light": ['160', '196', '202', '208', '214', '178', '142', '106', '70', '34', '35', + '36', '37', '38', '39', '33', '32', '27', '26', '21', '232' ] } @@ -925,22 +925,18 @@ def highlightHeatDate(self, normal_blame_list, unix_blame_list): heat_seconds = sorted((current_time - timestamp for date, timestamp in self._date_dict.values())) heat_seconds_len = len(heat_seconds) if heat_seconds_len > color_num: - # 2h, 6h, 12h - special_heat_seconds = [7200, 21600, 43200] - index = Bisect.bisect_right(heat_seconds, special_heat_seconds[-1]) - step, remainder = divmod(heat_seconds_len - index, color_num - len(special_heat_seconds)) - if step == 0: - heat_seconds = special_heat_seconds + heat_seconds[index:] - else: - t = heat_seconds[index + step - 1 : heat_seconds_len - remainder : step] + step, remainder = divmod(heat_seconds_len, color_num) + if step > 0: + tmp = heat_seconds[step - 1 : heat_seconds_len - remainder : step] if remainder > 0: - t[-1] = heat_seconds[-1] - heat_seconds = special_heat_seconds + t + tmp[-1] = heat_seconds[-1] + heat_seconds = tmp self._heat_seconds = heat_seconds for date, timestamp in self._date_dict.values(): index = Bisect.bisect_left(heat_seconds, current_time - timestamp) - id = int(lfEval(r'''matchadd('Lf_hl_blame_heat_{}', '\<{}\>', -100)'''.format(index, date))) + id = int(lfEval(r'''matchadd('Lf_hl_blame_heat_{}', '\(, \)\@', -100)''' + .format(index, date))) self._match_ids.append(id) def highlightRestHeatDate(self, normal_blame_list, unix_blame_list): @@ -967,7 +963,8 @@ def highlightRestHeatDate(self, normal_blame_list, unix_blame_list): current_time = int(time.time()) for date, timestamp in date_dict.values(): index = Bisect.bisect_left(self._heat_seconds, current_time - timestamp) - id = int(lfEval(r'''matchadd('Lf_hl_blame_heat_{}', '\<{}\>', -100)'''.format(index, date))) + id = int(lfEval(r'''matchadd('Lf_hl_blame_heat_{}', '\(, \)\@', -100)''' + .format(index, date))) self._match_ids.append(id) From aa354ae3a42681dc2c2bae3df67429e60a4deca4 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Tue, 28 May 2024 17:25:20 +0800 Subject: [PATCH 222/365] show "Not Committed Yet" instead of "External file (--contents)" --- autoload/leaderf/python/leaderf/gitExpl.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index ad86ff26..c108f4b7 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -2542,6 +2542,9 @@ def getBlameBufferDict(self, buffer_name): @staticmethod def formatLine(arguments_dict, line_num_width, line): + if line.startswith("0000000"): + line = line.replace("External file (--contents)", "Not Committed Yet ") + date_format = arguments_dict.get("--date", ["iso"])[0] if date_format in ["iso", "iso-strict", "short"]: # 6817817e autoload/leaderf/manager.py 1 (Yggdroot 2014-02-26 00:37:26 +0800 1) #!/usr/bin/env python From 71fe58a3436d493ebb4418ce9b29390899a50dd6 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 29 May 2024 15:53:05 +0800 Subject: [PATCH 223/365] use s to toggle between side by side diff view and unified diff view --- autoload/leaderf/Git.vim | 2 ++ autoload/leaderf/python/leaderf/gitExpl.py | 24 ++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/autoload/leaderf/Git.vim b/autoload/leaderf/Git.vim index 6f5ba1c6..b2d56a75 100644 --- a/autoload/leaderf/Git.vim +++ b/autoload/leaderf/Git.vim @@ -108,6 +108,7 @@ let s:help = { \ "<2-LeftMouse>: open the folder or open the diffs of current file", \ "O: open the folder recursively", \ "t: open the diffs in a new tabpage", + \ "s: toggle between side by side diff view and unified diff view", \ "p: preview the diffs, i.e., like 'o', but leave the cursor in the current panel", \ "x: collapse the parent folder", \ "X: collapse all the children of the current folder", @@ -365,6 +366,7 @@ function! leaderf#Git#ExplorerMaps(id) abort exec printf('nnoremap :exec g:Lf_py "%s.open(False)"', explorer_page) exec printf('nnoremap O :exec g:Lf_py "%s.open(True)"', explorer_page) exec printf('nnoremap t :exec g:Lf_py "%s.open(False, mode=''t'')"', explorer_page) + exec printf('nnoremap s :exec g:Lf_py "%s.toggleDiffMode()"', explorer_page) exec printf('nnoremap p :exec g:Lf_py "%s.open(False, preview=True)"', explorer_page) exec printf('nnoremap x :call leaderf#Git#CollapseParent("%s")', explorer_page) exec printf('nnoremap f :exec g:Lf_py "%s.fuzzySearch()"', explorer_page) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index c108f4b7..d6b80f2c 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -2018,6 +2018,7 @@ def create(self, arguments_dict, source, **kwargs): lfCmd("call win_execute({}, 'setlocal cursorline')".format(winid)) lfCmd("call win_execute({}, 'let b:lf_explorer_page_id = {}')" .format(winid, kwargs.get("explorer_page_id", 0))) + lfCmd("""call win_execute({}, 'let b:lf_diff_view_mode = "side_by_side"')""".format(winid)) # if the buffer also in another tabpage, BufHidden is not triggerd # should run this code @@ -2037,6 +2038,9 @@ def create(self, arguments_dict, source, **kwargs): else: lfCmd("call win_execute({}, 'norm! gg]c0')".format(target_winid)) + # sometimes the two sides don't align. + lfCmd("call win_execute({}, 'norm! ztzz')".format(target_winid)) + class UnifiedDiffViewPanel(Panel): def __init__(self, bufhidden_callback=None, commit_id=""): @@ -2449,6 +2453,7 @@ def create(self, arguments_dict, source, **kwargs): lfCmd("let b:Leaderf_matches = getmatches()") lfCmd("let b:lf_change_start_lines = {}".format(str(change_start_lines))) lfCmd("let b:lf_explorer_page_id = {}".format(kwargs.get("explorer_page_id", 0))) + lfCmd("let b:lf_diff_view_mode = 'unified'") blame_map = lfEval("g:Lf_GitKeyMap") lfCmd("nnoremap {} :call leaderf#Git#PreviousChange()".format(blame_map["previous_change"])) lfCmd("nnoremap {} :call leaderf#Git#NextChange()".format(blame_map["next_change"])) @@ -2640,6 +2645,7 @@ def __init__(self, project_root, commit_id, owner): self._arguments = {} self.tabpage = None self._git_diff_manager = None + self._diff_view_mode = None def openNavigationPanel(self): buffer_name = self._navigation_buffer_name @@ -2761,11 +2767,29 @@ def cleanup(self): self._unified_diff_view_panel.cleanup() self._owner.cleanupExplorerPage(self) + def toggleDiffMode(self): + if self._diff_view_mode == 'side_by_side': + self._diff_view_mode = 'unified' + else: + self._diff_view_mode = 'side_by_side' + + self.open(False) + + def makeOnly(self): + for w in vim.current.tabpage.windows: + if (lfEval("getbufvar({}, 'lf_diff_view_mode', '{}')".format(w.buffer.number, + self._diff_view_mode)) + != self._diff_view_mode): + lfCmd("only") + break + def open(self, recursive, **kwargs): kwargs["project_root"] = self._project_root kwargs["explorer_page_id"] = id(self) source = self._navigation_panel.tree_view.expandOrCollapseFolder(recursive) if source is not None: + self.makeOnly() + if kwargs.get("mode", '') == 't': tabpage_count = len(vim.tabpages) self.getDiffViewPanel().create(self._arguments, source, **kwargs) From 41bd157b48cddfa95327edb1d009b29fd77d1411 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 29 May 2024 23:16:20 +0800 Subject: [PATCH 224/365] =?UTF-8?q?g:Lf=5FGitRenameIcon=20from=20=EF=91=9A?= =?UTF-8?q?=20to=20=F3=B0=9B=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- autoload/leaderf/python/leaderf/gitExpl.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index d6b80f2c..8c1f0a0c 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -1078,7 +1078,7 @@ def __init__(self, owner, cmd, project_root, target_path, callback): self._copy_icon = lfEval("get(g:, 'Lf_GitCopyIcon', '')") self._del_icon = lfEval("get(g:, 'Lf_GitDelIcon', '')") #   self._modification_icon = lfEval("get(g:, 'Lf_GitModifyIcon', '')") - self._rename_icon = lfEval("get(g:, 'Lf_GitRenameIcon', '')") + self._rename_icon = lfEval("get(g:, 'Lf_GitRenameIcon', '󰛂')") self._status_icons = { "A": self._add_icon, "C": self._copy_icon, From 538cf5d400730057632b06239c0a5e0f2e768986 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 30 May 2024 10:31:12 +0800 Subject: [PATCH 225/365] =?UTF-8?q?Revert=20"g:Lf=5FGitRenameIcon=20from?= =?UTF-8?q?=20=EF=91=9A=20to=20=F3=B0=9B=82"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 41bd157b48cddfa95327edb1d009b29fd77d1411. --- autoload/leaderf/python/leaderf/gitExpl.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 8c1f0a0c..d6b80f2c 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -1078,7 +1078,7 @@ def __init__(self, owner, cmd, project_root, target_path, callback): self._copy_icon = lfEval("get(g:, 'Lf_GitCopyIcon', '')") self._del_icon = lfEval("get(g:, 'Lf_GitDelIcon', '')") #   self._modification_icon = lfEval("get(g:, 'Lf_GitModifyIcon', '')") - self._rename_icon = lfEval("get(g:, 'Lf_GitRenameIcon', '󰛂')") + self._rename_icon = lfEval("get(g:, 'Lf_GitRenameIcon', '')") self._status_icons = { "A": self._add_icon, "C": self._copy_icon, From cd40460f1f1dafad2b3e87c49df4bd6ab9a38048 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 30 May 2024 11:12:49 +0800 Subject: [PATCH 226/365] side_by_side => side-by-side --- autoload/leaderf/python/leaderf/gitExpl.py | 12 ++++++------ doc/leaderf.txt | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index d6b80f2c..fd3281df 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -2018,7 +2018,7 @@ def create(self, arguments_dict, source, **kwargs): lfCmd("call win_execute({}, 'setlocal cursorline')".format(winid)) lfCmd("call win_execute({}, 'let b:lf_explorer_page_id = {}')" .format(winid, kwargs.get("explorer_page_id", 0))) - lfCmd("""call win_execute({}, 'let b:lf_diff_view_mode = "side_by_side"')""".format(winid)) + lfCmd("""call win_execute({}, 'let b:lf_diff_view_mode = "side-by-side"')""".format(winid)) # if the buffer also in another tabpage, BufHidden is not triggerd # should run this code @@ -2724,7 +2724,7 @@ def defineMaps(self, winid): .format(winid, id(self))) def getDiffViewPanel(self): - if self._diff_view_mode == "side_by_side": + if self._diff_view_mode == "side-by-side": return self._diff_view_panel else: return self._unified_diff_view_panel @@ -2743,9 +2743,9 @@ def create(self, arguments_dict, cmd, target_path=None, line_num=None): if "-u" in arguments_dict: self._diff_view_mode = "unified" elif "-s" in arguments_dict: - self._diff_view_mode = "side_by_side" + self._diff_view_mode = "side-by-side" else: - self._diff_view_mode = lfEval("get(g:, 'Lf_GitDiffViewMode', 'side_by_side')") + self._diff_view_mode = lfEval("get(g:, 'Lf_GitDiffViewMode', 'side-by-side')") callback = partial(self.getDiffViewPanel().create, arguments_dict, @@ -2768,10 +2768,10 @@ def cleanup(self): self._owner.cleanupExplorerPage(self) def toggleDiffMode(self): - if self._diff_view_mode == 'side_by_side': + if self._diff_view_mode == 'side-by-side': self._diff_view_mode = 'unified' else: - self._diff_view_mode = 'side_by_side' + self._diff_view_mode = 'side-by-side' self.open(False) diff --git a/doc/leaderf.txt b/doc/leaderf.txt index 3439a385..ac2d6ca6 100644 --- a/doc/leaderf.txt +++ b/doc/leaderf.txt @@ -1176,8 +1176,8 @@ g:Lf_GitContextNum *g:Lf_GitContextNum* g:Lf_GitDiffViewMode *g:Lf_GitDiffViewMode* Show diffs in a side by side view or in a unified view. - Value can be: 'side_by_side' or 'unified'. - Default value is 'side_by_side'. + Value can be: 'side-by-side' or 'unified'. + Default value is 'side-by-side'. g:Lf_GitHightlightLineNumber *g:Lf_GitHightlightLineNumber* Specify whether to highlight the line number when diff view is in From f0d94adc59e3fd67cabebdfb2e048d9b238c46b6 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 30 May 2024 15:24:32 +0800 Subject: [PATCH 227/365] use mouse to select the diff view mode --- autoload/leaderf/Git.vim | 4 +- .../leaderf/colorscheme/popup/default.vim | 4 ++ autoload/leaderf/python/leaderf/gitExpl.py | 54 ++++++++++++++++++- 3 files changed, 60 insertions(+), 2 deletions(-) diff --git a/autoload/leaderf/Git.vim b/autoload/leaderf/Git.vim index b2d56a75..5443df11 100644 --- a/autoload/leaderf/Git.vim +++ b/autoload/leaderf/Git.vim @@ -366,12 +366,14 @@ function! leaderf#Git#ExplorerMaps(id) abort exec printf('nnoremap :exec g:Lf_py "%s.open(False)"', explorer_page) exec printf('nnoremap O :exec g:Lf_py "%s.open(True)"', explorer_page) exec printf('nnoremap t :exec g:Lf_py "%s.open(False, mode=''t'')"', explorer_page) - exec printf('nnoremap s :exec g:Lf_py "%s.toggleDiffMode()"', explorer_page) + exec printf('nnoremap s :exec g:Lf_py "%s.toggleDiffViewMode()"', explorer_page) exec printf('nnoremap p :exec g:Lf_py "%s.open(False, preview=True)"', explorer_page) exec printf('nnoremap x :call leaderf#Git#CollapseParent("%s")', explorer_page) exec printf('nnoremap f :exec g:Lf_py "%s.fuzzySearch()"', explorer_page) exec printf('nnoremap F :exec g:Lf_py "%s.fuzzySearch(True)"', explorer_page) exec printf('nnoremap m :exec g:Lf_py "%s.showCommitMessage()"', explorer_page) + exec printf('nnoremap :exec g:Lf_py "%s.selectDiffViewMode()"', explorer_page) + exec printf('nnoremap :exec g:Lf_py "%s.selectDiffViewMode()"', explorer_page) nnoremap q :q endfunction diff --git a/autoload/leaderf/colorscheme/popup/default.vim b/autoload/leaderf/colorscheme/popup/default.vim index ebab4563..ce3a103c 100644 --- a/autoload/leaderf/colorscheme/popup/default.vim +++ b/autoload/leaderf/colorscheme/popup/default.vim @@ -168,6 +168,8 @@ if &background ==? 'dark' highlight def link Lf_hl_gitGraph4 Lf_hl_gitGraph1 highlight def link Lf_hl_gitGraphSlash Constant highlight def link Lf_hl_gitBlameDate Number + highlight def link Lf_hl_gitSelectedOption Tag + highlight def link Lf_hl_gitNonSelectedOption Comment call leaderf#colorscheme#popup#link_no_reverse("Lf_hl_gitDiffAdd", "DiffAdd") call leaderf#colorscheme#popup#link_no_reverse("Lf_hl_gitDiffDelete", "DiffDelete") call leaderf#colorscheme#popup#link_no_reverse("Lf_hl_gitDiffChange", "DiffChange") @@ -327,6 +329,8 @@ else highlight def link Lf_hl_gitGraph4 Lf_hl_gitGraph1 highlight def link Lf_hl_gitGraphSlash Constant highlight def link Lf_hl_gitBlameDate Number + highlight def link Lf_hl_gitSelectedOption Tag + highlight def link Lf_hl_gitNonSelectedOption Comment call leaderf#colorscheme#popup#link_no_reverse("Lf_hl_gitDiffAdd", "DiffAdd") call leaderf#colorscheme#popup#link_no_reverse("Lf_hl_gitDiffDelete", "DiffDelete") call leaderf#colorscheme#popup#link_no_reverse("Lf_hl_gitDiffChange", "DiffChange") diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index fd3281df..82d29fb9 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -1088,11 +1088,20 @@ def __init__(self, owner, cmd, project_root, target_path, callback): } self._head = [ '" Press for help', + ' Side-by-side ✔  Unified ✘', '', self._project_root + "/", ] self._match_ids = [] + def setDiffViewMode(self, mode): + self._buffer.options['modifiable'] = True + if mode == 'side-by-side': + self._buffer[1] = ' Side-by-side ✔  Unified ✘' + else: + self._buffer[1] = ' Side-by-side ✘  Unified ✔' + self._buffer.options['modifiable'] = False + def enableColor(self, winid): if lfEval("hlexists('Lf_hl_help')") == '0': lfCmd("call leaderf#colorscheme#popup#load('{}', '{}')" @@ -1146,6 +1155,27 @@ def enableColor(self, winid): id = int(lfEval("matchid")) self._match_ids.append(id) + lfCmd(r"""call win_execute({}, 'let matchid = matchadd(''Identifier'', '''', -100)')""" + .format(winid)) + id = int(lfEval("matchid")) + self._match_ids.append(id) + lfCmd(r"""call win_execute({}, 'let matchid = matchadd(''Lf_hl_gitSelectedOption'', ''\( \)\@<=\S\+ ✔\@='', -100)')""" + .format(winid)) + id = int(lfEval("matchid")) + self._match_ids.append(id) + lfCmd(r"""call win_execute({}, 'let matchid = matchadd(''Lf_hl_gitDiffAddition'', ''\( \S\+ \)\@<=✔'', -100)')""" + .format(winid)) + id = int(lfEval("matchid")) + self._match_ids.append(id) + lfCmd(r"""call win_execute({}, 'let matchid = matchadd(''Lf_hl_gitNonSelectedOption'', ''\( \)\@<=\S\+ ✘\@='', -100)')""" + .format(winid)) + id = int(lfEval("matchid")) + self._match_ids.append(id) + lfCmd(r"""call win_execute({}, 'let matchid = matchadd(''Lf_hl_gitDiffDeletion'', ''\( \S\+ \)\@<=✘'', -100)')""" + .format(winid)) + id = int(lfEval("matchid")) + self._match_ids.append(id) + def defineMaps(self, winid): lfCmd("call win_execute({}, 'call leaderf#Git#TreeViewMaps({})')" .format(winid, id(self))) @@ -2754,6 +2784,7 @@ def create(self, arguments_dict, cmd, target_path=None, line_num=None): project_root=self._project_root, explorer_page_id=id(self)) self._navigation_panel.create(cmd, winid, self._project_root, target_path, callback) + self._navigation_panel.tree_view.setDiffViewMode(self._diff_view_mode) self.defineMaps(self._navigation_panel.getWindowId()) def afterBufhidden(self): @@ -2767,11 +2798,32 @@ def cleanup(self): self._unified_diff_view_panel.cleanup() self._owner.cleanupExplorerPage(self) - def toggleDiffMode(self): + def selectDiffViewMode(self): + mouse_pos = lfEval("getmousepos()") + if mouse_pos["line"] == '2': + column = int(mouse_pos["column"]) + if column >= 5 and column <= 16: + mode = 'side-by-side' + elif column >= 28 and column <= 34: + mode = 'unified' + else: + mode = None + + if mode is not None and mode != self._diff_view_mode: + self.toggleDiffViewMode() + + def toggleDiffViewMode(self): if self._diff_view_mode == 'side-by-side': self._diff_view_mode = 'unified' else: self._diff_view_mode = 'side-by-side' + self._navigation_panel.tree_view.setDiffViewMode(self._diff_view_mode) + + for w in vim.current.tabpage.windows: + if lfEval("getbufvar({}, 'lf_explorer_page_id', 0)".format(w.buffer.number)) != '0': + current_file_path = w.buffer.name.rsplit(':', 1)[1] + self._navigation_panel.tree_view.locateFile(current_file_path) + break self.open(False) From 47e81c1dbfb05f6830cd55bca56db421ffed80a9 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Fri, 31 May 2024 01:27:31 -0500 Subject: [PATCH 228/365] fix issue #1073 --- autoload/leaderf/python/leaderf/gitExpl.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 82d29fb9..5f524df6 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -1020,6 +1020,9 @@ def __init__(self, iterable, key): self._key = key def __getitem__(self, i): + if self._key is None: + return self._list[i] + return self._key(self._list[i]) def __len__(self): From a8fe81e47ef88dff3d7510e8c8b7fa6e57e5c150 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Fri, 31 May 2024 16:00:26 +0800 Subject: [PATCH 229/365] add support for ignoring whitespace --- autoload/leaderf/Git.vim | 5 +- autoload/leaderf/python/leaderf/gitExpl.py | 104 +++++++++++++++++++-- 2 files changed, 97 insertions(+), 12 deletions(-) diff --git a/autoload/leaderf/Git.vim b/autoload/leaderf/Git.vim index 5443df11..26d892da 100644 --- a/autoload/leaderf/Git.vim +++ b/autoload/leaderf/Git.vim @@ -109,6 +109,7 @@ let s:help = { \ "O: open the folder recursively", \ "t: open the diffs in a new tabpage", \ "s: toggle between side by side diff view and unified diff view", + \ "i: toggle between ignoring whitespace and not ignoring whitespace", \ "p: preview the diffs, i.e., like 'o', but leave the cursor in the current panel", \ "x: collapse the parent folder", \ "X: collapse all the children of the current folder", @@ -367,13 +368,13 @@ function! leaderf#Git#ExplorerMaps(id) abort exec printf('nnoremap O :exec g:Lf_py "%s.open(True)"', explorer_page) exec printf('nnoremap t :exec g:Lf_py "%s.open(False, mode=''t'')"', explorer_page) exec printf('nnoremap s :exec g:Lf_py "%s.toggleDiffViewMode()"', explorer_page) + exec printf('nnoremap i :exec g:Lf_py "%s.toggleIgnoreWhitespace()"', explorer_page) exec printf('nnoremap p :exec g:Lf_py "%s.open(False, preview=True)"', explorer_page) exec printf('nnoremap x :call leaderf#Git#CollapseParent("%s")', explorer_page) exec printf('nnoremap f :exec g:Lf_py "%s.fuzzySearch()"', explorer_page) exec printf('nnoremap F :exec g:Lf_py "%s.fuzzySearch(True)"', explorer_page) exec printf('nnoremap m :exec g:Lf_py "%s.showCommitMessage()"', explorer_page) - exec printf('nnoremap :exec g:Lf_py "%s.selectDiffViewMode()"', explorer_page) - exec printf('nnoremap :exec g:Lf_py "%s.selectDiffViewMode()"', explorer_page) + exec printf('nnoremap :exec g:Lf_py "%s.selectOption()"', explorer_page) nnoremap q :q endfunction diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 5f524df6..13337a11 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -1092,6 +1092,7 @@ def __init__(self, owner, cmd, project_root, target_path, callback): self._head = [ '" Press for help', ' Side-by-side ✔  Unified ✘', + ' Ignore Whitespace 🗷 ', '', self._project_root + "/", ] @@ -1101,10 +1102,29 @@ def setDiffViewMode(self, mode): self._buffer.options['modifiable'] = True if mode == 'side-by-side': self._buffer[1] = ' Side-by-side ✔  Unified ✘' + + if "iwhiteall" in lfEval("&diffopt"): + self._buffer[2] = ' Ignore Whitespace 🗹 ' + else: + self._buffer[2] = ' Ignore Whitespace 🗷 ' else: self._buffer[1] = ' Side-by-side ✘  Unified ✔' self._buffer.options['modifiable'] = False + def setIgnoreWhitespace(self, diff_view_mode, ignore): + self._buffer.options['modifiable'] = True + if diff_view_mode == 'side-by-side': + if "iwhiteall" in lfEval("&diffopt"): + self._buffer[2] = ' Ignore Whitespace 🗹 ' + else: + self._buffer[2] = ' Ignore Whitespace 🗷 ' + else: + if ignore == True: + self._buffer[2] = ' Ignore Whitespace 🗹 ' + else: + self._buffer[2] = ' Ignore Whitespace 🗷 ' + self._buffer.options['modifiable'] = False + def enableColor(self, winid): if lfEval("hlexists('Lf_hl_help')") == '0': lfCmd("call leaderf#colorscheme#popup#load('{}', '{}')" @@ -1178,6 +1198,22 @@ def enableColor(self, winid): .format(winid)) id = int(lfEval("matchid")) self._match_ids.append(id) + lfCmd(r"""call win_execute({}, 'let matchid = matchadd(''Lf_hl_gitSelectedOption'', ''\( \)\@<=Ignore Whitespace 🗹\@='', -100)')""" + .format(winid)) + id = int(lfEval("matchid")) + self._match_ids.append(id) + lfCmd(r"""call win_execute({}, 'let matchid = matchadd(''Lf_hl_gitDiffAddition'', ''\( Ignore Whitespace \)\@<=🗹 '', -100)')""" + .format(winid)) + id = int(lfEval("matchid")) + self._match_ids.append(id) + lfCmd(r"""call win_execute({}, 'let matchid = matchadd(''Lf_hl_gitNonSelectedOption'', ''\( \)\@<=Ignore Whitespace 🗷\@='', -100)')""" + .format(winid)) + id = int(lfEval("matchid")) + self._match_ids.append(id) + lfCmd(r"""call win_execute({}, 'let matchid = matchadd(''Lf_hl_gitDiffDeletion'', ''\( Ignore Whitespace \)\@<=🗷 '', -100)')""" + .format(winid)) + id = int(lfEval("matchid")) + self._match_ids.append(id) def defineMaps(self, winid): lfCmd("call win_execute({}, 'call leaderf#Git#TreeViewMaps({})')" @@ -2052,6 +2088,8 @@ def create(self, arguments_dict, source, **kwargs): lfCmd("call win_execute({}, 'let b:lf_explorer_page_id = {}')" .format(winid, kwargs.get("explorer_page_id", 0))) lfCmd("""call win_execute({}, 'let b:lf_diff_view_mode = "side-by-side"')""".format(winid)) + lfCmd("""call win_execute({}, "let b:lf_diff_view_source = {}")""".format(winid, + str(list(source)))) # if the buffer also in another tabpage, BufHidden is not triggerd # should run this code @@ -2285,7 +2323,10 @@ def create(self, arguments_dict, source, **kwargs): source is a tuple like (b90f76fc1, bad07e644, R099, src/version.c, src/version2.c) """ self._project_root = kwargs.get("project_root", None) - buf_name = "LeaderF://{}:{}".format(self._commit_id, lfGetFilePath(source)) + ignore_whitespace = int(kwargs.get("ignore_whitespace", False)) + buf_name = "LeaderF://{}:{}:{}".format(self._commit_id, + ignore_whitespace, + lfGetFilePath(source)) if buf_name in self._views: winid = self._views[buf_name].getWindowId() lfCmd("call win_gotoid({})".format(winid)) @@ -2336,10 +2377,20 @@ def create(self, arguments_dict, source, **kwargs): if "extra" in arguments_dict: extra_options += " " + " ".join(arguments_dict["extra"]) + + if kwargs.get("ignore_whitespace", False) == True: + extra_options += " -w" + git_cmd = "git diff -U999999 --no-color {} -- {}".format(extra_options, source[3]) else: - git_cmd = "git diff -U999999 --no-color {} {}".format(source[0], source[1]) + extra_options = "" + if kwargs.get("ignore_whitespace", False) == True: + extra_options += " -w" + + git_cmd = "git diff -U999999 --no-color {} {} {}".format(extra_options, + source[0], + source[1]) outputs = ParallelExecutor.run(git_cmd, directory=self._project_root) start = 0 @@ -2487,6 +2538,7 @@ def create(self, arguments_dict, source, **kwargs): lfCmd("let b:lf_change_start_lines = {}".format(str(change_start_lines))) lfCmd("let b:lf_explorer_page_id = {}".format(kwargs.get("explorer_page_id", 0))) lfCmd("let b:lf_diff_view_mode = 'unified'") + lfCmd("let b:lf_diff_view_source = {}".format(str(list(source)))) blame_map = lfEval("g:Lf_GitKeyMap") lfCmd("nnoremap {} :call leaderf#Git#PreviousChange()".format(blame_map["previous_change"])) lfCmd("nnoremap {} :call leaderf#Git#NextChange()".format(blame_map["next_change"])) @@ -2679,6 +2731,7 @@ def __init__(self, project_root, commit_id, owner): self.tabpage = None self._git_diff_manager = None self._diff_view_mode = None + self._ignore_whitespace = False def openNavigationPanel(self): buffer_name = self._navigation_buffer_name @@ -2801,7 +2854,7 @@ def cleanup(self): self._unified_diff_view_panel.cleanup() self._owner.cleanupExplorerPage(self) - def selectDiffViewMode(self): + def selectOption(self): mouse_pos = lfEval("getmousepos()") if mouse_pos["line"] == '2': column = int(mouse_pos["column"]) @@ -2814,21 +2867,48 @@ def selectDiffViewMode(self): if mode is not None and mode != self._diff_view_mode: self.toggleDiffViewMode() + elif mouse_pos["line"] == '3': + column = int(mouse_pos["column"]) + if column >= 5 and column <= 23: + self.toggleIgnoreWhitespace() + + def getExistingSource(self): + for w in vim.current.tabpage.windows: + source = lfEval("getbufvar({}, 'lf_diff_view_source', 0)".format(w.buffer.number)) + if source != '0': + return source + + return None def toggleDiffViewMode(self): if self._diff_view_mode == 'side-by-side': self._diff_view_mode = 'unified' + self._ignore_whitespace = "iwhiteall" in lfEval("&diffopt") else: self._diff_view_mode = 'side-by-side' + if self._ignore_whitespace == True: + lfCmd("set diffopt+=iwhiteall") + else: + lfCmd("set diffopt-=iwhiteall") + self._navigation_panel.tree_view.setDiffViewMode(self._diff_view_mode) - for w in vim.current.tabpage.windows: - if lfEval("getbufvar({}, 'lf_explorer_page_id', 0)".format(w.buffer.number)) != '0': - current_file_path = w.buffer.name.rsplit(':', 1)[1] - self._navigation_panel.tree_view.locateFile(current_file_path) - break + source = self.getExistingSource() + self.open(False, preview=True, diff_view_source=source) - self.open(False) + def toggleIgnoreWhitespace(self): + if self._diff_view_mode == 'side-by-side': + if "iwhiteall" in lfEval("&diffopt"): + lfCmd("set diffopt-=iwhiteall") + else: + lfCmd("set diffopt+=iwhiteall") + else: + self._ignore_whitespace = not self._ignore_whitespace + source = self.getExistingSource() + self.open(False, preview=True, diff_view_source=source) + + self._navigation_panel.tree_view.setIgnoreWhitespace(self._diff_view_mode, + self._ignore_whitespace) def makeOnly(self): for w in vim.current.tabpage.windows: @@ -2841,7 +2921,11 @@ def makeOnly(self): def open(self, recursive, **kwargs): kwargs["project_root"] = self._project_root kwargs["explorer_page_id"] = id(self) - source = self._navigation_panel.tree_view.expandOrCollapseFolder(recursive) + kwargs["ignore_whitespace"] = self._ignore_whitespace + if "diff_view_source" in kwargs: + source = kwargs["diff_view_source"] + else: + source = self._navigation_panel.tree_view.expandOrCollapseFolder(recursive) if source is not None: self.makeOnly() From bf7d3a4d42b2300b81917dd0310f8f00d88f793a Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Fri, 31 May 2024 17:35:48 +0800 Subject: [PATCH 230/365] ensure highlighting of preview --- autoload/leaderf/python/leaderf/gitExpl.py | 1 + 1 file changed, 1 insertion(+) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 13337a11..859eed6c 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -3906,6 +3906,7 @@ def preview(self): lfCmd("call win_execute({}, 'setlocal nonumber')".format(preview_winid)) self.gotoLine(preview_winid, line_num) + lfCmd("call win_execute({}, 'setlocal filetype=diff')".format(preview_winid)) def gotoLine(self, winid, line_num): found = False From ca29fcf9ccb2988c69758052a67dada4fb200b4d Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Sat, 1 Jun 2024 22:21:19 +0800 Subject: [PATCH 231/365] add support for selecting the diff algorithm --- autoload/leaderf/python/leaderf/gitExpl.py | 118 +++++++++++++++------ doc/leaderf.txt | 2 +- 2 files changed, 88 insertions(+), 32 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 859eed6c..edd764cc 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -1091,8 +1091,9 @@ def __init__(self, owner, cmd, project_root, target_path, callback): } self._head = [ '" Press for help', - ' Side-by-side ✔  Unified ✘', + ' Side-by-side  Unified ', ' Ignore Whitespace 🗷 ', + ' Myers  Minimal  Patience  Histogram ', '', self._project_root + "/", ] @@ -1101,14 +1102,19 @@ def __init__(self, owner, cmd, project_root, target_path, callback): def setDiffViewMode(self, mode): self._buffer.options['modifiable'] = True if mode == 'side-by-side': - self._buffer[1] = ' Side-by-side ✔  Unified ✘' + self._buffer[1] = ' Side-by-side  Unified ' - if "iwhiteall" in lfEval("&diffopt"): + diffopt = lfEval("&diffopt") + if "iwhiteall" in diffopt: self._buffer[2] = ' Ignore Whitespace 🗹 ' else: self._buffer[2] = ' Ignore Whitespace 🗷 ' + + if "algorithm:" in diffopt: + algo = re.sub(r".*algorithm:(\w+).*", r"\1", diffopt) + self.setDiffAlgorithm(algo) else: - self._buffer[1] = ' Side-by-side ✘  Unified ✔' + self._buffer[1] = ' Side-by-side  Unified ' self._buffer.options['modifiable'] = False def setIgnoreWhitespace(self, diff_view_mode, ignore): @@ -1125,6 +1131,18 @@ def setIgnoreWhitespace(self, diff_view_mode, ignore): self._buffer[2] = ' Ignore Whitespace 🗷 ' self._buffer.options['modifiable'] = False + def setDiffAlgorithm(self, algorithm): + self._buffer.options['modifiable'] = True + if algorithm == 'myers': + self._buffer[3] = ' Myers  Minimal  Patience  Histogram ' + elif algorithm == 'minimal': + self._buffer[3] = ' Myers  Minimal  Patience  Histogram ' + elif algorithm == 'patience': + self._buffer[3] = ' Myers  Minimal  Patience  Histogram ' + elif algorithm == 'histogram': + self._buffer[3] = ' Myers  Minimal  Patience  Histogram ' + self._buffer.options['modifiable'] = False + def enableColor(self, winid): if lfEval("hlexists('Lf_hl_help')") == '0': lfCmd("call leaderf#colorscheme#popup#load('{}', '{}')" @@ -1182,19 +1200,19 @@ def enableColor(self, winid): .format(winid)) id = int(lfEval("matchid")) self._match_ids.append(id) - lfCmd(r"""call win_execute({}, 'let matchid = matchadd(''Lf_hl_gitSelectedOption'', ''\( \)\@<=\S\+ ✔\@='', -100)')""" + lfCmd(r"""call win_execute({}, 'let matchid = matchadd(''Lf_hl_gitSelectedOption'', ''\S\+ \@='', -100)')""" .format(winid)) id = int(lfEval("matchid")) self._match_ids.append(id) - lfCmd(r"""call win_execute({}, 'let matchid = matchadd(''Lf_hl_gitDiffAddition'', ''\( \S\+ \)\@<=✔'', -100)')""" + lfCmd(r"""call win_execute({}, 'let matchid = matchadd(''Lf_hl_gitDiffAddition'', ''\(\S\+ \)\@<='', -100)')""" .format(winid)) id = int(lfEval("matchid")) self._match_ids.append(id) - lfCmd(r"""call win_execute({}, 'let matchid = matchadd(''Lf_hl_gitNonSelectedOption'', ''\( \)\@<=\S\+ ✘\@='', -100)')""" + lfCmd(r"""call win_execute({}, 'let matchid = matchadd(''Lf_hl_gitNonSelectedOption'', ''\S\+ \@='', -100)')""" .format(winid)) id = int(lfEval("matchid")) self._match_ids.append(id) - lfCmd(r"""call win_execute({}, 'let matchid = matchadd(''Lf_hl_gitDiffDeletion'', ''\( \S\+ \)\@<=✘'', -100)')""" + lfCmd(r"""call win_execute({}, 'let matchid = matchadd(''Lf_hl_gitDiffDeletion'', ''\(\S\+ \)\@<='', -100)')""" .format(winid)) id = int(lfEval("matchid")) self._match_ids.append(id) @@ -2323,9 +2341,17 @@ def create(self, arguments_dict, source, **kwargs): source is a tuple like (b90f76fc1, bad07e644, R099, src/version.c, src/version2.c) """ self._project_root = kwargs.get("project_root", None) - ignore_whitespace = int(kwargs.get("ignore_whitespace", False)) + ignore_whitespace = kwargs.get("ignore_whitespace", False) + diff_algorithm = kwargs.get("diff_algorithm", "myers") + algo_dict = { + "myers": 0, + "minimal": 2, + "patience": 4, + "histogram": 6 + } + uid = algo_dict[diff_algorithm] + int(ignore_whitespace) buf_name = "LeaderF://{}:{}:{}".format(self._commit_id, - ignore_whitespace, + uid, lfGetFilePath(source)) if buf_name in self._views: winid = self._views[buf_name].getWindowId() @@ -2371,21 +2397,21 @@ def create(self, arguments_dict, source, **kwargs): added_line_nums = [] else: if source[1].startswith("0000000"): - extra_options = "" + extra_options = "--diff-algorithm=" + diff_algorithm if "--cached" in arguments_dict: extra_options += " --cached" if "extra" in arguments_dict: extra_options += " " + " ".join(arguments_dict["extra"]) - if kwargs.get("ignore_whitespace", False) == True: + if ignore_whitespace == True: extra_options += " -w" git_cmd = "git diff -U999999 --no-color {} -- {}".format(extra_options, source[3]) else: - extra_options = "" - if kwargs.get("ignore_whitespace", False) == True: + extra_options = "--diff-algorithm=" + diff_algorithm + if ignore_whitespace == True: extra_options += " -w" git_cmd = "git diff -U999999 --no-color {} {} {}".format(extra_options, @@ -2732,6 +2758,7 @@ def __init__(self, project_root, commit_id, owner): self._git_diff_manager = None self._diff_view_mode = None self._ignore_whitespace = False + self._diff_algorithm = 'myers' def openNavigationPanel(self): buffer_name = self._navigation_buffer_name @@ -2749,13 +2776,13 @@ def openNavigationPanel(self): height = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelHeight', &lines * 0.3)"))) lfCmd("silent! noa keepa keepj botright {}sp {}".format(height, buffer_name)) elif win_pos == 'left': - width = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelWidth', &columns * 0.2)"))) + width = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelWidth', 43)"))) lfCmd("silent! noa keepa keepj topleft {}vsp {}".format(width, buffer_name)) elif win_pos == 'right': - width = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelWidth', &columns * 0.2)"))) + width = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelWidth', 43)"))) lfCmd("silent! noa keepa keepj botright {}vsp {}".format(width, buffer_name)) else: # left - width = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelWidth', &columns * 0.2)"))) + width = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelWidth', 43)"))) lfCmd("silent! noa keepa keepj topleft {}vsp {}".format(width, buffer_name)) lfCmd("call setmatches(b:lf_navigation_matches)") @@ -2770,13 +2797,13 @@ def _createWindow(self, win_pos, buffer_name): height = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelHeight', &lines * 0.3)"))) lfCmd("silent! noa keepa keepj bel {}sp {}".format(height, buffer_name)) elif win_pos == 'left': - width = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelWidth', &columns * 0.2)"))) + width = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelWidth', 43)"))) lfCmd("silent! noa keepa keepj abo {}vsp {}".format(width, buffer_name)) elif win_pos == 'right': - width = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelWidth', &columns * 0.2)"))) + width = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelWidth', 43)"))) lfCmd("silent! noa keepa keepj bel {}vsp {}".format(width, buffer_name)) else: # left - width = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelWidth', &columns * 0.2)"))) + width = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelWidth', 43)"))) lfCmd("silent! noa keepa keepj abo {}vsp {}".format(width, buffer_name)) return int(lfEval("win_getid()")) @@ -2791,16 +2818,16 @@ def splitWindow(self, win_pos): height = int(lfEval("&lines")) - height - 4 lfCmd("silent! noa keepa keepj abo {}sp".format(height)) elif win_pos == 'left': - width = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelWidth', &columns * 0.2)"))) - width = int(lfEval("&columns")) - width + 1 + width = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelWidth', 43)"))) + width = int(lfEval("&columns")) - width - 1 lfCmd("silent! noa keepa keepj bel {}vsp".format(width)) elif win_pos == 'right': - width = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelWidth', &columns * 0.2)"))) + width = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelWidth', 43)"))) width = int(lfEval("&columns")) - width - 1 lfCmd("silent! noa keepa keepj abo {}vsp".format(width)) else: # left - width = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelWidth', &columns * 0.2)"))) - width = int(lfEval("&columns")) - width + 1 + width = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelWidth', 43)"))) + width = int(lfEval("&columns")) - width - 1 lfCmd("silent! noa keepa keepj bel {}vsp".format(width)) return int(lfEval("win_getid()")) @@ -2856,11 +2883,11 @@ def cleanup(self): def selectOption(self): mouse_pos = lfEval("getmousepos()") + column = int(mouse_pos["column"]) if mouse_pos["line"] == '2': - column = int(mouse_pos["column"]) - if column >= 5 and column <= 16: + if column >= 5 and column <= 18: mode = 'side-by-side' - elif column >= 28 and column <= 34: + elif column >= 22 and column <= 30: mode = 'unified' else: mode = None @@ -2868,9 +2895,35 @@ def selectOption(self): if mode is not None and mode != self._diff_view_mode: self.toggleDiffViewMode() elif mouse_pos["line"] == '3': - column = int(mouse_pos["column"]) if column >= 5 and column <= 23: self.toggleIgnoreWhitespace() + elif mouse_pos["line"] == '4': + if column >= 5 and column <= 11: + diff_algorithm = 'myers' + elif column >= 15 and column <= 23: + diff_algorithm = 'minimal' + elif column >= 27 and column <= 36: + diff_algorithm = 'patience' + elif column >= 40 and column <= 50: + diff_algorithm = 'histogram' + + if self._diff_algorithm != diff_algorithm: + self._diff_algorithm = diff_algorithm + self.selectDiffAlgorithm() + + def selectDiffAlgorithm(self): + self._navigation_panel.tree_view.setDiffAlgorithm(self._diff_algorithm) + if self._diff_view_mode == 'side-by-side': + lfCmd("set diffopt+=internal") + diffopt = lfEval("&diffopt") + if "algorithm:" in diffopt: + diffopt = re.sub(r"(?<=algorithm:)\w+", self._diff_algorithm, diffopt) + lfCmd("let &diffopt = '{}'".format(diffopt)) + else: + lfCmd("set diffopt+=algorithm:{}".format(self._diff_algorithm)) + else: + source = self.getExistingSource() + self.open(False, preview=True, diff_view_source=source) def getExistingSource(self): for w in vim.current.tabpage.windows: @@ -2902,13 +2955,15 @@ def toggleIgnoreWhitespace(self): lfCmd("set diffopt-=iwhiteall") else: lfCmd("set diffopt+=iwhiteall") + self._navigation_panel.tree_view.setIgnoreWhitespace(self._diff_view_mode, + self._ignore_whitespace) else: self._ignore_whitespace = not self._ignore_whitespace + self._navigation_panel.tree_view.setIgnoreWhitespace(self._diff_view_mode, + self._ignore_whitespace) source = self.getExistingSource() self.open(False, preview=True, diff_view_source=source) - self._navigation_panel.tree_view.setIgnoreWhitespace(self._diff_view_mode, - self._ignore_whitespace) def makeOnly(self): for w in vim.current.tabpage.windows: @@ -2922,6 +2977,7 @@ def open(self, recursive, **kwargs): kwargs["project_root"] = self._project_root kwargs["explorer_page_id"] = id(self) kwargs["ignore_whitespace"] = self._ignore_whitespace + kwargs["diff_algorithm"] = self._diff_algorithm if "diff_view_source" in kwargs: source = kwargs["diff_view_source"] else: diff --git a/doc/leaderf.txt b/doc/leaderf.txt index ac2d6ca6..4e8f925a 100644 --- a/doc/leaderf.txt +++ b/doc/leaderf.txt @@ -1168,7 +1168,7 @@ g:Lf_GitNavigationPanelHeight *g:Lf_GitNavigationPanelHeight* g:Lf_GitNavigationPanelWidth *g:Lf_GitNavigationPanelWidth* To customize the width of navigation(tree) panel. - Default value is &columns * 0.2. + Default value is 43. g:Lf_GitContextNum *g:Lf_GitContextNum* Show diffs with g:Lf_GitContextNum lines of context. From e8e36ea127a9124b603bd22a88cd3b9cd5f8aaf1 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Sun, 2 Jun 2024 12:04:56 +0800 Subject: [PATCH 232/365] error occurs if an ExplorerPage is reopened after being closed --- autoload/leaderf/Git.vim | 2 +- autoload/leaderf/python/leaderf/gitExpl.py | 64 ++++++++++++---------- plugin/leaderf.vim | 2 +- 3 files changed, 38 insertions(+), 30 deletions(-) diff --git a/autoload/leaderf/Git.vim b/autoload/leaderf/Git.vim index 26d892da..c3e843e8 100644 --- a/autoload/leaderf/Git.vim +++ b/autoload/leaderf/Git.vim @@ -603,7 +603,7 @@ function! leaderf#Git#NextChange() abort endif endfunction -function! leaderf#Git#ExplorerPageDisplay() abort +function! leaderf#Git#OpenNavigationPanel() abort if !exists("b:lf_explorer_page_id") || b:lf_explorer_page_id == 0 return endif diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index edd764cc..9dffc415 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -2595,16 +2595,19 @@ def __init__(self, bufhidden_callback=None): super(NavigationPanel, self).__init__() self.tree_view = None self._bufhidden_cb = bufhidden_callback + self._is_hidden = False + self._arguments = {} def register(self, view): self.tree_view = view def bufHidden(self, view): + self._is_hidden = True if self._bufhidden_cb is not None: self._bufhidden_cb() def isHidden(self): - return lfEval("len(win_findbuf({})) == 0".format(self.tree_view.getBufferNum())) == "1" + return self._is_hidden def cleanup(self): if self.tree_view is not None: @@ -2612,9 +2615,40 @@ def cleanup(self): self.tree_view = None def create(self, cmd, winid, project_root, target_path, callback): + self._arguments = cmd.getArguments() TreeView(self, cmd, project_root, target_path, callback).create(winid, bufhidden="hide") lfCmd("call win_execute({}, 'let b:lf_navigation_matches = getmatches()')".format(winid)) + def open(self): + buffer_name = self.tree_view.getBufferName() + navigation_winid = int(lfEval("bufwinid('{}')".format(escQuote(buffer_name)))) + if navigation_winid != -1: + lfCmd("call win_gotoid({})".format(navigation_winid)) + return + + current_file_path = vim.current.buffer.name.rsplit(':', 1)[1] + win_pos = self._arguments.get("--navigation-position", ["left"])[0] + if win_pos == 'top': + height = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelHeight', &lines * 0.3)"))) + lfCmd("silent! noa keepa keepj topleft {}sp {}".format(height, buffer_name)) + elif win_pos == 'bottom': + height = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelHeight', &lines * 0.3)"))) + lfCmd("silent! noa keepa keepj botright {}sp {}".format(height, buffer_name)) + elif win_pos == 'left': + width = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelWidth', 43)"))) + lfCmd("silent! noa keepa keepj topleft {}vsp {}".format(width, buffer_name)) + elif win_pos == 'right': + width = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelWidth', 43)"))) + lfCmd("silent! noa keepa keepj botright {}vsp {}".format(width, buffer_name)) + else: # left + width = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelWidth', 43)"))) + lfCmd("silent! noa keepa keepj topleft {}vsp {}".format(width, buffer_name)) + + lfCmd("call setmatches(b:lf_navigation_matches)") + lfCmd("setlocal winfixwidth | wincmd =") + self._is_hidden = False + self.tree_view.locateFile(current_file_path) + def writeBuffer(self): # called in idle if self.tree_view is not None: @@ -2761,33 +2795,7 @@ def __init__(self, project_root, commit_id, owner): self._diff_algorithm = 'myers' def openNavigationPanel(self): - buffer_name = self._navigation_buffer_name - navigation_winid = int(lfEval("bufwinid('{}')".format(escQuote(buffer_name)))) - if navigation_winid != -1: - lfCmd("call win_gotoid({})".format(navigation_winid)) - return - - current_file_path = vim.current.buffer.name.rsplit(':', 1)[1] - win_pos = self._arguments.get("--navigation-position", ["left"])[0] - if win_pos == 'top': - height = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelHeight', &lines * 0.3)"))) - lfCmd("silent! noa keepa keepj topleft {}sp {}".format(height, buffer_name)) - elif win_pos == 'bottom': - height = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelHeight', &lines * 0.3)"))) - lfCmd("silent! noa keepa keepj botright {}sp {}".format(height, buffer_name)) - elif win_pos == 'left': - width = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelWidth', 43)"))) - lfCmd("silent! noa keepa keepj topleft {}vsp {}".format(width, buffer_name)) - elif win_pos == 'right': - width = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelWidth', 43)"))) - lfCmd("silent! noa keepa keepj botright {}vsp {}".format(width, buffer_name)) - else: # left - width = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelWidth', 43)"))) - lfCmd("silent! noa keepa keepj topleft {}vsp {}".format(width, buffer_name)) - - lfCmd("call setmatches(b:lf_navigation_matches)") - lfCmd("setlocal winfixwidth | wincmd =") - self._navigation_panel.tree_view.locateFile(current_file_path) + self._navigation_panel.open() def _createWindow(self, win_pos, buffer_name): if win_pos == 'top': diff --git a/plugin/leaderf.vim b/plugin/leaderf.vim index 0a963901..6d8b2f2f 100644 --- a/plugin/leaderf.vim +++ b/plugin/leaderf.vim @@ -259,7 +259,7 @@ command! -bar -nargs=0 LeaderfLocList Leaderf loclist command! -bar -nargs=0 LeaderfGit Leaderf git command! -bar -nargs=0 LeaderfGitSplitDiff Leaderf git diff --current-file --side-by-side -command! -bar -nargs=0 LeaderfGitNavigationOpen call leaderf#Git#ExplorerPageDisplay() +command! -bar -nargs=0 LeaderfGitNavigationOpen call leaderf#Git#OpenNavigationPanel() try if g:Lf_ShortcutF != "" From 72b27109ac97d9efe33b4ec1dd3577c95af06baa Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Mon, 3 Jun 2024 10:24:50 +0800 Subject: [PATCH 233/365] change the icon of radio button --- autoload/leaderf/python/leaderf/gitExpl.py | 44 +++++++++++----------- doc/leaderf.txt | 2 +- 2 files changed, 24 insertions(+), 22 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 9dffc415..d885d798 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -1091,9 +1091,9 @@ def __init__(self, owner, cmd, project_root, target_path, callback): } self._head = [ '" Press for help', - ' Side-by-side  Unified ', + ' Side-by-side ◉ Unified ○', ' Ignore Whitespace 🗷 ', - ' Myers  Minimal  Patience  Histogram ', + ' Myers ◉ Minimal ○ Patience ○ Histogram ○', '', self._project_root + "/", ] @@ -1102,7 +1102,7 @@ def __init__(self, owner, cmd, project_root, target_path, callback): def setDiffViewMode(self, mode): self._buffer.options['modifiable'] = True if mode == 'side-by-side': - self._buffer[1] = ' Side-by-side  Unified ' + self._buffer[1] = ' Side-by-side ◉ Unified ○' diffopt = lfEval("&diffopt") if "iwhiteall" in diffopt: @@ -1114,7 +1114,7 @@ def setDiffViewMode(self, mode): algo = re.sub(r".*algorithm:(\w+).*", r"\1", diffopt) self.setDiffAlgorithm(algo) else: - self._buffer[1] = ' Side-by-side  Unified ' + self._buffer[1] = ' Side-by-side ○ Unified ◉' self._buffer.options['modifiable'] = False def setIgnoreWhitespace(self, diff_view_mode, ignore): @@ -1134,13 +1134,13 @@ def setIgnoreWhitespace(self, diff_view_mode, ignore): def setDiffAlgorithm(self, algorithm): self._buffer.options['modifiable'] = True if algorithm == 'myers': - self._buffer[3] = ' Myers  Minimal  Patience  Histogram ' + self._buffer[3] = ' Myers ◉ Minimal ○ Patience ○ Histogram ○' elif algorithm == 'minimal': - self._buffer[3] = ' Myers  Minimal  Patience  Histogram ' + self._buffer[3] = ' Myers ○ Minimal ◉ Patience ○ Histogram ○' elif algorithm == 'patience': - self._buffer[3] = ' Myers  Minimal  Patience  Histogram ' + self._buffer[3] = ' Myers ○ Minimal ○ Patience ◉ Histogram ○' elif algorithm == 'histogram': - self._buffer[3] = ' Myers  Minimal  Patience  Histogram ' + self._buffer[3] = ' Myers ○ Minimal ○ Patience ○ Histogram ◉' self._buffer.options['modifiable'] = False def enableColor(self, winid): @@ -1200,19 +1200,19 @@ def enableColor(self, winid): .format(winid)) id = int(lfEval("matchid")) self._match_ids.append(id) - lfCmd(r"""call win_execute({}, 'let matchid = matchadd(''Lf_hl_gitSelectedOption'', ''\S\+ \@='', -100)')""" + lfCmd(r"""call win_execute({}, 'let matchid = matchadd(''Lf_hl_gitSelectedOption'', ''\S\+ ◉\@='', -100)')""" .format(winid)) id = int(lfEval("matchid")) self._match_ids.append(id) - lfCmd(r"""call win_execute({}, 'let matchid = matchadd(''Lf_hl_gitDiffAddition'', ''\(\S\+ \)\@<='', -100)')""" + lfCmd(r"""call win_execute({}, 'let matchid = matchadd(''Lf_hl_gitDiffAddition'', ''\(\S\+ \)\@<=◉'', -100)')""" .format(winid)) id = int(lfEval("matchid")) self._match_ids.append(id) - lfCmd(r"""call win_execute({}, 'let matchid = matchadd(''Lf_hl_gitNonSelectedOption'', ''\S\+ \@='', -100)')""" + lfCmd(r"""call win_execute({}, 'let matchid = matchadd(''Lf_hl_gitNonSelectedOption'', ''\S\+ ○\@='', -100)')""" .format(winid)) id = int(lfEval("matchid")) self._match_ids.append(id) - lfCmd(r"""call win_execute({}, 'let matchid = matchadd(''Lf_hl_gitDiffDeletion'', ''\(\S\+ \)\@<='', -100)')""" + lfCmd(r"""call win_execute({}, 'let matchid = matchadd(''Lf_hl_gitDiffDeletion'', ''\(\S\+ \)\@<=○'', -100)')""" .format(winid)) id = int(lfEval("matchid")) self._match_ids.append(id) @@ -2635,13 +2635,13 @@ def open(self): height = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelHeight', &lines * 0.3)"))) lfCmd("silent! noa keepa keepj botright {}sp {}".format(height, buffer_name)) elif win_pos == 'left': - width = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelWidth', 43)"))) + width = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelWidth', 44)"))) lfCmd("silent! noa keepa keepj topleft {}vsp {}".format(width, buffer_name)) elif win_pos == 'right': - width = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelWidth', 43)"))) + width = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelWidth', 44)"))) lfCmd("silent! noa keepa keepj botright {}vsp {}".format(width, buffer_name)) else: # left - width = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelWidth', 43)"))) + width = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelWidth', 44)"))) lfCmd("silent! noa keepa keepj topleft {}vsp {}".format(width, buffer_name)) lfCmd("call setmatches(b:lf_navigation_matches)") @@ -2805,13 +2805,13 @@ def _createWindow(self, win_pos, buffer_name): height = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelHeight', &lines * 0.3)"))) lfCmd("silent! noa keepa keepj bel {}sp {}".format(height, buffer_name)) elif win_pos == 'left': - width = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelWidth', 43)"))) + width = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelWidth', 44)"))) lfCmd("silent! noa keepa keepj abo {}vsp {}".format(width, buffer_name)) elif win_pos == 'right': - width = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelWidth', 43)"))) + width = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelWidth', 44)"))) lfCmd("silent! noa keepa keepj bel {}vsp {}".format(width, buffer_name)) else: # left - width = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelWidth', 43)"))) + width = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelWidth', 44)"))) lfCmd("silent! noa keepa keepj abo {}vsp {}".format(width, buffer_name)) return int(lfEval("win_getid()")) @@ -2826,15 +2826,15 @@ def splitWindow(self, win_pos): height = int(lfEval("&lines")) - height - 4 lfCmd("silent! noa keepa keepj abo {}sp".format(height)) elif win_pos == 'left': - width = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelWidth', 43)"))) + width = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelWidth', 44)"))) width = int(lfEval("&columns")) - width - 1 lfCmd("silent! noa keepa keepj bel {}vsp".format(width)) elif win_pos == 'right': - width = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelWidth', 43)"))) + width = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelWidth', 44)"))) width = int(lfEval("&columns")) - width - 1 lfCmd("silent! noa keepa keepj abo {}vsp".format(width)) else: # left - width = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelWidth', 43)"))) + width = int(float(lfEval("get(g:, 'Lf_GitNavigationPanelWidth', 44)"))) width = int(lfEval("&columns")) - width - 1 lfCmd("silent! noa keepa keepj bel {}vsp".format(width)) @@ -2914,6 +2914,8 @@ def selectOption(self): diff_algorithm = 'patience' elif column >= 40 and column <= 50: diff_algorithm = 'histogram' + else: + diff_algorithm = self._diff_algorithm if self._diff_algorithm != diff_algorithm: self._diff_algorithm = diff_algorithm diff --git a/doc/leaderf.txt b/doc/leaderf.txt index 4e8f925a..f9285a51 100644 --- a/doc/leaderf.txt +++ b/doc/leaderf.txt @@ -1168,7 +1168,7 @@ g:Lf_GitNavigationPanelHeight *g:Lf_GitNavigationPanelHeight* g:Lf_GitNavigationPanelWidth *g:Lf_GitNavigationPanelWidth* To customize the width of navigation(tree) panel. - Default value is 43. + Default value is 44. g:Lf_GitContextNum *g:Lf_GitContextNum* Show diffs with g:Lf_GitContextNum lines of context. From 7fe1e2169b20ed60fbd065a104ac7ee7637a0a74 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Tue, 4 Jun 2024 15:59:29 +0800 Subject: [PATCH 234/365] refresh the numstat --- autoload/leaderf/python/leaderf/gitExpl.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index d885d798..d35496d8 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -1012,6 +1012,7 @@ def __init__(self, level, is_dir, name, info, path): self.name = name self.info = info self.path = path + self.has_num_stat = False class KeyWrapper(object): @@ -1666,6 +1667,9 @@ def buildLine(self, meta_info): return "{}{} {}/".format(" " * meta_info.level, icon, meta_info.name) else: num_stat = self._num_stat.get(self._cur_parent, {}).get(meta_info.path, "") + if num_stat != "": + meta_info.has_num_stat = True + icon = self._status_icons.get(meta_info.info[2][0], self._modification_icon) orig_name = "" @@ -1713,6 +1717,19 @@ def initBuffer(self): finally: self._buffer.options['modifiable'] = False + def refreshNumStat(self): + self._buffer.options['modifiable'] = True + try: + init_line = len(self._head) + structure = self._file_structures[self._cur_parent] + for i, info in enumerate(structure, init_line): + if info.has_num_stat == True: + return + if not info.is_dir: + self._buffer[i] = self.buildLine(info) + finally: + self._buffer.options['modifiable'] = False + def writeBuffer(self): if self._cur_parent is None: return @@ -1762,6 +1779,7 @@ def writeBuffer(self): self._buffer.options['modifiable'] = False if self._read_finished == 1 and self._offset_in_content == len(structure): + self.refreshNumStat() shortstat = re.sub(r"( \d+)( files? changed)", r"%#Lf_hl_gitStlChangedNum#\1%#Lf_hl_gitStlFileChanged#\2", self._short_stat[self._cur_parent]) From 61438cafd11821dd1de65e5020ec6bab2710c5e7 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 5 Jun 2024 23:50:27 +0800 Subject: [PATCH 235/365] optimize the code fix a bug that blamePrevious fails if two commits have the same parent commit --- autoload/leaderf/python/leaderf/gitExpl.py | 167 +++++++++++++++------ 1 file changed, 123 insertions(+), 44 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index d35496d8..8848bcc8 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -15,6 +15,7 @@ from functools import partial from enum import Enum from collections import OrderedDict +from datetime import datetime from .utils import * from .explorer import * from .manager import * @@ -900,7 +901,43 @@ def suicide(self): self.blame_stack = [] self.blame_buffer_dict = {} - def highlightHeatDate(self, normal_blame_list, unix_blame_list): + def _helper(self, date_format): + if date_format == "iso": + # 6817817e (Yggdroot 2014-02-26 00:37:26 +0800) 1 autoload/leaderf/manager.py + pattern = r"\b\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} [+-]\d{4}\b" + format_str = "%Y-%m-%d %H:%M:%S %z" + to_timestamp = lambda date: int(datetime.strptime(date, format_str).timestamp()) + elif date_format == "iso-strict": + # 6817817e (Yggdroot 2014-02-26T00:37:26+08:00) 1 autoload/leaderf/manager.py + pattern = r"\b\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}[+-]\d{2}:\d{2}\b" + to_timestamp = lambda date: int(datetime.fromisoformat(date).timestamp()) + elif date_format == "short": + # 6817817e (Yggdroot 2014-02-26) 1 autoload/leaderf/manager.py + pattern = r"\b\d{4}-\d{2}-\d{2}\b" + to_timestamp = lambda date: int(datetime.fromisoformat(date).timestamp()) + else: + lfPrintError("Error. date_format = {}".format(date_format)) + + return (pattern, to_timestamp) + + def highlightHeatDate1(self, date_format, blame_list): + pattern, to_timestamp = self._helper(date_format) + self._date_dict = {} + for line in blame_list: + commit_id, rest = line.split(None, 1) + if commit_id not in self._date_dict: + match = re.search(pattern, rest) + if match: + date = match.group(0) + timestamp = to_timestamp(date) + else: + lfPrintError("Error. pattern '{}' can not be found in '{}'".format(pattern, rest)) + + self._date_dict[commit_id] = (date, timestamp) + + self._highlightHeatDate() + + def highlightHeatDate2(self, normal_blame_list, unix_blame_list): """ normal_blame_list: ["6817817e\t( Yggdroot\t10 years ago \t1)#!/usr/bin/env python", @@ -920,6 +957,9 @@ def highlightHeatDate(self, normal_blame_list, unix_blame_list): timestamp = int(unix_blame_list[i].split('\t')[2]) self._date_dict[commit_id] = (date, timestamp) + self._highlightHeatDate() + + def _highlightHeatDate(self): color_num = len(self._heat_colors[lfEval("&bg")]) current_time = int(time.time()) heat_seconds = sorted((current_time - timestamp for date, timestamp in self._date_dict.values())) @@ -933,13 +973,28 @@ def highlightHeatDate(self, normal_blame_list, unix_blame_list): heat_seconds = tmp self._heat_seconds = heat_seconds - for date, timestamp in self._date_dict.values(): - index = Bisect.bisect_left(heat_seconds, current_time - timestamp) - id = int(lfEval(r'''matchadd('Lf_hl_blame_heat_{}', '\(, \)\@', -100)''' - .format(index, date))) - self._match_ids.append(id) + self._highlight(current_time, self._date_dict) + + def highlightRestHeatDate1(self, date_format, blame_list): + pattern, to_timestamp = self._helper(date_format) + date_dict = {} + for line in blame_list: + commit_id, rest = line.split(None, 1) + if commit_id not in self._date_dict: + match = re.search(pattern, rest) + if match: + date = match.group(0) + timestamp = to_timestamp(date) + else: + lfPrintError("Error. pattern '{}' can not be found in '{}'".format(pattern, rest)) + + date_dict[commit_id] = (date, timestamp) + self._date_dict[commit_id] = date_dict[commit_id] + + current_time = int(time.time()) + self._highlight(current_time, date_dict) - def highlightRestHeatDate(self, normal_blame_list, unix_blame_list): + def highlightRestHeatDate2(self, normal_blame_list, unix_blame_list): """ normal_blame_list: ["6817817e\t( Yggdroot\t10 years ago \t1)#!/usr/bin/env python", @@ -961,6 +1016,9 @@ def highlightRestHeatDate(self, normal_blame_list, unix_blame_list): date_dict[commit_id] = (date, timestamp) current_time = int(time.time()) + self._highlight(current_time, date_dict) + + def _highlight(self, current_time, date_dict): for date, timestamp in date_dict.values(): index = Bisect.bisect_left(self._heat_seconds, current_time - timestamp) id = int(lfEval(r'''matchadd('Lf_hl_blame_heat_{}', '\(, \)\@', -100)''' @@ -2745,23 +2803,31 @@ def create(self, arguments_dict, cmd, project_root=None): buffer_name = cmd.getBufferName() line_num_width = len(str(len(vim.current.buffer))) + 1 - arguments_dict2 = arguments_dict.copy() - arguments_dict2["-c"] = [] - cmd2 = GitBlameCommand(arguments_dict2, None) - - arguments_dict3 = arguments_dict2.copy() - arguments_dict3["--date"] = ["unix"] - cmd3 = GitBlameCommand(arguments_dict3, None) - - outputs = ParallelExecutor.run(cmd.getCommand(), - cmd2.getCommand(), - cmd3.getCommand(), - format_line=[partial(BlamePanel.formatLine, - arguments_dict, - line_num_width), - None, - None], - directory=self._project_root) + date_format = arguments_dict.get("--date", ["iso"])[0] + if date_format in ["iso", "iso-strict", "short"]: + outputs = ParallelExecutor.run(cmd.getCommand(), + format_line=partial(BlamePanel.formatLine, + arguments_dict, + line_num_width), + directory=self._project_root) + else: + arguments_dict2 = arguments_dict.copy() + arguments_dict2["-c"] = [] + cmd2 = GitBlameCommand(arguments_dict2, None) + + arguments_dict3 = arguments_dict2.copy() + arguments_dict3["--date"] = ["unix"] + cmd3 = GitBlameCommand(arguments_dict3, None) + + outputs = ParallelExecutor.run(cmd.getCommand(), + cmd2.getCommand(), + cmd3.getCommand(), + format_line=[partial(BlamePanel.formatLine, + arguments_dict, + line_num_width), + None, + None], + directory=self._project_root) line_num_width = max(line_num_width, int(lfEval('&numberwidth'))) if len(outputs[0]) > 0: @@ -2784,7 +2850,10 @@ def create(self, arguments_dict, cmd, project_root=None): buffer_name)) blame_winid = int(lfEval("win_getid()")) blame_view.create(blame_winid, buf_content=outputs[0]) - blame_view.highlightHeatDate(outputs[1], outputs[2]) + if date_format in ["iso", "iso-strict", "short"]: + blame_view.highlightHeatDate1(date_format, outputs[0]) + else: + blame_view.highlightHeatDate2(outputs[1], outputs[2]) self._owner.defineMaps(blame_winid) lfCmd("let b:lf_blame_project_root = '{}'".format(self._project_root)) lfCmd("noautocmd norm! {}Gzt{}G0".format(top_line, cursor_line)) @@ -3709,10 +3778,11 @@ def blamePrevious(self): line_num, file_name = vim.current.line.rsplit('\t', 1)[1].split(None, 1) project_root = lfEval("b:lf_blame_project_root") blame_panel = self._blame_panels[project_root] - alternate_winid = blame_panel.getAlternateWinid(vim.current.buffer.name) + blame_buffer_name = vim.current.buffer.name + alternate_winid = blame_panel.getAlternateWinid(blame_buffer_name) blame_winid = lfEval("win_getid()") - if commit_id not in blame_panel.getBlameDict(vim.current.buffer.name): + if commit_id not in blame_panel.getBlameDict(blame_buffer_name): cmd = 'git log -2 --pretty="%H" --name-status --follow {} -- {}'.format(commit_id, file_name) # output is as below: @@ -3737,7 +3807,7 @@ def blamePrevious(self): parent_commit_id = outputs[0][3] blame_win_width = vim.current.window.width - blame_panel.getBlameStack(vim.current.buffer.name).append( + blame_panel.getBlameStack(blame_buffer_name).append( ( vim.current.buffer[:], lfEval("winbufnr({})".format(alternate_winid)), @@ -3748,24 +3818,30 @@ def blamePrevious(self): ) alternate_buffer_name = "LeaderF://{}:{}".format(parent_commit_id[:7], orig_name) - blame_buffer_dict = blame_panel.getBlameBufferDict(vim.current.buffer.name) + blame_buffer_dict = blame_panel.getBlameBufferDict(blame_buffer_name) lfCmd("noautocmd call win_gotoid({})".format(alternate_winid)) if alternate_buffer_name in blame_buffer_dict: blame_buffer, alternate_buffer_num = blame_buffer_dict[alternate_buffer_name] lfCmd("buffer {}".format(alternate_buffer_num)) else: - arguments_dict2 = self._arguments.copy() - arguments_dict2["-c"] = [] + date_format = self._arguments.get("--date", ["iso"])[0] + if date_format in ["iso", "iso-strict", "short"]: + cmd = [GitBlameCommand.buildCommand(self._arguments, parent_commit_id, orig_name), + "git show {}:{}".format(parent_commit_id, orig_name), + ] + else: + arguments_dict2 = self._arguments.copy() + arguments_dict2["-c"] = [] - arguments_dict3 = arguments_dict2.copy() - arguments_dict3["--date"] = ["unix"] + arguments_dict3 = arguments_dict2.copy() + arguments_dict3["--date"] = ["unix"] - cmd = [GitBlameCommand.buildCommand(self._arguments, parent_commit_id, orig_name), - "git show {}:{}".format(parent_commit_id, orig_name), - GitBlameCommand.buildCommand(arguments_dict2, parent_commit_id, orig_name), - GitBlameCommand.buildCommand(arguments_dict3, parent_commit_id, orig_name), - ] + cmd = [GitBlameCommand.buildCommand(self._arguments, parent_commit_id, orig_name), + "git show {}:{}".format(parent_commit_id, orig_name), + GitBlameCommand.buildCommand(arguments_dict2, parent_commit_id, orig_name), + GitBlameCommand.buildCommand(arguments_dict3, parent_commit_id, orig_name), + ] outputs = ParallelExecutor.run(*cmd, directory=project_root) line_num_width = len(str(len(outputs[1]))) + 1 @@ -3782,6 +3858,12 @@ def blamePrevious(self): lfCmd("setlocal nomodifiable") alternate_buffer_num = vim.current.buffer.number + blame_view = blame_panel.getBlameView(blame_buffer_name) + if date_format in ["iso", "iso-strict", "short"]: + blame_view.highlightRestHeatDate1(date_format, outputs[0]) + else: + blame_view.highlightRestHeatDate2(outputs[2], outputs[3]) + lfCmd("noautocmd norm! {}Gzz".format(line_num)) top_line = lfEval("line('w0')") @@ -3796,18 +3878,15 @@ def blamePrevious(self): lfCmd("noautocmd norm! {}Gzt{}G0".format(top_line, line_num)) lfCmd("call win_execute({}, 'setlocal scrollbind')".format(alternate_winid)) - blame_view = blame_panel.getBlameView(vim.current.buffer.name) - blame_view.highlightRestHeatDate(outputs[2], outputs[3]) - blame_win_width = vim.current.window.width - blame_panel.getBlameDict(vim.current.buffer.name)[commit_id] = ( + blame_panel.getBlameDict(blame_buffer_name)[commit_id] = ( blame_buffer, alternate_buffer_num, blame_win_width ) blame_buffer_dict[alternate_buffer_name] = (blame_buffer, alternate_buffer_num) else: - blame_panel.getBlameStack(vim.current.buffer.name).append( + blame_panel.getBlameStack(blame_buffer_name).append( ( vim.current.buffer[:], lfEval("winbufnr({})".format(alternate_winid)), @@ -3819,7 +3898,7 @@ def blamePrevious(self): (blame_buffer, alternate_buffer_num, blame_win_width - ) = blame_panel.getBlameDict(vim.current.buffer.name)[commit_id] + ) = blame_panel.getBlameDict(blame_buffer_name)[commit_id] lfCmd("noautocmd call win_gotoid({})".format(alternate_winid)) lfCmd("buffer {}".format(alternate_buffer_num)) lfCmd("noautocmd norm! {}Gzz".format(line_num)) From a59a0803008dfe6d6cdd465ae043c2dc54908c8b Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 6 Jun 2024 00:47:03 +0800 Subject: [PATCH 236/365] highlightRestHeatDate should be called in blame window --- autoload/leaderf/python/leaderf/gitExpl.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 8848bcc8..e514ffb5 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -3824,6 +3824,10 @@ def blamePrevious(self): if alternate_buffer_name in blame_buffer_dict: blame_buffer, alternate_buffer_num = blame_buffer_dict[alternate_buffer_name] lfCmd("buffer {}".format(alternate_buffer_num)) + lfCmd("noautocmd norm! {}Gzz".format(line_num)) + top_line = lfEval("line('w0')") + + lfCmd("noautocmd call win_gotoid({})".format(blame_winid)) else: date_format = self._arguments.get("--date", ["iso"])[0] if date_format in ["iso", "iso-strict", "short"]: @@ -3858,16 +3862,16 @@ def blamePrevious(self): lfCmd("setlocal nomodifiable") alternate_buffer_num = vim.current.buffer.number + lfCmd("noautocmd norm! {}Gzz".format(line_num)) + top_line = lfEval("line('w0')") + + lfCmd("noautocmd call win_gotoid({})".format(blame_winid)) blame_view = blame_panel.getBlameView(blame_buffer_name) if date_format in ["iso", "iso-strict", "short"]: blame_view.highlightRestHeatDate1(date_format, outputs[0]) else: blame_view.highlightRestHeatDate2(outputs[2], outputs[3]) - lfCmd("noautocmd norm! {}Gzz".format(line_num)) - top_line = lfEval("line('w0')") - - lfCmd("noautocmd call win_gotoid({})".format(blame_winid)) lfCmd("setlocal modifiable") vim.current.buffer[:] = blame_buffer lfCmd("setlocal nomodifiable") From 9c0dc42f52fa6b625c8c88a1f11bbf8a934a37f6 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 6 Jun 2024 00:54:47 +0800 Subject: [PATCH 237/365] update highlight regex --- autoload/leaderf/python/leaderf/gitExpl.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index e514ffb5..0f388d5a 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -1012,8 +1012,8 @@ def highlightRestHeatDate2(self, normal_blame_list, unix_blame_list): if commit_id not in self._date_dict: date = rest.split('\t')[1].strip() timestamp = int(unix_blame_list[i].split('\t')[2]) - self._date_dict[commit_id] = (date, timestamp) date_dict[commit_id] = (date, timestamp) + self._date_dict[commit_id] = date_dict[commit_id] current_time = int(time.time()) self._highlight(current_time, date_dict) @@ -1021,8 +1021,8 @@ def highlightRestHeatDate2(self, normal_blame_list, unix_blame_list): def _highlight(self, current_time, date_dict): for date, timestamp in date_dict.values(): index = Bisect.bisect_left(self._heat_seconds, current_time - timestamp) - id = int(lfEval(r'''matchadd('Lf_hl_blame_heat_{}', '\(, \)\@', -100)''' - .format(index, date))) + id = int(lfEval(r'''matchadd('Lf_hl_blame_heat_%d', '\(^.\{-}\)\@<=\<%s\>', -100)''' + % (index, date))) self._match_ids.append(id) @@ -3872,6 +3872,7 @@ def blamePrevious(self): else: blame_view.highlightRestHeatDate2(outputs[2], outputs[3]) + # here we are in the blame window lfCmd("setlocal modifiable") vim.current.buffer[:] = blame_buffer lfCmd("setlocal nomodifiable") From b0f5c497d0e277bc8f5f83c47f3e60979e1c4995 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 6 Jun 2024 11:04:25 +0800 Subject: [PATCH 238/365] adjust the length of long line --- autoload/leaderf/python/leaderf/gitExpl.py | 64 ++++++++++++++-------- 1 file changed, 42 insertions(+), 22 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 0f388d5a..3429efc5 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -409,7 +409,8 @@ def buildCommandAndBufferName(self): find_copies_harder = "" self._cmd = ('git show -m --raw -C{} --numstat --shortstat ' - '--pretty=format:"# %P" --no-abbrev {}').format(find_copies_harder, self._source) + '--pretty=format:"# %P" --no-abbrev {}').format(find_copies_harder, + self._source) self._buffer_name = "LeaderF://navigation/" + self._source self._file_type_cmd = "" @@ -931,7 +932,8 @@ def highlightHeatDate1(self, date_format, blame_list): date = match.group(0) timestamp = to_timestamp(date) else: - lfPrintError("Error. pattern '{}' can not be found in '{}'".format(pattern, rest)) + lfPrintError("Error. pattern '{}' can not be found in '{}'" + .format(pattern, rest)) self._date_dict[commit_id] = (date, timestamp) @@ -962,7 +964,8 @@ def highlightHeatDate2(self, normal_blame_list, unix_blame_list): def _highlightHeatDate(self): color_num = len(self._heat_colors[lfEval("&bg")]) current_time = int(time.time()) - heat_seconds = sorted((current_time - timestamp for date, timestamp in self._date_dict.values())) + heat_seconds = sorted((current_time - timestamp + for date, timestamp in self._date_dict.values())) heat_seconds_len = len(heat_seconds) if heat_seconds_len > color_num: step, remainder = divmod(heat_seconds_len, color_num) @@ -986,7 +989,8 @@ def highlightRestHeatDate1(self, date_format, blame_list): date = match.group(0) timestamp = to_timestamp(date) else: - lfPrintError("Error. pattern '{}' can not be found in '{}'".format(pattern, rest)) + lfPrintError("Error. pattern '{}' can not be found in '{}'" + .format(pattern, rest)) date_dict[commit_id] = (date, timestamp) self._date_dict[commit_id] = date_dict[commit_id] @@ -1809,7 +1813,8 @@ def writeBuffer(self): init_line = len(self._head) if cursor_line <= init_line: - lfCmd("call win_execute({}, 'norm! {}G')".format(self.getWindowId(), init_line)) + lfCmd("call win_execute({}, 'norm! {}G')" + .format(self.getWindowId(), init_line)) cursor_line = int(lfEval("getcurpos({})[1]".format(self.getWindowId()))) source = None @@ -1823,10 +1828,13 @@ def writeBuffer(self): if source is not None: self._callback(source) if lfEval("has('nvim')") == '1': - lfCmd("call nvim_win_set_option({}, 'cursorline', v:true)".format(self.getWindowId())) + lfCmd("call nvim_win_set_option({}, 'cursorline', v:true)" + .format(self.getWindowId())) else: - lfCmd("call win_execute({}, 'setlocal cursorline')".format(self.getWindowId())) - lfCmd("call win_execute({}, 'norm! {}G0zz')".format(self.getWindowId(), cursor_line)) + lfCmd("call win_execute({}, 'setlocal cursorline')" + .format(self.getWindowId())) + lfCmd("call win_execute({}, 'norm! {}G0zz')" + .format(self.getWindowId(), cursor_line)) if self._target_path is None: lfCmd("call win_gotoid({})".format(self.getWindowId())) @@ -2132,7 +2140,8 @@ def create(self, arguments_dict, source, **kwargs): self.bufShown(buffer_names[0], int(lfEval("win_getid()"))) else: GitCommandView(self, cmd).create(int(lfEval("win_getid()")), bufhidden='hide') - lfCmd("call win_execute({}, 'setlocal cursorlineopt=number')".format(int(lfEval("win_getid()")))) + lfCmd("call win_execute({}, 'setlocal cursorlineopt=number')" + .format(int(lfEval("win_getid()")))) lfCmd("call win_execute({}, 'setlocal cursorline')".format(int(lfEval("win_getid()")))) lfCmd("call win_gotoid({})".format(self._views[buffer_names[1]].getWindowId())) target_winid = int(lfEval("win_getid()")) @@ -2155,7 +2164,8 @@ def create(self, arguments_dict, source, **kwargs): for w in vim.current.tabpage.windows] else: # open buffer_names = self._buffer_names[vim.current.tabpage] - win_ids = [int(lfEval("bufwinid('{}')".format(escQuote(name)))) for name in buffer_names] + win_ids = [int(lfEval("bufwinid('{}')".format(escQuote(name)))) + for name in buffer_names] win_pos = arguments_dict.get("--navigation-position", ["left"])[0] win_ids = self.getValidWinIDs(win_ids, win_pos) @@ -2176,14 +2186,16 @@ def create(self, arguments_dict, source, **kwargs): lfCmd("call win_execute({}, 'setlocal bufhidden=wipe')".format(winid)) buffer_name = lfEval("bufname(winbufnr({}))".format(winid)) - lfCmd("call win_execute({}, 'diffoff | hide edit {}')".format(winid, cmd.getBufferName())) + lfCmd("call win_execute({}, 'diffoff | hide edit {}')" + .format(winid, cmd.getBufferName())) lfCmd("call win_execute({}, 'setlocal cursorlineopt=number')".format(winid)) lfCmd("call win_execute({}, 'setlocal cursorline')".format(winid)) lfCmd("call win_execute({}, 'let b:lf_explorer_page_id = {}')" .format(winid, kwargs.get("explorer_page_id", 0))) - lfCmd("""call win_execute({}, 'let b:lf_diff_view_mode = "side-by-side"')""".format(winid)) - lfCmd("""call win_execute({}, "let b:lf_diff_view_source = {}")""".format(winid, - str(list(source)))) + lfCmd("""call win_execute({}, 'let b:lf_diff_view_mode = "side-by-side"')""" + .format(winid)) + lfCmd("""call win_execute({}, "let b:lf_diff_view_source = {}")""" + .format(winid, str(list(source)))) # if the buffer also in another tabpage, BufHidden is not triggerd # should run this code @@ -2194,12 +2206,14 @@ def create(self, arguments_dict, source, **kwargs): if cmd.getBufferName() in self._hidden_views: self.bufShown(cmd.getBufferName(), winid) else: - GitCommandView(self, cmd).create(winid, bufhidden='hide', buf_content=outputs[i]) + GitCommandView(self, cmd).create(winid, bufhidden='hide', + buf_content=outputs[i]) lfCmd("call win_gotoid({})".format(win_ids[1])) if kwargs.get("line_num", None) is not None: - lfCmd("call win_execute({}, 'norm! {}G0zbzz')".format(target_winid, kwargs["line_num"])) + lfCmd("call win_execute({}, 'norm! {}G0zbzz')" + .format(target_winid, kwargs["line_num"])) else: lfCmd("call win_execute({}, 'norm! gg]c0')".format(target_winid)) @@ -2642,8 +2656,10 @@ def create(self, arguments_dict, source, **kwargs): lfCmd("let b:lf_diff_view_mode = 'unified'") lfCmd("let b:lf_diff_view_source = {}".format(str(list(source)))) blame_map = lfEval("g:Lf_GitKeyMap") - lfCmd("nnoremap {} :call leaderf#Git#PreviousChange()".format(blame_map["previous_change"])) - lfCmd("nnoremap {} :call leaderf#Git#NextChange()".format(blame_map["next_change"])) + lfCmd("nnoremap {} :call leaderf#Git#PreviousChange()" + .format(blame_map["previous_change"])) + lfCmd("nnoremap {} :call leaderf#Git#NextChange()" + .format(blame_map["next_change"])) else: lfCmd("call win_gotoid({})".format(winid)) if not vim.current.buffer.name: # buffer name is empty @@ -3413,7 +3429,8 @@ def vsplitDiff(self): lfCmd("keepa keepj abo vsp {}".format(file_name)) win_ids[1] = int(lfEval("win_getid()")) lfCmd("augroup Lf_Git_Diff | augroup END") - lfCmd("autocmd! Lf_Git_Diff BufWipeout call leaderf#Git#DiffOff({})".format(win_ids)) + lfCmd("autocmd! Lf_Git_Diff BufWipeout call leaderf#Git#DiffOff({})" + .format(win_ids)) lfCmd("call win_execute({}, 'autocmd! Lf_Git_Diff BufHidden,BufWipeout call leaderf#Git#DiffOff({})')" .format(win_ids[0], win_ids)) lfCmd("setlocal nobuflisted") @@ -3878,7 +3895,8 @@ def blamePrevious(self): lfCmd("setlocal nomodifiable") if len(blame_buffer) > 0: line_width = blame_buffer[0].rfind('\t') - line_num_width = max(len(str(len(vim.current.buffer))) + 1, int(lfEval('&numberwidth'))) + line_num_width = max(len(str(len(vim.current.buffer))) + 1, + int(lfEval('&numberwidth'))) lfCmd("vertical resize {}".format(line_width + line_num_width)) lfCmd("noautocmd norm! {}Gzt{}G0".format(top_line, line_num)) lfCmd("call win_execute({}, 'setlocal scrollbind')".format(alternate_winid)) @@ -4117,7 +4135,8 @@ def startExplorer(self, win_pos, *args, **kwargs): tmp_file_name = None if vim.current.buffer.options["modified"]: if sys.version_info >= (3, 0): - tmp_file = partial(tempfile.NamedTemporaryFile, encoding=lfEval("&encoding")) + tmp_file = partial(tempfile.NamedTemporaryFile, + encoding=lfEval("&encoding")) else: tmp_file = tempfile.NamedTemporaryFile @@ -4131,7 +4150,8 @@ def startExplorer(self, win_pos, *args, **kwargs): self._blame_panels[self._project_root] = BlamePanel(self) self._blame_panels[self._project_root].create(arguments_dict, - self.createGitCommand(self._arguments, None), + self.createGitCommand(self._arguments, + None), project_root=self._project_root) if tmp_file_name is not None: os.remove(tmp_file_name) From f86a6af13e0405b4efc60e115fb880d474552ca0 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 6 Jun 2024 16:51:12 +0800 Subject: [PATCH 239/365] add `def highlightCommitId(self, commit_id)` --- autoload/leaderf/python/leaderf/gitExpl.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 3429efc5..3e602a1d 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -856,12 +856,6 @@ def enableColor(self, winid): lfCmd("let g:Lf_GitStlHeatLine = '{}'".format(stl)) - for i in range(256): - lfCmd(r"""call win_execute({}, 'let matchid = matchadd(''Lf_hl_blame_{}'', ''^\^\?{}\x\+'', -100)')""" - .format(winid, i, format(i, '02x'))) - id = int(lfEval("matchid")) - self._match_ids.append(id) - if lfEval("hlexists('Lf_hl_gitBlameDate')") == '0': lfCmd("call leaderf#colorscheme#popup#load('{}', '{}')" .format("git", lfEval("get(g:, 'Lf_PopupColorscheme', 'default')"))) @@ -870,6 +864,13 @@ def enableColor(self, winid): id = int(lfEval("matchid")) self._match_ids.append(id) + def highlightCommitId(self, commit_id): + n = int(commit_id[:2], 16) + lfCmd(r"""let matchid = matchadd('Lf_hl_blame_{}', '^\^\?{}\x\+', -100)""" + .format(n, commit_id[:2])) + id = int(lfEval("matchid")) + self._match_ids.append(id) + def suicide(self): super(GitBlameView, self).suicide() @@ -927,6 +928,7 @@ def highlightHeatDate1(self, date_format, blame_list): for line in blame_list: commit_id, rest = line.split(None, 1) if commit_id not in self._date_dict: + self.highlightCommitId(commit_id) match = re.search(pattern, rest) if match: date = match.group(0) @@ -955,6 +957,7 @@ def highlightHeatDate2(self, normal_blame_list, unix_blame_list): for i, line in enumerate(normal_blame_list): commit_id, rest = line.split('\t', 1) if commit_id not in self._date_dict: + self.highlightCommitId(commit_id) date = rest.split('\t')[1].strip() timestamp = int(unix_blame_list[i].split('\t')[2]) self._date_dict[commit_id] = (date, timestamp) @@ -984,6 +987,7 @@ def highlightRestHeatDate1(self, date_format, blame_list): for line in blame_list: commit_id, rest = line.split(None, 1) if commit_id not in self._date_dict: + self.highlightCommitId(commit_id) match = re.search(pattern, rest) if match: date = match.group(0) @@ -1014,6 +1018,7 @@ def highlightRestHeatDate2(self, normal_blame_list, unix_blame_list): for i, line in enumerate(normal_blame_list): commit_id, rest = line.split('\t', 1) if commit_id not in self._date_dict: + self.highlightCommitId(commit_id) date = rest.split('\t')[1].strip() timestamp = int(unix_blame_list[i].split('\t')[2]) date_dict[commit_id] = (date, timestamp) From 98a0d1af8e901342718bd626e94ae4742fa1a937 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 6 Jun 2024 17:39:04 +0800 Subject: [PATCH 240/365] syn-match has better performance than matchadd, version.c --- autoload/leaderf/python/leaderf/gitExpl.py | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 3e602a1d..dd8b3ea1 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -729,7 +729,6 @@ def __init__(self, owner, cmd): self._alternate_winid = None self._alternate_buffer_num = None self._alternate_win_options = {} - self._match_ids = [] self._color_table = { '0': '#000000', '1': '#800000', '2': '#008000', '3': '#808000', '4': '#000080', '5': '#800080', '6': '#008080', '7': '#c0c0c0', @@ -860,16 +859,11 @@ def enableColor(self, winid): lfCmd("call leaderf#colorscheme#popup#load('{}', '{}')" .format("git", lfEval("get(g:, 'Lf_PopupColorscheme', 'default')"))) - lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''WarningMsg'', ''Not Committed Yet'', -100)')""" % winid) - id = int(lfEval("matchid")) - self._match_ids.append(id) + lfCmd(r"""call win_execute(%d, 'syn match WarningMsg /\/')""" % winid) def highlightCommitId(self, commit_id): n = int(commit_id[:2], 16) - lfCmd(r"""let matchid = matchadd('Lf_hl_blame_{}', '^\^\?{}\x\+', -100)""" - .format(n, commit_id[:2])) - id = int(lfEval("matchid")) - self._match_ids.append(id) + lfCmd(r"syn match Lf_hl_blame_{} /^\^\?{}\x\+/".format(n, commit_id[:2])) def suicide(self): super(GitBlameView, self).suicide() @@ -889,10 +883,6 @@ def suicide(self): for k, v in self._alternate_win_options.items(): lfCmd("call setwinvar({}, '&{}', {})".format(self._alternate_winid, k, v)) - for i in self._match_ids: - lfCmd("silent! call matchdelete(%d)" % i) - self._match_ids = [] - for item in self.blame_dict.values(): buffer_num = int(item[1]) # buftype is not empty @@ -1030,9 +1020,7 @@ def highlightRestHeatDate2(self, normal_blame_list, unix_blame_list): def _highlight(self, current_time, date_dict): for date, timestamp in date_dict.values(): index = Bisect.bisect_left(self._heat_seconds, current_time - timestamp) - id = int(lfEval(r'''matchadd('Lf_hl_blame_heat_%d', '\(^.\{-}\)\@<=\<%s\>', -100)''' - % (index, date))) - self._match_ids.append(id) + lfCmd(r"syn match Lf_hl_blame_heat_{} /\<{}\>/".format(index, date)) class LfOrderedDict(OrderedDict): From 395b632673a41329053c10ff5132c8671bbd425d Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Sat, 15 Jun 2024 14:53:28 +0800 Subject: [PATCH 241/365] fix issue #1078 --- autoload/leaderf/python/leaderf/gitExpl.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index dd8b3ea1..1b1c5209 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -3473,6 +3473,8 @@ def startExplorer(self, win_pos, *args, **kwargs): self.vsplitDiff() else: self._accept(self._arguments["current_file"], "") + + self._restoreOrigCwd() return if "--recall" in arguments_dict: From c5a0641db2ba337150844156c9377e6794f55330 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Sat, 15 Jun 2024 18:45:57 +0800 Subject: [PATCH 242/365] fix issue #1080 --- autoload/leaderf/python/leaderf/gitExpl.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 1b1c5209..db65c5b1 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -862,7 +862,7 @@ def enableColor(self, winid): lfCmd(r"""call win_execute(%d, 'syn match WarningMsg /\/')""" % winid) def highlightCommitId(self, commit_id): - n = int(commit_id[:2], 16) + n = int(commit_id.lstrip('^')[:2], 16) lfCmd(r"syn match Lf_hl_blame_{} /^\^\?{}\x\+/".format(n, commit_id[:2])) def suicide(self): From 0e8636bc53efd2f07d840aa970a6ba53227fccad Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Sun, 16 Jun 2024 10:54:41 +0800 Subject: [PATCH 243/365] fix issue #1079 --- autoload/leaderf/python/leaderf/manager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 81dfccdc..b29fed28 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -899,7 +899,7 @@ def _useExistingWindow(self, title, source, line_num, jump_cmd): self._preview_filetype = lfEval("getbufvar(winbufnr(%d), '&ft')" % self._preview_winid) else: if isinstance(source, int): - lfCmd("noautocmd call popup_settext(%d, getbufline(%d, 1, '$'))" % (self._preview_winid, source)) + lfCmd("noautocmd call popup_settext(%d, getbufline(%d, 1, 4096))" % (self._preview_winid, source)) filename = vim.buffers[source].name else: filename = source From 052c60f08869b2afdcbff720217ec3d74a0e45b4 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Mon, 17 Jun 2024 14:51:05 +0800 Subject: [PATCH 244/365] add support for inline blame --- autoload/leaderf/Any.vim | 1 + autoload/leaderf/Git.vim | 58 ++++- autoload/leaderf/colorscheme/popup.vim | 2 + .../leaderf/colorscheme/popup/default.vim | 2 + autoload/leaderf/python/leaderf/gitExpl.py | 245 +++++++++++++++++- doc/leaderf.txt | 13 + plugin/leaderf.vim | 4 + 7 files changed, 313 insertions(+), 12 deletions(-) diff --git a/autoload/leaderf/Any.vim b/autoload/leaderf/Any.vim index f72c2ea6..24534b26 100644 --- a/autoload/leaderf/Any.vim +++ b/autoload/leaderf/Any.vim @@ -264,6 +264,7 @@ let g:Lf_Arguments = { \ {"name": ["-w"], "nargs": 0, "help": "Ignore whitespace when comparing the parent’s version and the child’s to find where the lines came from."}, \ {"name": ["--date"], "nargs": 1, "choices": ["relative", "local", "iso", "iso-strict", "rfc", "short", "default"], \ "metavar": "", "help": "Specifies the format used to output dates. .i.e, git blame --date=. can be one of ['relative', 'local', 'iso', 'iso-strict', 'rfc', 'short', 'default']"}, + \ {"name": ["--inline"], "nargs": 0, "help": "Display inline git blame information."}, \ ], \ }, \} diff --git a/autoload/leaderf/Git.vim b/autoload/leaderf/Git.vim index c3e843e8..8e6f2423 100644 --- a/autoload/leaderf/Git.vim +++ b/autoload/leaderf/Git.vim @@ -432,6 +432,47 @@ function! leaderf#Git#Bufhidden(view_id) abort exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value.bufHidden()", a:view_id) endfunction +function! leaderf#Git#UpdateInlineBlame(manager_id) abort + exec g:Lf_py "import ctypes" + exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value.updateInlineBlame()", a:manager_id) +endfunction + +function! leaderf#Git#StartInlineBlame() abort + Leaderf git blame --inline +endfunction + +function! leaderf#Git#DisableInlineBlame() abort + if !exists("g:lf_blame_manager_id") || g:lf_blame_manager_id == 0 + return + endif + + exec g:Lf_py "import ctypes" + exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value.disableInlineBlame()", g:lf_blame_manager_id) +endfunction + +function! leaderf#Git#RestartInlineBlame() abort + call leaderf#Git#DisableInlineBlame() + call leaderf#Git#StartInlineBlame() +endfunction + +function! leaderf#Git#HideInlineBlame(manager_id) abort + exec g:Lf_py "import ctypes" + exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value.hideInlineBlame()", a:manager_id) +endfunction + +function! leaderf#Git#ShowInlineBlame(manager_id) abort + exec g:Lf_py "import ctypes" + exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value.showInlineBlame()", a:manager_id) +endfunction + +function! leaderf#Git#ToggleInlineBlame() abort + if !exists("g:Lf_git_inline_blame_enabled") || g:Lf_git_inline_blame_enabled == 0 + call leaderf#Git#StartInlineBlame() + else + call leaderf#Git#DisableInlineBlame() + endif +endfunction + function! leaderf#Git#ClearMatches() abort for m in b:Leaderf_matches call matchdelete(m.id) @@ -472,6 +513,10 @@ function! leaderf#Git#Commands() abort \ {"Leaderf git blame": "git blame current file"}, \ {"Leaderf git blame -w": "ignore whitespace when git blame current file"}, \ {"Leaderf git blame --date relative": "show relative date when git blame current file"}, + \ {"LeaderfGitEnableInlineBlame": "Enable inline blame. This command is a shortcut of `:Leaderf git blame --inline`"}, + \ {"LeaderfGitDisableInlineBlame": "Disable inline blame"}, + \ {"LeaderfGitToggleInlineBlame": "Toggle inline blame"}, + \ {"LeaderfGitUpdateInlineBlame": "If the file is updated in the git repository, we need to use this command to update the inline blame."}, \ ] endif @@ -555,7 +600,6 @@ function! leaderf#Git#SetLineNumberWin(line_num_content, buffer_num) abort endfor endfunction - function! leaderf#Git#SignPlace(added_line_nums, deleted_line_nums, buf_number) abort for i in a:added_line_nums call sign_place(0, "LeaderF", "Leaderf_diff_add", a:buf_number, {'lnum': i}) @@ -611,3 +655,15 @@ function! leaderf#Git#OpenNavigationPanel() abort exec g:Lf_py "import ctypes" exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value.openNavigationPanel()", b:lf_explorer_page_id) endfunction + +function! leaderf#Git#RemoveExtmarks(buffer_num) abort + let ns_id_0 = nvim_create_namespace('LeaderF_Git_Blame_0') + for [mark_id, row, col] in nvim_buf_get_extmarks(a:buffer_num, ns_id_0, 0, -1, {}) + call nvim_buf_del_extmark(a:buffer_num, ns_id_0, mark_id) + endfor + + let ns_id_1 = nvim_create_namespace('LeaderF_Git_Blame_1') + for [mark_id, row, col] in nvim_buf_get_extmarks(a:buffer_num, ns_id_1, 0, -1, {}) + call nvim_buf_del_extmark(a:buffer_num, ns_id_1, mark_id) + endfor +endfunction diff --git a/autoload/leaderf/colorscheme/popup.vim b/autoload/leaderf/colorscheme/popup.vim index 61cbcb5a..8aed660a 100644 --- a/autoload/leaderf/colorscheme/popup.vim +++ b/autoload/leaderf/colorscheme/popup.vim @@ -323,6 +323,8 @@ function! s:AddPropType() abort silent! call prop_type_add("Lf_hl_gitDiffChange", {'highlight': "Lf_hl_gitDiffChange", 'priority': 21}) silent! call prop_type_add("Lf_hl_gitDiffText", {'highlight': "Lf_hl_gitDiffText", 'priority': 22}) silent! call prop_type_add("Lf_hl_LineNr", {'highlight': "Lf_hl_LineNr", 'priority': 20}) + silent! call prop_type_add("Lf_hl_gitTransparent", {'highlight': "Lf_hl_gitTransparent", 'priority': -2000}) + silent! call prop_type_add("Lf_hl_gitInlineBlame", {'highlight': "Comment", 'priority': 20}) endfunction " diff --git a/autoload/leaderf/colorscheme/popup/default.vim b/autoload/leaderf/colorscheme/popup/default.vim index ce3a103c..3fa3b06c 100644 --- a/autoload/leaderf/colorscheme/popup/default.vim +++ b/autoload/leaderf/colorscheme/popup/default.vim @@ -174,6 +174,7 @@ if &background ==? 'dark' call leaderf#colorscheme#popup#link_no_reverse("Lf_hl_gitDiffDelete", "DiffDelete") call leaderf#colorscheme#popup#link_no_reverse("Lf_hl_gitDiffChange", "DiffChange") call leaderf#colorscheme#popup#link_no_reverse("Lf_hl_gitDiffText", "DiffText") + highlight def link Lf_hl_gitInlineBlame Comment else " Lf_hl_popup_inputText is the wincolor of input window highlight def Lf_hl_popup_inputText guifg=#525252 guibg=#f4f3d7 gui=NONE ctermfg=239 ctermbg=230 cterm=NONE @@ -335,4 +336,5 @@ else call leaderf#colorscheme#popup#link_no_reverse("Lf_hl_gitDiffDelete", "DiffDelete") call leaderf#colorscheme#popup#link_no_reverse("Lf_hl_gitDiffChange", "DiffChange") call leaderf#colorscheme#popup#link_no_reverse("Lf_hl_gitDiffText", "DiffText") + highlight def link Lf_hl_gitInlineBlame Comment endif diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index db65c5b1..44379d71 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -476,7 +476,7 @@ def __init__(self, arguments_dict, cmd, buf_name, file_type, file_type_cmd): class ParallelExecutor(object): @staticmethod - def run(*cmds, format_line=None, directory=None): + def run(*cmds, format_line=None, directory=None, silent=False): outputs = [[] for _ in range(len(cmds))] stop_thread = False @@ -487,8 +487,9 @@ def readContent(content, output): if stop_thread: break except Exception: - traceback.print_exc() - traceback.print_stack() + if silent == False: + traceback.print_exc() + traceback.print_stack() executors = [AsyncExecutor() for _ in range(len(cmds))] @@ -2267,9 +2268,9 @@ def cleanup(self): def isAllHidden(self): return len(self._views) == 0 - def signPlace(self, added_line_nums, deleted_line_nums, buf_number): + def signPlace(self, added_line_nums, deleted_line_nums, buffer_num): lfCmd("call leaderf#Git#SignPlace({}, {}, {})" - .format(str(added_line_nums), str(deleted_line_nums), buf_number)) + .format(str(added_line_nums), str(deleted_line_nums), buffer_num)) def setLineNumberWin(self, line_num_content, buffer_num): if lfEval("has('nvim')") == '1': @@ -3752,6 +3753,14 @@ def __init__(self): self._blame_panels = {} # key is commit_id, value is ExplorerPage self._pages = {} + # key is buffer number + self._blame_infos = {} + # key is buffer number + self._initial_changedtick = {} + lfCmd("let g:lf_blame_manager_id = {}".format(id(self))) + if lfEval("hlexists('Lf_hl_gitInlineBlame')") == '0': + lfCmd("call leaderf#colorscheme#popup#load('{}', '{}')" + .format("git", lfEval("get(g:, 'Lf_PopupColorscheme', 'default')"))) def discardPanel(self, project_root): del self._blame_panels[project_root] @@ -4115,6 +4124,217 @@ def gotoLine(self, winid, line_num): found = True current_line = start - 1 + def startInlineBlame(self, tmp_file_name): + if lfEval("exists('b:lf_blame_changedtick')") == "1": + return + + lfCmd("let g:Lf_git_inline_blame_enabled = 1") + + lfCmd("augroup Lf_Git_Blame | augroup END") + lfCmd("autocmd! Lf_Git_Blame BufRead * call leaderf#Git#StartInlineBlame()") + lfCmd("autocmd! Lf_Git_Blame BufWinEnter * call leaderf#Git#StartInlineBlame()") + + file_name = vim.current.buffer.name + self._initial_changedtick[vim.current.buffer.number] = vim.current.buffer.vars["changedtick"] + + if " " in file_name: + file_name = file_name.replace(' ', r'\ ') + + if tmp_file_name is None: + git_cmd = (r'git blame --line-porcelain -- {} | grep "^author \|^author-time\|^summary"' + .format(file_name)) + else: + git_cmd = (r'git blame --line-porcelain --contents {} -- {} | grep "^author \|^author-time\|^summary"' + .format(tmp_file_name, file_name)) + + outputs = ParallelExecutor.run(git_cmd, directory=self._project_root, silent=True) + if len(outputs[0]) == 0: + return + + lfCmd("let b:lf_blame_line_number = line('.')") + lfCmd("let b:lf_blame_changedtick = b:changedtick") + blame_list = iter(outputs[0]) + i = 0 + self._blame_infos[vim.current.buffer.number] = {} + blame_infos = self._blame_infos[vim.current.buffer.number] + if lfEval("has('nvim')") == '1': + lfCmd("let ns_id = nvim_create_namespace('LeaderF_Git_Blame_0')") + for i, (author, author_time, summary) in enumerate(itertools.zip_longest(blame_list, + blame_list, + blame_list)): + author = author.split(None, 1)[1].replace("External file (--contents)", "Not Committed Yet") + author_time = int(author_time.split(None, 1)[1]) + summary = summary.split(None, 1)[1] + mark_id = i + 1 + blame_infos[mark_id] = (vim.current.buffer[i], author, author_time, summary) + lfCmd("call nvim_buf_set_extmark(0, ns_id, %d, 0, {'id': %d})" % (i, mark_id)) + else: + for i, (author, author_time, summary) in enumerate(itertools.zip_longest(blame_list, + blame_list, + blame_list)): + author = author.split(None, 1)[1].replace("External file (--contents)", "Not Committed Yet") + author_time = int(author_time.split(None, 1)[1]) + summary = summary.split(None, 1)[1] + prop_id = i + 1 + blame_infos[prop_id] = (vim.current.buffer[i], author, author_time, summary) + lfCmd('call prop_add(%d, 1, {"type": "Lf_hl_gitTransparent", "length": 0, "id": %d})' + % (i+1, prop_id)) + + line_number = vim.current.window.cursor[0] + _, author, author_time, summary = blame_infos[line_number] + author_time = self.relative_time(author_time) + blame_info = "{} • {} • {}".format(author, author_time, summary) + if lfEval("has('nvim')") == '1': + lfCmd("let ns_id = nvim_create_namespace('LeaderF_Git_Blame_1')") + lfCmd("call nvim_buf_set_extmark(0, ns_id, line('.') - 1, 0, {'id': 1, 'virt_text': [[' %s', 'Lf_hl_gitInlineBlame']]})" + % (escQuote(blame_info))) + else: + lfCmd("call prop_add(line('.'), 0, {'type': 'Lf_hl_gitInlineBlame', 'text': ' %s'})" + % (escQuote(blame_info))) + + lfCmd("autocmd! Lf_Git_Blame CursorMoved call leaderf#Git#UpdateInlineBlame({})" + .format(id(self))) + lfCmd("autocmd! Lf_Git_Blame InsertEnter call leaderf#Git#HideInlineBlame({})" + .format(id(self))) + lfCmd("autocmd! Lf_Git_Blame InsertLeave call leaderf#Git#ShowInlineBlame({})" + .format(id(self))) + + def relative_time(self, timestamp): + def format_time_unit(value, unit): + if value == 1: + return "{} {}".format(value, unit) + else: + return "{} {}s".format(value, unit) + + current_time = datetime.now() + past_time = datetime.fromtimestamp(timestamp) + + delta = current_time - past_time + + years = delta.days // 365 + months = (delta.days % 365) // 30 + if years >= 1: + if months == 0: + return "{} ago".format(format_time_unit(years, "year")) + else: + return "{}, {} ago".format(format_time_unit(years, "year"), + format_time_unit(months, "month")) + elif months >= 1: + return "{} ago".format(format_time_unit(months, "month")) + else: + days = delta.days + if days >= 7: + weeks = days // 7 + return "{} ago".format(format_time_unit(weeks, "week")) + elif days >= 1: + return "{} ago".format(format_time_unit(days, "day")) + else: + hours = delta.seconds // 3600 + if hours >= 1: + return "{} ago".format(format_time_unit(hours, "hour")) + else: + minutes = delta.seconds // 60 + if minutes >= 1: + return "{} ago".format(format_time_unit(minutes, "minute")) + else: + return "{} ago".format(format_time_unit(delta.seconds, "second")) + + def updateInlineBlame(self): + if (lfEval("b:lf_blame_line_number == line('.')") == '1' + and lfEval("b:lf_blame_changedtick == b:changedtick") == '1'): + return + + self.showInlineBlame() + + def showInlineBlame(self): + if lfEval("has('nvim')") == '1': + self.nvim_showInlineBlame() + return + + lfCmd("let b:lf_blame_line_number = line('.')") + lfCmd("let b:lf_blame_changedtick = b:changedtick") + + lfCmd("call prop_remove({'type': 'Lf_hl_gitInlineBlame'})") + prop_list = lfEval("prop_list(line('.'), {'types':['Lf_hl_gitTransparent']})") + if len(prop_list) > 0: + prop_id = int(prop_list[0]["id"]) + line, author, author_time, summary = self._blame_infos[vim.current.buffer.number][prop_id] + if (vim.current.buffer.vars["changedtick"] == self._initial_changedtick[vim.current.buffer.number] + or vim.current.line == line): + author_time = self.relative_time(author_time) + blame_info = "{} • {} • {}".format(author, author_time, summary) + lfCmd("call prop_add(line('.'), 0, {'type': 'Lf_hl_gitInlineBlame', 'text': ' %s'})" + % (escQuote(blame_info))) + else: + lfCmd("call prop_add(line('.'), 0, {'type': 'Lf_hl_gitInlineBlame', 'text': ' Not Committed Yet'})") + else: + lfCmd("call prop_add(line('.'), 0, {'type': 'Lf_hl_gitInlineBlame', 'text': ' Not Committed Yet'})") + + def nvim_showInlineBlame(self): + lfCmd("let b:lf_blame_line_number = line('.')") + lfCmd("let b:lf_blame_changedtick = b:changedtick") + + lfCmd("let ns_id_1 = nvim_create_namespace('LeaderF_Git_Blame_1')") + lfCmd("call nvim_buf_del_extmark(0, ns_id_1, 1)") + + lfCmd("let ns_id_0 = nvim_create_namespace('LeaderF_Git_Blame_0')") + mark_list = lfEval("nvim_buf_get_extmarks(0, ns_id_0, [line('.')-1, 0], [line('.')-1, -1], {})") + if len(mark_list) > 0: + mark_id = int(mark_list[0][0]) + line, author, author_time, summary = self._blame_infos[vim.current.buffer.number][mark_id] + if (vim.current.buffer.vars["changedtick"] == self._initial_changedtick[vim.current.buffer.number] + or vim.current.line == line): + author_time = self.relative_time(author_time) + blame_info = "{} • {} • {}".format(author, author_time, summary) + if lfEval("has('nvim')") == '1': + lfCmd("call nvim_buf_set_extmark(0, ns_id_1, line('.') - 1, 0, {'id': 1, 'virt_text': [[' %s', 'Lf_hl_gitInlineBlame']]})" + % (escQuote(blame_info))) + else: + lfCmd("call prop_add(line('.'), 0, {'type': 'Lf_hl_gitInlineBlame', 'text': ' %s'})" + % (escQuote(blame_info))) + else: + if lfEval("has('nvim')") == '1': + lfCmd("call nvim_buf_set_extmark(0, ns_id_1, line('.') - 1, 0, {'id': 1, 'virt_text': [[ ' Not Committed Yet', 'Lf_hl_gitInlineBlame']]})") + else: + lfCmd("call prop_add(line('.'), 0, {'type': 'Lf_hl_gitInlineBlame', 'text': ' Not Committed Yet'})") + else: + if lfEval("has('nvim')") == '1': + lfCmd("call nvim_buf_set_extmark(0, ns_id_1, line('.') - 1, 0, {'id': 1, 'virt_text': [[ ' Not Committed Yet', 'Lf_hl_gitInlineBlame']]})") + else: + lfCmd("call prop_add(line('.'), 0, {'type': 'Lf_hl_gitInlineBlame', 'text': ' Not Committed Yet'})") + + def hideInlineBlame(self): + if lfEval("has('nvim')") == '1': + lfCmd("let ns_id_1 = nvim_create_namespace('LeaderF_Git_Blame_1')") + lfCmd("call nvim_buf_del_extmark(0, ns_id_1, 1)") + else: + lfCmd("call prop_remove({'type': 'Lf_hl_gitInlineBlame'})") + + def disableInlineBlame(self): + lfCmd("let g:Lf_git_inline_blame_enabled = 0") + lfCmd("augroup Lf_Git_Blame | au! | augroup END") + buffers = {b.number for b in vim.buffers} + if lfEval("has('nvim')") == '1': + for buffer_num in self._blame_infos: + if buffer_num not in buffers: + continue + + lfCmd("call leaderf#Git#RemoveExtmarks(%d)" % buffer_num) + del vim.buffers[buffer_num].vars["lf_blame_changedtick"] + else: + for buffer_num in self._blame_infos: + if buffer_num not in buffers: + continue + + lfCmd("call prop_remove({'type': 'Lf_hl_gitInlineBlame', 'bufnr': %d})" + % buffer_num) + lfCmd("call prop_remove({'type': 'Lf_hl_gitTransparent', 'bufnr': %d})" + % buffer_num) + del vim.buffers[buffer_num].vars["lf_blame_changedtick"] + + self._blame_infos = {} + self._initial_changedtick = {} + def startExplorer(self, win_pos, *args, **kwargs): if self.checkWorkingDirectory() == False: return @@ -4141,13 +4361,16 @@ def startExplorer(self, win_pos, *args, **kwargs): tmp_file_name = f.name self._arguments["--contents"] = [tmp_file_name] - if self._project_root not in self._blame_panels: - self._blame_panels[self._project_root] = BlamePanel(self) + if "--inline" in self._arguments: + self.startInlineBlame(tmp_file_name) + else: + if self._project_root not in self._blame_panels: + self._blame_panels[self._project_root] = BlamePanel(self) - self._blame_panels[self._project_root].create(arguments_dict, - self.createGitCommand(self._arguments, - None), - project_root=self._project_root) + self._blame_panels[self._project_root].create(arguments_dict, + self.createGitCommand(self._arguments, + None), + project_root=self._project_root) if tmp_file_name is not None: os.remove(tmp_file_name) else: diff --git a/doc/leaderf.txt b/doc/leaderf.txt index f9285a51..2060f72c 100644 --- a/doc/leaderf.txt +++ b/doc/leaderf.txt @@ -1291,6 +1291,19 @@ USAGE *leaderf-usage* :LeaderfGitNavigationOpen *LeaderfGitNavigationOpen* Open the navigation panel. +:LeaderfGitEnableInlineBlame *LeaderfGitEnableInlineBlame* + Enable inline blame. This command is a shortcut of `:Leaderf git blame --inline` + +:LeaderfGitDisableInlineBlame *LeaderfGitDisableInlineBlame* + Disable inline blame. + +:LeaderfGitToggleInlineBlame *LeaderfGitToggleInlineBlame* + Toggle inline blame. + +:LeaderfGitUpdateInlineBlame *LeaderfGitUpdateInlineBlame* + If the file is updated in the git repository, we need to use this command + to update the inline blame. + Some handy maps for `Leaderf rg`: | Map | Description diff --git a/plugin/leaderf.vim b/plugin/leaderf.vim index 6d8b2f2f..76ea82bc 100644 --- a/plugin/leaderf.vim +++ b/plugin/leaderf.vim @@ -260,6 +260,10 @@ command! -bar -nargs=0 LeaderfLocList Leaderf loclist command! -bar -nargs=0 LeaderfGit Leaderf git command! -bar -nargs=0 LeaderfGitSplitDiff Leaderf git diff --current-file --side-by-side command! -bar -nargs=0 LeaderfGitNavigationOpen call leaderf#Git#OpenNavigationPanel() +command! -bar -nargs=0 LeaderfGitEnableInlineBlame Leaderf git blame --inline +command! -bar -nargs=0 LeaderfGitDisableInlineBlame call leaderf#Git#DisableInlineBlame() +command! -bar -nargs=0 LeaderfGitToggleInlineBlame call leaderf#Git#ToggleInlineBlame() +command! -bar -nargs=0 LeaderfGitUpdateInlineBlame call leaderf#Git#RestartInlineBlame() try if g:Lf_ShortcutF != "" From a615204e3e3a0f9f1bcfcd367b4e79b69bc4791d Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Mon, 17 Jun 2024 17:30:41 +0800 Subject: [PATCH 245/365] silent --- autoload/leaderf/python/leaderf/gitExpl.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 44379d71..eee1f462 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -4131,8 +4131,8 @@ def startInlineBlame(self, tmp_file_name): lfCmd("let g:Lf_git_inline_blame_enabled = 1") lfCmd("augroup Lf_Git_Blame | augroup END") - lfCmd("autocmd! Lf_Git_Blame BufRead * call leaderf#Git#StartInlineBlame()") - lfCmd("autocmd! Lf_Git_Blame BufWinEnter * call leaderf#Git#StartInlineBlame()") + lfCmd("autocmd! Lf_Git_Blame BufRead * silent call leaderf#Git#StartInlineBlame()") + lfCmd("autocmd! Lf_Git_Blame BufWinEnter * silent call leaderf#Git#StartInlineBlame()") file_name = vim.current.buffer.name self._initial_changedtick[vim.current.buffer.number] = vim.current.buffer.vars["changedtick"] From 68b174400cff601d0692d74cee024f562d1e7dbc Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Mon, 17 Jun 2024 23:23:19 +0800 Subject: [PATCH 246/365] add g:Lf_GitBlameTimeFormat to customize the time format --- autoload/leaderf/python/leaderf/gitExpl.py | 13 ++++++++++--- doc/leaderf.txt | 6 ++++++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index eee1f462..1a0372c3 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -4182,7 +4182,7 @@ def startInlineBlame(self, tmp_file_name): line_number = vim.current.window.cursor[0] _, author, author_time, summary = blame_infos[line_number] - author_time = self.relative_time(author_time) + author_time = self.formated_time(author_time) blame_info = "{} • {} • {}".format(author, author_time, summary) if lfEval("has('nvim')") == '1': lfCmd("let ns_id = nvim_create_namespace('LeaderF_Git_Blame_1')") @@ -4199,6 +4199,13 @@ def startInlineBlame(self, tmp_file_name): lfCmd("autocmd! Lf_Git_Blame InsertLeave call leaderf#Git#ShowInlineBlame({})" .format(id(self))) + def formated_time(self, timestamp): + time_format = lfEval("get(g:, 'Lf_GitBlameTimeFormat', '')") + if time_format == "": + return self.relative_time(timestamp) + else: + return datetime.fromtimestamp(timestamp).strftime(time_format) + def relative_time(self, timestamp): def format_time_unit(value, unit): if value == 1: @@ -4261,7 +4268,7 @@ def showInlineBlame(self): line, author, author_time, summary = self._blame_infos[vim.current.buffer.number][prop_id] if (vim.current.buffer.vars["changedtick"] == self._initial_changedtick[vim.current.buffer.number] or vim.current.line == line): - author_time = self.relative_time(author_time) + author_time = self.formated_time(author_time) blame_info = "{} • {} • {}".format(author, author_time, summary) lfCmd("call prop_add(line('.'), 0, {'type': 'Lf_hl_gitInlineBlame', 'text': ' %s'})" % (escQuote(blame_info))) @@ -4284,7 +4291,7 @@ def nvim_showInlineBlame(self): line, author, author_time, summary = self._blame_infos[vim.current.buffer.number][mark_id] if (vim.current.buffer.vars["changedtick"] == self._initial_changedtick[vim.current.buffer.number] or vim.current.line == line): - author_time = self.relative_time(author_time) + author_time = self.formated_time(author_time) blame_info = "{} • {} • {}".format(author, author_time, summary) if lfEval("has('nvim')") == '1': lfCmd("call nvim_buf_set_extmark(0, ns_id_1, line('.') - 1, 0, {'id': 1, 'virt_text': [[' %s', 'Lf_hl_gitInlineBlame']]})" diff --git a/doc/leaderf.txt b/doc/leaderf.txt index 2060f72c..a9faaf87 100644 --- a/doc/leaderf.txt +++ b/doc/leaderf.txt @@ -1206,6 +1206,12 @@ g:Lf_GitKeyMap *g:Lf_GitKeyMap* it means you can use [c to jump backwards to the previous start of a change and use ]c to jump forwards to the next start of a change. +g:Lf_GitBlameTimeFormat *g:Lf_GitBlameTimeFormat* + Specify a string representing the date and time, controlled by an explicit format string. + The format string is the same as used by strftime(), for example, '%Y-%m-%d %H:%M:%S'. + + Default value is "". + ============================================================================== USAGE *leaderf-usage* From 5d133f15d5426f9adb967c84ca740fa81a7265a1 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Tue, 18 Jun 2024 10:41:08 +0800 Subject: [PATCH 247/365] add g:Lf_GitInlineBlameEnable to customize whether to enable inline blame or not by default --- doc/leaderf.txt | 9 +++++++-- plugin/leaderf.vim | 7 +++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/doc/leaderf.txt b/doc/leaderf.txt index a9faaf87..1984ce2d 100644 --- a/doc/leaderf.txt +++ b/doc/leaderf.txt @@ -1206,9 +1206,14 @@ g:Lf_GitKeyMap *g:Lf_GitKeyMap* it means you can use [c to jump backwards to the previous start of a change and use ]c to jump forwards to the next start of a change. +g:Lf_GitInlineBlameEnable *g:Lf_GitInlineBlameEnable* + Whether to enable inline blame or not by default. + + Default value is 0. + g:Lf_GitBlameTimeFormat *g:Lf_GitBlameTimeFormat* - Specify a string representing the date and time, controlled by an explicit format string. - The format string is the same as used by strftime(), for example, '%Y-%m-%d %H:%M:%S'. + Specify a format string to represent the date and time, the format string + is the same as used by strftime(), for example, '%Y-%m-%d %H:%M:%S'. Default value is "". diff --git a/plugin/leaderf.vim b/plugin/leaderf.vim index 76ea82bc..9da126ab 100644 --- a/plugin/leaderf.vim +++ b/plugin/leaderf.vim @@ -136,6 +136,13 @@ augroup LeaderF_Gtags endif augroup END +if get(g:, 'Lf_GitInlineBlameEnable', 0) == 1 + augroup Lf_Git_Blame + autocmd! BufRead * silent call leaderf#Git#StartInlineBlame() + autocmd! BufWinEnter * silent call leaderf#Git#StartInlineBlame() + augroup END +endif + noremap LeaderfFileTop :Leaderf file --top noremap LeaderfFileBottom :Leaderf file --bottom noremap LeaderfFileLeft :Leaderf file --left From d0aba25a98b2a2271f1ab6af2e42e0f8bbfc282b Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 19 Jun 2024 10:40:57 +0800 Subject: [PATCH 248/365] rename some commands :LeaderfGitEnableInlineBlame => :LeaderfGitInlineBlameEnable :LeaderfGitDisableInlineBlame => :LeaderfGitInlineBlameDisable :LeaderfGitToggleInlineBlame => :LeaderfGitInlineBlameToggle :LeaderfGitUpdateInlineBlame => :LeaderfGitInlineBlameUpdate --- autoload/leaderf/Git.vim | 8 ++++---- doc/leaderf.txt | 8 ++++---- plugin/leaderf.vim | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/autoload/leaderf/Git.vim b/autoload/leaderf/Git.vim index 8e6f2423..2fec269a 100644 --- a/autoload/leaderf/Git.vim +++ b/autoload/leaderf/Git.vim @@ -513,10 +513,10 @@ function! leaderf#Git#Commands() abort \ {"Leaderf git blame": "git blame current file"}, \ {"Leaderf git blame -w": "ignore whitespace when git blame current file"}, \ {"Leaderf git blame --date relative": "show relative date when git blame current file"}, - \ {"LeaderfGitEnableInlineBlame": "Enable inline blame. This command is a shortcut of `:Leaderf git blame --inline`"}, - \ {"LeaderfGitDisableInlineBlame": "Disable inline blame"}, - \ {"LeaderfGitToggleInlineBlame": "Toggle inline blame"}, - \ {"LeaderfGitUpdateInlineBlame": "If the file is updated in the git repository, we need to use this command to update the inline blame."}, + \ {"LeaderfGitInlineBlameEnable": "Enable inline blame. This command is a shortcut of `:Leaderf git blame --inline`"}, + \ {"LeaderfGitInlineBlameDisable": "Disable inline blame"}, + \ {"LeaderfGitInlineBlameToggle": "Toggle inline blame"}, + \ {"LeaderfGitInlineBlameUpdate": "If the file is updated in the git repository, we need to use this command to update the inline blame."}, \ ] endif diff --git a/doc/leaderf.txt b/doc/leaderf.txt index 1984ce2d..ff996822 100644 --- a/doc/leaderf.txt +++ b/doc/leaderf.txt @@ -1302,16 +1302,16 @@ USAGE *leaderf-usage* :LeaderfGitNavigationOpen *LeaderfGitNavigationOpen* Open the navigation panel. -:LeaderfGitEnableInlineBlame *LeaderfGitEnableInlineBlame* +:LeaderfGitInlineBlameEnable *LeaderfGitInlineBlameEnable* Enable inline blame. This command is a shortcut of `:Leaderf git blame --inline` -:LeaderfGitDisableInlineBlame *LeaderfGitDisableInlineBlame* +:LeaderfGitInlineBlameDisable *LeaderfGitInlineBlameDisable* Disable inline blame. -:LeaderfGitToggleInlineBlame *LeaderfGitToggleInlineBlame* +:LeaderfGitInlineBlameToggle *LeaderfGitInlineBlameToggle* Toggle inline blame. -:LeaderfGitUpdateInlineBlame *LeaderfGitUpdateInlineBlame* +:LeaderfGitInlineBlameUpdate *LeaderfGitInlineBlameUpdate* If the file is updated in the git repository, we need to use this command to update the inline blame. diff --git a/plugin/leaderf.vim b/plugin/leaderf.vim index 9da126ab..4a13e8a0 100644 --- a/plugin/leaderf.vim +++ b/plugin/leaderf.vim @@ -267,10 +267,10 @@ command! -bar -nargs=0 LeaderfLocList Leaderf loclist command! -bar -nargs=0 LeaderfGit Leaderf git command! -bar -nargs=0 LeaderfGitSplitDiff Leaderf git diff --current-file --side-by-side command! -bar -nargs=0 LeaderfGitNavigationOpen call leaderf#Git#OpenNavigationPanel() -command! -bar -nargs=0 LeaderfGitEnableInlineBlame Leaderf git blame --inline -command! -bar -nargs=0 LeaderfGitDisableInlineBlame call leaderf#Git#DisableInlineBlame() -command! -bar -nargs=0 LeaderfGitToggleInlineBlame call leaderf#Git#ToggleInlineBlame() -command! -bar -nargs=0 LeaderfGitUpdateInlineBlame call leaderf#Git#RestartInlineBlame() +command! -bar -nargs=0 LeaderfGitInlineBlameEnable Leaderf git blame --inline +command! -bar -nargs=0 LeaderfGitInlineBlameDisable call leaderf#Git#DisableInlineBlame() +command! -bar -nargs=0 LeaderfGitInlineBlameToggle call leaderf#Git#ToggleInlineBlame() +command! -bar -nargs=0 LeaderfGitInlineBlameUpdate call leaderf#Git#RestartInlineBlame() try if g:Lf_ShortcutF != "" From 8df758bf5e32f7c66899746b04e1edbe7bc4ca13 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 19 Jun 2024 16:12:58 +0800 Subject: [PATCH 249/365] update help message --- autoload/leaderf/Git.vim | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/autoload/leaderf/Git.vim b/autoload/leaderf/Git.vim index 2fec269a..9f834e49 100644 --- a/autoload/leaderf/Git.vim +++ b/autoload/leaderf/Git.vim @@ -131,7 +131,7 @@ let s:help = { \ "o: show the details of current commit in an explorer page", \ ": show the details of current commit in an explorer page", \ "<2-LeftMouse>: show the details of current commit in an explorer page", - \ "h: blame the parent commit", + \ "h: blame the parent commit of this line", \ "l: go to the previous blame status", \ "m: show the commit message", \ "p: preview the diffs around the current line", @@ -513,9 +513,9 @@ function! leaderf#Git#Commands() abort \ {"Leaderf git blame": "git blame current file"}, \ {"Leaderf git blame -w": "ignore whitespace when git blame current file"}, \ {"Leaderf git blame --date relative": "show relative date when git blame current file"}, - \ {"LeaderfGitInlineBlameEnable": "Enable inline blame. This command is a shortcut of `:Leaderf git blame --inline`"}, - \ {"LeaderfGitInlineBlameDisable": "Disable inline blame"}, - \ {"LeaderfGitInlineBlameToggle": "Toggle inline blame"}, + \ {"LeaderfGitInlineBlameEnable": "Enable inline blame. This command is a shortcut of `:Leaderf git blame --inline`."}, + \ {"LeaderfGitInlineBlameDisable": "Disable inline blame."}, + \ {"LeaderfGitInlineBlameToggle": "Toggle inline blame."}, \ {"LeaderfGitInlineBlameUpdate": "If the file is updated in the git repository, we need to use this command to update the inline blame."}, \ ] endif From 11c08af2ae56fac83772d21aa5133913784ca2c4 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 19 Jun 2024 17:41:03 +0800 Subject: [PATCH 250/365] update git log command --- autoload/leaderf/python/leaderf/gitExpl.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 1a0372c3..b96d43f7 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -357,8 +357,9 @@ def buildCommandAndBufferName(self): self._cmd = ('git show {} -C{} --pretty=format:"commit %H%nparent %P%n' 'Author: %an <%ae>%nAuthorDate: %ad%nCommitter: %cn <%ce>%nCommitDate:' - ' %cd{}%n%n%s%n%n%b%n" --stat=70 --stat-graph-width=10 -p --no-color' - ).format(self._source, find_copies_harder, sep) + ' %cd{}%n%n%s%n%n%b%n%x2d%x2d%x2d" --stat=70 --stat-graph-width=10 --no-color' + ' && git log -1 -p --pretty=format:"%x20" --no-color {}' + ).format(self._source, find_copies_harder, sep, self._source) if (("--recall" in self._arguments or "--current-file" in self._arguments) and "current_file" in self._arguments): From 7a7127bd0636c4e5ae21ecae2cbd5b0eaf74a02b Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Mon, 24 Jun 2024 22:45:27 +0800 Subject: [PATCH 251/365] use to jump to the corresponding file to edit --- autoload/leaderf.vim | 1 + autoload/leaderf/Git.vim | 46 ++++++++++++++++++++++ autoload/leaderf/python/leaderf/gitExpl.py | 4 ++ doc/leaderf.txt | 1 + 4 files changed, 52 insertions(+) diff --git a/autoload/leaderf.vim b/autoload/leaderf.vim index 2662d74a..708b5b37 100644 --- a/autoload/leaderf.vim +++ b/autoload/leaderf.vim @@ -150,6 +150,7 @@ call s:InitVar('g:Lf_GitFolderIcons', { call s:InitVar('g:Lf_GitKeyMap', { \ 'previous_change': '[c', \ 'next_change': ']c', + \ 'edit_file': '', \}) let s:Lf_CommandMap = { diff --git a/autoload/leaderf/Git.vim b/autoload/leaderf/Git.vim index 9f834e49..19c3b7eb 100644 --- a/autoload/leaderf/Git.vim +++ b/autoload/leaderf/Git.vim @@ -647,6 +647,52 @@ function! leaderf#Git#NextChange() abort endif endfunction +function! leaderf#Git#EditFile(tag) abort + if !filereadable(b:lf_git_buffer_name) + return + endif + + if a:tag == 0 + let start_line_num = line('.') + let line_num_content = b:lf_git_line_num_content + if len(line_num_content) == 0 + return + endif + + let line = line_num_content[0] + let line_len = strlen(line) + + let delimiter = get(g:, 'Lf_GitDelimiter', '│') + let delimiter_len = len(delimiter) + + let buffer_num = bufnr(b:lf_git_buffer_name) + if buffer_num == -1 + exec "tabedit " . b:lf_git_buffer_name + else + let buf_ids = win_findbuf(buffer_num) + call win_gotoid(buf_ids[0]) + endif + + let i = start_line_num - 1 + while i < len(line_num_content) + let line = line_num_content[i] + let last_part = strcharpart(line, line_len - (delimiter_len + 1), 2) + if last_part[0] != '-' + let numbers = split(line, ' ') + if len(numbers) == 2 + let line_num = numbers[0] + else + let line_num = numbers[1] + endif + exec "norm! " . line_num . "G" + return + endif + let i += 1 + endwhile + norm! G + endif +endfunction + function! leaderf#Git#OpenNavigationPanel() abort if !exists("b:lf_explorer_page_id") || b:lf_explorer_page_id == 0 return diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index b96d43f7..0c557e38 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -2626,6 +2626,8 @@ def create(self, arguments_dict, source, **kwargs): if not vim.current.buffer.name: # buffer name is empty lfCmd("setlocal bufhidden=wipe") lfCmd("silent hide edit {}".format(buf_name)) + lfCmd("let b:lf_git_buffer_name = '%s'" % escQuote(os.path.abspath(lfGetFilePath(source)))) + lfCmd("let b:lf_git_line_num_content = {}".format(str(line_num_content))) lfCmd("augroup Lf_Git_Log | augroup END") lfCmd("autocmd! Lf_Git_Log BufWinEnter call leaderf#Git#SetMatches()") ranges = (range(sublist[0], sublist[1] + 1) for sublist in fold_ranges) @@ -2655,6 +2657,8 @@ def create(self, arguments_dict, source, **kwargs): .format(blame_map["previous_change"])) lfCmd("nnoremap {} :call leaderf#Git#NextChange()" .format(blame_map["next_change"])) + lfCmd("nnoremap {} :call leaderf#Git#EditFile(0)" + .format(blame_map["edit_file"])) else: lfCmd("call win_gotoid({})".format(winid)) if not vim.current.buffer.name: # buffer name is empty diff --git a/doc/leaderf.txt b/doc/leaderf.txt index ff996822..95ba3edf 100644 --- a/doc/leaderf.txt +++ b/doc/leaderf.txt @@ -1201,6 +1201,7 @@ g:Lf_GitKeyMap *g:Lf_GitKeyMap* let g:Lf_GitKeyMap = { \ 'previous_change': '[c', \ 'next_change': ']c', + \ 'edit_file': '', \ } < it means you can use [c to jump backwards to the previous start of a change From 805cad832ed1cfb0a0a8450e0730373a23ebb51e Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Tue, 25 Jun 2024 07:25:14 +0800 Subject: [PATCH 252/365] let g:Lf_GitKeyMap support side-by-side mode --- autoload/leaderf/python/leaderf/gitExpl.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 0c557e38..3ff84920 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -2191,6 +2191,11 @@ def create(self, arguments_dict, source, **kwargs): .format(winid)) lfCmd("""call win_execute({}, "let b:lf_diff_view_source = {}")""" .format(winid, str(list(source)))) + key_map = lfEval("g:Lf_GitKeyMap") + lfCmd("""call win_execute({}, 'nnoremap {} [c')""" + .format(winid, key_map["previous_change"])) + lfCmd("""call win_execute({}, 'nnoremap {} ]c')""" + .format(winid, key_map["next_change"])) # if the buffer also in another tabpage, BufHidden is not triggerd # should run this code From 7cc364f5573fb6f2540f6c160f8e0c58bb22057e Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Tue, 25 Jun 2024 16:40:21 +0800 Subject: [PATCH 253/365] neovim has bug --- autoload/leaderf/python/leaderf/gitExpl.py | 10 ++++++++-- autoload/leaderf/python/leaderf/manager.py | 12 ++++++++++-- autoload/leaderf/python/leaderf/utils.py | 1 + 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 3ff84920..55b3c59f 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -270,7 +270,10 @@ def buildCommandAndBufferName(self): self._cmd += extra_options self._buffer_name = "LeaderF://git diff" + extra_options self._file_type = "diff" - self._file_type_cmd = "silent! doautocmd filetypedetect BufNewFile *.diff" + if lfEval("has('nvim')") == '1': + self._file_type_cmd = "setlocal filetype=diff" + else: + self._file_type_cmd = "silent! doautocmd filetypedetect BufNewFile *.diff" class GitLogDiffCommand(GitCommand): @@ -293,7 +296,10 @@ def buildCommandAndBufferName(self): ) self._buffer_name = "LeaderF://" + self._cmd self._file_type = "diff" - self._file_type_cmd = "silent! doautocmd filetypedetect BufNewFile *.diff" + if lfEval("has('nvim')") == '1': + self._file_type_cmd = "setlocal filetype=diff" + else: + self._file_type_cmd = "silent! doautocmd filetypedetect BufNewFile *.diff" class GitCatFileCommand(GitCommand): diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index b29fed28..1f57c78b 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -539,7 +539,11 @@ def _createPreviewWindow(self, config, source, line_num, jump_cmd): cur_winid = lfEval("win_getid()") lfCmd("noautocmd call win_gotoid(%d)" % self._preview_winid) if not isinstance(source, int): - lfCmd("silent! doautocmd filetypedetect BufNewFile %s" % source) + file_type = getExtension(source) + if file_type is None: + lfCmd("silent! doautocmd filetypedetect BufNewFile %s" % source) + else: + lfCmd("setf %s" % getExtension(source)) lfCmd("noautocmd call win_gotoid(%s)" % cur_winid) self._setWinOptions(self._preview_winid) @@ -895,7 +899,11 @@ def _useExistingWindow(self, title, source, line_num, jump_cmd): cur_filetype = getExtension(source) if cur_filetype != self._preview_filetype: - lfCmd("call win_execute(%d, 'silent! doautocmd filetypedetect BufNewFile %s')" % (self._preview_winid, escQuote(source))) + if cur_filetype is None: + lfCmd("call win_execute(%d, 'silent! doautocmd filetypedetect BufNewFile %s')" + % (self._preview_winid, escQuote(source))) + else: + lfCmd("call win_execute(%d, 'setf %s')" % (self._preview_winid, cur_filetype)) self._preview_filetype = lfEval("getbufvar(winbufnr(%d), '&ft')" % self._preview_winid) else: if isinstance(source, int): diff --git a/autoload/leaderf/python/leaderf/utils.py b/autoload/leaderf/python/leaderf/utils.py index 738c3f9b..cdaf67a5 100644 --- a/autoload/leaderf/python/leaderf/utils.py +++ b/autoload/leaderf/python/leaderf/utils.py @@ -1104,6 +1104,7 @@ def nearestAncestor(markers, path): ".csh" : "csh", ".tcsh" : "tcsh", ".xml" : "xml", + ".make" : "make", ".csproj.user" : "xml", ".fsproj.user" : "xml", ".vbproj.user" : "xml", From 50c62686853aab09d8e8ac90e21861bce919df0e Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 26 Jun 2024 21:48:40 +0800 Subject: [PATCH 254/365] define key map in diff file --- autoload/leaderf/Git.vim | 88 +++++++++++++++------- autoload/leaderf/python/leaderf/gitExpl.py | 7 ++ 2 files changed, 66 insertions(+), 29 deletions(-) diff --git a/autoload/leaderf/Git.vim b/autoload/leaderf/Git.vim index 19c3b7eb..53ccad00 100644 --- a/autoload/leaderf/Git.vim +++ b/autoload/leaderf/Git.vim @@ -610,40 +610,70 @@ function! leaderf#Git#SignPlace(added_line_nums, deleted_line_nums, buf_number) endfor endfunction -function! leaderf#Git#PreviousChange() abort - let n = line('.') - let low = 0 - let high = len(b:lf_change_start_lines) - while low < high - let mid = (low + high)/2 - if b:lf_change_start_lines[mid] < n - let low = mid + 1 - else - let high = mid - endif - endwhile +function! leaderf#Git#PreviousChange(tag) abort + if a:tag == 0 + let n = line('.') + let low = 0 + let high = len(b:lf_change_start_lines) + while low < high + let mid = (low + high)/2 + if b:lf_change_start_lines[mid] < n + let low = mid + 1 + else + let high = mid + endif + endwhile - if low - 1 >= 0 - exec printf("norm! %dG0", b:lf_change_start_lines[low - 1]) + if low - 1 >= 0 + exec printf("norm! %dG0", b:lf_change_start_lines[low - 1]) + endif + else +exec g:Lf_py "<< EOF" +cur_line = vim.current.window.cursor[0] +flag = False +for i, line in enumerate(reversed(vim.current.buffer[:cur_line])): + if len(line) > 0 and line[0] in '-+': + if flag == True: + vim.current.window.cursor = [cur_line - i, 0] + break + else: + flag = True + +EOF endif endfunction -function! leaderf#Git#NextChange() abort - let n = line('.') - let low = 0 - let size = len(b:lf_change_start_lines) - let high = size - while low < high - let mid = (low + high)/2 - if b:lf_change_start_lines[mid] <= n - let low = mid + 1 - else - let high = mid - endif - endwhile +function! leaderf#Git#NextChange(tag) abort + if a:tag == 0 + let n = line('.') + let low = 0 + let size = len(b:lf_change_start_lines) + let high = size + while low < high + let mid = (low + high)/2 + if b:lf_change_start_lines[mid] <= n + let low = mid + 1 + else + let high = mid + endif + endwhile - if high < size - exec printf("norm! %dG0", b:lf_change_start_lines[high]) + if high < size + exec printf("norm! %dG0", b:lf_change_start_lines[high]) + endif + else +exec g:Lf_py "<< EOF" +cur_line = vim.current.window.cursor[0] - 1 +flag = False +for i, line in enumerate(vim.current.buffer[cur_line:], cur_line): + if len(line) > 0 and line[0] in '-+': + if flag == True: + vim.current.window.cursor = [i+1, 0] + break + else: + flag = True + +EOF endif endfunction diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 55b3c59f..3e214f05 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -1958,6 +1958,13 @@ def create(self, cmd, content=None): win_pos = arguments.get("--position", ["top"])[0] winid = self._createWindow(win_pos, buffer_name) GitCommandView(self, cmd).create(winid, buf_content=content) + if cmd.getFileType() in ("diff", "git"): + key_map = lfEval("g:Lf_GitKeyMap") + lfCmd("call win_execute({}, 'nnoremap {} :call leaderf#Git#PreviousChange(1)')" + .format(winid, key_map["previous_change"])) + lfCmd("call win_execute({}, 'nnoremap {} :call leaderf#Git#NextChange(1)')" + .format(winid, key_map["next_change"])) + def writeBuffer(self): for v in self._views.values(): From 670ec9129a5299d9578b9123bfe2bf6eb8b9fb2a Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 26 Jun 2024 23:47:34 +0800 Subject: [PATCH 255/365] add key map for 'go to edit file' in diff file --- autoload/leaderf/Git.vim | 57 +++++++++++++++++++++- autoload/leaderf/python/leaderf/gitExpl.py | 3 +- 2 files changed, 57 insertions(+), 3 deletions(-) diff --git a/autoload/leaderf/Git.vim b/autoload/leaderf/Git.vim index 53ccad00..4fd0d717 100644 --- a/autoload/leaderf/Git.vim +++ b/autoload/leaderf/Git.vim @@ -677,12 +677,26 @@ EOF endif endfunction -function! leaderf#Git#EditFile(tag) abort - if !filereadable(b:lf_git_buffer_name) +function! s:GoToFile(file_name) abort + if !filereadable(a:file_name) return endif + let buffer_num = bufnr(fnamemodify(a:file_name, ':p')) + if buffer_num == -1 + exec "tabedit " . a:file_name + else + let buf_ids = win_findbuf(buffer_num) + call win_gotoid(buf_ids[0]) + endif +endfunction + +function! leaderf#Git#EditFile(tag) abort if a:tag == 0 + if !filereadable(b:lf_git_buffer_name) + return + endif + let start_line_num = line('.') let line_num_content = b:lf_git_line_num_content if len(line_num_content) == 0 @@ -720,6 +734,45 @@ function! leaderf#Git#EditFile(tag) abort let i += 1 endwhile norm! G + else + let cur_line = getline('.') + if cur_line =~ '^diff --git a/\S* b/\S*' + let file_name = split(getline('.'))[3][2:] + call s:GoToFile(file_name) + return + endif + + let diff_line_num = search('^diff --git a/\S* b/\S*', 'bnW') + if diff_line_num == 0 + return + endif + let diff_line = getline(diff_line_num) + let file_name = split(diff_line)[3][2:] + let at_line_num = search('^@@', 'bnW') + if at_line_num < diff_line_num || cur_line =~ '^@@' + call s:GoToFile(file_name) + return + endif + + let start_line_num = matchstr(getline(at_line_num), '+\zs\(\d\+\)') + let i = at_line_num + 1 + let cur_line_num = line('.') + let delta = 0 + while i <= cur_line_num + if getline(i) !~ '^-' + let delta += 1 + endif + let i += 1 + endwhile + + if cur_line !~ '^-' + let line_num = start_line_num + delta - 1 + else + let line_num = start_line_num + delta + endif + call s:GoToFile(file_name) + exec "norm! " . line_num . "G" + setlocal cursorline! | redraw | sleep 150m | setlocal cursorline! endif endfunction diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 3e214f05..68dc7e0d 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -1964,7 +1964,8 @@ def create(self, cmd, content=None): .format(winid, key_map["previous_change"])) lfCmd("call win_execute({}, 'nnoremap {} :call leaderf#Git#NextChange(1)')" .format(winid, key_map["next_change"])) - + lfCmd("call win_execute({}, 'nnoremap {} :call leaderf#Git#EditFile(1)')" + .format(winid, key_map["edit_file"])) def writeBuffer(self): for v in self._views.values(): From c831ac590612c4858254bce5bd0ebb01ede5bf11 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 27 Jun 2024 13:50:22 +0800 Subject: [PATCH 256/365] add key map for 'go to edit file' in diff file --- autoload/leaderf/Git.vim | 12 +++++++++++- autoload/leaderf/python/leaderf/gitExpl.py | 6 ++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/autoload/leaderf/Git.vim b/autoload/leaderf/Git.vim index 4fd0d717..b132ae7f 100644 --- a/autoload/leaderf/Git.vim +++ b/autoload/leaderf/Git.vim @@ -734,7 +734,7 @@ function! leaderf#Git#EditFile(tag) abort let i += 1 endwhile norm! G - else + elseif a:tag == 1 let cur_line = getline('.') if cur_line =~ '^diff --git a/\S* b/\S*' let file_name = split(getline('.'))[3][2:] @@ -773,6 +773,16 @@ function! leaderf#Git#EditFile(tag) abort call s:GoToFile(file_name) exec "norm! " . line_num . "G" setlocal cursorline! | redraw | sleep 150m | setlocal cursorline! + else + let file_name = b:lf_git_buffer_name + if b:lf_git_diff_win_pos == 1 + let line_num = line('.') + else + let line_num = getcurpos(b:lf_git_diff_win_id)[1] + endif + call s:GoToFile(file_name) + exec "norm! " . line_num . "G" + setlocal cursorline! | redraw | sleep 150m | setlocal cursorline! endif endfunction diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 68dc7e0d..c79ea0ba 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -2201,6 +2201,10 @@ def create(self, arguments_dict, source, **kwargs): lfCmd("call win_execute({}, 'setlocal cursorline')".format(winid)) lfCmd("call win_execute({}, 'let b:lf_explorer_page_id = {}')" .format(winid, kwargs.get("explorer_page_id", 0))) + lfCmd("call win_execute({}, 'let b:lf_git_diff_win_pos = {}')".format(winid, i)) + lfCmd("call win_execute({}, 'let b:lf_git_diff_win_id = {}')".format(winid, win_ids[1])) + lfCmd("""call win_execute(%d, "let b:lf_git_buffer_name = '%s'")""" + % (winid, escQuote(os.path.abspath(lfGetFilePath(source))))) lfCmd("""call win_execute({}, 'let b:lf_diff_view_mode = "side-by-side"')""" .format(winid)) lfCmd("""call win_execute({}, "let b:lf_diff_view_source = {}")""" @@ -2210,6 +2214,8 @@ def create(self, arguments_dict, source, **kwargs): .format(winid, key_map["previous_change"])) lfCmd("""call win_execute({}, 'nnoremap {} ]c')""" .format(winid, key_map["next_change"])) + lfCmd("""call win_execute({}, 'nnoremap {} :call leaderf#Git#EditFile(2)')""" + .format(winid, key_map["edit_file"])) # if the buffer also in another tabpage, BufHidden is not triggerd # should run this code From e7bcd3b72fa0096aaac974742b8a5b670d50efa0 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 27 Jun 2024 17:17:55 +0800 Subject: [PATCH 257/365] accept needs to confirm if changed --- autoload/leaderf/python/leaderf/rgExpl.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/autoload/leaderf/python/leaderf/rgExpl.py b/autoload/leaderf/python/leaderf/rgExpl.py index 86d96f7d..713a438f 100644 --- a/autoload/leaderf/python/leaderf/rgExpl.py +++ b/autoload/leaderf/python/leaderf/rgExpl.py @@ -1518,7 +1518,7 @@ def undo(self): lfCmd("undo") lfCmd("echohl WarningMsg | redraw | echo ' undo finished!' | echohl None") - def quit(self): + def confirm(self): if self._getInstance().buffer.options["modified"]: selection = int(lfEval("""confirm("buffer changed, apply changes or discard?", "&apply\n&discard")""")) if selection == 0: @@ -1537,8 +1537,14 @@ def quit(self): self._getInstance().buffer.options["modifiable"] = False self._getInstance().buffer.options["undolevels"] = -1 + def quit(self): + self.confirm() super(RgExplManager, self).quit() + lfCmd("silent! autocmd! Lf_Rg_ReplaceMode") + def accept(self, mode=''): + self.confirm() + super(RgExplManager, self).accept(mode) lfCmd("silent! autocmd! Lf_Rg_ReplaceMode") def _writeBuffer(self): From 4f55b230a31e817fbff78707273cc38ceab828c3 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Sat, 29 Jun 2024 19:17:35 +0800 Subject: [PATCH 258/365] use popup_setbuf() --- autoload/leaderf/python/leaderf/manager.py | 60 ++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 1f57c78b..0a8dc71b 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -556,6 +556,44 @@ def _createPreviewWindow(self, config, source, line_num, jump_cmd): lfCmd("""call nvim_win_set_cursor(%d, [%d, 1])""" % (self._preview_winid, line_num)) lfCmd("norm! zz") lfCmd("noautocmd call win_gotoid(%s)" % cur_winid) + elif lfEval("exists('*popup_setbuf')") == "1": + if isinstance(source, int): + lfCmd("noautocmd silent! let winid = popup_create(%d, %s)" + % (source, json.dumps(config))) + else: + filename = source + try: + if self._isBinaryFile(filename): + lfCmd("""let content = map(range(128), '"^@"')""") + else: + lfCmd("let content = readfile('%s', '', 4096)" % escQuote(filename)) + except vim.error as e: + lfPrintError(e) + return + + lfCmd("noautocmd silent! let winid = popup_create(bufadd('/Lf_preview_%s'), %s)" + % (id(self), json.dumps(config))) + lfCmd("call win_execute(winid, 'setlocal modeline')") + lfCmd("call win_execute(winid, 'setlocal undolevels=-1')") + lfCmd("call win_execute(winid, 'setlocal noswapfile')") + lfCmd("call win_execute(winid, 'setlocal nobuflisted')") + lfCmd("call win_execute(winid, 'setlocal bufhidden=hide')") + lfCmd("call win_execute(winid, 'setlocal buftype=nofile')") + lfCmd("noautocmd call popup_settext(winid, content)") + + lfCmd("call win_execute(winid, 'silent! doautocmd filetypedetect BufNewFile %s')" + % escQuote(filename)) + + self._preview_winid = int(lfEval("winid")) + self._setWinOptions(self._preview_winid) + self._preview_filetype = lfEval("getbufvar(winbufnr(winid), '&ft')") + + if jump_cmd: + lfCmd("""call win_execute(%d, '%s')""" % (self._preview_winid, escQuote(jump_cmd))) + lfCmd("call win_execute(%d, 'norm! zz')" % self._preview_winid) + elif line_num > 0: + lfCmd("""call win_execute(%d, "call cursor(%d, 1)")""" % (self._preview_winid, line_num)) + lfCmd("call win_execute(%d, 'norm! zz')" % self._preview_winid) else: if isinstance(source, int): lfCmd("let content = getbufline(%d, 1, '$')" % source) @@ -905,6 +943,28 @@ def _useExistingWindow(self, title, source, line_num, jump_cmd): else: lfCmd("call win_execute(%d, 'setf %s')" % (self._preview_winid, cur_filetype)) self._preview_filetype = lfEval("getbufvar(winbufnr(%d), '&ft')" % self._preview_winid) + elif lfEval("exists('*popup_setbuf')") == "1": + if isinstance(source, int): + lfCmd("call popup_setbuf(%d, %d)" % (self._preview_winid, source)) + self._preview_filetype = lfEval("getbufvar(winbufnr(%d), '&ft')" % self._preview_winid) + else: + filename = source + try: + if self._isBinaryFile(filename): + lfCmd("""let content = map(range(128), '"^@"')""") + else: + lfCmd("let content = readfile('%s', '', 4096)" % escQuote(filename)) + except vim.error as e: + lfPrintError(e) + return + lfCmd("call popup_setbuf(%d, bufadd('/Lf_preview_%d'))" % (self._preview_winid, id(self))) + lfCmd("noautocmd call popup_settext(%d, content)" % self._preview_winid) + + cur_filetype = getExtension(filename) + if cur_filetype != self._preview_filetype: + lfCmd("call win_execute(%d, 'silent! doautocmd filetypedetect BufNewFile %s')" + % (self._preview_winid, escQuote(filename))) + self._preview_filetype = lfEval("getbufvar(winbufnr(%d), '&ft')" % self._preview_winid) else: if isinstance(source, int): lfCmd("noautocmd call popup_settext(%d, getbufline(%d, 1, 4096))" % (self._preview_winid, source)) From e91858f71703971692110c032febe0c63c1b1690 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Tue, 2 Jul 2024 13:16:51 +0800 Subject: [PATCH 259/365] G0zz --- autoload/leaderf/python/leaderf/gitExpl.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index c79ea0ba..2919f371 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -1692,7 +1692,7 @@ def getKey(info): if index < len(structure) and structure[index].path == path: # lfCmd("call win_gotoid({})" .format(self.getWindowId())) # lfCmd("{} | norm! 0zz" .format(index + 1 + len(self._head))) - lfCmd("call win_execute({}, 'norm! {}Gzz')" + lfCmd("call win_execute({}, 'norm! {}G0zz')" .format(self.getWindowId(), index + 1 + len(self._head))) else: if not self.inFileStructure(path): @@ -1714,7 +1714,7 @@ def getKey(info): index = Bisect.bisect_left(structure, 0, index, index + increment, key=getKey) if index < len(structure) and structure[index].path == path: - lfCmd("call win_execute({}, 'norm! {}Gzz')" + lfCmd("call win_execute({}, 'norm! {}G0zz')" .format(self.getWindowId(), index + 1 + len(self._head))) # lfCmd("call win_gotoid({})" .format(self.getWindowId())) # lfCmd("{} | norm! 0zz" .format(index + 1 + len(self._head))) From ea67d004f86ac10e29708fbb4de84f72b87df612 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 3 Jul 2024 14:34:33 +0800 Subject: [PATCH 260/365] 'Leaderf git diff @~5 @ -- autoload/leaderf/python/leaderf/rgExpl.py' raise exception --- autoload/leaderf/python/leaderf/gitExpl.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 2919f371..dfccd396 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -260,10 +260,11 @@ def buildCommandAndBufferName(self): extra_options += " " + " ".join(self._arguments["extra"]) if self._source is not None: - file_name = lfGetFilePath(self._source) - if " " in file_name: - file_name = file_name.replace(' ', r'\ ') - extra_options += " -- {}".format(file_name) + if " -- " not in self._arguments["arg_line"]: + file_name = lfGetFilePath(self._source) + if " " in file_name: + file_name = file_name.replace(' ', r'\ ') + extra_options += " -- {}".format(file_name) elif "--current-file" in self._arguments and "current_file" in self._arguments: extra_options += " -- {}".format(self._arguments["current_file"]) From 47380c49d17fe93dc30ec34bb2bc783e3759c88b Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 3 Jul 2024 16:48:43 +0800 Subject: [PATCH 261/365] diff algorithm is not right when switch to side-by-side mode --- autoload/leaderf/python/leaderf/gitExpl.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index dfccd396..e3a767a6 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -1178,6 +1178,8 @@ def setDiffViewMode(self, mode): if "algorithm:" in diffopt: algo = re.sub(r".*algorithm:(\w+).*", r"\1", diffopt) self.setDiffAlgorithm(algo) + else: + self.setDiffAlgorithm("myers") else: self._buffer[1] = ' Side-by-side ○ Unified ◉' self._buffer.options['modifiable'] = False @@ -3084,6 +3086,14 @@ def toggleDiffViewMode(self): self._navigation_panel.tree_view.setDiffViewMode(self._diff_view_mode) + if self._diff_view_mode == 'side-by-side': + diffopt = lfEval("&diffopt") + if "algorithm:" in diffopt: + algo = re.sub(r".*algorithm:(\w+).*", r"\1", diffopt) + self._diff_algorithm = algo + else: + self._diff_algorithm = "myers" + source = self.getExistingSource() self.open(False, preview=True, diff_view_source=source) From 967393ddd68f9f10f5379fa11ed0d4a6c487a142 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 4 Jul 2024 15:26:37 +0800 Subject: [PATCH 262/365] fix issue #1087 --- autoload/leaderf.vim | 2 ++ autoload/leaderf/python/leaderf/instance.py | 3 ++- autoload/leaderf/python/leaderf/manager.py | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/autoload/leaderf.vim b/autoload/leaderf.vim index 708b5b37..d5ad609f 100644 --- a/autoload/leaderf.vim +++ b/autoload/leaderf.vim @@ -621,7 +621,9 @@ endfunction function! leaderf#Quit(manager_id) abort exec g:Lf_py "import ctypes" + exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value.is_autocmd = True", a:manager_id) exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value.quit()", a:manager_id) + exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value.is_autocmd = False", a:manager_id) endfunction function! leaderf#ResetPopupOptions(winid, option, value) abort diff --git a/autoload/leaderf/python/leaderf/instance.py b/autoload/leaderf/python/leaderf/instance.py index 71b4f165..a628f3f5 100644 --- a/autoload/leaderf/python/leaderf/instance.py +++ b/autoload/leaderf/python/leaderf/instance.py @@ -1189,7 +1189,8 @@ def exitBuffer(self): vim.options['eventignore'] = saved_eventignore if len(vim.windows) > 1: - lfCmd("silent! hide") + if self._manager.is_autocmd == False: + lfCmd("silent! hide") if self._orig_win_id is not None: lfCmd("call win_gotoid(%d)" % self._orig_win_id) else: diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 0a8dc71b..135dfe26 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -131,6 +131,7 @@ def __init__(self): self._preview_filetype = None self._orig_source = None self._preview_config = {} + self.is_autocmd = False self._circular_scroll = lfEval("get(g:, 'Lf_EnableCircularScroll', 0)") == '1' if lfEval("has('patch-8.1.1615') || has('nvim-0.5.0')") == '0': lfCmd("let g:Lf_PreviewInPopup = 0") From ed37b5c628cdf0496f8d9deb6f0d6a87645b99b0 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 4 Jul 2024 21:32:46 +0800 Subject: [PATCH 263/365] setlocal filetype=git --- autoload/leaderf/python/leaderf/gitExpl.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index e3a767a6..496f54b8 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -4137,7 +4137,7 @@ def preview(self): lfCmd("call win_execute({}, 'setlocal nonumber')".format(preview_winid)) self.gotoLine(preview_winid, line_num) - lfCmd("call win_execute({}, 'setlocal filetype=diff')".format(preview_winid)) + lfCmd("call win_execute({}, 'setlocal filetype=git')".format(preview_winid)) def gotoLine(self, winid, line_num): found = False From 46b056e15df33827a043445c9ac5d72269682b15 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Fri, 5 Jul 2024 18:22:53 +0800 Subject: [PATCH 264/365] can not jump to the right line when blamePrevious --- autoload/leaderf/python/leaderf/gitExpl.py | 53 +++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 496f54b8..48dcd260 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -3824,6 +3824,51 @@ def setOptions(self, winid): lfCmd("call win_execute({}, 'setlocal noswapfile')".format(winid)) lfCmd("call win_execute({}, 'setlocal nospell')".format(winid)) + def getLineNumber(self, commit_id, file_name, line_num, text, project_root): + cmd = 'git show --pretty= -U0 {} -- {}'.format(commit_id, file_name) + outputs = ParallelExecutor.run(cmd, directory=project_root) + found = False + for i, line in enumerate(outputs[0]): + # @@ -2,11 +2,21 @@ + if line.startswith("@@"): + line_numbers = line.split("+", 1)[1].split(None, 1)[0] + if "," in line_numbers: + start, count = line_numbers.split(",") + start = int(start) + count = int(count) + else: + # @@ -1886 +1893 @@ + start = int(line_numbers) + count = 1 + + if start + count > line_num: + found = True + orig_line_numbers = line.split(None, 2)[1].lstrip("-") + if "," in orig_line_numbers: + orig_start, orig_count = orig_line_numbers.split(",") + orig_start = int(orig_start) + orig_count = int(orig_count) + else: + orig_start = int(orig_line_numbers) + orig_count = 1 + + if orig_count == 1 or orig_count == 0: + return orig_start + elif orig_count == count: + return orig_start + line_num - start + else: + ratio = 0 + index = i + 1 + for j, line in enumerate(outputs[0][index: index + orig_count], index): + r = SequenceMatcher(None, text, line).ratio() + if r > ratio: + ratio = r + index = j + + return orig_start + index - i - 1 + + return line_num + def blamePrevious(self): if vim.current.line == "": return @@ -3838,12 +3883,17 @@ def blamePrevious(self): return line_num, file_name = vim.current.line.rsplit('\t', 1)[1].split(None, 1) + line_num = int(line_num) project_root = lfEval("b:lf_blame_project_root") blame_panel = self._blame_panels[project_root] blame_buffer_name = vim.current.buffer.name alternate_winid = blame_panel.getAlternateWinid(blame_buffer_name) blame_winid = lfEval("win_getid()") + alternate_buffer_num = int(lfEval("winbufnr({})".format(alternate_winid))) + text = vim.buffers[alternate_buffer_num][vim.current.window.cursor[0] - 1] + line_num = self.getLineNumber(commit_id, file_name, line_num, text, project_root) + if commit_id not in blame_panel.getBlameDict(blame_buffer_name): cmd = 'git log -2 --pretty="%H" --name-status --follow {} -- {}'.format(commit_id, file_name) @@ -4158,8 +4208,9 @@ def gotoLine(self, winid, line_num): start = int(start) count = int(count) else: + # @@ -1886 +1893 @@ start = int(line_numbers) - count = 0 + count = 1 if start + count > line_num: found = True From 039dd5c9fb070bc64fe2ec1e47e3fe81a8dbaa5e Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Fri, 5 Jul 2024 22:44:30 +0800 Subject: [PATCH 265/365] do not change the cursorline position when blamePrevious --- autoload/leaderf/python/leaderf/gitExpl.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 48dcd260..ac188065 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -3893,6 +3893,7 @@ def blamePrevious(self): alternate_buffer_num = int(lfEval("winbufnr({})".format(alternate_winid))) text = vim.buffers[alternate_buffer_num][vim.current.window.cursor[0] - 1] line_num = self.getLineNumber(commit_id, file_name, line_num, text, project_root) + top_line_delta = vim.current.window.cursor[0] - int(lfEval("line('w0')")) if commit_id not in blame_panel.getBlameDict(blame_buffer_name): cmd = 'git log -2 --pretty="%H" --name-status --follow {} -- {}'.format(commit_id, @@ -3936,7 +3937,7 @@ def blamePrevious(self): if alternate_buffer_name in blame_buffer_dict: blame_buffer, alternate_buffer_num = blame_buffer_dict[alternate_buffer_name] lfCmd("buffer {}".format(alternate_buffer_num)) - lfCmd("noautocmd norm! {}Gzz".format(line_num)) + lfCmd("noautocmd norm! {}Gzt{}G0".format(line_num-top_line_delta, line_num)) top_line = lfEval("line('w0')") lfCmd("noautocmd call win_gotoid({})".format(blame_winid)) @@ -3974,7 +3975,7 @@ def blamePrevious(self): lfCmd("setlocal nomodifiable") alternate_buffer_num = vim.current.buffer.number - lfCmd("noautocmd norm! {}Gzz".format(line_num)) + lfCmd("noautocmd norm! {}Gzt{}G0".format(line_num-top_line_delta, line_num)) top_line = lfEval("line('w0')") lfCmd("noautocmd call win_gotoid({})".format(blame_winid)) @@ -4019,7 +4020,7 @@ def blamePrevious(self): ) = blame_panel.getBlameDict(blame_buffer_name)[commit_id] lfCmd("noautocmd call win_gotoid({})".format(alternate_winid)) lfCmd("buffer {}".format(alternate_buffer_num)) - lfCmd("noautocmd norm! {}Gzz".format(line_num)) + lfCmd("noautocmd norm! {}Gzt{}G0".format(line_num-top_line_delta, line_num)) top_line = lfEval("line('w0')") lfCmd("noautocmd call win_gotoid({})".format(blame_winid)) From 63f551b9e47a50b33a15b23e464b6085bc06d0bb Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Fri, 5 Jul 2024 22:54:20 +0800 Subject: [PATCH 266/365] revert ed37b5c628cdf0496f8d9deb6f0d6a87645b99b0 sometimes no color if `setlocal filetype=git`, bug? --- autoload/leaderf/python/leaderf/gitExpl.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index ac188065..e8e45147 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -4188,7 +4188,7 @@ def preview(self): lfCmd("call win_execute({}, 'setlocal nonumber')".format(preview_winid)) self.gotoLine(preview_winid, line_num) - lfCmd("call win_execute({}, 'setlocal filetype=git')".format(preview_winid)) + lfCmd("call win_execute({}, 'setlocal filetype=diff')".format(preview_winid)) def gotoLine(self, winid, line_num): found = False From b0dda596e3757fb10a2e97bae346c3240b305477 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Sat, 6 Jul 2024 20:52:11 +0800 Subject: [PATCH 267/365] color dispears if change the date format --- autoload/leaderf/python/leaderf/gitExpl.py | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index e8e45147..edd25e39 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -1027,9 +1027,16 @@ def highlightRestHeatDate2(self, normal_blame_list, unix_blame_list): self._highlight(current_time, date_dict) def _highlight(self, current_time, date_dict): + date_set = set() for date, timestamp in date_dict.values(): - index = Bisect.bisect_left(self._heat_seconds, current_time - timestamp) - lfCmd(r"syn match Lf_hl_blame_heat_{} /\<{}\>/".format(index, date)) + if date not in date_set: + date_set.add(date) + index = Bisect.bisect_left(self._heat_seconds, current_time - timestamp) + lfCmd(r"syn match Lf_hl_blame_heat_{} /\<{}\>/".format(index, date)) + + def clearHeatSyntax(self): + for i in range(len(self._heat_seconds)): + lfCmd("silent! syn clear Lf_hl_blame_heat_{}".format(i)) class LfOrderedDict(OrderedDict): @@ -2881,6 +2888,14 @@ def create(self, arguments_dict, cmd, project_root=None): self._views[buffer_name].create(-1, buf_content=outputs[0]) lfCmd("vertical resize {}".format(line_width + line_num_width)) lfCmd("noautocmd norm! {}Gzt{}G0".format(top_line, cursor_line)) + if date_format != lfEval("b:lf_blame_date_format"): + lfCmd("let b:lf_blame_date_format = '{}'".format(date_format)) + blame_view = self._views[buffer_name] + blame_view.clearHeatSyntax() + if date_format in ["iso", "iso-strict", "short"]: + blame_view.highlightHeatDate1(date_format, outputs[0]) + else: + blame_view.highlightHeatDate2(outputs[1], outputs[2]) else: winid = int(lfEval("win_getid()")) blame_view = GitBlameView(self, cmd) @@ -2899,6 +2914,7 @@ def create(self, arguments_dict, cmd, project_root=None): blame_view.highlightHeatDate2(outputs[1], outputs[2]) self._owner.defineMaps(blame_winid) lfCmd("let b:lf_blame_project_root = '{}'".format(self._project_root)) + lfCmd("let b:lf_blame_date_format = '{}'".format(date_format)) lfCmd("noautocmd norm! {}Gzt{}G0".format(top_line, cursor_line)) lfCmd("call win_execute({}, 'setlocal scrollbind')".format(winid)) lfCmd("setlocal scrollbind") From ce15814ac8010ce02bec34b62d2c70a2644ea8bf Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Sun, 7 Jul 2024 10:20:15 +0800 Subject: [PATCH 268/365] preview when blamePrevious --- autoload/leaderf/Git.vim | 10 ++++++++++ autoload/leaderf/python/leaderf/gitExpl.py | 19 ++++++++++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/autoload/leaderf/Git.vim b/autoload/leaderf/Git.vim index b132ae7f..b9ab748c 100644 --- a/autoload/leaderf/Git.vim +++ b/autoload/leaderf/Git.vim @@ -327,6 +327,16 @@ function leaderf#Git#PreviewFilter(winid, key) abort call popup_close(a:winid) call feedkeys("\", 't') return 1 + elseif a:key == "h" + let manager_id = getbufvar(winbufnr(a:winid), 'lf_blame_manager_id') + exec g:Lf_py "import ctypes" + exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value.blamePrevious()", manager_id) + return 1 + elseif a:key == "l" + let manager_id = getbufvar(winbufnr(a:winid), 'lf_blame_manager_id') + exec g:Lf_py "import ctypes" + exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value.blameNext()", manager_id) + return 1 elseif a:key == "\" call win_execute(a:winid, "norm! j") return 1 diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index edd25e39..d99d79f2 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -4046,6 +4046,13 @@ def blamePrevious(self): lfCmd("vertical resize {}".format(blame_win_width)) lfCmd("noautocmd norm! {}Gzt{}G0".format(top_line, line_num)) + if lfEval("exists('b:lf_preview_winid') && winbufnr(b:lf_preview_winid) != -1") == '1': + if lfEval("has('nvim')") == '1': + lfCmd("call nvim_win_close(b:lf_preview_winid, 1)") + else: + lfCmd("call popup_close(b:lf_preview_winid)") + self.preview() + def blameNext(self): project_root = lfEval("b:lf_blame_project_root") blame_panel = self._blame_panels[project_root] @@ -4059,6 +4066,7 @@ def blameNext(self): lfCmd("noautocmd call win_gotoid({})".format(alternate_winid)) lfCmd("buffer {}".format(alternate_buffer_num)) + lfCmd("noautocmd norm! {}Gzt{}G0".format(top_line, cursor_line)) lfCmd("noautocmd call win_gotoid({})".format(blame_winid)) lfCmd("setlocal modifiable") @@ -4067,6 +4075,13 @@ def blameNext(self): lfCmd("vertical resize {}".format(blame_win_width)) lfCmd("noautocmd norm! {}Gzt{}G0".format(top_line, cursor_line)) + if lfEval("exists('b:lf_preview_winid') && winbufnr(b:lf_preview_winid) != -1") == '1': + if lfEval("has('nvim')") == '1': + lfCmd("call nvim_win_close(b:lf_preview_winid, 1)") + else: + lfCmd("call popup_close(b:lf_preview_winid)") + self.preview() + def showCommitMessage(self): if vim.current.line == "": return @@ -4197,11 +4212,13 @@ def preview(self): self._preview_panel.create(cmd, self.generateConfig(project_root), outputs[0]) preview_winid = self._preview_panel.getPreviewWinId() self._setWinOptions(preview_winid) + lfCmd("let b:lf_preview_winid = {}".format(preview_winid)) if lfEval("has('nvim')") == '1': - lfCmd("let b:lf_preview_winid = {}".format(preview_winid)) lfCmd("call nvim_win_set_option(%d, 'number', v:false)" % preview_winid) else: lfCmd("call win_execute({}, 'setlocal nonumber')".format(preview_winid)) + lfCmd("call win_execute({}, 'let b:lf_blame_manager_id = {}')".format(preview_winid, + id(self))) self.gotoLine(preview_winid, line_num) lfCmd("call win_execute({}, 'setlocal filetype=diff')".format(preview_winid)) From d0053098f9919319a7a493bc9694f48caeb433fc Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Sun, 7 Jul 2024 10:24:50 +0800 Subject: [PATCH 269/365] leaderf#Git#ShowCommitMessage should have its own filter --- autoload/leaderf/Git.vim | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/autoload/leaderf/Git.vim b/autoload/leaderf/Git.vim index b9ab748c..76223107 100644 --- a/autoload/leaderf/Git.vim +++ b/autoload/leaderf/Git.vim @@ -297,7 +297,7 @@ function! leaderf#Git#ShowCommitMessage(message) abort \ "border": [1, 1, 1, 1], \ "borderchars": g:Lf_PopupBorders, \ "borderhighlight": ["Lf_hl_popupBorder"], - \ "filter": "leaderf#Git#PreviewFilter", + \ "filter": "leaderf#Git#ShowMsgFilter", \ "mapping": 0, \} @@ -350,6 +350,39 @@ function leaderf#Git#PreviewFilter(winid, key) abort return 1 endfunction +function leaderf#Git#ShowMsgFilter(winid, key) abort + if a:key == "\" + if exists("*getmousepos") + let pos = getmousepos() + if pos.winid != a:winid + call popup_close(a:winid) + endif + endif + endif + + if a:key == "\" + call popup_close(a:winid) + return 1 + elseif a:key == "j" || a:key == "k" + call popup_close(a:winid) + return 0 + elseif a:key == "\" + call popup_close(a:winid) + call feedkeys("\", 't') + return 1 + elseif a:key == "\" + call win_execute(a:winid, "norm! j") + return 1 + elseif a:key == "\" + call win_execute(a:winid, "norm! k") + return 1 + else + return leaderf#popupModePreviewFilter(a:winid, a:key) + endif + + return 1 +endfunction + function! leaderf#Git#TreeViewMaps(id) abort exec g:Lf_py "import ctypes" let tree_view = printf("ctypes.cast(%d, ctypes.py_object).value", a:id) From 0d0a0f4a81583152d53223fe32f695fe141da83f Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Sun, 7 Jul 2024 11:34:56 +0800 Subject: [PATCH 270/365] the preview should quit after the blame window quits --- autoload/leaderf/Git.vim | 6 +++++- autoload/leaderf/python/leaderf/gitExpl.py | 7 +++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/autoload/leaderf/Git.vim b/autoload/leaderf/Git.vim index 76223107..c0ef76a7 100644 --- a/autoload/leaderf/Git.vim +++ b/autoload/leaderf/Git.vim @@ -327,6 +327,10 @@ function leaderf#Git#PreviewFilter(winid, key) abort call popup_close(a:winid) call feedkeys("\", 't') return 1 + elseif a:key == "q" + call popup_close(a:winid) + call feedkeys("q", 't') + return 1 elseif a:key == "h" let manager_id = getbufvar(winbufnr(a:winid), 'lf_blame_manager_id') exec g:Lf_py "import ctypes" @@ -440,6 +444,7 @@ function! leaderf#Git#BlameMaps(id) abort exec printf('nnoremap l :exec g:Lf_py "%s.blameNext()"', blame_manager) exec printf('nnoremap m :exec g:Lf_py "%s.showCommitMessage()"', blame_manager) exec printf('nnoremap p :exec g:Lf_py "%s.preview()"', blame_manager) + exec printf('nnoremap q :exec g:Lf_py "%s.quit()"', blame_manager) if has("nvim") nnoremap j :call leaderf#Git#CloseFloatWin()j nnoremap k :call leaderf#Git#CloseFloatWin()k @@ -447,7 +452,6 @@ function! leaderf#Git#BlameMaps(id) abort nnoremap :call leaderf#Git#CloseFloatWinMouse() endif nnoremap :call leaderf#Git#ShowHelp("blame") - nnoremap q :bwipe endfunction function! leaderf#Git#TimerCallback(manager_id, id) abort diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index d99d79f2..23ace56f 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -4223,6 +4223,13 @@ def preview(self): self.gotoLine(preview_winid, line_num) lfCmd("call win_execute({}, 'setlocal filetype=diff')".format(preview_winid)) + def quit(self): + if lfEval("has('nvim')") == '1': + if lfEval("exists('b:lf_preview_winid') && winbufnr(b:lf_preview_winid) != -1") == '1': + lfCmd("call nvim_win_close(b:lf_preview_winid, 1)") + + lfCmd("bwipe") + def gotoLine(self, winid, line_num): found = False current_line = 0 From 38d3fcb49d198a50b1d91cdf5ad38fae1c756d0e Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Sun, 7 Jul 2024 19:37:45 +0800 Subject: [PATCH 271/365] the return value of matchadd() can be the same for different tabpages the vim.current.window is not the same as the window where the hidden buffer located in the callback of BufHidden autocmd --- autoload/leaderf/python/leaderf/gitExpl.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 23ace56f..6619f2b1 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -2280,7 +2280,10 @@ def deregister(self, view): del self._hidden_views[name] def bufHidden(self, view): - lfCmd("silent! call leaderf#Git#ClearMatches()") + # window is closed if not equal + if int(lfEval("win_getid()")) == view.getWindowId(): + lfCmd("silent! call leaderf#Git#ClearMatches()") + name = view.getBufferName() if name in self._views: del self._views[name] From 5110a91318a401ea9d68dbc8cfb36079adbe2354 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Mon, 8 Jul 2024 15:43:20 +0800 Subject: [PATCH 272/365] blamePrevious does not work well if the file was renamed --- autoload/leaderf/python/leaderf/gitExpl.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 6619f2b1..e02015c5 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -468,7 +468,7 @@ def __init__(self, arguments_dict, commit_id, file_name): super(GitShowCommand, self).__init__(arguments_dict, None) def buildCommandAndBufferName(self): - self._cmd = "git show {} -- {}".format(self._commit_id, self._file_name) + self._cmd = "git log -1 -p --follow {} -- {}".format(self._commit_id, self._file_name) self._file_type = "git" self._file_type_cmd = "setlocal filetype=git" @@ -3844,7 +3844,7 @@ def setOptions(self, winid): lfCmd("call win_execute({}, 'setlocal nospell')".format(winid)) def getLineNumber(self, commit_id, file_name, line_num, text, project_root): - cmd = 'git show --pretty= -U0 {} -- {}'.format(commit_id, file_name) + cmd = 'git log -1 -p --pretty= -U0 --follow {} -- {}'.format(commit_id, file_name) outputs = ParallelExecutor.run(cmd, directory=project_root) found = False for i, line in enumerate(outputs[0]): From 4a92e265195db2199369bd4da985c15e41a90b16 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Mon, 8 Jul 2024 17:43:46 +0800 Subject: [PATCH 273/365] bug when jump to next change in unified view --- autoload/leaderf/Git.vim | 12 ++++++++++-- autoload/leaderf/python/leaderf/gitExpl.py | 4 ++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/autoload/leaderf/Git.vim b/autoload/leaderf/Git.vim index c0ef76a7..5de97831 100644 --- a/autoload/leaderf/Git.vim +++ b/autoload/leaderf/Git.vim @@ -675,6 +675,11 @@ function! leaderf#Git#PreviousChange(tag) abort exec printf("norm! %dG0", b:lf_change_start_lines[low - 1]) endif else + call s:PreviousChange() + endif +endfunction + +function! s:PreviousChange() abort exec g:Lf_py "<< EOF" cur_line = vim.current.window.cursor[0] flag = False @@ -687,7 +692,6 @@ for i, line in enumerate(reversed(vim.current.buffer[:cur_line])): flag = True EOF - endif endfunction function! leaderf#Git#NextChange(tag) abort @@ -709,6 +713,11 @@ function! leaderf#Git#NextChange(tag) abort exec printf("norm! %dG0", b:lf_change_start_lines[high]) endif else + call s:NextChange() + endif +endfunction + +function! s:NextChange() abort exec g:Lf_py "<< EOF" cur_line = vim.current.window.cursor[0] - 1 flag = False @@ -721,7 +730,6 @@ for i, line in enumerate(vim.current.buffer[cur_line:], cur_line): flag = True EOF - endif endfunction function! s:GoToFile(file_name) abort diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index e02015c5..54568c3a 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -2691,9 +2691,9 @@ def create(self, arguments_dict, source, **kwargs): lfCmd("let b:lf_diff_view_mode = 'unified'") lfCmd("let b:lf_diff_view_source = {}".format(str(list(source)))) blame_map = lfEval("g:Lf_GitKeyMap") - lfCmd("nnoremap {} :call leaderf#Git#PreviousChange()" + lfCmd("nnoremap {} :call leaderf#Git#PreviousChange(0)" .format(blame_map["previous_change"])) - lfCmd("nnoremap {} :call leaderf#Git#NextChange()" + lfCmd("nnoremap {} :call leaderf#Git#NextChange(0)" .format(blame_map["next_change"])) lfCmd("nnoremap {} :call leaderf#Git#EditFile(0)" .format(blame_map["edit_file"])) From b8ca00a70737d6ccb71b996c60234f20635a8d52 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Mon, 8 Jul 2024 18:00:18 +0800 Subject: [PATCH 274/365] add support for `Leaderf git log --current-line` --- autoload/leaderf/Any.vim | 5 +- autoload/leaderf/Git.vim | 2 + autoload/leaderf/python/leaderf/gitExpl.py | 97 +++++++++++++++++++--- 3 files changed, 93 insertions(+), 11 deletions(-) diff --git a/autoload/leaderf/Any.vim b/autoload/leaderf/Any.vim index 24534b26..779b51d9 100644 --- a/autoload/leaderf/Any.vim +++ b/autoload/leaderf/Any.vim @@ -217,7 +217,10 @@ let g:Lf_Arguments = { \ "jumps": [], \ "git":{ \ "log": [ - \ {"name": ["--current-file"], "nargs": 0, "help": "show logs of current file"}, + \ [ + \ {"name": ["--current-file"], "nargs": 0, "help": "show logs of current file"}, + \ {"name": ["--current-line"], "nargs": 0, "help": "show logs of current line"}, + \ ], \ [ \ {"name": ["--directly"], "nargs": 0, "help": "output the logs directly"}, \ {"name": ["--explorer"], "nargs": 0, "help": "view changed files of one commit in a tree explorer"}, diff --git a/autoload/leaderf/Git.vim b/autoload/leaderf/Git.vim index 5de97831..3485f457 100644 --- a/autoload/leaderf/Git.vim +++ b/autoload/leaderf/Git.vim @@ -557,6 +557,8 @@ function! leaderf#Git#Commands() abort \ {"Leaderf git log --explorer --navigation-position bottom": "specify the position of navigation panel in explorer tabpage"}, \ {"Leaderf git log --current-file": "fuzzy search and view the log of current file"}, \ {"Leaderf git log --current-file --explorer":"fuzzy search and view the log of current file in explorer tabpage"}, + \ {"Leaderf git log --current-line": "fuzzy search and view the log of current line"}, + \ {"Leaderf git log --current-line --explorer":"fuzzy search and view the log of current line in explorer tabpage"}, \ {"Leaderf git blame": "git blame current file"}, \ {"Leaderf git blame -w": "ignore whitespace when git blame current file"}, \ {"Leaderf git blame --date relative": "show relative date when git blame current file"}, diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 54568c3a..7d837a17 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -143,6 +143,7 @@ class GitLogExplorer(GitExplorer): def __init__(self): super(GitLogExplorer, self).__init__() self.orig_name = {} + self.patches = {} def generateContent(self, content): for line1, line2, _ in itertools.zip_longest(content, content, content): @@ -150,8 +151,22 @@ def generateContent(self, content): self.orig_name[commit_id] = line2 yield line1 + def generateContentPatches(self, content): + result = [] + commit = None + for line in content: + if line.startswith("$"): + result.append(line[1:]) + commit = line.split(None, 1)[0].lstrip("$") + self.patches[commit] = [] + else: + self.patches[commit].append(line) + + return result + def getContent(self, *args, **kwargs): self.orig_name.clear() + self.patches = {} arguments_dict = kwargs.get("arguments", {}) @@ -162,9 +177,17 @@ def getContent(self, *args, **kwargs): cmd = 'git log {} --pretty=format:"%h%d %s"'.format(options) if "--current-file" in arguments_dict and "current_file" in arguments_dict: cmd += " --name-only --follow -- {}".format(arguments_dict["current_file"]) + elif "--current-line" in arguments_dict and "current_file" in arguments_dict: + cmd = 'git log {} --pretty=format:"$%h%d %s"'.format(options) + cmd += " -L{},{}:{}".format(arguments_dict["current_line_num"], + arguments_dict["current_line_num"], + arguments_dict["current_file"]) + content = executor.execute(cmd, encoding=lfEval("&encoding")) + return self.generateContentPatches(content) if "extra" in arguments_dict: cmd += " " + " ".join(arguments_dict["extra"]) + content = executor.execute(cmd, encoding=lfEval("&encoding")) if "--current-file" in arguments_dict and "current_file" in arguments_dict: @@ -355,6 +378,8 @@ def buildCommandAndBufferName(self): self._cmd += " --follow -- {}".format(self._arguments["current_file"]) self._buffer_name = "LeaderF://" + self._cmd + elif "--current-line" in self._arguments and "current_file" in self._arguments: + self._buffer_name = "LeaderF://" + self._source else: sep = ' ' if os.name == 'nt' else '' if "--find-copies-harder" in self._arguments: @@ -2690,13 +2715,13 @@ def create(self, arguments_dict, source, **kwargs): lfCmd("let b:lf_explorer_page_id = {}".format(kwargs.get("explorer_page_id", 0))) lfCmd("let b:lf_diff_view_mode = 'unified'") lfCmd("let b:lf_diff_view_source = {}".format(str(list(source)))) - blame_map = lfEval("g:Lf_GitKeyMap") + key_map = lfEval("g:Lf_GitKeyMap") lfCmd("nnoremap {} :call leaderf#Git#PreviousChange(0)" - .format(blame_map["previous_change"])) + .format(key_map["previous_change"])) lfCmd("nnoremap {} :call leaderf#Git#NextChange(0)" - .format(blame_map["next_change"])) + .format(key_map["next_change"])) lfCmd("nnoremap {} :call leaderf#Git#EditFile(0)" - .format(blame_map["edit_file"])) + .format(key_map["edit_file"])) else: lfCmd("call win_gotoid({})".format(winid)) if not vim.current.buffer.name: # buffer name is empty @@ -3658,9 +3683,15 @@ def _createPreviewWindow(self, config, source, line_num, jump_cmd): if source is None: return - self._preview_panel.create(self.createGitCommand(self._arguments, source), - config, - project_root=self._project_root) + if "--current-line" in self._arguments and len(self._getExplorer().patches) > 0: + self._preview_panel.create(self.createGitCommand(self._arguments, source), + config, + buf_content=self._getExplorer().patches[source], + project_root=self._project_root) + else: + self._preview_panel.create(self.createGitCommand(self._arguments, source), + config, + project_root=self._project_root) self._preview_winid = self._preview_panel.getPreviewWinId() self._setWinOptions(self._preview_winid) @@ -3678,7 +3709,10 @@ def _useExistingWindow(self, title, source, line_num, jump_cmd): content = self._preview_panel.getContent(source) if content is None: - self._preview_panel.createView(self.createGitCommand(self._arguments, source)) + if "--current-line" in self._arguments and len(self._getExplorer().patches) > 0: + self._preview_panel.setContent(self._getExplorer().patches[source]) + else: + self._preview_panel.createView(self.createGitCommand(self._arguments, source)) else: self._preview_panel.setContent(content) @@ -3698,6 +3732,15 @@ def startExplorer(self, win_pos, *args, **kwargs): file_name = file_name.replace(' ', r'\ ') self._arguments["current_file"] = lfRelpath(file_name) self._arguments["orig_name"] = self._getExplorer().orig_name + elif ("--current-line" in arguments_dict + and vim.current.buffer.name + and not vim.current.buffer.options['bt'] + ): + file_name = vim.current.buffer.name + if " " in file_name: + file_name = file_name.replace(' ', r'\ ') + self._arguments["current_file"] = lfRelpath(file_name) + self._arguments["current_line_num"] = vim.current.window.cursor[0] if "--recall" in arguments_dict: super(GitExplManager, self).startExplorer(win_pos, *args, **kwargs) @@ -3751,14 +3794,32 @@ def _afterEnter(self): def _accept(self, file, mode, *args, **kwargs): super(GitExplManager, self)._accept(file, mode, *args, **kwargs) - def _createExplorerPage(self, commit_id, target_path=None): + def _createExplorerPage(self, commit_id, target_path=None, line_num=None): if commit_id in self._pages: vim.current.tabpage = self._pages[commit_id].tabpage else: self._pages[commit_id] = ExplorerPage(self._project_root, commit_id, self) self._pages[commit_id].create(self._arguments, GitLogExplCommand(self._arguments, commit_id), - target_path=target_path) + target_path=target_path, + line_num=line_num) + + def _getPathAndLineNum(self, commit_id): + patch = self._getExplorer().patches[commit_id] + file_path = patch[0].rsplit(None, 1)[1][2:] + line_num = 1 + for line in patch: + if line.startswith("@@"): + line_numbers = line.split("+", 1)[1].split(None, 1)[0] + if "," in line_numbers: + line_num, count = line_numbers.split(",") + line_num = int(line_num) + else: + # @@ -1886 +1893 @@ + line_num = int(line_numbers) + break + + return (file_path, line_num) def _acceptSelection(self, *args, **kwargs): if len(args) == 0: @@ -3784,6 +3845,22 @@ def _acceptSelection(self, *args, **kwargs): if len(outputs[0]) > 0: _, source = TreeView.generateSource(outputs[0][0]) self._diff_view_panel.create(self._arguments, source, **kwargs) + elif "--current-line" in self._arguments and len(self._getExplorer().patches) > 0: + if "--explorer" in self._arguments: + file_path, line_num = self._getPathAndLineNum(commit_id) + self._createExplorerPage(commit_id, file_path, line_num) + else: + if kwargs.get("mode", '') == 't' and commit_id not in self._result_panel.getSources(): + self._arguments["mode"] = 't' + lfCmd("tabnew") + + tabpage_count = len(vim.tabpages) + + self._result_panel.create(self.createGitCommand(self._arguments, commit_id), + self._getExplorer().patches[commit_id]) + + if kwargs.get("mode", '') == 't' and len(vim.tabpages) > tabpage_count: + tabmove() elif "--explorer" in self._arguments: self._createExplorerPage(commit_id) else: From b8c8ce0680ef43b2c366e0a004bed02a73c73744 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Tue, 9 Jul 2024 16:51:35 +0800 Subject: [PATCH 275/365] the target line is not precise when --current-line --- autoload/leaderf/python/leaderf/gitExpl.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 7d837a17..82e1d7d3 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -3808,16 +3808,26 @@ def _getPathAndLineNum(self, commit_id): patch = self._getExplorer().patches[commit_id] file_path = patch[0].rsplit(None, 1)[1][2:] line_num = 1 + count = 0 + found = False for line in patch: if line.startswith("@@"): + found = True line_numbers = line.split("+", 1)[1].split(None, 1)[0] if "," in line_numbers: - line_num, count = line_numbers.split(",") + line_num, _ = line_numbers.split(",") line_num = int(line_num) else: # @@ -1886 +1893 @@ line_num = int(line_numbers) - break + elif found: + if line.startswith("-"): + pass + elif line.startswith("+"): + line_num += count + break + else: + count += 1 return (file_path, line_num) From 38e2384761112dbc9994c8896c54c44a1faad778 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Tue, 9 Jul 2024 20:55:22 +0800 Subject: [PATCH 276/365] 'Leaderf git blame' now can be used in the blame window --- autoload/leaderf/python/leaderf/gitExpl.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 82e1d7d3..49b1e42b 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -2943,6 +2943,7 @@ def create(self, arguments_dict, cmd, project_root=None): self._owner.defineMaps(blame_winid) lfCmd("let b:lf_blame_project_root = '{}'".format(self._project_root)) lfCmd("let b:lf_blame_date_format = '{}'".format(date_format)) + lfCmd("let b:lf_blame_file_name = '{}'".format(escQuote(arguments_dict["blamed_file_name"]))) lfCmd("noautocmd norm! {}Gzt{}G0".format(top_line, cursor_line)) lfCmd("call win_execute({}, 'setlocal scrollbind')".format(winid)) lfCmd("setlocal scrollbind") @@ -4572,11 +4573,19 @@ def startExplorer(self, win_pos, *args, **kwargs): arguments_dict = kwargs.get("arguments", {}) self.setArguments(arguments_dict) + if lfEval("exists('b:lf_blame_file_name')") == "1": + buf_winid = int(lfEval("bufwinid(b:lf_blame_file_name)")) + if buf_winid != -1: + lfCmd("call win_gotoid({})".format(buf_winid)) + else: + lfCmd("bel vsp {}".format(lfEval("b:lf_blame_file_name"))) + if vim.current.buffer.name and not vim.current.buffer.options['bt']: if not vim.current.buffer.name.startswith(self._project_root): lfPrintError("fatal: '{}' is outside repository at '{}'" .format(lfRelpath(vim.current.buffer.name), self._project_root)) else: + self._arguments["blamed_file_name"] = vim.current.buffer.name tmp_file_name = None if vim.current.buffer.options["modified"]: if sys.version_info >= (3, 0): From 380f48505415c703d34d6725ab9f2d7c96897943 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 10 Jul 2024 21:55:01 +0800 Subject: [PATCH 277/365] fix a bug --- autoload/leaderf/Git.vim | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/autoload/leaderf/Git.vim b/autoload/leaderf/Git.vim index 3485f457..532ac550 100644 --- a/autoload/leaderf/Git.vim +++ b/autoload/leaderf/Git.vim @@ -771,7 +771,11 @@ function! leaderf#Git#EditFile(tag) abort exec "tabedit " . b:lf_git_buffer_name else let buf_ids = win_findbuf(buffer_num) - call win_gotoid(buf_ids[0]) + if len(buf_ids) == 0 + exec "tabedit " . b:lf_git_buffer_name + else + call win_gotoid(buf_ids[0]) + endif endif let i = start_line_num - 1 From fea1afc65ed76f61e8f525ab43d1a25eb97350a3 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 11 Jul 2024 11:07:16 +0800 Subject: [PATCH 278/365] echo if file does not exist --- autoload/leaderf/Git.vim | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/autoload/leaderf/Git.vim b/autoload/leaderf/Git.vim index 532ac550..55192c70 100644 --- a/autoload/leaderf/Git.vim +++ b/autoload/leaderf/Git.vim @@ -736,6 +736,9 @@ endfunction function! s:GoToFile(file_name) abort if !filereadable(a:file_name) + echohl WarningMsg + echo a:file_name .. " does not exist." + echohl None return endif @@ -744,13 +747,20 @@ function! s:GoToFile(file_name) abort exec "tabedit " . a:file_name else let buf_ids = win_findbuf(buffer_num) - call win_gotoid(buf_ids[0]) + if len(buf_ids) == 0 + exec "tabedit " . a:file_name + else + call win_gotoid(buf_ids[0]) + endif endif endfunction function! leaderf#Git#EditFile(tag) abort if a:tag == 0 if !filereadable(b:lf_git_buffer_name) + echohl WarningMsg + echo b:lf_git_buffer_name .. " does not exist." + echohl None return endif From 9dc801dc2117043082277f9336da9ee171ef3243 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 11 Jul 2024 18:16:21 +0800 Subject: [PATCH 279/365] fix issue #1056 --- autoload/leaderf.vim | 2 +- autoload/leaderf/python/leaderf/cli.py | 39 +++++----------------- autoload/leaderf/python/leaderf/manager.py | 14 ++++++-- 3 files changed, 20 insertions(+), 35 deletions(-) diff --git a/autoload/leaderf.vim b/autoload/leaderf.vim index d5ad609f..68613d67 100644 --- a/autoload/leaderf.vim +++ b/autoload/leaderf.vim @@ -74,7 +74,7 @@ call s:InitVar('g:Lf_WindowHeight', '0.5') call s:InitVar('g:Lf_TabpagePosition', 3) call s:InitVar('g:Lf_ShowRelativePath', 1) call s:InitVar('g:Lf_DefaultMode', 'FullPath') -call s:InitVar('g:Lf_CursorBlink', 1) +call s:InitVar('g:Lf_CursorBlink', 0) call s:InitVar('g:Lf_NeedCacheTime', '1.5') call s:InitVar('g:Lf_NumberOfCache', 5) call s:InitVar('g:Lf_UseMemoryCache', 1) diff --git a/autoload/leaderf/python/leaderf/cli.py b/autoload/leaderf/python/leaderf/cli.py index 039a9017..d71b0517 100644 --- a/autoload/leaderf/python/leaderf/cli.py +++ b/autoload/leaderf/python/leaderf/cli.py @@ -663,6 +663,7 @@ def input(self, callback): start = time.time() update = False prefix = "" + block = "1" while 1: if len(self._instance._manager._content) < 60000: @@ -675,11 +676,9 @@ def input(self, callback): if lfEval("has('nvim') && exists('g:GuiLoaded')") == '1': time.sleep(0.005) # this is to solve issue 375 leaderF hangs in nvim-qt - else: - time.sleep(0.001) if lfEval("get(g:, 'Lf_NoAsync', 0)") == '0': - lfCmd("let nr = getchar(1)") + lfCmd("let nr = getchar({})".format(block)) if lfEval("!type(nr) && nr == 0") == '1': self._idle = True if lfEval("has('nvim') && exists('g:GuiLoaded')") == '1': @@ -695,40 +694,18 @@ def input(self, callback): start = time.time() else: try: - callback() - except Exception: - lfPrintTraceback() - break - - continue - # https://groups.google.com/forum/#!topic/vim_dev/gg-l-kaCz_M - # '<80>^B' is , '<80>^D' is , - # '<80>^H' is , '<80>^L' is - elif lfEval("type(nr) != 0") == '1': - lfCmd("call getchar(0)") - lfCmd("call feedkeys('a') | call getchar()") - self._idle = True - if lfEval("has('nvim') && exists('g:GuiLoaded')") == '1': - time.sleep(0.009) # this is to solve issue 375 leaderF hangs in nvim-qt - - if update == True: - if time.time() - start >= threshold: - update = False - if ''.join(self._cmdline).startswith(prefix): - yield '' - else: - yield '' - start = time.time() - else: - try: - callback() + ret = callback() + if ret == 100: + block = "" except Exception: lfPrintTraceback() break continue else: - lfCmd("let nr = getchar()") + if block == "1": + lfCmd("let nr = getchar()") + block = "1" lfCmd("let ch = !type(nr) ? nr2char(nr) : nr") self._blinkon = True else: diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 135dfe26..d7a0ca22 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -67,7 +67,7 @@ def catchException(func): @wraps(func) def deco(self, *args, **kwargs): try: - func(self, *args, **kwargs) + return func(self, *args, **kwargs) except vim.error as e: # for neovim if str(e) != "b'Keyboard interrupt'" and str(e) != 'Keyboard interrupt': raise e @@ -2931,7 +2931,7 @@ def _workInIdle(self, content=None, bang=False): self._timer_id = None lfPrintError(self._read_content_exception[1]) - return + return None else: raise self._read_content_exception[1] @@ -2944,7 +2944,9 @@ def _workInIdle(self, content=None, bang=False): else: step = 2000 self._search(self._content, True, step) - return + return None + else: + return 100 if content: i = -1 @@ -3021,6 +3023,10 @@ def _workInIdle(self, content=None, bang=False): if bang: self._getInstance().appendBuffer(self._result_content[self._initial_count:]) + else: + return 100 + else: + return 100 else: cur_len = len(self._content) if time.time() - self._start_time > 0.1: @@ -3068,6 +3074,8 @@ def _workInIdle(self, content=None, bang=False): if not self.isPreviewWindowOpen(): self._previewResult(False) + return None + @modifiableController def input(self): From b6948cf3719315905060721a9c19252c9ac827d7 Mon Sep 17 00:00:00 2001 From: Martin Date: Fri, 12 Jul 2024 11:18:01 +0800 Subject: [PATCH 280/365] fix typo in install.sh (#1088) --- install.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/install.sh b/install.sh index 145c66ac..010d8db0 100755 --- a/install.sh +++ b/install.sh @@ -6,7 +6,7 @@ then rm -rf build rm -f ../python/*.so ../python/*.dll echo ======================================== - echo ^_^ C extension uninstalled sucessfully! + echo ^_^ C extension uninstalled successfully! echo ======================================== exit 0 fi @@ -23,7 +23,7 @@ if command -v python2 > /dev/null 2>&1; then then echo echo ================================================= - echo ^_^ C extension of Python2 installed sucessfully! + echo ^_^ C extension of Python2 installed successfully! echo ================================================= fi fi @@ -38,7 +38,7 @@ if command -v python3 > /dev/null 2>&1; then then echo echo ================================================= - echo ^_^ C extension of Python3 installed sucessfully! + echo ^_^ C extension of Python3 installed successfully! echo ================================================= fi fi From 6cf434d031f13356bc9b3fcc8943e24afa499987 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Fri, 12 Jul 2024 13:59:57 +0800 Subject: [PATCH 281/365] time.sleep(0) --- autoload/leaderf/python/leaderf/cli.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/autoload/leaderf/python/leaderf/cli.py b/autoload/leaderf/python/leaderf/cli.py index d71b0517..0e116219 100644 --- a/autoload/leaderf/python/leaderf/cli.py +++ b/autoload/leaderf/python/leaderf/cli.py @@ -676,6 +676,8 @@ def input(self, callback): if lfEval("has('nvim') && exists('g:GuiLoaded')") == '1': time.sleep(0.005) # this is to solve issue 375 leaderF hangs in nvim-qt + else: + time.sleep(0) if lfEval("get(g:, 'Lf_NoAsync', 0)") == '0': lfCmd("let nr = getchar({})".format(block)) @@ -697,6 +699,8 @@ def input(self, callback): ret = callback() if ret == 100: block = "" + if self._instance.getWinPos() in ('popup', 'floatwin'): + self.buildPopupPrompt() except Exception: lfPrintTraceback() break From 5b575f65eafb3fba9ae38c387dba567cd48a45c2 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Fri, 12 Jul 2024 17:26:27 +0800 Subject: [PATCH 282/365] fix issue #1037 --- autoload/leaderf/python/leaderf/instance.py | 80 +++++++++++++++++++++ autoload/leaderf/python/leaderf/manager.py | 7 ++ 2 files changed, 87 insertions(+) diff --git a/autoload/leaderf/python/leaderf/instance.py b/autoload/leaderf/python/leaderf/instance.py index a628f3f5..008780b9 100644 --- a/autoload/leaderf/python/leaderf/instance.py +++ b/autoload/leaderf/python/leaderf/instance.py @@ -278,6 +278,7 @@ def __init__(self, manager, category, cli, self._popup_cursor_line = 1 self._auto_adjust_height = lfEval("get(g:, 'Lf_PopupAutoAdjustHeight', 1)") == '1' self._preview_position = None + self._initial_maxwidth = 0 def _initStlVar(self): if int(lfEval("!exists('g:Lf_{}_StlCategory')".format(self._category))): @@ -397,6 +398,83 @@ def _vim_set_options(self, winid): lfCmd("call win_execute(%d, 'setlocal cursorlineopt=both')" % winid) lfCmd("call win_execute(%d, 'setlocal colorcolumn=')" % winid) + def enlargePopupWindow(self): + if self._win_pos not in ('popup', 'floatwin'): + return + + preview_pos = self._arguments.get("--preview-position", [""])[0] + if preview_pos == "": + preview_pos = lfEval("get(g:, 'Lf_PopupPreviewPosition', 'right')") + + if preview_pos.lower() == 'right': + if self._popup_instance.input_win.width > self._initial_maxwidth * 2: + return + + if lfEval("has('nvim')") == '1': + width = self._initial_maxwidth * 2 + 2 + + lfCmd("call leaderf#ResetFloatwinOptions({}, 'width', {})" + .format(self._popup_winid, width)) + lfCmd("call leaderf#ResetFloatwinOptions({}, 'width', {})" + .format(self._popup_instance.input_win.id, width)) + if lfEval("get(g:, 'Lf_PopupShowStatusline', 1)") == '1': + lfCmd("call leaderf#ResetFloatwinOptions({}, 'width', {})" + .format(self._popup_instance.statusline_win.id, width)) + else: + width = self._initial_maxwidth * 2 + 2 + + lfCmd("call leaderf#ResetPopupOptions({}, 'maxwidth', {})" + .format(self._popup_winid, width)) + lfCmd("call leaderf#ResetPopupOptions({}, 'minwidth', {})" + .format(self._popup_winid, width)) + + lfCmd("call leaderf#ResetPopupOptions({}, 'maxwidth', {})" + .format(self._popup_instance.input_win.id, width)) + lfCmd("call leaderf#ResetPopupOptions({}, 'minwidth', {})" + .format(self._popup_instance.input_win.id, width)) + + if lfEval("get(g:, 'Lf_PopupShowStatusline', 1)") == '1': + lfCmd("call leaderf#ResetPopupOptions({}, 'maxwidth', {})" + .format(self._popup_instance.statusline_win.id, width)) + lfCmd("call leaderf#ResetPopupOptions({}, 'minwidth', {})" + .format(self._popup_instance.statusline_win.id, width)) + + self._cli.buildPopupPrompt() + + def shrinkPopupWindow(self): + preview_pos = self._arguments.get("--preview-position", [""])[0] + if preview_pos == "": + preview_pos = lfEval("get(g:, 'Lf_PopupPreviewPosition', 'right')") + + if preview_pos.lower() == 'right': + if lfEval("has('nvim')") == '1': + lfCmd("call leaderf#ResetFloatwinOptions({}, 'width', {})" + .format(self._popup_winid, self._initial_maxwidth)) + lfCmd("call leaderf#ResetFloatwinOptions({}, 'width', {})" + .format(self._popup_instance.input_win.id, self._initial_maxwidth)) + + if lfEval("get(g:, 'Lf_PopupShowStatusline', 1)") == '1': + lfCmd("call leaderf#ResetFloatwinOptions({}, 'width', {})" + .format(self._popup_instance.statusline_win.id, self._initial_maxwidth)) + else: + lfCmd("call leaderf#ResetPopupOptions({}, 'maxwidth', {})" + .format(self._popup_winid, self._initial_maxwidth)) + lfCmd("call leaderf#ResetPopupOptions({}, 'minwidth', {})" + .format(self._popup_winid, self._initial_maxwidth)) + + lfCmd("call leaderf#ResetPopupOptions({}, 'maxwidth', {})" + .format(self._popup_instance.input_win.id, self._initial_maxwidth)) + lfCmd("call leaderf#ResetPopupOptions({}, 'minwidth', {})" + .format(self._popup_instance.input_win.id, self._initial_maxwidth)) + + if lfEval("get(g:, 'Lf_PopupShowStatusline', 1)") == '1': + lfCmd("call leaderf#ResetPopupOptions({}, 'maxwidth', {})" + .format(self._popup_instance.statusline_win.id, self._initial_maxwidth)) + lfCmd("call leaderf#ResetPopupOptions({}, 'minwidth', {})" + .format(self._popup_instance.statusline_win.id, self._initial_maxwidth)) + + self._cli.buildPopupPrompt() + def _createPopupWindow(self): preview_pos = self._arguments.get("--preview-position", [""])[0] if preview_pos == "": @@ -439,6 +517,8 @@ def _createPopupWindow(self): maxwidth = min(width, int(lfEval("&columns"))) maxwidth = max(20, maxwidth) + self._initial_maxwidth = maxwidth + show_borders = lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1' height = lfEval("get(g:, 'Lf_PopupHeight', 0)") height = self._arguments.get("--popup-height", [height])[0] diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index d7a0ca22..732cc562 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -433,6 +433,7 @@ def _previewResult(self, preview): if not self._needPreview(preview, preview_in_popup): if preview_in_popup: self._closePreviewPopup() + self._getInstance().enlargePopupWindow() return line_num = self._getInstance().window.cursor[0] @@ -440,6 +441,10 @@ def _previewResult(self, preview): if preview_in_popup: self._previewInPopup(line, self._getInstance().buffer, line_num) + + if not self.isPreviewWindowOpen(): + self._getInstance().enlargePopupWindow() + return orig_pos = self._getInstance().getOriginalPos() @@ -635,6 +640,8 @@ def _createPopupModePreview(self, title, source, line_num, jump_cmd): if the type is str, it is a file name """ + self._getInstance().shrinkPopupWindow() + self._is_previewed = True show_borders = lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1' From feb7ca9c6281ee6d2954d8de3455879a31389767 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Fri, 12 Jul 2024 21:31:33 +0800 Subject: [PATCH 283/365] remove some code #664 --- autoload/leaderf/python/leaderf/cli.py | 2 ++ autoload/leaderf/python/leaderf/manager.py | 5 +---- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/autoload/leaderf/python/leaderf/cli.py b/autoload/leaderf/python/leaderf/cli.py index 0e116219..f3b6b815 100644 --- a/autoload/leaderf/python/leaderf/cli.py +++ b/autoload/leaderf/python/leaderf/cli.py @@ -701,6 +701,8 @@ def input(self, callback): block = "" if self._instance.getWinPos() in ('popup', 'floatwin'): self.buildPopupPrompt() + else: + lfCmd("redraw") except Exception: lfPrintTraceback() break diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 732cc562..8a10b707 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -2022,7 +2022,7 @@ def _fuzzySearch(self, content, is_continue, step): if return_index == True: step = 30000 * cpu_count else: - step = 60000 * cpu_count + step = 50000 * cpu_count _, self._result_content = self._filter(step, filter_method, content, is_continue, True, return_index) else: @@ -2049,9 +2049,6 @@ def _fuzzySearch(self, content, is_continue, step): self._highlight_method = highlight_method self._highlight_method() - if len(self._cli.pattern) > 1 and not is_continue: - lfCmd("silent! redraw") - def _guessFilter(self, filename, suffix, dirname, icon, iterable): """ return a list, each item is a pair (weight, line) From 5bcb8683ebf584daff7b480a20dfba9555d98e76 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Tue, 23 Jul 2024 12:53:02 +0800 Subject: [PATCH 284/365] self._orig_source is not updated --- autoload/leaderf/python/leaderf/manager.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 8a10b707..8dfa263e 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -519,6 +519,7 @@ def _setWinOptions(self, winid): def _createPreviewWindow(self, config, source, line_num, jump_cmd): self._preview_config = config + self._orig_source = source if lfEval("has('nvim')") == '1': if isinstance(source, int): @@ -1202,8 +1203,6 @@ def _createPopupPreview(self, title, source, line_num, jump_cmd=''): self._updateOptions(preview_pos, show_borders, options) self._createPreviewWindow(options, source, line_num, jump_cmd) - self._orig_source = source - return True def _updateOptions(self, preview_pos, show_borders, options): From b5f1990bd06dd376e46a906d383d1b8dc436b3fd Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 24 Jul 2024 22:42:01 +0800 Subject: [PATCH 285/365] do not list the terminal buffer --- autoload/leaderf/python/leaderf/bufExpl.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/autoload/leaderf/python/leaderf/bufExpl.py b/autoload/leaderf/python/leaderf/bufExpl.py index 25660bd2..6dfb6cec 100644 --- a/autoload/leaderf/python/leaderf/bufExpl.py +++ b/autoload/leaderf/python/leaderf/bufExpl.py @@ -52,6 +52,9 @@ def getContent(self, *args, **kwargs): buffers = {w.buffer.number: w.buffer for w in vim.current.tabpage.windows if os.path.basename(w.buffer.name) != "LeaderF"} + if lfEval("has('nvim')") == '0': + buffers = {number : buffer for number, buffer in buffers.items() + if buffer.options["buftype"] != b"terminal"} # e.g., 12 u %a+-  aaa.txt bufnr_len = len(lfEval("bufnr('$')")) From 83736aa234d156fa91aad717b7f0a65b432ed099 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Sat, 27 Jul 2024 23:35:33 +0800 Subject: [PATCH 286/365] preview noncommited changes --- autoload/leaderf/python/leaderf/gitExpl.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 49b1e42b..7b0a27f6 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -4284,9 +4284,6 @@ def preview(self): return commit_id = vim.current.line.lstrip('^').split(None, 1)[0] - if commit_id.startswith('0000000'): - lfPrintError("Not Committed Yet!") - return line_num, file_name = vim.current.line.rsplit('\t', 1)[1].split(None, 1) line_num = int(line_num) @@ -4298,7 +4295,11 @@ def preview(self): lfCmd("call nvim_win_close(b:lf_preview_winid, 1)") project_root = lfEval("b:lf_blame_project_root") - cmd = GitShowCommand(self._arguments, commit_id, file_name) + if commit_id.startswith('0000000'): + cmd = GitCustomizeCommand(self._arguments, "git diff @ -- {}".format(file_name), + None, "git", "setlocal filetype=git") + else: + cmd = GitShowCommand(self._arguments, commit_id, file_name) outputs = ParallelExecutor.run(cmd.getCommand(), directory=project_root) self._preview_panel.create(cmd, self.generateConfig(project_root), outputs[0]) preview_winid = self._preview_panel.getPreviewWinId() From 7c4db3f7da8d4269d026000021439db632b19a19 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Mon, 29 Jul 2024 13:11:00 +0800 Subject: [PATCH 287/365] replace `set ft` with `set syntax` --- autoload/leaderf/python/leaderf/manager.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 8dfa263e..e83a3608 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -550,7 +550,8 @@ def _createPreviewWindow(self, config, source, line_num, jump_cmd): if file_type is None: lfCmd("silent! doautocmd filetypedetect BufNewFile %s" % source) else: - lfCmd("setf %s" % getExtension(source)) + lfCmd("noautocmd set ft=%s" % getExtension(source)) + lfCmd("set syntax=%s" % getExtension(source)) lfCmd("noautocmd call win_gotoid(%s)" % cur_winid) self._setWinOptions(self._preview_winid) @@ -950,7 +951,8 @@ def _useExistingWindow(self, title, source, line_num, jump_cmd): lfCmd("call win_execute(%d, 'silent! doautocmd filetypedetect BufNewFile %s')" % (self._preview_winid, escQuote(source))) else: - lfCmd("call win_execute(%d, 'setf %s')" % (self._preview_winid, cur_filetype)) + lfCmd("call win_execute(%d, 'noautocmd set ft=%s')" % (self._preview_winid, cur_filetype)) + lfCmd("call win_execute(%d, 'set syntax=%s')" % (self._preview_winid, cur_filetype)) self._preview_filetype = lfEval("getbufvar(winbufnr(%d), '&ft')" % self._preview_winid) elif lfEval("exists('*popup_setbuf')") == "1": if isinstance(source, int): From 10ad367e4b523ccb4fe2953078d0affcddb1f1a7 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 31 Jul 2024 13:04:55 +0800 Subject: [PATCH 288/365] highlight vimrc gvimrc --- autoload/leaderf/python/leaderf/utils.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/autoload/leaderf/python/leaderf/utils.py b/autoload/leaderf/python/leaderf/utils.py index cdaf67a5..4a563ba2 100644 --- a/autoload/leaderf/python/leaderf/utils.py +++ b/autoload/leaderf/python/leaderf/utils.py @@ -1346,6 +1346,8 @@ def nearestAncestor(markers, path): "trustees.conf" : "trustees", "Vagrantfile" : "ruby", ".vimrc" : "vim", + "vimrc" : "vim", + "gvimrc" : "vim", "_vimrc" : "vim", ".exrc" : "vim", "_exrc" : "vim", From edd8ffa94b458e3954983d56c0a8d70d3fd3d92a Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Mon, 12 Aug 2024 21:18:15 +0800 Subject: [PATCH 289/365] fix issue #1091 --- autoload/leaderf/python/leaderf/instance.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/autoload/leaderf/python/leaderf/instance.py b/autoload/leaderf/python/leaderf/instance.py index 008780b9..12e17b3f 100644 --- a/autoload/leaderf/python/leaderf/instance.py +++ b/autoload/leaderf/python/leaderf/instance.py @@ -653,6 +653,7 @@ def _createPopupWindow(self): lfCmd("noautocmd silent let winid = nvim_open_win(%d, 0, %s)" % (buf_number, str(input_win_config))) winid = int(lfEval("winid")) self._nvim_set_options(buf_number, winid) + lfCmd("silent! call nvim_win_set_option(%d, 'statuscolumn', '')" % winid) lfCmd("call nvim_win_set_option(%d, 'winhighlight', 'Normal:Lf_hl_popup_inputText')" % winid) def getWindow(number): @@ -689,6 +690,7 @@ def getWindow(number): lfCmd("noautocmd silent let winid = nvim_open_win(%d, 0, %s)" % (buf_number, str(stl_win_config))) winid = int(lfEval("winid")) self._nvim_set_options(buf_number, winid) + lfCmd("silent! call nvim_win_set_option(%d, 'statuscolumn', '')" % winid) lfCmd("call nvim_win_set_option(%d, 'winhighlight', 'Normal:Lf_hl_popup_blank')" % winid) self._popup_instance.statusline_win = FloatWindow(winid, getWindow(int(lfEval("win_id2win(%d)" % winid))), From 3a82e36099368d2eff62cdedfabbdcc82b105acc Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 15 Aug 2024 14:14:19 +0800 Subject: [PATCH 290/365] update syntax --- autoload/leaderf/Git.vim | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/autoload/leaderf/Git.vim b/autoload/leaderf/Git.vim index 55192c70..97270b3e 100644 --- a/autoload/leaderf/Git.vim +++ b/autoload/leaderf/Git.vim @@ -587,9 +587,11 @@ endfunction function! leaderf#Git#DefineSyntax() abort syntax region Lf_hl_gitStat start=/^---$/ end=/^ \d\+ files\? changed,/ syn match Lf_hl_gitStatPath /^ \S*\%(\s*|\s*\d\+\s*+*-*$\)\@=/ display containedin=Lf_hl_gitStat contained - syn match Lf_hl_gitStatPath /^ \S*\%(\s*|\s*Bin \d\+ -> \d\+ bytes\?$\)\@=/ display containedin=Lf_hl_gitStat contained + syn match Lf_hl_gitStatPath /^ \S*\%(\s*|\s*Bin\%( \d\+ -> \d\+ bytes\?\)\?$\)\@=/ display containedin=Lf_hl_gitStat contained syn match Lf_hl_gitStatPath /^ \S*\%( => \S*\s*|\s*\d\+\s*+*-*$\)\@=/ display containedin=Lf_hl_gitStat contained + syn match Lf_hl_gitStatPath /^ \S*\%( => \S*\s*|\s*Bin\%( \d\+ -> \d\+ bytes\?\)\?$\)\@=/ display containedin=Lf_hl_gitStat contained syn match Lf_hl_gitStatPath /\%(^ \S* => \)\@<=\S*\%(\s*|\s*\d\+\s*+*-*$\)\@=/ display containedin=Lf_hl_gitStat contained + syn match Lf_hl_gitStatPath /\%(^ \S* => \)\@<=\S*\%(\s*|\s*Bin\%( \d\+ -> \d\+ bytes\?\)\?$\)\@=/ display containedin=Lf_hl_gitStat contained syn match Lf_hl_gitStatNumber /\%(^ \S*\%( => \S*\)\?\s*|\s*\)\@<=\d\+\%(\s*+*-*$\)\@=/ display containedin=Lf_hl_gitStat contained syn match Lf_hl_gitStatNumber /\%(^ \S*\%( => \S*\)\?\s*|\s*Bin \)\@<=\d\+ -> \d\+\%( bytes\?$\)\@=/ display containedin=Lf_hl_gitStat contained syn match Lf_hl_gitStatPlus /\%(^ \S*\%( => \S*\)\?\s*|\s*\d\+\s*\)\@<=+*\%(-*$\)\@=/ display containedin=Lf_hl_gitStat contained From 10c36e91b0e767c53117fc00aa51be10ceae6456 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 21 Aug 2024 10:51:10 +0800 Subject: [PATCH 291/365] `Leaderf help` can not preview winnr() --- autoload/leaderf/python/leaderf/helpExpl.py | 2 +- autoload/leaderf/python/leaderf/manager.py | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/autoload/leaderf/python/leaderf/helpExpl.py b/autoload/leaderf/python/leaderf/helpExpl.py index a76de389..d88fd326 100644 --- a/autoload/leaderf/python/leaderf/helpExpl.py +++ b/autoload/leaderf/python/leaderf/helpExpl.py @@ -146,7 +146,7 @@ def _previewInPopup(self, *args, **kwargs): line = args[0] tagname, tagfile, file_id = line.split(None, 2) tagfile = os.path.join(self._getExplorer()._file_ids[int(file_id)], tagfile) - jump_cmd = r"call search('\m\*%s\*', 'w')" % escQuote(tagname) + jump_cmd = r"let pos = search('\m\*%s\*', 'w') | exec 'norm! '.pos.'G'" % escQuote(tagname) self._createPopupPreview("", tagfile, 0, jump_cmd) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index e83a3608..503cf5d9 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -530,7 +530,7 @@ def _createPreviewWindow(self, config, source, line_num, jump_cmd): if self._isBinaryFile(source): lfCmd("""let content = map(range(128), '"^@"')""") else: - lfCmd("let content = readfile('%s', '', 4096)" % escQuote(source)) + lfCmd("let content = readfile('%s', '', 20480)" % escQuote(source)) except vim.error as e: lfPrintError(e) return @@ -574,7 +574,7 @@ def _createPreviewWindow(self, config, source, line_num, jump_cmd): if self._isBinaryFile(filename): lfCmd("""let content = map(range(128), '"^@"')""") else: - lfCmd("let content = readfile('%s', '', 4096)" % escQuote(filename)) + lfCmd("let content = readfile('%s', '', 20480)" % escQuote(filename)) except vim.error as e: lfPrintError(e) return @@ -612,7 +612,7 @@ def _createPreviewWindow(self, config, source, line_num, jump_cmd): if self._isBinaryFile(filename): lfCmd("""let content = map(range(128), '"^@"')""") else: - lfCmd("let content = readfile('%s', '', 4096)" % escQuote(filename)) + lfCmd("let content = readfile('%s', '', 20480)" % escQuote(filename)) except vim.error as e: lfPrintError(e) return @@ -934,7 +934,7 @@ def _useExistingWindow(self, title, source, line_num, jump_cmd): if self._isBinaryFile(source): lfCmd("""let content = map(range(128), '"^@"')""") else: - lfCmd("let content = readfile('%s', '', 4096)" % escQuote(source)) + lfCmd("let content = readfile('%s', '', 20480)" % escQuote(source)) except vim.error as e: lfPrintError(e) return @@ -964,7 +964,7 @@ def _useExistingWindow(self, title, source, line_num, jump_cmd): if self._isBinaryFile(filename): lfCmd("""let content = map(range(128), '"^@"')""") else: - lfCmd("let content = readfile('%s', '', 4096)" % escQuote(filename)) + lfCmd("let content = readfile('%s', '', 20480)" % escQuote(filename)) except vim.error as e: lfPrintError(e) return @@ -978,7 +978,7 @@ def _useExistingWindow(self, title, source, line_num, jump_cmd): self._preview_filetype = lfEval("getbufvar(winbufnr(%d), '&ft')" % self._preview_winid) else: if isinstance(source, int): - lfCmd("noautocmd call popup_settext(%d, getbufline(%d, 1, 4096))" % (self._preview_winid, source)) + lfCmd("noautocmd call popup_settext(%d, getbufline(%d, 1, 20480))" % (self._preview_winid, source)) filename = vim.buffers[source].name else: filename = source @@ -986,7 +986,7 @@ def _useExistingWindow(self, title, source, line_num, jump_cmd): if self._isBinaryFile(filename): lfCmd("""let content = map(range(128), '"^@"')""") else: - lfCmd("let content = readfile('%s', '', 4096)" % escQuote(filename)) + lfCmd("let content = readfile('%s', '', 20480)" % escQuote(filename)) except vim.error as e: lfPrintError(e) return From 908f3b06180d8e7131f919ed857545abe0df7c1f Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 29 Aug 2024 16:15:52 +0800 Subject: [PATCH 292/365] fix issue #1095 --- autoload/leaderf/colorscheme/popup.vim | 110 ++++++++++++++----------- 1 file changed, 62 insertions(+), 48 deletions(-) diff --git a/autoload/leaderf/colorscheme/popup.vim b/autoload/leaderf/colorscheme/popup.vim index 8aed660a..507f1776 100644 --- a/autoload/leaderf/colorscheme/popup.vim +++ b/autoload/leaderf/colorscheme/popup.vim @@ -55,6 +55,20 @@ function! s:HighlightGroup(category, name) abort endif endfunction +function! s:SynIDattr(synID, what, ...) abort + if a:0 == 0 + let result = synIDattr(a:synID, a:what) + else + let result = synIDattr(a:synID, a:what, a:1) + endif + + if result == -1 + return '' + else + return result + endif +endfunction + function! s:HighlightSeperator(category) abort exec printf("highlight link Lf_hl_popup_%s_mode Lf_hl_popup_inputMode", a:category) exec printf("highlight link Lf_hl_popup_%s_matchMode %s", a:category, s:matchModeMap[g:Lf_DefaultMode]) @@ -65,10 +79,10 @@ function! s:HighlightSeperator(category) abort for [sep, dict] in items(s:leftSep) let sid_left = synIDtrans(hlID(s:HighlightGroup(a:category, dict.left))) let sid_right = synIDtrans(hlID(s:HighlightGroup(a:category, dict.right))) - let left_guibg = synIDattr(sid_left, "bg", "gui") - let left_ctermbg = synIDattr(sid_left, "bg", "cterm") - let right_guibg = synIDattr(sid_right, "bg", "gui") - let right_ctermbg = synIDattr(sid_right, "bg", "cterm") + let left_guibg = s:SynIDattr(sid_left, "bg", "gui") + let left_ctermbg = s:SynIDattr(sid_left, "bg", "cterm") + let right_guibg = s:SynIDattr(sid_right, "bg", "gui") + let right_ctermbg = s:SynIDattr(sid_right, "bg", "cterm") let hiCmd = printf("hi Lf_hl_popup_%s_%s", a:category, sep) let hiCmd .= printf(" guifg=%s guibg=%s", left_guibg == '' ? 'NONE': left_guibg, right_guibg == '' ? 'NONE': right_guibg) let hiCmd .= printf(" ctermfg=%s ctermbg=%s", left_ctermbg == '' ? 'NONE': left_ctermbg, right_ctermbg == '' ? 'NONE': right_ctermbg) @@ -83,10 +97,10 @@ function! s:HighlightSeperator(category) abort for [sep, dict] in items(s:rightSep) let sid_left = synIDtrans(hlID(s:HighlightGroup(a:category, dict.left))) let sid_right = synIDtrans(hlID(s:HighlightGroup(a:category, dict.right))) - let left_guibg = synIDattr(sid_left, "bg", "gui") - let left_ctermbg = synIDattr(sid_left, "bg", "cterm") - let right_guibg = synIDattr(sid_right, "bg", "gui") - let right_ctermbg = synIDattr(sid_right, "bg", "cterm") + let left_guibg = s:SynIDattr(sid_left, "bg", "gui") + let left_ctermbg = s:SynIDattr(sid_left, "bg", "cterm") + let right_guibg = s:SynIDattr(sid_right, "bg", "gui") + let right_ctermbg = s:SynIDattr(sid_right, "bg", "cterm") let hiCmd = printf("hi Lf_hl_popup_%s_%s", a:category, sep) let hiCmd .= printf(" guifg=%s guibg=%s", right_guibg == '' ? 'NONE': right_guibg, left_guibg == '' ? 'NONE': left_guibg) let hiCmd .= printf(" ctermfg=%s ctermbg=%s", right_ctermbg == '' ? 'NONE': right_ctermbg, left_ctermbg == '' ? 'NONE': left_ctermbg) @@ -101,45 +115,45 @@ endfunction function! s:getSynAttr(sid) abort let attr = "" - if synIDattr(a:sid, "bold") + if s:SynIDattr(a:sid, "bold") let attr = "bold" endif - if synIDattr(a:sid, "italic") + if s:SynIDattr(a:sid, "italic") if attr == "" let attr = "italic" else let attr = attr . ",italic" endif endif - if synIDattr(a:sid, "standout") + if s:SynIDattr(a:sid, "standout") if attr == "" let attr = "standout" else let attr = attr . ",standout" endif endif - if synIDattr(a:sid, "underline") + if s:SynIDattr(a:sid, "underline") if attr == "" let attr = "underline" else let attr = attr . ",underline" endif endif - if synIDattr(a:sid, "undercurl") + if s:SynIDattr(a:sid, "undercurl") if attr == "" let attr = "undercurl" else let attr = attr . ",undercurl" endif endif - if synIDattr(a:sid, "strike") + if s:SynIDattr(a:sid, "strike") if attr == "" let attr = "strike" else let attr = attr . ",strike" endif endif - if synIDattr(a:sid, "nocombine") + if s:SynIDattr(a:sid, "nocombine") if attr == "" let attr = "nocombine" else @@ -153,16 +167,16 @@ endfunction " same as `hi link` but filter out the `reverse` attribute function! leaderf#colorscheme#popup#link_no_reverse(from, to) abort let sid = synIDtrans(hlID(a:to)) - if synIDattr(sid, "reverse") || synIDattr(sid, "inverse") - let guibg = synIDattr(sid, "fg", "gui") - let guifg = synIDattr(sid, "bg", "gui") - let ctermbg = synIDattr(sid, "fg", "cterm") - let ctermfg = synIDattr(sid, "bg", "cterm") + if s:SynIDattr(sid, "reverse") || s:SynIDattr(sid, "inverse") + let guibg = s:SynIDattr(sid, "fg", "gui") + let guifg = s:SynIDattr(sid, "bg", "gui") + let ctermbg = s:SynIDattr(sid, "fg", "cterm") + let ctermfg = s:SynIDattr(sid, "bg", "cterm") else - let guibg = synIDattr(sid, "bg", "gui") - let guifg = synIDattr(sid, "fg", "gui") - let ctermbg = synIDattr(sid, "bg", "cterm") - let ctermfg = synIDattr(sid, "fg", "cterm") + let guibg = s:SynIDattr(sid, "bg", "gui") + let guifg = s:SynIDattr(sid, "fg", "gui") + let ctermbg = s:SynIDattr(sid, "bg", "cterm") + let ctermfg = s:SynIDattr(sid, "fg", "cterm") endif let attr = s:getSynAttr(sid) @@ -180,32 +194,32 @@ endfunction " link to bg's background color and fg's foreground color function! leaderf#colorscheme#popup#link_two(from, bg, fg, no_attr) abort let bg_sid = synIDtrans(hlID(a:bg)) - if synIDattr(bg_sid, "reverse") || synIDattr(bg_sid, "inverse") - let guibg = synIDattr(bg_sid, "fg", "gui") - let ctermbg = synIDattr(bg_sid, "fg", "cterm") + if s:SynIDattr(bg_sid, "reverse") || s:SynIDattr(bg_sid, "inverse") + let guibg = s:SynIDattr(bg_sid, "fg", "gui") + let ctermbg = s:SynIDattr(bg_sid, "fg", "cterm") else - let guibg = synIDattr(bg_sid, "bg", "gui") - let ctermbg = synIDattr(bg_sid, "bg", "cterm") + let guibg = s:SynIDattr(bg_sid, "bg", "gui") + let ctermbg = s:SynIDattr(bg_sid, "bg", "cterm") endif let fg_sid = synIDtrans(hlID(a:fg)) - if synIDattr(fg_sid, "reverse") || synIDattr(fg_sid, "inverse") - let guifg = synIDattr(fg_sid, "bg", "gui") + if s:SynIDattr(fg_sid, "reverse") || s:SynIDattr(fg_sid, "inverse") + let guifg = s:SynIDattr(fg_sid, "bg", "gui") if guifg == guibg - let guifg = synIDattr(fg_sid, "fg", "gui") + let guifg = s:SynIDattr(fg_sid, "fg", "gui") endif - let ctermfg = synIDattr(fg_sid, "bg", "cterm") + let ctermfg = s:SynIDattr(fg_sid, "bg", "cterm") if ctermfg == ctermbg - let ctermfg = synIDattr(fg_sid, "fg", "cterm") + let ctermfg = s:SynIDattr(fg_sid, "fg", "cterm") endif else - let guifg = synIDattr(fg_sid, "fg", "gui") + let guifg = s:SynIDattr(fg_sid, "fg", "gui") if guifg == guibg - let guifg = synIDattr(fg_sid, "bg", "gui") + let guifg = s:SynIDattr(fg_sid, "bg", "gui") endif - let ctermfg = synIDattr(fg_sid, "fg", "cterm") + let ctermfg = s:SynIDattr(fg_sid, "fg", "cterm") if ctermfg == ctermbg - let ctermfg = synIDattr(fg_sid, "bg", "cterm") + let ctermfg = s:SynIDattr(fg_sid, "bg", "cterm") endif endif @@ -229,7 +243,7 @@ endfunction " and `hi def link Lf_hl_popup_cursor Cursor`, the bug occurs. function! leaderf#colorscheme#popup#link_cursor(from) abort let sid = synIDtrans(hlID("Cursor")) - if synIDattr(sid, "bg") == '' || synIDattr(sid, "fg") == '' + if s:SynIDattr(sid, "bg") == '' || s:SynIDattr(sid, "fg") == '' exec printf("hi def %s gui=reverse guifg=NONE guibg=NONE cterm=reverse ctermfg=NONE ctermbg=NONE", a:from) else exec printf("hi def link %s Cursor", a:from) @@ -246,8 +260,8 @@ function! leaderf#colorscheme#popup#hiMode(category, mode) abort exec printf("hi link Lf_hl_popup_%s_mode Lf_hl_popup_inputMode", a:category) endif let sid = synIDtrans(hlID(printf("Lf_hl_popup_%s_mode", a:category))) - let guibg = synIDattr(sid, "bg", "gui") - let ctermbg = synIDattr(sid, "bg", "cterm") + let guibg = s:SynIDattr(sid, "bg", "gui") + let ctermbg = s:SynIDattr(sid, "bg", "cterm") exec printf("hi Lf_hl_popup_%s_sep0 guifg=%s", a:category, guibg == '' ? 'NONE': guibg) exec printf("hi Lf_hl_popup_%s_sep0 ctermfg=%s", a:category, ctermbg == '' ? 'NONE': ctermbg) endfunction @@ -259,8 +273,8 @@ endfunction " 4. Regex mode function! leaderf#colorscheme#popup#hiMatchMode(category, mode) abort let sid = synIDtrans(hlID(s:matchModeMap[a:mode])) - let guibg = synIDattr(sid, "bg", "gui") - let ctermbg = synIDattr(sid, "bg", "cterm") + let guibg = s:SynIDattr(sid, "bg", "gui") + let ctermbg = s:SynIDattr(sid, "bg", "cterm") exec printf("hi link Lf_hl_popup_%s_matchMode %s", a:category, s:matchModeMap[a:mode]) exec printf("hi Lf_hl_popup_%s_sep1 guibg=%s", a:category, guibg == '' ? 'NONE': guibg) exec printf("hi Lf_hl_popup_%s_sep1 ctermbg=%s", a:category, ctermbg == '' ? 'NONE': ctermbg) @@ -272,7 +286,7 @@ endfunction function! s:hiDefineLineNr() abort call leaderf#colorscheme#popup#link_no_reverse("Lf_hl_LineNr", "LineNr") let sid = synIDtrans(hlID("Lf_hl_LineNr")) - if synIDattr(sid, "nocombine") == "" + if s:SynIDattr(sid, "nocombine") == "" let attr = s:getSynAttr(sid) if attr == "" let attr = "nocombine" @@ -280,16 +294,16 @@ function! s:hiDefineLineNr() abort let attr = attr . ",nocombine" endif - let guibg = synIDattr(sid, "bg", "gui") - let ctermbg = synIDattr(sid, "bg", "cterm") + let guibg = s:SynIDattr(sid, "bg", "gui") + let ctermbg = s:SynIDattr(sid, "bg", "cterm") if guibg == "" - let guibg = synIDattr(synIDtrans(hlID("Normal")), "bg", "gui") + let guibg = s:SynIDattr(synIDtrans(hlID("Normal")), "bg", "gui") if guibg == "" let guibg = "NONE" endif endif if ctermbg == "" - let ctermbg = synIDattr(synIDtrans(hlID("Normal")), "bg", "cterm") + let ctermbg = s:SynIDattr(synIDtrans(hlID("Normal")), "bg", "cterm") if ctermbg == "" let ctermbg = "NONE" endif From 4358f381ce1f5dd19a7f451f5869cc6699819859 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Tue, 10 Sep 2024 14:38:54 +0800 Subject: [PATCH 293/365] fix issue #1099 --- autoload/leaderf/python/leaderf/gitExpl.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 7b0a27f6..a483a386 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -624,7 +624,7 @@ def setOptions(self, winid, bufhidden): lfCmd("call win_execute({}, 'setlocal nospell')".format(winid)) lfCmd("call win_execute({}, 'setlocal nomodifiable')".format(winid)) if lfEval("getbufvar(winbufnr(%d), '&ft')" % winid) != self._cmd.getFileType(): - lfCmd("call win_execute({}, '{}')".format(winid, self._cmd.getFileTypeCommand())) + lfCmd("silent! call win_execute({}, '{}')".format(winid, self._cmd.getFileTypeCommand())) def initBuffer(self): pass From 63e3fc0945029edd10483360acbf43ab954ecfd8 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Tue, 10 Sep 2024 21:41:51 +0800 Subject: [PATCH 294/365] remove useless code --- autoload/leaderf/python/leaderf/gitExpl.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index a483a386..84ac6219 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -79,12 +79,6 @@ def cleanup(self): exe.killProcess() self._executor = [] - def getPatternRegex(self): - return self._pattern_regex - - def getContextSeparator(self): - return self._context_separator - class GitDiffExplorer(GitExplorer): def __init__(self): @@ -1083,6 +1077,7 @@ def first_value(self): def first_key_value(self): return next(iter(self.items())) + class FolderStatus(Enum): CLOSED = 0 OPEN = 1 @@ -2071,6 +2066,7 @@ def getViewContent(self): return [] + class DiffViewPanel(Panel): def __init__(self, bufhidden_callback=None, commit_id=""): super(DiffViewPanel, self).__init__() From d2a6714f37cdb7b9cc1fd5e1aa66a5a799e4b1a1 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Tue, 10 Sep 2024 22:05:59 +0800 Subject: [PATCH 295/365] add 'def autoJump(self, content):' --- autoload/leaderf/python/leaderf/gtagsExpl.py | 8 ++++++++ autoload/leaderf/python/leaderf/manager.py | 8 ++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gtagsExpl.py b/autoload/leaderf/python/leaderf/gtagsExpl.py index e286cebe..d0591a1c 100644 --- a/autoload/leaderf/python/leaderf/gtagsExpl.py +++ b/autoload/leaderf/python/leaderf/gtagsExpl.py @@ -956,6 +956,14 @@ def setArguments(self, arguments): self._arguments = arguments self._match_path = "--match-path" in arguments + def autoJump(self, content): + if "--auto-jump" in self._arguments and isinstance(content, list) and len(content) == 1: + mode = self._arguments["--auto-jump"][0] if len(self._arguments["--auto-jump"]) else "" + self._accept(content[0], mode) + return True + + return False + def _getDigest(self, line, mode): """ specify what part in the line to be processed and highlighted diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 503cf5d9..d7d1be9d 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -210,6 +210,9 @@ def _issue_422_set_option(self): def _acceptSelection(self, *args, **kwargs): pass + def autoJump(self, content): + return False + def _getDigest(self, line, mode): """ this function can be overridden @@ -2751,10 +2754,7 @@ def startExplorer(self, win_pos, *args, **kwargs): else: content = self._getExplorer().getContent(*args, **kwargs) self._getInstance().setCwd(lfGetCwd()) - if self._getExplorer().getStlCategory() in ["Gtags"] and "--auto-jump" in self._arguments \ - and isinstance(content, list) and len(content) == 1: - mode = self._arguments["--auto-jump"][0] if len(self._arguments["--auto-jump"]) else "" - self._accept(content[0], mode) + if self.autoJump(content) == True: return self._index = 0 From 71ac24712da87ac127fd4d9656d61274909e938a Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 11 Sep 2024 11:40:47 +0800 Subject: [PATCH 296/365] gtags report 'No content!' if no result --- autoload/leaderf/python/leaderf/gtagsExpl.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/autoload/leaderf/python/leaderf/gtagsExpl.py b/autoload/leaderf/python/leaderf/gtagsExpl.py index d0591a1c..72eb4fa6 100644 --- a/autoload/leaderf/python/leaderf/gtagsExpl.py +++ b/autoload/leaderf/python/leaderf/gtagsExpl.py @@ -281,7 +281,9 @@ def getContent(self, *args, **kwargs): if auto_jump: first_two = list(itertools.islice(content, 2)) - if len(first_two) == 1: + if len(first_two) == 0: + return [] + elif len(first_two) == 1: return first_two else: return content.join_left(first_two) From 00d18a8a5734c50ed68f72d07d88a1ce6efb9418 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Fri, 13 Sep 2024 17:00:26 +0800 Subject: [PATCH 297/365] add `Leaderf coc` this is a thin wrapper of some coc commands: | Command | Action | |-----------------------------------------------------------|---------------------------------------------| | Leaderf! coc definitions --auto-jump | run CocAction('jumpDefinition') | | Leaderf! coc references --auto-jump | run CocAction('jumpReferences') | | Leaderf! coc references --auto-jump --exclude-declaration | run CocAction('jumpUsed') | | Leaderf! coc declarations --auto-jump | run CocAction('jumpDeclaration') | | Leaderf! coc implementations --auto-jump | run CocAction('jumpImplementation') | | Leaderf! coc typeDefinitions --auto-jump | run CocAction('jumpTypeDefinition') | --- autoload/leaderf/Any.vim | 19 + autoload/leaderf/Coc.vim | 55 ++ autoload/leaderf/python/leaderf/anyExpl.py | 5 +- autoload/leaderf/python/leaderf/cocExpl.py | 566 ++++++++++++++++++++ autoload/leaderf/python/leaderf/instance.py | 5 +- autoload/leaderf/python/leaderf/manager.py | 3 + doc/leaderf.txt | 14 + 7 files changed, 665 insertions(+), 2 deletions(-) create mode 100644 autoload/leaderf/Coc.vim create mode 100644 autoload/leaderf/python/leaderf/cocExpl.py diff --git a/autoload/leaderf/Any.vim b/autoload/leaderf/Any.vim index 779b51d9..ce60dc45 100644 --- a/autoload/leaderf/Any.vim +++ b/autoload/leaderf/Any.vim @@ -69,6 +69,7 @@ let g:Lf_Helps = { \ "git-log": "show the commit logs", \ "git-diff": "show changes between commits, commit and working tree, etc", \ "git-blame": "show what revision and author last modified each line of a file", + \ "coc": "execute coc's commands", \ } let g:Lf_Arguments = { @@ -270,6 +271,24 @@ let g:Lf_Arguments = { \ {"name": ["--inline"], "nargs": 0, "help": "Display inline git blame information."}, \ ], \ }, + \ "coc":{ + \ "definitions": [ + \ {"name": ["--auto-jump"], "nargs": "?", "metavar": "", "help": "Jump to the target directly when there is only one match. can be 'h', 'v' or 't', which mean jump to a horizontally, vertically split window, or a new tabpage respectively. If is omitted, jump to a position in current window."}, + \ ], + \ "declarations": [ + \ {"name": ["--auto-jump"], "nargs": "?", "metavar": "", "help": "Jump to the target directly when there is only one match. can be 'h', 'v' or 't', which mean jump to a horizontally, vertically split window, or a new tabpage respectively. If is omitted, jump to a position in current window."}, + \ ], + \ "implementations": [ + \ {"name": ["--auto-jump"], "nargs": "?", "metavar": "", "help": "Jump to the target directly when there is only one match. can be 'h', 'v' or 't', which mean jump to a horizontally, vertically split window, or a new tabpage respectively. If is omitted, jump to a position in current window."}, + \ ], + \ "typeDefinitions": [ + \ {"name": ["--auto-jump"], "nargs": "?", "metavar": "", "help": "Jump to the target directly when there is only one match. can be 'h', 'v' or 't', which mean jump to a horizontally, vertically split window, or a new tabpage respectively. If is omitted, jump to a position in current window."}, + \ ], + \ "references": [ + \ {"name": ["--auto-jump"], "nargs": "?", "metavar": "", "help": "Jump to the target directly when there is only one match. can be 'h', 'v' or 't', which mean jump to a horizontally, vertically split window, or a new tabpage respectively. If is omitted, jump to a position in current window."}, + \ {"name": ["--exclude-declaration"], "nargs": 0, "help": "Exclude declaration locations."}, + \ ], + \ }, \} let g:Lf_CommonArguments = [ diff --git a/autoload/leaderf/Coc.vim b/autoload/leaderf/Coc.vim new file mode 100644 index 00000000..2cc2f94a --- /dev/null +++ b/autoload/leaderf/Coc.vim @@ -0,0 +1,55 @@ +" ============================================================================ +" File: Coc.vim +" Description: +" Author: Yggdroot +" Website: https://github.com/Yggdroot +" Note: +" License: Apache License, Version 2.0 +" ============================================================================ + +if leaderf#versionCheck() == 0 " this check is necessary + finish +endif + +exec g:Lf_py "from leaderf.cocExpl import *" + +function! leaderf#Coc#Maps(id) abort + nmapclear + exec g:Lf_py "import ctypes" + let manager = printf("ctypes.cast(%d, ctypes.py_object).value", a:id) + exec printf('nnoremap :exec g:Lf_py "%s.accept()"', manager) + exec printf('nnoremap o :exec g:Lf_py "%s.accept()"', manager) + exec printf('nnoremap <2-LeftMouse> :exec g:Lf_py "%s.accept()"', manager) + exec printf('nnoremap x :exec g:Lf_py "%s.accept(''h'')"', manager) + exec printf('nnoremap v :exec g:Lf_py "%s.accept(''v'')"', manager) + exec printf('nnoremap t :exec g:Lf_py "%s.accept(''t'')"', manager) + exec printf('nnoremap p :exec g:Lf_py "%s._previewResult(True)"', manager) + exec printf('nnoremap j :exec g:Lf_py "%s.moveAndPreview(''j'')"', manager) + exec printf('nnoremap k :exec g:Lf_py "%s.moveAndPreview(''k'')"', manager) + exec printf('nnoremap :exec g:Lf_py "%s.moveAndPreview(''Up'')"', manager) + exec printf('nnoremap :exec g:Lf_py "%s.moveAndPreview(''Down'')"', manager) + exec printf('nnoremap :exec g:Lf_py "%s.moveAndPreview(''PageUp'')"', manager) + exec printf('nnoremap :exec g:Lf_py "%s.moveAndPreview(''PageDown'')"', manager) + exec printf('nnoremap q :exec g:Lf_py "%s.quit()"', manager) + exec printf('nnoremap i :exec g:Lf_py "%s.input()"', manager) + exec printf('nnoremap :exec g:Lf_py "%s.input()"', manager) + exec printf('nnoremap :exec g:Lf_py "%s.toggleHelp()"', manager) + exec printf('nnoremap :exec g:Lf_py "%s._toUpInPopup()"', manager) + exec printf('nnoremap :exec g:Lf_py "%s._toDownInPopup()"', manager) + exec printf('nnoremap :exec g:Lf_py "%s.closePreviewPopupOrQuit()"', manager) +endfunction + +function! leaderf#Coc#Commands() abort + if !exists("g:Lf_CocCommands") + let g:Lf_CocCommands = [ + \ {"Leaderf! coc definitions --auto-jump": "run CocAction('jumpDefinition')"}, + \ {"Leaderf! coc references --auto-jump": "run CocAction('jumpReferences')"}, + \ {"Leaderf! coc references --auto-jump --exclude-declaration": "run CocAction('jumpUsed')"}, + \ {"Leaderf! coc declarations --auto-jump": "run CocAction('jumpDeclaration')"}, + \ {"Leaderf! coc implementations --auto-jump": "run CocAction('jumpImplementation')"}, + \ {"Leaderf! coc typeDefinitions --auto-jump": "run CocAction('jumpTypeDefinition')"}, + \ ] + endif + + return g:Lf_CocCommands +endfunction diff --git a/autoload/leaderf/python/leaderf/anyExpl.py b/autoload/leaderf/python/leaderf/anyExpl.py index dd14722c..46cf9cbe 100644 --- a/autoload/leaderf/python/leaderf/anyExpl.py +++ b/autoload/leaderf/python/leaderf/anyExpl.py @@ -72,7 +72,7 @@ def setConfig(self, category, config): def getContent(self, *args, **kwargs): source = self._config.get("source") if not source: - return None + return [] if isinstance(source, list): result = source @@ -722,6 +722,9 @@ def _default_action(self, category, positional_args, arguments, *args, **kwargs) elif category == "git": from .gitExpl import gitExplManager manager = gitExplManager + elif category == "coc": + from .cocExpl import cocExplManager + manager = cocExplManager else: import ctypes manager_id = lfFunction(lfEval("g:Lf_PythonExtensions['%s'].manager_id" % category))() diff --git a/autoload/leaderf/python/leaderf/cocExpl.py b/autoload/leaderf/python/leaderf/cocExpl.py new file mode 100644 index 00000000..9d412241 --- /dev/null +++ b/autoload/leaderf/python/leaderf/cocExpl.py @@ -0,0 +1,566 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import vim +import re +import os +import os.path +from functools import wraps +from .utils import * +from .explorer import * +from .manager import * + + +def workingDirectory(func): + @wraps(func) + def deco(self, *args, **kwargs): + if self._getExplorer()._cmd_work_dir == lfGetCwd(): + return func(self, *args, **kwargs) + + # https://github.com/neovim/neovim/issues/8336 + if lfEval("has('nvim')") == '1': + chdir = vim.chdir + else: + chdir = os.chdir + orig_cwd = lfGetCwd() + chdir(self._getExplorer()._cmd_work_dir) + try: + return func(self, *args, **kwargs) + finally: + chdir(orig_cwd) + + return deco + +#***************************************************** +# CocExplorer +#***************************************************** +class CocExplorer(Explorer): + def __init__(self): + self._pattern_regex = [] + self._cmd_work_dir = "" + + def getContent(self, *args, **kwargs): + self._cmd_work_dir = lfGetCwd() + commands = lfEval("leaderf#Coc#Commands()") + return [list(item)[0] for item in commands] + + def getStlCategory(self): + return 'Coc' + + def getStlCurDir(self): + return escQuote(lfEncode(self._cmd_work_dir)) + + def supportsNameOnly(self): + return False + + def getPatternRegex(self): + return self._pattern_regex + + def getFileLine(self, file_name, line_num, file_contents): + if lfEval("bufloaded('%s')" % escQuote(file_name)) == '1': + return lfEval("getbufline('{}', {}, {})[0]".format(file_name, line_num, line_num)) + else: + if file_name not in file_contents: + with lfOpen(file_name, 'r', errors='ignore') as f: + file_contents[file_name] = f.readlines() + + return file_contents[file_name][line_num-1].rstrip("\r\n") + + def generateContent(self, items): + self._pattern_regex = [] + content = [] + file_contents = {} + for item in items: + file_path = lfRelpath(item["uri"][7:]) + line_num = int(item["range"]["start"]["line"]) + col_num = int(item["range"]["start"]["character"]) + line = self.getFileLine(file_path, line_num + 1, file_contents) + if len(self._pattern_regex) == 0: + end_line_num = int(item["range"]["end"]["line"]) + end_col_num = int(item["range"]["end"]["character"]) + if end_line_num == line_num: + self._pattern_regex.append(line[col_num: end_col_num]) + + content.append("{}:{}:{}:{}".format(file_path, line_num+1, col_num+1, line)) + + return content + + +class DefinitionsExplorer(CocExplorer): + def getContent(self, *args, **kwargs): + try: + self._cmd_work_dir = lfGetCwd() + definitions = lfEval("CocAction('definitions')") + return self.generateContent(definitions) + except vim.error as e: + lfPrintError(str(e).split('\n')[-1]) + return None + + def supportsNameOnly(self): + return True + + def getStlCategory(self): + return 'definitions' + + +class DeclarationsExplorer(CocExplorer): + def getContent(self, *args, **kwargs): + try: + self._cmd_work_dir = lfGetCwd() + declarations = lfEval("CocAction('declarations')") + return self.generateContent(declarations) + except vim.error as e: + lfPrintError(str(e).split('\n')[-1]) + return None + + def supportsNameOnly(self): + return True + + def getStlCategory(self): + return 'declarations' + + +class ImplementationsExplorer(CocExplorer): + def getContent(self, *args, **kwargs): + try: + self._cmd_work_dir = lfGetCwd() + implementations = lfEval("CocAction('implementations')") + return self.generateContent(implementations) + except vim.error as e: + lfPrintError(str(e).split('\n')[-1]) + return None + + def supportsNameOnly(self): + return True + + def getStlCategory(self): + return 'implementations' + + +class TypeDefinitionsExplorer(CocExplorer): + def getContent(self, *args, **kwargs): + try: + self._cmd_work_dir = lfGetCwd() + typeDefinitions = lfEval("CocAction('typeDefinitions')") + return self.generateContent(typeDefinitions) + except vim.error as e: + lfPrintError(str(e).split('\n')[-1]) + return None + + def supportsNameOnly(self): + return True + + def getStlCategory(self): + return 'typeDefinitions' + + +class ReferencesExplorer(CocExplorer): + def getContent(self, *args, **kwargs): + try: + self._cmd_work_dir = lfGetCwd() + + arguments_dict = kwargs.get("arguments", {}) + if "--exclude-declaration" in arguments_dict: + references = lfEval("CocAction('references', 1)") + else: + references = lfEval("CocAction('references')") + + return self.generateContent(references) + except vim.error as e: + lfPrintError(str(e).split('\n')[-1]) + return None + + def supportsNameOnly(self): + return True + + def getStlCategory(self): + return 'references' + + +#***************************************************** +# CocExplManager +#***************************************************** +class CocExplManager(Manager): + def __init__(self): + super(CocExplManager, self).__init__() + self._managers = {} + + def _getExplClass(self): + return CocExplorer + + def _defineMaps(self): + lfCmd("call leaderf#Coc#Maps({})".format(id(self))) + + def _createHelp(self): + help = [] + help.append('" //o : open file under cursor') + help.append('" x : open file under cursor in a horizontally split window') + help.append('" v : open file under cursor in a vertically split window') + help.append('" t : open file under cursor in a new tabpage') + help.append('" i/ : switch to input mode') + help.append('" p : preview the file') + help.append('" q : quit') + help.append('" : toggle this help') + help.append('" : close the preview window or quit') + help.append('" ---------------------------------------------------------') + return help + + def _getDigest(self, line, mode): + """ + specify what part in the line to be processed and highlighted + Args: + mode: 0, return the full path + 1, return the name only + 2, return the directory name + """ + return line + + def _getDigestStartPos(self, line, mode): + """ + return the start position of the digest returned by _getDigest() + Args: + mode: 0, return the start postion of full path + 1, return the start postion of name only + 2, return the start postion of directory name + """ + return 0 + + def createManager(self, subcommand): + if subcommand == "definitions": + return DefinitionsExplManager() + elif subcommand == "declarations": + return DeclarationsExplManager() + elif subcommand == "implementations": + return ImplementationsExplManager() + elif subcommand == "typeDefinitions": + return TypeDefinitionsExplManager() + elif subcommand == "references": + return ReferencesExplManager() + else: + return super(CocExplManager, self) + + def getExplManager(self, subcommand): + if subcommand not in self._managers: + self._managers[subcommand] = self.createManager(subcommand) + return self._managers[subcommand] + + def startExplorer(self, win_pos, *args, **kwargs): + arguments_dict = kwargs.get("arguments", {}) + if "--recall" in arguments_dict: + self._arguments.update(arguments_dict) + else: + self.setArguments(arguments_dict) + + arg_list = self._arguments.get("arg_line", 'coc').split() + arg_list = [item for item in arg_list if not item.startswith('-')] + if len(arg_list) == 1: + subcommand = "" + else: + subcommand = arg_list[1] + self.getExplManager(subcommand).startExplorer(win_pos, *args, **kwargs) + + def _acceptSelection(self, *args, **kwargs): + if len(args) == 0: + return + + line = args[0] + cmd = line + try: + lfCmd(cmd) + except vim.error: + lfPrintTraceback() + + def getSource(self, line): + commands = lfEval("leaderf#Coc#Commands()") + for cmd in commands: + if line in cmd: + return cmd[line] + + return None + + def _previewInPopup(self, *args, **kwargs): + if len(args) == 0 or args[0] == '': + return + + line = args[0] + source = self.getSource(line) + + self._createPopupPreview("", source, 0) + + def _createPreviewWindow(self, config, source, line_num, jump_cmd): + if lfEval("has('nvim')") == '1': + lfCmd("noautocmd let scratch_buffer = nvim_create_buf(0, 1)") + lfCmd("noautocmd call setbufline(scratch_buffer, 1, '{}')".format(escQuote(source))) + lfCmd("noautocmd call nvim_buf_set_option(scratch_buffer, 'bufhidden', 'wipe')") + lfCmd("noautocmd call nvim_buf_set_option(scratch_buffer, 'undolevels', -1)") + + self._preview_winid = int(lfEval("nvim_open_win(scratch_buffer, 0, {})" + .format(json.dumps(config)))) + else: + lfCmd("noautocmd let winid = popup_create('{}', {})" + .format(escQuote(source), json.dumps(config))) + self._preview_winid = int(lfEval("winid")) + + self._setWinOptions(self._preview_winid) + + def _useExistingWindow(self, title, source, line_num, jump_cmd): + self.setOptionsForCursor() + + if lfEval("has('nvim')") == '1': + lfCmd("""call win_execute({}, "call nvim_buf_set_lines(0, 0, -1, v:false, ['{}'])")""" + .format(self._preview_winid, escQuote(source))) + else: + lfCmd("noautocmd call popup_settext({}, '{}')" + .format(self._preview_winid, escQuote(source))) + + def _beforeExit(self): + super(CocExplManager, self)._beforeExit() + for k, v in self._cursorline_dict.items(): + if k.valid: + k.options["cursorline"] = v + self._cursorline_dict.clear() + + +class CommonExplManager(CocExplManager): + def _afterEnter(self): + super(CocExplManager, self)._afterEnter() + if self._getInstance().getWinPos() == 'popup': + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_rgFileName'', ''^.\{-}\ze\:\d\+:'', 10)')""" + % self._getInstance().getPopupWinId()) + id = int(lfEval("matchid")) + self._match_ids.append(id) + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_rgLineNumber'', ''^.\{-}\zs:\d\+:'', 10)')""" + % self._getInstance().getPopupWinId()) + id = int(lfEval("matchid")) + self._match_ids.append(id) + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_rgColumnNumber'', ''^.\{-}:\d\+:\zs\d\+:'', 10)')""" + % self._getInstance().getPopupWinId()) + id = int(lfEval("matchid")) + self._match_ids.append(id) + try: + for i in self._getExplorer().getPatternRegex(): + lfCmd("""call win_execute(%d, "let matchid = matchadd('Lf_hl_rgHighlight', '%s', 9)")""" + % (self._getInstance().getPopupWinId(), re.sub(r'\\(?!")', r'\\\\', escQuote(i)))) + id = int(lfEval("matchid")) + self._match_ids.append(id) + except vim.error: + pass + else: + id = int(lfEval(r"matchadd('Lf_hl_rgFileName', '^.\{-}\ze\:\d\+:', 10)")) + self._match_ids.append(id) + id = int(lfEval(r"matchadd('Lf_hl_rgLineNumber', '^.\{-}\zs:\d\+:', 10)")) + self._match_ids.append(id) + id = int(lfEval(r"matchadd('Lf_hl_rgColumnNumber', '^.\{-}:\d\+:\zs\d\+:', 10)")) + self._match_ids.append(id) + + try: + for i in self._getExplorer().getPatternRegex(): + id = int(lfEval("matchadd('Lf_hl_rgHighlight', '%s', 9)" % escQuote(i))) + self._match_ids.append(id) + except vim.error: + pass + + def setStlMode(self, mode): + if mode == "FullPath": + mode = "WholeLine" + elif mode == "NameOnly": + mode = "Contents" + super(CocExplManager, self).setStlMode(mode) + + def _getFileInfo(self, args): + line = args[0] + + m = re.match(r'^(.+?):(\d+):', line) + if m is None: + return (None, None) + + file, line_num = m.group(1, 2) + if not os.path.isabs(file): + file = os.path.join(self._getInstance().getCwd(), lfDecode(file)) + i = 1 + while not os.path.exists(lfDecode(file)): + m = re.match(r'^(.+?(?::\d+.*?){%d}):(\d+):' % i, line) + i += 1 + file, line_num = m.group(1, 2) + if not os.path.isabs(file): + file = os.path.join(self._getInstance().getCwd(), lfDecode(file)) + + file = os.path.normpath(lfEncode(file)) + + return (file, line_num) + + @workingDirectory + def _acceptSelection(self, *args, **kwargs): + if len(args) == 0: + return + + file, line_num = self._getFileInfo(args) + if file is None: + return + + if isinstance(file, int): + buf_number = file + else: + buf_number = -1 + + try: + if buf_number == -1: + if kwargs.get("mode", '') == 't': + if lfEval("get(g:, 'Lf_JumpToExistingWindow', 1)") == '1' \ + and lfEval("bufloaded('%s')" % escQuote(file)) == '1': + lfDrop('tab', file, line_num) + else: + lfCmd("tabe %s | %s" % (escSpecial(file), line_num)) + else: + if lfEval("get(g:, 'Lf_JumpToExistingWindow', 1)") == '1' \ + and lfEval("bufloaded('%s')" % escQuote(file)) == '1': + lfDrop('', file, line_num) + else: + lfCmd("hide edit +%s %s" % (line_num, escSpecial(file))) + else: + lfCmd("hide buffer +%s %s" % (line_num, buf_number)) + lfCmd("norm! ^zv") + if self._getExplorer().getPatternRegex(): + lfCmd(r"call search('\V%s', 'zW', line('.'))" % escQuote(self._getExplorer().getPatternRegex()[0])) + lfCmd("norm! zz") + + if "preview" not in kwargs: + lfCmd("setlocal cursorline! | redraw | sleep 150m | setlocal cursorline!") + + if vim.current.window not in self._cursorline_dict: + self._cursorline_dict[vim.current.window] = vim.current.window.options["cursorline"] + + lfCmd("setlocal cursorline") + except vim.error as e: # E37 + if 'E325' not in str(e).split(':'): + lfPrintTraceback() + + def _highlightInPreview(self): + if lfEval("has('nvim')") != '1': + try: + for i in self._getExplorer().getPatternRegex(): + lfCmd("""call win_execute(%d, "let matchid = matchadd('Lf_hl_rgHighlight', '%s', 9)")""" + % (self._preview_winid, re.sub(r'\\(?!")', r'\\\\', escQuote(i)))) + id = int(lfEval("matchid")) + self._match_ids.append(id) + except vim.error: + pass + else: + cur_winid = lfEval("win_getid()") + lfCmd("noautocmd call win_gotoid(%d)" % self._preview_winid) + if lfEval("win_getid()") != cur_winid: + try: + for i in self._getExplorer().getPatternRegex(): + id = int(lfEval("matchadd('Lf_hl_rgHighlight', '%s', 9)" % escQuote(i))) + self._match_ids.append(id) + except vim.error: + pass + lfCmd("noautocmd call win_gotoid(%s)" % cur_winid) + + def _previewInPopup(self, *args, **kwargs): + if len(args) == 0 or args[0] == '': + return + + file, line_num = self._getFileInfo(args) + if file is None: + return + + if isinstance(file, int): + source = file + else: + if lfEval("bufloaded('%s')" % escQuote(file)) == '1': + source = int(lfEval("bufadd('%s')" % escQuote(file))) + else: + source = file + + self._createPopupPreview("", source, line_num) + self._highlightInPreview() + + def _getDigest(self, line, mode): + """ + specify what part in the line to be processed and highlighted + Args: + mode: 0, return the full path + 1, return the name only + 2, return the directory name + """ + if mode == 0: + return line + elif mode == 1: + return line.split(":", 3)[-1] + else: + return line.split(":", 1)[0] + + def _getDigestStartPos(self, line, mode): + """ + return the start position of the digest returned by _getDigest() + Args: + mode: 0, return the start postion of full path + 1, return the start postion of name only + 2, return the start postion of directory name + """ + if mode == 0 or mode == 2: + return 0 + else: + file_path, line_num, column, content = line.split(":", 3) + return lfBytesLen(file_path + line_num + column) + 3 + + def _createPreviewWindow(self, config, source, line_num, jump_cmd): + return super(CocExplManager, self)._createPreviewWindow(config, source, line_num, jump_cmd) + + def _useExistingWindow(self, title, source, line_num, jump_cmd): + return super(CocExplManager, self)._useExistingWindow(title, source, line_num, jump_cmd) + + def startExplorer(self, win_pos, *args, **kwargs): + return super(CocExplManager, self).startExplorer(win_pos, *args, **kwargs) + + def autoJump(self, content): + if "--auto-jump" in self._arguments and isinstance(content, list) and len(content) == 1: + mode = self._arguments["--auto-jump"][0] if len(self._arguments["--auto-jump"]) else "" + self._accept(content[0], mode) + return True + + return False + + +class DefinitionsExplManager(CommonExplManager): + def _getExplorer(self): + if self._explorer is None: + self._explorer = DefinitionsExplorer() + return self._explorer + + +class DeclarationsExplManager(CommonExplManager): + def _getExplorer(self): + if self._explorer is None: + self._explorer = DeclarationsExplorer() + return self._explorer + + +class ImplementationsExplManager(CommonExplManager): + def _getExplorer(self): + if self._explorer is None: + self._explorer = ImplementationsExplorer() + return self._explorer + + +class TypeDefinitionsExplManager(CommonExplManager): + def _getExplorer(self): + if self._explorer is None: + self._explorer = TypeDefinitionsExplorer() + return self._explorer + + +class ReferencesExplManager(CommonExplManager): + def _getExplorer(self): + if self._explorer is None: + self._explorer = ReferencesExplorer() + return self._explorer + + +#***************************************************** +# cocExplManager is a singleton +#***************************************************** +cocExplManager = CocExplManager() + +__all__ = ['cocExplManager'] diff --git a/autoload/leaderf/python/leaderf/instance.py b/autoload/leaderf/python/leaderf/instance.py index 12e17b3f..4165306e 100644 --- a/autoload/leaderf/python/leaderf/instance.py +++ b/autoload/leaderf/python/leaderf/instance.py @@ -323,7 +323,10 @@ def _setAttributes(self): lfCmd("setlocal nofoldenable") lfCmd("setlocal foldmethod=manual") lfCmd("setlocal shiftwidth=4") - lfCmd("setlocal cursorline") + if lfEval("has('nvim')") == '1': + lfCmd("call nvim_win_set_option(win_getid(), 'cursorline', v:true)") + else: + lfCmd("setlocal cursorline") if lfEval("exists('+cursorlineopt')") == '1': lfCmd("setlocal cursorlineopt=both") lfCmd("silent! setlocal signcolumn=no") # make vim flicker diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index d7d1be9d..60f88448 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -2766,6 +2766,9 @@ def startExplorer(self, win_pos, *args, **kwargs): self._result_content = [] self._cb_content = [] + if content is None: + return + if not content: lfCmd("echohl Error | redraw | echo ' No content!' | echohl NONE") return diff --git a/doc/leaderf.txt b/doc/leaderf.txt index 95ba3edf..1e8df0b4 100644 --- a/doc/leaderf.txt +++ b/doc/leaderf.txt @@ -1218,6 +1218,20 @@ g:Lf_GitBlameTimeFormat *g:Lf_GitBlameTimeFormat* Default value is "". +g:Lf_CocCommands *g:Lf_CocCommands* + Define a list of commands you may want to use frequently. + The list is as follows: > + let g:Lf_CocCommands = [ + \ {"Leaderf! coc definitions --auto-jump": "run CocAction('jumpDefinition')"}, + \ {"Leaderf! coc references --auto-jump": "run CocAction('jumpReferences')"}, + \ {"Leaderf! coc references --auto-jump --exclude-declaration": "run CocAction('jumpUsed')"}, + \ {"Leaderf! coc declarations --auto-jump": "run CocAction('jumpDeclaration')"}, + \ {"Leaderf! coc implementations --auto-jump": "run CocAction('jumpImplementation')"}, + \ {"Leaderf! coc typeDefinitions --auto-jump": "run CocAction('jumpTypeDefinition')"}, + \ ] +< + Open the commands panel using `:Leaderf coc` . + ============================================================================== USAGE *leaderf-usage* From 74f3042368b547d481fc08464e9f42c5ddc79b15 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Mon, 23 Sep 2024 13:17:02 +0800 Subject: [PATCH 298/365] don't do `norm! zz` if already shown in the window --- autoload/leaderf/python/leaderf/cocExpl.py | 53 ++++++++++++---------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/autoload/leaderf/python/leaderf/cocExpl.py b/autoload/leaderf/python/leaderf/cocExpl.py index 9d412241..2996a0ad 100644 --- a/autoload/leaderf/python/leaderf/cocExpl.py +++ b/autoload/leaderf/python/leaderf/cocExpl.py @@ -398,31 +398,37 @@ def _acceptSelection(self, *args, **kwargs): if file is None: return - if isinstance(file, int): - buf_number = file - else: - buf_number = -1 - try: - if buf_number == -1: - if kwargs.get("mode", '') == 't': - if lfEval("get(g:, 'Lf_JumpToExistingWindow', 1)") == '1' \ - and lfEval("bufloaded('%s')" % escQuote(file)) == '1': - lfDrop('tab', file, line_num) - else: - lfCmd("tabe %s | %s" % (escSpecial(file), line_num)) + is_shown = False + if kwargs.get("mode", '') == 't': + if lfEval("get(g:, 'Lf_JumpToExistingWindow', 1)") == '1' \ + and lfEval("bufloaded('%s')" % escQuote(file)) == '1': + winid = int(lfEval("bufwinid('%s')" % escQuote(file))) + start_line = int(lfEval("line('w0', %d)" % winid)) + end_line = int(lfEval("line('w$', %d)" % winid)) + lfDrop('tab', file, line_num) + if start_line <= int(line_num) <= end_line: + is_shown = True else: - if lfEval("get(g:, 'Lf_JumpToExistingWindow', 1)") == '1' \ - and lfEval("bufloaded('%s')" % escQuote(file)) == '1': - lfDrop('', file, line_num) - else: - lfCmd("hide edit +%s %s" % (line_num, escSpecial(file))) + lfCmd("tabe %s | %s" % (escSpecial(file), line_num)) else: - lfCmd("hide buffer +%s %s" % (line_num, buf_number)) + if lfEval("get(g:, 'Lf_JumpToExistingWindow', 1)") == '1' \ + and lfEval("bufloaded('%s')" % escQuote(file)) == '1': + winid = int(lfEval("bufwinid('%s')" % escQuote(file))) + start_line = int(lfEval("line('w0', %d)" % winid)) + end_line = int(lfEval("line('w$', %d)" % winid)) + lfDrop('', file, line_num) + if start_line <= int(line_num) <= end_line: + is_shown = True + else: + lfCmd("hide edit +%s %s" % (line_num, escSpecial(file))) + lfCmd("norm! ^zv") if self._getExplorer().getPatternRegex(): lfCmd(r"call search('\V%s', 'zW', line('.'))" % escQuote(self._getExplorer().getPatternRegex()[0])) - lfCmd("norm! zz") + + if is_shown == False: + lfCmd("norm! zz") if "preview" not in kwargs: lfCmd("setlocal cursorline! | redraw | sleep 150m | setlocal cursorline!") @@ -465,13 +471,10 @@ def _previewInPopup(self, *args, **kwargs): if file is None: return - if isinstance(file, int): - source = file + if lfEval("bufloaded('%s')" % escQuote(file)) == '1': + source = int(lfEval("bufadd('%s')" % escQuote(file))) else: - if lfEval("bufloaded('%s')" % escQuote(file)) == '1': - source = int(lfEval("bufadd('%s')" % escQuote(file))) - else: - source = file + source = file self._createPopupPreview("", source, line_num) self._highlightInPreview() From 0fa53aea5b6f0fb4c8fec42fe84b26845aa6ce75 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 25 Sep 2024 20:59:01 +0800 Subject: [PATCH 299/365] fix high cpu --- autoload/leaderf/python/leaderf/cli.py | 2 +- autoload/leaderf/python/leaderf/rgExpl.py | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/autoload/leaderf/python/leaderf/cli.py b/autoload/leaderf/python/leaderf/cli.py index f3b6b815..5e5da156 100644 --- a/autoload/leaderf/python/leaderf/cli.py +++ b/autoload/leaderf/python/leaderf/cli.py @@ -677,7 +677,7 @@ def input(self, callback): if lfEval("has('nvim') && exists('g:GuiLoaded')") == '1': time.sleep(0.005) # this is to solve issue 375 leaderF hangs in nvim-qt else: - time.sleep(0) + time.sleep(0.001) if lfEval("get(g:, 'Lf_NoAsync', 0)") == '0': lfCmd("let nr = getchar({})".format(block)) diff --git a/autoload/leaderf/python/leaderf/rgExpl.py b/autoload/leaderf/python/leaderf/rgExpl.py index 713a438f..6f54556d 100644 --- a/autoload/leaderf/python/leaderf/rgExpl.py +++ b/autoload/leaderf/python/leaderf/rgExpl.py @@ -1549,7 +1549,7 @@ def accept(self, mode=''): def _writeBuffer(self): if not self._cli.pattern: # e.g., when or is typed - return + return 100 if self._read_content_exception is not None: raise self._read_content_exception[1] @@ -1568,6 +1568,8 @@ def _writeBuffer(self): if self._getInstance().getWinPos() not in ('popup', 'floatwin'): lfCmd("redrawstatus") + + return 100 else: cur_len = len(self._content) if time.time() - self._start_time > 0.1: From ed349b76f3feff7dc68a1e478d51e59cb41e1e6f Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Sun, 29 Sep 2024 16:43:00 +0800 Subject: [PATCH 300/365] 'setlocal signcolumn=no' make vim flicker --- autoload/leaderf/python/leaderf/instance.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/autoload/leaderf/python/leaderf/instance.py b/autoload/leaderf/python/leaderf/instance.py index 4165306e..e7a6d0a7 100644 --- a/autoload/leaderf/python/leaderf/instance.py +++ b/autoload/leaderf/python/leaderf/instance.py @@ -329,7 +329,8 @@ def _setAttributes(self): lfCmd("setlocal cursorline") if lfEval("exists('+cursorlineopt')") == '1': lfCmd("setlocal cursorlineopt=both") - lfCmd("silent! setlocal signcolumn=no") # make vim flicker + if lfEval("has('nvim')") == '1': + lfCmd("silent! setlocal signcolumn=no") # make vim flicker lfCmd("setlocal colorcolumn=") if self._reverse_order: lfCmd("setlocal nonumber") @@ -396,7 +397,7 @@ def _vim_set_options(self, winid): lfCmd("call win_execute(%d, 'setlocal shiftwidth=4')" % winid) lfCmd("call win_execute(%d, 'setlocal nocursorline')" % winid) lfCmd("call win_execute(%d, 'setlocal foldcolumn=0')" % winid) - lfCmd("call win_execute(%d, 'silent! setlocal signcolumn=no')" % winid) + # lfCmd("call win_execute(%d, 'silent! setlocal signcolumn=no')" % winid) if lfEval("exists('+cursorlineopt')") == '1': lfCmd("call win_execute(%d, 'setlocal cursorlineopt=both')" % winid) lfCmd("call win_execute(%d, 'setlocal colorcolumn=')" % winid) From b9591fde81ff07ae6576103d5650f8e540f87f7e Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Tue, 8 Oct 2024 15:54:31 +0800 Subject: [PATCH 301/365] c++ is escaped as c%2B%2B --- autoload/leaderf/python/leaderf/cocExpl.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/autoload/leaderf/python/leaderf/cocExpl.py b/autoload/leaderf/python/leaderf/cocExpl.py index 2996a0ad..48b9ae49 100644 --- a/autoload/leaderf/python/leaderf/cocExpl.py +++ b/autoload/leaderf/python/leaderf/cocExpl.py @@ -5,6 +5,7 @@ import re import os import os.path +import urllib.parse from functools import wraps from .utils import * from .explorer import * @@ -71,7 +72,7 @@ def generateContent(self, items): content = [] file_contents = {} for item in items: - file_path = lfRelpath(item["uri"][7:]) + file_path = lfRelpath(urllib.parse.unquote(item["uri"][7:])) line_num = int(item["range"]["start"]["line"]) col_num = int(item["range"]["start"]["character"]) line = self.getFileLine(file_path, line_num + 1, file_contents) From 1b946ab7df2430ab7ba5e99f48167a5196d76b58 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 9 Oct 2024 10:50:09 +0800 Subject: [PATCH 302/365] preview is not right --- autoload/leaderf/python/leaderf/bufTagExpl.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/autoload/leaderf/python/leaderf/bufTagExpl.py b/autoload/leaderf/python/leaderf/bufTagExpl.py index 51df2ce1..7bf074cf 100644 --- a/autoload/leaderf/python/leaderf/bufTagExpl.py +++ b/autoload/leaderf/python/leaderf/bufTagExpl.py @@ -535,6 +535,8 @@ def _relocateCursor(self): lfCmd(str(index)) lfCmd("norm! zz") + self._previewResult(False) + def _previewInPopup(self, *args, **kwargs): if len(args) == 0 or args[0] == '': return From 1f00feafbde66263760ea6b066ef07515ae03a42 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 10 Oct 2024 15:54:22 +0800 Subject: [PATCH 303/365] the highlight is not right --- autoload/leaderf/python/leaderf/cocExpl.py | 23 ++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/autoload/leaderf/python/leaderf/cocExpl.py b/autoload/leaderf/python/leaderf/cocExpl.py index 48b9ae49..e00e2df5 100644 --- a/autoload/leaderf/python/leaderf/cocExpl.py +++ b/autoload/leaderf/python/leaderf/cocExpl.py @@ -340,6 +340,7 @@ def _afterEnter(self): self._match_ids.append(id) try: for i in self._getExplorer().getPatternRegex(): + i = r'\<{}\>'.format(i) lfCmd("""call win_execute(%d, "let matchid = matchadd('Lf_hl_rgHighlight', '%s', 9)")""" % (self._getInstance().getPopupWinId(), re.sub(r'\\(?!")', r'\\\\', escQuote(i)))) id = int(lfEval("matchid")) @@ -356,6 +357,7 @@ def _afterEnter(self): try: for i in self._getExplorer().getPatternRegex(): + i = r'\<{}\>'.format(i) id = int(lfEval("matchadd('Lf_hl_rgHighlight', '%s', 9)" % escQuote(i))) self._match_ids.append(id) except vim.error: @@ -371,31 +373,31 @@ def setStlMode(self, mode): def _getFileInfo(self, args): line = args[0] - m = re.match(r'^(.+?):(\d+):', line) + m = re.match(r'^(.+?):(\d+):(\d+):', line) if m is None: - return (None, None) + return (None, None, None) - file, line_num = m.group(1, 2) + file, line_num, col_num = m.group(1, 2, 3) if not os.path.isabs(file): file = os.path.join(self._getInstance().getCwd(), lfDecode(file)) i = 1 while not os.path.exists(lfDecode(file)): - m = re.match(r'^(.+?(?::\d+.*?){%d}):(\d+):' % i, line) + m = re.match(r'^(.+?(?::\d+.*?){%d}):(\d+):(\d+):' % i, line) i += 1 - file, line_num = m.group(1, 2) + file, line_num, col_num = m.group(1, 2, 3) if not os.path.isabs(file): file = os.path.join(self._getInstance().getCwd(), lfDecode(file)) file = os.path.normpath(lfEncode(file)) - return (file, line_num) + return (file, line_num, col_num) @workingDirectory def _acceptSelection(self, *args, **kwargs): if len(args) == 0: return - file, line_num = self._getFileInfo(args) + file, line_num, col_num = self._getFileInfo(args) if file is None: return @@ -425,8 +427,7 @@ def _acceptSelection(self, *args, **kwargs): lfCmd("hide edit +%s %s" % (line_num, escSpecial(file))) lfCmd("norm! ^zv") - if self._getExplorer().getPatternRegex(): - lfCmd(r"call search('\V%s', 'zW', line('.'))" % escQuote(self._getExplorer().getPatternRegex()[0])) + lfCmd("norm! {}|".format(col_num)) if is_shown == False: lfCmd("norm! zz") @@ -446,6 +447,7 @@ def _highlightInPreview(self): if lfEval("has('nvim')") != '1': try: for i in self._getExplorer().getPatternRegex(): + i = r'\<{}\>'.format(i) lfCmd("""call win_execute(%d, "let matchid = matchadd('Lf_hl_rgHighlight', '%s', 9)")""" % (self._preview_winid, re.sub(r'\\(?!")', r'\\\\', escQuote(i)))) id = int(lfEval("matchid")) @@ -458,6 +460,7 @@ def _highlightInPreview(self): if lfEval("win_getid()") != cur_winid: try: for i in self._getExplorer().getPatternRegex(): + i = r'\<{}\>'.format(i) id = int(lfEval("matchadd('Lf_hl_rgHighlight', '%s', 9)" % escQuote(i))) self._match_ids.append(id) except vim.error: @@ -468,7 +471,7 @@ def _previewInPopup(self, *args, **kwargs): if len(args) == 0 or args[0] == '': return - file, line_num = self._getFileInfo(args) + file, line_num, col_num = self._getFileInfo(args) if file is None: return From 5fdf6ca45c8f7d3f5a03c75f04b7af4ba2f52f10 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 13 Nov 2024 21:38:42 +0800 Subject: [PATCH 304/365] fix issue #1104 --- autoload/leaderf/python/leaderf/bufExpl.py | 3 ++- autoload/leaderf/python/leaderf/fileExpl.py | 4 +++- autoload/leaderf/python/leaderf/mruExpl.py | 4 +++- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/autoload/leaderf/python/leaderf/bufExpl.py b/autoload/leaderf/python/leaderf/bufExpl.py index 6dfb6cec..2b6c7387 100644 --- a/autoload/leaderf/python/leaderf/bufExpl.py +++ b/autoload/leaderf/python/leaderf/bufExpl.py @@ -300,7 +300,8 @@ def _previewInPopup(self, *args, **kwargs): if lfEval("bufloaded(%d)" % buf_number) == '0': lfCmd("silent call bufload(%d)" % buf_number) - self._createPopupPreview(vim.buffers[buf_number].name, buf_number, 0) + jump_cmd = 'normal! g`"' + self._createPopupPreview(vim.buffers[buf_number].name, buf_number, 0, jump_cmd) #***************************************************** diff --git a/autoload/leaderf/python/leaderf/fileExpl.py b/autoload/leaderf/python/leaderf/fileExpl.py index 3930e9d2..a5e48bc2 100644 --- a/autoload/leaderf/python/leaderf/fileExpl.py +++ b/autoload/leaderf/python/leaderf/fileExpl.py @@ -842,7 +842,9 @@ def _previewInPopup(self, *args, **kwargs): source = int(lfEval("bufadd('%s')" % escQuote(line))) else: source = line - self._createPopupPreview(line, source, 0) + + jump_cmd = 'normal! g`"' + self._createPopupPreview(line, source, 0, jump_cmd) @removeDevIcons def _acceptSelection(self, *args, **kwargs): diff --git a/autoload/leaderf/python/leaderf/mruExpl.py b/autoload/leaderf/python/leaderf/mruExpl.py index ca10d10d..f4ba5622 100644 --- a/autoload/leaderf/python/leaderf/mruExpl.py +++ b/autoload/leaderf/python/leaderf/mruExpl.py @@ -387,7 +387,9 @@ def _previewInPopup(self, *args, **kwargs): source = int(lfEval("bufadd('%s')" % escQuote(file))) else: source = file - self._createPopupPreview(file, source, 0) + + jump_cmd = 'normal! g`"' + self._createPopupPreview(file, source, 0, jump_cmd) #***************************************************** From 36ae13482afb69ceb092974351cdeef823e4f83c Mon Sep 17 00:00:00 2001 From: Ishan Date: Mon, 18 Nov 2024 09:35:35 +0800 Subject: [PATCH 305/365] fix: variable g:Lf_pI not defined when switch normal mode to insert mode in LeaderfCommand (#1105) --- autoload/leaderf/Command.vim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autoload/leaderf/Command.vim b/autoload/leaderf/Command.vim index ab5007ab..9e25eb49 100644 --- a/autoload/leaderf/Command.vim +++ b/autoload/leaderf/Command.vim @@ -19,7 +19,7 @@ function! leaderf#Command#Maps() nnoremap o :exec g:Lf_py "commandExplManager.accept()" nnoremap <2-LeftMouse> :exec g:Lf_py "commandExplManager.accept()" nnoremap q :exec g:Lf_py "commandExplManager.quit()" - nnoremap :exec g:Lf_pI "commandExplManager.input()" + nnoremap :exec g:Lf_py "commandExplManager.input()" nnoremap e :exec g:Lf_py "commandExplManager.editCommand()" nnoremap :exec g:Lf_py "commandExplManager.toggleHelp()" if has_key(g:Lf_NormalMap, "Command") From 26ed56df8c4f89a23727232bc52fd8fc41ec9c98 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Mon, 18 Nov 2024 16:55:27 +0800 Subject: [PATCH 306/365] fix a bug that statusline disappears sometimes --- autoload/leaderf/python/leaderf/instance.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/autoload/leaderf/python/leaderf/instance.py b/autoload/leaderf/python/leaderf/instance.py index e7a6d0a7..9fe9996f 100644 --- a/autoload/leaderf/python/leaderf/instance.py +++ b/autoload/leaderf/python/leaderf/instance.py @@ -444,6 +444,7 @@ def enlargePopupWindow(self): .format(self._popup_instance.statusline_win.id, width)) self._cli.buildPopupPrompt() + self.refreshPopupStatusline() def shrinkPopupWindow(self): preview_pos = self._arguments.get("--preview-position", [""])[0] @@ -478,6 +479,7 @@ def shrinkPopupWindow(self): .format(self._popup_instance.statusline_win.id, self._initial_maxwidth)) self._cli.buildPopupPrompt() + self.refreshPopupStatusline() def _createPopupWindow(self): preview_pos = self._arguments.get("--preview-position", [""])[0] From 1116c71e3290560a6f98fa336adf39d9bba7a997 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 28 Nov 2024 14:27:18 +0800 Subject: [PATCH 307/365] fix a bug --- autoload/leaderf/Any.vim | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/autoload/leaderf/Any.vim b/autoload/leaderf/Any.vim index ce60dc45..efccf119 100644 --- a/autoload/leaderf/Any.vim +++ b/autoload/leaderf/Any.vim @@ -28,12 +28,12 @@ function! leaderf#Any#Maps(category) nnoremap :exec g:Lf_py b:Lf_AnyExplManager."input()" nnoremap :exec g:Lf_py b:Lf_AnyExplManager."toggleHelp()" nnoremap p :exec g:Lf_py b:Lf_AnyExplManager."_previewResult(True)" - nnoremap j :exec g:Lf_py b:Lf_AnyExplManager.moveAndPreview('j')" - nnoremap k :exec g:Lf_py b:Lf_AnyExplManager.moveAndPreview('k')" - nnoremap :exec g:Lf_py b:Lf_AnyExplManager.moveAndPreview('Up')" - nnoremap :exec g:Lf_py b:Lf_AnyExplManager.moveAndPreview('Down')" - nnoremap :exec g:Lf_py b:Lf_AnyExplManager.moveAndPreview('PageUp')" - nnoremap :exec g:Lf_py b:Lf_AnyExplManager.moveAndPreview('PageDown')" + nnoremap j :exec g:Lf_py b:Lf_AnyExplManager."moveAndPreview('j')" + nnoremap k :exec g:Lf_py b:Lf_AnyExplManager."moveAndPreview('k')" + nnoremap :exec g:Lf_py b:Lf_AnyExplManager."moveAndPreview('Up')" + nnoremap :exec g:Lf_py b:Lf_AnyExplManager."moveAndPreview('Down')" + nnoremap :exec g:Lf_py b:Lf_AnyExplManager."moveAndPreview('PageUp')" + nnoremap :exec g:Lf_py b:Lf_AnyExplManager."moveAndPreview('PageDown')" nnoremap :exec g:Lf_py b:Lf_AnyExplManager."_toUpInPopup()" nnoremap :exec g:Lf_py b:Lf_AnyExplManager."_toDownInPopup()" nnoremap :exec g:Lf_py b:Lf_AnyExplManager."closePreviewPopupOrQuit()" From 25edf5fef735a26cbdf167d304fb8a1adf2832d0 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 2 Jan 2025 14:59:20 +0800 Subject: [PATCH 308/365] use os.sep --- autoload/leaderf/python/leaderf/gitExpl.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 84ac6219..34162bf8 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -1187,7 +1187,7 @@ def __init__(self, owner, cmd, project_root, target_path, callback): ' Ignore Whitespace 🗷 ', ' Myers ◉ Minimal ○ Patience ○ Histogram ○', '', - self._project_root + "/", + self._project_root + os.sep, ] self._match_ids = [] From 4d798879b6f1a8914a269c413ac3d920b381e94b Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 16 Jan 2025 11:07:42 +0800 Subject: [PATCH 309/365] fix a bug on Windows --- autoload/leaderf/python/leaderf/gitExpl.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 34162bf8..c28e90dd 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -343,7 +343,7 @@ def buildCommandAndBufferName(self): if self._source[0].startswith("0000000"): if self._source[1] == "M": if os.name == 'nt': - self._cmd = "type {}".format(self._source[2]) + self._cmd = "type {}".format(os.path.normpath(self._source[2])) else: self._cmd = "cat {}".format(self._source[2]) else: @@ -1246,7 +1246,7 @@ def enableColor(self, winid): .format(winid)) id = int(lfEval("matchid")) self._match_ids.append(id) - lfCmd(r"""call win_execute({}, 'let matchid = matchadd(''Lf_hl_gitFolder'', ''\S*/'', -100)')""" + lfCmd(r"""call win_execute({}, 'let matchid = matchadd(''Lf_hl_gitFolder'', ''\S*[/\\]'', -100)')""" .format(winid)) id = int(lfEval("matchid")) self._match_ids.append(id) From f50ee8414783c23c3b1bc23e4cb695fafc492829 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 16 Jan 2025 15:27:30 +0800 Subject: [PATCH 310/365] fix a bug on Windows --- autoload/leaderf/python/leaderf/gitExpl.py | 4 +++- autoload/leaderf/python/leaderf/utils.py | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index c28e90dd..3d404714 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -10,6 +10,7 @@ import bisect import tempfile import itertools +from pathlib import PurePath from difflib import SequenceMatcher from itertools import islice from functools import partial @@ -1686,7 +1687,8 @@ def inFileStructure(self, path): def locateFile(self, path): with self._lock: - self._locateFile(lfRelpath(path)) + path = PurePath(lfRelpath(path)) + self._locateFile(path.as_posix()) @staticmethod def getDirName(path): diff --git a/autoload/leaderf/python/leaderf/utils.py b/autoload/leaderf/python/leaderf/utils.py index 4a563ba2..d7df204a 100644 --- a/autoload/leaderf/python/leaderf/utils.py +++ b/autoload/leaderf/python/leaderf/utils.py @@ -166,7 +166,7 @@ def lfWinId(winnr, tab=None): def lfPrintError(error): if lfEval("get(g:, 'Lf_Exception', 0)") == '1': - raise error + raise Exception(error) else: error = lfEncode(str(repr(error))) lfCmd("echohl Error | redraw | echo '%s' | echohl None" % escQuote(error)) From e0534f35eb1c597bd6a142ccc656c991698681a3 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 16 Jan 2025 17:39:19 +0800 Subject: [PATCH 311/365] AttributeError: 'NoneType' object has no attribute 'poll' --- autoload/leaderf/python/leaderf/asyncExecutor.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/autoload/leaderf/python/leaderf/asyncExecutor.py b/autoload/leaderf/python/leaderf/asyncExecutor.py index 160fe8bb..767301dd 100644 --- a/autoload/leaderf/python/leaderf/asyncExecutor.py +++ b/autoload/leaderf/python/leaderf/asyncExecutor.py @@ -118,6 +118,8 @@ def read(source): self._process.poll() except IOError: pass + except AttributeError: + pass if cleanup: cleanup() @@ -166,6 +168,8 @@ def read(source): self._process.poll() except IOError: pass + except AttributeError: + pass if cleanup: cleanup() From 079335f423b910cb145609c36c12d0b87a88a720 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 16 Jan 2025 18:07:36 +0800 Subject: [PATCH 312/365] fix a bug when using `Leaderf git log --graph` --- autoload/leaderf/python/leaderf/gitExpl.py | 30 +++++++++++----------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 3d404714..7afda953 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -3659,10 +3659,10 @@ def _getExplorer(self): return self._explorer def _getDigest(self, line, mode): - return line.lstrip(r"*\|/ ") + return line.lstrip(r"*\|_/ ") def _getDigestStartPos(self, line, mode): - return len(line) - len(line.lstrip(r"*\|/ ")) + return len(line) - len(line.lstrip(r"*\|_/ ")) def afterBufhidden(self): if self._diff_view_panel.isAllHidden(): @@ -3672,7 +3672,7 @@ def getSource(self, line): """ return the hash """ - line = line.lstrip(r"*\|/ ") + line = line.lstrip(r"*\|_/ ") if line == '': return None @@ -3756,38 +3756,38 @@ def _afterEnter(self): lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_gitGraph1'', ''^|'')')""" % self._getInstance().getPopupWinId()) id = int(lfEval("matchid")) - lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_gitGraph2'', ''^[*\|/ ]\{2}\zs|'')')""" + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_gitGraph2'', ''^[*\|_/ ]\{2}\zs|'')')""" % self._getInstance().getPopupWinId()) id = int(lfEval("matchid")) - lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_gitGraph3'', ''^[*\|/ ]\{4}\zs|'')')""" + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_gitGraph3'', ''^[*\|_/ ]\{4}\zs|'')')""" % self._getInstance().getPopupWinId()) id = int(lfEval("matchid")) - lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_gitGraph4'', ''\(^[*\|/ ]\{6,}\)\@<=|'')')""" + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_gitGraph4'', ''\(^[*\|_/ ]\{6,}\)\@<=|'')')""" % self._getInstance().getPopupWinId()) id = int(lfEval("matchid")) - lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_gitGraphSlash'', ''\(^[*\|/ ]\{-}\)\@<=[\/]'')')""" + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_gitGraphSlash'', ''\(^[*\|_/ ]\{-}\)\@<=[\/]'')')""" % self._getInstance().getPopupWinId()) id = int(lfEval("matchid")) - lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_gitHash'', ''\(^[*\|/ ]*\)\@<=[0-9A-Fa-f]\+'')')""" + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_gitHash'', ''\(^[*\|_/ ]*\)\@<=[0-9A-Fa-f]\+'')')""" % self._getInstance().getPopupWinId()) id = int(lfEval("matchid")) - lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_gitRefNames'', ''^[*\|/ ]*[0-9A-Fa-f]\+\s*\zs(.\{-})'')')""" + lfCmd(r"""call win_execute(%d, 'let matchid = matchadd(''Lf_hl_gitRefNames'', ''^[*\|_/ ]*[0-9A-Fa-f]\+\s*\zs(.\{-})'')')""" % self._getInstance().getPopupWinId()) id = int(lfEval("matchid")) else: id = int(lfEval(r'''matchadd('Lf_hl_gitGraph1', '^|')''')) self._match_ids.append(id) - id = int(lfEval(r'''matchadd('Lf_hl_gitGraph2', '^[*\|/ ]\{2}\zs|')''')) + id = int(lfEval(r'''matchadd('Lf_hl_gitGraph2', '^[*\|_/ ]\{2}\zs|')''')) self._match_ids.append(id) - id = int(lfEval(r'''matchadd('Lf_hl_gitGraph3', '^[*\|/ ]\{4}\zs|')''')) + id = int(lfEval(r'''matchadd('Lf_hl_gitGraph3', '^[*\|_/ ]\{4}\zs|')''')) self._match_ids.append(id) - id = int(lfEval(r'''matchadd('Lf_hl_gitGraph4', '\(^[*\|/ ]\{6,}\)\@<=|')''')) + id = int(lfEval(r'''matchadd('Lf_hl_gitGraph4', '\(^[*\|_/ ]\{6,}\)\@<=|')''')) self._match_ids.append(id) - id = int(lfEval(r'''matchadd('Lf_hl_gitGraphSlash', '\(^[*\|/ ]\{-}\)\@<=[\/]')''')) + id = int(lfEval(r'''matchadd('Lf_hl_gitGraphSlash', '\(^[*\|_/ ]\{-}\)\@<=[\/]')''')) self._match_ids.append(id) - id = int(lfEval(r'''matchadd('Lf_hl_gitHash', '\(^[*\|/ ]*\)\@<=[0-9A-Fa-f]\+')''')) + id = int(lfEval(r'''matchadd('Lf_hl_gitHash', '\(^[*\|_/ ]*\)\@<=[0-9A-Fa-f]\+')''')) self._match_ids.append(id) - id = int(lfEval(r'''matchadd('Lf_hl_gitRefNames', '^[*\|/ ]*[0-9A-Fa-f]\+\s*\zs(.\{-})')''')) + id = int(lfEval(r'''matchadd('Lf_hl_gitRefNames', '^[*\|_/ ]*[0-9A-Fa-f]\+\s*\zs(.\{-})')''')) self._match_ids.append(id) def _accept(self, file, mode, *args, **kwargs): From d22212121314495517f5e319c72126986682fe79 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Fri, 17 Jan 2025 10:10:24 +0800 Subject: [PATCH 313/365] change the default value of g:Lf_GitHightlightLineNumber to 1 --- autoload/leaderf/Git.vim | 2 +- autoload/leaderf/python/leaderf/gitExpl.py | 2 +- doc/leaderf.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/autoload/leaderf/Git.vim b/autoload/leaderf/Git.vim index 97270b3e..aeb006d4 100644 --- a/autoload/leaderf/Git.vim +++ b/autoload/leaderf/Git.vim @@ -617,7 +617,7 @@ function! leaderf#Git#SetLineNumberWin(line_num_content, buffer_num) abort let line = a:line_num_content[0] let line_len = strlen(line) - let hi_line_num = get(g:, 'Lf_GitHightlightLineNumber', 0) + let hi_line_num = get(g:, 'Lf_GitHightlightLineNumber', 1) let delimiter = get(g:, 'Lf_GitDelimiter', '│') let delimiter_len = len(delimiter) let ns_id = nvim_create_namespace('LeaderF') diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 7afda953..e013f2f6 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -2339,7 +2339,7 @@ def setLineNumberWin(self, line_num_content, buffer_num): self.nvim_setLineNumberWin(line_num_content, buffer_num) return - hi_line_num = int(lfEval("get(g:, 'Lf_GitHightlightLineNumber', 0)")) + hi_line_num = int(lfEval("get(g:, 'Lf_GitHightlightLineNumber', 1)")) for i, line in enumerate(line_num_content, 1): if line[-2] == '-': if hi_line_num == 1: diff --git a/doc/leaderf.txt b/doc/leaderf.txt index 1e8df0b4..ccac3c93 100644 --- a/doc/leaderf.txt +++ b/doc/leaderf.txt @@ -1183,7 +1183,7 @@ g:Lf_GitHightlightLineNumber *g:Lf_GitHightlightLineNumber* Specify whether to highlight the line number when diff view is in 'unified' mode. If enabled, the line numbers of changed lines are also highlighted with 'DiffAdd' or 'DiffDelete'. - Default value is 0. + Default value is 1. g:Lf_GitWorkingDirectoryMode *g:Lf_GitWorkingDirectoryMode* Specify the working directory when launch Leaderf git command. The value From 40e2fa5853a616d70a2d66756b35a023574d8a95 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Fri, 17 Jan 2025 10:19:19 +0800 Subject: [PATCH 314/365] change the default value of g:Lf_GitDiffViewMode to 'unified' --- autoload/leaderf/python/leaderf/gitExpl.py | 2 +- doc/leaderf.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index e013f2f6..8cae552c 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -3039,7 +3039,7 @@ def create(self, arguments_dict, cmd, target_path=None, line_num=None): elif "-s" in arguments_dict: self._diff_view_mode = "side-by-side" else: - self._diff_view_mode = lfEval("get(g:, 'Lf_GitDiffViewMode', 'side-by-side')") + self._diff_view_mode = lfEval("get(g:, 'Lf_GitDiffViewMode', 'unified')") callback = partial(self.getDiffViewPanel().create, arguments_dict, diff --git a/doc/leaderf.txt b/doc/leaderf.txt index ccac3c93..e2695906 100644 --- a/doc/leaderf.txt +++ b/doc/leaderf.txt @@ -1177,7 +1177,7 @@ g:Lf_GitContextNum *g:Lf_GitContextNum* g:Lf_GitDiffViewMode *g:Lf_GitDiffViewMode* Show diffs in a side by side view or in a unified view. Value can be: 'side-by-side' or 'unified'. - Default value is 'side-by-side'. + Default value is 'unified'. g:Lf_GitHightlightLineNumber *g:Lf_GitHightlightLineNumber* Specify whether to highlight the line number when diff view is in From d9acacdc4e1391736ac1fdd870b03858d6c83e3c Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Fri, 17 Jan 2025 11:05:53 +0800 Subject: [PATCH 315/365] fix a bug on Windows --- autoload/leaderf/python/leaderf/gitExpl.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 8cae552c..8d09c889 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -3553,7 +3553,7 @@ def startExplorer(self, win_pos, *args, **kwargs): file_name = vim.current.buffer.name if " " in file_name: file_name = file_name.replace(' ', r'\ ') - self._arguments["current_file"] = lfRelpath(file_name) + self._arguments["current_file"] = PurePath(lfRelpath(file_name)).as_posix() if "-s" in self._arguments: self.vsplitDiff() else: From 1b907fbf7717ae1244745b8ffa2b604510e713c7 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Fri, 17 Jan 2025 15:30:22 +0800 Subject: [PATCH 316/365] use posix path style --- autoload/leaderf/python/leaderf/gitExpl.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 8d09c889..1c51ede8 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -473,7 +473,7 @@ def buildCommandAndBufferName(self): file_name = vim.current.buffer.name if " " in file_name: file_name = file_name.replace(' ', r'\ ') - file_name = lfRelpath(file_name) + file_name = PurePath(lfRelpath(file_name)).as_posix() self._cmd = GitBlameCommand.buildCommand(self._arguments, commit_id, file_name, True) self._buffer_name = "LeaderF://git blame {} {}".format(commit_id, file_name) @@ -1687,8 +1687,7 @@ def inFileStructure(self, path): def locateFile(self, path): with self._lock: - path = PurePath(lfRelpath(path)) - self._locateFile(path.as_posix()) + self._locateFile(PurePath(lfRelpath(path)).as_posix()) @staticmethod def getDirName(path): @@ -1769,8 +1768,8 @@ def buildLine(self, meta_info): orig_name = "" if meta_info.info[2][0] in ("R", "C"): - orig_name = "{} => ".format(lfRelpath(meta_info.info[3], - os.path.dirname(meta_info.info[4]))) + orig_name = "{} => ".format(PurePath(lfRelpath(meta_info.info[3], + os.path.dirname(meta_info.info[4]))).as_posix()) return "{}{} {}{}\t{}".format(" " * meta_info.level, icon, @@ -3729,7 +3728,7 @@ def startExplorer(self, win_pos, *args, **kwargs): file_name = vim.current.buffer.name if " " in file_name: file_name = file_name.replace(' ', r'\ ') - self._arguments["current_file"] = lfRelpath(file_name) + self._arguments["current_file"] = PurePath(lfRelpath(file_name)).as_posix() self._arguments["orig_name"] = self._getExplorer().orig_name elif ("--current-line" in arguments_dict and vim.current.buffer.name @@ -3738,7 +3737,7 @@ def startExplorer(self, win_pos, *args, **kwargs): file_name = vim.current.buffer.name if " " in file_name: file_name = file_name.replace(' ', r'\ ') - self._arguments["current_file"] = lfRelpath(file_name) + self._arguments["current_file"] = PurePath(lfRelpath(file_name)).as_posix() self._arguments["current_line_num"] = vim.current.window.cursor[0] if "--recall" in arguments_dict: From ac173ac726d50cd45c9d832010b991e2ba37e231 Mon Sep 17 00:00:00 2001 From: lsq Date: Mon, 20 Jan 2025 10:15:01 +0800 Subject: [PATCH 317/365] support MSYS python enviroment (#1112) Co-authored-by: lsq --- autoload/leaderf/fuzzyMatch_C/setup.py | 3 ++- install.bat | 18 ++++++++++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/autoload/leaderf/fuzzyMatch_C/setup.py b/autoload/leaderf/fuzzyMatch_C/setup.py index bbd07fd1..9521903c 100644 --- a/autoload/leaderf/fuzzyMatch_C/setup.py +++ b/autoload/leaderf/fuzzyMatch_C/setup.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- import os +import platform try: from setuptools import setup @@ -8,7 +9,7 @@ from distutils.core import setup from distutils.extension import Extension -if os.name == 'nt': +if os.name == 'nt' and ("MSC" in platform.python_compiler()): from distutils.msvccompiler import get_build_version if get_build_version() < 14.0: # Visual Studio 2015 diff --git a/install.bat b/install.bat index 35af7c8f..1f19866c 100644 --- a/install.bat +++ b/install.bat @@ -1,4 +1,9 @@ @echo off +set pyFlag=0 +where /Q py +if %ERRORLEVEL% NEQ 0 set pyFlag=1 +echo pyFlag=%pyFlag% + if /i "%1" equ "--reverse" ( cd autoload\leaderf\fuzzyMatch_C rd /s /q build @@ -11,7 +16,12 @@ if /i "%1" equ "--reverse" ( ) echo Begin to compile C extension of Python2 ... cd autoload\leaderf\fuzzyMatch_C -py -2 setup.py build --build-lib ..\python + +if %pyFlag% EQU 0 ( + py -2 setup.py build --build-lib ..\python +) else ( + python2 setup.py build --build-lib ..\python +) if %errorlevel% equ 0 ( echo= echo =============================================== @@ -21,7 +31,11 @@ if %errorlevel% equ 0 ( echo= echo Begin to compile C extension of Python3 ... -py -3 setup.py build --build-lib ..\python +if %pyFlag% EQU 0 ( + py -3 setup.py build --build-lib ..\python +) else ( + python3 setup.py build --build-lib ..\python +) if %errorlevel% equ 0 ( echo= echo =============================================== From 399c5af43755a9c09f840d892921186514171d87 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Mon, 20 Jan 2025 11:12:03 +0800 Subject: [PATCH 318/365] update setup.py --- autoload/leaderf/fuzzyMatch_C/setup.py | 73 ++++++++++++-------------- 1 file changed, 34 insertions(+), 39 deletions(-) diff --git a/autoload/leaderf/fuzzyMatch_C/setup.py b/autoload/leaderf/fuzzyMatch_C/setup.py index 9521903c..8cf22ddc 100644 --- a/autoload/leaderf/fuzzyMatch_C/setup.py +++ b/autoload/leaderf/fuzzyMatch_C/setup.py @@ -1,42 +1,37 @@ # -*- coding: utf-8 -*- import os import platform - -try: - from setuptools import setup - from setuptools import Extension -except ImportError: - from distutils.core import setup - from distutils.extension import Extension - -if os.name == 'nt' and ("MSC" in platform.python_compiler()): - from distutils.msvccompiler import get_build_version - - if get_build_version() < 14.0: # Visual Studio 2015 - if get_build_version() >= 8.0: - from distutils.msvc9compiler import MSVCCompiler - else: - from distutils.msvccompiler import MSVCCompiler - - # Because the msvc compiler does not support c99, - # treat .c files as .cpp files - MSVCCompiler._c_extensions = [] - MSVCCompiler._cpp_extensions = ['.c', '.cc', '.cpp', '.cxx'] - - -module1 = Extension("fuzzyMatchC", - sources = ["fuzzyMatch.c"]) - -module2 = Extension("fuzzyEngine", - sources = ["fuzzyMatch.c", "fuzzyEngine.c"]) - - -setup(name = "fuzzyEngine", - version = "2.0", - description = "fuzzy match algorithm written in C.", - author = "Yggdroot", - author_email = "archofortune@gmail.com", - url = "https://github.com/Yggdroot/LeaderF", - license = "Apache License 2.0", - ext_modules = [module1, module2] - ) +from setuptools import setup, Extension +from setuptools.command.build_ext import build_ext + +class BuildExt(build_ext): + def build_extensions(self): + if os.name == 'nt' and "MSC" in platform.python_compiler(): + for ext in self.extensions: + ext.extra_compile_args = ['/TP'] + elif os.name == 'posix': + for ext in self.extensions: + ext.extra_compile_args = ['-std=c99', '-O2'] + build_ext.build_extensions(self) + +module1 = Extension( + "fuzzyMatchC", + sources=["fuzzyMatch.c"], +) + +module2 = Extension( + "fuzzyEngine", + sources=["fuzzyMatch.c", "fuzzyEngine.c"], +) + +setup( + name="fuzzyEngine", + version="2.0", + description="Fuzzy match algorithm written in C.", + author="Yggdroot", + author_email="archofortune@gmail.com", + url="https://github.com/Yggdroot/LeaderF", + license="Apache License 2.0", + ext_modules=[module1, module2], + cmdclass={"build_ext": BuildExt}, +) From 8384c090c774727140452f5053e47d3683cdcc0b Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Tue, 4 Feb 2025 19:26:23 +0800 Subject: [PATCH 319/365] deprecate g:Lf_CursorBlink --- autoload/leaderf/python/leaderf/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autoload/leaderf/python/leaderf/cli.py b/autoload/leaderf/python/leaderf/cli.py index 5e5da156..fc7c3219 100644 --- a/autoload/leaderf/python/leaderf/cli.py +++ b/autoload/leaderf/python/leaderf/cli.py @@ -344,7 +344,7 @@ def _buildPrompt(self): else: lfCmd("hi! default link Lf_hl_cursor NONE") - if lfEval("g:Lf_CursorBlink") == '1': + if lfEval("g:Lf_CursorBlink") == '1' and 0: self._blinkon = not self._blinkon elif self._idle: lfCmd("silent! redraw") From d1d698e74bfb46abecaa5191e0c9ad3433d132f8 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 5 Feb 2025 14:27:27 +0800 Subject: [PATCH 320/365] fix issue #1113 --- autoload/leaderf/python/leaderf/manager.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 60f88448..7ed84f31 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -60,7 +60,10 @@ def modifiableController(func): def deco(self, *args, **kwargs): self._getInstance().buffer.options['modifiable'] = True func(self, *args, **kwargs) - self._getInstance().buffer.options['modifiable'] = False + try: + self._getInstance().buffer.options['modifiable'] = False + except: + pass return deco def catchException(func): From 4b942e5177775d6a13c133a6884139666a1ec72b Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 5 Feb 2025 17:02:26 +0800 Subject: [PATCH 321/365] fix a bug --- autoload/leaderf.vim | 14 ++++++++++---- autoload/leaderf/python/leaderf/manager.py | 1 + 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/autoload/leaderf.vim b/autoload/leaderf.vim index 68613d67..88927da5 100644 --- a/autoload/leaderf.vim +++ b/autoload/leaderf.vim @@ -610,6 +610,7 @@ function! leaderf#PopupClosed(id_list, manager_id, winid, result) abort " result is -1 if CTRL-C was pressed, if a:result == -1 exec g:Lf_py "import ctypes" + exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value.is_ctrl_c = True", a:manager_id) exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value.quit()", a:manager_id) for id in a:id_list if id != a:winid @@ -620,10 +621,15 @@ function! leaderf#PopupClosed(id_list, manager_id, winid, result) abort endfunction function! leaderf#Quit(manager_id) abort - exec g:Lf_py "import ctypes" - exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value.is_autocmd = True", a:manager_id) - exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value.quit()", a:manager_id) - exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value.is_autocmd = False", a:manager_id) +exec g:Lf_py "<< EOF" +import ctypes +manager = ctypes.cast(int(vim.eval("a:manager_id")), ctypes.py_object).value +if manager.is_ctrl_c == False: + manager.is_autocmd = True + manager.quit() + manager.is_autocmd = False +manager.is_ctrl_c = False +EOF endfunction function! leaderf#ResetPopupOptions(winid, option, value) abort diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 7ed84f31..7d3a34f5 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -135,6 +135,7 @@ def __init__(self): self._orig_source = None self._preview_config = {} self.is_autocmd = False + self.is_ctrl_c = False self._circular_scroll = lfEval("get(g:, 'Lf_EnableCircularScroll', 0)") == '1' if lfEval("has('patch-8.1.1615') || has('nvim-0.5.0')") == '0': lfCmd("let g:Lf_PreviewInPopup = 0") From 5fec453720246f85ba5238a6f14a3649b8b41573 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 6 Feb 2025 10:26:43 +0800 Subject: [PATCH 322/365] sometimes preview window is not open --- autoload/leaderf/python/leaderf/manager.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 7d3a34f5..0e48efae 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -3017,8 +3017,8 @@ def _workInIdle(self, content=None, bang=False): self._getInstance().setStlResultsCount(len(self._content)) - if not self.isPreviewWindowOpen(): - self._previewResult(False) + if not self.isPreviewWindowOpen(): + self._previewResult(False) if self._getInstance().getWinPos() not in ('popup', 'floatwin'): lfCmd("redrawstatus") From fcdb0222c3ecad1344a7262155a5eb8f9db3d94f Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 19 Feb 2025 17:39:03 +0800 Subject: [PATCH 323/365] use __builtin_ctzll() --- autoload/leaderf/fuzzyMatch_C/fuzzyMatch.c | 51 +++++++++++++++------- 1 file changed, 35 insertions(+), 16 deletions(-) diff --git a/autoload/leaderf/fuzzyMatch_C/fuzzyMatch.c b/autoload/leaderf/fuzzyMatch_C/fuzzyMatch.c index cc193541..fbba3cfb 100644 --- a/autoload/leaderf/fuzzyMatch_C/fuzzyMatch.c +++ b/autoload/leaderf/fuzzyMatch_C/fuzzyMatch.c @@ -37,6 +37,7 @@ #if defined(_M_AMD64) || defined(_M_X64) #define FM_BITSCAN_WINDOWS64 #pragma intrinsic(_BitScanReverse64) + #pragma intrinsic(_BitScanForward64) #endif #endif @@ -47,10 +48,10 @@ { unsigned long index; #if defined(FM_BITSCAN_WINDOWS64) - if ( !_BitScanReverse64(&index, x) ) - return 0; - else + if ( _BitScanReverse64(&index, x) ) return index + 1; + else + return 0; #else if ( (x & 0xFFFFFFFF00000000) == 0 ) { @@ -69,14 +70,28 @@ #define FM_BIT_LENGTH(x) FM_BitLength(x) + #if defined(FM_BITSCAN_WINDOWS64) + + uint16_t FM_ctz(uint64_t x) { + unsigned long index; + if (_BitScanForward64(&index, x)) { + return (uint16_t)index; + } + return 64; + } + #define FM_CTZ(x) FM_ctz(x) + + #endif #elif defined(__GNUC__) #define FM_BIT_LENGTH(x) ((uint32_t)(8 * sizeof(unsigned long long) - __builtin_clzll(x))) + #define FM_CTZ(x) __builtin_ctzll(x) #elif defined(__clang__) #if __has_builtin(__builtin_clzll) #define FM_BIT_LENGTH(x) ((uint32_t)(8 * sizeof(unsigned long long) - __builtin_clzll(x))) + #define FM_CTZ(x) __builtin_ctzll(x) #endif #endif @@ -116,21 +131,25 @@ #endif -static uint64_t deBruijn = 0x022FDD63CC95386D; +#if !defined(FM_CTZ) -static uint8_t MultiplyDeBruijnBitPosition[64] = -{ - 0, 1, 2, 53, 3, 7, 54, 27, - 4, 38, 41, 8, 34, 55, 48, 28, - 62, 5, 39, 46, 44, 42, 22, 9, - 24, 35, 59, 56, 49, 18, 29, 11, - 63, 52, 6, 26, 37, 40, 33, 47, - 61, 45, 43, 21, 23, 58, 17, 10, - 51, 25, 36, 32, 60, 20, 57, 16, - 50, 31, 19, 15, 30, 14, 13, 12, -}; + static uint64_t deBruijn = 0x022FDD63CC95386D; + + static uint8_t MultiplyDeBruijnBitPosition[64] = + { + 0, 1, 2, 53, 3, 7, 54, 27, + 4, 38, 41, 8, 34, 55, 48, 28, + 62, 5, 39, 46, 44, 42, 22, 9, + 24, 35, 59, 56, 49, 18, 29, 11, + 63, 52, 6, 26, 37, 40, 33, 47, + 61, 45, 43, 21, 23, 58, 17, 10, + 51, 25, 36, 32, 60, 20, 57, 16, + 50, 31, 19, 15, 30, 14, 13, 12, + }; -#define FM_CTZ(x) MultiplyDeBruijnBitPosition[((uint64_t)((x) & -(int64_t)(x)) * deBruijn) >> 58] + #define FM_CTZ(x) MultiplyDeBruijnBitPosition[((uint64_t)((x) & -(int64_t)(x)) * deBruijn) >> 58] + +#endif static uint16_t valTable[64] = { From 1c0ce2ccf8f0728bc62540cab2d23f449f1e1117 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 19 Feb 2025 17:47:45 +0800 Subject: [PATCH 324/365] format code --- autoload/leaderf/fuzzyMatch_C/fuzzyMatch.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/autoload/leaderf/fuzzyMatch_C/fuzzyMatch.c b/autoload/leaderf/fuzzyMatch_C/fuzzyMatch.c index fbba3cfb..ae4889d6 100644 --- a/autoload/leaderf/fuzzyMatch_C/fuzzyMatch.c +++ b/autoload/leaderf/fuzzyMatch_C/fuzzyMatch.c @@ -72,14 +72,14 @@ #if defined(FM_BITSCAN_WINDOWS64) - uint16_t FM_ctz(uint64_t x) { - unsigned long index; - if (_BitScanForward64(&index, x)) { - return (uint16_t)index; + uint16_t FM_ctz(uint64_t x) { + unsigned long index; + if (_BitScanForward64(&index, x)) { + return (uint16_t)index; + } + return 64; } - return 64; - } - #define FM_CTZ(x) FM_ctz(x) + #define FM_CTZ(x) FM_ctz(x) #endif #elif defined(__GNUC__) From 2f49b88c967f23f846ff12d215fb7e4d65d1d840 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 19 Feb 2025 20:31:45 +0800 Subject: [PATCH 325/365] fix issue "error: command 'gcc-11' failed: No such file or directory" --- install.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/install.sh b/install.sh index 010d8db0..f240ce64 100755 --- a/install.sh +++ b/install.sh @@ -15,6 +15,12 @@ no_python=true cd autoload/leaderf/fuzzyMatch_C +if command -v gcc > /dev/null 2>&1; then + export CC=gcc +elif command -v clang > /dev/null 2>&1; then + export CC=clang +fi + if command -v python2 > /dev/null 2>&1; then no_python=false echo "Begin to compile C extension of Python2 ..." From 5488f63e7c608d8d0074f6d079a08785c5fbb872 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 19 Feb 2025 22:25:48 +0800 Subject: [PATCH 326/365] ModuleNotFoundError: No module named 'setuptools' --- install.bat | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/install.bat b/install.bat index 1f19866c..e73f5f31 100644 --- a/install.bat +++ b/install.bat @@ -18,9 +18,11 @@ echo Begin to compile C extension of Python2 ... cd autoload\leaderf\fuzzyMatch_C if %pyFlag% EQU 0 ( - py -2 setup.py build --build-lib ..\python + py -2 -m pip install setuptools + py -2 setup.py build --build-lib ..\python ) else ( - python2 setup.py build --build-lib ..\python + python2 -m pip install setuptools + python2 setup.py build --build-lib ..\python ) if %errorlevel% equ 0 ( echo= @@ -32,9 +34,11 @@ if %errorlevel% equ 0 ( echo= echo Begin to compile C extension of Python3 ... if %pyFlag% EQU 0 ( - py -3 setup.py build --build-lib ..\python + py -3 -m pip install setuptools + py -3 setup.py build --build-lib ..\python ) else ( - python3 setup.py build --build-lib ..\python + python3 -m pip install setuptools + python3 setup.py build --build-lib ..\python ) if %errorlevel% equ 0 ( echo= From 2b73430dd34a5c94c0173fb8b9b25dd12a327488 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Sat, 22 Feb 2025 17:53:29 +0800 Subject: [PATCH 327/365] try to install setuptools if it is not installed --- autoload/leaderf/fuzzyMatch_C/setup.py | 21 ++++++++++++++++++--- install.bat | 8 ++------ install.sh | 4 ++-- 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/autoload/leaderf/fuzzyMatch_C/setup.py b/autoload/leaderf/fuzzyMatch_C/setup.py index 8cf22ddc..63307afb 100644 --- a/autoload/leaderf/fuzzyMatch_C/setup.py +++ b/autoload/leaderf/fuzzyMatch_C/setup.py @@ -1,8 +1,23 @@ # -*- coding: utf-8 -*- import os import platform -from setuptools import setup, Extension -from setuptools.command.build_ext import build_ext +import subprocess +import sys + +try: + from setuptools import setup, Extension + from setuptools.command.build_ext import build_ext +except ImportError: + print("\nsetuptools is not installed. Attempting to install...") + print(" ".join([sys.executable, "-m", "pip", "install", "setuptools"])) + try: + subprocess.check_call([sys.executable, "-m", "pip", "install", "setuptools"]) + from setuptools import setup, Extension + from setuptools.command.build_ext import build_ext + except Exception as e: + print("\nFailed to install setuptools: {}".format(e)) + print("Please turn to https://stackoverflow.com/questions/69919970/no-module-named-distutils-util-but-distutils-is-installed/76691103#76691103 for help") + sys.exit(1) class BuildExt(build_ext): def build_extensions(self): @@ -11,7 +26,7 @@ def build_extensions(self): ext.extra_compile_args = ['/TP'] elif os.name == 'posix': for ext in self.extensions: - ext.extra_compile_args = ['-std=c99', '-O2'] + ext.extra_compile_args = ['-std=c99', '-O3'] build_ext.build_extensions(self) module1 = Extension( diff --git a/install.bat b/install.bat index e73f5f31..bbe76843 100644 --- a/install.bat +++ b/install.bat @@ -14,14 +14,12 @@ if /i "%1" equ "--reverse" ( echo ====================================== goto end ) -echo Begin to compile C extension of Python2 ... +echo Beginning to compile C extension of Python2 ... cd autoload\leaderf\fuzzyMatch_C if %pyFlag% EQU 0 ( - py -2 -m pip install setuptools py -2 setup.py build --build-lib ..\python ) else ( - python2 -m pip install setuptools python2 setup.py build --build-lib ..\python ) if %errorlevel% equ 0 ( @@ -32,12 +30,10 @@ if %errorlevel% equ 0 ( ) echo= -echo Begin to compile C extension of Python3 ... +echo Beginning to compile C extension of Python3 ... if %pyFlag% EQU 0 ( - py -3 -m pip install setuptools py -3 setup.py build --build-lib ..\python ) else ( - python3 -m pip install setuptools python3 setup.py build --build-lib ..\python ) if %errorlevel% equ 0 ( diff --git a/install.sh b/install.sh index f240ce64..64f2e91b 100755 --- a/install.sh +++ b/install.sh @@ -23,7 +23,7 @@ fi if command -v python2 > /dev/null 2>&1; then no_python=false - echo "Begin to compile C extension of Python2 ..." + echo "Beginning to compile C extension of Python2 ..." python2 setup.py build --build-lib ../python if [ $? -eq 0 ] then @@ -38,7 +38,7 @@ if command -v python3 > /dev/null 2>&1; then $no_python || echo no_python=false - echo "Begin to compile C extension of Python3 ..." + echo "Beginning to compile C extension of Python3 ..." python3 setup.py build --build-lib ../python if [ $? -eq 0 ] then From 7aa21582fccf0b370ea4a7a601e1d528dad8f7ea Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Sat, 22 Feb 2025 20:04:32 +0800 Subject: [PATCH 328/365] remove "echo pyFlag=%pyFlag%" --- install.bat | 1 - 1 file changed, 1 deletion(-) diff --git a/install.bat b/install.bat index bbe76843..47d8f3c4 100644 --- a/install.bat +++ b/install.bat @@ -2,7 +2,6 @@ set pyFlag=0 where /Q py if %ERRORLEVEL% NEQ 0 set pyFlag=1 -echo pyFlag=%pyFlag% if /i "%1" equ "--reverse" ( cd autoload\leaderf\fuzzyMatch_C From 2c774a88527c0b9c541f2680c119736f5a2a7d0a Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Sun, 23 Feb 2025 22:46:22 +0800 Subject: [PATCH 329/365] optimize the fuzzy matching algorithm --- autoload/leaderf/fuzzyMatch_C/fuzzyEngine.cpp | 2643 +++++++++++++++++ autoload/leaderf/fuzzyMatch_C/fuzzyMatch.c | 110 +- autoload/leaderf/fuzzyMatch_C/fuzzyMatch.cpp | 2000 +++++++++++++ autoload/leaderf/fuzzyMatch_C/setup.py | 32 +- 4 files changed, 4748 insertions(+), 37 deletions(-) create mode 100644 autoload/leaderf/fuzzyMatch_C/fuzzyEngine.cpp create mode 100644 autoload/leaderf/fuzzyMatch_C/fuzzyMatch.cpp diff --git a/autoload/leaderf/fuzzyMatch_C/fuzzyEngine.cpp b/autoload/leaderf/fuzzyMatch_C/fuzzyEngine.cpp new file mode 100644 index 00000000..d21b1685 --- /dev/null +++ b/autoload/leaderf/fuzzyMatch_C/fuzzyEngine.cpp @@ -0,0 +1,2643 @@ +/** + * Copyright (C) 2018 Yggdroot + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PY_SSIZE_T_CLEAN + #define PY_SSIZE_T_CLEAN +#endif + +#include +#include +#include +#include + +#if defined(_MSC_VER) +#include +#else +#include +#endif + +#include "fuzzyEngine.h" +#include "fuzzyMatch.h" + +typedef float weight_t; + +typedef struct FeString +{ + char* str; + uint32_t len; +}FeString; + +typedef struct TaskItem +{ + uint32_t function; + uint32_t offset; + uint32_t length; +}TaskItem; + +typedef struct FeResult +{ + union + { + weight_t weight; + uint32_t path_weight; + }; + uint32_t index; +}FeResult; + +typedef struct MergeTaskItem +{ + uint32_t function; + uint32_t offset_1; + uint32_t length_1; + /* offset_2 = offset_1 + length_1, so no need to define it */ + uint32_t length_2; + /* a buffer that helps merge two list, its length is `length_2` */ + FeResult* buffer; +}MergeTaskItem; + +typedef struct PySetTaskItem +{ + uint32_t function; + uint32_t offset; + uint32_t length; + union + { + weight_t* weights; + uint32_t* path_weights; + }; + PyObject* text_list; + PyObject* py_source; +}PySetTaskItem; + +typedef struct FeCircularQueue +{ + void** buffer; + uint32_t capacity; + uint32_t head; + uint32_t tail; +#if defined(_MSC_VER) + uint32_t done_num; + uint32_t task_count; + CRITICAL_SECTION cs; + HANDLE task_sem; + HANDLE all_done_event; +#else + uint32_t unfinished_tasks; + pthread_mutex_t mutex; + pthread_cond_t not_empty_cond; + pthread_cond_t task_cond; +#endif +}FeCircularQueue; + +struct FuzzyEngine +{ + uint32_t cpu_count; +#if defined(_MSC_VER) + HANDLE* threads; +#else + pthread_t* threads; +#endif + union + { + struct + { + PatternContext* pPattern_ctxt; + uint8_t is_name_only; + }; + struct + { + const char* filename; + const char* suffix; + const char* dirname; + }; + }; + FeString* source; + union + { + FeResult* results; + HighlightGroup** highlights; + }; + FeCircularQueue task_queue; +}; + +#if defined(_MSC_VER) + +#define QUEUE_INIT(queue, queue_capacity, ret_val) \ + do { \ + (queue).buffer = (void**)calloc((queue_capacity), sizeof(void*)); \ + if ( !(queue).buffer ) \ + { \ + fprintf(stderr, "Out of memory at %s:%d\n", __FILE__, __LINE__); \ + ret_val = -1; \ + break; \ + } \ + (queue).capacity = (queue_capacity); \ + (queue).head = (queue).tail = 0; \ + (queue).done_num = 0; \ + (queue).task_count = 0; \ + InitializeCriticalSection(&(queue).cs); \ + (queue).task_sem = CreateSemaphore(NULL, 0, 2048, NULL); \ + if ( !(queue).task_sem ) \ + { \ + fprintf(stderr, "CreateSemaphore error: %d\n", GetLastError()); \ + ret_val = -1; \ + break; \ + } \ + /* auto-reset event */ \ + (queue).all_done_event = CreateEvent(NULL, FALSE, FALSE, NULL); \ + if ( !(queue).all_done_event ) \ + { \ + fprintf(stderr, "CreateEvent error: %d\n", GetLastError()); \ + ret_val = -1; \ + break; \ + } \ + } while(0) + +#define QUEUE_SET_TASK_COUNT(queue, count) \ + do { \ + EnterCriticalSection(&(queue).cs); \ + (queue).task_count = (count); \ + LeaveCriticalSection(&(queue).cs); \ + } while(0) + +#define QUEUE_DESTROY(queue) \ + do { \ + free((queue).buffer); \ + DeleteCriticalSection(&(queue).cs); \ + CloseHandle((queue).task_sem); \ + CloseHandle((queue).all_done_event); \ + } while(0) + +#define QUEUE_PUT(queue, pTask) \ + do { \ + EnterCriticalSection(&(queue).cs); \ + (queue).buffer[(queue).tail] = (void*)(pTask); \ + (queue).tail = ((queue).tail + 1) % (queue).capacity; \ + LeaveCriticalSection(&(queue).cs); \ + if ( !ReleaseSemaphore((queue).task_sem, 1, NULL) ) \ + { \ + fprintf(stderr, "ReleaseSemaphore error: %d\n", GetLastError()); \ + break; \ + } \ + } while(0) + +#define QUEUE_GET(queue, type, pTask) \ + do { \ + if ( WaitForSingleObject((queue).task_sem, INFINITE) == WAIT_FAILED ) \ + { \ + fprintf(stderr, "WaitForSingleObject error: %d\n", GetLastError()); \ + break; \ + } \ + EnterCriticalSection(&(queue).cs); \ + pTask = (type)(queue).buffer[(queue).head]; \ + (queue).head = ((queue).head + 1) % (queue).capacity; \ + LeaveCriticalSection(&(queue).cs); \ + } while(0) + +#define QUEUE_JOIN(queue) \ + do { \ + if ( WaitForSingleObject((queue).all_done_event, INFINITE) == WAIT_FAILED ) \ + { \ + fprintf(stderr, "WaitForSingleObject error: %d\n", GetLastError()); \ + break; \ + } \ + EnterCriticalSection(&(queue).cs); \ + (queue).done_num = 0; \ + (queue).task_count = 0; \ + LeaveCriticalSection(&(queue).cs); \ + } while(0) + +#define QUEUE_TASK_DONE(queue) \ + do { \ + EnterCriticalSection(&(queue).cs); \ + ++(queue).done_num; \ + if ( (queue).done_num >= (queue).task_count ) \ + SetEvent((queue).all_done_event); \ + LeaveCriticalSection(&(queue).cs); \ + } while(0) + +#else + +#define QUEUE_INIT(queue, queue_capacity, ret_val) \ + do { \ + (queue).buffer = (void**)calloc((queue_capacity), sizeof(void*)); \ + if ( !(queue).buffer ) \ + { \ + fprintf(stderr, "Out of memory at %s:%d\n", __FILE__, __LINE__); \ + ret_val = -1; \ + break; \ + } \ + (queue).capacity = (queue_capacity); \ + (queue).head = (queue).tail = 0; \ + (queue).unfinished_tasks = 0; \ + int ret; \ + ret = pthread_mutex_init(&(queue).mutex, NULL); \ + if ( ret != 0 ) \ + { \ + fprintf(stderr, "pthread_mutex_init error!\n"); \ + ret_val = -1; \ + break; \ + } \ + ret = pthread_cond_init(&(queue).not_empty_cond, NULL); \ + if ( ret != 0 ) \ + { \ + fprintf(stderr, "pthread_cond_init error!\n"); \ + ret_val = -1; \ + break; \ + } \ + ret = pthread_cond_init(&(queue).task_cond, NULL); \ + if ( ret != 0 ) \ + { \ + fprintf(stderr, "pthread_cond_init error!\n"); \ + ret_val = -1; \ + break; \ + } \ + } while(0) + +#define QUEUE_DESTROY(queue) \ + do { \ + free((queue).buffer); \ + pthread_mutex_destroy(&(queue).mutex); \ + pthread_cond_destroy(&(queue).not_empty_cond); \ + pthread_cond_destroy(&(queue).task_cond); \ + } while(0) + +#define QUEUE_PUT(queue, pTask) \ + do { \ + pthread_mutex_lock(&(queue).mutex); \ + (queue).buffer[(queue).tail] = (void*)(pTask); \ + (queue).tail = ((queue).tail + 1) % (queue).capacity; \ + ++(queue).unfinished_tasks; \ + pthread_cond_signal(&(queue).not_empty_cond); \ + pthread_mutex_unlock(&(queue).mutex); \ + } while(0) + +#define QUEUE_GET(queue, type, pTask) \ + do { \ + pthread_mutex_lock(&(queue).mutex); \ + while ( (queue).head == (queue).tail ) \ + { \ + pthread_cond_wait(&(queue).not_empty_cond, &(queue).mutex); \ + } \ + pTask = (type)(queue).buffer[(queue).head]; \ + (queue).head = ((queue).head + 1) % (queue).capacity; \ + pthread_mutex_unlock(&(queue).mutex); \ + } while(0) + +#define QUEUE_JOIN(queue) \ + do { \ + pthread_mutex_lock(&(queue).mutex); \ + while ( (queue).unfinished_tasks > 0 ) \ + { \ + pthread_cond_wait(&(queue).task_cond, &(queue).mutex); \ + } \ + (queue).unfinished_tasks = 0; \ + pthread_mutex_unlock(&(queue).mutex); \ + } while(0) + +#define QUEUE_TASK_DONE(queue) \ + do { \ + pthread_mutex_lock(&(queue).mutex); \ + --(queue).unfinished_tasks; \ + if ( (queue).unfinished_tasks <= 0 ) \ + pthread_cond_signal(&(queue).task_cond); \ + pthread_mutex_unlock(&(queue).mutex); \ + } while(0) + +#endif + +#define MIN(a, b) ((a) < (b) ? (a) : (b)) + +#define MAX_TASK_COUNT(cpu_count) ((cpu_count) << 3) + +enum +{ + GET_WEIGHT = 0, + GET_HIGHLIGHTS, + GET_PATH_WEIGHT, + Q_SORT, + Q_SORT_2, + MERGE, + MERGE_2, + PY_SET_ITEM, + PY_SET_ITEM_2 +}; + +/* sort in descending order */ +static int compare(const void* a, const void* b) +{ + weight_t wa = ((const FeResult*)a)->weight; + weight_t wb = ((const FeResult*)b)->weight; + return (wa < wb) - (wa > wb); +} + +/* sort in descending order */ +static int compare2(const void* a, const void* b) +{ + uint32_t wa = ((const FeResult*)a)->path_weight; + uint32_t wb = ((const FeResult*)b)->path_weight; + + return (int)wb - (int)wa; +} + +#if defined(_MSC_VER) +static DWORD WINAPI _worker(LPVOID pParam) +#else +static void* _worker(void* pParam) +#endif +{ + FuzzyEngine* pEngine = (FuzzyEngine*)pParam; + + while ( 1 ) + { + TaskItem* pTask = NULL; + QUEUE_GET(pEngine->task_queue, TaskItem*, pTask); + + if ( pTask ) + { + switch ( pTask->function ) + { + case GET_WEIGHT: + { + FeString* tasks = pEngine->source + pTask->offset; + FeResult* results = pEngine->results + pTask->offset; + uint32_t length = pTask->length; + uint32_t i = 0; + for ( ; i < length; ++i ) + { + results[i].weight = getWeight(tasks[i].str, tasks[i].len, + pEngine->pPattern_ctxt, pEngine->is_name_only); + results[i].index = pTask->offset + i; + } + } + break; + case GET_HIGHLIGHTS: + { + FeString* tasks = pEngine->source + pTask->offset; + HighlightGroup** results = pEngine->highlights + pTask->offset; + uint32_t length = pTask->length; + uint32_t i = 0; + for ( ; i < length; ++i ) + { + results[i] = getHighlights(tasks[i].str, tasks[i].len, + pEngine->pPattern_ctxt, pEngine->is_name_only); + } + } + break; + case GET_PATH_WEIGHT: + { + FeString* tasks = pEngine->source + pTask->offset; + FeResult* results = pEngine->results + pTask->offset; + uint32_t length = pTask->length; + uint32_t i = 0; + for ( ; i < length; ++i ) + { + results[i].path_weight = getPathWeight(pEngine->filename, pEngine->suffix, pEngine->dirname, tasks[i].str, tasks[i].len); + results[i].index = pTask->offset + i; + } + } + break; + case Q_SORT: + { + FeResult* tasks = pEngine->results + pTask->offset; + qsort(tasks, pTask->length, sizeof(FeResult), compare); + } + break; + case Q_SORT_2: + { + FeResult* tasks = pEngine->results + pTask->offset; + qsort(tasks, pTask->length, sizeof(FeResult), compare2); + } + break; + case MERGE: + { + MergeTaskItem* pMergeTask = (MergeTaskItem*)pTask; + FeResult* list_1 = pEngine->results + pMergeTask->offset_1; + FeResult* list_2 = list_1 + pMergeTask->length_1; + FeResult* buffer = pMergeTask->buffer; + memcpy(buffer, list_2, pMergeTask->length_2 * sizeof(FeResult)); + int32_t i = pMergeTask->length_1 - 1; + int32_t j = pMergeTask->length_2 - 1; + int32_t k = pMergeTask->length_1 + j; + while ( i >= 0 && j >= 0 ) + { + if ( list_1[i].weight < buffer[j].weight ) + { + list_1[k--] = list_1[i--]; + } + else + { + list_1[k--] = buffer[j--]; + } + } + while ( j >= 0 ) + { + list_1[k--] = buffer[j--]; + } + } + break; + case MERGE_2: + { + MergeTaskItem* pMergeTask = (MergeTaskItem*)pTask; + FeResult* list_1 = pEngine->results + pMergeTask->offset_1; + FeResult* list_2 = list_1 + pMergeTask->length_1; + FeResult* buffer = pMergeTask->buffer; + memcpy(buffer, list_2, pMergeTask->length_2 * sizeof(FeResult)); + int32_t i = pMergeTask->length_1 - 1; + int32_t j = pMergeTask->length_2 - 1; + int32_t k = pMergeTask->length_1 + j; + while ( i >= 0 && j >= 0 ) + { + if ( list_1[i].path_weight < buffer[j].path_weight ) + { + list_1[k--] = list_1[i--]; + } + else + { + list_1[k--] = buffer[j--]; + } + } + while ( j >= 0 ) + { + list_1[k--] = buffer[j--]; + } + } + break; + case PY_SET_ITEM: + { + PySetTaskItem* pPySetTask = (PySetTaskItem*)pTask; + weight_t* weights = pPySetTask->weights + pPySetTask->offset; + FeResult* results = pEngine->results + pPySetTask->offset; + PyObject* text_list = pPySetTask->text_list; + PyObject* py_source = pPySetTask->py_source; + uint32_t i = 0; + uint32_t length = pPySetTask->length; + + for ( i = 0; i < length; ++i ) + { + weights[i] = results[i].weight; + PyObject* item = PyList_GET_ITEM(py_source, results[i].index); + Py_INCREF(item); + /* PyList_SET_ITEM() steals a reference to item. */ + PyList_SET_ITEM(text_list, pPySetTask->offset + i, item); + } + } + break; + case PY_SET_ITEM_2: + { + PySetTaskItem* pPySetTask = (PySetTaskItem*)pTask; + uint32_t* path_weights = pPySetTask->path_weights + pPySetTask->offset; + FeResult* results = pEngine->results + pPySetTask->offset; + PyObject* text_list = pPySetTask->text_list; + PyObject* py_source = pPySetTask->py_source; + uint32_t i = 0; + uint32_t length = pPySetTask->length; + + for ( i = 0; i < length; ++i ) + { + path_weights[i] = results[i].path_weight; + PyObject* item = PyList_GET_ITEM(py_source, results[i].index); + Py_INCREF(item); + /* PyList_SET_ITEM() steals a reference to item. */ + PyList_SET_ITEM(text_list, pPySetTask->offset + i, item); + } + } + break; + } + + QUEUE_TASK_DONE(pEngine->task_queue); + } + else + { + break; + } + } + +#if defined(_MSC_VER) + return 0; +#else + return NULL; +#endif +} + +FuzzyEngine* createFuzzyEngine(uint32_t cpu_count) +{ + FuzzyEngine* pEngine = (FuzzyEngine*)malloc(sizeof(FuzzyEngine)); + if ( !pEngine ) + { + return NULL; + } + + pEngine->cpu_count = cpu_count; + pEngine->threads = NULL; + pEngine->pPattern_ctxt = NULL; + pEngine->source = NULL; + + int32_t ret = 0; + QUEUE_INIT(pEngine->task_queue, MAX_TASK_COUNT(cpu_count) + cpu_count + 1, ret); + if ( ret != 0 ) + { + free(pEngine); + return NULL; + } + + return pEngine; +} + +void closeFuzzyEngine(FuzzyEngine* pEngine) +{ + if ( !pEngine ) + return; + + /** + * pEngine->threads is NULL if fuzzyMatch() is not called, + * or fuzzyMatch() returns before malloc for pEngine->threads. + */ + if ( pEngine->threads ) + { + uint32_t i = 0; + for ( ; i < pEngine->cpu_count; ++i ) + { + QUEUE_PUT(pEngine->task_queue, NULL); + } + +#if defined(_MSC_VER) + WaitForMultipleObjects(pEngine->cpu_count, pEngine->threads, TRUE, INFINITE); + for ( i = 0; i < pEngine->cpu_count; ++i ) + { + CloseHandle(pEngine->threads[i]); + } +#else + for ( i = 0; i < pEngine->cpu_count; ++i ) + { + pthread_join(pEngine->threads[i], NULL); + } +#endif + free(pEngine->threads); + } + + QUEUE_DESTROY(pEngine->task_queue); + free(pEngine); +} + +static int32_t pyObject_ToStringAndSize(PyObject* obj, char** buffer, uint32_t* size) +{ + Py_ssize_t length = 0; +#if PY_MAJOR_VERSION >= 3 + *buffer = (char*)PyUnicode_AsUTF8AndSize(obj, &length); + *size = (uint32_t)length; + if ( buffer ) + return 0; + else + return -1; +#else + int ret = PyString_AsStringAndSize(obj, buffer, &length); + *size = (uint32_t)length; + if ( ret >= 0 ) + return 0; + else + return -1; +#endif +} + +static void delFuzzyEngine(PyObject* obj) +{ + closeFuzzyEngine((FuzzyEngine*)PyCapsule_GetPointer(obj, NULL)); +} + +/** + * createFuzzyEngine(cpu_count, auto_free=False) + * + * `auto_free` is optional that specifies whether auto free the fuzzyEngine object. + * It defaults to `False`, which means do not auto free the fuzzyEngine object, + * so that you should call closeFuzzyEngine() manually. + * return a fuzzyEngine object + */ +static PyObject* fuzzyEngine_createFuzzyEngine(PyObject* self, PyObject* args, PyObject* kwargs) +{ + uint32_t cpu_count; + uint8_t auto_free = 0; + static char* kwlist[] = {"cpu_count", "auto_free", NULL}; + + if ( !PyArg_ParseTupleAndKeywords(args, kwargs, "I|b:createFuzzyEngine", kwlist, &cpu_count, &auto_free) ) + return NULL; + + FuzzyEngine* pEngine = createFuzzyEngine(cpu_count); + + return PyCapsule_New(pEngine, NULL, auto_free ? delFuzzyEngine : NULL); +} + +/** + * closeFuzzyEngine(engine) + */ +static PyObject* fuzzyEngine_closeFuzzyEngine(PyObject* self, PyObject* args) +{ + PyObject* engine = NULL; + if ( !PyArg_ParseTuple(args, "O:closeFuzzyEngine", &engine) ) + return NULL; + + closeFuzzyEngine((FuzzyEngine*)PyCapsule_GetPointer(engine, NULL)); + + Py_RETURN_NONE; +} + +static void delPatternContext(PyObject* obj) +{ + free(PyCapsule_GetPointer(obj, NULL)); +} + +/** + * initPattern(pattern) + */ +static PyObject* fuzzyEngine_initPattern(PyObject* self, PyObject* args) +{ + const char* pattern; + Py_ssize_t pattern_len; + + if ( !PyArg_ParseTuple(args, "s#:initPattern", &pattern, &pattern_len) ) + return NULL; + + PatternContext* pCtxt = initPattern(pattern, (uint16_t)pattern_len); + + return PyCapsule_New(pCtxt, NULL, delPatternContext); +} + +static void delWeights(PyObject* obj) +{ + free(PyCapsule_GetPointer(obj, NULL)); +} + +static PyObject* createWeights(void* weights) +{ + return PyCapsule_New(weights, NULL, delWeights); +} + +/** + * fuzzyMatch(engine, source, pattern, is_name_only=False, sort_results=True) + * + * `is_name_only` is optional, it defaults to `False`, which indicates using the full path matching algorithm. + * `sort_results` is optional, it defaults to `True`, which indicates whether to sort the results. + * + * return a tuple, (a list of corresponding weight, a sorted list of items from `source` that match `pattern`). + */ +static PyObject* fuzzyEngine_fuzzyMatch(PyObject* self, PyObject* args, PyObject* kwargs) +{ + PyObject* py_engine = NULL; + PyObject* py_source = NULL; + PyObject* py_patternCtxt = NULL; + uint8_t is_name_only = 0; + uint8_t sort_results = 1; + static char* kwlist[] = {"engine", "source", "pattern", "is_name_only", "sort_results", NULL}; + + if ( !PyArg_ParseTupleAndKeywords(args, kwargs, "OOO|bb:fuzzyMatch", kwlist, &py_engine, + &py_source, &py_patternCtxt, &is_name_only, &sort_results) ) + return NULL; + + FuzzyEngine* pEngine = (FuzzyEngine*)PyCapsule_GetPointer(py_engine, NULL); + if ( !pEngine ) + return NULL; + + if ( !PyList_Check(py_source) ) + { + PyErr_SetString(PyExc_TypeError, "parameter `source` must be a list."); + return NULL; + } + + uint32_t source_size = (uint32_t)PyList_Size(py_source); + if ( source_size == 0 ) + { + return Py_BuildValue("([],[])"); + } + + pEngine->pPattern_ctxt = (PatternContext*)PyCapsule_GetPointer(py_patternCtxt, NULL); + if ( !pEngine->pPattern_ctxt ) + return NULL; + + pEngine->is_name_only = is_name_only; + + uint32_t max_task_count = MAX_TASK_COUNT(pEngine->cpu_count); + uint32_t chunk_size = (source_size + max_task_count - 1) / max_task_count; + uint32_t task_count = (source_size + chunk_size - 1) / chunk_size; + if ( chunk_size == 1 || pEngine->cpu_count == 1 ) + { + chunk_size = source_size; + task_count = 1; + } + + pEngine->source = (FeString*)malloc(source_size * sizeof(FeString)); + if ( !pEngine->source ) + { + fprintf(stderr, "Out of memory at %s:%d\n", __FILE__, __LINE__); + return NULL; + } + + TaskItem* tasks = (TaskItem*)malloc(task_count * sizeof(TaskItem)); + if ( !tasks ) + { + free(pEngine->source); + fprintf(stderr, "Out of memory at %s:%d\n", __FILE__, __LINE__); + return NULL; + } + + pEngine->results = (FeResult*)malloc(source_size * sizeof(FeResult)); + if ( !pEngine->results ) + { + free(pEngine->source); + free(tasks); + fprintf(stderr, "Out of memory at %s:%d\n", __FILE__, __LINE__); + return NULL; + } + + FeResult* results = pEngine->results; + + if ( !pEngine->threads ) + { +#if defined(_MSC_VER) + pEngine->threads = (HANDLE*)malloc(pEngine->cpu_count * sizeof(HANDLE)); +#else + pEngine->threads = (pthread_t*)malloc(pEngine->cpu_count * sizeof(pthread_t)); +#endif + if ( !pEngine->threads ) + { + free(pEngine->source); + free(tasks); + free(results); + fprintf(stderr, "Out of memory at %s:%d\n", __FILE__, __LINE__); + return NULL; + } + + uint32_t i = 0; + for ( ; i < pEngine->cpu_count; ++i) + { +#if defined(_MSC_VER) + pEngine->threads[i] = CreateThread(NULL, 0, _worker, pEngine, 0, NULL); + if ( !pEngine->threads[i] ) +#else + int ret = pthread_create(&pEngine->threads[i], NULL, _worker, pEngine); + if ( ret != 0 ) +#endif + { + free(pEngine->source); + free(tasks); + free(results); + free(pEngine->threads); + fprintf(stderr, "pthread_create error!\n"); + return NULL; + } + } + } + +#if defined(_MSC_VER) + QUEUE_SET_TASK_COUNT(pEngine->task_queue, task_count); +#endif + + uint32_t i = 0; + for ( ; i < task_count; ++i ) + { + uint32_t offset = i * chunk_size; + uint32_t length = MIN(chunk_size, source_size - offset); + + tasks[i].function = GET_WEIGHT; + tasks[i].offset = offset; + tasks[i].length = length; + + uint32_t j = 0; + for ( ; j < length; ++j ) + { + FeString *s = pEngine->source + offset + j; + PyObject* item = PyList_GET_ITEM(py_source, offset + j); + if ( pyObject_ToStringAndSize(item, &s->str, &s->len) < 0 ) + { + free(pEngine->source); + free(tasks); + free(results); + fprintf(stderr, "pyObject_ToStringAndSize error!\n"); + return NULL; + } + } + + QUEUE_PUT(pEngine->task_queue, tasks + i); + } + + QUEUE_JOIN(pEngine->task_queue); /* blocks until all tasks have finished */ + + uint32_t results_count = 0; + for ( i = 0; i < source_size; ++i ) + { + if ( results[i].weight > MIN_WEIGHT ) + { + if ( i > results_count ) + { + results[results_count] = results[i]; + } + ++results_count; + } + } + + if ( results_count == 0 ) + { + free(pEngine->source); + free(tasks); + free(results); + return Py_BuildValue("([],[])"); + } + + if ( sort_results ) + { + if ( task_count == 1 || results_count < 60000 ) + { + qsort(results, results_count, sizeof(FeResult), compare); + } + else + { + chunk_size = (results_count + task_count - 1) / task_count; + if ( chunk_size < 2000 ) + { + chunk_size = (results_count + (task_count >> 1) - 1) / (task_count >> 1); + } + task_count = (results_count + chunk_size - 1) / chunk_size; + FeResult* buffer = (FeResult*)malloc(chunk_size * (task_count >> 1) * sizeof(FeResult)); + if ( !buffer ) + { + free(pEngine->source); + free(tasks); + free(results); + fprintf(stderr, "Out of memory at %s:%d\n", __FILE__, __LINE__); + return NULL; + } +#if defined(_MSC_VER) + QUEUE_SET_TASK_COUNT(pEngine->task_queue, task_count); +#endif + for ( i = 0; i < task_count; ++i ) + { + uint32_t offset = i * chunk_size; + uint32_t length = MIN(chunk_size, results_count - offset); + + tasks[i].function = Q_SORT; + tasks[i].offset = offset; + tasks[i].length = length; + QUEUE_PUT(pEngine->task_queue, tasks + i); + } + + QUEUE_JOIN(pEngine->task_queue); /* blocks until all tasks have finished */ + + MergeTaskItem* merge_tasks = NULL; + merge_tasks = (MergeTaskItem*)malloc(task_count * sizeof(MergeTaskItem)); + if ( !merge_tasks ) + { + free(pEngine->source); + free(tasks); + free(results); + free(buffer); + fprintf(stderr, "Out of memory at %s:%d\n", __FILE__, __LINE__); + return NULL; + } + + while ( chunk_size < results_count ) + { + uint32_t q = results_count / (chunk_size << 1); + uint32_t r = results_count % (chunk_size << 1); +#if defined(_MSC_VER) + QUEUE_SET_TASK_COUNT(pEngine->task_queue, q + r/chunk_size); +#endif + for ( i = 0; i < q; ++i ) + { + merge_tasks[i].function = MERGE; + merge_tasks[i].offset_1 = i * (chunk_size << 1); + merge_tasks[i].length_1 = chunk_size; + merge_tasks[i].length_2 = chunk_size; + merge_tasks[i].buffer = buffer + (merge_tasks[i].offset_1 >> 1); /* buffer + i * chunk_size */ + QUEUE_PUT(pEngine->task_queue, merge_tasks + i); + } + + if ( r > chunk_size ) + { + merge_tasks[i].function = MERGE; + merge_tasks[i].offset_1 = i * (chunk_size << 1); + merge_tasks[i].length_1 = chunk_size; + merge_tasks[i].length_2 = r - chunk_size; + merge_tasks[i].buffer = buffer + (merge_tasks[i].offset_1 >> 1); /* buffer + i * chunk_size */ + QUEUE_PUT(pEngine->task_queue, merge_tasks + i); + } + + QUEUE_JOIN(pEngine->task_queue); /* blocks until all tasks have finished */ + + chunk_size <<= 1; + } + + free(buffer); + free(merge_tasks); + } + } + + weight_t* weights = (weight_t*)malloc(results_count * sizeof(weight_t)); + if ( !weights ) + { + free(pEngine->source); + free(tasks); + free(results); + fprintf(stderr, "Out of memory at %s:%d\n", __FILE__, __LINE__); + return NULL; + } + + PyObject* text_list = PyList_New(results_count); + if ( task_count == 1 || results_count < 40000 ) + { + for ( i = 0; i < results_count; ++i ) + { + weights[i] = results[i].weight; + /* PyList_SET_ITEM() steals a reference to item. */ + /* PySequence_ITEM() return value: New reference. */ + PyList_SET_ITEM(text_list, i, PySequence_ITEM(py_source, results[i].index)); + } + } + else + { + chunk_size = (results_count + task_count - 1) / task_count; + if ( chunk_size < 8000 ) + { + chunk_size = (results_count + (task_count >> 1) - 1) / (task_count >> 1); + } + task_count = (results_count + chunk_size - 1) / chunk_size; + + PySetTaskItem* py_set_tasks = NULL; + py_set_tasks = (PySetTaskItem*)malloc(task_count * sizeof(PySetTaskItem)); + if ( !py_set_tasks ) + { + free(pEngine->source); + free(tasks); + free(results); + fprintf(stderr, "Out of memory at %s:%d\n", __FILE__, __LINE__); + return NULL; + } + +#if defined(_MSC_VER) + QUEUE_SET_TASK_COUNT(pEngine->task_queue, task_count); +#endif + for ( i = 0; i < task_count; ++i ) + { + uint32_t offset = i * chunk_size; + uint32_t length = MIN(chunk_size, results_count - offset); + + py_set_tasks[i].function = PY_SET_ITEM; + py_set_tasks[i].offset = offset; + py_set_tasks[i].length = length; + py_set_tasks[i].weights = weights; + py_set_tasks[i].text_list = text_list; + py_set_tasks[i].py_source = py_source; + QUEUE_PUT(pEngine->task_queue, py_set_tasks + i); + } + + QUEUE_JOIN(pEngine->task_queue); /* blocks until all tasks have finished */ + + free(py_set_tasks); + } + + free(pEngine->source); + free(tasks); + free(results); + + return Py_BuildValue("(NN)", createWeights(weights), text_list); +} + +/** + * fuzzyMatchEx(engine, source, pattern, is_name_only=False, sort_results=True, is_and_mode=False) + * + * same as fuzzyMatch(), the only difference is the return value. + * return a tuple, (a list of corresponding weight, a sorted list of index to items from `source` that match `pattern`). + */ +static PyObject* fuzzyEngine_fuzzyMatchEx(PyObject* self, PyObject* args, PyObject* kwargs) +{ + PyObject* py_engine = NULL; + PyObject* py_source = NULL; + PyObject* py_patternCtxt = NULL; + uint8_t is_name_only = 0; + uint8_t sort_results = 1; + uint8_t is_and_mode = 0; + static char* kwlist[] = {"engine", "source", "pattern", "is_name_only", "sort_results", "is_and_mode", NULL}; + + if ( !PyArg_ParseTupleAndKeywords(args, kwargs, "OOO|bbb:fuzzyMatch", kwlist, &py_engine, + &py_source, &py_patternCtxt, &is_name_only, &sort_results, &is_and_mode) ) + return NULL; + + FuzzyEngine* pEngine = (FuzzyEngine*)PyCapsule_GetPointer(py_engine, NULL); + if ( !pEngine ) + return NULL; + + if ( !PyList_Check(py_source) ) + { + PyErr_SetString(PyExc_TypeError, "parameter `source` must be a list."); + return NULL; + } + + uint32_t source_size = (uint32_t)PyList_Size(py_source); + if ( source_size == 0 ) + { + return Py_BuildValue("([],[])"); + } + + pEngine->pPattern_ctxt = (PatternContext*)PyCapsule_GetPointer(py_patternCtxt, NULL); + if ( !pEngine->pPattern_ctxt ) + return NULL; + + pEngine->is_name_only = is_name_only; + + uint32_t max_task_count = MAX_TASK_COUNT(pEngine->cpu_count); + uint32_t chunk_size = (source_size + max_task_count - 1) / max_task_count; + uint32_t task_count = (source_size + chunk_size - 1) / chunk_size; + if ( chunk_size == 1 || pEngine->cpu_count == 1 ) + { + chunk_size = source_size; + task_count = 1; + } + + pEngine->source = (FeString*)malloc(source_size * sizeof(FeString)); + if ( !pEngine->source ) + { + fprintf(stderr, "Out of memory at %s:%d\n", __FILE__, __LINE__); + return NULL; + } + + TaskItem* tasks = (TaskItem*)malloc(task_count * sizeof(TaskItem)); + if ( !tasks ) + { + free(pEngine->source); + fprintf(stderr, "Out of memory at %s:%d\n", __FILE__, __LINE__); + return NULL; + } + + pEngine->results = (FeResult*)malloc(source_size * sizeof(FeResult)); + if ( !pEngine->results ) + { + free(pEngine->source); + free(tasks); + fprintf(stderr, "Out of memory at %s:%d\n", __FILE__, __LINE__); + return NULL; + } + + FeResult* results = pEngine->results; + + if ( !pEngine->threads ) + { +#if defined(_MSC_VER) + pEngine->threads = (HANDLE*)malloc(pEngine->cpu_count * sizeof(HANDLE)); +#else + pEngine->threads = (pthread_t*)malloc(pEngine->cpu_count * sizeof(pthread_t)); +#endif + if ( !pEngine->threads ) + { + free(pEngine->source); + free(tasks); + free(results); + fprintf(stderr, "Out of memory at %s:%d\n", __FILE__, __LINE__); + return NULL; + } + + uint32_t i = 0; + for ( ; i < pEngine->cpu_count; ++i) + { +#if defined(_MSC_VER) + pEngine->threads[i] = CreateThread(NULL, 0, _worker, pEngine, 0, NULL); + if ( !pEngine->threads[i] ) +#else + int ret = pthread_create(&pEngine->threads[i], NULL, _worker, pEngine); + if ( ret != 0 ) +#endif + { + free(pEngine->source); + free(tasks); + free(results); + free(pEngine->threads); + fprintf(stderr, "pthread_create error!\n"); + return NULL; + } + } + } + +#if defined(_MSC_VER) + QUEUE_SET_TASK_COUNT(pEngine->task_queue, task_count); +#endif + + uint32_t i = 0; + for ( ; i < task_count; ++i ) + { + uint32_t offset = i * chunk_size; + uint32_t length = MIN(chunk_size, source_size - offset); + + tasks[i].function = GET_WEIGHT; + tasks[i].offset = offset; + tasks[i].length = length; + + uint32_t j = 0; + for ( ; j < length; ++j ) + { + FeString *s = pEngine->source + offset + j; + PyObject* item = PyList_GET_ITEM(py_source, offset + j); + if ( pyObject_ToStringAndSize(item, &s->str, &s->len) < 0 ) + { + free(pEngine->source); + free(tasks); + free(results); + fprintf(stderr, "pyObject_ToStringAndSize error!\n"); + return NULL; + } + } + + QUEUE_PUT(pEngine->task_queue, tasks + i); + } + + QUEUE_JOIN(pEngine->task_queue); /* blocks until all tasks have finished */ + + uint32_t results_count = 0; + for ( i = 0; i < source_size; ++i ) + { + if ( results[i].weight > MIN_WEIGHT ) + { + if ( i > results_count ) + { + results[results_count] = results[i]; + } + ++results_count; + } + } + + if ( results_count == 0 ) + { + free(pEngine->source); + free(tasks); + free(results); + return Py_BuildValue("([],[])"); + } + + if ( sort_results ) + { + if ( task_count == 1 || results_count < 60000 ) + { + qsort(results, results_count, sizeof(FeResult), compare); + } + else + { + chunk_size = (results_count + task_count - 1) / task_count; + if ( chunk_size < 2000 ) + { + chunk_size = (results_count + (task_count >> 1) - 1) / (task_count >> 1); + } + task_count = (results_count + chunk_size - 1) / chunk_size; + FeResult* buffer = (FeResult*)malloc(chunk_size * (task_count >> 1) * sizeof(FeResult)); + if ( !buffer ) + { + free(pEngine->source); + free(tasks); + free(results); + fprintf(stderr, "Out of memory at %s:%d\n", __FILE__, __LINE__); + return NULL; + } +#if defined(_MSC_VER) + QUEUE_SET_TASK_COUNT(pEngine->task_queue, task_count); +#endif + for ( i = 0; i < task_count; ++i ) + { + uint32_t offset = i * chunk_size; + uint32_t length = MIN(chunk_size, results_count - offset); + + tasks[i].function = Q_SORT; + tasks[i].offset = offset; + tasks[i].length = length; + QUEUE_PUT(pEngine->task_queue, tasks + i); + } + + QUEUE_JOIN(pEngine->task_queue); /* blocks until all tasks have finished */ + + MergeTaskItem* merge_tasks = NULL; + merge_tasks = (MergeTaskItem*)malloc(task_count * sizeof(MergeTaskItem)); + if ( !merge_tasks ) + { + free(pEngine->source); + free(tasks); + free(results); + free(buffer); + fprintf(stderr, "Out of memory at %s:%d\n", __FILE__, __LINE__); + return NULL; + } + + while ( chunk_size < results_count ) + { + uint32_t q = results_count / (chunk_size << 1); + uint32_t r = results_count % (chunk_size << 1); +#if defined(_MSC_VER) + QUEUE_SET_TASK_COUNT(pEngine->task_queue, q + r/chunk_size); +#endif + for ( i = 0; i < q; ++i ) + { + merge_tasks[i].function = MERGE; + merge_tasks[i].offset_1 = i * (chunk_size << 1); + merge_tasks[i].length_1 = chunk_size; + merge_tasks[i].length_2 = chunk_size; + merge_tasks[i].buffer = buffer + (merge_tasks[i].offset_1 >> 1); /* buffer + i * chunk_size */ + QUEUE_PUT(pEngine->task_queue, merge_tasks + i); + } + + if ( r > chunk_size ) + { + merge_tasks[i].function = MERGE; + merge_tasks[i].offset_1 = i * (chunk_size << 1); + merge_tasks[i].length_1 = chunk_size; + merge_tasks[i].length_2 = r - chunk_size; + merge_tasks[i].buffer = buffer + (merge_tasks[i].offset_1 >> 1); /* buffer + i * chunk_size */ + QUEUE_PUT(pEngine->task_queue, merge_tasks + i); + } + + QUEUE_JOIN(pEngine->task_queue); /* blocks until all tasks have finished */ + + chunk_size <<= 1; + } + + free(buffer); + free(merge_tasks); + } + } + + if ( is_and_mode ) + { + PyObject* weight_list = PyList_New(results_count); + PyObject* index_list = PyList_New(results_count); + for ( i = 0; i < results_count; ++i ) + { + /* PyList_SET_ITEM() steals a reference to item. */ + PyList_SET_ITEM(weight_list, i, Py_BuildValue("f", results[i].weight)); + PyList_SET_ITEM(index_list, i, Py_BuildValue("I", results[i].index)); + } + + free(pEngine->source); + free(tasks); + free(results); + + return Py_BuildValue("(NN)", weight_list, index_list); + } + else + { + weight_t* weights = (weight_t*)malloc(results_count * sizeof(weight_t)); + if ( !weights ) + { + free(pEngine->source); + free(tasks); + free(results); + fprintf(stderr, "Out of memory at %s:%d\n", __FILE__, __LINE__); + return NULL; + } + + PyObject* index_list = PyList_New(results_count); + for ( i = 0; i < results_count; ++i ) + { + weights[i] = results[i].weight; + /* PyList_SET_ITEM() steals a reference to item. */ + /* PySequence_ITEM() return value: New reference. */ + PyList_SET_ITEM(index_list, i, Py_BuildValue("I", results[i].index)); + } + + free(pEngine->source); + free(tasks); + free(results); + + return Py_BuildValue("(NN)", createWeights(weights), index_list); + } +} + +/** + * merge(tuple_a, tuple_b) + * tuple_a, tuple_b are the return value of fuzzyEngine_fuzzyMatch + */ +static PyObject* fuzzyEngine_merge(PyObject* self, PyObject* args) +{ + PyObject* weight_list_a = NULL; + PyObject* text_list_a = NULL; + PyObject* weight_list_b = NULL; + PyObject* text_list_b = NULL; + if ( !PyArg_ParseTuple(args, "(OO)(OO):merge", &weight_list_a, &text_list_a, &weight_list_b, &text_list_b) ) + return NULL; + + uint32_t size_a = (uint32_t)PyList_Size(text_list_a); + if ( size_a == 0 ) + { + return Py_BuildValue("(OO)", weight_list_b, text_list_b); + } + uint32_t size_b = (uint32_t)PyList_Size(text_list_b); + if ( size_b == 0 ) + { + return Py_BuildValue("(OO)", weight_list_a, text_list_a); + } + + weight_t* weights = (weight_t*)malloc((size_a + size_b) * sizeof(weight_t)); + if ( !weights ) + { + fprintf(stderr, "Out of memory at %s:%d\n", __FILE__, __LINE__); + return NULL; + } + + PyObject* text_list = PyList_New(size_a + size_b); + + uint32_t i = 0; + uint32_t j = 0; + + weight_t* weights_a = (weight_t*)PyCapsule_GetPointer(weight_list_a, NULL); + weight_t w_a = weights_a[i]; + weight_t* weights_b = (weight_t*)PyCapsule_GetPointer(weight_list_b, NULL); + weight_t w_b = weights_b[j]; + while ( i < size_a && j < size_b ) + { + if ( w_a > w_b ) + { + weights[i + j] = weights_a[i]; + PyList_SET_ITEM(text_list, i + j, PySequence_ITEM(text_list_a, i)); + ++i; + if ( i < size_a ) + { + w_a = weights_a[i]; + } + } + else + { + weights[i + j] = weights_b[j]; + PyList_SET_ITEM(text_list, i + j, PySequence_ITEM(text_list_b, j)); + ++j; + if ( j < size_b ) + { + w_b = weights_b[j]; + } + } + } + while ( i < size_a ) + { + weights[i + j] = weights_a[i]; + PyList_SET_ITEM(text_list, i + j, PySequence_ITEM(text_list_a, i)); + ++i; + } + while ( j < size_b ) + { + weights[i + j] = weights_b[j]; + PyList_SET_ITEM(text_list, i + j, PySequence_ITEM(text_list_b, j)); + ++j; + } + return Py_BuildValue("(NN)", createWeights(weights), text_list); +} +/** + * getHighlights(engine, source, pattern, is_name_only=False) + * + * `is_name_only` is optional, it defaults to `False`, which indicates using the full path matching algorithm. + * + * return a list of list of pair [col, length], where `col` is the column number(start from 1, the value must + * correspond to the byte index of `text`) and `length` is the length of the highlight in bytes. + * e.g., [ + * [ [2,3], [6,2], [10,4], ... ], + * [ [3,2], [5,2], [9,3], ... ], + * ... + * ] + * NOTE: this function must be called after fuzzyMatch() is called, because this function assume that all the + * texts in `source` match `pattern` and all the threads in FuzzyEngine have already been started. + */ +static PyObject* fuzzyEngine_getHighlights(PyObject* self, PyObject* args, PyObject* kwargs) +{ + PyObject* py_source = NULL; + PyObject* py_patternCtxt = NULL; + PyObject* py_engine = NULL; + uint8_t is_name_only = 0; + static char* kwlist[] = {"engine", "source", "pattern", "is_name_only", NULL}; + + if ( !PyArg_ParseTupleAndKeywords(args, kwargs, "OOO|b:fuzzyMatch", kwlist, &py_engine, + &py_source, &py_patternCtxt, &is_name_only) ) + return NULL; + + FuzzyEngine* pEngine = (FuzzyEngine*)PyCapsule_GetPointer(py_engine, NULL); + if ( !pEngine ) + return NULL; + + if ( !PyList_Check(py_source) ) + { + PyErr_SetString(PyExc_TypeError, "parameter `source` must be a list."); + return NULL; + } + + pEngine->pPattern_ctxt = (PatternContext*)PyCapsule_GetPointer(py_patternCtxt, NULL); + if ( !pEngine->pPattern_ctxt ) + return NULL; + + pEngine->is_name_only = is_name_only; + + uint32_t source_size = (uint32_t)PyList_Size(py_source); + + uint32_t max_task_count = MAX_TASK_COUNT(pEngine->cpu_count); + uint32_t chunk_size = (source_size + max_task_count - 1) / max_task_count; + uint32_t task_count = (source_size + chunk_size - 1) / chunk_size; + + pEngine->source = (FeString*)malloc(source_size * sizeof(FeString)); + if ( !pEngine->source ) + { + fprintf(stderr, "Out of memory at %s:%d\n", __FILE__, __LINE__); + return NULL; + } + + TaskItem* tasks = (TaskItem*)malloc(task_count * sizeof(TaskItem)); + if ( !tasks ) + { + free(pEngine->source); + fprintf(stderr, "Out of memory at %s:%d\n", __FILE__, __LINE__); + return NULL; + } + + pEngine->highlights = (HighlightGroup**)malloc(source_size * sizeof(HighlightGroup*)); + if ( !pEngine->highlights ) + { + free(pEngine->source); + free(tasks); + fprintf(stderr, "Out of memory at %s:%d\n", __FILE__, __LINE__); + return NULL; + } + +#if defined(_MSC_VER) + QUEUE_SET_TASK_COUNT(pEngine->task_queue, task_count); +#endif + + uint32_t i = 0; + for ( ; i < task_count; ++i ) + { + uint32_t offset = i * chunk_size; + uint32_t length = MIN(chunk_size, source_size - offset); + + tasks[i].function = GET_HIGHLIGHTS; + tasks[i].offset = offset; + tasks[i].length = length; + + uint32_t j = 0; + for ( ; j < length; ++j ) + { + FeString *s = pEngine->source + offset + j; + PyObject* item = PyList_GET_ITEM(py_source, offset + j); + if ( pyObject_ToStringAndSize(item, &s->str, &s->len) < 0 ) + { + free(pEngine->source); + free(tasks); + free(pEngine->highlights); + fprintf(stderr, "pyObject_ToStringAndSize error!\n"); + return NULL; + } + } + + QUEUE_PUT(pEngine->task_queue, tasks + i); + } + + QUEUE_JOIN(pEngine->task_queue); /* blocks until all tasks have finished */ + + PyObject* res = PyList_New(source_size); + for ( i = 0; i < source_size; ++i ) + { + HighlightGroup* pGroup = pEngine->highlights[i]; + if ( !pGroup ) + { + free(pEngine->source); + free(tasks); + free(pEngine->highlights); + Py_XDECREF(res); + return NULL; + } + + PyObject* list = PyList_New(pGroup->end_index); + uint16_t j; + for ( j = 0; j < pGroup->end_index; ++j ) + { + PyList_SetItem(list, j, Py_BuildValue("[H,H]", pGroup->positions[j].col, pGroup->positions[j].len)); + } + PyList_SetItem(res, i, list); + free(pGroup); + } + + free(pEngine->source); + free(tasks); + free(pEngine->highlights); + + return res; +} + +/** + * guessMatch(engine, source, filename, suffix, dirname, icon, sort_results=True) + * + * e.g., /usr/src/example.tar.gz + * `filename` is "example.tar" + * `suffix` is ".gz" + * `dirname` is "/usr/src" + * + * return a tuple, (a list of corresponding weight, a sorted list of items from `source` that match `pattern`). + */ +static PyObject* fuzzyEngine_guessMatch(PyObject* self, PyObject* args, PyObject* kwargs) +{ + PyObject* py_engine = NULL; + PyObject* py_source = NULL; + const char* filename = NULL; + const char* suffix = NULL; + const char* dirname = NULL; + PyObject* py_icon = NULL; + uint8_t sort_results = 1; + static char* kwlist[] = {"engine", "source", "filename", "suffix", "dirname", "icon", "sort_results", NULL}; + + if ( !PyArg_ParseTupleAndKeywords(args, kwargs, "OOsssO|b:guessMatch", kwlist, &py_engine, + &py_source, &filename, &suffix, &dirname, &py_icon, &sort_results) ) + return NULL; + + FuzzyEngine* pEngine = (FuzzyEngine*)PyCapsule_GetPointer(py_engine, NULL); + if ( !pEngine ) + return NULL; + + if ( !PyList_Check(py_source) ) + { + PyErr_SetString(PyExc_TypeError, "parameter `source` must be a list."); + return NULL; + } + + uint32_t source_size = (uint32_t)PyList_Size(py_source); + if ( source_size == 0 ) + { + return Py_BuildValue("([],[])"); + } + + pEngine->filename = filename; + pEngine->suffix = suffix; + pEngine->dirname = dirname; + + uint32_t max_task_count = MAX_TASK_COUNT(pEngine->cpu_count); + uint32_t chunk_size = (source_size + max_task_count - 1) / max_task_count; + uint32_t task_count = (source_size + chunk_size - 1) / chunk_size; + if ( chunk_size == 1 || pEngine->cpu_count == 1 ) + { + chunk_size = source_size; + task_count = 1; + } + + pEngine->source = (FeString*)malloc(source_size * sizeof(FeString)); + if ( !pEngine->source ) + { + fprintf(stderr, "Out of memory at %s:%d\n", __FILE__, __LINE__); + return NULL; + } + + TaskItem* tasks = (TaskItem*)malloc(task_count * sizeof(TaskItem)); + if ( !tasks ) + { + free(pEngine->source); + fprintf(stderr, "Out of memory at %s:%d\n", __FILE__, __LINE__); + return NULL; + } + + pEngine->results = (FeResult*)malloc(source_size * sizeof(FeResult)); + if ( !pEngine->results ) + { + free(pEngine->source); + free(tasks); + fprintf(stderr, "Out of memory at %s:%d\n", __FILE__, __LINE__); + return NULL; + } + + FeResult* results = pEngine->results; + + if ( !pEngine->threads ) + { +#if defined(_MSC_VER) + pEngine->threads = (HANDLE*)malloc(pEngine->cpu_count * sizeof(HANDLE)); +#else + pEngine->threads = (pthread_t*)malloc(pEngine->cpu_count * sizeof(pthread_t)); +#endif + if ( !pEngine->threads ) + { + free(pEngine->source); + free(tasks); + free(results); + fprintf(stderr, "Out of memory at %s:%d\n", __FILE__, __LINE__); + return NULL; + } + + uint32_t i = 0; + for ( ; i < pEngine->cpu_count; ++i) + { +#if defined(_MSC_VER) + pEngine->threads[i] = CreateThread(NULL, 0, _worker, pEngine, 0, NULL); + if ( !pEngine->threads[i] ) +#else + int ret = pthread_create(&pEngine->threads[i], NULL, _worker, pEngine); + if ( ret != 0 ) +#endif + { + free(pEngine->source); + free(tasks); + free(results); + free(pEngine->threads); + fprintf(stderr, "pthread_create error!\n"); + return NULL; + } + } + } + +#if defined(_MSC_VER) + QUEUE_SET_TASK_COUNT(pEngine->task_queue, task_count); +#endif + + char *icon_str = NULL; + uint32_t icon_len = 0; + if ( pyObject_ToStringAndSize(py_icon, &icon_str, &icon_len) < 0 ) + { + free(pEngine->source); + free(tasks); + free(results); + fprintf(stderr, "pyObject_ToStringAndSize error!\n"); + return NULL; + } + + uint32_t i = 0; + for ( ; i < task_count; ++i ) + { + uint32_t offset = i * chunk_size; + uint32_t length = MIN(chunk_size, source_size - offset); + + tasks[i].function = GET_PATH_WEIGHT; + tasks[i].offset = offset; + tasks[i].length = length; + + uint32_t j = 0; + for ( ; j < length; ++j ) + { + FeString *s = pEngine->source + offset + j; + PyObject* item = PyList_GET_ITEM(py_source, offset + j); + if ( pyObject_ToStringAndSize(item, &s->str, &s->len) < 0 ) + { + free(pEngine->source); + free(tasks); + free(results); + fprintf(stderr, "pyObject_ToStringAndSize error!\n"); + return NULL; + } + + if ( icon_len > 0 ) + { + s->str += icon_len; + s->len -= icon_len; + } + } + + QUEUE_PUT(pEngine->task_queue, tasks + i); + } + + QUEUE_JOIN(pEngine->task_queue); /* blocks until all tasks have finished */ + + if ( sort_results ) + { + if ( task_count == 1 || source_size < 60000 ) + { + qsort(results, source_size, sizeof(FeResult), compare2); + } + else + { + chunk_size = (source_size + task_count - 1) / task_count; + if ( chunk_size < 2000 ) + { + chunk_size = (source_size + (task_count >> 1) - 1) / (task_count >> 1); + } + task_count = (source_size + chunk_size - 1) / chunk_size; + FeResult* buffer = (FeResult*)malloc(chunk_size * (task_count >> 1) * sizeof(FeResult)); + if ( !buffer ) + { + free(pEngine->source); + free(tasks); + free(results); + fprintf(stderr, "Out of memory at %s:%d\n", __FILE__, __LINE__); + return NULL; + } +#if defined(_MSC_VER) + QUEUE_SET_TASK_COUNT(pEngine->task_queue, task_count); +#endif + for ( i = 0; i < task_count; ++i ) + { + uint32_t offset = i * chunk_size; + uint32_t length = MIN(chunk_size, source_size - offset); + + tasks[i].function = Q_SORT_2; + tasks[i].offset = offset; + tasks[i].length = length; + QUEUE_PUT(pEngine->task_queue, tasks + i); + } + + QUEUE_JOIN(pEngine->task_queue); /* blocks until all tasks have finished */ + + MergeTaskItem* merge_tasks = NULL; + merge_tasks = (MergeTaskItem*)malloc(task_count * sizeof(MergeTaskItem)); + if ( !merge_tasks ) + { + free(pEngine->source); + free(tasks); + free(results); + free(buffer); + fprintf(stderr, "Out of memory at %s:%d\n", __FILE__, __LINE__); + return NULL; + } + + while ( chunk_size < source_size ) + { + uint32_t q = source_size / (chunk_size << 1); + uint32_t r = source_size % (chunk_size << 1); +#if defined(_MSC_VER) + QUEUE_SET_TASK_COUNT(pEngine->task_queue, q + r/chunk_size); +#endif + for ( i = 0; i < q; ++i ) + { + merge_tasks[i].function = MERGE_2; + merge_tasks[i].offset_1 = i * (chunk_size << 1); + merge_tasks[i].length_1 = chunk_size; + merge_tasks[i].length_2 = chunk_size; + merge_tasks[i].buffer = buffer + (merge_tasks[i].offset_1 >> 1); /* buffer + i * chunk_size */ + QUEUE_PUT(pEngine->task_queue, merge_tasks + i); + } + + if ( r > chunk_size ) + { + merge_tasks[i].function = MERGE_2; + merge_tasks[i].offset_1 = i * (chunk_size << 1); + merge_tasks[i].length_1 = chunk_size; + merge_tasks[i].length_2 = r - chunk_size; + merge_tasks[i].buffer = buffer + (merge_tasks[i].offset_1 >> 1); /* buffer + i * chunk_size */ + QUEUE_PUT(pEngine->task_queue, merge_tasks + i); + } + + QUEUE_JOIN(pEngine->task_queue); /* blocks until all tasks have finished */ + + chunk_size <<= 1; + } + + free(buffer); + free(merge_tasks); + } + } + + uint32_t* path_weights = (uint32_t*)malloc(source_size * sizeof(uint32_t)); + if ( !path_weights ) + { + free(pEngine->source); + free(tasks); + free(results); + fprintf(stderr, "Out of memory at %s:%d\n", __FILE__, __LINE__); + return NULL; + } + + PyObject* text_list = PyList_New(source_size); + if ( task_count == 1 || source_size < 40000 ) + { + for ( i = 0; i < source_size; ++i ) + { + path_weights[i] = results[i].path_weight; + /* PyList_SET_ITEM() steals a reference to item. */ + /* PySequence_ITEM() return value: New reference. */ + PyList_SET_ITEM(text_list, i, PySequence_ITEM(py_source, results[i].index)); + } + } + else + { + chunk_size = (source_size + task_count - 1) / task_count; + if ( chunk_size < 8000 ) + { + chunk_size = (source_size + (task_count >> 1) - 1) / (task_count >> 1); + } + task_count = (source_size + chunk_size - 1) / chunk_size; + + PySetTaskItem* py_set_tasks = NULL; + py_set_tasks = (PySetTaskItem*)malloc(task_count * sizeof(PySetTaskItem)); + if ( !py_set_tasks ) + { + free(pEngine->source); + free(tasks); + free(results); + fprintf(stderr, "Out of memory at %s:%d\n", __FILE__, __LINE__); + return NULL; + } + +#if defined(_MSC_VER) + QUEUE_SET_TASK_COUNT(pEngine->task_queue, task_count); +#endif + for ( i = 0; i < task_count; ++i ) + { + uint32_t offset = i * chunk_size; + uint32_t length = MIN(chunk_size, source_size - offset); + + py_set_tasks[i].function = PY_SET_ITEM_2; + py_set_tasks[i].offset = offset; + py_set_tasks[i].length = length; + py_set_tasks[i].path_weights = path_weights; + py_set_tasks[i].text_list = text_list; + py_set_tasks[i].py_source = py_source; + QUEUE_PUT(pEngine->task_queue, py_set_tasks + i); + } + + QUEUE_JOIN(pEngine->task_queue); /* blocks until all tasks have finished */ + + free(py_set_tasks); + } + + free(pEngine->source); + free(tasks); + free(results); + + return Py_BuildValue("(NN)", createWeights(path_weights), text_list); +} + +enum +{ + Category_Rg = 0, + Category_Tag, + Category_File, + Category_Gtags, + Category_Line, + Category_GitDiff, +}; + +typedef struct RgParameter +{ + uint32_t display_multi; + const char* separator; + uint32_t separator_len; + uint32_t has_column; +}RgParameter; + +typedef struct Parameter +{ + uint32_t mode; +}Parameter; + +typedef struct GtagsParameter +{ + uint32_t mode; + uint32_t format; + uint32_t match_path; +}GtagsParameter; + +static void delParamObj(PyObject* obj) +{ + free(PyCapsule_GetPointer(obj, NULL)); +} + +/** + * createRgParameter(display_multi, separator, has_column) + */ +static PyObject* fuzzyEngine_createRgParameter(PyObject* self, PyObject* args) +{ + uint32_t display_multi = 0; + const char* separator; + Py_ssize_t separator_len; + uint32_t has_column = 0; + + if ( !PyArg_ParseTuple(args, "Is#I:createRgParameter", &display_multi, &separator, &separator_len, &has_column) ) + return NULL; + + RgParameter* param = (RgParameter*)malloc(sizeof(RgParameter)); + if ( !param ) + { + return NULL; + } + param->display_multi = display_multi; + param->separator = separator; + param->separator_len = (uint32_t)separator_len; + param->has_column = has_column; + + return PyCapsule_New(param, NULL, delParamObj); +} + +/** + * createParameter(mode) + */ +static PyObject* fuzzyEngine_createParameter(PyObject* self, PyObject* args) +{ + uint32_t mode = 0; + + if ( !PyArg_ParseTuple(args, "I:createParameter", &mode) ) + return NULL; + + Parameter* param = (Parameter*)malloc(sizeof(Parameter)); + if ( !param ) + { + return NULL; + } + + param->mode = mode; + + return PyCapsule_New(param, NULL, delParamObj); +} + +/** + * createGtagsParameter(mode, format, match_path) + */ +static PyObject* fuzzyEngine_createGtagsParameter(PyObject* self, PyObject* args) +{ + uint32_t mode; + uint32_t format; + uint32_t match_path; + + if ( !PyArg_ParseTuple(args, "III:createGtagsParameter", &mode, &format, &match_path) ) + return NULL; + + GtagsParameter* param = (GtagsParameter*)malloc(sizeof(GtagsParameter)); + if ( !param ) + { + return NULL; + } + + param->mode = mode; + param->format = format; + param->match_path = match_path; + + return PyCapsule_New(param, NULL, delParamObj); +} + +static void rg_getDigest(char** str, uint32_t* length, RgParameter* param) +{ + char* s = *str; + uint32_t len = *length; + char* p = NULL; + + if ( param->display_multi ) + { + if ( len == param->separator_len && strncmp(s, param->separator, len) == 0 ) + { + *length = 0; + return; + } + else + { + uint8_t colon = 0; + uint8_t minus = 0; + for ( p = s; p < s + len; ++p ) + { + if ( *p == ':' ) + { + minus = 0; + ++colon; + if ( (colon == 2 && !param->has_column) || colon == 3 ) + { + *str = p + 1; + *length -= (uint32_t)(*str - s); + return; + } + } + else if ( *p == '-' ) + { + colon = 0; + ++minus; + if ( minus == 2 ) + { + *str = p + 1; + *length -= (uint32_t)(*str - s); + return; + } + } + else if ( !isdigit(*p) && colon + minus > 0 ) + { + colon = 0; + minus = 0; + } + } + } + } + else + { + uint8_t colon = 0; + for ( p = s; p < s + len; ++p ) + { + if ( *p == ':' ) + { + ++colon; + if ( (colon == 2 && !param->has_column) || colon == 3 ) + { + *str = p + 1; + *length -= (uint32_t)(*str - s); + return; + } + } + else if ( !isdigit(*p) && colon > 0 ) + { + colon = 0; + } + } + } +} + +static void tag_getDigest(char** str, uint32_t* length, Parameter* param) +{ + char* s = *str; + uint32_t len = *length; + char* p = s; + for ( ; p < s + len; ++p ) + { + if ( *p == '\t' ) + { + *length = (uint32_t)(p - s); + return; + } + } + /* if there is no '\t', the text is invalid */ + *length = 0; +} + +static void file_getDigest(char** str, uint32_t* length, Parameter* param) +{ + char* s = *str; + char *p = s + *length - 1; + for ( ; p >= s; --p ) + { + if ( *p == '/' || *p == '\\' ) + { + *str = p + 1; + *length -= (uint32_t)(*str - s); + return; + } + } +} + +static void gtags_getDigest(char** str, uint32_t* length, GtagsParameter* param) +{ + char* s = *str; + uint32_t len = *length; + char* p = NULL; + + if ( param->match_path ) + return; + + if ( param->format == 0 ) /* ctags-mod */ + { + uint8_t tab = 0; + for ( p = s; p < s + len; ++p ) + { + if ( *p == '\t' ) + { + ++tab; + if ( tab == 2 ) + { + *str = p + 1; + *length -= (uint32_t)(*str - s); + return; + } + } + } + } + else if ( param->format == 1 ) /* ctags */ + { + for ( p = s; p < s + len; ++p ) + { + if ( *p == '\t' ) + { + *length = (uint32_t)(p - s); + return; + } + } + } + else if ( param->format == 2 ) /* ctags-x */ + { + for ( p = s; p < s + len; ++p ) + { + if ( *p == ' ' ) + { + *length = (uint32_t)(p - s); + return; + } + } + } +} + +static void line_getDigest(char** str, uint32_t* length, Parameter* param) +{ + char* s = *str; + char *p = s + *length - 1; + for ( ; p >= s; --p ) + { + if ( *p == '\t' ) + { + *length = (uint32_t)(p - s); + return; + } + } +} + +static void gitdiff_getDigest(char** str, uint32_t* length, Parameter* param) +{ + if ( param->mode == 0 ) { + uint32_t len = 5; + *str += len; + *length -= len; + } + else { + file_getDigest(str, length, param); + } +} + +/** + * fuzzyMatchPart(engine, source, pattern, category, param, is_name_only=False, sort_results=True) + * + * `is_name_only` is optional, it defaults to `False`, which indicates using the full path matching algorithm. + * `sort_results` is optional, it defaults to `True`, which indicates whether to sort the results. + * + * return a tuple, (a list of corresponding weight, a sorted list of items from `source` that match `pattern`). + */ +static PyObject* fuzzyEngine_fuzzyMatchPart(PyObject* self, PyObject* args, PyObject* kwargs) +{ + PyObject* py_engine = NULL; + PyObject* py_source = NULL; + PyObject* py_patternCtxt = NULL; + PyObject* py_param = NULL; + uint32_t category; + uint8_t is_name_only = 0; + uint8_t sort_results = 1; + static char* kwlist[] = {"engine", "source", "pattern", "category", "param", "is_name_only", "sort_results", NULL}; + + if ( !PyArg_ParseTupleAndKeywords(args, kwargs, "OOOIO|bb:fuzzyMatch", kwlist, &py_engine, &py_source, + &py_patternCtxt, &category, &py_param, &is_name_only, &sort_results) ) + return NULL; + + FuzzyEngine* pEngine = (FuzzyEngine*)PyCapsule_GetPointer(py_engine, NULL); + if ( !pEngine ) + return NULL; + + if ( !PyList_Check(py_source) ) + { + PyErr_SetString(PyExc_TypeError, "parameter `source` must be a list."); + return NULL; + } + + uint32_t source_size = (uint32_t)PyList_Size(py_source); + if ( source_size == 0 ) + { + return Py_BuildValue("([],[])"); + } + + pEngine->pPattern_ctxt = (PatternContext*)PyCapsule_GetPointer(py_patternCtxt, NULL); + if ( !pEngine->pPattern_ctxt ) + return NULL; + + pEngine->is_name_only = is_name_only; + + uint32_t max_task_count = MAX_TASK_COUNT(pEngine->cpu_count); + uint32_t chunk_size = (source_size + max_task_count - 1) / max_task_count; + uint32_t task_count = (source_size + chunk_size - 1) / chunk_size; + if ( chunk_size == 1 || pEngine->cpu_count == 1 ) + { + chunk_size = source_size; + task_count = 1; + } + + pEngine->source = (FeString*)malloc(source_size * sizeof(FeString)); + if ( !pEngine->source ) + { + fprintf(stderr, "Out of memory at %s:%d\n", __FILE__, __LINE__); + return NULL; + } + + TaskItem* tasks = (TaskItem*)malloc(task_count * sizeof(TaskItem)); + if ( !tasks ) + { + free(pEngine->source); + fprintf(stderr, "Out of memory at %s:%d\n", __FILE__, __LINE__); + return NULL; + } + + pEngine->results = (FeResult*)malloc(source_size * sizeof(FeResult)); + if ( !pEngine->results ) + { + free(pEngine->source); + free(tasks); + fprintf(stderr, "Out of memory at %s:%d\n", __FILE__, __LINE__); + return NULL; + } + + FeResult* results = pEngine->results; + + if ( !pEngine->threads ) + { +#if defined(_MSC_VER) + pEngine->threads = (HANDLE*)malloc(pEngine->cpu_count * sizeof(HANDLE)); +#else + pEngine->threads = (pthread_t*)malloc(pEngine->cpu_count * sizeof(pthread_t)); +#endif + if ( !pEngine->threads ) + { + free(pEngine->source); + free(tasks); + free(results); + fprintf(stderr, "Out of memory at %s:%d\n", __FILE__, __LINE__); + return NULL; + } + + uint32_t i = 0; + for ( ; i < pEngine->cpu_count; ++i) + { +#if defined(_MSC_VER) + pEngine->threads[i] = CreateThread(NULL, 0, _worker, pEngine, 0, NULL); + if ( !pEngine->threads[i] ) +#else + int ret = pthread_create(&pEngine->threads[i], NULL, _worker, pEngine); + if ( ret != 0 ) +#endif + { + free(pEngine->source); + free(tasks); + free(results); + free(pEngine->threads); + fprintf(stderr, "pthread_create error!\n"); + return NULL; + } + } + } + +#if defined(_MSC_VER) + QUEUE_SET_TASK_COUNT(pEngine->task_queue, task_count); +#endif + + uint32_t i = 0; + for ( ; i < task_count; ++i ) + { + uint32_t offset = i * chunk_size; + uint32_t length = MIN(chunk_size, source_size - offset); + + tasks[i].function = GET_WEIGHT; + tasks[i].offset = offset; + tasks[i].length = length; + + uint32_t j = 0; + for ( ; j < length; ++j ) + { + FeString *s = pEngine->source + offset + j; + PyObject* item = PyList_GET_ITEM(py_source, offset + j); + if ( pyObject_ToStringAndSize(item, &s->str, &s->len) < 0 ) + { + free(pEngine->source); + free(tasks); + free(results); + fprintf(stderr, "pyObject_ToStringAndSize error!\n"); + return NULL; + } + + switch ( category ) + { + case Category_Rg: + { + RgParameter* param = (RgParameter*)PyCapsule_GetPointer(py_param, NULL); + if ( !param ) + { + free(pEngine->source); + free(tasks); + free(results); + fprintf(stderr, "PyCapsule_GetPointer error!\n"); + return NULL; + } + rg_getDigest(&s->str, &s->len, param); + break; + } + case Category_Tag: + tag_getDigest(&s->str, &s->len, (Parameter*)PyCapsule_GetPointer(py_param, NULL)); + break; + case Category_File: + file_getDigest(&s->str, &s->len, (Parameter*)PyCapsule_GetPointer(py_param, NULL)); + break; + case Category_Gtags: + { + GtagsParameter* param = (GtagsParameter*)PyCapsule_GetPointer(py_param, NULL); + if ( !param ) + { + free(pEngine->source); + free(tasks); + free(results); + fprintf(stderr, "PyCapsule_GetPointer error!\n"); + return NULL; + } + gtags_getDigest(&s->str, &s->len, param); + break; + } + case Category_Line: + line_getDigest(&s->str, &s->len, (Parameter*)PyCapsule_GetPointer(py_param, NULL)); + break; + case Category_GitDiff: + gitdiff_getDigest(&s->str, &s->len, (Parameter*)PyCapsule_GetPointer(py_param, NULL)); + break; + } + } + + QUEUE_PUT(pEngine->task_queue, tasks + i); + } + + QUEUE_JOIN(pEngine->task_queue); /* blocks until all tasks have finished */ + + uint32_t results_count = 0; + for ( i = 0; i < source_size; ++i ) + { + if ( results[i].weight > MIN_WEIGHT ) + { + if ( i > results_count ) + { + results[results_count] = results[i]; + } + ++results_count; + } + } + + if ( results_count == 0 ) + { + free(pEngine->source); + free(tasks); + free(results); + return Py_BuildValue("([],[])"); + } + + if ( sort_results ) + { + if ( task_count == 1 || results_count < 60000 ) + { + qsort(results, results_count, sizeof(FeResult), compare); + } + else + { + chunk_size = (results_count + task_count - 1) / task_count; + if ( chunk_size < 2000 ) + { + chunk_size = (results_count + (task_count >> 1) - 1) / (task_count >> 1); + } + task_count = (results_count + chunk_size - 1) / chunk_size; + FeResult* buffer = (FeResult*)malloc(chunk_size * (task_count >> 1) * sizeof(FeResult)); + if ( !buffer ) + { + free(pEngine->source); + free(tasks); + free(results); + fprintf(stderr, "Out of memory at %s:%d\n", __FILE__, __LINE__); + return NULL; + } +#if defined(_MSC_VER) + QUEUE_SET_TASK_COUNT(pEngine->task_queue, task_count); +#endif + for ( i = 0; i < task_count; ++i ) + { + uint32_t offset = i * chunk_size; + uint32_t length = MIN(chunk_size, results_count - offset); + + tasks[i].function = Q_SORT; + tasks[i].offset = offset; + tasks[i].length = length; + QUEUE_PUT(pEngine->task_queue, tasks + i); + } + + QUEUE_JOIN(pEngine->task_queue); /* blocks until all tasks have finished */ + + MergeTaskItem* merge_tasks = NULL; + merge_tasks = (MergeTaskItem*)malloc(task_count * sizeof(MergeTaskItem)); + if ( !merge_tasks ) + { + free(pEngine->source); + free(tasks); + free(results); + free(buffer); + fprintf(stderr, "Out of memory at %s:%d\n", __FILE__, __LINE__); + return NULL; + } + + while ( chunk_size < results_count ) + { + uint32_t q = results_count / (chunk_size << 1); + uint32_t r = results_count % (chunk_size << 1); +#if defined(_MSC_VER) + QUEUE_SET_TASK_COUNT(pEngine->task_queue, q + r/chunk_size); +#endif + for ( i = 0; i < q; ++i ) + { + merge_tasks[i].function = MERGE; + merge_tasks[i].offset_1 = i * (chunk_size << 1); + merge_tasks[i].length_1 = chunk_size; + merge_tasks[i].length_2 = chunk_size; + merge_tasks[i].buffer = buffer + (merge_tasks[i].offset_1 >> 1); /* buffer + i * chunk_size */ + QUEUE_PUT(pEngine->task_queue, merge_tasks + i); + } + + if ( r > chunk_size ) + { + merge_tasks[i].function = MERGE; + merge_tasks[i].offset_1 = i * (chunk_size << 1); + merge_tasks[i].length_1 = chunk_size; + merge_tasks[i].length_2 = r - chunk_size; + merge_tasks[i].buffer = buffer + (merge_tasks[i].offset_1 >> 1); /* buffer + i * chunk_size */ + QUEUE_PUT(pEngine->task_queue, merge_tasks + i); + } + + QUEUE_JOIN(pEngine->task_queue); /* blocks until all tasks have finished */ + + chunk_size <<= 1; + } + + free(buffer); + free(merge_tasks); + } + } + + weight_t* weights = (weight_t*)malloc(results_count * sizeof(weight_t)); + if ( !weights ) + { + free(pEngine->source); + free(tasks); + free(results); + fprintf(stderr, "Out of memory at %s:%d\n", __FILE__, __LINE__); + return NULL; + } + + PyObject* text_list = PyList_New(results_count); + if ( task_count == 1 || results_count < 40000 ) + { + for ( i = 0; i < results_count; ++i ) + { + weights[i] = results[i].weight; + /* PyList_SET_ITEM() steals a reference to item. */ + /* PySequence_ITEM() return value: New reference. */ + PyList_SET_ITEM(text_list, i, PySequence_ITEM(py_source, results[i].index)); + } + } + else + { + chunk_size = (results_count + task_count - 1) / task_count; + if ( chunk_size < 8000 ) + { + chunk_size = (results_count + (task_count >> 1) - 1) / (task_count >> 1); + } + task_count = (results_count + chunk_size - 1) / chunk_size; + + PySetTaskItem* py_set_tasks = NULL; + py_set_tasks = (PySetTaskItem*)malloc(task_count * sizeof(PySetTaskItem)); + if ( !py_set_tasks ) + { + free(pEngine->source); + free(tasks); + free(results); + fprintf(stderr, "Out of memory at %s:%d\n", __FILE__, __LINE__); + return NULL; + } + +#if defined(_MSC_VER) + QUEUE_SET_TASK_COUNT(pEngine->task_queue, task_count); +#endif + for ( i = 0; i < task_count; ++i ) + { + uint32_t offset = i * chunk_size; + uint32_t length = MIN(chunk_size, results_count - offset); + + py_set_tasks[i].function = PY_SET_ITEM; + py_set_tasks[i].offset = offset; + py_set_tasks[i].length = length; + py_set_tasks[i].weights = weights; + py_set_tasks[i].text_list = text_list; + py_set_tasks[i].py_source = py_source; + QUEUE_PUT(pEngine->task_queue, py_set_tasks + i); + } + + QUEUE_JOIN(pEngine->task_queue); /* blocks until all tasks have finished */ + + free(py_set_tasks); + } + + free(pEngine->source); + free(tasks); + free(results); + + return Py_BuildValue("(NN)", createWeights(weights), text_list); +} + +static PyMethodDef fuzzyEngine_Methods[] = +{ + { "createFuzzyEngine", (PyCFunction)fuzzyEngine_createFuzzyEngine, METH_VARARGS | METH_KEYWORDS, "" }, + { "closeFuzzyEngine", (PyCFunction)fuzzyEngine_closeFuzzyEngine, METH_VARARGS, "" }, + { "initPattern", (PyCFunction)fuzzyEngine_initPattern, METH_VARARGS, "initialize the pattern." }, + { "fuzzyMatch", (PyCFunction)fuzzyEngine_fuzzyMatch, METH_VARARGS | METH_KEYWORDS, "" }, + { "fuzzyMatchEx", (PyCFunction)fuzzyEngine_fuzzyMatchEx, METH_VARARGS | METH_KEYWORDS, "" }, + { "fuzzyMatchPart", (PyCFunction)fuzzyEngine_fuzzyMatchPart, METH_VARARGS | METH_KEYWORDS, "" }, + { "getHighlights", (PyCFunction)fuzzyEngine_getHighlights, METH_VARARGS | METH_KEYWORDS, "" }, + { "guessMatch", (PyCFunction)fuzzyEngine_guessMatch, METH_VARARGS | METH_KEYWORDS, "" }, + { "merge", (PyCFunction)fuzzyEngine_merge, METH_VARARGS, "" }, + { "createRgParameter", (PyCFunction)fuzzyEngine_createRgParameter, METH_VARARGS, "" }, + { "createParameter", (PyCFunction)fuzzyEngine_createParameter, METH_VARARGS, "" }, + { "createGtagsParameter", (PyCFunction)fuzzyEngine_createGtagsParameter, METH_VARARGS, "" }, + { NULL, NULL, 0, NULL } +}; + +#if PY_MAJOR_VERSION >= 3 + +static struct PyModuleDef fuzzyEngine_module = +{ + PyModuleDef_HEAD_INIT, + "fuzzyEngine", /* name of module */ + "fuzzy matching algorithm which takes full advantage of the cpu cores.", + -1, + fuzzyEngine_Methods +}; + +PyMODINIT_FUNC PyInit_fuzzyEngine(void) +{ + PyObject* module = NULL; + module = PyModule_Create(&fuzzyEngine_module); + + if ( !module ) + return NULL; + + if ( PyModule_AddObject(module, "Category_Rg", Py_BuildValue("I", Category_Rg)) ) + { + Py_DECREF(module); + return NULL; + } + + if ( PyModule_AddObject(module, "Category_Tag", Py_BuildValue("I", Category_Tag)) ) + { + Py_DECREF(module); + return NULL; + } + + if ( PyModule_AddObject(module, "Category_File", Py_BuildValue("I", Category_File)) ) + { + Py_DECREF(module); + return NULL; + } + + if ( PyModule_AddObject(module, "Category_Gtags", Py_BuildValue("I", Category_Gtags)) ) + { + Py_DECREF(module); + return NULL; + } + + if ( PyModule_AddObject(module, "Category_Line", Py_BuildValue("I", Category_Line)) ) + { + Py_DECREF(module); + return NULL; + } + + if ( PyModule_AddObject(module, "Category_GitDiff", Py_BuildValue("I", Category_GitDiff)) ) + { + Py_DECREF(module); + return NULL; + } + + return module; +} + +#else + +PyMODINIT_FUNC initfuzzyEngine(void) +{ + PyObject* module = NULL; + module = Py_InitModule("fuzzyEngine", fuzzyEngine_Methods); + + if ( !module ) + return; + + if ( PyModule_AddObject(module, "Category_Rg", Py_BuildValue("I", Category_Rg)) ) + { + Py_DECREF(module); + return; + } + + if ( PyModule_AddObject(module, "Category_Tag", Py_BuildValue("I", Category_Tag)) ) + { + Py_DECREF(module); + return; + } + + if ( PyModule_AddObject(module, "Category_File", Py_BuildValue("I", Category_File)) ) + { + Py_DECREF(module); + return; + } + + if ( PyModule_AddObject(module, "Category_Gtags", Py_BuildValue("I", Category_Gtags)) ) + { + Py_DECREF(module); + return; + } + + if ( PyModule_AddObject(module, "Category_Line", Py_BuildValue("I", Category_Line)) ) + { + Py_DECREF(module); + return; + } + + if ( PyModule_AddObject(module, "Category_GitDiff", Py_BuildValue("I", Category_GitDiff)) ) + { + Py_DECREF(module); + return; + } +} + +#endif + diff --git a/autoload/leaderf/fuzzyMatch_C/fuzzyMatch.c b/autoload/leaderf/fuzzyMatch_C/fuzzyMatch.c index ae4889d6..77d1c024 100644 --- a/autoload/leaderf/fuzzyMatch_C/fuzzyMatch.c +++ b/autoload/leaderf/fuzzyMatch_C/fuzzyMatch.c @@ -151,6 +151,14 @@ #endif +#if defined(_MSC_VER) + #define THREAD_LOCAL thread_local +#else + #define THREAD_LOCAL __thread +#endif + +static THREAD_LOCAL uint64_t TEXT_MASK[256*2]; + static uint16_t valTable[64] = { 0, 1, 4, 7, 13, 19, 25, 31, @@ -740,12 +748,20 @@ float getWeight(const char* text, uint16_t text_len, return MIN_WEIGHT; col_num = (text_len + 63) >> 6; /* (text_len + 63)/64 */ - /* uint64_t text_mask[256][col_num] */ - text_mask = (uint64_t*)calloc(col_num << 8, sizeof(uint64_t)); - if ( !text_mask ) + if (col_num <= 2) { - fprintf(stderr, "Out of memory in getWeight()!\n"); - return MIN_WEIGHT; + memset(TEXT_MASK, 0, sizeof(TEXT_MASK)); + text_mask = TEXT_MASK; + } + else + { + /* uint64_t text_mask[256][col_num] */ + text_mask = (uint64_t*)calloc(col_num << 8, sizeof(uint64_t)); + if ( !text_mask ) + { + fprintf(stderr, "Out of memory in getWeight()!\n"); + return MIN_WEIGHT; + } } char c; for ( i = first_char_pos; i <= last_char_pos; ++i ) @@ -818,12 +834,20 @@ float getWeight(const char* text, uint16_t text_len, return MIN_WEIGHT; col_num = (text_len + 63) >> 6; - /* uint64_t text_mask[256][col_num] */ - text_mask = (uint64_t*)calloc(col_num << 8, sizeof(uint64_t)); - if ( !text_mask ) + if (col_num <= 2) { - fprintf(stderr, "Out of memory in getWeight()!\n"); - return MIN_WEIGHT; + memset(TEXT_MASK, 0, sizeof(TEXT_MASK)); + text_mask = TEXT_MASK; + } + else + { + /* uint64_t text_mask[256][col_num] */ + text_mask = (uint64_t*)calloc(col_num << 8, sizeof(uint64_t)); + if ( !text_mask ) + { + fprintf(stderr, "Out of memory in getWeight()!\n"); + return MIN_WEIGHT; + } } char c; int16_t i; @@ -855,7 +879,10 @@ float getWeight(const char* text, uint16_t text_len, if ( j < pattern_len ) { - free(text_mask); + if (col_num > 2) + { + free(text_mask); + } return MIN_WEIGHT; } @@ -879,7 +906,10 @@ float getWeight(const char* text, uint16_t text_len, if ( j < pPattern_ctxt->actual_pattern_len ) { - free(text_mask); + if (col_num > 2) + { + free(text_mask); + } return MIN_WEIGHT; } } @@ -900,7 +930,10 @@ float getWeight(const char* text, uint16_t text_len, uint16_t beg = pVal->beg; uint16_t end = pVal->end; - free(text_mask); + if (col_num > 2) + { + free(text_mask); + } return score + (1 >> beg) + 1.0f/(beg + end) + 1.0f/text_len; } @@ -910,7 +943,10 @@ float getWeight(const char* text, uint16_t text_len, float score = pVal->score; uint16_t beg = pVal->beg; - free(text_mask); + if (col_num > 2) + { + free(text_mask); + } return score + (float)(pattern_len<<1)/text_len + (float)pattern_len/(text_len - beg); } @@ -1499,12 +1535,20 @@ HighlightGroup* getHighlights(const char* text, } col_num = (text_len + 63) >> 6; /* (text_len + 63)/64 */ - /* uint64_t text_mask[256][col_num] */ - text_mask = (uint64_t*)calloc(col_num << 8, sizeof(uint64_t)); - if ( !text_mask ) + if (col_num <= 2) { - fprintf(stderr, "Out of memory in getHighlights()!\n"); - return NULL; + memset(TEXT_MASK, 0, sizeof(TEXT_MASK)); + text_mask = TEXT_MASK; + } + else + { + /* uint64_t text_mask[256][col_num] */ + text_mask = (uint64_t*)calloc(col_num << 8, sizeof(uint64_t)); + if ( !text_mask ) + { + fprintf(stderr, "Out of memory in getHighlights()!\n"); + return NULL; + } } char c; for ( i = first_char_pos; i <= last_char_pos; ++i ) @@ -1570,12 +1614,20 @@ HighlightGroup* getHighlights(const char* text, } col_num = (text_len + 63) >> 6; - /* uint64_t text_mask[256][col_num] */ - text_mask = (uint64_t*)calloc(col_num << 8, sizeof(uint64_t)); - if ( !text_mask ) + if (col_num <= 2) { - fprintf(stderr, "Out of memory in getHighlights()!\n"); - return NULL; + memset(TEXT_MASK, 0, sizeof(TEXT_MASK)); + text_mask = TEXT_MASK; + } + else + { + /* uint64_t text_mask[256][col_num] */ + text_mask = (uint64_t*)calloc(col_num << 8, sizeof(uint64_t)); + if ( !text_mask ) + { + fprintf(stderr, "Out of memory in getHighlights()!\n"); + return NULL; + } } char c; @@ -1612,7 +1664,10 @@ HighlightGroup* getHighlights(const char* text, if ( !groups ) { fprintf(stderr, "Out of memory in getHighlights()!\n"); - free(text_mask); + if (col_num > 2) + { + free(text_mask); + } return NULL; } @@ -1622,7 +1677,10 @@ HighlightGroup* getHighlights(const char* text, else pGroup = evaluateHighlights(&text_ctxt, pPattern_ctxt, 0, groups); - free(text_mask); + if (col_num > 2) + { + free(text_mask); + } uint16_t i; for ( i = 0; i < pattern_len; ++i ) { diff --git a/autoload/leaderf/fuzzyMatch_C/fuzzyMatch.cpp b/autoload/leaderf/fuzzyMatch_C/fuzzyMatch.cpp new file mode 100644 index 00000000..77d1c024 --- /dev/null +++ b/autoload/leaderf/fuzzyMatch_C/fuzzyMatch.cpp @@ -0,0 +1,2000 @@ +/** + * Copyright (C) 2017 Yggdroot + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PY_SSIZE_T_CLEAN + #define PY_SSIZE_T_CLEAN +#endif + +#include +#include +#include +#include +#include +#include "fuzzyMatch.h" + + +#if defined(_MSC_VER) && \ + (defined(_M_IX86) || defined(_M_AMD64) || defined(_M_X64)) + + #define FM_BITSCAN_WINDOWS + + #include + #pragma intrinsic(_BitScanReverse) + + #if defined(_M_AMD64) || defined(_M_X64) + #define FM_BITSCAN_WINDOWS64 + #pragma intrinsic(_BitScanReverse64) + #pragma intrinsic(_BitScanForward64) + #endif + +#endif + +#if defined(FM_BITSCAN_WINDOWS) + + uint32_t FM_BitLength(uint64_t x) + { + unsigned long index; + #if defined(FM_BITSCAN_WINDOWS64) + if ( _BitScanReverse64(&index, x) ) + return index + 1; + else + return 0; + #else + if ( (x & 0xFFFFFFFF00000000) == 0 ) + { + if ( !_BitScanReverse(&index, (unsigned long)x) ) + return 0; + else + return index + 1; + } + else + { + _BitScanReverse(&index, (unsigned long)(x >> 32)); + return index + 33; + } + #endif + } + + #define FM_BIT_LENGTH(x) FM_BitLength(x) + + #if defined(FM_BITSCAN_WINDOWS64) + + uint16_t FM_ctz(uint64_t x) { + unsigned long index; + if (_BitScanForward64(&index, x)) { + return (uint16_t)index; + } + return 64; + } + #define FM_CTZ(x) FM_ctz(x) + + #endif +#elif defined(__GNUC__) + + #define FM_BIT_LENGTH(x) ((uint32_t)(8 * sizeof(unsigned long long) - __builtin_clzll(x))) + #define FM_CTZ(x) __builtin_ctzll(x) + +#elif defined(__clang__) + + #if __has_builtin(__builtin_clzll) + #define FM_BIT_LENGTH(x) ((uint32_t)(8 * sizeof(unsigned long long) - __builtin_clzll(x))) + #define FM_CTZ(x) __builtin_ctzll(x) + #endif + +#endif + +#if !defined(FM_BIT_LENGTH) + + static uint8_t clz_table_8bit[256] = + { + 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + + uint32_t FM_BIT_LENGTH(uint64_t x) + { + uint32_t n = 0; + if ((x & 0xFFFFFFFF00000000) == 0) {n = 32; x <<= 32;} + if ((x & 0xFFFF000000000000) == 0) {n += 16; x <<= 16;} + if ((x & 0xFF00000000000000) == 0) {n += 8; x <<= 8;} + n += (uint32_t)clz_table_8bit[x >> 56]; + + return 64 - n; + } + +#endif + +#if !defined(FM_CTZ) + + static uint64_t deBruijn = 0x022FDD63CC95386D; + + static uint8_t MultiplyDeBruijnBitPosition[64] = + { + 0, 1, 2, 53, 3, 7, 54, 27, + 4, 38, 41, 8, 34, 55, 48, 28, + 62, 5, 39, 46, 44, 42, 22, 9, + 24, 35, 59, 56, 49, 18, 29, 11, + 63, 52, 6, 26, 37, 40, 33, 47, + 61, 45, 43, 21, 23, 58, 17, 10, + 51, 25, 36, 32, 60, 20, 57, 16, + 50, 31, 19, 15, 30, 14, 13, 12, + }; + + #define FM_CTZ(x) MultiplyDeBruijnBitPosition[((uint64_t)((x) & -(int64_t)(x)) * deBruijn) >> 58] + +#endif + +#if defined(_MSC_VER) + #define THREAD_LOCAL thread_local +#else + #define THREAD_LOCAL __thread +#endif + +static THREAD_LOCAL uint64_t TEXT_MASK[256*2]; + +static uint16_t valTable[64] = +{ + 0, 1, 4, 7, 13, 19, 25, 31, + 37, 43, 49, 55, 61, 67, 73, 79, + 85, 91, 97, 103, 109, 115, 121, 127, + 133, 139, 145, 151, 157, 163, 169, 175, + 181, 187, 193, 199, 205, 211, 217, 223, + 229, 235, 241, 247, 253, 259, 265, 271, + 277, 283, 289, 295, 301, 307, 313, 319, + 325, 331, 337, 343, 349, 355, 361, 367 +}; + +typedef struct TextContext +{ + const char* text; + uint64_t* text_mask; + uint16_t text_len; + uint16_t col_num; + uint16_t offset; +}TextContext; + +typedef struct ValueElements +{ + float score; + uint16_t beg; + uint16_t end; +}ValueElements; + +PatternContext* initPattern(const char* pattern, uint16_t pattern_len) +{ + PatternContext* pPattern_ctxt = (PatternContext*)malloc(sizeof(PatternContext)); + if ( !pPattern_ctxt ) + { + fprintf(stderr, "Out of memory in initPattern()!\n"); + return NULL; + } + pPattern_ctxt->actual_pattern_len = pattern_len; + if ( pattern_len >= 64 ) + { + pattern_len = 63; + } + pPattern_ctxt->pattern = pattern; + pPattern_ctxt->pattern_len = pattern_len; + memset(pPattern_ctxt->pattern_mask, -1, sizeof(pPattern_ctxt->pattern_mask)); + + uint16_t i; + for ( i = 0; i < pattern_len; ++i ) + { + pPattern_ctxt->pattern_mask[(uint8_t)pattern[i]] ^= (1LL << i); + if ( islower(pattern[i]) && pPattern_ctxt->pattern_mask[(uint8_t)toupper(pattern[i])] != -1 ) + { + pPattern_ctxt->pattern_mask[(uint8_t)toupper(pattern[i])] ^= (1LL << i); + } + } + pPattern_ctxt->is_lower = 1; + + for ( i = 0; i < pattern_len; ++i ) + { + if ( isupper(pattern[i]) ) + { + pPattern_ctxt->is_lower = 0; + break; + } + } + + return pPattern_ctxt; +} + +ValueElements* evaluate_nameOnly(TextContext* pText_ctxt, + PatternContext* pPattern_ctxt, + uint16_t k, + ValueElements val[]) +{ + uint64_t* text_mask = pText_ctxt->text_mask; + uint16_t col_num = pText_ctxt->col_num; + uint16_t j = pText_ctxt->offset; + + const char* pattern = pPattern_ctxt->pattern; + uint16_t base_offset = pattern[k] * col_num; + uint64_t x = text_mask[base_offset + (j >> 6)] >> (j & 63); + uint16_t i = 0; + + if ( x == 0 ) + { + uint64_t bits = 0; + uint16_t col = 0; + for ( col = (j >> 6) + 1; col < col_num; ++col ) + { + if ( (bits = text_mask[base_offset + col]) != 0 ) + break; + } + if ( bits == 0 ) + { + memset(val, 0, sizeof(ValueElements)); + return val; + } + else + { + i = (col << 6) + FM_CTZ(bits); + } + } + else + { + i = j + FM_CTZ(x); + } + + /** + * e.g., text = '~abc~~AbcD~~', pattern = 'abcd' + * j > 0 means val[k].beg > 0, means k in val + */ + if ( j > 0 && val[k].beg >= j ) + return val + k; + + uint16_t beg = 0; + uint16_t end = 0; + + uint16_t max_prefix_score = 0; + float max_score = MIN_WEIGHT; + + const char* text = pText_ctxt->text; + uint16_t text_len = pText_ctxt->text_len; + uint16_t pattern_len = pPattern_ctxt->pattern_len - k; + int64_t* pattern_mask = pPattern_ctxt->pattern_mask; + + uint16_t special = 0; + if ( i == 0 ) + special = 3; + else if ( isupper(text[i]) ) + special = !isupper(text[i-1]) || (i+1 < text_len && islower(text[i+1])) ? 3 : 0; + /* else if ( text[i-1] == '_' || text[i-1] == '-' || text[i-1] == ' ' ) */ + /* special = 3; */ + /* else if ( text[i-1] == '.' ) */ + /* special = 3; */ + else if ( !isalnum(text[i-1]) ) + special = 3; + else + special = 0; + ++i; + int64_t d = -2; /* ~1 */ + int64_t last = d; + while ( i < text_len ) + { + last = d; + char c = text[i]; + /* c in pattern */ + if ( pattern_mask[(uint8_t)c] != -1 ) + d = (d << 1) | (pattern_mask[(uint8_t)c] >> k); + /** + * text = 'xxABC', pattern = 'abc'; text[i] == 'B' + * text = 'xxABC', pattern = 'abc'; text[i] == 'C' + * NOT text = 'xxABCd', pattern = 'abc'; text[i] == 'C' + * 'Cd' is considered as a word + */ + else if ( isupper(text[i-1]) && pattern_mask[(uint8_t)tolower(c)] != -1 + && (i+1 == text_len || !islower(text[i+1])) ) + d = (d << 1) | (pattern_mask[(uint8_t)tolower(c)] >> k); + else + d = ~0; + + if ( d >= last ) + { + float score = MIN_WEIGHT; + uint16_t end_pos = 0; + uint16_t n = FM_BIT_LENGTH(~last); + /* e.g., text = '~~abcd~~~~', pattern = 'abcd' */ + if ( n == pattern_len ) + { + score = (float)(special > 0 ? (n > 1 ? valTable[n+1] : valTable[n]) + special : valTable[n]); + if ( special > 0 ) + { + val[k].score = score; + val[k].beg = i - n; + val[k].end = i; + return val + k; + } + else + end_pos = i; + } + else + { + uint16_t prefix_score = special > 0 ? (n > 1 ? valTable[n+1] : valTable[n]) + special : valTable[n]; + if ( prefix_score > max_prefix_score ) + { + max_prefix_score = prefix_score; + pText_ctxt->offset = i; + ValueElements* pVal = evaluate_nameOnly(pText_ctxt, pPattern_ctxt, k + n, val); + if ( pVal->end ) + { + score = prefix_score + pVal->score - 0.2f * (pVal->beg - i); + end_pos = pVal->end; + } + } + } + if ( score > max_score ) + { + max_score = score; + beg = i - n; + end = end_pos; + } + /* e.g., text = '~_ababc~~~~', pattern = 'abc' */ + special = 0; + } + + /* + * e.g., text = 'a~c~~~~ab~c', pattern = 'abc', + * to find the index of the second 'a' + * `d == last` is for the case when text = 'kpi_oos1', pattern = 'kos' + */ + if ( d == ~0 || d == last ) + { + x = text_mask[base_offset + (i >> 6)] >> (i & 63); + + if ( x == 0 ) + { + uint64_t bits = 0; + uint16_t col = 0; + for ( col = (i >> 6) + 1; col < col_num; ++col ) + { + if ( (bits = text_mask[base_offset + col]) != 0 ) + break; + } + if ( bits == 0 ) + break; + else + i = (col << 6) + FM_CTZ(bits); + } + else + { + i += FM_CTZ(x); + } + + if ( isupper(text[i]) ) + special = !isupper(text[i-1]) || (i+1 < text_len && islower(text[i+1])) ? 3 : 0; + /* else if ( text[i-1] == '_' || text[i-1] == '-' || text[i-1] == ' ' ) */ + /* special = 3; */ + /* else if ( text[i-1] == '.' ) */ + /* special = 3; */ + else if ( !isalnum(text[i-1]) ) + special = 3; + else + special = 0; + d = -2; + ++i; + } + else + ++i; + } + + /* e.g., text = '~~~~abcd', pattern = 'abcd' */ + if ( i == text_len ) + { + if ( ~d >> (pattern_len - 1) ) + { + float score = (float)(special > 0 ? (pattern_len > 1 ? valTable[pattern_len + 1] : valTable[pattern_len]) + special + : valTable[pattern_len]); + if ( score > max_score ) + { + max_score = score; + beg = i - pattern_len; + end = i; + } + } + } + + val[k].score = max_score; + val[k].beg = beg; + val[k].end = end; + + return val + k; +} + +ValueElements* evaluate(TextContext* pText_ctxt, + PatternContext* pPattern_ctxt, + uint16_t k, + ValueElements val[]) +{ + uint64_t* text_mask = pText_ctxt->text_mask; + uint16_t col_num = pText_ctxt->col_num; + uint16_t j = pText_ctxt->offset; + + const char* pattern = pPattern_ctxt->pattern; + uint16_t base_offset = pattern[k] * col_num; + uint64_t x = text_mask[base_offset + (j >> 6)] >> (j & 63); + uint16_t i = 0; + + if ( x == 0 ) + { + uint64_t bits = 0; + uint16_t col = 0; + for ( col = (j >> 6) + 1; col < col_num; ++col ) + { + if ( (bits = text_mask[base_offset + col]) != 0 ) + break; + } + if ( bits == 0 ) + { + return val; + } + else + { + i = (col << 6) + FM_CTZ(bits); + } + } + else + { + i = j + FM_CTZ(x); + } + + /** + * e.g., text = '~abc~~AbcD~~', pattern = 'abcd' + * j > 0 means val[k].beg > 0, means k in val + */ + if ( j > 0 && val[k].beg >= j ) + return val + k; + + uint16_t beg = 0; + uint16_t end = 0; + + uint16_t max_prefix_score = 0; + float max_score = MIN_WEIGHT; + + const char* text = pText_ctxt->text; + uint16_t text_len = pText_ctxt->text_len; + uint16_t pattern_len = pPattern_ctxt->pattern_len - k; + int64_t* pattern_mask = pPattern_ctxt->pattern_mask; + + uint16_t special = 0; + if ( i == 0 ) + special = 5; +#if defined(_MSC_VER) + else if ( text[i-1] == '\\' || text[i-1] == '/' ) +#else + else if ( text[i-1] == '/' ) +#endif + special = k == 0 ? 5 : 3; + else if ( isupper(text[i]) ) + special = (!isupper(text[i-1]) || (i+1 < text_len && islower(text[i+1])) ? + (i < 5 ? 5 : 3) : 0); + /* else if ( text[i-1] == '_' || text[i-1] == '-' || text[i-1] == ' ' ) */ + /* special = 3; */ + /* else if ( text[i-1] == '.' ) */ + /* special = 3; */ + else if ( !isalnum(text[i-1]) ) + /* if there is an icon at the beginning, `if ( i == 0 )` won't meet */ + special = i < 5 ? 5 : 3; + else + special = 0; + ++i; + int64_t d = -2; /* ~1 */ + int64_t last = d; + while ( i < text_len ) + { + last = d; + char c = text[i]; + /* c in pattern */ + if ( pattern_mask[(uint8_t)c] != -1 ) + d = (d << 1) | (pattern_mask[(uint8_t)c] >> k); + /** + * text = 'xxABC', pattern = 'abc'; text[i] == 'B' + * text = 'xxABC', pattern = 'abc'; text[i] == 'C' + * NOT text = 'xxABCd', pattern = 'abc'; text[i] == 'C' + * 'Cd' is considered as a word + */ + /* else if ( isupper(text[i-1]) && pattern_mask[(uint8_t)tolower(c)] != -1 */ + /* && (i+1 == text_len || !islower(text[i+1])) ) */ + else if ( pattern_mask[(uint8_t)tolower(c)] != -1 ) + d = (d << 1) | (pattern_mask[(uint8_t)tolower(c)] >> k); + else + d = ~0; + + if ( d >= last ) + { + float score = MIN_WEIGHT; + uint16_t end_pos = 0; + uint16_t n = FM_BIT_LENGTH(~last); + /* e.g., text = '~~abcd~~~~', pattern = 'abcd' */ + if ( n == pattern_len ) + { + score = (float)(special > 0 ? (n > 1 ? valTable[n+1] : valTable[n]) + special : valTable[n]); + if ( (k == 0 && special == 5) || (k > 0 && special > 0) ) + { + val[k].score = score; + val[k].beg = i - n; + val[k].end = i; + return val + k; + } + else + end_pos = i; + } + else + { + uint16_t prefix_score = special > 0 ? (n > 1 ? valTable[n+1] : valTable[n]) + special : valTable[n]; + /** + * e.g., text = 'AbcxxAbcyyde', pattern = 'abcde' + * prefer matching 'Abcyyde' + */ + if ( prefix_score > max_prefix_score + || (special > 0 && prefix_score == max_prefix_score) ) + { + max_prefix_score = prefix_score; + pText_ctxt->offset = i; + ValueElements* pVal = evaluate(pText_ctxt, pPattern_ctxt, k + n, val); + if ( pVal->end ) + { + score = prefix_score + pVal->score - 0.3f * (pVal->beg - i); + end_pos = pVal->end; + } + else + { + break; + } + } + } + + if ( score > max_score ) + { + max_score = score; + beg = i - n; + end = end_pos; + } + /* e.g., text = '~_ababc~~~~', pattern = 'abc' */ + special = 0; + } + + /* + * e.g., text = 'a~c~~~~ab~c', pattern = 'abc', + * to find the index of the second 'a' + * `d == last` is for the case when text = 'kpi_oos1', pattern = 'kos' + */ + if ( d == ~0 || d == last ) + { + x = text_mask[base_offset + (i >> 6)] >> (i & 63); + + if ( x == 0 ) + { + uint64_t bits = 0; + uint16_t col = 0; + for ( col = (i >> 6) + 1; col < col_num; ++col ) + { + if ( (bits = text_mask[base_offset + col]) != 0 ) + break; + } + if ( bits == 0 ) + break; + else + i = (col << 6) + FM_CTZ(bits); + } + else + { + i += FM_CTZ(x); + } + +#if defined(_MSC_VER) + if ( text[i-1] == '\\' || text[i-1] == '/' ) +#else + if ( text[i-1] == '/' ) +#endif + special = k == 0 ? 5 : 3; + else if ( isupper(text[i]) ) + special = !isupper(text[i-1]) || (i+1 < text_len && islower(text[i+1])) ? 3 : 0; + /* else if ( text[i-1] == '_' || text[i-1] == '-' || text[i-1] == ' ' ) */ + /* special = 3; */ + /* else if ( text[i-1] == '.' ) */ + /* special = 3; */ + else if ( !isalnum(text[i-1]) ) + special = 3; + else + special = 0; + d = -2; + ++i; + } + else + ++i; + } + + /* e.g., text = '~~~~abcd', pattern = 'abcd' */ + if ( i == text_len ) + { + if ( ~d >> (pattern_len - 1) ) + { + float score = (float)(special > 0 ? (pattern_len > 1 ? valTable[pattern_len + 1] : valTable[pattern_len]) + special + : valTable[pattern_len]); + if ( score > max_score ) + { + max_score = score; + beg = i - pattern_len; + end = i; + } + } + } + + val[k].score = max_score; + val[k].beg = beg; + val[k].end = end; + + return val + k; +} + +float getWeight(const char* text, uint16_t text_len, + PatternContext* pPattern_ctxt, + uint8_t is_name_only) +{ + if ( !text || !pPattern_ctxt ) + return MIN_WEIGHT; + + uint16_t j = 0; + uint16_t col_num = 0; + uint64_t* text_mask = NULL; + const char* pattern = pPattern_ctxt->pattern; + uint16_t pattern_len = pPattern_ctxt->pattern_len; + int64_t* pattern_mask = pPattern_ctxt->pattern_mask; + char first_char = pattern[0]; + char last_char = pattern[pattern_len - 1]; + + /* maximum number of int16_t is (1 << 15) - 1 */ + if ( text_len >= (1 << 15) ) + { + text_len = (1 << 15) - 1; + } + + if ( pattern_len == 1 ) + { + if ( isupper(first_char) ) + { + int16_t first_char_pos = -1; + int16_t i; + for ( i = 0; i < text_len; ++i ) + { + if ( text[i] == first_char ) + { + first_char_pos = i; + break; + } + } + if ( first_char_pos == -1 ) + return MIN_WEIGHT; + else + return 1.0f/(first_char_pos + 1) + 1.0f/text_len; + } + else + { + int16_t first_char_pos = -1; + int16_t i; + for ( i = 0; i < text_len; ++i ) + { + if ( tolower(text[i]) == first_char ) + { + if ( first_char_pos == -1 ) + first_char_pos = i; + + if ( isupper(text[i]) || i == 0 || !isalnum(text[i-1]) ) + return 2 + 1.0f/(i + 1) + 1.0f/text_len; + } + } + if ( first_char_pos == -1 ) + return MIN_WEIGHT; + else + return 1.0f/(first_char_pos + 1) + 1.0f/text_len; + } + } + + int16_t first_char_pos = -1; + if ( pPattern_ctxt->is_lower ) + { + int16_t i; + for ( i = 0; i < text_len; ++i ) + { + if ( tolower(text[i]) == first_char ) + { + first_char_pos = i; + break; + } + } + if ( first_char_pos == -1 ) + return MIN_WEIGHT; + + int16_t last_char_pos = -1; + for ( i = text_len - 1; i >= first_char_pos; --i ) + { + if ( tolower(text[i]) == last_char ) + { + last_char_pos = i; + break; + } + } + if ( last_char_pos == -1 ) + return MIN_WEIGHT; + + col_num = (text_len + 63) >> 6; /* (text_len + 63)/64 */ + if (col_num <= 2) + { + memset(TEXT_MASK, 0, sizeof(TEXT_MASK)); + text_mask = TEXT_MASK; + } + else + { + /* uint64_t text_mask[256][col_num] */ + text_mask = (uint64_t*)calloc(col_num << 8, sizeof(uint64_t)); + if ( !text_mask ) + { + fprintf(stderr, "Out of memory in getWeight()!\n"); + return MIN_WEIGHT; + } + } + char c; + for ( i = first_char_pos; i <= last_char_pos; ++i ) + { + c = tolower(text[i]); + /* c in pattern */ + if ( pattern_mask[(uint8_t)c] != -1 ) + { + text_mask[(uint8_t)c * col_num + (i >> 6)] |= 1ULL << (i & 63); + if ( j < pattern_len && c == pattern[j] ) + ++j; + } + } + } + else + { + if ( isupper(first_char) ) + { + int16_t i; + for ( i = 0; i < text_len; ++i ) + { + if ( text[i] == first_char ) + { + first_char_pos = i; + break; + } + } + } + else + { + int16_t i; + for ( i = 0; i < text_len; ++i ) + { + if ( tolower(text[i]) == first_char ) + { + first_char_pos = i; + break; + } + } + } + if ( first_char_pos == -1 ) + return MIN_WEIGHT; + + int16_t last_char_pos = -1; + if ( isupper(last_char) ) + { + int16_t i; + for ( i = text_len - 1; i >= first_char_pos; --i ) + { + if ( text[i] == last_char ) + { + last_char_pos = i; + break; + } + } + } + else + { + int16_t i; + for ( i = text_len - 1; i >= first_char_pos; --i ) + { + if ( tolower(text[i]) == last_char ) + { + last_char_pos = i; + break; + } + } + } + if ( last_char_pos == -1 ) + return MIN_WEIGHT; + + col_num = (text_len + 63) >> 6; + if (col_num <= 2) + { + memset(TEXT_MASK, 0, sizeof(TEXT_MASK)); + text_mask = TEXT_MASK; + } + else + { + /* uint64_t text_mask[256][col_num] */ + text_mask = (uint64_t*)calloc(col_num << 8, sizeof(uint64_t)); + if ( !text_mask ) + { + fprintf(stderr, "Out of memory in getWeight()!\n"); + return MIN_WEIGHT; + } + } + char c; + int16_t i; + for ( i = first_char_pos; i <= last_char_pos; ++i ) + { + c = text[i]; + if ( isupper(c) ) + { + /* c in pattern */ + if ( pattern_mask[(uint8_t)c] != -1 ) + text_mask[(uint8_t)c * col_num + (i >> 6)] |= 1ULL << (i & 63); + if ( pattern_mask[(uint8_t)tolower(c)] != -1 ) + text_mask[(uint8_t)tolower(c) * col_num + (i >> 6)] |= 1ULL << (i & 63); + if ( j < pattern_len && c == toupper(pattern[j]) ) + ++j; + } + else + { + /* c in pattern */ + if ( pattern_mask[(uint8_t)c] != -1 ) + { + text_mask[(uint8_t)c * col_num + (i >> 6)] |= 1ULL << (i & 63); + if ( j < pattern_len && c == pattern[j] ) + ++j; + } + } + } + } + + if ( j < pattern_len ) + { + if (col_num > 2) + { + free(text_mask); + } + return MIN_WEIGHT; + } + + if ( pPattern_ctxt->actual_pattern_len >= 64 ) + { + int16_t i; + j = 0; + for ( i = first_char_pos; i < text_len; ++i ) + { + if ( j < pPattern_ctxt->actual_pattern_len ) + { + if ( (pPattern_ctxt->is_lower && tolower(text[i]) == pattern[j]) + || text[i] == pattern[j] ) + { + ++j; + } + } + else + break; + } + + if ( j < pPattern_ctxt->actual_pattern_len ) + { + if (col_num > 2) + { + free(text_mask); + } + return MIN_WEIGHT; + } + } + + TextContext text_ctxt; + text_ctxt.text = text; + text_ctxt.text_len = text_len; + text_ctxt.text_mask = text_mask; + text_ctxt.col_num = col_num; + text_ctxt.offset = 0; + + ValueElements val[64]; + memset(val, 0, sizeof(val)); + if ( is_name_only ) + { + ValueElements* pVal = evaluate_nameOnly(&text_ctxt, pPattern_ctxt, 0, val); + float score = pVal->score; + uint16_t beg = pVal->beg; + uint16_t end = pVal->end; + + if (col_num > 2) + { + free(text_mask); + } + + return score + (1 >> beg) + 1.0f/(beg + end) + 1.0f/text_len; + } + else + { + ValueElements* pVal = evaluate(&text_ctxt, pPattern_ctxt, 0, val); + float score = pVal->score; + uint16_t beg = pVal->beg; + + if (col_num > 2) + { + free(text_mask); + } + + return score + (float)(pattern_len<<1)/text_len + (float)pattern_len/(text_len - beg); + } +} + + +HighlightGroup* evaluateHighlights_nameOnly(TextContext* pText_ctxt, + PatternContext* pPattern_ctxt, + uint16_t k, + HighlightGroup* groups[]) +{ + uint16_t j = pText_ctxt->offset; + + if ( groups[k] && groups[k]->beg >= j ) + return groups[k]; + + uint64_t* text_mask = pText_ctxt->text_mask; + uint16_t col_num = pText_ctxt->col_num; + + const char* pattern = pPattern_ctxt->pattern; + uint16_t base_offset = pattern[k] * col_num; + uint64_t x = text_mask[base_offset + (j >> 6)] >> (j & 63); + uint16_t i = 0; + + if ( x == 0 ) + { + uint64_t bits = 0; + uint16_t col = 0; + for ( col = (j >> 6) + 1; col < col_num; ++col ) + { + if ( (bits = text_mask[base_offset + col]) != 0 ) + break; + } + if ( bits == 0 ) + { + return NULL; + } + else + { + i = (col << 6) + FM_CTZ(bits); + } + } + else + { + i = j + FM_CTZ(x); + } + + uint16_t max_prefix_score = 0; + float max_score = MIN_WEIGHT; + + if ( !groups[k] ) + { + groups[k] = (HighlightGroup*)calloc(1, sizeof(HighlightGroup)); + if ( !groups[k] ) + { + fprintf(stderr, "Out of memory in evaluateHighlights_nameOnly()!\n"); + return NULL; + } + } + else + { + memset(groups[k], 0, sizeof(HighlightGroup)); + } + + HighlightGroup cur_highlights; + memset(&cur_highlights, 0, sizeof(HighlightGroup)); + + const char* text = pText_ctxt->text; + uint16_t text_len = pText_ctxt->text_len; + uint16_t pattern_len = pPattern_ctxt->pattern_len - k; + int64_t* pattern_mask = pPattern_ctxt->pattern_mask; + + uint16_t special = 0; + if ( i == 0 ) + special = 3; + else if ( isupper(text[i]) ) + special = !isupper(text[i-1]) || (i+1 < text_len && islower(text[i+1])) ? 3 : 0; + /* else if ( text[i-1] == '_' || text[i-1] == '-' || text[i-1] == ' ' ) */ + /* special = 3; */ + /* else if ( text[i-1] == '.' ) */ + /* special = 3; */ + else if ( !isalnum(text[i-1]) ) + special = 3; + else + special = 0; + ++i; + int64_t d = -2; /* ~1 */ + int64_t last = d; + while ( i < text_len ) + { + last = d; + char c = text[i]; + /* c in pattern */ + if ( pattern_mask[(uint8_t)c] != -1 ) + d = (d << 1) | (pattern_mask[(uint8_t)c] >> k); + /** + * text = 'xxABC', pattern = 'abc'; text[i] == 'B' + * text = 'xxABC', pattern = 'abc'; text[i] == 'C' + * NOT text = 'xxABCd', pattern = 'abc'; text[i] == 'C' + * 'Cd' is considered as a word + */ + else if ( isupper(text[i-1]) && pattern_mask[(uint8_t)tolower(c)] != -1 + && (i+1 == text_len || !islower(text[i+1])) ) + d = (d << 1) | (pattern_mask[(uint8_t)tolower(c)] >> k); + else + d = ~0; + + if ( d >= last ) + { + float score = MIN_WEIGHT; + uint16_t n = FM_BIT_LENGTH(~last); + /* e.g., text = '~~abcd~~~~', pattern = 'abcd' */ + if ( n == pattern_len ) + { + score = (float)(special > 0 ? (n > 1 ? valTable[n+1] : valTable[n]) + special : valTable[n]); + cur_highlights.score = score; + cur_highlights.beg = i - n; + cur_highlights.end = i; + cur_highlights.end_index = 1; + cur_highlights.positions[0].col = i - n + 1; + cur_highlights.positions[0].len = n; + if ( special > 0 ) + { + memcpy(groups[k], &cur_highlights, sizeof(HighlightGroup)); + return groups[k]; + } + } + else + { + uint16_t prefix_score = special > 0 ? (n > 1 ? valTable[n+1] : valTable[n]) + special : valTable[n]; + if ( prefix_score > max_prefix_score ) + { + max_prefix_score = prefix_score; + pText_ctxt->offset = i; + HighlightGroup* pGroup = evaluateHighlights_nameOnly(pText_ctxt, pPattern_ctxt, k + n, groups); + if ( pGroup ) + { + if ( pGroup->end ) + { + score = prefix_score + pGroup->score - 0.2f * (pGroup->beg - i); + cur_highlights.score = score; + cur_highlights.beg = i - n; + cur_highlights.end = pGroup->end; + cur_highlights.positions[0].col = i - n + 1; + cur_highlights.positions[0].len = n; + memcpy(cur_highlights.positions + 1, pGroup->positions, pGroup->end_index * sizeof(HighlightPos)); + cur_highlights.end_index = pGroup->end_index + 1; + } + } + } + } + if ( score > max_score ) + { + max_score = score; + memcpy(groups[k], &cur_highlights, sizeof(HighlightGroup)); + } + /* e.g., text = '~_ababc~~~~', pattern = 'abc' */ + special = 0; + } + + /* + * e.g., text = 'a~c~~~~ab~c', pattern = 'abc', + * to find the index of the second 'a' + * `d == last` is for the case when text = 'kpi_oos1', pattern = 'kos' + */ + if ( d == ~0 || d == last ) + { + x = text_mask[base_offset + (i >> 6)] >> (i & 63); + + if ( x == 0 ) + { + uint64_t bits = 0; + uint16_t col = 0; + for ( col = (i >> 6) + 1; col < col_num; ++col ) + { + if ( (bits = text_mask[base_offset + col]) != 0 ) + break; + } + if ( bits == 0 ) + break; + else + i = (col << 6) + FM_CTZ(bits); + } + else + { + i += FM_CTZ(x); + } + + if ( isupper(text[i]) ) + special = !isupper(text[i-1]) || (i+1 < text_len && islower(text[i+1])) ? 3 : 0; + /* else if ( text[i-1] == '_' || text[i-1] == '-' || text[i-1] == ' ' ) */ + /* special = 3; */ + /* else if ( text[i-1] == '.' ) */ + /* special = 3; */ + else if ( !isalnum(text[i-1]) ) + special = 3; + else + special = 0; + d = -2; + ++i; + } + else + ++i; + } + + /* e.g., text = '~~~~abcd', pattern = 'abcd' */ + if ( i == text_len ) + { + if ( ~d >> (pattern_len - 1) ) + { + float score = (float)(special > 0 ? (pattern_len > 1 ? valTable[pattern_len + 1] : valTable[pattern_len]) + special + : valTable[pattern_len]); + if ( score > max_score ) + { + groups[k]->score = score; + groups[k]->beg = i - pattern_len; + groups[k]->end = i; + groups[k]->positions[0].col = i - pattern_len + 1; + groups[k]->positions[0].len = pattern_len; + groups[k]->end_index = 1; + } + } + } + + return groups[k]; +} + + +HighlightGroup* evaluateHighlights(TextContext* pText_ctxt, + PatternContext* pPattern_ctxt, + uint16_t k, + HighlightGroup* groups[]) +{ + uint16_t j = pText_ctxt->offset; + + if ( groups[k] && groups[k]->beg >= j ) + return groups[k]; + + uint64_t* text_mask = pText_ctxt->text_mask; + uint16_t col_num = pText_ctxt->col_num; + + const char* pattern = pPattern_ctxt->pattern; + uint16_t base_offset = pattern[k] * col_num; + uint64_t x = text_mask[base_offset + (j >> 6)] >> (j & 63); + uint16_t i = 0; + + if ( x == 0 ) + { + uint64_t bits = 0; + uint16_t col = 0; + for ( col = (j >> 6) + 1; col < col_num; ++col ) + { + if ( (bits = text_mask[base_offset + col]) != 0 ) + break; + } + if ( bits == 0 ) + { + return NULL; + } + else + { + i = (col << 6) + FM_CTZ(bits); + } + } + else + { + i = j + FM_CTZ(x); + } + + uint16_t max_prefix_score = 0; + float max_score = MIN_WEIGHT; + + if ( !groups[k] ) + { + groups[k] = (HighlightGroup*)calloc(1, sizeof(HighlightGroup)); + if ( !groups[k] ) + { + fprintf(stderr, "Out of memory in evaluateHighlights()!\n"); + return NULL; + } + } + else + { + memset(groups[k], 0, sizeof(HighlightGroup)); + } + + HighlightGroup cur_highlights; + memset(&cur_highlights, 0, sizeof(HighlightGroup)); + + const char* text = pText_ctxt->text; + uint16_t text_len = pText_ctxt->text_len; + uint16_t pattern_len = pPattern_ctxt->pattern_len - k; + int64_t* pattern_mask = pPattern_ctxt->pattern_mask; + + uint16_t special = 0; + if ( i == 0 ) + special = 5; +#if defined(_MSC_VER) + else if ( text[i-1] == '\\' || text[i-1] == '/' ) +#else + else if ( text[i-1] == '/' ) +#endif + special = k == 0 ? 5 : 3; + else if ( isupper(text[i]) ) + special = !isupper(text[i-1]) || (i+1 < text_len && islower(text[i+1])) ? 3 : 0; + /* else if ( text[i-1] == '_' || text[i-1] == '-' || text[i-1] == ' ' ) */ + /* special = 3; */ + /* else if ( text[i-1] == '.' ) */ + /* special = 3; */ + else if ( !isalnum(text[i-1]) ) + special = 3; + else + special = 0; + ++i; + int64_t d = -2; /* ~1 */ + int64_t last = d; + while ( i < text_len ) + { + last = d; + char c = text[i]; + /* c in pattern */ + if ( pattern_mask[(uint8_t)c] != -1 ) + d = (d << 1) | (pattern_mask[(uint8_t)c] >> k); + /** + * text = 'xxABC', pattern = 'abc'; text[i] == 'B' + * text = 'xxABC', pattern = 'abc'; text[i] == 'C' + * NOT text = 'xxABCd', pattern = 'abc'; text[i] == 'C' + * 'Cd' is considered as a word + */ + /* else if ( isupper(text[i-1]) && pattern_mask[(uint8_t)tolower(c)] != -1 */ + /* && (i+1 == text_len || !islower(text[i+1])) ) */ + else if ( pattern_mask[(uint8_t)tolower(c)] != -1 ) + d = (d << 1) | (pattern_mask[(uint8_t)tolower(c)] >> k); + else + d = ~0; + + if ( d >= last ) + { + float score = MIN_WEIGHT; + uint16_t n = FM_BIT_LENGTH(~last); + /* e.g., text = '~~abcd~~~~', pattern = 'abcd' */ + if ( n == pattern_len ) + { + score = (float)(special > 0 ? (n > 1 ? valTable[n+1] : valTable[n]) + special : valTable[n]); + cur_highlights.score = score; + cur_highlights.beg = i - n; + cur_highlights.end = i; + cur_highlights.end_index = 1; + cur_highlights.positions[0].col = i - n + 1; + cur_highlights.positions[0].len = n; + if ( (k == 0 && special == 5) || (k > 0 && special > 0) ) + { + memcpy(groups[k], &cur_highlights, sizeof(HighlightGroup)); + return groups[k]; + } + } + else + { + uint16_t prefix_score = special > 0 ? (n > 1 ? valTable[n+1] : valTable[n]) + special : valTable[n]; + /** + * e.g., text = 'AbcxxAbcyyde', pattern = 'abcde' + * prefer matching 'Abcyyde' + */ + if ( prefix_score > max_prefix_score + || (special > 0 && prefix_score == max_prefix_score) ) + { + max_prefix_score = prefix_score; + pText_ctxt->offset = i; + HighlightGroup* pGroup = evaluateHighlights(pText_ctxt, pPattern_ctxt, k + n, groups); + if ( pGroup && pGroup->end ) + { + score = prefix_score + pGroup->score - 0.3f * (pGroup->beg - i); + cur_highlights.score = score; + cur_highlights.beg = i - n; + cur_highlights.end = pGroup->end; + cur_highlights.positions[0].col = i - n + 1; + cur_highlights.positions[0].len = n; + memcpy(cur_highlights.positions + 1, pGroup->positions, pGroup->end_index * sizeof(HighlightPos)); + cur_highlights.end_index = pGroup->end_index + 1; + } + else + { + break; + } + } + } + if ( score > max_score ) + { + max_score = score; + memcpy(groups[k], &cur_highlights, sizeof(HighlightGroup)); + } + /* e.g., text = '~_ababc~~~~', pattern = 'abc' */ + special = 0; + } + + /* + * e.g., text = 'a~c~~~~ab~c', pattern = 'abc', + * to find the index of the second 'a' + * `d == last` is for the case when text = 'kpi_oos1', pattern = 'kos' + */ + if ( d == ~0 || d == last ) + { + x = text_mask[base_offset + (i >> 6)] >> (i & 63); + + if ( x == 0 ) + { + uint64_t bits = 0; + uint16_t col = 0; + for ( col = (i >> 6) + 1; col < col_num; ++col ) + { + if ( (bits = text_mask[base_offset + col]) != 0 ) + break; + } + if ( bits == 0 ) + break; + else + i = (col << 6) + FM_CTZ(bits); + } + else + { + i += FM_CTZ(x); + } + +#if defined(_MSC_VER) + if ( text[i-1] == '\\' || text[i-1] == '/' ) +#else + if ( text[i-1] == '/' ) +#endif + special = k == 0 ? 5 : 3; + else if ( isupper(text[i]) ) + special = !isupper(text[i-1]) || (i+1 < text_len && islower(text[i+1])) ? 3 : 0; + /* else if ( text[i-1] == '_' || text[i-1] == '-' || text[i-1] == ' ' ) */ + /* special = 3; */ + /* else if ( text[i-1] == '.' ) */ + /* special = 3; */ + else if ( !isalnum(text[i-1]) ) + special = 3; + else + special = 0; + d = -2; + ++i; + } + else + ++i; + } + + /* e.g., text = '~~~~abcd', pattern = 'abcd' */ + if ( i == text_len ) + { + if ( ~d >> (pattern_len - 1) ) + { + float score = (float)(special > 0 ? (pattern_len > 1 ? valTable[pattern_len + 1] : valTable[pattern_len]) + special + : valTable[pattern_len]); + if ( score > max_score ) + { + groups[k]->score = score; + groups[k]->beg = i - pattern_len; + groups[k]->end = i; + groups[k]->positions[0].col = i - pattern_len + 1; + groups[k]->positions[0].len = pattern_len; + groups[k]->end_index = 1; + } + } + } + + return groups[k]; +} + +/** + * return a list of pair [col, length], where `col` is the column number(start + * from 1, the value must correspond to the byte index of `text`) and `length` + * is the length of the highlight in bytes. + * e.g., [ [2,3], [6,2], [10,4], ... ] + */ +HighlightGroup* getHighlights(const char* text, + uint16_t text_len, + PatternContext* pPattern_ctxt, + uint8_t is_name_only) +{ + if ( !text || !pPattern_ctxt ) + return NULL; + + uint16_t col_num = 0; + uint64_t* text_mask = NULL; + const char* pattern = pPattern_ctxt->pattern; + uint16_t pattern_len = pPattern_ctxt->pattern_len; + int64_t* pattern_mask = pPattern_ctxt->pattern_mask; + char first_char = pattern[0]; + char last_char = pattern[pattern_len - 1]; + + /* maximum number of int16_t is (1 << 15) - 1 */ + if ( text_len >= (1 << 15) ) + { + text_len = (1 << 15) - 1; + } + + if ( pattern_len == 1 ) + { + if ( isupper(first_char) ) + { + int16_t first_char_pos = -1; + int16_t i; + for ( i = 0; i < text_len; ++i ) + { + if ( text[i] == first_char ) + { + first_char_pos = i; + break; + } + } + if ( first_char_pos == -1 ) + return NULL; + else + { + HighlightGroup* pGroup = (HighlightGroup*)malloc(sizeof(HighlightGroup)); + if ( !pGroup ) + { + fprintf(stderr, "Out of memory in getHighlights()!\n"); + return NULL; + } + pGroup->positions[0].col = first_char_pos + 1; + pGroup->positions[0].len = 1; + pGroup->end_index = 1; + + return pGroup; + } + } + else + { + int16_t first_char_pos = -1; + int16_t i; + for ( i = 0; i < text_len; ++i ) + { + if ( tolower(text[i]) == first_char ) + { + if ( first_char_pos == -1 ) + first_char_pos = i; + + if ( isupper(text[i]) || i == 0 || !isalnum(text[i-1]) ) + { + first_char_pos = i; + break; + } + } + } + if ( first_char_pos == -1 ) + return NULL; + else + { + HighlightGroup* pGroup = (HighlightGroup*)malloc(sizeof(HighlightGroup)); + if ( !pGroup ) + { + fprintf(stderr, "Out of memory in getHighlights()!\n"); + return NULL; + } + pGroup->positions[0].col = first_char_pos + 1; + pGroup->positions[0].len = 1; + pGroup->end_index = 1; + + return pGroup; + } + } + } + + if ( pPattern_ctxt->is_lower ) + { + int16_t first_char_pos = -1; + int16_t i; + for ( i = 0; i < text_len; ++i ) + { + if ( tolower(text[i]) == first_char ) + { + first_char_pos = i; + break; + } + } + + int16_t last_char_pos = -1; + for ( i = text_len - 1; i >= first_char_pos; --i ) + { + if ( tolower(text[i]) == last_char ) + { + last_char_pos = i; + break; + } + } + + col_num = (text_len + 63) >> 6; /* (text_len + 63)/64 */ + if (col_num <= 2) + { + memset(TEXT_MASK, 0, sizeof(TEXT_MASK)); + text_mask = TEXT_MASK; + } + else + { + /* uint64_t text_mask[256][col_num] */ + text_mask = (uint64_t*)calloc(col_num << 8, sizeof(uint64_t)); + if ( !text_mask ) + { + fprintf(stderr, "Out of memory in getHighlights()!\n"); + return NULL; + } + } + char c; + for ( i = first_char_pos; i <= last_char_pos; ++i ) + { + c = tolower(text[i]); + /* c in pattern */ + if ( pattern_mask[(uint8_t)c] != -1 ) + text_mask[(uint8_t)c * col_num + (i >> 6)] |= 1ULL << (i & 63); + } + } + else + { + int16_t first_char_pos = -1; + if ( isupper(first_char) ) + { + int16_t i; + for ( i = 0; i < text_len; ++i ) + { + if ( text[i] == first_char ) + { + first_char_pos = i; + break; + } + } + } + else + { + int16_t i; + for ( i = 0; i < text_len; ++i ) + { + if ( tolower(text[i]) == first_char ) + { + first_char_pos = i; + break; + } + } + } + + int16_t last_char_pos = -1; + if ( isupper(last_char) ) + { + int16_t i; + for ( i = text_len - 1; i >= first_char_pos; --i ) + { + if ( text[i] == last_char ) + { + last_char_pos = i; + break; + } + } + } + else + { + int16_t i; + for ( i = text_len - 1; i >= first_char_pos; --i ) + { + if ( tolower(text[i]) == last_char ) + { + last_char_pos = i; + break; + } + } + } + + col_num = (text_len + 63) >> 6; + if (col_num <= 2) + { + memset(TEXT_MASK, 0, sizeof(TEXT_MASK)); + text_mask = TEXT_MASK; + } + else + { + /* uint64_t text_mask[256][col_num] */ + text_mask = (uint64_t*)calloc(col_num << 8, sizeof(uint64_t)); + if ( !text_mask ) + { + fprintf(stderr, "Out of memory in getHighlights()!\n"); + return NULL; + } + } + + char c; + int16_t i; + for ( i = first_char_pos; i <= last_char_pos; ++i ) + { + c = text[i]; + if ( isupper(c) ) + { + /* c in pattern */ + if ( pattern_mask[(uint8_t)c] != -1 ) + text_mask[(uint8_t)c * col_num + (i >> 6)] |= 1ULL << (i & 63); + if ( pattern_mask[(uint8_t)tolower(c)] != -1 ) + text_mask[(uint8_t)tolower(c) * col_num + (i >> 6)] |= 1ULL << (i & 63); + } + else + { + /* c in pattern */ + if ( pattern_mask[(uint8_t)c] != -1 ) + text_mask[(uint8_t)c * col_num + (i >> 6)] |= 1ULL << (i & 63); + } + } + } + + TextContext text_ctxt; + text_ctxt.text = text; + text_ctxt.text_len = text_len; + text_ctxt.text_mask = text_mask; + text_ctxt.col_num = col_num; + text_ctxt.offset = 0; + + /* HighlightGroup* groups[pattern_len] */ + HighlightGroup** groups = (HighlightGroup**)calloc(pattern_len, sizeof(HighlightGroup*)); + if ( !groups ) + { + fprintf(stderr, "Out of memory in getHighlights()!\n"); + if (col_num > 2) + { + free(text_mask); + } + return NULL; + } + + HighlightGroup* pGroup = NULL; + if ( is_name_only ) + pGroup = evaluateHighlights_nameOnly(&text_ctxt, pPattern_ctxt, 0, groups); + else + pGroup = evaluateHighlights(&text_ctxt, pPattern_ctxt, 0, groups); + + if (col_num > 2) + { + free(text_mask); + } + uint16_t i; + for ( i = 0; i < pattern_len; ++i ) + { + if ( groups[i] && groups[i] != pGroup ) + free(groups[i]); + } + free(groups); + + return pGroup; +} + +/** + * e.g., /usr/src/example.tar.gz + * `dirname` is "/usr/src" + * `basename` is "example.tar.gz" + * `filename` is "example.tar", `suffix` is ".gz" + */ +uint32_t getPathWeight(const char* filename, + const char* suffix, + const char* dirname, + const char* path, uint32_t path_len) +{ + uint32_t filename_lcp = 0; + uint32_t filename_prefix = 0; + uint32_t dirname_lcp = 0; + uint32_t is_suffix_diff = 0; + uint32_t is_basename_same = 0; + uint32_t is_dirname_same = 0; + + const char* filename_start = path; + const char* p = path + path_len; + const char* p1 = NULL; + + while ( p >= path ) + { +#if defined(_MSC_VER) + if ( *p == '\\' || *p == '/' ) +#else + if ( *p == '/' ) +#endif + { + filename_start = p + 1; + break; + } + --p; + } + + if ( *suffix != '\0' ) + { + p = filename_start; + p1 = filename; + while ( *p != '\0' && *p == *p1 ) + { + ++filename_lcp; + ++p; + ++p1; + } + + filename_prefix = filename_lcp; + + if ( filename_lcp > 0 ) + { + if ( (*p >= 'a' && *p <= 'z') || (*p >= '0' && *p <= '9') + || (*p1 >= 'a' && *p1 <= 'z') || (*p1 >= '0' && *p1 <= '9') ) + { + --p; + while ( p > filename_start ) + { + if ( *p >= 'a' && *p <= 'z' ) + { + --p; + } + else + { + break; + } + } + filename_prefix = (uint32_t)(p - filename_start); + } + else if ( (*p >= 'A' && *p <= 'Z') && (*p1 >= 'A' && *p1 <= 'Z') + && (*(p-1) >= 'A' && *(p-1) <= 'Z') ) + { + --p; + while ( p > filename_start ) + { + if ( *p >= 'A' && *p <= 'Z' ) + { + --p; + } + else + { + break; + } + } + filename_prefix = (uint32_t)(p - filename_start); + } + } + + p = path + path_len - 1; + while ( p > filename_start ) + { + if ( *p == '.' ) + { + if ( strcmp(suffix, p) != 0 ) + { + if ( filename_lcp > 0 ) + is_suffix_diff = 1; + } + else if ( *p1 == '\0' && filename_lcp == p - filename_start ) + { + is_basename_same = 1; + } + break; + } + --p; + } + } + else + { + is_basename_same = strcmp(filename, filename_start) == 0; + } + + p = path; + p1 = dirname; +#if defined(_MSC_VER) + while ( p < filename_start ) + { + if ( *p1 == '\\' ) + { + if ( *p == '\\' || *p == '/' ) + { + ++dirname_lcp; + } + else + { + break; + } + } + else if ( *p != *p1 ) + { + break; + } + ++p; + ++p1; + } +#else + while ( p < filename_start && *p == *p1 ) + { + if ( *p == '/' ) + { + ++dirname_lcp; + } + ++p; + ++p1; + } +#endif + /** + * e.g., dirname = "abc" , path = "abc/test.h" + * p1 != dirname is to avoid such a case: + * e.g., buffer name is "aaa.h", path is "/abc/def.h" + */ +#if defined(_MSC_VER) + if ( *p1 == '\0' && p1 != dirname && (*p == '\\' || *p == '/') ) +#else + if ( *p1 == '\0' && p1 != dirname && *p == '/' ) +#endif + { + ++dirname_lcp; + } + + /* if dirname is empty, filename_start == path */ + is_dirname_same = filename_start - p == 1 || (*dirname == '\0' && filename_start == path) ; + + /* dirname/filename+suffix is the same as path */ + if ( is_basename_same && is_dirname_same ) + { + return 0; + } + + if ( filename_start == path && *dirname == '\0') + { + dirname_lcp = 1; + } + + return (((filename_prefix + 1) << 24) | (dirname_lcp << 12) | (is_dirname_same << 11) + | filename_lcp) + (is_suffix_diff << 2) - path_len; +} + +static void delPatternContext(PyObject* obj) +{ + free(PyCapsule_GetPointer(obj, NULL)); +} + +static PyObject* fuzzyMatchC_initPattern(PyObject* self, PyObject* args) +{ + const char* pattern; + Py_ssize_t pattern_len; + + if ( !PyArg_ParseTuple(args, "s#:initPattern", &pattern, &pattern_len) ) + return NULL; + + PatternContext* pCtxt = initPattern(pattern, (uint16_t)pattern_len); + + return PyCapsule_New(pCtxt, NULL, delPatternContext); +} + +static PyObject* fuzzyMatchC_getWeight(PyObject* self, PyObject* args, PyObject* kwargs) +{ + const char* text; + Py_ssize_t text_len; + PyObject* py_patternCtxt; + uint8_t is_name_only; + static char* kwlist[] = {"text", "pattern", "is_name_only", NULL}; + + if ( !PyArg_ParseTupleAndKeywords(args, kwargs, "s#Ob:getWeight", kwlist, &text, + &text_len, &py_patternCtxt, &is_name_only) ) + return NULL; + + PatternContext* pCtxt = (PatternContext*)PyCapsule_GetPointer(py_patternCtxt, NULL); + if ( !pCtxt ) + return NULL; + + return Py_BuildValue("f", getWeight(text, (uint16_t)text_len, pCtxt, is_name_only)); +} + +static PyObject* fuzzyMatchC_getHighlights(PyObject* self, PyObject* args, PyObject* kwargs) +{ + const char* text; + Py_ssize_t text_len; + PyObject* py_patternCtxt; + uint8_t is_name_only; + static char* kwlist[] = {"text", "pattern", "is_name_only", NULL}; + + if ( !PyArg_ParseTupleAndKeywords(args, kwargs, "s#Ob:getHighlights", kwlist, &text, + &text_len, &py_patternCtxt, &is_name_only) ) + return NULL; + + PatternContext* pCtxt = (PatternContext*)PyCapsule_GetPointer(py_patternCtxt, NULL); + if ( !pCtxt ) + return NULL; + + HighlightGroup* pGroup = getHighlights(text, (uint16_t)text_len, pCtxt, is_name_only); + if ( !pGroup ) + return NULL; + + PyObject* list = PyList_New(pGroup->end_index); + uint16_t i; + for ( i = 0; i < pGroup->end_index; ++i ) + { + PyList_SetItem(list, i, Py_BuildValue("[H,H]", pGroup->positions[i].col, pGroup->positions[i].len)); + } + free(pGroup); + + return list; +} + +static PyMethodDef fuzzyMatchC_Methods[] = +{ + { "initPattern", (PyCFunction)fuzzyMatchC_initPattern, METH_VARARGS, "initialize the pattern." }, + { "getWeight", (PyCFunction)fuzzyMatchC_getWeight, METH_VARARGS | METH_KEYWORDS, "" }, + { "getHighlights", (PyCFunction)fuzzyMatchC_getHighlights, METH_VARARGS | METH_KEYWORDS, "" }, + { NULL, NULL, 0, NULL } +}; + +#if PY_MAJOR_VERSION >= 3 + +static struct PyModuleDef fuzzyMatchC_module = +{ + PyModuleDef_HEAD_INIT, + "fuzzyMatchC", /* name of module */ + "fuzzy match algorithm written in C.", + -1, + fuzzyMatchC_Methods +}; + +PyMODINIT_FUNC PyInit_fuzzyMatchC(void) +{ + PyObject* module = NULL; + module = PyModule_Create(&fuzzyMatchC_module); + if ( !module ) + return NULL; + + if ( PyModule_AddObject(module, "MIN_WEIGHT", Py_BuildValue("f", (float)MIN_WEIGHT)) ) + { + Py_DECREF(module); + return NULL; + } + + return module; +} + +#else + +PyMODINIT_FUNC initfuzzyMatchC(void) +{ + PyObject* module = NULL; + module = Py_InitModule("fuzzyMatchC", fuzzyMatchC_Methods); + if ( !module ) + return; + + if ( PyModule_AddObject(module, "MIN_WEIGHT", Py_BuildValue("f", (float)MIN_WEIGHT)) ) + { + Py_DECREF(module); + return; + } +} + +#endif + +int main(int argc, const char* argv[]) +{ + + printf("%d\n", FM_BIT_LENGTH(0x2f00)); + + return 0; +} + diff --git a/autoload/leaderf/fuzzyMatch_C/setup.py b/autoload/leaderf/fuzzyMatch_C/setup.py index 63307afb..fd2cea8d 100644 --- a/autoload/leaderf/fuzzyMatch_C/setup.py +++ b/autoload/leaderf/fuzzyMatch_C/setup.py @@ -22,22 +22,32 @@ class BuildExt(build_ext): def build_extensions(self): if os.name == 'nt' and "MSC" in platform.python_compiler(): - for ext in self.extensions: - ext.extra_compile_args = ['/TP'] + pass elif os.name == 'posix': for ext in self.extensions: - ext.extra_compile_args = ['-std=c99', '-O3'] + ext.extra_compile_args = ['-std=c99'] build_ext.build_extensions(self) -module1 = Extension( - "fuzzyMatchC", - sources=["fuzzyMatch.c"], -) +if os.name == 'nt': + module1 = Extension( + "fuzzyMatchC", + sources=["fuzzyMatch.cpp"], + ) -module2 = Extension( - "fuzzyEngine", - sources=["fuzzyMatch.c", "fuzzyEngine.c"], -) + module2 = Extension( + "fuzzyEngine", + sources=["fuzzyMatch.cpp", "fuzzyEngine.cpp"], + ) +else: + module1 = Extension( + "fuzzyMatchC", + sources=["fuzzyMatch.c"], + ) + + module2 = Extension( + "fuzzyEngine", + sources=["fuzzyMatch.c", "fuzzyEngine.c"], + ) setup( name="fuzzyEngine", From 0fdf6b1640c65d1c86770773b206395c64f2a15f Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Tue, 25 Feb 2025 17:45:50 +0800 Subject: [PATCH 330/365] optimize the fuzzy matching algorithm --- autoload/leaderf/fuzzyMatch_C/fuzzyMatch.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/autoload/leaderf/fuzzyMatch_C/fuzzyMatch.c b/autoload/leaderf/fuzzyMatch_C/fuzzyMatch.c index 77d1c024..cb23c5fd 100644 --- a/autoload/leaderf/fuzzyMatch_C/fuzzyMatch.c +++ b/autoload/leaderf/fuzzyMatch_C/fuzzyMatch.c @@ -721,6 +721,7 @@ float getWeight(const char* text, uint16_t text_len, } int16_t first_char_pos = -1; + uint16_t better_text_len = text_len; if ( pPattern_ctxt->is_lower ) { int16_t i; @@ -747,7 +748,8 @@ float getWeight(const char* text, uint16_t text_len, if ( last_char_pos == -1 ) return MIN_WEIGHT; - col_num = (text_len + 63) >> 6; /* (text_len + 63)/64 */ + better_text_len = last_char_pos + 1; + col_num = (better_text_len + 63) >> 6; /* (better_text_len + 63)/64 */ if (col_num <= 2) { memset(TEXT_MASK, 0, sizeof(TEXT_MASK)); @@ -833,7 +835,8 @@ float getWeight(const char* text, uint16_t text_len, if ( last_char_pos == -1 ) return MIN_WEIGHT; - col_num = (text_len + 63) >> 6; + better_text_len = last_char_pos + 1; + col_num = (better_text_len + 63) >> 6; if (col_num <= 2) { memset(TEXT_MASK, 0, sizeof(TEXT_MASK)); @@ -890,7 +893,7 @@ float getWeight(const char* text, uint16_t text_len, { int16_t i; j = 0; - for ( i = first_char_pos; i < text_len; ++i ) + for ( i = first_char_pos; i < better_text_len; ++i ) { if ( j < pPattern_ctxt->actual_pattern_len ) { @@ -916,7 +919,7 @@ float getWeight(const char* text, uint16_t text_len, TextContext text_ctxt; text_ctxt.text = text; - text_ctxt.text_len = text_len; + text_ctxt.text_len = better_text_len; text_ctxt.text_mask = text_mask; text_ctxt.col_num = col_num; text_ctxt.offset = 0; From ce7246f7a76c3804d5b5b5e704e4acf9d67042f2 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Tue, 25 Feb 2025 21:40:33 +0800 Subject: [PATCH 331/365] optimize the fuzzy matching algorithm --- autoload/leaderf/fuzzyMatch_C/fuzzyMatch.c | 30 +++++++++++--------- autoload/leaderf/fuzzyMatch_C/fuzzyMatch.cpp | 27 +++++++++++------- 2 files changed, 32 insertions(+), 25 deletions(-) diff --git a/autoload/leaderf/fuzzyMatch_C/fuzzyMatch.c b/autoload/leaderf/fuzzyMatch_C/fuzzyMatch.c index cb23c5fd..d5f696ce 100644 --- a/autoload/leaderf/fuzzyMatch_C/fuzzyMatch.c +++ b/autoload/leaderf/fuzzyMatch_C/fuzzyMatch.c @@ -721,7 +721,7 @@ float getWeight(const char* text, uint16_t text_len, } int16_t first_char_pos = -1; - uint16_t better_text_len = text_len; + uint16_t short_text_len = text_len; if ( pPattern_ctxt->is_lower ) { int16_t i; @@ -748,8 +748,8 @@ float getWeight(const char* text, uint16_t text_len, if ( last_char_pos == -1 ) return MIN_WEIGHT; - better_text_len = last_char_pos + 1; - col_num = (better_text_len + 63) >> 6; /* (better_text_len + 63)/64 */ + short_text_len = last_char_pos + 1; + col_num = (short_text_len + 63) >> 6; /* (short_text_len + 63)/64 */ if (col_num <= 2) { memset(TEXT_MASK, 0, sizeof(TEXT_MASK)); @@ -835,8 +835,8 @@ float getWeight(const char* text, uint16_t text_len, if ( last_char_pos == -1 ) return MIN_WEIGHT; - better_text_len = last_char_pos + 1; - col_num = (better_text_len + 63) >> 6; + short_text_len = last_char_pos + 1; + col_num = (short_text_len + 63) >> 6; if (col_num <= 2) { memset(TEXT_MASK, 0, sizeof(TEXT_MASK)); @@ -893,7 +893,7 @@ float getWeight(const char* text, uint16_t text_len, { int16_t i; j = 0; - for ( i = first_char_pos; i < better_text_len; ++i ) + for ( i = first_char_pos; i < short_text_len; ++i ) { if ( j < pPattern_ctxt->actual_pattern_len ) { @@ -919,10 +919,10 @@ float getWeight(const char* text, uint16_t text_len, TextContext text_ctxt; text_ctxt.text = text; - text_ctxt.text_len = better_text_len; + text_ctxt.text_len = short_text_len; text_ctxt.text_mask = text_mask; text_ctxt.col_num = col_num; - text_ctxt.offset = 0; + text_ctxt.offset = first_char_pos; ValueElements val[64]; memset(val, 0, sizeof(val)); @@ -1514,9 +1514,10 @@ HighlightGroup* getHighlights(const char* text, } } + int16_t first_char_pos = -1; + uint16_t short_text_len = text_len; if ( pPattern_ctxt->is_lower ) { - int16_t first_char_pos = -1; int16_t i; for ( i = 0; i < text_len; ++i ) { @@ -1537,7 +1538,8 @@ HighlightGroup* getHighlights(const char* text, } } - col_num = (text_len + 63) >> 6; /* (text_len + 63)/64 */ + short_text_len = last_char_pos + 1; + col_num = (short_text_len + 63) >> 6; /* (short_text_len + 63)/64 */ if (col_num <= 2) { memset(TEXT_MASK, 0, sizeof(TEXT_MASK)); @@ -1564,7 +1566,6 @@ HighlightGroup* getHighlights(const char* text, } else { - int16_t first_char_pos = -1; if ( isupper(first_char) ) { int16_t i; @@ -1616,7 +1617,8 @@ HighlightGroup* getHighlights(const char* text, } } - col_num = (text_len + 63) >> 6; + short_text_len = last_char_pos + 1; + col_num = (short_text_len + 63) >> 6; if (col_num <= 2) { memset(TEXT_MASK, 0, sizeof(TEXT_MASK)); @@ -1657,10 +1659,10 @@ HighlightGroup* getHighlights(const char* text, TextContext text_ctxt; text_ctxt.text = text; - text_ctxt.text_len = text_len; + text_ctxt.text_len = short_text_len; text_ctxt.text_mask = text_mask; text_ctxt.col_num = col_num; - text_ctxt.offset = 0; + text_ctxt.offset = first_char_pos; /* HighlightGroup* groups[pattern_len] */ HighlightGroup** groups = (HighlightGroup**)calloc(pattern_len, sizeof(HighlightGroup*)); diff --git a/autoload/leaderf/fuzzyMatch_C/fuzzyMatch.cpp b/autoload/leaderf/fuzzyMatch_C/fuzzyMatch.cpp index 77d1c024..d5f696ce 100644 --- a/autoload/leaderf/fuzzyMatch_C/fuzzyMatch.cpp +++ b/autoload/leaderf/fuzzyMatch_C/fuzzyMatch.cpp @@ -721,6 +721,7 @@ float getWeight(const char* text, uint16_t text_len, } int16_t first_char_pos = -1; + uint16_t short_text_len = text_len; if ( pPattern_ctxt->is_lower ) { int16_t i; @@ -747,7 +748,8 @@ float getWeight(const char* text, uint16_t text_len, if ( last_char_pos == -1 ) return MIN_WEIGHT; - col_num = (text_len + 63) >> 6; /* (text_len + 63)/64 */ + short_text_len = last_char_pos + 1; + col_num = (short_text_len + 63) >> 6; /* (short_text_len + 63)/64 */ if (col_num <= 2) { memset(TEXT_MASK, 0, sizeof(TEXT_MASK)); @@ -833,7 +835,8 @@ float getWeight(const char* text, uint16_t text_len, if ( last_char_pos == -1 ) return MIN_WEIGHT; - col_num = (text_len + 63) >> 6; + short_text_len = last_char_pos + 1; + col_num = (short_text_len + 63) >> 6; if (col_num <= 2) { memset(TEXT_MASK, 0, sizeof(TEXT_MASK)); @@ -890,7 +893,7 @@ float getWeight(const char* text, uint16_t text_len, { int16_t i; j = 0; - for ( i = first_char_pos; i < text_len; ++i ) + for ( i = first_char_pos; i < short_text_len; ++i ) { if ( j < pPattern_ctxt->actual_pattern_len ) { @@ -916,10 +919,10 @@ float getWeight(const char* text, uint16_t text_len, TextContext text_ctxt; text_ctxt.text = text; - text_ctxt.text_len = text_len; + text_ctxt.text_len = short_text_len; text_ctxt.text_mask = text_mask; text_ctxt.col_num = col_num; - text_ctxt.offset = 0; + text_ctxt.offset = first_char_pos; ValueElements val[64]; memset(val, 0, sizeof(val)); @@ -1511,9 +1514,10 @@ HighlightGroup* getHighlights(const char* text, } } + int16_t first_char_pos = -1; + uint16_t short_text_len = text_len; if ( pPattern_ctxt->is_lower ) { - int16_t first_char_pos = -1; int16_t i; for ( i = 0; i < text_len; ++i ) { @@ -1534,7 +1538,8 @@ HighlightGroup* getHighlights(const char* text, } } - col_num = (text_len + 63) >> 6; /* (text_len + 63)/64 */ + short_text_len = last_char_pos + 1; + col_num = (short_text_len + 63) >> 6; /* (short_text_len + 63)/64 */ if (col_num <= 2) { memset(TEXT_MASK, 0, sizeof(TEXT_MASK)); @@ -1561,7 +1566,6 @@ HighlightGroup* getHighlights(const char* text, } else { - int16_t first_char_pos = -1; if ( isupper(first_char) ) { int16_t i; @@ -1613,7 +1617,8 @@ HighlightGroup* getHighlights(const char* text, } } - col_num = (text_len + 63) >> 6; + short_text_len = last_char_pos + 1; + col_num = (short_text_len + 63) >> 6; if (col_num <= 2) { memset(TEXT_MASK, 0, sizeof(TEXT_MASK)); @@ -1654,10 +1659,10 @@ HighlightGroup* getHighlights(const char* text, TextContext text_ctxt; text_ctxt.text = text; - text_ctxt.text_len = text_len; + text_ctxt.text_len = short_text_len; text_ctxt.text_mask = text_mask; text_ctxt.col_num = col_num; - text_ctxt.offset = 0; + text_ctxt.offset = first_char_pos; /* HighlightGroup* groups[pattern_len] */ HighlightGroup** groups = (HighlightGroup**)calloc(pattern_len, sizeof(HighlightGroup*)); From 06004b204090ac18aa88e2f79e7697abdc8e3a98 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Mon, 3 Mar 2025 21:55:56 +0800 Subject: [PATCH 332/365] optimize the fuzzy matching algorithm --- autoload/leaderf/fuzzyMatch_C/fuzzyMatch.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/autoload/leaderf/fuzzyMatch_C/fuzzyMatch.c b/autoload/leaderf/fuzzyMatch_C/fuzzyMatch.c index d5f696ce..766f207b 100644 --- a/autoload/leaderf/fuzzyMatch_C/fuzzyMatch.c +++ b/autoload/leaderf/fuzzyMatch_C/fuzzyMatch.c @@ -252,7 +252,6 @@ ValueElements* evaluate_nameOnly(TextContext* pText_ctxt, } if ( bits == 0 ) { - memset(val, 0, sizeof(ValueElements)); return val; } else @@ -350,6 +349,10 @@ ValueElements* evaluate_nameOnly(TextContext* pText_ctxt, score = prefix_score + pVal->score - 0.2f * (pVal->beg - i); end_pos = pVal->end; } + else + { + break; + } } } if ( score > max_score ) From 57b3e1c9df424f55ed8a6cccca51a0a14f575672 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Tue, 4 Mar 2025 10:42:44 +0800 Subject: [PATCH 333/365] bufTag only works on normal buffer --- autoload/leaderf/python/leaderf/bufTagExpl.py | 3 ++- autoload/leaderf/python/leaderf/functionExpl.py | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/autoload/leaderf/python/leaderf/bufTagExpl.py b/autoload/leaderf/python/leaderf/bufTagExpl.py index 7bf074cf..c36d9543 100644 --- a/autoload/leaderf/python/leaderf/bufTagExpl.py +++ b/autoload/leaderf/python/leaderf/bufTagExpl.py @@ -78,7 +78,8 @@ def _getTagList(self): yield itertools.chain(tag_list, itertools.chain.from_iterable(exe_taglist)) def _getTagResult(self, buffer): - if not buffer.name or lfEval("bufloaded(%d)" % buffer.number) == '0': + if (not buffer.name or lfEval("bufloaded(%d)" % buffer.number) == '0' + or lfEval("&bt") != ''): return [] changedtick = int(lfEval("getbufvar(%d, 'changedtick')" % buffer.number)) # there is no change since last call diff --git a/autoload/leaderf/python/leaderf/functionExpl.py b/autoload/leaderf/python/leaderf/functionExpl.py index 6b631dfe..5c39a624 100644 --- a/autoload/leaderf/python/leaderf/functionExpl.py +++ b/autoload/leaderf/python/leaderf/functionExpl.py @@ -104,7 +104,8 @@ def _getFunctionList(self): yield itertools.chain(func_list, itertools.chain.from_iterable(exe_taglist)) def _getFunctionResult(self, buffer): - if not buffer.name or lfEval("bufloaded(%d)" % buffer.number) == '0': + if (not buffer.name or lfEval("bufloaded(%d)" % buffer.number) == '0' + or lfEval("&bt") != ''): return [] changedtick = int(lfEval("getbufvar(%d, 'changedtick')" % buffer.number)) # there is no change since last call From 17cb04b2fbb817e899ba057c0f3d794134a0c35d Mon Sep 17 00:00:00 2001 From: WitWnd4Uoo <5491128+WitWnd4Uoo@users.noreply.github.com> Date: Wed, 5 Mar 2025 16:56:59 +0800 Subject: [PATCH 334/365] Enable project-specific configuration of gtags.files (#1117) Co-authored-by: Feng Lee <379943137@qq.com> --- autoload/leaderf/python/leaderf/gtagsExpl.py | 23 ++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/autoload/leaderf/python/leaderf/gtagsExpl.py b/autoload/leaderf/python/leaderf/gtagsExpl.py index 72eb4fa6..9ecc6bc4 100644 --- a/autoload/leaderf/python/leaderf/gtagsExpl.py +++ b/autoload/leaderf/python/leaderf/gtagsExpl.py @@ -623,6 +623,22 @@ def _exists(self, path, dir): return False + def _gtagsFilesExists(self, path): + """ + return True if `gtags.files` exists in project root + otherwise return False + """ + root_markers = lfEval("g:Lf_RootMarkers") + project_root = nearestAncestor(root_markers, path) + if project_root == "": + return False + + cur_path = os.path.join(path, "gtags.files") + if os.path.exists(cur_path): + return True + + return False + def _buildCmd(self, dir, **kwargs): """ this function comes from FileExplorer @@ -634,6 +650,13 @@ def _buildCmd(self, dir, **kwargs): if self._Lf_ExternalCommand: return self._Lf_ExternalCommand.replace('"%s"', '%s') % dir.join('""') + if self._gtagsFilesExists(dir): + if os.name == 'nt': + cmd = 'type gtags.files' + else: + cmd = 'cat gtags.files' + return cmd + arguments_dict = kwargs.get("arguments", {}) if self._Lf_UseVersionControlTool: if self._exists(dir, ".git"): From 675cd53462759796e5e410a9f25b9c39c286941c Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Mon, 17 Mar 2025 17:30:04 +0800 Subject: [PATCH 335/365] remove useless code --- autoload/leaderf/python/leaderf/gitExpl.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 1c51ede8..2f065dbe 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -2800,11 +2800,6 @@ def open(self): self._is_hidden = False self.tree_view.locateFile(current_file_path) - def writeBuffer(self): - # called in idle - if self.tree_view is not None: - self.tree_view.writeBuffer() - def getWindowId(self): return self.tree_view.getWindowId() From 570b2f62b1c3d2ace893d203f970c6da3e619c71 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Mon, 24 Mar 2025 21:00:49 +0800 Subject: [PATCH 336/365] refactor the code --- autoload/leaderf/Git.vim | 34 +- autoload/leaderf/python/leaderf/gitExpl.py | 441 +++++++++++---------- 2 files changed, 249 insertions(+), 226 deletions(-) diff --git a/autoload/leaderf/Git.vim b/autoload/leaderf/Git.vim index aeb006d4..24dbc73c 100644 --- a/autoload/leaderf/Git.vim +++ b/autoload/leaderf/Git.vim @@ -400,28 +400,28 @@ function! leaderf#Git#TreeViewMaps(id) abort nnoremap ) :call leaderf#Git#OuterBlock(1) endfunction -function! leaderf#Git#CollapseParent(explorer_page) abort +function! leaderf#Git#CollapseParent(navigation_panel) abort if leaderf#Git#OuterIndent(0) != 0 - exec g:Lf_py printf("%s.open(False)", a:explorer_page) + exec g:Lf_py printf("%s.openDiffView(False)", a:navigation_panel) endif endfunction -function! leaderf#Git#ExplorerMaps(id) abort +function! leaderf#Git#NavigationPanelMaps(id) abort exec g:Lf_py "import ctypes" - let explorer_page = printf("ctypes.cast(%d, ctypes.py_object).value", a:id) - exec printf('nnoremap o :exec g:Lf_py "%s.open(False)"', explorer_page) - exec printf('nnoremap <2-LeftMouse> :exec g:Lf_py "%s.open(False)"', explorer_page) - exec printf('nnoremap :exec g:Lf_py "%s.open(False)"', explorer_page) - exec printf('nnoremap O :exec g:Lf_py "%s.open(True)"', explorer_page) - exec printf('nnoremap t :exec g:Lf_py "%s.open(False, mode=''t'')"', explorer_page) - exec printf('nnoremap s :exec g:Lf_py "%s.toggleDiffViewMode()"', explorer_page) - exec printf('nnoremap i :exec g:Lf_py "%s.toggleIgnoreWhitespace()"', explorer_page) - exec printf('nnoremap p :exec g:Lf_py "%s.open(False, preview=True)"', explorer_page) - exec printf('nnoremap x :call leaderf#Git#CollapseParent("%s")', explorer_page) - exec printf('nnoremap f :exec g:Lf_py "%s.fuzzySearch()"', explorer_page) - exec printf('nnoremap F :exec g:Lf_py "%s.fuzzySearch(True)"', explorer_page) - exec printf('nnoremap m :exec g:Lf_py "%s.showCommitMessage()"', explorer_page) - exec printf('nnoremap :exec g:Lf_py "%s.selectOption()"', explorer_page) + let navigation_panel = printf("ctypes.cast(%d, ctypes.py_object).value", a:id) + exec printf('nnoremap o :exec g:Lf_py "%s.openDiffView(False)"', navigation_panel) + exec printf('nnoremap <2-LeftMouse> :exec g:Lf_py "%s.openDiffView(False)"', navigation_panel) + exec printf('nnoremap :exec g:Lf_py "%s.openDiffView(False)"', navigation_panel) + exec printf('nnoremap O :exec g:Lf_py "%s.openDiffView(True)"', navigation_panel) + exec printf('nnoremap t :exec g:Lf_py "%s.openDiffView(False, mode=''t'')"', navigation_panel) + exec printf('nnoremap s :exec g:Lf_py "%s.toggleDiffViewMode()"', navigation_panel) + exec printf('nnoremap i :exec g:Lf_py "%s.toggleIgnoreWhitespace()"', navigation_panel) + exec printf('nnoremap p :exec g:Lf_py "%s.openDiffView(False, preview=True)"', navigation_panel) + exec printf('nnoremap x :call leaderf#Git#CollapseParent("%s")', navigation_panel) + exec printf('nnoremap f :exec g:Lf_py "%s.fuzzySearch()"', navigation_panel) + exec printf('nnoremap F :exec g:Lf_py "%s.fuzzySearch(True)"', navigation_panel) + exec printf('nnoremap m :exec g:Lf_py "%s.showCommitMessage()"', navigation_panel) + exec printf('nnoremap :exec g:Lf_py "%s.selectOption()"', navigation_panel) nnoremap q :q endfunction diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 2f065dbe..1bf376ad 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -1183,60 +1183,12 @@ def __init__(self, owner, cmd, project_root, target_path, callback): "R": self._rename_icon, } self._head = [ - '" Press for help', - ' Side-by-side ◉ Unified ○', - ' Ignore Whitespace 🗷 ', - ' Myers ◉ Minimal ○ Patience ○ Histogram ○', - '', self._project_root + os.sep, ] self._match_ids = [] - def setDiffViewMode(self, mode): - self._buffer.options['modifiable'] = True - if mode == 'side-by-side': - self._buffer[1] = ' Side-by-side ◉ Unified ○' - - diffopt = lfEval("&diffopt") - if "iwhiteall" in diffopt: - self._buffer[2] = ' Ignore Whitespace 🗹 ' - else: - self._buffer[2] = ' Ignore Whitespace 🗷 ' - - if "algorithm:" in diffopt: - algo = re.sub(r".*algorithm:(\w+).*", r"\1", diffopt) - self.setDiffAlgorithm(algo) - else: - self.setDiffAlgorithm("myers") - else: - self._buffer[1] = ' Side-by-side ○ Unified ◉' - self._buffer.options['modifiable'] = False - - def setIgnoreWhitespace(self, diff_view_mode, ignore): - self._buffer.options['modifiable'] = True - if diff_view_mode == 'side-by-side': - if "iwhiteall" in lfEval("&diffopt"): - self._buffer[2] = ' Ignore Whitespace 🗹 ' - else: - self._buffer[2] = ' Ignore Whitespace 🗷 ' - else: - if ignore == True: - self._buffer[2] = ' Ignore Whitespace 🗹 ' - else: - self._buffer[2] = ' Ignore Whitespace 🗷 ' - self._buffer.options['modifiable'] = False - - def setDiffAlgorithm(self, algorithm): - self._buffer.options['modifiable'] = True - if algorithm == 'myers': - self._buffer[3] = ' Myers ◉ Minimal ○ Patience ○ Histogram ○' - elif algorithm == 'minimal': - self._buffer[3] = ' Myers ○ Minimal ◉ Patience ○ Histogram ○' - elif algorithm == 'patience': - self._buffer[3] = ' Myers ○ Minimal ○ Patience ◉ Histogram ○' - elif algorithm == 'histogram': - self._buffer[3] = ' Myers ○ Minimal ○ Patience ○ Histogram ◉' - self._buffer.options['modifiable'] = False + def startLine(self): + return self._owner.startLine() def enableColor(self, winid): if lfEval("hlexists('Lf_hl_help')") == '0': @@ -1560,7 +1512,7 @@ def metaInfoGenerator(self, meta_info, recursive, level): def expandOrCollapseFolder(self, recursive=False): with self._lock: line_num = int(lfEval("getcurpos({})[1]".format(self.getWindowId()))) - index = line_num - len(self._head) - 1 + index = line_num - self.startLine() # the root if index == -1 and recursive == True: self.expandRoot(line_num) @@ -1586,7 +1538,7 @@ def expandOrCollapseFolder(self, recursive=False): def collapseChildren(self): with self._lock: line_num = vim.current.window.cursor[0] - index = line_num - len(self._head) - 1 + index = line_num - self.startLine() structure = self._file_structures[self._cur_parent] if index < -1 or index >= len(structure): return @@ -1721,10 +1673,8 @@ def getKey(info): structure = self._file_structures[self._cur_parent] index = Bisect.bisect_left(structure, 0, key=getKey) if index < len(structure) and structure[index].path == path: - # lfCmd("call win_gotoid({})" .format(self.getWindowId())) - # lfCmd("{} | norm! 0zz" .format(index + 1 + len(self._head))) lfCmd("call win_execute({}, 'norm! {}G0zz')" - .format(self.getWindowId(), index + 1 + len(self._head))) + .format(self.getWindowId(), index + self.startLine())) else: if not self.inFileStructure(path): lfPrintError("File can't be found!") @@ -1740,15 +1690,13 @@ def getKey(info): node = node.dirs[d] node.status = FolderStatus.OPEN - line_num = index + len(self._head) + line_num = index + self.startLine() - 1 increment = self.expandFolder(line_num, index - 1, meta_info, False) index = Bisect.bisect_left(structure, 0, index, index + increment, key=getKey) if index < len(structure) and structure[index].path == path: lfCmd("call win_execute({}, 'norm! {}G0zz')" - .format(self.getWindowId(), index + 1 + len(self._head))) - # lfCmd("call win_gotoid({})" .format(self.getWindowId())) - # lfCmd("{} | norm! 0zz" .format(index + 1 + len(self._head))) + .format(self.getWindowId(), index + self.startLine())) else: lfPrintError("BUG: File can't be found!") @@ -1807,14 +1755,14 @@ def setOptions(self, winid, bufhidden): def initBuffer(self): self._buffer.options['modifiable'] = True try: - self._buffer[:] = self._head + self._buffer.append(self._head) finally: self._buffer.options['modifiable'] = False def refreshNumStat(self): self._buffer.options['modifiable'] = True try: - init_line = len(self._head) + init_line = self.startLine() - 1 structure = self._file_structures[self._cur_parent] for i, info in enumerate(structure, init_line): if info.has_num_stat == True: @@ -1842,7 +1790,7 @@ def writeBuffer(self): cur_len = len(structure) if cur_len > self._offset_in_content: cursor_line = int(lfEval("getcurpos({})[1]".format(self.getWindowId()))) - init_line = len(self._head) + init_line = self.startLine() - 1 if cursor_line <= init_line: lfCmd("call win_execute({}, 'norm! {}G')" @@ -2742,12 +2690,40 @@ def create(self, arguments_dict, source, **kwargs): class NavigationPanel(Panel): - def __init__(self, bufhidden_callback=None): + def __init__(self, owner, project_root, commit_id, bufhidden_callback=None): super(NavigationPanel, self).__init__() + self._owner = owner + self._project_root = project_root + self._commit_id = commit_id self.tree_view = None self._bufhidden_cb = bufhidden_callback self._is_hidden = False self._arguments = {} + self._diff_view_mode = None + self._ignore_whitespace = False + self._diff_algorithm = 'myers' + self._git_diff_manager = None + self._winid = None + self._buffer = None + self._head = [ + '" Press for help', + ' Side-by-side ◉ Unified ○', + ' Ignore Whitespace 🗷 ', + ' Myers ◉ Minimal ○ Patience ○ Histogram ○', + '', + ] + + def startLine(self): + return len(self._head) + 1 + 1 + + def getDiffViewMode(self): + return self._diff_view_mode + + def getIgnoreWhitespace(self): + return self._ignore_whitespace + + def getDiffAlgorithm(self): + return self._diff_algorithm def register(self, view): self.tree_view = view @@ -2765,11 +2741,158 @@ def cleanup(self): self.tree_view.cleanup() self.tree_view = None - def create(self, cmd, winid, project_root, target_path, callback): + def create(self, arguments_dict, cmd, winid, project_root, target_path, callback): + if "-u" in arguments_dict: + self._diff_view_mode = "unified" + elif "-s" in arguments_dict: + self._diff_view_mode = "side-by-side" + else: + self._diff_view_mode = lfEval("get(g:, 'Lf_GitDiffViewMode', 'unified')") + + self._winid = winid + self._buffer = vim.buffers[int(lfEval("winbufnr({})".format(winid)))] + self._buffer[:] = self._head + self.setDiffViewMode(self._diff_view_mode) + self._arguments = cmd.getArguments() TreeView(self, cmd, project_root, target_path, callback).create(winid, bufhidden="hide") lfCmd("call win_execute({}, 'let b:lf_navigation_matches = getmatches()')".format(winid)) + self.defineMaps(winid) + + def defineMaps(self, winid): + lfCmd("call win_execute({}, 'call leaderf#Git#NavigationPanelMaps({})')" + .format(winid, id(self))) + + def setDiffViewMode(self, mode): + self._buffer.options['modifiable'] = True + if mode == 'side-by-side': + self._buffer[1] = ' Side-by-side ◉ Unified ○' + + diffopt = lfEval("&diffopt") + if "iwhiteall" in diffopt: + self._buffer[2] = ' Ignore Whitespace 🗹 ' + else: + self._buffer[2] = ' Ignore Whitespace 🗷 ' + + if "algorithm:" in diffopt: + algo = re.sub(r".*algorithm:(\w+).*", r"\1", diffopt) + self.setDiffAlgorithm(algo) + else: + self.setDiffAlgorithm("myers") + else: + self._buffer[1] = ' Side-by-side ○ Unified ◉' + self._buffer.options['modifiable'] = False + + def setIgnoreWhitespace(self, diff_view_mode, ignore): + self._buffer.options['modifiable'] = True + if diff_view_mode == 'side-by-side': + if "iwhiteall" in lfEval("&diffopt"): + self._buffer[2] = ' Ignore Whitespace 🗹 ' + else: + self._buffer[2] = ' Ignore Whitespace 🗷 ' + else: + if ignore == True: + self._buffer[2] = ' Ignore Whitespace 🗹 ' + else: + self._buffer[2] = ' Ignore Whitespace 🗷 ' + self._buffer.options['modifiable'] = False + + def setDiffAlgorithm(self, algorithm): + self._buffer.options['modifiable'] = True + if algorithm == 'myers': + self._buffer[3] = ' Myers ◉ Minimal ○ Patience ○ Histogram ○' + elif algorithm == 'minimal': + self._buffer[3] = ' Myers ○ Minimal ◉ Patience ○ Histogram ○' + elif algorithm == 'patience': + self._buffer[3] = ' Myers ○ Minimal ○ Patience ◉ Histogram ○' + elif algorithm == 'histogram': + self._buffer[3] = ' Myers ○ Minimal ○ Patience ○ Histogram ◉' + self._buffer.options['modifiable'] = False + + def selectOption(self): + mouse_pos = lfEval("getmousepos()") + column = int(mouse_pos["column"]) + if mouse_pos["line"] == '2': + if column >= 5 and column <= 18: + mode = 'side-by-side' + elif column >= 22 and column <= 30: + mode = 'unified' + else: + mode = None + + if mode is not None and mode != self._diff_view_mode: + self.toggleDiffViewMode() + elif mouse_pos["line"] == '3': + if column >= 5 and column <= 23: + self.toggleIgnoreWhitespace() + elif mouse_pos["line"] == '4': + if column >= 5 and column <= 11: + diff_algorithm = 'myers' + elif column >= 15 and column <= 23: + diff_algorithm = 'minimal' + elif column >= 27 and column <= 36: + diff_algorithm = 'patience' + elif column >= 40 and column <= 50: + diff_algorithm = 'histogram' + else: + diff_algorithm = self._diff_algorithm + + if self._diff_algorithm != diff_algorithm: + self._diff_algorithm = diff_algorithm + self.selectDiffAlgorithm() + + def selectDiffAlgorithm(self): + self.setDiffAlgorithm(self._diff_algorithm) + if self._diff_view_mode == 'side-by-side': + lfCmd("set diffopt+=internal") + diffopt = lfEval("&diffopt") + if "algorithm:" in diffopt: + diffopt = re.sub(r"(?<=algorithm:)\w+", self._diff_algorithm, diffopt) + lfCmd("let &diffopt = '{}'".format(diffopt)) + else: + lfCmd("set diffopt+=algorithm:{}".format(self._diff_algorithm)) + else: + self.openDiffView(False, preview=True, diff_view_source=True) + + def toggleDiffViewMode(self): + if self._diff_view_mode == 'side-by-side': + self._diff_view_mode = 'unified' + self._ignore_whitespace = "iwhiteall" in lfEval("&diffopt") + else: + self._diff_view_mode = 'side-by-side' + if self._ignore_whitespace == True: + lfCmd("set diffopt+=iwhiteall") + else: + lfCmd("set diffopt-=iwhiteall") + + self.setDiffViewMode(self._diff_view_mode) + + if self._diff_view_mode == 'side-by-side': + diffopt = lfEval("&diffopt") + if "algorithm:" in diffopt: + algo = re.sub(r".*algorithm:(\w+).*", r"\1", diffopt) + self._diff_algorithm = algo + else: + self._diff_algorithm = "myers" + + self.openDiffView(False, preview=True, diff_view_source=True) + + def toggleIgnoreWhitespace(self): + if self._diff_view_mode == 'side-by-side': + if "iwhiteall" in lfEval("&diffopt"): + lfCmd("set diffopt-=iwhiteall") + else: + lfCmd("set diffopt+=iwhiteall") + self.setIgnoreWhitespace(self._diff_view_mode, self._ignore_whitespace) + else: + self._ignore_whitespace = not self._ignore_whitespace + self.setIgnoreWhitespace(self._diff_view_mode, self._ignore_whitespace) + self.openDiffView(False, preview=True, diff_view_source=True) + + def openDiffView(self, recursive, **kwargs): + return self._owner.openDiffView(recursive, **kwargs) + def open(self): buffer_name = self.tree_view.getBufferName() navigation_winid = int(lfEval("bufwinid('{}')".format(escQuote(buffer_name)))) @@ -2803,6 +2926,34 @@ def open(self): def getWindowId(self): return self.tree_view.getWindowId() + def locateFile(self, path, line_num=None, preview=True): + self.tree_view.locateFile(path) + self.openDiffView(False, line_num=line_num, preview=preview) + + @ensureWorkingDirectory + def fuzzySearch(self, recall=False): + if self._git_diff_manager is None: + self._git_diff_manager = GitDiffExplManager() + + kwargs = {} + kwargs["arguments"] = { + "owner": self._owner._owner, + "commit_id": self._commit_id, + "parent": self.tree_view.getCurrentParent(), + "content": self.tree_view.getFileList(), + "accept": self.locateFile + } + + if recall == True: + kwargs["arguments"]["--recall"] = [] + + self._git_diff_manager.startExplorer("popup", **kwargs) + + @ensureWorkingDirectory + def showCommitMessage(self): + cmd = "git show {} -s --decorate --pretty=fuller".format(self._commit_id) + lfCmd("""call leaderf#Git#ShowCommitMessage(systemlist('{}'))""".format(cmd)) + class BlamePanel(Panel): def __init__(self, owner): @@ -2948,18 +3099,12 @@ def create(self, arguments_dict, cmd, project_root=None): class ExplorerPage(object): def __init__(self, project_root, commit_id, owner): self._project_root = project_root - self._navigation_panel = NavigationPanel(self.afterBufhidden) - self._navigation_buffer_name = None + self._navigation_panel = NavigationPanel(self, project_root, commit_id, self.afterBufhidden) self._diff_view_panel = DiffViewPanel(self.afterBufhidden, commit_id) self._unified_diff_view_panel = UnifiedDiffViewPanel(self.afterBufhidden, commit_id) self.commit_id = commit_id self._owner = owner self._arguments = {} - self.tabpage = None - self._git_diff_manager = None - self._diff_view_mode = None - self._ignore_whitespace = False - self._diff_algorithm = 'myers' def openNavigationPanel(self): self._navigation_panel.open() @@ -3007,12 +3152,8 @@ def splitWindow(self, win_pos): return int(lfEval("win_getid()")) - def defineMaps(self, winid): - lfCmd("call win_execute({}, 'call leaderf#Git#ExplorerMaps({})')" - .format(winid, id(self))) - def getDiffViewPanel(self): - if self._diff_view_mode == "side-by-side": + if self._navigation_panel.getDiffViewMode() == "side-by-side": return self._diff_view_panel else: return self._unified_diff_view_panel @@ -3021,19 +3162,10 @@ def create(self, arguments_dict, cmd, target_path=None, line_num=None): self._arguments = arguments_dict lfCmd("noautocmd tabnew") - self.tabpage = vim.current.tabpage diff_view_winid = int(lfEval("win_getid()")) win_pos = arguments_dict.get("--navigation-position", ["left"])[0] - self._navigation_buffer_name = cmd.getBufferName() - winid = self._createWindow(win_pos, self._navigation_buffer_name) - - if "-u" in arguments_dict: - self._diff_view_mode = "unified" - elif "-s" in arguments_dict: - self._diff_view_mode = "side-by-side" - else: - self._diff_view_mode = lfEval("get(g:, 'Lf_GitDiffViewMode', 'unified')") + winid = self._createWindow(win_pos, cmd.getBufferName()) callback = partial(self.getDiffViewPanel().create, arguments_dict, @@ -3041,9 +3173,12 @@ def create(self, arguments_dict, cmd, target_path=None, line_num=None): line_num=line_num, project_root=self._project_root, explorer_page_id=id(self)) - self._navigation_panel.create(cmd, winid, self._project_root, target_path, callback) - self._navigation_panel.tree_view.setDiffViewMode(self._diff_view_mode) - self.defineMaps(self._navigation_panel.getWindowId()) + self._navigation_panel.create(arguments_dict, + cmd, + winid, + self._project_root, + target_path, + callback) def afterBufhidden(self): if (self._navigation_panel.isHidden() and self._diff_view_panel.isAllHidden() @@ -3056,52 +3191,6 @@ def cleanup(self): self._unified_diff_view_panel.cleanup() self._owner.cleanupExplorerPage(self) - def selectOption(self): - mouse_pos = lfEval("getmousepos()") - column = int(mouse_pos["column"]) - if mouse_pos["line"] == '2': - if column >= 5 and column <= 18: - mode = 'side-by-side' - elif column >= 22 and column <= 30: - mode = 'unified' - else: - mode = None - - if mode is not None and mode != self._diff_view_mode: - self.toggleDiffViewMode() - elif mouse_pos["line"] == '3': - if column >= 5 and column <= 23: - self.toggleIgnoreWhitespace() - elif mouse_pos["line"] == '4': - if column >= 5 and column <= 11: - diff_algorithm = 'myers' - elif column >= 15 and column <= 23: - diff_algorithm = 'minimal' - elif column >= 27 and column <= 36: - diff_algorithm = 'patience' - elif column >= 40 and column <= 50: - diff_algorithm = 'histogram' - else: - diff_algorithm = self._diff_algorithm - - if self._diff_algorithm != diff_algorithm: - self._diff_algorithm = diff_algorithm - self.selectDiffAlgorithm() - - def selectDiffAlgorithm(self): - self._navigation_panel.tree_view.setDiffAlgorithm(self._diff_algorithm) - if self._diff_view_mode == 'side-by-side': - lfCmd("set diffopt+=internal") - diffopt = lfEval("&diffopt") - if "algorithm:" in diffopt: - diffopt = re.sub(r"(?<=algorithm:)\w+", self._diff_algorithm, diffopt) - lfCmd("let &diffopt = '{}'".format(diffopt)) - else: - lfCmd("set diffopt+=algorithm:{}".format(self._diff_algorithm)) - else: - source = self.getExistingSource() - self.open(False, preview=True, diff_view_source=source) - def getExistingSource(self): for w in vim.current.tabpage.windows: source = lfEval("getbufvar({}, 'lf_diff_view_source', 0)".format(w.buffer.number)) @@ -3110,63 +3199,25 @@ def getExistingSource(self): return None - def toggleDiffViewMode(self): - if self._diff_view_mode == 'side-by-side': - self._diff_view_mode = 'unified' - self._ignore_whitespace = "iwhiteall" in lfEval("&diffopt") - else: - self._diff_view_mode = 'side-by-side' - if self._ignore_whitespace == True: - lfCmd("set diffopt+=iwhiteall") - else: - lfCmd("set diffopt-=iwhiteall") - - self._navigation_panel.tree_view.setDiffViewMode(self._diff_view_mode) - - if self._diff_view_mode == 'side-by-side': - diffopt = lfEval("&diffopt") - if "algorithm:" in diffopt: - algo = re.sub(r".*algorithm:(\w+).*", r"\1", diffopt) - self._diff_algorithm = algo - else: - self._diff_algorithm = "myers" - - source = self.getExistingSource() - self.open(False, preview=True, diff_view_source=source) - - def toggleIgnoreWhitespace(self): - if self._diff_view_mode == 'side-by-side': - if "iwhiteall" in lfEval("&diffopt"): - lfCmd("set diffopt-=iwhiteall") - else: - lfCmd("set diffopt+=iwhiteall") - self._navigation_panel.tree_view.setIgnoreWhitespace(self._diff_view_mode, - self._ignore_whitespace) - else: - self._ignore_whitespace = not self._ignore_whitespace - self._navigation_panel.tree_view.setIgnoreWhitespace(self._diff_view_mode, - self._ignore_whitespace) - source = self.getExistingSource() - self.open(False, preview=True, diff_view_source=source) - - def makeOnly(self): + diff_view_mode = self._navigation_panel.getDiffViewMode() for w in vim.current.tabpage.windows: if (lfEval("getbufvar({}, 'lf_diff_view_mode', '{}')".format(w.buffer.number, - self._diff_view_mode)) - != self._diff_view_mode): + diff_view_mode)) + != diff_view_mode): lfCmd("only") break - def open(self, recursive, **kwargs): + def openDiffView(self, recursive, **kwargs): kwargs["project_root"] = self._project_root kwargs["explorer_page_id"] = id(self) - kwargs["ignore_whitespace"] = self._ignore_whitespace - kwargs["diff_algorithm"] = self._diff_algorithm + kwargs["ignore_whitespace"] = self._navigation_panel.getIgnoreWhitespace() + kwargs["diff_algorithm"] = self._navigation_panel.getDiffAlgorithm() if "diff_view_source" in kwargs: - source = kwargs["diff_view_source"] + source = self.getExistingSource() else: source = self._navigation_panel.tree_view.expandOrCollapseFolder(recursive) + if source is not None: self.makeOnly() @@ -3186,34 +3237,6 @@ def open(self, recursive, **kwargs): if kwargs.get("preview", False) == True: lfCmd("call win_gotoid({})".format(self._navigation_panel.getWindowId())) - def locateFile(self, path, line_num=None, preview=True): - self._navigation_panel.tree_view.locateFile(path) - self.open(False, line_num=line_num, preview=preview) - - @ensureWorkingDirectory - def fuzzySearch(self, recall=False): - if self._git_diff_manager is None: - self._git_diff_manager = GitDiffExplManager() - - kwargs = {} - kwargs["arguments"] = { - "owner": self._owner, - "commit_id": self.commit_id, - "parent": self._navigation_panel.tree_view.getCurrentParent(), - "content": self._navigation_panel.tree_view.getFileList(), - "accept": self.locateFile - } - - if recall == True: - kwargs["arguments"]["--recall"] = [] - - self._git_diff_manager.startExplorer("popup", **kwargs) - - @ensureWorkingDirectory - def showCommitMessage(self): - cmd = "git show {} -s --decorate --pretty=fuller".format(self.commit_id) - lfCmd("""call leaderf#Git#ShowCommitMessage(systemlist('{}'))""".format(cmd)) - #***************************************************** # GitExplManager From 46e00c91d8bf24871a14ed0ef0a29070c303e27a Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 27 Mar 2025 13:47:26 +0800 Subject: [PATCH 337/365] fix a bug introduced by last commit --- autoload/leaderf/python/leaderf/gitExpl.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 1bf376ad..86cc73ac 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -3105,6 +3105,7 @@ def __init__(self, project_root, commit_id, owner): self.commit_id = commit_id self._owner = owner self._arguments = {} + self.tabpage = None def openNavigationPanel(self): self._navigation_panel.open() @@ -3162,6 +3163,7 @@ def create(self, arguments_dict, cmd, target_path=None, line_num=None): self._arguments = arguments_dict lfCmd("noautocmd tabnew") + self.tabpage = vim.current.tabpage diff_view_winid = int(lfEval("win_getid()")) win_pos = arguments_dict.get("--navigation-position", ["left"])[0] @@ -3237,6 +3239,9 @@ def openDiffView(self, recursive, **kwargs): if kwargs.get("preview", False) == True: lfCmd("call win_gotoid({})".format(self._navigation_panel.getWindowId())) + def locateFile(self, path, line_num=None, preview=True): + self._navigation_panel.locateFile(path, line_num, preview) + #***************************************************** # GitExplManager From 16484c86c92a7e4b46d3a12da97979d7fba50886 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Fri, 28 Mar 2025 14:52:39 +0800 Subject: [PATCH 338/365] escape parentheses --- autoload/leaderf/python/leaderf/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autoload/leaderf/python/leaderf/utils.py b/autoload/leaderf/python/leaderf/utils.py index d7df204a..a563adda 100644 --- a/autoload/leaderf/python/leaderf/utils.py +++ b/autoload/leaderf/python/leaderf/utils.py @@ -141,7 +141,7 @@ def escQuote(str): return "" if str is None else str.replace("'","''") def escSpecial(str): - return re.sub('([%#$" ])', r"\\\1", str) + return re.sub('([()%#$" ])', r"\\\1", str) def equal(str1, str2, ignorecase=True): if ignorecase: From be03bd851327506de2d3d6858c08003c68b95c09 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 10 Apr 2025 10:25:38 +0800 Subject: [PATCH 339/365] add support for `Leaderf git status` --- autoload/leaderf/Any.vim | 9 + autoload/leaderf/Git.vim | 3 +- .../leaderf/colorscheme/popup/default.vim | 4 + autoload/leaderf/python/leaderf/gitExpl.py | 328 ++++++++++++++---- autoload/leaderf/python/leaderf/utils.py | 7 + 5 files changed, 287 insertions(+), 64 deletions(-) diff --git a/autoload/leaderf/Any.vim b/autoload/leaderf/Any.vim index efccf119..72ff9e62 100644 --- a/autoload/leaderf/Any.vim +++ b/autoload/leaderf/Any.vim @@ -66,6 +66,7 @@ let g:Lf_Helps = { \ "loclist": "navigate location list", \ "jumps": "navigate jumps list", \ "git": "use git", + \ "git-status": "show git status", \ "git-log": "show the commit logs", \ "git-diff": "show changes between commits, commit and working tree, etc", \ "git-blame": "show what revision and author last modified each line of a file", @@ -270,6 +271,14 @@ let g:Lf_Arguments = { \ "metavar": "", "help": "Specifies the format used to output dates. .i.e, git blame --date=. can be one of ['relative', 'local', 'iso', 'iso-strict', 'rfc', 'short', 'default']"}, \ {"name": ["--inline"], "nargs": 0, "help": "Display inline git blame information."}, \ ], + \ "status": [ + \ {"name": ["--navigation-position"], "nargs": 1, "choices": ["top", "right", "bottom", "left"], "metavar": "", + \ "help": "specifies the position of the navigation panel"}, + \ [ + \ {"name": ["-s", "--side-by-side"], "nargs": 0, "help": "show diffs in a side-by-side view"}, + \ {"name": ["-u", "--unified"], "nargs": 0, "help": "show diffs in a unified view"}, + \ ], + \ ], \ }, \ "coc":{ \ "definitions": [ diff --git a/autoload/leaderf/Git.vim b/autoload/leaderf/Git.vim index 24dbc73c..05ef5d33 100644 --- a/autoload/leaderf/Git.vim +++ b/autoload/leaderf/Git.vim @@ -390,7 +390,6 @@ endfunction function! leaderf#Git#TreeViewMaps(id) abort exec g:Lf_py "import ctypes" let tree_view = printf("ctypes.cast(%d, ctypes.py_object).value", a:id) - exec printf('nnoremap X :exec g:Lf_py "%s.collapseChildren()"', tree_view) nnoremap :call leaderf#Git#ShowHelp("tree") nnoremap - :call leaderf#Git#OuterIndent(0) nnoremap + :call leaderf#Git#OuterIndent(1) @@ -418,6 +417,7 @@ function! leaderf#Git#NavigationPanelMaps(id) abort exec printf('nnoremap i :exec g:Lf_py "%s.toggleIgnoreWhitespace()"', navigation_panel) exec printf('nnoremap p :exec g:Lf_py "%s.openDiffView(False, preview=True)"', navigation_panel) exec printf('nnoremap x :call leaderf#Git#CollapseParent("%s")', navigation_panel) + exec printf('nnoremap X :exec g:Lf_py "%s.collapseChildren()"', navigation_panel) exec printf('nnoremap f :exec g:Lf_py "%s.fuzzySearch()"', navigation_panel) exec printf('nnoremap F :exec g:Lf_py "%s.fuzzySearch(True)"', navigation_panel) exec printf('nnoremap m :exec g:Lf_py "%s.showCommitMessage()"', navigation_panel) @@ -533,6 +533,7 @@ endfunction function! leaderf#Git#Commands() abort if !exists("g:Lf_GitCommands") let g:Lf_GitCommands = [ + \ {"Leaderf git status": "show git status"}, \ {"Leaderf git diff": "fuzzy search and view the diffs"}, \ {"Leaderf git diff --side-by-side": "fuzzy search and view the side-by-side diffs"}, \ {"Leaderf git diff --side-by-side --current-file":"view the side-by-side diffs of the current file"}, diff --git a/autoload/leaderf/colorscheme/popup/default.vim b/autoload/leaderf/colorscheme/popup/default.vim index 3fa3b06c..e70cf349 100644 --- a/autoload/leaderf/colorscheme/popup/default.vim +++ b/autoload/leaderf/colorscheme/popup/default.vim @@ -144,6 +144,8 @@ if &background ==? 'dark' highlight def link Lf_hl_gitHash Identifier highlight def link Lf_hl_gitRefNames Special highlight def link Lf_hl_gitFolder Directory + highlight def link Lf_hl_gitTitle Label + highlight def link Lf_hl_gitFilesNum Number highlight def link Lf_hl_gitFolderIcon Special highlight def link Lf_hl_gitAddIcon Lf_hl_gitDiffAddition highlight def link Lf_hl_gitCopyIcon Number @@ -306,6 +308,8 @@ else highlight def link Lf_hl_gitHash Identifier highlight def link Lf_hl_gitRefNames Special highlight def link Lf_hl_gitFolder Directory + highlight def link Lf_hl_gitTitle Label + highlight def link Lf_hl_gitFilesNum Number highlight def link Lf_hl_gitFolderIcon Special highlight def link Lf_hl_gitAddIcon Lf_hl_gitDiffAddition highlight def link Lf_hl_gitCopyIcon Number diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 86cc73ac..cdbc7d22 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -8,6 +8,7 @@ import os.path import json import bisect +import ctypes import tempfile import itertools from pathlib import PurePath @@ -260,6 +261,9 @@ def getArguments(self): def getSource(self): return self._source + def getTitle(self): + return None + class GitDiffCommand(GitCommand): def __init__(self, arguments_dict, source): @@ -423,6 +427,46 @@ def buildCommandAndBufferName(self): self._file_type_cmd = "" +class GitStagedCommand(GitCommand): + def __init__(self, arguments_dict, source): + super(GitStagedCommand, self).__init__(arguments_dict, source) + + def buildCommandAndBufferName(self): + self._cmd = 'git diff --cached --raw -C --numstat --shortstat --no-abbrev' + extra_options = "" + + if "extra" in self._arguments: + extra_options += " " + " ".join(self._arguments["extra"]) + + self._cmd += extra_options + + self._buffer_name = "LeaderF://navigation/" + self._source + self._file_type_cmd = "" + + def getTitle(self): + return "Staged Changes:" + + +class GitUnstagedCommand(GitCommand): + def __init__(self, arguments_dict, source): + super(GitUnstagedCommand, self).__init__(arguments_dict, source) + + def buildCommandAndBufferName(self): + self._cmd = 'git diff --raw -C --numstat --shortstat --no-abbrev' + extra_options = "" + + if "extra" in self._arguments: + extra_options += " " + " ".join(self._arguments["extra"]) + + self._cmd += extra_options + + self._buffer_name = "LeaderF://navigation/" + self._source + self._file_type_cmd = "" + + def getTitle(self): + return "Unstaged Changes:" + + class GitLogExplCommand(GitCommand): def __init__(self, arguments_dict, source): """ @@ -621,9 +665,6 @@ def setOptions(self, winid, bufhidden): if lfEval("getbufvar(winbufnr(%d), '&ft')" % winid) != self._cmd.getFileType(): lfCmd("silent! call win_execute({}, '{}')".format(winid, self._cmd.getFileTypeCommand())) - def initBuffer(self): - pass - def defineMaps(self, winid): pass @@ -674,7 +715,6 @@ def create(self, winid, bufhidden='wipe', buf_content=None, format_line=None): self._owner.writeFinished(self.getWindowId()) return - self.initBuffer() self.start() def writeBuffer(self): @@ -739,7 +779,7 @@ def cleanup(self, wipe=True): # must do this at last self._executor.killProcess() - if self._bufhidden == "hide" and wipe == True: + if self._bufhidden == "hide" and wipe == True and self._buffer.valid: lfCmd("noautocmd bwipe! {}".format(self._buffer.number)) def suicide(self): @@ -1147,13 +1187,14 @@ def bisect_right(a, x, lo=0, hi=None, *, key=None): class TreeView(GitCommandView): - def __init__(self, owner, cmd, project_root, target_path, callback): + def __init__(self, owner, cmd, project_root, target_path, callback, next_tree_view=None): super(TreeView, self).__init__(owner, cmd) self._project_root = project_root self._target_path = target_path # the argument is source, source is a tuple like # (b90f76fc1, bad07e644, R099, src/version.c, src/version2.c) self._callback = callback + self._next_tree_view = next_tree_view # key is the parent hash, value is a TreeNode self._trees = LfOrderedDict() # key is the parent hash, value is a list of MetaInfo @@ -1182,13 +1223,11 @@ def __init__(self, owner, cmd, project_root, target_path, callback): "M": self._modification_icon, "R": self._rename_icon, } - self._head = [ - self._project_root + os.sep, - ] self._match_ids = [] + self._init = False def startLine(self): - return self._owner.startLine() + return self._owner.startLine(self) def enableColor(self, winid): if lfEval("hlexists('Lf_hl_help')") == '0': @@ -1203,6 +1242,14 @@ def enableColor(self, winid): .format(winid)) id = int(lfEval("matchid")) self._match_ids.append(id) + lfCmd(r"""call win_execute({}, 'let matchid = matchadd(''Lf_hl_gitTitle'', ''.*:'', -100)')""" + .format(winid)) + id = int(lfEval("matchid")) + self._match_ids.append(id) + lfCmd(r"""call win_execute({}, 'let matchid = matchadd(''Lf_hl_gitFilesNum'', ''(\d\+)'', -100)')""" + .format(winid)) + id = int(lfEval("matchid")) + self._match_ids.append(id) lfCmd(r"""call win_execute({}, 'let matchid = matchadd(''Lf_hl_gitFolderIcon'', ''^\s*\zs[{}{}]'', -100)')""" .format(winid, self._closed_folder_icon, self._open_folder_icon)) id = int(lfEval("matchid")) @@ -1288,7 +1335,7 @@ def getCurrentParent(self): return self._cur_parent def getFileList(self): - return self._file_list[self._cur_parent] + return self._file_list.get(self._cur_parent, []) @staticmethod def generateSource(line): @@ -1404,6 +1451,8 @@ def buildTree(self, line): parent, tree_node = self._trees.last_key_value() root_node = tree_node mode, source = TreeView.generateSource(line) + if source[2] == "U": + return file_path = lfGetFilePath(source) icon = webDevIconsGetFileTypeSymbol(file_path) if self._show_icon else "" self._file_list[parent].append("{:<4} {}{}{}" @@ -1511,6 +1560,9 @@ def metaInfoGenerator(self, meta_info, recursive, level): def expandOrCollapseFolder(self, recursive=False): with self._lock: + if len(self._file_structures) == 0: + return None + line_num = int(lfEval("getcurpos({})[1]".format(self.getWindowId()))) index = line_num - self.startLine() # the root @@ -1563,12 +1615,13 @@ def collapseChildren(self): def expandRoot(self, line_num): meta_info = MetaInfo(-1, True, "", self._trees[self._cur_parent], "") + orig_len = len(self._file_structures[self._cur_parent]) self._file_structures[self._cur_parent] = list(self.metaInfoGenerator(meta_info, True, -1)) self._buffer.options['modifiable'] = True structure = self._file_structures[self._cur_parent] try: increment = len(structure) - self._buffer[line_num:] = [self.buildLine(info) for info in structure] + self._buffer[line_num : line_num+orig_len] = [self.buildLine(info) for info in structure] self._offset_in_content = increment finally: self._buffer.options['modifiable'] = False @@ -1728,13 +1781,12 @@ def buildLine(self, meta_info): def setOptions(self, winid, bufhidden): super(TreeView, self).setOptions(winid, bufhidden) - lfCmd(r"""call win_execute({}, 'let &l:stl="%#Lf_hl_gitStlChangedNum# 0 %#Lf_hl_gitStlFileChanged#file changed, %#Lf_hl_gitStlAdd#0 (+), %#Lf_hl_gitStlDel#0 (-)"')""" - .format(winid)) + if self._cmd.getTitle() is None: + lfCmd(r"""call win_execute({}, 'let &l:stl="%#Lf_hl_gitStlChangedNum# 0 %#Lf_hl_gitStlFileChanged#file changed, %#Lf_hl_gitStlAdd#0 (+), %#Lf_hl_gitStlDel#0 (-)"')""" + .format(winid)) if lfEval("has('nvim')") == '1': - lfCmd("call nvim_win_set_option(%d, 'cursorline', v:false)" % winid) lfCmd("call nvim_win_set_option(%d, 'number', v:false)" % winid) else: - lfCmd("call win_execute({}, 'setlocal nocursorline')".format(winid)) lfCmd("call win_execute({}, 'setlocal nonumber')".format(winid)) lfCmd("call win_execute({}, 'noautocmd setlocal sw=2 tabstop=4')".format(winid)) lfCmd("call win_execute({}, 'setlocal signcolumn=no')".format(winid)) @@ -1753,11 +1805,32 @@ def setOptions(self, winid, bufhidden): .format(lfEval("get(g:, 'Lf_PopupColorscheme', 'default')"))) def initBuffer(self): - self._buffer.options['modifiable'] = True - try: - self._buffer.append(self._head) - finally: - self._buffer.options['modifiable'] = False + if self._init == True: + return + + self._init = True + + self._buffer.append('') + title = self._cmd.getTitle() + if title is not None: + self._buffer.append(title) + + self._buffer.append(shrinkUser(self._project_root) + os.sep) + + def getCommand(self): + return self._cmd + + def getTitleHeight(self): + if self._cmd.getTitle() is None: + return 0 + else: + return 1 + + def getHeight(self): + if len(self._file_structures) == 0: + return 0 + + return len(self._file_structures[self._cur_parent]) def refreshNumStat(self): self._buffer.options['modifiable'] = True @@ -1774,6 +1847,10 @@ def refreshNumStat(self): def writeBuffer(self): if self._cur_parent is None: + if self._read_finished == 1: + self.stopTimer() + if self._next_tree_view is not None: + self._next_tree_view() return if self._read_finished == 2: @@ -1788,14 +1865,12 @@ def writeBuffer(self): try: structure = self._file_structures[self._cur_parent] cur_len = len(structure) + if cur_len > 0: + self.initBuffer() + if cur_len > self._offset_in_content: - cursor_line = int(lfEval("getcurpos({})[1]".format(self.getWindowId()))) init_line = self.startLine() - 1 - - if cursor_line <= init_line: - lfCmd("call win_execute({}, 'norm! {}G')" - .format(self.getWindowId(), init_line)) - cursor_line = int(lfEval("getcurpos({})[1]".format(self.getWindowId()))) + cursor_line = init_line source = None for info in structure[self._offset_in_content:cur_len]: @@ -1805,8 +1880,7 @@ def writeBuffer(self): cursor_line = len(self._buffer) source = info.info - if source is not None: - self._callback(source) + if source is not None and self._callback(source, tree_view_id=id(self)) == True: if lfEval("has('nvim')") == '1': lfCmd("call nvim_win_set_option({}, 'cursorline', v:true)" .format(self.getWindowId())) @@ -1826,16 +1900,30 @@ def writeBuffer(self): if self._read_finished == 1 and self._offset_in_content == len(structure): self.refreshNumStat() - shortstat = re.sub(r"( \d+)( files? changed)", - r"%#Lf_hl_gitStlChangedNum#\1%#Lf_hl_gitStlFileChanged#\2", - self._short_stat[self._cur_parent]) - shortstat = re.sub(r"(\d+) insertions?", r"%#Lf_hl_gitStlAdd#\1 ",shortstat) - shortstat = re.sub(r"(\d+) deletions?", r"%#Lf_hl_gitStlDel#\1 ", shortstat) - lfCmd(r"""call win_execute({}, 'let &l:stl="{}"')""" - .format(self.getWindowId(), shortstat)) + if self._cmd.getTitle() is None: + shortstat = re.sub(r"( \d+)( files? changed)", + r"%#Lf_hl_gitStlChangedNum#\1%#Lf_hl_gitStlFileChanged#\2", + self._short_stat[self._cur_parent]) + shortstat = re.sub(r"(\d+) insertions?", r"%#Lf_hl_gitStlAdd#\1 ",shortstat) + shortstat = re.sub(r"(\d+) deletions?", r"%#Lf_hl_gitStlDel#\1 ", shortstat) + lfCmd(r"""call win_execute({}, 'let &l:stl="{}"')""" + .format(self.getWindowId(), shortstat)) + else: + num = self._short_stat[self._cur_parent].split(None, 1)[0] + self._setChangedFilesNum(num) self._read_finished = 2 self._owner.writeFinished(self.getWindowId()) self.stopTimer() + if self._next_tree_view is not None: + self._next_tree_view() + + def _setChangedFilesNum(self, num): + self._buffer.options['modifiable'] = True + try: + title = self._buffer[self.startLine() - 3] + self._buffer[self.startLine() - 3] = title.replace(':', ' ({}):'.format(num)) + finally: + self._buffer.options['modifiable'] = False def _readContent(self, encoding): try: @@ -2181,6 +2269,8 @@ def create(self, arguments_dict, source, **kwargs): lfCmd("call win_execute({}, 'setlocal cursorline')".format(winid)) lfCmd("call win_execute({}, 'let b:lf_explorer_page_id = {}')" .format(winid, kwargs.get("explorer_page_id", 0))) + lfCmd("call win_execute({}, 'let b:lf_tree_view_id = {}')" + .format(winid, kwargs.get("tree_view_id", 0))) lfCmd("call win_execute({}, 'let b:lf_git_diff_win_pos = {}')".format(winid, i)) lfCmd("call win_execute({}, 'let b:lf_git_diff_win_id = {}')".format(winid, win_ids[1])) lfCmd("""call win_execute(%d, "let b:lf_git_buffer_name = '%s'")""" @@ -2442,8 +2532,12 @@ def create(self, arguments_dict, source, **kwargs): "patience": 4, "histogram": 6 } + if source[1].startswith("0000000"): + commit_id = hex(int(self._commit_id, 16) + int(source[0][-7:], 16))[2:] + else: + commit_id = self._commit_id uid = algo_dict[diff_algorithm] + int(ignore_whitespace) - buf_name = "LeaderF://{}:{}:{}".format(self._commit_id, + buf_name = "LeaderF://{}:{}:{}".format(commit_id, uid, lfGetFilePath(source)) if buf_name in self._views: @@ -2658,6 +2752,7 @@ def create(self, arguments_dict, source, **kwargs): lfCmd("let b:Leaderf_matches = getmatches()") lfCmd("let b:lf_change_start_lines = {}".format(str(change_start_lines))) lfCmd("let b:lf_explorer_page_id = {}".format(kwargs.get("explorer_page_id", 0))) + lfCmd("let b:lf_tree_view_id = {}".format(kwargs.get("tree_view_id", 0))) lfCmd("let b:lf_diff_view_mode = 'unified'") lfCmd("let b:lf_diff_view_source = {}".format(str(list(source)))) key_map = lfEval("g:Lf_GitKeyMap") @@ -2695,7 +2790,7 @@ def __init__(self, owner, project_root, commit_id, bufhidden_callback=None): self._owner = owner self._project_root = project_root self._commit_id = commit_id - self.tree_view = None + self._tree_view = [] self._bufhidden_cb = bufhidden_callback self._is_hidden = False self._arguments = {} @@ -2703,18 +2798,35 @@ def __init__(self, owner, project_root, commit_id, bufhidden_callback=None): self._ignore_whitespace = False self._diff_algorithm = 'myers' self._git_diff_manager = None - self._winid = None self._buffer = None self._head = [ '" Press for help', ' Side-by-side ◉ Unified ○', ' Ignore Whitespace 🗷 ', ' Myers ◉ Minimal ○ Patience ○ Histogram ○', - '', ] - def startLine(self): - return len(self._head) + 1 + 1 + def startLine(self, tree_view): + n = len(self._head) + 1 + for view in self._tree_view: + if view.getHeight() > 0: + n += view.getTitleHeight() + 2 + + if tree_view is view: + return n + else: + n += view.getHeight() + + return n + + def getTreeView(self): + line_num = int(lfEval("getcurpos({})[1]".format(self.getWindowId()))) + n = len(self._head) + 1 + for view in self._tree_view: + if view.getHeight() > 0: + n += view.getTitleHeight() + view.getHeight() + 2 + if line_num < n: + return view def getDiffViewMode(self): return self._diff_view_mode @@ -2726,7 +2838,7 @@ def getDiffAlgorithm(self): return self._diff_algorithm def register(self, view): - self.tree_view = view + self._tree_view.append(view) def bufHidden(self, view): self._is_hidden = True @@ -2737,11 +2849,12 @@ def isHidden(self): return self._is_hidden def cleanup(self): - if self.tree_view is not None: - self.tree_view.cleanup() - self.tree_view = None + for view in self._tree_view: + if view is not None: + view.cleanup() + self._tree_view = [] - def create(self, arguments_dict, cmd, winid, project_root, target_path, callback): + def create(self, arguments_dict, command, winid, project_root, target_path, callback): if "-u" in arguments_dict: self._diff_view_mode = "unified" elif "-s" in arguments_dict: @@ -2749,13 +2862,39 @@ def create(self, arguments_dict, cmd, winid, project_root, target_path, callback else: self._diff_view_mode = lfEval("get(g:, 'Lf_GitDiffViewMode', 'unified')") - self._winid = winid self._buffer = vim.buffers[int(lfEval("winbufnr({})".format(winid)))] self._buffer[:] = self._head self.setDiffViewMode(self._diff_view_mode) - self._arguments = cmd.getArguments() - TreeView(self, cmd, project_root, target_path, callback).create(winid, bufhidden="hide") + flag = [False] + def wrapper(cb, flag, *args, **kwargs): + if flag[0] == False: + flag[0] = True + cb(*args, **kwargs) + return True + else: + return False + + if isinstance(command, list): + def createTreeView(cmds): + if len(cmds) > 0: + TreeView(self, cmds[0], + project_root, + target_path, + partial(wrapper, callback, flag), + partial(createTreeView, cmds[1:]) + ).create(winid, bufhidden="hide") + + self._arguments = command[0].getArguments() + createTreeView(command) + else: + self._arguments = command.getArguments() + TreeView(self, command, + project_root, + target_path, + partial(wrapper, callback, flag), + ).create(winid, bufhidden="hide") + lfCmd("call win_execute({}, 'let b:lf_navigation_matches = getmatches()')".format(winid)) self.defineMaps(winid) @@ -2894,12 +3033,13 @@ def openDiffView(self, recursive, **kwargs): return self._owner.openDiffView(recursive, **kwargs) def open(self): - buffer_name = self.tree_view.getBufferName() - navigation_winid = int(lfEval("bufwinid('{}')".format(escQuote(buffer_name)))) + navigation_winid = self.getWindowId() if navigation_winid != -1: lfCmd("call win_gotoid({})".format(navigation_winid)) return + tree_view_id = int(lfEval("b:lf_tree_view_id")) + buffer_name = self._buffer.name current_file_path = vim.current.buffer.name.rsplit(':', 1)[1] win_pos = self._arguments.get("--navigation-position", ["left"])[0] if win_pos == 'top': @@ -2921,13 +3061,21 @@ def open(self): lfCmd("call setmatches(b:lf_navigation_matches)") lfCmd("setlocal winfixwidth | wincmd =") self._is_hidden = False - self.tree_view.locateFile(current_file_path) + if len(self._tree_view) == 1: + self.getTreeView().locateFile(current_file_path) + else: + ctypes.cast(tree_view_id, ctypes.py_object).value.locateFile(current_file_path) def getWindowId(self): - return self.tree_view.getWindowId() + return int(lfEval("bufwinid('{}')".format(escQuote(self._buffer.name)))) + + def collapseChildren(self): + tree_view = self.getTreeView() + if tree_view is not None: + tree_view.collapseChildren() def locateFile(self, path, line_num=None, preview=True): - self.tree_view.locateFile(path) + self.getTreeView().locateFile(path) self.openDiffView(False, line_num=line_num, preview=preview) @ensureWorkingDirectory @@ -2935,12 +3083,17 @@ def fuzzySearch(self, recall=False): if self._git_diff_manager is None: self._git_diff_manager = GitDiffExplManager() + tree_view = self.getTreeView() + if tree_view is None: + return + kwargs = {} kwargs["arguments"] = { "owner": self._owner._owner, "commit_id": self._commit_id, - "parent": self.tree_view.getCurrentParent(), - "content": self.tree_view.getFileList(), + "command": tree_view.getCommand(), + "parent": tree_view.getCurrentParent(), + "content": tree_view.getFileList(), "accept": self.locateFile } @@ -3159,15 +3312,20 @@ def getDiffViewPanel(self): else: return self._unified_diff_view_panel - def create(self, arguments_dict, cmd, target_path=None, line_num=None): + def create(self, arguments_dict, command, target_path=None, line_num=None): self._arguments = arguments_dict lfCmd("noautocmd tabnew") self.tabpage = vim.current.tabpage diff_view_winid = int(lfEval("win_getid()")) - win_pos = arguments_dict.get("--navigation-position", ["left"])[0] - winid = self._createWindow(win_pos, cmd.getBufferName()) + + if isinstance(command, list): + buffer_name = command[0].getBufferName() + winid = self._createWindow(win_pos, buffer_name) + else: + buffer_name = command.getBufferName() + winid = self._createWindow(win_pos, buffer_name) callback = partial(self.getDiffViewPanel().create, arguments_dict, @@ -3175,8 +3333,9 @@ def create(self, arguments_dict, cmd, target_path=None, line_num=None): line_num=line_num, project_root=self._project_root, explorer_page_id=id(self)) + self._navigation_panel.create(arguments_dict, - cmd, + command, winid, self._project_root, target_path, @@ -3218,7 +3377,11 @@ def openDiffView(self, recursive, **kwargs): if "diff_view_source" in kwargs: source = self.getExistingSource() else: - source = self._navigation_panel.tree_view.expandOrCollapseFolder(recursive) + tree_view = self._navigation_panel.getTreeView() + if tree_view is None: + return + source = tree_view.expandOrCollapseFolder(recursive) + kwargs["tree_view_id"] = id(tree_view) if source is not None: self.makeOnly() @@ -3255,6 +3418,7 @@ def __init__(self): self._git_diff_manager = None self._git_log_manager = None self._git_blame_manager = None + self._git_status_manager = None self._selected_content = None self._project_root = None @@ -3302,6 +3466,10 @@ def getExplManager(self, subcommand): if self._git_blame_manager is None: self._git_blame_manager = GitBlameExplManager() return self._git_blame_manager + elif subcommand == "status": + if self._git_status_manager is None: + self._git_status_manager = GitStatusExplManager() + return self._git_status_manager else: return super(GitExplManager, self) @@ -3590,7 +3758,7 @@ def startExplorer(self, win_pos, *args, **kwargs): self._result_panel.create(self.createGitCommand(self._arguments, None)) self._restoreOrigCwd() elif "--explorer" in self._arguments: - uid = str(int(time.time()))[-7:] + uid = str(hex(int(time.time())))[-7:] page = ExplorerPage(self._project_root, uid, self) page.create(arguments_dict, GitDiffExplCommand(arguments_dict, uid)) self._pages.add(page) @@ -4642,6 +4810,40 @@ def cleanupExplorerPage(self, page): del self._pages[page.commit_id] +class GitStatusExplManager(GitExplManager): + def __init__(self): + super(GitStatusExplManager, self).__init__() + self._pages = set() + + def startExplorer(self, win_pos, *args, **kwargs): + arguments_dict = kwargs.get("arguments", {}) + if "--recall" not in arguments_dict and self.checkWorkingDirectory() == False: + return + + if "--recall" in arguments_dict: + super(GitExplManager, self).startExplorer(win_pos, *args, **kwargs) + else: + self.setArguments(arguments_dict) + + uid = str(hex(int(time.time())))[-7:] + page = ExplorerPage(self._project_root, uid, self) + command = [ + GitStagedCommand(arguments_dict, uid), + GitUnstagedCommand(arguments_dict, uid), + ] + page.create(arguments_dict, command) + self._pages.add(page) + + def getPreviewCommand(self, arguments_dict, source): + arguments_dict.update(self._arguments) + if isinstance(arguments_dict["command"], GitStagedCommand): + arguments_dict["--cached"] = [] + return GitDiffCommand(arguments_dict, source) + + def cleanupExplorerPage(self, page): + self._pages.discard(page) + + #***************************************************** # gitExplManager is a singleton #***************************************************** diff --git a/autoload/leaderf/python/leaderf/utils.py b/autoload/leaderf/python/leaderf/utils.py index a563adda..6fe6ab2f 100644 --- a/autoload/leaderf/python/leaderf/utils.py +++ b/autoload/leaderf/python/leaderf/utils.py @@ -230,6 +230,13 @@ def lfDrop(type, file_name, line_num=None): else: lfCmd("hide edit %s" % escSpecial(file_name)) + +def shrinkUser(path): + home = os.path.expanduser("~") + if path.lower().startswith(home): + return path.replace(home, "~", 1) + return path + def nearestAncestor(markers, path): """ return the nearest ancestor path(including itself) of `path` that contains From ee2825f3867ec12bb16b1ca53f3c7046273a31ef Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 10 Apr 2025 13:44:22 +0800 Subject: [PATCH 340/365] remove empty buffer added by tabnew --- autoload/leaderf/python/leaderf/gitExpl.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index cdbc7d22..dcfb1019 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -3314,7 +3314,7 @@ def getDiffViewPanel(self): def create(self, arguments_dict, command, target_path=None, line_num=None): self._arguments = arguments_dict - lfCmd("noautocmd tabnew") + lfCmd("noautocmd tabnew | setlocal bufhidden=wipe") self.tabpage = vim.current.tabpage diff_view_winid = int(lfEval("win_getid()")) From 11c771e4924ea700668bca5d6867c5084c7fd198 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Fri, 11 Apr 2025 10:56:28 +0800 Subject: [PATCH 341/365] there is no syntax color in preview window sometimes --- autoload/leaderf/python/leaderf/manager.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 0e48efae..8d72eee1 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -964,7 +964,6 @@ def _useExistingWindow(self, title, source, line_num, jump_cmd): elif lfEval("exists('*popup_setbuf')") == "1": if isinstance(source, int): lfCmd("call popup_setbuf(%d, %d)" % (self._preview_winid, source)) - self._preview_filetype = lfEval("getbufvar(winbufnr(%d), '&ft')" % self._preview_winid) else: filename = source try: @@ -975,14 +974,13 @@ def _useExistingWindow(self, title, source, line_num, jump_cmd): except vim.error as e: lfPrintError(e) return - lfCmd("call popup_setbuf(%d, bufadd('/Lf_preview_%d'))" % (self._preview_winid, id(self))) + lfCmd("silent call popup_setbuf(%d, bufadd('/Lf_preview_%d'))" % (self._preview_winid, id(self))) lfCmd("noautocmd call popup_settext(%d, content)" % self._preview_winid) + cur_filetype = lfEval("getbufvar(winbufnr(%d), '&ft')" % self._preview_winid) - cur_filetype = getExtension(filename) - if cur_filetype != self._preview_filetype: + if cur_filetype != getExtension(filename): lfCmd("call win_execute(%d, 'silent! doautocmd filetypedetect BufNewFile %s')" % (self._preview_winid, escQuote(filename))) - self._preview_filetype = lfEval("getbufvar(winbufnr(%d), '&ft')" % self._preview_winid) else: if isinstance(source, int): lfCmd("noautocmd call popup_settext(%d, getbufline(%d, 1, 20480))" % (self._preview_winid, source)) From b93f4c29f4af8b4d087f1c934f6538231e20d2cf Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Fri, 11 Apr 2025 11:22:02 +0800 Subject: [PATCH 342/365] there is no syntax color in preview window sometimes --- autoload/leaderf/python/leaderf/manager.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 8d72eee1..2900c0b0 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -933,9 +933,8 @@ def _useExistingWindow(self, title, source, line_num, jump_cmd): if lfEval("has('nvim')") == '1': if isinstance(source, int): - lfCmd("noautocmd call nvim_win_set_buf(%d, %d)" % (self._preview_winid, source)) + lfCmd("silent noautocmd call nvim_win_set_buf(%d, %d)" % (self._preview_winid, source)) self._setWinOptions(self._preview_winid) - self._preview_filetype = '' else: try: if self._isBinaryFile(source): @@ -950,17 +949,17 @@ def _useExistingWindow(self, title, source, line_num, jump_cmd): lfCmd("noautocmd call nvim_buf_set_option(g:Lf_preview_scratch_buffer, 'undolevels', -1)") lfCmd("noautocmd call nvim_buf_set_option(g:Lf_preview_scratch_buffer, 'modeline', v:true)") lfCmd("noautocmd call nvim_buf_set_lines(g:Lf_preview_scratch_buffer, 0, -1, v:false, content)") - lfCmd("noautocmd call nvim_win_set_buf(%d, g:Lf_preview_scratch_buffer)" % self._preview_winid) + lfCmd("silent noautocmd call nvim_win_set_buf(%d, g:Lf_preview_scratch_buffer)" % self._preview_winid) + preview_filetype = lfEval("getbufvar(winbufnr(%d), '&ft')" % self._preview_winid) cur_filetype = getExtension(source) - if cur_filetype != self._preview_filetype: + if cur_filetype != preview_filetype: if cur_filetype is None: lfCmd("call win_execute(%d, 'silent! doautocmd filetypedetect BufNewFile %s')" % (self._preview_winid, escQuote(source))) else: lfCmd("call win_execute(%d, 'noautocmd set ft=%s')" % (self._preview_winid, cur_filetype)) lfCmd("call win_execute(%d, 'set syntax=%s')" % (self._preview_winid, cur_filetype)) - self._preview_filetype = lfEval("getbufvar(winbufnr(%d), '&ft')" % self._preview_winid) elif lfEval("exists('*popup_setbuf')") == "1": if isinstance(source, int): lfCmd("call popup_setbuf(%d, %d)" % (self._preview_winid, source)) From 4d72433f647db4bdedd8f030c3d2e0aeae13042a Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Fri, 11 Apr 2025 13:59:02 +0800 Subject: [PATCH 343/365] fix a bug --- autoload/leaderf/python/leaderf/cocExpl.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/autoload/leaderf/python/leaderf/cocExpl.py b/autoload/leaderf/python/leaderf/cocExpl.py index e00e2df5..d4018f89 100644 --- a/autoload/leaderf/python/leaderf/cocExpl.py +++ b/autoload/leaderf/python/leaderf/cocExpl.py @@ -383,6 +383,8 @@ def _getFileInfo(self, args): i = 1 while not os.path.exists(lfDecode(file)): m = re.match(r'^(.+?(?::\d+.*?){%d}):(\d+):(\d+):' % i, line) + if m is None: + return (None, None, None) i += 1 file, line_num, col_num = m.group(1, 2, 3) if not os.path.isabs(file): From 7b2f7f96b2a0c6606ebdf873b7456fd259bc9217 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Fri, 11 Apr 2025 14:33:55 +0800 Subject: [PATCH 344/365] wipe the preview buffer before exiting --- autoload/leaderf/python/leaderf/manager.py | 1 + 1 file changed, 1 insertion(+) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 2900c0b0..4ab352de 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -425,6 +425,7 @@ def _closePreviewPopup(self): if self._preview_winid: lfCmd("call popup_close(%d)" % self._preview_winid) self._preview_winid = 0 + lfCmd("silent! noautocmd bwipe /Lf_preview_{}".format(id(self))) self._preview_filetype = None From 284f0a5d069f13294fee6332bd48464bb4a1d449 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Fri, 11 Apr 2025 14:55:50 +0800 Subject: [PATCH 345/365] buftype of preview buffer should be nofile --- autoload/leaderf/python/leaderf/cocExpl.py | 25 ++++++++++++---------- autoload/leaderf/python/leaderf/manager.py | 6 ++++++ 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/autoload/leaderf/python/leaderf/cocExpl.py b/autoload/leaderf/python/leaderf/cocExpl.py index d4018f89..ad41d942 100644 --- a/autoload/leaderf/python/leaderf/cocExpl.py +++ b/autoload/leaderf/python/leaderf/cocExpl.py @@ -72,17 +72,20 @@ def generateContent(self, items): content = [] file_contents = {} for item in items: - file_path = lfRelpath(urllib.parse.unquote(item["uri"][7:])) - line_num = int(item["range"]["start"]["line"]) - col_num = int(item["range"]["start"]["character"]) - line = self.getFileLine(file_path, line_num + 1, file_contents) - if len(self._pattern_regex) == 0: - end_line_num = int(item["range"]["end"]["line"]) - end_col_num = int(item["range"]["end"]["character"]) - if end_line_num == line_num: - self._pattern_regex.append(line[col_num: end_col_num]) - - content.append("{}:{}:{}:{}".format(file_path, line_num+1, col_num+1, line)) + try: + file_path = lfRelpath(urllib.parse.unquote(item["uri"][7:])) + line_num = int(item["range"]["start"]["line"]) + col_num = int(item["range"]["start"]["character"]) + line = self.getFileLine(file_path, line_num + 1, file_contents) + if len(self._pattern_regex) == 0: + end_line_num = int(item["range"]["end"]["line"]) + end_col_num = int(item["range"]["end"]["character"]) + if end_line_num == line_num: + self._pattern_regex.append(line[col_num: end_col_num]) + + content.append("{}:{}:{}:{}".format(file_path, line_num+1, col_num+1, line)) + except: + pass return content diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index 4ab352de..ea344010 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -975,6 +975,12 @@ def _useExistingWindow(self, title, source, line_num, jump_cmd): lfPrintError(e) return lfCmd("silent call popup_setbuf(%d, bufadd('/Lf_preview_%d'))" % (self._preview_winid, id(self))) + lfCmd("call win_execute(%d, 'setlocal modeline')" % self._preview_winid) + lfCmd("call win_execute(%d, 'setlocal undolevels=-1')" % self._preview_winid) + lfCmd("call win_execute(%d, 'setlocal noswapfile')" % self._preview_winid) + lfCmd("call win_execute(%d, 'setlocal nobuflisted')" % self._preview_winid) + lfCmd("call win_execute(%d, 'setlocal bufhidden=hide')" % self._preview_winid) + lfCmd("call win_execute(%d, 'setlocal buftype=nofile')" % self._preview_winid) lfCmd("noautocmd call popup_settext(%d, content)" % self._preview_winid) cur_filetype = lfEval("getbufvar(winbufnr(%d), '&ft')" % self._preview_winid) From 3e6204529ed65a382386fc77e4ad13875f55b630 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Fri, 11 Apr 2025 22:31:03 +0800 Subject: [PATCH 346/365] gui=nocombine --- autoload/leaderf/colorscheme.vim | 8 +- autoload/leaderf/colorscheme/default.vim | 44 +++++----- .../leaderf/colorscheme/gruvbox_material.vim | 88 +++++++++---------- autoload/leaderf/colorscheme/one.vim | 44 +++++----- autoload/leaderf/colorscheme/onedark.vim | 22 ++--- autoload/leaderf/colorscheme/powerline.vim | 44 +++++----- autoload/leaderf/colorscheme/solarized.vim | 40 ++++----- 7 files changed, 145 insertions(+), 145 deletions(-) diff --git a/autoload/leaderf/colorscheme.vim b/autoload/leaderf/colorscheme.vim index aab01aea..88f0d898 100644 --- a/autoload/leaderf/colorscheme.vim +++ b/autoload/leaderf/colorscheme.vim @@ -111,8 +111,8 @@ function! leaderf#colorscheme#highlight(category, bufnr) let right_guibg = synIDattr(sid_right, "bg", "gui") let right_ctermbg = synIDattr(sid_right, "bg", "cterm") let hiCmd = printf("hi Lf_hl_%s_%s", a:category, sep) - let hiCmd .= printf(" guifg=%s guibg=%s", left_guibg == '' ? 'NONE': left_guibg, right_guibg == '' ? 'NONE': right_guibg) - let hiCmd .= printf(" ctermfg=%s ctermbg=%s", left_ctermbg == '' ? 'NONE': left_ctermbg, right_ctermbg == '' ? 'NONE': right_ctermbg) + let hiCmd .= printf(" gui=nocombine guifg=%s guibg=%s", left_guibg == '' ? 'NONE': left_guibg, right_guibg == '' ? 'NONE': right_guibg) + let hiCmd .= printf(" cterm=nocombine ctermfg=%s ctermbg=%s", left_ctermbg == '' ? 'NONE': left_ctermbg, right_ctermbg == '' ? 'NONE': right_ctermbg) if get(g:Lf_StlSeparator, "font", "") != "" let hiCmd .= printf(" font='%s'", g:Lf_StlSeparator["font"]) endif @@ -127,8 +127,8 @@ function! leaderf#colorscheme#highlight(category, bufnr) let right_guibg = synIDattr(sid_right, "bg", "gui") let right_ctermbg = synIDattr(sid_right, "bg", "cterm") let hiCmd = printf("hi Lf_hl_%s_%s", a:category, sep) - let hiCmd .= printf(" guifg=%s guibg=%s", right_guibg == '' ? 'NONE': right_guibg, left_guibg == '' ? 'NONE': left_guibg) - let hiCmd .= printf(" ctermfg=%s ctermbg=%s", right_ctermbg == '' ? 'NONE': right_ctermbg, left_ctermbg == '' ? 'NONE': left_ctermbg) + let hiCmd .= printf(" gui=nocombine guifg=%s guibg=%s", right_guibg == '' ? 'NONE': right_guibg, left_guibg == '' ? 'NONE': left_guibg) + let hiCmd .= printf(" cterm=nocombine ctermfg=%s ctermbg=%s", right_ctermbg == '' ? 'NONE': right_ctermbg, left_ctermbg == '' ? 'NONE': left_ctermbg) if get(g:Lf_StlSeparator, "font", "") != "" let hiCmd .= printf(" font='%s'", g:Lf_StlSeparator["font"]) endif diff --git a/autoload/leaderf/colorscheme/default.vim b/autoload/leaderf/colorscheme/default.vim index c96a78fe..e83da67a 100644 --- a/autoload/leaderf/colorscheme/default.vim +++ b/autoload/leaderf/colorscheme/default.vim @@ -9,101 +9,101 @@ let s:palette = { \ 'stlName': { - \ 'gui': 'bold', + \ 'gui': 'bold,nocombine', \ 'font': 'NONE', \ 'guifg': '#2F5C00', \ 'guibg': '#BAFFA3', - \ 'cterm': 'bold', + \ 'cterm': 'bold,nocombine', \ 'ctermfg': '22', \ 'ctermbg': '157' \ }, \ 'stlCategory': { - \ 'gui': 'NONE', + \ 'gui': 'nocombine', \ 'font': 'NONE', \ 'guifg': '#000000', \ 'guibg': '#F28379', - \ 'cterm': 'NONE', + \ 'cterm': 'nocombine', \ 'ctermfg': '16', \ 'ctermbg': '210' \ }, \ 'stlNameOnlyMode': { - \ 'gui': 'NONE', + \ 'gui': 'nocombine', \ 'font': 'NONE', \ 'guifg': '#000000', \ 'guibg': '#E8ED51', - \ 'cterm': 'NONE', + \ 'cterm': 'nocombine', \ 'ctermfg': '16', \ 'ctermbg': '227' \ }, \ 'stlFullPathMode': { - \ 'gui': 'NONE', + \ 'gui': 'nocombine', \ 'font': 'NONE', \ 'guifg': '#000000', \ 'guibg': '#AAAAFF', - \ 'cterm': 'NONE', + \ 'cterm': 'nocombine', \ 'ctermfg': '16', \ 'ctermbg': '147' \ }, \ 'stlFuzzyMode': { - \ 'gui': 'NONE', + \ 'gui': 'nocombine', \ 'font': 'NONE', \ 'guifg': '#000000', \ 'guibg': '#E8ED51', - \ 'cterm': 'NONE', + \ 'cterm': 'nocombine', \ 'ctermfg': '16', \ 'ctermbg': '227' \ }, \ 'stlRegexMode': { - \ 'gui': 'NONE', + \ 'gui': 'nocombine', \ 'font': 'NONE', \ 'guifg': '#000000', \ 'guibg': '#7FECAD', - \ 'cterm': 'NONE', + \ 'cterm': 'nocombine', \ 'ctermfg': '16', \ 'ctermbg': '121' \ }, \ 'stlCwd': { - \ 'gui': 'NONE', + \ 'gui': 'nocombine', \ 'font': 'NONE', \ 'guifg': '#EBFFEF', \ 'guibg': '#606168', - \ 'cterm': 'NONE', + \ 'cterm': 'nocombine', \ 'ctermfg': '195', \ 'ctermbg': '241' \ }, \ 'stlBlank': { - \ 'gui': 'NONE', + \ 'gui': 'nocombine', \ 'font': 'NONE', \ 'guifg': 'NONE', \ 'guibg': '#3B3E4C', - \ 'cterm': 'NONE', + \ 'cterm': 'nocombine', \ 'ctermfg': 'NONE', \ 'ctermbg': '237' \ }, \ 'stlSpin': { - \ 'gui': 'NONE', + \ 'gui': 'nocombine', \ 'font': 'NONE', \ 'guifg': '#E6E666', \ 'guibg': '#3B3E4C', - \ 'cterm': 'NONE', + \ 'cterm': 'nocombine', \ 'ctermfg': '185', \ 'ctermbg': '237' \ }, \ 'stlLineInfo': { - \ 'gui': 'NONE', + \ 'gui': 'nocombine', \ 'font': 'NONE', \ 'guifg': '#000000', \ 'guibg': '#EBFFEF', - \ 'cterm': 'NONE', + \ 'cterm': 'nocombine', \ 'ctermfg': '16', \ 'ctermbg': '195' \ }, \ 'stlTotal': { - \ 'gui': 'NONE', + \ 'gui': 'nocombine', \ 'font': 'NONE', \ 'guifg': '#000000', \ 'guibg': '#BCDC5C', - \ 'cterm': 'NONE', + \ 'cterm': 'nocombine', \ 'ctermfg': '16', \ 'ctermbg': '149' \ } diff --git a/autoload/leaderf/colorscheme/gruvbox_material.vim b/autoload/leaderf/colorscheme/gruvbox_material.vim index c02146da..7cb443ad 100644 --- a/autoload/leaderf/colorscheme/gruvbox_material.vim +++ b/autoload/leaderf/colorscheme/gruvbox_material.vim @@ -11,101 +11,101 @@ if &background ==# 'light' let s:palette = { \ 'stlName': { - \ 'gui': 'bold', + \ 'gui': 'bold,nocombine', \ 'font': 'NONE', \ 'guifg': '#ebdbb2', \ 'guibg': '#7c6f64', - \ 'cterm': 'bold', + \ 'cterm': 'bold,nocombine', \ 'ctermfg': '223', \ 'ctermbg': '243' \ }, \ 'stlCategory': { - \ 'gui': 'NONE', + \ 'gui': 'nocombine', \ 'font': 'NONE', \ 'guifg': '#4f3829', \ 'guibg': '#bdae93', - \ 'cterm': 'NONE', + \ 'cterm': 'nocombine', \ 'ctermfg': '241', \ 'ctermbg': '248' \ }, \ 'stlNameOnlyMode': { - \ 'gui': 'NONE', + \ 'gui': 'nocombine', \ 'font': 'NONE', \ 'guifg': '#4f3829', \ 'guibg': '#d5c4a1', - \ 'cterm': 'NONE', + \ 'cterm': 'nocombine', \ 'ctermfg': '241', \ 'ctermbg': '250' \ }, \ 'stlFullPathMode': { - \ 'gui': 'NONE', + \ 'gui': 'nocombine', \ 'font': 'NONE', \ 'guifg': '#4f3829', \ 'guibg': '#d5c4a1', - \ 'cterm': 'NONE', + \ 'cterm': 'nocombine', \ 'ctermfg': '241', \ 'ctermbg': '250' \ }, \ 'stlFuzzyMode': { - \ 'gui': 'NONE', + \ 'gui': 'nocombine', \ 'font': 'NONE', \ 'guifg': '#4f3829', \ 'guibg': '#d5c4a1', - \ 'cterm': 'NONE', + \ 'cterm': 'nocombine', \ 'ctermfg': '241', \ 'ctermbg': '250' \ }, \ 'stlRegexMode': { - \ 'gui': 'NONE', + \ 'gui': 'nocombine', \ 'font': 'NONE', \ 'guifg': '#4f3829', \ 'guibg': '#d5c4a1', - \ 'cterm': 'NONE', + \ 'cterm': 'nocombine', \ 'ctermfg': '241', \ 'ctermbg': '250' \ }, \ 'stlCwd': { - \ 'gui': 'NONE', + \ 'gui': 'nocombine', \ 'font': 'NONE', \ 'guifg': '#4f3829', \ 'guibg': '#ebdbb2', - \ 'cterm': 'NONE', + \ 'cterm': 'nocombine', \ 'ctermfg': '241', \ 'ctermbg': '223' \ }, \ 'stlBlank': { - \ 'gui': 'NONE', + \ 'gui': 'nocombine', \ 'font': 'NONE', \ 'guifg': '#4f3829', \ 'guibg': '#ebdbb2', - \ 'cterm': 'NONE', + \ 'cterm': 'nocombine', \ 'ctermfg': '241', \ 'ctermbg': '223' \ }, \ 'stlSpin': { - \ 'gui': 'NONE', + \ 'gui': 'nocombine', \ 'font': 'NONE', \ 'guifg': '#984c93', \ 'guibg': '#ebdbb2', - \ 'cterm': 'NONE', + \ 'cterm': 'nocombine', \ 'ctermfg': '96', \ 'ctermbg': '223' \ }, \ 'stlLineInfo': { - \ 'gui': 'NONE', + \ 'gui': 'nocombine', \ 'font': 'NONE', \ 'guifg': '#4f3829', \ 'guibg': '#d5c4a1', - \ 'cterm': 'NONE', + \ 'cterm': 'nocombine', \ 'ctermfg': '241', \ 'ctermbg': '250' \ }, \ 'stlTotal': { - \ 'gui': 'bold', + \ 'gui': 'bold,nocombine', \ 'font': 'NONE', \ 'guifg': '#ebdbb2', \ 'guibg': '#7c6f64', - \ 'cterm': 'bold', + \ 'cterm': 'bold,nocombine', \ 'ctermfg': '223', \ 'ctermbg': '243' \ } @@ -113,101 +113,101 @@ if &background ==# 'light' else let s:palette = { \ 'stlName': { - \ 'gui': 'bold', + \ 'gui': 'bold,nocombine', \ 'font': 'NONE', \ 'guifg': '#282828', \ 'guibg': '#a89984', - \ 'cterm': 'bold', + \ 'cterm': 'bold,nocombine', \ 'ctermfg': '235', \ 'ctermbg': '246' \ }, \ 'stlCategory': { - \ 'gui': 'NONE', + \ 'gui': 'nocombine', \ 'font': 'NONE', \ 'guifg': '#ddc7a1', \ 'guibg': '#665c54', - \ 'cterm': 'NONE', + \ 'cterm': 'nocombine', \ 'ctermfg': '223', \ 'ctermbg': '241' \ }, \ 'stlNameOnlyMode': { - \ 'gui': 'NONE', + \ 'gui': 'nocombine', \ 'font': 'NONE', \ 'guifg': '#ddc7a1', \ 'guibg': '#504945', - \ 'cterm': 'NONE', + \ 'cterm': 'nocombine', \ 'ctermfg': '223', \ 'ctermbg': '239' \ }, \ 'stlFullPathMode': { - \ 'gui': 'NONE', + \ 'gui': 'nocombine', \ 'font': 'NONE', \ 'guifg': '#ddc7a1', \ 'guibg': '#504945', - \ 'cterm': 'NONE', + \ 'cterm': 'nocombine', \ 'ctermfg': '223', \ 'ctermbg': '239' \ }, \ 'stlFuzzyMode': { - \ 'gui': 'NONE', + \ 'gui': 'nocombine', \ 'font': 'NONE', \ 'guifg': '#ddc7a1', \ 'guibg': '#504945', - \ 'cterm': 'NONE', + \ 'cterm': 'nocombine', \ 'ctermfg': '223', \ 'ctermbg': '239' \ }, \ 'stlRegexMode': { - \ 'gui': 'NONE', + \ 'gui': 'nocombine', \ 'font': 'NONE', \ 'guifg': '#ddc7a1', \ 'guibg': '#504945', - \ 'cterm': 'NONE', + \ 'cterm': 'nocombine', \ 'ctermfg': '223', \ 'ctermbg': '239' \ }, \ 'stlCwd': { - \ 'gui': 'NONE', + \ 'gui': 'nocombine', \ 'font': 'NONE', \ 'guifg': '#ddc7a1', \ 'guibg': '#3c3836', - \ 'cterm': 'NONE', + \ 'cterm': 'nocombine', \ 'ctermfg': '223', \ 'ctermbg': '237' \ }, \ 'stlBlank': { - \ 'gui': 'NONE', + \ 'gui': 'nocombine', \ 'font': 'NONE', \ 'guifg': '#ddc7a1', \ 'guibg': '#3c3836', - \ 'cterm': 'NONE', + \ 'cterm': 'nocombine', \ 'ctermfg': '223', \ 'ctermbg': '237' \ }, \ 'stlSpin': { - \ 'gui': 'NONE', + \ 'gui': 'nocombine', \ 'font': 'NONE', \ 'guifg': '#E6E666', \ 'guibg': '#3c3836', - \ 'cterm': 'NONE', + \ 'cterm': 'nocombine', \ 'ctermfg': '185', \ 'ctermbg': '227' \ }, \ 'stlLineInfo': { - \ 'gui': 'NONE', + \ 'gui': 'nocombine', \ 'font': 'NONE', \ 'guifg': '#ddc7a1', \ 'guibg': '#665c54', - \ 'cterm': 'NONE', + \ 'cterm': 'nocombine', \ 'ctermfg': '223', \ 'ctermbg': '241' \ }, \ 'stlTotal': { - \ 'gui': 'NONE', + \ 'gui': 'nocombine', \ 'font': 'NONE', \ 'guifg': '#282828', \ 'guibg': '#a89984', - \ 'cterm': 'bold', + \ 'cterm': 'bold,nocombine', \ 'ctermfg': '235', \ 'ctermbg': '246' \ } diff --git a/autoload/leaderf/colorscheme/one.vim b/autoload/leaderf/colorscheme/one.vim index 40987352..52c0dd2f 100644 --- a/autoload/leaderf/colorscheme/one.vim +++ b/autoload/leaderf/colorscheme/one.vim @@ -10,101 +10,101 @@ let s:palette = { \ 'stlName': { - \ 'gui': 'bold', + \ 'gui': 'bold,nocombine', \ 'font': 'NONE', \ 'guifg': '#3E4452', \ 'guibg': '#98C379', - \ 'cterm': 'bold', + \ 'cterm': 'bold,nocombine', \ 'ctermfg': '16', \ 'ctermbg': '76' \ }, \ 'stlCategory': { - \ 'gui': 'NONE', + \ 'gui': 'nocombine', \ 'font': 'NONE', \ 'guifg': '#3E4452', \ 'guibg': '#E06C75', - \ 'cterm': 'NONE', + \ 'cterm': 'nocombine', \ 'ctermfg': '16', \ 'ctermbg': '168' \ }, \ 'stlNameOnlyMode': { - \ 'gui': 'NONE', + \ 'gui': 'nocombine', \ 'font': 'NONE', \ 'guifg': '#3E4452', \ 'guibg': '#61AFEF', - \ 'cterm': 'NONE', + \ 'cterm': 'nocombine', \ 'ctermfg': '16', \ 'ctermbg': '75' \ }, \ 'stlFullPathMode': { - \ 'gui': 'NONE', + \ 'gui': 'nocombine', \ 'font': 'NONE', \ 'guifg': '#3E4452', \ 'guibg': '#61AFEF', - \ 'cterm': 'NONE', + \ 'cterm': 'nocombine', \ 'ctermfg': '16', \ 'ctermbg': '147' \ }, \ 'stlFuzzyMode': { - \ 'gui': 'NONE', + \ 'gui': 'nocombine', \ 'font': 'NONE', \ 'guifg': '#3E4452', \ 'guibg': '#E5C07B', - \ 'cterm': 'NONE', + \ 'cterm': 'nocombine', \ 'ctermfg': '16', \ 'ctermbg': '180' \ }, \ 'stlRegexMode': { - \ 'gui': 'NONE', + \ 'gui': 'nocombine', \ 'font': 'NONE', \ 'guifg': '#3E4452', \ 'guibg': '#98C379', - \ 'cterm': 'NONE', + \ 'cterm': 'nocombine', \ 'ctermfg': '16', \ 'ctermbg': '76' \ }, \ 'stlCwd': { - \ 'gui': 'NONE', + \ 'gui': 'nocombine', \ 'font': 'NONE', \ 'guifg': '#ABB2BF', \ 'guibg': '#475265', - \ 'cterm': 'NONE', + \ 'cterm': 'nocombine', \ 'ctermfg': '145', \ 'ctermbg': '236' \ }, \ 'stlBlank': { - \ 'gui': 'NONE', + \ 'gui': 'nocombine', \ 'font': 'NONE', \ 'guifg': '#ABB2BF', \ 'guibg': '#3E4452', - \ 'cterm': 'NONE', + \ 'cterm': 'nocombine', \ 'ctermfg': '145', \ 'ctermbg': '235' \ }, \ 'stlSpin': { - \ 'gui': 'NONE', + \ 'gui': 'nocombine', \ 'font': 'NONE', \ 'guifg': '#E6E666', \ 'guibg': '#3E4452', - \ 'cterm': 'NONE', + \ 'cterm': 'nocombine', \ 'ctermfg': '185', \ 'ctermbg': '235' \ }, \ 'stlLineInfo': { - \ 'gui': 'NONE', + \ 'gui': 'nocombine', \ 'font': 'NONE', \ 'guifg': '#3E4452', \ 'guibg': '#98C379', - \ 'cterm': 'NONE', + \ 'cterm': 'nocombine', \ 'ctermfg': '16', \ 'ctermbg': '76' \ }, \ 'stlTotal': { - \ 'gui': 'NONE', + \ 'gui': 'nocombine', \ 'font': 'NONE', \ 'guifg': '#3E4452', \ 'guibg': '#98C379', - \ 'cterm': 'NONE', + \ 'cterm': 'nocombine', \ 'ctermfg': '16', \ 'ctermbg': '76' \ } diff --git a/autoload/leaderf/colorscheme/onedark.vim b/autoload/leaderf/colorscheme/onedark.vim index 3f079f1f..21371485 100644 --- a/autoload/leaderf/colorscheme/onedark.vim +++ b/autoload/leaderf/colorscheme/onedark.vim @@ -8,17 +8,17 @@ if &background ==? 'dark' \ 'match4': { 'guifg': '#56B6C2', 'ctermfg': '38' }, \ 'matchRefine': { 'guifg': '#D19A66', 'ctermfg': '173' }, \ 'cursorline': { 'guifg': '#ABB2BF', 'ctermfg': '145' }, - \ 'stlName': { 'guifg': '#2C323C', 'ctermfg': '236', 'guibg': '#98C379', 'ctermbg': '114', 'gui': 'bold', 'cterm': 'bold' }, - \ 'stlCategory': { 'guifg': '#2C323C', 'ctermfg': '236', 'guibg': '#ABB2BF', 'ctermbg': '145', 'gui': 'NONE', 'cterm': 'NONE' }, - \ 'stlNameOnlyMode': { 'guifg': '#2C323C', 'ctermfg': '236', 'guibg': '#C678DD', 'ctermbg': '170', 'gui': 'NONE', 'cterm': 'NONE' }, - \ 'stlFullPathMode': { 'guifg': '#2C323C', 'ctermfg': '236', 'guibg': '#E5C07B', 'ctermbg': '180', 'gui': 'NONE', 'cterm': 'NONE' }, - \ 'stlFuzzyMode': { 'guifg': '#2C323C', 'ctermfg': '236', 'guibg': '#56B6C2', 'ctermbg': '38', 'gui': 'NONE', 'cterm': 'NONE' }, - \ 'stlRegexMode': { 'guifg': '#2C323C', 'ctermfg': '236', 'guibg': '#E06C75', 'ctermbg': '204', 'gui': 'NONE', 'cterm': 'NONE' }, - \ 'stlCwd': { 'guifg': '#ABB2BF', 'ctermfg': '145', 'guibg': '#3E4452', 'ctermbg': '237', 'gui': 'NONE', 'cterm': 'NONE' }, - \ 'stlBlank': { 'guifg': '#ABB2BF', 'ctermfg': '145', 'guibg': '#282C34', 'ctermbg': '235', 'gui': 'NONE', 'cterm': 'NONE' }, - \ 'stlLineInfo': { 'guifg': '#ABB2BF', 'ctermfg': '145', 'guibg': '#3E4452', 'ctermbg': '237', 'gui': 'NONE', 'cterm': 'NONE' }, - \ 'stlTotal': { 'guifg': '#2C323C', 'ctermfg': '236', 'guibg': '#98C379', 'ctermbg': '114', 'gui': 'NONE', 'cterm': 'NONE' }, - \ 'stlSpin': { 'guifg': '#ABB2BF', 'ctermfg': '145', 'guibg': '#282C34', 'ctermbg': '235', 'gui': 'NONE', 'cterm': 'NONE' }, + \ 'stlName': { 'guifg': '#2C323C', 'ctermfg': '236', 'guibg': '#98C379', 'ctermbg': '114', 'gui': 'bold,nocombine', 'cterm': 'bold,nocombine' }, + \ 'stlCategory': { 'guifg': '#2C323C', 'ctermfg': '236', 'guibg': '#ABB2BF', 'ctermbg': '145', 'gui': 'nocombine', 'cterm': 'nocombine' }, + \ 'stlNameOnlyMode': { 'guifg': '#2C323C', 'ctermfg': '236', 'guibg': '#C678DD', 'ctermbg': '170', 'gui': 'nocombine', 'cterm': 'nocombine' }, + \ 'stlFullPathMode': { 'guifg': '#2C323C', 'ctermfg': '236', 'guibg': '#E5C07B', 'ctermbg': '180', 'gui': 'nocombine', 'cterm': 'nocombine' }, + \ 'stlFuzzyMode': { 'guifg': '#2C323C', 'ctermfg': '236', 'guibg': '#56B6C2', 'ctermbg': '38', 'gui': 'nocombine', 'cterm': 'nocombine' }, + \ 'stlRegexMode': { 'guifg': '#2C323C', 'ctermfg': '236', 'guibg': '#E06C75', 'ctermbg': '204', 'gui': 'nocombine', 'cterm': 'nocombine' }, + \ 'stlCwd': { 'guifg': '#ABB2BF', 'ctermfg': '145', 'guibg': '#3E4452', 'ctermbg': '237', 'gui': 'nocombine', 'cterm': 'nocombine' }, + \ 'stlBlank': { 'guifg': '#ABB2BF', 'ctermfg': '145', 'guibg': '#282C34', 'ctermbg': '235', 'gui': 'nocombine', 'cterm': 'nocombine' }, + \ 'stlLineInfo': { 'guifg': '#ABB2BF', 'ctermfg': '145', 'guibg': '#3E4452', 'ctermbg': '237', 'gui': 'nocombine', 'cterm': 'nocombine' }, + \ 'stlTotal': { 'guifg': '#2C323C', 'ctermfg': '236', 'guibg': '#98C379', 'ctermbg': '114', 'gui': 'nocombine', 'cterm': 'nocombine' }, + \ 'stlSpin': { 'guifg': '#ABB2BF', 'ctermfg': '145', 'guibg': '#282C34', 'ctermbg': '235', 'gui': 'nocombine', 'cterm': 'nocombine' }, \ } endif diff --git a/autoload/leaderf/colorscheme/powerline.vim b/autoload/leaderf/colorscheme/powerline.vim index e41d6771..fdb3c8d1 100644 --- a/autoload/leaderf/colorscheme/powerline.vim +++ b/autoload/leaderf/colorscheme/powerline.vim @@ -9,101 +9,101 @@ let s:palette = { \ 'stlName': { - \ 'gui': 'bold', + \ 'gui': 'bold,nocombine', \ 'font': 'NONE', \ 'guifg': '#005F00', \ 'guibg': '#AFDF00', - \ 'cterm': 'bold', + \ 'cterm': 'bold,nocombine', \ 'ctermfg': '22', \ 'ctermbg': '148' \ }, \ 'stlCategory': { - \ 'gui': 'NONE', + \ 'gui': 'nocombine', \ 'font': 'NONE', \ 'guifg': '#870000', \ 'guibg': '#FF8700', - \ 'cterm': 'NONE', + \ 'cterm': 'nocombine', \ 'ctermfg': '88', \ 'ctermbg': '208' \ }, \ 'stlNameOnlyMode': { - \ 'gui': 'NONE', + \ 'gui': 'nocombine', \ 'font': 'NONE', \ 'guifg': '#005D5D', \ 'guibg': '#FFFFFF', - \ 'cterm': 'NONE', + \ 'cterm': 'nocombine', \ 'ctermfg': '23', \ 'ctermbg': '231' \ }, \ 'stlFullPathMode': { - \ 'gui': 'NONE', + \ 'gui': 'nocombine', \ 'font': 'NONE', \ 'guifg': '#FFFFFF', \ 'guibg': '#FF2929', - \ 'cterm': 'NONE', + \ 'cterm': 'nocombine', \ 'ctermfg': '231', \ 'ctermbg': '196' \ }, \ 'stlFuzzyMode': { - \ 'gui': 'NONE', + \ 'gui': 'nocombine', \ 'font': 'NONE', \ 'guifg': '#004747', \ 'guibg': '#FFFFFF', - \ 'cterm': 'NONE', + \ 'cterm': 'nocombine', \ 'ctermfg': '23', \ 'ctermbg': '231' \ }, \ 'stlRegexMode': { - \ 'gui': 'NONE', + \ 'gui': 'nocombine', \ 'font': 'NONE', \ 'guifg': '#000000', \ 'guibg': '#7FECAD', - \ 'cterm': 'NONE', + \ 'cterm': 'nocombine', \ 'ctermfg': '16', \ 'ctermbg': '121' \ }, \ 'stlCwd': { - \ 'gui': 'NONE', + \ 'gui': 'nocombine', \ 'font': 'NONE', \ 'guifg': '#FFFFFF', \ 'guibg': '#585858', - \ 'cterm': 'NONE', + \ 'cterm': 'nocombine', \ 'ctermfg': '231', \ 'ctermbg': '240' \ }, \ 'stlBlank': { - \ 'gui': 'NONE', + \ 'gui': 'nocombine', \ 'font': 'NONE', \ 'guifg': 'NONE', \ 'guibg': '#303136', - \ 'cterm': 'NONE', + \ 'cterm': 'nocombine', \ 'ctermfg': 'NONE', \ 'ctermbg': '236' \ }, \ 'stlSpin': { - \ 'gui': 'NONE', + \ 'gui': 'nocombine', \ 'font': 'NONE', \ 'guifg': '#E6E666', \ 'guibg': '#303136', - \ 'cterm': 'NONE', + \ 'cterm': 'nocombine', \ 'ctermfg': '185', \ 'ctermbg': '236' \ }, \ 'stlLineInfo': { - \ 'gui': 'NONE', + \ 'gui': 'nocombine', \ 'font': 'NONE', \ 'guifg': '#C9C9C9', \ 'guibg': '#585858', - \ 'cterm': 'NONE', + \ 'cterm': 'nocombine', \ 'ctermfg': '251', \ 'ctermbg': '240' \ }, \ 'stlTotal': { - \ 'gui': 'NONE', + \ 'gui': 'nocombine', \ 'font': 'NONE', \ 'guifg': '#545454', \ 'guibg': '#D0D0D0', - \ 'cterm': 'NONE', + \ 'cterm': 'nocombine', \ 'ctermfg': '240', \ 'ctermbg': '252' \ } diff --git a/autoload/leaderf/colorscheme/solarized.vim b/autoload/leaderf/colorscheme/solarized.vim index e184d186..aeba28ef 100644 --- a/autoload/leaderf/colorscheme/solarized.vim +++ b/autoload/leaderf/colorscheme/solarized.vim @@ -8,16 +8,16 @@ if &background ==? 'dark' \ 'match4': { 'guifg': '#859900', 'ctermfg': '100' }, \ 'matchRefine': { 'guifg': '#cb4b16', 'ctermfg': '166' }, \ 'cursorline': { 'guifg': '#fdf6e3', 'ctermfg': '230' }, - \ 'stlName': { 'guifg': '#fdf6e3', 'ctermfg': '230', 'guibg': '#b58900', 'ctermbg': '136', 'gui': 'bold', 'cterm': 'bold' }, - \ 'stlCategory': { 'guifg': '#eee8d5', 'ctermfg': '224', 'guibg': '#657b83', 'ctermbg': '66', 'gui': 'NONE', 'cterm': 'NONE' }, - \ 'stlNameOnlyMode': { 'guifg': '#eee8d5', 'ctermfg': '224', 'guibg': '#268bd2', 'ctermbg': '32', 'gui': 'NONE', 'cterm': 'NONE' }, - \ 'stlFullPathMode': { 'guifg': '#eee8d5', 'ctermfg': '224', 'guibg': '#586e75', 'ctermbg': '60', 'gui': 'NONE', 'cterm': 'NONE' }, - \ 'stlFuzzyMode': { 'guifg': '#eee8d5', 'ctermfg': '224', 'guibg': '#586e75', 'ctermbg': '60', 'gui': 'NONE', 'cterm': 'NONE' }, - \ 'stlRegexMode': { 'guifg': '#eee8d5', 'ctermfg': '224', 'guibg': '#dc322f', 'ctermbg': '166', 'gui': 'NONE', 'cterm': 'NONE' }, - \ 'stlCwd': { 'guifg': '#93a1a1', 'ctermfg': '109', 'guibg': '#073642', 'ctermbg': '23', 'gui': 'NONE', 'cterm': 'NONE' }, - \ 'stlBlank': { 'guifg': '#93a1a1', 'ctermfg': '109', 'guibg': '#073642', 'ctermbg': '23', 'gui': 'NONE', 'cterm': 'NONE' }, - \ 'stlLineInfo': { 'guifg': '#eee8d5', 'ctermfg': '224', 'guibg': '#657b83', 'ctermbg': '66', 'gui': 'NONE', 'cterm': 'NONE' }, - \ 'stlTotal': { 'guifg': '#fdf6e3', 'ctermfg': '230', 'guibg': '#93a1a1', 'ctermbg': '109', 'gui': 'NONE', 'cterm': 'NONE' }, + \ 'stlName': { 'guifg': '#fdf6e3', 'ctermfg': '230', 'guibg': '#b58900', 'ctermbg': '136', 'gui': 'bold,nocombine', 'cterm': 'bold,nocombine' }, + \ 'stlCategory': { 'guifg': '#eee8d5', 'ctermfg': '224', 'guibg': '#657b83', 'ctermbg': '66', 'gui': 'nocombine', 'cterm': 'nocombine' }, + \ 'stlNameOnlyMode': { 'guifg': '#eee8d5', 'ctermfg': '224', 'guibg': '#268bd2', 'ctermbg': '32', 'gui': 'nocombine', 'cterm': 'nocombine' }, + \ 'stlFullPathMode': { 'guifg': '#eee8d5', 'ctermfg': '224', 'guibg': '#586e75', 'ctermbg': '60', 'gui': 'nocombine', 'cterm': 'nocombine' }, + \ 'stlFuzzyMode': { 'guifg': '#eee8d5', 'ctermfg': '224', 'guibg': '#586e75', 'ctermbg': '60', 'gui': 'nocombine', 'cterm': 'nocombine' }, + \ 'stlRegexMode': { 'guifg': '#eee8d5', 'ctermfg': '224', 'guibg': '#dc322f', 'ctermbg': '166', 'gui': 'nocombine', 'cterm': 'nocombine' }, + \ 'stlCwd': { 'guifg': '#93a1a1', 'ctermfg': '109', 'guibg': '#073642', 'ctermbg': '23', 'gui': 'nocombine', 'cterm': 'nocombine' }, + \ 'stlBlank': { 'guifg': '#93a1a1', 'ctermfg': '109', 'guibg': '#073642', 'ctermbg': '23', 'gui': 'nocombine', 'cterm': 'nocombine' }, + \ 'stlLineInfo': { 'guifg': '#eee8d5', 'ctermfg': '224', 'guibg': '#657b83', 'ctermbg': '66', 'gui': 'nocombine', 'cterm': 'nocombine' }, + \ 'stlTotal': { 'guifg': '#fdf6e3', 'ctermfg': '230', 'guibg': '#93a1a1', 'ctermbg': '109', 'gui': 'nocombine', 'cterm': 'nocombine' }, \ } else let s:palette = { @@ -29,16 +29,16 @@ else \ 'match4': { 'guifg': '#859900', 'ctermfg': '100' }, \ 'matchRefine': { 'guifg': '#cb4b16', 'ctermfg': '166' }, \ 'cursorline': { 'guifg': '#002b36', 'ctermfg': '17' }, - \ 'stlName': { 'guifg': '#fdf6e3', 'ctermfg': '230', 'guibg': '#b58900', 'ctermbg': '136', 'gui': 'bold', 'cterm': 'bold' }, - \ 'stlCategory': { 'guifg': '#eee8d5', 'ctermfg': '224', 'guibg': '#839496', 'ctermbg': '102', 'gui': 'NONE', 'cterm': 'NONE' }, - \ 'stlNameOnlyMode': { 'guifg': '#eee8d5', 'ctermfg': '224', 'guibg': '#268bd2', 'ctermbg': '32', 'gui': 'NONE', 'cterm': 'NONE' }, - \ 'stlFullPathMode': { 'guifg': '#eee8d5', 'ctermfg': '224', 'guibg': '#93a1a1', 'ctermbg': '109', 'gui': 'NONE', 'cterm': 'NONE' }, - \ 'stlFuzzyMode': { 'guifg': '#eee8d5', 'ctermfg': '224', 'guibg': '#93a1a1', 'ctermbg': '109', 'gui': 'NONE', 'cterm': 'NONE' }, - \ 'stlRegexMode': { 'guifg': '#eee8d5', 'ctermfg': '224', 'guibg': '#dc322f', 'ctermbg': '166', 'gui': 'NONE', 'cterm': 'NONE' }, - \ 'stlCwd': { 'guifg': '#586e75', 'ctermfg': '60', 'guibg': '#eee8d5', 'ctermbg': '224', 'gui': 'NONE', 'cterm': 'NONE' }, - \ 'stlBlank': { 'guifg': '#586e75', 'ctermfg': '60', 'guibg': '#eee8d5', 'ctermbg': '224', 'gui': 'NONE', 'cterm': 'NONE' }, - \ 'stlLineInfo': { 'guifg': '#eee8d5', 'ctermfg': '224', 'guibg': '#839496', 'ctermbg': '102', 'gui': 'NONE', 'cterm': 'NONE' }, - \ 'stlTotal': { 'guifg': '#fdf6e3', 'ctermfg': '230', 'guibg': '#586e75', 'ctermbg': '60', 'gui': 'NONE', 'cterm': 'NONE' }, + \ 'stlName': { 'guifg': '#fdf6e3', 'ctermfg': '230', 'guibg': '#b58900', 'ctermbg': '136', 'gui': 'bold,nocombine', 'cterm': 'bold,nocombine' }, + \ 'stlCategory': { 'guifg': '#eee8d5', 'ctermfg': '224', 'guibg': '#839496', 'ctermbg': '102', 'gui': 'nocombine', 'cterm': 'nocombine' }, + \ 'stlNameOnlyMode': { 'guifg': '#eee8d5', 'ctermfg': '224', 'guibg': '#268bd2', 'ctermbg': '32', 'gui': 'nocombine', 'cterm': 'nocombine' }, + \ 'stlFullPathMode': { 'guifg': '#eee8d5', 'ctermfg': '224', 'guibg': '#93a1a1', 'ctermbg': '109', 'gui': 'nocombine', 'cterm': 'nocombine' }, + \ 'stlFuzzyMode': { 'guifg': '#eee8d5', 'ctermfg': '224', 'guibg': '#93a1a1', 'ctermbg': '109', 'gui': 'nocombine', 'cterm': 'nocombine' }, + \ 'stlRegexMode': { 'guifg': '#eee8d5', 'ctermfg': '224', 'guibg': '#dc322f', 'ctermbg': '166', 'gui': 'nocombine', 'cterm': 'nocombine' }, + \ 'stlCwd': { 'guifg': '#586e75', 'ctermfg': '60', 'guibg': '#eee8d5', 'ctermbg': '224', 'gui': 'nocombine', 'cterm': 'nocombine' }, + \ 'stlBlank': { 'guifg': '#586e75', 'ctermfg': '60', 'guibg': '#eee8d5', 'ctermbg': '224', 'gui': 'nocombine', 'cterm': 'nocombine' }, + \ 'stlLineInfo': { 'guifg': '#eee8d5', 'ctermfg': '224', 'guibg': '#839496', 'ctermbg': '102', 'gui': 'nocombine', 'cterm': 'nocombine' }, + \ 'stlTotal': { 'guifg': '#fdf6e3', 'ctermfg': '230', 'guibg': '#586e75', 'ctermbg': '60', 'gui': 'nocombine', 'cterm': 'nocombine' }, \ } endif From 93d10afd44bb51e13284043614e29f6eebef7c12 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 23 Apr 2025 10:15:43 +0800 Subject: [PATCH 347/365] fix issue #1118 --- autoload/leaderf/python/leaderf/gitExpl.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index dcfb1019..84df6047 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -3762,6 +3762,7 @@ def startExplorer(self, win_pos, *args, **kwargs): page = ExplorerPage(self._project_root, uid, self) page.create(arguments_dict, GitDiffExplCommand(arguments_dict, uid)) self._pages.add(page) + self._restoreOrigCwd() else: super(GitExplManager, self).startExplorer(win_pos, *args, **kwargs) @@ -4833,6 +4834,7 @@ def startExplorer(self, win_pos, *args, **kwargs): ] page.create(arguments_dict, command) self._pages.add(page) + self._restoreOrigCwd() def getPreviewCommand(self, arguments_dict, source): arguments_dict.update(self._arguments) From accfaaffdbbc4656e347211f3498c9c3dcdf2eb0 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 23 Apr 2025 21:45:01 +0800 Subject: [PATCH 348/365] fix issue #1118 file path is not correct --- autoload/leaderf/python/leaderf/gitExpl.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 84df6047..ee956e77 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -2273,8 +2273,9 @@ def create(self, arguments_dict, source, **kwargs): .format(winid, kwargs.get("tree_view_id", 0))) lfCmd("call win_execute({}, 'let b:lf_git_diff_win_pos = {}')".format(winid, i)) lfCmd("call win_execute({}, 'let b:lf_git_diff_win_id = {}')".format(winid, win_ids[1])) + abs_file_path = os.path.join(self._project_root, lfGetFilePath(source)) lfCmd("""call win_execute(%d, "let b:lf_git_buffer_name = '%s'")""" - % (winid, escQuote(os.path.abspath(lfGetFilePath(source))))) + % (winid, escQuote(abs_file_path))) lfCmd("""call win_execute({}, 'let b:lf_diff_view_mode = "side-by-side"')""" .format(winid)) lfCmd("""call win_execute({}, "let b:lf_diff_view_source = {}")""" @@ -2728,7 +2729,8 @@ def create(self, arguments_dict, source, **kwargs): if not vim.current.buffer.name: # buffer name is empty lfCmd("setlocal bufhidden=wipe") lfCmd("silent hide edit {}".format(buf_name)) - lfCmd("let b:lf_git_buffer_name = '%s'" % escQuote(os.path.abspath(lfGetFilePath(source)))) + abs_file_path = os.path.join(self._project_root, lfGetFilePath(source)) + lfCmd("let b:lf_git_buffer_name = '%s'" % escQuote(abs_file_path)) lfCmd("let b:lf_git_line_num_content = {}".format(str(line_num_content))) lfCmd("augroup Lf_Git_Log | augroup END") lfCmd("autocmd! Lf_Git_Log BufWinEnter call leaderf#Git#SetMatches()") From c99bfac121236bb9e868fe1392c513f0e14c2085 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 23 Apr 2025 23:46:22 +0800 Subject: [PATCH 349/365] fix a bug introduced by last commit --- autoload/leaderf/python/leaderf/gitExpl.py | 1 + 1 file changed, 1 insertion(+) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index ee956e77..716b5240 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -4046,6 +4046,7 @@ def _acceptSelection(self, *args, **kwargs): outputs = ParallelExecutor.run(cmd, directory=self._project_root) if len(outputs[0]) > 0: _, source = TreeView.generateSource(outputs[0][0]) + kwargs["project_root"] = self._project_root self._diff_view_panel.create(self._arguments, source, **kwargs) elif "--current-line" in self._arguments and len(self._getExplorer().patches) > 0: if "--explorer" in self._arguments: From c28ac4fbf32fef715a0ca031c6b13f38d2106b7f Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 24 Apr 2025 00:10:54 +0800 Subject: [PATCH 350/365] fix issue #1119 --- autoload/leaderf/Git.vim | 6 +++++- autoload/leaderf/python/leaderf/gitExpl.py | 3 ++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/autoload/leaderf/Git.vim b/autoload/leaderf/Git.vim index 05ef5d33..b9dd6ff0 100644 --- a/autoload/leaderf/Git.vim +++ b/autoload/leaderf/Git.vim @@ -484,8 +484,12 @@ function! leaderf#Git#UpdateInlineBlame(manager_id) abort exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value.updateInlineBlame()", a:manager_id) endfunction +function! leaderf#Git#StartInlineBlameImpl(timer) abort + call leaderf#LfPy("gitExplManager.startExplorer('--bottom', arguments={'arg_line': 'git blame', '--inline': [], 'autocmd': True})") +endfunction + function! leaderf#Git#StartInlineBlame() abort - Leaderf git blame --inline + call timer_start(0, 'leaderf#Git#StartInlineBlameImpl') endfunction function! leaderf#Git#DisableInlineBlame() abort diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 716b5240..bb837f27 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -4806,7 +4806,8 @@ def startExplorer(self, win_pos, *args, **kwargs): if tmp_file_name is not None: os.remove(tmp_file_name) else: - lfPrintError("fatal: no such path '{}' in HEAD".format(vim.current.buffer.name)) + if arguments_dict.get('autocmd', None) == None: + lfPrintError("fatal: no such path '{}' in HEAD".format(vim.current.buffer.name)) self._restoreOrigCwd() From 0ff3adc49beaea093cb120eacd6164f2238bb9a4 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 24 Apr 2025 09:55:20 +0800 Subject: [PATCH 351/365] report 'No content!' if no result --- autoload/leaderf/python/leaderf/gitExpl.py | 6 +++--- autoload/leaderf/python/leaderf/manager.py | 9 +++++++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index bb837f27..032160d9 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -3521,7 +3521,7 @@ def _accept(self, file, mode, *args, **kwargs): self._acceptSelection(file, *args, **kwargs) def _acceptSelection(self, *args, **kwargs): - if len(args) == 0: + if len(args) == 0 or args[0] == '': return line = args[0] @@ -3804,7 +3804,7 @@ def _accept(self, file, mode, *args, **kwargs): super(GitExplManager, self)._accept(file, mode, *args, **kwargs) def _acceptSelection(self, *args, **kwargs): - if len(args) == 0: + if len(args) == 0 or args[0] == '': return line = args[0] @@ -4024,7 +4024,7 @@ def _getPathAndLineNum(self, commit_id): return (file_path, line_num) def _acceptSelection(self, *args, **kwargs): - if len(args) == 0: + if len(args) == 0 or args[0] == '': return line = args[0] diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index ea344010..d9db8fa7 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -2777,6 +2777,15 @@ def startExplorer(self, win_pos, *args, **kwargs): if content is None: return + if isinstance(content, AsyncExecutor.Result): + first_two = list(itertools.islice(content, 2)) + if len(first_two) == 0: + content = [] + elif len(first_two) == 1: + content = first_two + else: + content = content.join_left(first_two) + if not content: lfCmd("echohl Error | redraw | echo ' No content!' | echohl NONE") return From 98c1e10cd1de6e31afc0fe7fe453d1957c1d63cc Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 24 Apr 2025 10:11:51 +0800 Subject: [PATCH 352/365] remove useless code in gtagsExpl.py --- autoload/leaderf/python/leaderf/gtagsExpl.py | 16 ---------------- autoload/leaderf/python/leaderf/manager.py | 18 +++++++++--------- 2 files changed, 9 insertions(+), 25 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gtagsExpl.py b/autoload/leaderf/python/leaderf/gtagsExpl.py index 9ecc6bc4..65d9c440 100644 --- a/autoload/leaderf/python/leaderf/gtagsExpl.py +++ b/autoload/leaderf/python/leaderf/gtagsExpl.py @@ -119,7 +119,6 @@ def getContent(self, *args, **kwargs): else: path_style = "" - auto_jump = False self._last_result_format = self._result_format self._result_format = 'ctags-mod' if "--result" in arguments_dict: @@ -128,13 +127,9 @@ def getContent(self, *args, **kwargs): if "-d" in arguments_dict: pattern = arguments_dict["-d"][0] pattern_option = "-d -e %s " % pattern - if "--auto-jump" in arguments_dict: - auto_jump = True elif "-r" in arguments_dict: pattern = arguments_dict["-r"][0] pattern_option = "-r -e %s " % pattern - if "--auto-jump" in arguments_dict: - auto_jump = True elif "-s" in arguments_dict: pattern = arguments_dict["-s"][0] pattern_option = "-s -e %s " % pattern @@ -144,8 +139,6 @@ def getContent(self, *args, **kwargs): elif "--by-context" in arguments_dict: pattern = lfEval('expand("")') pattern_option = '--from-here "%d:%s" %s ' % (vim.current.window.cursor[0], vim.current.buffer.name, pattern) - if "--auto-jump" in arguments_dict: - auto_jump = True else: if "--current-buffer" in arguments_dict: pattern_option = '-f "%s" -q' % vim.current.buffer.name @@ -279,15 +272,6 @@ def getContent(self, *args, **kwargs): self._executor.append(executor) content += executor.execute(cmd, env=env) - if auto_jump: - first_two = list(itertools.islice(content, 2)) - if len(first_two) == 0: - return [] - elif len(first_two) == 1: - return first_two - else: - return content.join_left(first_two) - return content def translateRegex(self, regex, is_perl=False): diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index d9db8fa7..d35fdb48 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -2761,6 +2761,15 @@ def startExplorer(self, win_pos, *args, **kwargs): win_pos = self._getInstance().getWinPos() else: content = self._getExplorer().getContent(*args, **kwargs) + if isinstance(content, AsyncExecutor.Result): + first_two = list(itertools.islice(content, 2)) + if len(first_two) == 0: + content = [] + elif len(first_two) == 1: + content = first_two + else: + content = content.join_left(first_two) + self._getInstance().setCwd(lfGetCwd()) if self.autoJump(content) == True: return @@ -2777,15 +2786,6 @@ def startExplorer(self, win_pos, *args, **kwargs): if content is None: return - if isinstance(content, AsyncExecutor.Result): - first_two = list(itertools.islice(content, 2)) - if len(first_two) == 0: - content = [] - elif len(first_two) == 1: - content = first_two - else: - content = content.join_left(first_two) - if not content: lfCmd("echohl Error | redraw | echo ' No content!' | echohl NONE") return From 8a7422c32269f7c05c56ef531884350fe6984dcc Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 24 Apr 2025 10:31:17 +0800 Subject: [PATCH 353/365] subcommand is not correct when `Leaderf --recall` --- autoload/leaderf/python/leaderf/gitExpl.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 032160d9..3346bdc1 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -3423,6 +3423,7 @@ def __init__(self): self._git_status_manager = None self._selected_content = None self._project_root = None + self._subcommand = "" def _getExplClass(self): return GitExplorer @@ -3500,15 +3501,19 @@ def startExplorer(self, win_pos, *args, **kwargs): arguments_dict = kwargs.get("arguments", {}) if "--recall" in arguments_dict: self._arguments.update(arguments_dict) + subcommand = self._subcommand else: self.setArguments(arguments_dict) - arg_list = self._arguments.get("arg_line", 'git').split() - arg_list = [item for item in arg_list if not item.startswith('-')] - if len(arg_list) == 1: - subcommand = "" - else: - subcommand = arg_list[1] + arg_list = self._arguments.get("arg_line", 'git').split() + arg_list = [item for item in arg_list if not item.startswith('-')] + if len(arg_list) == 1: + subcommand = "" + else: + subcommand = arg_list[1] + if "autocmd" not in arguments_dict: + self._subcommand = subcommand + self.getExplManager(subcommand).startExplorer(win_pos, *args, **kwargs) def accept(self, mode=''): From 4ea667b5c9cfa684a871044230106974d33926e7 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 24 Apr 2025 12:37:27 +0800 Subject: [PATCH 354/365] don't report error if launched by autocmd --- autoload/leaderf/python/leaderf/gitExpl.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 3346bdc1..45ca3560 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -3485,14 +3485,15 @@ def getWorkingDirectory(self, orig_cwd): return nearestAncestor([".git"], orig_cwd) - def checkWorkingDirectory(self): + def checkWorkingDirectory(self, *args, **kwargs): self._orig_cwd = lfGetCwd() self._project_root = self.getWorkingDirectory(self._orig_cwd) if self._project_root: # there exists a root marker in nearest ancestor path lfChdir(self._project_root) else: - lfPrintError("Not a git repository (or any of the parent directories): .git") + if kwargs.get('autocmd', None) == None: + lfPrintError("Not a git repository (or any of the parent directories): .git") return False return True @@ -4765,10 +4766,10 @@ def disableInlineBlame(self): self._initial_changedtick = {} def startExplorer(self, win_pos, *args, **kwargs): - if self.checkWorkingDirectory() == False: + arguments_dict = kwargs.get("arguments", {}) + if self.checkWorkingDirectory(**arguments_dict) == False: return - arguments_dict = kwargs.get("arguments", {}) self.setArguments(arguments_dict) if lfEval("exists('b:lf_blame_file_name')") == "1": From 9f2be54f726648ba2a4038e5c6ffffaed8d52623 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Sat, 26 Apr 2025 19:40:02 +0800 Subject: [PATCH 355/365] Revert "remove useless code in gtagsExpl.py" This reverts commit 98c1e10cd1de6e31afc0fe7fe453d1957c1d63cc. --- autoload/leaderf/python/leaderf/gtagsExpl.py | 16 ++++++++++++++++ autoload/leaderf/python/leaderf/manager.py | 18 +++++++++--------- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gtagsExpl.py b/autoload/leaderf/python/leaderf/gtagsExpl.py index 65d9c440..9ecc6bc4 100644 --- a/autoload/leaderf/python/leaderf/gtagsExpl.py +++ b/autoload/leaderf/python/leaderf/gtagsExpl.py @@ -119,6 +119,7 @@ def getContent(self, *args, **kwargs): else: path_style = "" + auto_jump = False self._last_result_format = self._result_format self._result_format = 'ctags-mod' if "--result" in arguments_dict: @@ -127,9 +128,13 @@ def getContent(self, *args, **kwargs): if "-d" in arguments_dict: pattern = arguments_dict["-d"][0] pattern_option = "-d -e %s " % pattern + if "--auto-jump" in arguments_dict: + auto_jump = True elif "-r" in arguments_dict: pattern = arguments_dict["-r"][0] pattern_option = "-r -e %s " % pattern + if "--auto-jump" in arguments_dict: + auto_jump = True elif "-s" in arguments_dict: pattern = arguments_dict["-s"][0] pattern_option = "-s -e %s " % pattern @@ -139,6 +144,8 @@ def getContent(self, *args, **kwargs): elif "--by-context" in arguments_dict: pattern = lfEval('expand("")') pattern_option = '--from-here "%d:%s" %s ' % (vim.current.window.cursor[0], vim.current.buffer.name, pattern) + if "--auto-jump" in arguments_dict: + auto_jump = True else: if "--current-buffer" in arguments_dict: pattern_option = '-f "%s" -q' % vim.current.buffer.name @@ -272,6 +279,15 @@ def getContent(self, *args, **kwargs): self._executor.append(executor) content += executor.execute(cmd, env=env) + if auto_jump: + first_two = list(itertools.islice(content, 2)) + if len(first_two) == 0: + return [] + elif len(first_two) == 1: + return first_two + else: + return content.join_left(first_two) + return content def translateRegex(self, regex, is_perl=False): diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index d35fdb48..d9db8fa7 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -2761,15 +2761,6 @@ def startExplorer(self, win_pos, *args, **kwargs): win_pos = self._getInstance().getWinPos() else: content = self._getExplorer().getContent(*args, **kwargs) - if isinstance(content, AsyncExecutor.Result): - first_two = list(itertools.islice(content, 2)) - if len(first_two) == 0: - content = [] - elif len(first_two) == 1: - content = first_two - else: - content = content.join_left(first_two) - self._getInstance().setCwd(lfGetCwd()) if self.autoJump(content) == True: return @@ -2786,6 +2777,15 @@ def startExplorer(self, win_pos, *args, **kwargs): if content is None: return + if isinstance(content, AsyncExecutor.Result): + first_two = list(itertools.islice(content, 2)) + if len(first_two) == 0: + content = [] + elif len(first_two) == 1: + content = first_two + else: + content = content.join_left(first_two) + if not content: lfCmd("echohl Error | redraw | echo ' No content!' | echohl NONE") return From 79f8f290a08c9730fef61d7feb6e0649ca4c5ae9 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Sat, 26 Apr 2025 19:50:34 +0800 Subject: [PATCH 356/365] fix issue #1120 --- autoload/leaderf/python/leaderf/manager.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index d9db8fa7..ea344010 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -2777,15 +2777,6 @@ def startExplorer(self, win_pos, *args, **kwargs): if content is None: return - if isinstance(content, AsyncExecutor.Result): - first_two = list(itertools.islice(content, 2)) - if len(first_two) == 0: - content = [] - elif len(first_two) == 1: - content = first_two - else: - content = content.join_left(first_two) - if not content: lfCmd("echohl Error | redraw | echo ' No content!' | echohl NONE") return From 7958016e291f1899958cee24ab00114edfa7e415 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Sat, 26 Apr 2025 21:21:14 +0800 Subject: [PATCH 357/365] there is a bug if `let g:Lf_GitInlineBlameEnable = 1` --- autoload/leaderf/python/leaderf/gitExpl.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 45ca3560..13580fc8 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -4241,7 +4241,7 @@ def blamePrevious(self): lfCmd("noautocmd call win_gotoid({})".format(alternate_winid)) if alternate_buffer_name in blame_buffer_dict: blame_buffer, alternate_buffer_num = blame_buffer_dict[alternate_buffer_name] - lfCmd("buffer {}".format(alternate_buffer_num)) + lfCmd("noautocmd buffer {}".format(alternate_buffer_num)) lfCmd("noautocmd norm! {}Gzt{}G0".format(line_num-top_line_delta, line_num)) top_line = lfEval("line('w0')") @@ -4324,7 +4324,7 @@ def blamePrevious(self): blame_win_width ) = blame_panel.getBlameDict(blame_buffer_name)[commit_id] lfCmd("noautocmd call win_gotoid({})".format(alternate_winid)) - lfCmd("buffer {}".format(alternate_buffer_num)) + lfCmd("noautocmd buffer {}".format(alternate_buffer_num)) lfCmd("noautocmd norm! {}Gzt{}G0".format(line_num-top_line_delta, line_num)) top_line = lfEval("line('w0')") @@ -4354,7 +4354,7 @@ def blameNext(self): alternate_winid = blame_panel.getAlternateWinid(vim.current.buffer.name) lfCmd("noautocmd call win_gotoid({})".format(alternate_winid)) - lfCmd("buffer {}".format(alternate_buffer_num)) + lfCmd("noautocmd buffer {}".format(alternate_buffer_num)) lfCmd("noautocmd norm! {}Gzt{}G0".format(top_line, cursor_line)) lfCmd("noautocmd call win_gotoid({})".format(blame_winid)) From 0a082b31947abc58db154ec29edfb63ef87068d3 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Sun, 27 Apr 2025 17:10:13 +0800 Subject: [PATCH 358/365] don't print traceback --- autoload/leaderf/python/leaderf/gitExpl.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 13580fc8..28898c2b 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -548,7 +548,7 @@ def __init__(self, arguments_dict, cmd, buf_name, file_type, file_type_cmd): class ParallelExecutor(object): @staticmethod - def run(*cmds, format_line=None, directory=None, silent=False): + def run(*cmds, format_line=None, directory=None, silent=False, error=None): outputs = [[] for _ in range(len(cmds))] stop_thread = False @@ -558,10 +558,12 @@ def readContent(content, output): output.append(line) if stop_thread: break - except Exception: + except Exception as e: if silent == False: traceback.print_exc() traceback.print_stack() + elif isinstance(error, list): + error.append(str(e)) executors = [AsyncExecutor() for _ in range(len(cmds))] @@ -3180,12 +3182,15 @@ def create(self, arguments_dict, cmd, project_root=None): line_num_width = len(str(len(vim.current.buffer))) + 1 date_format = arguments_dict.get("--date", ["iso"])[0] + error = [] if date_format in ["iso", "iso-strict", "short"]: outputs = ParallelExecutor.run(cmd.getCommand(), format_line=partial(BlamePanel.formatLine, arguments_dict, line_num_width), - directory=self._project_root) + directory=self._project_root, + silent=True, + error=error) else: arguments_dict2 = arguments_dict.copy() arguments_dict2["-c"] = [] @@ -3203,7 +3208,12 @@ def create(self, arguments_dict, cmd, project_root=None): line_num_width), None, None], - directory=self._project_root) + directory=self._project_root, + silent=True, + error=error) + if len(error) > 0: + lfPrintError(error[0]) + return line_num_width = max(line_num_width, int(lfEval('&numberwidth'))) if len(outputs[0]) > 0: From 5316ba1976c7bdcc0033d0f5f9d434cd4dceaf5e Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Sun, 27 Apr 2025 22:36:04 +0800 Subject: [PATCH 359/365] `--side-by-side` is broken by 570b2f6 --- autoload/leaderf/Git.vim | 4 ++-- autoload/leaderf/python/leaderf/gitExpl.py | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/autoload/leaderf/Git.vim b/autoload/leaderf/Git.vim index b9dd6ff0..76a02182 100644 --- a/autoload/leaderf/Git.vim +++ b/autoload/leaderf/Git.vim @@ -542,7 +542,7 @@ function! leaderf#Git#Commands() abort \ {"Leaderf git diff --side-by-side": "fuzzy search and view the side-by-side diffs"}, \ {"Leaderf git diff --side-by-side --current-file":"view the side-by-side diffs of the current file"}, \ {"Leaderf git diff --explorer": "view the diffs in an explorer tabpage"}, - \ {"Leaderf git diff --explorer --unified": "view the diffs in an explorer tabpage, the diffs is shown in unified view"}, + \ {"Leaderf git diff --explorer --side-by-side":"view the diffs in an explorer tabpage, the diffs is shown in a side-by-side view"}, \ {"Leaderf git diff --directly": "view the diffs directly"}, \ {"Leaderf git diff --directly --position right":"view the diffs in the right split window"}, \ {"Leaderf git diff --cached": "fuzzy search and view `git diff --cached`"}, @@ -558,7 +558,7 @@ function! leaderf#Git#Commands() abort \ {"Leaderf git log": "fuzzy search and view the log"}, \ {"Leaderf git log --directly": "view the logs directly"}, \ {"Leaderf git log --explorer": "fuzzy search and view the log in an explorer tabpage"}, - \ {"Leaderf git log --explorer --unified": "fuzzy search and view the log in an explorer tabpage, the diffs is shown in unified view"}, + \ {"Leaderf git log --explorer --side-by-side":"fuzzy search and view the log in an explorer tabpage, the diffs is shown in a side-by-side view"}, \ {"Leaderf git log --explorer --navigation-position bottom": "specify the position of navigation panel in explorer tabpage"}, \ {"Leaderf git log --current-file": "fuzzy search and view the log of current file"}, \ {"Leaderf git log --current-file --explorer":"fuzzy search and view the log of current file in explorer tabpage"}, diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index 28898c2b..a2d0ddb2 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -3339,7 +3339,11 @@ def create(self, arguments_dict, command, target_path=None, line_num=None): buffer_name = command.getBufferName() winid = self._createWindow(win_pos, buffer_name) - callback = partial(self.getDiffViewPanel().create, + def createDiffViewPanel(get_diff_view_panel, arguments_dict, source, **kwargs): + return get_diff_view_panel().create(arguments_dict, source, **kwargs) + + callback = partial(createDiffViewPanel, + self.getDiffViewPanel, arguments_dict, winid=diff_view_winid, line_num=line_num, From 544b9d85dbd26489a128b6e60d8cf0d0bce077ae Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 8 May 2025 23:37:23 +0800 Subject: [PATCH 360/365] fix issue #1119 --- autoload/leaderf/Git.vim | 5 ++ autoload/leaderf/python/leaderf/gitExpl.py | 56 +++++++++++++++++----- 2 files changed, 50 insertions(+), 11 deletions(-) diff --git a/autoload/leaderf/Git.vim b/autoload/leaderf/Git.vim index 76a02182..63e2bb6c 100644 --- a/autoload/leaderf/Git.vim +++ b/autoload/leaderf/Git.vim @@ -484,6 +484,11 @@ function! leaderf#Git#UpdateInlineBlame(manager_id) abort exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value.updateInlineBlame()", a:manager_id) endfunction +function! leaderf#Git#InlineBlame(manager_id, id) abort + exec g:Lf_py "import ctypes" + exec g:Lf_py printf("ctypes.cast(%d, ctypes.py_object).value.inlineBlame()", a:manager_id) +endfunction + function! leaderf#Git#StartInlineBlameImpl(timer) abort call leaderf#LfPy("gitExplManager.startExplorer('--bottom', arguments={'arg_line': 'git blame', '--inline': [], 'autocmd': True})") endfunction diff --git a/autoload/leaderf/python/leaderf/gitExpl.py b/autoload/leaderf/python/leaderf/gitExpl.py index a2d0ddb2..1b9e246f 100644 --- a/autoload/leaderf/python/leaderf/gitExpl.py +++ b/autoload/leaderf/python/leaderf/gitExpl.py @@ -4121,6 +4121,7 @@ def __init__(self): if lfEval("hlexists('Lf_hl_gitInlineBlame')") == '0': lfCmd("call leaderf#colorscheme#popup#load('{}', '{}')" .format("git", lfEval("get(g:, 'Lf_PopupColorscheme', 'default')"))) + self._blame_timer_id = None def discardPanel(self, project_root): del self._blame_panels[project_root] @@ -4565,15 +4566,10 @@ def startInlineBlame(self, tmp_file_name): if lfEval("exists('b:lf_blame_changedtick')") == "1": return - lfCmd("let g:Lf_git_inline_blame_enabled = 1") - - lfCmd("augroup Lf_Git_Blame | augroup END") - lfCmd("autocmd! Lf_Git_Blame BufRead * silent call leaderf#Git#StartInlineBlame()") - lfCmd("autocmd! Lf_Git_Blame BufWinEnter * silent call leaderf#Git#StartInlineBlame()") - - file_name = vim.current.buffer.name + lfCmd("let b:lf_blame_changedtick = b:changedtick") self._initial_changedtick[vim.current.buffer.number] = vim.current.buffer.vars["changedtick"] + file_name = vim.current.buffer.name if " " in file_name: file_name = file_name.replace(' ', r'\ ') @@ -4584,13 +4580,51 @@ def startInlineBlame(self, tmp_file_name): git_cmd = (r'git blame --line-porcelain --contents {} -- {} | grep "^author \|^author-time\|^summary"' .format(tmp_file_name, file_name)) - outputs = ParallelExecutor.run(git_cmd, directory=self._project_root, silent=True) - if len(outputs[0]) == 0: + self._blame_info_list = [] + self._read_finished = 0 + + reader_thread = threading.Thread(target=self._readBlameInfo, args=(git_cmd, lfEval("&encoding"))) + reader_thread.daemon = True + reader_thread.start() + + if self._blame_timer_id is not None: + lfCmd("call timer_stop(%s)" % self._blame_timer_id) + self._blame_timer_id = lfEval("timer_start(50, function('leaderf#Git#InlineBlame', [%d]), {'repeat': -1})" % id(self)) + + lfCmd("let g:Lf_git_inline_blame_enabled = 1") + + def _readBlameInfo(self, git_cmd, encoding): + try: + executor = AsyncExecutor() + content = executor.execute(git_cmd, + encoding=encoding, + cwd=self._project_root + ) + self._blame_info_list = list(content) + self._read_finished = 1 + except Exception: + # traceback.print_exc() + # traceback.print_stack() + self._read_finished = 1 + + def inlineBlame(self): + if self._read_finished == 0: return + if self._blame_timer_id is not None: + lfCmd("call timer_stop(%s)" % self._blame_timer_id) + self._blame_timer_id = None + + lfCmd("augroup Lf_Git_Blame | augroup END") + lfCmd("autocmd! Lf_Git_Blame BufRead * silent call leaderf#Git#StartInlineBlame()") + lfCmd("autocmd! Lf_Git_Blame BufWinEnter * silent call leaderf#Git#StartInlineBlame()") + lfCmd("let b:lf_blame_line_number = line('.')") - lfCmd("let b:lf_blame_changedtick = b:changedtick") - blame_list = iter(outputs[0]) + + if len(self._blame_info_list) == 0: + return + + blame_list = iter(self._blame_info_list) i = 0 self._blame_infos[vim.current.buffer.number] = {} blame_infos = self._blame_infos[vim.current.buffer.number] From f1e194ce84edc21c5658b1238a54efa92ef642f0 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Sat, 10 May 2025 10:20:25 +0800 Subject: [PATCH 361/365] fix issue #1119 --- autoload/leaderf/python/leaderf/asyncExecutor.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/autoload/leaderf/python/leaderf/asyncExecutor.py b/autoload/leaderf/python/leaderf/asyncExecutor.py index 767301dd..037db53b 100644 --- a/autoload/leaderf/python/leaderf/asyncExecutor.py +++ b/autoload/leaderf/python/leaderf/asyncExecutor.py @@ -15,6 +15,8 @@ lfDEVNULL = open(os.devnull) +max_count = int(lfEval("g:Lf_MaxCount")) + class AsyncExecutor(object): """ A class to implement executing a command in subprocess, then @@ -24,7 +26,7 @@ def __init__(self): self._errQueue = None self._process = None self._finished = False - self._max_count = int(lfEval("g:Lf_MaxCount")) + self._max_count = max_count def _readerThread(self, fd, queue): try: From 5da7ae1607fc50295073efa14678b2334d697a78 Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 21 May 2025 20:12:58 +0800 Subject: [PATCH 362/365] fix issue #1122 --- autoload/leaderf/python/leaderf/bufExpl.py | 2 +- autoload/leaderf/python/leaderf/fileExpl.py | 2 +- autoload/leaderf/python/leaderf/mruExpl.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/autoload/leaderf/python/leaderf/bufExpl.py b/autoload/leaderf/python/leaderf/bufExpl.py index 2b6c7387..4dc8d196 100644 --- a/autoload/leaderf/python/leaderf/bufExpl.py +++ b/autoload/leaderf/python/leaderf/bufExpl.py @@ -300,7 +300,7 @@ def _previewInPopup(self, *args, **kwargs): if lfEval("bufloaded(%d)" % buf_number) == '0': lfCmd("silent call bufload(%d)" % buf_number) - jump_cmd = 'normal! g`"' + jump_cmd = 'silent! normal! g`"' self._createPopupPreview(vim.buffers[buf_number].name, buf_number, 0, jump_cmd) diff --git a/autoload/leaderf/python/leaderf/fileExpl.py b/autoload/leaderf/python/leaderf/fileExpl.py index a5e48bc2..16e58af4 100644 --- a/autoload/leaderf/python/leaderf/fileExpl.py +++ b/autoload/leaderf/python/leaderf/fileExpl.py @@ -843,7 +843,7 @@ def _previewInPopup(self, *args, **kwargs): else: source = line - jump_cmd = 'normal! g`"' + jump_cmd = 'silent! normal! g`"' self._createPopupPreview(line, source, 0, jump_cmd) @removeDevIcons diff --git a/autoload/leaderf/python/leaderf/mruExpl.py b/autoload/leaderf/python/leaderf/mruExpl.py index f4ba5622..1869d288 100644 --- a/autoload/leaderf/python/leaderf/mruExpl.py +++ b/autoload/leaderf/python/leaderf/mruExpl.py @@ -388,7 +388,7 @@ def _previewInPopup(self, *args, **kwargs): else: source = file - jump_cmd = 'normal! g`"' + jump_cmd = 'silent! normal! g`"' self._createPopupPreview(file, source, 0, jump_cmd) From 007d8487d888dbeacbd4a06783ce3b35d7ba90f4 Mon Sep 17 00:00:00 2001 From: Haoyuan Li Date: Mon, 26 May 2025 09:52:27 +0800 Subject: [PATCH 363/365] fix(python): TypeError: a bytes-like object is required, not 'str' (#1124) --- autoload/leaderf/python/leaderf/anyExpl.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/autoload/leaderf/python/leaderf/anyExpl.py b/autoload/leaderf/python/leaderf/anyExpl.py index 46cf9cbe..f0c2e31b 100644 --- a/autoload/leaderf/python/leaderf/anyExpl.py +++ b/autoload/leaderf/python/leaderf/anyExpl.py @@ -384,10 +384,11 @@ def _previewInPopup(self, *args, **kwargs): # for backward compatibility if isinstance(filename, int): # it is a buffer number lfCmd("silent call bufload(%d)" % filename) - elif lfEval("bufloaded('%s')" % escQuote(filename)) == '1': + else: if not self._has_nvim: # py3 in nvim return str, in vim return bytes filename = lfBytes2Str(filename) - filename = int(lfEval("bufnr('%s')" % escQuote(filename))) # actually, it's a buffer number + if lfEval("bufloaded('%s')" % escQuote(filename)) == '1': + filename = int(lfEval("bufnr('%s')" % escQuote(filename))) # actually, it's a buffer number self._createPopupPreview("", filename, line_num, lfBytes2Str(jump_cmd) if not self._has_nvim else jump_cmd) except vim.error as err: raise Exception("Error occurred in user defined %s: %s" % (str(preview), err)) From d0532194ad12dd9a889b0e369bafd562f8c167be Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Wed, 11 Jun 2025 10:42:16 +0800 Subject: [PATCH 364/365] fix issue #1128 --- autoload/leaderf/python/leaderf/manager.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/autoload/leaderf/python/leaderf/manager.py b/autoload/leaderf/python/leaderf/manager.py index ea344010..5e8500db 100644 --- a/autoload/leaderf/python/leaderf/manager.py +++ b/autoload/leaderf/python/leaderf/manager.py @@ -514,8 +514,8 @@ def _setWinOptions(self, winid): lfCmd("call nvim_win_set_option(%d, 'colorcolumn', '')" % winid) lfCmd("call nvim_win_set_option(%d, 'winhighlight', 'Normal:Lf_hl_popup_window')" % winid) else: - lfCmd("call win_execute(%d, 'setlocal number norelativenumber cursorline')" % winid) - lfCmd("call win_execute(%d, 'setlocal nofoldenable foldmethod=manual')" % winid) + lfCmd("noautocmd call win_execute(%d, 'setlocal number norelativenumber cursorline')" % winid) + lfCmd("noautocmd call win_execute(%d, 'setlocal nofoldenable foldmethod=manual')" % winid) if lfEval("get(g:, 'Lf_PopupShowFoldcolumn', 1)") == '0' or lfEval("get(g:, 'Lf_PopupShowBorder', 1)") == '1': lfCmd("call win_execute(%d, 'setlocal foldcolumn=0')" % winid) else: From b3e44d5dce2a9f1f882f64d2b24bb68f71acce4c Mon Sep 17 00:00:00 2001 From: Yggdroot Date: Thu, 12 Jun 2025 09:43:30 +0800 Subject: [PATCH 365/365] fix issue #1125 --- autoload/leaderf/python/leaderf/mruExpl.py | 1 + 1 file changed, 1 insertion(+) diff --git a/autoload/leaderf/python/leaderf/mruExpl.py b/autoload/leaderf/python/leaderf/mruExpl.py index 1869d288..7202bfe6 100644 --- a/autoload/leaderf/python/leaderf/mruExpl.py +++ b/autoload/leaderf/python/leaderf/mruExpl.py @@ -127,6 +127,7 @@ def getContent(self, *args, **kwargs): self._max_bufname_len = max(int(lfEval("strdisplaywidth('%s')" % escQuote(getBasename(line)))) for line in lines) + self._max_bufname_len = min(25, self._max_bufname_len) for i, line in enumerate(lines): if lfEval("g:Lf_ShowRelativePath") == '1' and show_absolute == False: line = lfRelpath(line)