From de5d100c2f7cce390e6a01540c368e438ed41c61 Mon Sep 17 00:00:00 2001 From: Amelia Clarke Date: Fri, 6 Feb 2026 09:44:16 +0000 Subject: [PATCH] runtime(hare): update to match upstream closes: #18640 Signed-off-by: Amelia Clarke Signed-off-by: Christian Brabandt --- runtime/autoload/dist/ft.vim | 19 ++- runtime/autoload/hare.vim | 39 ++---- runtime/compiler/hare.vim | 19 +-- runtime/doc/ft_hare.txt | 90 +++++++------ runtime/doc/tags | 5 +- runtime/ftplugin/hare.vim | 17 ++- runtime/ftplugin/haredoc.vim | 17 ++- runtime/indent/hare.vim | 10 +- runtime/syntax/hare.vim | 236 +++++++++++++++++------------------ runtime/syntax/haredoc.vim | 13 +- 10 files changed, 226 insertions(+), 239 deletions(-) diff --git a/runtime/autoload/dist/ft.vim b/runtime/autoload/dist/ft.vim index 75a4bb5e60..188573f690 100644 --- a/runtime/autoload/dist/ft.vim +++ b/runtime/autoload/dist/ft.vim @@ -3,7 +3,7 @@ vim9script # Vim functions for file type detection # # Maintainer: The Vim Project -# Last Change: 2026 Jan 25 +# Last Change: 2026 Feb 06 # Former Maintainer: Bram Moolenaar # These functions are moved here from runtime/filetype.vim to make startup @@ -473,12 +473,19 @@ def IsHareModule(dir: string, depth: number): bool endif # Check all files in the directory before recursing into subdirectories. - return glob(dir .. '/*', true, true) + const items = glob(dir .. '/*', true, true) ->sort((a, b) => isdirectory(a) - isdirectory(b)) - ->reduce((acc, n) => acc - || n =~ '\.ha$' - || isdirectory(n) && IsHareModule(n, depth - 1), - false) + for n in items + if isdirectory(n) + if IsHareModule(n, depth - 1) + return true + endif + elseif n =~ '\.ha$' + return true + endif + endfor + + return false enddef # Determines whether a README file is inside a Hare module and should receive diff --git a/runtime/autoload/hare.vim b/runtime/autoload/hare.vim index 479b0f6812..d85a05b38c 100644 --- a/runtime/autoload/hare.vim +++ b/runtime/autoload/hare.vim @@ -1,13 +1,13 @@ vim9script # Helper functions for Hare. -# Language: Hare -# Maintainer: Amelia Clarke -# Last Updated: 2025 Sep 06 -# Upstream: https://git.sr.ht/~sircmpwn/hare.vim +# Language: Hare +# Maintainer: Amelia Clarke +# Last Change: 2026 Jan 24 +# Upstream: https://git.sr.ht/~sircmpwn/hare.vim -# Returns the value of HAREPATH, if it exists. Otherwise, returns a safe -# default. +# Returns the value of $HAREPATH, if it exists. Otherwise, returns a safe +# default value. export def GetPath(): string var path: list if !empty($HAREPATH) @@ -18,24 +18,7 @@ export def GetPath(): string return '/usr/src/hare/stdlib,/usr/src/hare/third-party' endif endif - return mapnew(path, (_, n) => escape(n, ' ,;'))->join(',') -enddef - -# Converts a module identifier into a path. -export def IncludeExpr(): string - var path = trim(v:fname, ':', 2)->substitute('::', '/', 'g') - - # If the module cannot be found, it might be a member instead. Try removing - # the final component until a directory is found. - while !finddir(path) - const head = fnamemodify(path, ':h') - if head == '.' - break - endif - path = head - endwhile - - return path + return map(path, (_, n) => escape(n, ' ,;'))->join(',') enddef # Modifies quickfix or location list entries to refer to the correct paths after @@ -61,14 +44,14 @@ export def QuickFixPaths() SetList([], 'r', list) enddef -# Attempts to parse the directories in $HAREPATH from the output of `hare -# version -v`. Otherwise, returns an empty list. +# Attempts to parse a list of directories from the output of `hare version -v`. +# Otherwise, returns an empty list. def ParsePath(): list if !executable('hare') return [] endif - silent const lines = systemlist('hare version -v') + silent final lines = systemlist('hare version -v') const min = match(lines, '^HAREPATH') + 1 if min == 0 return [] @@ -76,7 +59,7 @@ def ParsePath(): list const max = match(lines, '^\S', min) return (max < 0 ? slice(lines, min) : slice(lines, min, max)) - ->mapnew((_, n) => matchstr(n, '^\s*\zs.*')) + ->map((_, n) => matchstr(n, '^\s*\zs.*')) enddef # vim: et sts=2 sw=2 ts=8 tw=80 diff --git a/runtime/compiler/hare.vim b/runtime/compiler/hare.vim index 88f36a9e20..2b7d9345b4 100644 --- a/runtime/compiler/hare.vim +++ b/runtime/compiler/hare.vim @@ -3,25 +3,30 @@ vim9script # Vim compiler file. # Compiler: Hare # Maintainer: Amelia Clarke -# Last Change: 2025 Sep 06 +# Last Change: 2026 Jan 24 # Upstream: https://git.sr.ht/~sircmpwn/hare.vim if exists('g:current_compiler') finish endif +g:current_compiler = 'hare' if filereadable('Makefile') || filereadable('makefile') CompilerSet makeprg=make else - const makeprg = 'hare build ' - .. get(b:, 'hare_makeprg_params', get(g:, 'hare_makeprg_params', '-q')) + const makeprg = 'hare build ' .. get(g:, 'hare_makeprg_params', '-q') execute 'CompilerSet makeprg=' .. escape(makeprg, ' "\|') endif CompilerSet errorformat= - \%o:%l:%v:\ syntax\ error:\ %m, - \%o:%l:%v:\ error:\ %m, - \Error:\ %m, + \%E%o:%l:%v:\ error:\ %m, + \%E%o:%l:%v:\ syntax\ error:\ %m, + \%E%o:%l:%v:\ %\\%%(unexpected\ name\ %\\)%\\@=%m, + \%C,%C\ %.%#,%C%l\ %.%#, + \%trror:\ %o:\ %\\%%(%\\h%\\w%\\+%\\%%(::%\\h%\\w%\\+%\\)%#:\ %\\)%\\@=%m, + \%trror:\ %m, + \%+EAbort:\ %m%>, + \%C%.%#, \%-G%.%# augroup HareQuickFix @@ -30,6 +35,4 @@ augroup HareQuickFix autocmd QuickFixCmdPost lmake hare#QuickFixPaths() augroup END -g:current_compiler = 'hare' - # vim: et sts=2 sw=2 ts=8 tw=80 diff --git a/runtime/doc/ft_hare.txt b/runtime/doc/ft_hare.txt index ce344b73d9..918ff2a5bc 100644 --- a/runtime/doc/ft_hare.txt +++ b/runtime/doc/ft_hare.txt @@ -19,23 +19,33 @@ functionality for the Hare programming language. FILETYPE PLUGIN *ft-hare-plugin* This plugin has a few different variables that can be defined inside your -|vimrc| to tweak its behavior. +|vimrc| to adjust its behavior. -Additionally, support is provided for folding `{ }` blocks. To enable folding, -add the following to a file inside your |after-directory| (e.g. + *hare-folding* +This plugin supports folding `{ }` blocks. To enable folding, add the +following to a file inside your |after-directory| (e.g. ~/.vim/after/ftplugin/hare.vim): > setlocal foldmethod=syntax -Because block-based folding tends to create many small folds, consider setting -a few related options, such as 'foldminlines' and 'foldnestmax'. +Because syntax-based folding tends to create many small folds, consider +setting a few related options, such as 'foldminlines' or 'foldnestmax'. + *hare-symbol-operators* +Most symbolic operators do not receive any highlighting by default (with the +exception of "?", "!", and "::"). If you prefer highlighting all operators, +you can link them to your preferred highlight group inside your |vimrc|. For +example: > + + hi def link hareCast hareSymbolOperator + hi def link hareSymbolOperator hareOperator +< *g:hare_recommended_style* The following options are set by default, in accordance with Hare's official style guide: > setlocal noexpandtab - setlocal shiftwidth=0 + setlocal shiftwidth=8 setlocal softtabstop=0 setlocal tabstop=8 setlocal textwidth=80 @@ -43,18 +53,11 @@ style guide: > To disable this behavior, add the following to your |vimrc|: > let g:hare_recommended_style = 0 -< - *g:hare_symbol_operators* -By default, symbolic operators do not receive any special highlighting (with -`!`, `?`, and `::` being the only exceptions). To enable syntax highlighting -for most other operators, add the following to your |vimrc|: > - - let g:hare_symbol_operators = 1 < *g:hare_space_error* -By default, trailing whitespace and spaces followed by characters will -be highlighted as errors. This is automatically disabled in Insert mode. To -turn off this highlighting completely, add the following to your |vimrc|: > +By default, trailing whitespace and spaces followed by characters are +highlighted as errors. This is automatically disabled while in insert mode. +To turn off this highlighting completely, add the following to your |vimrc|: > let g:hare_space_error = 0 @@ -67,28 +70,27 @@ this is such a common filename, this plugin only searches for Hare source files within the same directory by default. *g:filetype_haredoc* -The |g:filetype_haredoc| variable can be used to tweak the depth of this +The `g:filetype_haredoc` variable can be used to tweak the depth of this search, or bypass the detection of Hare documentation files altogether: Value Effect~ - 0 No automatic detection + 0 Search disabled 1 Search current directory only (this is the default) 2 Search one level of subdirectories - 3 Search two levels of subdirectories -The search depth may be any positive integer, but values higher than `2` are -unlikely to provide a tangible benefit in most situations. +The search depth may be any positive integer, but values greater than 2 are +very unlikely to provide any tangible benefit and can impact performance. INDENTATION SETTINGS *ft-hare-indent* -Unlike most other settings for this plugin, the indentation settings may also -be set per-buffer, overriding any global configuration that exists. To do -this, simply prefix the variable with |b:| instead of |g:|. +Unlike other settings, indentation settings may be configured on a per-buffer +basis, overriding any existing global configuration. To do so, simply prefix +the variable with |b:| instead of |g:|. - *g:hare_indent_match_switch* -By default, continuation lines for "match" and "switch" conditions are -indented only one level: >hare + *g:hare_indent_match_switch* *b:hare_indent_match_switch* +By default, the continuation lines for "match" and "switch" conditions are +only indented one level: >hare const file = match (os::create(path, 0o644, flag::WRONLY | flag::TRUNC)) { @@ -96,39 +98,33 @@ indented only one level: >hare yield file; // ... -If you instead prefer indenting them two levels, to more closely resemble "if" -and "for" conditions, add the following line to your |vimrc|: > +If you prefer indenting them two levels, more closely resembling "if" and +"for" conditions, add the following line to your |vimrc|: > let g:hare_indent_match_switch = 2 < - *g:hare_indent_case* -By default, continuation lines for cases in "match" and "switch" expressions -are indented two levels, to visually distinguish them from the body of the -case: >hare + *g:hare_indent_case* *b:hare_indent_case* +By default, the continuation lines for "match" and "switch" cases are indented +two levels, to visually distinguish them from the case body: >hare case ltok::I8, ltok::I16, ltok::I32, ltok::I64, ltok::INT => // ... -If you prefer a different amount of indentation, you can adjust it using -|g:hare_indent_case|. Valid values include `0`, `1`, and `2`. +If you prefer a different level of indentation, you can adjust it using +`g:hare_indent_case`. The possible values are 0, 1, and 2. COMPILER SUPPORT *compiler-hare* -If this plugin detects a Makefile in the current directory, it will assume you -wish to use `make` for your build system, and will leave 'makeprg' untouched. -Otherwise, `hare build` will be used. - - *g:hare_makeprg_params* -When `hare build` is used, additional compiler options may be appended to -'makeprg' with the |g:hare_makeprg_params| variable. It may also be set on a -per-buffer basis (using |b:| instead of |g:|), overriding any global -configuration that exists. For example: > - - let b:hare_makeprg_params = '-lc -t o' +If a Makefile is detected in the current directory, this plugin will assume +you are using "make" for your build system, and will leave 'makeprg' as-is. +Otherwise, "hare build" will be used. -The global default is "-q", to suppress writing to stdout while building. + *g:hare_makeprg_params* +When using "hare build", additional compiler options may be appended to +'makeprg' using `g:hare_makeprg_params`. The default is "-q", to suppress +printing to stdout when building. ============================================================================== vim:tw=78:ts=8:noet:ft=help:norl: diff --git a/runtime/doc/tags b/runtime/doc/tags index cafe489a77..23aa279607 100644 --- a/runtime/doc/tags +++ b/runtime/doc/tags @@ -6315,6 +6315,8 @@ b:changelog_name filetype.txt /*b:changelog_name* b:clojure_syntax_keywords syntax.txt /*b:clojure_syntax_keywords* b:clojure_syntax_without_core_keywords syntax.txt /*b:clojure_syntax_without_core_keywords* b:current_syntax-variable syntax.txt /*b:current_syntax-variable* +b:hare_indent_case ft_hare.txt /*b:hare_indent_case* +b:hare_indent_match_switch ft_hare.txt /*b:hare_indent_match_switch* b:lf_shell_syntax syntax.txt /*b:lf_shell_syntax* b:netrw_lastfile pi_netrw.txt /*b:netrw_lastfile* b:rust_cargo_avoid_whole_workspace ft_rust.txt /*b:rust_cargo_avoid_whole_workspace* @@ -7819,7 +7821,6 @@ g:hare_indent_match_switch ft_hare.txt /*g:hare_indent_match_switch* g:hare_makeprg_params ft_hare.txt /*g:hare_makeprg_params* g:hare_recommended_style ft_hare.txt /*g:hare_recommended_style* g:hare_space_error ft_hare.txt /*g:hare_space_error* -g:hare_symbol_operators ft_hare.txt /*g:hare_symbol_operators* g:help_example_languages helphelp.txt /*g:help_example_languages* g:html_charset_override syntax.txt /*g:html_charset_override* g:html_diff_one_file syntax.txt /*g:html_diff_one_file* @@ -8313,6 +8314,8 @@ haiku-vimdir os_haiku.txt /*haiku-vimdir* hangul hangulin.txt /*hangul* hangulin.txt hangulin.txt /*hangulin.txt* hare ft_hare.txt /*hare* +hare-folding ft_hare.txt /*hare-folding* +hare-symbol-operators ft_hare.txt /*hare-symbol-operators* hare.vim ft_hare.txt /*hare.vim* has() builtin.txt /*has()* has-patch builtin.txt /*has-patch* diff --git a/runtime/ftplugin/hare.vim b/runtime/ftplugin/hare.vim index eca1a78817..ebd7fbdcc3 100644 --- a/runtime/ftplugin/hare.vim +++ b/runtime/ftplugin/hare.vim @@ -1,10 +1,10 @@ vim9script # Vim filetype plugin. -# Language: Hare -# Maintainer: Amelia Clarke -# Last Updated: 2025 Sep 06 -# Upstream: https://git.sr.ht/~sircmpwn/hare.vim +# Language: Hare +# Maintainer: Amelia Clarke +# Last Change: 2026 Jan 24 +# Upstream: https://git.sr.ht/~sircmpwn/hare.vim if exists('b:did_ftplugin') finish @@ -18,22 +18,21 @@ b:undo_ftplugin = 'compiler make' # Formatting settings. setlocal comments=:// setlocal commentstring=//\ %s -setlocal formatlistpat=^\\s*-\ +setlocal formatlistpat=^\\s*-\\s\\+ setlocal formatoptions+=croqnlj/ formatoptions-=t b:undo_ftplugin ..= ' | setl cms< com< flp< fo<' # Locate Hare modules. &l:include = '\v^\s*use\s+%(\h\w*\s*\=)?' -setlocal includeexpr=hare#IncludeExpr() +&l:includeexpr = 'trim(v:fname, ":", 2)->substitute("::", "/", "g")' setlocal isfname+=: &l:path = ',,' .. hare#GetPath() -setlocal suffixesadd=.ha -b:undo_ftplugin ..= ' | setl inc< inex< isf< pa< sua<' +b:undo_ftplugin ..= ' | setl inc< inex< isf< pa<' # Follow the official style guide by default. if get(g:, 'hare_recommended_style', 1) setlocal noexpandtab - setlocal shiftwidth=0 + setlocal shiftwidth=8 setlocal softtabstop=0 setlocal tabstop=8 setlocal textwidth=80 diff --git a/runtime/ftplugin/haredoc.vim b/runtime/ftplugin/haredoc.vim index ca66b06638..04cabfb4b5 100644 --- a/runtime/ftplugin/haredoc.vim +++ b/runtime/ftplugin/haredoc.vim @@ -1,10 +1,10 @@ vim9script # Vim filetype plugin. -# Language: Haredoc (Hare documentation format) -# Maintainer: Amelia Clarke -# Last Updated: 2025 Sep 06 -# Upstream: https://git.sr.ht/~sircmpwn/hare.vim +# Language: Haredoc (Hare documentation format) +# Maintainer: Amelia Clarke +# Last Change: 2026 Jan 24 +# Upstream: https://git.sr.ht/~sircmpwn/hare.vim if exists('b:did_ftplugin') finish @@ -18,21 +18,20 @@ b:undo_ftplugin = 'compiler make' # Formatting settings. setlocal comments=:\ setlocal commentstring=\ %s -setlocal formatlistpat=^-\ +setlocal formatlistpat=^\\s*-\\s\\+ setlocal formatoptions+=tnlj formatoptions-=c formatoptions-=q b:undo_ftplugin ..= ' | setl cms< com< flp< fo<' # Locate Hare modules. -setlocal includeexpr=hare#IncludeExpr() +&l:includeexpr = 'trim(v:fname, ":", 2)->substitute("::", "/", "g")' setlocal isfname+=: &l:path = ',,' .. hare#GetPath() -setlocal suffixesadd=.ha -b:undo_ftplugin ..= ' | setl inex< isf< pa< sua<' +b:undo_ftplugin ..= ' | setl inex< isf< pa<' # Follow the official style guide by default. if get(g:, 'hare_recommended_style', 1) setlocal noexpandtab - setlocal shiftwidth=0 + setlocal shiftwidth=8 setlocal softtabstop=0 setlocal tabstop=8 setlocal textwidth=80 diff --git a/runtime/indent/hare.vim b/runtime/indent/hare.vim index 84496348a1..ff38f600e8 100644 --- a/runtime/indent/hare.vim +++ b/runtime/indent/hare.vim @@ -3,7 +3,7 @@ vim9script # Vim indent file. # Language: Hare # Maintainer: Amelia Clarke -# Last Change: 2025 Sep 06 +# Last Change: 2026 Jan 24 # Upstream: https://git.sr.ht/~sircmpwn/hare.vim if exists('b:did_indent') @@ -17,7 +17,7 @@ b:did_indent = 1 # +0 -> Don't indent continuation lines. # (s -> Indent one level inside parens. # u0 -> Don't indent additional levels inside nested parens. -# U1 -> Don't treat `(` any differently if it is at the start of a line. +# U1 -> Don't treat `(` any differently if it started a line. # m1 -> Indent lines starting with `)` the same as the matching `(`. # j1 -> Indent blocks one level inside parens. # J1 -> Indent structs and unions correctly. @@ -56,7 +56,11 @@ def GetHareIndent(): number # If the previous line started the block, use the same indent. if pline =~ '{$' - return pindent + if pline =~ '\v<%(match|switch)>[^(]*\(' + return pindent + endif + return pindent - GetValue('hare_indent_match_switch', 1, 1, 2) + * shiftwidth() endif # If the current line contains a `:` that is not part of `::`, use the diff --git a/runtime/syntax/hare.vim b/runtime/syntax/hare.vim index 992b7b9059..44f72b6d78 100644 --- a/runtime/syntax/hare.vim +++ b/runtime/syntax/hare.vim @@ -3,7 +3,7 @@ vim9script # Vim syntax file. # Language: Hare # Maintainer: Amelia Clarke -# Last Change: 2025 Sep 06 +# Last Change: 2026 Feb 01 # Upstream: https://git.sr.ht/~sircmpwn/hare.vim if exists('b:current_syntax') @@ -14,11 +14,39 @@ endif syn case match syn iskeyword @,48-57,@-@,_ +# Identifiers {{{2 +syn cluster hareIdentifier contains=hareName,hareScopeDelimiter,@hareReserved +syn match hareIdentifier '\v<\h\w*%(::\h\w*)*>' contains=@hareIdentifier nextgroup=hareScopeDelimiter,@harePostfix skipempty skipwhite +syn match hareName '\<\h\w*\>' contained transparent + # Reserved keywords. -syn cluster hareReserved contains=hareBoolean,hareBuiltin,hareConditional,hareConstant,hareDefine,hareInclude,hareKeyword,hareLabel,hareOperator,hareRepeat,hareStorageClass,hareStructure,hareType,hareTypedef +syn cluster hareReserved contains=hareBoolean,hareBuiltin,hareConditional,hareConstant,hareDefine,hareInclude,hareKeyword,hareLabel,hareOperator,hareRepeat,hareStatement,hareStorageClass,hareStructure,hareType,hareTypedef + +# Punctuators {{{2 + +# Balanced tokens. +syn region hareBraces matchgroup=hareBrace start='{' end='}' contains=TOP fold transparent +syn region hareBrackets matchgroup=hareBracket start='\[' end=']' contains=TOP transparent +syn region hareParens matchgroup=hareParen start='(' end=')' contains=TOP nextgroup=@harePostfix skipempty skipwhite transparent + +# Symbolic operators. +syn match hareSymbolOperator '\.\{2,3}' +syn match hareSymbolOperator '[!<=>]=\?' +syn match hareSymbolOperator '=>' + +# Additive and multiplicative arithmetic. +syn match hareSymbolOperator '[-+*/%]=\?' + +# Bitwise arithmetic. +syn match hareSymbolOperator '\%(<<\|>>\)=\?' +syn match hareSymbolOperator '[&^|]=\?' +syn match hareSymbolOperator '\~' + +# Logical arithmetic. +syn match hareSymbolOperator '\%(&&\|^^\|||\)=\?' # Types {{{2 -syn cluster hareType contains=hareErrorFlag,harePointer,hareSlice,hareStorageClass,hareStructure,hareTaggedUnion,hareType +syn cluster hareType contains=hareArray,hareError,harePointer,hareStorageClass,hareStructure,hareTaggedUnion,hareType syn keyword hareType bool syn keyword hareType done syn keyword hareType f32 f64 @@ -33,199 +61,167 @@ syn keyword hareType void # C ABI. syn keyword hareType valist +# Pointer types. +syn match harePointer '*' contained containedin=hareTaggedUnion,hareTypeParens nextgroup=@hareType skipempty skipwhite +syn keyword hareStorageClass nullable nextgroup=harePointer skipempty skipwhite + # Slice and array types. -syn region hareSlice matchgroup=hareSlice start='\[' end=']' contained containedin=hareBuiltinTypeCall,hareTaggedUnion contains=TOP nextgroup=@hareType skipempty skipwhite -syn match hareSlice '\[[*_]]' contains=hareSliceBounds nextgroup=@hareType skipempty skipwhite -syn match hareSliceBounds '[*_]' contained display +syn region hareArray matchgroup=hareBracket start='\[' end=']' contained containedin=hareTaggedUnion,hareTypeParens contains=TOP nextgroup=@hareType skipempty skipwhite transparent +syn match hareArray '\[[*_]]' contains=hareArrayBounds nextgroup=@hareType skipempty skipwhite transparent +syn match hareArrayBounds '*' contained display + +# Tagged union and tuple types. +syn region hareTaggedUnion matchgroup=hareParen start='(' end=')' contained containedin=hareTaggedUnion,hareTypeParens contains=TOP transparent +syn match hareTaggedUnionBar '|' contained containedin=hareTaggedUnion # Other types. -syn keyword hareStorageClass nullable nextgroup=harePointer skipempty skipwhite +syn match hareError '!' contained containedin=hareTaggedUnion,hareTypeParens nextgroup=@hareType skipempty skipwhite syn keyword hareStructure enum struct union # Declarations {{{2 syn keyword hareDefine def syn keyword hareInclude use -syn keyword hareKeyword const nextgroup=@hareType skipempty skipwhite syn keyword hareKeyword export static -syn keyword hareKeyword fn nextgroup=@hareFunction skipempty skipwhite -syn keyword hareKeyword let -syn keyword hareTypedef type nextgroup=hareTypeIdentifier skipempty skipwhite +syn keyword hareKeyword fn nextgroup=@hareFunction,@hareReserved skipempty skipwhite +syn keyword hareStatement const let +syn keyword hareTypedef type nextgroup=hareTypedefBinding,@hareReserved skipempty skipwhite + +# Highlight `const` as a storage-class in places types are expected. +syn keyword hareStorageClass const contained containedin=hareTaggedUnion,hareTypeParens nextgroup=@hareType skipempty skipwhite # Function declarations. -syn cluster hareFunction contains=hareFunction,hareFuncParams -syn match hareFunction '\v<\h\w*%(::\h\w*)*>' contained contains=@hareIdentifier nextgroup=hareFuncParams skipempty skipwhite -syn region hareFuncParams matchgroup=hareFuncParams start='(' end=')' contained contains=TOP nextgroup=@hareType skipempty skipwhite +syn cluster hareFunction contains=hareFunction,hareFunctionParams +syn match hareFunction '\v<\h\w*%(::\h\w*)*>' contained contains=@hareIdentifier nextgroup=hareFunctionParams skipempty skipwhite +syn region hareFunctionParams matchgroup=hareParen start='(' end=')' contained contains=TOP nextgroup=@hareType skipempty skipwhite transparent # Type declarations. -# FIXME: Does not yet account for type declarations with multiple bindings. -syn match hareTypeIdentifier '\v<\h\w*%(::\h\w*)*>' contained contains=hareIdentifier nextgroup=hareTypeEquals skipempty skipwhite transparent -syn match hareTypeEquals '=' contained nextgroup=@hareType skipempty skipwhite transparent - -# Identifiers. -syn match hareIdentifier '\v<\h\w*%(::\h\w*)*>' contains=@hareIdentifier nextgroup=@harePostfix skipempty skipwhite -syn cluster hareIdentifier contains=hareDelimiter,hareName -syn match hareName '\<\h\w*\>' contained contains=@hareReserved transparent +# XXX: Does not yet account for type declarations with multiple bindings. +syn match hareTypedefBinding '\v<\h\w*%(::\h\w*)*>' contained nextgroup=hareTypedefEquals skipempty skipwhite transparent +syn match hareTypedefEquals '=' contained nextgroup=@hareType skipempty skipwhite transparent # Attributes {{{3 syn keyword hareAttribute @init @fini @test -syn keyword hareAttribute @offset nextgroup=hareAttrParens skipempty skipwhite +syn keyword hareAttribute @offset nextgroup=hareAttributeParens skipempty skipwhite syn keyword hareAttribute @packed -syn keyword hareAttribute @symbol nextgroup=hareAttrParens skipempty skipwhite +syn keyword hareAttribute @symbol nextgroup=hareAttributeParens skipempty skipwhite syn keyword hareAttribute @threadlocal -# Match the parens after attributes. -syn region hareAttrParens matchgroup=hareAttrParens start='(' end=')' contained contains=TOP +# Match the parens following attributes. +syn region hareAttributeParens matchgroup=hareParen start='(' end=')' contained contains=TOP transparent # Expressions {{{2 syn keyword hareConditional else -syn keyword hareConditional if nextgroup=hareCondParens skipempty skipwhite +syn keyword hareConditional if nextgroup=hareConditionParens skipempty skipwhite syn keyword hareConditional match switch nextgroup=@hareCondition skipempty skipwhite -syn keyword hareKeyword break continue return yield -syn keyword hareKeyword defer syn keyword hareLabel case nextgroup=@hareType skipempty skipwhite syn keyword hareOperator as is nextgroup=@hareType skipempty skipwhite syn keyword hareRepeat for nextgroup=@hareCondition skipempty skipwhite +syn keyword hareStatement break continue return yield +syn keyword hareStatement defer -# Match the parens in conditionals and for-loops. -syn cluster hareCondition contains=hareCondLabel,hareCondParens -syn match hareCondLabel ':\h\w*\>' contained contains=hareUserLabel nextgroup=hareCondParens skipempty skipwhite transparent -syn region hareCondParens matchgroup=hareCondParens start='(' end=')' contained contains=TOP +# Match the parens in conditionals and loops. +syn cluster hareCondition contains=hareConditionLabel,hareConditionParens +syn match hareConditionLabel ':\h\w*\>' contained nextgroup=hareConditionParens skipempty skipwhite transparent +syn region hareConditionParens matchgroup=hareParen start='(' end=')' contained contains=TOP transparent # Builtins {{{3 -syn keyword hareBuiltin abort assert nextgroup=hareBuiltinCall skipempty skipwhite -syn keyword hareBuiltin align nextgroup=hareBuiltinTypeCall skipempty skipwhite -syn keyword hareBuiltin alloc free nextgroup=hareBuiltinCall skipempty skipwhite -syn keyword hareBuiltin append insert delete nextgroup=hareBuiltinCall skipempty skipwhite -syn keyword hareBuiltin len offset nextgroup=hareBuiltinCall skipempty skipwhite +syn keyword hareBuiltin abort assert +syn keyword hareBuiltin align nextgroup=hareTypeParens skipempty skipwhite +syn keyword hareBuiltin alloc free +syn keyword hareBuiltin append insert delete +syn keyword hareBuiltin len offset # C ABI. -syn keyword hareBuiltin vastart vaarg vaend nextgroup=hareBuiltinCall skipempty skipwhite +syn keyword hareBuiltin vastart vaarg vaend -# Highlight `size` as a builtin only if it is followed by an open paren. +# Highlight `size` as a type unless it is followed by an open paren. syn match hareType '\' -syn match hareBuiltin '\]=\?' -syn match hareSymbolOperator '=>' - -# Additive and multiplicative arithmetic. -syn match hareSymbolOperator '[-+*/%]=\?' - -# Bit-shifting arithmetic. -syn match hareSymbolOperator '\%(<<\|>>\)=\?' - -# Bitwise arithmetic. -syn match hareSymbolOperator '[&^|]=\?' -syn match hareSymbolOperator '\~' - -# Logical arithmetic. -syn match hareSymbolOperator '\%(&&\|^^\|||\)=\?' - -# Highlight `!`, `*`, and `|` correctly in types. -syn match hareErrorFlag '!' contained containedin=hareBuiltinTypeCall,hareTaggedUnion nextgroup=@hareType skipempty skipwhite -syn match harePointer '*' contained containedin=hareBuiltinTypeCall,hareTaggedUnion nextgroup=@hareType skipempty skipwhite -syn match hareTaggedUnionBar '|' contained containedin=hareTaggedUnion +# Match the parens in builtin expressions expecting a type. +syn region hareTypeParens matchgroup=hareParen start='(' end=')' contained contains=TOP nextgroup=@harePostfix skipempty skipwhite transparent # Postfix expressions {{{3 # TODO: Match postfix expressions after literals. -syn cluster harePostfix contains=hareCast,hareErrorCheck,hareFieldAccess,hareFuncCall,hareIndex +syn cluster harePostfix contains=hareCast,hareField,hareSlice,hareSpecial # Casts and type hints. syn match hareCast ':' nextgroup=@hareType skipempty skipwhite -# Error handling. -syn match hareErrorCheck '!=\@!' contained nextgroup=@harePostfix skipempty skipwhite -syn match hareErrorCheck '?' nextgroup=@harePostfix skipempty skipwhite +# Error checking. +syn match hareSpecial '!=\@!' contained nextgroup=@harePostfix skipempty skipwhite +syn match hareSpecial '?' nextgroup=@harePostfix skipempty skipwhite # Field access. -syn match hareFieldAccess '\.\w\+\>' contained contains=hareName,hareNumber nextgroup=@harePostfix skipempty skipwhite - -# Function calls. -syn region hareFuncCall matchgroup=hareFuncCall start='(' end=')' contained contains=TOP nextgroup=@harePostfix skipempty skipwhite +syn match hareField '\.\w\+\>' contained contains=hareName,hareNumber,@hareReserved nextgroup=@harePostfix skipempty skipwhite transparent # Indexing and slicing. -syn region hareIndex matchgroup=hareIndex start='\[' end=']' contained contains=TOP nextgroup=@harePostfix skipempty skipwhite - -# Nested expressions. -syn region hareParens matchgroup=hareParens start='(' end=')' contains=TOP nextgroup=@harePostfix skipempty skipwhite +syn region hareSlice matchgroup=hareBracket start='\[' end=']' contained contains=TOP nextgroup=@harePostfix skipempty skipwhite transparent -# Tagged union and tuple types. -syn region hareTaggedUnion matchgroup=hareTaggedUnion start='(' end=')' contained containedin=hareBuiltinTypeCall,hareTaggedUnion contains=TOP - -# Literals {{{3 +# Literals {{{2 syn keyword hareBoolean true false syn keyword hareConstant null -# Integers. +# Integers {{{3 syn match hareNumber '\v<%(0|[1-9]%(_?\d)*)%([Ee]\+?\d+)?%([iu]%(8|16|32|64)?|z)?>' syn match hareNumber '\v<0b[01]%(_?[01])*%([iu]%(8|16|32|64)?|z)?>' syn match hareNumber '\v<0o\o%(_?\o)*%([iu]%(8|16|32|64)?|z)?>' syn match hareNumber '\v<0x\x%(_?\x)*%([iu]%(8|16|32|64)?|z)?>' -# Floats. +# Floats {{{3 +# XXX: Technically, the third form is not a valid floating literal according to +# the specification, but is currently accepted by the Hare compiler and +# used occasionally within the standard library. syn match hareFloat '\v<%(0|[1-9]%(_?\d)*)\.\d%(_?\d)*%([Ee][+-]?\d+)?%(f32|f64)?>' syn match hareFloat '\v<%(0|[1-9]%(_?\d)*)%([Ee][+-]?\d+)?%(f32|f64)>' syn match hareFloat '\v<%(0|[1-9]%(_?\d)*)[Ee]-\d+>' syn match hareFloat '\v<0x\x%(_?\x)*%(\.\x%(_?\x)*)?[Pp][+-]?\d+%(f32|f64)?>' -# Rune and string literals. -syn region hareRune start="'" skip="\\'" end="'" contains=hareEscape -syn region hareString start='"' skip='\\"' end='"' contains=hareEscape,hareFormat -syn region hareString start='`' end='`' contains=hareFormat +# Rune and string literals {{{3 +syn region hareRune matchgroup=hareRuneDelimiter start="'" skip="\\'" end="'" contains=hareEscape +syn region hareString matchgroup=hareStringDelimiter start='"' skip='\\"' end='"' contains=hareEscape,hareFormat +syn region hareString matchgroup=hareStringDelimiter start='`' end='`' contains=hareFormat # Escape sequences. syn match hareEscape '\\[0abfnrtv\\'"]' contained syn match hareEscape '\v\\%(x\x{2}|u\x{4}|U\x{8})' contained display # Format sequences. -syn match hareFormat '\v\{\d*%(:%(\.?\d+|[- +=Xbefgox]|F[.2ESUs]|_%(\_.|\\%([0abfnrtv\'"]|x\x{2}|u\x{4}|U\x{8})))*)?}' contained contains=hareEscape +syn match hareFormat '\v\{\d*%(:%(\.?\d+|[- +=befgoxX]|F[.2EsSU]|_%(\_[^\\]|\\%([0abfnrtv\\'"]|x\x{2}|u\x{4}|U\x{8})))*)?}' contained contains=hareEscape syn match hareFormat '{\d*%\d*}' contained display syn match hareFormat '{{\|}}' contained # Miscellaneous {{{2 # Annotations. -syn region hareAnnotation start='#\[' end=']' contains=hareAnnotationIdentifier -syn match hareAnnotationIdentifier '\v<\h\w*%(::\h\w*)*>' contained contains=@hareIdentifier nextgroup=hareAnnotationParens skipempty skipwhite transparent -syn region hareAnnotationParens matchgroup=hareAnnotationParens start='(' end=')' contained contains=TOP - -# Blocks. -syn region hareBlock matchgroup=hareBlock start='{' end='}' contains=TOP fold nextgroup=@harePostfix skipempty skipwhite +syn region hareAnnotation start='#\[' end=']' contains=hareAnnotationIdentifier,hareComment,hareRune,hareString +syn match hareAnnotationIdentifier '\v#\[\s*\zs\h\w*%(::\h\w*)*>' contained contains=hareName,@hareReserved nextgroup=hareAnnotationParens skipempty skipwhite +syn region hareAnnotationParens matchgroup=hareAnnotationParen start='(' end=')' contained contains=TOP # Comments. -syn region hareComment start='//' end='$' contains=@hareComment keepend -syn cluster hareComment contains=hareCommentCode,hareCommentRef,hareTodo,@Spell -syn region hareCommentCode start='\t\zs' end='$' contained contains=@NoSpell display -syn match hareCommentRef '\v\[\[\h\w*%(::\h\w*)*%(::)?]]' contained contains=@NoSpell display +syn region hareComment excludenl start='//' end='$' contains=hareSpecialComment,hareTodo,@Spell +syn match hareSpecialComment '\v\[\[\h\w*%(::\h\w*)*%(::)?]]' contained contains=@NoSpell display syn keyword hareTodo FIXME TODO XXX contained -# Delimiters. -syn match hareDelimiter '::' +# Scope delimiters. +syn match hareScopeDelimiter '::' -# Labels. -syn match hareUserLabel ':\h\w*\>' contains=hareName +# User labels. +syn match hareUserLabel ':\h\w*\>' contains=hareName,@hareReserved # Default highlighting {{{1 -hi def link hareAnnotation PreProc -hi def link hareAnnotationParens hareAnnotation +hi def link hareAnnotation Special +hi def link hareAnnotationIdentifier hareAnnotation +hi def link hareAnnotationParen hareAnnotation +hi def link hareArrayBounds harePointer hi def link hareAttribute PreProc hi def link hareBoolean Boolean -hi def link hareBuiltin Operator +hi def link hareBuiltin hareOperator hi def link hareComment Comment -hi def link hareCommentCode hareComment -hi def link hareCommentRef SpecialComment hi def link hareConditional Conditional hi def link hareConstant Constant hi def link hareDefine Define -hi def link hareDelimiter Delimiter -hi def link hareErrorFlag hareStorageClass -hi def link hareErrorCheck Special +hi def link hareError hareSpecial hi def link hareEscape SpecialChar hi def link hareFloat Float hi def link hareFormat SpecialChar @@ -238,24 +234,22 @@ hi def link hareOperator Operator hi def link harePointer hareStorageClass hi def link hareRepeat Repeat hi def link hareRune Character -hi def link hareSliceBounds harePointer +hi def link hareRuneDelimiter hareRune +hi def link hareScopeDelimiter Delimiter +hi def link hareSpecial Special +hi def link hareSpecialComment SpecialComment +hi def link hareStatement Statement hi def link hareStorageClass StorageClass hi def link hareString String +hi def link hareStringDelimiter hareString hi def link hareStructure Structure hi def link hareTodo Todo hi def link hareType Type hi def link hareTypedef Typedef hi def link hareUserLabel Identifier -# Optionally highlight symbolic operators. -if get(g:, 'hare_symbol_operators') - hi! def link hareSymbolOperator hareOperator -else - hi! def link hareSymbolOperator NONE -endif - # Highlight incorrect whitespace by default. -syn match hareSpaceError '\s\+$' containedin=ALL display +syn match hareSpaceError excludenl '\s\+$' containedin=ALL display syn match hareSpaceError ' \+\ze\t' display if get(g:, 'hare_space_error', 1) hi! def link hareSpaceError Error diff --git a/runtime/syntax/haredoc.vim b/runtime/syntax/haredoc.vim index adf15bc3df..953962c2ef 100644 --- a/runtime/syntax/haredoc.vim +++ b/runtime/syntax/haredoc.vim @@ -3,7 +3,7 @@ vim9script # Vim syntax file. # Language: Haredoc (Hare documentation format) # Maintainer: Amelia Clarke -# Last Change: 2025 Aug 14 +# Last Change: 2026 Jan 24 # Upstream: https://git.sr.ht/~sircmpwn/hare.vim if exists('b:current_syntax') @@ -15,23 +15,22 @@ syn case match syn iskeyword @,48-57,_ # Embedded code samples. -syn region haredocCode start='\t\zs' end='$' contains=@NoSpell display +syn region haredocCode excludenl start='\v%(^\s*\t)@<=' end='$' contains=@NoSpell display # References to other declarations and modules. -syn match haredocRef '\v\[\[\h\w*%(::\h\w*)*%(::)?]]' contains=@NoSpell display +syn match haredocSpecial '\v\[\[\h\w*%(::\h\w*)*%(::)?]]' contains=@NoSpell display # Miscellaneous. syn keyword haredocTodo FIXME TODO XXX # Default highlighting {{{1 hi def link haredocCode Comment -hi def link haredocRef Special +hi def link haredocSpecial Special hi def link haredocTodo Todo # Highlight incorrect whitespace by default. -syn match haredocSpaceError '\s\+$' containedin=ALL display -syn match haredocSpaceError '^ \zs \+\ze\t' containedin=ALL display -syn match haredocSpaceError '[^ ]\zs \+\ze\t' containedin=ALL display +syn match haredocSpaceError excludenl '\s\+$' containedin=ALL display +syn match haredocSpaceError '.\zs \+\ze\t' containedin=ALL display if get(g:, 'hare_space_error', 1) hi! def link haredocSpaceError Error else -- 2.47.3