Skip to content
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

option to restore previous TAB behavior #196

Merged
merged 9 commits into from
May 6, 2024

Conversation

tpapp
Copy link
Collaborator

@tpapp tpapp commented Jun 20, 2023

Fixes #193.

This is preliminary, comments are welcome, even along the lines of "Tamás your elisp code is so horrible that I had to wash my eyes with soap after reading it, here is how you do it nicer".

Try it with

(define-key julia-mode-map (kbd "TAB") 'julia-latexsub-or-indent)

Maybe we can add an option for it.

Possible improvements:

  • use something else than completing-read? is there a nicer popup version?
  • annotate with the actual replacement in completing-read
  • option for greedy replacement for a full match (eg \bar will replace, no popup)
  • option to pick the first replacement, whatever it is

Have to do before merging this:

  • some unit tests
  • code review from someone
  • some testing by interested users

@tpapp tpapp marked this pull request as draft June 20, 2023 12:53
tpapp added 4 commits June 20, 2023 15:35
Simplify code by saving the `\` and looking up the match from the
primary hash table.
@torfjelde
Copy link

I can be one of those "interested users":) Currently trying it out, and it seems to be working nicely :) Thanks! @tpapp !

Copy link
Contributor

@dhanak dhanak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried this briefly and apart from the two comments below, it seems to work as expected. Nice work, and thanks for the effort!

julia-mode.el Outdated
(let ((partial (buffer-substring-no-properties beg (point))))
(message "partial %s" partial)
(when-let (replacements (gethash partial julia-mode--latexsubs-partials))
(message "replacements %s" (prin1 replacements))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is cool for debugging purposes, but it bloats the minibuffer unnecessarily, even if temporarily.

This and the previous message line should probably be deleted before merging.

julia-mode.el Outdated
(message "replacements %s" (prin1 replacements))
(let* ((complete-match (member partial replacements))
(replacement (cond ((and complete-match julia-latexsub-greedy) partial)
((cdr replacements) (gethash (completing-read "LaTeX completions: " replacements) julia-mode-latexsubs))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is an error.

When the completion is not full, e.g., \cir, I am offered a list of valid completions. When I press enter on one of them, I get a progn: Wrong type argument: char-or-string-p, nil error.

After some inspection, it seems that this is because this line here should return the raw latex control sequence, not the already substituted value. The substitution is performed in the julia-latexsub-or-indent function.

If I change this line to

((cdr replacements) (completing-read "LaTeX completions: " replacements))

then it works as expected.

@dhanak
Copy link
Contributor

dhanak commented Sep 26, 2023

Any chance of getting this merged soon?

@tpapp
Copy link
Collaborator Author

tpapp commented Sep 26, 2023

It still needs tests. I will try to do them soon and merge your suggestions too. I appreciate the ping.

@tpapp tpapp marked this pull request as ready for review April 10, 2024 18:00
@tpapp
Copy link
Collaborator Author

tpapp commented Apr 10, 2024

I incorporated the suggestions by @dhanak and added some basic tests. While one can always prettify this further, it is functional so I would prefer to merge and then leave bells & whistles for future work.

Further testing is welcome, but a code review would be best.

@tpapp
Copy link
Collaborator Author

tpapp commented May 3, 2024

asking the usual suspects for review before merging, @giordano, @non-Jedi, @FelipeLema, @ajhalme

@tpapp tpapp merged commit d360ad5 into JuliaEditorSupport:master May 6, 2024
7 of 10 checks passed
@tpapp tpapp deleted the tp/repl-style-completion branch May 6, 2024 12:05

eg in your `julia-mode-hook'."
(interactive "*i")
(if-let (replacement (julia-mode--latexsub-before-point))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for not reviewing before you merged. I've been meaning to dig into this for months. Could you please comment on why this entire if-let couldn't be replaced with something like:

(let ((completion-at-point-functions '(julia-mode-latexsubs-completion-at-point-before)))
  (unless (completion-at-point)
    (julia-indent-line)))

I'm not immediately seeing why this wouldn't give both better features and integration and significantly more implementation simplicity.

I had meant to do a mock-up PR of this implementation to let others play with it and compare with the one in this PR, but haven't had the mental energy to do so, and I'm not sure when I will, so I'm just posting the idea in case there's an obvious problem I'm missing.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this option is missing this from the OP

option for greedy replacement for a full match (eg \bar will replace, no popup)

but I think you could handle just that case with significantly less complexity than this PR.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I do not understand. julia-latexsub-greedy, which is set to t by default, does exactly this (eg \bar just completes).

Regarding complexity: I agree that in an ideal world, this PR would not have been necessary. But practically, the generic completion mechanisms of Emacs have proven to be baroque and full of corner cases and/or implementation bugs like #204 (thanks for chasing many of those down!). I think that for now there is value in maintaining our own version which Just Works ™️.

(progn
(delete-backward-char (- (point) (car replacement)))
(insert (gethash (cdr replacement) julia-mode-latexsubs)))
(julia-indent-line)))
Copy link
Contributor

@non-Jedi non-Jedi May 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait, if this ultimately calls julia-indent-line, I don't think it solves the problem from #193 at all. The issue in #193 was being able to have TAB work for both latex substitution as well as inserting TABs (see example in this comment). I think this might do what ronisbr was looking for if it called indent-for-tab-command instead of julia-indent-line.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I missed this comment, just found it among messages. This PR solves the problem for me, if anyone still has problems with it please open another issue.

Specifically, it only calls julia-indent-line when it could not make a substitution. So, TAB tries to subtitute, and indents if it can't. I find that behavior useful.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So basically it gives you the reverse of the behavior of indent-for-tab-command when tab-always-indent is set to 'complete:

  • With indent-for-tab-command with (setq tab-always-indent 'complete): indent then complete
  • With this function: complete (but only latexsubs) then indent

If we change julia-indent-line in this function to indent-for-tab-command, the user can change between TAB inserting tabs and TAB indenting the line by customizing the value of tab-always-indent. I'll create a PR for your review when I have a few minutes.

If you haven't seen it yet, could you please comment on my other review comment when you get a chance?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Consider creating an option to mimic previous tab behavior
5 participants