From 7a0b7fac6607831182db4a4b75b62f7d42d70d0c Mon Sep 17 00:00:00 2001 From: bhagwan Date: Fri, 8 Jul 2022 19:51:49 -0700 Subject: [PATCH] make_entry.file: optimized performance and logic --- lua/fzf-lua/make_entry.lua | 60 ++++++++++++++++++++++---------------- lua/fzf-lua/utils.lua | 18 ++++++++++++ 2 files changed, 53 insertions(+), 25 deletions(-) diff --git a/lua/fzf-lua/make_entry.lua b/lua/fzf-lua/make_entry.lua index 7e33d35..8a055d3 100644 --- a/lua/fzf-lua/make_entry.lua +++ b/lua/fzf-lua/make_entry.lua @@ -298,50 +298,59 @@ M.lcol = function(entry, opts) (opts and opts.trim_entry and vim.trim(entry.text)) or entry.text) end +local COLON_BYTE = string.byte(":") + M.file = function(x, opts) opts = opts or {} local ret = {} local icon, hl - local file = utils.strip_ansi_coloring(string.match(x, '[^:]*')) - if opts.cwd_only and path.starts_with_separator(file) then - local cwd = opts.cwd or vim.loop.cwd() - if not path.is_relative(file, cwd) then - return nil - end - end + local colon_idx = utils.find_next_char(x, COLON_BYTE) or 0 + local file_part = colon_idx>1 and x:sub(1, colon_idx-1) or x + local rest_of_line = colon_idx>1 and x:sub(colon_idx) or nil + -- strip ansi coloring from path so we can use filters + -- otherwise the ANSI escape sequnce will get in the way + -- TODO: we only support path modfication without ANSI + -- escape sequences, it becomes too expensive to modify + -- and restore the path with escape sequences + local filepath, file_is_ansi = utils.strip_ansi_coloring(file_part) -- fd v8.3 requires adding '--strip-cwd-prefix' to remove -- the './' prefix, will not work with '--color=always' -- https://github.com/sharkdp/fd/blob/master/CHANGELOG.md - if not (opts.strip_cwd_prefix == false) and path.starts_with_cwd(x) then - x = path.strip_cwd_prefix(x) - -- this is required to fix git icons not showing - -- since `git status -s` does not prepend './' - -- we can assume no ANSI coloring is present - -- since 'path.starts_with_cwd == true' - file = x + if not (opts.strip_cwd_prefix == false) and path.starts_with_cwd(filepath) then + filepath = path.strip_cwd_prefix(filepath) end - if opts.cwd and #opts.cwd > 0 then - -- TODO: does this work if there are ANSI escape codes in x? - x = path.relative(x, opts.cwd) + -- make path relative + if opts.cwd and #opts.cwd>0 then + filepath = path.relative(filepath, opts.cwd) end - -- replace $HOME with ~ - if path.starts_with_separator(x) then - x = path.HOME_to_tilde(x) + if path.starts_with_separator(filepath) then + -- filter for cwd only + if opts.cwd_only then + local cwd = opts.cwd or vim.loop.cwd() + if not path.is_relative(filepath, cwd) then + return nil + end + end + -- replace $HOME with ~ + filepath = path.HOME_to_tilde(filepath) end -- only check for ignored patterns after './' was -- stripped and path was transformed to relative if opts.file_ignore_patterns then for _, pattern in ipairs(opts.file_ignore_patterns) do - if #pattern>0 and x:match(pattern) then + if #pattern>0 and filepath:match(pattern) then return nil end end end + -- only shorten after we're done with all the filtering + -- save a copy for git indicator and icon lookups + local origpath = filepath if opts.path_shorten then - x = path.shorten(x, tonumber(opts.path_shorten)) + filepath = path.shorten(filepath, tonumber(opts.path_shorten)) end if opts.git_icons then - local indicators = opts.diff_files and opts.diff_files[file] or utils.nbsp + local indicators = opts.diff_files and opts.diff_files[origpath] or utils.nbsp for i=1,#indicators do icon = indicators:sub(i,i) local git_icon = config.globals.git.icons[icon] @@ -356,7 +365,7 @@ M.file = function(x, opts) ret[#ret+1] = utils.nbsp end if opts.file_icons then - local filename = path.tail(file) + local filename = path.tail(origpath) local ext = path.extension(filename) icon, hl = M.get_devicon(filename, ext) if opts.color_icons then @@ -368,7 +377,8 @@ M.file = function(x, opts) ret[#ret+1] = icon ret[#ret+1] = utils.nbsp end - ret[#ret+1] = x + ret[#ret+1] = file_is_ansi>0 and file_part or filepath + ret[#ret+1] = rest_of_line return table.concat(ret) end diff --git a/lua/fzf-lua/utils.lua b/lua/fzf-lua/utils.lua index 1b27aee..68a1b49 100644 --- a/lua/fzf-lua/utils.lua +++ b/lua/fzf-lua/utils.lua @@ -60,6 +60,24 @@ M.strsplit = function(inputstr, sep) return t end +local string_byte = string.byte + +M.find_last_char = function(str, c) + for i=#str,1,-1 do + if string_byte(str, i) == c then + return i + end + end +end + +M.find_next_char = function(str, c, start_idx) + for i=start_idx or 1,#str do + if string_byte(str, i) == c then + return i + end + end +end + function M.round(num, limit) if not num then return nil end if not limit then limit = 0.5 end