-
-
Notifications
You must be signed in to change notification settings - Fork 5.7k
The Fanciest REPL History in the Land #59819
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
Anyone else getting "video playback aborted due to a network error"? |
If possible, it would be nice to cut this up into some orthogonal pieces. For example, the AnnotatedString perf improvements could be a separate PR that (with benchmarks) could be merged and would make the diff here smaller and easier to review. |
stdlib/REPL/src/History/search.jl
Outdated
filename = try | ||
readline(term.in_stream) | ||
catch err | ||
if err isa InterruptException | ||
"" | ||
else | ||
rethrow() | ||
end | ||
end | ||
isempty(filename) && (println(out, S"\e[F\e[2K{light,grey:{bold:history>} {red:×} History selection aborted}\n"); return) | ||
write(filename, "# Julia REPL history excerpt\n\n", content) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe it should default write to a location? The prompt could default to ~/.julia/history.jl
(or a more appropriate location).
Ideally, the prompt for the filename would also allow scrolling up and down with the up arrow and down arrow, typing some characters of the file and hitting up arrow to narrow the search, have a ghost text of the last file name or the default file name so right arrow completes it etc. But I can imagine this being awkward the way things are set up in the REPL?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ideally, the prompt for the filename would also allow scrolling up and down with the up arrow and down arrow, typing some characters of the file and hitting up arrow to narrow the search, have a ghost text of the last file name or the default file name so right arrow completes it etc. But I can imagine this being awkward the way things are set up in the REPL?
I've had exactly the same thought. I just can't be bothered to make it happen 😅
I'm happy to split this up, but there are really just three parts to it:
I could split 1-2 off into a separate PR to review, if that sounds like a nice idea?
There's only suspicious performance here, not perf improvements, unfortunately 😞. I say "suspicious" because if I remove the keyword argument from For now, I've left these julia/base/strings/annotated_io.jl Lines 202 to 226 in cc7ed22
julia/base/strings/annotated_io.jl Lines 236 to 240 in cc7ed22
|
cc7ed22
to
75fd56d
Compare
I've just added back ~400 loc of the original code for using up/down arrow keys to go through recent history without If you start a new REPL and immediately press up arrow, it does nothing the first time. Not quite sure why... (any ideas?) I would like to add session-awareness. Maybe I'll try to drop that in this PR too? |
75fd56d
to
221b4e5
Compare
Rebased to the latest REPL Syntax Highlighting |
221b4e5
to
ee23322
Compare
Fixed some typos. |
The precompilation situation is looking pretty decent, this is all I'm seeing with
|
ee23322
to
3a6d8d7
Compare
Rebased now that #59778 has been merged. |
3a6d8d7
to
4bac24f
Compare
Fixed. |
4bac24f
to
c7a66cb
Compare
Thanks to Miguel, Camillo, and Sundar for taking this for a test-drive and providing feedback 🙂 Changes:
|
7126dd7
to
0da2a86
Compare
Rebase (get the REPL precompilation improvements) |
dade819
to
20658d5
Compare
|
On an unrelated note, I'm very sad that the diff is no longer |
20658d5
to
7e2228f
Compare
|
7e2228f
to
3761825
Compare
|
3761825
to
c20074d
Compare
|
c97a251
to
ba66c91
Compare
|
ba66c91
to
0495021
Compare
|
73d36b0
to
9b7ceb7
Compare
|
9b7ceb7
to
29172d2
Compare
|
That's truly excellent!! Thank you! I just started using it, and noticed a couple of problems:
|
Extract the replacement loop body into `_replace_once` to ease future annotation tracking during string replacement operations. The new function returns match information (pattern index, match range, bytes written) that will be needed to properly adjust annotation positions when replacements occur.
Implement `replace` function for `AnnotatedString` that properly handles annotation regions during pattern replacement operations. The function tracks which bytes are replaced versus preserved, maintaining annotations only on original content and adding new annotations from replacement text. - Supports AnnotatedChar, AnnotatedString, and SubString replacements - Drops, shifts, and splits existing annotations appropriately - Refactored `_insert_annotations!` to work with annotation vectors directly - Adjacent replacements with identical annotations are merged into single regions - Lots of tests (thanks Claude!) Performance is strangely poor. For the test case mentioned in the REVIEW comment within `_insert_annotations!` we should be able to perform the replacement in ~200ns (compared to ~70ns for the equivalent unannotated case). However, for two reasons that are beyond me instead it takes ~4400ns. See the REVIEW comments for more details, help would be much appreciated.
Discarding the annotations can come as a bit of a surprise best avoided.
Since the dawn of the Julia REPL, history completion has been limited to a readline-style interface. OhMyREPL improved the experience with fzf, but those who yearned for a delightful history completion experience (me) were left underwhelmed. With this overhaul, I now find myself spending more time looking through my history because it's just *so nice* to do so. The new history system is organised as a standalone module in stdlib/REPL/src/History with a clear separation of concerns: 1. History file management 2. Event-driven prompt/UI updating 3. Incremental filtering 4. UI display 5. Search coordination (prompt + display + filter) I've attempted to pull out all the (reasonable) stops to make history searching as fluid and snappy as possible. By memory mapping the history file in the initial read, and optimising the parser, we can read ~2 million history items per second. Result filtering is incremental and resumable, performed in dynamically sized batches to ensure responsiveness. Rapid user inputs are debouced. We store a log-structured record of previous search result, and compare search strictness to resume from prior partial results instead of filtering the history from scratch every time. Syncronisation between the interface and filtering is enabled via a Channel-based event loop. Enjoy! (I know I am)
29172d2
to
03ca9f0
Compare
|
The Fanciest REPL History in the Land ✨
Do you dread typing out code for the second time? Are you a particular enjoyed of REPL history?
Well, I know I am, and for years I have yearned for something better than the current
readline
-style completion, better than OhMyREPL.jl's fzf-driven completion, better than any REPL history I've seen before!It's not quite finished baking, but we're onto the final stretch 😀
repl_history_demo.webm
Thanks to @kdheepak, @jakobnissen, and @digital-carver for helping me design the UI and UX over on Zulip (#repl > Revamped REPL history).
Features
TODO
replace
methodreplace
methodreplace
method (see: theREVIEW: ...
code comments inannotated_io.jl
)This PR is on top of #59778, because I think I can safely assume that will be merged first.