@@ -7,9 +7,6 @@ local actions = require "fzf-lua.actions"
77local win = require " fzf-lua.win"
88local libuv = require " fzf-lua.libuv"
99local shell = require " fzf-lua.shell"
10- local make_entry = require " fzf-lua.make_entry"
11- local base64 = require " fzf-lua.lib.base64"
12- local serpent = require " fzf-lua.lib.serpent"
1310
1411local M = {}
1512
@@ -161,48 +158,22 @@ M.fzf_exec = function(contents, opts)
161158 opts .fn_selected = opts .fn_selected or function (selected , o )
162159 actions .act (selected , o )
163160 end
164- -- Contents sent to fzf can only be nil or a shell command (string)
165- -- the API accepts both tables and functions which we "stringify"
166- if not opts .fn_reload then
167- opts .__contents = contents
168- contents = shell .stringify (opts )
169- end
170- assert (contents == nil or type (contents ) == " string" , " contents must be of type string" )
171- -- setup as "live": disables fuzzy matching and reload the content
172- -- every keystroke (query changed), utilizes fzf's 'change:reload'
173- -- event trigger or skim's "interactive" mode
174- if type (opts .fn_reload ) == " string" then
175- if not opts .fn_transform then
176- -- TODO: add support for 'fn_transform' using 'mt_cmd_wrapper'
177- -- functions can be stored using 'config.bytecode' which uses
178- -- 'string.dump' to convert from function code to bytes
179- opts .fn_reload = M .mt_cmd_wrapper (opts ) or opts .fn_reload
180- opts = M .setup_fzf_interactive_native (opts .fn_reload , opts )
181- contents = opts .__fzf_init_cmd
182- else
183- -- the caller requested to transform, we need to convert
184- -- to a function that returns string so that libuv.spawn
185- -- is called
186- local cmd = opts .fn_reload --[[ @as string]]
187- opts .fn_reload = function (q )
188- if cmd :match (M .fzf_query_placeholder ) then
189- return cmd :gsub (M .fzf_query_placeholder , q or " " )
190- else
191- return string.format (" %s %s" , cmd , q or " " )
192- end
193- end
194- end
195- end
196- if type (opts .fn_reload ) == " function" then
197- opts .__fn_transform = opts .fn_transform
198- opts .__fn_reload = function (query )
199- config .resume_set (" query" , query , opts )
200- return opts .fn_reload (query )
201- end
202- opts = M .setup_fzf_interactive_wrap (opts )
161+ if opts .fn_reload then
162+ -- AKA "live": fzf acts as a selector only (fuzzy matching is disabled)
163+ -- each keypress reloads fzf's input usually based on the typed query
164+ -- utilizes fzf's 'change:reload' event or skim's "interactive" mode
165+ opts .fn_reload = shell .stringify (opts .fn_reload , opts )
166+ opts = M .setup_fzf_interactive_native (opts .fn_reload , opts )
203167 contents = opts .__fzf_init_cmd
168+ elseif contents then
169+ -- Contents sent to fzf can only be nil or a shell command (string)
170+ -- the API accepts both tables and functions which we "stringify"
171+ -- We also send string commands as stringify is also responsible
172+ -- for multiprocess wrapping of shell commands with processing
173+ contents = shell .stringify (contents , opts ) or nil
204174 end
205- return M .fzf_wrap (opts , contents )
175+ assert (contents == nil or type (contents ) == " string" , " contents must be of type string" )
176+ return M .fzf_wrap (contents , opts )
206177end
207178
208179--- @param contents string | fun ( query : string ): string | string[] | function
@@ -229,11 +200,11 @@ M.fzf_resume = function(opts)
229200 M .fzf_exec (config .__resume_data .contents , config .__resume_data .opts )
230201end
231202
232- --- @param opts table
233203--- @param contents string ?
204+ --- @param opts table
234205--- @param fn_selected function ?
235206--- @return thread
236- M .fzf_wrap = function (opts , contents , fn_selected )
207+ M .fzf_wrap = function (contents , opts , fn_selected )
237208 opts = opts or {}
238209 local _co
239210 coroutine.wrap (function ()
@@ -456,7 +427,7 @@ M.fzf = function(contents, opts)
456427 -- reminder: this doesn't get called with 'live_grep' when using skim
457428 -- due to a bug where '--print-query --interactive' combo is broken:
458429 -- skim always prints an empty line where the typed query should be.
459- -- see additional note above 'opts.fn_post_fzf' inside 'live_grep_mt '
430+ -- see additional note above 'opts.fn_post_fzf' inside 'live_grep '
460431 config .resume_set (" query" , selected [1 ], opts )
461432 end
462433 table.remove (selected , 1 )
@@ -625,7 +596,7 @@ M.create_fzf_binds = function(opts)
625596 v = v [1 ]
626597 elseif type (v ) == " function" then
627598 if utils .has (opts , " fzf" ) then
628- v = " execute-silent:" .. shell .raw_action (v , nil , opts . debug )
599+ v = " execute-silent:" .. shell .stringify_data (v , opts )
629600 else
630601 v = nil
631602 end
@@ -682,7 +653,7 @@ M.build_fzf_cli = function(opts, fzf_win)
682653 local preview_cmd
683654 local preview_spec = opts .fzf_opts [" --preview" ]
684655 if type (preview_spec ) == " function" then
685- preview_cmd = shell .raw_action (preview_spec , " {}" , opts . debug )
656+ preview_cmd = shell .stringify_data (preview_spec , opts , " {}" )
686657 elseif type (preview_spec ) == " table" then
687658 preview_spec = vim .tbl_extend (" keep" , preview_spec , {
688659 fn = preview_spec .fn or preview_spec [1 ],
@@ -691,10 +662,9 @@ M.build_fzf_cli = function(opts, fzf_win)
691662 field_index = " {}" ,
692663 })
693664 if preview_spec .type == " cmd" then
694- preview_cmd = shell .raw_preview_action_cmd (
695- preview_spec .fn , preview_spec .field_index , opts .debug )
665+ preview_cmd = shell .stringify_cmd (preview_spec .fn , opts , preview_spec .field_index )
696666 else
697- preview_cmd = shell .raw_action (preview_spec .fn , preview_spec . field_index , opts . debug )
667+ preview_cmd = shell .stringify_data (preview_spec .fn , opts , preview_spec . field_index )
698668 end
699669 end
700670 if preview_cmd then
@@ -785,132 +755,6 @@ M.build_fzf_cli = function(opts, fzf_win)
785755 return cli_args
786756end
787757
788- --- @param opts table
789- --- @return string ?
790- M .mt_cmd_wrapper = function (opts )
791- assert (opts and opts .cmd )
792- --- @param o table<string , unknown>
793- --- @return table
794- local filter_opts = function (o )
795- local names = {
796- " debug" ,
797- " profile" ,
798- " process1" ,
799- " silent" ,
800- " argv_expr" ,
801- " cmd" ,
802- " cwd" ,
803- " stdout" ,
804- " stderr" ,
805- " stderr_to_stdout" ,
806- " formatter" ,
807- " multiline" ,
808- " git_dir" ,
809- " git_worktree" ,
810- " git_icons" ,
811- " file_icons" ,
812- " color_icons" ,
813- " path_shorten" ,
814- " strip_cwd_prefix" ,
815- " exec_empty_query" ,
816- " file_ignore_patterns" ,
817- " rg_glob" ,
818- " _base64" ,
819- utils .__IS_WINDOWS and " __FZF_VERSION" or nil ,
820- }
821- -- caller requested rg with glob support
822- if o .rg_glob then
823- table.insert (names , " glob_flag" )
824- table.insert (names , " glob_separator" )
825- end
826- local t = {}
827- for _ , name in ipairs (names ) do
828- if o [name ] ~= nil then
829- t [name ] = o [name ]
830- end
831- end
832- t .g = {}
833- for k , v in pairs ({
834- [" _fzf_lua_server" ] = vim .g .fzf_lua_server ,
835- -- [NOTE] No longer needed, we use RPC for icons
836- -- ["_devicons_path"] = devicons.plugin_path(),
837- -- ["_devicons_setup"] = config._devicons_setup,
838- [" _EOL" ] = opts .multiline and " \0 " or " \n " ,
839- [" _debug" ] = opts .debug ,
840- }) do
841- t .g [k ] = v
842- end
843- return t
844- end
845-
846- --- @param obj table | string
847- --- @return string
848- local serialize = function (obj )
849- local str = type (obj ) == " table"
850- and serpent .line (obj , { comment = false , sortkeys = false })
851- or tostring (obj )
852- if opts ._base64 ~= false then
853- -- by default, base64 encode all arguments
854- return " [==[" .. base64 .encode (str ) .. " ]==]"
855- else
856- -- if not encoding, don't string wrap the table
857- return type (obj ) == " table" and str
858- or " [==[" .. str .. " ]==]"
859- end
860- end
861-
862- if not opts .requires_processing
863- and not opts .git_icons
864- and not opts .file_icons
865- and not opts .file_ignore_patterns
866- and not opts .path_shorten
867- and not opts .formatter
868- and not opts .multiline
869- then
870- -- command does not require any processing, we also reset `argv_expr`
871- -- to keep `setup_fzf_interactive_flags::no_query_condi` in the command
872- opts .argv_expr = nil
873- return opts .cmd
874- elseif opts .multiprocess then
875- assert (not opts .__mt_transform or type (opts .__mt_transform ) == " string" )
876- assert (not opts .__mt_preprocess or type (opts .__mt_preprocess ) == " string" )
877- assert (not opts .__mt_postprocess or type (opts .__mt_postprocess ) == " string" )
878- if opts .argv_expr then
879- -- Since the `rg` command will be wrapped inside the shell escaped
880- -- '--headless .. --cmd', we won't be able to search single quotes
881- -- as it will break the escape sequence. So we use a nifty trick:
882- -- * replace the placeholder with {argv1}
883- -- * re-add the placeholder at the end of the command
884- -- * preprocess then replace it with vim.fn.argv(1)
885- -- NOTE: since we cannot guarantee the positional index
886- -- of arguments (#291), we use the last argument instead
887- opts .cmd = opts .cmd :gsub (M .fzf_query_placeholder , " {argvz}" )
888- end
889- local cmd = libuv .wrap_spawn_stdio (
890- serialize (filter_opts (opts )),
891- serialize (opts .__mt_transform or [[ return require("fzf-lua.make_entry").file]] ),
892- serialize (opts .__mt_preprocess or [[ return require("fzf-lua.make_entry").preprocess]] ),
893- serialize (opts .__mt_postprocess or " nil" )
894- )
895- if opts .argv_expr then
896- -- prefix the query with `--` so we can support `--fixed-strings` (#781)
897- cmd = string.format (" %s -- %s" , cmd , M .fzf_query_placeholder )
898- end
899- return cmd
900- else
901- assert (not opts .__fn_transform or type (opts .__fn_transform ) == " function" )
902- assert (not opts .__fn_preprocess or type (opts .__fn_preprocess ) == " function" )
903- assert (not opts .__fn_postprocess or type (opts .__fn_postprocess ) == " function" )
904- opts .__fn_transform = opts .__fn_transform == nil
905- and function (x ) return make_entry .file (x , opts ) end
906- or opts .__fn_transform
907- opts .__fn_preprocess = opts .__fn_preprocess == nil
908- and function (o ) return make_entry .preprocess (o ) end
909- or opts .__fn_preprocess
910- return nil
911- end
912- end
913-
914758-- given the default delimiter ':' this is the
915759-- fzf expression field index for the line number
916760-- when entry format is 'file:line:col: text'
@@ -1136,7 +980,7 @@ local patch_shell_action = function(v, opts)
1136980 overide_f_idx = true
1137981 end
1138982 -- replace the action with shell cmd proxy to the original action
1139- return shell .raw_action (function (items , _ , _ )
983+ return shell .stringify_data (function (items , _ , _ )
1140984 assert (field_index :match (" ^{q} {n}" ))
1141985 local query , idx = unpack (items , 1 , 2 )
1142986 config .resume_set (" query" , query , opts )
@@ -1158,7 +1002,7 @@ local patch_shell_action = function(v, opts)
11581002 items = (zero_matched and zero_selected ) and {} or items
11591003 end
11601004 v .fn (items , opts )
1161- end , field_index , opts . debug )
1005+ end , opts , field_index )
11621006end
11631007
11641008-- converts actions defined with "reload=true" to use fzf's `reload` bind
@@ -1244,8 +1088,7 @@ M.convert_reload_actions = function(reload_cmd, opts)
12441088 -- NOTE: this fixes existence of both load as function and rebind, e.g. git_status with:
12451089 -- setup({ keymap = { fzf = { true, load = function() _G._fzf_load_called = true end } } }
12461090 if type (opts .keymap .fzf .load ) == " function" then
1247- opts .keymap .fzf .load = " execute-silent:" ..
1248- shell .raw_action (opts .keymap .fzf .load , nil , opts .debug )
1091+ opts .keymap .fzf .load = " execute-silent:" .. shell .stringify_data (opts .keymap .fzf .load , opts )
12491092 end
12501093 if rebind and type (opts .keymap .fzf .load ) == " string" then
12511094 return string.format (" %s+%s" , rebind , opts .keymap .fzf .load )
@@ -1411,18 +1254,6 @@ M.fzf_field_expression = function(opts)
14111254 return opts and opts .field_index or opts ._is_skim and [[ "{}"]] or " {q}"
14121255end
14131256
1414- -- Sets up the flags and commands required for running a "live" interface
1415- -- @param fn_reload :function called for reloading contents
1416- -- @param fn_transform :function to transform entries when using shell cmd
1417- M .setup_fzf_interactive_wrap = function (opts )
1418- assert (opts and opts .__fn_reload )
1419-
1420- -- neovim shell wrapper for parsing the query and loading contents
1421- local fzf_field_expression = M .fzf_field_expression (opts )
1422- local command = shell .stringify (opts , fzf_field_expression )
1423- return M .setup_fzf_interactive_flags (command , fzf_field_expression , opts )
1424- end
1425-
14261257M .setup_fzf_interactive_native = function (command , opts )
14271258 local fzf_field_expression = M .fzf_field_expression (opts )
14281259
0 commit comments