utop icon indicating copy to clipboard operation
utop copied to clipboard

Proposal: Shift-Enter as shortcut for ";;Enter"

Open vog opened this issue 6 years ago • 10 comments

I propose to enable users to get rid of having to type the annoying <semicolon>-<semicolon>-<enter> every time they want to execute a command in utop. Users should have the option to do a more user friendly <shift>-<enter> instead.

Right now, <shift>-<enter> does the same as <enter>. I propose do let <shift>-<enter> perform the following steps instead:

  • Jump to the end of the currently edited command
  • Add ";;"
  • Execute command

This is roughly the behaviour of the Emacs Tuareg mode, which I find very convenient. I would love to have it in Utop when starting it directly from shell as well.

Side note: I pesonally would prefer it to be exactly reverse: Use <shift>-<enter> to produce a newline, and use <enter> to produce ;; followed by newline. This would be more in line with other command line tools as well as instant messagers, where <shift>-<enter> produces a newline in the message/command and <enter> sends the message / executes the command. But I believe that consistency with OCaml-related tools like Tuareg is more important than consistency with OCaml-unrelated tools.

vog avatar Jun 11 '18 12:06 vog

There is currently a way to do it using UTop.end_and_accept_current_phrase:

val end_and_accept_current_phrase : LTerm_read_line.action
 (** Action that add the phrase terminator at the end of the current phrase
     and accepts it. For instance to avoid typing [;;], add this to your
     ~/.ocamlinit:

     {[
       #require "lambda-term";;
       LTerm_read_line.bind
         [ { control = false; meta = false; shift = false; code = Enter } ]
         [ UTop.end_and_accept_current_phrase ]
     ]}
 *)

It requires editing the ~/.ocamlinit file. Adding a default keybinding for it seems fine. However it cannot be <shift>-<enter> since the terminal sends the same event for both <enter> and <shift>-<enter>. i.e. it is not possible for an application running inside a terminal to distinguish the two events.

ghost avatar Jun 11 '18 12:06 ghost

Thanks for the hint. I just tried it, and it works, but I get the following annoying warning messages:

File ".ocamlinit", line 9, characters 4-66:
Warning 40: this record of type LTerm_key.t contains fields that are 
not visible in the current scope: control meta shift code.
They will not be selected if the type becomes unknown.
File ".ocamlinit", line 9, characters 59-64:
Warning 40: Enter was selected from type LTerm_key.code.
It is not visible in the current scope, and will not 
be selected if the type becomes unknown.

How do I get rid of these warnings?

Moreover, I tried the usual candidates (Ctrl-J, Ctrl-Enter, etc.) but they all seem to be equivalent to Enter.

Is it possible to bind to "Ctrl+O" instead? (which corresponds to "\r" rather than "\n")

vog avatar Jun 11 '18 13:06 vog

One more question:

In Emacs, the utop.el minor mode seems to work different from the normal toplevel mode of Tuareg. Namely, Shift-Enter doesn't work there.

Is it possible to enable Shift-Enter in utop.el?

vog avatar Jun 11 '18 13:06 vog

That seems fine. However I haven't touched this code in so long that I don't remember what would need to be changed. Patch welcome though :)

ghost avatar Jun 11 '18 14:06 ghost

Hi! I'm not an expert at Emacs Lisp, but from reading through the code, it seems that this line: https://github.com/diml/utop/blob/master/src/top/utop.el#L144 defines the shortcut C-j for exactly what @vog needs;

Adding this to my .emacs file seems to do the trick:

(defun my-utop-mode-hook ()
  (define-key utop-mode-map [S-return] 'utop-eval-input-auto-end))
(add-hook 'utop-mode-hook 'my-utop-mode-hook)

A patch adding (define-key map [S-return] 'utop-eval-input-auto-end) after line 144 should work ?

alarsyo avatar Jul 20 '18 22:07 alarsyo

@alarsyo your diagnosis is correct, but I'm curious why you don't like C-j? This is a standard keyboard short cut for this stuff in Emacs. I kind of think that binding S-return should be left up to user customization like most things in Emacs. In other repl like modes, S-return doesn't seem to do anything special either btw. Do you have an example of this convention somewhere?

rgrinberg avatar Jul 22 '18 21:07 rgrinberg

I don't really need this bound to S-return myself, I was just reading through the issues and thought I could provide a possible solution for this one ; it looks like the author of this issue just wants it to behave similarly to Tuareg's toplevel, where S-return does work

alarsyo avatar Jul 22 '18 22:07 alarsyo

I see. Okay, I think making it consistent with tuareg's (actually caml mode's) toplevel is a good enough reason to add the binding.

rgrinberg avatar Jul 22 '18 22:07 rgrinberg

I tried the setup from @alarsyo and it worked perfectly for me (Emacs 26.1 on Debian 9). I understand that "C-j is standard keyboard short cut for this stuff in Emacs". But I appreciate to get S-return as with tuareg mode. Thanks.

RogerTarani avatar Sep 25 '18 17:09 RogerTarani

I also support changing the default to @.vog's personal preference, where Enter submits and Shift+Enter adds a newline.

twome avatar Sep 15 '23 17:09 twome