Skip to content

Commit

Permalink
[LaTeX] xparse command definition support (#3585)
Browse files Browse the repository at this point in the history
This commit adds support for xparse package.

see: https://mirror.informatik.hs-fulda.de/tex-archive/macros/latex/contrib/l3packages/xparse.pdf

Co-authored-by: deathaxe <[email protected]>
  • Loading branch information
ngc92 and deathaxe authored Nov 26, 2022
1 parent 45dc6d9 commit e4b0425
Show file tree
Hide file tree
Showing 3 changed files with 605 additions and 16 deletions.
183 changes: 167 additions & 16 deletions LaTeX/LaTeX.sublime-syntax
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ contexts:
scope: punctuation.definition.group.brace.begin.latex
push: brace-group-body

brace-group-begin:
- meta_include_prototype: false
- match: \{
scope: punctuation.definition.group.brace.begin.latex
pop: true

brace-group-body:
- meta_scope: meta.group.brace.latex
- include: brace-group-end
Expand Down Expand Up @@ -83,26 +89,34 @@ contexts:
- include: general-optional-arguments
- include: else-pop

###[ MACROS ]##################################################################

macros:
- meta_append: true
- include: latex-newcommand-macros
- include: xparse-newcommand-macros

###[ LATEX NEWCOMMAND MACROS ]#################################################

latex-newcommand-macros:
- match: (\\)(?:new|renew|provide)command(?:\*|(?![A-Za-z@]))
scope: keyword.declaration.function.latex storage.modifier.newcommand.latex
captures:
1: punctuation.definition.backslash.latex
push:
- newcommand-definition
- newcommand-optarg
- newcommand-argspec
- newcommand-commandname
- latex-newcommand-definition
- latex-newcommand-optarg
- latex-newcommand-argspec
- latex-newcommand-commandname
- match: (\\)DeclareMathOperator(?:\*|(?![A-Za-z@]))
scope: support.function.declare-math-operator.latex storage.modifier.newcommand.latex
captures:
1: punctuation.definition.backslash.latex
push:
- newcommand-definition
- newcommand-commandname
- latex-newcommand-definition
- latex-newcommand-commandname

newcommand-argspec:
latex-newcommand-argspec:
- match: \[
scope: punctuation.definition.group.bracket.begin.latex
push:
Expand All @@ -119,14 +133,14 @@ contexts:
- include: paragraph-pop
- include: else-pop

newcommand-optarg:
latex-newcommand-optarg:
- match: \[
scope: punctuation.definition.group.bracket.begin.latex
push: newcommand-optarg-body
push: latex-newcommand-optarg-body
- include: paragraph-pop
- include: else-pop

newcommand-optarg-body:
latex-newcommand-optarg-body:
- clear_scopes: 1
- meta_scope: meta.function.parameters.default-value.latex
- match: \]
Expand All @@ -136,7 +150,7 @@ contexts:
- include: general-commands
- include: macro-braces

newcommand-commandname:
latex-newcommand-commandname:
# version one: brace-wrapped command name
- match: \{
scope: punctuation.definition.group.brace.begin.latex
Expand Down Expand Up @@ -167,19 +181,18 @@ contexts:

# we need a separate context for command definitions, because they can contain
# un-balanced elements.
newcommand-definition:
latex-newcommand-definition:
- meta_scope: meta.function.latex
- match: (?=\{)
set:
- def-function-body-meta
- macro-braces-begin
- match: (?=\\)
set: newcommand-expression
set: latex-newcommand-expression
- include: paragraph-pop
- include: else-pop


newcommand-expression:
latex-newcommand-expression:
- meta_scope: meta.function.body.latex
# but in principle, a single token is also valid,
# thus either a command sequence ...
Expand All @@ -198,6 +211,145 @@ contexts:
- include: paragraph-pop
- include: else-pop

###[ XPARSE NEWCOMMAND MACROS ]################################################

xparse-newcommand-macros:
# https://www.ctan.org/pkg/xparse
- match: (\\)(?:(?:New|Renew|Provide|Declare)(:?Expandable)?DocumentCommand){{endcs}}
scope: keyword.declaration.function.latex storage.modifier.newcommand.latex
captures:
1: punctuation.definition.backslash.latex
push:
- latex-newcommand-definition
- xparse-newcommand-argspec
- latex-newcommand-commandname

xparse-newcommand-argspec:
- match: (?=\{)
set:
- xparse-newcommand-argspec-body
- brace-group-begin
- include: paragraph-pop
- include: else-pop

xparse-newcommand-argspec-body:
- clear_scopes: 1
- meta_scope: meta.function.parameters.latex
- include: brace-group-end
- include: macro-braces
- include: xparse-newcommand-single-argspec
# not actually allowed, but included here to future-proof highlighting
- include: general-constants
- include: general-commands
- include: paragraph-pop

xparse-newcommand-single-argspec:
# modifiers and simple specs
- match: '[+!]'
scope: storage.modifier.latex
- match: '[movsb]'
scope: storage.type.latex
- match: t
scope: storage.type.latex
push: xparse-newcommand-args-token
# delimited arguments without default
- match: '[rd]'
scope: storage.type.latex
push:
- xparse-newcommand-args-token
- xparse-newcommand-args-token
# delimited arguments with default
- match: '[RD]'
scope: storage.type.latex
push:
- xparse-newcommand-optarg-value
- xparse-newcommand-args-token
- xparse-newcommand-args-token
# optional argument with default
- match: O
scope: storage.type.latex
push: xparse-newcommand-optarg-value
# embellishment argument
- match: e
scope: storage.type.latex
push: xparse-newcommand-args-token
# embellishment argument with default
- match: E
scope: storage.type.latex
push:
- xparse-newcommand-optarg-value
- xparse-newcommand-args-token
# argument processors
- match: '>'
scope: storage.modifier.latex

xparse-newcommand-args-token:
- meta_include_prototype: false
- include: unmatched-brace-pop
- match: (?={)
set:
- xparse-newcommand-args-wrapped-token
- brace-group-begin
- match: (?=\S)
set: xparse-newcommand-args-bare-token
- include: paragraph-pop

xparse-newcommand-args-bare-token:
# either a command
- match: (\\){{cmdname}}{{endcs}}
scope: constant.other.token.latex
captures:
1: punctuation.definition.backslash.latex
pop: 1
# or a single character
- match: \S
scope: constant.character.latex constant.other.token.latex
pop: 1
- include: paragraph-pop

xparse-newcommand-args-wrapped-token:
- meta_scope: meta.group.brace.latex
- include: brace-group-end
# either a command
- match: (\\){{cmdname}}{{endcs}}
scope: constant.other.token.latex
captures:
1: punctuation.definition.backslash.latex
# or a single character
- match: \S
scope: constant.character.latex constant.other.token.latex

xparse-newcommand-optarg-value:
- meta_include_prototype: false
- include: unmatched-brace-pop
- match: (?={)
set:
- xparse-newcommand-optarg-wrapped-value
- brace-group-begin
- match: (?=\S)
set: xparse-newcommand-optarg-bare-value
- include: paragraph-pop

xparse-newcommand-optarg-bare-value:
- clear_scopes: 1
- meta_scope: meta.function.parameters.default-value.latex
- match: (\\){{cmdname}}{{endcs}}
scope: support.function.latex
captures:
1: punctuation.definition.backslash.latex
pop: 1
- match: \S
pop: 1
- include: paragraph-pop

xparse-newcommand-optarg-wrapped-value:
- clear_scopes: 1
- meta_scope: meta.function.parameters.default-value.latex meta.group.brace.latex
- include: brace-group-end
- include: macro-braces-content

###[ CONSTANTS ]###############################################################

general-constants:
- meta_prepend: true
- match: (\\\\)(?:(\[)\s*-?((?:[[:digit:]]|\.)*)\s*(\w*)\s*(\]))?
Expand Down Expand Up @@ -566,7 +718,6 @@ contexts:
scope: punctuation.definition.verb.latex
pop: true


text-decorators:
- match: ((\\)emph)(\{)
captures:
Expand Down
10 changes: 10 additions & 0 deletions LaTeX/TeX.sublime-syntax
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,12 @@ contexts:
scope: punctuation.definition.group.brace.begin.tex
push: brace-group-body

brace-group-begin:
- meta_include_prototype: false
- match: \{
scope: punctuation.definition.group.brace.begin.tex
pop: true

brace-group-body:
- meta_scope: meta.group.brace.tex
- include: brace-group-end
Expand Down Expand Up @@ -645,3 +651,7 @@ contexts:
paragraph-pop:
- match: ^(?=\s*$)
pop: true

unmatched-brace-pop:
- match: (?=})
pop: true
Loading

0 comments on commit e4b0425

Please sign in to comment.