[ANN?] Fzf (fuzzy search) for REPL history

By wrapping the fzf (fzf_jll and JLFzf) (I realize it should probably just be called Fzf.jl but name is then too short (since potentially one can make a julia implementation of Fzf)

now one can have a cool fuzzy search experience, demo: https://streamable.com/jxdjx9

by adding this to startup.jl: https://gist.github.com/Moelf/d1f366b4005f71edc80b24dc43ef1857 , (triggered by Ctrl-f)

the eventual goal is to add this to OhMyREPL

15 Likes

awesome. I am already addicted to fzf + fish.

1 Like

Ctrl-f is already used for forward one character (as in emacs). I install your package and the gist, and find that Ctrl-f still does forward one character rather than fuzzy history search. Am I missing something?

(btw. I have successfully ignored config chores in favor of work today, but was unable to resist here.)

ah, you can just change ^f in startup.jl to something else then

I see. I looks like I have to choose something that is not already bound. In my case ^q works. But, I’m using default keybindings (linux, if that matters). fzf errors out complaining that the list (my repl history) is too long (190K lines). If I delete repl_history.jl then your package + init code do work !

1 Like

oh interesting, I didn’t know fzf would complain, ehh, so you can probably hack the call in startup.jl to take the last 10k lines maybe

FYI, here is another setup for using fzf with https://github.com/tkf/InteractiveCodeSearch.jl

using InteractiveCodeSearch
InteractiveCodeSearch.CONFIG.interactive_matcher = `fzf`
@search show             # search method definitions of show
@searchmethods 1         # search methods defined for integer
@searchhistory           # search history

If you have pygmentize, you can have multi-line preview with syntax highlighting:

InteractiveCodeSearch.CONFIG.interactive_matcher = `fzf --preview 'echo {} | sed "s/⏎/\n/g" | pygmentize -l jl'`
4 Likes

thanks to @denius , using Julia’s IOBuffer solved the problem of “repl history too long”. Also now that when selecting a entry, the prompt mode will be switched automatically (i.e to Pkg> or help> or shell> etc.)

1 Like

Many thanks for this. I tried to incorporate it into my startup.jl but got an error because of a comma missing at the end of line 9 in your gist.

Also, my startup.jl looks like this:

atreplinit() do repl
   try
     @info "importing JLFzf"
     @eval import REPL
     @eval import REPL.LineEdit
     @eval import JLFzf
     mykeys = Dict{Any,Any}(
         # primary history search: most recent first
         "^R" => function (mistate, o, c)
             line = JLFzf.inter_fzf(JLFzf.read_repl_hist(),
                                    "--read0",
                                    "--tiebreak=index",
                                    "--height=80%");
             JLFzf.insert_history_to_repl(mistate, line)
         end,
     )
     function customize_keys(repl)
         repl.interface = REPL.setup_interface(repl; extra_repl_keymap = mykeys)
     end
     customize_keys(repl)
   catch e
     @error "error while importing JLFzf" e
   end

  # similar blocks for other packages that are imported at startup...
end

I had to remove the const in the declaration of mykeys because Julia complained that

ERROR: LoadError: syntax: unsupported `const` declaration on local variable

How would one may mykeys a const in a case like this?

1 Like

ah, sorry about the typo. Btw, now Fzf is integrated with OhMyREPL, you can use that and make startup.jl cleaner :wink: . If it’s not in global scope, it’s fine for not being const I guess.

2 Likes

Wonderful. Thanks!