Fix error handling after hashtag

This commit is contained in:
Laurenz 2023-02-17 16:32:48 +01:00
parent dd5f07eb91
commit 028632a3a1
26 changed files with 180 additions and 169 deletions

View File

@ -390,8 +390,8 @@ pub fn label(args: &mut Args) -> SourceResult<Value> {
/// The numbers 1 to 10. /// The numbers 1 to 10.
/// ///
/// // Works with string methods. /// // Works with string methods.
/// #{ "a,b;c" /// #("a,b;c"
/// .split(regex("[,;]")) } /// .split(regex("[,;]")))
/// ``` /// ```
/// ///
/// ## Parameters /// ## Parameters

View File

@ -517,16 +517,16 @@ mod tests {
fn test_captures() { fn test_captures() {
// Let binding and function definition. // Let binding and function definition.
test("#let x = x", &["x"]); test("#let x = x", &["x"]);
test("#let x; #{x + y}", &["y"]); test("#let x; #(x + y)", &["y"]);
test("#let f(x, y) = x + y", &[]); test("#let f(x, y) = x + y", &[]);
test("#let f(x, y) = f", &[]); test("#let f(x, y) = f", &[]);
test("#let f = (x, y) => f", &["f"]); test("#let f = (x, y) => f", &["f"]);
// Closure with different kinds of params. // Closure with different kinds of params.
test("#{(x, y) => x + z}", &["z"]); test("#((x, y) => x + z)", &["z"]);
test("#{(x: y, z) => x + z}", &["y"]); test("#((x: y, z) => x + z)", &["y"]);
test("#{(..x) => x + y}", &["y"]); test("#((..x) => x + y)", &["y"]);
test("#{(x, y: x + z) => x + y}", &["x", "z"]); test("#((x, y: x + z) => x + y)", &["x", "z"]);
test("#{x => x; x}", &["x"]); test("#{x => x; x}", &["x"]);
// Show rule. // Show rule.

View File

@ -133,7 +133,7 @@ impl Value {
format_str!("{:?}", self) format_str!("{:?}", self)
} }
/// Attach a span to the value, if possibly. /// Attach a span to the value, if possible.
pub fn spanned(self, span: Span) -> Self { pub fn spanned(self, span: Span) -> Self {
match self { match self {
Value::Content(v) => Value::Content(v.spanned(span)), Value::Content(v) => Value::Content(v.spanned(span)),

View File

@ -521,7 +521,14 @@ fn embedded_code_expr(p: &mut Parser) {
| SyntaxKind::Include | SyntaxKind::Include
); );
let prev = p.prev_end();
code_expr_prec(p, true, 0); code_expr_prec(p, true, 0);
// Consume error for things like `#12p` or `#"abc\"`.
if !p.progress(prev) {
p.unexpected();
}
let semi = p.eat_if(SyntaxKind::Semicolon); let semi = p.eat_if(SyntaxKind::Semicolon);
if stmt && !semi && !p.eof() && !p.at(SyntaxKind::RightBracket) { if stmt && !semi && !p.eof() && !p.at(SyntaxKind::RightBracket) {
p.expected("semicolon or line break"); p.expected("semicolon or line break");

View File

@ -7,21 +7,21 @@
#set page(width: 150pt) #set page(width: 150pt)
// Empty. // Empty.
#{()} #()
// Not an array, just a parenthesized expression. // Not an array, just a parenthesized expression.
#{(1)} #(1)
// One item and trailing comma. // One item and trailing comma.
#{(-1,)} #(-1,)
// No trailing comma. // No trailing comma.
#{(true, false)} #(true, false)
// Multiple lines and items and trailing comma. // Multiple lines and items and trailing comma.
#{("1" #("1"
, rgb("002") , rgb("002")
,)} ,)
--- ---
// Test the `len` method. // Test the `len` method.
@ -47,8 +47,8 @@
--- ---
// Test rvalue out of bounds. // Test rvalue out of bounds.
// Error: 3-18 array index out of bounds (index: 5, len: 3) // Error: 2-17 array index out of bounds (index: 5, len: 3)
#{(1, 2, 3).at(5)} #(1, 2, 3).at(5)
--- ---
// Test lvalue out of bounds. // Test lvalue out of bounds.
@ -60,15 +60,15 @@
--- ---
// Test bad lvalue. // Test bad lvalue.
// Error: 2:4-2:15 cannot mutate a temporary value // Error: 2:3-2:14 cannot mutate a temporary value
#let array = (1, 2, 3) #let array = (1, 2, 3)
#{ array.len() = 4 } #(array.len() = 4)
--- ---
// Test bad lvalue. // Test bad lvalue.
// Error: 2:4-2:16 type array has no method `yolo` // Error: 2:3-2:15 type array has no method `yolo`
#let array = (1, 2, 3) #let array = (1, 2, 3)
#{ array.yolo() = 4 } #(array.yolo() = 4)
--- ---
// Test negative indices. // Test negative indices.
@ -89,12 +89,12 @@
#test((1, 2, 3).last(), 3) #test((1, 2, 3).last(), 3)
--- ---
// Error: 4-14 array is empty // Error: 2-12 array is empty
#{ ().first() } #().first()
--- ---
// Error: 4-13 array is empty // Error: 2-11 array is empty
#{ ().last() } #().last()
--- ---
// Test the `push` and `pop` methods. // Test the `push` and `pop` methods.
@ -117,9 +117,9 @@
} }
--- ---
// Error: 2:18-2:20 missing argument: index // Error: 2:16-2:18 missing argument: index
#let numbers = () #let numbers = ()
#{ numbers.insert() } #numbers.insert()
--- ---
// Test the `slice` method. // Test the `slice` method.
@ -133,12 +133,12 @@
#test("ABCD".split("").slice(1, -1).join("-"), "A-B-C-D") #test("ABCD".split("").slice(1, -1).join("-"), "A-B-C-D")
--- ---
// Error: 4-32 array index out of bounds (index: 12, len: 10) // Error: 2-30 array index out of bounds (index: 12, len: 10)
#{ range(10).slice(9, count: 3) } #range(10).slice(9, count: 3)
--- ---
// Error: 4-26 array index out of bounds (index: -4, len: 3) // Error: 2-24 array index out of bounds (index: -4, len: 3)
#{ (1, 2, 3).slice(0, -4) } #(1, 2, 3).slice(0, -4)
--- ---
// Test the `position` method. // Test the `position` method.
@ -163,8 +163,8 @@
#test((1, 2, 3, 4).fold(0, (s, x) => s + x), 10) #test((1, 2, 3, 4).fold(0, (s, x) => s + x), 10)
--- ---
// Error: 22-32 function must have exactly two parameters // Error: 20-30 function must have exactly two parameters
#{ (1, 2, 3).fold(0, () => none) } #(1, 2, 3).fold(0, () => none)
--- ---
// Test the `rev` method. // Test the `rev` method.
@ -178,17 +178,17 @@
#test("(" + ("a", "b", "c").join(", ") + ")", "(a, b, c)") #test("(" + ("a", "b", "c").join(", ") + ")", "(a, b, c)")
--- ---
// Error: 3-23 cannot join boolean with boolean // Error: 2-22 cannot join boolean with boolean
#{(true, false).join()} #(true, false).join()
--- ---
// Error: 3-21 cannot join string with integer // Error: 2-20 cannot join string with integer
#{("a", "b").join(1)} #("a", "b").join(1)
--- ---
// Test joining content. // Test joining content.
// Ref: true // Ref: true
#{([One], [Two], [Three]).join([, ], last: [ and ])}. #([One], [Two], [Three]).join([, ], last: [ and ]).
--- ---
// Test the `sorted` method. // Test the `sorted` method.
@ -198,12 +198,12 @@
#test((2, 1, 3, 10, 5, 8, 6, -7, 2).sorted(), (-7, 1, 2, 2, 3, 5, 6, 8, 10)) #test((2, 1, 3, 10, 5, 8, 6, -7, 2).sorted(), (-7, 1, 2, 2, 3, 5, 6, 8, 10))
--- ---
// Error: 3-27 cannot order content and content // Error: 2-26 cannot order content and content
#{([Hi], [There]).sorted()} #([Hi], [There]).sorted()
--- ---
// Error: 3-19 array index out of bounds (index: -4, len: 3) // Error: 2-18 array index out of bounds (index: -4, len: 3)
#{(1, 2, 3).at(-4)} #(1, 2, 3).at(-4)
--- ---
// Error: 4 expected closing paren // Error: 4 expected closing paren
@ -212,23 +212,23 @@
// Error: 3-4 unexpected closing paren // Error: 3-4 unexpected closing paren
#{)} #{)}
// Error: 5-7 unexpected end of block comment // Error: 4-6 unexpected end of block comment
#{(1*/2)} #(1*/2)
// Error: 7-9 invalid number suffix // Error: 6-8 invalid number suffix
#{(1, 1u 2)} #(1, 1u 2)
// Error: 4-5 unexpected comma // Error: 3-4 unexpected comma
#{(,1)} #(,1)
// Missing expression makes named pair incomplete, making this an empty array. // Missing expression makes named pair incomplete, making this an empty array.
// Error: 6 expected expression // Error: 5 expected expression
#{(a:)} #(a:)
// Named pair after this is already identified as an array. // Named pair after this is already identified as an array.
// Error: 7-11 expected expression, found named pair // Error: 6-10 expected expression, found named pair
#{(1, b: 2)} #(1, b: 2)
// Keyed pair after this is already identified as an array. // Keyed pair after this is already identified as an array.
// Error: 7-15 expected expression, found keyed pair // Error: 6-14 expected expression, found keyed pair
#{(1, "key": 2)} #(1, "key": 2)

View File

@ -7,7 +7,7 @@
// ... but also "content" values. While these contain markup, // ... but also "content" values. While these contain markup,
// they are also values and can be summed, stored in arrays etc. // they are also values and can be summed, stored in arrays etc.
// There are also more standard control flow structures, like #if and #for. // There are also more standard control flow structures, like #if and #for.
#let university = [*Technische Universität #{city}*] #let university = [*Technische Universität #city*]
#let faculty = [*Fakultät II, Institut for Mathematik*] #let faculty = [*Fakultät II, Institut for Mathematik*]
// The `box` function just places content into a rectangular container. When // The `box` function just places content into a rectangular container. When

View File

@ -83,8 +83,8 @@
test(b, 1) test(b, 1)
}} }}
// Error: 3-4 unknown variable // Error: 2-3 unknown variable
#{b} #b
--- ---
// Multiple nested scopes. // Multiple nested scopes.
@ -106,14 +106,14 @@
// Content blocks also create a scope. // Content blocks also create a scope.
#[#let x = 1] #[#let x = 1]
// Error: 3-4 unknown variable // Error: 2-3 unknown variable
#{x} #x
--- ---
// Multiple unseparated expressions in one line. // Multiple unseparated expressions in one line.
// Error: 3-5 invalid number suffix // Error: 2-4 invalid number suffix
#{1u} #1u
// Should output `1`. // Should output `1`.
// Error: 4 expected semicolon or line break // Error: 4 expected semicolon or line break
@ -142,5 +142,5 @@
#{ #{
--- ---
// Error: 2 expected expression // Error: 2-3 unexpected closing brace
#} #}

View File

@ -48,8 +48,8 @@
#set text(family: "Arial", family: "Helvetica") #set text(family: "Arial", family: "Helvetica")
--- ---
// Error: 3-7 expected function, found boolean // Error: 2-6 expected function, found boolean
#{true()} #true()
--- ---
#let x = "x" #let x = "x"
@ -90,8 +90,8 @@
// Error: 7-12 expected identifier, found string // Error: 7-12 expected identifier, found string
#func("abc": 2) #func("abc": 2)
// Error: 8-11 expected identifier, found group // Error: 7-10 expected identifier, found group
#{func((x):1)} #func((x):1)
--- ---
// Error: 2:1 expected closing bracket // Error: 2:1 expected closing bracket

View File

@ -157,7 +157,7 @@
--- ---
// Error: 7-17 expected identifier, named pair or argument sink, found keyed pair // Error: 7-17 expected identifier, named pair or argument sink, found keyed pair
#{(a, "named": b) => none} #((a, "named": b) => none)
--- ---
// Error: 10-15 expected identifier, found string // Error: 10-15 expected identifier, found string

View File

@ -5,7 +5,7 @@
// Ref: true // Ref: true
// Empty // Empty
#{(:)} #(:)
// Two pairs and string key. // Two pairs and string key.
#let dict = (normal: 1, "spacy key": 2) #let dict = (normal: 1, "spacy key": 2)
@ -51,36 +51,36 @@
#test(dict.values(), (3, 1, 2)) #test(dict.values(), (3, 1, 2))
#test(dict.pairs().map(p => p.first() + str(p.last())).join(), "a3b1c2") #test(dict.pairs().map(p => p.first() + str(p.last())).join(), "a3b1c2")
#{ dict.remove("c") } #dict.remove("c")
#test("c" in dict, false) #test("c" in dict, false)
#test(dict, (a: 3, b: 1)) #test(dict, (a: 3, b: 1))
--- ---
// Error: 25-30 duplicate key // Error: 24-29 duplicate key
#{(first: 1, second: 2, first: 3)} #(first: 1, second: 2, first: 3)
--- ---
// Error: 18-21 duplicate key // Error: 17-20 duplicate key
#{(a: 1, "b": 2, "a": 3)} #(a: 1, "b": 2, "a": 3)
--- ---
// Simple expression after already being identified as a dictionary. // Simple expression after already being identified as a dictionary.
// Error: 10-11 expected named or keyed pair, found identifier // Error: 9-10 expected named or keyed pair, found identifier
#{(a: 1, b)} #(a: 1, b)
// Identified as dictionary due to initial colon. // Identified as dictionary due to initial colon.
// Error: 5-6 expected named or keyed pair, found integer // Error: 4-5 expected named or keyed pair, found integer
// Error: 6 expected comma // Error: 5 expected comma
// Error: 13-17 expected identifier or string, found boolean // Error: 12-16 expected identifier or string, found boolean
// Error: 18 expected expression // Error: 17 expected expression
#{(:1 b:"", true:)} #(:1 b:"", true:)
// Error: 4-9 expected identifier or string, found binary expression // Error: 3-8 expected identifier or string, found binary expression
#{(a + b: "hey")} #(a + b: "hey")
--- ---
// Error: 4-16 cannot mutate a temporary value // Error: 3-15 cannot mutate a temporary value
#{ (key: "val").other = "some" } #((key: "val").other = "some")
--- ---
#{ #{

View File

@ -23,12 +23,12 @@
- C - C
--- ---
// Error: 7-14 dictionary does not contain key "invalid" // Error: 6-13 dictionary does not contain key "invalid"
#{(:).invalid} #(:).invalid
--- ---
// Error: 9-11 cannot access fields on type boolean // Error: 8-10 cannot access fields on type boolean
#{false.ok} #false.ok
--- ---
// Error: 29-32 unknown field `fun` // Error: 29-32 unknown field `fun`

View File

@ -115,7 +115,7 @@
// Error: 6 expected block // Error: 6 expected block
#if x #if x
// Error: 2 expected expression // Error: 2-6 unexpected keyword `else`
#else {} #else {}
// Should output `x`. // Should output `x`.

View File

@ -49,8 +49,8 @@
#test((module,).at(0).item(1, 2), 3) #test((module,).at(0).item(1, 2), 3)
// Doesn't work because of mutating name. // Doesn't work because of mutating name.
// Error: 3-12 cannot mutate a temporary value // Error: 2-11 cannot mutate a temporary value
#{(module,).at(0).push()} #(module,).at(0).push()
--- ---
// Who needs whitespace anyways? // Who needs whitespace anyways?

View File

@ -27,20 +27,20 @@
} }
--- ---
// Error: 2:4-2:17 type array has no method `fun` // Error: 2:2-2:15 type array has no method `fun`
#let numbers = () #let numbers = ()
#{ numbers.fun() } #numbers.fun()
--- ---
// Error: 2:4-2:45 cannot mutate a temporary value // Error: 2:2-2:43 cannot mutate a temporary value
#let numbers = (1, 2, 3) #let numbers = (1, 2, 3)
#{ numbers.map(v => v / 2).sorted().map(str).remove(4) } #numbers.map(v => v / 2).sorted().map(str).remove(4)
--- ---
// Error: 2:4-2:20 cannot mutate a temporary value // Error: 2:3-2:19 cannot mutate a temporary value
#let numbers = (1, 2, 3) #let numbers = (1, 2, 3)
#{ numbers.sorted() = 1 } #(numbers.sorted() = 1)
--- ---
// Error: 4-7 cannot mutate a constant // Error: 2-5 cannot mutate a constant
#{ box.push(1) } #box.push(1)

View File

@ -3,7 +3,7 @@
--- ---
// Error: 4 expected expression // Error: 4 expected expression
#{-} #(-)
--- ---
// Error: 10 expected expression // Error: 10 expected expression
@ -15,40 +15,40 @@
--- ---
// Error: 3-13 cannot apply '+' to content // Error: 3-13 cannot apply '+' to content
#{+([] + [])} #(+([] + []))
--- ---
// Error: 3-6 cannot apply '-' to string // Error: 3-6 cannot apply '-' to string
#{-""} #(-"")
--- ---
// Error: 3-9 cannot apply 'not' to array // Error: 3-9 cannot apply 'not' to array
#{not ()} #(not ())
--- ---
// Error: 3-19 cannot apply '<=' to relative length and ratio // Error: 3-19 cannot apply '<=' to relative length and ratio
#{30% + 1pt <= 40%} #(30% + 1pt <= 40%)
--- ---
// Error: 3-14 cannot apply '<=' to length and length // Error: 3-14 cannot apply '<=' to length and length
#{1em <= 10pt} #(1em <= 10pt)
--- ---
// Error: 3-12 cannot divide by zero // Error: 3-12 cannot divide by zero
#{1.2 / 0.0} #(1.2 / 0.0)
--- ---
// Error: 3-8 cannot divide by zero // Error: 3-8 cannot divide by zero
#{1 / 0} #(1 / 0)
--- ---
// Error: 3-15 cannot divide by zero // Error: 3-15 cannot divide by zero
#{15deg / 0deg} #(15deg / 0deg)
--- ---
// Special messages for +, -, * and /. // Special messages for +, -, * and /.
// Error: 4-11 cannot add integer and string // Error: 3-10 cannot add integer and string
#{(1 + "2", 40% - 1)} #(1 + "2", 40% - 1)
--- ---
// Error: 15-23 cannot add integer and string // Error: 15-23 cannot add integer and string
@ -56,35 +56,35 @@
--- ---
// Error: 4-13 cannot divide ratio by length // Error: 4-13 cannot divide ratio by length
#{ 10% / 5pt } #( 10% / 5pt )
--- ---
// Error: 4-13 cannot divide these two lengths // Error: 3-12 cannot divide these two lengths
#{ 1em / 5pt } #(1em / 5pt)
--- ---
// Error: 4-20 cannot divide relative length by ratio // Error: 3-19 cannot divide relative length by ratio
#{ (10% + 1pt) / 5% } #((10% + 1pt) / 5%)
--- ---
// Error: 4-29 cannot divide these two relative lengths // Error: 3-28 cannot divide these two relative lengths
#{ (10% + 1pt) / (20% + 1pt) } #((10% + 1pt) / (20% + 1pt))
--- ---
// Error: 13-20 cannot subtract integer from ratio // Error: 13-20 cannot subtract integer from ratio
#{(1234567, 40% - 1)} #((1234567, 40% - 1))
--- ---
// Error: 3-11 cannot multiply integer with boolean // Error: 3-11 cannot multiply integer with boolean
#{2 * true} #(2 * true)
--- ---
// Error: 3-11 cannot divide integer by length // Error: 3-11 cannot divide integer by length
#{3 / 12pt} #(3 / 12pt)
--- ---
// Error: 3-10 cannot repeat this string -1 times // Error: 3-10 cannot repeat this string -1 times
#{-1 * ""} #(-1 * "")
--- ---
#{ #{
@ -97,32 +97,32 @@
} }
--- ---
// Error: 5-6 unknown variable // Error: 4-5 unknown variable
#{ (x) = "" } #((x) = "")
--- ---
// Error: 4-9 cannot mutate a temporary value // Error: 3-8 cannot mutate a temporary value
#{ 1 + 2 += 3 } #(1 + 2 += 3)
--- ---
// Error: 2:3-2:8 cannot apply 'not' to string // Error: 2:3-2:8 cannot apply 'not' to string
#let x = "Hey" #let x = "Hey"
#{not x = "a"} #(not x = "a")
--- ---
// Error: 8-9 unknown variable // Error: 7-8 unknown variable
#{ 1 + x += 3 } #(1 + x += 3)
--- ---
// Error: 4-5 unknown variable // Error: 3-4 unknown variable
#{ z = 1 } #(z = 1)
--- ---
// Error: 4-8 cannot mutate a constant // Error: 3-7 cannot mutate a constant
#{ rect = "hi" } #(rect = "hi")
--- ---
// Works if we define rect beforehand // Works if we define rect beforehand
// (since then it doesn't resolve to the standard library version anymore). // (since then it doesn't resolve to the standard library version anymore).
#let rect = "" #let rect = ""
#{ rect = "hi" } #(rect = "hi")

View File

@ -16,12 +16,12 @@
// Assignment binds stronger than boolean operations. // Assignment binds stronger than boolean operations.
// Error: 2:3-2:8 cannot mutate a temporary value // Error: 2:3-2:8 cannot mutate a temporary value
#let x = false #let x = false
#{not x = "a"} #(not x = "a")
--- ---
// Precedence doesn't matter for chained unary operators. // Precedence doesn't matter for chained unary operators.
// Error: 3-12 cannot apply '-' to boolean // Error: 3-12 cannot apply '-' to boolean
#{-not true} #(-not true)
--- ---
// Not in handles precedence. // Not in handles precedence.

View File

@ -4,7 +4,7 @@
--- ---
// Test adding content. // Test adding content.
// Ref: true // Ref: true
#{[*Hello* ] + [world!]} #([*Hello* ] + [world!])
--- ---
// Test math operators. // Test math operators.
@ -176,17 +176,17 @@
// Test assignment operators. // Test assignment operators.
#let x = 0 #let x = 0
#{ x = 10 } #test(x, 10) #(x = 10) #test(x, 10)
#{ x -= 5 } #test(x, 5) #(x -= 5) #test(x, 5)
#{ x += 1 } #test(x, 6) #(x += 1) #test(x, 6)
#{ x *= x } #test(x, 36) #(x *= x) #test(x, 36)
#{ x /= 2.0 } #test(x, 18.0) #(x /= 2.0) #test(x, 18.0)
#{ x = "some" } #test(x, "some") #(x = "some") #test(x, "some")
#{ x += "thing" } #test(x, "something") #(x += "thing") #test(x, "something")
--- ---
// Error: 4-7 cannot mutate a constant // Error: 3-6 cannot mutate a constant
#{ box = 1 } #(box = 1)
--- ---
// Test `in` operator. // Test `in` operator.
@ -205,7 +205,7 @@
--- ---
// Error: 10 expected keyword `in` // Error: 10 expected keyword `in`
#{"a" not} #("a" not)
--- ---
// Test `with` method. // Test `with` method.

View File

@ -20,15 +20,15 @@
#2.5rad \ #2.5rad \
#45deg \ #45deg \
#1.7em \ #1.7em \
#{1cm + 0em} \ #(1cm + 0em) \
#{2em + 10pt} \ #(2em + 10pt) \
#2.3fr #2.3fr
--- ---
// Colors and strokes. // Colors and strokes.
#set text(0.8em) #set text(0.8em)
#rgb("f7a205") \ #rgb("f7a205") \
#{2pt + rgb("f7a205")} #(2pt + rgb("f7a205"))
--- ---
// Strings and escaping. // Strings and escaping.
@ -45,4 +45,4 @@ Nothing
#let f(x) = x #let f(x) = x
#f #f
#rect #rect
#{() => none} #(() => none)

View File

@ -29,5 +29,5 @@ Forest
Ignored Ignored
--- ---
// Error: 5-20 show is only allowed directly in code and content blocks // Error: 4-19 show is only allowed directly in code and content blocks
#{ (show: body => 2) * body } #((show: body => 2) * body)

View File

@ -100,5 +100,5 @@ Another text.
#show red: [] #show red: []
--- ---
// Error: 8-26 show is only allowed directly in code and content blocks // Error: 7-25 show is only allowed directly in code and content blocks
#{ 1 + show heading: none } #(1 + show heading: none)

View File

@ -85,9 +85,9 @@
} }
--- ---
// Error: 12-18 cannot spread dictionary into array // Error: 11-17 cannot spread dictionary into array
#{(1, 2, ..(a: 1))} #(1, 2, ..(a: 1))
--- ---
// Error: 6-12 cannot spread array into dictionary // Error: 5-11 cannot spread array into dictionary
#{(..(1, 2), a: 1)} #(..(1, 2), a: 1)

View File

@ -13,12 +13,12 @@
#test("🏳🌈A🏳".last(), "🏳️‍⚧️") #test("🏳🌈A🏳".last(), "🏳️‍⚧️")
--- ---
// Error: 4-14 string is empty // Error: 2-12 string is empty
#{ "".first() } #"".first()
--- ---
// Error: 4-13 string is empty // Error: 2-11 string is empty
#{ "".last() } #"".last()
--- ---
// Test the `at` method. // Test the `at` method.
@ -150,8 +150,8 @@
#test("hello world".trim(regex(".")), "") #test("hello world".trim(regex(".")), "")
--- ---
// Error: 18-22 expected either `start` or `end` // Error: 17-21 expected either `start` or `end`
#{"abc".trim(at: left)} #"abc".trim(at: left)
--- ---
// Test the `split` method. // Test the `split` method.
@ -159,3 +159,7 @@
#test("abc".split("b"), ("a", "c")) #test("abc".split("b"), ("a", "c"))
#test("a123c".split(regex("\d")), ("a", "", "", "c")) #test("a123c".split(regex("\d")), ("a", "", "", "c"))
#test("a123c".split(regex("\d+")), ("a", "c")) #test("a123c".split(regex("\d+")), ("a", "c"))
---
// Error: 2:1 expected quote
#"hello\"

View File

@ -4,7 +4,7 @@
// Should output `2 4 6 8 10`. // Should output `2 4 6 8 10`.
#let i = 0 #let i = 0
#while i < 10 [ #while i < 10 [
#{ i += 2 } #(i += 2)
#i #i
] ]
@ -26,7 +26,7 @@
#test(while false {}, none) #test(while false {}, none)
#let i = 0 #let i = 0
#test(type(while i < 1 [#{ i += 1 }]), "content") #test(type(while i < 1 [#(i += 1)]), "content")
--- ---
// Condition must be boolean. // Condition must be boolean.

View File

@ -15,7 +15,7 @@
// Parsed as headings if at start of the context. // Parsed as headings if at start of the context.
/**/ = Level 1 /**/ = Level 1
#{[== Level 2]} #[== Level 2]
#box[=== Level 3] #box[=== Level 3]
// Not at the start of the context. // Not at the start of the context.

View File

@ -7,7 +7,7 @@ C #let x = 2;D #test(x, 2) \
E#if true [F]G \ E#if true [F]G \
H #if true{"I"} J \ H #if true{"I"} J \
K #if true [L] else []M \ K #if true [L] else []M \
#let c = true; N#while c [#{c = false}O] P \ #let c = true; N#while c [#(c = false)O] P \
#let c = true; Q #while c { c = false; "R" } S \ #let c = true; Q #while c { c = false; "R" } S \
T#for _ in (none,) {"U"}V T#for _ in (none,) {"U"}V

View File

@ -16,7 +16,7 @@
variant(fill: forest, stroke: black + 2pt), variant(fill: forest, stroke: black + 2pt),
variant(fill: forest, stroke: conifer + 2pt), variant(fill: forest, stroke: conifer + 2pt),
) { ) {
(align(horizon)[#{i + 1}.], item, []) (align(horizon)[#(i + 1).], item, [])
} }
#grid( #grid(