Skip to content

Commit 478869c

Browse files
committed
feat(files): support paths with CRLF (closes #2367)
Note that due to grep/rg limitations this doesn't work with grep. Use `render_crlf` option: ```lua :FzfLua files render_crlf=true -- Or with lua :lua FzfLua.live_grep({ render_crlf = true }) ```
1 parent e9d95a2 commit 478869c

6 files changed

Lines changed: 46 additions & 5 deletions

File tree

lua/fzf-lua/config.lua

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -711,6 +711,21 @@ function M.normalize_opts(opts, globals, __resume_key)
711711
opts.multiline = nil
712712
end
713713

714+
-- Support filenames with CRLF (#2367), idea borrowed from fzf v0.39 changelog:
715+
-- carriage return and a line feed characters will be rendered as dim ␍ and ␊ respectively
716+
if opts.render_crlf then
717+
opts.fzf_opts["--read0"] = true
718+
if opts.fd_opts then
719+
-- adding "-0" to fd prepends entries with "./", since we cannot guarantee fd v8.3
720+
-- we remove the prefix in `make_entry.file` (instead of adding "--strip-cwd-prefix")
721+
opts.strip_cwd_prefix = true
722+
opts.fd_opts = "-0 " .. opts.fd_opts
723+
end
724+
if opts.rg_opts then opts.rg_opts = "-0 " .. opts.rg_opts end
725+
if opts.grep_opts then opts.grep_opts = "-Z " .. opts.grep_opts end
726+
if opts.find_opts then opts.find_opts = "-print0 " .. opts.find_opts end
727+
end
728+
714729
do
715730
-- Remove incompatible flags / values
716731
-- (1) `true` flags are removed entirely (regardless of value)
@@ -908,6 +923,7 @@ function M.normalize_opts(opts, globals, __resume_key)
908923
or opts.file_icons
909924
or opts.file_ignore_patterns
910925
or opts.strip_cwd_prefix
926+
or opts.render_crlf
911927
or opts.path_shorten
912928
or opts.formatter
913929
or opts.multiline

lua/fzf-lua/libuv.lua

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,14 +47,24 @@ end
4747

4848
---@param opts {cwd: string, cmd: string|table, env: table?, cb_finish: function,
4949
---cb_write: function?, cb_write_lines: function?, cb_err: function, cb_pid: function,
50-
---fn_transform: function?, EOL: string?, process1: boolean?, profiler: boolean?,
51-
---use_queue: boolean?}
50+
---fn_transform: function?, EOL: string?, EOL_data: string?, process1: boolean?,
51+
---profiler: boolean?, use_queue: boolean?}
5252
---@param fn_transform function?
5353
---@param fn_done function?
5454
---@return uv.uv_process_t proc
5555
---@return integer pid
5656
M.spawn = function(opts, fn_transform, fn_done)
5757
local EOL = opts.EOL or "\n"
58+
local EOL_data = type(opts.cmd) == "string"
59+
-- fd -0|--print0
60+
-- rg -0|--null
61+
-- grep -Z|--null
62+
-- find . -print0
63+
and (opts.cmd:match("%s%-0")
64+
or opts.cmd:match("%s%-?%-print0") -- -print0|--print0
65+
or opts.cmd:match("%s%-%-null")
66+
or opts.cmd:match("%s%-Z"))
67+
and "\0" or "\n"
5868
local output_pipe = assert(uv.new_pipe(false))
5969
local error_pipe = assert(uv.new_pipe(false))
6070
local write_cb_count, read_cb_count = 0, 0
@@ -176,7 +186,7 @@ M.spawn = function(opts, fn_transform, fn_done)
176186
local ret = {}
177187
local start_idx = 1
178188
repeat
179-
local nl_idx = data:find("\n", start_idx, true)
189+
local nl_idx = data:find(EOL_data, start_idx, true)
180190
if nl_idx then
181191
local cr = data:byte(nl_idx - 1, nl_idx - 1) == 13 -- \r
182192
local line = data:sub(start_idx, nl_idx - (cr and 2 or 1))
@@ -378,8 +388,6 @@ end
378388
---@param opts table
379389
---@return uv.uv_process_t, integer
380390
M.spawn_stdio = function(opts)
381-
local EOL = opts.multiline and "\0" or "\n"
382-
383391
-- stdin/stdout are already buffered, not stderr. This means
384392
-- that every character is flushed immediately which caused
385393
-- rendering issues on Mac (#316, #287) and Linux (#414)
@@ -397,6 +405,9 @@ M.spawn_stdio = function(opts)
397405
-- setup global vars
398406
for k, v in pairs(opts.g or {}) do _G[k] = v end
399407

408+
---@diagnostic disable-next-line: undefined-field
409+
local EOL = _G._EOL or opts.multiline and "\0" or "\n"
410+
400411
-- Requiring make_entry will create the pseudo `_G.FzfLua` global
401412
-- Must be called after global vars are created or devicons will
402413
-- err with "fzf-lua fatal: '_G._fzf_lua_server', '_G._devicons_path' both nil"

lua/fzf-lua/make_entry.lua

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,9 @@ M.file = function(x, opts)
577577
if opts.strip_cwd_prefix then
578578
filepath = path.strip_cwd_prefix(filepath)
579579
end
580+
if opts.render_crlf then
581+
filepath = path.render_crlf(filepath)
582+
end
580583
-- make path relative
581584
if opts.cwd and #opts.cwd > 0 then
582585
filepath = path.relative_to(filepath, opts.cwd)

lua/fzf-lua/path.lua

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,12 @@ M.strip_cwd_prefix = function(path)
9696
end
9797
end
9898

99+
---@param path string
100+
---@return string
101+
M.render_crlf = function(path)
102+
return (path:gsub("\n", ""):gsub("\r", ""))
103+
end
104+
99105
---Get the basename|tail of the given path.
100106
---@param path string
101107
---@return string
@@ -426,6 +432,9 @@ function M.entry_to_file(entry, opts, force_uri)
426432
end
427433
-- Remove ANSI coloring and prefixed icons
428434
entry = utils.strip_ansi_coloring(entry)
435+
if opts.render_crlf then
436+
entry = entry:gsub("", "\n"):gsub("", "\r")
437+
end
429438
local stripped, idx = (function()
430439
-- Returns the first viable path:line?:col? + rest of line
431440
-- stripping until the last occurrence of utils.nbsp may err

lua/fzf-lua/providers/grep.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ M.live_grep_native = function(opts)
169169
file_icons = false,
170170
file_ignore_patterns = false,
171171
strip_cwd_prefix = false,
172+
render_crlf = false,
172173
path_shorten = false,
173174
formatter = false,
174175
multiline = false,

lua/fzf-lua/shell.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ M.stringify_mt = function(contents, opts)
214214
"color_icons",
215215
"path_shorten",
216216
"strip_cwd_prefix",
217+
"render_crlf",
217218
"exec_empty_query",
218219
"file_ignore_patterns",
219220
"rg_glob",

0 commit comments

Comments
 (0)