Skip to content

Commit

Permalink
Newlines in macro backend
Browse files Browse the repository at this point in the history
  • Loading branch information
lampsitter committed Jul 12, 2024
1 parent c4846cf commit fc662b5
Show file tree
Hide file tree
Showing 6 changed files with 241 additions and 153 deletions.
7 changes: 7 additions & 0 deletions egui_commonmark/examples/mixing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,13 @@ A footnote [^F1]
"#,
);

ui.label(label);
egui_commonmark::CommonMarkViewer::new("viewer").show(
ui,
&mut cache,
"---------------",
);

ui.label(label);
});
},
Expand Down
4 changes: 2 additions & 2 deletions egui_commonmark/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -326,10 +326,10 @@ impl List {
ui.add_space(4.0);
}

pub fn end_level(&mut self, ui: &mut egui::Ui) {
pub fn end_level(&mut self, ui: &mut egui::Ui, insert_newline: bool) {
self.items.pop();

if self.items.is_empty() {
if self.items.is_empty() && insert_newline {
newline(ui);
}
}
Expand Down
2 changes: 1 addition & 1 deletion egui_commonmark/src/parsers/comrak.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ impl CommonMarkViewerInternal {

NodeValue::ThematicBreak => {
newline(ui);
rule(ui);
rule(ui, true);
}

NodeValue::FootnoteDefinition(f) => {
Expand Down
163 changes: 89 additions & 74 deletions egui_commonmark/src/parsers/pulldown.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,61 @@ use egui_commonmark_backend::misc::*;
use egui_commonmark_backend::pulldown::*;
use pulldown_cmark::{CowStr, HeadingLevel};

/// Newline logic is constructed by the following:
/// All elements try to insert a newline before them (if they are allowed)
/// and end their own line.
struct Newline {
/// Whether an element should insert a newline before it
should_start_newline: bool,
/// Whether an element should end it's own line using a newline
/// This will have to be set to false in cases such as when blocks are within
/// a list.
should_end_newline: bool,
/// only false when the widget is the last one.
should_end_newline_forced: bool,
}

impl Default for Newline {
fn default() -> Self {
Self {
// Default as false as the first line should not have a newline above it
should_start_newline: false,
should_end_newline: true,
should_end_newline_forced: true,
}
}
}

impl Newline {
pub fn can_insert_end(&self) -> bool {
self.should_end_newline && self.should_end_newline_forced
}

pub fn can_insert_start(&self) -> bool {
self.should_start_newline
}

pub fn try_insert_start(&self, ui: &mut Ui) {
if self.should_start_newline {
newline(ui);
}
}

pub fn try_insert_end(&self, ui: &mut Ui) {
if self.can_insert_end() {
newline(ui);
}
}
}

pub struct CommonMarkViewerInternal {
source_id: Id,
curr_table: usize,
text_style: Style,
list: List,
link: Option<Link>,
image: Option<Image>,
/// Newline logic is constructed by the following:
/// All elements try to insert a newline before them (if they are allowed)
/// and end their own line.
/// Whether an element should insert a newline before it
should_start_newline: bool,
/// Whether an element should end it's own line using a newline
/// This will have to be set to false in cases such as when blocks are within
/// a list.
// FIXME: Can this be avoided by changing lists?
should_end_newline: bool,
line: Newline,
fenced_code_block: Option<FencedCodeBlock>,
is_list_item: bool,
is_table: bool,
Expand All @@ -48,8 +86,7 @@ impl CommonMarkViewerInternal {
list: List::default(),
link: None,
image: None,
should_start_newline: false,
should_end_newline: true,
line: Newline::default(),
is_list_item: false,
fenced_code_block: None,
is_table: false,
Expand Down Expand Up @@ -88,7 +125,7 @@ impl CommonMarkViewerInternal {
let should_add_split_point = self.list.is_inside_a_list() && is_element_end;

if events.peek().is_none() {
self.should_end_newline = false;
self.line.should_end_newline_forced = false;
}

self.process_event(ui, &mut events, e, src_span, cache, options, max_width);
Expand All @@ -110,7 +147,7 @@ impl CommonMarkViewerInternal {
}

if index == 0 {
self.should_start_newline = true;
self.line.should_start_newline = true;
}
}

Expand Down Expand Up @@ -193,13 +230,13 @@ impl CommonMarkViewerInternal {

while let Some((i, (e, src_span))) = events.next() {
if events.peek().is_none() {
self.should_end_newline = false;
self.line.should_end_newline_forced = false;
}

self.process_event(ui, &mut events, e, src_span, cache, options, max_width);

if i == 0 {
self.should_start_newline = true;
self.line.should_start_newline = true;
}
}
});
Expand Down Expand Up @@ -274,10 +311,7 @@ impl CommonMarkViewerInternal {
) {
if self.is_blockquote {
let mut collected_events = delayed_events(events, pulldown_cmark::TagEnd::BlockQuote);

if self.should_start_newline {
newline(ui)
}
self.line.try_insert_start(ui);

if let Some(alert) = parse_alerts(&options.alerts, &mut collected_events) {
egui_commonmark_backend::alert_ui(alert, ui, |ui| {
Expand All @@ -295,10 +329,7 @@ impl CommonMarkViewerInternal {
});
}

if self.should_end_newline {
newline(ui);
}

self.line.try_insert_end(ui);
self.is_blockquote = false;
}
}
Expand All @@ -312,9 +343,7 @@ impl CommonMarkViewerInternal {
max_width: f32,
) {
if self.is_table {
if self.should_start_newline {
newline(ui);
}
self.line.try_insert_start(ui);

let id = self.source_id.with(self.curr_table);
self.curr_table += 1;
Expand All @@ -327,12 +356,12 @@ impl CommonMarkViewerInternal {
ui.horizontal(|ui| {
for (e, src_span) in col {
let tmp_start =
std::mem::replace(&mut self.should_start_newline, false);
std::mem::replace(&mut self.line.should_start_newline, false);
let tmp_end =
std::mem::replace(&mut self.should_end_newline, false);
std::mem::replace(&mut self.line.should_end_newline, false);
self.event(ui, e, src_span, cache, options, max_width);
self.should_start_newline = tmp_start;
self.should_end_newline = tmp_end;
self.line.should_start_newline = tmp_start;
self.line.should_end_newline = tmp_end;
}
});
}
Expand All @@ -343,13 +372,15 @@ impl CommonMarkViewerInternal {
for col in row {
ui.horizontal(|ui| {
for (e, src_span) in col {
let tmp_start =
std::mem::replace(&mut self.should_start_newline, false);
let tmp_start = std::mem::replace(
&mut self.line.should_start_newline,
false,
);
let tmp_end =
std::mem::replace(&mut self.should_end_newline, false);
std::mem::replace(&mut self.line.should_end_newline, false);
self.event(ui, e, src_span, cache, options, max_width);
self.should_start_newline = tmp_start;
self.should_end_newline = tmp_end;
self.line.should_start_newline = tmp_start;
self.line.should_end_newline = tmp_end;
}
});
}
Expand All @@ -361,9 +392,7 @@ impl CommonMarkViewerInternal {

self.is_table = false;

if self.should_end_newline {
newline(ui);
}
self.line.try_insert_end(ui);
}
}

Expand Down Expand Up @@ -397,10 +426,8 @@ impl CommonMarkViewerInternal {
}
pulldown_cmark::Event::HardBreak => newline(ui),
pulldown_cmark::Event::Rule => {
if self.should_start_newline {
newline(ui);
}
rule(ui);
self.line.try_insert_start(ui);
rule(ui, self.line.can_insert_end());
}
pulldown_cmark::Event::TaskListMarker(mut checkbox) => {
if options.mutable {
Expand Down Expand Up @@ -438,9 +465,7 @@ impl CommonMarkViewerInternal {
fn start_tag(&mut self, ui: &mut Ui, tag: pulldown_cmark::Tag, options: &CommonMarkOptions) {
match tag {
pulldown_cmark::Tag::Paragraph => {
if self.should_start_newline {
newline(ui);
}
self.line.try_insert_start(ui);
}
pulldown_cmark::Tag::Heading { level, .. } => {
// Headings should always insert a newline even if it is at the start.
Expand Down Expand Up @@ -468,15 +493,13 @@ impl CommonMarkViewerInternal {
content: "".to_string(),
});

if self.should_start_newline {
newline(ui);
}
self.line.try_insert_start(ui);
}

self.text_style.code = true;
}
pulldown_cmark::Tag::List(point) => {
if !self.list.is_inside_a_list() && self.should_start_newline {
if !self.list.is_inside_a_list() && self.line.can_insert_start() {
newline(ui);
}

Expand All @@ -485,20 +508,20 @@ impl CommonMarkViewerInternal {
} else {
self.list.start_level_without_number();
}
self.should_start_newline = false;
self.should_end_newline = false;
self.line.should_start_newline = false;
self.line.should_end_newline = false;
}

pulldown_cmark::Tag::Item => {
self.is_list_item = true;
self.list.start_item(ui, options);
}

pulldown_cmark::Tag::FootnoteDefinition(note) => {
if self.should_start_newline {
newline(ui);
}
self.line.try_insert_start(ui);

self.should_start_newline = false;
self.should_end_newline = false;
self.line.should_start_newline = false;
self.line.should_end_newline = false;
footnote(ui, &note);
}
pulldown_cmark::Tag::Table(_) => {
Expand Down Expand Up @@ -540,33 +563,27 @@ impl CommonMarkViewerInternal {
) {
match tag {
pulldown_cmark::TagEnd::Paragraph => {
if self.should_end_newline {
newline(ui);
}
self.line.try_insert_end(ui);
}
pulldown_cmark::TagEnd::Heading { .. } => {
if self.should_end_newline {
newline(ui);
}
self.line.try_insert_end(ui);
self.text_style.heading = None;
}
pulldown_cmark::TagEnd::BlockQuote => {}
pulldown_cmark::TagEnd::CodeBlock => {
self.end_code_block(ui, cache, options, max_width);
}
pulldown_cmark::TagEnd::List(_) => {
self.list.end_level(ui);
self.list.end_level(ui, self.line.can_insert_end());

if !self.list.is_inside_a_list() {
newline(ui);
}
self.line.should_start_newline = true;
self.line.should_end_newline = true;
}
pulldown_cmark::TagEnd::Item => {}
pulldown_cmark::TagEnd::FootnoteDefinition => {
self.should_start_newline = true;
self.should_end_newline = true;
// End the footnote line
newline(ui);
self.line.should_start_newline = true;
self.line.should_end_newline = true;
self.line.try_insert_end(ui);
}
pulldown_cmark::TagEnd::Table => {}
pulldown_cmark::TagEnd::TableHead => {}
Expand Down Expand Up @@ -609,9 +626,7 @@ impl CommonMarkViewerInternal {
if let Some(block) = self.fenced_code_block.take() {
block.end(ui, cache, options, max_width);
self.text_style.code = false;
if self.should_end_newline {
newline(ui);
}
self.line.try_insert_end(ui);
}
}
}
6 changes: 4 additions & 2 deletions egui_commonmark_backend/src/elements.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
use egui::{self, epaint, NumExt, RichText, Sense, TextStyle, Ui, Vec2};

#[inline]
pub fn rule(ui: &mut Ui) {
pub fn rule(ui: &mut Ui, end_line: bool) {
ui.add(egui::Separator::default().horizontal());
// This does not add a new line, but instead ends the separator
newline(ui);
if end_line {
newline(ui);
}
}

#[inline]
Expand Down
Loading

0 comments on commit fc662b5

Please sign in to comment.