syl20bnr / spacemacs

A community-driven Emacs distribution - The best editor is neither Emacs nor Vim, it's Emacs *and* Vim!
http://spacemacs.org
GNU General Public License v3.0
23.64k stars 4.89k forks source link

Saving history for sub-shells #4039

Closed rahulmutt closed 8 years ago

rahulmutt commented 8 years ago

When working with eshell, if I press Up, I'll get the last thing I typed. If I use an interactive program like the Clojure REPL, I'm unable to get the history by pressing Up even though it's available in any normal terminal emulator. Reusing the last expressing is such a frequent operation that having this feature is a huge help.

bmag commented 8 years ago

Try C- and C-, these are the usual key bindings in shells in Emacs. Most shell modes use the commands comint-previous-input, comint-next-input, comint-previous-matching-input-from-input and comint-next-matching-input-from-input. These are usually bound to M-p, M-n, C-c M-r and C-c M-s, unless some other package took over these keys (for example evil-mc can do this). Personally I recommend using comint-previous-matching-input-from-input and comint-next-matching-input-from-input, after re-binding them to better keys.

Note that some shell modes use other commands, so for them you'll have to find the commands yourself.

If you want to also save the history from previous sessions, and not only the current session, that can also be done but requires more effort (I read about it not so long ago, but didn't try it).

rahulmutt commented 8 years ago

Those commands didn't work for the purpose I wanted. But I realized I could implement a custom solution for the clojure REPL by doing a regexp search for the REPL prompt and copying what comes after. If anyone has a solution for retrieving the previous input from any REPL-like program like lein repl, ghci, sbt, then please let me know.

bmag commented 8 years ago

@rahulmutt I was surprised to read what you wrote, so I checked the bindings for clojure REPL. I found these commands:

These work for both normal state and hybrid state. Don't you have them?

P.S. I'm not sure what's the difference between "forward" and "next", they seem to do the same thing.

rahulmutt commented 8 years ago

I was getting errors with the cider repl because of version inconsistencies so I've been running 'lein repl' in eshell, but I fixed all that this morning and everything is working like a charm. Thanks!

The solution you gave works for Clojure. What about Haskell? Scala? My point was that one shouldn't have to rely on a specific package for every REPL environment for every language if you're just simply running through eshell. If I was using gnome-terminal, I'd be able to access the previous input inside of 'lein repl' by pressing 'Up', so having that in eshell would be nice as well since it is a full-blown terminal emulator on its own.

TheBB commented 8 years ago

Eshell is a shell, not a terminal emulator (that would be term). I really don't recommend running REPLs inside eshell or term. They're good but not that good. I have the impression that most REPL modes are built (as they should be) on comint, in which Spacemacs (in the develop branch) supports input browsing with C-j and C-k. These only work within the current session. Unfortunately comint doesn't have generic commands for fetching previous inputs from the underlying REPL, because these invaribly work differently from each other.

Note: Up-arrow works fine for me when running REPLs in term.

Note 2: Cider REPL is not a comint-mode for whatever reason.

bmag commented 8 years ago

I wanted to expand on @TheBB's answer, so I searched for more details on comint-mode, but apparently it's not documented very much. Emacs being emacs, at least the code is documented quite well (see C-h f comint-mode for example).

Cider REPL doesn't use comint-mode only because of historic reasons, and because nobody has fixed that yet. Ref: https://github.com/clojure-emacs/cider/issues/709