runtime(hare): update for Hare 0.25.2
closes: #18222 Signed-off-by: Amelia Clarke <selene@perilune.dev> Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
committed by
Christian Brabandt
parent
6bb16d2cee
commit
6d68508e62
32
runtime/autoload/dist/ft.vim
vendored
32
runtime/autoload/dist/ft.vim
vendored
@ -3,7 +3,7 @@ vim9script
|
|||||||
# Vim functions for file type detection
|
# Vim functions for file type detection
|
||||||
#
|
#
|
||||||
# Maintainer: The Vim Project <https://github.com/vim/vim>
|
# Maintainer: The Vim Project <https://github.com/vim/vim>
|
||||||
# Last Change: 2025 Sep 04
|
# Last Change: 2025 Sep 08
|
||||||
# Former Maintainer: Bram Moolenaar <Bram@vim.org>
|
# Former Maintainer: Bram Moolenaar <Bram@vim.org>
|
||||||
|
|
||||||
# These functions are moved here from runtime/filetype.vim to make startup
|
# These functions are moved here from runtime/filetype.vim to make startup
|
||||||
@ -441,29 +441,29 @@ export def FTfs()
|
|||||||
endif
|
endif
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
# Recursively search for Hare source files in a directory and any
|
# Recursively searches for Hare source files within a directory, up to a given
|
||||||
# subdirectories, up to a given depth.
|
# depth.
|
||||||
def IsHareModule(dir: string, depth: number): bool
|
def IsHareModule(dir: string, depth: number): bool
|
||||||
if depth <= 0
|
if depth < 1
|
||||||
return !empty(glob(dir .. '/*.ha'))
|
return false
|
||||||
|
elseif depth == 1
|
||||||
|
return !glob(dir .. '/*.ha')->empty()
|
||||||
endif
|
endif
|
||||||
|
|
||||||
return reduce(sort(glob(dir .. '/*', true, true),
|
# Check all files in the directory before recursing into subdirectories.
|
||||||
(a, b) => isdirectory(a) - isdirectory(b)),
|
return glob(dir .. '/*', true, true)
|
||||||
(acc, n) => acc
|
->sort((a, b) => isdirectory(a) - isdirectory(b))
|
||||||
|
->reduce((acc, n) => acc
|
||||||
|| n =~ '\.ha$'
|
|| n =~ '\.ha$'
|
||||||
|| isdirectory(n)
|
|| isdirectory(n) && IsHareModule(n, depth - 1),
|
||||||
&& IsHareModule(n, depth - 1),
|
|
||||||
false)
|
false)
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
# Determine if a README file exists within a Hare module and should be given the
|
# Determines whether a README file is inside a Hare module and should receive
|
||||||
# Haredoc filetype.
|
# the 'haredoc' filetype.
|
||||||
export def FTharedoc()
|
export def FTharedoc()
|
||||||
if exists('g:filetype_haredoc')
|
if IsHareModule('<afile>:h', get(g:, 'filetype_haredoc', 1))
|
||||||
if IsHareModule('<afile>:h', get(g:, 'haredoc_search_depth', 1))
|
setf haredoc
|
||||||
setf haredoc
|
|
||||||
endif
|
|
||||||
endif
|
endif
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
|
@ -1,26 +1,82 @@
|
|||||||
" Vim autoload file.
|
vim9script
|
||||||
" Language: Hare
|
|
||||||
" Maintainer: Amelia Clarke <selene@perilune.dev>
|
|
||||||
" Last Updated: 2024-05-10
|
|
||||||
" Upstream: https://git.sr.ht/~sircmpwn/hare.vim
|
|
||||||
|
|
||||||
" Attempt to find the directory for a given Hare module.
|
# Helper functions for Hare.
|
||||||
function hare#FindModule(str)
|
# Language: Hare
|
||||||
let path = substitute(trim(a:str, ':', 2), '::', '/', 'g')
|
# Maintainer: Amelia Clarke <selene@perilune.dev>
|
||||||
let dir = finddir(path)
|
# Last Updated: 2025 Sep 06
|
||||||
while !empty(path) && empty(dir)
|
# Upstream: https://git.sr.ht/~sircmpwn/hare.vim
|
||||||
let path = substitute(path, '/\?\h\w*$', '', '')
|
|
||||||
let dir = finddir(path)
|
|
||||||
endwhile
|
|
||||||
return dir
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" Return the value of HAREPATH if it exists. Otherwise use a reasonable default.
|
# Returns the value of HAREPATH, if it exists. Otherwise, returns a safe
|
||||||
function hare#GetPath()
|
# default.
|
||||||
if empty($HAREPATH)
|
export def GetPath(): string
|
||||||
return '/usr/src/hare/stdlib,/usr/src/hare/third-party'
|
var path: list<string>
|
||||||
|
if !empty($HAREPATH)
|
||||||
|
path = split($HAREPATH, ':')
|
||||||
|
else
|
||||||
|
path = ParsePath()
|
||||||
|
if empty(path)
|
||||||
|
return '/usr/src/hare/stdlib,/usr/src/hare/third-party'
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
return substitute($HAREPATH, ':', ',', 'g')
|
return mapnew(path, (_, n) => escape(n, ' ,;'))->join(',')
|
||||||
endfunction
|
enddef
|
||||||
|
|
||||||
" vim: et sts=2 sw=2 ts=8
|
# 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
|
||||||
|
enddef
|
||||||
|
|
||||||
|
# Modifies quickfix or location list entries to refer to the correct paths after
|
||||||
|
# running :make or :lmake, respectively.
|
||||||
|
export def QuickFixPaths()
|
||||||
|
var GetList: func
|
||||||
|
var SetList: func
|
||||||
|
|
||||||
|
if expand('<amatch>') =~ '^l'
|
||||||
|
GetList = function('getloclist', [0])
|
||||||
|
SetList = function('setloclist', [0])
|
||||||
|
else
|
||||||
|
GetList = function('getqflist')
|
||||||
|
SetList = function('setqflist')
|
||||||
|
endif
|
||||||
|
|
||||||
|
final list = GetList({ items: 0 })
|
||||||
|
for n in list.items
|
||||||
|
if !empty(n.module)
|
||||||
|
n.filename = findfile(n.module)
|
||||||
|
endif
|
||||||
|
endfor
|
||||||
|
SetList([], 'r', list)
|
||||||
|
enddef
|
||||||
|
|
||||||
|
# Attempts to parse the directories in $HAREPATH 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')
|
||||||
|
const min = match(lines, '^HAREPATH') + 1
|
||||||
|
if min == 0
|
||||||
|
return []
|
||||||
|
endif
|
||||||
|
|
||||||
|
const max = match(lines, '^\S', min)
|
||||||
|
return (max < 0 ? slice(lines, min) : slice(lines, min, max))
|
||||||
|
->mapnew((_, n) => matchstr(n, '^\s*\zs.*'))
|
||||||
|
enddef
|
||||||
|
|
||||||
|
# vim: et sts=2 sw=2 ts=8 tw=80
|
||||||
|
@ -1,29 +1,35 @@
|
|||||||
" Vim compiler file.
|
vim9script
|
||||||
" Compiler: Hare
|
|
||||||
" Maintainer: Amelia Clarke <selene@perilune.dev>
|
|
||||||
" Last Change: 2024-05-23
|
|
||||||
" Upstream: https://git.sr.ht/~sircmpwn/hare.vim
|
|
||||||
|
|
||||||
if exists('current_compiler')
|
# Vim compiler file.
|
||||||
|
# Compiler: Hare
|
||||||
|
# Maintainer: Amelia Clarke <selene@perilune.dev>
|
||||||
|
# Last Change: 2025 Sep 06
|
||||||
|
# Upstream: https://git.sr.ht/~sircmpwn/hare.vim
|
||||||
|
|
||||||
|
if exists('g:current_compiler')
|
||||||
finish
|
finish
|
||||||
endif
|
endif
|
||||||
let current_compiler = 'hare'
|
|
||||||
|
|
||||||
let s:cpo_save = &cpo
|
|
||||||
set cpo&vim
|
|
||||||
|
|
||||||
if filereadable('Makefile') || filereadable('makefile')
|
if filereadable('Makefile') || filereadable('makefile')
|
||||||
CompilerSet makeprg=make
|
CompilerSet makeprg=make
|
||||||
else
|
else
|
||||||
CompilerSet makeprg=hare\ build
|
const makeprg = 'hare build '
|
||||||
|
.. get(b:, 'hare_makeprg_params', get(g:, 'hare_makeprg_params', '-q'))
|
||||||
|
execute 'CompilerSet makeprg=' .. escape(makeprg, ' "\|')
|
||||||
endif
|
endif
|
||||||
|
|
||||||
CompilerSet errorformat=
|
CompilerSet errorformat=
|
||||||
\%f:%l:%c:\ syntax\ error:\ %m,
|
\%o:%l:%v:\ syntax\ error:\ %m,
|
||||||
\%f:%l:%c:\ error:\ %m,
|
\%o:%l:%v:\ error:\ %m,
|
||||||
|
\Error:\ %m,
|
||||||
\%-G%.%#
|
\%-G%.%#
|
||||||
|
|
||||||
let &cpo = s:cpo_save
|
augroup HareQuickFix
|
||||||
unlet s:cpo_save
|
autocmd!
|
||||||
|
autocmd QuickFixCmdPost make hare#QuickFixPaths()
|
||||||
|
autocmd QuickFixCmdPost lmake hare#QuickFixPaths()
|
||||||
|
augroup END
|
||||||
|
|
||||||
" vim: et sts=2 sw=2 ts=8
|
g:current_compiler = 'hare'
|
||||||
|
|
||||||
|
# vim: et sts=2 sw=2 ts=8 tw=80
|
||||||
|
@ -1,77 +1,134 @@
|
|||||||
*ft_hare.txt* Support for the Hare programming language
|
*ft_hare.txt* Support for the Hare programming language
|
||||||
|
|
||||||
==============================================================================
|
==============================================================================
|
||||||
CONTENTS *hare*
|
CONTENTS *hare* *hare.vim*
|
||||||
|
|
||||||
1. Introduction |hare-intro|
|
1. Introduction |ft-hare-intro|
|
||||||
2. Filetype plugin |hare-plugin|
|
2. Filetype plugin |ft-hare-plugin|
|
||||||
3. Settings |hare-settings|
|
3. Haredoc filetype |ft-haredoc-plugin|
|
||||||
|
4. Indentation settings |ft-hare-indent|
|
||||||
|
5. Compiler support |compiler-hare|
|
||||||
|
|
||||||
==============================================================================
|
==============================================================================
|
||||||
INTRODUCTION *hare-intro*
|
INTRODUCTION *ft-hare-intro*
|
||||||
|
|
||||||
This plugin provides syntax highlighting, indentation, and other functionality
|
This plugin provides syntax highlighting, indentation, and other supporting
|
||||||
for the Hare programming language. Support is also provided for README files
|
functionality for the Hare programming language.
|
||||||
inside Hare modules, but this must be enabled by setting |g:filetype_haredoc|.
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
FILETYPE PLUGIN *hare-plugin*
|
|
||||||
|
|
||||||
This plugin automatically sets the value of 'path' to include the contents of
|
FILETYPE PLUGIN *ft-hare-plugin*
|
||||||
the HAREPATH environment variable, allowing commands such as |gf| to directly
|
|
||||||
open standard library or third-party modules. If HAREPATH is not set, it
|
|
||||||
defaults to the recommended paths for most Unix-like filesystems, namely
|
|
||||||
/usr/src/hare/stdlib and /usr/src/hare/third-party.
|
|
||||||
|
|
||||||
==============================================================================
|
This plugin has a few different variables that can be defined inside your
|
||||||
SETTINGS *hare-settings*
|
|vimrc| to tweak its behavior.
|
||||||
|
|
||||||
This plugin provides a small number of variables that you can define in your
|
Additionally, support is provided for folding `{ }` blocks. To enable folding,
|
||||||
vimrc to configure its behavior.
|
add the following to a file inside your |after-directory| (e.g.
|
||||||
|
~/.vim/after/ftplugin/hare.vim): >
|
||||||
|
|
||||||
*g:filetype_haredoc*
|
setlocal foldmethod=syntax
|
||||||
This plugin is able to automatically detect Hare modules and set the "haredoc"
|
|
||||||
filetype for any README files. As the recursive directory search used as a
|
Because block-based folding tends to create many small folds, consider setting
|
||||||
heuristic has a minor performance impact, this feature is disabled by default
|
a few related options, such as 'foldminlines' and 'foldnestmax'.
|
||||||
and must be specifically opted into: >
|
|
||||||
let g:filetype_haredoc = 1
|
|
||||||
<
|
|
||||||
See |g:haredoc_search_depth| for ways to tweak the searching behavior.
|
|
||||||
|
|
||||||
*g:hare_recommended_style*
|
*g:hare_recommended_style*
|
||||||
The following options are set by default, in accordance with the official Hare
|
The following options are set by default, in accordance with Hare's official
|
||||||
style guide: >
|
style guide: >
|
||||||
|
|
||||||
setlocal noexpandtab
|
setlocal noexpandtab
|
||||||
setlocal shiftwidth=0
|
setlocal shiftwidth=0
|
||||||
setlocal softtabstop=0
|
setlocal softtabstop=0
|
||||||
setlocal tabstop=8
|
setlocal tabstop=8
|
||||||
setlocal textwidth=80
|
setlocal textwidth=80
|
||||||
<
|
|
||||||
To disable this behavior: >
|
To disable this behavior, add the following to your |vimrc|: >
|
||||||
|
|
||||||
let g:hare_recommended_style = 0
|
let g:hare_recommended_style = 0
|
||||||
<
|
<
|
||||||
*g:hare_space_error*
|
*g:hare_symbol_operators*
|
||||||
By default, trailing whitespace and tabs preceded by space characters are
|
By default, symbolic operators do not receive any special highlighting (with
|
||||||
highlighted as errors. This is automatically turned off when in insert mode.
|
`!`, `?`, and `::` being the only exceptions). To enable syntax highlighting
|
||||||
To disable this highlighting completely: >
|
for most other operators, add the following to your |vimrc|: >
|
||||||
let g:hare_space_error = 0
|
|
||||||
<
|
|
||||||
*g:haredoc_search_depth*
|
|
||||||
By default, when |g:filetype_haredoc| is enabled, only the current directory
|
|
||||||
and its immediate subdirectories are searched for Hare files. The maximum
|
|
||||||
search depth may be adjusted with: >
|
|
||||||
let g:haredoc_search_depth = 2
|
|
||||||
<
|
|
||||||
Value Effect~
|
|
||||||
0 Only search the current directory.
|
|
||||||
1 Search the current directory and immediate
|
|
||||||
subdirectories.
|
|
||||||
2 Search the current directory and two levels of
|
|
||||||
subdirectories.
|
|
||||||
|
|
||||||
The maximum search depth can be set to any integer, but using values higher
|
let g:hare_symbol_operators = 1
|
||||||
than 2 is not recommended, and will likely provide no tangible benefit in most
|
<
|
||||||
situations.
|
*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|: >
|
||||||
|
|
||||||
|
let g:hare_space_error = 0
|
||||||
|
|
||||||
|
|
||||||
|
HAREDOC FILETYPE *ft-haredoc-plugin*
|
||||||
|
|
||||||
|
This plugin will automatically detect README files inside Hare modules, using
|
||||||
|
a recursive directory search, and give them the "haredoc" filetype. Because
|
||||||
|
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
|
||||||
|
search, or bypass the detection of Hare documentation files altogether:
|
||||||
|
|
||||||
|
Value Effect~
|
||||||
|
0 No automatic detection
|
||||||
|
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.
|
||||||
|
|
||||||
|
|
||||||
|
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:|.
|
||||||
|
|
||||||
|
*g:hare_indent_match_switch*
|
||||||
|
By default, continuation lines for "match" and "switch" conditions are
|
||||||
|
indented only one level: >hare
|
||||||
|
|
||||||
|
const file = match (os::create(path, 0o644,
|
||||||
|
flag::WRONLY | flag::TRUNC)) {
|
||||||
|
case let file: io::file =>
|
||||||
|
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|: >
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
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`.
|
||||||
|
|
||||||
|
|
||||||
|
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'
|
||||||
|
|
||||||
|
The global default is "-q", to suppress writing to stdout while building.
|
||||||
|
|
||||||
==============================================================================
|
==============================================================================
|
||||||
vim:tw=78:ts=8:noet:ft=help:norl:
|
vim:ft=help:noet:ts=8:tw=78:norl:
|
||||||
|
@ -6718,6 +6718,7 @@ compiler-dotnet quickfix.txt /*compiler-dotnet*
|
|||||||
compiler-gcc quickfix.txt /*compiler-gcc*
|
compiler-gcc quickfix.txt /*compiler-gcc*
|
||||||
compiler-gnat ft_ada.txt /*compiler-gnat*
|
compiler-gnat ft_ada.txt /*compiler-gnat*
|
||||||
compiler-groff quickfix.txt /*compiler-groff*
|
compiler-groff quickfix.txt /*compiler-groff*
|
||||||
|
compiler-hare ft_hare.txt /*compiler-hare*
|
||||||
compiler-hpada ft_ada.txt /*compiler-hpada*
|
compiler-hpada ft_ada.txt /*compiler-hpada*
|
||||||
compiler-javac quickfix.txt /*compiler-javac*
|
compiler-javac quickfix.txt /*compiler-javac*
|
||||||
compiler-make quickfix.txt /*compiler-make*
|
compiler-make quickfix.txt /*compiler-make*
|
||||||
@ -7508,6 +7509,10 @@ ft-gprof-plugin filetype.txt /*ft-gprof-plugin*
|
|||||||
ft-groff-syntax syntax.txt /*ft-groff-syntax*
|
ft-groff-syntax syntax.txt /*ft-groff-syntax*
|
||||||
ft-gsp-syntax syntax.txt /*ft-gsp-syntax*
|
ft-gsp-syntax syntax.txt /*ft-gsp-syntax*
|
||||||
ft-hare filetype.txt /*ft-hare*
|
ft-hare filetype.txt /*ft-hare*
|
||||||
|
ft-hare-indent ft_hare.txt /*ft-hare-indent*
|
||||||
|
ft-hare-intro ft_hare.txt /*ft-hare-intro*
|
||||||
|
ft-hare-plugin ft_hare.txt /*ft-hare-plugin*
|
||||||
|
ft-haredoc-plugin ft_hare.txt /*ft-haredoc-plugin*
|
||||||
ft-haskell-syntax syntax.txt /*ft-haskell-syntax*
|
ft-haskell-syntax syntax.txt /*ft-haskell-syntax*
|
||||||
ft-help-omni helphelp.txt /*ft-help-omni*
|
ft-help-omni helphelp.txt /*ft-help-omni*
|
||||||
ft-html-indent indent.txt /*ft-html-indent*
|
ft-html-indent indent.txt /*ft-html-indent*
|
||||||
@ -7759,9 +7764,12 @@ g:gnat.Set_Project_File() ft_ada.txt /*g:gnat.Set_Project_File()*
|
|||||||
g:gnat.Tags() ft_ada.txt /*g:gnat.Tags()*
|
g:gnat.Tags() ft_ada.txt /*g:gnat.Tags()*
|
||||||
g:gnat.Tags_Command ft_ada.txt /*g:gnat.Tags_Command*
|
g:gnat.Tags_Command ft_ada.txt /*g:gnat.Tags_Command*
|
||||||
g:gzip_exec pi_gzip.txt /*g:gzip_exec*
|
g:gzip_exec pi_gzip.txt /*g:gzip_exec*
|
||||||
|
g:hare_indent_case ft_hare.txt /*g:hare_indent_case*
|
||||||
|
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_recommended_style ft_hare.txt /*g:hare_recommended_style*
|
||||||
g:hare_space_error ft_hare.txt /*g:hare_space_error*
|
g:hare_space_error ft_hare.txt /*g:hare_space_error*
|
||||||
g:haredoc_search_depth ft_hare.txt /*g:haredoc_search_depth*
|
g:hare_symbol_operators ft_hare.txt /*g:hare_symbol_operators*
|
||||||
g:help_example_languages helphelp.txt /*g:help_example_languages*
|
g:help_example_languages helphelp.txt /*g:help_example_languages*
|
||||||
g:html_charset_override syntax.txt /*g:html_charset_override*
|
g:html_charset_override syntax.txt /*g:html_charset_override*
|
||||||
g:html_diff_one_file syntax.txt /*g:html_diff_one_file*
|
g:html_diff_one_file syntax.txt /*g:html_diff_one_file*
|
||||||
@ -8252,9 +8260,7 @@ haiku-vimdir os_haiku.txt /*haiku-vimdir*
|
|||||||
hangul hangulin.txt /*hangul*
|
hangul hangulin.txt /*hangul*
|
||||||
hangulin.txt hangulin.txt /*hangulin.txt*
|
hangulin.txt hangulin.txt /*hangulin.txt*
|
||||||
hare ft_hare.txt /*hare*
|
hare ft_hare.txt /*hare*
|
||||||
hare-intro ft_hare.txt /*hare-intro*
|
hare.vim ft_hare.txt /*hare.vim*
|
||||||
hare-plugin ft_hare.txt /*hare-plugin*
|
|
||||||
hare-settings ft_hare.txt /*hare-settings*
|
|
||||||
has() builtin.txt /*has()*
|
has() builtin.txt /*has()*
|
||||||
has-patch builtin.txt /*has-patch*
|
has-patch builtin.txt /*has-patch*
|
||||||
has-python if_pyth.txt /*has-python*
|
has-python if_pyth.txt /*has-python*
|
||||||
|
@ -1,61 +1,52 @@
|
|||||||
" Vim filetype plugin.
|
vim9script
|
||||||
" Language: Hare
|
|
||||||
" Maintainer: Amelia Clarke <selene@perilune.dev>
|
# Vim filetype plugin.
|
||||||
" Last Updated: 2024 Oct 04
|
# Language: Hare
|
||||||
" Upstream: https://git.sr.ht/~sircmpwn/hare.vim
|
# Maintainer: Amelia Clarke <selene@perilune.dev>
|
||||||
|
# Last Updated: 2025 Sep 06
|
||||||
|
# Upstream: https://git.sr.ht/~sircmpwn/hare.vim
|
||||||
|
|
||||||
if exists('b:did_ftplugin')
|
if exists('b:did_ftplugin')
|
||||||
finish
|
finish
|
||||||
endif
|
endif
|
||||||
let b:did_ftplugin = 1
|
b:did_ftplugin = 1
|
||||||
|
|
||||||
let s:cpo_save = &cpo
|
# Use the Hare compiler.
|
||||||
set cpo&vim
|
compiler hare
|
||||||
|
b:undo_ftplugin = 'compiler make'
|
||||||
|
|
||||||
" Formatting settings.
|
# Formatting settings.
|
||||||
setlocal comments=://
|
setlocal comments=://
|
||||||
setlocal commentstring=//\ %s
|
setlocal commentstring=//\ %s
|
||||||
setlocal formatlistpat=^\ \\?-\
|
setlocal formatlistpat=^\\s*-\
|
||||||
setlocal formatoptions+=croqnlj/ formatoptions-=t
|
setlocal formatoptions+=croqnlj/ formatoptions-=t
|
||||||
|
b:undo_ftplugin ..= ' | setl cms< com< flp< fo<'
|
||||||
|
|
||||||
" Search for Hare modules.
|
# Locate Hare modules.
|
||||||
setlocal include=^\\s*use\\>
|
&l:include = '\v^\s*use\s+%(\h\w*\s*\=)?'
|
||||||
setlocal includeexpr=hare#FindModule(v:fname)
|
setlocal includeexpr=hare#IncludeExpr()
|
||||||
setlocal isfname+=:
|
setlocal isfname+=:
|
||||||
|
&l:path = ',,' .. hare#GetPath()
|
||||||
setlocal suffixesadd=.ha
|
setlocal suffixesadd=.ha
|
||||||
|
b:undo_ftplugin ..= ' | setl inc< inex< isf< pa< sua<'
|
||||||
|
|
||||||
" Add HAREPATH to the default search paths.
|
# Follow the official style guide by default.
|
||||||
setlocal path-=/usr/include,,
|
|
||||||
let &l:path .= ',' .. hare#GetPath() .. ',,'
|
|
||||||
|
|
||||||
let b:undo_ftplugin = 'setl cms< com< flp< fo< inc< inex< isf< pa< sua< mp<'
|
|
||||||
|
|
||||||
" Follow the Hare style guide by default.
|
|
||||||
if get(g:, 'hare_recommended_style', 1)
|
if get(g:, 'hare_recommended_style', 1)
|
||||||
setlocal noexpandtab
|
setlocal noexpandtab
|
||||||
setlocal shiftwidth=0
|
setlocal shiftwidth=0
|
||||||
setlocal softtabstop=0
|
setlocal softtabstop=0
|
||||||
setlocal tabstop=8
|
setlocal tabstop=8
|
||||||
setlocal textwidth=80
|
setlocal textwidth=80
|
||||||
let b:undo_ftplugin .= ' et< sts< sw< ts< tw<'
|
b:undo_ftplugin ..= ' | setl et< sts< sw< ts< tw<'
|
||||||
endif
|
endif
|
||||||
|
|
||||||
augroup hare.vim
|
# Highlight incorrect whitespace outside of insert mode.
|
||||||
autocmd!
|
if get(g:, 'hare_space_error', 1)
|
||||||
|
augroup HareSpaceError
|
||||||
" Highlight whitespace errors by default.
|
autocmd!
|
||||||
if get(g:, 'hare_space_error', 1)
|
|
||||||
autocmd InsertEnter * hi link hareSpaceError NONE
|
autocmd InsertEnter * hi link hareSpaceError NONE
|
||||||
autocmd InsertLeave * hi link hareSpaceError Error
|
autocmd InsertLeave * hi link hareSpaceError Error
|
||||||
endif
|
augroup END
|
||||||
augroup END
|
|
||||||
|
|
||||||
if !exists('current_compiler')
|
|
||||||
let b:undo_ftplugin .= "| compiler make"
|
|
||||||
compiler hare
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let &cpo = s:cpo_save
|
# vim: et sts=2 sw=2 ts=8 tw=80
|
||||||
unlet s:cpo_save
|
|
||||||
|
|
||||||
" vim: et sts=2 sw=2 ts=8
|
|
||||||
|
@ -1,44 +1,51 @@
|
|||||||
" Vim filetype plugin.
|
vim9script
|
||||||
" Language: Haredoc (Hare documentation format)
|
|
||||||
" Maintainer: Amelia Clarke <selene@perilune.dev>
|
# Vim filetype plugin.
|
||||||
" Last Updated: 2024-05-02
|
# Language: Haredoc (Hare documentation format)
|
||||||
" Upstream: https://git.sr.ht/~selene/hare.vim
|
# Maintainer: Amelia Clarke <selene@perilune.dev>
|
||||||
|
# Last Updated: 2025 Sep 06
|
||||||
|
# Upstream: https://git.sr.ht/~sircmpwn/hare.vim
|
||||||
|
|
||||||
if exists('b:did_ftplugin')
|
if exists('b:did_ftplugin')
|
||||||
finish
|
finish
|
||||||
endif
|
endif
|
||||||
let b:did_ftplugin = 1
|
b:did_ftplugin = 1
|
||||||
|
|
||||||
let s:cpo_save = &cpo
|
# Use the Hare compiler.
|
||||||
set cpo&vim
|
compiler hare
|
||||||
|
b:undo_ftplugin = 'compiler make'
|
||||||
|
|
||||||
" Formatting settings.
|
# Formatting settings.
|
||||||
setlocal comments=:\
|
setlocal comments=:\
|
||||||
setlocal formatlistpat=^\ \\?-\
|
setlocal commentstring=\ %s
|
||||||
|
setlocal formatlistpat=^-\
|
||||||
setlocal formatoptions+=tnlj formatoptions-=c formatoptions-=q
|
setlocal formatoptions+=tnlj formatoptions-=c formatoptions-=q
|
||||||
|
b:undo_ftplugin ..= ' | setl cms< com< flp< fo<'
|
||||||
|
|
||||||
" Search for Hare modules.
|
# Locate Hare modules.
|
||||||
setlocal includeexpr=hare#FindModule(v:fname)
|
setlocal includeexpr=hare#IncludeExpr()
|
||||||
setlocal isfname+=:
|
setlocal isfname+=:
|
||||||
|
&l:path = ',,' .. hare#GetPath()
|
||||||
setlocal suffixesadd=.ha
|
setlocal suffixesadd=.ha
|
||||||
|
b:undo_ftplugin ..= ' | setl inex< isf< pa< sua<'
|
||||||
|
|
||||||
" Add HAREPATH to the default search paths.
|
# Follow the official style guide by default.
|
||||||
setlocal path-=/usr/include,,
|
|
||||||
let &l:path .= ',' .. hare#GetPath() .. ',,'
|
|
||||||
|
|
||||||
let b:undo_ftplugin = 'setl com< flp< fo< inex< isf< pa< sua<'
|
|
||||||
|
|
||||||
" Follow the Hare style guide by default.
|
|
||||||
if get(g:, 'hare_recommended_style', 1)
|
if get(g:, 'hare_recommended_style', 1)
|
||||||
setlocal noexpandtab
|
setlocal noexpandtab
|
||||||
setlocal shiftwidth=0
|
setlocal shiftwidth=0
|
||||||
setlocal softtabstop=0
|
setlocal softtabstop=0
|
||||||
setlocal tabstop=8
|
setlocal tabstop=8
|
||||||
setlocal textwidth=80
|
setlocal textwidth=80
|
||||||
let b:undo_ftplugin .= ' et< sts< sw< ts< tw<'
|
b:undo_ftplugin ..= ' | setl et< sts< sw< ts< tw<'
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let &cpo = s:cpo_save
|
# Highlight incorrect whitespace outside of insert mode.
|
||||||
unlet s:cpo_save
|
if get(g:, 'hare_space_error', 1)
|
||||||
|
augroup HaredocSpaceError
|
||||||
|
autocmd!
|
||||||
|
autocmd InsertEnter * hi link haredocSpaceError NONE
|
||||||
|
autocmd InsertLeave * hi link haredocSpaceError Error
|
||||||
|
augroup END
|
||||||
|
endif
|
||||||
|
|
||||||
" vim: et sts=2 sw=2 ts=8
|
# vim: et sts=2 sw=2 ts=8 tw=80
|
||||||
|
@ -1,146 +1,340 @@
|
|||||||
" Vim indent file
|
vim9script
|
||||||
" Language: Hare
|
|
||||||
" Maintainer: Amelia Clarke <selene@perilune.dev>
|
# Vim indent file.
|
||||||
" Last Change: 2024-04-14
|
# Language: Hare
|
||||||
" Upstream: https://git.sr.ht/~sircmpwn/hare.vim
|
# Maintainer: Amelia Clarke <selene@perilune.dev>
|
||||||
|
# Last Change: 2025 Sep 06
|
||||||
|
# Upstream: https://git.sr.ht/~sircmpwn/hare.vim
|
||||||
|
|
||||||
if exists('b:did_indent')
|
if exists('b:did_indent')
|
||||||
finish
|
finish
|
||||||
endif
|
endif
|
||||||
let b:did_indent = 1
|
b:did_indent = 1
|
||||||
|
|
||||||
let s:cpo_save = &cpo
|
|
||||||
set cpo&vim
|
|
||||||
|
|
||||||
" L0 -> don't deindent labels
|
|
||||||
" (s -> use one indent after a trailing (
|
|
||||||
" m1 -> if ) starts a line, indent it the same as its matching (
|
|
||||||
" ks -> add an extra indent to extra lines in an if expression or for expression
|
|
||||||
" j1 -> indent code inside {} one level when in parentheses
|
|
||||||
" J1 -> see j1
|
|
||||||
" *0 -> don't search for unclosed block comments
|
|
||||||
" #1 -> don't deindent lines that begin with #
|
|
||||||
setlocal cinoptions=L0,(s,m1,ks,j1,J1,*0,#1
|
|
||||||
|
|
||||||
" Controls which keys reindent the current line.
|
|
||||||
" 0{ -> { at beginning of line
|
|
||||||
" 0} -> } at beginning of line
|
|
||||||
" 0) -> ) at beginning of line
|
|
||||||
" 0] -> ] at beginning of line
|
|
||||||
" !^F -> <C-f> (not inserted)
|
|
||||||
" o -> <CR> or `o` command
|
|
||||||
" O -> `O` command
|
|
||||||
" e -> else
|
|
||||||
" 0=case -> case
|
|
||||||
setlocal indentkeys=0{,0},0),0],!^F,o,O,e,0=case
|
|
||||||
|
|
||||||
setlocal cinwords=if,else,for,switch,match
|
|
||||||
|
|
||||||
|
# L0 -> Don't unindent lines that look like C labels.
|
||||||
|
# :0 -> Don't indent `case` in match and switch expressions. This only affects
|
||||||
|
# lines containing `:` (that isn't part of `::`).
|
||||||
|
# +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.
|
||||||
|
# m1 -> Indent lines starting with `)` the same as the matching `(`.
|
||||||
|
# j1 -> Indent blocks one level inside parens.
|
||||||
|
# J1 -> Indent structs and unions correctly.
|
||||||
|
# *0 -> Don't search for unclosed C-style block comments.
|
||||||
|
# #1 -> Don't unindent lines starting with `#`.
|
||||||
|
setlocal cinoptions=L0,:0,+0,(s,u0,U1,m1,j1,J1,*0,#1
|
||||||
|
setlocal cinscopedecls=
|
||||||
setlocal indentexpr=GetHareIndent()
|
setlocal indentexpr=GetHareIndent()
|
||||||
|
setlocal indentkeys=0{,0},0),0],!^F,o,O,e,0=case
|
||||||
|
setlocal nolisp
|
||||||
|
b:undo_indent = 'setl cino< cinsd< inde< indk< lisp<'
|
||||||
|
|
||||||
let b:undo_indent = 'setl cino< cinw< inde< indk<'
|
# Calculates the indentation for the current line, using the value computed by
|
||||||
|
# cindent and manually fixing the cases where it behaves incorrectly.
|
||||||
|
def GetHareIndent(): number
|
||||||
|
# Get the preceding lines of context and the value computed by cindent.
|
||||||
|
const line = getline(v:lnum)
|
||||||
|
const [plnum, pline] = PrevNonBlank(v:lnum - 1)
|
||||||
|
const [pplnum, ppline] = PrevNonBlank(plnum - 1)
|
||||||
|
const pindent = indent(plnum)
|
||||||
|
const ppindent = indent(pplnum)
|
||||||
|
const cindent = cindent(v:lnum) / shiftwidth() * shiftwidth()
|
||||||
|
|
||||||
if exists('*GetHareIndent()')
|
# If this line is a comment, don't try to align it with a comment at the end
|
||||||
finish
|
# of the previous line.
|
||||||
endif
|
if line =~ '^\s*//' && getline(plnum) =~ '\s*//.*$'
|
||||||
|
return -1
|
||||||
function! FloorCindent(lnum)
|
|
||||||
return cindent(a:lnum) / shiftwidth() * shiftwidth()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! GetHareIndent()
|
|
||||||
let line = getline(v:lnum)
|
|
||||||
let prevlnum = prevnonblank(v:lnum - 1)
|
|
||||||
let prevline = getline(prevlnum)
|
|
||||||
let prevprevline = getline(prevnonblank(prevlnum - 1))
|
|
||||||
|
|
||||||
" This is all very hacky and imperfect, but it's tough to do much better when
|
|
||||||
" working with regex-based indenting rules.
|
|
||||||
|
|
||||||
" If the previous line ended with =, indent by one shiftwidth.
|
|
||||||
if prevline =~# '\v\=\s*(//.*)?$'
|
|
||||||
return indent(prevlnum) + shiftwidth()
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
" If the previous line ended in a semicolon and the line before that ended
|
# Indent `case`.
|
||||||
" with =, deindent by one shiftwidth.
|
if line =~ '^\s*case\>'
|
||||||
if prevline =~# '\v;\s*(//.*)?$' && prevprevline =~# '\v\=\s*(//.*)?$'
|
# If the previous line was also a `case`, use the same indent.
|
||||||
return indent(prevlnum) - shiftwidth()
|
if pline =~ '^\s*case\>'
|
||||||
endif
|
return pindent
|
||||||
|
|
||||||
" TODO: The following edge-case is still indented incorrectly:
|
|
||||||
" case =>
|
|
||||||
" if (foo) {
|
|
||||||
" bar;
|
|
||||||
" };
|
|
||||||
" | // cursor is incorrectly deindented by one shiftwidth.
|
|
||||||
"
|
|
||||||
" This only happens if the {} block is the first statement in the case body.
|
|
||||||
" If `case` is typed, the case will also be incorrectly deindented by one
|
|
||||||
" shiftwidth. Are you having fun yet?
|
|
||||||
|
|
||||||
" Deindent cases.
|
|
||||||
if line =~# '\v^\s*case'
|
|
||||||
" If the previous line was also a case, don't do any special indenting.
|
|
||||||
if prevline =~# '\v^\s*case'
|
|
||||||
return indent(prevlnum)
|
|
||||||
end
|
|
||||||
|
|
||||||
" If the previous line was a multiline case, deindent by one shiftwidth.
|
|
||||||
if prevline =~# '\v\=\>\s*(//.*)?$'
|
|
||||||
return indent(prevlnum) - shiftwidth()
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
" If the previous line started a block, deindent by one shiftwidth.
|
# If the previous line started the block, use the same indent.
|
||||||
" This handles the first case in a switch/match block.
|
if pline =~ '{$'
|
||||||
if prevline =~# '\v\{\s*(//.*)?$'
|
return pindent
|
||||||
return FloorCindent(v:lnum) - shiftwidth()
|
|
||||||
end
|
|
||||||
|
|
||||||
" If the previous line ended in a semicolon and the line before that wasn't
|
|
||||||
" a case, deindent by one shiftwidth.
|
|
||||||
if prevline =~# '\v;\s*(//.*)?$' && prevprevline !~# '\v\=\>\s*(//.*)?$'
|
|
||||||
return FloorCindent(v:lnum) - shiftwidth()
|
|
||||||
end
|
|
||||||
|
|
||||||
let l:indent = FloorCindent(v:lnum)
|
|
||||||
|
|
||||||
" If a normal cindent would indent the same amount as the previous line,
|
|
||||||
" deindent by one shiftwidth. This fixes some issues with `case let` blocks.
|
|
||||||
if l:indent == indent(prevlnum)
|
|
||||||
return l:indent - shiftwidth()
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
" Otherwise, do a normal cindent.
|
# If the current line contains a `:` that is not part of `::`, use the
|
||||||
return l:indent
|
# computed cindent.
|
||||||
|
if line =~ '\v%(%(::)*)@>:'
|
||||||
|
return cindent
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Unindent after a multi-line `case`.
|
||||||
|
if pline =~ '=>$'
|
||||||
|
return pindent - shiftwidth() * GetValue('hare_indent_case', 2)
|
||||||
|
endif
|
||||||
|
|
||||||
|
# If the previous line closed a set of parens, search for the previous
|
||||||
|
# `case` within the same block and use the same indent. This fixes issues
|
||||||
|
# with `case` not being correctly unindented after a function call
|
||||||
|
# continuation line:
|
||||||
|
#
|
||||||
|
# case let err: fs::error =>
|
||||||
|
# fmt::fatalf("Unable to open {}: {}",
|
||||||
|
# os::args[1], fs::strerror(err));
|
||||||
|
# case // <-- cindent tries to unindent by only one shiftwidth
|
||||||
|
if pline =~ ');$'
|
||||||
|
const case = PrevMatchInBlock('^\s*case\>', plnum - 1)
|
||||||
|
if case > 0
|
||||||
|
return indent(case)
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
# If cindent would indent the same or more than the previous line, unindent.
|
||||||
|
if cindent >= pindent
|
||||||
|
return pindent - shiftwidth()
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Otherwise, use the computed cindent.
|
||||||
|
return cindent
|
||||||
endif
|
endif
|
||||||
|
|
||||||
" Don't indent an extra shiftwidth for cases which span multiple lines.
|
# Indent after `case`.
|
||||||
if prevline =~# '\v\=\>\s*(//.*)?$' && prevline !~# '\v^\s*case\W'
|
if line !~ '^\s*}'
|
||||||
return indent(prevlnum)
|
# If the previous `case` started and ended on the same line, indent.
|
||||||
|
if pline =~ '^\s*case\>.*;$'
|
||||||
|
return pindent + shiftwidth()
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Indent after a single-line `case`.
|
||||||
|
if pline =~ '^\s*case\>.*=>$'
|
||||||
|
return pindent + shiftwidth()
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Indent inside a multi-line `case`.
|
||||||
|
if pline =~ '^\s*case\>' && pline !~ '=>'
|
||||||
|
return pindent + shiftwidth() * GetValue('hare_indent_case', 2)
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Indent after a multi-line `case`.
|
||||||
|
if pline =~ '=>$'
|
||||||
|
return pindent - shiftwidth() * (GetValue('hare_indent_case', 2) - 1)
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Don't unindent while inside a `case` body.
|
||||||
|
if ppline =~ '=>$' && pline =~ ';$'
|
||||||
|
return pindent
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Don't unindent if the previous line ended a block. This fixes a very
|
||||||
|
# peculiar edge case where cindent would try to unindent after a block, but
|
||||||
|
# only if it is the first expression within a `case` body:
|
||||||
|
#
|
||||||
|
# case =>
|
||||||
|
# if (foo) {
|
||||||
|
# bar();
|
||||||
|
# };
|
||||||
|
# | <-- cindent tries to unindent by one shiftwidth
|
||||||
|
if pline =~ '};$' && cindent < pindent
|
||||||
|
return pindent
|
||||||
|
endif
|
||||||
|
|
||||||
|
# If the previous line closed a set of parens, and cindent would try to
|
||||||
|
# unindent more than one level, search for the previous `case` within the
|
||||||
|
# same block. If that line didn't contain a `:` (excluding `::`), indent one
|
||||||
|
# level more. This fixes an issue where cindent would unindent too far when
|
||||||
|
# there was no `:` after a `case`:
|
||||||
|
#
|
||||||
|
# case foo =>
|
||||||
|
# bar(baz,
|
||||||
|
# quux);
|
||||||
|
# | <-- cindent tries to unindent by two shiftwidths
|
||||||
|
if pline =~ ').*;$' && cindent < pindent - shiftwidth()
|
||||||
|
const case = PrevMatchInBlock('^\s*case\>', plnum - 1)
|
||||||
|
if case > 0 && GetTrimmedLine(case) !~ '\v%(%(::)*)@>:'
|
||||||
|
return indent(case) + shiftwidth()
|
||||||
|
endif
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
" Indent the body of a case.
|
# If the previous line ended with `=`, indent.
|
||||||
" If the previous line ended in a semicolon and the line before that was a
|
if pline =~ '=$'
|
||||||
" case, don't do any special indenting.
|
return pindent + shiftwidth()
|
||||||
if prevline =~# '\v;\s*(//.*)?$' && prevprevline =~# '\v\=\>\s*(//.*)?$'
|
|
||||||
\ && line !~# '\v^\s*}'
|
|
||||||
return indent(prevlnum)
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let l:indent = FloorCindent(v:lnum)
|
# If the previous line opened an array literal, indent.
|
||||||
|
if pline =~ '[$'
|
||||||
" If the previous line was a case and a normal cindent wouldn't indent, indent
|
return pindent + shiftwidth()
|
||||||
" an extra shiftwidth.
|
|
||||||
if prevline =~# '\v\=\>\s*(//.*)?$' && l:indent == indent(prevlnum)
|
|
||||||
return l:indent + shiftwidth()
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
" If everything above is false, do a normal cindent.
|
# If the previous line started a binding expression, indent.
|
||||||
return l:indent
|
if pline =~ '\v<%(const|def|let|type)$'
|
||||||
endfunction
|
return pindent + shiftwidth()
|
||||||
|
endif
|
||||||
|
|
||||||
let &cpo = s:cpo_save
|
# Indent continuation lines.
|
||||||
unlet s:cpo_save
|
if !TrailingParen(pline)
|
||||||
|
# If this line closed an array and cindent would indent the same amount as
|
||||||
|
# the previous line, unindent.
|
||||||
|
if line =~ '^\s*]' && cindent == pindent
|
||||||
|
return cindent - shiftwidth()
|
||||||
|
endif
|
||||||
|
|
||||||
" vim: et sw=2 sts=2 ts=8
|
# If the previous line closed an array literal, use the same indent. This
|
||||||
|
# fixes an issue where cindent would try to indent an additional level after
|
||||||
|
# an array literal containing indexing or slicing expressions, but only
|
||||||
|
# inside a block:
|
||||||
|
#
|
||||||
|
# export fn main() void = {
|
||||||
|
# const foo = [
|
||||||
|
# bar[..4],
|
||||||
|
# baz[..],
|
||||||
|
# quux[1..],
|
||||||
|
# ];
|
||||||
|
# | <-- cindent tries to indent by one shiftwidth
|
||||||
|
if pline =~ '^\s*];$' && cindent > pindent
|
||||||
|
return pindent
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Don't indent any further if the previous line closed an enum, struct, or
|
||||||
|
# union.
|
||||||
|
if pline =~ '^\s*},$' && cindent > pindent
|
||||||
|
return pindent
|
||||||
|
endif
|
||||||
|
|
||||||
|
# If the previous line started a binding expression, and the first binding
|
||||||
|
# was on the same line, indent.
|
||||||
|
if pline =~ '\v<%(const|def|let|type)>.{-}\=.*,$'
|
||||||
|
return pindent + shiftwidth()
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Use the original indentation after a single continuation line.
|
||||||
|
if pline =~ '[,;]$' && ppline =~ '=$'
|
||||||
|
return ppindent
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Don't unindent within a binding expression.
|
||||||
|
if pline =~ ',$' && ppline =~ '\v<%(const|def|let|type)$'
|
||||||
|
return pindent
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
# If the previous line had an unclosed `if` or `for` condition, indent twice.
|
||||||
|
if pline =~ '\v<%(if|for)>'
|
||||||
|
const cond = match(pline, '\v%(if|for)>[^(]*\zs\(')
|
||||||
|
if cond != -1 && TrailingParen(pline, cond)
|
||||||
|
return pindent + shiftwidth() * 2
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Optionally indent unclosed `match` and `switch` conditions an extra level.
|
||||||
|
if pline =~ '\v<%(match|switch)>'
|
||||||
|
const cond = match(pline, '\v<%(match|switch)>[^(]*\zs\(')
|
||||||
|
if cond != -1 && TrailingParen(pline, cond)
|
||||||
|
return pindent + shiftwidth()
|
||||||
|
* GetValue('hare_indent_match_switch', 1, 1, 2)
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Otherwise, use the computed cindent.
|
||||||
|
return cindent
|
||||||
|
enddef
|
||||||
|
|
||||||
|
# Returns a line, with any comments or whitespace trimmed from the end.
|
||||||
|
def GetTrimmedLine(lnum: number): string
|
||||||
|
var line = getline(lnum)
|
||||||
|
|
||||||
|
# Use syntax highlighting attributes when possible.
|
||||||
|
if has('syntax_items')
|
||||||
|
# If the last character is inside a comment, do a binary search to find the
|
||||||
|
# beginning of the comment.
|
||||||
|
const len = strlen(line)
|
||||||
|
if synIDattr(synID(lnum, len, true), 'name') =~ 'Comment\|Todo'
|
||||||
|
var min = 1
|
||||||
|
var max = len
|
||||||
|
while min < max
|
||||||
|
const col = (min + max) / 2
|
||||||
|
if synIDattr(synID(lnum, col, true), 'name') =~ 'Comment\|Todo'
|
||||||
|
max = col
|
||||||
|
else
|
||||||
|
min = col + 1
|
||||||
|
endif
|
||||||
|
endwhile
|
||||||
|
line = strpart(line, 0, min - 1)
|
||||||
|
endif
|
||||||
|
return substitute(line, '\s*$', '', '')
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Otherwise, use a regex as a fallback.
|
||||||
|
return substitute(line, '\s*//.*$', '', '')
|
||||||
|
enddef
|
||||||
|
|
||||||
|
# Returns the value of a configuration variable, clamped within the given range.
|
||||||
|
def GetValue(
|
||||||
|
name: string,
|
||||||
|
default: number,
|
||||||
|
min: number = 0,
|
||||||
|
max: number = default,
|
||||||
|
): number
|
||||||
|
const n = get(b:, name, get(g:, name, default))
|
||||||
|
return min([max, max([n, min])])
|
||||||
|
enddef
|
||||||
|
|
||||||
|
# Returns the line number of the previous match for a pattern within the same
|
||||||
|
# block. Returns 0 if nothing was found.
|
||||||
|
def PrevMatchInBlock(
|
||||||
|
pattern: string,
|
||||||
|
lnum: number,
|
||||||
|
maxlines: number = 20,
|
||||||
|
): number
|
||||||
|
var block = 0
|
||||||
|
for n in range(lnum, lnum - maxlines, -1)
|
||||||
|
if n < 1
|
||||||
|
break
|
||||||
|
endif
|
||||||
|
|
||||||
|
const line = GetTrimmedLine(n)
|
||||||
|
if line =~ '{$'
|
||||||
|
block -= 1
|
||||||
|
if block < 0
|
||||||
|
break
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
if line =~ pattern && block == 0
|
||||||
|
return n
|
||||||
|
endif
|
||||||
|
|
||||||
|
if line =~ '^\s*}'
|
||||||
|
block += 1
|
||||||
|
endif
|
||||||
|
endfor
|
||||||
|
return 0
|
||||||
|
enddef
|
||||||
|
|
||||||
|
# Returns the line number and contents of the previous non-blank line, with any
|
||||||
|
# comments trimmed.
|
||||||
|
def PrevNonBlank(lnum: number): tuple<number, string>
|
||||||
|
var plnum = prevnonblank(lnum)
|
||||||
|
var pline = GetTrimmedLine(plnum)
|
||||||
|
while plnum > 1 && pline !~ '[^[:blank:]]'
|
||||||
|
plnum = prevnonblank(plnum - 1)
|
||||||
|
pline = GetTrimmedLine(plnum)
|
||||||
|
endwhile
|
||||||
|
return (plnum, pline)
|
||||||
|
enddef
|
||||||
|
|
||||||
|
# Returns whether a line contains at least one unclosed `(`.
|
||||||
|
# XXX: Can still be fooled by parens inside rune and string literals.
|
||||||
|
def TrailingParen(line: string, start: number = 0): bool
|
||||||
|
var total = 0
|
||||||
|
for n in strpart(line, start)->filter((_, n) => n =~ '[()]')->reverse()
|
||||||
|
if n == ')'
|
||||||
|
total += 1
|
||||||
|
else
|
||||||
|
total -= 1
|
||||||
|
if total < 0
|
||||||
|
return true
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endfor
|
||||||
|
return false
|
||||||
|
enddef
|
||||||
|
|
||||||
|
# vim: et sts=2 sw=2 ts=8 tw=80
|
||||||
|
@ -1,157 +1,268 @@
|
|||||||
" Vim syntax file.
|
vim9script
|
||||||
" Language: Hare
|
|
||||||
" Maintainer: Amelia Clarke <selene@perilune.dev>
|
# Vim syntax file.
|
||||||
" Last Change: 2024-05-10
|
# Language: Hare
|
||||||
" Upstream: https://git.sr.ht/~sircmpwn/hare.vim
|
# Maintainer: Amelia Clarke <selene@perilune.dev>
|
||||||
|
# Last Change: 2025 Sep 06
|
||||||
|
# Upstream: https://git.sr.ht/~sircmpwn/hare.vim
|
||||||
|
|
||||||
if exists('b:current_syntax')
|
if exists('b:current_syntax')
|
||||||
finish
|
finish
|
||||||
endif
|
endif
|
||||||
syn include @haredoc syntax/haredoc.vim
|
|
||||||
let b:current_syntax = 'hare'
|
|
||||||
|
|
||||||
" Syntax {{{1
|
# Syntax {{{1
|
||||||
syn case match
|
syn case match
|
||||||
syn iskeyword @,48-57,@-@,_
|
syn iskeyword @,48-57,@-@,_
|
||||||
|
|
||||||
" Keywords {{{2
|
# Reserved keywords.
|
||||||
syn keyword hareConditional else if match switch
|
syn cluster hareReserved contains=hareBoolean,hareBuiltin,hareConditional,hareConstant,hareDefine,hareInclude,hareKeyword,hareLabel,hareOperator,hareRepeat,hareStorageClass,hareStructure,hareType,hareTypedef
|
||||||
syn keyword hareDefine def
|
|
||||||
syn keyword hareInclude use
|
|
||||||
syn keyword hareKeyword break continue return yield
|
|
||||||
syn keyword hareKeyword case
|
|
||||||
syn keyword hareKeyword const let
|
|
||||||
syn keyword hareKeyword defer
|
|
||||||
syn keyword hareKeyword export static
|
|
||||||
syn keyword hareKeyword fn
|
|
||||||
syn keyword hareOperator as is
|
|
||||||
syn keyword hareRepeat for
|
|
||||||
syn keyword hareTypedef type
|
|
||||||
|
|
||||||
" Attributes.
|
# Types {{{2
|
||||||
syn keyword hareAttribute @fini @init @test
|
syn cluster hareType contains=hareErrorFlag,harePointer,hareSlice,hareStorageClass,hareStructure,hareTaggedUnion,hareType
|
||||||
syn keyword hareAttribute @offset @packed
|
|
||||||
syn keyword hareAttribute @symbol
|
|
||||||
syn keyword hareAttribute @threadlocal
|
|
||||||
|
|
||||||
" Builtins.
|
|
||||||
syn keyword hareBuiltin abort assert
|
|
||||||
syn keyword hareBuiltin align len offset
|
|
||||||
syn keyword hareBuiltin alloc free
|
|
||||||
syn keyword hareBuiltin append delete insert
|
|
||||||
syn keyword hareBuiltin vaarg vaend vastart
|
|
||||||
|
|
||||||
" Types {{{2
|
|
||||||
syn keyword hareType bool
|
syn keyword hareType bool
|
||||||
syn keyword hareType done
|
syn keyword hareType done
|
||||||
syn keyword hareType f32 f64
|
syn keyword hareType f32 f64
|
||||||
syn keyword hareType i8 i16 i32 i64 int
|
syn keyword hareType i8 i16 i32 i64 int
|
||||||
syn keyword hareType never
|
syn keyword hareType never
|
||||||
|
syn keyword hareType nomem
|
||||||
syn keyword hareType opaque
|
syn keyword hareType opaque
|
||||||
syn keyword hareType rune str
|
syn keyword hareType rune str
|
||||||
syn keyword hareType u8 u16 u32 u64 uint
|
syn keyword hareType u8 u16 u32 u64 uint uintptr
|
||||||
syn keyword hareType uintptr
|
|
||||||
syn keyword hareType valist
|
|
||||||
syn keyword hareType void
|
syn keyword hareType void
|
||||||
|
|
||||||
" Other types.
|
# C ABI.
|
||||||
syn keyword hareStorageClass nullable
|
syn keyword hareType valist
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# Other types.
|
||||||
|
syn keyword hareStorageClass nullable nextgroup=harePointer skipempty skipwhite
|
||||||
syn keyword hareStructure enum struct union
|
syn keyword hareStructure enum struct union
|
||||||
|
|
||||||
" Literals {{{2
|
# Declarations {{{2
|
||||||
syn keyword hareBoolean false true
|
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
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# Attributes {{{3
|
||||||
|
syn keyword hareAttribute @init @fini @test
|
||||||
|
syn keyword hareAttribute @offset nextgroup=hareAttrParens skipempty skipwhite
|
||||||
|
syn keyword hareAttribute @packed
|
||||||
|
syn keyword hareAttribute @symbol nextgroup=hareAttrParens skipempty skipwhite
|
||||||
|
syn keyword hareAttribute @threadlocal
|
||||||
|
|
||||||
|
# Match the parens after attributes.
|
||||||
|
syn region hareAttrParens matchgroup=hareAttrParens start='(' end=')' contained contains=TOP
|
||||||
|
|
||||||
|
# Expressions {{{2
|
||||||
|
syn keyword hareConditional else
|
||||||
|
syn keyword hareConditional if nextgroup=hareCondParens 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
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# C ABI.
|
||||||
|
syn keyword hareBuiltin vastart vaarg vaend nextgroup=hareBuiltinCall skipempty skipwhite
|
||||||
|
|
||||||
|
# Highlight `size` as a builtin only if it is followed by an open paren.
|
||||||
|
syn match hareType '\<size\>'
|
||||||
|
syn match hareBuiltin '\<size\ze(' nextgroup=hareBuiltinTypeCall
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# Postfix expressions {{{3
|
||||||
|
# TODO: Match postfix expressions after literals.
|
||||||
|
syn cluster harePostfix contains=hareCast,hareErrorCheck,hareFieldAccess,hareFuncCall,hareIndex
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# Tagged union and tuple types.
|
||||||
|
syn region hareTaggedUnion matchgroup=hareTaggedUnion start='(' end=')' contained containedin=hareBuiltinTypeCall,hareTaggedUnion contains=TOP
|
||||||
|
|
||||||
|
# Literals {{{3
|
||||||
|
syn keyword hareBoolean true false
|
||||||
syn keyword hareConstant null
|
syn keyword hareConstant null
|
||||||
|
|
||||||
" Integer literals.
|
# Integers.
|
||||||
syn match hareNumber '\v<%(0|[1-9]%(_?\d)*)%([Ee]\+?\d+)?%([iu]%(8|16|32|64)?|z)?>' display
|
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)?>' display
|
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)?>' display
|
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)?>' display
|
syn match hareNumber '\v<0x\x%(_?\x)*%([iu]%(8|16|32|64)?|z)?>'
|
||||||
|
|
||||||
" Floating-point literals.
|
# Floats.
|
||||||
syn match hareFloat '\v<%(0|[1-9]%(_?\d)*)\.\d%(_?\d)*%([Ee][+-]?\d+)?%(f32|f64)?>' display
|
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)>' display
|
syn match hareFloat '\v<%(0|[1-9]%(_?\d)*)%([Ee][+-]?\d+)?%(f32|f64)>'
|
||||||
syn match hareFloat '\v<0x\x%(_?\x)*%(\.\x%(_?\x)*)?[Pp][+-]?\d+%(f32|f64)?>' display
|
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.
|
# Rune and string literals.
|
||||||
syn region hareRune start="'" skip="\\'" end="'" contains=hareEscape
|
syn region hareRune start="'" skip="\\'" end="'" contains=hareEscape
|
||||||
syn region hareString start='"' skip='\\"' end='"' contains=hareEscape,hareFormat
|
syn region hareString start='"' skip='\\"' end='"' contains=hareEscape,hareFormat
|
||||||
syn region hareString start='`' end='`' contains=hareFormat
|
syn region hareString start='`' end='`' contains=hareFormat
|
||||||
|
|
||||||
" Escape sequences.
|
# Escape sequences.
|
||||||
syn match hareEscape '\\[0abfnrtv\\'"]' contained
|
syn match hareEscape '\\[0abfnrtv\\'"]' contained
|
||||||
syn match hareEscape '\v\\%(x\x{2}|u\x{4}|U\x{8})' contained display
|
syn match hareEscape '\v\\%(x\x{2}|u\x{4}|U\x{8})' contained display
|
||||||
|
|
||||||
" Format sequences.
|
# Format sequences.
|
||||||
syn match hareFormat '\v\{\d*%(:%(\.?\d+|[ +\-=Xbefgox]|F[.2ESUs]|_%(.|\\%([0abfnrtv\\'"]|x\x{2}|u\x{4}|U\x{8})))*)?}' contained contains=hareEscape display
|
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 '{\d*%\d*}' contained display
|
syn match hareFormat '{\d*%\d*}' contained display
|
||||||
syn match hareFormat '{{\|}}' contained display
|
syn match hareFormat '{{\|}}' contained
|
||||||
|
|
||||||
" Miscellaneous {{{2
|
# Miscellaneous {{{2
|
||||||
|
|
||||||
" Comments.
|
# Annotations.
|
||||||
syn region hareComment start='//' end='$' contains=hareTodo,@haredoc,@Spell display
|
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
|
||||||
|
|
||||||
|
# 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 keyword hareTodo FIXME TODO XXX contained
|
syn keyword hareTodo FIXME TODO XXX contained
|
||||||
|
|
||||||
" Identifiers.
|
# Delimiters.
|
||||||
syn match hareDelimiter '::' display
|
syn match hareDelimiter '::'
|
||||||
syn match hareName '\<\h\w*\>' nextgroup=@harePostfix skipempty skipwhite transparent
|
|
||||||
|
|
||||||
" Labels.
|
# Labels.
|
||||||
syn match hareLabel ':\h\w*\>' display
|
syn match hareUserLabel ':\h\w*\>' contains=hareName
|
||||||
|
|
||||||
" Match `size` as a type unless it is followed by an open paren.
|
# Default highlighting {{{1
|
||||||
syn match hareType '\<size\>' display
|
hi def link hareAnnotation PreProc
|
||||||
syn match hareBuiltin '\<size\ze(' display
|
hi def link hareAnnotationParens hareAnnotation
|
||||||
|
|
||||||
" Postfix expressions.
|
|
||||||
syn cluster harePostfix contains=hareErrorTest,hareField,hareIndex,hareParens
|
|
||||||
syn match hareErrorTest '!=\@!' contained nextgroup=@harePostfix skipempty skipwhite
|
|
||||||
syn match hareErrorTest '?' nextgroup=@harePostfix skipempty skipwhite
|
|
||||||
syn match hareField '\.\w*\>'hs=s+1 contained contains=hareNumber nextgroup=@harePostfix skipempty skipwhite
|
|
||||||
syn region hareIndex start='\[' end=']' contained nextgroup=@harePostfix skipempty skipwhite transparent
|
|
||||||
syn region hareParens start='(' end=')' nextgroup=@harePostfix skipempty skipwhite transparent
|
|
||||||
|
|
||||||
" Whitespace errors.
|
|
||||||
syn match hareSpaceError '^ \+\ze\t' display
|
|
||||||
syn match hareSpaceError excludenl '\s\+$' containedin=ALL display
|
|
||||||
|
|
||||||
" Folding {{{3
|
|
||||||
syn region hareBlock start='{' end='}' fold transparent
|
|
||||||
|
|
||||||
" Default highlighting {{{1
|
|
||||||
hi def link hareAttribute PreProc
|
hi def link hareAttribute PreProc
|
||||||
hi def link hareBoolean Boolean
|
hi def link hareBoolean Boolean
|
||||||
hi def link hareBuiltin Operator
|
hi def link hareBuiltin Operator
|
||||||
hi def link hareComment Comment
|
hi def link hareComment Comment
|
||||||
|
hi def link hareCommentCode hareComment
|
||||||
|
hi def link hareCommentRef SpecialComment
|
||||||
hi def link hareConditional Conditional
|
hi def link hareConditional Conditional
|
||||||
hi def link hareConstant Constant
|
hi def link hareConstant Constant
|
||||||
hi def link hareDefine Define
|
hi def link hareDefine Define
|
||||||
hi def link hareDelimiter Delimiter
|
hi def link hareDelimiter Delimiter
|
||||||
hi def link hareErrorTest Special
|
hi def link hareErrorFlag hareStorageClass
|
||||||
|
hi def link hareErrorCheck Special
|
||||||
hi def link hareEscape SpecialChar
|
hi def link hareEscape SpecialChar
|
||||||
hi def link hareFloat Float
|
hi def link hareFloat Float
|
||||||
hi def link hareFormat SpecialChar
|
hi def link hareFormat SpecialChar
|
||||||
|
hi def link hareFunction Function
|
||||||
hi def link hareInclude Include
|
hi def link hareInclude Include
|
||||||
hi def link hareKeyword Keyword
|
hi def link hareKeyword Keyword
|
||||||
hi def link hareLabel Special
|
hi def link hareLabel Label
|
||||||
hi def link hareNumber Number
|
hi def link hareNumber Number
|
||||||
hi def link hareOperator Operator
|
hi def link hareOperator Operator
|
||||||
|
hi def link harePointer hareStorageClass
|
||||||
hi def link hareRepeat Repeat
|
hi def link hareRepeat Repeat
|
||||||
hi def link hareRune Character
|
hi def link hareRune Character
|
||||||
|
hi def link hareSliceBounds harePointer
|
||||||
hi def link hareStorageClass StorageClass
|
hi def link hareStorageClass StorageClass
|
||||||
hi def link hareString String
|
hi def link hareString String
|
||||||
hi def link hareStructure Structure
|
hi def link hareStructure Structure
|
||||||
hi def link hareTodo Todo
|
hi def link hareTodo Todo
|
||||||
hi def link hareType Type
|
hi def link hareType Type
|
||||||
hi def link hareTypedef Typedef
|
hi def link hareTypedef Typedef
|
||||||
|
hi def link hareUserLabel Identifier
|
||||||
|
|
||||||
" Highlight embedded haredoc references.
|
# Optionally highlight symbolic operators.
|
||||||
hi! def link haredocRefValid SpecialComment
|
if get(g:, 'hare_symbol_operators')
|
||||||
|
hi! def link hareSymbolOperator hareOperator
|
||||||
" Highlight whitespace errors by default.
|
else
|
||||||
if get(g:, 'hare_space_error', 1)
|
hi! def link hareSymbolOperator NONE
|
||||||
hi def link hareSpaceError Error
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
" vim: et sts=2 sw=2 ts=8
|
# Highlight incorrect whitespace by default.
|
||||||
|
syn match hareSpaceError '\s\+$' containedin=ALL display
|
||||||
|
syn match hareSpaceError ' \+\ze\t' display
|
||||||
|
if get(g:, 'hare_space_error', 1)
|
||||||
|
hi! def link hareSpaceError Error
|
||||||
|
else
|
||||||
|
hi! def link hareSpaceError NONE
|
||||||
|
endif
|
||||||
|
|
||||||
|
b:current_syntax = 'hare'
|
||||||
|
|
||||||
|
# vim: fdm=marker et sts=2 sw=2 ts=8 tw=80
|
||||||
|
@ -1,32 +1,43 @@
|
|||||||
" Vim syntax file.
|
vim9script
|
||||||
" Language: Haredoc (Hare documentation format)
|
|
||||||
" Maintainer: Amelia Clarke <selene@perilune.dev>
|
# Vim syntax file.
|
||||||
" Last Change: 2024-05-10
|
# Language: Haredoc (Hare documentation format)
|
||||||
" Upstream: https://git.sr.ht/~selene/hare.vim
|
# Maintainer: Amelia Clarke <selene@perilune.dev>
|
||||||
|
# Last Change: 2025 Aug 14
|
||||||
|
# Upstream: https://git.sr.ht/~sircmpwn/hare.vim
|
||||||
|
|
||||||
if exists('b:current_syntax')
|
if exists('b:current_syntax')
|
||||||
finish
|
finish
|
||||||
endif
|
endif
|
||||||
let b:current_syntax = 'haredoc'
|
|
||||||
|
|
||||||
" Syntax {{{1
|
# Syntax {{{1
|
||||||
syn case match
|
syn case match
|
||||||
syn iskeyword @,48-57,_
|
syn iskeyword @,48-57,_
|
||||||
|
|
||||||
" Code samples.
|
# Embedded code samples.
|
||||||
syn region haredocCodeSample excludenl start='\t\zs' end='$' contains=@NoSpell display
|
syn region haredocCode start='\t\zs' end='$' contains=@NoSpell display
|
||||||
|
|
||||||
" References to other declarations and modules.
|
# References to other declarations and modules.
|
||||||
syn region haredocRef start='\[\[' end=']]' contains=haredocRefValid,@NoSpell display keepend oneline
|
syn match haredocRef '\v\[\[\h\w*%(::\h\w*)*%(::)?]]' contains=@NoSpell display
|
||||||
syn match haredocRefValid '\v\[\[\h\w*%(::\h\w*)*%(::)?]]' contained contains=@NoSpell display
|
|
||||||
|
|
||||||
" Miscellaneous.
|
# Miscellaneous.
|
||||||
syn keyword haredocTodo FIXME TODO XXX
|
syn keyword haredocTodo FIXME TODO XXX
|
||||||
|
|
||||||
" Default highlighting {{{1
|
# Default highlighting {{{1
|
||||||
hi def link haredocCodeSample Comment
|
hi def link haredocCode Comment
|
||||||
hi def link haredocRef Error
|
hi def link haredocRef Special
|
||||||
hi def link haredocRefValid Special
|
|
||||||
hi def link haredocTodo Todo
|
hi def link haredocTodo Todo
|
||||||
|
|
||||||
" vim: et sts=2 sw=2 ts=8
|
# 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
|
||||||
|
if get(g:, 'hare_space_error', 1)
|
||||||
|
hi! def link haredocSpaceError Error
|
||||||
|
else
|
||||||
|
hi! def link haredocSpaceError NONE
|
||||||
|
endif
|
||||||
|
|
||||||
|
b:current_syntax = 'haredoc'
|
||||||
|
|
||||||
|
# vim: fdm=marker et sts=2 sw=2 ts=8 tw=80
|
||||||
|
@ -1708,6 +1708,7 @@ endfunc
|
|||||||
|
|
||||||
func Test_haredoc_file()
|
func Test_haredoc_file()
|
||||||
filetype on
|
filetype on
|
||||||
|
|
||||||
call assert_true(mkdir('foo/bar', 'pR'))
|
call assert_true(mkdir('foo/bar', 'pR'))
|
||||||
|
|
||||||
call writefile([], 'README', 'D')
|
call writefile([], 'README', 'D')
|
||||||
@ -1715,28 +1716,37 @@ func Test_haredoc_file()
|
|||||||
call assert_notequal('haredoc', &filetype)
|
call assert_notequal('haredoc', &filetype)
|
||||||
bwipe!
|
bwipe!
|
||||||
|
|
||||||
|
let g:filetype_haredoc = 3
|
||||||
|
call writefile([], 'foo/bar/bar.ha', 'D')
|
||||||
|
split README
|
||||||
|
call assert_equal('haredoc', &filetype)
|
||||||
|
bwipe!
|
||||||
|
|
||||||
|
let g:filetype_haredoc = 2
|
||||||
|
split README
|
||||||
|
call assert_notequal('haredoc', &filetype)
|
||||||
|
bwipe!
|
||||||
|
|
||||||
|
call writefile([], 'foo/foo.ha', 'D')
|
||||||
|
split README
|
||||||
|
call assert_equal('haredoc', &filetype)
|
||||||
|
bwipe!
|
||||||
|
|
||||||
let g:filetype_haredoc = 1
|
let g:filetype_haredoc = 1
|
||||||
split README
|
split README
|
||||||
call assert_notequal('haredoc', &filetype)
|
call assert_notequal('haredoc', &filetype)
|
||||||
bwipe!
|
bwipe!
|
||||||
|
|
||||||
call writefile([], 'foo/quux.ha')
|
call writefile([], 'main.ha', 'D')
|
||||||
split README
|
split README
|
||||||
call assert_equal('haredoc', &filetype)
|
call assert_equal('haredoc', &filetype)
|
||||||
bwipe!
|
bwipe!
|
||||||
call delete('foo/quux.ha')
|
|
||||||
|
|
||||||
call writefile([], 'foo/bar/baz.ha', 'D')
|
let g:filetype_haredoc = 0
|
||||||
split README
|
split README
|
||||||
call assert_notequal('haredoc', &filetype)
|
call assert_notequal('haredoc', &filetype)
|
||||||
bwipe!
|
bwipe!
|
||||||
|
|
||||||
let g:haredoc_search_depth = 2
|
|
||||||
split README
|
|
||||||
call assert_equal('haredoc', &filetype)
|
|
||||||
bwipe!
|
|
||||||
unlet g:filetype_haredoc
|
unlet g:filetype_haredoc
|
||||||
unlet g:haredoc_search_depth
|
|
||||||
|
|
||||||
filetype off
|
filetype off
|
||||||
endfunc
|
endfunc
|
||||||
|
Reference in New Issue
Block a user