helix icon indicating copy to clipboard operation
helix copied to clipboard

Configurable rendering of invisible characters like space, tab, and line feed

Open Omnikar opened this issue 3 years ago • 17 comments

Some config option for whether to display invisible characters like rendering spaces as dots, tabs as arrows, etc.

The config option would have 3 possible values:

  • none: Don't render invisible characters.
  • selection: Render invisible characters that fall into a selection.
  • all: Render all invisible characters.

I presume this would also add a field to themes?

Omnikar avatar Nov 10 '21 23:11 Omnikar

Usually the most annoying invisible characters are those at the end of the line. In my opinion an option to highlight only these is very useful.

Rational-Curiosity avatar Nov 15 '21 23:11 Rational-Curiosity

Perhaps the config option could allow things like this:

Render all whitespace

[editor]
render-whitespace = "all"

Render all newlines

[editor]
render-whitespace = { newline = "all" }
[editor.render-whitespace]
newline = "all"

Render all newlines, render other whitespace when selected

[editor]
render-whitespace = { default = "selection", newline = "all" }
[editor.render-whitespace]
default = "selection"
newline = "all"

Omnikar avatar Nov 16 '21 02:11 Omnikar

We definitely could take some user experience from vscode, last time I used it setting this part they have some sort of presets, we could do that with what you showed.

[editor]
render-whitespace = "all"

And when customization is needed, we can can always fall back to

[editor.render-whitespace]
default = "selection"
newline = "all"

Thinking aloud, should we also let the users choose the characters of their choice like what you can do in vim?

Should we also allow theming this one? Since I sometimes see different foreground and background color for these texts, like in doom emacs?

pickfire avatar Nov 19 '21 14:11 pickfire

Should we also allow theming this one? Since I sometimes see different foreground and background color for these texts, like in doom emacs?

Yeah, this definitely should be a theme thing.

Omnikar avatar Nov 19 '21 16:11 Omnikar

I would also like the option to only render trailing whitespace, i.e. spaces at the end of a line with no other characters following them.

mtoohey31 avatar Apr 20 '22 02:04 mtoohey31

In addition to trailing whitespace, VSCode has a useful option to show boundary whitespace, e.g. double space. Ideally, the option would also allow to show both trailing and boundary whitespace beside just one or the other.

vwkd avatar Dec 09 '22 10:12 vwkd

Usually the most annoying invisible characters are those at the end of the line. In my opinion an option to highlight only these is very useful.

I have found "renderWhitespace": "boundary" from VSCode to be exactly what i want (and i patched kakoune to get it, unfortunately it never got merged).

divarvel avatar Jan 08 '23 13:01 divarvel

@divarvel I gave implementing a boundary whitespace renderer a go; it's on this branch here: https://github.com/mtoohey31/helix/tree/feat/boundary-whitespace. If you happen to have time, would you mind trying it out and letting me know if it works the way you'd expect? To enable it, running :set whitespace.render boundary should be all that's necessary.

mtoohey31 avatar Jan 11 '23 01:01 mtoohey31

Wow, thanks! I gave it a go and it works as documented indeed. I wonder if your work could be adapted to provide support for trailing as well, as it might be the most useful for people (reading the VSCode docs, i realized that trailing made more sense to me than boundary).

I can have a go at it and see how it goes.

divarvel avatar Jan 11 '23 09:01 divarvel

The main issue with trailing is that it requires a double traversal of each line (one to know where the trailing whitespace starts, and one to actually draw graphemes), which might have a non-negligible perf impact. One alternative solution would be to display the newline character only when the last char in an line is whitespace. This avoids requiring traversing each line twice as well as not interfering with how other whitespace is displayed.

Here's my attempt: https://github.com/divarvel/helix/commit/2ef08c11e40cfaadc759a40e6dfc18c42a7a8dee

2023-01-11-141109_580x154_scrot

pros:

  • it only affects newlines and doesn't interact with settings for other whitespace chars
  • it does not require traversing each line twice

cons:

  • it's a bit subtle and not always easy to spot trailing whitespace that is not otherwise displayed
  • it's different from what VScode does
  • it only affects newlines, even though it's possible to set trailing for spaces, tabs and nbsp as well, where it will be simply ignored

It depends on @mtoohey31's patch (which i believe only supports boundary for spaces) so i can't PR it as is.

divarvel avatar Jan 11 '23 13:01 divarvel

Nice idea @divarvel, that's an interesting solution! The challenges you mentioned with trailing are actually why I decided to give boundary a shot first; I'd perfer trailing myself too. It might still be worth checking how much the double traversal solution would impact performance, because it might not be too bad. Or, we could give this kind of whitespace rendering a different name other than "trailing" and add it now, then if we come up with a performant implementation for what other editors refer to as "trailing", that could get added later under that name without changing the behaviour of an existing option.

I don't know if I'll get around to working on this again any time soon. Don't feel like you need to wait for me if you'd like to create a PR, if you want to create a PR based on my chanes that's fine with me. Not sure how the changes in #5420 will play with our changes though; I haven't checked but the mention of "rework rendering" in the title suggests that there might be significant conflicts.

mtoohey31 avatar Feb 05 '23 17:02 mtoohey31

Nice idea @divarvel, that's an interesting solution! The challenges you mentioned with trailing are actually why I decided to give boundary a shot first; I'd perfer trailing myself too. It might still be worth checking how much the double traversal solution would impact performance, because it might not be too bad. Or, we could give this kind of whitespace rendering a different name other than "trailing" and add it now, then if we come up with a performant implementation for what other editors refer to as "trailing", that could get added later under that name without changing the behaviour of an existing option.

I don't know if I'll get around to working on this again any time soon. Don't feel like you need to wait for me if you'd like to create a PR, if you want to create a PR based on my chanes that's fine with me. Not sure how the changes in #5420 will play with our changes though; I haven't checked but the mention of "rework rendering" in the title suggests that there might be significant conflicts.

The text rendering code was completely replaced so your code would likely require significant changes.

pascalkuthe avatar Feb 05 '23 17:02 pascalkuthe

Ok, that's alright. Thanks for your work on that PR by the way @pascalkuthe, I've been waiting for softwrap for a long time!

mtoohey31 avatar Feb 05 '23 17:02 mtoohey31

Is it possible to only show invisibles in normal mode? Or to have a mode-specific configuration for when invisible whitespace is shown? Plus, I want my cursor to change colour depending on whether the cursor is on a newline character.

I don't know about you, but because you can select both whitespace and newline, wanting to delete whitespace, you can accidentally delete a newline, and I find that I want the cursor to just change the colour if I am on a newline character so I know whether or not I want to delete it. To me, this strikes a balance between not being able to select a newline character (vim) and being able to know you're on a newline.

Finally, this is a bit tangential, but I find the "soft-wrapped newline" symbol kind of unnecessary in soft-wrap. This is for a different issue, but I don't really want to know that a line is soft-wrapped because line numbers already show that.

wmstack avatar Mar 08 '24 16:03 wmstack

Regarding the "soft-wrapped newline" symbol, you can configure that to any string you like using editor.soft-wrap.wrap-indicator in your config.toml. I personally like seeing it, but if you want to turn it off, change it to the empty string.

Zoybean avatar Mar 09 '24 02:03 Zoybean

I too would like an option to show trailing whitespaces only, because showing all whitespaces adds a lot of clutter. I quite like the solution proposed by @divarvel, also I reimplemented it on master if someone else is interested: https://github.com/jean-dao/helix/commit/3d0e232039e506333f40e5128f156c0b56f01b0e (there's also an additional commit to have a separate style for newlines https://github.com/jean-dao/helix/commit/b026823e8ea225ed4e5485f02d8ef790328b1703)

jean-dao avatar Apr 20 '24 11:04 jean-dao

@jean-dao I like this! would you make a PR for it?

Zoybean avatar Jun 23 '24 02:06 Zoybean