egui/crates
Matt Keeter f11a3510ba
Support custom syntect settings in syntax highlighter (#7084)
<!--
Please read the "Making a PR" section of
[`CONTRIBUTING.md`](https://github.com/emilk/egui/blob/main/CONTRIBUTING.md)
before opening a Pull Request!

* Keep your PR:s small and focused.
* The PR title is what ends up in the changelog, so make it descriptive!
* If applicable, add a screenshot or gif.
* If it is a non-trivial addition, consider adding a demo for it to
`egui_demo_lib`, or a new example.
* Do NOT open PR:s from your `master` branch, as that makes it hard for
maintainers to test and add commits to your PR.
* Remember to run `cargo fmt` and `cargo clippy`.
* Open the PR as a draft until you have self-reviewed it and run
`./scripts/check.sh`.
* When you have addressed a PR comment, mark it as resolved.

Please be patient! I will review your PR, but my time is limited!
-->

* Closes <https://github.com/emilk/egui/issues/3964>
* [X] I have followed the instructions in the PR template

This PR adds support for syntax highlighting with custom
`syntect::parsing::SyntaxSet` and `syntect::highlighting::ThemeSet`. It
adds a new `egui_extras::highlight_with` function (enabled with `feature
= "syntect"`), which takes a new public`struct SyntectSettings`
containing the syntax and theme sets.

```rust
let mut builder = SyntaxSetBuilder::new();
builder.add_from_folder("syntax", true).unwrap();
let ps = builder.build();
let ts = syntect::highlighting::ThemeSet::load_defaults();
let syntax =
    egui_extras::syntax_highlighting::SyntectSettings { ps, ts };

// ...elsewhere
egui_extras::syntax_highlighting::highlight_with(
    ui.ctx(),
    ui.style(),
    &theme,
    buf,
    "rhai",
    &syntax,
);
```

There's a little bit of architectural complexity, but it all emerges
naturally from the problem's constraints.

Previously, the `Highlighter` both contained the `syntect` settings
_and_ implemented `egui::cache::ComputerMut` to highlight a string; the
settings would never change. After this change, the `syntect` settings
have become part of the cache key, so we should redo highlighting if
they change. The `Highlighter` becomes an empty `struct` which just
serves to implement `ComputerMut`.

`SyntaxSet` and `ThemeSet` are not hasheable themselves, so can't be
used as cache keys direction. Instead, we can use the *address* of the
`&SyntectSettings` as the key. This requires an object with a custom
`Hash` implementation, so I added a new `HighlightSettings(&'a
SyntectSettings)`, implementing `Hash` using `std::ptr::hash` on the
reference. I think using the address is reasonable – it would be _weird_
for a user to be constantly moving around their `SyntectSettings`, and
there's a warning in the docstring to this effect.

To work _without_ custom settings, `SyntectSettings::default` preserves
the same behavior as before, using `SyntaxSet::load_defaults_newlines`
and `ThemeSet::load_defaults`. If the user doesn't provide custom
settings, then we instantiate a singleton `SyntectSettings` in `data`
and use it; this will only be constructed once.

Finally, in cases where the `syntect` feature is disabled,
`SyntectSettings` are replaced with a unit `()`. This adds a _tiny_
amount of overhead – one singleton `Arc<()>` allocation and a lookup in
`data` per `highlight` – but I think that's better than dramatically
different implementations. If this is an issue, I can refactor to make
it zero-cost when the feature is disabled.
2025-06-24 15:09:29 +02:00
..
ecolor Make `HSVA` derive serde (#7132) 2025-06-16 01:40:42 +02:00
eframe Fix incorrect window sizes for non-resizable windows on Wayland (#7103) 2025-06-24 13:44:56 +02:00
egui Use the new Popup api for the color picker button (#7137) 2025-06-18 19:19:05 +02:00
egui-wgpu Track original SVG size (#7098) 2025-05-28 08:33:01 +02:00
egui-winit Fix incorrect window sizes for non-resizable windows on Wayland (#7103) 2025-06-24 13:44:56 +02:00
egui_demo_app Create custom `egui_kittest::Node` (#7138) 2025-06-17 12:17:38 +02:00
egui_demo_lib Create custom `egui_kittest::Node` (#7138) 2025-06-17 12:17:38 +02:00
egui_extras Support custom syntect settings in syntax highlighter (#7084) 2025-06-24 15:09:29 +02:00
egui_glow Track original SVG size (#7098) 2025-05-28 08:33:01 +02:00
egui_kittest Create custom `egui_kittest::Node` (#7138) 2025-06-17 12:17:38 +02:00
egui_plot Move `egui_plot` to its own repo (#4828) 2024-07-15 18:45:19 +02:00
egui_web Rename `master` branch to `main` (#7034) 2025-05-08 09:15:42 +02:00
emath Add Vec2::ONE 2025-06-15 18:01:58 -07:00
epaint Clamp text cursor positions in the same places where we used to (#7081) 2025-06-16 01:53:00 +02:00
epaint_default_fonts Update `emoji-icon-font` with fix for fullwidth latin characters (#7067) 2025-05-21 13:22:23 +02:00