Skip to content

Instantly share code, notes, and snippets.

@omegacoleman
Last active May 28, 2024 10:03
Show Gist options
  • Save omegacoleman/8d523cd8188bc8bfcbb74f3e89713b34 to your computer and use it in GitHub Desktop.
Save omegacoleman/8d523cd8188bc8bfcbb74f3e89713b34 to your computer and use it in GitHub Desktop.
scaffold of a new snippet plugin for vim9
vim9script
def AsMatcher(str: string): list<string>
return reverse(split(str, '\zs'))
enddef
def GetLineBeforeCur(): string
if col('.') <= 1
return ''
endif
return getline('.')[ : col('.') - 2]
enddef
def Match(tree: list<dict<number>>, matcher: list<string>): number
var curr = 0
for it in matcher
if has_key(tree[curr], it)
curr = tree[curr][it]
else
return curr
endif
endfor
return curr
enddef
var snips: dict<list<string>> = {
'ol': ['\begin{outline}', ' ####', '\end{outline}'],
'ww': ['\newwordstub{####}'],
's': ['\section{####}'],
'ss': ['\subsection{####}'],
'n': ['\notice{####}'],
}
var targets: dict<list<string>> = {}
var target_dels: dict<number> = {}
var the_tree: list<dict<number>> = [{}]
export def g:LiteSnipBuildTree()
the_tree = [{}]
targets = {}
target_dels = {}
for smatcher in keys(snips)
var matcher = AsMatcher(smatcher)
var curr = 0
for it in matcher
if has_key(the_tree[curr], it)
curr = the_tree[curr][it]
else
add(the_tree, {})
the_tree[curr][it] = len(the_tree) - 1
curr = len(the_tree) - 1
endif
endfor
targets[curr] = snips[smatcher]
target_dels[curr] = len(smatcher)
endfor
enddef
def ExpandSnip(snip: list<string>, dels: number)
if len(snip) < 1
return
endif
var line = getline('.')
var oldcur = col('.') - 1
var before = strpart(line, 0, oldcur - dels)
var after = strpart(line, oldcur)
var toset = copy(snip)
var overridecur = -1
var overridecurline = 0
for ii in range(len(toset))
var idx = stridx(toset[ii], '####')
if idx != -1
overridecur = idx
if overridecurline == 0
overridecur += oldcur - dels
endif
toset[ii] = strpart(toset[ii], 0, idx) .. strpart(toset[ii], idx + 4)
break
endif
overridecurline += 1
endfor
overridecurline += line('.')
toset[0] = before .. toset[0]
var newcur = len(toset[len(toset) - 1])
var newcurline = line('.') + len(toset) - 1
toset[len(toset) - 1] = toset[len(toset) - 1] .. after
if len(toset) > 1
append(line('.'), range(len(toset) - 1))
endif
setline('.', toset)
if overridecur != -1
cursor(overridecurline, overridecur + 1)
else
cursor(newcurline, newcur + 1)
endif
enddef
export def g:LiteSnipAttemptExpand(): bool
var bc = GetLineBeforeCur()
var n = Match(the_tree, AsMatcher(bc))
if has_key(targets, n)
ExpandSnip(targets[n], target_dels[n])
return true
else
return false
endif
enddef
export def g:LiteSnipExpand()
if !g:LiteSnipAttemptExpand()
echo "LiteSnip: snippet not found"
endif
enddef
export def g:LiteSnipDebugPrintTree()
var i = 0
for it in the_tree
echo "#" .. i
for key in keys(it)
echo " " .. key .. " -> " .. it[key]
endfor
i += 1
endfor
enddef
defcompile
g:LiteSnipBuildTree()
inoremap <silent> <c-s> <c-\><c-o>:call LiteSnipExpand()<cr>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment