diff --git a/org_mode_samples/lesser_element/lesser_block/example/switches_with_label.org b/org_mode_samples/lesser_element/lesser_block/example/switches_with_label.org index e844b0e9..a450ab8b 100644 --- a/org_mode_samples/lesser_element/lesser_block/example/switches_with_label.org +++ b/org_mode_samples/lesser_element/lesser_block/example/switches_with_label.org @@ -1,3 +1,3 @@ #+BEGIN_SRC elisp -n -r -l "((%s))" -foo + foo #+END_SRC diff --git a/src/compare/diff.rs b/src/compare/diff.rs index 025c922e..938622d8 100644 --- a/src/compare/diff.rs +++ b/src/compare/diff.rs @@ -1547,8 +1547,6 @@ fn compare_example_block<'b, 's>( let mut this_status = DiffStatus::Good; let mut message = None; - // TODO: Compare :preserve-indent :retain-labels :use-labels :label-fmt - // Compare value let contents = get_property_quoted_string(emacs, ":value")?.unwrap_or(String::new()); if contents != rust.contents { @@ -1609,6 +1607,49 @@ fn compare_example_block<'b, 's>( } }; + // Compare preserve-indent + let preserve_indent = get_property_boolean(emacs, ":preserve-indent")?; + if preserve_indent { + // I don't know what :preserve-indent is for, but it seems to always be nil. This is here to alert me to value being non-nil so I can investigate. + this_status = DiffStatus::Bad; + message = Some(format!("Non-nil :preserve-indent {:?}", preserve_indent)); + } + + // Compare retain-labels + let retain_labels = get_property_boolean(emacs, ":retain-labels")?; + if retain_labels != rust.retain_labels { + this_status = DiffStatus::Bad; + message = Some(format!( + "Retain labels mismatch (emacs != rust) {:?} != {:?}", + retain_labels, rust.retain_labels + )); + } + + // Compare use-labels + let use_labels = get_property_boolean(emacs, ":use-labels")?; + if use_labels != rust.use_labels { + this_status = DiffStatus::Bad; + message = Some(format!( + "Use labels mismatch (emacs != rust) {:?} != {:?}", + use_labels, rust.use_labels + )); + } + + // Compare label-fmt + let label_format = get_property_quoted_string(emacs, ":label-fmt")?; + match (label_format.as_ref(), rust.label_format) { + (None, None) => {} + (Some(emacs_label_format), Some(rust_label_format)) + if emacs_label_format == rust_label_format => {} + _ => { + this_status = DiffStatus::Bad; + message = Some(format!( + "Label format mismatch (emacs != rust) {:?} != {:?}", + label_format, rust.label_format + )); + } + } + Ok(DiffResult { status: this_status, name: rust.get_elisp_name(), diff --git a/src/parser/lesser_block.rs b/src/parser/lesser_block.rs index da6c1458..1ba5f6c4 100644 --- a/src/parser/lesser_block.rs +++ b/src/parser/lesser_block.rs @@ -1,5 +1,6 @@ use nom::branch::alt; use nom::bytes::complete::is_not; +use nom::bytes::complete::tag; use nom::bytes::complete::tag_no_case; use nom::character::complete::line_ending; use nom::character::complete::space0; @@ -154,11 +155,17 @@ pub(crate) fn example_block<'b, 'g, 'r, 's>( let (remaining, _end) = lesser_block_end_specialized(&parser_context, remaining)?; let source = get_consumed(input, remaining); - let (switches, number_lines) = { + let (switches, number_lines, retain_labels, use_labels, label_format) = { if let Some(parameters) = parameters { - (Some(parameters.source), parameters.number_lines) + ( + Some(parameters.source), + parameters.number_lines, + parameters.retain_labels, + parameters.use_labels, + parameters.label_format, + ) } else { - (None, None) + (None, None, true, true, None) } }; Ok(( @@ -168,6 +175,9 @@ pub(crate) fn example_block<'b, 'g, 'r, 's>( name: source.into(), switches, number_lines, + retain_labels, + use_labels, + label_format, contents: contents.into(), }, )) @@ -317,58 +327,86 @@ fn _lesser_block_begin<'b, 'g, 'r, 's, 'c>( struct ExampleSwitches<'s> { source: &'s str, number_lines: Option, + retain_labels: bool, + use_labels: bool, + label_format: Option<&'s str>, } enum SwitchState { Normal, NewLineNumber, ContinuedLineNumber, + LabelFormat, } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] fn example_switches<'s>(input: OrgSource<'s>) -> Res, ExampleSwitches<'s>> { let mut number_lines = None; + let mut retain_labels = true; + let mut use_labels = true; + let mut label_format = None; let (remaining, (source, (words, _))) = consumed(tuple(( - separated_list1( - space1, - map(is_not(" \t\r\n"), |val| Into::<&str>::into(val)), - ), + separated_list1(space1, map(switch_word, |val| Into::<&str>::into(val))), space0, )))(input)?; let mut state = SwitchState::Normal; for word in words { - state = match (state, word) { - (SwitchState::Normal, "-n") => SwitchState::NewLineNumber, - (SwitchState::Normal, "+n") => SwitchState::ContinuedLineNumber, - (SwitchState::NewLineNumber, _) => { - let val = match word.parse::() { - Ok(val) => val, - Err(_) => 1, - }; - if val < 0 { - number_lines = Some(SwitchNumberLines::New(0)); - } else { - // Note that this can result in a negative 1 if the val is originally 0. - number_lines = Some(SwitchNumberLines::New(val - 1)); + loop { + match (&state, word) { + (SwitchState::Normal, "-n") => { + state = SwitchState::NewLineNumber; } - SwitchState::Normal - } - (SwitchState::ContinuedLineNumber, _) => { - let val = match word.parse::() { - Ok(val) => val, - Err(_) => 1, - }; - if val < 0 { - number_lines = Some(SwitchNumberLines::Continued(0)); - } else { - // Note that this can result in a negative 1 if the val is originally 0. - number_lines = Some(SwitchNumberLines::Continued(val - 1)); + (SwitchState::Normal, "+n") => { + state = SwitchState::ContinuedLineNumber; } - SwitchState::Normal - } - (state @ SwitchState::Normal, _) => state, - }; + (SwitchState::Normal, "-r") => { + retain_labels = false; + use_labels = false; + } + (SwitchState::Normal, "-l") => { + state = SwitchState::LabelFormat; + } + (SwitchState::NewLineNumber, _) => { + let val = word.parse::(); + if let Ok(val) = val { + if val < 0 { + number_lines = Some(SwitchNumberLines::New(0)); + } else { + // Note that this can result in a negative 1 if the val is originally 0. + number_lines = Some(SwitchNumberLines::New(val - 1)); + } + state = SwitchState::Normal; + } else { + number_lines = Some(SwitchNumberLines::New(0)); + state = SwitchState::Normal; + continue; // Re-processes the word + } + } + (SwitchState::ContinuedLineNumber, _) => { + let val = word.parse::(); + if let Ok(val) = val { + if val < 0 { + number_lines = Some(SwitchNumberLines::Continued(0)); + } else { + // Note that this can result in a negative 1 if the val is originally 0. + number_lines = Some(SwitchNumberLines::Continued(val - 1)); + } + state = SwitchState::Normal; + } else { + number_lines = Some(SwitchNumberLines::Continued(0)); + state = SwitchState::Normal; + continue; // Re-processes the word + } + } + (SwitchState::LabelFormat, _) => { + label_format = Some(word); + state = SwitchState::Normal; + } + (SwitchState::Normal, _) => {} + }; + break; + } } Ok(( @@ -376,6 +414,20 @@ fn example_switches<'s>(input: OrgSource<'s>) -> Res, ExampleSwitc ExampleSwitches { source: Into::<&str>::into(source), number_lines, + retain_labels, + use_labels, + label_format, }, )) } + +#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] +fn switch_word<'s>(input: OrgSource<'s>) -> Res, OrgSource<'s>> { + alt(( + map( + tuple((tag(r#"""#), is_not("\"\r\n"), tag(r#"""#))), + |(_, contents, _)| contents, + ), + is_not(" \t\r\n"), + ))(input) +} diff --git a/src/types/lesser_element.rs b/src/types/lesser_element.rs index 20e932b4..3d8a21f0 100644 --- a/src/types/lesser_element.rs +++ b/src/types/lesser_element.rs @@ -42,6 +42,9 @@ pub struct ExampleBlock<'s> { pub name: &'s str, pub switches: Option<&'s str>, pub number_lines: Option, + pub retain_labels: bool, + pub use_labels: bool, + pub label_format: Option<&'s str>, pub contents: &'s str, }