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

Add syntax highlighing feature to egui_extras #3333

Merged
merged 4 commits into from
Sep 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,19 +49,22 @@ jobs:
run: cargo check --locked --all-features --all-targets

- name: check egui_extras --all-features
run: cargo check --locked --all-features --all-targets -p egui_extras
run: cargo check --locked --all-features -p egui_extras

- name: check default features
run: cargo check --locked --all-targets

- name: check --no-default-features
run: cargo check --locked --no-default-features --lib --all-targets

- name: check epaint --no-default-features
run: cargo check --locked --no-default-features --lib --all-targets -p epaint

- name: check eframe --no-default-features
run: cargo check --locked --no-default-features --features x11 --lib --all-targets -p eframe
run: cargo check --locked --no-default-features --features x11 --lib -p eframe

- name: check egui_extras --no-default-features
run: cargo check --locked --no-default-features --lib -p egui_extras

- name: check epaint --no-default-features
run: cargo check --locked --no-default-features --lib -p epaint

- name: Test doc-tests
run: cargo test --doc --all-features
Expand Down
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions crates/egui/src/load/bytes_loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ impl DefaultBytesLoader {
self.cache
.lock()
.entry(uri.into())
.or_insert_with_key(|uri| {
.or_insert_with_key(|_uri| {
let bytes: Bytes = bytes.into();

#[cfg(feature = "log")]
log::trace!("loaded {} bytes for uri {uri:?}", bytes.len());
log::trace!("loaded {} bytes for uri {_uri:?}", bytes.len());

bytes
});
Expand Down
2 changes: 1 addition & 1 deletion crates/egui_demo_app/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ image_viewer = ["image", "egui_extras/all-loaders", "rfd"]
persistence = ["eframe/persistence", "egui/persistence", "serde"]
web_screen_reader = ["eframe/web_screen_reader"] # experimental
serde = ["dep:serde", "egui_demo_lib/serde", "egui/serde"]
syntax_highlighting = ["egui_demo_lib/syntax_highlighting"]
syntect = ["egui_demo_lib/syntect"]

glow = ["eframe/glow"]
wgpu = ["eframe/wgpu", "bytemuck"]
Expand Down
12 changes: 3 additions & 9 deletions crates/egui_demo_app/src/apps/http_app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,25 +223,19 @@ fn selectable_text(ui: &mut egui::Ui, mut text: &str) {
// ----------------------------------------------------------------------------
// Syntax highlighting:

#[cfg(feature = "syntect")]
fn syntax_highlighting(
ctx: &egui::Context,
response: &ehttp::Response,
text: &str,
) -> Option<ColoredText> {
let extension_and_rest: Vec<&str> = response.url.rsplitn(2, '.').collect();
let extension = extension_and_rest.get(0)?;
let theme = crate::syntax_highlighting::CodeTheme::from_style(&ctx.style());
Some(ColoredText(crate::syntax_highlighting::highlight(
let extension = extension_and_rest.first()?;
let theme = egui_extras::syntax_highlighting::CodeTheme::from_style(&ctx.style());
Some(ColoredText(egui_extras::syntax_highlighting::highlight(
ctx, &theme, text, extension,
)))
}

#[cfg(not(feature = "syntect"))]
fn syntax_highlighting(_ctx: &egui::Context, _: &ehttp::Response, _: &str) -> Option<ColoredText> {
None
}

struct ColoredText(egui::text::LayoutJob);

impl ColoredText {
Expand Down
6 changes: 1 addition & 5 deletions crates/egui_demo_lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ chrono = ["egui_extras/datepicker", "dep:chrono"]
serde = ["egui/serde", "egui_plot/serde", "dep:serde"]

## Enable better syntax highlighting using [`syntect`](https://docs.rs/syntect).
syntax_highlighting = ["syntect"]
syntect = ["egui_extras/syntect"]


[dependencies]
Expand All @@ -37,7 +37,6 @@ egui_extras = { version = "0.22.0", path = "../egui_extras", features = [
"log",
] }
egui_plot = { version = "0.22.0", path = "../egui_plot" }
enum-map = { version = "2", features = ["serde"] }
log = { version = "0.4", features = ["std"] }
unicode_names2 = { version = "0.6.0", default-features = false }

Expand All @@ -46,9 +45,6 @@ chrono = { version = "0.4", optional = true, features = ["js-sys", "wasmbind"] }
## Enable this when generating docs.
document-features = { version = "0.2", optional = true }
serde = { version = "1", optional = true, features = ["derive"] }
syntect = { version = "5", optional = true, default-features = false, features = [
"default-fancy",
] }


[dev-dependencies]
Expand Down
3 changes: 1 addition & 2 deletions crates/egui_demo_lib/src/demo/about.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ impl super::View for About {
}

fn about_immediate_mode(ui: &mut egui::Ui) {
use crate::syntax_highlighting::code_view_ui;
ui.style_mut().spacing.interact_size.y = 0.0; // hack to make `horizontal_wrapped` work better with text.

ui.horizontal_wrapped(|ui| {
Expand All @@ -56,7 +55,7 @@ fn about_immediate_mode(ui: &mut egui::Ui) {
});

ui.add_space(8.0);
code_view_ui(
crate::rust_view_ui(
ui,
r#"
if ui.button("Save").clicked() {
Expand Down
4 changes: 2 additions & 2 deletions crates/egui_demo_lib/src/demo/code_editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ impl super::View for CodeEditor {
});
}

let mut theme = crate::syntax_highlighting::CodeTheme::from_memory(ui.ctx());
let mut theme = egui_extras::syntax_highlighting::CodeTheme::from_memory(ui.ctx());
ui.collapsing("Theme", |ui| {
ui.group(|ui| {
theme.ui(ui);
Expand All @@ -77,7 +77,7 @@ impl super::View for CodeEditor {

let mut layouter = |ui: &egui::Ui, string: &str, wrap_width: f32| {
let mut layout_job =
crate::syntax_highlighting::highlight(ui.ctx(), &theme, string, language);
egui_extras::syntax_highlighting::highlight(ui.ctx(), &theme, string, language);
layout_job.wrap.max_width = wrap_width;
ui.fonts(|f| f.layout_job(layout_job))
};
Expand Down
12 changes: 5 additions & 7 deletions crates/egui_demo_lib/src/demo/code_example.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,11 @@ impl super::Demo for CodeExample {

impl super::View for CodeExample {
fn ui(&mut self, ui: &mut egui::Ui) {
use crate::syntax_highlighting::code_view_ui;

ui.vertical_centered(|ui| {
ui.add(crate::egui_github_link_file!());
});

code_view_ui(
crate::rust_view_ui(
ui,
r"
pub struct CodeExample {
Expand Down Expand Up @@ -117,15 +115,15 @@ impl CodeExample {
});
});

code_view_ui(ui, " }\n}");
crate::rust_view_ui(ui, " }\n}");

ui.separator();

code_view_ui(ui, &format!("{self:#?}"));
crate::rust_view_ui(ui, &format!("{self:#?}"));

ui.separator();

let mut theme = crate::syntax_highlighting::CodeTheme::from_memory(ui.ctx());
let mut theme = egui_extras::syntax_highlighting::CodeTheme::from_memory(ui.ctx());
ui.collapsing("Theme", |ui| {
theme.ui(ui);
theme.store_in_memory(ui.ctx());
Expand All @@ -135,7 +133,7 @@ impl CodeExample {

fn show_code(ui: &mut egui::Ui, code: &str) {
let code = remove_leading_indentation(code.trim_start_matches('\n'));
crate::syntax_highlighting::code_view_ui(ui, &code);
crate::rust_view_ui(ui, &code);
}

fn remove_leading_indentation(code: &str) -> String {
Expand Down
8 changes: 7 additions & 1 deletion crates/egui_demo_lib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,17 @@
mod color_test;
mod demo;
pub mod easy_mark;
pub mod syntax_highlighting;

pub use color_test::ColorTest;
pub use demo::DemoWindows;

/// View some Rust code with syntax highlighting and selection.
pub(crate) fn rust_view_ui(ui: &mut egui::Ui, code: &str) {
let language = "rs";
let theme = egui_extras::syntax_highlighting::CodeTheme::from_memory(ui.ctx());
egui_extras::syntax_highlighting::code_view_ui(ui, &theme, code, language);
}

// ----------------------------------------------------------------------------

/// Create a [`Hyperlink`](egui::Hyperlink) to this egui source code file on github.
Expand Down
10 changes: 9 additions & 1 deletion crates/egui_extras/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,13 @@ puffin = ["dep:puffin", "egui/puffin"]
## Support loading svg images.
svg = ["resvg", "tiny-skia", "usvg"]

## Enable better syntax highlighting using [`syntect`](https://docs.rs/syntect).
syntect = ["dep:syntect"]


[dependencies]
egui = { version = "0.22.0", path = "../egui", default-features = false }

enum-map = { version = "2", features = ["serde"] }
serde = { version = "1", features = ["derive"] }

#! ### Optional dependencies
Expand Down Expand Up @@ -83,6 +87,10 @@ mime_guess = { version = "2.0.4", optional = true, default-features = false }

puffin = { version = "0.16", optional = true }

syntect = { version = "5", optional = true, default-features = false, features = [
"default-fancy",
] }

# svg feature
resvg = { version = "0.28", optional = true, default-features = false }
tiny-skia = { version = "0.8", optional = true, default-features = false } # must be updated in lock-step with resvg
Expand Down
2 changes: 2 additions & 0 deletions crates/egui_extras/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
#[cfg(feature = "chrono")]
mod datepicker;

pub mod syntax_highlighting;

#[doc(hidden)]
pub mod image;
mod layout;
Expand Down
22 changes: 15 additions & 7 deletions crates/egui_extras/src/loaders/file_loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,21 +63,29 @@ impl BytesLoader for FileLoader {
.spawn({
let ctx = ctx.clone();
let cache = self.cache.clone();
let uri = uri.to_owned();
let _uri = uri.to_owned();
move || {
let result = match std::fs::read(&path) {
Ok(bytes) => Ok(File {
bytes: bytes.into(),
mime: mime_guess::from_path(&path)
Ok(bytes) => {
#[cfg(feature = "mime_guess")]
let mime = mime_guess::from_path(&path)
.first_raw()
.map(|v| v.to_owned()),
}),
.map(|v| v.to_owned());

#[cfg(not(feature = "mime_guess"))]
let mime = None;

Ok(File {
bytes: bytes.into(),
mime,
})
}
Err(err) => Err(err.to_string()),
};
let prev = cache.lock().insert(path, Poll::Ready(result));
assert!(matches!(prev, Some(Poll::Pending)));
ctx.request_repaint();
crate::log_trace!("finished loading {uri:?}");
crate::log_trace!("finished loading {_uri:?}");
}
})
.expect("failed to spawn thread");
Expand Down
2 changes: 1 addition & 1 deletion crates/egui_extras/src/sizing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ impl From<Vec<Size>> for Sizing {
#[test]
fn test_sizing() {
let sizing: Sizing = vec![].into();
assert_eq!(sizing.to_lengths(50.0, 0.0), vec![]);
assert_eq!(sizing.to_lengths(50.0, 0.0), Vec::<f32>::new());

let sizing: Sizing = vec![Size::remainder().at_least(20.0), Size::remainder()].into();
assert_eq!(sizing.to_lengths(50.0, 0.0), vec![25.0, 25.0]);
Expand Down
Loading