From b127c2514df6b5a3a84b07435fe3e7770c033fd3 Mon Sep 17 00:00:00 2001 From: Ismo Vuorinen Date: Thu, 3 Oct 2024 01:32:19 +0300 Subject: [PATCH] feat(nvim): another configuration tweak round added snippets! --- config/nvim/lua/plugins/cmp.lua | 87 +++- config/nvim/lua/plugins/comment.lua | 9 + config/nvim/lua/plugins/conform.lua | 84 ++++ config/nvim/lua/plugins/flash.lua | 39 ++ config/nvim/lua/plugins/harpoon.lua | 47 ++ config/nvim/lua/plugins/lazy.lua | 66 --- config/nvim/lua/plugins/lsp-saga.lua | 21 + config/nvim/lua/plugins/lsp.lua | 553 +++++++--------------- config/nvim/lua/plugins/neogen.lua | 8 + config/nvim/lua/plugins/noice.lua | 8 +- config/nvim/lua/plugins/refactoring.lua | 8 + config/nvim/lua/plugins/surround.lua | 8 + config/nvim/lua/plugins/telescope.lua | 46 -- config/nvim/lua/plugins/todo-comments.lua | 8 + config/nvim/lua/plugins/treesitter.lua | 4 +- config/nvim/lua/plugins/treesj.lua | 9 + config/nvim/lua/plugins/trouble.lua | 2 +- config/nvim/lua/plugins/ufo.lua | 116 +++++ config/nvim/lua/plugins/ui.lua | 4 + config/nvim/lua/plugins/vim-sleuth.lua | 3 + config/nvim/lua/plugins/wakatime.lua | 4 + config/nvim/lua/plugins/which-key.lua | 102 +--- config/nvim/snippets/javascript.json | 462 ++++++++++++++++++ config/nvim/snippets/lua.json | 262 ++++++++++ config/nvim/snippets/markdown.json | 133 ++++++ config/nvim/snippets/php.snippets | 165 +++++++ config/nvim/snippets/sh.json | 334 +++++++++++++ config/nvim/snippets/yaml.json | 7 + 28 files changed, 2006 insertions(+), 593 deletions(-) create mode 100644 config/nvim/lua/plugins/comment.lua create mode 100644 config/nvim/lua/plugins/conform.lua create mode 100644 config/nvim/lua/plugins/flash.lua create mode 100644 config/nvim/lua/plugins/harpoon.lua delete mode 100644 config/nvim/lua/plugins/lazy.lua create mode 100644 config/nvim/lua/plugins/lsp-saga.lua create mode 100644 config/nvim/lua/plugins/neogen.lua create mode 100644 config/nvim/lua/plugins/refactoring.lua create mode 100644 config/nvim/lua/plugins/surround.lua create mode 100644 config/nvim/lua/plugins/todo-comments.lua create mode 100644 config/nvim/lua/plugins/treesj.lua create mode 100644 config/nvim/lua/plugins/ufo.lua create mode 100644 config/nvim/lua/plugins/vim-sleuth.lua create mode 100644 config/nvim/lua/plugins/wakatime.lua create mode 100644 config/nvim/snippets/javascript.json create mode 100644 config/nvim/snippets/lua.json create mode 100644 config/nvim/snippets/markdown.json create mode 100644 config/nvim/snippets/php.snippets create mode 100644 config/nvim/snippets/sh.json create mode 100644 config/nvim/snippets/yaml.json diff --git a/config/nvim/lua/plugins/cmp.lua b/config/nvim/lua/plugins/cmp.lua index e660cd3..dcc6b34 100644 --- a/config/nvim/lua/plugins/cmp.lua +++ b/config/nvim/lua/plugins/cmp.lua @@ -12,9 +12,16 @@ return { -- ── LuaSnip Dependencies ──────────────────────────────────────────── -- Snippet Engine for Neovim written in Lua. -- https://github.com/L3MON4D3/LuaSnip - { 'L3MON4D3/LuaSnip', build = 'make install_jsregexp' }, - -- luasnip completion source for nvim-cmp - -- https://github.com/saadparwaiz1/cmp_luasnip + { + 'L3MON4D3/LuaSnip', + build = 'make install_jsregexp', + dependencies = { + -- luasnip completion source for nvim-cmp + -- https://github.com/saadparwaiz1/cmp_luasnip + 'saadparwaiz1/cmp_luasnip', + 'rafamadriz/friendly-snippets', + }, + }, { 'saadparwaiz1/cmp_luasnip' }, -- ── Adds other completion capabilities. ───────────────────────────── @@ -23,9 +30,25 @@ return { { 'hrsh7th/cmp-nvim-lsp' }, { 'hrsh7th/cmp-buffer' }, { 'hrsh7th/cmp-path' }, + { 'hrsh7th/cmp-nvim-lsp-signature-help' }, + { 'hrsh7th/cmp-emoji' }, + { 'hrsh7th/cmp-cmdline' }, -- cmp import and use all environment variables from .env.* and system -- https://github.com/SergioRibera/cmp-dotenv { 'SergioRibera/cmp-dotenv' }, + -- A dictionary completion source for nvim-cmp + -- https://github.com/uga-rosa/cmp-dictionary + { 'uga-rosa/cmp-dictionary' }, + -- An additional source for nvim-cmp to autocomplete packages and its versions + -- https://github.com/David-Kunz/cmp-npm + { + 'David-Kunz/cmp-npm', + dependencies = { 'nvim-lua/plenary.nvim' }, + ft = 'json', + opts = {}, + }, + -- https://github.com/chrisgrieser/cmp-nerdfont + { 'chrisgrieser/cmp-nerdfont' }, -- ── Other deps ────────────────────────────────────────────────────── -- vscode-like pictograms for neovim lsp completion items @@ -63,8 +86,14 @@ return { local luasnip = require 'luasnip' local lspkind = require 'lspkind' luasnip.config.setup {} + require('luasnip.loaders.from_vscode').lazy_load() require('copilot_cmp').setup() + require('cmp_dictionary').setup { + paths = { '/usr/share/dict/words' }, + exact_length = 2, + } + local has_words_before = function() if vim.api.nvim_get_option_value('buftype', {}) == 'prompt' then return false @@ -90,12 +119,16 @@ return { }, }, }, + window = { + completion = cmp.config.window.bordered(), + documentation = cmp.config.window.bordered(), + }, view = { width = function(_, _) return math.min(80, vim.o.columns) end, - entries = { - name = 'custom', - selection_order = 'near_cursor', - }, + -- entries = { + -- name = 'custom', + -- selection_order = 'near_cursor', + -- }, }, snippet = { expand = function(args) luasnip.lsp_expand(args.body) end, @@ -131,14 +164,20 @@ return { end, { 'i', 's' }), }, sources = { + -- function arg popups while typing + { name = 'nvim_lsp_signature_help', group_index = 2 }, + -- Copilot Source { name = 'copilot', group_index = 2 }, -- Other Sources + { name = 'dictionary', keyword_length = 2, group_index = 2 }, + { name = 'npm', keyword_length = 4, group_index = 2 }, { name = 'nvim_lsp', group_index = 2 }, - { name = 'path', group_index = 2 }, { name = 'luasnip', group_index = 2 }, - { name = 'buffer', group_index = 2 }, { name = 'dotenv', group_index = 2 }, + { name = 'path', group_index = 2 }, + { name = 'emoji', group_index = 2 }, + { name = 'nerdfont', group_index = 2 }, }, sorting = { priority_weight = 2, @@ -147,7 +186,7 @@ return { -- Below is the default comparator list and order for nvim-cmp cmp.config.compare.offset, - -- cmp.config.compare.scopes, --this is commented in nvim-cmp too + cmp.config.compare.scopes, --this is commented in nvim-cmp too cmp.config.compare.exact, cmp.config.compare.score, cmp.config.compare.recently_used, @@ -159,6 +198,34 @@ return { }, }, } + + cmp.setup.cmdline({ '/', '?' }, { + mapping = cmp.mapping.preset.cmdline(), + sources = { + { name = 'buffer' }, + }, + }) + + -- Use cmdline & path source for ':' (if you enabled `native_menu`, this won't work anymore). + cmp.setup.cmdline(':', { + mapping = cmp.mapping.preset.cmdline(), + sources = cmp.config.sources({ + { name = 'path' }, + }, { + { name = 'cmdline' }, + }), + matching = { disallow_symbol_nonprefix_matching = false }, + }) + end, + }, + -- Luasnip choice node completion source for nvim-cmp + -- https://github.com/doxnit/cmp-luasnip-choice + { + 'doxnit/cmp-luasnip-choice', + config = function() + require('cmp_luasnip_choice').setup { + auto_open = true, -- Automatically open nvim-cmp on choice node (default: true) + } end, }, } diff --git a/config/nvim/lua/plugins/comment.lua b/config/nvim/lua/plugins/comment.lua new file mode 100644 index 0000000..5f37fd1 --- /dev/null +++ b/config/nvim/lua/plugins/comment.lua @@ -0,0 +1,9 @@ +-- Commenting +-- "gc" to comment visual regions/lines +-- https://github.com/numToStr/Comment.nvim +return { + 'numToStr/Comment.nvim', + version = '*', + event = { 'BufRead', 'BufNewFile' }, + opts = {}, +} diff --git a/config/nvim/lua/plugins/conform.lua b/config/nvim/lua/plugins/conform.lua new file mode 100644 index 0000000..e25edaa --- /dev/null +++ b/config/nvim/lua/plugins/conform.lua @@ -0,0 +1,84 @@ +-- ── Formatting ────────────────────────────────────────────────────── +-- Lightweight yet powerful formatter plugin for Neovim +-- https://github.com/stevearc/conform.nvim +return { + 'stevearc/conform.nvim', + event = { 'BufWritePre' }, + cmd = { 'ConformInfo' }, + config = function() + -- Select first conform formatter that is available + ---@param bufnr integer + ---@param ... string + ---@return string + local function first(bufnr, ...) + local conform = require 'conform' + for i = 1, select('#', ...) do + local formatter = select(i, ...) + if conform.get_formatter_info(formatter, bufnr).available then + return formatter + end + end + return select(1, ...) + end + + require('conform').setup { + -- Enable or disable logging + notify_on_error = true, + -- Set the default formatter for all filetypes + default_formatter = 'injected', + -- Set the default formatter for all filetypes + default_formatter_opts = { + lsp_format = 'fallback', + -- Set the default formatter for all filetypes + -- formatter = 'injected', + -- Set the default formatter for all filetypes + -- formatter_opts = {}, + }, + formatters_by_ft = { + markdown = function(bufnr) + return { first(bufnr, 'prettierd', 'prettier'), 'injected' } + end, + javascript = function(bufnr) + return { first(bufnr, 'prettier', 'eslint'), 'injected' } + end, + lua = { 'stylua' }, + -- Conform will run multiple formatters sequentially + -- python = { 'isort', 'black', lsp_format = 'fallback' }, + -- You can customize some of the format options for the filetype (:help conform.format) + -- rust = { 'rustfmt', lsp_format = 'fallback' }, + }, + format_on_save = function(bufnr) + -- Disable autoformat on certain filetypes + local ignore_filetypes = { + 'c', + 'cpp', + 'sql', + 'java', + } + if vim.tbl_contains(ignore_filetypes, vim.bo[bufnr].filetype) then + return + end + -- Disable with a global or buffer-local variable + if + vim.g.disable_autoformat or vim.b[bufnr].disable_autoformat + then + return + end + -- Disable autoformat for files in a certain path + local bufname = vim.api.nvim_buf_get_name(bufnr) + if bufname:match '/node_modules/' then return end + if bufname:match '/vendor/' then return end + if bufname:match '/dist/' then return end + if bufname:match '/build/' then return end + + return { timeout_ms = 500, lsp_format = 'fallback' } + end, + } + end, + init = function() + -- If you want the formatexpr, here is the place to set it + vim.o.formatexpr = "v:lua.require'conform'.formatexpr()" + end, + + +} diff --git a/config/nvim/lua/plugins/flash.lua b/config/nvim/lua/plugins/flash.lua new file mode 100644 index 0000000..9c0bc45 --- /dev/null +++ b/config/nvim/lua/plugins/flash.lua @@ -0,0 +1,39 @@ +return { + 'folke/flash.nvim', + event = 'VeryLazy', + opts = {}, + keys = { + { + 'zk', + mode = { 'n', 'x', 'o' }, + function() require('flash').jump() end, + desc = 'Flash', + }, + { + 'Zk', + mode = { 'n', 'x', 'o' }, + function() require('flash').treesitter() end, + desc = 'Flash Treesitter', + }, + { + 'r', + mode = 'o', + function() require('flash').remote() end, + desc = 'Remote Flash', + }, + { + 'R', + mode = { 'o', 'x' }, + function() require('flash').treesitter_search() end, + desc = 'Treesitter Search', + }, + { + '', + mode = { 'c' }, + function() require('flash').toggle() end, + desc = 'Toggle Flash Search', + }, + }, +} + +-- vim: ts=2 sts=2 sw=2 et diff --git a/config/nvim/lua/plugins/harpoon.lua b/config/nvim/lua/plugins/harpoon.lua new file mode 100644 index 0000000..206cf6d --- /dev/null +++ b/config/nvim/lua/plugins/harpoon.lua @@ -0,0 +1,47 @@ +-- Getting you where you want with the fewest keystrokes. +-- https://github.com/ThePrimeagen/harpoon +return { + 'ThePrimeagen/harpoon', + branch = 'harpoon2', + dependencies = { + 'nvim-lua/plenary.nvim', + 'nvim-telescope/telescope.nvim', + }, + config = function() + local harpoon = require 'harpoon' + harpoon:setup {} + + -- basic telescope configuration + local conf = require('telescope.config').values + local function toggle_telescope(harpoon_files) + local file_paths = {} + for _, item in ipairs(harpoon_files.items) do + table.insert(file_paths, item.value) + end + + require('telescope.pickers') + .new({}, { + prompt_title = 'Harpoon', + finder = require('telescope.finders').new_table { + results = file_paths, + }, + previewer = conf.file_previewer {}, + sorter = conf.generic_sorter {}, + }) + :find() + end + + vim.keymap.set( + 'n', + 'hw', + function() toggle_telescope(harpoon:list()) end, + { desc = 'Open harpoon window with telescope' } + ) + vim.keymap.set( + 'n', + 'ht', + function() harpoon.ui:toggle_quick_menu(harpoon:list()) end, + { desc = 'Open Harpoon Quick menu' } + ) + end, +} diff --git a/config/nvim/lua/plugins/lazy.lua b/config/nvim/lua/plugins/lazy.lua deleted file mode 100644 index bfe0288..0000000 --- a/config/nvim/lua/plugins/lazy.lua +++ /dev/null @@ -1,66 +0,0 @@ -return { - - -- A better annotation generator. - -- Supports multiple languages and annotation conventions. - -- https://github.com/danymat/neogen - { - 'danymat/neogen', - version = '*', - opts = { enabled = true, snippet_engine = 'luasnip' }, - }, - - -- The Refactoring library based off the Refactoring book by Martin Fowler - -- https://github.com/ThePrimeagen/refactoring.nvim - { - 'ThePrimeagen/refactoring.nvim', - version = '*', - dependencies = { 'nvim-lua/plenary.nvim', 'nvim-treesitter/nvim-treesitter' }, - opts = {}, - }, - - -- All the npm/yarn/pnpm commands I don't want to type - -- https://github.com/vuki656/package-info.nvim - { - 'vuki656/package-info.nvim', - version = '*', - dependencies = { 'MunifTanjim/nui.nvim' }, - opts = {}, - }, - - -- Add/change/delete surrounding delimiter pairs with ease. Written with ❤️ in Lua. - -- https://github.com/kylechui/nvim-surround - { - 'kylechui/nvim-surround', - version = '*', - event = 'VeryLazy', - opts = {}, - }, - - -- Highlight, list and search todo comments in your projects - -- https://github.com/folke/todo-comments.nvim - { - 'folke/todo-comments.nvim', - version = '*', - dependencies = { 'nvim-lua/plenary.nvim' }, - opts = {}, - }, - - -- Commenting - -- "gc" to comment visual regions/lines - -- https://github.com/numToStr/Comment.nvim - { - 'numToStr/Comment.nvim', - version = '*', - event = { 'BufRead', 'BufNewFile' }, - opts = {}, - }, - - -- Detect tabstop and shiftwidth automatically - -- https://github.com/tpope/vim-sleuth - { 'tpope/vim-sleuth' }, - - -- Vim plugin for automatic time tracking and metrics - -- generated from your programming activity. - -- https://github.com/wakatime/vim-wakatime - { 'wakatime/vim-wakatime', lazy = false, enabled = true }, -} diff --git a/config/nvim/lua/plugins/lsp-saga.lua b/config/nvim/lua/plugins/lsp-saga.lua new file mode 100644 index 0000000..aec604f --- /dev/null +++ b/config/nvim/lua/plugins/lsp-saga.lua @@ -0,0 +1,21 @@ +-- improve neovim lsp experience +-- https://github.com/nvimdev/lspsaga.nvim +-- https://nvimdev.github.io/lspsaga/ +return { + 'nvimdev/lspsaga.nvim', + event = 'LspAttach', + dependencies = { + 'nvim-treesitter/nvim-treesitter', -- optional + 'nvim-tree/nvim-web-devicons', -- optional + }, + opts = { + code_action = { + show_server_name = true, + }, + diagnostic = { + keys = { + quit = { 'q', '' }, + }, + }, + }, +} diff --git a/config/nvim/lua/plugins/lsp.lua b/config/nvim/lua/plugins/lsp.lua index 3e411a5..8f1f3eb 100644 --- a/config/nvim/lua/plugins/lsp.lua +++ b/config/nvim/lua/plugins/lsp.lua @@ -1,219 +1,36 @@ --- Quick start configs for Nvim LSP --- https://github.com/neovim/nvim-lspconfig +-- ── Mason and LSPConfig integration ──────────────────────────────────── + +-- ── LSP settings. ─────────────────────────────────────────────── +-- This function gets run when an LSP connects to a particular buffer. + +-- Make runtime files discoverable to the server +local runtime_path = vim.split(package.path, ';') +table.insert(runtime_path, 'lua/?.lua') +table.insert(runtime_path, 'lua/?/init.lua') + +-- nvim-cmp supports additional completion capabilities +local capabilities = vim.lsp.protocol.make_client_capabilities() +capabilities = require('cmp_nvim_lsp').default_capabilities(capabilities) +-- Tell the server the capability of foldingRange, +-- Neovim hasn't added foldingRange to default capabilities, users must add it manually +capabilities.textDocument.foldingRange = { + dynamicRegistration = true, + lineFoldingOnly = true, +} + return { + -- Portable package manager for Neovim that runs everywhere Neovim runs. + -- Easily install and manage LSP servers, DAP servers, linters, and formatters. + -- https://github.com/williamboman/mason.nvim { - 'neovim/nvim-lspconfig', - lazy = false, - dependencies = { - -- ── Mason and LSPConfig integration ───────────────────────────────── - -- Automatically install LSPs to stdpath for neovim - - -- Portable package manager for Neovim that runs everywhere Neovim runs. - -- Easily install and manage LSP servers, DAP servers, linters, and formatters. - -- https://github.com/williamboman/mason.nvim - { - 'williamboman/mason.nvim', - cmd = 'Mason', - run = ':MasonUpdate', - }, - -- Extension to mason.nvim that makes it easier to use lspconfig with mason.nvim. - -- https://github.com/williamboman/mason-lspconfig.nvim - { 'williamboman/mason-lspconfig.nvim' }, - - -- ── Formatting ────────────────────────────────────────────────────── - -- Lightweight yet powerful formatter plugin for Neovim - -- https://github.com/stevearc/conform.nvim - { - 'stevearc/conform.nvim', - event = { 'BufWritePre' }, - cmd = { 'ConformInfo' }, - config = function() - -- Select first conform formatter that is available - ---@param bufnr integer - ---@param ... string - ---@return string - local function first(bufnr, ...) - local conform = require 'conform' - for i = 1, select('#', ...) do - local formatter = select(i, ...) - if conform.get_formatter_info(formatter, bufnr).available then - return formatter - end - end - return select(1, ...) - end - - require('conform').setup { - -- Enable or disable logging - notify_on_error = true, - -- Set the default formatter for all filetypes - default_formatter = 'injected', - -- Set the default formatter for all filetypes - default_formatter_opts = { - lsp_format = 'fallback', - -- Set the default formatter for all filetypes - -- formatter = 'injected', - -- Set the default formatter for all filetypes - -- formatter_opts = {}, - }, - formatters_by_ft = { - markdown = function(bufnr) - return { first(bufnr, 'prettierd', 'prettier'), 'injected' } - end, - javascript = function(bufnr) - return { first(bufnr, 'prettier', 'eslint'), 'injected' } - end, - lua = { 'stylua' }, - -- Conform will run multiple formatters sequentially - -- python = { 'isort', 'black', lsp_format = 'fallback' }, - -- You can customize some of the format options for the filetype (:help conform.format) - -- rust = { 'rustfmt', lsp_format = 'fallback' }, - }, - format_on_save = function(bufnr) - -- Disable autoformat on certain filetypes - local ignore_filetypes = { - 'c', - 'cpp', - 'sql', - 'java', - } - if vim.tbl_contains(ignore_filetypes, vim.bo[bufnr].filetype) then - return - end - -- Disable with a global or buffer-local variable - if - vim.g.disable_autoformat or vim.b[bufnr].disable_autoformat - then - return - end - -- Disable autoformat for files in a certain path - local bufname = vim.api.nvim_buf_get_name(bufnr) - if bufname:match '/node_modules/' then return end - if bufname:match '/vendor/' then return end - if bufname:match '/dist/' then return end - if bufname:match '/build/' then return end - - return { timeout_ms = 500, lsp_format = 'fallback' } - end, - } - end, - init = function() - -- If you want the formatexpr, here is the place to set it - vim.o.formatexpr = "v:lua.require'conform'.formatexpr()" - end, - }, - - -- ── Misc ──────────────────────────────────────────────────────────── - -- vscode-like pictograms for neovim lsp completion items - -- https://github.com/onsails/lspkind-nvim - { 'onsails/lspkind.nvim' }, - -- JSON schemas for Neovim - -- https://github.com/b0o/SchemaStore.nvim - { 'b0o/schemastore.nvim' }, - }, - config = function() - -- ── LSP settings. ─────────────────────────────────────────────────── - -- This function gets run when an LSP connects to a particular buffer. - - -- Make runtime files discoverable to the server - local runtime_path = vim.split(package.path, ';') - table.insert(runtime_path, 'lua/?.lua') - table.insert(runtime_path, 'lua/?/init.lua') - - -- Generate a command `:Format` local to the LSP buffer - -- - ---@param _ nil Skipped - ---@param bufnr number Buffer number - ---@output nil - local on_attach = function(_, bufnr) - -- Create a command `:Format` local to the LSP buffer - vim.api.nvim_create_user_command('Format', function(args) - local range = nil - if args.count ~= -1 then - local end_line = vim.api.nvim_buf_get_lines( - bufnr, - args.line2 - 1, - args.line2, - true - )[1] - range = { - start = { args.line1, 0 }, - ['end'] = { args.line2, end_line:len() }, - } - end - require('conform').format { - async = true, - lsp_format = 'fallback', - range = range, - } - end, { range = true, desc = 'Format current buffer with LSP' }) - end - - -- ── Enable the following language servers ─────────────────────────── - -- :help lspconfig-all for all pre-configured LSPs - local servers = { - bashls = {}, -- Bash - -- csharp_ls = {}, -- C#, requires dotnet executable - gopls = {}, -- Go - html = {}, -- HTML - intelephense = {}, -- PHP - tailwindcss = {}, -- Tailwind CSS - ts_ls = {}, -- TypeScript - volar = {}, -- Vue - - lua_ls = { - settings = { - Lua = { - runtime = { - -- Tell the language server which version of Lua you're using (most likely LuaJIT) - version = 'LuaJIT', - -- Setup your lua path - path = runtime_path, - }, - diagnostics = { - globals = { 'vim' }, - disable = { - -- Ignore Lua_LS's noisy `missing-fields` warnings - 'missing-fields', - }, - }, - workspace = { - library = vim.api.nvim_get_runtime_file('', true), - checkThirdParty = false, - }, - -- Do not send telemetry data containing a randomized but unique identifier - telemetry = { enable = false }, - - completion = { - callSnippet = 'Replace', - }, - }, - }, - }, - jsonls = { - settings = { - json = { - schemas = require('schemastore').json.schemas(), - validate = { enable = true }, - }, - yaml = { - schemaStore = { - -- You must disable built-in schemaStore support if you want to use - -- this plugin and its advanced options like `ignore`. - enable = false, - -- Avoid TypeError: Cannot read properties of undefined (reading 'length') - url = '', - }, - schemas = require('schemastore').yaml.schemas(), - validate = { enable = true }, - }, - }, - }, - } - - -- Mason servers should be it's own variable for mason-nvim-lint + 'williamboman/mason.nvim', + cmd = 'Mason', + run = ':MasonUpdate', + opts = { + PATH = 'prepend', + -- Mason servers to install -- See: https://mason-registry.dev/registry/list - local mason_servers = { + ensure_installed = { 'bash-language-server', 'clang-format', 'codespell', @@ -234,62 +51,160 @@ return { 'vim-language-server', 'vue-language-server', 'yamllint', - } - local ensure_installed = vim.tbl_keys(servers or {}) - vim.list_extend(ensure_installed, mason_servers) - - -- ── Setup mason so it can manage external tooling ─────────────────── - require('mason').setup { - ensure_installed = ensure_installed, - automatic_installation = true, - } - - -- nvim-cmp supports additional completion capabilities - local capabilities = vim.lsp.protocol.make_client_capabilities() - capabilities = require('cmp_nvim_lsp').default_capabilities(capabilities) - -- Tell the server the capability of foldingRange, - -- Neovim hasn't added foldingRange to default capabilities, users must add it manually - capabilities.textDocument.foldingRange = { - dynamicRegistration = true, - lineFoldingOnly = true, - } - - capabilities.textDocument.completion.completionItem.snippetSupport = true - capabilities.textDocument.completion.completionItem.resolveSupport = { - properties = { - 'documentation', - 'detail', - 'additionalTextEdits', - }, - } - - local lspconfig_handlers = { + }, + }, + }, + -- Extension to mason.nvim that makes it easier to use lspconfig with mason.nvim. + -- https://github.com/williamboman/mason-lspconfig.nvim + { + 'williamboman/mason-lspconfig.nvim', + opts = { + -- ── Enable the following language servers ─────────────────────────── + -- :help lspconfig-all for all pre-configured LSPs + ensure_installed = { + 'bashls', + -- 'csharp_ls', + 'gopls', + 'html', + 'intelephense', + 'tailwindcss', + 'ts_ls', + 'lua_ls', + 'jsonls', + }, + automatic_installation = true, + handlers = { -- The first entry (without a key) will be the default handler -- and will be called for each installed server that doesn't have -- a dedicated handler. function(server_name) -- default handler (optional) require('lspconfig')[server_name].setup { - on_attach = on_attach, + on_attach = function(_, bufnr) + -- Create a command `:Format` local to the LSP buffer + vim.api.nvim_buf_create_user_command( + bufnr, + 'Format', + function(_) + require('conform').format { + formatters = { 'injected' }, + async = true, + lsp_fallback = true, + } + end, + { desc = 'Format current buffer with LSP' } + ) + end, capabilities = capabilities, } end, -- Next, you can provide targeted overrides for specific servers. ['lua_ls'] = function() - require('lspconfig')['lua_ls'].setup { settings = servers.lua_ls } + require('lspconfig')['lua_ls'].setup { + on_attach = function(_, bufnr) + -- Create a command `:Format` local to the LSP buffer + vim.api.nvim_buf_create_user_command( + bufnr, + 'Format', + function(_) + require('conform').format { + formatters = { 'injected' }, + async = true, + lsp_fallback = true, + } + end, + { desc = 'Format current buffer with LSP' } + ) + end, + capabilities = capabilities, + settings = { + Lua = { + runtime = { + -- Tell the language server which version of Lua you're + -- using (most likely LuaJIT) + version = 'LuaJIT', + -- Setup your lua path + path = runtime_path, + }, + diagnostics = { + globals = { 'vim' }, + disable = { + -- Ignore lua_ls noisy `missing-fields` warnings + 'missing-fields', + }, + }, + workspace = { + library = vim.api.nvim_get_runtime_file('', true), + checkThirdParty = false, + }, + -- Do not send telemetry data containing a randomized + -- but unique identifier + telemetry = { enable = false }, + + completion = { + callSnippet = 'Replace', + }, + }, + }, + } end, ['jsonls'] = function() - require('lspconfig')['jsonls'].setup { settings = servers.jsonls } + require('lspconfig')['jsonls'].setup { + on_attach = function(_, bufnr) + -- Create a command `:Format` local to the LSP buffer + vim.api.nvim_buf_create_user_command( + bufnr, + 'Format', + function(_) + require('conform').format { + formatters = { 'injected' }, + async = true, + lsp_fallback = true, + } + end, + { desc = 'Format current buffer with LSP' } + ) + end, + capabilities = capabilities, + settings = { + json = { + schemas = require('schemastore').json.schemas(), + validate = { enable = true }, + }, + yaml = { + schemaStore = { + -- You must disable built-in SchemaStore support if you want to use + -- this plugin and its advanced options like `ignore`. + enable = false, + -- Avoid TypeError: Cannot read properties of undefined (reading 'length') + url = '', + }, + schemas = require('schemastore').yaml.schemas(), + validate = { enable = true }, + }, + }, + } end, - } - - require('mason-lspconfig').setup { - ensure_installed = vim.tbl_keys(servers or {}), - automatic_installation = true, - handlers = lspconfig_handlers, - } - end, + }, + }, }, + -- Automatically install formatters registered with conform.nvim via mason.nvim + -- https://github.com/zapling/mason-conform.nvim + -- { 'zapling/mason-conform.nvim', opts = {} }, + + -- ── Misc ─────────────────────────────────────────────────── + -- vscode-like pictograms for neovim lsp completion items + -- https://github.com/onsails/lspkind-nvim + { 'onsails/lspkind.nvim', opts = {} }, + -- JSON schemas for Neovim + -- https://github.com/b0o/SchemaStore.nvim + { 'b0o/schemastore.nvim' }, + + -- ── LSP ──────────────────────────────────────────────────── + -- Quick start configs for Nvim LSP + -- https://github.com/neovim/nvim-lspconfig + { 'neovim/nvim-lspconfig' }, + -- Garbage collector that stops inactive LSP clients to free RAM -- https://github.com/Zeioth/garbage-day.nvim { @@ -298,134 +213,4 @@ return { event = 'VeryLazy', opts = {}, }, - - -- improve neovim lsp experience - -- https://github.com/nvimdev/lspsaga.nvim - -- https://nvimdev.github.io/lspsaga/ - { - 'nvimdev/lspsaga.nvim', - event = 'LspAttach', - dependencies = { - 'nvim-treesitter/nvim-treesitter', -- optional - 'nvim-tree/nvim-web-devicons', -- optional - }, - opts = { - code_action = { - show_server_name = true, - }, - diagnostic = { - keys = { - quit = { 'q', '' }, - }, - }, - }, - }, - - -- Not UFO in the sky, but an ultra fold in Neovim. - -- https://github.com/kevinhwang91/nvim-ufo/ - { - 'kevinhwang91/nvim-ufo', - version = '*', - dependencies = { - { 'neovim/nvim-lspconfig' }, - { 'kevinhwang91/promise-async' }, - { 'nvim-treesitter/nvim-treesitter', run = ':TSUpdate' }, - { - -- Status column plugin that provides a configurable - -- 'statuscolumn' and click handlers. - -- https://github.com/luukvbaal/statuscol.nvim - 'luukvbaal/statuscol.nvim', - config = function() - local builtin = require 'statuscol.builtin' - require('statuscol').setup { - relculright = true, - segments = { - { - text = { builtin.foldfunc }, - click = 'v:lua.ScFa', - }, - { - sign = { - namespace = { 'diagnostic/signs' }, - maxwidth = 2, - -- auto = true, - }, - click = 'v:lua.ScSa', - }, - { - text = { builtin.lnumfunc, ' ' }, - click = 'v:lua.ScLa', - }, - }, - } - end, - }, - }, - opts = { - open_fold_hl_timeout = 150, - close_fold_kinds_for_ft = { 'imports', 'comment' }, - preview = { - win_config = { - border = { '', '─', '', '', '', '─', '', '' }, - winhighlight = 'Normal:Folded', - winblend = 0, - }, - mappings = { - scrollU = '', - scrollD = '', - jumpTop = '[', - jumpBot = ']', - }, - }, - - provider_selector = function(_, _, _) -- bufnr, filetype, buftype - return { 'treesitter', 'indent' } - end, - - -- fold_virt_text_handler - -- - -- This handler is called when the fold text is too long to fit in the window. - -- It is expected to truncate the text and return a new list of virtual text. - -- - ---@param virtText table The current virtual text list. - ---@param lnum number The line number of the first line in the fold. - ---@param endLnum number The line number of the last line in the fold. - ---@param width number The width of the window. - ---@param truncate function Truncate function - ---@return table - fold_virt_text_handler = function( - virtText, - lnum, - endLnum, - width, - truncate - ) - local newVirtText = {} - local suffix = (' 󰁂 %d '):format(endLnum - lnum) - local sufWidth = vim.fn.strdisplaywidth(suffix) - local targetWidth = width - sufWidth - local curWidth = 0 - for _, chunk in ipairs(virtText) do - local chunkText = chunk[1] - local chunkWidth = vim.fn.strdisplaywidth(chunkText) - if targetWidth > curWidth + chunkWidth then - table.insert(newVirtText, chunk) - else - chunkText = truncate(chunkText, targetWidth - curWidth) - local hlGroup = chunk[2] - table.insert(newVirtText, { chunkText, hlGroup }) - chunkWidth = vim.fn.strdisplaywidth(chunkText) - -- str width returned from truncate() may less than 2nd argument, need padding - if curWidth + chunkWidth < targetWidth then - suffix = suffix .. (' '):rep(targetWidth - curWidth - chunkWidth) - end - break - end - curWidth = curWidth + chunkWidth - end - table.insert(newVirtText, { suffix, 'MoreMsg' }) - return newVirtText - end, - }, - }, } diff --git a/config/nvim/lua/plugins/neogen.lua b/config/nvim/lua/plugins/neogen.lua new file mode 100644 index 0000000..46d3b75 --- /dev/null +++ b/config/nvim/lua/plugins/neogen.lua @@ -0,0 +1,8 @@ +-- A better annotation generator. +-- Supports multiple languages and annotation conventions. +-- https://github.com/danymat/neogen +return { + 'danymat/neogen', + version = '*', + opts = { enabled = true, snippet_engine = 'luasnip' }, +} diff --git a/config/nvim/lua/plugins/noice.lua b/config/nvim/lua/plugins/noice.lua index 713bc9a..a58ba65 100644 --- a/config/nvim/lua/plugins/noice.lua +++ b/config/nvim/lua/plugins/noice.lua @@ -1,7 +1,6 @@ -- Highly experimental plugin that completely replaces the UI -- for messages, cmdline and the popupmenu. -- https://github.com/folke/noice.nvim - return { 'folke/noice.nvim', lazy = false, @@ -44,6 +43,13 @@ return { }, opts = { skip = true }, }, + { + filter = { + event = 'notify', + find = 'No information available', + }, + opts = { skip = true }, + }, }, views = { cmdline_popup = { diff --git a/config/nvim/lua/plugins/refactoring.lua b/config/nvim/lua/plugins/refactoring.lua new file mode 100644 index 0000000..cde56ed --- /dev/null +++ b/config/nvim/lua/plugins/refactoring.lua @@ -0,0 +1,8 @@ +-- The Refactoring library based off the Refactoring book by Martin Fowler +-- https://github.com/ThePrimeagen/refactoring.nvim +return { + 'ThePrimeagen/refactoring.nvim', + version = '*', + dependencies = { 'nvim-lua/plenary.nvim', 'nvim-treesitter/nvim-treesitter' }, + opts = {}, +} diff --git a/config/nvim/lua/plugins/surround.lua b/config/nvim/lua/plugins/surround.lua new file mode 100644 index 0000000..701788e --- /dev/null +++ b/config/nvim/lua/plugins/surround.lua @@ -0,0 +1,8 @@ +-- Add/change/delete surrounding delimiter pairs with ease. +-- https://github.com/kylechui/nvim-surround +return { + 'kylechui/nvim-surround', + version = '*', + event = 'VeryLazy', + opts = {}, +} diff --git a/config/nvim/lua/plugins/telescope.lua b/config/nvim/lua/plugins/telescope.lua index 71cfa90..ae79084 100644 --- a/config/nvim/lua/plugins/telescope.lua +++ b/config/nvim/lua/plugins/telescope.lua @@ -8,53 +8,7 @@ return { { 'nvim-lua/plenary.nvim' }, { 'nvim-telescope/telescope-symbols.nvim' }, { 'folke/which-key.nvim' }, - -- Getting you where you want with the fewest keystrokes. - -- https://github.com/ThePrimeagen/harpoon - { - 'ThePrimeagen/harpoon', - branch = 'harpoon2', - dependencies = { - 'nvim-lua/plenary.nvim', - 'nvim-telescope/telescope.nvim', - }, - config = function() - local harpoon = require 'harpoon' - harpoon:setup {} - -- basic telescope configuration - local conf = require('telescope.config').values - local function toggle_telescope(harpoon_files) - local file_paths = {} - for _, item in ipairs(harpoon_files.items) do - table.insert(file_paths, item.value) - end - - require('telescope.pickers') - .new({}, { - prompt_title = 'Harpoon', - finder = require('telescope.finders').new_table { - results = file_paths, - }, - previewer = conf.file_previewer {}, - sorter = conf.generic_sorter {}, - }) - :find() - end - - vim.keymap.set( - 'n', - 'hw', - function() toggle_telescope(harpoon:list()) end, - { desc = 'Open harpoon window with telescope' } - ) - vim.keymap.set( - 'n', - 'ht', - function() harpoon.ui:toggle_quick_menu(harpoon:list()) end, - { desc = 'Open Harpoon Quick menu' } - ) - end, - }, -- A Telescope picker to quickly access configurations -- of plugins managed by lazy.nvim. -- https://github.com/polirritmico/telescope-lazy-plugins.nvim diff --git a/config/nvim/lua/plugins/todo-comments.lua b/config/nvim/lua/plugins/todo-comments.lua new file mode 100644 index 0000000..7d9efb0 --- /dev/null +++ b/config/nvim/lua/plugins/todo-comments.lua @@ -0,0 +1,8 @@ +-- Highlight, list and search todo comments in your projects +-- https://github.com/folke/todo-comments.nvim +return { + 'folke/todo-comments.nvim', + version = '*', + dependencies = { 'nvim-lua/plenary.nvim' }, + opts = {}, +} diff --git a/config/nvim/lua/plugins/treesitter.lua b/config/nvim/lua/plugins/treesitter.lua index 1fbf9b0..30a7eaa 100644 --- a/config/nvim/lua/plugins/treesitter.lua +++ b/config/nvim/lua/plugins/treesitter.lua @@ -52,8 +52,8 @@ return { incremental_selection = { enable = true, keymaps = { - init_selection = '', - node_incremental = '', + init_selection = '', + node_incremental = '', scope_incremental = '', node_decremental = '', }, diff --git a/config/nvim/lua/plugins/treesj.lua b/config/nvim/lua/plugins/treesj.lua new file mode 100644 index 0000000..0a7b802 --- /dev/null +++ b/config/nvim/lua/plugins/treesj.lua @@ -0,0 +1,9 @@ +-- Neovim plugin for splitting/joining blocks of code +-- https://github.com/Wansmer/treesj +return { + 'Wansmer/treesj', + dependencies = { 'nvim-treesitter/nvim-treesitter' }, + opts = { + use_default_keymaps = false, + }, +} diff --git a/config/nvim/lua/plugins/trouble.lua b/config/nvim/lua/plugins/trouble.lua index 5dcedeb..2bd73cc 100644 --- a/config/nvim/lua/plugins/trouble.lua +++ b/config/nvim/lua/plugins/trouble.lua @@ -7,7 +7,7 @@ return { lazy = false, dependencies = { 'nvim-tree/nvim-web-devicons' }, opts = { - auto_preview = false, + auto_preview = true, auto_fold = true, auto_close = true, use_lsp_diagnostic_signs = true, diff --git a/config/nvim/lua/plugins/ufo.lua b/config/nvim/lua/plugins/ufo.lua new file mode 100644 index 0000000..a6480e7 --- /dev/null +++ b/config/nvim/lua/plugins/ufo.lua @@ -0,0 +1,116 @@ +-- Not UFO in the sky, but an ultra fold in Neovim. +-- https://github.com/kevinhwang91/nvim-ufo/ +return { + 'kevinhwang91/nvim-ufo', + version = '*', + dependencies = { + { 'neovim/nvim-lspconfig' }, + { 'kevinhwang91/promise-async' }, + { 'nvim-treesitter/nvim-treesitter' }, + { + -- Status column plugin that provides a configurable + -- 'statuscolumn' and click handlers. + -- https://github.com/luukvbaal/statuscol.nvim + 'luukvbaal/statuscol.nvim', + config = function() + local builtin = require 'statuscol.builtin' + require('statuscol').setup { + relculright = true, + segments = { + { + text = { builtin.foldfunc }, + click = 'v:lua.ScFa', + }, + { + sign = { + namespace = { 'diagnostic/signs' }, + maxwidth = 2, + -- auto = true, + }, + click = 'v:lua.ScSa', + }, + { + text = { builtin.lnumfunc, ' ' }, + click = 'v:lua.ScLa', + }, + }, + } + end, + }, + }, + config = function() + local capabilities = vim.lsp.protocol.make_client_capabilities() + capabilities.textDocument.foldingRange = { + dynamicRegistration = false, + lineFoldingOnly = true, + } + local language_servers = require('lspconfig').util.available_servers() -- or list servers manually like {'gopls', 'clangd'} + for _, ls in ipairs(language_servers) do + require('lspconfig')[ls].setup { + capabilities = capabilities, + -- you can add other fields for setting up lsp server in this table + } + end + + require('ufo').setup { + open_fold_hl_timeout = 150, + close_fold_kinds_for_ft = { 'imports', 'comment' }, + preview = { + win_config = { + border = { '', '─', '', '', '', '─', '', '' }, + winhighlight = 'Normal:Folded', + winblend = 0, + }, + mappings = { + scrollU = '', + scrollD = '', + jumpTop = '[', + jumpBot = ']', + }, + }, + + provider_selector = function(_, _, _) -- bufnr, filetype, buftype + return { 'treesitter', 'indent' } + end, + + -- fold_virt_text_handler + -- + -- This handler is called when the fold text is too long to fit in the window. + -- It is expected to truncate the text and return a new list of virtual text. + -- + ---@param virtText table The current virtual text list. + ---@param lnum number The line number of the first line in the fold. + ---@param endLnum number The line number of the last line in the fold. + ---@param width number The width of the window. + ---@param truncate function Truncate function + ---@return table + fold_virt_text_handler = function(virtText, lnum, endLnum, width, truncate) + local newVirtText = {} + local suffix = (' 󰁂 %d '):format(endLnum - lnum) + local sufWidth = vim.fn.strdisplaywidth(suffix) + local targetWidth = width - sufWidth + local curWidth = 0 + for _, chunk in ipairs(virtText) do + local chunkText = chunk[1] + local chunkWidth = vim.fn.strdisplaywidth(chunkText) + if targetWidth > curWidth + chunkWidth then + table.insert(newVirtText, chunk) + else + chunkText = truncate(chunkText, targetWidth - curWidth) + local hlGroup = chunk[2] + table.insert(newVirtText, { chunkText, hlGroup }) + chunkWidth = vim.fn.strdisplaywidth(chunkText) + -- str width returned from truncate() may less than 2nd argument, need padding + if curWidth + chunkWidth < targetWidth then + suffix = suffix .. (' '):rep(targetWidth - curWidth - chunkWidth) + end + break + end + curWidth = curWidth + chunkWidth + end + table.insert(newVirtText, { suffix, 'MoreMsg' }) + return newVirtText + end, + } + end, +} diff --git a/config/nvim/lua/plugins/ui.lua b/config/nvim/lua/plugins/ui.lua index 8b719cc..70d94a3 100644 --- a/config/nvim/lua/plugins/ui.lua +++ b/config/nvim/lua/plugins/ui.lua @@ -27,6 +27,10 @@ return { }, }, + -- Extensible Neovim Scrollbar + -- https://github.com/petertriho/nvim-scrollbar + { 'petertriho/nvim-scrollbar', opts = {} }, + -- vim dashboard -- https://github.com/nvimdev/dashboard-nvim { diff --git a/config/nvim/lua/plugins/vim-sleuth.lua b/config/nvim/lua/plugins/vim-sleuth.lua new file mode 100644 index 0000000..a6ff93b --- /dev/null +++ b/config/nvim/lua/plugins/vim-sleuth.lua @@ -0,0 +1,3 @@ +-- Detect tabstop and shiftwidth automatically +-- https://github.com/tpope/vim-sleuth +return { 'tpope/vim-sleuth' } diff --git a/config/nvim/lua/plugins/wakatime.lua b/config/nvim/lua/plugins/wakatime.lua new file mode 100644 index 0000000..bac0efd --- /dev/null +++ b/config/nvim/lua/plugins/wakatime.lua @@ -0,0 +1,4 @@ +-- Vim plugin for automatic time tracking and metrics +-- generated from your programming activity. +-- https://github.com/wakatime/vim-wakatime +return { 'wakatime/vim-wakatime', lazy = false, enabled = true } diff --git a/config/nvim/lua/plugins/which-key.lua b/config/nvim/lua/plugins/which-key.lua index 15b05eb..377fb05 100644 --- a/config/nvim/lua/plugins/which-key.lua +++ b/config/nvim/lua/plugins/which-key.lua @@ -22,10 +22,8 @@ return { { 'b', group = '[b] Buffer', - expand = function() - -- Add the current buffers to the menu - return require('which-key.extras').expand.buf() - end, + -- Add the current buffers to the menu + expand = function() return require('which-key.extras').expand.buf() end, }, { { 'bk', 'blast', desc = 'Buffer: Last' }, @@ -38,56 +36,23 @@ return { -- ── Code ──────────────────────────────────────────────────────────── { 'c', group = '[c] Code' }, - { - { - 'ca', - 'lua vim.lsp.buf.code_action()', - desc = 'LSP: Code Action', - }, - { - 'cg', - 'lua require("neogen").generate()', - desc = 'Generate annotations', - }, - }, + { 'ca', 'lua vim.lsp.buf.code_action()', desc = 'LSP: Code Action' }, + { 'cg', 'lua require("neogen").generate()', desc = 'Generate annotations' }, + + -- Code: treesj + { 'cc', group = 'Code Split/Join' }, + -- see: lua/plugins/treesj.lua + { 'cct', 'TSJToggle', desc = 'Split/Join: Toggle' }, + { 'ccs', 'TSJSplit', desc = 'Split/Join: Split' }, + { 'ccj', 'TSJJoin', desc = 'Split/Join: Join' }, + -- ── Code: CommentBox ──────────────────────────────────────────────── - { - { 'cb', group = 'CommentBox' }, - { 'cbb', 'CBccbox', desc = 'CommentBox: Box Title' }, - { 'cbd', 'CBd', desc = 'CommentBox: Remove a box' }, - { 'cbl', 'CBline', desc = 'CommentBox: Simple Line' }, - { 'cbm', 'CBllbox14', desc = 'CommentBox: Marked' }, - { - 'cbt', - 'CBllline', - desc = 'CommentBox: Titled Line', - }, - }, - -- ── Code: package.json control ────────────────────────────────────── - -- See: lua/plugins/lazy.lua - { 'cn', group = 'package.json control' }, - { - { - 'cnd', - 'lua require("package-info").delete()', - desc = 'Delete package', - }, - { - 'cni', - 'lua require("package-info").install()', - desc = 'Install package', - }, - { - 'cns', - 'lua require("package-info").show({ force = true })', - desc = 'Show package info', - }, - { - 'cnu', - 'lua require("package-info").change_version()', - desc = 'Change version', - }, - }, + { 'cb', group = 'CommentBox' }, + { 'cbb', 'CBccbox', desc = 'CommentBox: Box Title' }, + { 'cbd', 'CBd', desc = 'CommentBox: Remove a box' }, + { 'cbl', 'CBline', desc = 'CommentBox: Simple Line' }, + { 'cbm', 'CBllbox14', desc = 'CommentBox: Marked' }, + { 'cbt', 'CBllline', desc = 'CommentBox: Titled Line' }, -- ── Code: Refactoring ─────────────────────────────────────────────── { 'cx', group = '[x] Refactoring' }, @@ -410,36 +375,7 @@ return { }, -- ── Misc ──────────────────────────────────────────────────────────── - { - '1', - 'lua require("harpoon"):list():select(1)', - desc = 'harpoon to file 1', - }, - { - '2', - 'lua require("harpoon"):list():select(2)', - desc = 'harpoon to file 2', - }, - { - '3', - 'lua require("harpoon"):list():select(3)', - desc = 'harpoon to file 3', - }, - { - '4', - 'lua require("harpoon"):list():select(4)', - desc = 'harpoon to file 4', - }, - { - '5', - 'lua require("harpoon"):list():select(5)', - desc = 'harpoon to file 5', - }, - { - 'D', - 'lua vim.lsp.buf.type_definition()', - desc = 'LSP: Type Definition', - }, + { 'D', 'lua vim.lsp.buf.type_definition()', desc = 'LSP: Type Definition' }, { 'e', 'Neotree reveal', desc = 'NeoTree reveal' }, -- ╭─────────────────────────────────────────────────────────╮ diff --git a/config/nvim/snippets/javascript.json b/config/nvim/snippets/javascript.json new file mode 100644 index 0000000..c67efaf --- /dev/null +++ b/config/nvim/snippets/javascript.json @@ -0,0 +1,462 @@ +{ + "While ..": { + "body": [ + "while (${1:condition}) {", + "\t$0", + "}" + ], + "prefix": "while .." + }, + "argv (node)": { + "body": "const argv = process.argv.slice(2);", + "description": "Arguments from the command line. [0] is the node executable path, [1] the path of the file being executed, making [2] the first positional argument.", + "prefix": "argv (node)" + }, + "cast (JSDoc)": { + "body": "/** @type {${1:string}} */ (${2:bracketedVar})", + "prefix": "cast (JSDoc)" + }, + "class (JSDoc) + typedef (JSDoc)": { + "body": [ + "/** @typedef {Object} ${1:name}", + " * @property {${2:string}} ${3:prop1}", + " */" + ], + "description": "https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html#typedef-callback-and-param", + "prefix": [ + "class (JSDoc)", + "typedef (JSDoc)" + ] + }, + "do .. while ..": { + "body": [ + "do {", + "\t$0", + "} while (${1:condition});" + ], + "prefix": [ + "do .. while", + "repeat until" + ] + }, + "ec (export const)": { + "body": "export const ${1:CONSTANT}", + "prefix": "ec (export const)" + }, + "ef (export function)": { + "body": [ + "export function ${1:name}($2) {", + "\t$0", + "}" + ], + "prefix": "ef (export function)" + }, + "filter ( => )": { + "body": "filter(${1:item} => ${1:item}$0)", + "prefix": "filter ( => )" + }, + "for (i++)": { + "body": [ + "for (let i = 0; i < ${1:array}.length; i++) {", + "\tconst ${2:element} = ${1:array}[i];", + "\t$0", + "}" + ], + "prefix": "for (i++)" + }, + "for (i--)": { + "body": [ + "for (let i = ${1:array}.length - 1; i >= 0; i--) {", + "\tconst ${2:element} = ${1:array}[i];", + "\t$0", + "}" + ], + "prefix": "for (i--)" + }, + "for (key, value)": { + "body": [ + "for (const [key, value] of Object.entries(${1:dict})) {", + "\t$0", + "}" + ], + "prefix": "for (key, value)" + }, + "for .. in (key)": { + "body": [ + "for (const ${1:key} in ${2:object}) {", + "\t$0", + "}" + ], + "prefix": "for .. in (key)" + }, + "for .. of (array)": { + "body": [ + "for (const ${1:iterator} of ${2:array}) {", + "\t$0", + "}" + ], + "prefix": "for .. of (array)" + }, + "forEach": { + "body": [ + "forEach(${1:item} => {", + "\t$0", + "});" + ], + "prefix": "forEach =>" + }, + "function_trad": { + "body": [ + "function ${1:name}() {", + "\t$0", + "}" + ], + "prefix": "function" + }, + "if ..": { + "body": [ + "if (${1:condition}) {", + "\t$0", + "}" + ], + "prefix": "if" + }, + "if .. else": { + "body": [ + "if (${1:condition}) {", + "\t$0", + "} else {", + "\t", + "}" + ], + "prefix": "if .. else" + }, + "ignore (biome formatter)": { + "body": "// biome-ignore format: ${1:explanation}", + "description": "Ignores the next block of code.", + "prefix": "ignore (biome formatter)" + }, + "ignore file (TypeScript) + nocheck (TypeScript)": { + "body": "// @ts-nocheck", + "prefix": [ + "ignore file (TypeScript)", + "nocheck (TypeScript)" + ] + }, + "map ( () => {} )": { + "body": [ + "map(${1:item} => {", + "\t$0", + "\treturn;", + "})" + ], + "prefix": "map ( () => {} )" + }, + "map ( => )": { + "body": "map(${1:item} => ${1:item}$0)", + "prefix": "map ( => )" + }, + "reduce()": { + "body": [ + ".reduce((acc, ${1:item}) => {", + "\t$0", + "\treturn acc;", + "}, ${2:initialValue})" + ], + "prefix": "reduce()" + }, + "relative date": { + "body": [ + "/**", + " * @param {string} absoluteDate string to be converted to a date", + " * @return {string} relative date", + " */", + "function relativeDate(absoluteDate) {", + "\tconst deltaSecs = (+new Date() - +new Date(absoluteDate)) / 1000;", + "\t/** @type {\"year\"|\"month\"|\"week\"|\"day\"|\"hour\"|\"minute\"|\"second\"} */", + "\tlet unit;", + "\tlet delta;", + "\tif (deltaSecs < 60) {", + "\t\tunit = \"second\";", + "\t\tdelta = deltaSecs;", + "\t} else if (deltaSecs < 60 * 60) {", + "\t\tunit = \"minute\";", + "\t\tdelta = Math.ceil(deltaSecs / 60);", + "\t} else if (deltaSecs < 60 * 60 * 24) {", + "\t\tunit = \"hour\";", + "\t\tdelta = Math.ceil(deltaSecs / 60 / 60);", + "\t} else if (deltaSecs < 60 * 60 * 24 * 7) {", + "\t\tunit = \"day\";", + "\t\tdelta = Math.ceil(deltaSecs / 60 / 60 / 24);", + "\t} else if (deltaSecs < 60 * 60 * 24 * 7 * 4) {", + "\t\tunit = \"week\";", + "\t\tdelta = Math.ceil(deltaSecs / 60 / 60 / 24 / 7);", + "\t} else if (deltaSecs < 60 * 60 * 24 * 7 * 4 * 12) {", + "\t\tunit = \"month\";", + "\t\tdelta = Math.ceil(deltaSecs / 60 / 60 / 24 / 7 / 4);", + "\t} else {", + "\t\tunit = \"year\";", + "\t\tdelta = Math.ceil(deltaSecs / 60 / 60 / 24 / 7 / 4 / 12);", + "\t}", + "\tconst formatter = new Intl.RelativeTimeFormat(\"en\", { style: \"long\", numeric: \"auto\" });", + "\treturn formatter.format(-delta, unit);", + "}" + ], + "prefix": "relative date" + }, + "replace": { + "body": "replace(/${1:regexp}/, \"$2\")", + "prefix": "replace" + }, + "sort ( () => {} )": { + "body": [ + "sort((a, b) => {", + "\treturn ${1:b - a};", + "})" + ], + "description": "Sort Array with basic a-b-comparator function", + "prefix": "sort ( () => {} )" + }, + "split by \\n": { + "body": ".split(\"\\n\")", + "prefix": ".split by \\n" + }, + "split by \\r": { + "body": ".split(\"\\r\")", + "description": "required for output from app.doShellScript()", + "prefix": ".split by \\r" + }, + "switch .. case": { + "body": [ + "switch (${1:key}) {", + "\tcase ${2:value}:", + "\t\t$0", + "\t\tbreak;", + "\tdefault:", + "}" + ], + "prefix": "switch .. case" + }, + "ternary": { + "body": "${1:condition} ? ${2:value1} : ${3:value2}", + "prefix": "ternary" + }, + "thousand separator": { + "body": ".toLocaleString(\"de-DE\")", + "description": "insert thousand separator into a digit string", + "prefix": "thousand separator" + }, + "timeout + delay": { + "body": [ + "setTimeout(() => {", + "\t$0", + "}, ${1:timeoutMs});" + ], + "prefix": [ + "timeout", + "delay" + ] + }, + "today as ISO 8601 string": { + "body": "new Date().toISOString().slice(0, 10);", + "prefix": "ISO date" + }, + "today's date": { + "body": "const today = new Date();", + "prefix": [ + "today", + "date" + ] + }, + "tomorrow's date": { + "body": [ + "const tomorrow = new Date();", + "tomorrow.setDate(tomorrow.getDate() + 1);" + ], + "prefix": [ + "tomorrow", + "date" + ] + }, + "try .. catch": { + "body": [ + "try {", + "\t$0", + "} catch (_error) {", + "\t", + "}" + ], + "description": "leading underscore so the variable is ignored by biome when not used.", + "prefix": "try .. catch" + }, + "type (JSDoc)": { + "body": "/** @type {${1:string}} */", + "prefix": "type (JSDoc)" + }, + "type: Record (JSDoc)": { + "body": "/** @type {Record} */", + "prefix": "type: Record (JSDoc)" + }, + "unique items": { + "body": "${1:arr} = [...new Set(${2:arr})];", + "prefix": "unique items" + }, + "Class": { + "prefix": [ + "clax" + ], + "body": [ + "export class $1 ${2:extends ${3:Parent} }{", + "\tconstructor(${4:props}) {", + "\t\tthis.$4 = $4;", + "\t}", + "", + "\t$0", + "}" + ], + "description": "Class definition template." + }, + "test": { + "prefix": [ + "it" + ], + "body": [ + "it('${1:should ${2}}', async () => {", + "\t$0", + "});" + ], + "description": "Test template" + }, + "method": { + "prefix": [ + "mtd" + ], + "body": [ + "${1:async ${2:method}}(${3:params}) {", + "\t$0", + "}" + ], + "description": "method" + }, + "function": { + "prefix": [ + "fun" + ], + "body": [ + "${1:async }${2:(${3:params})} => {$0}" + ], + "description": "function" + }, + "const": { + "prefix": [ + "const" + ], + "body": [ + "const $1 = $0;" + ], + "description": "const" + }, + "let": { + "prefix": [ + "let" + ], + "body": [ + "let $1 = $0;" + ], + "description": "let" + }, + "Console log": { + "prefix": [ + "cl" + ], + "body": [ + "console.log($0);" + ], + "description": "Console log" + }, + "Console debug": { + "prefix": [ + "cd" + ], + "body": [ + "console.debug($0);" + ], + "description": "Console debug" + }, + "Console log all": { + "prefix": [ + "clj" + ], + "body": [ + "console.log(JSON.stringify($0, null, 2));" + ], + "description": "Console log whole object" + }, + "Console debug all": { + "prefix": [ + "cdj" + ], + "body": [ + "console.debug(JSON.stringify($0, null, 2));" + ], + "description": "Console debug whole object" + }, + "If": { + "prefix": [ + "if" + ], + "body": [ + "if (${1:condition}) {", + "\t$0", + "}" + ], + "description": "Console debug whole object" + }, + "If-else": { + "prefix": [ + "ifelse" + ], + "body": [ + "if (${1:condition}) {", + "\t$2", + "} else {", + "\t$0", + "}" + ], + "description": "Console debug whole object" + }, + "docblock": { + "prefix": [ + "/**" + ], + "body": [ + "/**", + " * $0", + " */" + ] + }, + "trycatch": { + "prefix": [ + "tc" + ], + "body": [ + "try {", + "\t$0", + "} catch (e) {", + "\tthrow e;", + "}" + ], + "description": "Try catch block" + }, + "Describe test": { + "prefix": [ + "desc" + ], + "body": [ + "describe('${1}', () => {", + "\t$0", + "})" + ], + "description": "Describe test" + } +} diff --git a/config/nvim/snippets/lua.json b/config/nvim/snippets/lua.json new file mode 100644 index 0000000..2a95e6a --- /dev/null +++ b/config/nvim/snippets/lua.json @@ -0,0 +1,262 @@ +{ + "@class (LuaDoc)": { + "body": [ + "---@class (exact) ${1:class_name}", + "---@field ${2:field_name} string" + ], + "description": "https://github.com/LuaLS/lua-language-server/wiki/Annotations#class", + "prefix": "@class (LuaDoc)" + }, + "@type (LuaDoc)": { + "body": "---@type ${1:string}", + "prefix": "@type (LuaDoc)" + }, + "Record (type)": { + "body": "---@type table", + "prefix": "Record (type)" + }, + "count occurrences in string": { + "body": "local _, count = ${1:str}:gsub(\"${2:find}\", \"\")", + "prefix": "count occurrences in string" + }, + "export module": { + "body": [ + "local M = {}", + "--------------------------------------------------------------------------------", + "", + "$0--------------------------------------------------------------------------------", + "return M" + ], + "prefix": "export module" + }, + "find all in string": { + "body": [ + "local ${1:matches} = {}", + "for match in ${2:str}:gmatch(${3:pattern}) do", + "\ttable.insert(${1:matches}, match)", + "end" + ], + "prefix": "find all in string" + }, + "for each (list)": { + "body": [ + "for _, ${1:v} in pairs(${2:table}) do", + "\t$0", + "end" + ], + "prefix": "for each (list)" + }, + "for each line (of file)": { + "body": [ + "for line in io.lines(${1:filepath}) do", + "\t$0", + "end" + ], + "prefix": [ + "for each line (file)", + "read file (as lines)" + ] + }, + "home": { + "body": "os.getenv(\"HOME\")", + "prefix": "home" + }, + "if .. then .. else": { + "body": [ + "if ${1:true} then", + "\t$2", + "else", + "\t$0", + "end" + ], + "filetype": "lua", + "prefix": "if .. then .. else" + }, + "nodiscard": { + "body": "---@nodiscard", + "description": "Luadoc Annotation that a function's return value should not be discarded. https://github.com/LuaLS/lua-language-server/wiki/Annotations#nodiscard", + "prefix": "nodiscard" + }, + "path of this file": { + "body": "local pathOfThisFile = debug.getinfo(1).source:sub(2)", + "prefix": "path of this file" + }, + "path separator (os-independent)": { + "body": "local osPathSep = package.config:sub(1, 1)", + "prefix": "path separator (os-independent)" + }, + "pcall": { + "body": [ + "local success = pcall(${1:func})", + "if not success then", + "\t$0", + "\treturn", + "end" + ], + "prefix": [ + "try", + "pcall" + ] + }, + "read file": { + "body": [ + "---@param filePath string", + "---@return string? -- content or error message", + "---@return boolean success", + "local function readFile(filePath)", + "\tlocal file, err = io.open(filePath, \"r\")", + "\tif not file then return err, false end", + "\tlocal content = file:read(\"*a\")", + "\tfile:close()", + "\treturn content, true", + "end" + ], + "prefix": "read file" + }, + "redirect (metatable __index)": { + "body": [ + "setmetatable(M, {", + "\t__index = function(_, key)", + "\t\treturn function(...)", + "\t\t\trequire(${1:moduleToRedirectTo})[key](...)", + "\t\tend", + "\tend,", + "})" + ], + "prefix": "redirect (metatable __index)" + }, + "round number": { + "body": "local roundedNum = tonumber(string.format(\"%.${1:decimals}f\", exactNum))", + "prefix": "round number" + }, + "safe require": { + "body": [ + "local ok, ${1:module} = require(\"${1:module}\")", + "if not (ok and ${1:module}) then return end", + "${1:module}.$0" + ], + "prefix": "safe require" + }, + "sort (table)": { + "body": "table.sort(${1:table}, function(a, b) return ${2:a} > ${3:b} end)", + "prefix": "sort (table)" + }, + "split (gmatch)": { + "body": [ + "local acc = {}", + "for part in ${1:str}:gmatch(\"(.-)\" .. ${2:delimiter}) do", + "\ttable.insert(acc, part)", + "end" + ], + "filetype": "lua", + "prefix": "split (gmatch)" + }, + "ternary": { + "body": "${1:condition} and ${2:value1} or ${3:value2}", + "prefix": "ternary" + }, + "trim trailing line break": { + "body": ":gsub(\"\\n$\", \"\")", + "prefix": "trim" + }, + "write file": { + "body": [ + "---@param str string", + "---@param filePath string", + "---@return string|nil -- error message", + "local function overwriteFile(filePath, str)", + "\tlocal file, _ = io.open(filePath, \"w\")", + "\tif not file then return end", + "\tfile:write(str)", + "\tfile:close()", + "end" + ], + "description": "Overwriting file, for appending use `a` instead of `w`.", + "prefix": "write file" + }, + "Create Auto Command": { + "prefix": "autocmd", + "body": [ + "vim.api.nvim_create_autocmd(\"${1:event}\", {", + " group = vim.api.nvim_create_augroup(\"${2:group}\", { clear = true }),", + " callback = function(ev)", + " ${0}", + " end", + "})" + ] + }, + "Create Auto Command Group": { + "prefix": "augroup", + "body": [ + "vim.api.nvim_create_augroup(\"${1:group}\", { clear = true })$0" + ] + }, + "Current Win": { + "prefix": "win", + "body": "local win = vim.api.nvim_get_current_win()\n$0" + }, + "Current Buf": { + "prefix": "buf", + "body": "local buf = vim.api.nvim_get_current_buf()\n$0" + }, + "Buf Valid": { + "prefix": "bufvalid", + "body": "vim.api.nvim_buf_is_valid(${1:buf})" + }, + "Win Valid": { + "prefix": "winvalid", + "body": "vim.api.nvim_win_is_valid(${1:win})" + }, + "Win Call": { + "prefix": "wincall", + "body": [ + "vim.api.nvim_win_call(${1:win}, function(win)", + " ${0}", + "end)" + ] + }, + "Buf Call": { + "prefix": "bufcall", + "body": [ + "vim.api.nvim_buf_call(${1:buf}, function(buf)", + " ${0}", + "end)" + ] + }, + "Schedule": { + "prefix": "schedule", + "body": [ + "vim.schedule(function()", + " ${0}", + "end)" + ] + }, + "Table Deep Extend": { + "prefix": "deepextend", + "body": "vim.tbl_deep_extend(\"force\", ${1:table}, ${2:table})$0" + }, + "Table Filter": { + "prefix": "filter", + "body": [ + "vim.tbl_filter(function()", + " $0", + "end, ${1:table})" + ] + }, + "Table Map": { + "prefix": "map", + "body": [ + "vim.tbl_map(function()", + " $0", + "end, ${1:table})" + ] + }, + "Table Values": { + "prefix": "values", + "body": "vim.tbl_values(${1:table})" + }, + "Table Keys": { + "prefix": "keys", + "body": "vim.tbl_keys(${1:table})" + } +} diff --git a/config/nvim/snippets/markdown.json b/config/nvim/snippets/markdown.json new file mode 100644 index 0000000..7f35ef3 --- /dev/null +++ b/config/nvim/snippets/markdown.json @@ -0,0 +1,133 @@ +{ + "Misc": { + "body": "Miscellaneous", + "prefix": "Misc" + }, + "bash (Codeblock)": { + "body": [ + "```bash", + "$CLIPBOARD$0", + "```" + ], + "prefix": "bash (Codeblock)" + }, + "caution (callout)": { + "body": [ + "> [!CAUTION]", + "> $0" + ], + "description": "https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#alerts", + "prefix": "caution (callout)" + }, + "details & summary": { + "body": [ + "
", + "${1:Text}", + "$0", + "
" + ], + "description": "https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details", + "prefix": [ + "toggle / fold", + "details & summary" + ] + }, + "ignore file (ltex)": { + "body": "", + "prefix": "ignore file (ltex)" + }, + "image": { + "body": "\"${2:alt", + "description": "HTML syntax for images used to display images with reduced size", + "prefix": "image" + }, + "important (callout)": { + "body": [ + "> [!IMPORTANT]", + "> $0" + ], + "description": "https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#alerts", + "prefix": "important (callout)" + }, + "insert table 2x2": { + "body": [ + "| ${1:Column1} | ${2:Column2} |", + "|--------------- | -------------- |", + "| ${3:Item1.1} | ${4:Item2.1} |" + ], + "prefix": "table (2x2)" + }, + "insert toc": { + "body": [ + "## Table of Content", + "", + "" + ], + "description": "https://github.com/jonschlinkert/markdown-toc#tocinsert", + "prefix": "insert toc" + }, + "js (Codeblock)": { + "body": [ + "```js", + "$CLIPBOARD$0", + "```" + ], + "prefix": "js (Codeblock)" + }, + "kbd": { + "body": "$0", + "description": "HTML tag for keys", + "prefix": "kbd" + }, + "lua (Codeblock)": { + "body": [ + "```lua", + "$CLIPBOARD$0", + "```" + ], + "prefix": "lua (Codeblock)" + }, + "note (GitHub callout)": { + "body": [ + "> [!NOTE]", + "> $0" + ], + "description": "https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#alerts", + "prefix": [ + "info (callout)", + "note (callout)" + ] + }, + "py (Codeblock)": { + "body": [ + "```py", + "$CLIPBOARD$0", + "```" + ], + "prefix": "py (Codeblock)" + }, + "tip (callout)": { + "body": [ + "> [!TIP]", + "> $0" + ], + "description": "https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#alerts", + "prefix": "tip (callout)" + }, + "ts (Codeblock)": { + "body": [ + "```ts", + "$CLIPBOARD$0", + "```" + ], + "prefix": "ts (Codeblock)" + }, + "warning (callout)": { + "body": [ + "> [!WARNING]", + "> $0" + ], + "description": "https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#alerts", + "prefix": "warning (callout)" + } +} diff --git a/config/nvim/snippets/php.snippets b/config/nvim/snippets/php.snippets new file mode 100644 index 0000000..b7afa63 --- /dev/null +++ b/config/nvim/snippets/php.snippets @@ -0,0 +1,165 @@ +snippet php "php" + + +snippet . "$this->" i + $this-> + +# If statement + +snippet if "if" + if (${1}) { + ${2} + } + +snippet ife "ife" + if (${1}) { + ${2} + } else { + ${3} + } + +snippet elif "elif" + else if (${1}) { + ${2} + } + +snippet el "el" + else { + ${1} + } + +# Switch + +snippet sw "sw" + switch (${1}) { + default: + break; + } + +snippet case "case" + case '${1}': + ${2} + break;${3} + +# Do-while loop + +snippet do "do" + do { + ${2} + } while (${1}); + +# While loop + +snippet wh "wh" + while (${1}) { + ${2} + } + +# For loop + +snippet for "for" + for (${1}; ${2}; ${3}) { + ${4} + } + +snippet fore "fore" + foreach (${1} as ${2}) { + ${3} + } + +# Functions and methods + +snippet fun "fun" + function ${1}(${2}) { + ${3} + } + +snippet met "met" + ${1}function ${2}(${3}) { + ${4} + } + +# Return + +snippet r "return" + return ${1} + +# Todos + +snippet todo "todo" + // TODO ${1} diff --git a/config/nvim/snippets/sh.json b/config/nvim/snippets/sh.json new file mode 100644 index 0000000..967a750 --- /dev/null +++ b/config/nvim/snippets/sh.json @@ -0,0 +1,334 @@ +{ + "PATH (export)": { + "body": "export PATH=/usr/local/lib:/usr/local/bin:/opt/homebrew/bin/:\\$PATH", + "description": "Extends PATH in a way that homebrew installed CLIs are recognized in ARM and Intel Macs.", + "prefix": "PATH (export)" + }, + "awk (get field)": { + "body": "awk '{ print $${1:1} }'", + "description": "Retrieve a field from the piped in string, with whitespace as the default field delimiter. `$n` means that the nth field will be used.", + "prefix": "awk (field)" + }, + "check device name": { + "body": "scutil --get ComputerName | grep -q \"$0\"", + "prefix": "device name" + }, + "check if dark mode (macOS)": { + "body": "defaults read -g AppleInterfaceStyle &>/dev/null; && echo 'isDark'", + "prefix": "check if dark mode (macOS)" + }, + "check if in git repo": { + "body": "if ! git rev-parse --is-inside-work-tree &>/dev/null ; then print \"\\e[0;33mfile is not ins a git repository.\\e[0m\" && return 1 ; fi", + "prefix": "check if in git repo" + }, + "check if installed": { + "body": [ + "if [[ ! -x \"\\$(command -v ${1:cli})\" ]]; then print \"\\e[0;33m${1:cli} not installed.\\e[0m\" && return 1; fi", + "$0" + ], + "description": "https://stackoverflow.com/a/26759734/22114136", + "prefix": "check if installed" + }, + "check if on macOS": { + "body": "[[ \"\\$OSTYPE\" =~ \"darwin\" ]]", + "prefix": "check if on macOS" + }, + "check if process is running": { + "body": "pgrep -xq \"${1:process}\" && $0", + "prefix": "check if process is running" + }, + "check if sudo user": { + "body": "sudo -nv && ${1:some_sudo_action}", + "prefix": "check if sudo user" + }, + "confirmation prompt": { + "body": [ + "# confirmation prompt", + "print \"\\e[1;34m$0Proceed? (y/n)\\e[0m\"", + "read -rk pressed", + "echo", + "if [[ \"\\$pressed\" != \"y\" ]]; then", + "\techo \"Aborted.\"", + "\treturn 1", + "fi", + "echo" + ], + "prefix": "confirmation prompt" + }, + "default value": { + "body": "\\${${1:var}:-${2:default_value}}", + "prefix": "default value" + }, + "directory of script": { + "body": "\"$(dirname \"$(readlink -f \"\\$0\")\")\"", + "prefix": "directory of this script" + }, + "elseif": { + "body": "elif [[ ${1:condition} ]]; then\n\t${0}", + "description": "Add an elseif to an if statement.", + "prefix": "elseif" + }, + "extension": { + "body": "ext=${${1:file_name}##*.}", + "prefix": "get extension" + }, + "filename": { + "body": "file_name=$(basename \"$${1:file_path}\")", + "prefix": "filename" + }, + "filename w/o ext": { + "body": "${1:file_name}=${${1:file_name}%.*}", + "prefix": "filename w/o ext" + }, + "find & xargs": { + "body": "find . -print0 | xargs -0 -I '{}'", + "prefix": "find & xargs" + }, + "find -exec": { + "body": "find . $0 -exec open '{}' \\;", + "prefix": "find -exec" + }, + "for each file": { + "body": [ + "for filename in *.txt; do", + "\techo \"\\$filename\"", + "done" + ], + "prefix": "for each file" + }, + "for each line (read)": { + "body": [ + "while read -r line; do", + "\techo \"\\$line\"$0", + "done < \"\\$${1:input_file}\"" + ], + "prefix": "for each line (read)" + }, + "for each line (variable)": { + "body": [ + "echo \"\\$lines\" | while read -r line; do", + "\techo \"\\$line\"", + "done" + ], + "prefix": "for each line (variable)" + }, + "for i ..": { + "body": [ + "for ((i = 0; i <= ${1:length}; i++)); do", + " echo \\$i$0", + "done" + ], + "prefix": "for i .." + }, + "function": { + "body": "function ${1:name} {\n\t${0}\n}", + "prefix": "function" + }, + "get nth line from string": { + "body": "line=$(echo \"\\$${1:str}\" | sed -n \"${2:n}p\")", + "prefix": "get nth line from string" + }, + "i++": { + "body": "((${1:i}++))", + "prefix": "i++" + }, + "i--": { + "body": "((${1:i}--))", + "prefix": "i--" + }, + "if (short)": { + "body": "[[ \"\\$${1:var}\" ]] && $0", + "prefix": "if (short)" + }, + "if .. then": { + "body": [ + "if [[ \"\\$${1:var}\" ]]; then", + "\t$0", + "fi" + ], + "prefix": "if .. then" + }, + "if .. then .. else": { + "body": [ + "if [[ \"$${1:cond}\" ]]; then", + "\t$0", + "else", + "\t", + "fi" + ], + "prefix": "if .. then .. else" + }, + "input (stdin or $1)": { + "body": [ + "if [[ $# -eq 0 ]]; then", + "\tinput=$(< /dev/stdin)", + "else", + "\tinput=\"$1\"", + "fi" + ], + "description": "reads either from STDIN or $1. stdin may have unescaped newlines, which have to be removed, e.g. via `tr -d '\n'`.", + "prefix": "input (stdin or $1)" + }, + "notify (msg)": { + "body": "osascript -e 'display notification \"\" with title \"${1:msg}\"'", + "prefix": "notify (msg)" + }, + "notify (var)": { + "body": "osascript -e \"display notification \\\"\\\" with title \\\"$${1:var}\\\"\"", + "prefix": "notify (var)" + }, + "null (pipe)": { + "body": "&> /dev/null", + "prefix": "null (pipe)" + }, + "osascript jxa (run script)": { + "body": "osascript -l JavaScript \"${1:file}\"", + "prefix": [ + "jxa (run script)", + "osascript -l JavaScript" + ] + }, + "plist: extract key": { + "body": "plutil -extract name.childkey xml1 -o - example.plist | sed -n 4p | cut -d'>' -f2 | cut -d'<' -f1", + "prefix": "plist: extract key" + }, + "print in blue": { + "body": "print \"\\e[1;34m$0\\e[0m\"", + "prefix": "print in blue" + }, + "progress bar": { + "body": [ + "for _ in {1..100}; do", + "\tprintf \"🬋\"", + "\tsleep 0.5", + "done" + ], + "prefix": "progress bar" + }, + "quicklook": { + "body": "qlmanage -p \"${1:filepath}\"", + "description": "QuickLook the file. MacOS only.", + "prefix": "quicklook" + }, + "redirect to stderr": { + "body": ">&2", + "prefix": "redirect to stderr" + }, + "resolve home": { + "body": "${1:path}=\"\\${${1:path}/#\\~/\\$HOME}\"", + "prefix": "resolve home" + }, + "restart app": { + "body": [ + "killall \"${1:app_name}\"", + "while pgrep -xq \"${1:app_name}\"; do sleep 0.1; done", + "open -a \"${1:app_name}\"" + ], + "description": "safely restart app, avoiding race condition", + "prefix": "restart app" + }, + "sed substitution": { + "body": "sed 's/$0//'", + "prefix": "sed substitution" + }, + "shebang": { + "body": "#!/usr/bin/env zsh", + "prefix": "shebang" + }, + "slice": { + "body": "${1:var}=\"${${1:var}:${2:from}:${3:to}}\"", + "prefix": "slice" + }, + "spinner": { + "body": [ + "# spinner with 20s timeout", + "spinner=\"⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏\"", + "for i in {1..100}; do", + "\tpos=\\$((i % \\${#spinner}))", + "\tprintf \"\\r%s\" \"\\${spinner:\\$pos:1}\"", + "\tsleep 0.2", + "done", + "printf \"\\r\" # remove spinner" + ], + "prefix": "spinner" + }, + "stderr (merge with stdout)": { + "body": "2>&1", + "prefix": "stderr (merge with stdout)" + }, + "stdin": { + "body": "stdin=\\$(< /dev/stdin)", + "description": "$(cat) also works. See https://stackoverflow.com/questions/32363887/in-a-bash-function-how-do-i-get-stdin-into-a-variable", + "prefix": "stdin" + }, + "stdout is to a terminal": { + "body": "[[ -t true ]]", + "prefix": "stdout is to a terminal" + }, + "substitute": { + "body": "\\${${1:var}//${2:search}/${3:replace}}", + "description": "one slash for single substitution, two for global", + "prefix": "substitute (expansion)" + }, + "suppress stderr": { + "body": "2>/dev/null", + "prefix": "suppress stderr" + }, + "switch case": { + "body": [ + "case $${1:var} in", + "\"one\" | \"two\")", + "\techo \"foo\"", + "\t;;", + "\"three\")", + "\techo \"bar\"", + "\t;;", + "*)", + "\techo \"default\"", + "\t;;", + "esac" + ], + "description": "A case command first expands word, and tries to match it against each pattern in turn.", + "prefix": "switch case" + }, + "ternary": { + "body": "\\$([[ \"${1:cond}\" ]] && echo \"${2:value1}\" || echo \"${3:value2}\")", + "prefix": "ternary" + }, + "then": { + "body": "then\n\t$0\nfi", + "prefix": "then .. fi" + }, + "today (ISO date) + now": { + "body": "${1:now}=\\$(date +\"%Y-%m-%d %H:%M:%S\")", + "prefix": [ + "today (ISO date)", + "now" + ] + }, + "trim whitespace": { + "body": "${1:text}=$(echo -n \"$${1:text}\" | sed -e 's/^ *//' -e 's/ *$//')", + "prefix": "trim whitespace" + }, + "urlEncode": { + "body": "osascript -l JavaScript -e \"encodeURIComponent('${1:text}')\"", + "prefix": "urlEncode" + }, + "wait until app running": { + "body": "while ! pgrep -xq \"${1:app_name}\"; do sleep 0.1; done", + "prefix": "wait until app running" + }, + "wait until app terminated": { + "body": "while pgrep -xq \"${1:app_name}\"; do sleep 0.1; done", + "prefix": "wait until app terminated" + }, + "while": { + "body": "while [[ ${1:condition} ]]; do\n\t${0}\ndone\n", + "description": "A while loop by condition.", + "prefix": "while" + }, + "xargs (for each line)": { + "body": "xargs -I {} ${1:some_cmd} '{}'", + "prefix": "xargs (for each line)" + } +} diff --git a/config/nvim/snippets/yaml.json b/config/nvim/snippets/yaml.json new file mode 100644 index 0000000..9047907 --- /dev/null +++ b/config/nvim/snippets/yaml.json @@ -0,0 +1,7 @@ +{ + "schema (modeline)": { + "body": "# yaml-language-server: $$schema=${1:url}", + "description": "https://github.com/redhat-developer/yaml-language-server#using-inlined-schema", + "prefix": "schema (modeline)" + } +}