Vendor vim-plugins/vim-typst=308e7737d09

This commit is contained in:
Dmitry Bogatov 2023-12-31 15:57:14 -05:00
commit 91ab5402c3
15 changed files with 3681 additions and 0 deletions

View File

@ -8,5 +8,10 @@
"rev": "master",
"sha1": "8e735f84d2d954229ee65f4dc71bfc0bec897d98",
"url": "https://github.com/ledger/vim-ledger"
},
"vim-plugins/vim-typst": {
"rev": "main",
"sha1": "308e7737d09de8c1100320ddc6bc270615ae791a",
"url": "https://github.com/kaarmu/typst.vim"
}
}

2
vim-plugins/vim-typst/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*.swp

View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2023 Kaj Munhoz Arfvidsson
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,108 @@
# typst.vim
*OBS: Work In Progress*
(Neo)vim plugin for [Typst](https://typst.app).
I am applying the 80/20 rule in this project since I prefer to have
something now rather than waiting for everything later.
## Features
![image](https://user-images.githubusercontent.com/19633647/230785889-0d449fc3-747b-4183-b00b-14c0ea8dd590.png)
*Editing [typst-palette](https://github.com/kaarmu/typst-palette) in Vim with the gruvbox colorscheme*
**Existing**
- Vim syntax highlighting.
- Compile the active document with `:make`.
- Concealing for italic, bold. Can be enabled with `g:typst_conceal`.
- Concealing symbols in math mode. Can be enabled with `g:typst_conceal_math`.
- Emojis! Can be enabled with `g:typst_conceal_emoji`.
- Syntax highlighting of code blocks. See `g:typst_embedded_languages`.
**Possible features**
- Formatting using [this](https://github.com/astrale-sharp/typst-fmt/)?
- Even better highlighting for neovim using treesitter?
Do you miss anything from other packages, e.g. `vimtex`, create an issue
and I'll probably add it! Also feel free to make a PR!
## Installation
### packer.nvim
```lua
require('packer').startup(function(use)
use {'kaarmu/typst.vim', ft = {'typst'}}
end)
```
- Call `:so %` or restart neovim to reload config
- Call `:PackerSync`
### lazy.nvim
```lua
return {
'kaarmu/typst.vim',
ft = 'typst',
lazy=false,
}
```
### vim-plug
```vim
call plug#begin('~/.vim/plugged')
Plug 'kaarmu/typst.vim'
call plug#end()
```
- Restart (neo)vim to reload config
- Call `:PlugInstall`
## Usage
### Options
- `g:typst_cmd`:
Specifies the location of the Typst executable.
*Default:* `'typst'`
- `g:typst_pdf_viewer`:
Specifies pdf viewer that `typst watch --open` will use.
*Default:* `''`
- `gtypst_conceal`:
Enable concealment.
*Default:* `0`
- `g:typst_conceal_math`:
Enable concealment for math symbols in math mode (i.e. replaces symbols
with their actual unicode character). **OBS**: this can affect performance,
see issue [#64](https://github.com/kaarmu/typst.vim/issues/64).
*Default:* `g:typst_conceal`
- `g:typst_conceal_emoji`:
Enable concealing emojis, e.g. `#emoji.alien` becomes 👽.
*Default:* `g:typst_conceal`
- `g:typst_auto_close_toc`:
Specifies whether TOC will be automatically closed after using it.
*Default:* `0`
- `g:typst_auto_open_quickfix`:
Specifies whether the quickfix list should automatically open when there are errors from typst.
*Default:* `1`
- `g:typst_embedded_languages`:
A list of languages that will be highlighted in code blocks. Typst is always highlighted.
*Default:* `[]`
### Commands
- `:TypstWatch`:
Watches your document and recompiles on change; also opens the document with your default pdf viewer.
## Tips
If you are using `neovim` you can install [typst-lsp](https://github.com/nvarner/typst-lsp).
There exist a server configuration in `nvim-lspconfig` so it should be easy to set it up. The
config currently requires that you're working in a git repo. Once the neovim+LSP recognizes
the file the LSP will compile your document while you write (almost like a wysiwyg!). By default
it will compile on save but you can set it to compile-on-write as well.

View File

@ -0,0 +1,291 @@
function! typst#TypstWatch(...)
" Prepare command
" NOTE: added arguments #23 but they will always be like
" `typst <args> watch <file> --open` so in the future this might be
" sensitive to in which order typst options should come.
let l:cmd = g:typst_cmd
\ . ' ' . join(a:000)
\ . ' watch'
\ . ' --diagnostic-format short'
\ . " '" . expand('%') . "'"
if !empty(g:typst_pdf_viewer)
let l:cmd = l:cmd . ' --open ' . g:typst_pdf_viewer
else
let l:cmd = l:cmd . ' --open'
endif
" Write message
echom 'Starting: ' . l:cmd
let l:str = has('win32')
\ ? 'cmd /s /c "' . l:cmd . '"'
\ : 'sh -c "' . l:cmd . '"'
if has('nvim')
let l:JobStart = function('jobstart')
let l:JobStop = function('jobstop')
let l:options = {'on_stderr': 'typst#TypstWatcherCb'}
else
let l:JobStart = function('job_start')
let l:JobStop = function('job_stop')
let l:options = {'err_mode': 'raw',
\'err_cb': 'typst#TypstWatcherCb'}
endif
if exists('s:watcher') " && job_status(s:watcher) == 'run'
" echoerr 'TypstWatch is already running.'
call l:JobStop(s:watcher)
endif
let s:watcher = l:JobStart(l:str, l:options)
endfunction
" Callback function for job exit
function! typst#TypstWatcherCb(channel, content, ...)
let l:errors = []
let l:lines = a:content
if !has('nvim')
let l:lines = split(l:lines, "\n")
endif
for l:line in l:lines
" Probably this match can be done using errorformat.
" Maybe do something like vim-dispatch.
let l:match = matchlist(l:line, '\v^([^:]+):(\d+):(\d+):\s*(.+)$')
if 0 < len(l:match)
let l:error = {'filename': l:match[1],
\'lnum': l:match[2],
\'col': l:match[3],
\'text': l:match[4]}
call add(l:errors, l:error)
endif
endfor
call setqflist(l:errors)
if g:typst_auto_open_quickfix
execute empty(l:errors) ? 'cclose' : 'copen'
endif
endfunction
" Below are adapted from preservim/vim-markdown
" They have their own MIT License at https://github.com/preservim/vim-markdown#license
let s:headersRegexp = '^='
" For each level, contains the regexp that matches at that level only.
"
let s:levelRegexpDict = {
\ 1: '^=[^=]',
\ 2: '^==[^=]',
\ 3: '^===[^=]',
\ 4: '^====[^=]',
\ 5: '^=====[^=]',
\ 6: '^======[^=]'
\ }
" Returns the level of the header at the given line.
"
" If there is no header at the given line, returns `0`.
"
function! s:GetLevelOfHeaderAtLine(linenum)
let l:lines = join(getline(a:linenum, a:linenum + 1), "\n")
for l:key in keys(s:levelRegexpDict)
if l:lines =~ get(s:levelRegexpDict, l:key)
return l:key
endif
endfor
return 0
endfunction
function! s:GetHeaderLineNum(...)
if a:0 == 0
let l:l = line('.')
else
let l:l = a:1
endif
while(l:l > 0)
if join(getline(l:l, l:l + 1), "\n") =~ s:headersRegexp
return l:l
endif
let l:l -= 1
endwhile
return 0
endfunction
function! s:GetHeaderLevel(...)
if a:0 == 0
let l:line = line('.')
else
let l:line = a:1
endif
let l:linenum = s:GetHeaderLineNum(l:line)
if l:linenum !=# 0
return s:GetLevelOfHeaderAtLine(l:linenum)
else
return 0
endif
endfunction
function! s:GetHeaderList()
let l:bufnr = bufnr('%')
let l:fenced_block = 0
let l:front_matter = 0
let l:header_list = []
let l:vim_markdown_frontmatter = get(g:, 'vim_markdown_frontmatter', 0)
for i in range(1, line('$'))
let l:lineraw = getline(i)
let l:l1 = getline(i+1)
let l:line = substitute(l:lineraw, '#', "\\\#", 'g')
if join(getline(i, i + 1), "\n") =~# s:headersRegexp && l:line =~# '^\S'
let l:is_header = 1
else
let l:is_header = 0
endif
if l:is_header ==# 1 && l:fenced_block ==# 0 && l:front_matter ==# 0
if match(l:line, '^#') > -1
let l:line = substitute(l:line, '\v^#*[ ]*', '', '')
let l:line = substitute(l:line, '\v[ ]*#*$', '', '')
endif
let l:level = s:GetHeaderLevel(i)
let l:item = {'level': l:level, 'text': l:line, 'lnum': i, 'bufnr': bufnr}
let l:header_list = l:header_list + [l:item]
endif
endfor
return l:header_list
endfunction
function! typst#Toc(...)
if a:0 > 0
let l:window_type = a:1
else
let l:window_type = 'vertical'
endif
let l:cursor_line = line('.')
let l:cursor_header = 0
let l:header_list = s:GetHeaderList()
let l:indented_header_list = []
if len(l:header_list) == 0
echom 'Toc: No headers.'
return
endif
let l:header_max_len = 0
let l:vim_markdown_toc_autofit = get(g:, 'vim_markdown_toc_autofit', 0)
for h in l:header_list
if l:cursor_header == 0
let l:header_line = h.lnum
if l:header_line == l:cursor_line
let l:cursor_header = index(l:header_list, h) + 1
elseif l:header_line > l:cursor_line
let l:cursor_header = index(l:header_list, h)
endif
endif
let l:text = repeat(' ', h.level-1) . h.text
let l:total_len = strdisplaywidth(l:text)
if l:total_len > l:header_max_len
let l:header_max_len = l:total_len
endif
let l:item = {'lnum': h.lnum, 'text': l:text, 'valid': 1, 'bufnr': h.bufnr, 'col': 1}
let l:indented_header_list = l:indented_header_list + [l:item]
endfor
" Open the TOC buffer in a new window
let l:orig_winid = win_getid()
let l:toc_bufnr = bufnr('TOC', 1)
" execute 'sbuffer ' . l:toc_bufnr
if a:0 > 0
if a:1 == 'vertical'
execute 'vsplit +buffer' . l:toc_bufnr
if (&columns/2) > l:header_max_len && l:vim_markdown_toc_autofit == 1
execute 'vertical resize ' . (l:header_max_len + 1 + 3)
else
execute 'vertical resize ' . (&columns/2)
endif
elseif a:1 == 'tab'
execute 'tabnew | buffer' . l:toc_bufnr
else
execute 'sbuffer ' . l:toc_bufnr
endif
else
execute 'sbuffer ' . l:toc_bufnr
endif
setlocal buftype=nofile
setlocal bufhidden=delete
call setbufline(l:toc_bufnr, 1, map(copy(l:indented_header_list), 'v:val.text'))
let b:indented_header_list = l:indented_header_list
let b:orig_winid = l:orig_winid
" Define a mapping to jump to the corresponding line in the original file when a line is clicked
nnoremap <buffer> <silent> <Enter> :call <SID>JumpToHeader()<CR>
" Move the cursor to the current header in the TOC
execute 'normal! ' . l:cursor_header . 'G'
endfunction
function! s:JumpToHeader()
let l:lnum = line('.')
let l:header_info = b:indented_header_list[l:lnum - 1]
let l:orig_winid = b:orig_winid
call win_execute(l:orig_winid, 'buffer ' . l:header_info.bufnr)
call win_execute(l:orig_winid, 'normal! ' . l:header_info.lnum . 'G')
if g:typst_auto_close_toc
bwipeout!
endif
call win_gotoid(l:orig_winid)
endfunction
" Detect context for #51
" Detects the inner most syntax group under the cursor by default.
function! typst#synstack(kwargs = {}) abort
let l:pos = get(a:kwargs, 'pos', getcurpos()[1:3])
let l:only_inner = get(a:kwargs, 'only_inner', v:true)
if mode() ==# 'i'
let l:pos[1] -= 1
endif
call map(l:pos, 'max([v:val, 1])')
let l:stack = map(synstack(l:pos[0], l:pos[1]), "synIDattr(v:val, 'name')")
return l:only_inner ? l:stack[-1:] : l:stack
endfunction
function! typst#in_markup(...) abort
let l:stack = call('typst#synstack', a:000)
let l:ret = empty(l:stack)
for l:name in l:stack
let l:ret = l:ret
\ || l:name =~? '^typstMarkup'
\ || l:name =~? 'Bracket$'
endfor
return l:ret
endfunction
function! typst#in_code(...) abort
let l:ret = v:false
for l:name in call('typst#synstack', a:000)
let l:ret = l:ret
\ || l:name =~? '^typstCode'
\ || l:name =~? 'Brace$'
endfor
return l:ret
endfunction
function! typst#in_math(...) abort
let l:ret = v:false
for l:name in call('typst#synstack', a:000)
let l:ret = l:ret
\ || l:name =~? '^typstMath'
\ || l:name =~? 'Dollar$'
endfor
return l:ret
endfunction
function! typst#in_comment(...) abort
let l:ret = v:false
for l:name in call('typst#synstack', a:000)
let l:ret = l:ret
\ || l:name =~? '^typstComment'
endfor
return l:ret
endfunction

View File

@ -0,0 +1,34 @@
" Vim compiler file
" Compiler: typst
if exists("current_compiler")
finish
endif
let current_compiler = g:typst_cmd
let s:save_cpo = &cpo
set cpo&vim
if exists(":CompilerSet") != 2
command -nargs=* CompilerSet setlocal <args>
endif
" With `--diagnostic-format` we can use the default errorformat
let s:makeprg = [current_compiler, 'compile',
\ '--diagnostic-format', 'short']
if has('patch-7.4.191')
call add(s:makeprg, '%:S')
else
call add(s:makeprg, '%')
endif
" This style of `CompilerSet makeprg` is non-typical. The reason is that I
" want to avoid a long string of escaped spaces and we can very succinctly
" build makeprg. You cannot write something like this `CompilerSet
" makeprg=s:makeprg`.
execute 'CompilerSet makeprg=' . join(s:makeprg, '\ ')
let &cpo = s:save_cpo
unlet s:save_cpo
" vim: tabstop=8 shiftwidth=4 softtabstop=4 expandtab

View File

@ -0,0 +1 @@
autocmd! BufRead,BufNewFile *.typ set filetype=typst

View File

@ -0,0 +1,57 @@
" Only do this when not done yet for this buffer
if exists("b:did_ftplugin")
finish
endif
function! s:declare_option(option, value)
if !exists('g:'..a:option)
exec 'let g:'..a:option..' = '..string(a:value)
endif
endfunction
call s:declare_option('typst_cmd', 'typst')
call s:declare_option('typst_pdf_viewer', '')
call s:declare_option('typst_conceal', 0)
call s:declare_option('typst_conceal_math', g:typst_conceal)
call s:declare_option('typst_conceal_emoji', g:typst_conceal)
call s:declare_option('typst_auto_close_toc', 0)
call s:declare_option('typst_auto_open_quickfix', 1)
call s:declare_option('typst_embedded_languages', [])
let b:did_ftplugin = 1
let s:cpo_orig = &cpo
set cpo&vim
compiler typst
" " If you're on typst <v0.8, workaround for https://github.com/typst/typst/issues/1937
" set errorformat^=\/%f:%l:%c:%m
setlocal expandtab
setlocal tabstop=8
setlocal softtabstop=2
setlocal shiftwidth=2
if g:typst_conceal
setlocal conceallevel=2
endif
setlocal commentstring=//%s
setlocal comments=s1:/*,mb:*,ex:*/,://
setlocal formatoptions+=croq
setlocal iskeyword=a-z,A-Z,48-57,_,-
setlocal suffixesadd=.typ
command! -nargs=* -buffer TypstWatch call typst#TypstWatch(<f-args>)
command! -buffer Toc call typst#Toc('vertical')
command! -buffer Toch call typst#Toc('horizontal')
command! -buffer Tocv call typst#Toc('vertical')
command! -buffer Toct call typst#Toc('tab')
let &cpo = s:cpo_orig
unlet s:cpo_orig
" vim: tabstop=8 shiftwidth=4 softtabstop=4 expandtab

View File

@ -0,0 +1,40 @@
if exists('b:did_indent')
finish
endif
let b:did_indent = 1
let s:cpo_save = &cpoptions
set cpoptions&vim
setlocal autoindent
setlocal indentexpr=TypstIndent(v:lnum)
" setlocal indentkeys=... " We use the default
function! TypstIndent(lnum) abort " {{{1
let s:sw = shiftwidth()
let l:plnum = prevnonblank(a:lnum - 1)
if l:plnum == 0
return 0
endif
let l:line = getline(a:lnum)
let l:pline = getline(l:plnum)
if l:pline =~ '\v[\{\[\(]\s*$'
return indent(l:plnum) + s:sw
endif
if l:line =~ '\v[\}\]\)]$'
return indent(a:lnum) - s:sw
endif
return indent(l:plnum)
endfunction
" }}}1
let &cpoptions = s:cpo_save
unlet s:cpo_save
" vim: et sts=2 sw=2 ft=vim

View File

@ -0,0 +1,21 @@
" Vim syntax file
" Language: Typst
" Maintainer: Kaj Munhoz Arfvidsson
for s:name in g:typst_embedded_languages
let s:include = ['syntax include'
\ ,'@typstEmbedded_'..s:name
\ ,'syntax/'..s:name..'.vim']
let s:rule = ['syn region'
\,s:name
\,'matchgroup=Macro'
\,'start=/```'..s:name..'\>/ end=/```/'
\,'contains=@typstEmbedded_'..s:name
\,'keepend']
if g:typst_conceal
let s:rule += ['concealends']
endif
execute join(s:include, ' ')
unlet! b:current_syntax
execute join(s:rule, ' ')
endfor

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,472 @@
" Vim syntax file
" Language: Typst
" Maintainer: Kaj Munhoz Arfvidsson
if exists("b:current_syntax")
finish
endif
syntax sync fromstart
syntax spell toplevel
" Common {{{1
syntax cluster typstCommon
\ contains=@typstComment
" Common > Comment {{{2
syntax cluster typstComment
\ contains=typstCommentBlock,typstCommentLine
syntax match typstCommentBlock
\ #/\*\%(\_.\{-}\)\*/#
\ contains=typstCommentTodo,@Spell
syntax match typstCommentLine
\ #//.*#
\ contains=typstCommentTodo,@Spell
syntax keyword typstCommentTodo
\ contained
\ TODO FIXME XXX TBD
" Code {{{1
syntax cluster typstCode
\ contains=@typstCommon
\ ,@typstCodeKeywords
\ ,@typstCodeConstants
\ ,@typstCodeIdentifiers
\ ,@typstCodeFunctions
\ ,@typstCodeParens
" Code > Keywords {{{2
syntax cluster typstCodeKeywords
\ contains=typstCodeConditional
\ ,typstCodeRepeat
\ ,typstCodeKeyword
\ ,typstCodeStatement
syntax keyword typstCodeConditional
\ contained
\ if else
syntax keyword typstCodeRepeat
\ contained
\ while for
syntax keyword typstCodeKeyword
\ contained
\ not in and or return
syntax region typstCodeStatement
\ contained
\ matchgroup=typstCodeStatementWord start=/\v(let|set|import|include)>/
\ matchgroup=Noise end=/\v%(;|$)/
\ contains=@typstCode
syntax region typstCodeStatement
\ contained
\ matchgroup=typstCodeStatementWord start=/show/
\ matchgroup=Noise end=/\v%(:|$)/ keepend
\ contains=@typstCode
\ skipwhite nextgroup=@typstCode,typstCodeShowRocket
syntax match typstCodeShowRocket
\ contained
\ /.*=>/
\ contains=@typstCode
\ skipwhite nextgroup=@typstCode
" Code > Identifiers {{{2
syntax cluster typstCodeIdentifiers
\ contains=typstCodeIdentifier
\ ,typstCodeFieldAccess
syntax match typstCodeIdentifier
\ contained
\ /\v\w\k*>(<%(let|set|show|import|include))@<![\.\[\(]@!/
syntax match typstCodeFieldAccess
\ contained
\ /\v\w\k*>(<%(let|set|show|import|include))@<!\.[\[\(]@!/
\ nextgroup=typstCodeFieldAccess,typstCodeFunction
" Code > Functions {{{2
syntax cluster typstCodeFunctions
\ contains=typstCodeFunction
syntax match typstCodeFunction
\ contained
\ /\v\w\k*>(<%(let|set|show|import|include))@<![\(\[]@=/
\ nextgroup=typstCodeFunctionArgument
syntax match typstCodeFunctionArgument
\ contained
\ /\v%(%(\(.{-}\)|\[.{-}\]|\{.{-}\}))*/ transparent
\ contains=@typstCode
" Code > Constants {{{2
syntax cluster typstCodeConstants
\ contains=typstCodeConstant
\ ,typstCodeNumberInteger
\ ,typstCodeNumberFloat
\ ,typstCodeNumberLength
\ ,typstCodeNumberAngle
\ ,typstCodeNumberRatio
\ ,typstCodeNumberFraction
\ ,typstCodeString
syntax match typstCodeConstant
\ contained
\ /\v<%(none|auto|true|false)-@!>/
syntax match typstCodeNumberInteger
\ contained
\ /\v<\d+>/
syntax match typstCodeNumberFloat
\ contained
\ /\v<\d+\.\d*>/
syntax match typstCodeNumberLength
\ contained
\ /\v<\d+(\.\d*)?(pt|mm|cm|in|em)>/
syntax match typstCodeNumberAngle
\ contained
\ /\v<\d+(\.\d*)?(deg|rad)>/
syntax match typstCodeNumberRatio
\ contained
\ /\v<\d+(\.\d*)?\%/
syntax match typstCodeNumberFraction
\ contained
\ /\v<\d+(\.\d*)?fr>/
syntax region typstCodeString
\ contained
\ start=/"/ skip=/\v\\\\|\\"/ end=/"/
\ contains=@Spell
" Code > Parens {{{2
syntax cluster typstCodeParens
\ contains=typstCodeParen
\ ,typstCodeBrace
\ ,typstCodeBracket
\ ,typstCodeDollar
\ ,typstMarkupRawInline
\ ,typstMarkupRawBlock
syntax region typstCodeParen
\ contained
\ matchgroup=Noise start=/(/ end=/)/
\ contains=@typstCode
syntax region typstCodeBrace
\ contained
\ matchgroup=Noise start=/{/ end=/}/
\ contains=@typstCode
syntax region typstCodeBracket
\ contained
\ matchgroup=Noise start=/\[/ end=/\]/
\ contains=@typstMarkup
syntax region typstCodeDollar
\ contained
\ matchgroup=Number start=/\$/ end=/\$/
\ contains=@typstMath
" Hashtag {{{1
syntax cluster typstHashtag
\ contains=@typstHashtagKeywords
\ ,@typstHashtagConstants
\ ,@typstHashtagIdentifiers
\ ,@typstHashtagFunctions
\ ,@typstHashtagParens
" Hashtag > Keywords {{{2
syntax cluster typstHashtagKeywords
\ contains=typstHashtagConditional
\ ,typstHashtagRepeat
\ ,typstHashtagKeywords
\ ,typstHashtagStatement
" syntax match typstHashtagControlFlowError
" \ /\v#%(if|while|for)>-@!.{-}$\_.{-}%(\{|\[|\()/
syntax match typstHashtagControlFlow
\ /\v#%(if|while|for)>.{-}\ze%(\{|\[|\()/
\ contains=typstHashtagConditional,typstHashtagRepeat
\ nextgroup=@typstCode
syntax region typstHashtagConditional
\ contained
\ start=/\v#if>/ end=/\v\ze(\{|\[)/
\ contains=@typstCode
syntax region typstHashtagRepeat
\ contained
\ start=/\v#(while|for)>/ end=/\v\ze(\{|\[)/
\ contains=@typstCode
syntax match typstHashtagKeyword
\ /\v#(return)>/
\ skipwhite nextgroup=@typstCode
syntax region typstHashtagStatement
\ matchgroup=typstHashtagStatementWord start=/\v#(let|set|import|include)>/
\ matchgroup=Noise end=/\v%(;|$)/
\ contains=@typstCode
syntax region typstHashtagStatement
\ matchgroup=typstHashtagStatementWord start=/#show/
\ matchgroup=Noise end=/\v%(:|$)/ keepend
\ contains=@typstCode
\ skipwhite nextgroup=@typstCode,typstCodeShowRocket
" Hashtag > Constants {{{2
syntax cluster typstHashtagConstants
\ contains=typstHashtagConstant
syntax match typstHashtagConstant
\ /\v#(none|auto|true|false)>/
" Hashtag > Identifiers {{{2
syntax cluster typstHashtagIdentifiers
\ contains=typstHashtagIdentifier
\ ,typstHashtagFieldAccess
syntax match typstHashtagIdentifier
\ /\v#\w\k*>(<%(let|set|show|import|include))@<![\.\[\(]@!/
syntax match typstHashtagFieldAccess
\ /\v#\w\k*>(<%(let|set|show|import|include))@<!\.[\[\(]@!/
\ nextgroup=typstCodeFieldAccess,typstCodeFunction
if g:typst_conceal_emoji
runtime! syntax/typst-emoji.vim
endif
" Hashtag > Functions {{{2
syntax cluster typstHashtagFunctions
\ contains=typstHashtagFunction
syntax match typstHashtagFunction
\ /\v#\w\k*>(<%(let|set|show|import|include))@<![\(\[]@=/
\ nextgroup=typstCodeFunctionArgument
" Hashtag > Parens {{{2
syntax cluster typstHashtagParens
\ contains=typstHashtagParen
\ ,typstHashtagBrace
\ ,typstHashtagBracket
\ ,typstHashtagDollar
syntax region typstHashtagParen
\ matchgroup=Noise start=/#(/ end=/)/
\ contains=@typstCode
syntax region typstHashtagBrace
\ matchgroup=Noise start=/#{/ end=/}/
\ contains=@typstCode
syntax region typstHashtagBracket
\ matchgroup=Noise start=/#\[/ end=/\]/
\ contains=@typstMarkup
syntax region typstHashtagDollar
\ matchgroup=Noise start=/#\$/ end=/\$/
\ contains=@typstMath
" Markup {{{1
syntax cluster typstMarkup
\ contains=@typstCommon
\ ,@Spell
\ ,@typstHashtag
\ ,@typstMarkupText
\ ,@typstMarkupParens
" Markup > Text {{{2
syntax cluster typstMarkupText
\ contains=typstMarkupRawInline
\ ,typstMarkupRawBlock
\ ,typstMarkupLabel
\ ,typstMarkupReference
\ ,typstMarkupUrl
\ ,typstMarkupHeading
\ ,typstMarkupBulletList
\ ,typstMarkupEnumList
\ ,typstMarkupBold
\ ,typstMarkupItalic
\ ,typstMarkupLinebreak
\ ,typstMarkupNonbreakingSpace
\ ,typstMarkupShy
\ ,typstMarkupDash
\ ,typstMarkupEllipsis
\ ,typstMarkupTermList
syntax match typstMarkupRawInline
\ /`.\{-}`/
syntax region typstMarkupRawBlock
\ matchgroup=Macro start=/```\w*/
\ matchgroup=Macro end=/```/ keepend
if g:typst_conceal
syntax region typstMarkupCodeBlockTypst
\ matchgroup=Macro start=/```typst/
\ matchgroup=Macro end=/```/ contains=@typstCode keepend
\ concealends
else
syntax region typstMarkupCodeBlockTypst
\ matchgroup=Macro start=/```typst/
\ matchgroup=Macro end=/```/ contains=@typstCode keepend
endif
runtime! syntax/typst-embedded.vim
syntax match typstMarkupLabel
\ /\v\<\K%(\k*-*)*\>/
syntax match typstMarkupReference
\ /\v\@\K%(\k*-*)*/
syntax match typstMarkupUrl
\ #\v\w+://\S*#
syntax match typstMarkupHeading
\ /^\s*\zs=\{1,6}\s.*$/
\ contains=typstMarkupLabel,@Spell
syntax match typstMarkupBulletList
\ /\v^\s*-\s+/
syntax match typstMarkupEnumList
\ /\v^\s*(\+|\d+\.)\s+/
" syntax match typstMarkupItalicError
" \ /\v(\w|\\)@<!_\S@=.*|.*\S@<=\\@<!_/
syntax match typstMarkupItalic
\ /\v(\w|\\)@1<!_\S@=.{-}(\n.{-1,})*\S@1<=\\@1<!_/
\ contains=typstMarkupItalicRegion
if g:typst_conceal
syntax region typstMarkupItalicRegion
\ contained
\ matchgroup=typstMarkupItalicDelimiter
\ start=/\(^\|[^0-9a-zA-Z]\)\@<=_/ end=/_\($\|[^0-9a-zA-Z]\)\@=/
\ concealends contains=typstMarkupLabel,typstMarkupBold,@Spell
else
syntax region typstMarkupItalicRegion
\ contained
\ matchgroup=typstMarkupItalicDelimiter
\ start=/\(^\|[^0-9a-zA-Z]\)\@<=_/ end=/_\($\|[^0-9a-zA-Z]\)\@=/
\ contains=typstMarkupLabel,typstMarkupBold,@Spell
endif
" syntax match typstMarkupBoldError
" \ /\v(\w|\\)@<!\*\S@=.*|.*\S@<=\\@<!\*/
syntax match typstMarkupBold
\ /\v(\w|\\)@1<!\*\S@=.{-}(\n.{-1,})*\S@1<=\\@1<!\*/
\ contains=typstMarkupBoldRegion
if g:typst_conceal
syntax region typstMarkupBoldRegion
\ contained
\ matchgroup=typstMarkupBoldDelimiter
\ start=/\(^\|[^0-9a-zA-Z]\)\@<=\*/ end=/\*\($\|[^0-9a-zA-Z]\)\@=/
\ concealends contains=typstMarkupLabel,typstMarkupBold,@Spell
else
syntax region typstMarkupBoldRegion
\ contained
\ matchgroup=typstMarkupBoldDelimiter
\ start=/\(^\|[^0-9a-zA-Z]\)\@<=\*/ end=/\*\($\|[^0-9a-zA-Z]\)\@=/
\ contains=typstMarkupLabel,typstMarkupBold,@Spell
endif
syntax match typstMarkupLinebreak
\ /\\\\/
syntax match typstMarkupNonbreakingSpace
\ /\~/
syntax match typstMarkupShy
\ /-?/
syntax match typstMarkupDash
\ /-\{2,3}/
syntax match typstMarkupEllipsis
\ /\.\.\./
syntax match typstMarkupTermList
\ #\v^\s*\/\s+[^:]*:#
" Markup > Parens {{{2
syntax cluster typstMarkupParens
\ contains=typstMarkupBracket
\ ,typstMarkupDollar
syntax region typstMarkupBracket
\ matchgroup=Noise start=/\[/ end=/\]/
\ contains=@typstMarkup
syntax region typstMarkupDollar
\ matchgroup=Special start=/\$/ skip=/\\\$/ end=/\$/
\ contains=@typstMath
" Math {{{1
syntax cluster typstMath
\ contains=@typstCommon
\ ,@typstHashtag
\ ,typstMathIdentifier
\ ,typstMathFunction
\ ,typstMathNumber
\ ,typstMathSymbol
\ ,typstMathBold
\ ,typstMathScripts
\ ,typstMathQuote
syntax match typstMathIdentifier
\ /\a\a\+/
\ contained
syntax match typstMathFunction
\ /\a\a\+\ze(/
\ contained
syntax match typstMathNumber
\ /\<\d\+\>/
\ contained
syntax region typstMathQuote
\ matchgroup=String start=/"/ skip=/\\"/ end=/"/
\ contained
if g:typst_conceal_math
runtime! syntax/typst-symbols.vim
endif
" Math > Linked groups {{{2
highlight default link typstMathIdentifier Identifier
highlight default link typstMathFunction Statement
highlight default link typstMathNumber Number
highlight default link typstMathSymbol Statement
" Highlighting {{{1
" Highlighting > Linked groups {{{2
highlight default link typstCommentBlock Comment
highlight default link typstCommentLine Comment
highlight default link typstCommentTodo Todo
highlight default link typstCodeConditional Conditional
highlight default link typstCodeRepeat Repeat
highlight default link typstCodeKeyword Keyword
highlight default link typstCodeConstant Constant
highlight default link typstCodeNumberInteger Number
highlight default link typstCodeNumberFloat Number
highlight default link typstCodeNumberLength Number
highlight default link typstCodeNumberAngle Number
highlight default link typstCodeNumberRatio Number
highlight default link typstCodeNumberFraction Number
highlight default link typstCodeString String
highlight default link typstCodeStatementWord Statement
highlight default link typstCodeIdentifier Identifier
highlight default link typstCodeFieldAccess Identifier
highlight default link typstCodeFunction Function
highlight default link typstCodeParen Noise
highlight default link typstCodeBrace Noise
highlight default link typstCodeBracket Noise
highlight default link typstCodeDollar Noise
" highlight default link typstHashtagControlFlowError Error
highlight default link typstHashtagConditional Conditional
highlight default link typstHashtagRepeat Repeat
highlight default link typstHashtagKeyword Keyword
highlight default link typstHashtagConstant Constant
highlight default link typstHashtagStatementWord Statement
highlight default link typstHashtagIdentifier Identifier
highlight default link typstHashtagFieldAccess Identifier
highlight default link typstHashtagFunction Function
highlight default link typstHashtagParen Noise
highlight default link typstHashtagBrace Noise
highlight default link typstHashtagBracket Noise
highlight default link typstHashtagDollar Noise
highlight default link typstMarkupRawInline Macro
highlight default link typstMarkupRawBlock Macro
highlight default link typstMarkupLabel Structure
highlight default link typstMarkupReference Structure
highlight default link typstMarkupBulletList Structure
" highlight default link typstMarkupItalicError Error
" highlight default link typstMarkupBoldError Error
highlight default link typstMarkupEnumList Structure
highlight default link typstMarkupLinebreak Structure
highlight default link typstMarkupNonbreakingSpace Structure
highlight default link typstMarkupShy Structure
highlight default link typstMarkupDash Structure
highlight default link typstMarkupEllipsis Structure
highlight default link typstMarkupTermList Structure
highlight default link typstMarkupDollar Noise
" Highlighting > Custom Styling {{{2
highlight! Conceal ctermfg=NONE ctermbg=NONE guifg=NONE guibg=NONE
highlight default typstMarkupHeading term=underline,bold cterm=underline,bold gui=underline,bold
highlight default typstMarkupUrl term=underline cterm=underline gui=underline
highlight default typstMarkupBoldRegion term=bold cterm=bold gui=bold
highlight default typstMarkupItalicRegion term=italic cterm=italic gui=italic
highlight default link typstMarkupBoldDelimiter typstMarkupBold
highlight default link typstMarkupItalicDelimiter typstMarkupItalic
" }}}1
let b:current_syntax = "typst"
" vim: foldmethod=marker foldlevel=0 tabstop=8 shiftwidth=4 softtabstop=4 expandtab

View File

@ -0,0 +1,59 @@
= Italic
// Italic
_Lorem ipsum_
// Not italic
Lorem\_ipsum
// Italic
_Lorem\_ipsum_
// Error
_Lorem ipsum\_
// Ialic
_Lorem
ipsum_
// Error
_Lorem
ipsum_
// Citations
_Lorem ipsum_ @dolor_sit
_Lorem ipsum_ #cite("dolor_sit")
= Bold
// Bold
*Lorem ipsum*
// Not bold
Lorem\*ipsum
// Bold
*Lorem\*ipsum*
// Error
*Lorem ipsum\*
// Bold
*Lorem
ipsum*
// Error
*Lorem
ipsum*
// Citations
*Lorem ipsum* @dolor_sit
*Lorem ipsum* #cite("dolor_sit")

View File

@ -0,0 +1,54 @@
= Leaky Bodies
== Issue #69
// Broken
#show link: underline
#show link: set text(navy)
#show par: set block(spacing: 1.75em)
// Not Broken
#show link: underline
#show link: set text(navy);;
#show par: set block(spacing: 1.75em)
== Issue #46 (solved)
// Not Broken
#{ // Function body
[ // Content block
+ text
+ text
+ #box()[text another text]
+ text
+ text
]
}
// Broken
#{ // Function body
[ // Content block
+ text
+ text
+ #box()[text
another text]
+ text
+ text
]
}
== Issue #43 (solved)
#while index < 3 {
let x = "abc" // Wrong highlighting
}
#{
while index < 3 {
let x = "abc" // Correct highlighting
}
}