Extract the line number from the switches.
This commit is contained in:
parent
3d7f411cf9
commit
317293f0f2
@ -0,0 +1,7 @@
|
||||
#+begin_example -n -10
|
||||
foo
|
||||
#+end_example
|
||||
|
||||
#+begin_example +n -15
|
||||
bar
|
||||
#+end_example
|
@ -0,0 +1,7 @@
|
||||
#+begin_example -n 0
|
||||
foo
|
||||
#+end_example
|
||||
|
||||
#+begin_example +n 0
|
||||
bar
|
||||
#+end_example
|
@ -6,10 +6,12 @@ use nom::character::complete::space0;
|
||||
use nom::character::complete::space1;
|
||||
use nom::combinator::consumed;
|
||||
use nom::combinator::eof;
|
||||
use nom::combinator::map;
|
||||
use nom::combinator::opt;
|
||||
use nom::combinator::recognize;
|
||||
use nom::combinator::verify;
|
||||
use nom::multi::many_till;
|
||||
use nom::multi::separated_list1;
|
||||
use nom::sequence::tuple;
|
||||
|
||||
use super::org_source::OrgSource;
|
||||
@ -29,9 +31,11 @@ use crate::parser::util::text_until_exit;
|
||||
use crate::types::CommentBlock;
|
||||
use crate::types::ExampleBlock;
|
||||
use crate::types::ExportBlock;
|
||||
use crate::types::LineNumber;
|
||||
use crate::types::Object;
|
||||
use crate::types::PlainText;
|
||||
use crate::types::SrcBlock;
|
||||
use crate::types::SwitchNumberLines;
|
||||
use crate::types::VerseBlock;
|
||||
|
||||
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||
@ -130,7 +134,7 @@ pub(crate) fn example_block<'b, 'g, 'r, 's>(
|
||||
input: OrgSource<'s>,
|
||||
) -> Res<OrgSource<'s>, ExampleBlock<'s>> {
|
||||
let (remaining, _name) = lesser_block_begin("example")(context, input)?;
|
||||
let (remaining, parameters) = opt(tuple((space1, data)))(remaining)?;
|
||||
let (remaining, parameters) = opt(tuple((space1, example_switches)))(remaining)?;
|
||||
let (remaining, _nl) = recognize(tuple((space0, line_ending)))(remaining)?;
|
||||
let lesser_block_end_specialized = lesser_block_end("example");
|
||||
let contexts = [
|
||||
@ -150,13 +154,20 @@ 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) = {
|
||||
if let Some(parameters) = parameters {
|
||||
(Some(parameters.source), parameters.number_lines)
|
||||
} else {
|
||||
(None, None)
|
||||
}
|
||||
};
|
||||
Ok((
|
||||
remaining,
|
||||
ExampleBlock {
|
||||
source: source.into(),
|
||||
name: source.into(),
|
||||
switches: parameters.map(|parameters| Into::<&str>::into(parameters)),
|
||||
number_lines: None, // TODO
|
||||
switches,
|
||||
number_lines,
|
||||
contents: contents.into(),
|
||||
},
|
||||
))
|
||||
@ -302,3 +313,64 @@ fn _lesser_block_begin<'b, 'g, 'r, 's, 'c>(
|
||||
))(remaining)?;
|
||||
Ok((remaining, name))
|
||||
}
|
||||
|
||||
struct ExampleSwitches<'s> {
|
||||
source: &'s str,
|
||||
number_lines: Option<SwitchNumberLines>,
|
||||
}
|
||||
|
||||
enum SwitchState {
|
||||
Normal,
|
||||
NewLineNumber,
|
||||
ContinuedLineNumber,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||
fn example_switches<'s>(input: OrgSource<'s>) -> Res<OrgSource<'s>, ExampleSwitches<'s>> {
|
||||
let mut number_lines = None;
|
||||
let (remaining, (source, words)) = consumed(separated_list1(
|
||||
space1,
|
||||
map(is_not(" \t\r\n"), |val| Into::<&str>::into(val)),
|
||||
))(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 = word
|
||||
.parse::<LineNumber>()
|
||||
.expect("TODO: I should be able to return CustomError from nom parsers.");
|
||||
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));
|
||||
}
|
||||
SwitchState::Normal
|
||||
}
|
||||
(SwitchState::ContinuedLineNumber, _) => {
|
||||
let val = word
|
||||
.parse::<LineNumber>()
|
||||
.expect("TODO: I should be able to return CustomError from nom parsers.");
|
||||
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
|
||||
}
|
||||
(state @ SwitchState::Normal, _) => state,
|
||||
};
|
||||
}
|
||||
|
||||
Ok((
|
||||
remaining,
|
||||
ExampleSwitches {
|
||||
source: Into::<&str>::into(source),
|
||||
number_lines,
|
||||
},
|
||||
))
|
||||
}
|
||||
|
@ -108,7 +108,10 @@ pub struct LatexEnvironment<'s> {
|
||||
pub source: &'s str,
|
||||
}
|
||||
|
||||
pub type LineNumber = usize;
|
||||
/// A line number used in switches to lesser blocks.
|
||||
///
|
||||
/// This must be signed because emacs subtracts 1 from the actual value in the org-mode text, which makes a 0 turn into a -1.
|
||||
pub type LineNumber = isize;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum SwitchNumberLines {
|
||||
|
Loading…
Reference in New Issue
Block a user