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

Allow separate styles for markup headings #1618

Merged
merged 2 commits into from
Feb 21, 2022

Conversation

CptPotato
Copy link
Contributor

@CptPotato CptPotato commented Feb 3, 2022

This makes it possible to use separate styles for each markup heading level:

image

I've never worked with tree sitter before, so someone might want to confirm that highlights.scm is okay.

adresses #1597

@CptPotato
Copy link
Contributor Author

CptPotato commented Feb 3, 2022

I ended up updating helix-term/src/ui/markdown.rs aswell, thinking it was required for markdown highlighting to work but it looks like it isn't 👀

I'm not 100% sure what it is used for. (edit: it's used for doc and completion popups)

@CptPotato CptPotato changed the title Draft: Allow separate styles for markup headings Allow separate styles for markup headings Feb 3, 2022
@CptPotato CptPotato force-pushed the markup-headings-style branch 2 times, most recently from 8591851 to a39c452 Compare February 3, 2022 09:58
@sudormrfbin
Copy link
Member

I ended up updating helix-term/src/ui/markdown.rs aswell, thinking it was required for markdown highlighting to work but it looks like it isn't eyes

I'm not 100% sure what it is used for.

It's used for rendering markdown in the completion and documentation popups btw.

@CptPotato
Copy link
Contributor Author

CptPotato commented Feb 3, 2022

It's used for rendering markdown in the completion and documentation popups btw.

Thanks, The popups seemed to work as expected

Edit: actually, the line that overrides self.heading_styles in style_group() breaks the highlighting in the popup.
If I remove that part the colors are correct again. I'm a bit confused, I hope someone can explain the behavior of style_group().


I think I get it now: There's markup.[...].completion and markup.[...].hover.

hover actually refers to the doc popup, so I need to set markup.heading.1.hover in the theme to make it work.
Still, it's odd that it doesn't fall back to markup.heading.1 when it's missing.

@sudormrfbin
Copy link
Member

Still, it's odd that it doesn't fall back to markup.heading.1 when it's missing.

It works for syntax highlight scopes automatically but IIRC it has to be done manually for ui theming as of now (here we are manually applying the styles in the popup markdown component even though it's technically syntax highlighting).

Copy link
Member

@sudormrfbin sudormrfbin left a comment

Choose a reason for hiding this comment

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

Tested and works.

@sudormrfbin sudormrfbin linked an issue Feb 3, 2022 that may be closed by this pull request
let heading_styles: Vec<Style> = self
.heading_styles
.iter()
.map(|key| get_theme(key))
Copy link
Member

Choose a reason for hiding this comment

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

This has no fallback though, if markup.heading.1 isn't defined, just markup.heading it won't highlight.

Copy link
Member

Choose a reason for hiding this comment

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

The macro would have to be modified to try get_theme(key, "markup.heading") in order. We can also simplify and just use markup.heading for this component.

Copy link
Contributor Author

@CptPotato CptPotato Feb 4, 2022

Choose a reason for hiding this comment

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

Not sure if recursion is a good idea but something along those lines should work:

// example program

use std::collections::HashMap;

fn get_theme<'a, Y>(theme: &'a HashMap<&str, Y>, key: &str) -> Option<&'a Y> {
    theme
        .get(key)
        .or_else(|| key.rfind(".").and_then(|n| get_theme(theme, &key[..n])))
}

fn main() {
    let mut theme = HashMap::new();

    theme.insert("markup.heading", 1);
    theme.insert("markup.heading.2", 2);

    assert_eq!(get_theme(&theme, "markup.heading.1"), Some(&1));
    assert_eq!(get_theme(&theme, "markup.heading.2"), Some(&2));
    assert_eq!(get_theme(&theme, "markup.bold"), None);
}

Edit: Note that this performs a fallback rather than an override. Though, overriding shouldn't be much more difficult either.

Alternatively, the fallbacks for every key (Vec<String>) could be specified manually in markdown.rs or generated in the constructor, if this is a rather hot function.

I'm not very familiar with macros, sorry. Do they have a performance/convinience advantage in this case?

Copy link
Member

Choose a reason for hiding this comment

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

Yeah I don't think there was any reason for macros, personally in not sure if we really need the namespacing for different popups #1363

Here's a similar method in syntax.rs, perhaps we can use the same algorithm:

helix/helix-core/src/syntax.rs

Lines 1197 to 1211 in d3221b0

for (i, recognized_name) in recognized_names.iter().enumerate() {
let recognized_name = recognized_name;
let mut len = 0;
let mut matches = true;
for part in recognized_name.split('.') {
len += 1;
if !capture_parts.contains(&part) {
matches = false;
break;
}
}
if matches && len > best_match_len {
best_index = Some(i);
best_match_len = len;
}

Copy link
Member

Choose a reason for hiding this comment

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

Yeah I don't think there was any reason for macros, personally in not sure if we really need the namespacing for different popups.

I would be in favour of removing the namespacing part, it seems unnecessary and too granular to be widely used in themes.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I would be in favour of removing the namespacing part, it seems unnecessary and too granular to be widely used in themes.

Sorry for the delay. I went ahead and removed the namespacing of the markdown theme keys in the ui. Things seem to work but let me know if I missed anything.

Now that the keys and fallbacks don't change during runtime, I ended up turning them into constants. It's not the prettiest but I didn't have much luck with using macros to make it less manual.


Here's a similar method in syntax.rs, perhaps we can use the same algorithm:

helix/helix-core/src/syntax.rs

Lines 1197 to 1211 in d3221b0

for (i, recognized_name) in recognized_names.iter().enumerate() {
let recognized_name = recognized_name;
let mut len = 0;
let mut matches = true;
for part in recognized_name.split('.') {
len += 1;
if !capture_parts.contains(&part) {
matches = false;
break;
}
}
if matches && len > best_match_len {
best_index = Some(i);
best_match_len = len;
}

I might take a look at that at some point. Right now I don't know of a quick way to see if my changes there produce the correct results.

@archseer
Copy link
Member

archseer commented Feb 4, 2022

Note: This doesn't fully address all the things in #1597

@CptPotato CptPotato force-pushed the markup-headings-style branch 2 times, most recently from aba7c83 to cc08480 Compare February 14, 2022 09:57
Copy link
Member

@archseer archseer left a comment

Choose a reason for hiding this comment

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

Tested locally 👍🏻

@archseer archseer merged commit d5ba0b5 into helix-editor:master Feb 21, 2022
@CptPotato CptPotato deleted the markup-headings-style branch March 31, 2022 09:38
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.

None yet

3 participants