swarm-game / swarm

Resource gathering + programming game
Other
837 stars 52 forks source link

Multi-line REPL input #134

Open byorgey opened 3 years ago

byorgey commented 3 years ago

It would be nice if somehow you could enter expressions at the REPL using multiple lines. In theory, this should be easy, since the input form itself does not care whether it contains newline characters. The difficulty is how we distinguish between entering a newline and executing the contents of the REPL.

Originally, I thought to allow Enter at the REPL to type normal newlines, and use a special keystroke like Shift-Enter or Ctrl-Enter to execute it (like what Jupyter notebook does). However, Shift-Enter and Ctrl-Enter are problematic in the terminal; in most terminals they just send a regular Enter key event. This makes no sense whatsoever, but that's the way things are. =( One solution is to use a different special key (Ctrl-J? Ctrl-M?) for entering a newline; though that seems dangerous because it would be too easy to forget and hit Enter when you meant to add a new line. Or probably better would be to come up with some other special key to execute (accidentally entering a newline when you meant to execute is no big deal). It just might be annoying to always have to hit some other key combination every time you want to execute. Maybe it could be an opt-in feature.

Very open to other solutions as well!

jrvieira commented 3 years ago

Some REPLS assume newlines when current input does not validate in some way.

A simple solution to swarm would be to assume a newline iff there are any unmatched brackets or parens. Typing '{\' is very intuitive and we'd have the added advantage of quickly signaling "unmatched whatever" errors to the user while providing optimal UX, letting the user quickly solve the problem instead of forcing a retype.

To consider:

byorgey commented 3 years ago

This is the way the Python REPL works so I was curious what Python does re: multiline input when browsing the command history. The answer is that it just browses through all previous input line by line, regardless of whether the lines were entered by themselves or together with other lines. This seems like a reasonably simple solution.

jrvieira commented 3 years ago

It would be important to have a way of clearing all input while in the middle of writing a multiline command. I think having CTRL-c doing this would be the expected behaviour and it plays well with #44 since you're not supposed to write while base is actively running a computation (right?). This way, CTRL-c either cancels execution or clears all current input.

byorgey commented 3 years ago

Right, you can't enter anything while base is actively running a computation. (If someone asked for the ability to start typing something even while the base is still running a computation, I would say no, just build a robot to do the computation for you instead.)

Anrock commented 3 years ago

AFAIK some repl used \n\n to execute things. So single enter starts a new line and if you press enter on a new line instead of typing more code REPL executes whatever you already typed.

byorgey commented 2 years ago

This would still be cool, though I think it's pretty low priority since one can easily just put multi-line definitions in a file and then run it.

byorgey commented 2 years ago

Reading over this issue again, I think if we do this at all, "enter creates a new line; hitting enter twice in a row executes" (as in Anrock's comment) is probably the best solution. But with nice editor support there doesn't seem to be that much impetus for allowing multi-line REPL input.

TristanCacqueray commented 2 years ago

Note that bash features C-x C-e to edit multi-line command in $EDITOR.

byorgey commented 2 years ago

That seems like a nice idea: some special key shortcut to either open an external editor, or just to open an editor in the REPL window (brick has built-in support for an editor widget).

byorgey commented 2 years ago

Added a Language Server tag --- this doesn't directly have to do with LSP, but more generally it relates to external editor support.

byorgey commented 1 year ago

Coming back around to review old issues. @xsebek , @kostmo , @TristanCacqueray , how often have you wanted multi-line REPL input in Swarm? Personally, I have been playing a lot in classic mode recently and I have never wanted it. I am tempted to just close this as won't fix.

kostmo commented 1 year ago

Personally I find the multi-line input experience in both Python and Haskell REPLs to be infuriating. So I probably wouldn't use it much in Swarm.

xsebek commented 1 year ago

I want it a lot. 🙂

In Swarm I often run into the edge of screen, so being able to extend it to few lines would improve the experience significantly.

My experience with REPL in ZSH is much more positive, so that could play a role.

byorgey commented 1 year ago

OK, well, I think @xsebek just volunteered to implement this issue. :laughing:

TristanCacqueray commented 1 year ago

I agree with @kostmo, so I would vote won't fix, but it can be useful too.

xsebek commented 2 months ago

A neat feature would be to automatically start multiline on unclosed def. ZSH does it for for and if:

> for i in *; do                                                                                         
for>  echo $i
for> done  

This would allow easily writing longer functions in REPL. Not sure if that is easy to tell from parser failure though.

xsebek commented 2 months ago

Note that bash features C-x C-e to edit multi-line command in $EDITOR.

This could be a complementary feature - you could write in your editor and then quickly fix typos in brick multiline editor in REPL. Most importantly we need to be able to show multiline REPL input.

xsebek commented 2 months ago

Hah, I just remebered I tried to set up REPL through the Web API:

So with a little modification, you can already send multiline commands to the REPL written in your EDITOR:

#!/usr/bin/env bash

PORT="5357"
HOST="localhost"
tmpfile="$(mktemp -d)/run.sw"
EDITOR="${EDITOR:-vim}"

$EDITOR $tmpfile

curl --header "Content-Type: text/plain;charset=utf-8" --data "$(cat $tmpfile)" $HOST:$PORT/code/run

But without further support it is a bit broken - previous command brings up just first line, so we currently have the annoying experience @kostmo described.