From 7d3ef607c22be64596d124b5ccf06d4aa25d16da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Dom=C3=ADnguez=20Ochoa?= Date: Wed, 2 Apr 2025 20:01:11 +0200 Subject: [PATCH] add snippets for common languages --- nvim/.config/nvim/lua/plugins/completion.lua | 27 +- nvim/.config/nvim/snippets/.gitkeep | 0 nvim/.config/nvim/snippets/bash.lua | 353 +++++++++++++++++++ nvim/.config/nvim/snippets/lua.lua | 79 +++++ nvim/.config/nvim/snippets/python.lua | 75 ++++ nvim/.config/nvim/snippets/rust.lua | 340 ++++++++++++++++++ 6 files changed, 865 insertions(+), 9 deletions(-) delete mode 100644 nvim/.config/nvim/snippets/.gitkeep create mode 100644 nvim/.config/nvim/snippets/bash.lua create mode 100644 nvim/.config/nvim/snippets/lua.lua create mode 100644 nvim/.config/nvim/snippets/python.lua create mode 100644 nvim/.config/nvim/snippets/rust.lua diff --git a/nvim/.config/nvim/lua/plugins/completion.lua b/nvim/.config/nvim/lua/plugins/completion.lua index 961cdaa..3acbf85 100644 --- a/nvim/.config/nvim/lua/plugins/completion.lua +++ b/nvim/.config/nvim/lua/plugins/completion.lua @@ -9,15 +9,24 @@ return { build = "make install_jsregexp", config = function() local ls = require("luasnip") - local s = ls.snippet - local t = ls.text_node - local i = ls.insert_node - - ls.add_snippets("lua", { - s("hello", { - t('print("hello world!")'), - }), - }) + local snippets_folder = vim.fn.stdpath("config") .. "/snippets" + local function load_snippets() + -- Load all Lua files in the snippets directory except init.lua + local files = vim.fn.glob(snippets_folder .. "/*.lua", false, true) + for _, file in ipairs(files) do + local filename = vim.fn.fnamemodify(file, ":t") + -- Remove .lua extension to get the filetype + local ft = filename:match("(.+)%.lua$") + if ft then + -- Load the file which should return a table of snippets + local ok, snippets = pcall(dofile, file) + if ok and type(snippets) == "table" then + ls.add_snippets(ft, snippets) + end + end + end + end + load_snippets() end, }, { diff --git a/nvim/.config/nvim/snippets/.gitkeep b/nvim/.config/nvim/snippets/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/nvim/.config/nvim/snippets/bash.lua b/nvim/.config/nvim/snippets/bash.lua new file mode 100644 index 0000000..318868a --- /dev/null +++ b/nvim/.config/nvim/snippets/bash.lua @@ -0,0 +1,353 @@ +-- Lua snippets +local ls = require("luasnip") +local s = ls.snippet +local t = ls.text_node +local i = ls.insert_node +local f = ls.function_node +local c = ls.choice_node +local d = ls.dynamic_node +local sn = ls.snippet_node +local fmt = require("luasnip.extras.fmt").fmt +local rep = require("luasnip.extras").rep + +-- Return a table of snippets for Bash +-- stylua: ignore start +return { + -- Shebang + s("shebang", { + t("#!/usr/bin/env bash"), + }), + + -- Bash strict mode + s("strict", fmt([[ + set -euo pipefail + IFS=$'\n\t' + ]], {})), + + -- Function definition + s("func", fmt([[ + {}() {{ + {} + }} + ]], { + i(1, "function_name"), + i(2, "# function body"), + })), + + -- If statement + s("if", fmt([[ + if [ {} ]; then + {} + fi + ]], { + i(1, "condition"), + i(2, "# code"), + })), + + -- If-else statement + s("ifelse", fmt([[ + if [ {} ]; then + {} + else + {} + fi + ]], { + i(1, "condition"), + i(2, "# if code"), + i(3, "# else code"), + })), + + -- If-elif-else statement + s("ifelif", fmt([[ + if [ {} ]; then + {} + elif [ {} ]; then + {} + else + {} + fi + ]], { + i(1, "condition1"), + i(2, "# if code"), + i(3, "condition2"), + i(4, "# elif code"), + i(5, "# else code"), + })), + + -- For loop + s("for", fmt([[ + for {} in {}; do + {} + done + ]], { + i(1, "item"), + i(2, "items"), + i(3, "# loop body"), + })), + + -- For loop with range + s("fori", fmt([[ + for ((i={}; i<{}; i++)); do + {} + done + ]], { + i(1, "0"), + i(2, "10"), + i(3, "# loop body"), + })), + + -- While loop + s("while", fmt([[ + while [ {} ]; do + {} + done + ]], { + i(1, "condition"), + i(2, "# loop body"), + })), + + -- Until loop + s("until", fmt([[ + until [ {} ]; do + {} + done + ]], { + i(1, "condition"), + i(2, "# loop body"), + })), + + -- Case statement + s("case", fmt([[ + case {} in + {}) + {} + ;; + {}) + {} + ;; + *) + {} + ;; + esac + ]], { + i(1, "variable"), + i(2, "pattern1"), + i(3, "# code for pattern1"), + i(4, "pattern2"), + i(5, "# code for pattern2"), + i(6, "# default code"), + })), + + -- Read input + s("read", fmt([[ + read -p "{}" {} + ]], { + i(1, "Enter value: "), + i(2, "variable"), + })), + + -- Command substitution + s("cmd", fmt([[ + {}=$({}$) + ]], { + i(1, "result"), + i(2, "command"), + })), + + -- Variable declaration + s("var", fmt([[ + {}="{}" + ]], { + i(1, "variable"), + i(2, "value"), + })), + + -- Array declaration + s("array", fmt([[ + {}=({}) + ]], { + i(1, "array"), + i(2, "item1 item2 item3"), + })), + + -- Check if command exists + s("cmdexists", fmt([[ + if command -v {} &> /dev/null; then + {} + else + {} + fi + ]], { + i(1, "command"), + i(2, "# command exists"), + i(3, "# command does not exist"), + })), + + -- Check if file exists + s("fileexists", fmt([[ + if [ -f {} ]; then + {} + else + {} + fi + ]], { + i(1, "file"), + i(2, "# file exists"), + i(3, "# file does not exist"), + })), + + -- Check if directory exists + s("direxists", fmt([[ + if [ -d {} ]; then + {} + else + {} + fi + ]], { + i(1, "directory"), + i(2, "# directory exists"), + i(3, "# directory does not exist"), + })), + + -- Check if variable is empty + s("isempty", fmt([[ + if [ -z "${{{}}}" ]; then + {} + else + {} + fi + ]], { + i(1, "variable"), + i(2, "# variable is empty"), + i(3, "# variable is not empty"), + })), + + -- Check if variable is not empty + s("isnotempty", fmt([[ + if [ -n "${{{}}}" ]; then + {} + else + {} + fi + ]], { + i(1, "variable"), + i(2, "# variable is not empty"), + i(3, "# variable is empty"), + })), + + -- Error handling + s("error", fmt([[ + error() {{ + echo "[ERROR] $1" >&2 + exit 1 + }} + ]], {})), + + -- Parse command line arguments + s("getopts", fmt([[ + while getopts ":{}:" opt; do + case $opt in + {}) + {} + ;; + {}) + {} + ;; + \?) + echo "Invalid option: -$OPTARG" >&2 + exit 1 + ;; + :) + echo "Option -$OPTARG requires an argument." >&2 + exit 1 + ;; + esac + done + shift $((OPTIND-1)) + ]], { + i(1, "ab:c:"), + i(2, "a"), + i(3, "# handle option a"), + i(4, "b"), + i(5, "# handle option b with value in $OPTARG"), + })), + + -- Trap signals + s("trap", fmt([[ + trap '{}' {} + ]], { + i(1, "echo 'Caught signal, cleaning up...; exit 1'"), + i(2, "SIGINT SIGTERM"), + })), + + -- Cleanup function with trap + s("cleanup", fmt([[ + cleanup() {{ + {} + }} + + trap cleanup EXIT + ]], { + i(1, "# cleanup code here"), + })), + + -- Redirect stdout and stderr to file + s("redirect", fmt([[ + {} > {} 2>&1 + ]], { + i(1, "command"), + i(2, "logfile.log"), + })), + + -- Check exit status + s("checkstatus", fmt([[ + if [ $? -eq 0 ]; then + {} + else + {} + fi + ]], { + i(1, "# success"), + i(2, "# failure"), + })), + + -- Here document + s("heredoc", fmt([[ + cat << EOF > {} + {} + EOF + ]], { + i(1, "output.txt"), + i(2, "content goes here"), + })), + + -- Here string + s("herestring", fmt([[ + {} <<< "{}" + ]], { + i(1, "command"), + i(2, "string"), + })), + + -- Script usage/help + s("usage", fmt([[ + usage() {{ + cat << EOF + Usage: $(basename $0) [options] + + Options: + -h, --help Show this help message and exit + -v, --verbose Enable verbose output + {} + + Examples: + $(basename $0) {} + EOF + exit ${1:-0} + }} + ]], { + i(1, "-o, --option Description of option"), + i(2, "example_argument"), + })), +} +-- stylua: ignore end diff --git a/nvim/.config/nvim/snippets/lua.lua b/nvim/.config/nvim/snippets/lua.lua new file mode 100644 index 0000000..58b2473 --- /dev/null +++ b/nvim/.config/nvim/snippets/lua.lua @@ -0,0 +1,79 @@ +-- Lua snippets +local ls = require("luasnip") +local s = ls.snippet +local t = ls.text_node +local i = ls.insert_node +local f = ls.function_node +local c = ls.choice_node +local d = ls.dynamic_node +local sn = ls.snippet_node +local fmt = require("luasnip.extras.fmt").fmt +local rep = require("luasnip.extras").rep + +-- Return a table of snippets for Lua +-- stylua: ignore start +return { + -- Basic print statement + s("pr", { + t('print("'), + i(1, "text"), + t('")'), + }), + + -- Function definition + s("fn", fmt([[ + local function {}({}) + {} + end + ]], { + i(1, "name"), + i(2, ""), + i(3, "-- TODO: implement"), + })), + + -- Module pattern + s("mod", fmt([[ + local {} = {{}} + + function {}:new(o) + o = o or {{}} + setmetatable(o, self) + self.__index = self + return o + end + + {} + + return {} + ]], { + i(1, "ModuleName"), + rep(1), + i(2, "-- TODO: add methods"), + rep(1), + })), + + -- For loop + s("for", fmt([[ + for {} = {}, {} do + {} + end + ]], { + i(1, "i"), + i(2, "1"), + i(3, "10"), + i(4, "-- TODO: loop body"), + })), + + -- For pairs loop + s("forp", fmt([[ + for {}, {} in pairs({}) do + {} + end + ]], { + i(1, "k"), + i(2, "v"), + i(3, "table"), + i(4, "-- TODO: loop body"), + })), +} +-- stylua: ignore end diff --git a/nvim/.config/nvim/snippets/python.lua b/nvim/.config/nvim/snippets/python.lua new file mode 100644 index 0000000..fb37813 --- /dev/null +++ b/nvim/.config/nvim/snippets/python.lua @@ -0,0 +1,75 @@ +-- Python snippets +local ls = require("luasnip") +local s = ls.snippet +local t = ls.text_node +local i = ls.insert_node +local f = ls.function_node +local c = ls.choice_node +local d = ls.dynamic_node +local sn = ls.snippet_node +local fmt = require("luasnip.extras.fmt").fmt +local rep = require("luasnip.extras").rep + +-- Return a table of snippets for Python +-- stylua: ignore start +return { + -- Print statement + s("pr", { + t("print("), + i(1, "text"), + t(")"), + }), + + -- Function definition + s("def", fmt([[ + def {}({}): + {} + ]], { + i(1, "function_name"), + i(2, ""), + i(3, "pass"), + })), + + -- Class definition + s("class", fmt([[ + class {}: + def __init__(self, {}): + {} + ]], { + i(1, "ClassName"), + i(2, ""), + i(3, "pass"), + })), + + -- For loop + s("for", fmt([[ + for {} in {}: + {} + ]], { + i(1, "item"), + i(2, "iterable"), + i(3, "pass"), + })), + + -- If statement + s("if", fmt([[ + if {}: + {} + ]], { + i(1, "condition"), + i(2, "pass"), + })), + + -- Try/except + s("try", fmt([[ + try: + {} + except {}: + {} + ]], { + i(1, "# code"), + i(2, "Exception"), + i(3, "pass"), + })), +} +-- stylua: ignore end diff --git a/nvim/.config/nvim/snippets/rust.lua b/nvim/.config/nvim/snippets/rust.lua new file mode 100644 index 0000000..1619551 --- /dev/null +++ b/nvim/.config/nvim/snippets/rust.lua @@ -0,0 +1,340 @@ +-- Lua snippets +local ls = require("luasnip") +local s = ls.snippet +local t = ls.text_node +local i = ls.insert_node +local f = ls.function_node +local c = ls.choice_node +local d = ls.dynamic_node +local sn = ls.snippet_node +local fmt = require("luasnip.extras.fmt").fmt +local rep = require("luasnip.extras").rep + +-- Return a table of snippets for Rust +-- stylua: ignore start +return { + -- Basic main function + s("main", fmt([[ + fn main() {{ + {} + }} + ]], { + i(1, "// Your code here"), + })), + + -- Function definition + s("fn", fmt([[ + fn {}({}) {} {{ + {} + }} + ]], { + i(1, "function_name"), + i(2, ""), + c(3, { + t(""), + t("-> ()"), + sn(nil, {t("-> "), i(1, "ReturnType")}), + }), + i(4, "// Function body"), + })), + + -- Public function + s("pfn", fmt([[ + pub fn {}({}) {} {{ + {} + }} + ]], { + i(1, "function_name"), + i(2, ""), + c(3, { + t(""), + t("-> ()"), + sn(nil, {t("-> "), i(1, "ReturnType")}), + }), + i(4, "// Function body"), + })), + + -- Struct definition + s("struct", fmt([[ + struct {} {{ + {} + }} + ]], { + i(1, "StructName"), + i(2, "// fields"), + })), + + -- Public struct + s("pstruct", fmt([[ + pub struct {} {{ + {} + }} + ]], { + i(1, "StructName"), + i(2, "// fields"), + })), + + -- Struct implementation + s("impl", fmt([[ + impl {} {{ + {} + }} + ]], { + i(1, "StructName"), + i(2, "// methods"), + })), + + -- Trait implementation + s("implfor", fmt([[ + impl {} for {} {{ + {} + }} + ]], { + i(1, "Trait"), + i(2, "Type"), + i(3, "// trait implementation"), + })), + + -- Trait definition + s("trait", fmt([[ + trait {} {{ + {} + }} + ]], { + i(1, "TraitName"), + i(2, "// trait methods"), + })), + + -- Public trait + s("ptrait", fmt([[ + pub trait {} {{ + {} + }} + ]], { + i(1, "TraitName"), + i(2, "// trait methods"), + })), + + -- Enum definition + s("enum", fmt([[ + enum {} {{ + {}, + }} + ]], { + i(1, "EnumName"), + i(2, "// variants"), + })), + + -- Public enum + s("penum", fmt([[ + pub enum {} {{ + {}, + }} + ]], { + i(1, "EnumName"), + i(2, "// variants"), + })), + + -- Match expression + s("match", fmt([[ + match {} {{ + {} => {}, + _ => {}, + }} + ]], { + i(1, "expression"), + i(2, "pattern"), + i(3, "result"), + i(4, "default_result"), + })), + + -- If let expression + s("iflet", fmt([[ + if let {} = {} {{ + {} + }} + ]], { + i(1, "pattern"), + i(2, "expression"), + i(3, "// code"), + })), + + -- While let loop + s("whilelet", fmt([[ + while let {} = {} {{ + {} + }} + ]], { + i(1, "pattern"), + i(2, "expression"), + i(3, "// loop body"), + })), + + -- For loop + s("for", fmt([[ + for {} in {} {{ + {} + }} + ]], { + i(1, "item"), + i(2, "iterator"), + i(3, "// loop body"), + })), + + -- Loop + s("loop", fmt([[ + loop {{ + {} + + {} + }} + ]], { + i(1, "// loop body"), + i(2, "break;"), + })), + + -- Closure + s("closure", fmt([[ + |{}| {} {{ + {} + }} + ]], { + i(1, "args"), + c(2, { + t(""), + sn(nil, {t("-> "), i(1, "ReturnType")}), + }), + i(3, "// closure body"), + })), + + -- Derive attribute + s("derive", fmt([[ + #[derive({})] + ]], { + i(1, "Debug, Clone"), + })), + + -- Module + s("mod", fmt([[ + mod {} {{ + {} + }} + ]], { + i(1, "module_name"), + i(2, "// module contents"), + })), + + -- Public module + s("pmod", fmt([[ + pub mod {} {{ + {} + }} + ]], { + i(1, "module_name"), + i(2, "// module contents"), + })), + + -- Use statement + s("use", fmt([[ + use {}; + ]], { + i(1, "path::to::module"), + })), + + -- Test module + s("testmod", fmt([[ + #[cfg(test)] + mod tests {{ + use super::*; + + #[test] + fn {}() {{ + {} + }} + }} + ]], { + i(1, "test_name"), + i(2, "// test code"), + })), + + -- Test function + s("test", fmt([[ + #[test] + fn {}() {{ + {} + }} + ]], { + i(1, "test_name"), + i(2, "// test code"), + })), + + -- Async function + s("async", fmt([[ + async fn {}({}) {} {{ + {} + }} + ]], { + i(1, "function_name"), + i(2, ""), + c(3, { + t(""), + t("-> ()"), + sn(nil, {t("-> "), i(1, "ReturnType")}), + }), + i(4, "// async function body"), + })), + + -- Result type + s("result", fmt([[ + Result<{}, {}> + ]], { + i(1, "T"), + i(2, "Error"), + })), + + -- Option type + s("option", fmt([[ + Option<{}> + ]], { + i(1, "T"), + })), + + -- Unwrap with error message + s("expect", fmt([[ + .expect("{}") + ]], { + i(1, "Failed to unwrap value"), + })), + + -- Print debug + s("dbg", fmt([[ + dbg!({}); + ]], { + i(1, "expression"), + })), + + -- Print + s("print", fmt([[ + println!("{}", {}); + ]], { + i(1, "{}"), + i(2, "expression"), + })), + + -- Let statement + s("let", fmt([[ + let {} = {}; + ]], { + i(1, "variable"), + i(2, "value"), + })), + + -- Let mut statement + s("letmut", fmt([[ + let mut {} = {}; + ]], { + i(1, "variable"), + i(2, "value"), + })), +} +-- stylua: ignore end