Skip to content

Commit 98907e2

Browse files
committed
Implement escape markdown, handle trailing literal sections
1 parent e566500 commit 98907e2

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
@@ -254,7 +254,7 @@ fn parse_at_keyword(p: &mut impl Parser) {
254254
}
255255
"markdown" => {
256256
parse_markdown(p);
257-
},
257+
}
258258
_ => {
259259
p.consume();
260260
p.test(SyntaxKind::Identifier); // consume the identifier, so that autocomplete works
@@ -444,7 +444,7 @@ fn parse_markdown(p: &mut impl Parser) {
444444
debug_assert!(p.peek().as_str().ends_with("markdown"));
445445
p.expect(SyntaxKind::Identifier); //eg "markdown"
446446
p.expect(SyntaxKind::LParent);
447-
447+
448448
fn consume_literal(p: &mut impl Parser) -> bool {
449449
let peek = p.peek();
450450
if peek.kind() != SyntaxKind::StringLiteral

internal/compiler/passes/resolving.rs

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -704,16 +704,16 @@ impl Expression {
704704
}
705705
}
706706
}
707-
707+
708708
fn from_at_markdown(node: syntax_nodes::AtMarkdown, ctx: &mut LookupCtx) -> Expression {
709-
let Some(string) = std::dbg!(node
710-
.child_text(SyntaxKind::StringLiteral))
709+
let Some(string) = node
710+
.child_text(SyntaxKind::StringLiteral)
711711
.and_then(|s| crate::literals::unescape_string(&s))
712712
else {
713713
ctx.diag.push_error("Cannot parse string literal".into(), &node);
714714
return Expression::Invalid;
715715
};
716-
716+
717717
let subs = node.Expression().map(|n| {
718718
Expression::from_expression_node(n.clone(), ctx).maybe_convert_to(
719719
Type::String,
@@ -722,10 +722,9 @@ impl Expression {
722722
)
723723
});
724724
let values = subs.collect::<Vec<_>>();
725-
std::dbg!(&values);
726725

727726
let mut expr = None;
728-
727+
729728
// check format string
730729
{
731730
let mut arg_idx = 0;
@@ -774,19 +773,28 @@ impl Expression {
774773
break;
775774
};
776775
let argument = &string[p + 1..end];
777-
if argument.is_empty() {
776+
let argument_index = if argument.is_empty() {
777+
let argument_index = arg_idx;
778778
arg_idx += 1;
779+
argument_index
779780
} else if let Ok(n) = argument.parse::<u16>() {
780781
pos_max = pos_max.max(n as usize + 1);
782+
n as usize
781783
} else {
782784
ctx.diag
783785
.push_error("Invalid '{...}' placeholder in format string. The placeholder must be a number, or braces must be escaped with '{{' and '}}'".into(), &node);
784786
break;
785787
};
786788
let add = Expression::BinaryExpression {
787-
lhs: Box::new(Expression::StringLiteral((&string[literal_start_pos..p]).into())),
789+
lhs: Box::new(Expression::StringLiteral(
790+
(&string[literal_start_pos..p]).into(),
791+
)),
788792
op: '+',
789-
rhs: Box::new(values[arg_idx-1].clone())
793+
rhs: Box::new(Expression::FunctionCall {
794+
function: BuiltinFunction::EscapeMarkdown.into(),
795+
arguments: vec![values[argument_index].clone()],
796+
source_location: Some(node.to_source_location()),
797+
}),
790798
};
791799
expr = Some(match expr {
792800
None => add,
@@ -799,6 +807,17 @@ impl Expression {
799807
pos = end + 1;
800808
literal_start_pos = pos;
801809
}
810+
{
811+
let trailing = Expression::StringLiteral((&string[literal_start_pos..]).into());
812+
expr = Some(match expr {
813+
None => trailing,
814+
Some(expr) => Expression::BinaryExpression {
815+
lhs: Box::new(expr),
816+
op: '+',
817+
rhs: Box::new(trailing),
818+
},
819+
});
820+
}
802821
if arg_idx > 0 && pos_max > 0 {
803822
ctx.diag.push_error(
804823
"Cannot mix positional and non-positional placeholder in format string".into(),
@@ -810,16 +829,13 @@ impl Expression {
810829
format!("Format string contains {num} placeholders, but only {} extra arguments were given", values.len()),
811830
&node,
812831
);
813-
}
832+
}
814833
}
815-
816-
std::dbg!(&expr);
817834

818835
Expression::FunctionCall {
819836
function: BuiltinFunction::ParseMarkdown.into(),
820837
arguments: vec![
821-
expr.unwrap()//Expression::StringLiteral(string),
822-
838+
expr.unwrap_or_else(|| Expression::default_value_for_type(&Type::String))
823839
],
824840
source_location: Some(node.to_source_location()),
825841
}

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
@@ -1399,12 +1399,12 @@ fn call_builtin_function(
13991399
BuiltinFunction::EscapeMarkdown => {
14001400
let text: SharedString =
14011401
eval_expression(&arguments[0], local_context).try_into().unwrap();
1402-
Value::String(corelib::escape_markdown(&text).into())
1402+
Value::String(corelib::escape_markdown(&text).into())
14031403
}
14041404
BuiltinFunction::ParseMarkdown => {
14051405
let text: SharedString =
14061406
eval_expression(&arguments[0], local_context).try_into().unwrap();
1407-
Value::String(corelib::parse_markdown(&text).into())
1407+
Value::String(corelib::parse_markdown(&text).into())
14081408
}
14091409
}
14101410
}

0 commit comments

Comments
 (0)