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

feat: support custom theme #187

Merged
merged 2 commits into from
Oct 31, 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
83 changes: 83 additions & 0 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ default-features = false
[dependencies.syntect]
version = "5.0.0"
default-features = false
features = ["parsing", "regex-onig"]
features = ["parsing", "regex-onig", "plist-load"]

[profile.release]
lto = true
Expand Down
28 changes: 26 additions & 2 deletions src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ use std::{
process::exit,
sync::Arc,
};
use syntect::highlighting::ThemeSet;

/// Monokai Extended
const DARK_THEME: &[u8] = include_bytes!("../../assets/monokai-extended.theme.bin");
const LIGHT_THEME: &[u8] = include_bytes!("../../assets/monokai-extended-light.theme.bin");

const CONFIG_FILE_NAME: &str = "config.yaml";
const ROLES_FILE_NAME: &str = "roles.yaml";
Expand Down Expand Up @@ -522,13 +527,32 @@ impl Config {
}
}

pub fn get_render_options(&self) -> RenderOptions {
pub fn get_render_options(&self) -> Result<RenderOptions> {
let theme = if self.highlight {
let theme_mode = if self.light_theme { "light" } else { "dark" };
let theme_filename = format!("{theme_mode}.tmTheme");
let theme_path = Self::local_path(&theme_filename)?;
if theme_path.exists() {
let theme = ThemeSet::get_theme(&theme_path)
.with_context(|| format!("Invalid theme at {}", theme_path.display()))?;
Some(theme)
} else {
let theme = if self.light_theme {
bincode::deserialize_from(LIGHT_THEME).expect("Invalid builtin light theme")
} else {
bincode::deserialize_from(DARK_THEME).expect("Invalid builtin dark theme")
};
Some(theme)
}
} else {
None
};
let wrap = if stdout().is_terminal() {
self.wrap.clone()
} else {
None
};
RenderOptions::new(self.highlight, self.light_theme, wrap, self.wrap_code)
Ok(RenderOptions::new(theme, wrap, self.wrap_code))
}

pub fn maybe_print_send_tokens(&self, input: &str) {
Expand Down
2 changes: 1 addition & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ fn start_directive(
}
config.read().maybe_print_send_tokens(input);
let output = if no_stream {
let render_options = config.read().get_render_options();
let render_options = config.read().get_render_options()?;
let output = client.send_message(input)?;
let mut markdown_render = MarkdownRender::init(render_options)?;
println!("{}", markdown_render.render(&output).trim());
Expand Down
42 changes: 5 additions & 37 deletions src/render/markdown.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,6 @@ use syntect::highlighting::{Color as SyntectColor, FontStyle, Style, Theme};
use syntect::parsing::SyntaxSet;
use syntect::{easy::HighlightLines, parsing::SyntaxReference};

/// Monokai Extended
const MD_THEME: &[u8] = include_bytes!("../../assets/monokai-extended.theme.bin");
const MD_THEME_LIGHT: &[u8] = include_bytes!("../../assets/monokai-extended-light.theme.bin");
/// Comes from https://github.com/sharkdp/bat/raw/5e77ca37e89c873e4490b42ff556370dc5c6ba4f/assets/syntaxes.bin
const SYNTAXES: &[u8] = include_bytes!("../../assets/syntaxes.bin");

Expand All @@ -25,7 +22,6 @@ lazy_static! {
pub struct MarkdownRender {
options: RenderOptions,
syntax_set: SyntaxSet,
md_theme: Option<Theme>,
code_color: Option<Color>,
md_syntax: SyntaxReference,
code_syntax: Option<SyntaxReference>,
Expand All @@ -38,18 +34,7 @@ impl MarkdownRender {
let syntax_set: SyntaxSet = bincode::deserialize_from(SYNTAXES)
.with_context(|| "MarkdownRender: invalid syntaxes binary")?;

let md_theme: Option<Theme> = match (options.highlight, options.light_theme) {
(false, _) => None,
(true, false) => Some(
bincode::deserialize_from(MD_THEME)
.with_context(|| "MarkdownRender: invalid theme binary")?,
),
(true, true) => Some(
bincode::deserialize_from(MD_THEME_LIGHT)
.expect("MarkdownRender: invalid theme binary"),
),
};
let code_color = md_theme.as_ref().map(get_code_color);
let code_color = options.theme.as_ref().map(get_code_color);
let md_syntax = syntax_set.find_syntax_by_extension("md").unwrap().clone();
let line_type = LineType::Normal;
let wrap_width = match options.wrap.as_deref() {
Expand All @@ -70,7 +55,6 @@ impl MarkdownRender {
};
Ok(Self {
syntax_set,
md_theme,
code_color,
md_syntax,
code_syntax: None,
Expand Down Expand Up @@ -161,7 +145,7 @@ impl MarkdownRender {
let ws: String = line.chars().take_while(|c| c.is_whitespace()).collect();
let trimed_line: &str = &line[ws.len()..];
let mut line_highlighted = None;
if let Some(theme) = &self.md_theme {
if let Some(theme) = &self.options.theme {
let mut highlighter = HighlightLines::new(syntax, theme);
if let Ok(ranges) = highlighter.highlight_line(trimed_line, &self.syntax_set) {
line_highlighted = Some(format!("{ws}{}", as_terminal_escaped(&ranges)))
Expand Down Expand Up @@ -207,22 +191,15 @@ impl MarkdownRender {

#[derive(Debug, Clone, Default)]
pub struct RenderOptions {
pub highlight: bool,
pub light_theme: bool,
pub theme: Option<Theme>,
pub wrap: Option<String>,
pub wrap_code: bool,
}

impl RenderOptions {
pub(crate) fn new(
highlight: bool,
light_theme: bool,
wrap: Option<String>,
wrap_code: bool,
) -> Self {
pub(crate) fn new(theme: Option<Theme>, wrap: Option<String>, wrap_code: bool) -> Self {
Self {
highlight,
light_theme,
theme,
wrap,
wrap_code,
}
Expand Down Expand Up @@ -343,15 +320,6 @@ std::error::Error>> {
```
"#;

#[test]
fn test_assets() {
let syntax_set: SyntaxSet =
bincode::deserialize_from(SYNTAXES).expect("invalid syntaxes.bin");
assert!(syntax_set.find_syntax_by_extension("md").is_some());
let md_theme: Theme = bincode::deserialize_from(MD_THEME).expect("invalid md_theme binary");
assert_eq!(md_theme.name, Some("Monokai Extended".into()));
}

#[test]
fn test_render() {
let options = RenderOptions::default();
Expand Down
2 changes: 1 addition & 1 deletion src/render/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pub fn render_stream(
abort: SharedAbortSignal,
wg: WaitGroup,
) -> Result<String> {
let render_options = config.read().get_render_options();
let render_options = config.read().get_render_options()?;
let mut stream_handler = {
let (tx, rx) = unbounded();
let abort_clone = abort.clone();
Expand Down
2 changes: 1 addition & 1 deletion src/repl/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ impl ReplCmdHandler {
}
ReplCmd::SessionInfo => {
if let Some(session) = &self.config.read().session {
let render_options = self.config.read().get_render_options();
let render_options = self.config.read().get_render_options()?;
let mut markdown_render = MarkdownRender::init(render_options)?;
print_now!("{}\n\n", session.render(&mut markdown_render)?);
} else {
Expand Down
16 changes: 5 additions & 11 deletions src/repl/highlighter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,13 @@ use crate::config::SharedConfig;
use nu_ansi_term::{Color, Style};
use reedline::{Highlighter, StyledText};

const MATCH_COLOR: Color = Color::Green;

pub struct ReplHighlighter {
external_commands: Vec<String>,
config: SharedConfig,
}

impl ReplHighlighter {
/// Construct the default highlighter with a given set of extern commands/keywords to detect and highlight
pub fn new(config: SharedConfig, external_commands: Vec<String>) -> Self {
pub fn new(external_commands: Vec<String>, config: SharedConfig) -> Self {
Self {
external_commands,
config,
Expand All @@ -22,18 +19,15 @@ impl ReplHighlighter {

impl Highlighter for ReplHighlighter {
fn highlight(&self, line: &str, _cursor: usize) -> StyledText {
let mut styled_text = StyledText::new();
let color = if self.config.read().light_theme {
Color::Black
} else {
Color::White
};
let color = Color::Default;
let match_color = if self.config.read().highlight {
MATCH_COLOR
Color::Green
} else {
color
};

let mut styled_text = StyledText::new();

if self
.external_commands
.clone()
Expand Down
2 changes: 1 addition & 1 deletion src/repl/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ impl Repl {
.collect();

let completer = Self::create_completer(&config, &commands);
let highlighter = ReplHighlighter::new(config.clone(), commands);
let highlighter = ReplHighlighter::new(commands, config.clone());
let menu = Self::create_menu();
let edit_mode: Box<dyn EditMode> = if config.read().keybindings.is_vi() {
let mut normal_keybindings = default_vi_normal_keybindings();
Expand Down
1 change: 0 additions & 1 deletion src/repl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,6 @@ impl Repl {
}
".set" => {
handler.handle(ReplCmd::Set(args.unwrap_or_default().to_string()))?;
self.prompt.sync_config();
}
".copy" => {
handler.handle(ReplCmd::Copy)?;
Expand Down
Loading