diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..eac713a --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ +tt.* +.tests +doc/tags +debug +.repro +foo.* +*.log +data +lazy-lock.json +lazyvim.json + +.luarc.json diff --git a/.neoconf.json b/.neoconf.json new file mode 100644 index 0000000..7c48087 --- /dev/null +++ b/.neoconf.json @@ -0,0 +1,15 @@ +{ + "neodev": { + "library": { + "enabled": true, + "plugins": true + } + }, + "neoconf": { + "plugins": { + "lua_ls": { + "enabled": true + } + } + } +} diff --git a/init.lua b/init.lua new file mode 100644 index 0000000..08cbdbb --- /dev/null +++ b/init.lua @@ -0,0 +1,2 @@ +-- bootstrap lazy.nvim, LazyVim and your plugins +require "config.lazy" diff --git a/lua/config/autocmds.lua b/lua/config/autocmds.lua new file mode 100644 index 0000000..0a0f420 --- /dev/null +++ b/lua/config/autocmds.lua @@ -0,0 +1,40 @@ +-- Autocmds are automatically loaded on the VeryLazy event +-- Default autocmds that are always set: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/config/autocmds.lua +-- Add any additional autocmds here + +local opt = vim.opt + +opt.shiftwidth = 4 +opt.tabstop = 4 + +-- vim.api.nvim_create_autocmd("BufReadPost", { +-- group = vim.api.nvim_create_augroup("LazyVim_AutoUpdate", {}), +-- once = true, +-- callback = function() +-- require("lazy").update { +-- show = false, +-- wait = false, +-- concurrency = 4, +-- } +-- end, +-- }) + +-- Golang templ filetype +vim.filetype.add { + extension = { + templ = "templ", + }, +} + +require("lspconfig").nil_ls.setup { + settings = { + ["nil"] = { + nix = { + flake = { + autoArchive = true, + autoEvalInputs = vim.fn.getenv "NIL_LS_NIX_AUTO_EVAL_INPUTS" ~= vim.NIL, + }, + }, + }, + }, +} diff --git a/lua/config/keymaps.lua b/lua/config/keymaps.lua new file mode 100644 index 0000000..e4b6322 --- /dev/null +++ b/lua/config/keymaps.lua @@ -0,0 +1,11 @@ +-- Keymaps are automatically loaded on the VeryLazy event +-- Default keymaps that are always set: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/config/keymaps.lua +-- Add any additional keymaps here + +require "config.neovide" + +vim.keymap.set("t", "", "", { silent = true, desc = "Exit Terminal Mode" }) + +-- LazyVim hardcode tabs to jump snippet completions. Very fucking annoying. +vim.keymap.del({ "i" }, "") +vim.keymap.del({ "i" }, "") diff --git a/lua/config/lazy.lua b/lua/config/lazy.lua new file mode 100644 index 0000000..7aac0a0 --- /dev/null +++ b/lua/config/lazy.lua @@ -0,0 +1,65 @@ +local lazypath = vim.fn.stdpath "data" .. "/lazy/lazy.nvim" +if not vim.loop.fs_stat(lazypath) then + -- bootstrap lazy.nvim + -- stylua: ignore + vim.fn.system({ "git", "clone", "--filter=blob:none", "https://github.com/folke/lazy.nvim.git", "--branch=stable", lazypath }) +end +vim.opt.rtp:prepend(vim.env.LAZY or lazypath) + +require("lazy").setup { + spec = { + -- add LazyVim and import its plugins + { "LazyVim/LazyVim", import = "lazyvim.plugins" }, + -- import any extras modules here + { import = "lazyvim.plugins.extras.lang.typescript" }, + { import = "lazyvim.plugins.extras.lang.json" }, + { import = "lazyvim.plugins.extras.coding.copilot" }, + { import = "lazyvim.plugins.extras.coding.yanky" }, + { import = "lazyvim.plugins.extras.coding.luasnip" }, + { import = "lazyvim.plugins.extras.formatting.prettier" }, + + { import = "lazyvim.plugins.extras.dap.core" }, + { import = "lazyvim.plugins.extras.dap.nlua" }, + { import = "lazyvim.plugins.extras.test.core" }, + { import = "lazyvim.plugins.extras.lang.docker" }, + { import = "lazyvim.plugins.extras.lang.go" }, + { import = "lazyvim.plugins.extras.lang.json" }, + -- { import = "lazyvim.plugins.extras.lang.markdown" }, + { import = "lazyvim.plugins.extras.lang.tailwind" }, + { import = "lazyvim.plugins.extras.lang.typescript" }, + { import = "lazyvim.plugins.extras.lang.yaml" }, + { import = "lazyvim.plugins.extras.lsp.none-ls" }, + { import = "lazyvim.plugins.extras.lang.java" }, + { import = "lazyvim.plugins.extras.util.project" }, + { import = "lazyvim.plugins.extras.editor.mini-files" }, + -- { import = "lazyvim.plugins.extras.ui.edgy" }, + -- import/override with your plugins + { import = "plugins" }, + }, + defaults = { + -- By default, only LazyVim plugins will be lazy-loaded. Your custom plugins will load during startup. + -- If you know what you're doing, you can set this to `true` to have all your custom plugins lazy-loaded by default. + lazy = false, + -- It's recommended to leave version=false for now, since a lot the plugin that support versioning, + -- have outdated releases, which may break your Neovim install. + version = false, -- always use the latest git commit + -- version = "*", -- try installing the latest stable version for plugins that support semver + }, + install = { colorscheme = { "tokyonight", "habamax" } }, + checker = { enabled = false }, -- automatically check for plugin updates + performance = { + rtp = { + -- disable some rtp plugins + disabled_plugins = { + "gzip", + -- "matchit", + -- "matchparen", + -- "netrwPlugin", + "tarPlugin", + "tohtml", + "tutor", + "zipPlugin", + }, + }, + }, +} diff --git a/lua/config/neovide.lua b/lua/config/neovide.lua new file mode 100644 index 0000000..e08f30f --- /dev/null +++ b/lua/config/neovide.lua @@ -0,0 +1,21 @@ +if not vim.g.neovide then + return +end + +local font = "JetBrainsMono Nerd Font Mono" + +local font_size = vim.o.lines < 60 and 11 or 12 + +vim.o.guifont = font .. ":h" .. font_size + +vim.keymap.set("n", "", function() + font_size = font_size - 1 + vim.o.guifont = font .. ":h" .. font_size + vim.notify("Font Set: " .. font .. ":h" .. font_size) +end, { desc = "Decrease font size" }) + +vim.keymap.set("n", "", function() + font_size = font_size + 1 + vim.o.guifont = font .. ":h" .. font_size + vim.notify("Font Set: " .. font .. ":h" .. font_size) +end, { desc = "Increase font size" }) diff --git a/lua/config/options.lua b/lua/config/options.lua new file mode 100644 index 0000000..a0c827f --- /dev/null +++ b/lua/config/options.lua @@ -0,0 +1,10 @@ +-- Options are automatically loaded before lazy.nvim startup +-- Default options that are always set: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/config/options.lua +-- Add any additional options here + +-- Disable swap files +vim.opt.swapfile = false + +vim.defer_fn(function() + vim.opt.title = true +end, 100) diff --git a/lua/plugins/arrow.lua b/lua/plugins/arrow.lua new file mode 100644 index 0000000..2d19830 --- /dev/null +++ b/lua/plugins/arrow.lua @@ -0,0 +1,10 @@ +return { + "otavioschwanck/arrow.nvim", + opts = { + show_icons = true, + leader_key = [[\]], -- Recommended to be a single key + }, + keys = { + { "", desc = "Open Arrow bookmarks" }, + }, +} diff --git a/lua/plugins/base16.lua b/lua/plugins/base16.lua new file mode 100644 index 0000000..566db61 --- /dev/null +++ b/lua/plugins/base16.lua @@ -0,0 +1,70 @@ +return { + { + "rktjmp/fwatch.nvim", + dependencies = { + "xiyaowong/transparent.nvim", -- For Transparency support + { "echasnovski/mini.nvim", version = false }, + }, + lazy = false, + config = function() + local fwatch = require "fwatch" + + local color_file = vim.fn.getenv "HOME" .. "/.cache/wallust/base16-nvim.lua" + local error_fn = function(err) + vim.notify("Watch Error: " .. err, vim.log.levels.ERROR, { title = "fwatch.nvim" }) + end + local command = {} + local source_fn = function(_, _, unwatch) + vim.schedule(function() + if vim.fn.filereadable(color_file) == 1 then + vim.cmd(("source %s"):format(color_file)) + if not vim.g.neovide then + require("transparent").setup { + groups = { + "Normal", + "NormalNC", + "Comment", + "Constant", + "Special", + "Identifier", + "Statement", + "PreProc", + "Type", + "Underlined", + "Todo", + "String", + "Function", + "Conditional", + "Repeat", + "Operator", + "Structure", + "LineNr", + "NonText", + "SignColumn", + -- "CursorLine", + -- "CursorLineNr", + "StatusLine", + "StatusLineNC", + "EndOfBuffer", + }, + } + end + if unwatch then + unwatch() + end + fwatch.watch(color_file, command) + end + end) + end + command.on_event = source_fn + command.on_error = error_fn + source_fn() + fwatch.watch(color_file, command) + end, + }, + { + "brenoprata10/nvim-highlight-colors", + opts = {}, + event = "VeryLazy", + }, +} diff --git a/lua/plugins/before.lua b/lua/plugins/before.lua new file mode 100644 index 0000000..206524b --- /dev/null +++ b/lua/plugins/before.lua @@ -0,0 +1,9 @@ +return { + "bloznelis/before.nvim", + opts = {}, + event = { "InsertEnter" }, + keys = { + { "", "lua require'before'.jump_to_last_edit()", desc = "Jump to last edit" }, + { "", "lua require'before'.jump_to_next_edit()", desc = "Jump to next edit" }, + }, +} diff --git a/lua/plugins/caddyfile.lua b/lua/plugins/caddyfile.lua new file mode 100644 index 0000000..0f71ab9 --- /dev/null +++ b/lua/plugins/caddyfile.lua @@ -0,0 +1,4 @@ +return { + "isobit/vim-caddyfile", + event = { "BufReadPre", "BufNewFile" }, +} diff --git a/lua/plugins/catppuccin.lua b/lua/plugins/catppuccin.lua new file mode 100644 index 0000000..f489ccb --- /dev/null +++ b/lua/plugins/catppuccin.lua @@ -0,0 +1,18 @@ +return { + { + "catppuccin/nvim", + name = "catppuccin", + opts = { + styles = { + functions = { "italic" }, + keywords = { "italic" }, + }, + }, + }, + -- { + -- "LazyVim/LazyVim", + -- opts = { + -- colorscheme = "catppuccin", + -- }, + -- }, +} diff --git a/lua/plugins/cmp.lua b/lua/plugins/cmp.lua new file mode 100644 index 0000000..49ae531 --- /dev/null +++ b/lua/plugins/cmp.lua @@ -0,0 +1,62 @@ +return { + "hrsh7th/nvim-cmp", + dependencies = { + "hrsh7th/cmp-cmdline", + "hrsh7th/cmp-nvim-lsp-document-symbol", + -- "hrsh7th/cmp-nvim-lsp-signature-help", + { "lukas-reineke/cmp-rg", enabled = vim.fn.exepath "rg" ~= "" }, + }, + event = { "InsertEnter", "CmdlineEnter" }, + opts = function(_, opts) + local cmp = require "cmp" + + if vim.fn.exepath "rg" ~= "" then + table.insert(opts.sources, 3, { name = "rg" }) + end + + opts.preselect = cmp.PreselectMode.None + + opts.mapping = cmp.mapping.preset.insert { + [""] = function(fallback) + cmp.abort() + fallback() + end, + [""] = cmp.mapping.confirm { select = true }, + [""] = cmp.mapping.select_next_item { behavior = cmp.SelectBehavior.Insert }, + [""] = cmp.mapping.select_prev_item { behavior = cmp.SelectBehavior.Insert }, + [""] = cmp.mapping.scroll_docs(-4), + [""] = cmp.mapping.scroll_docs(4), + [""] = cmp.mapping.complete(), + [""] = cmp.mapping.abort(), + [""] = cmp.mapping.confirm { + behavior = cmp.ConfirmBehavior.Replace, + select = true, + }, -- Accept currently selected item. Set `select` to `false` to only confirm explicitly selected items. + } + + ---@diagnostic disable-next-line: missing-fields + cmp.setup.cmdline(":", { + mapping = cmp.mapping.preset.cmdline(), + sources = cmp.config.sources { + { name = "path" }, + { + name = "cmdline", + option = { + ignore_cmds = { "Man", "!" }, + }, + }, + }, + }) + + ---@diagnostic disable-next-line: missing-fields + cmp.setup.cmdline("/", { + mapping = cmp.mapping.preset.cmdline(), + sources = cmp.config.sources { + { name = "nvim_lsp_document_symbol" }, + { name = "buffer" }, + }, + }) + + return opts + end, +} diff --git a/lua/plugins/conform.lua b/lua/plugins/conform.lua new file mode 100644 index 0000000..5858a1b --- /dev/null +++ b/lua/plugins/conform.lua @@ -0,0 +1,9 @@ +return { + "conform.nvim", + opts = { + formatters_by_ft = { + nix = { "nixpkgs_fmt" }, + templ = { "templ" }, + }, + }, +} diff --git a/lua/plugins/copilot.lua b/lua/plugins/copilot.lua new file mode 100644 index 0000000..8234922 --- /dev/null +++ b/lua/plugins/copilot.lua @@ -0,0 +1,28 @@ +return { + { + "zbirenbaum/copilot.lua", + event = { "InsertEnter" }, + opts = { + panel = { enabled = false }, + suggestion = { + enabled = true, + auto_trigger = true, + keymap = { + accept = "", + accept_word = false, + accept_line = false, + next = "", + prev = "", + dismiss = "", + }, + }, + filetypes = { + ["*"] = true, + }, + }, + }, + { + "zbirenbaum/copilot-cmp", + enabled = false, + }, +} diff --git a/lua/plugins/corn.lua b/lua/plugins/corn.lua new file mode 100644 index 0000000..9f46ae3 --- /dev/null +++ b/lua/plugins/corn.lua @@ -0,0 +1,21 @@ +return { + "RaafatTurki/corn.nvim", + event = { "LspAttach" }, + opts = { + border_style = "rounded", + icons = { + error = " ", + warn = " ", + hint = " ", + info = " ", + }, + item_preprocess_func = function(item) + return item + end, + }, + config = function(_, opts) + vim.diagnostic.config { virtual_text = false } + require("corn").setup(opts) + end, + enabled = false, +} diff --git a/lua/plugins/diagflow.lua b/lua/plugins/diagflow.lua new file mode 100644 index 0000000..d751e5a --- /dev/null +++ b/lua/plugins/diagflow.lua @@ -0,0 +1,18 @@ +return { + "dgagn/diagflow.nvim", + event = { "LspAttach" }, + opts = { + scope = "line", + show_sign = false, + show_borders = true, + text_align = "right", + max_width = 60, + format = function(diagnostic) + if diagnostic.source and #diagnostic.source > 0 then + return string.format("[%s] %s: %s", diagnostic.source, diagnostic.code, diagnostic.message) + end + return diagnostic.message + end, + }, + -- enabled = false, +} diff --git a/lua/plugins/discord-presence.lua b/lua/plugins/discord-presence.lua new file mode 100644 index 0000000..d9c766e --- /dev/null +++ b/lua/plugins/discord-presence.lua @@ -0,0 +1,5 @@ +return { + "andweeb/presence.nvim", + event = "BufReadPost", + config = true, +} diff --git a/lua/plugins/gitsigns.lua b/lua/plugins/gitsigns.lua new file mode 100644 index 0000000..655de4f --- /dev/null +++ b/lua/plugins/gitsigns.lua @@ -0,0 +1,6 @@ +return { + "lewis6991/gitsigns.nvim", + opts = { + current_line_blame = true, + }, +} diff --git a/lua/plugins/incline.lua b/lua/plugins/incline.lua new file mode 100644 index 0000000..ba19cd7 --- /dev/null +++ b/lua/plugins/incline.lua @@ -0,0 +1,28 @@ +return { + -- Show filenames in the right top most of buffer + "b0o/incline.nvim", + config = function() + local helpers = require "incline.helpers" + local devicons = require "nvim-web-devicons" + require("incline").setup { + window = { + padding = 0, + margin = { horizontal = 0 }, + }, + render = function(props) + local filename = vim.fn.fnamemodify(vim.api.nvim_buf_get_name(props.buf), ":t") + local ft_icon, ft_color = devicons.get_icon_color(filename) + local modified = vim.bo[props.buf].modified + return { + ft_icon and { " ", ft_icon, " ", guibg = ft_color, guifg = helpers.contrast_color(ft_color) } or "", + " ", + { filename, gui = modified and "bold,italic" or "bold" }, + " ", + guibg = "#44406e", + } + end, + } + end, + -- Optional: Lazy load Incline + event = "VeryLazy", +} diff --git a/lua/plugins/java.lua b/lua/plugins/java.lua new file mode 100644 index 0000000..a1510a0 --- /dev/null +++ b/lua/plugins/java.lua @@ -0,0 +1,40 @@ +return { + { + "conform.nvim", + opts = function(_, opts) + opts.formatters_by_ft = opts.formatters_by_ft or {} + opts.formatters_by_ft.xml = { "xmlformat" } + + require("conform").formatters.xmlformat = { + prepend_args = { "--indent", "1", "--indent-char", "\t" }, + } + end, + }, + { + "williamboman/mason.nvim", + opts = function(_, opts) + opts.ensure_installed = opts.ensure_installed or {} + vim.list_extend(opts.ensure_installed, { "xmlformatter" }) + end, + }, + { + -- Add lombok support + "mfussenegger/nvim-jdtls", + opts = function(_, opts) + local lombok_jar_path = (vim.fn.expand "$MASON") .. "/packages/jdtls/lombok.jar" + opts.cmd = { + vim.fn.exepath "jdtls", + ([[--jvm-arg=-javaagent:%s]]):format(lombok_jar_path), + } + end, + }, + { "rcasia/neotest-java", lazy = true }, + { + "nvim-neotest/neotest", + opts = function(_, opts) + opts = opts or {} + opts.adapters = opts.adapters or {} + vim.list_extend(opts.adapters, { "neotest-java" }) + end, + }, +} diff --git a/lua/plugins/lang-go.lua b/lua/plugins/lang-go.lua new file mode 100644 index 0000000..5e31068 --- /dev/null +++ b/lua/plugins/lang-go.lua @@ -0,0 +1,108 @@ +return { + { + "neovim/nvim-lspconfig", + opts = { + servers = { + gopls = { + settings = { + gopls = { + analyses = { + fieldalignment = false, + }, + usePlaceholders = false, + hints = { + assignVariableTypes = false, + compositeLiteralFields = false, + compositeLiteralTypes = false, + constantValues = false, + functionTypeParameters = false, + parameterNames = false, + rangeVariableTypes = false, + }, + }, + }, + }, + }, + setup = { + gopls = function(_, opts) + require("lazyvim.util").lsp.on_attach(function(client, bufnr) + if client.name == "gopls" then + -- workaround for gopls not supporting semanticTokensProvider + -- https://github.com/golang/go/issues/54531#issuecomment-1464982242 + if not client.server_capabilities.semanticTokensProvider then + local semantic = client.config.capabilities.textDocument.semanticTokens + client.server_capabilities.semanticTokensProvider = { + full = true, + legend = { + tokenTypes = semantic.tokenTypes, + tokenModifiers = semantic.tokenModifiers, + }, + range = true, + } + end + -- end workaround + + -- run lsp imports code action on save. + vim.api.nvim_create_autocmd("BufWritePre", { + desc = "Auto format and organize imports on save (gopls)", + group = vim.api.nvim_create_augroup("GoplsAutoFormat", {}), + buffer = bufnr, + callback = function(event) + local context = { source = { organizeImports = true } } + local params = vim.lsp.util.make_range_params() + params.context = context + local result = + vim.lsp.buf_request_sync(event.buf, "textDocument/codeAction", params, 3000) + if not result then + return + end + if not result[1] then + return + end + result = result[1].result + if not result then + return + end + if not result[1] then + return + end + local edit = result[1].edit + if not edit then + return + end + vim.lsp.util.apply_workspace_edit(edit, "utf-8") + end, + }) + end + end) + end, + }, + }, + }, + { + "olexsmir/gopher.nvim", + ft = "go", + }, + { + "edolphin-ydf/goimpl.nvim", + ft = "go", + config = function() + require("telescope").load_extension "goimpl" + vim.api.nvim_create_autocmd("LspAttach", { + group = vim.api.nvim_create_augroup("GoImpl", {}), + callback = function(ctx) + local client = vim.lsp.get_client_by_id(ctx.data.client_id) or {} + if client.name == "gopls" then + vim.api.nvim_create_user_command("Impl", [[Telescope goimpl]], {}) + vim.keymap.set( + "n", + "ci", + [[Telescope goimpl]], + { buffer = ctx.buf, desc = "Generate implementation stub" } + ) + end + end, + }) + end, + }, +} diff --git a/lua/plugins/lazygit.lua b/lua/plugins/lazygit.lua new file mode 100644 index 0000000..6c93d2c --- /dev/null +++ b/lua/plugins/lazygit.lua @@ -0,0 +1,11 @@ +return { + "kdheepak/lazygit.nvim", + -- optional for floating window border decoration + dependencies = { + "nvim-lua/plenary.nvim", + }, + enabled = vim.fn.exepath("lazygit") ~= "", + keys = { + { "z", "LazyGit", desc = "Symbols Outline" }, + }, +} diff --git a/lua/plugins/lsp-html.lua b/lua/plugins/lsp-html.lua new file mode 100644 index 0000000..77a5f36 --- /dev/null +++ b/lua/plugins/lsp-html.lua @@ -0,0 +1,9 @@ +return { + { + "williamboman/mason.nvim", + opts = function(_, opts) + opts.ensure_installed = opts.ensure_installed or {} + vim.list_extend(opts.ensure_installed, { "html-lsp" }) + end, + }, +} diff --git a/lua/plugins/lsp-lazy.lua b/lua/plugins/lsp-lazy.lua new file mode 100644 index 0000000..9c85bb6 --- /dev/null +++ b/lua/plugins/lsp-lazy.lua @@ -0,0 +1,8 @@ +return { + "dundalek/lazy-lsp.nvim", + dependencies = { "neovim/nvim-lspconfig" }, + opts = { + excluded_servers = { "jdtls", "gopls", "tsserver" }, + }, + enabled = false, +} diff --git a/lua/plugins/lspconfig.lua b/lua/plugins/lspconfig.lua new file mode 100644 index 0000000..f02af8c --- /dev/null +++ b/lua/plugins/lspconfig.lua @@ -0,0 +1,61 @@ +return { + "nvim-lspconfig", + init = function() + local keys = require("lazyvim.plugins.lsp.keymaps").get() + keys[#keys + 1] = { + "gD", + "lua require('telescope.builtin').lsp_definitions({ jump_type = 'vsplit' })", + desc = "Jump to definitions in vsplit", + } + keys[#keys + 1] = { + "grr", + "Trouble lsp_references focus=true", + desc = "Jump to references", + } + keys[#keys + 1] = { + "gri", + "Trouble lsp_implementations focus=true", + desc = "Jump to references", + } + keys[#keys + 1] = { + "grt", + "Trouble lsp_type_definitions focus=true", + desc = "Jump to references", + } + keys[#keys + 1] = { + "grs", + "Trouble lsp_document_symbols focus=true", + desc = "Jump to references", + } + keys[#keys + 1] = { + "", + vim.lsp.buf.rename, + desc = "Rename Symbol", + } + keys[#keys + 1] = { + "", + false, + mode = { "i" }, + } + keys[#keys + 1] = { + "gr", + false, + } + end, + opts = { + servers = { + templ = { + on_attach = function(client, _) + client.server_capabilities.documentFormattingProvider = false + client.server_capabilities.documentRangeFormattingProvider = false + end, + }, + html = { + on_attach = function(client, _) + client.server_capabilities.documentFormattingProvider = false + client.server_capabilities.documentRangeFormattingProvider = false + end, + }, + }, + }, +} diff --git a/lua/plugins/luasnip.lua b/lua/plugins/luasnip.lua new file mode 100644 index 0000000..b0c3d42 --- /dev/null +++ b/lua/plugins/luasnip.lua @@ -0,0 +1,7 @@ +return { + "L3MON4D3/LuaSnip", + opts = function(_, opts) + require "snippets" + return opts + end, +} diff --git a/lua/plugins/makefile.lua b/lua/plugins/makefile.lua new file mode 100644 index 0000000..4cdcd35 --- /dev/null +++ b/lua/plugins/makefile.lua @@ -0,0 +1,14 @@ +return { + "sopa0/telescope-makefile", + dependencies = { + "akinsho/toggleterm.nvim", + }, + cmd = { "Make" }, + keys = { + { "m", "Telescope make", { desc = "Launch Make Items" } }, + }, + config = function() + require("telescope").load_extension "make" + vim.api.nvim_create_user_command("Make", [[Telescope make]], {}) + end, +} diff --git a/lua/plugins/markdown.lua b/lua/plugins/markdown.lua new file mode 100644 index 0000000..b7416e1 --- /dev/null +++ b/lua/plugins/markdown.lua @@ -0,0 +1,8 @@ +return { + "MeanderingProgrammer/markdown.nvim", + name = "render-markdown", -- Only needed if you have another plugin named markdown.nvim + dependencies = { "nvim-treesitter/nvim-treesitter" }, + config = function() + require("render-markdown").setup {} + end, +} diff --git a/lua/plugins/mason.lua b/lua/plugins/mason.lua new file mode 100644 index 0000000..5f53c0d --- /dev/null +++ b/lua/plugins/mason.lua @@ -0,0 +1,7 @@ +return { + "mason.nvim", + opts = { + -- NixOS packages should override Mason packages if exist + PATH = vim.loop.os_uname().version:find("NixOS") and "append" or "prepend", + }, +} diff --git a/lua/plugins/mini_files.lua b/lua/plugins/mini_files.lua new file mode 100644 index 0000000..d1c2d07 --- /dev/null +++ b/lua/plugins/mini_files.lua @@ -0,0 +1,55 @@ +return { + "echasnovski/mini.nvim", + version = false, + opts = { + windows = { + preview = true, + width_preview = 50, + }, + }, + config = function(_, opts) + require("mini.files").setup(opts) + local map_split = function(buf_id, lhs, direction) + local mf = require "mini.files" + local rhs = function() + -- Make new window and set it as target + local new_target_window + vim.api.nvim_win_call(mf.get_target_window(), function() + vim.cmd(direction .. " split") + new_target_window = vim.api.nvim_get_current_win() + end) + + mf.set_target_window(new_target_window) + end + + -- Adding `desc` will result into `show_help` entries + local desc = "Split " .. direction + vim.keymap.set("n", lhs, rhs, { buffer = buf_id, desc = desc }) + end + vim.api.nvim_create_autocmd("User", { + pattern = "MiniFilesBufferCreate", + callback = function(args) + local mf = require "mini.files" + local buf_id = args.data.buf_id + -- Tweak keys to your liking + map_split(buf_id, "gs", "belowright horizontal") + map_split(buf_id, "gv", "belowright vertical") + vim.keymap.set("n", "", function() + mf.go_in { close_on_file = true } + end, { buffer = buf_id, desc = "Open file or directory" }) + end, + }) + end, + keys = { + { + "-", + function() + local mf = require "mini.files" + if not mf.close() then + mf.open(vim.api.nvim_buf_get_name(0), false) + end + end, + desc = "Open/Close mini files from current file directory", + }, + }, +} diff --git a/lua/plugins/neotree.lua b/lua/plugins/neotree.lua new file mode 100644 index 0000000..1de96e1 --- /dev/null +++ b/lua/plugins/neotree.lua @@ -0,0 +1,12 @@ +return { + "nvim-neo-tree/neo-tree.nvim", + opts = { + filesystem = { + filtered_items = { + visible = true, + }, + group_empty_dirs = true, + }, + }, + enabled = true, +} diff --git a/lua/plugins/nix.lua b/lua/plugins/nix.lua new file mode 100644 index 0000000..a3f54b5 --- /dev/null +++ b/lua/plugins/nix.lua @@ -0,0 +1,9 @@ +return { + { + "williamboman/mason.nvim", + opts = function(_, opts) + opts.ensure_installed = opts.ensure_installed or {} + vim.list_extend(opts.ensure_installed, { "nixpkgs-fmt", "nil" }) + end, + }, +} diff --git a/lua/plugins/notifier.lua b/lua/plugins/notifier.lua new file mode 100644 index 0000000..8bcb51b --- /dev/null +++ b/lua/plugins/notifier.lua @@ -0,0 +1,9 @@ +return { + { "rcarriga/nvim-notify", enabled = false }, + { + "folke/noice.nvim", + dependencies = { + "vigoux/notifier.nvim", + }, + }, +} diff --git a/lua/plugins/obsidian.lua b/lua/plugins/obsidian.lua new file mode 100644 index 0000000..bccdd58 --- /dev/null +++ b/lua/plugins/obsidian.lua @@ -0,0 +1,53 @@ +local function workspace(name) + return { + name = name, + path = ("%s/Obsidian/%s"):format(vim.env.HOME, name), + } +end + +local function event(name) + return ("%s %s/Obsidian/**.md"):format(name, vim.env.HOME) +end + +return { + "epwalsh/obsidian.nvim", + cmd = { + "ObsidianOpen", + "ObsidianNew", + "ObsidianToday", + "ObsidianYesterday", + "ObsidianWorkspace", + "ObsidianSearch", + "ObsidianQuickSwitch", + }, + dependencies = { + -- Required. + "nvim-lua/plenary.nvim", + + -- see below for full list of optional dependencies 👇 + }, + event = { + event "BufReadPre", + event "BufNewFile", + }, + opts = { + workspaces = { + workspace "personal", + workspace "work", + workspace "stories", + workspace "tigor", + }, + mappings = {}, + }, + config = function(_, opts) + require("obsidian").setup(opts) + + vim.keymap.set("n", "gf", function() + if require("obsidian").util.cursor_on_markdown_link() then + return "ObsidianFollowLink" + else + return "gf" + end + end, { noremap = false, expr = true, desc = "Obsidian Follow Link or Fallback" }) + end, +} diff --git a/lua/plugins/oil.lua b/lua/plugins/oil.lua new file mode 100644 index 0000000..e0a449b --- /dev/null +++ b/lua/plugins/oil.lua @@ -0,0 +1,15 @@ +return { + "stevearc/oil.nvim", + opts = { + keymaps = { + ["q"] = "actions.close", + [""] = "actions.parent", + }, + }, + dependencies = { "nvim-tree/nvim-web-devicons" }, + cmd = { "Oil" }, + keys = { + { "-", "Oil", desc = "Open Oil" }, + }, + enabled = false, +} diff --git a/lua/plugins/precognition.lua b/lua/plugins/precognition.lua new file mode 100644 index 0000000..09633c6 --- /dev/null +++ b/lua/plugins/precognition.lua @@ -0,0 +1,27 @@ +return { + "tris203/precognition.nvim", + event = "VeryLazy", + opts = { + -- startVisible = true, + -- showBlankVirtLine = true, + -- highlightColor = { link = "Comment" }, + -- hints = { + -- Caret = { text = "^", prio = 2 }, + -- Dollar = { text = "$", prio = 1 }, + -- MatchingPair = { text = "%", prio = 5 }, + -- Zero = { text = "0", prio = 1 }, + -- w = { text = "w", prio = 10 }, + -- b = { text = "b", prio = 9 }, + -- e = { text = "e", prio = 8 }, + -- W = { text = "W", prio = 7 }, + -- B = { text = "B", prio = 6 }, + -- E = { text = "E", prio = 5 }, + -- }, + -- gutterHints = { + -- G = { text = "G", prio = 10 }, + -- gg = { text = "gg", prio = 9 }, + -- PrevParagraph = { text = "{", prio = 8 }, + -- NextParagraph = { text = "}", prio = 8 }, + -- }, + }, +} diff --git a/lua/plugins/protobuf.lua b/lua/plugins/protobuf.lua new file mode 100644 index 0000000..9e48c9a --- /dev/null +++ b/lua/plugins/protobuf.lua @@ -0,0 +1,19 @@ +return { + { + "williamboman/mason.nvim", + opts = function(_, opts) + opts.ensure_installed = opts.ensure_installed or {} + vim.list_extend(opts.ensure_installed, { "buf", "buf-language-server" }) + end, + }, + { + "nvimtools/none-ls.nvim", + opts = function(_, opts) + local nls = require("null-ls") + opts.sources = vim.list_extend(opts.sources or {}, { + nls.builtins.diagnostics.buf, + nls.builtins.formatting.buf, + }) + end, + }, +} diff --git a/lua/plugins/rest.lua b/lua/plugins/rest.lua new file mode 100644 index 0000000..4a13bb1 --- /dev/null +++ b/lua/plugins/rest.lua @@ -0,0 +1,17 @@ +return { + { + "nicwest/vim-http", + ft = "http", + init = function() + vim.g.vim_http_tempbuffer = 1 + vim.g.vim_http_clean_before_do = 0 + end, + }, + { + "nvim-treesitter/nvim-treesitter", + opts = function(_, opts) + opts.ensure_installed = opts.ensure_installed or {} + vim.list_extend(opts.ensure_installed, { "http", "json" }) + end, + }, +} diff --git a/lua/plugins/rose-pine.lua b/lua/plugins/rose-pine.lua new file mode 100644 index 0000000..2db3418 --- /dev/null +++ b/lua/plugins/rose-pine.lua @@ -0,0 +1,9 @@ +return { + { "rose-pine/neovim", name = "rose-pine" }, + -- { + -- "LazyVim/LazyVim", + -- opts = { + -- colorscheme = "rose-pine", + -- }, + -- }, +} diff --git a/lua/plugins/silicon.lua b/lua/plugins/silicon.lua new file mode 100644 index 0000000..0d65b6b --- /dev/null +++ b/lua/plugins/silicon.lua @@ -0,0 +1,56 @@ +return { + "tigorlazuardi/silicon.lua", + cmd = { "Silicon" }, + config = function() + require("silicon").setup { + output = function() + return ([[%s/Pictures/SILICON_%s.png]]):format(vim.env.HOME, os.date "%Y-%m-%d_%H-%M-%S") + end, + padHoriz = 40, + padVert = 50, + } + vim.api.nvim_create_user_command("Silicon", function(ctx) + local args = (ctx.fargs or {})[1] + local opts = {} + if args == "buffer" then + opts.show_buf = true + end + if args == "visible" then + opts.visible = true + end + if not ctx.bang then + opts.to_clip = true + end + require("silicon").visualise_cmdline(opts) + end, { + range = 2, + desc = "Create screenshot from given range. Add Bang (!) at the end of the command to save to file instead of clipboard", + bang = true, + nargs = "?", + complete = function(arg) + if not arg then + return { "buffer", "visible" } + end + if arg:gsub(" ", "") == "" then + return { "buffer", "visible" } + end + if string.find("buffer", arg) then + return { "buffer" } + end + if string.find("visible", arg) then + return { "visible" } + end + return {} + end, + }) + vim.api.nvim_create_autocmd({ "ColorScheme" }, { + group = vim.api.nvim_create_augroup("SiliconRefresh", {}), + callback = function() + local silicon_utils = require "silicon.utils" + silicon_utils.build_tmTheme() + silicon_utils.reload_silicon_cache { async = true } + end, + desc = "Reload silicon themes cache on colorscheme switch", + }) + end, +} diff --git a/lua/plugins/ssh.lua b/lua/plugins/ssh.lua new file mode 100644 index 0000000..b297d82 --- /dev/null +++ b/lua/plugins/ssh.lua @@ -0,0 +1,13 @@ +return { + "ojroques/nvim-osc52", + cond = vim.env.SSH_CLIENT ~= nil, + config = function() + require("osc52").setup({}) + vim.api.nvim_create_autocmd("TextYankPost", { + callback = function() + require("osc52").copy(table.concat(vim.v.event.regcontents, "\n")) + end, + desc = "Copy to Clipboard from SSH Session", + }) + end, +} diff --git a/lua/plugins/tailwind.lua b/lua/plugins/tailwind.lua new file mode 100644 index 0000000..80099ef --- /dev/null +++ b/lua/plugins/tailwind.lua @@ -0,0 +1,15 @@ +return { + "neovim/nvim-lspconfig", + opts = { + servers = { + tailwindcss = { + -- exclude a filetype from the default_config + filetypes_exclude = { "markdown", "javascript", "typescript" }, + -- add additional filetypes to the default_config + filetypes_include = {}, + -- to fully override the default_config, change the below + -- filetypes = {} + }, + }, + }, +} diff --git a/lua/plugins/telescope-fzf-native.lua b/lua/plugins/telescope-fzf-native.lua new file mode 100644 index 0000000..16689b4 --- /dev/null +++ b/lua/plugins/telescope-fzf-native.lua @@ -0,0 +1,10 @@ +return { + "telescope.nvim", + dependencies = { + "nvim-telescope/telescope-fzf-native.nvim", + build = "make", + config = function() + require("telescope").load_extension("fzf") + end, + }, +} diff --git a/lua/plugins/toggleterm.lua b/lua/plugins/toggleterm.lua new file mode 100644 index 0000000..a3263a1 --- /dev/null +++ b/lua/plugins/toggleterm.lua @@ -0,0 +1,21 @@ +return { + "akinsho/toggleterm.nvim", + keys = { + { "", "Open Toggleterm" }, + }, + cmd = { "ToggleTerm" }, + version = "*", + opts = { + size = function(term) + if term.direction == "horizontal" then + if vim.o.lines < 60 then + return 12 + end + return 20 + elseif term.direction == "vertical" then + return vim.o.columns * 0.3 + end + end, + open_mapping = [[]], + }, +} diff --git a/lua/plugins/treesitter.lua b/lua/plugins/treesitter.lua new file mode 100644 index 0000000..145c07d --- /dev/null +++ b/lua/plugins/treesitter.lua @@ -0,0 +1,38 @@ +return { + { + "nvim-treesitter/nvim-treesitter", + dependencies = { + "RRethy/nvim-treesitter-endwise", + }, + opts = { + endwise = { + enable = true, + }, + }, + }, + { + "windwp/nvim-ts-autotag", + opts = { + filetypes = { + "astro", + "glimmer", + "handlebars", + "hbs", + "html", + "javascript", + "javascriptreact", + "jsx", + "markdown", + "php", + "rescript", + "svelte", + "templ", + "tsx", + "typescript", + "typescriptreact", + "vue", + "xml", + }, + }, + }, +} diff --git a/lua/plugins/vim-test.lua b/lua/plugins/vim-test.lua new file mode 100644 index 0000000..af2352f --- /dev/null +++ b/lua/plugins/vim-test.lua @@ -0,0 +1,10 @@ +return { + "vim-test/vim-test", + keys = { + { "Tr", "TestNearest", desc = "Test Run Nearest" }, + { "Tt", "TestFile", desc = "Test File" }, + { "TT", "TestSuite", desc = "Test All Files" }, + { "Tl", "TestLast", desc = "Test Last" }, + { "Tg", "TestVisit", desc = "Test Visit" }, + }, +} diff --git a/lua/plugins/yanky.lua b/lua/plugins/yanky.lua new file mode 100644 index 0000000..e6e450a --- /dev/null +++ b/lua/plugins/yanky.lua @@ -0,0 +1,10 @@ +return { + "gbprod/yanky.nvim", + dependencies = { + { "kkharji/sqlite.lua" }, + }, + opts = { + ring = { storage = "sqlite" }, + highlight = { timer = 150 }, + }, +} diff --git a/lua/snippets/go/apm_span.lua b/lua/snippets/go/apm_span.lua new file mode 100644 index 0000000..8475af9 --- /dev/null +++ b/lua/snippets/go/apm_span.lua @@ -0,0 +1,170 @@ +local ls = require "luasnip" +local sn = ls.sn +local s = ls.s +local i = ls.insert_node +local t = ls.text_node +local d = ls.dynamic_node +local f = ls.function_node +local fmta = require("luasnip.extras.fmt").fmta +local c = ls.choice_node + +local get_node_text = vim.treesitter.get_node_text + +local create_package_query = function() + return vim.treesitter.query.parse( + "go", + [[ + ((package_identifier) @package) + ]] + ) +end + +local function get_method_receiver_type_text(node) + local query = vim.treesitter.query.parse( + "go", + [[ + (method_declaration receiver: (parameter_list + (parameter_declaration type: (_) @method_receiver))) + ]] + ) + + for _, capture in query:iter_captures(node, 0) do + return get_node_text(capture, 0) + end + return "Method Receiver Not Found" +end + +local function get_package_node(node) + local root = node:tree():root() + local query = create_package_query() + for _, capture in query:iter_captures(root, 0) do + return capture + end + return nil +end + +local function get_method_or_function_declaration_node(node) + local parent = node:parent() + while parent ~= nil do + if parent:type() == "function_declaration" or parent:type() == "method_declaration" then + return parent + end + parent = parent:parent() + end +end + +local root_types = { + method_declaration = true, + function_declaration = true, + func_literal = true, +} + +local handlers = { + ["context.Context"] = function(node) + local var_name_node = node:prev_named_sibling() + local text = get_node_text(var_name_node, 0) + return text + end, + ["*http.Request"] = function(node) + local var_name_node = node:prev_named_sibling() + local text = get_node_text(var_name_node, 0) + return text .. ".Context()" + end, +} + +local build_context_node = function() + local query = assert(vim.treesitter.query.get("go", "search-context"), "No Query") + local node = vim.treesitter.get_node() + while node ~= nil do + if root_types[node:type()] then + for _, capture in query:iter_captures(node, 0) do + local text = get_node_text(capture, 0) + local handle = handlers[text] + if handle then + return handle(capture) + end + end + end + node = node:parent() + end + return "context.Background()" +end + +local function get_method_or_function_name(node) + if node:type() == "method_declaration" then + return get_node_text(node:named_child(1), 0) + end + return get_node_text(node:named_child(0), 0) +end + +local build_span_type_node = function(ctx) + local node = vim.treesitter.get_node() + local method_or_function_node = get_method_or_function_declaration_node(node) + if method_or_function_node == nil then + vim.notify "Not inside method or function" + return { t "" } + end + local package_node = get_package_node(node) + if package_node == nil then + vim.notify "No package node found" + return { t "" } + end + local package_text = get_node_text(package_node, 0) + local final_name = "" + if method_or_function_node:type() == "method_declaration" then + local method_node = method_or_function_node + local receiver_type = get_method_receiver_type_text(method_node) + final_name = ([[%s.%s]]):format(package_text, receiver_type) + else + if method_or_function_node:type() == "function_declaration" then + local function_node = method_or_function_node + local fn_name = get_method_or_function_name(function_node) + final_name = ([[%s.%s]]):format(package_text, fn_name) + end + end + ctx.index = ctx.index + 1 + return { i(ctx.index, final_name) } +end + +local build_span_name_node = function(ctx) + local node = vim.treesitter.get_node() + local method_or_function_node = get_method_or_function_declaration_node(node) + if method_or_function_node == nil then + vim.notify "Not inside method or function" + return { t "" } + end + local fn_name = get_method_or_function_name(method_or_function_node) + ctx.index = ctx.index + 1 + return { i(ctx.index, fn_name) } +end + +local get_span_name_node = function() + return sn(nil, build_span_name_node { index = 0 }) +end + +local get_span_type_node = function() + return sn(nil, build_span_type_node { index = 0 }) +end + +ls.add_snippets("go", { + s( + "apm:span", + fmta( + [[ +span, := apm.StartSpan(, "", "") +defer span.End() + +]], + { + ctx_var = c(1, { + t "ctx", + t "_", + }), + ctx = f(build_context_node, {}), + span_name = d(2, get_span_name_node), + span_type = d(3, get_span_type_node), + finish = i(0), + } + ) + ), +}) diff --git a/lua/snippets/go/efi.lua b/lua/snippets/go/efi.lua new file mode 100644 index 0000000..8684849 --- /dev/null +++ b/lua/snippets/go/efi.lua @@ -0,0 +1,178 @@ +local ls = require "luasnip" + +local sn = ls.sn + +local s = ls.s +local i = ls.insert_node +local t = ls.text_node +local d = ls.dynamic_node +local c = ls.choice_node +local fmta = require("luasnip.extras.fmt").fmta +local rep = require("luasnip.extras").rep + +local get_node_text = vim.treesitter.get_node_text + +local default_values = { + int = "0", + int8 = "0", + int16 = "0", + int32 = "0", + int64 = "0", + uint = "0", + uint8 = "0", + uint16 = "0", + uint32 = "0", + uint64 = "0", + ["time.Time"] = "time.Time{}", + ["time.Duration"] = "time.Duration(0)", + bool = "false", + string = [[""]], + float32 = "0", + float64 = "0", + error = function(_, info) + if info then + info.index = info.index + 1 + + return c(info.index, { + t(info.err_name), + t(string.format('errors.Wrap(%s, "%s")', info.err_name, info.func_name)), + }) + else + return t "err" + end + end, + + -- Types with a "*" mean they are pointers, so return nil + [function(text) + return string.find(text, "*", 1, true) ~= nil + end] = function(_, _) + return t "nil" + end, + + [function(text) + return not string.find(text, "*", 1, true) and string.upper(string.sub(text, 1, 1)) == string.sub(text, 1, 1) + end] = function(text, info) + info.index = info.index + 1 + return sn(info.index, { + c(1, { + t(text .. "{}"), + i(2, text), + }), + }) + end, +} + +local transform = function(text, info) + local condition_matches = function(condition, ...) + if type(condition) == "string" then + return condition == text + else + return condition(...) + end + end + + for condition, result in pairs(default_values) do + if condition_matches(condition, text, info) then + if type(result) == "string" then + return t(result) + end + return result(text, info) + end + end + info.index = info.index + 1 + return sn(info.index, { + c(1, { + t(text .. "{}"), + i(2, text), + }), + }) +end + +local handlers = { + parameter_list = function(node, info) + local result = {} + + local count = node:named_child_count() + for idx = 0, count - 1 do + local matching_node = node:named_child(idx) + local type_node = matching_node:field("type")[1] + table.insert(result, transform(get_node_text(type_node, 0), info)) + if idx ~= count - 1 then + table.insert(result, t { ", " }) + end + end + + return result + end, + + type_identifier = function(node, info) + local text = get_node_text(node, 0) + return { transform(text, info) } + end, +} + +local function_node_types = { + function_declaration = true, + method_declaration = true, + func_literal = true, +} + +local function go_result_type(info) + local node = vim.treesitter.get_node() + while node ~= nil do + if function_node_types[node:type()] then + break + end + node = node:parent() + end + if not node then + vim.notify("Not inside a function", vim.log.levels.ERROR, { title = "Snippet" }) + return t "" + end + + local query = assert(vim.treesitter.query.get("go", "return-snippet"), "No Query") + + for _, capture in query:iter_captures(node, 0) do + if handlers[capture:type()] then + return handlers[capture:type()](capture, info) + end + end + + info.index = info.index + 1 + return { i(info.index, "nil") } +end + +local go_return_values = function(args) + return sn( + nil, + go_result_type { + index = 0, + err_name = args[1][1], + func_name = args[2][1], + } + ) +end + +ls.add_snippets("go", { + s( + "efi", + fmta( + [[ +, := () +if != nil { + return +} + +]], + { + val = i(1), + err = i(2, "err"), + f = i(3), + args = i(4), + err_same = rep(2), + result = d(5, go_return_values, { 2, 3 }), + finish = i(0), + } + ) + ), +}) diff --git a/lua/snippets/go/err_tower.lua b/lua/snippets/go/err_tower.lua new file mode 100644 index 0000000..0d92326 --- /dev/null +++ b/lua/snippets/go/err_tower.lua @@ -0,0 +1,452 @@ +local ls = require "luasnip" + +local sn = ls.snippet_node +local isn = ls.indent_snippet_node + +local s = ls.s +local i = ls.insert_node +local t = ls.text_node +local d = ls.dynamic_node +local c = ls.choice_node +local f = ls.function_node +local fmta = require("luasnip.extras.fmt").fmta +local rep = require("luasnip.extras").rep + +local get_node_text = vim.treesitter.get_node_text + +local default_values = { + int = "0", + int8 = "0", + int16 = "0", + int32 = "0", + int64 = "0", + uint = "0", + uint8 = "0", + uint16 = "0", + uint32 = "0", + uint64 = "0", + ["time.Time"] = "time.Time{}", + ["time.Duration"] = "time.Duration(0)", + bool = "false", + string = [[""]], + float32 = "0", + float64 = "0", + error = "errt", + + -- Types with a "*" mean they are pointers, so return nil + [function(text) + return string.find(text, "*", 1, true) ~= nil + end] = function(_, _) + return t "nil" + end, + + [function(text) + return not string.find(text, "*", 1, true) and string.upper(string.sub(text, 1, 1)) == string.sub(text, 1, 1) + end] = function(text, info) + info.index = info.index + 1 + return sn(info.index, { + c(1, { + t(text .. "{}"), + i(2, text), + }), + }) + end, +} + +local transform = function(text, info) + local condition_matches = function(condition, ...) + if type(condition) == "string" then + return condition == text + else + return condition(...) + end + end + + for condition, result in pairs(default_values) do + if condition_matches(condition, text, info) then + if type(result) == "string" then + return t(result) + end + return result(text, info) + end + end + info.index = info.index + 1 + return sn(info.index, { + c(1, { + t(text .. "{}"), + i(2, text), + }), + }) +end + +local handlers = { + parameter_list = function(node, info) + local result = {} + + local count = node:named_child_count() + for idx = 0, count - 1 do + local matching_node = node:named_child(idx) + local type_node = matching_node:field("type")[1] + table.insert(result, transform(get_node_text(type_node, 0), info)) + if idx ~= count - 1 then + table.insert(result, t { ", " }) + end + end + + return result + end, + + type_identifier = function(node, info) + local text = get_node_text(node, 0) + return { transform(text, info) } + end, +} + +local function_node_types = { + function_declaration = true, + method_declaration = true, + func_literal = true, +} + +local function go_result_type(info) + local node = vim.treesitter.get_node() + while node ~= nil do + if function_node_types[node:type()] then + break + end + node = node:parent() + end + if not node then + vim.notify("Not inside a function", vim.log.levels.ERROR, { title = "Snippet" }) + return t "" + end + + local query = assert(vim.treesitter.query.get("go", "return-snippet"), "No Query") + + for _, capture in query:iter_captures(node, 0) do + if handlers[capture:type()] then + return handlers[capture:type()](capture, info) + end + end + return {} +end + +local go_return_values = function() + return sn( + nil, + go_result_type { + index = 0, + } + ) +end + +local function get_method_or_function_declaration_node(node) + local parent = node:parent() + while parent ~= nil do + if parent:type() == "function_declaration" or parent:type() == "method_declaration" then + return parent + end + parent = parent:parent() + end +end + +local function get_method_or_function_name(node) + if node:type() == "method_declaration" then + return get_node_text(node:named_child(1), 0) + end + return get_node_text(node:named_child(0), 0) +end + +local function get_method_receiver_type_text(node) + local query = vim.treesitter.query.parse( + "go", + [[ + (method_declaration receiver: (parameter_list + (parameter_declaration type: (_) @method_receiver))) + ]] + ) + + for _, capture in query:iter_captures(node, 0) do + local text = get_node_text(capture, 0) + if text:sub(1, 1) == "*" then + return "(" .. text .. ")" + end + return text + end + return "Method Receiver Not Found" +end + +local function get_package_node(node) + local root = node:tree():root() + local query = assert(vim.treesitter.query.get("go", "package-node"), "No Query") + for _, capture in query:iter_captures(root, 0) do + return capture + end + return nil +end + +local function get_package_text(node) + local package_node = get_package_node(node) + if package_node then + return get_node_text(package_node, 0) .. "." + end + vim.notify("Package name not found", vim.log.levels.ERROR, { title = "Snippet" }) + return "" +end + +local function get_function_name() + local node = vim.treesitter.get_node() + local method_or_function_node = get_method_or_function_declaration_node(node) + if not method_or_function_node then + vim.notify("Not inside a function", vim.log.levels.ERROR, { title = "Snippet" }) + return "" + end + local fn_name = get_method_or_function_name(method_or_function_node) + if method_or_function_node:type() == "method_declaration" then + return ([[(%s.%s.%s)]]):format(get_package_text(node), get_method_receiver_type_text(node), fn_name) + end + return ([[(%s.%s)]]):format(get_package_text(node), fn_name) +end + +local function get_context_var_name() + local node = vim.treesitter.get_node() + while node ~= nil do + if function_node_types[node:type()] then + local query = assert(vim.treesitter.query.get("go", "get-function-params"), "No Query") + for _, capture in query:iter_captures(node, 0) do + local var_name = capture:named_child(0) + if var_name:type() == "identifier" then + local type_name = capture:named_child(1) + local type_text = get_node_text(type_name, 0) + if type_text == "context.Context" then + return get_node_text(var_name, 0) + end + end + end + end + node = node:parent() + end + return "context.Background()" +end + +local create_tower_build_choice = function(index) + return c(index, { + t "Freeze()", + sn(nil, { i(1), t "Log(", f(get_context_var_name), t ")" }), + -- stylua: ignore start + isn(nil, { + i(1), t "Log(", f(get_context_var_name), t ").", + t {"", "Notify("}, f(get_context_var_name), t ")", + }, "$PARENT_INDENT\t\t"), + -- stylua: ignore end + }, { + node_ext_opts = { + active = { + virt_text = { { "<-- Choose build choice" } }, + }, + }, + }) +end + +local function register_snippet() + ls.add_snippets("go", { + s( + "errt", + fmta( + [[ +if != nil { + errt := tower. + Wrap(, " "). + + return +} + +]], + { + err = i(1, "err"), + err_same = rep(1), + caller = f(get_function_name), + message = i(2, "message"), + build = create_tower_build_choice(3), + result = d(4, go_return_values), + finish = i(0), + } + ) + ), + s( + "errtc", + fmta( + [[ +if != nil { + errt := tower. + Wrap(, " "). + Context(). + + return +} + +]], + { + err = i(1, "err"), + err_same = rep(1), + caller = f(get_function_name), + message = i(2, "message"), + fields = i(3), + build = create_tower_build_choice(4), + result = d(5, go_return_values), + finish = i(0), + } + ) + ), + s( + "errtp", + fmta( + [[ +if != nil { + errt := tower. + Wrap(, " "). + PublicMessage(""). + + return +} + +]], + { + err = i(1, "err"), + err_same = rep(1), + caller = f(get_function_name), + message = i(2, "message"), + public_message = i(3, "public_message"), + build = create_tower_build_choice(4), + result = d(5, go_return_values), + finish = i(0), + } + ) + ), + s( + "errtpc", + fmta( + [[ +if != nil { + errt := tower. + Wrap(, " "). + PublicMessage(""). + Context(). + + return +} + +]], + { + err = i(1, "err"), + err_same = rep(1), + caller = f(get_function_name), + message = i(2, "message"), + public_message = i(3, "public_message"), + fields = i(4), + build = create_tower_build_choice(5), + result = d(6, go_return_values), + finish = i(0), + } + ) + ), + s( + "errb", + fmta( + [[ +if { + errt := tower. + Bail(" "). + + return +} + +]], + { + condition = i(1), + caller = f(get_function_name), + message = i(2, "message"), + build = create_tower_build_choice(3), + result = d(4, go_return_values), + finish = i(0), + } + ) + ), + s( + "errbc", + fmta( + [[ +if { + errt := tower. + Bail(" "). + Context(). + + return +} + +]], + { + condition = i(1), + caller = f(get_function_name), + message = i(2, "message"), + fields = i(3), + build = create_tower_build_choice(4), + result = d(5, go_return_values), + finish = i(0), + } + ) + ), + s( + "errbp", + fmta( + [[ +if { + errt := tower. + Bail(" "). + PublicMessage(""). + + return +} + +]], + { + condition = i(1), + caller = f(get_function_name), + message = i(2, "message"), + public_message = i(3, "public_message"), + build = create_tower_build_choice(4), + result = d(5, go_return_values), + finish = i(0), + } + ) + ), + s( + "errbpc", + fmta( + [[ +if { + errt := tower. + Bail(" "). + PublicMessage(""). + Context(). + + return +} + +]], + { + condition = i(1), + caller = f(get_function_name), + message = i(2, "message"), + public_message = i(3, "public_message"), + fields = i(4), + build = create_tower_build_choice(5), + result = d(6, go_return_values), + finish = i(0), + } + ) + ), + }) +end + +register_snippet() diff --git a/lua/snippets/go/init.lua b/lua/snippets/go/init.lua new file mode 100644 index 0000000..77b9f3c --- /dev/null +++ b/lua/snippets/go/init.lua @@ -0,0 +1,9 @@ +-- Use to clear snippets when sourced. +-- +-- Useful when building a new snippet. +-- +-- require("luasnip.session.snippet_collection").clear_snippets("go") + +require "snippets.go.efi" +require "snippets.go.apm_span" +require "snippets.go.err_tower" diff --git a/lua/snippets/init.lua b/lua/snippets/init.lua new file mode 100644 index 0000000..144dbbf --- /dev/null +++ b/lua/snippets/init.lua @@ -0,0 +1 @@ +require "snippets.go" diff --git a/queries/go/get-function-params.scm b/queries/go/get-function-params.scm new file mode 100644 index 0000000..64b8fbc --- /dev/null +++ b/queries/go/get-function-params.scm @@ -0,0 +1,10 @@ +[ + (method_declaration + parameters: (parameter_list + (parameter_declaration) @params)) + (function_declaration + parameters: (parameter_list + (parameter_declaration) @params)) + (func_literal parameters: + (parameter_list (parameter_declaration) @params)) +] diff --git a/queries/go/package-node.scm b/queries/go/package-node.scm new file mode 100644 index 0000000..06edc37 --- /dev/null +++ b/queries/go/package-node.scm @@ -0,0 +1 @@ +(source_file (package_clause (package_identifier) @package_name) ) diff --git a/queries/go/return-snippet.scm b/queries/go/return-snippet.scm new file mode 100644 index 0000000..0a68f81 --- /dev/null +++ b/queries/go/return-snippet.scm @@ -0,0 +1,5 @@ +[ + (method_declaration result: (_) @type) + (function_declaration result: (_) @type) + (func_literal result: (_) @type) +] diff --git a/queries/go/search-context.scm b/queries/go/search-context.scm new file mode 100644 index 0000000..5969a4e --- /dev/null +++ b/queries/go/search-context.scm @@ -0,0 +1,11 @@ +[ + (method_declaration + parameters: (parameter_list + (parameter_declaration type: (_) @type))) + (function_declaration + parameters: (parameter_list + (parameter_declaration type: (_) @type))) + (func_literal + parameters: (parameter_list + (parameter_declaration type: (_) @type))) +] diff --git a/stylua.toml b/stylua.toml new file mode 100644 index 0000000..02ed90b --- /dev/null +++ b/stylua.toml @@ -0,0 +1,4 @@ +indent_type = "Spaces" +indent_width = 4 +column_width = 120 +call_parentheses = "None"