bhauman / rebel-readline

Terminal readline library for Clojure dialects
Eclipse Public License 1.0
680 stars 37 forks source link

Allow starting an external editor #129

Closed christoph-frick closed 6 years ago

christoph-frick commented 6 years ago

Wtth rlwrap one can start an external editor. E.g. I use this for Clojure besider other options:

rlwrap -m,, -M .clj

(note the -m ,, is not needed for rebel-rl; this just defined how line breaks from the editor session are squashed back into a single line of rlwrap). But the -M .clj allows me to run $EDITOR by pressing ctrl-6 or ctrl-^ for the current line.

I have no clue, if this is even possible via jline or is something that can be retrofited. So feel free to just outright close it.

bhauman commented 6 years ago

This is possible, and you are saying the result of editing ends up back in the relp buffer?

christoph-frick commented 6 years ago

Yes. E.g.

  1. You start with (map inc (range) in rlwrap
  2. Start $EDITOR with ctrl-6; this opens the editor with a temp file using the suffix given with -M.
  3. Edit the content (e.g. add line breaks: (map\ninc\n(range))
  4. Save and close $EDITOR
  5. The input line now is (map,,inc,,(range)) - the ,, are from the -m setting.

With rebel-rl already having line breaks supported, it makes not to much sense to deal with the -m ,,.

bhauman commented 6 years ago

I just tried this with rlwrap -M .clj clojure and the ctrl-6 or ctrl-^ didn't work for me. echo $EDITOR emacs

I'm assuming this doesn't launch an editor in the same terminal? But rather launches an editor in another window?

christoph-frick commented 6 years ago

I have EDITOR=vim and start my things in an xterm. With this setup the vim starts in that terminal and once write/quit, it executes that in the terminal. IIRC clojure is the non-rlwrapped script from 1.9?

bhauman commented 6 years ago

Yeah I don't see how this would be possible in the same terminal that the readline is running in without doing something crazy.

christoph-frick commented 6 years ago

You mean becasue both would be battling about stdin/out?

bhauman commented 6 years ago

Yes to make the example smaller, how would you launch a java process that then itself launches an editor in the same terminal?

On Wed, Mar 7, 2018 at 5:44 AM, Christoph Frick notifications@github.com wrote:

You mean becasue both would be battling about stdin/out?

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/bhauman/rebel-readline/issues/129#issuecomment-371098785, or mute the thread https://github.com/notifications/unsubscribe-auth/AAAKQLDE0b7ymMNkgrRoTUIVll4Ql1cnks5tb7oHgaJpZM4SY9D1 .

m2608 commented 1 year ago

It seems like this approach works in terminal REPL.

(defn edit []
  (when-let [editor (System/getenv "EDITOR")]
    (let [tempfile (java.io.File/createTempFile "repl" ".clj")
          tempname (.getPath tempfile)]
      (.deleteOnExit tempfile)
      (let [builder (java.lang.ProcessBuilder. [editor tempname])
            inherit (java.lang.ProcessBuilder$Redirect/INHERIT)]
        (.waitFor
          (.. builder 
              (redirectOutput inherit)
              (redirectError inherit)
              (redirectInput inherit)
              start))
        (load-file tempname)))))

So when you call edit function, it opens your default editor with a temporary file, and after editor process finishes, it loads code from temporary file into REPL.

The only (and significant) downside is that this code is not saved in the REPL history.

I borrowed some code from this SO question.