Skip to content

Commit d229515

Browse files
committed
Implement escape markdown, handle trailing literal sections
1 parent a3e7396 commit d229515

File tree

4 files changed

+51
-22
lines changed

4 files changed

+51
-22
lines changed

internal/compiler/parser/expressions.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ fn parse_at_keyword(p: &mut impl Parser) {
257257
}
258258
"markdown" => {
259259
parse_markdown(p);
260-
},
260+
}
261261
_ => {
262262
p.consume();
263263
p.test(SyntaxKind::Identifier); // consume the identifier, so that autocomplete works
@@ -447,7 +447,7 @@ fn parse_markdown(p: &mut impl Parser) {
447447
debug_assert!(p.peek().as_str().ends_with("markdown"));
448448
p.expect(SyntaxKind::Identifier); //eg "markdown"
449449
p.expect(SyntaxKind::LParent);
450-
450+
451451
fn consume_literal(p: &mut impl Parser) -> bool {
452452
let peek = p.peek();
453453
if peek.kind() != SyntaxKind::StringLiteral

internal/compiler/passes/resolving.rs

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -745,16 +745,16 @@ impl Expression {
745745
}
746746
}
747747
}
748-
748+
749749
fn from_at_markdown(node: syntax_nodes::AtMarkdown, ctx: &mut LookupCtx) -> Expression {
750-
let Some(string) = std::dbg!(node
751-
.child_text(SyntaxKind::StringLiteral))
750+
let Some(string) = node
751+
.child_text(SyntaxKind::StringLiteral)
752752
.and_then(|s| crate::literals::unescape_string(&s))
753753
else {
754754
ctx.diag.push_error("Cannot parse string literal".into(), &node);
755755
return Expression::Invalid;
756756
};
757-
757+
758758
let subs = node.Expression().map(|n| {
759759
Expression::from_expression_node(n.clone(), ctx).maybe_convert_to(
760760
Type::String,
@@ -763,10 +763,9 @@ impl Expression {
763763
)
764764
});
765765
let values = subs.collect::<Vec<_>>();
766-
std::dbg!(&values);
767766

768767
let mut expr = None;
769-
768+
770769
// check format string
771770
{
772771
let mut arg_idx = 0;
@@ -815,19 +814,28 @@ impl Expression {
815814
break;
816815
};
817816
let argument = &string[p + 1..end];
818-
if argument.is_empty() {
817+
let argument_index = if argument.is_empty() {
818+
let argument_index = arg_idx;
819819
arg_idx += 1;
820+
argument_index
820821
} else if let Ok(n) = argument.parse::<u16>() {
821822
pos_max = pos_max.max(n as usize + 1);
823+
n as usize
822824
} else {
823825
ctx.diag
824826
.push_error("Invalid '{...}' placeholder in format string. The placeholder must be a number, or braces must be escaped with '{{' and '}}'".into(), &node);
825827
break;
826828
};
827829
let add = Expression::BinaryExpression {
828-
lhs: Box::new(Expression::StringLiteral((&string[literal_start_pos..p]).into())),
830+
lhs: Box::new(Expression::StringLiteral(
831+
(&string[literal_start_pos..p]).into(),
832+
)),
829833
op: '+',
830-
rhs: Box::new(values[arg_idx-1].clone())
834+
rhs: Box::new(Expression::FunctionCall {
835+
function: BuiltinFunction::EscapeMarkdown.into(),
836+
arguments: vec![values[argument_index].clone()],
837+
source_location: Some(node.to_source_location()),
838+
}),
831839
};
832840
expr = Some(match expr {
833841
None => add,
@@ -840,6 +848,17 @@ impl Expression {
840848
pos = end + 1;
841849
literal_start_pos = pos;
842850
}
851+
{
852+
let trailing = Expression::StringLiteral((&string[literal_start_pos..]).into());
853+
expr = Some(match expr {
854+
None => trailing,
855+
Some(expr) => Expression::BinaryExpression {
856+
lhs: Box::new(expr),
857+
op: '+',
858+
rhs: Box::new(trailing),
859+
},
860+
});
861+
}
843862
if arg_idx > 0 && pos_max > 0 {
844863
ctx.diag.push_error(
845864
"Cannot mix positional and non-positional placeholder in format string".into(),
@@ -851,16 +870,13 @@ impl Expression {
851870
format!("Format string contains {num} placeholders, but only {} extra arguments were given", values.len()),
852871
&node,
853872
);
854-
}
873+
}
855874
}
856-
857-
std::dbg!(&expr);
858875

859876
Expression::FunctionCall {
860877
function: BuiltinFunction::ParseMarkdown.into(),
861878
arguments: vec![
862-
expr.unwrap()//Expression::StringLiteral(string),
863-
879+
expr.unwrap_or_else(|| Expression::default_value_for_type(&Type::String))
864880
],
865881
source_location: Some(node.to_source_location()),
866882
}

internal/core/lib.rs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -173,12 +173,25 @@ pub fn open_url(url: &str) {
173173
}
174174
}
175175

176-
pub fn escape_markdown(text: &str) -> std::string::String {
177-
std::dbg!(text);
178-
text.into()
176+
pub fn escape_markdown(text: &str) -> std::string::String {
177+
let mut out = std::string::String::with_capacity(text.len());
178+
179+
for c in text.chars() {
180+
match c {
181+
'*' => out.push_str("\\*"),
182+
'<' => out.push_str("&lt;"),
183+
'>' => out.push_str("&gt;"),
184+
'_' => out.push_str("\\_"),
185+
'#' => out.push_str("\\#"),
186+
'-' => out.push_str("\\-"),
187+
'`' => out.push_str("\\`"),
188+
_ => out.push(c),
189+
}
190+
}
191+
192+
out
179193
}
180194

181195
pub fn parse_markdown(text: &str) -> std::string::String {
182-
std::dbg!(text);
183196
text.into()
184197
}

internal/interpreter/eval.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1420,12 +1420,12 @@ fn call_builtin_function(
14201420
BuiltinFunction::EscapeMarkdown => {
14211421
let text: SharedString =
14221422
eval_expression(&arguments[0], local_context).try_into().unwrap();
1423-
Value::String(corelib::escape_markdown(&text).into())
1423+
Value::String(corelib::escape_markdown(&text).into())
14241424
}
14251425
BuiltinFunction::ParseMarkdown => {
14261426
let text: SharedString =
14271427
eval_expression(&arguments[0], local_context).try_into().unwrap();
1428-
Value::String(corelib::parse_markdown(&text).into())
1428+
Value::String(corelib::parse_markdown(&text).into())
14291429
}
14301430
}
14311431
}

0 commit comments

Comments
 (0)