Add src block properties.
These are largely the same as example blocks but with a :language property.
This commit is contained in:
parent
13163f2468
commit
b556f4617f
@ -1727,11 +1727,161 @@ fn compare_src_block<'b, 's>(
|
|||||||
_source: &'s str,
|
_source: &'s str,
|
||||||
emacs: &'b Token<'s>,
|
emacs: &'b Token<'s>,
|
||||||
rust: &'b SrcBlock<'s>,
|
rust: &'b SrcBlock<'s>,
|
||||||
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error + 's>> {
|
||||||
let this_status = DiffStatus::Good;
|
let mut this_status = DiffStatus::Good;
|
||||||
let message = None;
|
let mut message = None;
|
||||||
|
|
||||||
// TODO: Compare :language :switches :parameters :number-lines :preserve-indent :retain-labels :use-labels :label-fmt :value
|
// Compare language
|
||||||
|
let language = get_property_quoted_string(emacs, ":language")?;
|
||||||
|
if language.as_ref().map(String::as_str) != rust.language {
|
||||||
|
this_status = DiffStatus::Bad;
|
||||||
|
message = Some(format!(
|
||||||
|
"Language mismatch (emacs != rust) {:?} != {:?}",
|
||||||
|
language, rust.language
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compare value
|
||||||
|
let contents = get_property_quoted_string(emacs, ":value")?.unwrap_or(String::new());
|
||||||
|
if contents != rust.contents {
|
||||||
|
this_status = DiffStatus::Bad;
|
||||||
|
message = Some(format!(
|
||||||
|
"Value mismatch (emacs != rust) {:?} != {:?}",
|
||||||
|
contents, rust.contents
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compare switches
|
||||||
|
let switches = get_property_quoted_string(emacs, ":switches")?;
|
||||||
|
match (switches.as_ref().map(String::as_str), rust.switches) {
|
||||||
|
(None, None) => {}
|
||||||
|
(Some(""), None) => {}
|
||||||
|
(None, Some("")) => {
|
||||||
|
unreachable!("The organic parser would return a None instead of an empty string.");
|
||||||
|
}
|
||||||
|
(Some(e), Some(r)) if e == r => {}
|
||||||
|
_ => {
|
||||||
|
this_status = DiffStatus::Bad;
|
||||||
|
message = Some(format!(
|
||||||
|
"Switches mismatch (emacs != rust) {:?} != {:?}",
|
||||||
|
switches, rust.switches
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compare number-lines
|
||||||
|
let number_lines = get_property(emacs, ":number-lines")?;
|
||||||
|
match (number_lines, &rust.number_lines) {
|
||||||
|
(None, None) => {}
|
||||||
|
(Some(number_lines), Some(rust_number_lines)) => {
|
||||||
|
let token_list = number_lines.as_list()?;
|
||||||
|
let number_type = token_list
|
||||||
|
.get(0)
|
||||||
|
.map(Token::as_atom)
|
||||||
|
.map_or(Ok(None), |r| r.map(Some))?
|
||||||
|
.ok_or(":number-lines should have a type.")?;
|
||||||
|
let number_value = token_list
|
||||||
|
.get(2)
|
||||||
|
.map(Token::as_atom)
|
||||||
|
.map_or(Ok(None), |r| r.map(Some))?
|
||||||
|
.map(|val| val.parse::<LineNumber>())
|
||||||
|
.map_or(Ok(None), |r| r.map(Some))?
|
||||||
|
.ok_or(":number-lines should have a value.")?;
|
||||||
|
match (number_type, number_value, rust_number_lines) {
|
||||||
|
("new", emacs_val, SwitchNumberLines::New(rust_val)) if emacs_val == *rust_val => {}
|
||||||
|
("continued", emacs_val, SwitchNumberLines::Continued(rust_val))
|
||||||
|
if emacs_val == *rust_val => {}
|
||||||
|
_ => {
|
||||||
|
this_status = DiffStatus::Bad;
|
||||||
|
message = Some(format!(
|
||||||
|
"Number lines mismatch (emacs != rust) {:?} != {:?}",
|
||||||
|
number_lines, rust.number_lines
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
this_status = DiffStatus::Bad;
|
||||||
|
message = Some(format!(
|
||||||
|
"Number lines mismatch (emacs != rust) {:?} != {:?}",
|
||||||
|
number_lines, rust.number_lines
|
||||||
|
));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 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
|
||||||
|
// retain-labels is t by default, nil if -r is set, or a number if -k and -r is set.
|
||||||
|
let retain_labels = get_property_unquoted_atom(emacs, ":retain-labels")?;
|
||||||
|
if let Some(retain_labels) = retain_labels {
|
||||||
|
if retain_labels == "t" {
|
||||||
|
match rust.retain_labels {
|
||||||
|
RetainLabels::Yes => {}
|
||||||
|
_ => {
|
||||||
|
this_status = DiffStatus::Bad;
|
||||||
|
message = Some(format!(
|
||||||
|
"Retain labels mismatch (emacs != rust) {:?} != {:?}",
|
||||||
|
retain_labels, rust.retain_labels
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let retain_labels: CharOffsetInLine = get_property_numeric(emacs, ":retain-labels")?.expect("Cannot be None or else the earlier get_property_unquoted_atom would have been None.");
|
||||||
|
match (retain_labels, &rust.retain_labels) {
|
||||||
|
(e, RetainLabels::Keep(r)) if e == *r => {}
|
||||||
|
_ => {
|
||||||
|
this_status = DiffStatus::Bad;
|
||||||
|
message = Some(format!(
|
||||||
|
"Retain labels mismatch (emacs != rust) {:?} != {:?}",
|
||||||
|
retain_labels, rust.retain_labels
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
match rust.retain_labels {
|
||||||
|
RetainLabels::No => {}
|
||||||
|
_ => {
|
||||||
|
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 {
|
Ok(DiffResult {
|
||||||
status: this_status,
|
status: this_status,
|
||||||
|
@ -176,7 +176,6 @@ pub(crate) fn example_block<'b, 'g, 'r, 's>(
|
|||||||
remaining,
|
remaining,
|
||||||
ExampleBlock {
|
ExampleBlock {
|
||||||
source: source.into(),
|
source: source.into(),
|
||||||
name: source.into(),
|
|
||||||
switches,
|
switches,
|
||||||
number_lines,
|
number_lines,
|
||||||
retain_labels,
|
retain_labels,
|
||||||
@ -233,9 +232,9 @@ pub(crate) fn src_block<'b, 'g, 'r, 's>(
|
|||||||
context: RefContext<'b, 'g, 'r, 's>,
|
context: RefContext<'b, 'g, 'r, 's>,
|
||||||
input: OrgSource<'s>,
|
input: OrgSource<'s>,
|
||||||
) -> Res<OrgSource<'s>, SrcBlock<'s>> {
|
) -> Res<OrgSource<'s>, SrcBlock<'s>> {
|
||||||
let (remaining, name) = lesser_block_begin("src")(context, input)?;
|
let (remaining, _name) = lesser_block_begin("src")(context, input)?;
|
||||||
// https://orgmode.org/worg/org-syntax.html#Blocks claims that data is mandatory and must follow the LANGUAGE SWITCHES ARGUMENTS pattern but testing has shown that no data and incorrect data here will still parse to a src block.
|
// https://orgmode.org/worg/org-syntax.html#Blocks claims that data is mandatory and must follow the LANGUAGE SWITCHES ARGUMENTS pattern but testing has shown that no data and incorrect data here will still parse to a src block.
|
||||||
let (remaining, parameters) = opt(tuple((space1, data)))(remaining)?;
|
let (remaining, parameters) = opt(tuple((space1, src_switches)))(remaining)?;
|
||||||
let (remaining, _nl) = recognize(tuple((space0, line_ending)))(remaining)?;
|
let (remaining, _nl) = recognize(tuple((space0, line_ending)))(remaining)?;
|
||||||
let lesser_block_end_specialized = lesser_block_end("src");
|
let lesser_block_end_specialized = lesser_block_end("src");
|
||||||
let contexts = [
|
let contexts = [
|
||||||
@ -254,17 +253,35 @@ pub(crate) fn src_block<'b, 'g, 'r, 's>(
|
|||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let (remaining, contents) = parser_with_context!(text_until_exit)(&parser_context)(remaining)?;
|
let (remaining, contents) = content(&parser_context, remaining)?;
|
||||||
let (remaining, _end) = lesser_block_end_specialized(&parser_context, remaining)?;
|
let (remaining, _end) = lesser_block_end_specialized(&parser_context, remaining)?;
|
||||||
|
|
||||||
let source = get_consumed(input, remaining);
|
let source = get_consumed(input, remaining);
|
||||||
|
let (switches, language, number_lines, retain_labels, use_labels, label_format) = {
|
||||||
|
if let Some(parameters) = parameters {
|
||||||
|
(
|
||||||
|
Some(parameters.source),
|
||||||
|
parameters.language,
|
||||||
|
parameters.number_lines,
|
||||||
|
parameters.retain_labels,
|
||||||
|
parameters.use_labels,
|
||||||
|
parameters.label_format,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
(None, None, None, RetainLabels::Yes, true, None)
|
||||||
|
}
|
||||||
|
};
|
||||||
Ok((
|
Ok((
|
||||||
remaining,
|
remaining,
|
||||||
SrcBlock {
|
SrcBlock {
|
||||||
source: source.into(),
|
source: source.into(),
|
||||||
name: name.into(),
|
switches,
|
||||||
switches: parameters.map(|parameters| Into::<&str>::into(parameters)),
|
language,
|
||||||
contents: contents.into(),
|
number_lines,
|
||||||
|
retain_labels,
|
||||||
|
use_labels,
|
||||||
|
label_format,
|
||||||
|
contents,
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@ -329,8 +346,9 @@ fn _lesser_block_begin<'b, 'g, 'r, 's, 'c>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct ExampleSwitches<'s> {
|
struct ExampleSrcSwitches<'s> {
|
||||||
source: &'s str,
|
source: &'s str,
|
||||||
|
language: Option<&'s str>,
|
||||||
number_lines: Option<SwitchNumberLines>,
|
number_lines: Option<SwitchNumberLines>,
|
||||||
retain_labels: RetainLabels,
|
retain_labels: RetainLabels,
|
||||||
use_labels: bool,
|
use_labels: bool,
|
||||||
@ -346,17 +364,50 @@ enum SwitchState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||||
fn example_switches<'s>(input: OrgSource<'s>) -> Res<OrgSource<'s>, ExampleSwitches<'s>> {
|
fn src_switches<'s>(input: OrgSource<'s>) -> Res<OrgSource<'s>, ExampleSrcSwitches<'s>> {
|
||||||
|
example_src_switches(true)(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||||
|
fn example_switches<'s>(input: OrgSource<'s>) -> Res<OrgSource<'s>, ExampleSrcSwitches<'s>> {
|
||||||
|
let (remaining, switches) = example_src_switches(false)(input)?;
|
||||||
|
debug_assert!(switches.language.is_none());
|
||||||
|
Ok((remaining, switches))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||||
|
fn example_src_switches(
|
||||||
|
grab_language: bool,
|
||||||
|
) -> impl for<'s> Fn(OrgSource<'s>) -> Res<OrgSource<'s>, ExampleSrcSwitches<'s>> {
|
||||||
|
move |input| _example_src_switches(input, grab_language)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||||
|
fn _example_src_switches<'s>(
|
||||||
|
input: OrgSource<'s>,
|
||||||
|
grab_language: bool,
|
||||||
|
) -> Res<OrgSource<'s>, ExampleSrcSwitches<'s>> {
|
||||||
let mut number_lines = None;
|
let mut number_lines = None;
|
||||||
let mut retain_labels = RetainLabels::Yes;
|
let mut retain_labels = RetainLabels::Yes;
|
||||||
let mut use_labels = true;
|
let mut use_labels = true;
|
||||||
let mut label_format = None;
|
let mut label_format = None;
|
||||||
let mut saw_r = false;
|
let mut saw_r = false;
|
||||||
|
let mut language = None;
|
||||||
let (remaining, (source, (words, _))) =
|
let (remaining, (source, (words, _))) =
|
||||||
consumed(tuple((separated_list1(space1, switch_word), space0)))(input)?;
|
consumed(tuple((separated_list1(space1, switch_word), space0)))(input)?;
|
||||||
|
|
||||||
|
let mut words_iter = words.into_iter();
|
||||||
|
if grab_language {
|
||||||
|
match words_iter.next() {
|
||||||
|
Some(l) => {
|
||||||
|
language = Some(Into::<&str>::into(l));
|
||||||
|
}
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let mut state = SwitchState::Normal;
|
let mut state = SwitchState::Normal;
|
||||||
for word in words {
|
for word in words_iter {
|
||||||
let normalized_word = Into::<&str>::into(word);
|
let normalized_word = Into::<&str>::into(word);
|
||||||
loop {
|
loop {
|
||||||
match (&state, normalized_word) {
|
match (&state, normalized_word) {
|
||||||
@ -436,8 +487,9 @@ fn example_switches<'s>(input: OrgSource<'s>) -> Res<OrgSource<'s>, ExampleSwitc
|
|||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
remaining,
|
remaining,
|
||||||
ExampleSwitches {
|
ExampleSrcSwitches {
|
||||||
source: Into::<&str>::into(source),
|
source: Into::<&str>::into(source),
|
||||||
|
language,
|
||||||
number_lines,
|
number_lines,
|
||||||
retain_labels,
|
retain_labels,
|
||||||
use_labels,
|
use_labels,
|
||||||
|
@ -49,7 +49,6 @@ pub enum RetainLabels {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ExampleBlock<'s> {
|
pub struct ExampleBlock<'s> {
|
||||||
pub source: &'s str,
|
pub source: &'s str,
|
||||||
pub name: &'s str,
|
|
||||||
pub switches: Option<&'s str>,
|
pub switches: Option<&'s str>,
|
||||||
pub number_lines: Option<SwitchNumberLines>,
|
pub number_lines: Option<SwitchNumberLines>,
|
||||||
pub retain_labels: RetainLabels,
|
pub retain_labels: RetainLabels,
|
||||||
@ -69,9 +68,13 @@ pub struct ExportBlock<'s> {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct SrcBlock<'s> {
|
pub struct SrcBlock<'s> {
|
||||||
pub source: &'s str,
|
pub source: &'s str,
|
||||||
pub name: &'s str,
|
|
||||||
pub switches: Option<&'s str>,
|
pub switches: Option<&'s str>,
|
||||||
pub contents: &'s str,
|
pub language: Option<&'s str>,
|
||||||
|
pub number_lines: Option<SwitchNumberLines>,
|
||||||
|
pub retain_labels: RetainLabels,
|
||||||
|
pub use_labels: bool,
|
||||||
|
pub label_format: Option<&'s str>,
|
||||||
|
pub contents: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
Loading…
Reference in New Issue
Block a user