dbuenzli / down

An OCaml toplevel (REPL) upgrade

Home Page:http://erratique.ch/software/down

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Support `C-arrows`

cfcs opened this issue · comments

Support for control-left; control-right; control-up; control-down would be neat too.

Please be more specific. What are these supposed to do ?

Also as far as I'm concerned my terminal doesn't report those so I'm not sure exactly how to detect them.

Ah in fact I manage to get something for C-left and C-right but not for C-up and C-down.

Bound C-{left,right} to {prev,next}-word. Also eventually got something for C-{up,down} by tweaking my term a bit but there's nothing obvious to bind to (emacs jumps from empty lines to empty lines but that's kind of a limited use in the context of ocaml).

Thanks! That works for me, the left/right are the ones I was missing the most.

And yeah, I guess you are right that ctrl-up/down is not necessary in this setting.

FWIW I found this old reference of Tuareg key bindings: http://www.ocamlpro.com/files/tuareg-mode.pdf
I'm not sure how feasible each would be to implement (and I guess there's also no strict reason to implement exactly their key bindings), but I think these seem like interesting features to have in a REPL:

  • C-c C-t caml-types-show-type
  • C-c ' tuareg-interactive-next-error-source - kind of like setting the mark to where the error is pointed out by the interpreter. By the way, is it intentional that the mark does not survive across executions? It seems annoying that you need to execute the buffer (and thus lose your mark) to test your changes.

Err speaking of keybindings, [Delete] seems to be a no-op too, instead of delete character to the right of the cursor?

  • By the way, is it intentional that the mark does not survive across executions? It seems annoying
    that you need to execute the buffer (and thus lose your mark) to test your changes.

I don't understand what you mean, once you evaluate a phrase you get a new empty line to evaluate the next. There's no point in having a mark on that line as it is going to be invalid.

Err speaking of keybindings, [Delete] seems to be a no-op too, instead of delete character to the right of the cursor?

Yeah I no longer have such a key on my keyboard and I'm not exactly sure which escape sequence corresponds to it.

I had some wrong code to recognize delete, I corrected it and bound delete-next-char to it in c78a8bd.

Thank you, Delete works for me now!

By the way, is it intentional that the mark does not survive across executions? It seems annoying
that you need to execute the buffer (and thus lose your mark) to test your changes.

I don't understand what you mean, once you evaluate a phrase you get a new empty line to evaluate the next. There's no point in having a mark on that line as it is going to be invalid.

I often find myself running slightly modified versions of expressions, where the editing distance between the non-working line and the working line will be small - navigating to the point of the error in a multi-line REPL expression takes more effort than correcting the ; to a :; or " to '. Admittedly more so at the moment than usual since my shift key has gone on strike. :-)

Even in cases where an expression does not result in an error, it would be useful for trying various values for constants or inserting different test cases. In an editor this is easy: Switch to a terminal, recompile && run the program, switch back, cursor will be where it was before. I still have that option, so if you're not convinced that's fine, I just thought I'd bring it up since the awkwardness of editing multi-line expressions often annoys me in utop.

I often find myself running slightly modified versions of expressions, where the editing distance between the non-working line and the working line will be small - navigating to the point of the error in a multi-line REPL expression takes more effort than correcting the ; to a :; or " to '. Admittedly more so at the moment than usual since my shift key has gone on strike. :-)

Having a goto error would definitively be nice. But down is currently severly limited by the way it works which is to rely entirely on the current Toploop API (for example I have no control over error rendering or even the ability to know that one actually happened).

I hope in the future the latter can be improved, for example simply having a reference that indicates me what happened with the previous evaluation could indicate me the error position and would be useful for other things aswell (e.g. for recording only suceeding phrases in session recording).

Regarding keeping the mark I could try to see if I can simply keep it until it potentially invalidates. Which means if your next action is to actually go the previous history item you'd still get it exactly were it was before the next evaluation (if you move up further it could simply be non-sensical but maybe that's not too harmful).

That makes complete sense, and yes, it seems like toploop could expose some more control to the user.
Thanks again for implementing the key bindings.

From skimming the mli it looks like for example the ref containing the error-printing formatter callback is not exposed to consumers. Had a bit of fun with this, but it doesn't seem like quite the right places to hook :-)

$ ocaml -I +compiler-libs -I +typing
# #use "down.top";;
(* catch lexing errors, and some other stuff: *)
let a = !Toploop.parse_toplevel_phrase in
Toploop.parse_toplevel_phrase := (fun lexbuf -> try old lexbuf with
  | End_of_file -> exit 0
  | x  -> Printf.printf "lexing didn't go well %s\n%!" (Printexc.to_string x) ; Ptop_def []
);;

(* catch returned exceptions (and some other stuff): *)
let b : Outcometree.out_value option ref = None in
Toploop.print_out_value := (fun ppf ov -> b:=Some ov;
  Printf.printf "res: %s\n%!"
   (match ov with
   | Oval_constr (Oide_ident _, _) -> "exc..ish"
   | _ -> "ok"); pov ppf ov);;

The problem is that if you start evaluating the phrases youreslf you quickly run into the expunge process problem (see this issue point 1.).

I'm glad I managed to get the session support without having to go down that route.