Handle escaping the characters in org macro arguments.
This commit is contained in:
parent
a32cea8139
commit
a6adeee40b
7
org_mode_samples/object/macro/escape.org
Normal file
7
org_mode_samples/object/macro/escape.org
Normal file
@ -0,0 +1,7 @@
|
||||
{{{foo}}}
|
||||
|
||||
{{{fo\o}}}
|
||||
|
||||
{{{foo(b\ar)}}}
|
||||
|
||||
{{{foo(b\,r)}}}
|
@ -149,8 +149,8 @@ pub(crate) fn compare_property_list_of_quoted_string<
|
||||
if e != r {
|
||||
let this_status = DiffStatus::Bad;
|
||||
let message = Some(format!(
|
||||
"{} mismatch (emacs != rust) {:?} != {:?}",
|
||||
emacs_field, value, rust_value
|
||||
"{} mismatch (emacs != rust) {:?} != {:?}. Full list: {:?} != {:?}",
|
||||
emacs_field, e, r, value, rust_value
|
||||
));
|
||||
return Ok(Some((this_status, message)));
|
||||
}
|
||||
|
@ -243,3 +243,149 @@ enum CoalesceWhitespace {
|
||||
Normal,
|
||||
HasWhitespace { in_whitespace: bool, ret: String },
|
||||
}
|
||||
|
||||
/// Removes all whitespace from a string and handle escaping characters.
|
||||
///
|
||||
/// Example: "foo bar" => "foobar" and "foo \n bar" => "foobar" but if the escape character is backslash and comma is an escapable character than "foo\,bar" becomes "foo,bar".
|
||||
pub(crate) fn coalesce_whitespace_escaped<'c, C: Fn(char) -> bool>(
|
||||
escape_character: char,
|
||||
escapable_characters: C,
|
||||
) -> impl for<'s> Fn(&'s str) -> Cow<'s, str> {
|
||||
move |input| impl_coalesce_whitespace_escaped(input, escape_character, &escapable_characters)
|
||||
}
|
||||
|
||||
fn impl_coalesce_whitespace_escaped<'s, C: Fn(char) -> bool>(
|
||||
input: &'s str,
|
||||
escape_character: char,
|
||||
escapable_characters: C,
|
||||
) -> Cow<'s, str> {
|
||||
let mut state = CoalesceWhitespaceEscaped::Normal;
|
||||
for (offset, c) in input.char_indices() {
|
||||
state = match (state, c) {
|
||||
(CoalesceWhitespaceEscaped::Normal, c) if c == escape_character => {
|
||||
CoalesceWhitespaceEscaped::NormalEscaping {
|
||||
escape_offset: offset,
|
||||
}
|
||||
}
|
||||
(CoalesceWhitespaceEscaped::Normal, ' ' | '\t' | '\r' | '\n') => {
|
||||
let mut ret = String::with_capacity(input.len());
|
||||
ret.push_str(&input[..offset]);
|
||||
ret.push(' ');
|
||||
CoalesceWhitespaceEscaped::RequiresMutation {
|
||||
in_whitespace: true,
|
||||
ret,
|
||||
}
|
||||
}
|
||||
(CoalesceWhitespaceEscaped::Normal, _) => CoalesceWhitespaceEscaped::Normal,
|
||||
(CoalesceWhitespaceEscaped::NormalEscaping { escape_offset }, c)
|
||||
if escapable_characters(c) =>
|
||||
{
|
||||
// We escaped a character so we need mutation
|
||||
let mut ret = String::with_capacity(input.len());
|
||||
ret.push_str(&input[..escape_offset]);
|
||||
ret.push(c);
|
||||
CoalesceWhitespaceEscaped::RequiresMutation {
|
||||
in_whitespace: false,
|
||||
ret,
|
||||
}
|
||||
}
|
||||
|
||||
(
|
||||
CoalesceWhitespaceEscaped::NormalEscaping { escape_offset: _ },
|
||||
' ' | '\t' | '\r' | '\n',
|
||||
) => {
|
||||
// We didn't escape the character but we hit whitespace anyway.
|
||||
let mut ret = String::with_capacity(input.len());
|
||||
ret.push_str(&input[..offset]);
|
||||
ret.push(' ');
|
||||
CoalesceWhitespaceEscaped::RequiresMutation {
|
||||
in_whitespace: true,
|
||||
ret,
|
||||
}
|
||||
}
|
||||
(CoalesceWhitespaceEscaped::NormalEscaping { escape_offset: _ }, _) => {
|
||||
// We didn't escape the character so continue as normal.
|
||||
CoalesceWhitespaceEscaped::Normal
|
||||
}
|
||||
|
||||
(
|
||||
CoalesceWhitespaceEscaped::RequiresMutation {
|
||||
in_whitespace: _,
|
||||
ret,
|
||||
},
|
||||
c,
|
||||
) if c == escape_character => {
|
||||
CoalesceWhitespaceEscaped::RequiresMutationEscaping { ret }
|
||||
}
|
||||
(
|
||||
CoalesceWhitespaceEscaped::RequiresMutation {
|
||||
mut in_whitespace,
|
||||
mut ret,
|
||||
},
|
||||
' ' | '\t' | '\r' | '\n',
|
||||
) => {
|
||||
if !in_whitespace {
|
||||
in_whitespace = true;
|
||||
ret.push(' ');
|
||||
}
|
||||
CoalesceWhitespaceEscaped::RequiresMutation { in_whitespace, ret }
|
||||
}
|
||||
(
|
||||
CoalesceWhitespaceEscaped::RequiresMutation {
|
||||
in_whitespace,
|
||||
mut ret,
|
||||
},
|
||||
_,
|
||||
) => {
|
||||
ret.push(c);
|
||||
CoalesceWhitespaceEscaped::RequiresMutation {
|
||||
in_whitespace: false,
|
||||
ret,
|
||||
}
|
||||
}
|
||||
(CoalesceWhitespaceEscaped::RequiresMutationEscaping { mut ret }, c)
|
||||
if escapable_characters(c) =>
|
||||
{
|
||||
ret.push(c);
|
||||
CoalesceWhitespaceEscaped::RequiresMutation {
|
||||
in_whitespace: false,
|
||||
ret,
|
||||
}
|
||||
}
|
||||
(
|
||||
CoalesceWhitespaceEscaped::RequiresMutationEscaping { mut ret },
|
||||
' ' | '\t' | '\r' | '\n',
|
||||
) => {
|
||||
ret.push(' ');
|
||||
CoalesceWhitespaceEscaped::RequiresMutation {
|
||||
in_whitespace: true,
|
||||
ret,
|
||||
}
|
||||
}
|
||||
(CoalesceWhitespaceEscaped::RequiresMutationEscaping { mut ret }, c) => {
|
||||
ret.push(escape_character);
|
||||
ret.push(c);
|
||||
// TODO
|
||||
CoalesceWhitespaceEscaped::RequiresMutation {
|
||||
in_whitespace: false,
|
||||
ret,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// match state {
|
||||
// CoalesceWhitespaceEscaped::Normal => Cow::Borrowed(input),
|
||||
// CoalesceWhitespaceEscaped::RequiresMutation {
|
||||
// in_whitespace: _,
|
||||
// ret,
|
||||
// } => Cow::Owned(ret),
|
||||
// }
|
||||
todo!()
|
||||
}
|
||||
|
||||
enum CoalesceWhitespaceEscaped {
|
||||
Normal,
|
||||
NormalEscaping { escape_offset: usize },
|
||||
RequiresMutation { in_whitespace: bool, ret: String },
|
||||
RequiresMutationEscaping { ret: String },
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user