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

Initial support for Scintilla sub-styles #3794

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open

Conversation

b4n
Copy link
Member

@b4n b4n commented Mar 19, 2024

This is a first attempt with little testing, but it seems to work pretty OK. However, please review all levels, from design to implementation.

To summarize, what this does is look for stylename.N for styles that are known to be sub-stylable1, as well as the corresponding keywords/identifiers2. From there, it's just regular styles one can map as usual.

One limitation I am already aware of is that as it's not regular keywords, it doesn't integrate with the code merging the ctags symbols into them. It could be possible to augment this to work, but with the current design this would need a way of representing this in the filetypes file (which would be good, but is not the case currently).

One arbitrary design choice was to use the syntax stylename.N. This is mostly because using stylename[i] is tricky/hacky using GKeyFile, because it looks similar to Scintilla's properties, and doesn't clash with any style name. Other suggestions are welcome.

Footnotes

  1. we unfortunately cannot use SCI_GETSUBSTYLEBASES because we don't have access to a Scintilla instance when loading style data. Hence adding a new field in HLStyle.

  2. Note here that this feature is styles-based in Scintilla, meaning that there is no regular keywords entry associated, it's defined as kind of a style property.

@b4n b4n marked this pull request as draft March 19, 2024 10:31
src/highlighting.c Outdated Show resolved Hide resolved
Comment on lines 1752 to 1777
/* FIXME: this is sub-stylable, but we can't figure out the base
* style without the Scintilla instance -- and we can't simply
* assume that if the style ID is larger than the max possible
* one it's this, because SCE_C_IDENTIFIER is also sub-stylable... */
Copy link
Member Author

Choose a reason for hiding this comment

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

This I don't see how to fix short of having a separate API taking a ScintillaObject instead of a lexer ID. We might be able to store info about the allocated sub-style somewhere that could be accessed from here if we could rely on sub-style allocation to give predictable values. This would require Scintilla to actually be deterministic about that, which it might be, but likely not if some calls could happen adding or modifying substyles (think of a plugin that would mess with this).

Copy link
Member

Choose a reason for hiding this comment

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

Should it actually be per Scintilla instance, the plugin might only mess with one?

Copy link
Member Author

@b4n b4n Mar 19, 2024

Choose a reason for hiding this comment

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

It is, so yeah, we'd have to be sure allocation is the same for all lexer instances. That's the tricky part, then we can just fill something when initially allocating the substyles.

The proper solution should be style = SCI_GETSTYLEFROMSUBSTYLE(style) but we can't do that with this API.

Copy link
Member

Choose a reason for hiding this comment

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

Also, don't we only instantiate one lexer per sci instance? So the whole process needs to be done every time a new tab with a new filetype is opened because there is now a new type of lexer to query?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes we do have one lever per instance, that's why we'd need the allocations to be the same for all of them for this to have a chance of working.

But really, I probably should look at callers for this to see if anybody actually doesn't have a Scintilla instance ready at hand when calling this.

Copy link
Member

@elextr elextr Mar 23, 2024

Choose a reason for hiding this comment

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

Yeah, it should only be called on a document, so there should be a SCI available. Otherwise how did they get the "style" to pass in???

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed in e9ca102 by introducing an alternate API and deprecating this

src/ui_utils.c Outdated Show resolved Hide resolved
A filetype file can define substyles for appropriate styles using a
`stylename.N=style` syntax in both `styling` and `keywords` sections:

    [styling]
    # ...
    identifier.1=some_named_style

    [keywords]
    # ...
    identifier.1=foo bar baz

This allows to add arbitrarily more keyword styles for lexers that
support the feature (C, Python, Bash, GDScript and Verilog currently).
b4n added 4 commits March 26, 2024 00:37
Use the newer SCI_GETSTYLEINDEXAT which supports styles > 127 instead
of the historic  SCI_GETSTYLEAT that is limited to 127.

This is useful if a lexer has more than 127 styles, which is notably
the case when using the sub-styles feature.
Display them as `BASE "." SUB_INDEX` (e.g. `11.1` for the first
sub-style of style 11).
b4n added 4 commits March 26, 2024 00:43
highlighting_is_*_style() API cannot deal with substyles, because they
are inherently dynamic, but the API of these functions don't have
access to a mean of fetching the required dynamic info.

So, introduce replacement API editor_is_*_a(), and deprecate the other
one.

The new API takes an editor and a position, which allows to retrieve
the required dynamic information, and leaves room to further extend the
implementation if need arises.

Some design choices:

Q: Why use a GeanyEditor rather than a ScintillaObject?
A: We don't currently have original APIs that take a ScintillaObject.
   The APIs we have that do take one are mere wrapper around one or a
   few Scintilla calls, not original APIs altogether.  This means that
   one that do doesn't really have a spot to reside in, both in naming
   and source location.
   Additionally, this could allow future addition to the API that
   require extra data held on the GeanyEditor instance.
   The only downside is that this doesn't necessarily cover custom
   Scintilla instances, but it's a rather odd use case of having one
   and requiring this kind of info from it.

Q: Why replace style with position?  Current implementation would work
   fine with style as well.
A: Because of flexibility, and current usage.
   Flexibility: using a position could allow for looking around in the
   future if the exact meaning of a style could depend on the ones
   around, or if Scintilla had extra separate info that could be useful
   for determining the category that is not tied to the style itself.
   Reviewing current usage suggests that all callers perform a slight
   variation on `highlighting_is_*_style(lexer, style_at(sci, pos))`,
   so accepting a position directly just makes the API easier to use.
   The very few callers that use the style separately as well merely
   suffer from one additional call in this situation.
   Finally, there is no reason to tie the question "is there a comment
   here?" to a style from an user standpoint, so requiring one simply
   leak some internals when answering this question.
Following the deprecation of the former in favor of the latter.
This might not be entirely thorough, yet should cover most ground by
reviewing all `sci_get_style_at()` calls which should be the primary
source of Scintilla styles.
@b4n b4n marked this pull request as ready for review March 29, 2024 19:44
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