summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/src/text/highlighter.rs7
-rw-r--r--examples/editor/src/main.rs101
-rw-r--r--widget/src/text_editor.rs13
3 files changed, 99 insertions, 22 deletions
diff --git a/core/src/text/highlighter.rs b/core/src/text/highlighter.rs
index a929826f..b462d083 100644
--- a/core/src/text/highlighter.rs
+++ b/core/src/text/highlighter.rs
@@ -1,10 +1,9 @@
use crate::Color;
-use std::hash::Hash;
use std::ops::Range;
pub trait Highlighter: 'static {
- type Settings: Hash;
+ type Settings: PartialEq + Clone;
type Highlight;
type Iterator<'a>: Iterator<Item = (Range<usize>, Self::Highlight)>
@@ -13,6 +12,8 @@ pub trait Highlighter: 'static {
fn new(settings: &Self::Settings) -> Self;
+ fn update(&mut self, new_settings: &Self::Settings);
+
fn change_line(&mut self, line: usize);
fn highlight_line(&mut self, line: &str) -> Self::Iterator<'_>;
@@ -38,6 +39,8 @@ impl Highlighter for PlainText {
Self
}
+ fn update(&mut self, _new_settings: &Self::Settings) {}
+
fn change_line(&mut self, _line: usize) {}
fn highlight_line(&mut self, _line: &str) -> Self::Iterator<'_> {
diff --git a/examples/editor/src/main.rs b/examples/editor/src/main.rs
index 74649676..fa35ba0f 100644
--- a/examples/editor/src/main.rs
+++ b/examples/editor/src/main.rs
@@ -1,5 +1,5 @@
-use iced::widget::{container, text_editor};
-use iced::{Element, Font, Sandbox, Settings, Theme};
+use iced::widget::{column, horizontal_space, pick_list, row, text_editor};
+use iced::{Element, Font, Length, Sandbox, Settings, Theme};
use highlighter::Highlighter;
@@ -9,11 +9,13 @@ pub fn main() -> iced::Result {
struct Editor {
content: text_editor::Content,
+ theme: highlighter::Theme,
}
#[derive(Debug, Clone)]
enum Message {
Edit(text_editor::Action),
+ ThemeSelected(highlighter::Theme),
}
impl Sandbox for Editor {
@@ -21,9 +23,8 @@ impl Sandbox for Editor {
fn new() -> Self {
Self {
- content: text_editor::Content::with(include_str!(
- "../../../README.md"
- )),
+ content: text_editor::Content::with(include_str!("main.rs")),
+ theme: highlighter::Theme::SolarizedDark,
}
}
@@ -36,18 +37,33 @@ impl Sandbox for Editor {
Message::Edit(action) => {
self.content.edit(action);
}
+ Message::ThemeSelected(theme) => {
+ self.theme = theme;
+ }
}
}
fn view(&self) -> Element<Message> {
- container(
+ column![
+ row![
+ horizontal_space(Length::Fill),
+ pick_list(
+ highlighter::Theme::ALL,
+ Some(self.theme),
+ Message::ThemeSelected
+ )
+ .padding([5, 10])
+ ]
+ .spacing(10),
text_editor(&self.content)
.on_edit(Message::Edit)
.font(Font::with_name("Hasklug Nerd Font Mono"))
.highlight::<Highlighter>(highlighter::Settings {
- token: String::from("md"),
+ theme: self.theme,
+ extension: String::from("rs"),
}),
- )
+ ]
+ .spacing(10)
.padding(20)
.into()
}
@@ -60,21 +76,52 @@ impl Sandbox for Editor {
mod highlighter {
use iced::advanced::text::highlighter;
use iced::widget::text_editor;
- use iced::{Color, Font, Theme};
+ use iced::{Color, Font};
use std::ops::Range;
use syntect::highlighting;
use syntect::parsing::{self, SyntaxReference};
- #[derive(Debug, Clone, Hash)]
+ #[derive(Debug, Clone, PartialEq)]
pub struct Settings {
- pub token: String,
+ pub theme: Theme,
+ pub extension: String,
+ }
+
+ #[derive(Debug, Clone, Copy, PartialEq, Eq)]
+ pub enum Theme {
+ SolarizedDark,
+ InspiredGitHub,
+ Base16Mocha,
+ }
+
+ impl Theme {
+ pub const ALL: &[Self] =
+ &[Self::SolarizedDark, Self::InspiredGitHub, Self::Base16Mocha];
+
+ fn key(&self) -> &'static str {
+ match self {
+ Theme::InspiredGitHub => "InspiredGitHub",
+ Theme::Base16Mocha => "base16-mocha.dark",
+ Theme::SolarizedDark => "Solarized (dark)",
+ }
+ }
+ }
+
+ impl std::fmt::Display for Theme {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ match self {
+ Theme::InspiredGitHub => write!(f, "Inspired GitHub"),
+ Theme::Base16Mocha => write!(f, "Mocha"),
+ Theme::SolarizedDark => write!(f, "Solarized Dark"),
+ }
+ }
}
pub struct Highlight(highlighting::StyleModifier);
impl text_editor::Highlight for Highlight {
- fn format(&self, _theme: &Theme) -> highlighter::Format<Font> {
+ fn format(&self, _theme: &iced::Theme) -> highlighter::Format<Font> {
highlighter::Format {
color: self.0.foreground.map(|color| {
Color::from_rgba8(
@@ -92,8 +139,8 @@ mod highlighter {
pub struct Highlighter {
syntaxes: parsing::SyntaxSet,
syntax: SyntaxReference,
- caches: Vec<(parsing::ParseState, parsing::ScopeStack)>,
theme: highlighting::Theme,
+ caches: Vec<(parsing::ParseState, parsing::ScopeStack)>,
current_line: usize,
}
@@ -110,26 +157,42 @@ mod highlighter {
let syntaxes = parsing::SyntaxSet::load_defaults_nonewlines();
let syntax = syntaxes
- .find_syntax_by_token(&settings.token)
+ .find_syntax_by_token(&settings.extension)
.unwrap_or_else(|| syntaxes.find_syntax_plain_text());
- let parser = parsing::ParseState::new(syntax);
- let stack = parsing::ScopeStack::new();
-
let theme = highlighting::ThemeSet::load_defaults()
.themes
- .remove("base16-mocha.dark")
+ .remove(settings.theme.key())
.unwrap();
+ let parser = parsing::ParseState::new(syntax);
+ let stack = parsing::ScopeStack::new();
+
Highlighter {
syntax: syntax.clone(),
syntaxes,
- caches: vec![(parser, stack)],
theme,
+ caches: vec![(parser, stack)],
current_line: 0,
}
}
+ fn update(&mut self, new_settings: &Self::Settings) {
+ self.syntax = self
+ .syntaxes
+ .find_syntax_by_token(&new_settings.extension)
+ .unwrap_or_else(|| self.syntaxes.find_syntax_plain_text())
+ .clone();
+
+ self.theme = highlighting::ThemeSet::load_defaults()
+ .themes
+ .remove(new_settings.theme.key())
+ .unwrap();
+
+ // Restart the highlighter
+ self.change_line(0);
+ }
+
fn change_line(&mut self, line: usize) {
let snapshot = line / LINES_PER_SNAPSHOT;
diff --git a/widget/src/text_editor.rs b/widget/src/text_editor.rs
index c30e185f..0cde2c98 100644
--- a/widget/src/text_editor.rs
+++ b/widget/src/text_editor.rs
@@ -193,11 +193,12 @@ where
}
}
-struct State<Highlighter> {
+struct State<Highlighter: text::Highlighter> {
is_focused: bool,
last_click: Option<mouse::Click>,
drag_click: Option<mouse::click::Kind>,
highlighter: RefCell<Highlighter>,
+ highlighter_settings: Highlighter::Settings,
}
impl<'a, Highlighter, Message, Renderer> Widget<Message, Renderer>
@@ -220,6 +221,7 @@ where
highlighter: RefCell::new(Highlighter::new(
&self.highlighter_settings,
)),
+ highlighter_settings: self.highlighter_settings.clone(),
})
}
@@ -240,6 +242,15 @@ where
let mut internal = self.content.0.borrow_mut();
let state = tree.state.downcast_mut::<State<Highlighter>>();
+ if state.highlighter_settings != self.highlighter_settings {
+ state
+ .highlighter
+ .borrow_mut()
+ .update(&self.highlighter_settings);
+
+ state.highlighter_settings = self.highlighter_settings.clone();
+ }
+
internal.editor.update(
limits.pad(self.padding).max(),
self.font.unwrap_or_else(|| renderer.default_font()),