mawww / kakoune

mawww's experiment for a better code editor
http://kakoune.org
The Unlicense
9.93k stars 714 forks source link

Faces for fancy underline variations #4138

Closed EpocSquadron closed 3 years ago

EpocSquadron commented 3 years ago

Some terminals provide escape sequences, advertised in their terminfo files, which enable underline effects such as a separate colors for text and underline, wavy/curly underline, dotted underline and a few others. Neovim already has support for these, allowing for example red wavy underline with lint errors. At least two terminal emulators implement this, perhaps more. Here is the documentation on wezterm's implementation for quick example: https://wezfurlong.org/wezterm/faq.html#how-do-i-enable-undercurl-curly-underlines

I believe we recently switched away from ncurses to custom terminfo parsing, so enabling support for these features should be relatively straightforward. The biggest question is how kakoune's concept of faces, specifically the syntax, applies, and how fallback is handled.

Delapouite commented 3 years ago

Yes 7 years later, we should now have the right conditions to make it happen: https://github.com/mawww/kakoune/issues/56

Screwtapello commented 3 years ago

I believe we recently switched away from ncurses to custom terminfo parsing

The builtin-terminal-ui branch is not yet merged to master, and it does not use ncurses or terminfo. Instead, it hard-codes escape sequences, which means the same escape sequences would need to be supported in many terminals to make it worthwhile.

Using the printf demo from the wezterm docs and a bunch of terminals I had handy:

gnome-terminal

image

Everything works but dotted underlines.

kitty

image

Everything works but dotted underlines.

QTerminal/Konsole

image

Underlining works, but surprisingly with other formatting

st

image

No formatting at all

xterm

image

The formatting is "very dim mode"

Recommendation

If somebody does teach Kakoune about underline formatting and colour, we probably shouldn't use it anywhere by default, and just let people add it to their own custom colour schemes if they happen to have a terminal that supports it.

EpocSquadron commented 3 years ago

I didn't realize that builtin-terminal-ui wasn't merged. Thanks for doing the research as to how those escapes apply in various terminals. I kind of expected that the various supported underlines would be advertised with their correct escapes in the terminfo file, though I admit I don't really know how terminfo works. It would be nice if kakoune could look for them and only enable the ones supported by the terminal you're running and provide a command to list supported faces. Unsupported faces would maybe be passthrough, perhaps with a log to *debug*. That way you can use a community provided colorscheme that uses them without breakage.

Screwtapello commented 3 years ago

The terminfo model is that terminals set $TERM to a short terminal name, and applications can look up that name in/usr/share/terminfo to find a description of the kinds of escape sequences the terminal expects to send and receive. The descriptions are usually things like "the F1 key sends this string" or "to set the foreground color, send that string" or "this terminal supports N colours".

For basic things, the terminfo database works pretty well, but there's a number of places it falls down:

As a result, terminfo generally isn't a reliable guide to what features the current terminal supports.

Most new terminal sequences are designed so that older terminals will ignore them. That way, you can send a fallback sequence, then send the real sequence, and hope that if the terminal doesn't understand the real sequence it will use the fallback formatting instead. Unfortunately, as demonstrated above, some existing terminals don't ignore this custom-underline syntax, so Kakoune shouldn't use fancy underlines by default until terminals that support them are widely deployed.

(Using them in a community-provided colour scheme, or even in a non-default standard colorscheme, should be fine)

raiguard commented 3 years ago

Bump. The biggest thing I miss from vscode is colored squigglies. Regular underlines are serviceable, but having actual colored squigglies will make errors a lot easier to digest.

Now that builtin-terminal-ui is officially released, now seems like a good time to take a look.

mawww commented 3 years ago

I am hesitating on what the best approach is here, we can expose the whole support for RGB colors and each underline style, but that seems a bit overkill for a text editor purpose and requires extending the face definition syntax, or we can get 80% of the value with just two additional attributes: warning/error that would render as curvy yellow/red underlines.

raiguard commented 3 years ago

Honestly, even though it's more work, I think full RGB would be best. The red in my theme may be entirely different from the red in your theme. Or a plugin may add different kinds of diagnostics, which they would want to be different colors (e.g. hints, spelling errors, grammatical errors). I'd personally be happy with just solid and curly underlines, but I'm sure someone else would end up requesting the others at some point anyway.

A way to do the syntax extension might be to add another comma, then the following text specifies the underline style and color. E.g. face global DiagnosticError default,default,cff0000. c in this case meaning curly, then the rest of it is the color.

sclu1034 commented 3 years ago

Wouldn't hardcoded colours create issues with theming?

I guess if 80% is the only goal, hardcoding to Xresources colours can be enough. But it would still be a big step away from the current situation, where everything is themeable.

And I don't think full styling options would be overkill. Spellcheck and grammar-check tools often use blue or purple underline for something like "better wording" suggestions, where the current text isn't wrong and a warning/error wouldn't be warranted.

And with LSP integration, there would be multiple opportunities for underline styling. For one, the protocol includes four different levels of diagnostics (Error, Warning, Info and Hint) and separate underline colours + styles would be a good way to visualize even the multi-line diagnostics without interrupting syntax highlighting. Additionally, with Semantic Highlighting, the LSP server can assign various modifiers to highlighted tokens (e.g. read-only, public/private or deprecated), which could also be visualized by different underline colours and styles.

My ad-hoc idea for the extension of the face syntax:

krobelus commented 3 years ago

Maybe we should allow to pass raw escape sequences in a facespec

face global Error '\e[30;31m'

though that probably comes with its own share of problems..

raiguard commented 3 years ago

image

Beautiful! Thank you mawww! :heart:

In my colorscheme, I ended up adding a command (one-enable-curly-underlines) to enable them, since not every terminal supports the feature.