mirror of
https://github.com/typst/typst
synced 2025-05-14 17:15:28 +08:00
Parse import and include expressions
Co-Authored-By: Laurenz <laurmaedje@gmail.com>
This commit is contained in:
parent
0bfee5b777
commit
9f77f09aac
@ -146,6 +146,8 @@ impl Eval for Expr {
|
|||||||
Self::If(ref v) => v.eval(ctx),
|
Self::If(ref v) => v.eval(ctx),
|
||||||
Self::While(ref v) => v.eval(ctx),
|
Self::While(ref v) => v.eval(ctx),
|
||||||
Self::For(ref v) => v.eval(ctx),
|
Self::For(ref v) => v.eval(ctx),
|
||||||
|
Self::Import(ref v) => v.eval(ctx),
|
||||||
|
Self::Include(ref v) => v.eval(ctx),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -565,3 +567,19 @@ impl Eval for ForExpr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Eval for ImportExpr {
|
||||||
|
type Output = Value;
|
||||||
|
|
||||||
|
fn eval(&self, _: &mut EvalContext) -> Self::Output {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Eval for IncludeExpr {
|
||||||
|
type Output = Value;
|
||||||
|
|
||||||
|
fn eval(&self, _: &mut EvalContext) -> Self::Output {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -74,9 +74,15 @@ fn node(p: &mut Parser, at_start: &mut bool) -> Option<Node> {
|
|||||||
Token::UnicodeEscape(t) => Node::Text(unicode_escape(p, t)),
|
Token::UnicodeEscape(t) => Node::Text(unicode_escape(p, t)),
|
||||||
|
|
||||||
// Hashtag + keyword / identifier.
|
// Hashtag + keyword / identifier.
|
||||||
Token::Ident(_) | Token::Let | Token::If | Token::While | Token::For => {
|
Token::Ident(_)
|
||||||
|
| Token::Let
|
||||||
|
| Token::If
|
||||||
|
| Token::While
|
||||||
|
| Token::For
|
||||||
|
| Token::Import
|
||||||
|
| Token::Include => {
|
||||||
*at_start = false;
|
*at_start = false;
|
||||||
let stmt = token == Token::Let;
|
let stmt = token == Token::Let || token == Token::Import;
|
||||||
let group = if stmt { Group::Stmt } else { Group::Expr };
|
let group = if stmt { Group::Stmt } else { Group::Expr };
|
||||||
|
|
||||||
p.start_group(group, TokenMode::Code);
|
p.start_group(group, TokenMode::Code);
|
||||||
@ -279,6 +285,8 @@ fn primary(p: &mut Parser, atomic: bool) -> Option<Expr> {
|
|||||||
Some(Token::If) => expr_if(p),
|
Some(Token::If) => expr_if(p),
|
||||||
Some(Token::While) => expr_while(p),
|
Some(Token::While) => expr_while(p),
|
||||||
Some(Token::For) => expr_for(p),
|
Some(Token::For) => expr_for(p),
|
||||||
|
Some(Token::Import) => expr_import(p),
|
||||||
|
Some(Token::Include) => expr_include(p),
|
||||||
|
|
||||||
// Nothing.
|
// Nothing.
|
||||||
_ => {
|
_ => {
|
||||||
@ -331,7 +339,7 @@ fn parenthesized(p: &mut Parser) -> Option<Expr> {
|
|||||||
|
|
||||||
// Arrow means this is a closure's parameter list.
|
// Arrow means this is a closure's parameter list.
|
||||||
if p.eat_if(Token::Arrow) {
|
if p.eat_if(Token::Arrow) {
|
||||||
let params = params(p, items);
|
let params = idents(p, items);
|
||||||
let body = expr(p)?;
|
let body = expr(p)?;
|
||||||
return Some(Expr::Closure(ClosureExpr {
|
return Some(Expr::Closure(ClosureExpr {
|
||||||
span: span.join(body.span()),
|
span: span.join(body.span()),
|
||||||
@ -429,9 +437,9 @@ fn dict(p: &mut Parser, items: Vec<CallArg>, span: Span) -> Expr {
|
|||||||
Expr::Dict(DictExpr { span, items: items.collect() })
|
Expr::Dict(DictExpr { span, items: items.collect() })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert a collection into a parameter list, producing errors for anything
|
/// Convert a collection into a list of identifiers, producing errors for
|
||||||
/// other than identifiers.
|
/// anything other than identifiers.
|
||||||
fn params(p: &mut Parser, items: Vec<CallArg>) -> Vec<Ident> {
|
fn idents(p: &mut Parser, items: Vec<CallArg>) -> Vec<Ident> {
|
||||||
let items = items.into_iter().filter_map(|item| match item {
|
let items = items.into_iter().filter_map(|item| match item {
|
||||||
CallArg::Pos(Expr::Ident(id)) => Some(id),
|
CallArg::Pos(Expr::Ident(id)) => Some(id),
|
||||||
_ => {
|
_ => {
|
||||||
@ -511,24 +519,24 @@ fn expr_let(p: &mut Parser) -> Option<Expr> {
|
|||||||
let mut expr_let = None;
|
let mut expr_let = None;
|
||||||
if let Some(binding) = ident(p) {
|
if let Some(binding) = ident(p) {
|
||||||
// If a parenthesis follows, this is a function definition.
|
// If a parenthesis follows, this is a function definition.
|
||||||
let mut parameters = None;
|
let mut params = None;
|
||||||
if p.peek_direct() == Some(Token::LeftParen) {
|
if p.peek_direct() == Some(Token::LeftParen) {
|
||||||
p.start_group(Group::Paren, TokenMode::Code);
|
p.start_group(Group::Paren, TokenMode::Code);
|
||||||
let items = collection(p).0;
|
let items = collection(p).0;
|
||||||
parameters = Some(params(p, items));
|
params = Some(idents(p, items));
|
||||||
p.end_group();
|
p.end_group();
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut init = None;
|
let mut init = None;
|
||||||
if p.eat_if(Token::Eq) {
|
if p.eat_if(Token::Eq) {
|
||||||
init = expr(p);
|
init = expr(p);
|
||||||
} else if parameters.is_some() {
|
} else if params.is_some() {
|
||||||
// Function definitions must have a body.
|
// Function definitions must have a body.
|
||||||
p.expected_at("body", p.end());
|
p.expected_at("body", p.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rewrite into a closure expression if it's a function definition.
|
// Rewrite into a closure expression if it's a function definition.
|
||||||
if let Some(params) = parameters {
|
if let Some(params) = params {
|
||||||
let body = init?;
|
let body = init?;
|
||||||
init = Some(Expr::Closure(ClosureExpr {
|
init = Some(Expr::Closure(ClosureExpr {
|
||||||
span: binding.span.join(body.span()),
|
span: binding.span.join(body.span()),
|
||||||
@ -548,6 +556,54 @@ fn expr_let(p: &mut Parser) -> Option<Expr> {
|
|||||||
expr_let
|
expr_let
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parse an import expression.
|
||||||
|
fn expr_import(p: &mut Parser) -> Option<Expr> {
|
||||||
|
let start = p.start();
|
||||||
|
p.assert(Token::Import);
|
||||||
|
|
||||||
|
let mut expr_import = None;
|
||||||
|
if let Some(path) = expr(p) {
|
||||||
|
if p.expect(Token::Using) {
|
||||||
|
let imports = if p.eat_if(Token::Star) {
|
||||||
|
// This is the wildcard scenario.
|
||||||
|
Imports::Wildcard
|
||||||
|
} else {
|
||||||
|
// This is the list of identifier scenario.
|
||||||
|
p.start_group(Group::Expr, TokenMode::Code);
|
||||||
|
let items = collection(p).0;
|
||||||
|
if items.is_empty() {
|
||||||
|
p.expected_at("import items", p.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
let idents = idents(p, items);
|
||||||
|
p.end_group();
|
||||||
|
Imports::Idents(idents)
|
||||||
|
};
|
||||||
|
|
||||||
|
expr_import = Some(Expr::Import(ImportExpr {
|
||||||
|
span: p.span(start),
|
||||||
|
imports,
|
||||||
|
path: Box::new(path),
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
expr_import
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parse an include expression.
|
||||||
|
fn expr_include(p: &mut Parser) -> Option<Expr> {
|
||||||
|
let start = p.start();
|
||||||
|
p.assert(Token::Include);
|
||||||
|
|
||||||
|
expr(p).map(|path| {
|
||||||
|
Expr::Include(IncludeExpr {
|
||||||
|
span: p.span(start),
|
||||||
|
path: Box::new(path),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Parse an if expresion.
|
/// Parse an if expresion.
|
||||||
fn expr_if(p: &mut Parser) -> Option<Expr> {
|
fn expr_if(p: &mut Parser) -> Option<Expr> {
|
||||||
let start = p.start();
|
let start = p.start();
|
||||||
|
@ -46,9 +46,6 @@ pub enum Group {
|
|||||||
Bracket,
|
Bracket,
|
||||||
/// A curly-braced group: `{...}`.
|
/// A curly-braced group: `{...}`.
|
||||||
Brace,
|
Brace,
|
||||||
/// A group ended by a chained subheader or a closing bracket:
|
|
||||||
/// `... >>`, `...]`.
|
|
||||||
Subheader,
|
|
||||||
/// A group ended by a semicolon or a line break: `;`, `\n`.
|
/// A group ended by a semicolon or a line break: `;`, `\n`.
|
||||||
Stmt,
|
Stmt,
|
||||||
/// A group for a single expression, ended by a line break.
|
/// A group for a single expression, ended by a line break.
|
||||||
@ -129,7 +126,6 @@ impl<'s> Parser<'s> {
|
|||||||
Group::Paren => self.assert(Token::LeftParen),
|
Group::Paren => self.assert(Token::LeftParen),
|
||||||
Group::Bracket => self.assert(Token::LeftBracket),
|
Group::Bracket => self.assert(Token::LeftBracket),
|
||||||
Group::Brace => self.assert(Token::LeftBrace),
|
Group::Brace => self.assert(Token::LeftBrace),
|
||||||
Group::Subheader => {}
|
|
||||||
Group::Stmt => {}
|
Group::Stmt => {}
|
||||||
Group::Expr => {}
|
Group::Expr => {}
|
||||||
}
|
}
|
||||||
@ -152,7 +148,6 @@ impl<'s> Parser<'s> {
|
|||||||
Group::Paren => Some((Token::RightParen, true)),
|
Group::Paren => Some((Token::RightParen, true)),
|
||||||
Group::Bracket => Some((Token::RightBracket, true)),
|
Group::Bracket => Some((Token::RightBracket, true)),
|
||||||
Group::Brace => Some((Token::RightBrace, true)),
|
Group::Brace => Some((Token::RightBrace, true)),
|
||||||
Group::Subheader => None,
|
|
||||||
Group::Stmt => Some((Token::Semicolon, false)),
|
Group::Stmt => Some((Token::Semicolon, false)),
|
||||||
Group::Expr => None,
|
Group::Expr => None,
|
||||||
} {
|
} {
|
||||||
@ -365,7 +360,6 @@ impl<'s> Parser<'s> {
|
|||||||
Token::RightBracket => self.inside(Group::Bracket),
|
Token::RightBracket => self.inside(Group::Bracket),
|
||||||
Token::RightBrace => self.inside(Group::Brace),
|
Token::RightBrace => self.inside(Group::Brace),
|
||||||
Token::Semicolon => self.inside(Group::Stmt),
|
Token::Semicolon => self.inside(Group::Stmt),
|
||||||
Token::Pipe => self.inside(Group::Subheader),
|
|
||||||
Token::Space(n) => n >= 1 && self.stop_at_newline(),
|
Token::Space(n) => n >= 1 && self.stop_at_newline(),
|
||||||
_ => false,
|
_ => false,
|
||||||
} {
|
} {
|
||||||
|
@ -124,7 +124,6 @@ impl<'s> Iterator for Tokens<'s> {
|
|||||||
',' => Token::Comma,
|
',' => Token::Comma,
|
||||||
';' => Token::Semicolon,
|
';' => Token::Semicolon,
|
||||||
':' => Token::Colon,
|
':' => Token::Colon,
|
||||||
'|' => Token::Pipe,
|
|
||||||
'+' => Token::Plus,
|
'+' => Token::Plus,
|
||||||
'-' => Token::Hyph,
|
'-' => Token::Hyph,
|
||||||
'*' => Token::Star,
|
'*' => Token::Star,
|
||||||
@ -456,6 +455,9 @@ fn keyword(id: &str) -> Option<Token<'static>> {
|
|||||||
"break" => Token::Break,
|
"break" => Token::Break,
|
||||||
"continue" => Token::Continue,
|
"continue" => Token::Continue,
|
||||||
"return" => Token::Return,
|
"return" => Token::Return,
|
||||||
|
"import" => Token::Import,
|
||||||
|
"include" => Token::Include,
|
||||||
|
"using" => Token::Using,
|
||||||
_ => return None,
|
_ => return None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -617,7 +619,6 @@ mod tests {
|
|||||||
t!(Code: "," => Comma);
|
t!(Code: "," => Comma);
|
||||||
t!(Code: ";" => Semicolon);
|
t!(Code: ";" => Semicolon);
|
||||||
t!(Code: ":" => Colon);
|
t!(Code: ":" => Colon);
|
||||||
t!(Code: "|" => Pipe);
|
|
||||||
t!(Code: "+" => Plus);
|
t!(Code: "+" => Plus);
|
||||||
t!(Code: "-" => Hyph);
|
t!(Code: "-" => Hyph);
|
||||||
t!(Code[" a1"]: "*" => Star);
|
t!(Code[" a1"]: "*" => Star);
|
||||||
@ -637,7 +638,6 @@ mod tests {
|
|||||||
t!(Code: "=>" => Arrow);
|
t!(Code: "=>" => Arrow);
|
||||||
|
|
||||||
// Test combinations.
|
// Test combinations.
|
||||||
t!(Code: "|=>" => Pipe, Arrow);
|
|
||||||
t!(Code: "<=>" => LtEq, Gt);
|
t!(Code: "<=>" => LtEq, Gt);
|
||||||
t!(Code[" a/"]: "..." => Dots, Invalid("."));
|
t!(Code[" a/"]: "..." => Dots, Invalid("."));
|
||||||
|
|
||||||
|
@ -229,6 +229,8 @@ impl Pretty for Expr {
|
|||||||
Self::If(v) => v.pretty(p),
|
Self::If(v) => v.pretty(p),
|
||||||
Self::While(v) => v.pretty(p),
|
Self::While(v) => v.pretty(p),
|
||||||
Self::For(v) => v.pretty(p),
|
Self::For(v) => v.pretty(p),
|
||||||
|
Self::Import(v) => v.pretty(p),
|
||||||
|
Self::Include(v) => v.pretty(p),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -434,6 +436,31 @@ impl Pretty for ForPattern {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Pretty for ImportExpr {
|
||||||
|
fn pretty(&self, p: &mut Printer) {
|
||||||
|
p.push_str("import ");
|
||||||
|
self.path.pretty(p);
|
||||||
|
p.push_str(" using ");
|
||||||
|
self.imports.pretty(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Pretty for Imports {
|
||||||
|
fn pretty(&self, p: &mut Printer) {
|
||||||
|
match self {
|
||||||
|
Self::Wildcard => p.push('*'),
|
||||||
|
Self::Idents(idents) => p.join(idents, ", ", |item, p| item.pretty(p)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Pretty for IncludeExpr {
|
||||||
|
fn pretty(&self, p: &mut Printer) {
|
||||||
|
p.push_str("include ");
|
||||||
|
self.path.pretty(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Pretty for Ident {
|
impl Pretty for Ident {
|
||||||
fn pretty(&self, p: &mut Printer) {
|
fn pretty(&self, p: &mut Printer) {
|
||||||
p.push_str(self.as_str());
|
p.push_str(self.as_str());
|
||||||
|
@ -56,6 +56,10 @@ pub enum Expr {
|
|||||||
While(WhileExpr),
|
While(WhileExpr),
|
||||||
/// A for loop expression: `for x in y { z }`.
|
/// A for loop expression: `for x in y { z }`.
|
||||||
For(ForExpr),
|
For(ForExpr),
|
||||||
|
/// An import expression: `import "utils.typ" using a, b, c`.
|
||||||
|
Import(ImportExpr),
|
||||||
|
/// An include expression: `include "chapter1.typ"`.
|
||||||
|
Include(IncludeExpr),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Expr {
|
impl Expr {
|
||||||
@ -85,6 +89,8 @@ impl Expr {
|
|||||||
Self::If(ref v) => v.span,
|
Self::If(ref v) => v.span,
|
||||||
Self::While(ref v) => v.span,
|
Self::While(ref v) => v.span,
|
||||||
Self::For(ref v) => v.span,
|
Self::For(ref v) => v.span,
|
||||||
|
Self::Import(ref v) => v.span,
|
||||||
|
Self::Include(ref v) => v.span,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -432,6 +438,35 @@ pub struct LetExpr {
|
|||||||
pub init: Option<Box<Expr>>,
|
pub init: Option<Box<Expr>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An import expression: `import "utils.typ" using a, b, c`.
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub struct ImportExpr {
|
||||||
|
/// The source code location.
|
||||||
|
pub span: Span,
|
||||||
|
/// The items to be imported.
|
||||||
|
pub imports: Imports,
|
||||||
|
/// The location of the importable file.
|
||||||
|
pub path: Box<Expr>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The items that ought to be imported from a file.
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub enum Imports {
|
||||||
|
/// All items in the scope of the file should be imported.
|
||||||
|
Wildcard,
|
||||||
|
/// The specified identifiers from the file should be imported.
|
||||||
|
Idents(Vec<Ident>),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An include expression: `include "chapter1.typ"`.
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub struct IncludeExpr {
|
||||||
|
/// The source code location.
|
||||||
|
pub span: Span,
|
||||||
|
/// The location of the file to be included.
|
||||||
|
pub path: Box<Expr>,
|
||||||
|
}
|
||||||
|
|
||||||
/// An if-else expression: `if x { y } else { z }`.
|
/// An if-else expression: `if x { y } else { z }`.
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct IfExpr {
|
pub struct IfExpr {
|
||||||
|
@ -32,8 +32,6 @@ pub enum Token<'s> {
|
|||||||
Semicolon,
|
Semicolon,
|
||||||
/// A colon: `:`.
|
/// A colon: `:`.
|
||||||
Colon,
|
Colon,
|
||||||
/// A pipe: `|`.
|
|
||||||
Pipe,
|
|
||||||
/// A plus: `+`.
|
/// A plus: `+`.
|
||||||
Plus,
|
Plus,
|
||||||
/// A hyphen: `-`.
|
/// A hyphen: `-`.
|
||||||
@ -90,6 +88,12 @@ pub enum Token<'s> {
|
|||||||
Continue,
|
Continue,
|
||||||
/// The `return` keyword.
|
/// The `return` keyword.
|
||||||
Return,
|
Return,
|
||||||
|
/// The `import` keyword.
|
||||||
|
Import,
|
||||||
|
/// The `include` keyword.
|
||||||
|
Include,
|
||||||
|
/// The `using` keyword.
|
||||||
|
Using,
|
||||||
/// One or more whitespace characters.
|
/// One or more whitespace characters.
|
||||||
///
|
///
|
||||||
/// The contained `usize` denotes the number of newlines that were contained
|
/// The contained `usize` denotes the number of newlines that were contained
|
||||||
@ -201,7 +205,6 @@ impl<'s> Token<'s> {
|
|||||||
Self::Comma => "comma",
|
Self::Comma => "comma",
|
||||||
Self::Semicolon => "semicolon",
|
Self::Semicolon => "semicolon",
|
||||||
Self::Colon => "colon",
|
Self::Colon => "colon",
|
||||||
Self::Pipe => "pipe",
|
|
||||||
Self::Plus => "plus",
|
Self::Plus => "plus",
|
||||||
Self::Hyph => "minus",
|
Self::Hyph => "minus",
|
||||||
Self::Slash => "slash",
|
Self::Slash => "slash",
|
||||||
@ -231,6 +234,9 @@ impl<'s> Token<'s> {
|
|||||||
Self::Break => "keyword `break`",
|
Self::Break => "keyword `break`",
|
||||||
Self::Continue => "keyword `continue`",
|
Self::Continue => "keyword `continue`",
|
||||||
Self::Return => "keyword `return`",
|
Self::Return => "keyword `return`",
|
||||||
|
Self::Import => "keyword `import`",
|
||||||
|
Self::Include => "keyword `include`",
|
||||||
|
Self::Using => "keyword `using`",
|
||||||
Self::Space(_) => "space",
|
Self::Space(_) => "space",
|
||||||
Self::Text(_) => "text",
|
Self::Text(_) => "text",
|
||||||
Self::Raw(_) => "raw block",
|
Self::Raw(_) => "raw block",
|
||||||
|
@ -87,6 +87,8 @@ visit! {
|
|||||||
Expr::If(e) => v.visit_if(e),
|
Expr::If(e) => v.visit_if(e),
|
||||||
Expr::While(e) => v.visit_while(e),
|
Expr::While(e) => v.visit_while(e),
|
||||||
Expr::For(e) => v.visit_for(e),
|
Expr::For(e) => v.visit_for(e),
|
||||||
|
Expr::Import(e) => v.visit_import(e),
|
||||||
|
Expr::Include(e) => v.visit_include(e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,4 +191,17 @@ visit! {
|
|||||||
v.visit_expr(&node.iter);
|
v.visit_expr(&node.iter);
|
||||||
v.visit_expr(&node.body);
|
v.visit_expr(&node.body);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_import(v, node: &ImportExpr) {
|
||||||
|
v.visit_expr(&node.path);
|
||||||
|
if let Imports::Idents(idents) = &node.imports {
|
||||||
|
for ident in idents {
|
||||||
|
v.visit_binding(ident);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_include(v, node: &IncludeExpr) {
|
||||||
|
v.visit_expr(&node.path);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -119,7 +119,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "keyword.other.typst",
|
"name": "keyword.other.typst",
|
||||||
"match": "(#)(from|in)\\b",
|
"match": "(#)(in|using|as)\\b",
|
||||||
"captures": { "1": { "name": "punctuation.definition.keyword.typst" } }
|
"captures": { "1": { "name": "punctuation.definition.keyword.typst" } }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -159,6 +159,15 @@
|
|||||||
},
|
},
|
||||||
"patterns": [{ "include": "#code" }]
|
"patterns": [{ "include": "#code" }]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"begin": "(#)include\\b",
|
||||||
|
"end": "\n|(?=])",
|
||||||
|
"beginCaptures": {
|
||||||
|
"0": { "name": "keyword.control.include.typst" },
|
||||||
|
"1": { "name": "punctuation.definition.keyword.typst" }
|
||||||
|
},
|
||||||
|
"patterns": [{ "include": "#code" }]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"comment": "Function name",
|
"comment": "Function name",
|
||||||
"name": "entity.name.function.typst",
|
"name": "entity.name.function.typst",
|
||||||
@ -216,7 +225,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "keyword.other.typst",
|
"name": "keyword.other.typst",
|
||||||
"match": "\\b(pub|let|import|from)\\b"
|
"match": "\\b(pub|let|import|include|using|as)\\b"
|
||||||
},
|
},
|
||||||
{ "include": "#constants" },
|
{ "include": "#constants" },
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user