runtime(hare): update to match upstream

Commit: 
https://github.com/vim/vim/commit/de5d100c2f7cce390e6a01540c368e438ed41c61
Author: Amelia Clarke <[email protected]>
Date:   Fri Feb 6 09:44:16 2026 +0000

    runtime(hare): update to match upstream
    
    closes: https://github.com/vim/vim/issues/18640
    
    Signed-off-by: Amelia Clarke <[email protected]>
    Signed-off-by: Christian Brabandt <[email protected]>

diff --git a/runtime/autoload/dist/ft.vim b/runtime/autoload/dist/ft.vim
index 75a4bb5e6..188573f69 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 <https://github.com/vim/vim>
-# Last Change:         2026 Jan 25
+# Last Change:         2026 Feb 06
 # Former Maintainer:   Bram Moolenaar <[email protected]>
 
 # 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 479b0f681..d85a05b38 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 <[email protected]>
-# Last Updated: 2025 Sep 06
-# Upstream:     https://git.sr.ht/~sircmpwn/hare.vim
+# Language:    Hare
+# Maintainer:  Amelia Clarke <[email protected]>
+# 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<string>
   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<string>
   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<string>
 
   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 88f36a9e2..2b7d9345b 100644
--- a/runtime/compiler/hare.vim
+++ b/runtime/compiler/hare.vim
@@ -3,25 +3,30 @@ vim9script
 # Vim compiler file.
 # Compiler:    Hare
 # Maintainer:  Amelia Clarke <[email protected]>
-# 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 ce344b73d..918ff2a5b 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 <Tab> 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 <Tab> 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 cafe489a7..23aa27960 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 eca1a7881..ebd7fbdcc 100644
--- a/runtime/ftplugin/hare.vim
+++ b/runtime/ftplugin/hare.vim
@@ -1,10 +1,10 @@
 vim9script
 
 # Vim filetype plugin.
-# Language:     Hare
-# Maintainer:   Amelia Clarke <[email protected]>
-# Last Updated: 2025 Sep 06
-# Upstream:     https://git.sr.ht/~sircmpwn/hare.vim
+# Language:    Hare
+# Maintainer:  Amelia Clarke <[email protected]>
+# 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 = ' ^\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 ca66b0663..04cabfb4b 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 <[email protected]>
-# Last Updated: 2025 Sep 06
-# Upstream:     https://git.sr.ht/~sircmpwn/hare.vim
+# Language:    Haredoc (Hare documentation format)
+# Maintainer:  Amelia Clarke <[email protected]>
+# 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 84496348a..ff38f600e 100644
--- a/runtime/indent/hare.vim
+++ b/runtime/indent/hare.vim
@@ -3,7 +3,7 @@ vim9script
 # Vim indent file.
 # Language:    Hare
 # Maintainer:  Amelia Clarke <[email protected]>
-# 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 =~ ' <%(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 992b7b905..44f72b6d7 100644
--- a/runtime/syntax/hare.vim
+++ b/runtime/syntax/hare.vim
@@ -3,7 +3,7 @@ vim9script
 # Vim syntax file.
 # Language:    Hare
 # Maintainer:  Amelia Clarke <[email protected]>
-# 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 ' <\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 ' <\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 ' <\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 ' <\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 ' <\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 ' <\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 '\<size\>'
-syn match hareBuiltin '\<size\ze(' nextgroup=hareBuiltinTypeCall
+syn match hareBuiltin '\<size\ze(' nextgroup=hareTypeParens
 
-# Match the parens in builtin expressions.
-syn region hareBuiltinCall matchgroup=hareBuiltinCall start='(' end=')' 
contained contains=TOP nextgroup=@harePostfix skipempty skipwhite
-syn region hareBuiltinTypeCall matchgroup=hareBuiltinTypeCall start='(' 
end=')' contained contains=TOP nextgroup=@harePostfix skipempty skipwhite
-
-# Operators {{{3
-syn match hareSymbolOperator '\.\{2,3}'
-syn match hareSymbolOperator '[!<=>]=\?'
-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 ' 
<%(0|[1-9]%(_?\d)*)%([Ee]\+?\d+)?%([iu]%(8|16|32|64)?|z)?>'
 syn match hareNumber ' <0b[01]%(_?[01])*%([iu]%(8|16|32|64)?|z)?>'
 syn match hareNumber ' <0o\o%(_?\o)*%([iu]%(8|16|32|64)?|z)?>'
 syn match hareNumber ' <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 ' 
<%(0|[1-9]%(_?\d)*)\.\d%(_?\d)*%([Ee][+-]?\d+)?%(f32|f64)?>'
 syn match hareFloat ' <%(0|[1-9]%(_?\d)*)%([Ee][+-]?\d+)?%(f32|f64)>'
 syn match hareFloat ' <%(0|[1-9]%(_?\d)*)[Ee]-\d+>'
 syn match hareFloat ' <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 ' \%(x\x{2}|u\x{4}|U\x{8})' contained display
 
 # Format sequences.
-syn match hareFormat ' \{\d*%(:%(\.?\d+|[- 
+=Xbefgox]|F[.2ESUs]|_%(\_.|\%([0abfnrtv\'"]|x\x{2}|u\x{4}|U\x{8})))*)?}' 
contained contains=hareEscape
+syn match hareFormat ' \{\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 ' <\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 ' #\[\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='     \zs' end='$' contained 
contains=@NoSpell display
-syn match hareCommentRef ' \[\[\h\w*%(::\h\w*)*%(::)?]]' contained 
contains=@NoSpell display
+syn region hareComment excludenl start='//' end='$' 
contains=hareSpecialComment,hareTodo,@Spell
+syn match hareSpecialComment ' \[\[\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       ' 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 adf15bc3d..953962c2e 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 <[email protected]>
-# 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=' \zs' end='$' contains=@NoSpell display
+syn region haredocCode excludenl start=' %(^\s*        )@<=' end='$' 
contains=@NoSpell display
 
 # References to other declarations and modules.
-syn match haredocRef ' \[\[\h\w*%(::\h\w*)*%(::)?]]' contains=@NoSpell display
+syn match haredocSpecial ' \[\[\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       ' containedin=ALL display
-syn match haredocSpaceError '[^ ]\zs \+\ze     ' containedin=ALL display
+syn match haredocSpaceError excludenl '\s\+$' containedin=ALL display
+syn match haredocSpaceError '.\zs \+\ze        ' containedin=ALL display
 if get(g:, 'hare_space_error', 1)
   hi! def link haredocSpaceError Error
 else

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion visit 
https://groups.google.com/d/msgid/vim_dev/E1voIOm-00FmOI-7M%40256bit.org.

Raspunde prin e-mail lui