Skip to content
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

browse REPL input history #1860

Closed
johnv02139 opened this issue Oct 7, 2016 · 16 comments
Closed

browse REPL input history #1860

johnv02139 opened this issue Oct 7, 2016 · 16 comments

Comments

@johnv02139
Copy link
Contributor

Goal

I have wanted a better way to see and re-enter commands from my REPL input history. Scrolling through with M-p and M-n is good, but sometimes I want more.

When I saw cider-classpath, I realized that was very similar to what I wanted for input history. So, I adapted it, and really in just a couple of minutes, I think it came out very nice and useful. Please see:

johnv02139@764b529

Progress

What I've done so far allows you to see your history, most recent command on the top. It's Clojure code, so the buffer is derived from Clojure mode, so it's nicely highlighted. You can insert the command back into the REPL without executing it (bound to SPC), or insert it and execute it in one gesture (bound to RET).

Issue

However, there's a problem, and I'd like to see if anyone has any ideas. With cider-classpath, the text that it operates on is simply the text between the beginning and end of line. That is very often the case for history, too. But, not always.

It's fairly common to enter multi-line forms at the REPL prompt. And, once I've simply dumped all the text into the buffer, it's very tricky to reconstruct what was the beginning and end of the command.

Workaround

What my current version does is simply replace newlines with spaces, and then magically all the commands are a single line, and the bol/eol thing works fine. But then you lose your formatting (and Clojure strings containing newlines can be munged, etc.)

Wish

If this were a typical GUI application, it would be more like a list box, where each item in the list was associated with some text behind the scenes. But I don't think Emacs has any features like that, that I know of.

Options

So, some options:

  • insert a separator between each command, and then select the text between the separators
  • search backwards until you find a line that does not begin with a space (beginning of command); search forwards until you find a line that does not begin with a space, and then go back one character (end of command).
    • unfortunately that's not always correct. You can start your REPL input with a space. When entering a command, you could delete backwards so that the nth line does NOT begin with a space.
    • other option could be to format the command so that it does always have this property: first char of command is non-space, all newlines are followed by a space
  • find the valid Clojure form surrounding point
    • but input is not always valid. And you can do things like evaluate multiple forms at the same time. That (correctly, I believe) becomes a single entry in your history. So when using the history browser, if you choose that entry, you should get back the full text.

Enhancement?

Another option would be to output the lines numbered, much like the history command from a shell. And then, be able to re-enter a command that is not at point, by entering the number. This also would provide a natural separator. But, it could still be tricky if, say, a second line of an input entry started with an integer. And it also makes the buffer less Clojure-y.

Request

I'm interested to know

  1. if people think this is a useful feature
  2. any ideas for how to handle the multi-line input issue

Thanks!

@bbatsov
Copy link
Member

bbatsov commented Oct 8, 2016

That would be a wonderful feature!

I don't think the UI for cider-classpath is a good fit, though. I'd suggest lifting the UI from https://github.com/browse-kill-ring/browse-kill-ring/blob/master/browse-kill-ring.el

They are handling the multi-line items on the kill-ring there.

Basically for handling multi-line items you need to be inserting some delims between them, so on operations like clicking and so on you can get the boundaries of the current item and retrieve it completely. You already suggested this yourself, so I'd say you're on the right track.

@bbatsov
Copy link
Member

bbatsov commented Oct 24, 2016

@johnv02139 Any progress here?

@johnv02139
Copy link
Contributor Author

Sorry, distracted. I intend to work on it this week.

@bbatsov
Copy link
Member

bbatsov commented Dec 10, 2016

@johnv02139 ping :-)

@johnv02139 johnv02139 changed the title brows REPL input history browse REPL input history Dec 12, 2016
@johnv02139
Copy link
Contributor Author

I took a first pass at it, in case you (or anyone else) want to take a look. It needs more testing.

https://github.com/johnv02139/cider/tree/historycmd

@bbatsov
Copy link
Member

bbatsov commented Jan 3, 2017

Take your time and keep us posted. Just wanted to see if you were still working on this.

@expez
Copy link
Member

expez commented Jan 4, 2017

Wouldn't it be much easier (and better from a usability perspective) to just emulate the behavior of C-r and C-s of the typical shell?

@bbatsov
Copy link
Member

bbatsov commented Jan 4, 2017

Wouldn't it be much easier (and better from a usability perspective) to just emulate the behavior of C-r and C-s of the typical shell?

It's not as handy in some occasions. That's why similar extensions exist. In general it'd be nice to implement C-r and C-s, but given the fact that no one wants to work on this and I have very little time for OSS lately I don't see it happening soon. :-)

@bbatsov
Copy link
Member

bbatsov commented Jan 4, 2017

P.S. For a long time I believed we'd be moving to comint and this would come for free, that's why I just ignored all tasks to improve the REPL. Now that it's clear this is never happening we'll have to revisit such tasks.

@ckoparkar
Copy link
Contributor

ckoparkar commented Jan 4, 2017

@bbatsov I'd be willing to try working on the comint migration. The overall goal is to add all cider-repl functionality over comint right ? Is there any other discussion or ticket? And is there any reason why we're not moving to comint, or is it just because we've not started any work on it.

@bbatsov
Copy link
Member

bbatsov commented Jan 4, 2017

For a very long time this was on hold simply because no one had time to work on it. See the original issue here #709 Frankly, I'm not 100% certain that we can have all the functionality we have right now using comint (but I guess it's doable, if this works for sly). Perhaps just adding bits of comint functionality to our REPL is the way to go - it's certainly much more simple...

@bbatsov
Copy link
Member

bbatsov commented Jan 4, 2017

P.S. I was in your original message the tickets you referred to - #1099 is super important for sure. #1525 is also pretty important now, that we finally fixed the issue with some of the output ending up in *nrepl-server*.

@ckoparkar
Copy link
Contributor

Gotcha. I'll focus on finishing those then.

@expez
Copy link
Member

expez commented Jan 4, 2017

Perhaps just adding bits of comint functionality to our REPL is the way to go - it's certainly much more simple...

Isn't part of the motivation behind the comint move that it would solve some of our performance issues as well?

@bbatsov
Copy link
Member

bbatsov commented Jan 4, 2017

I don't recall some amazing output handling in comint, but I guess it'd be faster. We never tried to optimized our REPL that much. If someone is determined enough and spent a few days with the profiler there's probably a lot of room for improvement. :-)

For me the biggest motivation was removing a big chunk of the codebase and offloading it to some standard machinery, so we wouldn't have to worry about it.

@johnv02139
Copy link
Contributor Author

Regarding "C-r and C-s of the typical shell", isn't that what M-r and M-s already give you in Cider?

I think the work on the browse feature is done. The only reason I haven't made a pull request is that I need to write documentation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants