UnicodeMath icon indicating copy to clipboard operation
UnicodeMath copied to clipboard

Add instant and prefix-based completion (#36)

Open lephe opened this issue 2 years ago • 1 comments

This PR implements a rough version of the features proposed in the linked issue.

  • The prefix feature is supported by adding a symbol_by_unique_prefix() function in mathsymbols.py. The function only searches for 2 matching prefixes, and is used both in can_replace() and the replacement function.
  • The instant conversion feature is supported by using a text change listener. Apparently that listener is designed for replaying changes (and is quite recent), so I might be hacking a bit. But the view listener only gives on_modified() and that doesn't allow me to disable conversion during undos; the commented view-listener version would just run instantly after undoing a conversion and redo it again.

Not sure if this is fine to merge yet (I'm a bit worried about the text change listener), but at least it's out there. :smile:

lephe avatar Oct 09 '22 22:10 lephe

I realize the way I implemented it is a bit too greedy. When a name is complete (eg \subset) I substitute it automatically, without allowing longer names to be typed (eg. \subseteq). In this situation I should wait for another character.

Note for performance: the original feature I saw enters a special mode when typing a backslash; the characters that follow are underlined and the substitution is only active during that time. If you click away then it stops and the backslash will no longer be substituted without an explicit command. This might be a better approach for the greedy completer.

lephe avatar Oct 10 '22 07:10 lephe

Coming back to this now, I finally managed to make it behave as I want it to. It's starting to be quite a big change though. Since I made replacement logic more complex, I factored out can_convert() and replacement() which appeared to do the same work twice, into a single function.

In the end I think the most natural setting is to have "convert_instantly": true to get all the logic I just implemented, "accept_prefixes": false because it can be confusing that \forall gives you ∀ll, and "convert_on_space": false for extra saved keystrokes.

Just to be clear, instant conversion kicks in when:

  1. You type \name and, there is a symbol name and none other that starts with name, in which case it converts \name;
  2. You type \nameX, there is a symbol name, there are other symbols that starts with name (otherwise it would've been converted earlier) but none that starts with \nameX, in which case it converts \name and keeps the X.

The whole point is to get as close as possible to some "LaTeX effect" where there is zero control keystroke. If I close my eyes and type \delta \subseteq \pi(f), I will get δ ⊆ π(f) (δ triggered by case 1, ⊆ by case 2 with a space as X, π by case 2 with a parenthesis as X).

The prefix idea is so that I can close my eyes, type \all (\a \b: Type) and get ∀ (α β: Type), however it doesn't end up working super well. This is because \a and \b are not unambiguous. In addition, typing \forall with both prefixes and instant completion yields ∀ll, which is counter-intuitive. I will handle that locally by having aliases like a → alpha and b → beta. Prefix conversion is probably worth having outside of instant mode though, so I left it in.

This isn't finished (still need to tackle the sorting thing), but any feedback on the current code is welcome.

lephe avatar Nov 28 '22 22:11 lephe

For the performance problem, I wanted to use an ordered map so we could have a single data structure to replace the dictionary, but I couldn't easily find one in the standard library (?!). I elected to keep both the dictionary and the sorted version, which I wrapped along with the inverse in a utility class. I'm open to suggestions on how to handle this.

I don't have any more planned changes on this branch for now, so another review would be welcome. I noticed an exception on "Convert Back", but it seems to occur on the current master as well, so I guess that's orthogonal.

lephe avatar Dec 03 '22 16:12 lephe

All valid points, thanks! I'll remember to squash everything when we're done.

lephe avatar Dec 08 '22 16:12 lephe

Thanks for the review. Let me know when I can squash the branch. Also, I'm thinking the feature would be rather obscure without some proper documentation. Would a section in the README file be fine with you?

lephe avatar Dec 14 '22 18:12 lephe

Let me know when I can squash the branch

Looks good to me to squash

Would a section in the README file be fine with you?

It'll be nice to have readme section about new feature

mvoidex avatar Dec 16 '22 20:12 mvoidex

Oops, not sure how and when this flew off my radar. Sorry! I added the README section and squashed the branch (no other changes today). I've been using this mode for a while now, had to disable some of the conversions (such as \x → ×) that triggered too often, but really happy with it otherwise. Thanks for bearing with me :)

lephe avatar Feb 24 '23 15:02 lephe

Thanks, merged!

mvoidex avatar Mar 25 '23 14:03 mvoidex