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

**URL:** <https://discourse.julialang.org/t/ann-fzf-fuzzy-search-for-repl-history/42793>\
**Category:** Package Announcements\
**Created:** [July 9, 2020, 4:14pm UTC](https://discourse.julialang.org/t/ann-fzf-fuzzy-search-for-repl-history/42793 "2020-07-09T16:14:46Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [July 9, 2020, 4:14pm UTC](https://discourse.julialang.org/t/ann-fzf-fuzzy-search-for-repl-history/42793/1 "2020-07-09T16:14:46Z")

</div>

By wrapping the [fzf](https://github.com/junegunn/fzf) ([fzf\_jll](https://github.com/JuliaBinaryWrappers/fzf_jll.jl) and [JLFzf](https://github.com/Moelf/JLFzf.jl)) (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](https://streamable.com/jxdjx9)

by adding this to `startup.jl`: [Fzf Julia REPL · GitHub](https://gist.github.com/Moelf/d1f366b4005f71edc80b24dc43ef1857) , (triggered by `Ctrl-f`)

the eventual goal is to add this to `OhMyREPL`

---

<div class="post-metadata">

**Author:** ![jlapeyre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jlapeyre/32/4514_2.png) [@jlapeyre](https://discourse.julialang.org/u/jlapeyre)\
**Post date:** [July 9, 2020, 4:20pm UTC](https://discourse.julialang.org/t/ann-fzf-fuzzy-search-for-repl-history/42793/2 "2020-07-09T16:20:15Z")

</div>

awesome. I am already addicted to fzf + fish.

---

<div class="post-metadata">

**Author:** ![jlapeyre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jlapeyre/32/4514_2.png) [@jlapeyre](https://discourse.julialang.org/u/jlapeyre)\
**Post date:** [July 9, 2020, 4:34pm UTC](https://discourse.julialang.org/t/ann-fzf-fuzzy-search-for-repl-history/42793/3 "2020-07-09T16:34:27Z")

</div>

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.)

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [July 9, 2020, 4:43pm UTC](https://discourse.julialang.org/t/ann-fzf-fuzzy-search-for-repl-history/42793/4 "2020-07-09T16:43:38Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![jlapeyre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jlapeyre/32/4514_2.png) [@jlapeyre](https://discourse.julialang.org/u/jlapeyre)\
**Post date:** [July 9, 2020, 5:04pm UTC](https://discourse.julialang.org/t/ann-fzf-fuzzy-search-for-repl-history/42793/5 "2020-07-09T17:04:13Z")

</div>

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 !

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [July 9, 2020, 5:13pm UTC](https://discourse.julialang.org/t/ann-fzf-fuzzy-search-for-repl-history/42793/6 "2020-07-09T17:13:00Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![tkf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkf/32/17635_2.png) [@tkf](https://discourse.julialang.org/u/tkf)\
**Post date:** [July 9, 2020, 5:42pm UTC](https://discourse.julialang.org/t/ann-fzf-fuzzy-search-for-repl-history/42793/7 "2020-07-09T17:42:59Z")

</div>

FYI, here is another setup for using `fzf` with [https://github.com/tkf/InteractiveCodeSearch.jl](https://github.com/tkf/InteractiveCodeSearch.jl)

```julia
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:

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

```

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [August 30, 2020, 5:01am UTC](https://discourse.julialang.org/t/ann-fzf-fuzzy-search-for-repl-history/42793/8 "2020-08-30T05:01:46Z")

</div>

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.)

---

<div class="post-metadata">

**Author:** ![dpo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dpo/32/3335_2.png) [@dpo](https://discourse.julialang.org/u/dpo)\
**Post date:** [September 14, 2020, 10:38pm UTC](https://discourse.julialang.org/t/ann-fzf-fuzzy-search-for-repl-history/42793/9 "2020-09-14T22:38:13Z")

</div>

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:

```julia
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

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

```

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

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [September 14, 2020, 11:12pm UTC](https://discourse.julialang.org/t/ann-fzf-fuzzy-search-for-repl-history/42793/10 "2020-09-14T23:12:48Z")

</div>

ah, sorry about the typo. Btw, now Fzf is integrated with [OhMyREPL](https://github.com/KristofferC/OhMyREPL.jl), you can use that and make `startup.jl` cleaner 😉 . If it’s not in global scope, it’s fine for not being `const` I guess.

---

<div class="post-metadata">

**Author:** ![dpo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dpo/32/3335_2.png) [@dpo](https://discourse.julialang.org/u/dpo)\
**Post date:** [September 15, 2020, 12:20am UTC](https://discourse.julialang.org/t/ann-fzf-fuzzy-search-for-repl-history/42793/11 "2020-09-15T00:20:03Z")

</div>

Wonderful. Thanks!
