Last active
May 28, 2024 10:03
-
-
Save omegacoleman/8d523cd8188bc8bfcbb74f3e89713b34 to your computer and use it in GitHub Desktop.
scaffold of a new snippet plugin for vim9
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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