-
Notifications
You must be signed in to change notification settings - Fork 74
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
More functionnalities for repl #951
base: master
Are you sure you want to change the base?
Conversation
This is the cleaner version of pull request #943. |
src/repl.ml
Outdated
if is_repl_ready code then | ||
(* newline is for nicer look in REPL *) | ||
"\n" ^ trimmed_code | ||
else Printf.sprintf "\n%s\n;;" trimmed_code |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This formatting sometimes looks worse like in this example with a single expression:
#
x
;;
- : int = 1
Maybe it's worth checking if the code is a single line first? If it is, then there's no need to add any extra formatting.
I would prefer the following in simple cases:
# x ;;
- : int = 1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done!
I have done some tests and it seems to work well with the new version of the function.
I am not sure about the List.mem
efficiency, what do you think about this solution?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new behavior is great.
String.mem
is fine but I'm not sure what the difference is from String.contains
that we use in other parts of the extension.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few changes need to be made for Windows and the official OCaml REPL.
I haven't had a chance to try macOS or utop yet.
I made several tests to see if the jump is working but I am sure some cases unknown to me. |
@mnxn is this good to merge? |
I will have a look at this today |
It looked good to me when I tried it. Ready to merge unless @ulugbekna finds something. |
Add the functionnality to auto select the expression instead of the line if the selection is empty
Now handles single lines and fixe the `is_repl_ready` check
In previous versions, the cursor position was sent without worrying about whether it was an expression. Now we send the position so that the cursor is in the previous expression.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs a changelog entry.
Didn't look too closely at the 180-line function, but functionality added by the PR seems to work well
@@ -165,7 +183,188 @@ module Command = struct | |||
in | |||
Extension_commands.register ~id:Extension_consts.Commands.open_repl handler | |||
|
|||
let _evaluate_selection = | |||
let _evaluate_expression = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a little skeptical about having a 180-line function
I think this can me squashed and merged, but jumping to next expression implementation needs to be made on the ocamllsp side as a new custom request so that we avoid hacks that we have now. Also, one should be careful using |
I don't have much time this week. Nevertheless I will look at and improve the code in the coming weeks if necessary. Because there are some behaviours to be fixed at the ocaml-lsp level. |
Vscode.TextLine.text line | ||
let get_selected_code text_editor = | ||
let selection = TextEditor.selection text_editor in | ||
let document = TextEditor.document text_editor in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you obtain document
right away but only use it in one branch of the conditional?
let is_repl_ready s = String.is_suffix s ~suffix:";;" in | ||
let trimmed_code = String.strip code in | ||
if is_repl_ready trimmed_code then | ||
if String.mem trimmed_code '\n' then |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As far as I can tell String.mem trimmed_code '\n'
is always evaluated. Therefore it should be assigned a binding and moved before the conditionals.
| `ocaml.evaluate-file` | Evaluate Selection | `Shift+Alt+Enter` | | ||
|
||
Note: `ocaml.evaluate-expression` was previously named | ||
`ocaml.evaluate-selection`. You can also disabe the new cursor jumps after this |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why don't we preserve ocaml.evaluate-selection
? I don't see anything wrong with having both commands.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the new command evaluates the selection if there's one; otherwise, it evaluates a (module-level) let or module binding depending which comes first
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understood. I just don't see why we should remove a command with a clear name and semantics and replace it with a command that has neither of those things. Seems like we're just irritating users who are used to the old command this way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, but then I would show a deprecation message saying to use the new command because
- The new command has almost the same semantics - select and evaluate (no selection resulted in evaluating the whole line but I'm not sure that's very useful and the new command does the same thing if it's a single-line let binding)
- There's then contention for the shortcut: keep the old and miss out on a better command or replace and still irritate
Before merging this, I think we need to get on the same page of what good REPL functionality looks like. I have no interest in copying tuareg and its limitations. We can do a lot better if we think about things a bit more. |
Do you have precise limitations you'd like gone before merging? Things that are not addressed in this PR but can be done in other, IMO:
|
First of all, as a general comment, there's just too many knobs, settings, commands that all make the experience way too complicated. I've already went through this stuff with tuareg mode. In the end, their toplevel integration is hardly usable. 99% of the time when I use the toplevel, I do the following:
We should focus on this core feature first before we worry about directives, selecting repl instances. Finally, we should absolutely avoid any code that tries to parse OCaml. I see this PR is adding quite a bit of that and it's really wasted effort. Here's a simple idea for how to make the toplevel more useful.
Let's forget about all the other stuff for now. |
~position:correct_position | ||
in | ||
match range with | ||
| None -> () |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When can this request return None?
A few more thoughts:
|
This pr is intended to be a part of the work of @ulugbekna in #677.
It would be interesting to have an evaluation system similar to Tuareg in Emacs. For this it is not only necessary to evaluate the user's selection but also when there is no selection the expression corresponding to the cursor position.
The objectives :