A src/.config/nvim/compiler/hare.vim => src/.config/nvim/compiler/hare.vim +29 -0
@@ 0,0 1,29 @@
+" Vim compiler file
+" Compiler: Hare Compiler
+
+if exists("g:current_compiler")
+ finish
+endif
+let g:current_compiler = "hare"
+
+let s:cpo_save = &cpo
+set cpo&vim
+
+if exists(':CompilerSet') != 2
+ command -nargs=* CompilerSet setlocal <args>
+endif
+
+if filereadable("Makefile") || filereadable("makefile")
+ CompilerSet makeprg=make
+else
+ CompilerSet makeprg=hare\ build
+endif
+
+CompilerSet errorformat=
+ \Error\ %f:%l:%c:\ %m,
+ \Syntax\ error:\ %.%#\ at\ %f:%l:%c\\,\ %m,
+ \%-G%.%#
+
+let &cpo = s:cpo_save
+unlet s:cpo_save
+" vim: tabstop=2 shiftwidth=2 expandtab
A src/.config/nvim/ftdetect/hare.vim => src/.config/nvim/ftdetect/hare.vim +1 -0
@@ 0,0 1,1 @@
+au BufRead,BufNewFile *.ha set filetype=hare
A src/.config/nvim/ftplugin/hare.vim => src/.config/nvim/ftplugin/hare.vim +25 -0
@@ 0,0 1,25 @@
+" Hare filetype plugin
+" Maintainer: Drew DeVault <sir@cmpwn.com>
+" Last Updated: 2020-05-06
+
+" Only do this when not done yet for this buffer
+if exists('b:did_ftplugin')
+ finish
+endif
+
+" Don't load another plugin for this buffer
+let b:did_ftplugin = 1
+
+setlocal noexpandtab
+setlocal tabstop=8
+setlocal shiftwidth=0
+setlocal softtabstop=0
+setlocal textwidth=80
+setlocal commentstring=//\ %s
+
+" Set 'formatoptions' to break comment lines but not other lines,
+" and insert the comment leader when hitting <CR> or using "o".
+setlocal fo-=t fo+=croql
+
+compiler hare
+" vim: tabstop=2 shiftwidth=2 expandtab
A src/.config/nvim/indent/hare.vim => src/.config/nvim/indent/hare.vim +124 -0
@@ 0,0 1,124 @@
+" Vim indent file
+" Language: Hare
+
+if exists("b:did_indent")
+ finish
+endif
+let b:did_indent = 1
+
+if !has("cindent") || !has("eval")
+ finish
+endif
+
+setlocal cindent
+
+" L0 -> don't deindent labels
+" :0 -> don't indent cases
+" (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,:0,(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
+" !^F -> <C-f> (not inserted)
+" o -> <CR> or `o` command
+" O -> `O` command
+" e -> else
+" 0=case -> case
+setlocal indentkeys=0{,0},0),!^F,o,O,e,0=case
+
+setlocal cinwords=if,else,for,switch,match
+
+setlocal indentexpr=GetHareIndent()
+
+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
+
+ " If the previous line ended in a semicolon and the line before that ended
+ " with =, deindent by one shiftwidth.
+ if prevline =~# '\v;\s*(//.*)?$' && prevprevline =~# '\v\=\s*(//.*)?$'
+ return indent(prevlnum) - shiftwidth()
+ endif
+
+ " 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 started a block, deindent by one shiftwidth.
+ " This handles the first case in a switch/match block.
+ if prevline =~# '\v\{\s*(//.*)?$'
+ 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
+
+ " Otherwise, do a normal cindent.
+ return l:indent
+ endif
+
+ " Don't indent an extra shiftwidth for cases which span multiple lines.
+ if prevline =~# '\v\=\>\s*(//.*)?$' && prevline !~# '\v^\s*case\W'
+ return indent(prevlnum)
+ endif
+
+ " Indent the body of a case.
+ " If the previous line ended in a semicolon and the line before that was a
+ " case, don't do any special indenting.
+ if prevline =~# '\v;\s*(//.*)?$' && prevprevline =~# '\v\=\>\s*(//.*)?$'
+ \ && line !~# '\v^\s*}'
+ return indent(prevlnum)
+ endif
+
+ " If everything above is false, do a normal cindent.
+ return FloorCindent(v:lnum)
+endfunction
+
+" vim: tabstop=2 shiftwidth=2 expandtab
A src/.config/nvim/syntax/hare.vim => src/.config/nvim/syntax/hare.vim +78 -0
@@ 0,0 1,78 @@
+" Vim syntax file
+" Language: Hare
+
+if exists("b:current_syntax")
+ finish
+endif
+
+syn case match
+syn keyword hareKeyword let const fn def type static export defer _
+syn keyword hareBranch for return break continue yield
+syn keyword hareConditional if else match switch
+syn keyword hareLabel case
+syn keyword hareBuiltin len offset free alloc assert append abort delete insert
+syn keyword hareBuiltin vastart vaarg vaend
+syn keyword hareOperator is as
+syn match hareType "\vsize((\_\s|//.*)*\()@!"
+syn match hareBuiltin "\vsize((\_\s|//.*)*\()@="
+syn match harePreProc "^use .*;"
+syn match harePreProc "@[a-z]*"
+syn match hareOperator "\.\.\." "\.\."
+
+syn region hareString start=+\z(["']\)+ end=+\z1+ skip=+\\\\\|\\\z1+
+syn region hareString start=+`+ end=+`+
+
+"adapted from c.vim
+"integer number, or floating point number without a dot and with "f".
+syn match hareNumbers display transparent "\v<\d" contains=hareNumber,hareOctal,hareBinary,hareFloat
+syn match hareNumber display contained "\v\d+(e[-+]?\d+)?(z|[iu](8|16|32|64)?)?"
+"hex number
+syn match hareNumber display contained "\v0x\x+(z|[iu](8|16|32|64)?)?"
+"octal number
+syn match hareOctal display contained "\v0o\o+(z|[iu](8|16|32|64)?)?"
+"binary number
+syn match hareBinary display contained '\v0b[01]+(z|[iu](8|16|32|64)?)?'
+syn match hareFloat display contained "\v\d+(e[-+]?\d+)?(f32|f64)"
+"floating point number, with dot, optional exponent
+syn match hareFloat display contained "\v\d+\.\d+(e[-+]?\d+)?(f32|f64)?"
+
+syn match hareSpaceError display excludenl "\v\s+$"
+syn match hareSpaceError display "\v +\t"me=e-1
+
+syn keyword hareTodo contained TODO FIXME XXX
+syn region hareComment start="//" end="$" contains=hareTodo,@Spell
+
+syn keyword hareType u8 u16 u32 u64 i8 i16 i32 i64
+syn keyword hareType uint int
+syn keyword hareType uintptr
+syn keyword hareType f32 f64
+syn keyword hareType bool
+syn keyword hareType char str
+syn keyword hareType void
+syn keyword hareType struct union
+syn keyword hareType enum
+syn keyword hareType nullable
+syn keyword hareType rune
+syn keyword hareType valist
+syn keyword hareNull null
+syn keyword hareBoolean true false
+
+hi def link hareBinary Number
+hi def link hareBoolean Boolean
+hi def link hareBranch Repeat
+hi def link hareBuiltin Function
+hi def link hareComment Comment
+hi def link hareConditional Conditional
+hi def link hareFloat Number
+hi def link hareKeyword Keyword
+hi def link hareLabel Label
+hi def link hareNull Constant
+hi def link hareNumber Number
+hi def link hareOctal Number
+hi def link hareOperator Operator
+hi def link harePreProc PreProc
+hi def link hareString String
+hi def link hareTodo Todo
+hi def link hareType Type
+hi def link hareSpaceError Error
+" vim: tabstop=8 shiftwidth=2 expandtab