~gpanders/dotfiles

c860b39ee7170cec926bc66e7ee6432a29f56805 — Gregory Anders 2 months ago f9dc228
nvim: use snippets.nvim
D .config/nvim/autoload/snippets.vim => .config/nvim/autoload/snippets.vim +0 -43
@@ 1,43 0,0 @@
let s:placeholder = '{%}'

" Map filetypes to extensions for files that don't have extensions but do have
" a known filetype. If an extension and its filetype are the same (e.g. 'c')
" then it doesn't need an entry
let s:extmap = {'python': 'py', 'ruby': 'rb'}

function! snippets#expand() abort
    let lnum = line('.')
    let col = col('.')
    let line = getline('.')
    let curline = line[0:col-1]
    if curline =~# '^\s*$'
        return "\<Tab>"
    endif

    let token = split(curline[0:col-1])[-1]
    let ext = expand('%:e')
    if ext ==# ''
        let ext = get(s:extmap, &filetype, &filetype)
    endif

    if filereadable(g:snippets_dir . '/' . token . '.' . ext)
        let file = g:snippets_dir . '/' . token . '.' . ext
    elseif filereadable(g:snippets_dir . '/' . token . '.' . &filetype)
        let file = g:snippets_dir . '/' . token . '.' . &filetype
    else
        return "\<Tab>"
    endif

    delete _
    let snippet = readfile(file)
    call append(lnum - 1, snippet)
    normal! '[

    let [l, c] = searchpos(s:placeholder, '', lnum + len(snippet) - 1)
    if l
        call setline(l, substitute(getline(l), s:placeholder, '', ''))
    endif

    " Must return an empty string so that no extra characters are inserted
    return ''
endfunction

M .config/nvim/plugin/packer.vim => .config/nvim/plugin/packer.vim +2 -0
@@ 16,6 16,8 @@ require("packer").startup(function(use)

    use "gpanders/editorconfig.nvim"

    use "gpanders/snippets.nvim"

    use "gpanders/vim-surround"

    use "tpope/vim-commentary"

M .config/nvim/plugin/snippets.vim => .config/nvim/plugin/snippets.vim +102 -6
@@ 1,8 1,104 @@
if exists('g:loaded_snippets')
    finish
endif
let g:loaded_snippets = 1
function! s:load()
    inoremap <expr> <Tab> v:lua.check_snippet() ? '<Cmd>lua require("snippets").expand_or_advance(1)<CR>' : '<Tab>'
    inoremap <S-Tab> <Cmd>lua require("snippets").advance_snippet(-1)<CR>
lua <<
local ok, snippets = pcall(require, "snippets")
if not ok then
    return
end

let g:snippets_dir = split(&runtimepath, ',')[0] . '/snippets'
function _G.check_snippet()
    if snippets.has_active_snippet() then
        return true
    end

imap <silent> <expr> <Tab> pumvisible() ? "\<C-N>" : "\<C-R>=snippets#expand()\<CR>"
    local _, snippet = snippets.lookup_snippet_at_cursor()
    return snippet ~= nil
end

function _G.split_getopts(str)
    local lines = {}
    for c in str:gmatch("(%a[:]?)") do
        if c:find(":") then
            table.insert(lines, string.format("\t\t%s) echo \"$OPTARG\" ;;", c:sub(1, 1)))
        else
            table.insert(lines, string.format("\t\t%s) ;;", c))
        end
    end

    return table.concat(lines, "\n")
end

local U = require("snippets.utils")

snippets.ux = require("snippets.inserters.extmarks")

-- Map from snippet file extension to filetype
local ext_ft_map = {
    ["py"] = "python",
    ["rs"] = "rust",
}

-- Read snippets from snippets directory
local snippets_dir = vim.fn.stdpath("config") .. "/snippets"
local function read_snippets(t)
    local s = t or {}
    for filename in vim.gsplit(vim.fn.glob(snippets_dir .. "/*"), "\n") do
        local f = io.open(filename)
        if f then
            local name, ext = filename:match("^.+/([^/]+)%.([^.]+)$")
            local ft = ext_ft_map[ext] or ext
            if not s[ft] then
                s[ft] = {}
            end

            local snippet = f:read("*all")
            f:close()

            -- Strip trailing newline
            snippet = snippet:gsub("\n$", "")

            if snippet:find("\n") then
                snippet = U.match_indentation(snippet)
            end

            s[ft][name] = snippet
        end
    end

    return s
end

snippets.snippets = read_snippets({
    _global = {
        copyright = U.force_comment([[Copyright (C) ${=os.date("%Y")} Gregory Anders]]),
        GPL = (function()
            local S = U.force_comment([[
Copyright (C) ${=os.date("%Y")} Gregory Anders

SPDX-License-Identifier: GPL-3.0-or-later

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <https://www.gnu.org/licenses/>.]])
            table.insert(S, "\n")
            table.insert(S, "\n")
            return S
        end)(),
    },
})
.
endfunction

augroup my_snippets
    autocmd! InsertEnter * ++once call s:load()
augroup END

M .config/nvim/snippets/alloc.zig => .config/nvim/snippets/alloc.zig +1 -1
@@ 1,2 1,2 @@
var buf = try allocator.alloc(u8, {%});
var buf = try allocator.alloc(u8, $0);
defer allocator.free(buf);

M .config/nvim/snippets/cout.cpp => .config/nvim/snippets/cout.cpp +1 -1
@@ 1,1 1,1 @@
std::cout << {%} << std::endl;
std::cout << "$0" << std::endl;

M .config/nvim/snippets/eprint.rs => .config/nvim/snippets/eprint.rs +1 -1
@@ 1,1 1,1 @@
eprintln!("{%}");
eprintln!("$0");

A .config/nvim/snippets/for.c => .config/nvim/snippets/for.c +3 -0
@@ 0,0 1,3 @@
for (size_t ${1:i} = ${2:0}; $1 < ${3}; $1++) {
	$0
}

M .config/nvim/snippets/getopts.sh => .config/nvim/snippets/getopts.sh +4 -3
@@ 1,7 1,8 @@
while getopts "h" o; do
	case "$o" in
while getopts "h$1" o; do
	case "\$o" in
		h) usage; exit 0 ;;
${1|split_getopts(S.v)}
		*) usage >&2; exit 1 ;;
	esac
done
shift $((OPTIND-1))
shift \$((OPTIND-1))

A .config/nvim/snippets/ifndef.c => .config/nvim/snippets/ifndef.c +6 -0
@@ 0,0 1,6 @@
#ifndef $1_H_
#define $1_H_

$0

#endif // ${1|S.v:upper()}_H_

A .config/nvim/snippets/inc.c => .config/nvim/snippets/inc.c +1 -0
@@ 0,0 1,1 @@
#include "$0.h"

M .config/nvim/snippets/main.c => .config/nvim/snippets/main.c +1 -1
@@ 3,6 3,6 @@
int
main(int argc, char *argv[])
{
	{%}
	$0
	return 0;
}

M .config/nvim/snippets/main.go => .config/nvim/snippets/main.go +1 -1
@@ 1,5 1,5 @@
package main

func main() {

	$0
}

A .config/nvim/snippets/print.c => .config/nvim/snippets/print.c +1 -0
@@ 0,0 1,1 @@
printf("$0\n");

A .config/nvim/snippets/print.go => .config/nvim/snippets/print.go +1 -0
@@ 0,0 1,1 @@
fmt.Println("$0")

A .config/nvim/snippets/print.lua => .config/nvim/snippets/print.lua +1 -0
@@ 0,0 1,1 @@
print("$0")

A .config/nvim/snippets/print.py => .config/nvim/snippets/print.py +1 -0
@@ 0,0 1,1 @@
print(f"$0")

M .config/nvim/snippets/print.rs => .config/nvim/snippets/print.rs +1 -1
@@ 1,1 1,1 @@
println!("{%}");
println!("$0");

D .config/nvim/snippets/printf.c => .config/nvim/snippets/printf.c +0 -1
@@ 1,1 0,0 @@
printf("{%}\n");

A .config/nvim/snippets/sinc.c => .config/nvim/snippets/sinc.c +1 -0
@@ 0,0 1,1 @@
#include <$0.h>

M .config/nvim/snippets/stderr.c => .config/nvim/snippets/stderr.c +1 -1
@@ 1,1 1,1 @@
fprintf(stderr, "{%}\n");
fprintf(stderr, "$0\n");

M .config/nvim/snippets/warn.zig => .config/nvim/snippets/warn.zig +1 -1
@@ 1,1 1,1 @@
std.debug.warn("{%}", .{});
std.debug.warn("$0", .{});