Skip to content

Commit

Permalink
Inline code blocks
Browse files Browse the repository at this point in the history
  • Loading branch information
lampsitter committed Sep 7, 2024
1 parent bba8ec6 commit 8848291
Show file tree
Hide file tree
Showing 9 changed files with 95 additions and 54 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
### Added

- Definition lists
- Proper inline code block rendering

### Changed

Expand Down
16 changes: 11 additions & 5 deletions egui_commonmark/examples/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,17 @@ impl eframe::App for App {

commonmark!(ui, &mut self.cache, "------------");

commonmark_str!(
ui,
&mut self.cache,
"egui_commonmark/examples/markdown/tables.md"
);
// The table will end up with the same id as the table in the hello_world file.
// Providing the id explicitly is annoying for all other widgets that are not tables
// so push_id must be used in this case.
ui.push_id("tables", |ui| {
commonmark_str!(
ui,
&mut self.cache,
"egui_commonmark/examples/markdown/tables.md"
);
});

commonmark!(ui, &mut self.cache, "------------");

commonmark_str!(
Expand Down
3 changes: 3 additions & 0 deletions egui_commonmark/examples/markdown/code-blocks.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,7 @@ image = { version = "0.24", default-features = false, features = ["png"] }
```
- Code blocks can be in lists too :)


More content...

Inline code blocks are supported if you for some reason need them
3 changes: 3 additions & 0 deletions egui_commonmark/examples/mixing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ let x = 3;
```
"#,
r#"
let x = 3;
"#,
r#"
A footnote [^F1]
[^F1]: The footnote"#,
Expand Down
2 changes: 1 addition & 1 deletion egui_commonmark/examples/scroll.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ struct App {
impl eframe::App for App {
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
let mut text = r#"# Commonmark Viewer Example
This is a fairly large markdown file showcasing scroll.
This is a fairly large markdown file showcasing scroll.
"#
.to_string();

Expand Down
33 changes: 19 additions & 14 deletions egui_commonmark/src/parsers/pulldown.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ pub struct CommonMarkViewerInternal {
link: Option<Link>,
image: Option<Image>,
line: Newline,
fenced_code_block: Option<FencedCodeBlock>,
code_block: Option<CodeBlock>,
is_list_item: bool,
def_list: DefinitionList,
is_table: bool,
Expand All @@ -95,7 +95,7 @@ impl CommonMarkViewerInternal {
line: Newline::default(),
is_list_item: false,
def_list: Default::default(),
fenced_code_block: None,
code_block: None,
is_table: false,
is_blockquote: false,
checkbox_events: Vec::new(),
Expand Down Expand Up @@ -542,7 +542,7 @@ impl CommonMarkViewerInternal {
let rich_text = self.text_style.to_richtext(ui, &text);
if let Some(image) = &mut self.image {
image.alt_text.push(rich_text);
} else if let Some(block) = &mut self.fenced_code_block {
} else if let Some(block) = &mut self.code_block {
block.content.push_str(&text);
} else if let Some(link) = &mut self.link {
link.text.push(rich_text);
Expand Down Expand Up @@ -576,17 +576,23 @@ impl CommonMarkViewerInternal {
self.is_blockquote = true;
}
pulldown_cmark::Tag::CodeBlock(c) => {
if let pulldown_cmark::CodeBlockKind::Fenced(lang) = c {
self.fenced_code_block = Some(crate::FencedCodeBlock {
lang: lang.to_string(),
content: "".to_string(),
});

self.line.try_insert_start(ui);
match c {
pulldown_cmark::CodeBlockKind::Fenced(lang) => {
self.code_block = Some(crate::CodeBlock {
lang: Some(lang.to_string()),
content: "".to_string(),
});
}
pulldown_cmark::CodeBlockKind::Indented => {
self.code_block = Some(crate::CodeBlock {
lang: None,
content: "".to_string(),
});
}
}

self.text_style.code = true;
self.line.try_insert_start(ui);
}

pulldown_cmark::Tag::List(point) => {
if !self.list.is_inside_a_list() && self.line.can_insert_start() {
newline(ui);
Expand Down Expand Up @@ -739,10 +745,9 @@ impl CommonMarkViewerInternal {
options: &CommonMarkOptions,
max_width: f32,
) {
if let Some(block) = self.fenced_code_block.take() {
if let Some(block) = self.code_block.take() {
block.end(ui, cache, options, max_width);
self.line.try_insert_end(ui);
}
self.text_style.code = false;
}
}
2 changes: 1 addition & 1 deletion egui_commonmark_backend/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ pub use {
alerts::{alert_ui, Alert, AlertBundle},
// Pretty much every single element in this module is used by the proc macros
elements::*,
misc::{prepare_show, CommonMarkOptions, FencedCodeBlock, Image, Link},
misc::{prepare_show, CodeBlock, CommonMarkOptions, Image, Link},
};

// The only struct that is allowed to use directly. (If one does not need egui_commonmark)
Expand Down
36 changes: 27 additions & 9 deletions egui_commonmark_backend/src/misc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,12 +229,12 @@ impl Image {
}
}

pub struct FencedCodeBlock {
pub lang: String,
pub struct CodeBlock {
pub lang: Option<String>,
pub content: String,
}

impl FencedCodeBlock {
impl CodeBlock {
pub fn end(
&self,
ui: &mut Ui,
Expand All @@ -246,7 +246,12 @@ impl FencedCodeBlock {
Self::pre_syntax_highlighting(cache, options, ui);

let mut layout = |ui: &Ui, string: &str, wrap_width: f32| {
let mut job = self.syntax_highlighting(cache, options, &self.lang, ui, string);
let mut job = if let Some(lang) = &self.lang {
self.syntax_highlighting(cache, options, lang, ui, string)
} else {
plain_highlighting(ui, string)
};

job.wrap.max_width = wrap_width;
ui.fonts(|f| f.layout_job(job))
};
Expand All @@ -257,7 +262,7 @@ impl FencedCodeBlock {
}

#[cfg(not(feature = "better_syntax_highlighting"))]
impl FencedCodeBlock {
impl CodeBlock {
fn pre_syntax_highlighting(
_cache: &mut CommonMarkCache,
_options: &CommonMarkOptions,
Expand All @@ -274,12 +279,12 @@ impl FencedCodeBlock {
ui: &Ui,
text: &str,
) -> egui::text::LayoutJob {
plain_highlighting(ui, text, extension)
simple_highlighting(ui, text, extension)
}
}

#[cfg(feature = "better_syntax_highlighting")]
impl FencedCodeBlock {
impl CodeBlock {
fn pre_syntax_highlighting(
cache: &mut CommonMarkCache,
options: &CommonMarkOptions,
Expand Down Expand Up @@ -328,12 +333,12 @@ impl FencedCodeBlock {

job
} else {
plain_highlighting(ui, text, extension)
simple_highlighting(ui, text, extension)
}
}
}

fn plain_highlighting(ui: &Ui, text: &str, extension: &str) -> egui::text::LayoutJob {
fn simple_highlighting(ui: &Ui, text: &str, extension: &str) -> egui::text::LayoutJob {
egui_extras::syntax_highlighting::highlight(
ui.ctx(),
&egui_extras::syntax_highlighting::CodeTheme::from_style(ui.style()),
Expand All @@ -342,6 +347,19 @@ fn plain_highlighting(ui: &Ui, text: &str, extension: &str) -> egui::text::Layou
)
}

fn plain_highlighting(ui: &Ui, text: &str) -> egui::text::LayoutJob {
let mut job = egui::text::LayoutJob::default();
job.append(
text,
0.0,
egui::TextFormat::simple(
TextStyle::Monospace.resolve(ui.style()),
ui.style().visuals.text_color(),
),
);
job
}

#[cfg(feature = "better_syntax_highlighting")]
fn syntect_color_to_egui(color: syntect::highlighting::Color) -> egui::Color32 {
egui::Color32::from_rgb(color.r, color.g, color.b)
Expand Down
53 changes: 29 additions & 24 deletions egui_commonmark_macros/src/generator.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::iter::Peekable;

use egui_commonmark_backend::{
alerts::Alert, misc::Style, pulldown::*, CommonMarkOptions, FencedCodeBlock, Image,
alerts::Alert, misc::Style, pulldown::*, CodeBlock, CommonMarkOptions, Image,
};

use proc_macro2::TokenStream;
Expand Down Expand Up @@ -169,7 +169,7 @@ pub(crate) struct CommonMarkViewerInternal {
link: Option<StyledLink>,
image: Option<StyledImage>,
line: Newline,
fenced_code_block: Option<FencedCodeBlock>,
code_block: Option<CodeBlock>,
is_list_item: bool,
def_list: DefinitionList,
is_table: bool,
Expand All @@ -192,7 +192,7 @@ impl CommonMarkViewerInternal {
line: Newline::default(),
is_list_item: false,
def_list: Default::default(),
fenced_code_block: None,
code_block: None,
is_table: false,
is_blockquote: false,
dumps_heading: false,
Expand Down Expand Up @@ -559,7 +559,7 @@ impl CommonMarkViewerInternal {
image
.alt_text
.push(StyledText::new(self.text_style.clone(), text.to_string()));
} else if let Some(block) = &mut self.fenced_code_block {
} else if let Some(block) = &mut self.code_block {
block.content.push_str(&text);
} else if let Some(link) = &mut self.link {
link.text
Expand Down Expand Up @@ -595,18 +595,22 @@ impl CommonMarkViewerInternal {
TokenStream::new()
}
pulldown_cmark::Tag::CodeBlock(c) => {
self.text_style.code = true;

if let pulldown_cmark::CodeBlockKind::Fenced(lang) = c {
self.fenced_code_block = Some(FencedCodeBlock {
lang: lang.to_string(),
content: "".to_string(),
});

self.line.try_insert_start()
} else {
TokenStream::new()
match c {
pulldown_cmark::CodeBlockKind::Fenced(lang) => {
self.code_block = Some(CodeBlock {
lang: Some(lang.to_string()),
content: "".to_string(),
});
}
pulldown_cmark::CodeBlockKind::Indented => {
self.code_block = Some(CodeBlock {
lang: None,
content: "".to_string(),
});
}
}

self.line.try_insert_start()
}

pulldown_cmark::Tag::List(point) => {
Expand Down Expand Up @@ -807,21 +811,22 @@ impl CommonMarkViewerInternal {

fn end_code_block(&mut self, cache: &Expr) -> TokenStream {
let mut stream = TokenStream::new();
if let Some(block) = self.fenced_code_block.take() {
let lang = block.lang;
if let Some(block) = self.code_block.take() {
let content = block.content;

stream.extend(
quote!(
egui_commonmark_backend::FencedCodeBlock {lang: #lang.to_owned(), content: #content.to_owned()}
.end(ui, #cache, &options, max_width);
));
stream.extend(if let Some(lang) = block.lang {
quote!(egui_commonmark_backend::CodeBlock {
lang: Some(#lang.to_owned()), content: #content.to_owned()}
.end(ui, #cache, &options, max_width);)
} else {
quote!(egui_commonmark_backend::CodeBlock {
lang: None, content: #content.to_owned()}
.end(ui, #cache, &options, max_width);)
});

stream.extend(self.line.try_insert_end());
}

self.text_style.code = false;

stream
}

Expand Down

0 comments on commit 8848291

Please sign in to comment.