From 84f2be62aeb6ecb14f035aad2b71793127133216 Mon Sep 17 00:00:00 2001 From: S4NKALP Date: Fri, 12 Sep 2025 16:05:40 +0545 Subject: [PATCH] refactor: restructure init.lua to use lazy plugin manager and add lsp configurations --- README.md | 127 -- docs/img/screenshot.png | Bin 205548 -> 0 bytes docs/old_README.md | 147 --- init.lua | 19 +- lazy-lock.json | 45 + lsp/lua_ls.lua | 34 - lsp/python.lua | 17 - lsp/qml.lua | 5 - lsp/tailwindcss.lua | 8 - lsp/ts_ls.lua | 28 - lua/chadrc.lua | 8 - lua/core/autocmd.lua | 188 ++- lua/core/functions.lua | 21 +- lua/core/keys.lua | 200 ++- lua/core/lazy.lua | 37 + lua/core/lsp.lua | 135 +++ lua/core/options.lua | 133 +- lua/lib/icons.lua | 167 --- lua/lib/prompts.lua | 21 - lua/lib/util.lua | 65 - lua/plugins/ai.lua | 14 + lua/plugins/ai/avante.lua | 166 --- lua/plugins/ai/copilot.lua | 45 - lua/plugins/colorscheme.lua | 39 + lua/plugins/completion.lua | 58 + lua/plugins/editor.lua | 170 +++ lua/plugins/editor/ai.lua | 35 - lua/plugins/editor/bracketed.lua | 18 - lua/plugins/editor/pairs.lua | 18 - lua/plugins/editor/spider.lua | 10 - lua/plugins/editor/surround.lua | 25 - lua/plugins/editor/textobjects.lua | 116 -- lua/plugins/editor/treesitter.lua | 81 -- lua/plugins/files.lua | 55 + lua/plugins/format.lua | 37 + lua/plugins/git.lua | 63 + lua/plugins/lang/blink.lua | 84 -- lua/plugins/lang/conform.lua | 64 - lua/plugins/lang/lspconfig.lua | 75 -- lua/plugins/lang/lspsaga.lua | 21 - lua/plugins/lang/mason.lua | 35 - lua/plugins/lang/nvim-lint.lua | 64 - lua/plugins/languages.lua | 116 ++ lua/plugins/lazy.lua | 131 -- lua/plugins/lint.lua | 33 + lua/plugins/list.lua | 599 --------- lua/plugins/lock.json | 66 - lua/plugins/lsp.lua | 70 ++ lua/plugins/picker.lua | 362 ++++++ lua/plugins/statusline.lua | 254 ++++ lua/plugins/tools/ccc.lua | 10 - lua/plugins/tools/dap.lua | 107 -- lua/plugins/tools/dbee.lua | 19 - lua/plugins/tools/exercism.lua | 7 - lua/plugins/tools/files.lua | 39 - lua/plugins/tools/flash.lua | 57 - lua/plugins/tools/gitlinker.lua | 24 - lua/plugins/tools/navigator.lua | 8 - lua/plugins/tools/neotest.lua | 20 - lua/plugins/tools/octohub.lua | 18 - lua/plugins/tools/sniprun.lua | 27 - lua/plugins/tools/spectre.lua | 125 -- lua/plugins/tools/toggleterm.lua | 23 - lua/plugins/ui/gitsigns.lua | 63 - lua/plugins/ui/lualine.lua | 221 ---- lua/plugins/ui/snacks.lua | 334 ----- lua/plugins/ui/which-key.lua | 446 ------- lua/plugins/utility.lua | 169 +++ lua/plugins/whichkey.lua | 307 +++++ plugin/after/highlights.lua | 28 - pywal/.gitignore | 1 - pywal/LICENSE | 674 ----------- pywal/README.md | 71 -- pywal/chadwal.py | 120 -- pywal/dark.lua | 70 -- pywal/light.lua | 70 -- pywal/matugen.lua | 81 -- snippets/c.json | 360 ------ snippets/cpp.json | 219 ---- snippets/css.json | 651 ---------- snippets/django.json | 1052 ---------------- snippets/frameworks/django/filetemplates.json | 35 - snippets/frameworks/django/forms.json | 168 --- snippets/frameworks/django/imports.json | 43 - snippets/frameworks/django/models.json | 183 --- snippets/frameworks/django/views.json | 243 ---- snippets/frameworks/ejs.json | 87 -- snippets/frameworks/flutter.json | 498 -------- snippets/frameworks/jekyll.json | 526 -------- snippets/frameworks/rails.json | 294 ----- snippets/frameworks/twig.json | 536 -------- snippets/frameworks/vue/html.json | 397 ------ snippets/frameworks/vue/javascript.json | 1075 ----------------- snippets/frameworks/vue/pug.json | 352 ------ snippets/frameworks/vue/vue.json | 33 - snippets/gitcommit.json | 96 -- snippets/global.json | 44 - snippets/go.json | 286 ----- snippets/html.json | 850 ------------- snippets/htmldjango.json | 266 ---- snippets/java.json | 161 --- snippets/javascript/javascript.json | 693 ----------- snippets/javascript/react-native-ts.json | 445 ------- snippets/javascript/react-native.json | 476 -------- snippets/javascript/react-ts.json | 385 ------ snippets/javascript/react.json | 394 ------ snippets/javascript/typescript.json | 282 ----- snippets/lua.json | 88 -- snippets/make.json | 45 - snippets/markdown.json | 288 ----- snippets/package.json | 174 --- snippets/python/base.json | 163 --- snippets/python/comprehension.json | 47 - snippets/python/debug.json | 34 - snippets/python/python.json | 122 -- snippets/python/unittest.json | 54 - snippets/rust.json | 433 ------- snippets/shell.json | 93 -- snippets/sql.json | 62 - 119 files changed, 2201 insertions(+), 18000 deletions(-) delete mode 100644 README.md delete mode 100644 docs/img/screenshot.png delete mode 100644 docs/old_README.md create mode 100644 lazy-lock.json delete mode 100644 lsp/lua_ls.lua delete mode 100644 lsp/python.lua delete mode 100644 lsp/qml.lua delete mode 100644 lsp/tailwindcss.lua delete mode 100644 lsp/ts_ls.lua delete mode 100644 lua/chadrc.lua create mode 100644 lua/core/lazy.lua create mode 100644 lua/core/lsp.lua delete mode 100644 lua/lib/icons.lua delete mode 100644 lua/lib/prompts.lua delete mode 100644 lua/lib/util.lua create mode 100644 lua/plugins/ai.lua delete mode 100644 lua/plugins/ai/avante.lua delete mode 100644 lua/plugins/ai/copilot.lua create mode 100644 lua/plugins/colorscheme.lua create mode 100644 lua/plugins/completion.lua create mode 100644 lua/plugins/editor.lua delete mode 100644 lua/plugins/editor/ai.lua delete mode 100644 lua/plugins/editor/bracketed.lua delete mode 100644 lua/plugins/editor/pairs.lua delete mode 100644 lua/plugins/editor/spider.lua delete mode 100644 lua/plugins/editor/surround.lua delete mode 100644 lua/plugins/editor/textobjects.lua delete mode 100644 lua/plugins/editor/treesitter.lua create mode 100644 lua/plugins/files.lua create mode 100644 lua/plugins/format.lua create mode 100644 lua/plugins/git.lua delete mode 100644 lua/plugins/lang/blink.lua delete mode 100644 lua/plugins/lang/conform.lua delete mode 100644 lua/plugins/lang/lspconfig.lua delete mode 100644 lua/plugins/lang/lspsaga.lua delete mode 100644 lua/plugins/lang/mason.lua delete mode 100644 lua/plugins/lang/nvim-lint.lua create mode 100644 lua/plugins/languages.lua delete mode 100644 lua/plugins/lazy.lua create mode 100644 lua/plugins/lint.lua delete mode 100644 lua/plugins/list.lua delete mode 100644 lua/plugins/lock.json create mode 100644 lua/plugins/lsp.lua create mode 100644 lua/plugins/picker.lua create mode 100644 lua/plugins/statusline.lua delete mode 100644 lua/plugins/tools/ccc.lua delete mode 100644 lua/plugins/tools/dap.lua delete mode 100644 lua/plugins/tools/dbee.lua delete mode 100644 lua/plugins/tools/exercism.lua delete mode 100644 lua/plugins/tools/files.lua delete mode 100644 lua/plugins/tools/flash.lua delete mode 100644 lua/plugins/tools/gitlinker.lua delete mode 100644 lua/plugins/tools/navigator.lua delete mode 100644 lua/plugins/tools/neotest.lua delete mode 100644 lua/plugins/tools/octohub.lua delete mode 100644 lua/plugins/tools/sniprun.lua delete mode 100644 lua/plugins/tools/spectre.lua delete mode 100644 lua/plugins/tools/toggleterm.lua delete mode 100644 lua/plugins/ui/gitsigns.lua delete mode 100644 lua/plugins/ui/lualine.lua delete mode 100644 lua/plugins/ui/snacks.lua delete mode 100644 lua/plugins/ui/which-key.lua create mode 100644 lua/plugins/utility.lua create mode 100644 lua/plugins/whichkey.lua delete mode 100644 plugin/after/highlights.lua delete mode 100644 pywal/.gitignore delete mode 100644 pywal/LICENSE delete mode 100644 pywal/README.md delete mode 100644 pywal/chadwal.py delete mode 100644 pywal/dark.lua delete mode 100644 pywal/light.lua delete mode 100644 pywal/matugen.lua delete mode 100644 snippets/c.json delete mode 100644 snippets/cpp.json delete mode 100644 snippets/css.json delete mode 100644 snippets/django.json delete mode 100644 snippets/frameworks/django/filetemplates.json delete mode 100644 snippets/frameworks/django/forms.json delete mode 100644 snippets/frameworks/django/imports.json delete mode 100644 snippets/frameworks/django/models.json delete mode 100644 snippets/frameworks/django/views.json delete mode 100644 snippets/frameworks/ejs.json delete mode 100644 snippets/frameworks/flutter.json delete mode 100644 snippets/frameworks/jekyll.json delete mode 100644 snippets/frameworks/rails.json delete mode 100644 snippets/frameworks/twig.json delete mode 100644 snippets/frameworks/vue/html.json delete mode 100644 snippets/frameworks/vue/javascript.json delete mode 100644 snippets/frameworks/vue/pug.json delete mode 100644 snippets/frameworks/vue/vue.json delete mode 100644 snippets/gitcommit.json delete mode 100644 snippets/global.json delete mode 100644 snippets/go.json delete mode 100644 snippets/html.json delete mode 100644 snippets/htmldjango.json delete mode 100644 snippets/java.json delete mode 100644 snippets/javascript/javascript.json delete mode 100644 snippets/javascript/react-native-ts.json delete mode 100644 snippets/javascript/react-native.json delete mode 100644 snippets/javascript/react-ts.json delete mode 100644 snippets/javascript/react.json delete mode 100644 snippets/javascript/typescript.json delete mode 100644 snippets/lua.json delete mode 100644 snippets/make.json delete mode 100644 snippets/markdown.json delete mode 100644 snippets/package.json delete mode 100644 snippets/python/base.json delete mode 100644 snippets/python/comprehension.json delete mode 100644 snippets/python/debug.json delete mode 100644 snippets/python/python.json delete mode 100644 snippets/python/unittest.json delete mode 100644 snippets/rust.json delete mode 100644 snippets/shell.json delete mode 100644 snippets/sql.json diff --git a/README.md b/README.md deleted file mode 100644 index 4df5425..0000000 --- a/README.md +++ /dev/null @@ -1,127 +0,0 @@ -
- -

keycodex

- -

Your Personalized Dev Env ❤️👨‍💻

- -
- -Handcrafted Neovim setup for the ultimate CLI dev experience. - -## ✨ Features - -- **Fully configured LSP**: Out of the box LSP and completions, including Copilot (optional) -- **Awesome keybindings**: Intuitive and well documented keybindings with which-key -- **Blazingly fast**: Starts up in less than 30ms thanks to extensive lazy loading -- **Batteries included**: Has all the necessary plugins included out of the box -- **Git in there**: Powerful git integrations thanks to lazygit, fugitive, gitsigns and more -- **Pretty colors**: Comes with treesitter and onedark preconfigured with full transparency support -- **Tmux integration**: Works with your tmux configurations out of the box -- **Dev tools**: Comes with debugging, testing, database and REPL support, pick and choose -- **Auto install**: All necessary LSPs, Formatter, Linters, Treesitter Parsers etc. are auto installed -- **User module**: Configure keycodex according to your needs by using the `user` module! -- and some more - -Most importantly: - -**Built for extending**: keycodex has a easy to understand config structure that promotes personalization, so go ahead, bring your keybindings, functions and plugins over, and truly make **keycodex: Your Personalized Development Environment!** - -## ⚡ Setup - -### ⚙️ Requirements - -Before you begin, ensure you have met the following requirements: - -- You have installed the latest version of `neovim` -- Some command line tools: fd, ripgrep - -### 💻 Installation - -To install `keycodex` clone the repo and setup the symlink - -```bash -git clone https://github.com/S4NKALP/keycodex -``` - -On Linux and Mac - -```bash -ln -sfnv $PWD/keycodex $HOME/.config/nvim -``` - -On Windows Powershell - -```powershell -New-Item -ItemType SymbolicLink -Path "$env:LOCALAPPDATA\nvim" -Target "$PWD\keycodex" -Force -``` - -## 🚀 Usage - -### 🎨 User Configs - -`keycodex` supports a user module where you can store your custom configs and override any default configs. - -To use custom configs create the file `lua/user/init.lua` in keycodex, with the following structure: - -```lua --- lua/user/init.lua -local user = { - auto_install = true, -- enable auto install of LSPs, Treesitter parsers etc. - user_lsp_servers = { - -- Auto installed LSPs defined by user - }, - user_formatter_sources = { - -- Auto installed formatter sources defined by user - }, - user_linter_sources = { - -- Auto installed lintere sources defined by user - }, - user_treesitter_parsers = { - -- Auto installed Treesitter parsers defined by user - }, - - enable_db_explorer = false, -- enable dbee.nvim support - enable_debugger = false, -- enable dap.nvim support - enable_test_runner = false, -- enable neotest.nvim support - enable_trainer = false, -- enable hardtime.nvim support - user_plugins = { - -- Add your lazy plugin spec here - }, - - user_keybindings = { - -- Add your which-key bindings here - } -} - -return user -``` - -You can add and `require` any other custom modules and configurations you want in this file. - -`user` module is not part of the repo, you can set up `user` module as a separate git repository while continuing to receive `keycodex` updates. - -### Core - -Files in [lua/core](./lua/core/) control the core of neovim: - -- [options](./lua/core/options.lua), -- [functions](./lua/core/functions.lua) -- [autocmds](./lua/core/autocmd.lua) -- [core keybindings](./lua/core/keys.lua) - -### ⌨️ Keybindings - -Apart from [core/keys](./lua/core/keys.lua) most keybindings are configured using [which-key](./lua/plugins/tools/which-key.lua) - -### 📦 Plugins - -You can check out the [plugins list file](./lua/plugins/list.lua) file to see the plugins that are included in keycodex. - -- [lang](./lua/plugins/lang/): Plugins related to language features, completions, lsp, editing etc. -- [tools](./lua/plugins/tools/): Plugins that add tool integrations to the editor. -- [ui](./lua/plugins/ui/): Plugins that make improve Neovim user experience. - -## 🙏 Acknowledgments - -This project builds upon [nvim2k](https://github.com/2KAbhishek/nvim2k) by [2KAbhishek](https://github.com/2KAbhishek/), enhancing it with additional features and optimizations. - diff --git a/docs/img/screenshot.png b/docs/img/screenshot.png deleted file mode 100644 index e7b08ad6759b347e4ae0a02f61f053fb5325269f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 205548 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 z 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%0DT zEv@%~8}<*gtT77WH#jtuaJc=mtU|YBCPyu8+?Acwy7GPAItypLS$ z>T_t)6{XTiB62xi);dWa$L^(C_wp4{#Ub`LsD%Fw_d>ajq6oaO?bt7l7` znU@y|frv;dfPMQGABE;toK)@UEmCuFiSZ;y`pSPb~Z_(3TZ+doH*p62BH4P9qNQCWLDPq!oospHF>6`1nV6ZhVp-=EdVk#uFUZrze~7>Gn3>b;(Lm#Ao0_VsgXyP#c4Rf-H?PIS-y9vOiNkIK zsj0?~AE#PcT5=ZGVa=_oH=y3Ga2fn!BMzIXQ}#Sq7D(zP-ErIhwHF3ra+Jaeku&}jvw|p8>Hh!KR;Nw91=hFGC`)H#T9;vQ%#xnhYz@TJKGv6oLtxr$) zVlmX{^-OKOS2roJy4-&>*VKYZV+}xR++(|!L`B3t&R&oYd1r=VoOI z|4yX-Ey@Za#SLn@jTllmRy-|DPyGD3$p=vRgKeq)(NQ9)Rom5m)90atY;0^BBd8Zm z9RPq8swgX?HKpG*@kv#S&BfW7iuXsT^piKj$;t_w;y%Y21A@1)%hZ(%Oo08o+&K(i z!j$6dosCRPh-?TI!o{n>N(tkaXC~{#FXZI~RXW@^ZC+$+m^2V3@PrdmPnrn(Qve+n zE)9NH7sp4QH`miaVIbhu!7>5nyqYf(KAaIR7F|&D^XbY7qfA~~o10;>W;fTj&QEBb zP^|Y%RP?Hj6+Hd#ow80l?kyz>e383~UDsuAb z6X%XRqG> E4;O}fX#fBK diff --git a/docs/old_README.md b/docs/old_README.md deleted file mode 100644 index ccaade9..0000000 --- a/docs/old_README.md +++ /dev/null @@ -1,147 +0,0 @@ ---- - -these are the commands i am using recently: - -moving is easy u just use hlkj - -`$`: will always take you to the end of the line - -`0`: will take you always to the start of the line - -`^`: using caret will take you to the first not empty space or character in ur line - -`f`: to jump to the character you want to reach towards in the line - -`F`: (capital f) here u will be jumping backwords to the character u need. - -`t`: is to go towards the letter u want to jump but the cursor is just before it - -`T`: (you can think of it as till) works the same but backwards - -`w, b`: to navigate between the words and symbols - -`W, B`: to navigate between capital words - -`e`: to navigate through end of the words - -`ge`: to navigate through end of the words but backwords - -`gE`: to skip and navigate between words in all caps. - -`{}`: is to jump between paragraphs or between empty space blocks - -`G`: is to jump to end of the line. - -`gg`: is to go to the beginning of the file - -`17G`: will take u to the line of 17, also :17 will do the same - -`%`: if u are on the opening or closing parenthesis or bracket it will jump to the according closing bracket or parenthesis - -`[(`: to jump to the opening parenthesis if you are in the middle of them - -`ctrl + f`: will take u down to a full screen - -`ctrl + b`: will take u up to a full screen - -`ctrl + u`:, d will take u up and down resectively half a screen - -`zt, zb, zz`: to move respecivally to top, bottom and half screen with moving the cursor - -`ctrl + y`: and e is to scroll up and down without moving the cursor - -`/`: to execute a search, and enter to go and hop into it - -`:nohl`: is a command to undo a selection - -`n and N`: to move through your searches - -`(star\*)`: to execute a search on an exact word - -`ctrl + i`:, o will jump u between jumplists - -`d$ or D`: to delete from current cursor to end of the line - -`dG`: to delete until the end of the file - -`de`: to delete till the end of the word - -`dd`: to delete all line - -`u`: to undo for sure - -`ce, c`: short for change is to delete and move to insert mode after deleting - -`r,`: to replace a simple character - -`yf(character)`: you will copy until character and then p or P to paste - -`yy`: to copy the whole line - -`Y or y$`: is same to copy until end of the line - -`~`: to change case of a character - -`gU`: to change to uppercase - -`gu`: to change for lowercase - -`diw, d`: for delete, i for inside and w for word, this will do the magic to delete the word entirely when the cursor is inside - -`ciw`: is to change a word while the cursor is inside - -`yip`: to copy the paragraph you are inside - -`dip`: to delete the pragraph you are in - -`di(`: to delete inside the parenthesis - -`da(`: to delete outside the parenthesis which means including them - -`:%s/word/newword/g`: change word to newword - -`:%s/word/newword/gc`: to not prompt u for being sure or not - -check this guy's cheatsheet for more: - -`https://www.josean.com/posts/vim-essentials-cheatsheet` - ---- - -### advanced stuff - -`qa`: to start recording a couple of movements - -`q`: to quit recording and make sure you are in visual mode - -`@a`: to apply what you recorded on a - -`vap`: to select outside a whole paragraph - -`:%`: to start an operation on whole file - -`:%norm!`: to start an operation on norm mode - -`:'<,'>norm!`: @a is to start the operation of @a on the paragraph selected - -`ctrl + w` and how u can use s for split and closing with o - -`Marks` to add the m + a and m + b and then switch to marks with ' + a or ' + b - -`ctrl + f` and `ctrl + u` is to move cursor to last character of file or first line as well. - -`ctrl + n` and `ctrl + p` are for navigation - -`ctrl + d` and `ctrl + u` will jump certain number of phrases and make navigation easier for u - -`ctrl + a` to increment number and `ctrl + x` to decrement it - -`ctrl + shift + v` to paste to terminal from clipboard - -`ys-command` to surround certain word with whatever u write next for example "" - -`ds"` to delete surrounding double quote or if u replace " with `t` u will delete surrounding tag - -`cs"` to change surrounding character with whatever u want, in this case with quotes - -`"ay + command` will give u possibility to yank whatever u gave to register a diff --git a/init.lua b/init.lua index d7a1edc..4305870 100644 --- a/init.lua +++ b/init.lua @@ -1,14 +1,7 @@ -require('core.options') -require('core.functions') -require('core.keys') +-- load config +require("core.options") +require("core.functions") +require("core.keys") require('core.autocmd') -require('plugins.lazy') --- Add user configs to this module -pcall(require, 'user') - --- load theme -dofile(vim.g.base46_cache .. 'defaults') -dofile(vim.g.base46_cache .. 'statusline') - --- Run pywal chadwal script silently in background -os.execute('python3 ~/.config/nvim/pywal/chadwal.py &> /dev/null &') +require("core.lsp") +require("core.lazy") diff --git a/lazy-lock.json b/lazy-lock.json new file mode 100644 index 0000000..b6a97d4 --- /dev/null +++ b/lazy-lock.json @@ -0,0 +1,45 @@ +{ + "Comment.nvim": { "branch": "master", "commit": "e30b7f2008e52442154b66f7c519bfd2f1e32acb" }, + "LuaSnip": { "branch": "master", "commit": "458560534a73f7f8d7a11a146c801db00b081df0" }, + "Navigator.nvim": { "branch": "master", "commit": "91d86506ac2a039504d5205d32a1d4bc7aa57072" }, + "better-escape.nvim": { "branch": "master", "commit": "19a38aab94961016430905ebec30d272a01e9742" }, + "blink.cmp": { "branch": "main", "commit": "bae4bae0eedd1fa55f34b685862e94a222d5c6f8" }, + "conform.nvim": { "branch": "master", "commit": "b4aab989db276993ea5dcb78872be494ce546521" }, + "friendly-snippets": { "branch": "main", "commit": "572f5660cf05f8cd8834e096d7b4c921ba18e175" }, + "gitsigns.nvim": { "branch": "main", "commit": "6e3c66548035e50db7bd8e360a29aec6620c3641" }, + "gruvbox.nvim": { "branch": "main", "commit": "5e0a460d8e0f7f669c158dedd5f9ae2bcac31437" }, + "harpoon": { "branch": "harpoon2", "commit": "ed1f853847ffd04b2b61c314865665e1dadf22c7" }, + "lazy.nvim": { "branch": "main", "commit": "6c3bda4aca61a13a9c63f1c1d1b16b9d3be90d7a" }, + "lspsaga.nvim": { "branch": "main", "commit": "8efe00d6aed9db6449969f889170f1a7e43101a1" }, + "lualine.nvim": { "branch": "master", "commit": "b8c23159c0161f4b89196f74ee3a6d02cdc3a955" }, + "markdown-preview.nvim": { "branch": "master", "commit": "a923f5fc5ba36a3b17e289dc35dc17f66d0548ee" }, + "markview.nvim": { "branch": "main", "commit": "e6b0f5aee8105adab6077509c46459812db4cffa" }, + "mason-conform.nvim": { "branch": "main", "commit": "48da2ebd5efbaf8a99566eadc3ece82d523f03c5" }, + "mason-lspconfig.nvim": { "branch": "main", "commit": "5e085efe67fccb13372d54331d849219662a7e93" }, + "mason-nvim-lint": { "branch": "main", "commit": "767b8ccdddaa977bec8987fd7507b9865a279235" }, + "mason.nvim": { "branch": "main", "commit": "7dc4facca9702f95353d5a1f87daf23d78e31c2a" }, + "mini.ai": { "branch": "main", "commit": "e139eb1101beb0250fea322f8c07a42f0f175688" }, + "mini.bracketed": { "branch": "main", "commit": "672b4e2fe9222fd4d5a104ff23217801bae37046" }, + "mini.files": { "branch": "main", "commit": "49c855977e9f4821d1ed8179ed44fe098b93ea2a" }, + "mini.indentscope": { "branch": "main", "commit": "9d9490c172a4718d7d1f20eaae668a28f160c2d7" }, + "mini.surround": { "branch": "main", "commit": "5aab42fcdcf31fa010f012771eda5631c077840a" }, + "neogen": { "branch": "main", "commit": "d7f9461727751fb07f82011051338a9aba07581d" }, + "neoscroll.nvim": { "branch": "master", "commit": "f957373912e88579e26fdaea4735450ff2ef5c9c" }, + "netrw.nvim": { "branch": "master", "commit": "90501c62b9b816ed3ed1e912ae9db9af5671a1b2" }, + "nvim-autopairs": { "branch": "master", "commit": "23320e75953ac82e559c610bec5a90d9c6dfa743" }, + "nvim-lint": { "branch": "master", "commit": "f126af5345c7472e9a0cdbe1d1a29209be72c4c4" }, + "nvim-lspconfig": { "branch": "master", "commit": "c8b90ae5cbe21d547b342b05c9266dcb8ca0de8f" }, + "nvim-treesitter": { "branch": "master", "commit": "42fc28ba918343ebfd5565147a42a26580579482" }, + "nvim-ts-autotag": { "branch": "main", "commit": "a1d526af391f6aebb25a8795cbc05351ed3620b5" }, + "nvim-ts-context-commentstring": { "branch": "main", "commit": "1b212c2eee76d787bbea6aa5e92a2b534e7b4f8f" }, + "smartcolumn.nvim": { "branch": "main", "commit": "b9cdbdf42f7ac5a659204cd5926017c7ff724a19" }, + "snacks.nvim": { "branch": "main", "commit": "bc0630e43be5699bb94dadc302c0d21615421d93" }, + "tiny-code-action.nvim": { "branch": "main", "commit": "2b3fa2fbd25496259eaf50987097982f8ad08d1b" }, + "tiny-inline-diagnostic.nvim": { "branch": "main", "commit": "f64efd33a51ea89bdb847fb3aaf716e96b83ba1a" }, + "todo-comments.nvim": { "branch": "main", "commit": "304a8d204ee787d2544d8bc23cd38d2f929e7cc5" }, + "toggleterm.nvim": { "branch": "main", "commit": "50ea089fc548917cc3cc16b46a8211833b9e3c7c" }, + "uv.nvim": { "branch": "main", "commit": "be4a7d47a976249282bb2f71fc773ac2f5325973" }, + "vim-wakatime": { "branch": "master", "commit": "d7973b157a632d1edeff01818f18d67e584eeaff" }, + "which-key.nvim": { "branch": "main", "commit": "370ec46f710e058c9c1646273e6b225acf47cbed" }, + "windsurf.vim": { "branch": "main", "commit": "a8d47ec54fe82df920b2545559f767003e8a7f8d" } +} diff --git a/lsp/lua_ls.lua b/lsp/lua_ls.lua deleted file mode 100644 index 1db6fe0..0000000 --- a/lsp/lua_ls.lua +++ /dev/null @@ -1,34 +0,0 @@ -return { - cmd = { 'lua-language-server' }, - filetypes = { 'lua' }, - root_markers = { '.luarc.json', '.luarc.jsonc' }, - settings = { - Lua = { - diagnostics = { globals = { 'vim' } }, - telemetry = { enable = false }, - format = { - enable = true, - defaultConfig = { - align_continuous_assign_statement = false, - align_continuous_rect_table_field = false, - align_array_table = false, - }, - }, - runtime = { - version = 'LuaJIT', - path = { - 'lua/?.lua', - 'lua/?/init.lua', - }, - }, - workspace = { - checkThirdParty = false, - library = { - vim.env.VIMRUNTIME, - -- vim.api.nvim_get_runtime_file('', true), - -- '${3rd}/busted/library' - }, - }, - }, - }, -} diff --git a/lsp/python.lua b/lsp/python.lua deleted file mode 100644 index abf49c6..0000000 --- a/lsp/python.lua +++ /dev/null @@ -1,17 +0,0 @@ -return { - cmd = { 'pyright-langserver', '--stdio' }, - filetypes = { 'py', 'python' }, - root_markers = { 'pyproject.toml', 'setup.py', 'setup.cfg', 'requirements.txt' }, - settings = { - python = { - analysis = { - -- autoSearchPaths = true, - diagnosticMode = 'openFilesOnly', - -- useLibraryCodeForTypes = true, - }, - }, - }, - init_options = { - hostInfo = 'neovim', - }, -} diff --git a/lsp/qml.lua b/lsp/qml.lua deleted file mode 100644 index f6a73d5..0000000 --- a/lsp/qml.lua +++ /dev/null @@ -1,5 +0,0 @@ -return { - cmd = { "qmlls" }, - filetypes = { 'qml', 'qmljs' }, - root_markers = { '.git', 'shell.qml', '.qmlls.ini' }, - } \ No newline at end of file diff --git a/lsp/tailwindcss.lua b/lsp/tailwindcss.lua deleted file mode 100644 index 258ad2b..0000000 --- a/lsp/tailwindcss.lua +++ /dev/null @@ -1,8 +0,0 @@ -return { - cmd = { 'tailwindcss-language-server' }, - root_markers = { 'tsconfig.json', 'jsconfig.json', 'package.json', '.git' }, - filetypes = { 'javascript', 'javascriptreact', 'javascript.jsx', 'typescript', 'typescriptreact', 'typescript.tsx' }, - init_options = { - hostInfo = 'neovim', - }, -} diff --git a/lsp/ts_ls.lua b/lsp/ts_ls.lua deleted file mode 100644 index e997cf8..0000000 --- a/lsp/ts_ls.lua +++ /dev/null @@ -1,28 +0,0 @@ -return { - settings = { - typescript = { - inlayHints = { - includeInlayParameterNameHints = 'all', - includeInlayParameterNameHintsWhenArgumentMatchesName = false, - includeInlayFunctionParameterTypeHints = true, - includeInlayVariableTypeHints = true, - includeInlayVariableTypeHintsWhenTypeMatchesName = false, - includeInlayPropertyDeclarationTypeHints = true, - includeInlayFunctionLikeReturnTypeHints = true, - includeInlayEnumMemberValueHints = true, - }, - }, - javascript = { - inlayHints = { - includeInlayParameterNameHints = 'all', - includeInlayParameterNameHintsWhenArgumentMatchesName = false, - includeInlayFunctionParameterTypeHints = true, - includeInlayVariableTypeHints = true, - includeInlayVariableTypeHintsWhenTypeMatchesName = false, - includeInlayPropertyDeclarationTypeHints = true, - includeInlayFunctionLikeReturnTypeHints = true, - includeInlayEnumMemberValueHints = true, - }, - }, - }, -} diff --git a/lua/chadrc.lua b/lua/chadrc.lua deleted file mode 100644 index e02dc9b..0000000 --- a/lua/chadrc.lua +++ /dev/null @@ -1,8 +0,0 @@ ----@type ChadrcConfig -local M = {} - -M.base46 = { - theme = "chadwal", -} - -return M \ No newline at end of file diff --git a/lua/core/autocmd.lua b/lua/core/autocmd.lua index cb9ceae..6bab5c9 100644 --- a/lua/core/autocmd.lua +++ b/lua/core/autocmd.lua @@ -1,137 +1,129 @@ local function augroup(name) - return vim.api.nvim_create_augroup('keycodex' .. name, { clear = true }) + return vim.api.nvim_create_augroup("nvim" .. name, { clear = true }) end -- Strip trailing spaces before write -vim.api.nvim_create_autocmd({ 'BufWritePre' }, { - group = augroup('strip_space'), - pattern = { '*' }, - callback = function() - vim.cmd([[ %s/\s\+$//e ]]) - end, +vim.api.nvim_create_autocmd({ "BufWritePre" }, { + group = augroup("strip_space"), + pattern = { "*" }, + callback = function() + vim.cmd([[ %s/\s\+$//e ]]) + end, }) -- Check if we need to reload the file when it changed -vim.api.nvim_create_autocmd({ 'FocusGained', 'TermClose', 'TermLeave' }, { - group = augroup('checktime'), - command = 'checktime', +vim.api.nvim_create_autocmd({ "FocusGained", "TermClose", "TermLeave" }, { + group = augroup("checktime"), + command = "checktime", }) -- Highlight on yank -vim.api.nvim_create_autocmd('TextYankPost', { - group = augroup('highlight_yank'), - callback = function() - vim.highlight.on_yank() - end, +vim.api.nvim_create_autocmd("TextYankPost", { + group = augroup("highlight_yank"), + callback = function() + vim.highlight.on_yank() + end, }) -- resize splits if window got resized -vim.api.nvim_create_autocmd({ 'VimResized' }, { - group = augroup('resize_splits'), - callback = function() - vim.cmd('tabdo wincmd =') - end, +vim.api.nvim_create_autocmd({ "VimResized" }, { + group = augroup("resize_splits"), + callback = function() + vim.cmd("tabdo wincmd =") + end, }) -- go to last loc when opening a buffer -vim.api.nvim_create_autocmd('BufReadPost', { - group = augroup('last_loc'), - callback = function() - local mark = vim.api.nvim_buf_get_mark(0, '"') - local lcount = vim.api.nvim_buf_line_count(0) - if mark[1] > 0 and mark[1] <= lcount then - pcall(vim.api.nvim_win_set_cursor, 0, mark) - end - end, +vim.api.nvim_create_autocmd("BufReadPost", { + group = augroup("last_loc"), + callback = function() + local mark = vim.api.nvim_buf_get_mark(0, '"') + local lcount = vim.api.nvim_buf_line_count(0) + if mark[1] > 0 and mark[1] <= lcount then + pcall(vim.api.nvim_win_set_cursor, 0, mark) + end + end, }) -- close some filetypes with -vim.api.nvim_create_autocmd('FileType', { - group = augroup('close_with_q'), - pattern = { - 'Jaq', - 'PlenaryTestPopup', - 'Avante', - 'AvanteInput', - 'AvanteSelectedFiles', - 'fugitive', - 'git', - 'help', - 'lir', - 'lspinfo', - 'man', - 'netrw', - 'notify', - 'qf', - 'spectre_panel', - 'startuptime', - 'tsplayground', - }, - callback = function(event) - vim.bo[event.buf].buflisted = false - vim.keymap.set('n', 'q', 'close', { buffer = event.buf, silent = true }) - end, +vim.api.nvim_create_autocmd("FileType", { + group = augroup("close_with_q"), + pattern = { + "Jaq", + "PlenaryTestPopup", + "Avante", + "AvanteInput", + "AvanteSelectedFiles", + "fugitive", + "git", + "help", + "lir", + "lspinfo", + "man", + "netrw", + "notify", + "qf", + "spectre_panel", + "startuptime", + "tsplayground", + }, + callback = function(event) + vim.bo[event.buf].buflisted = false + vim.keymap.set("n", "q", "close", { buffer = event.buf, silent = true }) + end, }) -- wrap and check for spell in text filetypes -vim.api.nvim_create_autocmd('FileType', { - group = augroup('wrap_spell'), - pattern = { 'gitcommit', 'markdown' }, - callback = function() - vim.opt_local.wrap = true - vim.opt_local.spell = true - end, +vim.api.nvim_create_autocmd("FileType", { + group = augroup("wrap_spell"), + pattern = { "gitcommit", "markdown" }, + callback = function() + vim.opt_local.wrap = true + vim.opt_local.spell = true + end, }) -- Auto create dir when saving a file, in case some intermediate directory does not exist -vim.api.nvim_create_autocmd({ 'BufWritePre' }, { - group = augroup('auto_create_dir'), - callback = function(event) - local file = vim.loop.fs_realpath(event.match) or event.match - vim.fn.mkdir(vim.fn.fnamemodify(file, ':p:h'), 'p') - end, +vim.api.nvim_create_autocmd({ "BufWritePre" }, { + group = augroup("auto_create_dir"), + callback = function(event) + local file = vim.loop.fs_realpath(event.match) or event.match + vim.fn.mkdir(vim.fn.fnamemodify(file, ":p:h"), "p") + end, }) -- Set arb filetype -vim.api.nvim_create_autocmd({ 'BufEnter' }, { - group = augroup('set_file_type'), - pattern = { '*.arb' }, - command = require('lib.util').get_file_type_cmd('arb'), +vim.api.nvim_create_autocmd({ "BufEnter" }, { + group = augroup("set_file_type"), + pattern = { "*.arb" }, + command = "setfiletype arb", }) -- Disable format options -vim.api.nvim_create_autocmd('FileType', { - group = augroup('disable_formatoptions'), - pattern = '*', - callback = function() - vim.opt_local.formatoptions:remove({ 'c', 'r', 'o' }) - end, +vim.api.nvim_create_autocmd("FileType", { + group = augroup("disable_formatoptions"), + pattern = "*", + callback = function() + vim.opt_local.formatoptions:remove({ "c", "r", "o" }) + end, }) local function enable_autoformat() - vim.api.nvim_create_autocmd({ 'BufWritePre' }, { - group = augroup('autoformat'), - pattern = { '*' }, - callback = function() - vim.lsp.buf.format() - end, - }) + vim.api.nvim_create_autocmd({ "BufWritePre" }, { + group = augroup("autoformat"), + pattern = { "*" }, + callback = function() + vim.lsp.buf.format() + end, + }) end enable_autoformat() -vim.api.nvim_create_user_command('WriteNoFormat', function() - -- Temporarily disable the autoformat autocmd - vim.api.nvim_del_augroup_by_name('keycodex_autoformat') - vim.cmd('write') - -- Re-enable the autoformat autocmd - enable_autoformat() +vim.api.nvim_create_user_command("WriteNoFormat", function() + -- Temporarily disable the autoformat autocmd + vim.api.nvim_del_augroup_by_name("keycodex_autoformat") + vim.cmd("write") + -- Re-enable the autoformat autocmd + enable_autoformat() end, {}) - -local autocmd = vim.api.nvim_create_autocmd -autocmd('Signal', { - pattern = 'SIGUSR1', - callback = function() - require('nvchad.utils').reload() - end, -}) diff --git a/lua/core/functions.lua b/lua/core/functions.lua index 9f197ae..a92c3cb 100644 --- a/lua/core/functions.lua +++ b/lua/core/functions.lua @@ -46,10 +46,23 @@ end, {}) -- Switch to git root or file parent dir vim.api.nvim_create_user_command('RootDir', function() - local root = require('lib.util').get_root_dir() - - if root == '' then + local bufname = vim.fn.expand('%:p') + if vim.fn.filereadable(bufname) == 0 then return end - vim.cmd('lcd ' .. root) + + local parent = vim.fn.fnamemodify(bufname, ':h') + local git_root = vim.fn.systemlist('git -C ' .. vim.fn.fnameescape(parent) .. ' rev-parse --show-toplevel') + local root = '' + if #git_root > 0 and git_root[1] ~= '' then + root = git_root[1] + else + root = parent + end + + if root ~= '' then + vim.cmd('lcd ' .. vim.fn.fnameescape(root)) + vim.notify('Changed directory to ' .. root, vim.log.levels.INFO) + end end, {}) + diff --git a/lua/core/keys.lua b/lua/core/keys.lua index 043edaf..63064b9 100644 --- a/lua/core/keys.lua +++ b/lua/core/keys.lua @@ -1,160 +1,102 @@ local function map(mode, lhs, rhs, opts) - opts = opts or {} - opts.silent = opts.silent ~= false - vim.keymap.set(mode, lhs, rhs, opts) + opts = opts or {} + opts.silent = opts.silent ~= false + vim.keymap.set(mode, lhs, rhs, opts) end local opts = { noremap = true, silent = true } -- Space as leader -map('n', '', '', opts) -vim.g.mapleader = ' ' -vim.g.maplocalleader = ' ' +map("n", "", "", opts) +vim.g.mapleader = " " +vim.g.maplocalleader = " " -- Modes -- normal_mode = "n", insert_mode = "i", visual_mode = "v", -- visual_block_mode = "x", term_mode = "t", command_mode = "c", +-- Clear search, diff update and redraw +map({ "i", "n" }, "", "noh", { desc = "Escape and clear hlsearch" }) --- Use jj as escape -map('i', 'jj', '', opts) -map('i', 'jk', '', opts) -map('i', 'kj', '', opts) -map('t', 'JJ', '', opts) +map({ "i", "c" }, "", "") +map({ "i", "c" }, "", "") --- Terminal Mappings -map('t', 'jk', '') -map('t', 'kj', '') -map('t', '', '') +map("n", "r", vim.lsp.buf.rename) +map("n", "`", "'", { noremap = true }) -- better marks + +map("n", "H", "^", { desc = "Jump to line start" }) +map("n", "L", "$", { desc = "Jump to line end" }) -- Visual overwrite paste -map({ 'v', 'x' }, 'p', '"_dP', opts) +map({ "v", "x" }, "p", '"_dP', opts) -- Do not copy on x -map({ 'v', 'x' }, 'x', '"_x', opts) - --- VSCode style shortcuts --- File operations -map('n', '', ':w', { desc = 'Save file' }) -map('i', '', ':wa', { desc = 'Save file' }) -map('n', '', ':q', { desc = 'Quit' }) -map('n', '', ':bd', { desc = 'Close buffer' }) - --- Undo/Redo -map('n', '', 'u', { desc = 'Undo' }) -map('i', '', 'u', { desc = 'Undo' }) -map('n', '', '', { desc = 'Redo' }) -map('i', '', '', { desc = 'Redo' }) +map({ "v", "x" }, "x", '"_x', opts) +map("n", "X", '"_D', opts) +map({ "v", "x" }, "X", '"_d', opts) -- Select all -map('n', '', 'ggVG', { desc = 'Select all' }) -map('i', '', 'ggVG', { desc = 'Select all' }) - --- Copy/Cut -map('v', '', 'y', { desc = 'Copy' }) -map('v', '', 'd', { desc = 'Cut' }) - --- Line operations (VSCode style) -map('n', '', ':m .-2==', { desc = 'Move line up' }) -map('n', '', ':m .+1==', { desc = 'Move line down' }) -map('i', '', ':m .-2==gi', { desc = 'Move line up' }) -map('i', '', ':m .+1==gi', { desc = 'Move line down' }) -map('v', '', ":m '<-2gv=gv", { desc = 'Move selection up' }) -map('v', '', ":m '>+1gv=gv", { desc = 'Move selection down' }) - --- VSCode-style line operations -map('n', '', 'o', { desc = 'Insert line below' }) -map('i', '', 'o', { desc = 'Insert line below' }) - --- Quick word operations -map('n', '', 'db', { desc = 'Delete word backward' }) -map('i', '', '', { desc = 'Delete word backward' }) -map('n', '', 'dw', { desc = 'Delete word forward' }) -map('i', '', 'dw', { desc = 'Delete word forward' }) - --- Duplicate line -map('n', '', 'yykP', { desc = 'Duplicate line up' }) -map('n', '', 'yyp', { desc = 'Duplicate line down' }) -map('v', '', "y'', "y'>pgv", { desc = 'Duplicate selection down' }) - - --- Line manipulation -map('n', '', '>>', { desc = 'Indent line' }) -map('n', '', '<<', { desc = 'Unindent line' }) -map('i', '', '>>', { desc = 'Indent line' }) -map('i', '', '<<', { desc = 'Unindent line' }) - --- Visual overwrite paste -map({ 'v', 'x' }, 'p', '"_dP', opts) - --- Do not copy on x -map({ 'v', 'x' }, 'x', '"_x', opts) -map('n', 'X', '"_D', opts) -map({ 'v', 'x' }, 'X', '"_d', opts) - --- Increment/decrement -map({ 'n', 'v', 'x' }, '-', '', opts) -map({ 'n', 'v', 'x' }, '=', '', opts) - --- Move to line beginning and end -map({ 'n', 'v', 'x' }, 'gl', '$', { desc = 'End of line' }) -map({ 'n', 'v', 'x' }, 'gh', '^', { desc = 'Beginning of line' }) - --- Center Cursors -map('n', 'J', 'mzJ`z', opts) -map('n', '', 'zz', opts) -map('n', '', 'zz', opts) -map('n', 'n', 'nzzzv', opts) -map('n', 'N', 'Nzzzv', opts) - --- Better up/down -map('n', 'j', "v:count == 0 ? 'gj' : 'j'", { expr = true, silent = true }) -map('n', 'k', "v:count == 0 ? 'gk' : 'k'", { expr = true, silent = true }) +map("n", "", "ggVG", { desc = "Select all" }) +map("i", "", "ggVG", { desc = "Select all" }) -- Move text up and down -map({ 'v', 'x' }, 'J', ":move '>+1gv-gv", opts) -map({ 'v', 'x' }, 'K', ":move '<-2gv-gv", opts) +map({ "v", "x" }, "K", ":move '<-2gv-gv", opts) +map({ "v", "x" }, "J", ":move '>+1gv-gv", opts) --- Clear search, diff update and redraw -map({ 'i', 'n' }, '', 'noh', { desc = 'Escape and clear hlsearch' }) +-- Line operations +map("n", "", ":m .-2==", { desc = "Move line up" }) +map("n", "", ":m .+1==", { desc = "Move line down" }) +map("i", "", ":m .-2==gi", { desc = "Move line up" }) +map("i", "", ":m .+1==gi", { desc = "Move line down" }) +map("v", "", ":m '<-2gv=gv", { desc = "Move selection up" }) +map("v", "", ":m '>+1gv=gv", { desc = "Move selection down" }) --- Consistent n/N search navigation -map('n', 'n', "'Nn'[v:searchforward]", { expr = true, desc = 'Next search result' }) -map('x', 'n', "'Nn'[v:searchforward]", { expr = true, desc = 'Next search result' }) -map('o', 'n', "'Nn'[v:searchforward]", { expr = true, desc = 'Next search result' }) -map('n', 'N', "'nN'[v:searchforward]", { expr = true, desc = 'Prev search result' }) -map('x', 'N', "'nN'[v:searchforward]", { expr = true, desc = 'Prev search result' }) -map('o', 'N', "'nN'[v:searchforward]", { expr = true, desc = 'Prev search result' }) +-- Line manipulation +map("n", "", ">>", { desc = "Indent line" }) +map("n", "", "<<", { desc = "Unindent line" }) +map("i", "", ">>", { desc = "Indent line" }) +map("i", "", "<<", { desc = "Unindent line" }) --- Better indenting -map('v', '<', '', '>gv') +-- Quick word operations +map("n", "", "db", { desc = "Delete word backward" }) +map("i", "", "", { desc = "Delete word backward" }) +map("n", "", "dw", { desc = "Delete word forward" }) +map("i", "", "dw", { desc = "Delete word forward" }) --- Add undo breakpoints -map('i', ',', ',u') -map('i', '.', '.u') -map('i', ';', ';u') - -map('n', 'd', '"_d', { desc = 'Delete without replacing clipboard' }) -map('n', 'x', '"_x', { desc = 'Cut without replacing clipboard' }) -map('n', 'c', '"_c', { desc = 'Change without replacing clipboard' }) -map('v', 'p', '"_dP', { desc = 'Paste without replacing clipboard' }) - --- Toggle relative numbers off or on (for code presentation) -map({ 'n', 'v' }, 'tn', 'set rnu!', {}) +map("n", "d", '"_d', { desc = "Delete without replacing clipboard" }) +map("n", "x", '"_x', { desc = "Cut without replacing clipboard" }) +map("n", "c", '"_c', { desc = "Change without replacing clipboard" }) +map("v", "p", '"_dP', { desc = "Paste without replacing clipboard" }) --insert the following characters around the visual selection -map('v', '(', 's()Pll', { desc = 'wrap selection with parens' }) -map('v', '[', 's[]Pll', { desc = 'wrap selection with square braces' }) -map('v', '{', 's{}Pll', { desc = 'wrap selection with curly braces' }) -map('v', "'", "s''Pll", { desc = 'wrap selection with single quotes' }) -map('v', '"', 's""Pll', { desc = 'wrap selection with double quotes' }) +map("v", "(", "s()Pll", { desc = "wrap selection with parens" }) +map("v", "[", "s[]Pll", { desc = "wrap selection with square braces" }) +map("v", "{", "s{}Pll", { desc = "wrap selection with curly braces" }) +map("v", "'", "s''Pll", { desc = "wrap selection with single quotes" }) +map("v", '"', 's""Pll', { desc = "wrap selection with double quotes" }) -- Insert mode cursor movement with Ctrl+hjkl -map('i', '', '', { desc = 'Move cursor left' }) -map('i', '', '', { desc = 'Move cursor down' }) -map('i', '', '', { desc = 'Move cursor up' }) -map('i', '', '', { desc = 'Move cursor right' }) +map("i", "", "", { desc = "Move to end of previous line" }) +map("i", "", "", { desc = "Move cursor down" }) +map("i", "", "", { desc = "Move cursor up" }) +map("i", "", "", { desc = "Move cursor right" }) +-- toggle inlay hints +vim.keymap.set("n", "th", function() + vim.lsp.inlay_hint.enable(not vim.lsp.inlay_hint.is_enabled()) +end) +-- No arrow navigation +vim.api.nvim_set_keymap("n", "", "", opts) +vim.api.nvim_set_keymap("n", "", "", opts) +vim.api.nvim_set_keymap("n", "", "", opts) +vim.api.nvim_set_keymap("n", "", "", opts) +vim.api.nvim_set_keymap("v", "", "", opts) +vim.api.nvim_set_keymap("v", "", "", opts) +vim.api.nvim_set_keymap("v", "", "", opts) +vim.api.nvim_set_keymap("v", "", "", opts) + +vim.api.nvim_set_keymap("i", "", "", opts) +vim.api.nvim_set_keymap("i", "", "", opts) +vim.api.nvim_set_keymap("i", "", "", opts) +vim.api.nvim_set_keymap("i", "", "", opts) diff --git a/lua/core/lazy.lua b/lua/core/lazy.lua new file mode 100644 index 0000000..b2ef8ad --- /dev/null +++ b/lua/core/lazy.lua @@ -0,0 +1,37 @@ +-------------------------------------------------------------------------------- +-- Bootstrap lazy plugin manager +-------------------------------------------------------------------------------- +local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim" +if not (vim.uv or vim.loop).fs_stat(lazypath) then + local lazyrepo = "https://github.com/folke/lazy.nvim.git" + local out = vim.fn.system({ "git", "clone", "--filter=blob:none", "--branch=stable", lazyrepo, lazypath }) + if vim.v.shell_error ~= 0 then + vim.api.nvim_echo({ + { "Failed to clone lazy.nvim:\n", "ErrorMsg" }, + { out, "WarningMsg" }, + { "\nPress any key to exit..." }, + }, true, {}) + vim.fn.getchar() + os.exit(1) + end +end +vim.opt.rtp:prepend(lazypath) + +-- lazy config +require("lazy").setup({ + spec = { + { import = "plugins" }, + }, + install = { + missing = true, + colorscheme = { "onedark" }, + }, + change_detection = { + enable = true, + notify = false, + }, + ui = { + border = "rounded", + backdrop = 100, + }, +}) diff --git a/lua/core/lsp.lua b/lua/core/lsp.lua new file mode 100644 index 0000000..888195b --- /dev/null +++ b/lua/core/lsp.lua @@ -0,0 +1,135 @@ +-------------------------------------------------------------------------------- +-- LSP +-------------------------------------------------------------------------------- + +-- ts_ls +vim.lsp.config("ts_ls", { + settings = { + typescript = { + inlayHints = { + includeInlayParameterNameHints = "all", + includeInlayParameterNameHintsWhenArgumentMatchesName = false, + includeInlayFunctionParameterTypeHints = true, + includeInlayVariableTypeHints = true, + includeInlayPropertyDeclarationTypeHints = true, + includeInlayFunctionLikeReturnTypeHints = true, + includeInlayEnumMemberValueHints = true, + }, + }, + }, +}) +vim.lsp.enable("ts_ls") + +-- rust +vim.lsp.config("rust_analyzer", { + settings = { + ["rust-analyzer"] = { + diagnostics = { + enable = true, + experimental = { enable = true }, + }, + }, + }, +}) +vim.lsp.enable("rust_analyzer") + +-- lua +vim.lsp.config("lua_ls", { + settings = { + Lua = { + diagnostics = { + disable = { + "missing-fields", + "undefined-global", + }, + }, + }, + }, +}) +vim.lsp.enable("lua_ls") + +-- python +vim.lsp.config("basedpyright", { + settings = { + basedpyright = { + inlayHints = true, + disableDiagnostics = true, + disableOrganizeImports = true, + analysis = { + -- Ignore all files for analysis to exclusively use Ruff for linting + -- Enable diagnostics + -- ignore = { "*" }, + diagnosticSeverityOverrides = { + reportUnusedImport = "none", + reportUnusedVariable = "none", + reportAttributeAccessIssue = "none", + reportUnusedClass = "none", + reportUnusedFunction = "none", + reportDuplicateImport = "none", + reportArgumentType = "error", + }, + typeCheckingMode = "basic", + }, + }, + }, +}) +vim.lsp.enable("basedpyright") + +vim.lsp.config("pylsp", { + settings = { + pylsp = { + plugins = { + -- use black as default formatter + yapf = { enabled = false }, + autopep8 = { enabled = false }, + black = { enabled = true }, + pycodestyle = { + enabled = true, + ignore = { "E203", "E701", "W503" }, + maxLineLength = 88, + }, + }, + }, + }, +}) + +-- latex +vim.lsp.config("texlab", { + settings = { + texlab = { + build = { + executable = "latexmk", + args = { + "-lualatex", + "-interaction=nonstopmode", + "-outdir=build", + }, + onSave = true, + }, + }, + }, +}) +vim.lsp.enable("texlab") + +-- bash +vim.lsp.config("bashls", { + settings = { + bashIde = { + shellcheckArguments = { + "--exclude=SC1090,SC1091,SC2076,SC2164", + }, + }, + }, +}) +vim.lsp.enable("bashls") + +-- cpp +vim.lsp.config("clangd", { + cmd = { + "clangd", + "--fallback-style=llvm", + "--header-insertion=iwyu", + "-j=4", + }, +}) +vim.lsp.enable("clangd") diff --git a/lua/core/options.lua b/lua/core/options.lua index aa89df5..9402696 100644 --- a/lua/core/options.lua +++ b/lua/core/options.lua @@ -1,91 +1,64 @@ local options = { - ai = true, - autoindent = true, - autowrite = true, - backspace = 'indent,eol,start', - backup = false, -- creates a backup file - breakindent = true, - clipboard = 'unnamedplus', -- allows neovim to access the system clipboard - cmdheight = 1, -- more space in the neovim command line for displaying messages - completeopt = 'menu,menuone,noselect', -- mostly just for cmp - conceallevel = 0, -- so that `` is visible in markdown files - confirm = true, -- Confirm to save changes before exiting modified buffer - cursorline = true, -- highlight the current line - expandtab = true, -- convert tabs to spaces - fileencoding = 'utf-8', -- the encoding written to a file - formatoptions = 'jlnqt', -- set formatoptions, check help fo-table - grepformat = '%f:%l:%c:%m', - grepprg = 'rg --vimgrep', - hlsearch = true, -- highlight all matches on previous search pattern - ignorecase = true, -- ignore case in search patterns - inccommand = 'split', -- preview incremental substitute - laststatus = 3, - list = true, - -- listchars = { trail = '', tab = '', nbsp = '_', extends = '>', precedes = '<' }, -- highlight - mouse = 'a', -- allow the mouse to be used in neovim - number = true, -- set numbered lines - numberwidth = 4, -- set number column width to 2 {default 4} - pumblend = 10, -- Popup blen - pumheight = 10, -- pop up menu height - relativenumber = true, -- set relative numbered lines - scrolloff = 10, -- is one of my fav - sessionoptions = 'blank,buffers,curdir,folds,help,tabpages,winsize,winpos,terminal', - shiftround = true, -- Round indent - shiftwidth = 4, -- the number of spaces inserted for each indentation - showcmd = false, - showmode = false, -- we don't need to see things like -- INSERT -- anymore - showtabline = 0, -- always show tabs - si = true, - sidescrolloff = 8, - signcolumn = 'yes', -- always show the sign column, otherwise it would shift the text each time - smartcase = true, -- smart case - smartindent = true, -- make indenting smarter again - smarttab = true, - splitbelow = true, -- force all horizontal splits to go below current window - splitright = true, -- force all vertical splits to go to the right of current window - swapfile = false, -- creates a swapfile - tabstop = 4, -- insert 2 spaces for a tab - termguicolors = true, -- set term gui colors (most terminals support this) - timeoutlen = 300, -- time to wait for a mapped sequence to complete (in milliseconds) - title = true, -- window titles - undofile = true, -- enable persistent undo - undodir = vim.fn.stdpath('cache') .. '/undo', - undolevels = 10000, - updatetime = 250, -- balance between responsiveness and performance - wildmenu = true, -- wildmenu - wildmode = 'longest:full,full', -- Command-line completion mode - winminwidth = 5, -- Minimum window width - wrap = false, -- display lines as one long line - writebackup = false, -- do not edit backups + ai = true, + clipboard = "unnamedplus", -- use system clipboard + number = true, + relativenumber = true, + undofile = true, -- save state of file on write + undodir = vim.fn.stdpath("cache") .. "/undo", + undolevels = 10000, + autoread = true, -- autoread changes from other sources + signcolumn = "yes", + cursorline = true, + cursorlineopt = "number", + wrap = false, + scrolloff = 3, + ruler = false, -- removes cursor position from lastline + pumheight = 10, -- size of completion window + showmode = false, -- do not show mode under statusline + swapfile = false, -- creates a swapfile + backup = false, -- creates a backup file + writebackup = false, -- do not edit backups + winminwidth = 5, -- Minimum window width + termguicolors = true, -- set term gui colors (most terminals support this) + showtabline = 0, -- always show tabs + showcmd = false, + mouse = "a", -- allow the mouse to be used in neovim + confirm = true, -- Confirm to save changes before exiting modified buffer + + -- tabs + smarttab = true, + tabstop = 4, -- 1 tab represented as 4 spaces + expandtab = true, -- key will create " " instead of "\t" + shiftwidth = 4, -- indent change after backspace and >> << + softtabstop = 4, -- number of spaces instead of tab + autoindent = true, -- auto indent + smartindent = true, -- make indenting smarter again + list = true, + -- listchars = { trail = "", tab = "", nbsp = "_", extends = ">", precedes = "<" }, -- highlight + showbreak = string.rep(" ", 3), + + -- Search + ignorecase = true, + smartcase = true, + hlsearch = true, + wildmenu = true, + wildmode = "longest:full,full", + wildoptions = "pum", + + -- Window + splitright = true, + splitbelow = true, + title = true, } for k, v in pairs(options) do - vim.opt[k] = v + vim.opt[k] = v end --- netrw file explorer settings -vim.g.netrw_winsize = 20 -vim.g.netrw_banner = 0 -vim.g.netrw_liststyle = 1 +vim.opt.path:append({ "**" }) +vim.opt.shortmess:append({ W = true, I = true, c = true }) -- disable greeting -- Fix markdown indentation settings vim.g.markdown_recommended_style = 0 -vim.opt.path:append({ '**' }) -vim.opt.shortmess:append({ W = true, I = true, c = true }) - --- hides `~` at the end of the buffer vim.cmd([[set fillchars+=eob:\ ]]) - -vim.cmd([[ - setlocal spell spelllang=en "Set spellcheck language to en - setlocal spell! "Disable spell checks by default - filetype plugin indent on - if has('win32') - let g:python3_host_prog = $HOME . '/scoop/apps/python/current/python.exe' - endif - let &t_Cs = "\e[4:3m" "Undercurl - let &t_Ce = "\e[4:0m" - set whichwrap+=<,>,[,],h,l - set iskeyword+=- - ]]) diff --git a/lua/lib/icons.lua b/lua/lib/icons.lua deleted file mode 100644 index d2f2d15..0000000 --- a/lua/lib/icons.lua +++ /dev/null @@ -1,167 +0,0 @@ -return { - diagnostics = { - Error = ' ', - Hint = '󰠠 ', - Information = ' ', - Question = ' ', - Warning = ' ', - }, - documents = { - File = ' ', - FileEmpty = ' ', - Files = ' ', - Folder = ' ', - FolderEmpty = ' ', - OpenFolder = ' ', - OpenFolderEmpty = ' ', - SymLink = ' ', - SymlinkFolder = ' ', - Import = ' ', - }, - git = { - Add = ' ', - AddAlt = ' ', - Branch = ' ', - Diff = ' ', - DiffAlt = ' ', - Ignore = '◌ ', - Mod = ' ', - Octoface = ' ', - Remove = ' ', - RemoveAlt = ' ', - Rename = ' ', - Repo = ' ', - Tag = ' ', - Untrack = ' ', - Directory = '', - }, - kind = { - Class = ' ', - Color = ' ', - Constant = ' ', - Constructor = '󰈏 ', - Copilot = ' ', - Enum = ' ', - EnumMember = ' ', - Event = ' ', - Field = ' ', - File = ' ', - Folder = ' ', - Function = '󰊕 ', - Interface = ' ', - Keyword = ' ', - Method = ' ', - Module = '', - Operator = ' ', - Property = ' ', - Reference = ' ', - Snippet = ' ', - Struct = ' ', - Text = ' ', - TypeParameter = ' ', - Unit = ' ', - Value = ' ', - Variable = ' ', - }, - type = { - Array = ' ', - Boolean = '⏻ ', - Number = ' ', - Object = ' ', - String = ' ', - }, - ui = { - Arrow = ' ', - ArrowClosed = ' ', - ArrowLeft = ' ', - ArrowOpen = ' ', - ArrowRight = ' ', - Bluetooth = ' ', - Bookmark = ' ', - Bug = ' ', - Calendar = ' ', - Camera = ' ', - Check = ' ', - ChevronRight = '', - Circle = ' ', - CircleSmall = '● ', - CircleSmallEmpty = '○ ', - Clipboard = ' ', - Close = ' ', - Code = ' ', - Collection = ' ', - Color = ' ', - Command = ' ', - Comment = ' ', - Copilot = ' ', - CopilotError = ' ', - Corner = '└ ', - Dashboard = ' ', - Database = ' ', - Download = ' ', - Edit = ' ', - Edge = '│ ', - Electric = ' ', - Eye = ' ', - Fire = ' ', - Firefox = ' ', - Flag = ' ', - Game = ' ', - Gear = ' ', - GitHub = ' ', - Heart = ' ', - History = ' ', - Home = ' ', - Incoming = ' ', - Jump = ' ', - Keyboard = ' ', - Ligthbulb = '󰌵 ', - List = '', - Lock = ' ', - Minus = '‒ ', - Music = '󰝚 ', - Neovim = ' ', - NewFile = ' ', - None = ' ', - Note = ' ', - Outgoing = ' ', - Package = ' ', - Paint = ' ', - Pause = ' ', - Pencil = ' ', - Person = ' ', - Pin = ' ', - Play = ' ', - Plug = ' ', - Plus = ' ', - Power = ' ', - PowerlineArrowLeft = '', - PowerlineArrowRight = '', - PowerlineLeftRound = '', - PowerlineRightRound = '', - Project = ' ', - Question = ' ', - Reload = ' ', - Rocket = ' ', - Save = '󰆓 ', - Search = ' ', - Separator = '▊ ', - SeparatorLight = '▍', - SeparatorDashed = '┆', - SignIn = ' ', - SignOut = ' ', - Sleep = '󰒲 ', - Star = ' ', - Table = ' ', - Telescope = ' ', - Terminal = ' ', - Test = ' ', - Time = ' ', - Topline = '‾', - Trash = ' ', - User = ' ', - Vim = ' ', - Wifi = ' ', - Windows = ' ', - }, -} diff --git a/lua/lib/prompts.lua b/lua/lib/prompts.lua deleted file mode 100644 index 725557f..0000000 --- a/lua/lib/prompts.lua +++ /dev/null @@ -1,21 +0,0 @@ -local prompts = { - docs = 'Generate comprehensive documentation for this code including parameters, return values, and usage examples.', - explain = 'Explain this code in detail, including its purpose, logic flow, and any algorithms used.', - fix = 'Identify and fix any bugs, errors, or code smells in this code.', - commit = 'Create a descriptive commit message following conventional commits format for these changes.', - optimize = 'Optimize this code for better performance, readability, and maintainability.', - review = 'Review this code for best practices, potential issues, and suggest improvements.', - tests = 'Write comprehensive unit tests covering all edge cases for this code.', -} - ----Returns a function that inserts the named prompt at cursor position ----@param prompt_name string Name of the prompt to insert ----@return function Function to execute in a keybinding -prompts.add_prompt = function(prompt_name) - local prompt_text = prompts[prompt_name] - return function() - vim.cmd("put ='" .. prompt_text:gsub("'", "''") .. "'") - end -end - -return prompts diff --git a/lua/lib/util.lua b/lua/lib/util.lua deleted file mode 100644 index 1687021..0000000 --- a/lua/lib/util.lua +++ /dev/null @@ -1,65 +0,0 @@ -local util = {} - -util.get_user_config = function(key, default) - local status_ok, user = pcall(require, 'user') - if not status_ok then - return default - end - - local user_config = user[key] - if user_config == nil then - return default - end - return user_config -end - -util.get_root_dir = function() - local bufname = vim.fn.expand('%:p') - if vim.fn.filereadable(bufname) == 0 then - return - end - - local parent = vim.fn.fnamemodify(bufname, ':h') - local git_root = vim.fn.systemlist('git -C ' .. parent .. ' rev-parse --show-toplevel') - if #git_root > 0 and git_root[1] ~= '' then - return git_root[1] - else - return parent - end -end - -util.get_file_path = function() - local buf_name = vim.api.nvim_buf_get_name(0) - if vim.fn.filereadable(buf_name) == 1 then - return buf_name - end - - local dir_name = vim.fn.fnamemodify(buf_name, ':p:h') - if vim.fn.isdirectory(dir_name) == 1 then - return dir_name - end - - return vim.loop.cwd() -end - -util.get_file_type_cmd = function(extension) - local root = util.get_root_dir() - - if extension == 'arb' and root then - local gemfile_exists = vim.fn.filereadable(root .. '/Gemfile') == 1 - local pubspec_exists = vim.fn.filereadable(root .. '/pubspec.yaml') == 1 - if gemfile_exists then - return 'setfiletype ruby' - end - if pubspec_exists then - return 'setfiletype json' - end - end - return '' -end - -util.is_present = function(bin) - return vim.fn.executable(bin) == 1 -end - -return util diff --git a/lua/plugins/ai.lua b/lua/plugins/ai.lua new file mode 100644 index 0000000..67a7e69 --- /dev/null +++ b/lua/plugins/ai.lua @@ -0,0 +1,14 @@ +return { + { + "Exafunction/windsurf.vim", + event = "VeryLazy", + config = function() + vim.keymap.set("i", "", function() + return vim.fn["codeium#Accept"]() + end, { expr = true, silent = true }) + vim.keymap.set("i", "", function() + return vim.fn["codeium#Clear"]() + end, { expr = true, silent = true }) + end, + }, +} diff --git a/lua/plugins/ai/avante.lua b/lua/plugins/ai/avante.lua deleted file mode 100644 index 254b35b..0000000 --- a/lua/plugins/ai/avante.lua +++ /dev/null @@ -1,166 +0,0 @@ -local avante = require('avante') - -local model_names = { - 'claude-3.5-sonnet', - 'claude-3.7-sonnet', - 'claude-3.7-sonnet-thought', - 'claude-sonnet-4', - 'gemini-2.0-flash-001', - 'gemini-2.5-pro', - 'gpt-4.1', - 'gpt-4o-2024-11-20', - 'o1', - 'o3-mini', - 'o4-mini', -} - -avante.setup({ - mode = 'agentic', - provider = 'copilot-gpt-4.1', - -- cursor_applying_provider = 'copilot-o3-mini', - -- auto_suggestions_provider = 'copilot-claude-3.7-sonnet', - - providers = (function() - local providers_table = { - copilot = { - endpoint = 'https://api.githubcopilot.com', - allow_insecure = false, - timeout = 10 * 60 * 1000, - extra_request_body = { - temperature = 0, - max_completion_tokens = 1000000, - reasoning_effort = 'high', - }, - }, - } - for _, model_name in ipairs(model_names) do - local provider_key = 'copilot-' .. model_name - providers_table[provider_key] = { - __inherited_from = 'copilot', - model = model_name, - display_name = provider_key, - } - end - - return providers_table - end)(), - - behaviour = { - auto_suggestions = false, - auto_set_highlight_group = true, - auto_set_keymaps = true, - auto_apply_diff_after_generation = false, - support_paste_from_clipboard = false, - minimize_diff = true, -- Whether to remove unchanged lines when applying a code block - enable_token_counting = true, - }, - hints = { enabled = false }, - mappings = { - ---@class AvanteConflictMappings - diff = { - ours = 'co', - theirs = 'ct', - all_theirs = 'ca', - both = 'cb', - cursor = 'cc', - next = ']x', - prev = '[x', - }, - suggestion = { - accept = '', - next = '', - prev = '', - dismiss = '', - }, - jump = { - next = ']]', - prev = '[[', - }, - submit = { - normal = '', - insert = '', - }, - cancel = { - normal = { '', '', 'q' }, - insert = { '' }, - }, - ask = 'aa', - edit = 'ae', - refresh = 'ar', - focus = 'af', - stop = 'as', - select_model = 'aM', - select_history = 'ah', - files = { - add_current = 'ac', - add_all_buffers = 'ab', - }, - toggle = { - default = 'at', - debug = 'ad', - hint = 'aH', - suggestion = 'aS', - repomap = 'aR', - }, - sidebar = { - apply_all = 'A', - apply_cursor = 'a', - retry_user_request = 'r', - edit_user_request = 'e', - switch_windows = '', - reverse_switch_windows = '', - remove_file = 'd', - add_file = 'a', - close = { 'q' }, - close_from_input = nil, -- e.g., { normal = "", insert = "" } - }, - }, - windows = { - ---@type "right" | "left" | "top" | "bottom" - position = 'right', - wrap = true, - width = 40, - sidebar_header = { - enabled = true, - align = 'center', - rounded = true, - }, - input = { - prefix = '> ', - height = 32, - }, - edit = { - border = 'rounded', - start_insert = true, - }, - ask = { - floating = false, - start_insert = true, - border = 'rounded', - ---@type "ours" | "theirs" - focus_on_apply = 'ours', - }, - }, - highlights = { - diff = { - current = 'DiffText', - incoming = 'DiffAdd', - }, - }, - --- @class AvanteConflictUserConfig - diff = { - autojump = true, - ---@type string | fun(): any - list_opener = 'copen', - override_timeoutlen = 500, - }, - suggestion = { - debounce = 600, - throttle = 600, - }, - disabled_tools = { - 'replace_in_file', - 'web_search', - }, - slash_commands = {}, -}) diff --git a/lua/plugins/ai/copilot.lua b/lua/plugins/ai/copilot.lua deleted file mode 100644 index 31ad413..0000000 --- a/lua/plugins/ai/copilot.lua +++ /dev/null @@ -1,45 +0,0 @@ -local copilot = require('copilot') - -copilot.setup({ - panel = { - enabled = true, - auto_refresh = false, - keymap = { - jump_prev = '[[', - jump_next = ']]', - accept = '', - refresh = 'gr', - open = '', - }, - layout = { - position = 'bottom', - ratio = 0.4, - }, - }, - suggestion = { - enabled = true, - auto_trigger = false, - debounce = 75, - keymap = { - accept = '', - accept_word = false, - accept_line = false, - next = '', - prev = '', - dismiss = '', - }, - }, - filetypes = { - yaml = true, - markdown = true, - help = true, - gitcommit = true, - gitrebase = true, - hgcommit = true, - svn = true, - cvs = true, - ['.'] = true, - }, - copilot_node_command = 'node', -- Node.js version must be > 16.x - server_opts_overrides = {}, -}) diff --git a/lua/plugins/colorscheme.lua b/lua/plugins/colorscheme.lua new file mode 100644 index 0000000..4bf3efe --- /dev/null +++ b/lua/plugins/colorscheme.lua @@ -0,0 +1,39 @@ +return { + "ellisonleao/gruvbox.nvim", + priority = 1000, + config = function() + local palette = require("gruvbox").palette + require("gruvbox").setup({ + bold = false, + italic = { + strings = false, + emphasis = false, + comments = false, + folds = false, + }, + contrast = "hard", + transparent_mode = true, + overrides = { + -- builtin + SignColumn = { bg = "None" }, + CursorLineNr = { bg = "None" }, + Whitespace = { fg = palette.dark0 }, + EndOfBuffer = { fg = palette.dark0_hard }, + Visual = { fg = "None", bg = palette.dark1 }, + Label = { link = "GruvboxPurple" }, + + -- blink.cmp + BlinkCmpMenu = { link = "Normal" }, + BlinkCmpMenuBorder = { link = "BlinkCmpMenu" }, + BlinkCmpMenuSelection = { fg = "None", bg = palette.dark1 }, + BlinkCmpLabelMatch = { fg = palette.bright_green }, + BlinkCmpScrollBarGutter = { bg = palette.dark2 }, + BlinkCmpScrollBarThumb = { bg = palette.light1 }, + + -- indent guides + MiniIndentscopeSymbol = { fg = palette.dark1 }, + }, + }) + vim.cmd.colorscheme("gruvbox") + end, +} diff --git a/lua/plugins/completion.lua b/lua/plugins/completion.lua new file mode 100644 index 0000000..fe5384e --- /dev/null +++ b/lua/plugins/completion.lua @@ -0,0 +1,58 @@ +return { + -- snippets + { + "L3MON4D3/LuaSnip", + version = "*", + dependencies = { "rafamadriz/friendly-snippets" }, + config = function() + require("luasnip.loaders.from_vscode").lazy_load() + end, + }, + + -- completion + { + "saghen/blink.cmp", + version = "*", + dependencies = { + "L3MON4D3/LuaSnip", + }, + config = function() + require("blink.cmp").setup({ + completion = { + list = { + selection = { + preselect = false, + auto_insert = true, + }, + }, + documentation = { + window = { border = "rounded" }, + auto_show = true, + auto_show_delay_ms = 50, + }, + menu = { + border = "rounded", + }, + }, + signature = { + window = { border = "rounded" }, + }, + sources = { + default = { "lsp", "path", "snippets", "buffer" }, + providers = {}, + }, + snippets = { preset = "luasnip" }, + keymap = { + preset = "none", + [""] = { "select_prev", "snippet_backward", "fallback" }, + [""] = { "select_next", "snippet_forward", "fallback" }, + [""] = { "accept", "fallback" }, + [""] = { "hide", "show" }, + [""] = { "show", "show_documentation", "hide_documentation" }, + [""] = { "scroll_documentation_up", "fallback" }, + [""] = { "scroll_documentation_down", "fallback" }, + }, + }) + end, + }, +} diff --git a/lua/plugins/editor.lua b/lua/plugins/editor.lua new file mode 100644 index 0000000..3e7edeb --- /dev/null +++ b/lua/plugins/editor.lua @@ -0,0 +1,170 @@ +return { + -- surround actions + { + "nvim-mini/mini.surround", + version = "*", + config = function() + require("mini.surround").setup() + end, + }, + + -- indent guides + { + "nvim-mini/mini.indentscope", + event = "VeryLazy", + config = function() + require("mini.indentscope").setup({ + draw = { + delay = 50, + animation = require("mini.indentscope").gen_animation.linear({ + ease = "out", + duration = 15, + }), + }, + options = { + border = "top", + try_as_border = true, + indent_at_cursor = false, + }, + }) + + -- disable for certain filetypes + vim.api.nvim_create_autocmd("BufEnter", { + pattern = "*", + callback = function(args) + if vim.bo[args.buf].buftype ~= "" then + vim.b[args.buf].miniindentscope_disable = true + end + end, + }) + end, + }, + + -- Go forward/backward with square brackets + { + "echasnovski/mini.bracketed", + event = { "BufReadPost", "BufNewFile" }, + config = function() + require("mini.bracketed").setup() + end, + }, + + -- textobjects + { + "nvim-mini/mini.ai", + version = "*", + config = function() + require("mini.ai").setup({ + silent = true, + }) + end, + }, + + -- hiding colorcolumn when unneeded. + { + "m4xshen/smartcolumn.nvim", + opts = { + disabled_filetypes = { + "netrw", + "NvimTree", + "Lazy", + "mason", + "help", + "text", + "markdown", + "tex", + "html", + }, + custom_colorcolumn = { lua = "90", python = "100" }, + scope = "window", + }, + }, + + -- Dimming the highlights of unused functions, variables, parameters, and more. + { + "zbirenbaum/neodim", + enabled = false, + event = "LspAttach", + config = function() + require("neodim").setup({ + alpha = 0.5, + blend_color = nil, + hide = { + underline = true, + virtual_text = true, + signs = true, + }, + regex = { + "[uU]nused", + "[nN]ever [rR]ead", + "[nN]ot [rR]ead", + }, + priority = 128, + disable = {}, + }) + end, + }, + + { + "numToStr/Comment.nvim", + version = false, + dependencies = { + "JoosepAlviste/nvim-ts-context-commentstring", + }, + config = function() + require("Comment").setup({ + pre_hook = require("ts_context_commentstring.integrations.comment_nvim").create_pre_hook(), + mappings = { + basic = true, + extra = true, + }, + }) + end, + keys = { + { "gcc", mode = "n", desc = "Toggle comment line" }, + { "gc", mode = { "n", "o" }, desc = "Toggle comment linewise" }, + { "gc", mode = "x", desc = "Toggle comment linewise (visual)" }, + { "gbc", mode = "n", desc = "Toggle comment block" }, + { "gb", mode = { "n", "o" }, desc = "Toggle comment blockwise" }, + { "gb", mode = "x", desc = "Toggle comment blockwise (visual)" }, + { "/", "lua require('Comment.api').toggle.linewise.current()", desc = "Toggle comment" }, + { + "/", + "lua require('Comment.api').toggle.linewise(vim.fn.visualmode())", + desc = "Toggle comment", + mode = "v", + }, + }, + opts = {}, + }, + + -- Todo Comments + { + "folke/todo-comments.nvim", + event = "BufRead", + opts = {}, + }, + + -- inline diagnostic + { + "rachartier/tiny-inline-diagnostic.nvim", + event = "VeryLazy", + priority = 1000, + config = function() + require("tiny-inline-diagnostic").setup() + vim.diagnostic.config({ virtual_text = false }) -- Disable default virtual text + end, + }, + + -- multiple cursor + -- { + -- "terryma/vim-multiple-cursors", + -- config = function() + -- vim.g.multi_cursor_use_default_mapping = 0 + -- vim.g.multi_cursor_next_key = "" + -- vim.g.multi_cursor_prev_key = "" + -- vim.g.multi_cursor_skip_key = "" + -- vim.g.multi_cursor_quit_key = "mc" + -- end, + -- }, +} diff --git a/lua/plugins/editor/ai.lua b/lua/plugins/editor/ai.lua deleted file mode 100644 index 45f69d4..0000000 --- a/lua/plugins/editor/ai.lua +++ /dev/null @@ -1,35 +0,0 @@ -local ai = require('mini.ai') - -ai.setup({ - custom_textobjects = { - o = ai.gen_spec.treesitter({ - a = { '@block.outer', '@conditional.outer', '@loop.outer' }, - i = { '@block.inner', '@conditional.inner', '@loop.inner' }, - }, {}), - f = ai.gen_spec.treesitter({ a = '@function.outer', i = '@function.inner' }, {}), - c = ai.gen_spec.treesitter({ a = '@class.outer', i = '@class.inner' }, {}), - t = { '<([%p%w]-)%f[^<%w][^<>]->.-', '^<.->().*()$' }, - }, - - mappings = { - -- Main textobject prefixes - around = 'a', - inside = 'i', - - -- Next/last variants - around_next = 'an', - inside_next = 'in', - around_last = 'al', - inside_last = 'il', - - -- Move cursor to corresponding edge of `a` textobject - goto_left = 'g[', - goto_right = 'g]', - }, - - -- How to search for object - -- 'cover', 'cover_or_next', 'cover_or_prev','cover_or_nearest', 'next', 'previous', 'nearest'. - search_method = 'cover_or_next', - n_lines = 500, - silent = false, -}) diff --git a/lua/plugins/editor/bracketed.lua b/lua/plugins/editor/bracketed.lua deleted file mode 100644 index 24b3034..0000000 --- a/lua/plugins/editor/bracketed.lua +++ /dev/null @@ -1,18 +0,0 @@ -local bracketed = require('mini.bracketed') - -bracketed.setup({ - buffer = { suffix = 'b', options = {} }, - comment = { suffix = 'c', options = {} }, - conflict = { suffix = 'x', options = {} }, - diagnostic = { suffix = 'd', options = {} }, - file = { suffix = 'f', options = {} }, - indent = { suffix = 'i', options = {} }, - jump = { suffix = 'j', options = {} }, - location = { suffix = 'l', options = {} }, - oldfile = { suffix = 'r', options = {} }, - quickfix = { suffix = 'q', options = {} }, - treesitter = { suffix = 'n', options = {} }, - undo = { suffix = 'u', options = {} }, - window = { suffix = 'w', options = {} }, - yank = { suffix = 'y', options = {} }, -}) diff --git a/lua/plugins/editor/pairs.lua b/lua/plugins/editor/pairs.lua deleted file mode 100644 index 29b6351..0000000 --- a/lua/plugins/editor/pairs.lua +++ /dev/null @@ -1,18 +0,0 @@ -local pairs = require('mini.pairs') - -pairs.setup({ - modes = { insert = true, command = true, terminal = false }, - mappings = { - ['('] = { action = 'open', pair = '()', neigh_pattern = '[^\\].' }, - ['['] = { action = 'open', pair = '[]', neigh_pattern = '[^\\].' }, - ['{'] = { action = 'open', pair = '{}', neigh_pattern = '[^\\].' }, - - [')'] = { action = 'close', pair = '()', neigh_pattern = '[^\\].' }, - [']'] = { action = 'close', pair = '[]', neigh_pattern = '[^\\].' }, - ['}'] = { action = 'close', pair = '{}', neigh_pattern = '[^\\].' }, - - ['"'] = { action = 'closeopen', pair = '""', neigh_pattern = '[^\\].', register = { cr = false } }, - ["'"] = { action = 'closeopen', pair = "''", neigh_pattern = '[^%a\\].', register = { cr = false } }, - ['`'] = { action = 'closeopen', pair = '``', neigh_pattern = '[^\\].', register = { cr = false } }, - }, -}) diff --git a/lua/plugins/editor/spider.lua b/lua/plugins/editor/spider.lua deleted file mode 100644 index 77a12b0..0000000 --- a/lua/plugins/editor/spider.lua +++ /dev/null @@ -1,10 +0,0 @@ -local spider = require('spider') - -spider.setup({ - skipInsignificantPunctuation = true, -}) - -vim.keymap.set({ 'n', 'o', 'x' }, 'w', "lua require('spider').motion('w')", { desc = 'Spider-w' }) -vim.keymap.set({ 'n', 'o', 'x' }, 'e', "lua require('spider').motion('e')", { desc = 'Spider-e' }) -vim.keymap.set({ 'n', 'o', 'x' }, 'b', "lua require('spider').motion('b')", { desc = 'Spider-b' }) -vim.keymap.set({ 'n', 'o', 'x' }, 'ge', "lua require('spider').motion('ge')", { desc = 'Spider-ge' }) diff --git a/lua/plugins/editor/surround.lua b/lua/plugins/editor/surround.lua deleted file mode 100644 index 97a2f0d..0000000 --- a/lua/plugins/editor/surround.lua +++ /dev/null @@ -1,25 +0,0 @@ -local surround = require('mini.surround') - -surround.setup({ - custom_surroundings = nil, - mappings = { - add = 'gsa', - delete = 'gsd', - find = 'gsf', - find_left = 'gsF', - highlight = 'gsh', - replace = 'gsr', - update_n_lines = 'gsn', - - suffix_last = 'l', -- Suffix to search with "prev" method - suffix_next = 'n', -- Suffix to search with "next" method - }, - - -- How to search for surrounding - -- 'cover', 'cover_or_next', 'cover_or_prev','cover_or_nearest', 'next', 'previous', 'nearest'. - search_method = 'cover', - highlight_duration = 300, - n_lines = 20, - respect_selection_type = false, - silent = false, -}) diff --git a/lua/plugins/editor/textobjects.lua b/lua/plugins/editor/textobjects.lua deleted file mode 100644 index d7e565d..0000000 --- a/lua/plugins/editor/textobjects.lua +++ /dev/null @@ -1,116 +0,0 @@ -local textobjects = { - select = { - enable = true, - lookahead = true, - - keymaps = { - ['a='] = { query = '@assignment.outer', desc = 'Select outer part of an assignment' }, - ['i='] = { query = '@assignment.inner', desc = 'Select inner part of an assignment' }, - ['al='] = { query = '@assignment.lhs', desc = 'Select left hand side of an assignment' }, - ['ar='] = { - query = '@assignment.rhs', - desc = 'Select right hand side of an assignment', - }, - - ['a:'] = { query = '@property.outer', desc = 'Select outer part of an object property' }, - ['i:'] = { query = '@property.inner', desc = 'Select inner part of an object property' }, - ['l:'] = { query = '@property.lhs', desc = 'Select left part of an object property' }, - ['r:'] = { query = '@property.rhs', desc = 'Select right part of an object property' }, - - ['aa'] = { - query = '@parameter.outer', - desc = 'Select outer part of a parameter/argument', - }, - ['ia'] = { - query = '@parameter.inner', - desc = 'Select inner part of a parameter/argument', - }, - - ['ai'] = { query = '@conditional.outer', desc = 'Select outer part of a conditional' }, - ['ii'] = { query = '@conditional.inner', desc = 'Select inner part of a conditional' }, - - ['al'] = { query = '@loop.outer', desc = 'Select outer part of a loop' }, - ['il'] = { query = '@loop.inner', desc = 'Select inner part of a loop' }, - - ['af'] = { query = '@call.outer', desc = 'Select outer part of a function call' }, - ['if'] = { query = '@call.inner', desc = 'Select inner part of a function call' }, - - ['am'] = { - query = '@function.outer', - desc = 'Select outer part of a method/function definition', - }, - ['im'] = { - query = '@function.inner', - desc = 'Select inner part of a method/function definition', - }, - - ['ac'] = { query = '@class.outer', desc = 'Select outer part of a class' }, - ['ic'] = { query = '@class.inner', desc = 'Select inner part of a class' }, - }, - }, - swap = { - enable = true, - swap_next = { - ['rna'] = '@parameter.inner', -- swap object property with next - ['rn:'] = '@property.outer', -- swap parameters/argument with next - ['rnm'] = '@function.outer', -- swap function with next - }, - swap_previous = { - ['rpa'] = '@parameter.inner', -- swap parameters/argument with prev - ['rp:'] = '@property.outer', -- swap object property with prev - ['rpm'] = '@function.outer', -- swap function with previous - }, - }, - move = { - enable = true, - set_jumps = true, -- whether to set jumps in the jumplist - goto_previous_start = { - ['[oc'] = { query = '@class.outer', desc = 'Prev class start' }, - ['[of'] = { query = '@call.outer', desc = 'Prev function call start' }, - ['[oi'] = { query = '@conditional.outer', desc = 'Prev conditional start' }, - ['[ol'] = { query = '@loop.outer', desc = 'Prev loop start' }, - ['[om'] = { query = '@function.outer', desc = 'Prev method def start' }, - ['[z'] = { query = '@fold', query_group = 'folds', desc = 'Prev fold' }, - -- You can pass a query group to use query from `queries//.scm file in your runtime path. - -- Above example nvim-treesitter's folds.scm`. They also provide locals.scm, highlights.scm and indent.scm. - }, - goto_previous_end = { - ['[oC'] = { query = '@class.outer', desc = 'Prev class end' }, - ['[oF'] = { query = '@call.outer', desc = 'Prev function call end' }, - ['[oI'] = { query = '@conditional.outer', desc = 'Prev conditional end' }, - ['[oL'] = { query = '@loop.outer', desc = 'Prev loop end' }, - ['[oM'] = { query = '@function.outer', desc = 'Prev method def end' }, - ['[Z'] = { query = '@fold', query_group = 'folds', desc = 'Prev fold end' }, - }, - goto_next_start = { - [']oc'] = { query = '@class.outer', desc = 'Next class start' }, - [']of'] = { query = '@call.outer', desc = 'Next function call start' }, - [']oi'] = { query = '@conditional.outer', desc = 'Next conditional start' }, - [']ol'] = { query = '@loop.outer', desc = 'Next loop start' }, - [']om'] = { query = '@function.outer', desc = 'Next method def start' }, - [']z'] = { query = '@fold', query_group = 'folds', desc = 'Next fold' }, - }, - goto_next_end = { - [']oC'] = { query = '@class.outer', desc = 'Next class end' }, - [']oF'] = { query = '@call.outer', desc = 'Next function call end' }, - [']oI'] = { query = '@conditional.outer', desc = 'Next conditional end' }, - [']oL'] = { query = '@loop.outer', desc = 'Next loop end' }, - [']oM'] = { query = '@function.outer', desc = 'Next method def end' }, - [']Z'] = { query = '@fold', query_group = 'folds', desc = 'Next fold end' }, - }, - }, -} - -local ts_repeat_move = require('nvim-treesitter.textobjects.repeatable_move') - --- vim way: ; goes to the direction you were moving. -vim.keymap.set({ 'n', 'x', 'o' }, ';', ts_repeat_move.repeat_last_move) -vim.keymap.set({ 'n', 'x', 'o' }, ',', ts_repeat_move.repeat_last_move_opposite) - --- Optionally, make builtin f, F, t, T also repeatable with ; and , -vim.keymap.set({ 'n', 'x', 'o' }, 'f', ts_repeat_move.builtin_f) -vim.keymap.set({ 'n', 'x', 'o' }, 'F', ts_repeat_move.builtin_F) -vim.keymap.set({ 'n', 'x', 'o' }, 't', ts_repeat_move.builtin_t) -vim.keymap.set({ 'n', 'x', 'o' }, 'T', ts_repeat_move.builtin_T) - -return textobjects diff --git a/lua/plugins/editor/treesitter.lua b/lua/plugins/editor/treesitter.lua deleted file mode 100644 index 29ad6dc..0000000 --- a/lua/plugins/editor/treesitter.lua +++ /dev/null @@ -1,81 +0,0 @@ -local treesitter = require('nvim-treesitter.configs') -local textobjects = require('plugins.editor.textobjects') - -local auto_install = require('lib.util').get_user_config('auto_install', true) -local installed_parsers = {} -if auto_install then - installed_parsers = require('plugins.list').ts_parsers -end - -treesitter.setup({ - ensure_installed = installed_parsers, - sync_install = false, - ignore_install = {}, - auto_install = true, - - textobjects = textobjects, - matchup = { enable = true }, - indent = { enable = true }, - - highlight = { - enable = true, - disable = function(lang, buf) - local max_filesize = 1000 * 1024 -- 1 MB instead of 100 KB - local ok, stats = pcall(vim.loop.fs_stat, vim.api.nvim_buf_get_name(buf)) - if ok and stats and stats.size > max_filesize then - return true - end - end, - additional_vim_regex_highlighting = false, - }, - - incremental_selection = { - enable = true, - keymaps = { - init_selection = '', - node_incremental = '', - scope_incremental = false, - node_decremental = '', - }, - }, - - textsubjects = { - enable = true, - prev_selection = ',', - keymaps = { - ['.'] = { 'textsubjects-smart', desc = 'Select the current text subject' }, - ['a;'] = { - 'textsubjects-container-outer', - desc = 'Select outer container (class, function, etc.)', - }, - ['i;'] = { - 'textsubjects-container-inner', - desc = 'Select inside containers (classes, functions, etc.)', - }, - }, - }, - - refactor = { - highlight_definitions = { - enable = true, - clear_on_cursor_move = true, - }, - highlight_current_scope = { enable = true }, - smart_rename = { - enable = true, - keymaps = { - smart_rename = 'rr', - }, - }, - navigation = { - enable = true, - keymaps = { - goto_definition = 'rd', - list_definitions = 'rl', - list_definitions_toc = 'rh', - goto_next_usage = 'rj', - goto_previous_usage = 'rk', - }, - }, - }, -}) diff --git a/lua/plugins/files.lua b/lua/plugins/files.lua new file mode 100644 index 0000000..8e1c6e4 --- /dev/null +++ b/lua/plugins/files.lua @@ -0,0 +1,55 @@ +return { + { + "echasnovski/mini.files", + version = "*", + event = { "BufReadPost", "BufNewFile" }, + config = function() + require("mini.files").setup({ + content = { + filter = nil, + prefix = nil, + sort = nil, + }, + mappings = { + close = "q", + go_in = "L", + go_in_plus = "l", + go_out = "h", + go_out_plus = "H", + mark_goto = "'", + mark_set = "m", + reset = "", + reveal_cwd = "@", + show_help = "g?", + synchronize = "", + trim_left = "<", + trim_right = ">", + }, + options = { + permanent_delete = true, + use_as_default_explorer = true, + }, + windows = { + max_number = math.huge, + preview = false, + width_focus = 30, + width_nofocus = 20, + width_preview = 80, + }, + }) + end, + }, + { + "prichrd/netrw.nvim", + config = function() + require("netrw").setup({ + icons = { + symlink = "", + directory = "", + file = "", + }, + use_devicons = true, + }) + end, + }, +} diff --git a/lua/plugins/format.lua b/lua/plugins/format.lua new file mode 100644 index 0000000..506c3bb --- /dev/null +++ b/lua/plugins/format.lua @@ -0,0 +1,37 @@ +return { + "stevearc/conform.nvim", + dependencies = { "zapling/mason-conform.nvim" }, + event = "BufWritePre", + cmd = "ConformInfo", + keys = { "tf" }, + config = function() + require("conform").setup({ + formatters_by_ft = { + lua = { "stylua" }, + python = { "black" }, + ["_"] = { "trim_whitespace" }, + }, + format_after_save = function(bufnr) + if not vim.b[bufnr].conform_disable then + return { + lsp_format = "fallback", + } + end + end, + }) + + vim.keymap.set("n", "tf", function() + vim.b.conform_disable = not vim.b.conform_disable + local status = vim.b.conform_disable and "disabled" or "enabled" + vim.notify("Autoformat " .. status, vim.log.levels.INFO) + end) + require("mason-conform").setup({ + ensure_installed = { + "black", + "stylua", + "prettier", + }, + automatic_installation = true, + }) + end, +} diff --git a/lua/plugins/git.lua b/lua/plugins/git.lua new file mode 100644 index 0000000..61cb5dd --- /dev/null +++ b/lua/plugins/git.lua @@ -0,0 +1,63 @@ +return { + + -- git signs + { + "lewis6991/gitsigns.nvim", + opts = { + signs = { + add = { + text = "+", + }, + change = { + text = "▎", + }, + delete = { + text = "", + }, + topdelete = { + text = "▾", + }, + changedelete = { + text = "~", + }, + untracked = { + text = "┆", + }, + }, + signs_staged = { + add = { + text = "+", + }, + change = { + text = "▎", + }, + delete = { + text = "", + }, + topdelete = { + text = "▾", + }, + changedelete = { + text = "~", + }, + }, + }, + }, + + -- lazygit integration + { + "kdheepak/lazygit.nvim", + lazy = true, + enabled = false, + cmd = { + "LazyGit", + "LazyGitConfig", + "LazyGitCurrentFile", + "LazyGitFilter", + "LazyGitFilterCurrentFile", + }, + keys = { + { "lg", "LazyGit", desc = "LazyGit" }, + }, + }, +} diff --git a/lua/plugins/lang/blink.lua b/lua/plugins/lang/blink.lua deleted file mode 100644 index de36bd8..0000000 --- a/lua/plugins/lang/blink.lua +++ /dev/null @@ -1,84 +0,0 @@ -local blink = require('blink.cmp') -local icons = require('lib.icons') - -blink.setup({ - -- 'default', 'super-tab', 'enter' - keymap = { - preset = 'enter', - [''] = { 'select_next', 'snippet_forward', 'fallback' }, - [''] = { 'select_prev', 'snippet_backward', 'fallback' }, - [''] = { 'show', 'hide' }, - [''] = { 'show_documentation', 'hide_documentation' }, - }, - snippets = { preset = 'luasnip' }, - completion = { - list = { - selection = { - auto_insert = true, - preselect = true, - }, - }, - menu = { border = 'rounded' }, - documentation = { window = { border = 'rounded' } }, - }, - signature = { window = { border = 'rounded' } }, - appearance = { - -- Sets the fallback highlight groups to nvim-cmp's highlight groups - use_nvim_cmp_as_default = true, - -- Set to 'mono' for 'Nerd Font Mono' or 'normal' for 'Nerd Font' - nerd_font_variant = 'normal', - kind_icons = icons.kind, - }, - sources = { - default = { 'avante', 'lazydev', 'lsp', 'path', 'snippets', 'buffer', 'copilot', 'spell' }, - providers = { - avante = { - module = 'blink-cmp-avante', - name = 'Avante', - opts = {}, - }, - copilot = { - name = 'copilot', - module = 'blink-cmp-copilot', - score_offset = 90, - async = true, - transform_items = function(_, items) - local CompletionItemKind = require('blink.cmp.types').CompletionItemKind - local kind_idx = #CompletionItemKind + 1 - CompletionItemKind[kind_idx] = 'Copilot' - for _, item in ipairs(items) do - item.kind = kind_idx - end - return items - end, - }, - lazydev = { - name = 'LazyDev', - module = 'lazydev.integrations.blink', - -- make lazydev completions top priority (see `:h blink.cmp`) - score_offset = 100, - }, - spell = { - name = 'Spell', - module = 'blink-cmp-spell', - opts = { - -- EXAMPLE: Only enable source in `@spell` captures, and disable it - -- in `@nospell` captures. - enable_in_context = function() - local curpos = vim.api.nvim_win_get_cursor(0) - local captures = vim.treesitter.get_captures_at_pos(0, curpos[1] - 1, curpos[2] - 1) - local in_spell_capture = false - for _, cap in ipairs(captures) do - if cap.capture == 'spell' then - in_spell_capture = true - elseif cap.capture == 'nospell' then - return false - end - end - return in_spell_capture - end, - }, - }, - }, - }, -}) diff --git a/lua/plugins/lang/conform.lua b/lua/plugins/lang/conform.lua deleted file mode 100644 index 4143048..0000000 --- a/lua/plugins/lang/conform.lua +++ /dev/null @@ -1,64 +0,0 @@ -local conform = require('conform') - --- Setup formatters -conform.setup({ - formatters_by_ft = { - lua = { 'stylua' }, - javascript = { 'prettier' }, - typescript = { 'prettier' }, - javascriptreact = { 'prettier' }, - typescriptreact = { 'prettier' }, - markdown = { 'prettier' }, - css = { 'prettier' }, - scss = { 'prettier' }, - html = { 'prettier' }, - json = { 'prettier' }, - yaml = { 'prettier' }, - sh = { 'shfmt', 'shellcheck' }, - ['_'] = { 'trim_whitespace', lsp_format = 'prefer' }, - }, - - -- Autoformat on save - format_on_save = { - timeout_ms = 1000, - lsp_fallback = true, - }, -}) - -vim.api.nvim_create_user_command('FormatDisable', function(args) - if args.bang then - -- FormatDisable! will disable formatting just for this buffer - vim.b.disable_autoformat = true - else - vim.g.disable_autoformat = true - vim.notify('Autoformat on save disabled', vim.log.levels.WARN) - end -end, { - desc = 'Disable autoformat-on-save', - bang = true, -}) -vim.api.nvim_create_user_command('FormatEnable', function() - vim.b.disable_autoformat = false - vim.g.disable_autoformat = false - vim.notify('Autoformat on save enabled', vim.log.levels.INFO) -end, { - desc = 'Re-enable autoformat-on-save', -}) - --- Add keymap to disable and enable format on save -vim.keymap.set('n', [[\f]], function() - if vim.b.disable_autoformat or vim.g.disable_autoformat then - vim.cmd('FormatEnable') - else - vim.cmd('FormatDisable') - end -end, { desc = 'Toggle auto-format' }) - --- Setup mason-conform -local auto_install = require('lib.util').get_user_config('auto_install', true) -local installed_formatters = require('plugins.list').formatter_sources or {} - -require('mason-conform').setup({ - ensure_installed = installed_formatters, - automatic_installation = auto_install, -}) diff --git a/lua/plugins/lang/lspconfig.lua b/lua/plugins/lang/lspconfig.lua deleted file mode 100644 index 9bf6d39..0000000 --- a/lua/plugins/lang/lspconfig.lua +++ /dev/null @@ -1,75 +0,0 @@ -local lspconfig = require('lspconfig') -local icons = require('lib.icons').diagnostics - -local auto_install = require('lib.util').get_user_config('auto_install', true) -local installed_servers = {} -if auto_install then - installed_servers = require('plugins.list').lsp_servers -end - -local capabilities = require('blink.cmp').get_lsp_capabilities() - --- Function to load LSP config from separate files -local function load_lsp_config(server_name) - local config_path = 'lsp.' .. server_name - local ok, config = pcall(require, config_path) - if ok then - return config - end - return nil -end - -local default_setup = function(server) - -- Check if there's a separate config file for this server - local custom_config = load_lsp_config(server) - - if custom_config then - -- Use the custom configuration and add capabilities - local config = vim.tbl_deep_extend('force', custom_config, { - capabilities = capabilities, - }) - lspconfig[server].setup(config) - else - lspconfig[server].setup({ - capabilities = capabilities, - }) - end -end - -require('mason-lspconfig').setup({ - ensure_installed = installed_servers, - handlers = { default_setup }, -}) - --- Setup servers that don't come from Mason --- Dart language server (comes with Dart SDK) -if vim.fn.executable('dart') == 1 then - local dart_config = load_lsp_config('dartls') - if dart_config then - local config = vim.tbl_deep_extend('force', dart_config, { - capabilities = capabilities, - }) - lspconfig.dartls.setup(config) - else - lspconfig.dartls.setup({ - capabilities = capabilities, - }) - end -end - -local signs = { Error = icons.Error, Warn = icons.Warning, Hint = icons.Hint, Info = icons.Information } -vim.diagnostic.config({ - underline = true, - update_in_insert = true, - severity_sort = true, - virtual_text = true, - float = true, - signs = { - text = { - [vim.diagnostic.severity.ERROR] = signs.Error, - [vim.diagnostic.severity.WARN] = signs.Warn, - [vim.diagnostic.severity.INFO] = signs.Info, - [vim.diagnostic.severity.HINT] = signs.Hint, - }, - }, -}) diff --git a/lua/plugins/lang/lspsaga.lua b/lua/plugins/lang/lspsaga.lua deleted file mode 100644 index 892e3b5..0000000 --- a/lua/plugins/lang/lspsaga.lua +++ /dev/null @@ -1,21 +0,0 @@ -local lspsaga = require('lspsaga') - -local icons = require('lib.icons') - -lspsaga.setup({ - ui = { - theme = 'round', - border = 'rounded', - devicon = true, - title = true, - winblend = 1, - expand = icons.ui.ArrowOpen, - collapse = icons.ui.ArrowClosed, - preview = icons.ui.List, - code_action = icons.diagnostics.Hint, - diagnostic = icons.ui.Bug, - incoming = icons.ui.Incoming, - outgoing = icons.ui.Outgoing, - hover = icons.ui.Comment, - }, -}) diff --git a/lua/plugins/lang/mason.lua b/lua/plugins/lang/mason.lua deleted file mode 100644 index aa10be6..0000000 --- a/lua/plugins/lang/mason.lua +++ /dev/null @@ -1,35 +0,0 @@ -local mason = require('mason') - -local icons = require('lib.icons') -mason.setup({ - -- - "prepend": Use mason binary, "append": Use system binary - PATH = 'append', - - log_level = vim.log.levels.INFO, - max_concurrent_installers = 8, - - ui = { - check_outdated_packages_on_open = true, - border = 'rounded', - width = 0.8, - height = 0.8, - - icons = { - package_installed = icons.ui.Gear, - package_pending = icons.ui.Download, - package_uninstalled = icons.ui.Plus, - }, - - keymaps = { - toggle_package_expand = '', - install_package = 'i', - update_package = 'u', - check_package_version = 'c', - update_all_packages = 'U', - check_outdated_packages = 'C', - uninstall_package = 'x', - cancel_installation = '', - apply_language_filter = '', - }, - }, -}) diff --git a/lua/plugins/lang/nvim-lint.lua b/lua/plugins/lang/nvim-lint.lua deleted file mode 100644 index fb143e9..0000000 --- a/lua/plugins/lang/nvim-lint.lua +++ /dev/null @@ -1,64 +0,0 @@ -local lint = require('lint') - --- Filetype to linters mapping -lint.linters_by_ft = { - javascript = { 'eslint_d' }, - typescript = { 'eslint_d' }, - javascriptreact = { 'eslint_d' }, - typescriptreact = { 'eslint_d' }, - dockerfile = { 'hadolint' }, - vim = { 'vint' }, - markdown = { 'write_good', 'markdownlint' }, - text = { 'write_good' }, - sh = { 'shellcheck' }, - yaml = { 'actionlint' }, -} - --- Generic lint function with global linters -local function lint_buffer(bufnr) - local ft = vim.bo[bufnr or 0].filetype - local linters = vim.list_extend( - { 'codespell', 'editorconfig-checker' }, -- global linters - require('lint')._resolve_linter_by_ft(ft) or {} - ) - - local ctx = { - filename = vim.api.nvim_buf_get_name(bufnr or 0), - } - ctx.dirname = vim.fn.fnamemodify(ctx.filename, ':h') - - -- Filter linters by executable availability - linters = vim.tbl_filter(function(name) - local linter = require('lint').linters[name] - return linter and vim.fn.executable(linter.cmd) == 1 and (not linter.condition or linter.condition(ctx)) - end, linters) - - if #linters > 0 then - require('lint').try_lint(linters) - end -end - --- Create one reusable timer -local uv = vim.loop -local timer = uv.new_timer() - -vim.api.nvim_create_autocmd({ 'BufReadPost', 'BufWritePost', 'InsertLeave' }, { - callback = function(args) - timer:stop() - timer:start(100, 0, function() - vim.schedule(function() - lint_buffer(args.buf) - end) - end) - end, - desc = 'Lint buffer with custom linters', -}) - --- Setup mason-nvim-lint to auto-install linters -local auto_install = require('lib.util').get_user_config('auto_install', true) -local installed_linters = require('plugins.list').linter_sources or {} - -require('mason-nvim-lint').setup({ - ensure_installed = installed_linters, - automatic_installation = auto_install, -}) diff --git a/lua/plugins/languages.lua b/lua/plugins/languages.lua new file mode 100644 index 0000000..41c4a50 --- /dev/null +++ b/lua/plugins/languages.lua @@ -0,0 +1,116 @@ +return { + -- treesitter + { + "nvim-treesitter/nvim-treesitter", + build = ":TSUpdate", + event = { "BufReadPost", "BufNewFile" }, + config = function() + require("nvim-treesitter").setup({ + ensure_installed = { + "c", + "markdown", + "python", + "java", + "cpp", + "bash", + "lua", + "make", + "latex", + "json", + "jsonc", + "sql", + "yaml", + "toml", + "javascript", + "ts_ls", + "gitignore", + "go", + "rust", + "html", + "css", + "scss", + "markdown_inline", + }, + auto_install = true, + highlight = { + enable = true, + additional_vim_regex_highlighting = true, + }, + indent = { + enable = true, + }, + }) + end, + }, + + -- rendering for html, latex, md + { + "OXY2DEV/markview.nvim", + lazy = false, + -- to load before treesitter + priority = 45, + config = function() + require("markview").setup({ + markdown = { + code_blocks = { sign = false }, + }, + }) + end, + }, + + -- markdown preview + { + "iamcco/markdown-preview.nvim", + build = "cd app && yarn install", + init = function() + vim.g.mkdp_filetypes = { "markdown" } + end, + ft = "markdown", + cmd = { "MarkdownPreviewToggle", "MarkdownPreview" }, + }, + + { + "danymat/neogen", + dependencies = { "nvim-treesitter/nvim-treesitter" }, + opts = { + snippet_engine = "luasnip", + languages = { + python = { + template = { + annotation_convention = "google_docstrings", + }, + }, + }, + }, + }, + + -- auto pairs + { + "windwp/nvim-autopairs", + event = "InsertEnter", + config = function() + require("nvim-autopairs").setup() + + -- add new rules + local pairs = require("nvim-autopairs") + local rule = require("nvim-autopairs.rule") + local cond = require("nvim-autopairs.conds") + pairs.add_rules({ + rule("$", "$", { "tex", "latex", "plaintex" }) + -- do not move right when repeat character + :with_move(cond.none()), + }) + end, + }, + + { + "windwp/nvim-ts-autotag", + event = "InsertEnter", + lazy = true, + opts = { + enable_close = true, + enable_rename = true, + enable_close_on_slash = true, + }, + }, +} diff --git a/lua/plugins/lazy.lua b/lua/plugins/lazy.lua deleted file mode 100644 index e9b2fe4..0000000 --- a/lua/plugins/lazy.lua +++ /dev/null @@ -1,131 +0,0 @@ --- put this in your main init.lua file ( before lazy setup ) -vim.g.base46_cache = vim.fn.stdpath('data') .. '/base46_cache/' - -local lazypath = vim.fn.stdpath('data') .. '/lazy/lazy.nvim' -if not vim.loop.fs_stat(lazypath) then - vim.fn.system({ - 'git', - 'clone', - '--filter=blob:none', - '--single-branch', - 'https://github.com/folke/lazy.nvim.git', - lazypath, - }) -end -vim.opt.runtimepath:prepend(lazypath) - -local status_ok, lazy = pcall(require, 'lazy') -if not status_ok then - return -end - -local icons = require('lib.icons') -local plugins = require('plugins.list').plugins - -lazy.setup({ - root = vim.fn.stdpath('data') .. '/lazy', - defaults = { lazy = true }, - spec = plugins, - lockfile = vim.fn.stdpath('config') .. '/lua/plugins/lock.json', - concurrency = 8, - dev = { path = '~/Projects/Github', patterns = { 'Projects' }, fallback = true }, - install = { missing = true, colorscheme = { 'nvchad' } }, - - git = { - log = { '--since=3 days ago' }, - timeout = 120, - url_format = 'https://github.com/%s.git', - filter = true, - }, - - ui = { - size = { width = 0.9, height = 0.8 }, - wrap = true, - border = 'rounded', - icons = { - cmd = icons.ui.Terminal, - config = icons.ui.Gear, - event = icons.ui.Electric, - ft = icons.documents.File, - init = icons.ui.Rocket, - import = icons.documents.Import, - keys = icons.ui.Keyboard, - lazy = icons.ui.Sleep, - loaded = icons.ui.CircleSmall, - not_loaded = icons.ui.CircleSmallEmpty, - plugin = icons.ui.Package, - runtime = icons.ui.Neovim, - source = icons.ui.Code, - start = icons.ui.Play, - task = icons.ui.Check, - list = { - icons.ui.CircleSmall, - icons.ui.Arrow, - icons.ui.Star, - icons.ui.Minus, - }, - }, - browser = nil, - throttle = 20, - custom_keys = { - ['l'] = function(plugin) - require('lazy.util').float_term({ 'lazygit', 'log' }, { - cwd = plugin.dir, - }) - end, - - ['t'] = function(plugin) - require('lazy.util').float_term(nil, { - cwd = plugin.dir, - }) - end, - }, - }, - - diff = { cmd = 'git' }, - checker = { enabled = false, concurrency = nil, notify = true, frequency = 3600 }, - change_detection = { enabled = true, notify = true }, - performance = { - cache = { enabled = true }, - reset_packpath = true, - rtp = { - reset = true, - paths = {}, - disabled_plugins = { - 'gzip', - 'tarPlugin', - 'zipPlugin', - 'tohtml', - -- 'tutor', - -- 'matchit', - -- 'matchparen', - -- 'netrwPlugin', - }, - }, - }, - readme = { - root = vim.fn.stdpath('state') .. '/lazy/readme', - files = { 'README.md', 'lua/**/README.md' }, - skip_if_doc_exists = true, - }, - state = vim.fn.stdpath('state') .. '/lazy/state.json', -}) - --- put this after lazy setup --- Load base46 cache files if they exist -local function load_base46_cache() - local cache_dir = vim.g.base46_cache - - -- Check if cache files exist, if not try to generate them - if not vim.loop.fs_stat(cache_dir .. 'defaults') then - pcall(function() - require('base46').load_all_highlights() - end) - end - - -- Load cache files - pcall(dofile, cache_dir .. 'defaults') - pcall(dofile, cache_dir .. 'statusline') -end - -load_base46_cache() diff --git a/lua/plugins/lint.lua b/lua/plugins/lint.lua new file mode 100644 index 0000000..692e169 --- /dev/null +++ b/lua/plugins/lint.lua @@ -0,0 +1,33 @@ +return { + "mfussenegger/nvim-lint", + dependencies = { "rshkarin/mason-nvim-lint" }, + event = { "BufReadPost", "BufNewFile" }, + config = function() + require("lint").linters_by_ft = { + javascript = { "eslint_d" }, + typescript = { "eslint_d" }, + javascriptreact = { "eslint_d" }, + typescriptreact = { "eslint_d" }, + dockerfile = { "hadolint" }, + markdown = { "write_good", "markdownlint" }, + text = { "write_good" }, + sh = { "shellcheck" }, + yaml = { "actionlint" }, + python = { "ruff" }, + } + require("mason-nvim-lint").setup({ + ensure_installed = { + "eslint_d", + "hadolint", + "write_good", + "markdownlint", + "shellcheck", + "actionlint", + "djlint", + "ruff", + "pylint", + }, + automatic_installation = true, + }) + end, +} diff --git a/lua/plugins/list.lua b/lua/plugins/list.lua deleted file mode 100644 index 908c81f..0000000 --- a/lua/plugins/list.lua +++ /dev/null @@ -1,599 +0,0 @@ -local util = require('lib.util') -local function load_config(package) - return function() - require('plugins.' .. package) - end -end - -local plugins = { - -- UI - { - 'nvchad/ui', - config = function() - require('nvchad') - end, - }, - { - 'nvchad/base46', - lazy = false, - priority = 1000, - build = function() - require('base46').load_all_highlights() - end, - config = function() - require('base46').load_all_highlights() - end, - }, - { 'nvim-tree/nvim-web-devicons' }, - { - 'folke/snacks.nvim', - priority = 1000, - lazy = false, - config = load_config('ui.snacks'), - }, - { - 'nvim-lualine/lualine.nvim', - config = load_config('ui.lualine'), - event = { 'BufReadPost', 'BufNewFile' }, - }, - { - 'folke/which-key.nvim', - config = load_config('ui.which-key'), - event = 'VeryLazy', - }, - { - 'lewis6991/gitsigns.nvim', - config = load_config('ui.gitsigns'), - cmd = 'Gitsigns', - event = { 'BufReadPost', 'BufNewFile' }, - }, - - -- Editor - { - 'nvim-treesitter/nvim-treesitter', - build = ':TSUpdate', - dependencies = { - 'nvim-treesitter/nvim-treesitter-refactor', - 'nvim-treesitter/nvim-treesitter-textobjects', - 'RRethy/nvim-treesitter-textsubjects', - }, - config = load_config('editor.treesitter'), - event = { 'BufReadPost', 'BufNewFile' }, - }, - - { - 'echasnovski/mini.bracketed', - config = load_config('editor.bracketed'), - event = { 'BufReadPost', 'BufNewFile' }, - }, - { - 'echasnovski/mini.pairs', - config = load_config('editor.pairs'), - event = 'InsertEnter', - }, - { - 'echasnovski/mini.surround', - version = '*', - config = load_config('editor.surround'), - event = { 'BufReadPost', 'BufNewFile' }, - }, - { - 'echasnovski/mini.ai', - version = '*', - config = load_config('editor.ai'), - event = { 'BufReadPost', 'BufNewFile' }, - }, - { - 'Wansmer/treesj', - keys = { 'm', 'j', 's' }, - dependencies = { 'nvim-treesitter/nvim-treesitter' }, -- if you install parsers with `nvim-treesitter` - config = function() - require('treesj').setup() - end, - }, - { - 'chrisgrieser/nvim-spider', - config = load_config('editor.spider'), - event = { 'BufReadPost', 'BufNewFile' }, - }, - -- Language - { - 'neovim/nvim-lspconfig', - dependencies = { 'williamboman/mason-lspconfig.nvim' }, - config = load_config('lang.lspconfig'), - event = { 'BufReadPre', 'BufNewFile' }, - }, - { - 'folke/lazydev.nvim', - ft = 'lua', - }, - { - 'nvimdev/lspsaga.nvim', - config = load_config('lang.lspsaga'), - event = 'LspAttach', - }, - { - 'williamboman/mason.nvim', - config = load_config('lang.mason'), - cmd = 'Mason', - }, - { - 'stevearc/conform.nvim', - dependencies = { 'zapling/mason-conform.nvim' }, - config = load_config('lang.conform'), - event = { 'BufReadPre', 'BufNewFile' }, - }, - { - 'mfussenegger/nvim-lint', - dependencies = { 'rshkarin/mason-nvim-lint' }, - init = function() - if vim.fn.executable('codespell') == 1 then - vim.o.spell = false - end - end, - config = load_config('lang.nvim-lint'), - event = { 'BufReadPost', 'BufNewFile' }, - }, - { - 'saghen/blink.cmp', - dependencies = { - 'rafamadriz/friendly-snippets', - 'Kaiser-Yang/blink-cmp-avante', - 'ribru17/blink-cmp-spell', - { - 'L3MON4D3/LuaSnip', - config = function() - -- Lazy load VSCode-style snippets (including JSON) - require('luasnip.loaders.from_vscode').lazy_load({ - paths = { - vim.fn.stdpath('config') .. '/snippets', -- your custom snippets folder - }, - }) - end, - }, - }, - - version = '*', - config = load_config('lang.blink'), - opts_extend = { 'sources.default' }, - event = { 'InsertEnter' }, - }, - { - 'mg979/vim-visual-multi', - branch = 'master', -- Required to avoid loading the legacy branch - event = { 'BufReadPost', 'BufNewFile' }, -- Load earlier when buffer is ready - init = function() - vim.g.VM_leader = '\\' - vim.g.VM_maps = { - ['Find Under'] = '', -- Changed to match VSCode - ['Find Subword Under'] = '', -- Changed to match VSCode - ['Select All'] = '', - ['Add Cursor Down'] = '', -- More intuitive than - ['Add Cursor Up'] = '', -- More intuitive than - ['Select Cursor Down'] = '', - ['Select Cursor Up'] = '', - } - -- Keep default mappings for better functionality - vim.g.VM_default_mappings = 1 - end, - }, - - -- AI - { - 'zbirenbaum/copilot.lua', - dependencies = { 'giuxtaposition/blink-cmp-copilot' }, - config = load_config('ai.copilot'), - event = 'InsertEnter', - }, - { - 'yetone/avante.nvim', - version = false, - config = load_config('ai.avante'), - event = { 'BufReadPost', 'BufNewFile' }, - build = 'make', - -- build = "powershell -ExecutionPolicy Bypass -File Build.ps1 -BuildFromSource false" -- for windows - dependencies = { - 'MunifTanjim/nui.nvim', - 'nvim-lua/plenary.nvim', - }, - }, - - -- Tools - { - 'echasnovski/mini.files', - version = '*', - config = load_config('tools.files'), - event = { 'BufReadPost', 'BufNewFile' }, - keys = { - { - 'ee', - function() - require('mini.files').open(util.get_file_path(), true) - end, - desc = 'Explorer', - }, - }, - }, - { - 'michaelb/sniprun', - build = 'bash ./install.sh', - config = load_config('tools.sniprun'), - cmd = 'SnipRun', - }, - { - 'windwp/nvim-spectre', - config = load_config('tools.spectre'), - cmd = 'Spectre', - }, - { - 'folke/flash.nvim', - config = load_config('tools.flash'), - keys = { - { - 's', - mode = { 'n', 'x', 'o' }, - function() - require('flash').jump() - end, - desc = 'Flash', - }, - { - 'S', - mode = { 'n', 'x', 'o' }, - function() - require('flash').treesitter() - end, - desc = 'Flash Treesitter', - }, - }, - }, - { - 'windwp/nvim-ts-autotag', - ft = { - 'html', - 'javascriptreact', - 'typescriptreact', - 'svelte', - 'vue', - 'tsx', - 'jsx', - 'markdown', - 'handlebars', - 'hbs', - }, - opts = {}, - }, - { - 'gbprod/substitute.nvim', - event = { 'BufReadPre', 'BufNewFile' }, - config = function() - local substitute = require('substitute') - - substitute.setup() - - -- set keymaps - local keymap = vim.keymap -- for conciseness - - keymap.set('n', 's', substitute.operator, { desc = 'Substitute with motion' }) - keymap.set('n', 'ss', substitute.line, { desc = 'Substitute line' }) - keymap.set('n', 'S', substitute.eol, { desc = 'Substitute to end of line' }) - keymap.set('x', 's', substitute.visual, { desc = 'Substitute in visual mode' }) - end, - }, - { - 'davidmh/mdx.nvim', - config = true, - lazy = false, - }, - { - 'numToStr/Navigator.nvim', - config = load_config('tools.navigator'), - event = 'VeryLazy', - }, - { - 'iamcco/markdown-preview.nvim', - build = 'cd app && yarn install', - init = function() - vim.g.mkdp_filetypes = { 'markdown' } - end, - ft = 'markdown', - cmd = { 'MarkdownPreviewToggle', 'MarkdownPreview' }, - }, - { - 'uga-rosa/ccc.nvim', - config = load_config('tools.ccc'), - cmd = { 'CccHighlighterToggle', 'CccConvert', 'CccPick' }, - }, - { - 'ruifm/gitlinker.nvim', - config = load_config('tools.gitlinker'), - keys = 'yg', - }, - { - 'tpope/vim-fugitive', - cmd = 'Git', - }, - { - - 'akinsho/toggleterm.nvim', - cmd = { 'ToggleTerm' }, - version = 'v2.*', - config = load_config('tools.toggleterm'), - }, - { - 'mistricky/codesnap.nvim', - lazy = true, - build = 'make', - opts = { - save_path = '~/Pictures/code-screenshots/', - has_breadcrumbs = false, - show_workspace = false, - bg_theme = 'default', - watermark = 'S4NKALP', - code_font_family = 'Iosevka NF', - code_font_size = 12, - }, - cmd = { 'CodeSnap', 'CodeSnapSave', 'CodeSnapHighlight', 'CodeSnapASCII' }, - }, - { - 'LudoPinelli/comment-box.nvim', - event = 'BufReadPre', - opts = { - box_width = 70, - }, - }, - { - 'mistricky/codesnap.nvim', - lazy = true, - build = 'make', - opts = { - save_path = '~/Pictures/screenshots/code', - has_breadcrumbs = false, - show_workspace = false, - bg_theme = 'default', - watermark = 'S4NKALP', - code_font_family = 'Iosevka NF', - code_font_size = 12, - }, - cmd = { 'CodeSnap', 'CodeSnapSave', 'CodeSnapHighlight', 'CodeSnapASCII' }, - }, - { - 'jeryldev/pyworks.nvim', - lazy = false, -- Load immediately for autocmds - config = function() - require('pyworks').setup({ - python = { - preferred_venv_name = '.venv', - use_uv = true, -- Use uv when available - }, - auto_activate_venv = true, - }) - end, - }, - { - 'folke/todo-comments.nvim', - event = { 'BufReadPre', 'BufNewFile' }, - dependencies = { 'nvim-lua/plenary.nvim' }, - keys = { - { - 'tt', - function() - require('snacks').picker.todo_comments({ keywords = { 'TODO' } }) - end, - desc = 'Todo', - }, - { - 'tf', - function() - require('snacks').picker.todo_comments({ - keywords = { 'FIX', 'FIXME' }, - }) - end, - desc = 'Fix/Fixme', - }, - { - 'tn', - function() - require('snacks').picker.todo_comments({ keywords = { 'NOTE' } }) - end, - desc = 'Note', - }, - }, - config = function() - local todo_comments = require('todo-comments') - - todo_comments.setup({ - keywords = { - FIX = { - icon = ' ', -- icon used for the sign, and in search results - color = 'error', -- can be a hex color, or a named color (see below) - alt = { 'FIXME', 'BUG', 'FIXIT', 'ISSUE' }, -- a set of other keywords that all map to this FIX keywords - -- signs = false, -- configure signs for some keywords individually - }, - TODO = { icon = ' ', color = 'info' }, - HACK = { icon = ' ', color = 'warning', alt = { 'DON SKIP' } }, - WARN = { icon = ' ', color = 'warning', alt = { 'WARNING', 'XXX' } }, - PERF = { icon = ' ', alt = { 'OPTIM', 'PERFORMANCE', 'OPTIMIZE' } }, - NOTE = { icon = ' ', color = 'hint', alt = { 'INFO', 'READ', 'COLORS' } }, - TEST = { icon = '⏲ ', color = 'test', alt = { 'TESTING', 'PASSED', 'FAILED' } }, - }, - }) - - -- keymaps - vim.keymap.set('n', ']t', function() - todo_comments.jump_next() - end, { desc = 'Next todo comment' }) - - vim.keymap.set('n', '[t', function() - todo_comments.jump_prev() - end, { desc = 'Previous todo comment' }) - end, - }, - { - '2kabhishek/pickme.nvim', - cmd = 'PickMe', - event = 'VeryLazy', - dependencies = { - 'folke/snacks.nvim', - }, - opts = { - picker_provider = 'snacks', - }, - }, - { - '2kabhishek/termim.nvim', - cmd = { 'Fterm', 'FTerm', 'Sterm', 'STerm', 'Vterm', 'VTerm' }, - }, - - -- Optional - { - 'sphamba/smear-cursor.nvim', - event = 'VeryLazy', - cond = vim.g.neovide == nil, - opts = { - stiffness = 0.5, - trailing_stiffness = 0.49, - }, - enabled = util.get_user_config('enable_smear_cursor', false), - }, - { - 'nvzone/showkeys', - cmd = 'ShowkeysToggle', - opts = { - timeout = 1, - maxkeys = 10, - -- more opts - }, - }, - { - 'wakatime/vim-wakatime', - event = { 'VimEnter' }, - lazy = false, - enabled = util.get_user_config('enable_wakatime', false), - }, - { - 'm4xshen/hardtime.nvim', - dependencies = { 'MunifTanjim/nui.nvim', 'nvim-lua/plenary.nvim' }, - cmd = 'Hardtime', - enabled = util.get_user_config('enable_trainer', false), - }, - { - 'kndndrj/nvim-dbee', - dependencies = { 'MunifTanjim/nui.nvim' }, - build = function() - -- "curl", "wget", "bitsadmin", "go" - require('dbee').install('curl') - end, - config = load_config('tools.dbee'), - cmd = 'DBToggle', - enabled = util.get_user_config('enable_db_explorer', false), - }, - { - 'mfussenegger/nvim-dap', - dependencies = { 'rcarriga/nvim-dap-ui' }, - config = load_config('tools.dap'), - cmd = { 'DapUIToggle', 'DapToggleRepl', 'DapToggleBreakpoint' }, - enabled = util.get_user_config('enable_debugger', false), - }, - { - 'nvim-neotest/neotest', - dependencies = { - 'nvim-neotest/nvim-nio', - 'olimorris/neotest-rspec', - 'nvim-neotest/neotest-jest', - 'nvim-neotest/neotest-python', - }, - config = load_config('tools.neotest'), - cmd = 'Neotest', - enabled = util.get_user_config('enable_test_runner', false), - }, -} - -local treesitter_parsers = { - 'bash', - 'css', - 'dart', - 'elixir', - 'gitcommit', - 'go', - 'html', - 'java', - 'javascript', - 'json', - 'lua', - 'markdown', - 'markdown_inline', -- markdown code blocks - 'python', - 'ruby', - 'rust', - 'typescript', - 'vim', - 'vimdoc', - 'yaml', -} - -local linter_sources = { - 'shellcheck', - 'write_good', - 'markdownlint', - 'eslint_d', - 'hadolint', - 'actionlint', - 'vint', - 'codespell', - 'editorconfig-checker', -} - -local formatter_sources = { - 'prettier', - 'shfmt', - 'stylua', -} - -local lsp_servers = { - 'bashls', - 'jsonls', - 'typos_lsp', - 'vimls', - 'lua_ls', - 'qmlls', - 'tailwindcss', - 'ts_ls', - 'pyright', -} - -if util.is_present('npm') then - table.insert(lsp_servers, 'eslint') - table.insert(lsp_servers, 'ts_ls') -end - -if util.is_present('go') then - table.insert(lsp_servers, 'gopls') -end - -if util.is_present('java') then - table.insert(lsp_servers, 'jdtls') -end - -if util.is_present('pip') then - table.insert(lsp_servers, 'ruff') - table.insert(lsp_servers, 'pylsp') -end - -if util.is_present('cargo') then - table.insert(lsp_servers, 'rust_analyzer') -end - -plugins = vim.tbl_extend('force', plugins, util.get_user_config('user_plugins', {})) -lsp_servers = vim.tbl_extend('force', lsp_servers, util.get_user_config('user_lsp_servers', {})) -formatter_sources = vim.tbl_extend('force', formatter_sources, util.get_user_config('user_formatter_sources', {})) -linter_sources = vim.tbl_extend('force', linter_sources, util.get_user_config('user_linter_sources', {})) -treesitter_parsers = vim.tbl_extend('force', treesitter_parsers, util.get_user_config('user_tresitter_parsers', {})) - -return { - plugins = plugins, - lsp_servers = lsp_servers, - formatter_sources = formatter_sources, - linter_sources = linter_sources, - ts_parsers = treesitter_parsers, -} diff --git a/lua/plugins/lock.json b/lua/plugins/lock.json deleted file mode 100644 index e767958..0000000 --- a/lua/plugins/lock.json +++ /dev/null @@ -1,66 +0,0 @@ -{ - "LuaSnip": { "branch": "master", "commit": "3d5bced1b9ae69fa3f9b1942e28af5dbc537f946" }, - "Navigator.nvim": { "branch": "master", "commit": "91d86506ac2a039504d5205d32a1d4bc7aa57072" }, - "avante.nvim": { "branch": "main", "commit": "bd69ae14f6f1f21642e16c16cbd18954f62365aa" }, - "base46": { "branch": "v3.0", "commit": "cee12a263602cc97652d3dd55f0fc5e171012967" }, - "blink-cmp-avante": { "branch": "master", "commit": "4f494c6e124acbe31a8f5d58effa0c14aa38a6d5" }, - "blink-cmp-copilot": { "branch": "main", "commit": "439cff78780c033aa23cf061d7315314b347e3c1" }, - "blink-cmp-spell": { "branch": "master", "commit": "2bd0e0d5e7735c047e72b6918a0458f3e8fadaba" }, - "blink.cmp": { "branch": "main", "commit": "bae4bae0eedd1fa55f34b685862e94a222d5c6f8" }, - "ccc.nvim": { "branch": "main", "commit": "9d1a256e006decc574789dfc7d628ca11644d4c2" }, - "codesnap.nvim": { "branch": "main", "commit": "be6d6b9a3b5e6999edbda76b16dace03d9bfcd3d" }, - "comment-box.nvim": { "branch": "main", "commit": "06bb771690bc9df0763d14769b779062d8f12bc5" }, - "conform.nvim": { "branch": "master", "commit": "973f3cb73887d510321653044791d7937c7ec0fa" }, - "copilot.lua": { "branch": "master", "commit": "64422b725c4ae102838f3efe832dafb68be2246d" }, - "flash.nvim": { "branch": "main", "commit": "3c942666f115e2811e959eabbdd361a025db8b63" }, - "friendly-snippets": { "branch": "main", "commit": "572f5660cf05f8cd8834e096d7b4c921ba18e175" }, - "gitlinker.nvim": { "branch": "master", "commit": "cc59f732f3d043b626c8702cb725c82e54d35c25" }, - "gitsigns.nvim": { "branch": "main", "commit": "b01433169be710d6c69f7b4ee264d9670698b831" }, - "hardtime.nvim": { "branch": "main", "commit": "5d9adcbe2f12741de79e435c8b85dca69a3b22e4" }, - "lazy.nvim": { "branch": "main", "commit": "6c3bda4aca61a13a9c63f1c1d1b16b9d3be90d7a" }, - "lazydev.nvim": { "branch": "main", "commit": "2367a6c0a01eb9edb0464731cc0fb61ed9ab9d2c" }, - "lspsaga.nvim": { "branch": "main", "commit": "8efe00d6aed9db6449969f889170f1a7e43101a1" }, - "lualine.nvim": { "branch": "master", "commit": "a94fc68960665e54408fe37dcf573193c4ce82c9" }, - "markdown-preview.nvim": { "branch": "master", "commit": "a923f5fc5ba36a3b17e289dc35dc17f66d0548ee" }, - "mason-conform.nvim": { "branch": "main", "commit": "f3b96fa2217fcb1513301eefbe10ea0e765e33eb" }, - "mason-lspconfig.nvim": { "branch": "main", "commit": "bb3a17efc797c34c054463174e5522442576ebd8" }, - "mason-nvim-lint": { "branch": "main", "commit": "767b8ccdddaa977bec8987fd7507b9865a279235" }, - "mason.nvim": { "branch": "main", "commit": "197f6352c276bbc2d25541dfce00ec50d1a4e88f" }, - "mdx.nvim": { "branch": "main", "commit": "464a74be368dce212cff02f6305845dc7f209ab3" }, - "mini.ai": { "branch": "main", "commit": "e139eb1101beb0250fea322f8c07a42f0f175688" }, - "mini.bracketed": { "branch": "main", "commit": "4a005a6e5aad58230b69f0f59df2cbb8b1c2e643" }, - "mini.files": { "branch": "main", "commit": "49c855977e9f4821d1ed8179ed44fe098b93ea2a" }, - "mini.pairs": { "branch": "main", "commit": "1e1ca3f60f58d4050bf814902b472eec9963a5dd" }, - "mini.surround": { "branch": "main", "commit": "5aab42fcdcf31fa010f012771eda5631c077840a" }, - "neotest": { "branch": "master", "commit": "d66cf4e05a116957f0d3a7755a24291c7d1e1f72" }, - "nui.nvim": { "branch": "main", "commit": "de740991c12411b663994b2860f1a4fd0937c130" }, - "nvim-dap": { "branch": "master", "commit": "99807078c5089ed30e0547aa4b52c5867933f426" }, - "nvim-dbee": { "branch": "master", "commit": "9656fc59841291e9dbd2f3b50b1cb4c77d9fea79" }, - "nvim-lint": { "branch": "master", "commit": "9c6207559297b24f0b7c32829f8e45f7d65b991f" }, - "nvim-lspconfig": { "branch": "master", "commit": "4d3b3bb8815fbe37bcaf3dbdb12a22382bc11ebe" }, - "nvim-spectre": { "branch": "master", "commit": "72f56f7585903cd7bf92c665351aa585e150af0f" }, - "nvim-spider": { "branch": "main", "commit": "6da0307421bc4be6fe02815faabde51007c4ea1a" }, - "nvim-treesitter": { "branch": "master", "commit": "42fc28ba918343ebfd5565147a42a26580579482" }, - "nvim-treesitter-refactor": { "branch": "master", "commit": "d8b74fa87afc6a1e97b18da23e762efb032dc270" }, - "nvim-treesitter-textobjects": { "branch": "master", "commit": "89ebe73cd2836db80a22d9748999ace0241917a5" }, - "nvim-treesitter-textsubjects": { "branch": "master", "commit": "abcbb0e537c9c24800b03b9ca33bee5806604629" }, - "nvim-ts-autotag": { "branch": "main", "commit": "a1d526af391f6aebb25a8795cbc05351ed3620b5" }, - "nvim-web-devicons": { "branch": "master", "commit": "0422a19d9aa3aad2c7e5cca167e5407b13407a9d" }, - "pickme.nvim": { "branch": "main", "commit": "55ca0f1889ea2a4df4b45c77941327a590e025c5" }, - "plenary.nvim": { "branch": "master", "commit": "857c5ac632080dba10aae49dba902ce3abf91b35" }, - "pyworks.nvim": { "branch": "main", "commit": "ecc25f9a524aef2b7a02255906cc5ffe7a11e5bb" }, - "showkeys": { "branch": "main", "commit": "cb0a50296f11f1e585acffba8c253b9e8afc1f84" }, - "smear-cursor.nvim": { "branch": "main", "commit": "1a3df9af4ed017fafecd93c6837956914f269472" }, - "snacks.nvim": { "branch": "main", "commit": "bc0630e43be5699bb94dadc302c0d21615421d93" }, - "sniprun": { "branch": "master", "commit": "a90c65846c3c18efc3f799d8b6dc26af9d4a69ed" }, - "substitute.nvim": { "branch": "main", "commit": "9db749a880e3dd3b0eb57f698aa8f1e1630e1f25" }, - "termim.nvim": { "branch": "main", "commit": "e4bcf977bef6f6c79996e38fcb9faeccd912007c" }, - "todo-comments.nvim": { "branch": "main", "commit": "304a8d204ee787d2544d8bc23cd38d2f929e7cc5" }, - "toggleterm.nvim": { "branch": "main", "commit": "50ea089fc548917cc3cc16b46a8211833b9e3c7c" }, - "treesj": { "branch": "main", "commit": "3b4a2bc42738a63de17e7485d4cc5e49970ddbcc" }, - "ui": { "branch": "v3.0", "commit": "dc4950f5bd4117e2da108b681506c908b93d4a62" }, - "vim-fugitive": { "branch": "master", "commit": "61b51c09b7c9ce04e821f6cf76ea4f6f903e3cf4" }, - "vim-visual-multi": { "branch": "master", "commit": "a6975e7c1ee157615bbc80fc25e4392f71c344d4" }, - "vim-wakatime": { "branch": "master", "commit": "f39c4a201ae350aaba713b59d4a4fdd88e0811aa" }, - "which-key.nvim": { "branch": "main", "commit": "370ec46f710e058c9c1646273e6b225acf47cbed" } -} diff --git a/lua/plugins/lsp.lua b/lua/plugins/lsp.lua new file mode 100644 index 0000000..86e721c --- /dev/null +++ b/lua/plugins/lsp.lua @@ -0,0 +1,70 @@ +return { + -- default lsp configs + { + "neovim/nvim-lspconfig", + config = function() end, + }, + + -- lsp installer + { + "williamboman/mason.nvim", + dependencies = { + "williamboman/mason-lspconfig.nvim", + }, + cmd = "Mason", + config = function() + -- mason + require("mason").setup({ + ui = { + icons = { + package_installed = "✓", + package_pending = "➜", + package_uninstalled = "✗", + }, + border = "rounded", + backdrop = 100, + }, + }) + require("mason-lspconfig").setup({ + -- list of servers for mason to install + ensure_installed = { + "ts_ls", + "html", + "cssls", + "tailwindcss", + "lua_ls", + "basedpyright", + "bashls", + "clangd", + "pylsp", + "rust_analyzer", + }, + -- auto-install configured servers (with lspconfig) + automatic_installation = true, -- not the same as ensure_installed + }) + end, + }, + { + "nvimdev/lspsaga.nvim", + event = "LspAttach", + config = function() + require("lspsaga").setup({ + ui = { + theme = "round", + border = "rounded", + devicon = true, + title = true, + winblend = 1, + expand = " ", + collapse = " ", + preview = "", + code_action = "󰠠 ", + diagnostic = " ", + incoming = " ", + outgoing = " ", + hover = " ", + }, + }) + end, + }, +} diff --git a/lua/plugins/picker.lua b/lua/plugins/picker.lua new file mode 100644 index 0000000..568c16e --- /dev/null +++ b/lua/plugins/picker.lua @@ -0,0 +1,362 @@ +return { + "folke/snacks.nvim", + priority = 1000, + lazy = false, + -- opts = { + -- bigfile = { enabled = true }, + -- dashboard = { enabled = true }, + -- explorer = { enabled = true }, + -- indent = { enabled = true }, + -- input = { enabled = true }, + -- notifier = { + -- enabled = true, + -- timeout = 3000, + -- }, + -- picker = { enabled = true }, + -- quickfile = { enabled = true }, + -- scope = { enabled = true }, + -- scroll = { enabled = true }, + -- statuscolumn = { enabled = true }, + -- words = { enabled = true }, + -- styles = { + -- notification = { + -- -- wo = { wrap = true } -- Wrap notifications + -- }, + -- }, + -- }, + config = function() + local function files_layout(preview_width, height, width) + preview_width = preview_width or 0.6 + height = height or 0.8 + width = width or 0.9 + return { + layout = { + box = "horizontal", + width = width, + min_width = 120, + height = height, + { + box = "vertical", + border = "rounded", + title = "{title} {live} {flags}", + { win = "input", height = 1, border = "bottom" }, + { win = "list", border = "none" }, + }, + { win = "preview", title = "{preview}", border = "rounded", width = preview_width }, + }, + } + end + + local function palette_layout(height, width) + height = height or 0.4 + width = width or 0.6 + return { + preview = false, + layout = { + backdrop = false, + row = 1, + width = width, + min_width = 80, + height = height, + border = "rounded", + box = "vertical", + { + win = "input", + height = 1, + border = "rounded", + title = "{title} {live} {flags}", + title_pos = "center", + }, + { win = "list", border = "hpad" }, + { win = "preview", title = "{preview}", border = "rounded" }, + }, + } + end + + local Snacks = require("snacks") + Snacks.setup({ + animate = { + enabled = true, + duration = 20, -- ms per step + easing = "linear", + fps = 60, + }, + bigfile = { + enabled = true, + notify = true, + size = 1000 * 1024, -- 1 MB instead of 100 KB + }, + bufdelete = { enabled = true }, + dashboard = { + enabled = true, + sections = { + { section = "header" }, + { + icon = " ", + title = "Keymaps", + section = "keys", + indent = 2, + padding = 1, + }, + { + icon = " ", + title = "Recent Files", + section = "recent_files", + indent = 2, + padding = 1, + }, + { + icon = " ", + title = "Projects", + section = "projects", + indent = 2, + padding = 1, + }, + { section = "startup" }, + }, + }, + debug = { enabled = true }, + dim = { + enabled = true, + scope = { + min_size = 5, + max_size = 20, + siblings = true, + }, + }, + explorer = { enabled = false }, + git = { enabled = true }, + gitbrowse = { enabled = true }, + image = { enabled = true }, + indent = { + enabled = true, + priority = 1, + char = "▍", + only_scope = false, + only_current = false, + hl = { + "SnacksIndent1", + "SnacksIndent2", + "SnacksIndent3", + "SnacksIndent4", + "SnacksIndent5", + "SnacksIndent6", + "SnacksIndent7", + "SnacksIndent8", + }, + }, + input = { + enabled = true, + icon = " ", + icon_hl = "SnacksInputIcon", + icon_pos = "left", + prompt_pos = "title", + win = { style = "input" }, + expand = true, + }, + layout = { enabled = true }, + lazygit = { enabled = true }, + notifier = { + enabled = true, + timeout = 2000, + width = { min = 40, max = 0.4 }, + height = { min = 1, max = 0.6 }, + margin = { top = 0, right = 1, bottom = 0 }, + padding = true, + sort = { "level", "added" }, + level = vim.log.levels.TRACE, + icons = { + debug = " ", + error = " ", + info = " ", + trace = " ", + warn = " ", + }, + style = "compact", + top_down = true, + date_format = "%R", + more_format = " ↓ %d lines ", + refresh = 50, + }, + notify = { enabled = true }, + picker = { + enabled = true, + icon = " ", + icon_hl = "SnacksPickerIcon", + icon_pos = "left", + prompt_pos = "title", + win = { style = "picker" }, + expand = true, + matchers = { + frecency = true, + cwd_bonus = false, + }, + sources = { + -- layout options: dropdown, horizontal, vertical, vscode, ivy, ivy_split, telescope, top, left, right, bottom, sidebar + buffers = { layout = files_layout() }, + commands = { layout = palette_layout() }, + command_history = { layout = palette_layout() }, + files = { + hidden = true, + layout = files_layout(), + }, + icons = { + icon_sources = { "nerd_fonts", "emoji" }, + layout = palette_layout(), + }, + git_files = { layout = files_layout() }, + git_branches = { layout = { preset = "vertical" } }, + git_status = { layout = files_layout() }, + help = { layout = { preset = "ivy_split" } }, + man = { layout = { preset = "ivy_split" } }, + notifications = { layout = palette_layout() }, + projects = { layout = files_layout(0.8) }, + recent = { layout = files_layout() }, + search_history = { layout = palette_layout() }, + smart = { layout = files_layout() }, + undo = { layout = { preset = "ivy" } }, + zoxide = { layout = files_layout(0.7) }, + }, + }, + profiler = { enabled = true }, + quickfile = { enabled = true }, + rename = { enabled = true }, + scope = { + enabled = true, + keys = { + textobject = { + ii = { + min_size = 2, -- minimum size of the scope + edge = false, -- inner scope + cursor = false, + treesitter = { blocks = { enabled = false } }, + desc = "inner scope", + }, + ai = { + cursor = false, + min_size = 2, -- minimum size of the scope + treesitter = { blocks = { enabled = false } }, + desc = "full scope", + }, + }, + jump = { + ["[a"] = { + min_size = 1, -- allow single line scopes + bottom = false, + cursor = false, + edge = true, + treesitter = { blocks = { enabled = false } }, + desc = "jump to top edge of scope", + }, + ["]a"] = { + min_size = 1, -- allow single line scopes + bottom = true, + cursor = false, + edge = true, + treesitter = { blocks = { enabled = false } }, + desc = "jump to bottom edge of scope", + }, + }, + }, + }, + scratch = { + enabled = true, + name = "SCRATCH", + ft = function() + if vim.bo.buftype == "" and vim.bo.filetype ~= "" then + return vim.bo.filetype + end + return "markdown" + end, + icon = nil, + root = vim.fn.stdpath("data") .. "/scratch", + autowrite = true, + filekey = { + cwd = true, + branch = true, + count = true, + }, + win = { + width = 120, + height = 40, + bo = { buftype = "", buflisted = false, bufhidden = "hide", swapfile = false }, + minimal = false, + noautocmd = false, + zindex = 20, + wo = { winhighlight = "NormalFloat:Normal" }, + border = "rounded", + title_pos = "center", + footer_pos = "center", + + keys = { + ["execute"] = { + "", + function(_) + vim.cmd("%SnipRun") + end, + desc = "Execute buffer", + mode = { "n", "x" }, + }, + }, + }, + win_by_ft = { + lua = { + keys = { + ["source"] = { + "cr", + function(self) + local name = "scratch." + .. vim.fn.fnamemodify(vim.api.nvim_buf_get_name(self.buf), ":e") + Snacks.debug.run({ buf = self.buf, name = name }) + end, + desc = "Source buffer", + mode = { "n", "x" }, + }, + }, + }, + }, + }, + scroll = { enabled = false }, + statuscolumn = { + enabled = false, -- Change this to false + left = { "mark", "sign" }, + right = { "fold", "git" }, + folds = { + open = false, + git_hl = false, + }, + git = { + patterns = { "GitSign", "MiniDiffSign" }, + }, + refresh = 50, + }, + terminal = { enabled = false }, + toggle = { enabled = false }, + win = { enabled = true }, + words = { enabled = false }, + zen = { + enabled = true, + toggles = { + dim = true, + git_signs = false, + mini_diff_signs = false, + -- diagnostics = false, + -- inlay_hints = false, + }, + show = { + statusline = false, + tabline = false, + }, + win = { style = "zen" }, + zoom = { + toggles = {}, + show = { statusline = true, tabline = true }, + win = { + backdrop = false, + width = 0, + }, + }, + }, + }) + end, +} diff --git a/lua/plugins/statusline.lua b/lua/plugins/statusline.lua new file mode 100644 index 0000000..dcdaa20 --- /dev/null +++ b/lua/plugins/statusline.lua @@ -0,0 +1,254 @@ +return { + "nvim-lualine/lualine.nvim", + dependencies = { + "ellisonleao/gruvbox.nvim", + }, + config = function() + local lualine = require("lualine") + + -- Get gruvbox colors + local palette = require("gruvbox").palette + + local colors = { + bg = palette.dark0, + fg = palette.light1, + yellow = palette.bright_yellow, + cyan = palette.bright_aqua, + darkblue = palette.dark0_hard, + green = palette.bright_green, + orange = palette.bright_orange, + violet = palette.bright_purple, + magenta = palette.bright_purple, + blue = palette.bright_blue, + red = palette.bright_red, + } + + local mode_color = { + n = colors.green, + i = colors.blue, + v = colors.magenta, + [""] = colors.magenta, + V = colors.magenta, + c = colors.yellow, + t = colors.red, + R = colors.orange, + Rv = colors.orange, + no = colors.fg, + s = colors.violet, + S = colors.violet, + [""] = colors.violet, + ic = colors.yellow, + cv = colors.red, + ce = colors.red, + r = colors.cyan, + rm = colors.cyan, + ["r?"] = colors.cyan, + ["!"] = colors.red, + } + + local conditions = { + buffer_not_empty = function() + return vim.fn.empty(vim.fn.expand("%:t")) ~= 1 + end, + buffer_is_file = function() + return vim.bo.buftype == "" + end, + buffer_not_scratch = function() + return string.find(vim.fn.bufname(), "SCRATCH") == nil + end, + hide_in_width = function() + return vim.fn.winwidth(0) > 80 + end, + check_git_workspace = function() + local filepath = vim.fn.expand("%:p:h") + local gitdir = vim.fn.finddir(".git", filepath .. ";") + return gitdir and #gitdir > 0 and #gitdir < #filepath + end, + is_note = function() + local notes_dir = vim.env.NOTES_DIR + if not notes_dir then + return false + end + local current_file = vim.fn.expand("%:p") + return current_file:find(vim.fn.expand(notes_dir), 1, true) == 1 + end, + } + + local searchcount = { "searchcount", color = { fg = colors.fg, gui = "bold" } } + local selectioncount = { "selectioncount", color = { fg = colors.fg, gui = "bold" } } + local progress = { "progress", color = { fg = colors.fg, gui = "bold" } } + local filetype = { "filetype", color = { fg = colors.blue, gui = "bold" } } + local filesize = { "filesize", color = { fg = colors.fg, gui = "bold" }, cond = conditions.buffer_not_empty } + local fileformat = { "fileformat", icons_enabled = true, color = { fg = colors.fg, gui = "bold" } } + + local filename = { + "filename", + cond = conditions.buffer_not_empty and conditions.buffer_is_file and conditions.buffer_not_scratch, + color = { fg = colors.magenta, gui = "bold" }, + } + + local buffers = { + "buffers", + mode = 2, + cond = conditions.buffer_not_scratch, + filetype_names = { + NvimTree = " " .. "Files", + TelescopePrompt = " " .. "Telescope", + Avante = " " .. "Avante", + AvanteInput = " " .. "Avante", + AvanteSelectedFiles = " " .. "Avante", + dashboard = " " .. "Dashboard", + lazy = "󰒲 " .. "Lazy", + mason = " " .. "Mason", + minifiles = " " .. "Files", + snacks_picker_input = " " .. "Picker", + spectre_panel = " " .. "Spectre", + }, + use_mode_colors = true, + } + + local branch = { + "branch", + icon = " ", + fmt = function(str) + return str:sub(1, 32) + end, + color = { fg = colors.green, gui = "bold" }, + } + + local diff_icons = { + "diff", + symbols = { added = " ", modified = " ", removed = " " }, + diff_color = { + added = { fg = colors.green }, + modified = { fg = colors.orange }, + removed = { fg = colors.red }, + }, + cond = conditions.hide_in_width, + } + + local diagnostics = { + "diagnostics", + sources = { "nvim_lsp", "nvim_diagnostic", "nvim_workspace_diagnostic" }, + symbols = { + error = " ", + warn = " ", + info = " ", + hint = "󰠠 ", + }, + diagnostics_color = { + color_error = { fg = colors.red }, + color_warn = { fg = colors.yellow }, + color_info = { fg = colors.blue }, + color_hint = { fg = colors.yellow }, + }, + } + + local lsp = { + function() + local msg = "No LSP" + local buf_ft = vim.api.nvim_get_option_value("filetype", { buf = 0 }) + local clients = vim.lsp.get_clients() + if next(clients) == nil then + return msg + end + for _, client in ipairs(clients) do + local filetypes = client.config and client.config.filetypes or nil + if filetypes and vim.fn.index(filetypes, buf_ft) ~= -1 then + return client.name + end + end + return msg + end, + icon = " ", + color = { fg = colors.fg, gui = "bold" }, + } + + local tdo = { + function() + local update_frequency = 300 + if not vim.g.tdo_last_update or (os.time() - vim.g.tdo_last_update) > update_frequency then + vim.g.tdo_last_update = os.time() + local result = vim.fn.system("tdo pending") + vim.g.tdo_count = tonumber(result:match("%d+")) or 0 + end + return vim.g.tdo_count or 0 + end, + icon = " ", + color = { fg = "#8BCD5B", gui = "bold" }, + cond = conditions.is_note, + } + + local encoding = { + "o:encoding", + fmt = string.upper, + cond = conditions.hide_in_width, + color = { fg = colors.green, gui = "bold" }, + } + + local function mode(icon) + icon = icon or " " + return { + function() + return icon + end, + color = function() + return { fg = mode_color[vim.fn.mode()] } + end, + padding = { left = 1, right = 0 }, + } + end + + -- Create custom gruvbox theme + local function gruvbox_custom() + local function accent_status(accent) + return { + a = { bg = accent, fg = palette.dark0_hard }, + b = { bg = palette.dark1, fg = accent }, + c = { bg = palette.dark0, fg = palette.light1 }, + } + end + + return { + normal = accent_status(palette.bright_aqua), + insert = accent_status(palette.bright_green), + visual = accent_status(palette.bright_purple), + replace = accent_status(palette.bright_yellow), + command = accent_status(palette.bright_orange), + inactive = { + a = { bg = palette.dark1, fg = palette.light4 }, + b = { bg = palette.dark1, fg = palette.light4 }, + c = { bg = palette.dark1, fg = palette.light4 }, + }, + } + end + + lualine.setup({ + options = { + component_separators = "", + -- section_separators = '', + theme = gruvbox_custom(), + disabled_filetypes = { + "dashboard", + }, + }, + -- extensions = { 'quickfix', 'man', 'mason', 'lazy', 'toggleterm', 'nvim-tree' }, + tabline = { + lualine_a = {}, + lualine_b = { mode(), tdo, buffers }, + lualine_c = {}, + lualine_x = { diff_icons, branch }, + lualine_y = { searchcount, selectioncount }, + lualine_z = {}, + }, + sections = { + lualine_a = {}, + lualine_b = {}, + lualine_c = { mode(" "), "location", progress, filename }, + lualine_x = { diagnostics, lsp, filetype, filesize, fileformat, encoding }, + lualine_y = {}, + lualine_z = {}, + }, + }) + end, +} diff --git a/lua/plugins/tools/ccc.lua b/lua/plugins/tools/ccc.lua deleted file mode 100644 index 580a9d3..0000000 --- a/lua/plugins/tools/ccc.lua +++ /dev/null @@ -1,10 +0,0 @@ -vim.opt.termguicolors = true - -local ccc = require('ccc') - -ccc.setup({ - highlighter = { - auto_enable = true, - lsp = true, - }, -}) diff --git a/lua/plugins/tools/dap.lua b/lua/plugins/tools/dap.lua deleted file mode 100644 index 0d54ed2..0000000 --- a/lua/plugins/tools/dap.lua +++ /dev/null @@ -1,107 +0,0 @@ -local dap = require('dap') -local dapui = require('dapui') -local icons = require('lib.icons') - -dapui.setup({ - icons = { expanded = icons.ui.ArrowClosed, collapsed = icons.ui.ArrowOpen }, - mappings = { - expand = { '', '<2-LeftMouse>' }, - open = 'o', - remove = 'd', - edit = 'e', - repl = 'r', - toggle = 't', - }, - expand_lines = vim.fn.has('nvim-0.7'), - layouts = { - { - elements = { - { id = 'scopes', size = 0.25 }, - 'breakpoints', - 'stacks', - 'watches', - }, - size = 40, - position = 'right', - }, - { - elements = { - 'repl', - 'console', - }, - size = 0.25, - position = 'bottom', - }, - }, - floating = { - max_height = nil, - max_width = nil, - border = 'rounded', - mappings = { - close = { 'q', '' }, - }, - }, - windows = { indent = 1 }, - render = { - max_type_length = nil, - }, -}) - -vim.fn.sign_define('DapBreakpoint', { text = icons.ui.Bug, texthl = 'DiagnosticSignError', linehl = '', numhl = '' }) - -dap.listeners.after.event_initialized['dapui_config'] = function() - dapui.open() -end -dap.listeners.before.event_terminated['dapui_config'] = function() - dapui.close() -end -dap.listeners.before.event_exited['dapui_config'] = function() - dapui.close() -end - -dap.adapters.python = { - type = 'executable', - command = '/usr/bin/python', - args = { '-m', 'debugpy.adapter' }, -} - -dap.configurations.python = { - { - type = 'python', - request = 'launch', - name = 'Launch file', - - program = '${file}', - pythonPath = function() - local cwd = vim.fn.getcwd() - if vim.fn.executable(cwd .. '/venv/bin/python') == 1 then - return cwd .. '/venv/bin/python' - elseif vim.fn.executable(cwd .. '/.venv/bin/python') == 1 then - return cwd .. '/.venv/bin/python' - else - return '/usr/bin/python' - end - end, - }, -} - -dap.adapters.ruby = { - type = 'executable', - command = 'bundle', - args = { 'exec', 'readapt', 'stdio' }, -} - -dap.configurations.ruby = { - { - type = 'ruby', - request = 'launch', - name = 'Rails', - program = 'bundle', - programArgs = { 'exec', 'rails', 's' }, - useBundler = true, - }, -} - -vim.api.nvim_create_user_command('DapUIToggle', function() - require('dapui').toggle() -end, {}) diff --git a/lua/plugins/tools/dbee.lua b/lua/plugins/tools/dbee.lua deleted file mode 100644 index 6b883e6..0000000 --- a/lua/plugins/tools/dbee.lua +++ /dev/null @@ -1,19 +0,0 @@ -local dbee = require('dbee') - -dbee.setup({ - sources = { - require('dbee.sources').EnvSource:new('NVIM_DB'), - -- require("dbee.sources").MemorySource:new({ - -- { - -- name = "dbname", - -- type = "postgres", - -- url = "postgres://pguser:pguser@localhost:5602/dbname?sslmode=disable" - -- }, - -- }), - -- require("dbee.sources").FileSource:new(vim.fn.stdpath("cache") .. "/dbee/config.json"), - }, -}) - -vim.api.nvim_create_user_command('DBToggle', function() - require('dbee').toggle() -end, {}) diff --git a/lua/plugins/tools/exercism.lua b/lua/plugins/tools/exercism.lua deleted file mode 100644 index 0b77676..0000000 --- a/lua/plugins/tools/exercism.lua +++ /dev/null @@ -1,7 +0,0 @@ -local exercism = require('exercism') - -exercism.setup({ - exercism_workspace = '~/Projects/2KAbhishek/exercism', - add_default_keybindings = true, - default_language = 'elixir', -}) diff --git a/lua/plugins/tools/files.lua b/lua/plugins/tools/files.lua deleted file mode 100644 index 71c5530..0000000 --- a/lua/plugins/tools/files.lua +++ /dev/null @@ -1,39 +0,0 @@ -local files = require('mini.files') - -files.setup({ - content = { - filter = nil, - prefix = nil, - sort = nil, - }, - mappings = { - close = 'q', - go_in = 'L', - go_in_plus = 'l', - go_out = 'h', - go_out_plus = 'H', - mark_goto = "'", - mark_set = 'm', - reset = '', - reveal_cwd = '@', - show_help = 'g?', - synchronize = '', - trim_left = '<', - trim_right = '>', - }, - options = { - permanent_delete = true, - use_as_default_explorer = true, - }, - windows = { - max_number = math.huge, - preview = false, - width_focus = 30, - width_nofocus = 20, - width_preview = 80, - }, -}) - -vim.api.nvim_set_hl(0, 'MiniFilesBorder', { bg = 'none' }) -vim.api.nvim_set_hl(0, 'MiniFilesNormal', { bg = 'none' }) -vim.api.nvim_set_hl(0, 'MiniFilesTitle', { bg = 'none' }) diff --git a/lua/plugins/tools/flash.lua b/lua/plugins/tools/flash.lua deleted file mode 100644 index f7cffa4..0000000 --- a/lua/plugins/tools/flash.lua +++ /dev/null @@ -1,57 +0,0 @@ -local flash = require('flash') -local icons = require('lib.icons') - -flash.setup({ - -- exact, fuzzy, regex, custom function - mode = 'fuzzy', - -- behave like `incsearch` - incremental = true, - - jump = { - -- save location in the jumplist - jumplist = true, - -- automatically jump when there is only one match - autojump = true, - }, - label = { - rainbow = { - enabled = true, - -- number between 1 and 9 - shade = 4, - }, - }, - prompt = { - enabled = true, - prefix = { { icons.ui.Separator .. icons.ui.Rocket .. icons.ui.ChevronRight .. ' ', 'FlashPromptIcon' } }, - win_config = { relative = 'editor', width = 1, height = 1, row = 1, col = 0, zindex = 1000 }, - }, - modes = { - search = { - enabled = true, - }, - char = { - enabled = false, - jump_labels = false, - }, - }, -}) - -vim.api.nvim_create_user_command('FlashDiagnostics', function() - require('flash').jump({ - matcher = function(win) - return vim.tbl_map(function(diag) - return { - pos = { diag.lnum + 1, diag.col }, - end_pos = { diag.end_lnum + 1, diag.end_col - 1 }, - } - end, vim.diagnostic.get(vim.api.nvim_win_get_buf(win))) - end, - action = function(match, state) - vim.api.nvim_win_call(match.win, function() - vim.api.nvim_win_set_cursor(match.win, match.pos) - vim.diagnostic.open_float() - end) - state:restore() - end, - }) -end, {}) diff --git a/lua/plugins/tools/gitlinker.lua b/lua/plugins/tools/gitlinker.lua deleted file mode 100644 index a16dbcd..0000000 --- a/lua/plugins/tools/gitlinker.lua +++ /dev/null @@ -1,24 +0,0 @@ -local gitlinker = require('gitlinker') - -gitlinker.setup({ - opts = { - remote = nil, - add_current_line_on_normal_mode = true, - action_callback = require('gitlinker.actions').copy_to_clipboard, - print_url = true, - }, - callbacks = { - ['github.com'] = require('gitlinker.hosts').get_github_type_url, - ['gitlab.com'] = require('gitlinker.hosts').get_gitlab_type_url, - ['try.gitea.io'] = require('gitlinker.hosts').get_gitea_type_url, - ['codeberg.org'] = require('gitlinker.hosts').get_gitea_type_url, - ['bitbucket.org'] = require('gitlinker.hosts').get_bitbucket_type_url, - ['try.gogs.io'] = require('gitlinker.hosts').get_gogs_type_url, - ['git.sr.ht'] = require('gitlinker.hosts').get_srht_type_url, - ['git.launchpad.net'] = require('gitlinker.hosts').get_launchpad_type_url, - ['repo.or.cz'] = require('gitlinker.hosts').get_repoorcz_type_url, - ['git.kernel.org'] = require('gitlinker.hosts').get_cgit_type_url, - ['git.savannah.gnu.org'] = require('gitlinker.hosts').get_cgit_type_url, - }, - mappings = 'yg', -}) diff --git a/lua/plugins/tools/navigator.lua b/lua/plugins/tools/navigator.lua deleted file mode 100644 index a16a9d7..0000000 --- a/lua/plugins/tools/navigator.lua +++ /dev/null @@ -1,8 +0,0 @@ -local navigator = require('Navigator') - -navigator.setup({ - auto_save = 'current', - disable_on_zoom = false, - mux = 'auto', -}) - diff --git a/lua/plugins/tools/neotest.lua b/lua/plugins/tools/neotest.lua deleted file mode 100644 index e5fc2c6..0000000 --- a/lua/plugins/tools/neotest.lua +++ /dev/null @@ -1,20 +0,0 @@ -local neotest = require('neotest') - -neotest.setup({ - adapters = { - require('neotest-rspec')({ - rspec_cmd = function() - return vim.tbl_flatten({ - 'bundle', - 'exec', - 'rspec', - }) - end, - }), - require('neotest-jest')({ - jestCommand = 'npx jest --', - jestConfigFile = 'jest.config.js', - }), - require('neotest-python'), - }, -}) diff --git a/lua/plugins/tools/octohub.lua b/lua/plugins/tools/octohub.lua deleted file mode 100644 index 0d2a26c..0000000 --- a/lua/plugins/tools/octohub.lua +++ /dev/null @@ -1,18 +0,0 @@ -local octohub = require('octohub') - -octohub.setup({ - per_user_dir = true, - projects_dir = '~/Projects/', - contribution_icons = { '', '', '', '', '', '', '' }, - sort_repos_by = '', - repo_type = '', - max_contributions = 50, - top_lang_count = 5, - event_count = 5, - window_width = 90, - window_height = 60, - show_recent_activity = true, - show_contributions = true, - show_repo_stats = true, - add_default_keybindings = true, -}) diff --git a/lua/plugins/tools/sniprun.lua b/lua/plugins/tools/sniprun.lua deleted file mode 100644 index 711b157..0000000 --- a/lua/plugins/tools/sniprun.lua +++ /dev/null @@ -1,27 +0,0 @@ -local sniprun = require('sniprun') -local sniprun_api = require('sniprun.api') - -sniprun.setup({ - display = { 'Api' }, - show_no_output = { 'Classic', 'TempFloatingWindow' }, - - display_options = { - terminal_width = 45, - notification_timeout = 5, - }, - - inline_messages = 0, - borders = 'single', -}) - -local api_listener = function(d) - if d.status == 'ok' then - vim.notify('Output: \n' .. d.message, vim.log.levels.INFO) - elseif d.status == 'error' then - vim.notify('Error: \n' .. d.message, vim.log.levels.ERROR) - else - vim.notify('Sniprun: ' .. d.message, vim.log.levels.INFO) - end -end - -sniprun_api.register_listener(api_listener) diff --git a/lua/plugins/tools/spectre.lua b/lua/plugins/tools/spectre.lua deleted file mode 100644 index 5100d02..0000000 --- a/lua/plugins/tools/spectre.lua +++ /dev/null @@ -1,125 +0,0 @@ -local spectre = require('spectre') - -spectre.setup({ - color_devicons = true, - highlight = { - ui = 'String', - search = 'DiffChange', - replace = 'DiffDelete', - }, - mapping = { - ['toggle_line'] = { - map = 't', - cmd = ":lua require('spectre').toggle_line()", - desc = 'toggle current item', - }, - ['enter_file'] = { - map = '', - cmd = ":lua require('spectre.actions').select_entry()", - desc = 'goto current file', - }, - ['send_to_qf'] = { - map = 'Q', - cmd = ":lua require('spectre.actions').send_to_qf()", - desc = 'send all item to quickfix', - }, - ['replace_cmd'] = { - map = 'c', - cmd = ":lua require('spectre.actions').replace_cmd()", - desc = 'input replace vim command', - }, - ['show_option_menu'] = { - map = 'o', - cmd = ":lua require('spectre').show_options()", - desc = 'show option', - }, - ['run_replace'] = { - map = 'R', - cmd = ":lua require('spectre.actions').run_replace()", - desc = 'replace all', - }, - ['change_view_mode'] = { - map = 'm', - cmd = ":lua require('spectre').change_view()", - desc = 'change result view mode', - }, - ['toggle_ignore_case'] = { - map = 'I', - cmd = ":lua require('spectre').change_options('ignore-case')", - desc = 'toggle ignore case', - }, - ['toggle_ignore_hidden'] = { - map = 'H', - cmd = ":lua require('spectre').change_options('hidden')", - desc = 'toggle search hidden', - }, - }, - find_engine = { - ['rg'] = { - cmd = 'rg', - args = { - '--color=never', - '--no-heading', - '--with-filename', - '--line-number', - '--column', - }, - options = { - ['ignore-case'] = { - value = '--ignore-case', - icon = '[I]', - desc = 'ignore case', - }, - ['hidden'] = { - value = '--hidden', - desc = 'hidden file', - icon = '[H]', - }, - }, - }, - ['ag'] = { - cmd = 'ag', - args = { - '--vimgrep', - '-s', - }, - options = { - ['ignore-case'] = { - value = '-i', - icon = '[I]', - desc = 'ignore case', - }, - ['hidden'] = { - value = '--hidden', - desc = 'hidden file', - icon = '[H]', - }, - }, - }, - }, - replace_engine = { - ['sed'] = { - cmd = 'sed', - args = nil, - }, - options = { - ['ignore-case'] = { - value = '--ignore-case', - icon = '[I]', - desc = 'ignore case', - }, - }, - }, - default = { - find = { - cmd = 'rg', - options = { 'ignore-case' }, - }, - replace = { - cmd = 'sed', - }, - }, - replace_vim_cmd = 'cdo', - is_open_target_win = true, - is_insert_mode = true, -}) diff --git a/lua/plugins/tools/toggleterm.lua b/lua/plugins/tools/toggleterm.lua deleted file mode 100644 index a59a984..0000000 --- a/lua/plugins/tools/toggleterm.lua +++ /dev/null @@ -1,23 +0,0 @@ -require('toggleterm').setup({ - size = 10, - open_mapping = [[]], - hide_numbers = true, - shade_filetypes = {}, - shade_terminals = true, - shading_factor = '2', - start_in_insert = true, - insert_mappings = true, - terminal_mappings = true, - persist_size = true, - direction = 'float', -- Use 'float' for floating terminal windows - close_on_exit = true, - shell = vim.o.shell, - float_opts = { - border = 'curved', -- or 'single', 'double', 'shadow', etc. - winblend = 0, -- Set to 0 for full transparency - highlights = { - border = 'Normal', - background = 'Normal', - }, - }, -}) diff --git a/lua/plugins/ui/gitsigns.lua b/lua/plugins/ui/gitsigns.lua deleted file mode 100644 index 54b6c91..0000000 --- a/lua/plugins/ui/gitsigns.lua +++ /dev/null @@ -1,63 +0,0 @@ -local gitsigns = require('gitsigns') -local icons = require('lib.icons') - -gitsigns.setup({ - signs = { - add = { text = icons.ui.SeparatorLight }, - change = { text = icons.ui.SeparatorLight }, - delete = { text = icons.ui.SeparatorLight }, - topdelete = { text = icons.ui.Topline }, - changedelete = { text = icons.ui.SeparatorLight }, - untracked = { text = icons.ui.SeparatorDashed }, - }, - signcolumn = true, - numhl = false, - linehl = false, - word_diff = false, - watch_gitdir = { interval = 1000, follow_files = true }, - attach_to_untracked = true, - current_line_blame = false, - current_line_blame_opts = { - virt_text = true, - virt_text_pos = 'eol', - delay = 0, - ignore_whitespace = false, - }, - current_line_blame_formatter = ', - ', - sign_priority = 6, - update_debounce = 100, - status_formatter = nil, - max_file_length = 40000, - preview_config = { border = 'rounded', style = 'minimal', relative = 'cursor', row = 0, col = 1 }, - on_attach = function(bufnr) - local gs = package.loaded.gitsigns - - local function map(mode, l, r, opts) - opts = opts or {} - opts.buffer = bufnr - vim.keymap.set(mode, l, r, opts) - end - - map('n', ']e', function() - if vim.wo.diff then - return ']e' - end - vim.schedule(function() - gs.next_hunk() - end) - return '' - end, { expr = true, desc = 'Next Change' }) - - map('n', '[e', function() - if vim.wo.diff then - return '[e' - end - vim.schedule(function() - gs.prev_hunk() - end) - return '' - end, { expr = true, desc = 'Prev Change' }) - - map({ 'o', 'x' }, 'ih', ':Gitsigns select_hunk') - end, -}) diff --git a/lua/plugins/ui/lualine.lua b/lua/plugins/ui/lualine.lua deleted file mode 100644 index 5a29dd0..0000000 --- a/lua/plugins/ui/lualine.lua +++ /dev/null @@ -1,221 +0,0 @@ -local lualine = require('lualine') -local icons = require('lib.icons') - --- Get colors from base46 theme (chadwal) -local colors = require("base46").get_theme_tb "base_30" - -local mode_color = { - n = colors.green, - i = colors.blue, - v = colors.pink, - [''] = colors.pink, - V = colors.pink, - c = colors.yellow, - t = colors.red, - R = colors.orange, - Rv = colors.orange, - no = colors.white, - s = colors.purple, - S = colors.purple, - [''] = colors.purple, - ic = colors.yellow, - cv = colors.red, - ce = colors.red, - r = colors.cyan, - rm = colors.cyan, - ['r?'] = colors.cyan, - ['!'] = colors.red, -} - -local conditions = { - buffer_not_empty = function() - return vim.fn.empty(vim.fn.expand('%:t')) ~= 1 - end, - buffer_is_file = function() - return vim.bo.buftype == '' - end, - buffer_not_scratch = function() - return string.find(vim.fn.bufname(), 'SCRATCH') == nil - end, - hide_in_width = function() - return vim.fn.winwidth(0) > 80 - end, - check_git_workspace = function() - local filepath = vim.fn.expand('%:p:h') - local gitdir = vim.fn.finddir('.git', filepath .. ';') - return gitdir and #gitdir > 0 and #gitdir < #filepath - end, -} - -local searchcount = { 'searchcount', color = { fg = colors.white, gui = 'bold' } } -local selectioncount = { 'selectioncount', color = { fg = colors.white, gui = 'bold' } } -local progress = { 'progress', color = { fg = colors.white, gui = 'bold' } } -local filetype = { 'filetype', color = { fg = colors.blue, gui = 'bold' } } -local filesize = { 'filesize', color = { fg = colors.white, gui = 'bold' }, cond = conditions.buffer_not_empty } -local fileformat = { 'fileformat', icons_enabled = true, color = { fg = colors.white, gui = 'bold' } } - -local filename = { - 'filename', - cond = conditions.buffer_not_empty and conditions.buffer_is_file and conditions.buffer_not_scratch, - color = { fg = colors.pink, gui = 'bold' }, -} - -local buffers = { - 'buffers', - mode = 2, - cond = conditions.buffer_not_scratch, - filetype_names = { - NvimTree = icons.documents.OpenFolder .. 'Files', - TelescopePrompt = icons.ui.Telescope .. 'Telescope', - Avante = icons.ui.Copilot .. 'Avante', - AvanteInput = icons.ui.Pencil .. 'Avante', - AvanteSelectedFiles = icons.documents.File .. 'Avante', - dashboard = icons.ui.Dashboard .. 'Dashboard', - lazy = icons.ui.Sleep .. 'Lazy', - mason = icons.ui.Package .. 'Mason', - minifiles = icons.documents.OpenFolder .. 'Files', - snacks_picker_input = icons.ui.Telescope .. 'Picker', - spectre_panel = icons.ui.Search .. 'Spectre', - }, - use_mode_colors = true, -} - -local branch = { - 'branch', - icon = icons.git.Branch, - fmt = function(str) - return str:sub(1, 32) - end, - color = { fg = colors.green, gui = 'bold' }, -} - -local diff_icons = { - 'diff', - symbols = { added = icons.git.AddAlt, modified = icons.git.DiffAlt, removed = icons.git.RemoveAlt }, - diff_color = { - added = { fg = colors.green }, - modified = { fg = colors.orange }, - removed = { fg = colors.red }, - }, - cond = conditions.hide_in_width, -} - -local diagnostics = { - 'diagnostics', - sources = { 'nvim_lsp', 'nvim_diagnostic', 'nvim_workspace_diagnostic' }, - symbols = { - error = icons.diagnostics.Error, - warn = icons.diagnostics.Warning, - info = icons.diagnostics.Information, - hint = icons.diagnostics.Hint, - }, - diagnostics_color = { - color_error = { fg = colors.red }, - color_warn = { fg = colors.yellow }, - color_info = { fg = colors.blue }, - color_hint = { fg = colors.yellow }, - }, -} - -local lsp = { - function() - local msg = 'No LSP' - local buf_ft = vim.api.nvim_get_option_value('filetype', { buf = 0 }) - local clients = vim.lsp.get_clients() - if next(clients) == nil then - return msg - end - for _, client in ipairs(clients) do - local filetypes = client.config and client.config.filetypes or nil - if filetypes and vim.fn.index(filetypes, buf_ft) ~= -1 then - return client.name - end - end - return msg - end, - icon = icons.ui.Gear, - color = { fg = colors.white, gui = 'bold' }, -} - -local encoding = { - 'o:encoding', - fmt = string.upper, - cond = conditions.hide_in_width, - color = { fg = colors.green, gui = 'bold' }, -} - -local function mode(icon) - icon = icon or icons.ui.Neovim - return { - function() - return icon - end, - color = function() - return { fg = mode_color[vim.fn.mode()] } - end, - padding = { left = 1, right = 0 }, - } -end - --- Create a custom theme based on chadwal colors (onedark style) -local custom_theme = { - normal = { - a = { fg = colors.black, bg = colors.green, gui = 'bold' }, - b = { fg = colors.white, bg = colors.one_bg }, - c = { fg = colors.light_grey, bg = 'NONE' }, - }, - insert = { - a = { fg = colors.black, bg = colors.blue, gui = 'bold' }, - b = { fg = colors.white, bg = colors.one_bg }, - c = { fg = colors.light_grey, bg = 'NONE' }, - }, - visual = { - a = { fg = colors.black, bg = colors.pink, gui = 'bold' }, - b = { fg = colors.white, bg = colors.one_bg }, - c = { fg = colors.light_grey, bg = 'NONE' }, - }, - replace = { - a = { fg = colors.black, bg = colors.red, gui = 'bold' }, - b = { fg = colors.white, bg = colors.one_bg }, - c = { fg = colors.light_grey, bg = 'NONE' }, - }, - command = { - a = { fg = colors.black, bg = colors.yellow, gui = 'bold' }, - b = { fg = colors.white, bg = colors.one_bg }, - c = { fg = colors.light_grey, bg = 'NONE' }, - }, - inactive = { - a = { fg = colors.grey, bg = 'NONE' }, - b = { fg = colors.grey, bg = 'NONE' }, - c = { fg = colors.grey, bg = 'NONE' }, - }, -} - -lualine.setup({ - options = { - component_separators = '', - section_separators = { left = '', right = '' }, - theme = custom_theme, - disabled_filetypes = { - 'dashboard', - }, - globalstatus = true, - }, - -- extensions = { 'quickfix', 'man', 'mason', 'lazy', 'toggleterm', 'nvim-tree' }, - tabline = { - lualine_a = {}, - lualine_b = { mode(), buffers }, - lualine_c = {}, - lualine_x = { diff_icons, branch }, - lualine_y = { searchcount, selectioncount }, - lualine_z = {}, - }, - sections = { - lualine_a = {}, - lualine_b = {}, - lualine_c = { mode(icons.ui.Heart), 'location', progress, filename }, - lualine_x = { diagnostics, lsp, filetype, filesize, fileformat, encoding }, - lualine_y = {}, - lualine_z = {}, - }, -}) diff --git a/lua/plugins/ui/snacks.lua b/lua/plugins/ui/snacks.lua deleted file mode 100644 index 7c78df3..0000000 --- a/lua/plugins/ui/snacks.lua +++ /dev/null @@ -1,334 +0,0 @@ -local Snacks = require('snacks') -local icons = require('lib.icons') - -local function files_layout(preview_width, height, width) - preview_width = preview_width or 0.6 - height = height or 0.8 - width = width or 0.9 - return { - layout = { - box = 'horizontal', - width = width, - min_width = 120, - height = height, - { - box = 'vertical', - border = 'rounded', - title = '{title} {live} {flags}', - { win = 'input', height = 1, border = 'bottom' }, - { win = 'list', border = 'none' }, - }, - { win = 'preview', title = '{preview}', border = 'rounded', width = preview_width }, - }, - } -end - -local function palette_layout(height, width) - height = height or 0.4 - width = width or 0.6 - return { - preview = false, - layout = { - backdrop = false, - row = 1, - width = width, - min_width = 80, - height = height, - border = 'rounded', - box = 'vertical', - { - win = 'input', - height = 1, - border = 'rounded', - title = '{title} {live} {flags}', - title_pos = 'center', - }, - { win = 'list', border = 'hpad' }, - { win = 'preview', title = '{preview}', border = 'rounded' }, - }, - } -end - -Snacks.setup({ - animate = { - enabled = true, - duration = 20, -- ms per step - easing = 'linear', - fps = 60, - }, - bigfile = { - enabled = true, - notify = true, - size = 1000 * 1024, -- 1 MB instead of 100 KB - }, - bufdelete = { enabled = true }, - dashboard = { - enabled = true, - sections = { - { section = 'header' }, - { - icon = icons.ui.Keyboard, - title = 'Keymaps', - section = 'keys', - indent = 2, - padding = 1, - }, - { - icon = icons.documents.File, - title = 'Recent Files', - section = 'recent_files', - indent = 2, - padding = 1, - }, - { - icon = icons.documents.OpenFolder, - title = 'Projects', - section = 'projects', - indent = 2, - padding = 1, - }, - { section = 'startup' }, - }, - }, - debug = { enabled = true }, - dim = { - enabled = true, - scope = { - min_size = 5, - max_size = 20, - siblings = true, - }, - }, - explorer = { enabled = false }, - git = { enabled = true }, - gitbrowse = { enabled = true }, - image = { enabled = true }, - indent = { - enabled = true, - priority = 1, - char = icons.ui.SeparatorLight, - only_scope = false, - only_current = false, - hl = { - 'SnacksIndent1', - 'SnacksIndent2', - 'SnacksIndent3', - 'SnacksIndent4', - 'SnacksIndent5', - 'SnacksIndent6', - 'SnacksIndent7', - 'SnacksIndent8', - }, - }, - input = { - enabled = true, - icon = icons.ui.Edit, - icon_hl = 'SnacksInputIcon', - icon_pos = 'left', - prompt_pos = 'title', - win = { style = 'input' }, - expand = true, - }, - layout = { enabled = true }, - lazygit = { enabled = true }, - notifier = { - enabled = true, - timeout = 2000, - width = { min = 40, max = 0.4 }, - height = { min = 1, max = 0.6 }, - margin = { top = 0, right = 1, bottom = 0 }, - padding = true, - sort = { 'level', 'added' }, - level = vim.log.levels.TRACE, - icons = { - debug = icons.ui.Bug, - error = icons.diagnostics.Error, - info = icons.diagnostics.Information, - trace = icons.ui.Bookmark, - warn = icons.diagnostics.Warning, - }, - style = 'compact', - top_down = true, - date_format = '%R', - more_format = ' ↓ %d lines ', - refresh = 50, - }, - notify = { enabled = true }, - picker = { - enabled = true, - icon = icons.ui.Search, - icon_hl = 'SnacksPickerIcon', - icon_pos = 'left', - prompt_pos = 'title', - win = { style = 'picker' }, - expand = true, - matchers = { - frecency = true, - cwd_bonus = false, - }, - sources = { - -- layout options: dropdown, horizontal, vertical, vscode, ivy, ivy_split, telescope, top, left, right, bottom, sidebar - buffers = { layout = files_layout() }, - commands = { layout = palette_layout() }, - command_history = { layout = palette_layout() }, - files = { - hidden = true, - layout = files_layout(), - }, - icons = { - icon_sources = { 'nerd_fonts', 'emoji' }, - layout = palette_layout(), - }, - git_files = { layout = files_layout() }, - git_branches = { layout = { preset = 'vertical' } }, - git_status = { layout = files_layout() }, - help = { layout = { preset = 'ivy_split' } }, - man = { layout = { preset = 'ivy_split' } }, - notifications = { layout = palette_layout() }, - projects = { layout = files_layout(0.8) }, - recent = { layout = files_layout() }, - search_history = { layout = palette_layout() }, - smart = { layout = files_layout() }, - undo = { layout = { preset = 'ivy' } }, - zoxide = { layout = files_layout(0.7) }, - }, - }, - profiler = { enabled = true }, - quickfile = { enabled = true }, - rename = { enabled = true }, - scope = { - enabled = true, - keys = { - textobject = { - ii = { - min_size = 2, -- minimum size of the scope - edge = false, -- inner scope - cursor = false, - treesitter = { blocks = { enabled = false } }, - desc = 'inner scope', - }, - ai = { - cursor = false, - min_size = 2, -- minimum size of the scope - treesitter = { blocks = { enabled = false } }, - desc = 'full scope', - }, - }, - jump = { - ['[a'] = { - min_size = 1, -- allow single line scopes - bottom = false, - cursor = false, - edge = true, - treesitter = { blocks = { enabled = false } }, - desc = 'jump to top edge of scope', - }, - [']a'] = { - min_size = 1, -- allow single line scopes - bottom = true, - cursor = false, - edge = true, - treesitter = { blocks = { enabled = false } }, - desc = 'jump to bottom edge of scope', - }, - }, - }, - }, - scratch = { - enabled = true, - name = 'SCRATCH', - ft = function() - if vim.bo.buftype == '' and vim.bo.filetype ~= '' then - return vim.bo.filetype - end - return 'markdown' - end, - icon = nil, - root = vim.fn.stdpath('data') .. '/scratch', - autowrite = true, - filekey = { - cwd = true, - branch = true, - count = true, - }, - win = { - width = 120, - height = 40, - bo = { buftype = '', buflisted = false, bufhidden = 'hide', swapfile = false }, - minimal = false, - noautocmd = false, - zindex = 20, - wo = { winhighlight = 'NormalFloat:Normal' }, - border = 'rounded', - title_pos = 'center', - footer_pos = 'center', - - keys = { - ['execute'] = { - '', - function(_) - vim.cmd('%SnipRun') - end, - desc = 'Execute buffer', - mode = { 'n', 'x' }, - }, - }, - }, - win_by_ft = { - lua = { - keys = { - ['source'] = { - 'cr', - function(self) - local name = 'scratch.' .. vim.fn.fnamemodify(vim.api.nvim_buf_get_name(self.buf), ':e') - Snacks.debug.run({ buf = self.buf, name = name }) - end, - desc = 'Source buffer', - mode = { 'n', 'x' }, - }, - }, - }, - }, - }, - scroll = { enabled = false }, - statuscolumn = { - enabled = false, -- Change this to false - left = { 'mark', 'sign' }, - right = { 'fold', 'git' }, - folds = { - open = false, - git_hl = false, - }, - git = { - patterns = { 'GitSign', 'MiniDiffSign' }, - }, - refresh = 50, - }, - terminal = { enabled = false }, - toggle = { enabled = false }, - win = { enabled = true }, - words = { enabled = false }, - zen = { - enabled = true, - toggles = { - dim = true, - git_signs = false, - mini_diff_signs = false, - -- diagnostics = false, - -- inlay_hints = false, - }, - show = { - statusline = false, - tabline = false, - }, - win = { style = 'zen' }, - zoom = { - toggles = {}, - show = { statusline = true, tabline = true }, - win = { - backdrop = false, - width = 0, - }, - }, - }, -}) diff --git a/lua/plugins/ui/which-key.lua b/lua/plugins/ui/which-key.lua deleted file mode 100644 index 5f2435c..0000000 --- a/lua/plugins/ui/which-key.lua +++ /dev/null @@ -1,446 +0,0 @@ -local which_key = require('which-key') -local icons = require('lib.icons') -local util = require('lib.util') -local prompts = require('lib.prompts') - -local setup = { - preset = 'helix', - plugins = { - marks = true, - registers = true, - spelling = { - enabled = true, - suggestions = 30, - }, - presets = { - operators = true, - motions = true, - text_objects = true, - windows = true, - nav = true, - z = true, - g = true, - }, - }, - icons = { - breadcrumb = icons.ui.ArrowOpen, - separator = icons.ui.Arrow, - group = '', - keys = { - Space = icons.ui.Rocket, - }, - rules = false, -- enable auto icon rules - }, - show_help = false, - show_keys = true, - triggers = { - { '', mode = 'nvisoct' }, - { '', mode = { 'n', 'v' } }, - }, -} - -local normal_mappings = { - mode = 'n', - { 'x', ':x', desc = ' Save and Quit' }, - - { 'a', group = ' AI' }, - { 'aC', ':AvanteClear', desc = 'avante: clear' }, - { 'am', ':MCPHub', desc = 'MCPHub' }, - { 'an', ':AvanteChatNew', desc = 'avante: new' }, - { 'ap', group = 'Insert Prompt' }, - { 'apd', prompts.add_prompt('docs'), desc = 'Docs' }, - { 'ape', prompts.add_prompt('explain'), desc = 'Explain' }, - { 'apf', prompts.add_prompt('fix'), desc = 'Fix' }, - { 'apg', prompts.add_prompt('commit'), desc = 'Commit' }, - { 'apo', prompts.add_prompt('optimize'), desc = 'Optimize' }, - { 'apr', prompts.add_prompt('review'), desc = 'Review' }, - { 'apt', prompts.add_prompt('tests'), desc = 'Tests' }, - - { 'c', group = ' Code' }, - { 'cF', ':retab', desc = 'Fix Tabs' }, - { 'cP', ':CccConvert', desc = 'Convert Color' }, - { 'cR', ':ReloadConfig', desc = 'Reload Configs' }, - { 'cc', ':CccHighlighterToggle', desc = 'Highlight Colors' }, - { 'cd', ':RootDir', desc = 'Root Directory' }, - { 'ce', ':%SnipRun', desc = 'Execute File' }, - { 'cf', ':lua vim.lsp.buf.format({async = true})', desc = 'Format File' }, - { 'cl', '::g/^\\s*$/d', desc = 'Clean Empty Lines' }, - { 'cm', ':MarkdownPreviewToggle', desc = 'Markdown Preview' }, - { 'co', ':Dashboard', desc = 'Dashboard' }, - { 'cp', ':CccPick', desc = 'Pick Color' }, - { 'cs', ':source %', desc = 'Source File' }, - { 'cp', ':PyworksWeb', desc = 'Pyworks Setup' }, - - { 'C', group = ' Comment' }, - { 'Cb', 'CBccbox', desc = 'Comment Box' }, - { 'Ct', 'CBllline', desc = 'Tiled line' }, - { 'Cl', 'CBline', desc = 'Line' }, - { 'Cm', 'CBllbox14', desc = 'Marked' }, - { 'Cc', 'CBcatalog', desc = 'Catalog' }, - { 'Cd', 'CBd', desc = 'Delete Comment Style' }, - - { 'e', group = ' Edit' }, - { 'ea', ':b#', desc = 'Alternate File' }, - { 'ec', group = 'Edit Configs' }, - { 'ecg', ':e ~/.gitconfig', desc = 'Git Config' }, - { 'eck', ':e ~/.config/kitty/kitty.conf', desc = 'Kitty Config' }, - { 'ecn', ':e $MYVIMRC', desc = 'Neovim Init' }, - { 'ecp', ':e ~/.config/nvim/lua/plugins/list.lua', desc = 'Plugin List' }, - { 'ect', ':e ~/.config/tmux/tmux.conf', desc = 'Tmux Config' }, - { 'eE', ':lua Snacks.explorer()', desc = 'File Explorer' }, - { 'et', ':lua MiniFiles.open()', desc = 'Explore Tree' }, - { 'ef', 'gf', desc = 'File Under Cursor' }, - { 'em', ':e README.md', desc = 'Readme' }, - { 'en', ':enew', desc = 'New File' }, - - { 'f', group = ' Find' }, - { 'fx', ':%bd|e#|bd#', desc = 'Close except current' }, - - { 'g', group = ' Git' }, - { 'gA', ':Gitsigns stage_buffer', desc = 'Stage Buffer' }, - { 'gC', ':CoAuthor', desc = 'Co-Authors' }, - { 'gP', ':Git push', desc = 'Push' }, - { 'gR', ':Gitsigns reset_buffer', desc = 'Reset Buffer' }, - { 'ga', ':Gitsigns stage_hunk', desc = 'Stage Hunk' }, - { 'gb', ":lua require('gitsigns').blame_line({full = true})", desc = 'Blame' }, - { 'gc', ':Git commit', desc = 'Commit Staged' }, - { 'gB', ":lua require('snacks').git.blame_line()", desc = 'Detailed Blame' }, - { 'gd', ':Gitsigns diffthis HEAD', desc = 'Git Diff' }, - { 'gF', ':Git', desc = 'Fugitive Panel' }, - { 'gg', ':lua require("snacks").lazygit()', desc = 'Lazygit' }, - { 'gi', ':Gitsigns preview_hunk', desc = 'Hunk Info' }, - { 'gj', ':Gitsigns next_hunk', desc = 'Next Hunk' }, - { 'gk', ':Gitsigns prev_hunk', desc = 'Prev Hunk' }, - { 'gp', ':Git pull', desc = 'Pull' }, - { 'gr', ':Gitsigns reset_hunk', desc = 'Reset Hunk' }, - { 'gt', group = 'Toggle' }, - { 'gtb', ':Gitsigns toggle_current_line_blame', desc = 'Blame' }, - { 'gtd', ':Gitsigns toggle_deleted', desc = 'Deleted' }, - { 'gtl', ':Gitsigns toggle_linehl', desc = 'Line HL' }, - { 'gtn', ':Gitsigns toggle_numhl', desc = 'Number HL' }, - { 'gts', ':Gitsigns toggle_signs', desc = 'Signs' }, - { 'gtw', ':Gitsigns toggle_word_diff', desc = 'Word Diff' }, - { 'gu', ':Gitsigns undo_stage_hunk', desc = 'Undo Stage Hunk' }, - { 'gv', ':Gitsigns select_hunk', desc = 'Select Hunk' }, - { 'gw', ':lua require("snacks").gitbrowse()', desc = 'Git Browse' }, - - { 'i', group = ' Insert' }, - { 'id', ":put =strftime('## %a, %d %b, %Y, %r')", desc = 'Date' }, - { 'if', ":put =expand('%:t')", desc = 'File Name' }, - { 'ip', ':put %', desc = 'Relative Path' }, - { 'iP', ':put %:p', desc = 'Absolute Path' }, - { 'it', ":put =strftime('## %r')", desc = 'Time' }, - - { 'j', group = ' Jump' }, - { 'jc', '*', desc = 'Word' }, - { 'jd', ':FlashDiagnostics', desc = 'Diagnostics' }, - { 'jh', '', desc = 'Backward' }, - { 'jj', ":lua require('flash').remote()", desc = 'Remote' }, - { 'jk', ":lua require('flash').treesitter()", desc = 'Treesitter' }, - { 'jl', '', desc = 'Forward' }, - { 'jp', ":lua require('flash').jump({continue = true})", desc = 'Previous Jump' }, - { 'js', ":lua require('flash').jump()", desc = 'Search' }, - { 'jt', ":lua require('flash').treesitter_search()", desc = 'Remote Treesitter' }, - { - 'jn', - ":lua require('flash').jump({search = { forward = true, wrap = false, multi_window = false },})", - desc = 'Search Forward', - }, - { - 'jN', - ":lua require('flash').jump({search = { forward = false, wrap = false, multi_window = false },})", - desc = 'Search Backward', - }, - { - 'jw', - ':lua require("flash").jump({ pattern = vim.fn.expand("")})', - desc = 'Current Word', - }, - - { 'l', group = ' LSP' }, - { 'la', ':Lspsaga code_action', desc = 'Code Action' }, - { 'ld', ':Lspsaga goto_definition', desc = 'Goto Definition' }, - { 'lf', ':Lspsaga finder', desc = 'Finder' }, - { 'lh', ':Lspsaga hover_doc', desc = 'Hover' }, - { 'lI', ':LspInfo', desc = 'LSP Info' }, - { 'lj', ':Lspsaga diagnostic_jump_next', desc = 'Next Diagnostic' }, - { 'lk', ':Lspsaga diagnostic_jump_prev', desc = 'Prev Diagnostic' }, - { 'lo', ':Lspsaga outline', desc = 'Outline' }, - { 'lp', ':Lspsaga peek_definition', desc = 'Peek Definition' }, - { 'lq', ':LspStop', desc = 'Stop LSP' }, - { 'lQ', ':LspRestart', desc = 'Restart LSP' }, - { 'lr', ':Lspsaga rename', desc = 'Rename' }, - { 'lR', ':Lspsaga project_replace', desc = 'Replace' }, - { 'lt', ':Lspsaga goto_type_definition', desc = 'Goto Type Definition' }, - { 'lT', ':Lspsaga peek_type_definition', desc = 'Peek Type Definition' }, - - { 'o', group = ' Options' }, - { 'oi', 'vim.show_pos', desc = 'Inspect Position' }, - { 'oN', ':lua Snacks.notifier.show_history()', desc = 'Notification History' }, - { 'or', ':set relativenumber!', desc = 'Relative Numbers' }, - - { 'p', group = ' Packages' }, - { 'pc', ':Lazy check', desc = 'Check' }, - { 'pd', ':Lazy debug', desc = 'Debug' }, - { 'pe', ':lua require("snacks").profiler.scratch()', desc = 'Profiler Scratch' }, - { 'pf', ':lua require("snacks").profiler.pick()', desc = 'Profiler Pick' }, - { 'pi', ':Lazy install', desc = 'Install' }, - { 'pl', ':Lazy log', desc = 'Log' }, - { 'pm', ':Mason', desc = 'Mason' }, - { 'pp', ':Lazy', desc = 'Plugins' }, - { 'pP', ':Lazy profile', desc = 'Profile' }, - { 'pr', ':Lazy restore', desc = 'Restore' }, - { 'ps', ':Lazy sync', desc = 'Sync' }, - { 'pt', ':lua require("snacks").profiler.toggle()', desc = 'Profiler Toggle' }, - { 'pu', ':Lazy update', desc = 'Update' }, - { 'px', ':Lazy clean', desc = 'Clean' }, - - { 'q', group = ' Quit' }, - { 'qa', ':qall', desc = 'Quit All' }, - { 'qb', ':bw', desc = 'Close Buffer' }, - { 'qd', ':lua require("snacks").bufdelete()', desc = 'Delete Buffer' }, - { 'qf', ':qall!', desc = 'Force Quit' }, - { 'qo', ':%bdelete|b#|bdelete#', desc = 'Close Others' }, - { 'qq', ':q', desc = 'Quit' }, - { 'qs', 'c', desc = 'Close Split' }, - { 'qw', ':wq', desc = 'Write and Quit' }, - - { 'r', group = ' Refactor' }, - { 'ra', ":lua require('spectre').open()", desc = 'Replace All' }, - { 'rb', ":lua require('spectre').open_file_search()", desc = 'Replace Buffer' }, - { 'rd', '', desc = 'Go To Definition' }, -- treesitter navigation - { 'rh', '', desc = 'List Definition Head' }, - { 'rj', '', desc = 'Next Usage' }, - { 'rk', '', desc = 'Previous Usage' }, - { 'rl', '', desc = 'List Definition' }, - { 'rn', '', desc = 'Swap Next' }, - { 'rp', '', desc = 'Swap Previous' }, - { 'rr', '', desc = 'Smart Rename' }, - { 'rs', ':%s/\\<\\>//gI', desc = 'Replace Word Buffer' }, - { 'rw', ":lua require('spectre').open_visual({select_word=true})", desc = 'Replace Word Everywhere' }, - - { 's', group = ' Split' }, - { 's+', ':resize +10', desc = 'Increase window height' }, - { 's-', ':vertical resize -20', desc = 'Decrease window width' }, - { 's/', 's', desc = 'Split Below' }, - { 's=', ':vertical resize +20', desc = 'Increase window width' }, - { 'sH', ':vertical resize -10', desc = 'Decrease window width' }, - { 'sJ', ':resize -5', desc = 'Decrease window height' }, - { 'sK', ':resize +5', desc = 'Increase window height' }, - { 'sL', ':vertical resize +10', desc = 'Increase window width' }, - { 's\\', 'v', desc = 'Split Right' }, - { 's_', ':resize -10', desc = 'Decrease window height' }, - { 's`', 'p', desc = 'Previous Window' }, - { 'sa', ':split', desc = 'Horizontal Split' }, - { 'sc', ':tabclose', desc = 'Close Tab' }, - { 'sf', ':tabfirst', desc = 'First Tab' }, - { 'sh', 'h', desc = 'Move Left' }, - { 'sj', 'j', desc = 'Move Down' }, - { 'sk', 'k', desc = 'Move Up' }, - { 'sl', 'l', desc = 'Move Right' }, - { 'sp', ':NavigatorPrevious', desc = 'Previous Pane' }, - { 'sq', 'c', desc = 'Close Split' }, - { 'ss', ':vsplit', desc = 'Vertical Split' }, - - { 't', group = ' Terminal' }, - { 't1', '1ToggleTerm', desc = 'Toggle Terminal' }, - { 't2', '2ToggleTerm', desc = 'Toggle Terminal' }, - { 'th', 'Sterm', desc = 'Horizontal Terminal' }, - { 'tv', 'Vterm', desc = 'Vertical Terminal' }, - { 'tc', 'close', desc = 'Hide Terminal' }, - - { 'w', group = ' Writing' }, - { 'wc', ':set spell!', desc = 'Spellcheck' }, - { 'wd', ':lua require("snacks").dim.enable()', desc = 'Dim On' }, - { 'wD', ':lua require("snacks").dim.disable()', desc = 'Dim Off' }, - { 'wf', ":lua require'utils'.sudo_write()", desc = 'Force Write' }, - { 'wj', ']s', desc = 'Next Misspell' }, - { 'wk', '[s', desc = 'Prev Misspell' }, - { 'wn', ':WriteNoFormat', desc = 'Write Without Formatting' }, - { 'wq', ':wq', desc = 'Write and Quit' }, - { 'ww', ':w', desc = 'Write' }, - { 'wz', ':lua require("snacks").zen.zen()', desc = 'Zen' }, - { 'wZ', ':lua require("snacks").zen.zoom()', desc = 'Zoom' }, - - { 'y', group = ' Yank' }, - { 'yL', ':CopyAbsolutePathWithLine', desc = 'Absolute Path with Line' }, - { 'yP', ':CopyAbsolutePath', desc = 'Absolute Path' }, - { 'ya', ':%y+', desc = 'Copy Whole File' }, - { 'yf', ':CopyFileName', desc = 'File Name' }, - { 'yg', ':lua require"gitlinker".get_buf_range_url()', desc = 'Copy Git URL' }, - { 'yl', ':CopyRelativePathWithLine', desc = 'Relative Path with Line' }, - { 'yp', ':CopyRelativePath', desc = 'Relative Path' }, -} - --- Numerical mappings -for i = 1, 9 do - table.insert(normal_mappings, { - string.format('n%d', i), - string.format(':Tdo %d', i), - desc = string.format('Todo %d Days In Future', i), - }) - - table.insert(normal_mappings, { - string.format('np%d', i), - string.format(':Tdo -%d', i), - desc = string.format('Todo %d Days From Past', i), - }) - - table.insert(normal_mappings, { - string.format('f%d', i), - string.format(':LualineBuffersJump%d', i), - desc = string.format('File %d', i), - }) -end - -local visual_mappings = { - mode = 'v', - { 'a', group = ' AI' }, - - { 'c', group = ' Code' }, - { 'ce', ":'<,'>SnipRun", desc = 'Execute Selection' }, - { 'cS', ':sort!', desc = 'Sort Desc' }, - { 'ci', ':sort i', desc = 'Sort Case Insensitive' }, - { 'cs', ':sort', desc = 'Sort Asc' }, - { 'cu', ':!uniq', desc = 'Unique' }, - { 'cx', ':lua', desc = 'Execute Lua' }, - - { 'C', group = ' Comment' }, - { 'Cb', 'CBccbox', desc = 'Comment Box' }, - { 'Ct', 'CBllline', desc = 'Tiled line' }, - { 'Cl', 'CBline', desc = 'Line' }, - { 'Cm', 'CBllbox14', desc = 'Marked' }, - { 'Cc', 'CBcatalog', desc = 'Catalog' }, - { 'Cd', 'CBd', desc = 'Delete Comment Style' }, - - { 'g', group = ' Git' }, - { 'ga', ":'<,'>Gitsigns stage_hunk", desc = 'Stage Hunk' }, - { 'gr', ":'<,'>Gitsigns reset_hunk", desc = 'Reset Hunk' }, - { 'gu', ":'<,'>Gitsigns undo_stage_hunk", desc = 'Undo Stage Hunk' }, - - { 'j', group = ' Jump' }, - { - 'jN', - ":lua require('flash').jump({search = { forward = false, wrap = false, multi_window = false },})", - desc = 'Search Backward', - }, - { 'jd', ':FlashDiagnostics', desc = 'Diagnostics' }, - { 'jj', ":lua require('flash').remote()", desc = 'Remote' }, - { 'jk', ":lua require('flash').treesitter()", desc = 'Treesitter' }, - { - 'jn', - ":lua require('flash').jump({search = { forward = true, wrap = false, multi_window = false },})", - desc = 'Search Forward', - }, - { 'jp', ":lua require('flash').jump({continue = true})", desc = 'Previous Jump' }, - { 'js', ":lua require('flash').jump()", desc = 'Search' }, - { 'jt', ":lua require('flash').treesitter_search()", desc = 'Remote Treesitter' }, - { - 'jw', - ':lua require("flash").jump({ pattern = vim.fn.expand("")})', - desc = 'Current Word', - }, - - { 'l', group = ' LSP' }, - { 'la', ':Lspsaga range_code_action', desc = 'Code Action' }, - - { 'p', group = ' ScreenShot' }, - { 'py', 'CodeSnap', mode = 'x', desc = 'Save selected code snapshot into clipboard' }, - { 'ps', 'CodeSnapSave', mode = 'x', desc = 'Save selected code snapshot in ~/Pictures' }, - { - 'ph', - 'CodeSnapHighlight', - mode = 'x', - desc = 'Highlight and snapshot selected code into clipboard', - }, - { 'pi', 'CodeSnapASCII', mode = 'x', desc = 'Save ASCII code snapshot into clipboard' }, - - { 'y', group = ' Yank' }, - { 'yg', ':lua require"gitlinker".get_buf_range_url("v")', desc = 'Copy Git URL' }, -} - -local no_leader_mappings = { - mode = 'n', - { '', ':resize -10', desc = 'Decrease window height' }, - { '', ':vertical resize -10', desc = 'Decrease window width' }, - { '', ':vertical resize +10', desc = 'Increase window width' }, - { '', ':resize +10', desc = 'Increase window height' }, - { '', ':Fterm lazygit', desc = 'Lazygit' }, - - { '', ':NavigatorLeft', desc = 'Move Left' }, - { '', ':NavigatorDown', desc = 'Move Down' }, - { '', ':NavigatorUp', desc = 'Move Up' }, - { '', ':NavigatorRight', desc = 'Move Right' }, - { '', ':NavigatorPrevious', desc = 'Previous Pane' }, - - { '', ':bprevious', desc = 'Previous Buffer' }, - { '', ':bnext', desc = 'Next Buffer' }, - { '', ':bnext', desc = 'Next Buffer' }, - { '', ':bprevious', desc = 'Previous Buffer' }, - - { 'K', ':Lspsaga hover_doc', desc = 'LSP Hover' }, - { 'Q', ':qall!', desc = 'Force Quit!' }, - { 'U', ':redo', desc = 'Redo' }, - - { '[', group = ' Previous' }, - { '[g', ':Gitsigns prev_hunk', desc = 'Git Hunk' }, - { '[o', group = 'Textobjects' }, - - { ']', group = ' Next' }, - { ']g', ':Gitsigns next_hunk', desc = 'Git Hunk' }, - { ']o', group = 'Textobjects' }, - - { 'gd', ':Lspsaga goto_definition', desc = 'Goto Definition' }, -} - -which_key.setup(setup) -which_key.add(normal_mappings) -which_key.add(visual_mappings) -which_key.add(no_leader_mappings) - -if util.get_user_config('enable_test_runner', false) then - local test_runner_bindings = { - mode = 'n', - { 'u', group = ' Test' }, - { 'uc', ':lua require("neotest").run.run()', desc = 'Run Current Test' }, - { 'uf', ':lua require("neotest").run.run(vim.fn.expand("%"))', desc = 'Run Test File' }, - { 'uo', ':Neotest output-panel', desc = 'Test Output' }, - { 'us', ':Neotest summary', desc = 'Test Summary' }, - } - which_key.add(test_runner_bindings) -end - -if util.get_user_config('enable_db_explorer', false) then - local db_explorer_bindings = { - mode = 'n', - { 'd', group = ' Database' }, - { 'dS', ':lua require("dbee").store("json", "buffer", { extra_arg = 0 })', desc = 'To JSON' }, - { 'db', ':DBToggle', desc = 'DB Explorer' }, - { 'dj', ':lua require("dbee").next()', desc = 'DB Next' }, - { 'dk', ':lua require("dbee").prev()', desc = 'DB Prev' }, - { 'ds', ':lua require("dbee").store("csv", "buffer", { extra_arg = 0 })', desc = 'To CSV' }, - { 'dt', ':lua require("dbee").store("table", "buffer", { extra_arg = 0 })', desc = 'To Table' }, - } - which_key.add(db_explorer_bindings) -end - -if util.get_user_config('enable_debugger', false) then - local debugger_bindings = { - mode = 'n', - { 'b', group = ' Debug' }, - { 'bO', ':DapStepOut', desc = 'Out' }, - { 'bR', ':DapRestartFrame', desc = 'Restart Frame' }, - { 'bb', ':DapToggleBreakpoint', desc = 'Breakpoint' }, - { 'bc', ':DapContinue', desc = 'Continue' }, - { 'bi', ':DapStepInto', desc = 'Into' }, - { 'bl', ":lua require'dap'.run_last()", desc = 'Last' }, - { 'bo', ':DapStepOver', desc = 'Over' }, - { 'br', ':DapToggleRepl', desc = 'Repl' }, - { 'bt', ':DapUIToggle', desc = 'Debugger' }, - { 'bx', ':DapTerminate', desc = 'Exit' }, - } - which_key.add(debugger_bindings) -end - -local user_keybindings = require('lib.util').get_user_config('user_keybindings', {}) -which_key.add(user_keybindings) diff --git a/lua/plugins/utility.lua b/lua/plugins/utility.lua new file mode 100644 index 0000000..92ebacb --- /dev/null +++ b/lua/plugins/utility.lua @@ -0,0 +1,169 @@ +return { + + --harpoon + { + "ThePrimeagen/harpoon", + branch = "harpoon2", + keys = { + { + "", + function() + require("harpoon"):list():select(1) + end, + desc = "buffer j", + }, + { + "", + function() + require("harpoon"):list():select(2) + end, + desc = "buffer k", + }, + { + "", + function() + require("harpoon"):list():select(3) + end, + desc = "buffer l", + }, + { + "", + function() + require("harpoon"):list():select(4) + end, + desc = "buffer ;", + }, + }, + }, + + -- better escape + { + "max397574/better-escape.nvim", + config = function() + require("better_escape").setup({ + mappings = { + -- i for insert, other modes are the first letter too + i = { + -- map kj to exit insert mode + k = { + j = "", + }, + -- map jk and jj to exit insert mode + j = { + k = "", + j = "", + }, + -- disable jj + j = { + j = false, + }, + }, + }, + }) + end, + }, + + -- Navigator + { + "numToStr/Navigator.nvim", + event = "VeryLazy", + config = function() + require("Navigator").setup({ + auto_save = "current", + disable_on_zoom = false, + mux = "auto", + }) + end, + }, + + -- float terminal + { + "akinsho/toggleterm.nvim", + cmd = { "ToggleTerm" }, + version = "v2.*", + config = function() + require("toggleterm").setup({ + size = 10, + open_mapping = [[]], + hide_numbers = true, + shade_filetypes = {}, + shade_terminals = true, + shading_factor = "2", + start_in_insert = true, + insert_mappings = true, + terminal_mappings = true, + persist_size = true, + direction = "float", -- Use 'float' for floating terminal windows + close_on_exit = true, + shell = vim.o.shell, + float_opts = { + border = "curved", -- or 'single', 'double', 'shadow', etc. + winblend = 0, -- Set to 0 for full transparency + highlights = { + border = "Normal", + background = "Normal", + }, + }, + }) + end, + }, + + -- smooth scrolling + { + "karb94/neoscroll.nvim", + opts = {}, + }, + + -- discord presence + -- { + -- "vyfor/cord.nvim", + -- event = "VeryLazy", + -- }, + + { + "rachartier/tiny-code-action.nvim", + dependencies = { + { + "folke/snacks.nvim", + opts = { + terminal = {}, + }, + }, + }, + event = "LspAttach", + opts = {}, + vim.keymap.set({ "n", "x" }, "ca", function() + require("tiny-code-action").code_action() + end, { noremap = true, silent = true }), + }, + + -- uv + { + "benomahony/uv.nvim", + ft = "python", + event = "BufReadPre", + opts = { + picker_integration = true, + keymaps = { + prefix = "u", -- Main prefix for uv commands + commands = true, -- Show uv commands menu (x) + run_file = true, -- Run current file (xr) + run_selection = true, -- Run selected code (xs) + run_function = true, -- Run function (xf) + venv = true, -- Environment management (xe) + init = true, -- Initialize uv project (xi) + add = true, -- Add a package (xa) + remove = true, -- Remove a package (xd) + sync = true, -- Sync packages (xc) + sync_all = true, -- Sync all packages, extras and groups (xC) + }, + }, + }, + + { "wakatime/vim-wakatime", event = "VimEnter", lazy = false }, + -- { + -- "m4xshen/hardtime.nvim", + -- lazy = false, + -- opts = {}, + -- }, +} diff --git a/lua/plugins/whichkey.lua b/lua/plugins/whichkey.lua new file mode 100644 index 0000000..5ec4cde --- /dev/null +++ b/lua/plugins/whichkey.lua @@ -0,0 +1,307 @@ +return { + "folke/which-key.nvim", + event = "VeryLazy", + config = function() + local wk = require("which-key") + wk.setup({ + preset = "helix", + plugins = { + marks = true, + registers = true, + spelling = { + enabled = true, + suggestions = 30, + }, + }, + presets = { + operators = true, + motions = true, + text_objects = true, + windows = true, + nav = true, + z = true, + g = true, + }, + icons = { + breadcrumb = " ", + separator = " ", + group = "", + keys = { + Space = " ", + }, + rules = false, -- enable auto icon rules + }, + show_help = false, + show_keys = true, + triggers = { + { "", mode = "nvisoct" }, + { "", mode = { "n", "v" } }, + }, + }) + + local normal_mappings = { + mode = "n", + { "x", ":x", desc = " Save and Quit" }, + + -- { "a", group = " AI" }, + + { "c", group = " Code" }, + { "cF", ":retab", desc = "Fix Tabs" }, + { "cd", ":RootDir", desc = "Root Directory" }, + { "cf", ":lua vim.lsp.buf.format({async = true})", desc = "Format File" }, + { "cl", "::g/^\\s*$/d", desc = "Clean Empty Lines" }, + { "cm", ":MarkdownPreviewToggle", desc = "Markdown Preview" }, + { + "ct", + function() + local curr_path = vim.fn.expand("%:p") + Snacks.picker.todo_comments({ + transform = function(item) + local item_path = vim.fn.fnamemodify(item.cwd .. "/" .. item.file, ":p") + return item_path == curr_path + end, + }) + end, + desc = "Todo", + }, + + { "e", group = " Edit" }, + { "ea", ":b#", desc = "Alternate File" }, + { "ec", group = "Edit Configs" }, + { "ee", ":lua MiniFiles.open()", desc = "Explore Tree" }, + { "eE", ":lua Snacks.explorer()", desc = "File Explorer" }, + { "ef", "gf", desc = "File Under Cursor" }, + { "em", ":e README.md", desc = "Readme" }, + { "en", ":enew", desc = "New File" }, + { "er", ":lua require('snacks').rename.rename_file()", desc = "Rename Current File" }, + + { "f", group = " Find" }, + { "fx", ":%bd|e#|bd#", desc = "Close except current" }, + { "ff", ":lua require('snacks').picker.files()", desc = "Find Files" }, + { "fg", ":lua require('snacks').picker.live_grep()", desc = "Live Grep" }, + + { "g", group = " Git" }, + { "gA", ":Gitsigns stage_buffer", desc = "Stage Buffer" }, + { "gR", ":Gitsigns reset_buffer", desc = "Reset Buffer" }, + { "ga", ":Gitsigns stage_hunk", desc = "Stage Hunk" }, + { "gb", ":lua require('gitsigns').blame_line({full = true})", desc = "Blame" }, + { "gB", ":lua require('snacks').git.blame_line()", desc = "Detailed Blame" }, + { "gd", ":Gitsigns diffthis HEAD", desc = "Git Diff" }, + { "gF", ":Git", desc = "Fugitive Panel" }, + { "gi", ":Gitsigns preview_hunk", desc = "Hunk Info" }, + { "gj", ":Gitsigns next_hunk", desc = "Next Hunk" }, + { "gk", ":Gitsigns prev_hunk", desc = "Prev Hunk" }, + { "gr", ":Gitsigns reset_hunk", desc = "Reset Hunk" }, + { "gu", ":Gitsigns undo_stage_hunk", desc = "Undo Stage Hunk" }, + { "gv", ":Gitsigns select_hunk", desc = "Select Hunk" }, + { "gw", ':lua require("snacks").gitbrowse()', desc = "Git Browse" }, + { + "gbr", + ":lua require('snacks').picker.git_branches()", + desc = "Pick and Switch Git Branches", + }, + + { "h", group = "Harpoon" }, + { + "ha", + function() + require("harpoon"):list():add() + end, + desc = "Harpoon add file", + }, + { + "hl", + function() + require("harpoon").ui:toggle_quick_menu(require("harpoon"):list()) + end, + desc = "Harpoon quick menu", + }, + + { "gt", group = "Toggle" }, + { "gtb", ":Gitsigns toggle_current_line_blame", desc = "Blame" }, + { "gtd", ":Gitsigns toggle_deleted", desc = "Deleted" }, + { "gtl", ":Gitsigns toggle_linehl", desc = "Line HL" }, + { "gtn", ":Gitsigns toggle_numhl", desc = "Number HL" }, + { "gts", ":Gitsigns toggle_signs", desc = "Signs" }, + { "gtw", ":Gitsigns toggle_word_diff", desc = "Word Diff" }, + + { "i", group = " Insert" }, + { "id", ":put =strftime('## %a, %d %b, %Y, %r')", desc = "Date" }, + { "if", ":put =expand('%:t')", desc = "File Name" }, + { "ip", ":put %", desc = "Relative Path" }, + { "iP", ":put %:p", desc = "Absolute Path" }, + { "it", ":put =strftime('## %r')", desc = "Time" }, + + { "l", group = " LSP" }, + { "la", ":Lspsaga code_action", desc = "Code Action" }, + { "ld", ":Lspsaga goto_definition", desc = "Goto Definition" }, + { "lf", ":Lspsaga finder", desc = "Finder" }, + { "lh", ":Lspsaga hover_doc", desc = "Hover" }, + { "lI", ":LspInfo", desc = "LSP Info" }, + { "lj", ":Lspsaga diagnostic_jump_next", desc = "Next Diagnostic" }, + { "lk", ":Lspsaga diagnostic_jump_prev", desc = "Prev Diagnostic" }, + { "lo", ":Lspsaga outline", desc = "Outline" }, + { "lp", ":Lspsaga peek_definition", desc = "Peek Definition" }, + { "lq", ":LspStop", desc = "Stop LSP" }, + { "lQ", ":LspRestart", desc = "Restart LSP" }, + { "lr", ":Lspsaga rename", desc = "Rename" }, + { "lR", ":Lspsaga project_replace", desc = "Replace" }, + { "lt", ":Lspsaga goto_type_definition", desc = "Goto Type Definition" }, + { "lT", ":Lspsaga peek_type_definition", desc = "Peek Type Definition" }, + + { "o", group = " Options" }, + { "oi", "vim.show_pos", desc = "Inspect Position" }, + { "oN", ":lua Snacks.notifier.show_history()", desc = "Notification History" }, + { "or", ":set relativenumber!", desc = "Relative Numbers" }, + + { "p", group = " Packages" }, + { "pc", ":Lazy check", desc = "Check" }, + { "pd", ":Lazy debug", desc = "Debug" }, + { "pe", ':lua require("snacks").profiler.scratch()', desc = "Profiler Scratch" }, + { "pf", ':lua require("snacks").profiler.pick()', desc = "Profiler Pick" }, + { "pi", ":Lazy install", desc = "Install" }, + { "pl", ":Lazy log", desc = "Log" }, + { "pm", ":Mason", desc = "Mason" }, + { "pp", ":Lazy", desc = "Plugins" }, + { "pP", ":Lazy profile", desc = "Profile" }, + { "pr", ":Lazy restore", desc = "Restore" }, + { "ps", ":Lazy sync", desc = "Sync" }, + { "pt", ':lua require("snacks").profiler.toggle()', desc = "Profiler Toggle" }, + { "pu", ":Lazy update", desc = "Update" }, + { "px", ":Lazy clean", desc = "Clean" }, + + { "q", group = " Quit" }, + { "qa", ":qall", desc = "Quit All" }, + { "qb", ":bw", desc = "Close Buffer" }, + { "qd", ':lua require("snacks").bufdelete()', desc = "Delete Buffer" }, + { "qf", ":qall!", desc = "Force Quit" }, + { "qo", ":%bdelete|b#|bdelete#", desc = "Close Others" }, + { "qq", ":q", desc = "Quit" }, + { "qs", "c", desc = "Close Split" }, + { "qw", ":wq", desc = "Write and Quit" }, + + { "r", group = " Refactor" }, + { "rd", "", desc = "Go To Definition" }, -- treesitter navigation + { "rh", "", desc = "List Definition Head" }, + { "rj", "", desc = "Next Usage" }, + { "rk", "", desc = "Previous Usage" }, + { "rl", "", desc = "List Definition" }, + { "rn", "", desc = "Swap Next" }, + { "rp", "", desc = "Swap Previous" }, + { "rr", "", desc = "Smart Rename" }, + { "rs", ":%s/\\<\\>//gI", desc = "Replace Word Buffer" }, + + { "s", group = " Split" }, + { "s+", ":resize +10", desc = "Increase window height" }, + { "s-", ":vertical resize -20", desc = "Decrease window width" }, + { "s/", "s", desc = "Split Below" }, + { "s=", ":vertical resize +20", desc = "Increase window width" }, + { "sH", ":vertical resize -10", desc = "Decrease window width" }, + { "sJ", ":resize -5", desc = "Decrease window height" }, + { "sK", ":resize +5", desc = "Increase window height" }, + { "sL", ":vertical resize +10", desc = "Increase window width" }, + { "s\\", "v", desc = "Split Right" }, + { "s_", ":resize -10", desc = "Decrease window height" }, + { "s`", "p", desc = "Previous Window" }, + { "sa", ":split", desc = "Horizontal Split" }, + { "sc", ":tabclose", desc = "Close Tab" }, + { "sf", ":tabfirst", desc = "First Tab" }, + { "sh", "h", desc = "Move Left" }, + { "sj", "j", desc = "Move Down" }, + { "sk", "k", desc = "Move Up" }, + { "sl", "l", desc = "Move Right" }, + { "sp", ":NavigatorPrevious", desc = "Previous Pane" }, + { "sq", "c", desc = "Close Split" }, + { "ss", ":vsplit", desc = "Vertical Split" }, + + { "t", group = " Terminal" }, + { "t1", "1ToggleTerm", desc = "Toggle Terminal" }, + { "t2", "2ToggleTerm", desc = "Toggle Terminal" }, + { "tc", "close", desc = "Hide Terminal" }, + + { "th", group = "Inlay Hints" }, + + { "w", group = " Writing" }, + { "wc", ":set spell!", desc = "Spellcheck" }, + { "wd", ':lua require("snacks").dim.enable()', desc = "Dim On" }, + { "wD", ':lua require("snacks").dim.disable()', desc = "Dim Off" }, + { "wf", ":lua require'utils'.sudo_write()", desc = "Force Write" }, + { "wj", "]s", desc = "Next Misspell" }, + { "wk", "[s", desc = "Prev Misspell" }, + { "wn", ":WriteNoFormat", desc = "Write Without Formatting" }, + { "wq", ":wq", desc = "Write and Quit" }, + { "ww", ":w", desc = "Write" }, + { "wz", ':lua require("snacks").zen.zen()', desc = "Zen" }, + { "wZ", ':lua require("snacks").zen.zoom()', desc = "Zoom" }, + + { "y", group = " Yank" }, + { "yL", ":CopyAbsolutePathWithLine", desc = "Absolute Path with Line" }, + { "yP", ":CopyAbsolutePath", desc = "Absolute Path" }, + { "ya", ":%y+", desc = "Copy Whole File" }, + { "yf", ":CopyFileName", desc = "File Name" }, + { "yg", ':lua require"gitlinker".get_buf_range_url()', desc = "Copy Git URL" }, + { "yl", ":CopyRelativePathWithLine", desc = "Relative Path with Line" }, + { "yp", ":CopyRelativePath", desc = "Relative Path" }, + } + + local visual_mappings = { + mode = "v", + -- { "a", group = " AI" }, + + { "c", group = " Code" }, + { "cS", ":sort!", desc = "Sort Desc" }, + { "ci", ":sort i", desc = "Sort Case Insensitive" }, + { "cs", ":sort", desc = "Sort Asc" }, + { "cu", ":!uniq", desc = "Unique" }, + { "cx", ":lua", desc = "Execute Lua" }, + + { "g", group = " Git" }, + { "ga", ":'<,'>Gitsigns stage_hunk", desc = "Stage Hunk" }, + { "gr", ":'<,'>Gitsigns reset_hunk", desc = "Reset Hunk" }, + { "gu", ":'<,'>Gitsigns undo_stage_hunk", desc = "Undo Stage Hunk" }, + + { "l", group = " LSP" }, + { "la", ":Lspsaga range_code_action", desc = "Code Action" }, + + { "y", group = " Yank" }, + { "yg", ':lua require"gitlinker".get_buf_range_url("v")', desc = "Copy Git URL" }, + } + + local no_leader_mappings = { + mode = "n", + { "", ":resize -10", desc = "Decrease window height" }, + { "", ":vertical resize -10", desc = "Decrease window width" }, + { "", ":vertical resize +10", desc = "Increase window width" }, + { "", ":resize +10", desc = "Increase window height" }, + + { "", ":NavigatorLeft", desc = "Move Left" }, + { "", ":NavigatorDown", desc = "Move Down" }, + { "", ":NavigatorUp", desc = "Move Up" }, + { "", ":NavigatorRight", desc = "Move Right" }, + { "", ":NavigatorPrevious", desc = "Previous Pane" }, + + { "", ":bprevious", desc = "Previous Buffer" }, + { "", ":bnext", desc = "Next Buffer" }, + { "", ":bnext", desc = "Next Buffer" }, + { "", ":bprevious", desc = "Previous Buffer" }, + + { "K", ":Lspsaga hover_doc", desc = "LSP Hover" }, + { "Q", ":qall!", desc = "Force Quit!" }, + { "U", ":redo", desc = "Redo" }, + + { "[", group = " Previous" }, + { "[g", ":Gitsigns prev_hunk", desc = "Git Hunk" }, + { "[o", group = "Textobjects" }, + + { "]", group = " Next" }, + { "]g", ":Gitsigns next_hunk", desc = "Git Hunk" }, + { "]o", group = "Textobjects" }, + + { "gd", ":Lspsaga goto_definition", desc = "Goto Definition" }, + } + + wk.add(normal_mappings) + wk.add(visual_mappings) + wk.add(no_leader_mappings) + end, +} diff --git a/plugin/after/highlights.lua b/plugin/after/highlights.lua deleted file mode 100644 index 24ac199..0000000 --- a/plugin/after/highlights.lua +++ /dev/null @@ -1,28 +0,0 @@ --- transparent background -vim.api.nvim_set_hl(0, 'Normal', { bg = 'none' }) -vim.api.nvim_set_hl(0, 'NormalFloat', { bg = 'none' }) -vim.api.nvim_set_hl(0, 'FloatBorder', { bg = 'none' }) -vim.api.nvim_set_hl(0, 'Pmenu', { bg = 'none' }) -vim.api.nvim_set_hl(0, 'Terminal', { bg = 'none' }) -vim.api.nvim_set_hl(0, 'EndOfBuffer', { bg = 'none' }) -vim.api.nvim_set_hl(0, 'FoldColumn', { bg = 'none' }) -vim.api.nvim_set_hl(0, 'Folded', { bg = 'none' }) -vim.api.nvim_set_hl(0, 'SignColumn', { bg = 'none' }) - --- transparent background for nvim-tree -vim.api.nvim_set_hl(0, 'NvimTreeNormal', { bg = 'none' }) -vim.api.nvim_set_hl(0, 'NvimTreeVertSplit', { bg = 'none' }) -vim.api.nvim_set_hl(0, 'NvimTreeEndOfBuffer', { bg = 'none' }) - --- set hlsearch color -vim.api.nvim_set_hl(0, 'Search', { bg = '#8BCD5B', fg = '#202020' }) -vim.api.nvim_set_hl(0, 'CurSearch', { bg = '#EFBD5D', fg = '#000000' }) -vim.api.nvim_set_hl(0, 'IncSearch', { bg = '#F15664', fg = '#000000' }) - --- set cursorline color -vim.api.nvim_set_hl(0, 'CursorLine', { bg = '#1A1A1F' }) -vim.api.nvim_set_hl(0, 'CursorColumn', { bg = '#1A1A1F' }) - --- set visual highlight -vim.api.nvim_set_hl(0, 'Visual', { bg = '#103070' }) - diff --git a/pywal/.gitignore b/pywal/.gitignore deleted file mode 100644 index b0ac3ed..0000000 --- a/pywal/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.aider* diff --git a/pywal/LICENSE b/pywal/LICENSE deleted file mode 100644 index f288702..0000000 --- a/pywal/LICENSE +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/pywal/README.md b/pywal/README.md deleted file mode 100644 index e0bc5ef..0000000 --- a/pywal/README.md +++ /dev/null @@ -1,71 +0,0 @@ -

Base46: Pywal Edition

- -

Pywal and Matugen support for NvChad!

- -> [!NOTE] -> Support for Pywal requires these Python libraries to be installed: -> - `pywal` -> - `watchdog` - -## Installation -```bash -cd ~/.config/nvim -git clone https://github.com/NvChad/pywal -``` -Add this at the end of your `init.lua` file: -```lua -os.execute("python ~/.config/nvim/pywal/chadwal.py &> /dev/null &") - -local autocmd = vim.api.nvim_create_autocmd - -autocmd("Signal", { - pattern = "SIGUSR1", - callback = function() - require('nvchad.utils').reload() - end -}) -``` -Now you need to generate your Pywal theme again using `wal -i `. If not, `chadwal` will default to `gruvchad` colors. - -### Matugen support -Add this your `~/.config/matugen/config.toml` file: -```toml -[templates.nvim] -input_path = '~/.config/nvim/pywal/matugen.lua' -output_path = '~/.cache/wal/base46-dark.lua' - -[config.custom_colors.red] -color = "#FF0000" -blend = true - -[config.custom_colors.green] -color = "#00FF00" -blend = true - -[config.custom_colors.yellow] -color = "#FFFF00" -blend = true - -[config.custom_colors.blue] -color = "#0000FF" -blend = true - -[config.custom_colors.magenta] -color = "#FF00FF" -blend = true - -[config.custom_colors.cyan] -color = "#00FFFF" -blend = true - -[config.custom_colors.white] -color = "#FFFFFF" -blend = true -``` - -Just like with Pywal, you need to generate your theme again using `matugen image `. If not, `chadwal` will default to `gruvchad` colors. - -Select `chadwal` theme and enjoy! - -## Demo -https://github.com/user-attachments/assets/933c97f2-4566-406c-8c04-e2e9f0f3f6da diff --git a/pywal/chadwal.py b/pywal/chadwal.py deleted file mode 100644 index c676271..0000000 --- a/pywal/chadwal.py +++ /dev/null @@ -1,120 +0,0 @@ -#!/usr/bin/env python3 - -import os -import shutil -import sys -import time -import subprocess -from watchdog.observers import Observer -from watchdog.events import FileSystemEventHandler - -# Constants -SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) -HOME_DIR = os.path.expanduser("~") -TEMPLATE_SRC = { - "dark": os.path.join(SCRIPT_DIR, "dark.lua"), - "light": os.path.join(SCRIPT_DIR, "light.lua") -} -TEMPLATE_DST = { - "dark": f"{HOME_DIR}/.config/wal/templates/base46-dark.lua", - "light": f"{HOME_DIR}/.config/wal/templates/base46-light.lua" -} -CACHE_SRC = { - "dark": f"{HOME_DIR}/.cache/wal/base46-dark.lua", - "light": f"{HOME_DIR}/.cache/wal/base46-light.lua" -} -CACHE_DST = f"{HOME_DIR}/.local/share/nvim/lazy/base46/lua/base46/themes/chadwal.lua" -FALLBACK_THEME = f"{HOME_DIR}/.local/share/nvim/lazy/base46/lua/base46/themes/gruvchad.lua" -LOCK_FILE = "/tmp/wal_nvim_lock" -COLORS_FILE = f"{HOME_DIR}/.cache/wal/colors" - -# Utility functions -def is_dark(hex_color): - """Determine if the color is dark based on luminance.""" - hex_color = hex_color.lstrip('#') - r, g, b = (int(hex_color[i:i+2], 16) for i in (0, 2, 4)) - brightness = (r * 299 + g * 587 + b * 114) / 1000 - return brightness < 128 - -def get_hex_from_colors_file(): - """Read the first color from the colors file.""" - try: - with open(COLORS_FILE, 'r') as file: - return file.readline().strip() - except FileNotFoundError: - sys.exit(f"Error: Colors file not found: {COLORS_FILE}") - -def acquire_lock(): - """Create a lock file to prevent multiple instances.""" - if os.path.exists(LOCK_FILE): - sys.exit("Another instance is already running. Exiting...") - open(LOCK_FILE, 'w').close() - -def release_lock(): - """Remove the lock file.""" - if os.path.exists(LOCK_FILE): - os.remove(LOCK_FILE) - -def copy_file(src, dst, skip_if_exists=False): - """Copy a file from src to dst, optionally skipping if dst exists.""" - if skip_if_exists and os.path.exists(dst): - print(f"File already exists at {dst}, skipping copy.") - return - - try: - os.makedirs(os.path.dirname(dst), exist_ok=True) - shutil.copy(src, dst) - print(f"File copied from {src} to {dst}.") - except Exception as e: - sys.exit(f"Error copying file from {src} to {dst}: {e}") - -def on_file_modified(): - """Handle file modifications based on current color scheme.""" - is_dark_theme = is_dark(get_hex_from_colors_file()) - mode = "dark" if is_dark_theme else "light" - - copy_file(FALLBACK_THEME, CACHE_SRC[mode], skip_if_exists=True) - copy_file(TEMPLATE_SRC[mode], TEMPLATE_DST[mode]) - copy_file(CACHE_SRC[mode], CACHE_DST) - - # Signal running nvim instances, don't exit based on the result here. - subprocess.run(['killall', '-SIGUSR1', 'nvim']) - -# Watchdog event handler -class MyHandler(FileSystemEventHandler): - def on_modified(self, event): - if event.src_path == CACHE_SRC["dark"]: - on_file_modified() - -def monitor_file(file_path): - """Monitor the specified file for changes.""" - event_handler = MyHandler() - observer = Observer() - observer.schedule(event_handler, os.path.dirname(file_path), recursive=False) - observer.start() - - try: - while True: - # Check every 5 seconds if nvim is running - time.sleep(5) - # Use pgrep to check for exact process name 'nvim' - result = subprocess.run(['pgrep', '-x', 'nvim'], capture_output=True) - if result.returncode != 0: - print("No running nvim instances found. Exiting.") - observer.stop() # Stop the observer thread - break # Exit the loop - except KeyboardInterrupt: - print("\nKeyboard interrupt received. Exiting.") - observer.stop() - finally: - # Ensure the observer thread is joined before exiting - observer.join() - -if __name__ == "__main__": - on_file_modified() - acquire_lock() - try: - on_file_modified() - monitor_file(CACHE_SRC["dark"]) - finally: - release_lock() diff --git a/pywal/dark.lua b/pywal/dark.lua deleted file mode 100644 index 7837144..0000000 --- a/pywal/dark.lua +++ /dev/null @@ -1,70 +0,0 @@ -local M = {{}} - -local lighten = require("base46.colors").change_hex_lightness - -M.base_30 = {{ - white = "{color7}", - darker_black = lighten("{color0}", -3), - black = "{color0}", - black2 = lighten("{color0}", 6), - one_bg = lighten("{color0}", 10), - grey = lighten("{color0}", 40), - light_grey = "{color8}", - red = "{color1}", - baby_pink = "{color9}", - pink = "{color13}", - line = "{color8}", - green = "{color2}", - vibrant_green = "{color2}", - nord_blue = "{color4}", - blue = "{color4}", - yellow = "{color3}", - sun = lighten("{color3}", 6), - purple = "{color13}", - dark_purple = "{color13}", - teal = "{color4}", - orange = "{color1}", - cyan = "{color4}", - pmenu_bg = "{color8}", - folder_bg = "{color4}", -}} - -M.base_30.statusline_bg = M.base_30.black2 -M.base_30.lightbg = M.base_30.one_bg -M.base_30.one_bg2 = lighten(M.base_30.one_bg, 6) -M.base_30.one_bg3 = lighten(M.base_30.one_bg2, 6) -M.base_30.grey_fg = lighten(M.base_30.grey, 10) -M.base_30.grey_fg2 = lighten(M.base_30.grey, 5) - -M.base_16 = {{ - base00 = "{color0}", - base01 = "{color0}", - base02 = "{color8}", - base03 = "{color8}", - base04 = "{color7}", - base05 = "{color7}", - base06 = "{color15}", - base07 = "{color15}", - base08 = "{color1}", - base09 = "{color2}", - base0A = "{color3}", - base0B = "{color4}", - base0C = "{color5}", - base0D = "{color6}", - base0E = "{color1}", - base0F = "{color15}", -}} - -M.type = "dark" - -M.polish_hl = {{ - Operator = {{ - fg = M.base_30.nord_blue, - }}, - - ["@operator"] = {{ - fg = M.base_30.nord_blue, - }}, -}} - -return M diff --git a/pywal/light.lua b/pywal/light.lua deleted file mode 100644 index 3cb85a4..0000000 --- a/pywal/light.lua +++ /dev/null @@ -1,70 +0,0 @@ -local M = {{}} - -local lighten = require("base46.colors").change_hex_lightness - -M.base_30 = {{ - white = "{color7}", - darker_black = lighten("{color0}", -3), - black = "{color0}", - black2 = lighten("{color0}", -6), - one_bg = lighten("{color0}", -10), - grey = lighten("{color0}", -40), - light_grey = "{color8}", - red = "{color1}", - baby_pink = "{color9}", - pink = "{color13}", - line = "{color8}", - green = "{color2}", - vibrant_green = "{color2}", - nord_blue = "{color4}", - blue = "{color4}", - yellow = "{color3}", - sun = lighten("{color3}", -6), - purple = "{color13}", - dark_purple = "{color13}", - teal = "{color4}", - orange = "{color1}", - cyan = "{color4}", - pmenu_bg = "{color8}", - folder_bg = "{color4}", - }} - - M.base_30.statusline_bg = M.base_30.black2 - M.base_30.lightbg = M.base_30.one_bg - M.base_30.one_bg2 = lighten(M.base_30.one_bg, -6) - M.base_30.one_bg3 = lighten(M.base_30.one_bg2, -6) - M.base_30.grey_fg = lighten(M.base_30.grey, -10) - M.base_30.grey_fg2 = lighten(M.base_30.grey, -5) - -M.base_16 = {{ - base00 = "{color0}", - base01 = "{color0}", - base02 = "{color8}", - base03 = "{color8}", - base04 = "{color7}", - base05 = "{color7}", - base06 = "{color15}", - base07 = "{color15}", - base08 = "{color1}", - base09 = "{color2}", - base0A = "{color3}", - base0B = "{color4}", - base0C = "{color5}", - base0D = "{color6}", - base0E = "{color1}", - base0F = "{color15}", -}} - -M.type = "dark" - -M.polish_hl = {{ - Operator = {{ - fg = M.base_30.nord_blue, - }}, - - ["@operator"] = {{ - fg = M.base_30.nord_blue, - }}, -}} - -return M diff --git a/pywal/matugen.lua b/pywal/matugen.lua deleted file mode 100644 index 8755c2d..0000000 --- a/pywal/matugen.lua +++ /dev/null @@ -1,81 +0,0 @@ -local M = {} - -local lighten = require("base46.colors").change_hex_lightness - -M.base_30 = { - white = "{{colors.on_background.default.hex}}", - black = "{{colors.background.default.hex}}", - darker_black = lighten("{{colors.background.default.hex}}", -3), - black2 = lighten("{{colors.background.default.hex}}", 6), - one_bg = lighten("{{colors.background.default.hex}}", 10), - one_bg2 = lighten("{{colors.background.default.hex}}", 16), - one_bg3 = lighten("{{colors.background.default.hex}}", 22), - grey = "{{colors.surface_variant.default.hex}}", - grey_fg = lighten("{{colors.surface_variant.default.hex}}", -10), - grey_fg2 = lighten("{{colors.surface_variant.default.hex}}", -20), - light_grey = "{{colors.outline.default.hex}}", - red = "{{colors.red.default.hex}}", - baby_pink = lighten("{{colors.red.default.hex}}", 10), - pink = "{{colors.tertiary.default.hex}}", - line = "{{colors.outline.default.hex}}", - green = "{{colors.green.default.hex}}", - vibrant_green = lighten("{{colors.green.default.hex}}", 10), - blue = "{{colors.blue.default.hex}}", - nord_blue = lighten("{{colors.blue.default.hex}}", 10), - yellow = "{{colors.yellow.default.hex}}", - sun = lighten("{{colors.yellow.default.hex}}", 10), - purple = "{{colors.tertiary.default.hex}}", - dark_purple = lighten("{{colors.tertiary.default.hex}}", -10), - teal = "{{colors.secondary_container.default.hex}}", - orange = "{{colors.red.default.hex}}", - cyan = "{{colors.cyan.default.hex}}", - statusline_bg = lighten("{{colors.background.default.hex}}", 6), - pmenu_bg = "{{colors.surface_variant.default.hex}}", - folder_bg = lighten("{{colors.primary_fixed_dim.default.hex}}", 0), - lightbg = lighten("{{colors.background.default.hex}}", 10), -} - -M.base_16 = { - base00 = "{{colors.surface.default.hex}}", - base01 = lighten("{{colors.surface_variant.default.hex}}", 0), - base02 = lighten("{{colors.surface_variant.default.hex}}", 3), - base03 = lighten("{{colors.outline.default.hex}}", 0), - base04 = lighten("{{colors.on_surface_variant.default.hex}}", 0), - base05 = "{{colors.on_surface.default.hex}}", - base06 = lighten("{{colors.on_surface.default.hex}}", 0), - base07 = "{{colors.surface.default.hex}}", - base08 = "{{colors.red.default.hex}}", - base09 = "{{colors.yellow.default.hex}}", - base0A = "{{colors.blue.default.hex}}", - base0B = "{{colors.green.default.hex}}", - base0C = "{{colors.cyan.default.hex}}", - base0D = lighten("{{colors.blue.default.hex}}", 20), - base0E = "{{colors.tertiary.default.hex}}", - base0F = "{{colors.inverse_surface.default.hex}}", -} - -M.type = "dark" - -M.polish_hl = { - defaults = { - Comment = { - italic = true, - fg = M.base_16.base03, - }, - }, - Syntax = { - String = { - fg = "{{colors.tertiary.default.hex}}", - }, - }, - treesitter = { - ["@comment"] = { - fg = M.base_16.base03, - }, - ["@string"] = { - fg = "{{colors.tertiary.default.hex}}", - }, - }, -} - -return M diff --git a/snippets/c.json b/snippets/c.json deleted file mode 100644 index 96cbe4e..0000000 --- a/snippets/c.json +++ /dev/null @@ -1,360 +0,0 @@ -{ - "for": { - "prefix": "for", - "body": [ - "for (${1:size_t} ${2:i} = ${3:0}; $2 < ${4:length}; $2++) {", - "\t$0", - "}" - ], - "description": "Code snippet for 'for' loop" - }, - "_FOREACH": { - "prefix": "_FOREACH", - "body": [ - "#define foreach(item, array) \\", - "\tfor(int keep = 1, \\", - "\tcount = 0,\\", - "\tsize = sizeof (array) / sizeof *(array); \\", - "\tkeep && count != size; \\", - "\tkeep = !keep, count++) \\", - "\tfor(item = (array) + count; keep; keep = !keep)" - ], - "description": "foreach loop C" - }, - "*": { - "prefix": "*", - "body": ["/* $0 */"], - "description": "Block comment" - }, - "glfw330win": { - "prefix": "glfw330win", - "body": [ - "if (!glfwInit()) {", - "log_warn(\"GLFW failed\");", - "glfwTerminate();", - "return 1;", - "}", - "glfwWindowHint(GLFW_SAMPLES, 4);", - "glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);", - "glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);", - "glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);" - ], - "description": "Glfw window hint for opengl v3.3" - }, - "gl_vertex_arr": { - "prefix": "gl_vertex_arr", - "body": [ - "glGenVertexArrays(${1:size}, &$2);", - "glBindVertexArray($2);" - ], - "description": "GL generate vertex array" - }, - "gl_vertex_buffer": { - "prefix": "gl_vertex_buffer", - "body": [ - "glGenBuffers(${1:1}, &$2);", - "glBindBuffer(${3:buffer_type}, $2);", - "glBufferData($3, sizeof($4), $4, $5)" - ], - "description": "gl generate buffer" - }, - "DBG": { - "prefix": "DBG", - "body": ["#define WHERE fprintf(stderr,\"[LOG]%s:%d\\n\",__FILE__,__LINE__);"], - "description": "Debug code line" - }, - "forr": { - "prefix": "forr", - "body": [ - "for (${1:size_t} ${2:i} = ${3:length} - 1; $2 >= ${4:0}; $2--) {", - "\t$0", - "}" - ], - "description": "Code snippet for reverse 'for' loop" - }, - "mod": { - "prefix": "_MOD", - "body": ["#define MOD(N,M)\t((N)%(M) < 0 ? (N)%(M) + (M) : (N)%(M))\n"], - "description": "mod of N,M" - }, - "between": { - "prefix": "_BETWEEN", - "body": ["#define BETWEEN(x, a, b) ((a) <= (x) && (x) <= (b))\n"], - "description": "x is between a, b" - }, - "length" : { - "prefix": "_LENGTH", - "body": ["#define LENGTH(x) sizeof(x)/sizeof(x[0])\n"], - "description": "Array size macro" - }, - "max" : { - "prefix": "_MAX", - "body": ["#define MAX(x,y) (x) > (y) ? (x) : (y)","$0"], - "description": "Get max element" - }, - "min" : { - "prefix": "_MIN", - "body": ["#define MIN(x,y) (x) < (y) ? (x) : (y)","$0"], - "description": "Get min element" - }, - "getbit": { - "prefix": "_GETBIT", - "body": ["#define GETBIT(x,i) (x&(1<"], - "description": "Code snippet for #include < >" - }, - "#def": { - "prefix": "def", - "body": ["#define $0"], - "description": "Code snippet for #define \" \"" - }, - "Main function template": { - "prefix": "main", - "body": [ - "int main (int argc, char *argv[])", - "{", - "\t$0", - "\treturn 0;", - "}" - ], - "description": "A standard main function for a C program" - }, - "Standard Starter Template": { - "prefix": "sst", - "body": [ - "#include ", - "", - "int main ()", - "{", - "\t$0", - "\treturn 0;", - "}" - ], - "description": "A standard starter template for a C program" - }, - "Stdlib Variant Starter Template": { - "prefix": "libsst", - "body": [ - "#include ", - "#include ", - "", - "int main (int argc, char *argv[])", - "{", - "\t$0", - "\treturn 0;", - "}" - ], - "description": "A standard starter template for a C program with stdlib included" - }, - "Create linked list": { - "prefix": "clist", - "body": [ - "typedef struct _node * Link;", - "typedef struct _node node;", - "struct _node {", - "\tint value;", - "\tLink next;", - "};" - ], - "description": "Creates a linked list template" - }, - "Scan integer": { - "prefix": "sci", - "body": ["scanf(\"%d\", &$1);"], - "description": "Scan int" - }, - "Scan 2 integer": { - "prefix": "sci2", - "body": ["scanf(\"%d %d\", &$1, &$2);"], - "description": "Scan 2 int" - }, - "Scan unsigned integer": { - "prefix": "scui", - "body": ["scanf(\"%d\", &$1);"], - "description": "Scan unsigned int" - }, - "Scan float": { - "prefix": "scf", - "body": ["scanf(\"%f\", &$1);"], - "description": "Scan float" - }, - "Scan 2 float": { - "prefix": "scf2", - "body": ["scanf(\"%f %f\", &$1, &$2);"], - "description": "Scan 2 float" - }, - "Scan long": { - "prefix": "scl", - "body": ["scanf(\"%ld\", &$1);"], - "description": "Scan long" - }, - "Scan 2 long": { - "prefix": "scl2", - "body": ["scanf(\"%ld %ld\", &$1, &$2);"], - "description": "Scan 2 long" - }, - "Scan unsigned long": { - "prefix": "scul", - "body": ["scanf(\"%lu\", &$1);"], - "description": "Scan unsigned long" - }, - "Scan unsigned long long": { - "prefix": "scull", - "body": ["scanf(\"%llu\", &$1);"], - "description": "Scan unsigned long long" - }, - "Print variable of type float (2 decimal places)": { - "prefix": "pflo", - "body": ["printf(\"$1 :>> %.2f\\n\", $1);"], - "description": "Calls printf() to log value of variable of type float rounded to 2 decimal places" - }, - "Print variable of type integer": { - "prefix": "pint", - "body": ["printf(\"$1 : %d\\n\", $1);"], - "description": "Calls printf() to log value of variable of type signed integer" - }, - "Print variable of type char": { - "prefix": "pcha", - "body": ["printf(\"$1 : %c\\n\", $1);"], - "description": "Calls printf() to log value of variable of type char" - }, - "Print variable of type pointer": { - "prefix": "ppoint", - "body": ["printf(\"$1 : %p\\n\", (void *) $1);"], - "description": "Calls printf() to log value of variable of type pointer" - }, - "Print variable of type size_t": { - "prefix": "psiz", - "body": ["printf(\"$1 : %zu\\n\", $1);"], - "description": "Calls printf() to log value of variable of type size_t" - }, - "printf": { - "prefix": "printf", - "body": ["printf(\"$1\\n\"$0);"], - "description": "Generic printf() snippet" - }, - "sprintf": { - "prefix": "sprintf", - "body": ["sprintf($1, \"$2\\n\"$0);"], - "description": "Generic sprintf() snippet" - }, - "fprintf": { - "prefix": "fprintf", - "body": ["fprintf(${1:stderr}, \"$2\\n\"$0);"], - "description": "Generic fprintf() snippet" - }, - "scanf": { - "prefix": "scanf", - "body": ["scanf(\"$1\"$0);"], - "description": "Generic scanf() snippet" - }, - "sscanf": { - "prefix": "sscanf", - "body": ["sscanf($1, \"$2\"$0);"], - "description": "Generic sscanf() snippet" - }, - "fscanf": { - "prefix": "fscanf", - "body": ["fscanf($1, \"$2\"$0);"], - "description": "Generic fscanf() snippet" - }, - "Allocate memory using malloc": { - "prefix": "mal", - "body": [ - "${1:int} *${2:v} = malloc(${3:1} * sizeof($1));", - "", - "if (!$2) {", - "\tfprintf(stderr, \"Memory allocation failed!\\n\");", - "\t$4;", - "}", - "$0", - "free($2);" - ], - "description": "Allocates memory to a pointer variable using malloc(), then deallocates using free()." - }, - "Allocate memory using calloc": { - "prefix": "cal", - "body": [ - "${1:int} *${2:v} = calloc(${3:1}, sizeof($1));", - "", - "if (!$2) {", - "\tfprintf(stderr, \"Memory allocation failed!\\n\");", - "\t$4;", - "}", - "$0", - "free($2);" - ], - "description": "Allocates memory to a pointer variable using calloc(), then deallocates using free()." - }, - "X11 default incs": { - "prefix": "_X11", - "body": ["#include \n#include \n#include \n#include \n"], - "description": "X11 default library headers" - }, - "Primitive macros": { - "prefix": "_PRIMITIVE", - "body": [ - "#define i16 short", - "#define ui16 unsigned short", - "#define i32 int", - "#define ui32 unsigned int", - "#define i64 long long", - "#define ui64 unsigned long long" - ], - "description": "Primitive macros for int type" - } -} diff --git a/snippets/cpp.json b/snippets/cpp.json deleted file mode 100644 index c949464..0000000 --- a/snippets/cpp.json +++ /dev/null @@ -1,219 +0,0 @@ -{ - "for": { - "prefix": "for", - "body": [ - "for (${1:size_t} ${2:i} = ${3:0}; $2 < ${4:length}; $2++) {", - "\t$0", - "}" - ], - "description": "Code snippet for 'for' loop" - }, - "*": { - "prefix": "*", - "body": ["/* $0 */"], - "description": "Block comment" - }, - "forr": { - "prefix": "forr", - "body": [ - "for (${1:size_t} ${2:i} = ${3:length} - 1; $2 >= ${4:0}; $2--) {", - "\t$0", - "}" - ], - "description": "Code snippet for reverse 'for' loop" - }, - "mod": { - "prefix": "MOD", - "body": ["#define MOD(N,M)\t((N)%(M) < 0 ? (N)%(M) + (M) : (N)%(M))"], - "description": "mod of N,M" - }, - "between": { - "prefix": "between", - "body": ["#define BETWEEN(x, a, b)\t((a) <= (x) && (x) <= (b))"], - "description": "x is between a, b" - }, - "sze" : { - "prefix": "sze", - "body": ["#define SIZE(x) sizeof(x)/sizeof(x[0])","$0"], - "description": "Array size macro" - }, - "do": { - "prefix": "do", - "body": ["do", "{", "\t$1", "} while($2);"], - "description": "Code snippet for do...while loop" - }, - "while": { - "prefix": "while", - "body": ["while ($1) {", "\t$2", "}"], - "description": "" - }, - "foreach": { - "prefix": "foreach", - "body": ["for (${1:auto} ${2:var} : ${3:collection_to_loop}) {", "\t$0", "}"], - "description": "Code snippet for range-based for loop (c++11) statement" - }, - "enum": { - "prefix": "enum", - "body": ["enum ${1:MyEnum} {", "\t$0", "};"], - "description": "Code snippet for enum" - }, - "enum class": { - "prefix": "enum class", - "body": ["enum class ${1:MyClass} {$0};"], - "description": "Code snippet for enum class (c++11)" - }, - "class": { - "prefix": "class", - "body": [ - "class ${1:MyClass}", - "{", - "public:", - "\t$1();", - "\t$1($1 &&) = default;", - "\t$1(const $1 &) = default;", - "\t$1 &operator=($1 &&) = default;", - "\t$1 &operator=(const $1 &) = default;", - "\t~$1();", - "", - "private:", - "\t$2", - "};", - "", - "$1::$1()", - "{", - "}", - "", - "$1::~$1()", - "{", - "}" - ], - "description": "Code snippet for class" - }, - "classi": { - "prefix": "classi", - "body": [ - "class ${1:MyClass}", - "{", - "public:", - "\t$1() = default;", - "\t$1($1 &&) = default;", - "\t$1(const $1 &) = default;", - "\t$1 &operator=($1 &&) = default;", - "\t$1 &operator=(const $1 &) = default;", - "\t~$1() = default;", - "", - "private:", - "\t$2", - "};" - ], - "description": "Code snippet for class with inline constructor/destructor" - }, - "interface": { - "prefix": "interface", - "body": ["__interface I${1:Interface}", "{", "\t$0", "};"], - "description": "Code snippet for interface (Visual C++)" - }, - "namespace": { - "prefix": "namespace", - "body": ["namespace ${1:MyNamespace}", "{", "\t$0", "}"] - }, - "#ifdef": { - "prefix": "#ifdef", - "body": ["#ifdef ${1:DEBUG}", "$0", "#endif // ${DEBUG}"], - "description": "Code snippet for #ifdef" - }, - "#ifndef": { - "prefix": "#ifndef", - "body": ["#ifndef ${1:DEBUG}", "$0", "#endif // !$1"], - "description": "Code snippet for #ifndef" - }, - "#if": { - "prefix": "#if", - "body": ["#if ${1:0}", "$0", "#endif // $1"], - "description": "Code snippet for #if" - }, - "struct": { - "prefix": "struct", - "body": ["struct ${1:MyStruct}", "{", "\t$0", "};"], - "description": "Code snippet for struct" - }, - "switch": { - "prefix": "switch", - "body": ["switch (${1:switch_on}) {", "\tdefault:", "\t\t$0", "\t\tbreak;", "}"], - "description": "Code snippet for switch statement" - }, - "try": { - "prefix": "try", - "body": [ - "try {", - "\t", - "}", - "catch (const std::exception&)", - "{", - "\t$1", - "}" - ], - "description": "Code snippet for try catch" - }, - "union": { - "prefix": "union", - "body": ["union ${1:MyUnion}", "{", "\t$0", "};"], - "description": "Code snippet for union" - }, - "printf": { - "prefix": "printf", - "body": ["printf(\"$1\\n\"$0);"], - "description": "Generic printf() snippet" - }, - "sprintf": { - "prefix": "sprintf", - "body": ["sprintf($1, \"$2\\n\"$0);"], - "description": "Generic sprintf() snippet" - }, - "fprintf": { - "prefix": "fprintf", - "body": ["fprintf(${1:stderr}, \"$2\\n\"$0);"], - "description": "Generic fprintf() snippet" - }, - "scanf": { - "prefix": "scanf", - "body": ["scanf(\"$1\"$0);"], - "description": "Generic scanf() snippet" - }, - "sscanf": { - "prefix": "sscanf", - "body": ["sscanf($1, \"$2\"$0);"], - "description": "Generic sscanf() snippet" - }, - "fscanf": { - "prefix": "fscanf", - "body": ["fscanf($1, \"$2\"$0);"], - "description": "Generic fscanf() snippet" - }, - "#inc": { - "prefix": "#inc", - "body": ["#include \"$0\""], - "description": "Code snippet for #include \" \"" - }, - "#inc<": { - "prefix": "#inc<", - "body": ["#include <$0>"], - "description": "Code snippet for #include < >" - }, - "#def": { - "prefix": "def", - "body": ["#define $0"], - "description": "Code snippet for #define \" \"" - }, - "Main function template": { - "prefix": "main", - "body": [ - "int main (int argc, char *argv[])", - "{", - "\t$0", - "\treturn 0;", - "}" - ], - "description": "A standard main function for a C++ program" - } -} diff --git a/snippets/css.json b/snippets/css.json deleted file mode 100644 index 294af23..0000000 --- a/snippets/css.json +++ /dev/null @@ -1,651 +0,0 @@ -{ - "align-items": { - "prefix": "ai", - "body": "align-items: ${1|flex-start,flex-end,center,baseline,stretch,start,end,self-start,self-end|};", - "description": "initial value: stretch" - }, - "align-items: baseline": { - "prefix": "aib", - "body": "align-items: baseline;" - }, - "align-items: center": { - "prefix": "aic", - "body": "align-items: center;" - }, - "align-items: flex-start": { - "prefix": "aifs", - "body": "align-items: flex-start;" - }, - "align-items: flex-end": { - "prefix": "aife", - "body": "align-items: flex-end;" - }, - "align-items: stretch": { - "prefix": "ais", - "body": "align-items: stretch;" - }, - "align-self": { - "prefix": "as", - "body": "align-items: ${1|flex-start,flex-end,center,baseline,stretch,auto|};", - "description": "initial value: auto" - }, - "animation": { - "prefix": "ani", - "body": "animation: ${1:name} ${2:1s} ${3|linear,ease-in-out,ease,ease-in,ease-out,step-start,step-end,steps,cubic-bezier|};", - "description": "animation: name duration timing-function delay direction count fill-mode play-state" - }, - "animation-delay": { - "prefix": "anide", - "body": "animation-delay: ${0:1s};" - }, - "animation-direction": { - "prefix": "anidi", - "body": "animation-direction: ${1|alternate,alternate-reverse,reverse,normal|};", - "description": "initial value: normal" - }, - "animation-duratuion": { - "prefix": "anidu", - "body": "animation-duration: ${0:1s};" - }, - "animation-fill-mode": { - "prefix": "anifm", - "body": "animation-fill-mode: ${1|forwards,backwards,both,none|};", - "description": "initial value: none" - }, - "animation-iteration-count": { - "prefix": "aniic", - "body": "animation-iteration-count: ${0:infinite};", - "description": "initial value: 1" - }, - "animation-name": { - "prefix": "anin", - "body": "animation-name: ${0:name};" - }, - "animation-play-state": { - "prefix": "anips", - "body": "animation-play-state: ${1|paused,running|};", - "description": "initial value: running" - }, - "animation-timing-function": { - "prefix": "anitf", - "body": "animation-timing-function: ${1|linear,ease,ease-in-out,ease-in,ease-out,step-start,step-end,steps,cubic-bezier|};", - "description": "initial value: ease" - }, - "background": { - "prefix": "bg", - "body": "background: ${0:#fff};", - "description": "background: image position/size repeat attachment box box" - }, - "background-attachment": { - "prefix": "bga", - "body": "background-attachment: ${1|fixed,scroll,local|};", - "description": "initial value: scroll" - }, - "background-color": { - "prefix": "bgc", - "body": "background-color: ${0:#fff};" - }, - "background-clip": { - "prefix": "bgcl", - "body": "background-clip: ${1|border-box,padding-box,content-box,text|};", - "description": "initial value: border-box" - }, - "background-image": { - "prefix": "bgi", - "body": "background-image: url('${0:background.jpg}');" - }, - "background-origin": { - "prefix": "bgo", - "body": "background-origin: ${1|border-box,padding-box,content-box|};", - "description": "initial value: padding-box" - }, - "background-position": { - "prefix": "bgp", - "body": "background-position: ${1:left} ${2:top};" - }, - "background-repeat": { - "prefix": "bgr", - "body": "background-repeat: ${1|no-repeat,repeat-x,repeat-y,repeat,space,round|};", - "description": "initial value: repeat" - }, - "background-repeat: repeat": { - "prefix": "bgrr", - "body": "background-repeat: repeat;" - }, - "background-repeat: repeat-x": { - "prefix": "bgrx", - "body": "background-repeat: repeat-x;" - }, - "background-repeat: repeat-y": { - "prefix": "bgry", - "body": "background-repeat: repeat-y;" - }, - "background-repeat: no-repeat": { - "prefix": "bgrn", - "body": "background-repeat: no-repeat;" - }, - "background-size": { - "prefix": "bgs", - "body": "background-size: ${0:cover};" - }, - "border": { - "prefix": "bor", - "body": "border: ${1:1px} ${2|solid,dashed,dotted,double,groove,ridge,inset,outset,none,hidden|} ${0:#000};" - }, - "border: none": { - "prefix": "born", - "body": "border: none;" - }, - "border-color": { - "prefix": "borc", - "body": "border-color: ${0:#000};" - }, - "border-style": { - "prefix": "bors", - "body": "border-style: ${1|solid,dashed,dotted,double,groove,ridge,inset,outset,none,hidden|};" - }, - "border-width": { - "prefix": "borw", - "body": "border-width: ${0:1px};" - }, - "border-bottom": { - "prefix": "borb", - "body": "border-bottom: ${1:1px} ${2|solid,dashed,dotted,double,groove,ridge,inset,outset,none,hidden|} ${0:#000};" - }, - "border-left": { - "prefix": "borl", - "body": "border-left: ${1:1px} ${2|solid,dashed,dotted,double,groove,ridge,inset,outset,none,hidden|} ${0:#000};" - }, - "border-right": { - "prefix": "borr", - "body": "border-right: ${1:1px} ${2|solid,dashed,dotted,double,groove,ridge,inset,outset,none,hidden|} ${0:#000};" - }, - "border-top": { - "prefix": "bort", - "body": "border-top: ${1:1px} ${2|solid,dashed,dotted,double,groove,ridge,inset,outset,none,hidden|} ${0:#000};" - }, - "border-radius": { - "prefix": "br", - "body": "border-radius: ${0:2px};" - }, - "bottom": { - "prefix": "bot", - "body": "bottom: ${0:0};" - }, - "box-shadow": { - "prefix": "bos", - "body": "box-shadow: ${1:1px} ${2:1px} ${3:1px} ${4:1px} ${0:rgba(0, 0, 0, .5)};", - "description": "box-shadow: x-offset y-offset blur spread color" - }, - "box-sizing": { - "prefix": "boz", - "body": "box-sizing: ${1|border-box,content-box|};", - "description": "initial value: content-box" - }, - "clear": { - "prefix": "clr", - "body": "clear: ${1|both,left,right,none|};" - }, - "color": { - "prefix": "col", - "body": "color: ${0:#000};" - }, - "content": { - "prefix": "con", - "body": "content: '$0';" - }, - "cursor": { - "prefix": "cur", - "body": "cursor: ${1|auto,default,alias,cell,copy,crosshair,context-menu,help,grab,grabbing,move,none,no-drop,not-allowed,pointer,progress,e-resize,all-scroll,text,wait,vertical-text,zoom-in,zoom-out|};", - "description": "initial value: auto" - }, - "cursor: pointer": { - "prefix": "curp", - "body": "cursor: pointer;" - }, - "cursor: default": { - "prefix": "curd", - "body": "cursor: default;" - }, - "display": { - "prefix": "dis", - "body": "display: ${1|none,block,inline,inline-block,flex,inline-flex,list-item,table,inline-table,table-caption,table-cell,table-row,table-row-group,table-column|};" - }, - "display: block": { - "prefix": "disb", - "body": "display: block;" - }, - "display: inline-block": { - "prefix": "disi", - "body": "display: inline-block;" - }, - "display: none": { - "prefix": "disn", - "body": "display: none;" - }, - "display: flex": { - "prefix": "disf", - "body": "display: flex;" - }, - "flex": { - "prefix": "flex", - "body": "flex: ${1:1} ${2:1} ${3:auto};", - "description": "flex: grow shrink basis" - }, - "flex (alt)": { - "prefix": "fle", - "body": "flex: ${1:1} ${2:1} ${3:auto};" - }, - "flex-direction": { - "prefix": "fld", - "body": "flex-direction: ${1|row,row-reverse,column,column-reverse|};", - "description": "initial value: row" - }, - "flex-direction: row": { - "prefix": "fldr", - "body": "flex-direction: row;" - }, - "flex-direction: column": { - "prefix": "fldc", - "body": "flex-direction: column;" - }, - "flex-flow": { - "prefix": "flf", - "body": "flex-flow: ${1|row,row-reverse,column,column-reverse|} ${2|wrap,wrap-reverse,nowrap|};" - }, - "flex-wrap": { - "prefix": "flw", - "body": "flex-wrap: ${1|wrap,wrap-reverse,nowrap|};", - "description": "initial value: nowrap" - }, - "float": { - "prefix": "fl", - "body": "float: ${1|left,right,none|};" - }, - "float: left": { - "prefix": "fll", - "body": "float: left;" - }, - "float: right": { - "prefix": "flr", - "body": "float: right;" - }, - "float: none": { - "prefix": "fln", - "body": "float: none;" - }, - "font-family": { - "prefix": "ff", - "body": "font-family: ${0:arial};" - }, - "font-size": { - "prefix": "fz", - "body": "font-size: ${0:12px};" - }, - "font-style": { - "prefix": "fst", - "body": "font-style: ${1|italic,oblique,normal|};" - }, - "font-style: italic": { - "prefix": "fsti", - "body": "font-style: italic;" - }, - "font-style: normal": { - "prefix": "fstn", - "body": "font-style: normal;" - }, - "font-style: oblique": { - "prefix": "fsto", - "body": "font-style: oblique;" - }, - "font-weight": { - "prefix": "fw", - "body": "font-weight: ${0:bold};" - }, - "font-weight: bold": { - "prefix": "fwb", - "body": "font-weight: bold;" - }, - "font-weight: light": { - "prefix": "fwl", - "body": "font-weight: light;" - }, - "font-weight: normal": { - "prefix": "fwn", - "body": "font-weight: normal;" - }, - "font": { - "prefix": "ft", - "body": "font: ${0:12px/1.5};", - "description": "font: [weight style variant stretch] size/line-height family" - }, - "height": { - "prefix": "hei", - "body": "height: ${0:1px};" - }, - "justify-content": { - "prefix": "jc", - "body": "justify-content: ${1|flex-start,flex-end,center,space-between,space-around|};", - "description": "initial value: flex-start" - }, - "justify-content: flex-start": { - "prefix": "jcfs", - "body": "justify-content: flex-start;" - }, - "justify-content: flex-end": { - "prefix": "jcfe", - "body": "justify-content: flex-end;" - }, - "justify-content: center": { - "prefix": "jcc", - "body": "justify-content: center;" - }, - "justify-content: space-around": { - "prefix": "jcsa", - "body": "justify-content: space-around;" - }, - "justify-content: space-between": { - "prefix": "jcsb", - "body": "justify-content: space-between;" - }, - "list-style": { - "prefix": "lis", - "body": "list-style: ${1|disc,circle,square,decimal,lower-roman,upper-roman,lower-alpha,upper-alpha,none,armenian,cjk-ideographic,georgian,lower-greek,hebrew,hiragana,hiragana-iroha,katakana,katakana-iroha,lower-latin,upper-latin|} ${2|outside,inside|};", - "description": "list-style: type position image" - }, - "list-style-position": { - "prefix": "lisp", - "body": "${1|outside,inside|}", - "description": "initial value: outside" - }, - "list-style-type": { - "prefix": "list", - "body": "list-style-type: ${1|disc,circle,square,decimal,lower-roman,upper-roman,lower-alpha,upper-alpha,none,armenian,cjk-ideographic,georgian,lower-greek,hebrew,hiragana,hiragana-iroha,katakana,katakana-iroha,lower-latin,upper-latin|};", - "description": "initial value: disc" - }, - "list-style-type: circle": { - "prefix": "listc", - "body": "list-style-type: circle;" - }, - "list-style-type: disc": { - "prefix": "listd", - "body": "list-style-type: disc;" - }, - "list-style-type: none": { - "prefix": "listn", - "body": "list-style-type: none;" - }, - "list-style-type: square": { - "prefix": "lists", - "body": "list-style-type: square;" - }, - "list-style-type: lower-roman": { - "prefix": "listlr", - "body": "list-style-type: lower-roman;" - }, - "list-style-type: upper-roman": { - "prefix": "listur", - "body": "list-style-type: upper-roman;" - }, - "left": { - "prefix": "lef", - "body": "left: ${0:0};" - }, - "line-height": { - "prefix": "lh", - "body": "line-height: ${0:1.5};" - }, - "letter-spacing": { - "prefix": "ls", - "body": "letter-spacing: ${0:2px};" - }, - "letter-spacing: normal": { - "prefix": "lsn", - "body": "letter-spacing: normal;" - }, - "margin": { - "prefix": "mar", - "body": "margin: ${0:0};" - }, - "margin-bottom": { - "prefix": "marb", - "body": "margin-bottom: ${0:0};" - }, - "margin-left": { - "prefix": "marl", - "body": "margin-left: ${0:0};" - }, - "margin-right": { - "prefix": "marr", - "body": "margin-right: ${0:0};" - }, - "margin-top": { - "prefix": "mart", - "body": "margin-top: ${0:0};" - }, - "margin: 0 auto": { - "prefix": "mara", - "body": "margin: 0 auto;" - }, - "min-height": { - "prefix": "mih", - "body": "min-height: ${0:1px};" - }, - "min-width": { - "prefix": "miw", - "body": "min-width: ${0:1px};" - }, - "max-height": { - "prefix": "mah", - "body": "max-height: ${0:1px};" - }, - "max-width": { - "prefix": "maw", - "body": "max-width: ${0:1px};" - }, - "opacity": { - "prefix": "opa", - "body": "opacity: ${0:0};" - }, - "overflow": { - "prefix": "ov", - "body": "overflow: ${1|visible,hidden,scroll,auto,clip|};" - }, - "overflow: auto": { - "prefix": "ova", - "body": "overflow: auto;" - }, - "overflow: hidden": { - "prefix": "ovh", - "body": "overflow: hidden;" - }, - "overflow: scroll": { - "prefix": "ovs", - "body": "overflow: scroll;" - }, - "overflow: visible": { - "prefix": "ovv", - "body": "overflow: visible;" - }, - "padding": { - "prefix": "pad", - "body": "padding: ${0:0};" - }, - "padding-bottom": { - "prefix": "padb", - "body": "padding-bottom: ${0:0};" - }, - "padding-left": { - "prefix": "padl", - "body": "padding-left: ${0:0};" - }, - "padding-right": { - "prefix": "padr", - "body": "padding-right: ${0:0};" - }, - "padding-top": { - "prefix": "padt", - "body": "padding-top: ${0:0};" - }, - "position": { - "prefix": "pos", - "body": "position: ${1|relative,absolute,fixed,sticky,static|};" - }, - "position absolute": { - "prefix": "posa", - "body": "position: absolute;" - }, - "position fixed": { - "prefix": "posf", - "body": "position: fixed;" - }, - "position relative": { - "prefix": "posr", - "body": "position: relative;" - }, - "position sticky": { - "prefix": "poss", - "body": "position: sticky;" - }, - "right": { - "prefix": "rig", - "body": "right: ${0:0};" - }, - "text-align": { - "prefix": "ta", - "body": "text-align: ${1|center,left,right,justify,start,end|};" - }, - "text-align: center": { - "prefix": "tac", - "body": "text-align: center;" - }, - "text-align: left": { - "prefix": "tal", - "body": "text-align: left;" - }, - "text-align: right": { - "prefix": "tar", - "body": "text-align: right;" - }, - "text-decoration": { - "prefix": "td", - "body": "text-decoration: ${1|none,underline,overline,line-through|};" - }, - "text-decoration: underline": { - "prefix": "tdu", - "body": "text-decoration: underline;" - }, - "text-decoration: none": { - "prefix": "tdn", - "body": "text-decoration: none;" - }, - "text-decoration: line-through": { - "prefix": "tdl", - "body": "text-decoration: line-through;" - }, - "text-indent": { - "prefix": "ti", - "body": "text-indent: ${0:2em};" - }, - "text-shadow": { - "prefix": "ts", - "body": "text-shadow: ${1:1px} ${2:1px} ${3:1px} ${4:1px} ${0:rgba(0, 0, 0, .5)};", - "description": "text-shadow: x-offset y-offset blur spread color" - }, - "text-transform": { - "prefix": "tt", - "body": "text-transform: ${1|capitalize,uppercase,lowercase,full-width,none|};" - }, - "top": { - "prefix": "top", - "body": "top: ${0:0};" - }, - "vertical-align": { - "prefix": "va", - "body": "vertical-align: ${1|baseline,middle,top,bottom,sub,super,text-top,text-bottom|};" - }, - "vertical-align: bottom": { - "prefix": "vab", - "body": "vertical-align: bottom;" - }, - "vertical-align: middle": { - "prefix": "vam", - "body": "vertical-align: middle;" - }, - "vertical-align: top": { - "prefix": "vat", - "body": "vertical-align: top;" - }, - "visibility": { - "prefix": "vis", - "body": "visibility: ${1|visible,hidden,collapse|};" - }, - "visibility: visible": { - "prefix": "visv", - "body": "visibility: visible;" - }, - "visibility: hidden": { - "prefix": "vish", - "body": "visibility: hidden;" - }, - "word-break": { - "prefix": "wb", - "body": "word-break: ${1|break-all,keep-all,break-word,normal|};" - }, - "width": { - "prefix": "wid", - "body": "width: ${0:0};" - }, - "width: auto": { - "prefix": "wida", - "body": "width: auto;" - }, - "white-space": { - "prefix": "ws", - "body": "white-space: ${1|nowrap,pre,pre-wrap,pre-line,normal|};" - }, - "white-space: nowrap": { - "prefix": "wsn", - "body": "white-space: nowrap;" - }, - "white-space: pre": { - "prefix": "wsp", - "body": "white-space: pre;" - }, - "word-wrap": { - "prefix": "ww", - "body": "word-wrap: ${1|break-word,break-spaces,normal|};" - }, - "z-index": { - "prefix": "zi", - "body": "z-index: ${0:-1};" - }, - "@import": { - "prefix": "imp", - "body": "@import '${0:filename}';" - }, - "@mixin": { - "prefix": "mix", - "body": "@mixin ${1:name} {\n $0\n}" - }, - "@include": { - "prefix": "inc", - "body": "@include ${0:mixin};" - }, - "@keyframes": { - "prefix": "key", - "body": "@keyframes ${1:name} {\n $0\n}" - }, - "@media": { - "prefix": "med", - "body": "@media screen and (${1:max-width: 300px}) {\n $0\n}" - }, - "!important": { - "prefix": "!", - "body": "!important" - }, - "!important (alt)": { - "prefix": "i", - "body": "!important" - } -} diff --git a/snippets/django.json b/snippets/django.json deleted file mode 100644 index 0bb986f..0000000 --- a/snippets/django.json +++ /dev/null @@ -1,1052 +0,0 @@ -{ - "adminview": { - "prefix": "adminview", - "body": [ - "@admin.register(${1})", - "class ${1}Admin(admin.ModelAdmin):", - "\t'''Admin View for ${1}'''", - "", - "\tlist_display = ('${2}',)", - "\tlist_filter = ('${3}',)", - "\tinlines = [", - "\t\t${4}Inline,", - "\t]", - "\traw_id_fields = ('${5}',)", - "\treadonly_fields = ('${6}',)", - "\tsearch_fields = ('${7}',)", - "\tdate_hierarchy = '${8}'", - "\tordering = ('${9}',)" - ], - "description": "Model Admin View", - "scope": "source.python" - }, - "stackedinline": { - "prefix": "stackedinline", - "body": [ - "class ${1}Inline(admin.StackedInline):", - "\t'''Stacked Inline View for ${1}'''", - "", - "\tmodel = ${2:${1}}", - "\tmin_num = ${3:3}", - "\tmax_num = ${4:20}", - "\textra = ${5:1}", - "\traw_id_fields = (${6},)" - ], - "description": "Stacked Inline", - "scope": "source.python" - }, - "tabularinline": { - "prefix": "tabularinline", - "body": [ - "class ${1}Inline(admin.TabularInline):", - "\t'''Tabular Inline View for ${1}'''", - "", - "\tmodel = ${2:${1}}", - "\tmin_num = ${3:3}", - "\tmax_num = ${4:20}", - "\textra = ${5:1}", - "\traw_id_fields = (${6},)" - ], - "description": "Tabular Inline", - "scope": "source.python" - }, - "simplelistfilter": { - "prefix": "simplelistfilter", - "body": [ - "class ${1:NAME}Filter(admin.SimpleListFilter):", - "", - "\ttitle = '$2'", - "\tparameter_name = '$0'", - "", - "\tdef lookups(self, request, model_admin):", - "\t\tpass", - "", - "\tdef queryset(self, request, queryset):", - "\t\treturn queryset" - ], - "description": "Admin SimpleList Filter", - "scope": "source.python" - }, - "iadmin": { - "prefix": "iadmin", - "body": "from django.contrib import admin", - "description": "from ... import admin", - "scope": "source.python" - }, - "iadminsite": { - "prefix": "iadminsite", - "body": "from django.contrib.admin import AdminSite", - "description": "from ... import AdminSite", - "scope": "source.python" - }, - "register": { - "prefix": "register", - "body": "admin.site.register($1)", - "description": "register the model class without providing a ModelAdmin description.", - "scope": "source.python" - }, - "registermadmin": { - "prefix": "registermadmin", - "body": "admin.site.register($1, $1Admin)", - "description": "register the model class providing a ModelAdmin description", - "scope": "source.python" - }, - "fieldsets": { - "prefix": "fieldsets", - "body": [ - "fieldsets = (", - "\t(None, {", - "\t\t'fields': (", - "\t\t\t$1", - "\t\t),", - "\t}),", - ")" - ], - "description": "", - "scope": "source.python" - }, - "Form": { - "prefix": "Form", - "body": [ - "class ${1:FORMNAME}(forms.Form):", - "\t\"\"\"${2:$1 definition}.\"\"\"", - "", - "\t${3:# TODO: Define form fields here}", - "" - ], - "description": "Form", - "scope": "source.python" - }, - "ModelForm": { - "prefix": "ModelForm", - "body": [ - "class ${1:MODELNAME}Form(forms.ModelForm):", - "\t\"\"\"${2:Form definition for $1}.\"\"\"", - "", - "\tclass Meta:", - "\t\t\"\"\"Meta definition for ${1}form.\"\"\"", - "", - "\t\tmodel = $1", - "\t\tfields = ('$3',)", - "" - ], - "description": "ModelForm", - "scope": "source.python" - }, - "fbool": { - "prefix": "fbool", - "body": "${1:FIELDNAME} = forms.BooleanField($2, required=${3:False})", - "description": "BooleanField (fbool)", - "scope": "source.python" - }, - "fchar": { - "prefix": "fchar", - "body": "${1:FIELDNAME} = forms.CharField($2,${3: max_length=$4,} required=${5:False})", - "description": "CharField (fchar)", - "scope": "source.python" - }, - "fchoice": { - "prefix": "fchoice", - "body": "${1:FIELDNAME} = forms.ChoiceField($2, choices=[${3:CHOICES}], required=${4:False})", - "description": "ChoiceField (fchoice)", - "scope": "source.python" - }, - "fcombo": { - "prefix": "fcombo", - "body": "${1:FIELDNAME} = forms.ComboField($2)", - "description": "ComboField (fcombo)", - "scope": "source.python" - }, - "fdate": { - "prefix": "fdate", - "body": "${1:FIELDNAME} = forms.DateField($2, required=${3:False})", - "description": "DateField (fdate)", - "scope": "source.python" - }, - "fdatetime": { - "prefix": "fdatetime", - "body": "${1:FIELDNAME} = forms.DateTimeField($2, required=${3:False})", - "description": "DateTimeField (fdatetime)", - "scope": "source.python" - }, - "fdecimal": { - "prefix": "fdecimal", - "body": "${1:FIELDNAME} = forms.DecimalField($2, required=${3:False})", - "description": "DecimalField (fdecimal)", - "scope": "source.python" - }, - "fduration": { - "prefix": "fduration", - "body": "${1:FIELDNAME} = forms.DurationField($2, required=${3:False})", - "description": "DurationField (fduration)", - "scope": "source.python" - }, - "femail": { - "prefix": "femail", - "body": "${1:FIELDNAME} = forms.EmailField($2, required=${3:False})", - "description": "EmailField (femail)", - "scope": "source.python" - }, - "ffile": { - "prefix": "ffile", - "body": "${1:FIELDNAME} = forms.FileField($2,${3: max_length=$4,} required=${5:False})", - "description": "FileField (ffile)", - "scope": "source.python" - }, - "ffilepath": { - "prefix": "ffilepath", - "body": "${1:FIELDNAME} = forms.FilePathField($2, path=${3:/absolute_path/}, required=${4:False})", - "description": "FilePathField (ffilepath)", - "scope": "source.python" - }, - "ffloat": { - "prefix": "ffloat", - "body": "${1:FIELDNAME} = forms.FloatField($2, required=${3:False})", - "description": "FloatField (ffloat)", - "scope": "source.python" - }, - "fip": { - "prefix": "fip", - "body": "${1:FIELDNAME} = forms.IPAddressField($2)", - "description": "IPAddressField (fip).\n\nThis field has been deprecated since version 1.7 in favor of GenericIPAddressField.\n\n", - "scope": "source.python" - }, - "fgenericip": { - "prefix": "fip", - "body": "${1:FIELDNAME} = forms.GenericIPAddressField($2)", - "description": "IPAddressField (fgenericip)", - "scope": "source.python" - }, - "fimg": { - "prefix": "fimg", - "body": "${1:FIELDNAME} = forms.ImageField($2, required=${3:False})", - "description": "ImageField (fimg)", - "scope": "source.python" - }, - "fint": { - "prefix": "fint", - "body": "${1:FIELDNAME} = forms.IntegerField($2, required=${3:False})", - "description": "IntegerField (fint)", - "scope": "source.python" - }, - "fmochoice": { - "prefix": "fmochoice", - "body": "${1:FIELDNAME} = forms.ModelChoiceField($2)", - "description": "ModelChoiceField (fmochoice)", - "scope": "source.python" - }, - "fmomuchoice": { - "prefix": "fmomuchoice", - "body": "${1:FIELDNAME} = forms.ModelMultipleChoiceField($2)", - "description": "ModelMultipleChoiceField (fmomuchoice)", - "scope": "source.python" - }, - "fmuval": { - "prefix": "fmuval", - "body": "${1:FIELDNAME} = forms.MultiValueField($2)", - "description": "MultiValueField (fmuval)", - "scope": "source.python" - }, - "fmuchoice": { - "prefix": "fmuchoice", - "body": "${1:FIELDNAME} = forms.MultipleChoiceField($2, choices=[${3:CHOICES}], required=${4:False})", - "description": "MultipleChoiceField (fmuchoice)", - "scope": "source.python" - }, - "ftypedmuchoice": { - "prefix": "ftypedmuchoice", - "body": "${1:FIELDNAME} = forms.TypedMultipleChoiceField($2, choices=[${3:CHOICES}], coerce=${4:TYPE}, required=${5:False})", - "description": "TypedMultipleChoiceField (ftypedmuchoice)", - "scope": "source.python" - }, - "fnullbool": { - "prefix": "fnullbool", - "body": "${1:FIELDNAME} = forms.NullBooleanField($2, required=${3:False})", - "description": "NullBooleanField (fnullbool)", - "scope": "source.python" - }, - "fregex": { - "prefix": "fregex", - "body": "${1:FIELDNAME} = forms.RegexField($2, regex=${3:REGEX}, required=${4:False})", - "description": "RegexField (fregex)", - "scope": "source.python" - }, - "fslug": { - "prefix": "fslug", - "body": "${1:FIELDNAME} = forms.SlugField($2, allow_unicode=${3:False}, required=${4:False})", - "description": "SlugField (fslug)", - "scope": "source.python" - }, - "fsdatetime": { - "prefix": "fsdatetime", - "body": "${1:FIELDNAME} = forms.SplitDateTimeField($2)", - "description": "SplitDateTimeField (fsdatetime)", - "scope": "source.python" - }, - "ftime": { - "prefix": "ftime", - "body": "${1:FIELDNAME} = forms.TimeField($2, required=${3:False})", - "description": "TimeField (ftime)", - "scope": "source.python" - }, - "ftchoice": { - "prefix": "ftchoice", - "body": "${1:FIELDNAME} = forms.TypedChoiceField($2, required=${3:False})", - "description": "TypedChoiceField (ftchoice)", - "scope": "source.python" - }, - "ftmuchoice": { - "prefix": "ftmuchoice", - "body": "${1:FIELDNAME} = forms.TypedMultipleChoiceField($2)", - "description": "TypedMultipleChoiceField (ftmuchoice)", - "scope": "source.python" - }, - "furl": { - "prefix": "furl", - "body": "${1:FIELDNAME} = forms.URLField($2, required=${3:False})", - "description": "URLField (furl)", - "scope": "source.python" - }, - "fuuid": { - "prefix": "fuuid", - "body": "${1:FIELDNAME} = forms.UUIDField($2, required=${3:False})", - "description": "UUIDField (fuuid)", - "scope": "source.python" - }, - "fsimplearray": { - "prefix": "fsimplearray", - "body": "${1:FIELDNAME} = SimpleArrayField()", - "description": "SimpleArrayField (fsimplearray).\n\n*PostgreSQL specific form fields*.", - "scope": "source.python" - }, - "fsplitarray": { - "prefix": "fsplitarray", - "body": "${1:FIELDNAME} = SplitArrayField()", - "description": "SplitArrayField (fsplitarray).\n\n*PostgreSQL specific form fields*.", - "scope": "source.python" - }, - "fhstore": { - "prefix": "fhstore", - "body": "${1:FIELDNAME} = HStoreField()", - "description": "HStoreField (fhstore).\n\n*PostgreSQL specific form fields*.", - "scope": "source.python" - }, - "fjson": { - "prefix": "fjson", - "body": "${1:FIELDNAME} = JSONField()", - "description": "JSONField (fjson).\n\n*PostgreSQL specific form fields*.", - "scope": "source.python" - }, - "fintrange": { - "prefix": "fintrange", - "body": "${1:FIELDNAME} = IntegerRangeField()", - "description": "IntegerRangeField (fintrange).\n\n*PostgreSQL specific form fields*.", - "scope": "source.python" - }, - "ffloatrange": { - "prefix": "ffloatrange", - "body": "${1:FIELDNAME} = FloatRangeField()", - "description": "FloatRangeField (ffloatrange).\n\n*PostgreSQL specific form fields*.", - "scope": "source.python" - }, - "fdatetimerange": { - "prefix": "fdatetimerange", - "body": "${1:FIELDNAME} = DateTimeRangeField()", - "description": "DateTimeRangeField (fdatetimerange).\n\n*PostgreSQL specific form fields*.", - "scope": "source.python" - }, - "fdaterange": { - "prefix": "fdaterange", - "body": "${1:FIELDNAME} = DateRangeField()", - "description": "DateRangeField (fdaterange).\n\n*PostgreSQL specific form fields*.", - "scope": "source.python" - }, - "ffi": { - "prefix": "ffi", - "body": "from .forms import $1", - "description": "", - "scope": "source.python" - }, - "iforms": { - "prefix": "iforms", - "body": "from django import forms", - "description": "from ... import forms", - "scope": "source.python" - }, - "ipostgresff": { - "prefix": "ipostgresff", - "body": "from django.contrib.postgres.forms import ${1|SimpleArrayField,SplitArrayField,HStoreField,JSONField,IntegerRangeField,FloatRangeField,DateTimeRangeField,DateRangeField|}", - "description": "PostgreSQL specific forms fields", - "scope": "source.python" - }, - "clean_data": { - "prefix": "clean_data", - "body": [ - "def clean_${1:FIELD}(self):", - "\t${1:FIELD} = self.cleaned_data.get('${1:FIELD}')", - "\n\n\t # TODO Validation\n", - "\treturn ${1:FIELD}" - ], - "description": "", - "scope": "source.python" - }, - "Model_full": { - "prefix": "Model_full", - "body": [ - "class ${1:MODELNAME}(models.Model):", - "\t\"\"\"${2:Model definition for $1}.\"\"\"", - "", - "\t${3:# TODO: Define fields here}", - "", - "\tclass Meta:", - "\t\t\"\"\"Meta definition for $1.\"\"\"", - "", - "\t\tverbose_name = '$1'", - "\t\tverbose_name_plural = '$1s'", - "", - "\tdef ${4|__str__,__unicode__|}(self):", - "\t\t\"\"\"Unicode representation of $1.\"\"\"", - "\t\t${7|pass,return '{}'.format(self. ) # TODO,return f'{self. }' # TODO|}", - "", - "\tdef save(self):", - "\t\t\"\"\"Save method for $1.\"\"\"", - "\t\tpass", - "", - "\tdef get_absolute_url(self):", - "\t\t\"\"\"Return absolute url for $1.\"\"\"", - "\t\treturn ('')", - "", - "\t${6:# TODO: Define custom methods here}", - "" - ], - "description": "Model (full)", - "scope": "source.python" - }, - "Model": { - "prefix": "Model", - "body": [ - "class ${1:MODELNAME}(models.Model):", - "\t\"\"\"${2:Model definition for $1}.\"\"\"", - "", - "\t${3:# TODO: Define fields here}", - "", - "\tclass Meta:", - "\t\t\"\"\"Meta definition for $1.\"\"\"", - "", - "\t\tverbose_name = '$1'", - "\t\tverbose_name_plural = '$1s'", - "", - "\tdef ${4|__str__,__unicode__|}(self):", - "\t\t\"\"\"Unicode representation of $1.\"\"\"", - "\t\t${5|pass,return '{}'.format(self. ) # TODO,return f'{self. }' # TODO|}", - "" - ], - "description": "Model", - "scope": "source.python" - }, - "modelmixin": { - "prefix": "modelmixin", - "body": [ - "class $1Mixin(models.Model):", - "\t${2:# TODO}\r\n", - "\tclass Meta:", - "\t\tabstract = True" - ], - "description": "", - "scope": "source.python" - }, - "queryset": { - "prefix": "qs", - "body": ["class $1QuerySet(models.QuerySet):", "\tpass"], - "description": "", - "scope": "source.python" - }, - "manager": { - "prefix": "mngr", - "body": [ - "class $1Manager(models.Manager):", - "\tdef get_queryset(self):", - "\t\treturn super ($1Manager, self).get_queryset().${2|filter,exclude,order_by,distinct,reverse|}($3)" - ], - "description": "Add extra Manager methods", - "scope": "source.python" - }, - "queryset_from_manager": { - "prefix": "qs_mngr", - "body": [ - "class $1Manager(models.Manager):", - "\tdef get_queryset(self):", - "\t\treturn $1QuerySet(self.model, using=self._db)" - ], - "description": "Modify the initial QuerySet the Manager returns.", - "scope": "source.python" - }, - "mauto": { - "prefix": "mauto", - "body": "${1:FIELDNAME} = models.AutoField($2)", - "description": "AutoField (mauto).\n\nAn IntegerField that automatically increments according to available IDs.\n\n", - "scope": "source.python" - }, - "mbigauto": { - "prefix": "mbigauto", - "body": "${1:FIELDNAME} = models.BigAutoField($2)", - "description": "BigAutoField (mbigauto).\n\n[New in Django 1.10.]\n\nA 64-bit integer, much like an AutoField.\n\n", - "scope": "source.python" - }, - "mbigint": { - "prefix": "mbigint", - "body": "${1:FIELDNAME} = models.BigIntegerField($2)", - "description": "BigIntegerField (mbigint).\n\nA 64-bit integer, much like an IntegerField.\n\n", - "scope": "source.python" - }, - "mbinary": { - "prefix": "mbinary", - "body": "${1:FIELDNAME} = models.BinaryField($2)", - "description": "BinaryField (mbinary).\n\nA field to store raw binary data.\n\n", - "scope": "source.python" - }, - "mbool": { - "prefix": "mbool", - "body": "${1:FIELDNAME} = models.BooleanField($2)", - "description": "BooleanField (mbool).\n\nA true/false field.\n\n", - "scope": "source.python" - }, - "mchar": { - "prefix": "mchar", - "body": "${1:FIELDNAME} = models.CharField($2, max_length=${3:50})", - "description": "CharField (mchar)", - "scope": "source.python" - }, - "mcoseint": { - "prefix": "mcoseint", - "body": "${1:FIELDNAME} = models.CommaSeparatedIntegerField($2)", - "description": "CommaSeparatedIntegerField (mcoseint).\n\nThis field is deprecated since 1.9 in favor of CharField with validators.\n\n", - "scope": "source.python" - }, - "mdate": { - "prefix": "mdate", - "body": "${1:FIELDNAME} = models.DateField($2, auto_now=${3:False}, auto_now_add=${4:False})", - "description": "DateField (mdate).\n\nA date, represented in Python by a datetime.date instance.\n\n", - "scope": "source.python" - }, - "mdatetime": { - "prefix": "mdatetime", - "body": "${1:FIELDNAME} = models.DateTimeField($2, auto_now=${3:False}, auto_now_add=${4:False})", - "description": "DateTimeField (mdatetime).\n\nA date, represented in Python by a datetime.datetime instance.\n\n", - "scope": "source.python" - }, - "mdecimal": { - "prefix": "mdecimal", - "body": "${1:FIELDNAME} = models.DecimalField($2, max_digits=${3:5}, decimal_places=${4:2})", - "description": "DecimalField (mdecimal).\n\nA fixed-precision decimal number, represented in Python by a Decimal instance.\n\n", - "scope": "source.python" - }, - "mduration": { - "prefix": "mduration", - "body": "${1:FIELDNAME} = models.DurationField($2)", - "description": "DurationField (mduration).\n\nA field for storing periods of time - modeled in Python by timedelta.\n\n", - "scope": "source.python" - }, - "memail": { - "prefix": "memail", - "body": "${1:FIELDNAME} = models.EmailField($2, max_length=${3:254})", - "description": "EmailField (memail).\n\nA CharField that checks that the value is a valid email address.\n\n", - "scope": "source.python" - }, - "mfile": { - "prefix": "mfile", - "body": "${1:FIELDNAME} = models.FileField($2, upload_to=${3:None}, max_length=${4:100})", - "description": "FileField (mfile).\n\nA file-upload field.\n\n", - "scope": "source.python" - }, - "mfilepath": { - "prefix": "mfilepath", - "body": "${1:FIELDNAME} = models.FilePathField($2, path=${3:None}, match=${4:None}, recursive=${5:recursive}, max_length=${6:100})", - "description": "FilePathField (mfilepath).\n\nA CharField whose choices are limited to the filenames in a certain directory on the filesystem.\n\n", - "scope": "source.python" - }, - "mfloat": { - "prefix": "mfloat", - "body": "${1:FIELDNAME} = models.FloatField($2)", - "description": "FloatField (mfloat).\n\nA floating-point number represented in Python by a float instance.\n\n", - "scope": "source.python" - }, - "fk": { - "prefix": "fk", - "body": "${1:FIELDNAME} = models.ForeignKey(${2:OTHERMODEL}, on_delete=models.${3|CASCADE,PROTECT,SET_NULL,SET_DEFAULT,SET(),DO_NOTHING|})", - "description": "ForeignKey (fk).\n\nA many-to-one relationship.\n\non_delete will become a required argument in Django 2.0. In older versions it defaults to CASCADE.\n\n", - "scope": "source.python" - }, - "mip": { - "prefix": "mip", - "body": "${1:FIELDNAME} = models.IPAddressField($2)", - "description": "IPAddressField (mip).\n\nThis field has been deprecated since version 1.7 in favor of GenericIPAddressField.\n\n", - "scope": "source.python" - }, - "mimg": { - "prefix": "mimg", - "body": "${1:FIELDNAME} = models.ImageField($2, upload_to=${3:None}, height_field=${4:None}, width_field=${5:None}, max_length=${5:100})", - "description": "ImageField (mimg).\n\nInherits all attributes and methods from FileField, but also validates that the uploaded object is a valid image.\n\n", - "scope": "source.python" - }, - "mint": { - "prefix": "mint", - "body": "${1:FIELDNAME} = models.IntegerField($2)", - "description": "IntegerField (mint).\n\nAn integer. Values from -2147483648 to 2147483647 are safe in all databases supported by Django.\n\n", - "scope": "source.python" - }, - "mgenericip": { - "prefix": "mgenericip", - "body": "${1:FIELDNAME} = models.GenericIPAddressField($2, protocol=${3:'both'}, unpack_ipv4=${4:False})", - "description": "GenericIPAddressField (mimg).\n\nAn IPv4 or IPv6 address, in string format.\n\n", - "scope": "source.python" - }, - "m2m": { - "prefix": "m2m", - "body": "${1:FIELDNAME} = models.ManyToManyField(${2:OTHERMODEL})", - "description": "ManyToManyField (m2m).\n\nA many-to-many relationship.\n\n", - "scope": "source.python" - }, - "mnullbool": { - "prefix": "mnullbool", - "body": "${1:FIELDNAME} = models.NullBooleanField($2)", - "description": "NullBooleanField (mnullbool).\n\nLike a BooleanField, but allows NULL as one of the options.\n\n", - "scope": "source.python" - }, - "o2o": { - "prefix": "o2o", - "body": "${1:FIELDNAME} = models.OneToOneField(${2:OTHERMODEL}, on_delete=models.${3|CASCADE,PROTECT,SET_NULL,SET_DEFAULT,SET(),DO_NOTHING|})", - "description": "OneToOneField (o2o).\n\nA one-to-one relationship.\n\non_delete will become a required argument in Django 2.0. In older versions it defaults to CASCADE.\n\n", - "scope": "source.python" - }, - "mphone": { - "prefix": "mphone", - "body": "${1:FIELDNAME} = models.PhoneNumberField($2)", - "description": "PhoneNumberField (mphone).\n\n*external package: django-phonenumber-field*\n\n", - "scope": "source.python" - }, - "mposint": { - "prefix": "mposint", - "body": "${1:FIELDNAME} = models.PositiveIntegerField($2)", - "description": "PositiveIntegerField (mposint).\n\nLike an IntegerField, but must be either positive or zero (0).\n\n", - "scope": "source.python" - }, - "mpossmallint": { - "prefix": "mpossmallint", - "body": "${1:FIELDNAME} = models.PositiveSmallIntegerField($2)", - "description": "PositiveSmallIntegerField (mpossmallint).\n\nLike a PositiveIntegerField, but only allows values under a certain (database-dependent) point.\n\n", - "scope": "source.python" - }, - "mslug": { - "prefix": "mslug", - "body": "${1:FIELDNAME} = models.SlugField($2)", - "description": "SlugField (mslug).\n\nA slug is a short label for something, containing only letters, numbers, underscores or hyphens. They’re generally used in URLs.\n\n", - "scope": "source.python" - }, - "msmallint": { - "prefix": "msmallint", - "body": "${1:FIELDNAME} = models.SmallIntegerField($2)", - "description": "SmallIntegerField (msmallint).\n\nLike an IntegerField, but only allows values under a certain (database-dependent) point.\n\n", - "scope": "source.python" - }, - "mtext": { - "prefix": "mtext", - "body": "${1:FIELDNAME} = models.TextField($2)", - "description": "TextField (mtext).\n\nA large text field.\n\n", - "scope": "source.python" - }, - "mtime": { - "prefix": "mtime", - "body": "${1:FIELDNAME} = models.TimeField($2, auto_now=${4:False}, auto_now_add=${5:False})", - "description": "TimeField (mtime).\n\nA time, represented in Python by a datetime.time instance.\n\n", - "scope": "source.python" - }, - "murl": { - "prefix": "murl", - "body": "${1:FIELDNAME} = models.URLField($2, max_length=${3:200})", - "description": "URLField (murl).\n\nA CharField for a URL.\n\n", - "scope": "source.python" - }, - "musstate": { - "prefix": "musstate", - "body": "${1:FIELDNAME} = models.USStateField($2)", - "description": "USStateField (musstate).\n\n*external package: django-localflavor*\n\n", - "scope": "source.python" - }, - "muuid": { - "prefix": "muuid", - "body": "${1:FIELDNAME} = models.UUIDField($2)", - "description": "UUIDField (muuid).\n\nA field for storing universally unique identifiers. Uses Python’s UUID class.\n\n", - "scope": "source.python" - }, - "mxml": { - "prefix": "mxml", - "body": "${1:FIELDNAME} = models.XMLField($2)", - "description": "XMLField (mxml).\n\n*All uses of XMLField can be replaced with TextField. This field has been deprecated since version 1.3*\n\n", - "scope": "source.python" - }, - "mstore": { - "prefix": "mstore", - "body": "${1:FIELDNAME} = HStoreField()", - "description": "HStoreField (mstore).\n\n*PostgreSQL specific model fields*.\n\nA field for storing key-value pairs. The Python data type used is a dict.\n\n", - "scope": "source.python" - }, - "mjson": { - "prefix": "mjson", - "body": "${1:FIELDNAME} = JSONField()", - "description": "JSONField (mjson).\n\n*PostgreSQL specific model fields*.\n\n[New in Django 1.11.]\n\nA field for storing JSON encoded data.\n\n", - "scope": "source.python" - }, - "marray": { - "prefix": "marray", - "body": "${1:FIELDNAME} = ArrayField()", - "description": "ArrayField (marray).\n\n*PostgreSQL specific model fields*.\n\nA field for storing lists of data\n\n", - "scope": "source.python" - }, - "fmai": { - "prefix": "fmai", - "body": "from .managers import $1QuerySet", - "description": "", - "scope": "source.python" - }, - "fmi": { - "prefix": "fmi", - "body": "from .models import $1", - "description": "", - "scope": "source.python" - }, - "imodels": { - "prefix": "imodels", - "body": "from django.db import models", - "description": "from ... import models", - "scope": "source.python" - }, - "ipy2_unicode_compatible": { - "prefix": "iuc", - "body": "from django.utils.encoding import python_2_unicode_compatible", - "description": "For forwards compatibility, this decorator is available as of Django 1.4.2.", - "scope": "source.python" - }, - "ipostgresmf": { - "prefix": "ipostgresmf", - "body": "from django.contrib.postgres.fields import ${1|ArrayField,JSONField,HStoreField|}", - "description": "PostgreSQL specific model fields", - "scope": "source.python" - }, - "isignals": { - "prefix": "isignals", - "body": "from django.db.models.signals import ${1|pre_init,post_init,pre_save,post_save,pre_delete,post_delete,m2m_changed,class_prepared,Management signals,pre_migrate,post_migrate|}", - "description": "Signals for Django Model", - "scope": "source.python" - }, - "__str__": { - "prefix": "str", - "body": ["def __str__(self):", "\treturn self${1: # TODO}"], - "description": "", - "scope": "source.python" - }, - "get_absolute_url": { - "prefix": "get_absolute_url", - "body": [ - "def get_absolute_url(self):", - "\tfrom django.core.urlresolvers import reverse", - "\treturn reverse('$1', kwargs={'pk': self.pk})" - ], - "description": "", - "scope": "source.python" - }, - "receiver": { - "prefix": "receiver", - "body": [ - "def ${1:FUNCTIONNAME}_${2|pre_init,post_init,pre_save,post_save,pre_delete,post_delete,m2m_changed,class_prepared,Management signals,pre_migrate,post_migrate|}_receiver(sender, instance, *args, **kwargs):", - "\tpass", - "\n\n${2|pre_init,post_init,pre_save,post_save,pre_delete,post_delete,m2m_changed,class_prepared,Management signals,pre_migrate,post_migrate|}.connect(${1:name}_${2|pre_init,post_init,pre_save,post_save,pre_delete,post_delete,m2m_changed,class_prepared,Management signals,pre_migrate,post_migrate|}_receiver, sender=${3:MODELNAME})" - ], - "description": "", - "scope": "source.python" - }, - "__init__": { - "prefix": "__init__", - "body": "\r\ndef __init__(self, *args, **kwargs):\r\n super(${1:CLASS_NAME}, self).__init__(*args, **kwargs)\r\n", - "description": "", - "scope": "source.python" - }, - "ipdb": { - "prefix": "ipdb", - "body": "import ipdb; ipdb.set_trace()", - "description": "ipdb debug tool", - "scope": "source.python" - }, - "npdb": { - "prefix": "npdb", - "body": "from nose.tools import set_trace; set_trace()", - "description": "nose pdb debug tool", - "scope": "source.python" - }, - "pdb": { - "prefix": "pdb", - "body": "import pdb; pdb.set_trace()", - "description": "pdb debug tool", - "scope": "source.python" - }, - "traceback": { - "prefix": "traceback", - "body": "import traceback; traceback.print_exc();", - "description": "traceback print exception", - "scope": "source.python" - }, - "utfc": { - "prefix": "utfc", - "body": "# -*- coding: utf-8 -*-", - "description": "coding: utf-8", - "scope": "source.python" - }, - "iunicode_literals": { - "prefix": "iul", - "body": "from __future__ import unicode_literals", - "description": "In order to enable the same behavior in Python 2, every module must import: \n", - "scope": "source.python" - }, - "ilib": { - "prefix": "ilib", - "body": ["from django import template", "register = template.Library()"], - "description": "", - "scope": "source.python" - }, - "li18n": { - "prefix": "li18n", - "body": "{% load i18n %}", - "description": "", - "scope": "text.html.django" - }, - "lstatic": { - "prefix": "lstatic", - "body": "{% load staticfiles %}", - "description": "", - "scope": "text.html.django" - }, - "ltags": { - "prefix": "ltags", - "body": "{% load $SELECTION$1_tags %}", - "description": "", - "scope": "text.html.django" - }, - "register_assignment_tag": { - "prefix": "register_assignment_tag", - "body": [ - "def get_$1(context):", - "\trequest = context.get('request')", - "\t$1 = ${2:[]}", - "\treturn ${3:$1}" - ], - "description": "", - "scope": "source.python" - }, - "register_filter": { - "prefix": "register_filter", - "body": ["@register.filter", "def $1(value):", "\treturn value$2"], - "description": "", - "scope": "source.python" - }, - "register_inclusion_tag": { - "prefix": "register_inclusion_tag", - "body": [ - "@register.inclusion_tag(${2:'$1.html'}, takes_context=True)", - "def $1(context):", - "\trequest = context.get('request')", - "\t$3", - "\treturn {", - "\t\t'request': request,", - "\t\t$4", - "\t}" - ], - "description": "", - "scope": "source.python" - }, - "register_simple_tag": { - "prefix": "register_simple_tag", - "body": [ - "@register.simple_tag(takes_context=True)", - "def $1(context):", - "\trequest = context.get('request')", - "\treturn ${2:'It Works!'}" - ], - "description": "", - "scope": "source.python" - }, - "urlresolvers": { - "prefix": "iurlresolvers", - "body": "from django.core.urlresolvers import ${1|reverse,reverse_lazy,resolve,get_script_prefix|}", - "description": "*Deprecated since version 1.10*\n\nUtility functions.\n\n", - "scope": "source.python" - }, - "urls (≥1.10 & ≤1.11)": { - "prefix": "iurls", - "body": "from django.urls import ${1|reverse,reverse_lazy,resolve,get_script_prefix|}", - "description": "Utility functions for use in URLconfs.", - "scope": "source.python" - }, - "conf.urls (≤1.11)": { - "prefix": "iconf_urls", - "body": "from django.conf.urls import ${1|static,url,include,handler400,handler403,handler404,handler500|}", - "description": "Utility functions for use in URLconfs.", - "scope": "source.python" - }, - "urls (≥2.0)": { - "prefix": "iurls", - "body": "from django.urls import ${1|path,re_path,include,reverse,reverse_lazy,register_converter|}", - "description": "Utility functions for use in URLconfs.", - "scope": "source.python" - }, - "conf.urls (≥2.0)": { - "prefix": "iconf_urls", - "body": "from django.conf.urls import ${1|static,url,handler400,handler403,handler404,handler500|}", - "description": "Utilityfunctions for use in URLconfs.", - "scope": "source.python" - }, - "url_stack": { - "prefix": "url_stack", - "body": [ - "${1|url,re_path|}(", - "\tr'^${2:REGEX}/$',", - "\t${3:VIEW}${4:.as_view()},", - "\tname='$5'", - ")," - ], - "description": "url(regex, view, kwargs=None, name=None)\n\n*url is an alias to re_path*\n\n", - "scope": "source.python" - }, - "url_inline": { - "prefix": "url_inline", - "body": [ - "${1|url,re_path|}(r'^${2:REGEX}/$', ${3:VIEW}${4:.as_view()}, name='$5')," - ], - "description": "url(regex, view, kwargs=None, name=None)\n\n*url is an alias to re_path*\n\n", - "scope": "source.python" - }, - "path_stack": { - "prefix": "path_stack", - "body": [ - "path(", - "\t'${1:ROUTE}/',", - "\t${2:VIEW}${3:.as_view()},", - "\tname='$4'", - ")," - ], - "description": "path(route, view, kwargs=None, name=None)", - "scope": "source.python" - }, - "path_inline": { - "prefix": "path_inline", - "body": ["path('${1:ROUTE}/', ${2:VIEW}${3:.as_view()}, name='$4'),"], - "description": "path(route, view, kwargs=None, name=None)", - "scope": "source.python" - }, - "urlpatterns": { - "prefix": "urlpatterns", - "body": ["urlpatterns = [", "\t$0", "]"], - "description": "", - "scope": "source.python" - }, - "repk": { - "prefix": "repk", - "body": "r'^(?P<${1:pk}>d+)/$'", - "description": "PK URL regex", - "scope": "source.python" - }, - "reslug": { - "prefix": "reslug", - "body": "r'^(?P<${1:slug}>[-w]+)/$'", - "description": "Slug URL regex", - "scope": "source.python" - }, - "reusername": { - "prefix": "reusername", - "body": "r'^(?P[w.@+-]+)/$'", - "description": "Username regex", - "scope": "source.python" - }, - "createview": { - "prefix": "createview", - "body": "\r\nclass ${1:MODEL_NAME}CreateView(CreateView):\r\n model = ${1:MODEL_NAME}\r\n template_name = \"${2:TEMPLATE_NAME}\"\r\n", - "description": "", - "scope": "source.python" - }, - "deleteview": { - "prefix": "deleteview", - "body": "\r\nclass ${1:MODEL_NAME}DeleteView(DeleteView):\r\n model = ${1:MODEL_NAME}\r\n template_name = \"${2:TEMPLATE_NAME}\"\r\n", - "description": "", - "scope": "source.python" - }, - "detailview": { - "prefix": "detailview", - "body": "\r\nclass ${1:MODEL_NAME}DetailView(DetailView):\r\n model = ${1:MODEL_NAME}\r\n template_name = \"${2:TEMPLATE_NAME}\"\r\n", - "description": "", - "scope": "source.python" - }, - "listview": { - "prefix": "listview", - "body": "\r\nclass ${1:MODEL_NAME}ListView(ListView):\r\n model = ${1:MODEL_NAME}\r\n template_name = \"${2:TEMPLATE_NAME}\"\r\n", - "description": "", - "scope": "source.python" - }, - "templateview": { - "prefix": "templateview", - "body": "\r\nclass ${1:CLASS_NAME}(TemplateView):\r\n template_name = \"${2:TEMPLATE_NAME}\"\r\n", - "description": "", - "scope": "source.python" - }, - "updateview": { - "prefix": "updateview", - "body": "\r\nclass ${1:MODEL_NAME}UpdateView(UpdateView):\r\n model = ${1:MODEL_NAME}\r\n template_name = \"${2:TEMPLATE_NAME}\"\r\n", - "description": "", - "scope": "source.python" - }, - "from views import": { - "prefix": "fvi", - "body": "from . import $1", - "description": "", - "scope": "source.python" - }, - "igenericviews": { - "prefix": "igenericviews", - "body": "from django.views.generic import ${1|CreateView,DetailView,FormView,ListView,TemplateView,UpdateView|}", - "description": "Generic class-based views", - "scope": "source.python" - }, - "isettings": { - "prefix": "isettings", - "body": "from django.conf import settings", - "description": "from django.conf import settings", - "scope": "source.python" - }, - "view": { - "prefix": "view", - "body": "def ${1:VIEWNAME}(request):", - "description": "View", - "scope": "source.python" - }, - "dispatch": { - "prefix": "dispatch", - "body": "\r\ndef dispatch(self, request, *args, **kwargs):\r\n return super(${1:CLASS_NAME}, self).dispatch(request, *args, **kwargs)\r\n", - "description": "", - "scope": "source.python" - }, - "context": { - "prefix": "get_context_data", - "body": "\r\ndef get_context_data(self, **kwargs):\r\n context = super(${1:CLASS_NAME}, self).get_context_data(**kwargs)\r\n return context\r\n", - "description": "", - "scope": "source.python" - }, - "get_queryset": { - "prefix": "get_queryset", - "body": [ - "def get_queryset(self):", - "\tqueryset = super(${1:CLASS_NAME}, self).get_queryset()", - "\tqueryset = queryset${3: # TODO}", - "\treturn queryset" - ], - "description": "", - "scope": "source.python" - } -} diff --git a/snippets/frameworks/django/filetemplates.json b/snippets/frameworks/django/filetemplates.json deleted file mode 100644 index c6561f3..0000000 --- a/snippets/frameworks/django/filetemplates.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "Django URLFile Template":{ - "prefix": "fturl", - "body": [ - "from django.urls import path", - "from . import views as v", - "\n\napp_name = ${1:AppName}", - "urlpatterns = [", - "\t# TODO: Define $1 URLs here", - "\t${0}", - "]" - ], - "description": "Django File-Template Sinppet For ``URL`` File" - }, - "Django FormFile Template":{ - "prefix": "ftform", - "body": [ - "from django import forms", - "from ${1:.models} import ${2}", - "\n\n# TODO: Create your forms here", - "${0}" - ], - "description": "Django File-Template Sinppet For ``Form`` File" - }, - "Django CustomTagsFile Template":{ - "prefix": "ftcutomtags", - "body": [ - "from django import template", - "\nregister = template.Library()", - "\n# TODO: Create your custom tags here", - "${0}" - ], - "description": "Django File-Template Sinppet For ``CustomTags`` File" - } -} diff --git a/snippets/frameworks/django/forms.json b/snippets/frameworks/django/forms.json deleted file mode 100644 index 5b2c319..0000000 --- a/snippets/frameworks/django/forms.json +++ /dev/null @@ -1,168 +0,0 @@ -{ - "Django Simple Form ":{ - "prefix": "sform", - "body": [ - "class ${1:Name}Form(forms.Form):", - "\t# Define $1Form fields here", - "\t${0}" - ], - "description": "Django Simple Form" - }, - "Django Model Form ":{ - "prefix": "modelform", - "body": [ - "class ${1:ModelName}Form(forms.ModelForm):", - "\tclass Meta:", - "\t\tmodel = ${2:$1}", - "\t\tfields = (${3:\"__all__\"})", - "\t\t${0}" - ], - "description": "Django Model Form" - }, - "Forms BooleanField":{ - "prefix": "fbool", - "body": "${1:FIELDNAME} = forms.BooleanField(${2})", - "description": "Django forms ``BooleanField``" - }, - "Forms CharField":{ - "prefix": "fchar", - "body": "${1:FIELDNAME} = forms.CharField(${2})", - "description": "Django forms ``CharField``" - }, - "Forms ComboField":{ - "prefix": "fcombo", - "body": "${1:FIELDNAME} = forms.ComboField(${2})", - "description": "Django forms ``ComboField``" - }, - "Forms DateField":{ - "prefix": "fdate", - "body": "${1:FIELDNAME} = forms.DateField(${2})", - "description": "Django forms ``DateField``" - }, - "Forms DateTime":{ - "prefix": "fdatetime", - "body": "${1:FIELDNAME} = forms.DateTime(${2})", - "description": "Django forms ``DateTime``" - }, - "Forms DecimalField":{ - "prefix": "fdecimal", - "body": "${1:FIELDNAME} = forms.DecimalField(${2})", - "description": "Django forms ``DecimalField``" - }, - "Forms DurationField":{ - "prefix": "fduration", - "body": "${1:FIELDNAME} = forms.DurationField(${2})", - "description": "Django forms ``DurationField``" - }, - "Forms EmailField":{ - "prefix": "femail", - "body": "${1:FIELDNAME} = forms.EmailField(${2})", - "description": "Django forms ``EmailField``" - }, - "Forms FileField":{ - "prefix": "ffile", - "body": "${1:FIELDNAME} = forms.FileField(${2})", - "description": "Django forms ``FileField``" - }, - "Forms FilePathField":{ - "prefix": "ffilepath", - "body": "${1:FIELDNAME} = forms.FilePathField(${2})", - "description": "Django forms ``FilePathField``" - }, - "Forms FloatField":{ - "prefix": "ffloat", - "body": "${1:FIELDNAME} = forms.FloatField(${2})", - "description": "Django forms ``FloatField``" - }, - "Forms GenericIPAddressField":{ - "prefix": "fgip", - "body": "${1:FIELDNAME} = forms.GenericIPAddressField(${2})", - "description": "Django forms ``GenericIPAddressField``" - }, - "Forms GenericIPAddressField":{ - "prefix": "fgip", - "body": "${1:FIELDNAME} = forms.GenericIPAddressField(${2})", - "description": "Django forms ``GenericIPAddressField``" - }, - "Forms ImageField":{ - "prefix": "fimg", - "body": "${1:FIELDNAME} = forms.ImageField(${2})", - "description": "Django forms ``ImageField``" - }, - "Forms IntegerField":{ - "prefix": "fint", - "body": "${1:FIELDNAME} = forms.IntegerField(${2})", - "description": "Django forms ``IntegerField``" - }, - "Forms IPAddressField":{ - "prefix": "fip", - "body": "${1:FIELDNAME} = forms.IPAddressField(${2})", - "description": "Django forms ``IPAddressField``" - }, - "Forms ModelChoiceField":{ - "prefix": "fmochoice", - "body": "${1:FIELDNAME} = forms.ModelChoiceField(${2})", - "description": "Django forms ``ModelChoiceField``" - }, - "Forms ModelMultipleChoiceField":{ - "prefix": "fmomuchoice", - "body": "${1:FIELDNAME} = forms.ModelMultipleChoiceField(${2})", - "description": "Django forms ``ModelMultipleChoiceField``" - }, - "Forms MultipleChoiceField":{ - "prefix": "fmuchoice", - "body": "${1:FIELDNAME} = forms.MultipleChoiceField(${2})", - "description": "Django forms ``MultipleChoiceField``" - }, - "Forms MultipleValueField":{ - "prefix": "fmuvalue", - "body": "${1:FIELDNAME} = forms.MultipleValueField(${2})", - "description": "Django forms ``MultipleValueField``" - }, - "Forms NullBooleanField":{ - "prefix": "fnullbool", - "body": "${1:FIELDNAME} = forms.NullBooleanField(${2})", - "description": "Django forms ``NullBooleanField``" - }, - "Forms RegexField":{ - "prefix": "fregex", - "body": "${1:FIELDNAME} = forms.RegexField(${2})", - "description": "Django forms ``RegexField``" - }, - "Forms SlugField":{ - "prefix": "fslug", - "body": "${1:FIELDNAME} = forms.SlugField(${2})", - "description": "Django forms ``SlugField``" - }, - "Forms SplitDateTime":{ - "prefix": "fsdatetime", - "body": "${1:FIELDNAME} = forms.SplitDateTime(${2})", - "description": "Django forms ``SplitDateTime`` Field" - }, - "Forms TimeField":{ - "prefix": "ftime", - "body": "${1:FIELDNAME} = forms.TimeField(${2})", - "description": "Django forms ``TimeField``" - }, - "Forms TypedChoiceField":{ - "prefix": "ftchoice", - "body": "${1:FIELDNAME} = forms.TypedChoiceField(${2})", - "description": "Django forms ``TypedChoiceField``" - }, - "Forms TypedMultipleChoiceField":{ - "prefix": "ftmuchoice", - "body": "${1:FIELDNAME} = forms.TypedMultipleChoiceField(${2})", - "description": "Django forms ``TypedMultipleChoiceField``" - }, - "Forms URLField":{ - "prefix": "fulr", - "body": "${1:FIELDNAME} = forms.URLField(${2})", - "description": "Django forms ``URLField``" - }, - "Forms UUIDField":{ - "prefix": "fuuid", - "body": "${1:FIELDNAME} = forms.UUIDField(${2})", - "description": "Django forms ``UUIDField``" - } - -} diff --git a/snippets/frameworks/django/imports.json b/snippets/frameworks/django/imports.json deleted file mode 100644 index d099fb9..0000000 --- a/snippets/frameworks/django/imports.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "Import forms":{ - "prefix": "di-forms", - "body": "from django import forms", - "description": "Import Django ``forms``" - }, - "Import models":{ - "prefix": "di-model", - "body": "from django import models", - "description": "Import Django ``models``" - }, - "Import get_user_model":{ - "prefix": "di-getusermodel", - "body": "from django.contrib.auth import get_user_model", - "description": "Import Django ``get_user_model``" - }, - "Import generic views":{ - "prefix": "di-generic", - "body": "from django.views import generic", - "description": "Import Django ``generic``" - }, - "Import JsonResponse":{ - "prefix": "di-jsonresponse", - "body": "from django.http import JsonResponse", - "description": "Import Django ``JsonResponse``" - }, - "Import reverse":{ - "prefix": "di-reverse", - "body": "from django.urls import reverse", - "description": "Import Django ``reverse``" - }, - "Import reverse_lazy":{ - "prefix": "di-reverse_lazy", - "body": "from django.urls import revers_lazy", - "description": "Import Django ``revers_lazy``" - }, - - "Import messages":{ - "prefix": "di-messages", - "body": "from django.contrib import messages", - "description": "Import Django ``messages``" - } -} diff --git a/snippets/frameworks/django/models.json b/snippets/frameworks/django/models.json deleted file mode 100644 index c0b656c..0000000 --- a/snippets/frameworks/django/models.json +++ /dev/null @@ -1,183 +0,0 @@ -{ - "Django Simple Model": { - "prefix": "smodel", - "body": [ - "class ${1:ModelName}(models.Model):", - "\t# Define $1 fields here", - "\t${2}", - "\n\tclass Meta:", - "\t\tordering = [\"${3:-pk}\"]", - "\t\tverbose_name = \"${4:$1}\"", - "\t\tverbose_name_plural = \"${5:$1s}\"", - "\n\tdef __str__(self):", - "\t\treturn ${6:super().__str__()}", - "\n\t# Define $1 properties here", - "\t${0}" - ], - "description": "Django Simple Model with properties and attributes" - }, - "Django Full Model": { - "prefix": "model", - "body": [ - "class ${1:ModelName}(models.Model):", - "\t# Define $1 fields here", - "\t${2}", - "\n\tclass Meta:", - "\t\tordering = [\"${3:-pk}\"]", - "\t\tverbose_name = \"${4:$1}\"", - "\t\tverbose_name_plural = \"${5:$1s}\"", - "\n\tdef __str__(self):", - "\t\treturn ${6:super().__str__()}", - "\n\tdef save(self, *args, **kwargs):", - "\t\treturn ${7:super().save(*args, **kwargs)}", - "\n\tdef get_absolute_url(self):", - "\t\treturn reverse('${8:view_or_url_name}', kwargs={${9:'pk'}: ${10: self.pk}})", - "\n\t# Define $1 properties here", - "\t${0}" - ], - "description": "Django Full Model with properties and attributes" - }, - - "Models AutoField":{ - "prefix": "mauto", - "body": "${1:FIELDNAME} = models.AutoField(${2})", - "description": "Django model ``AutoField``" - }, - "Models BigIntegerField":{ - "prefix": "mbigint", - "body": "${1:FIELDNAME} = models.AutoField(${2})", - "description": "Django model ``AutoField``" - }, - "Models BinaryField":{ - "prefix": "mbinary", - "body": "${1:FIELDNAME} = models.BinaryField(${2})", - "description": "Django model ``BinaryField``" - }, - "Models Boolean":{ - "prefix": "mbool", - "body": "${1:FIELDNAME} = models.BooleanField(default=${2:False})", - "description": "Django model ``BooleanField``" - }, - "Models CharField":{ - "prefix": "mchar", - "body": "${1:FieldName} = models.CharField(max_length=${2:32})", - "description": "Django model ``CharField``" - }, - "Models CommaSeparatedIntegerField":{ - "prefix": "mcomma", - "body": "${1:FIELDNAME} = models.CommaSeparatedIntegerField(max_length=${2})", - "description": "Django model ``CommaSeparatedIntegerField``" - }, - "Models DateField":{ - "prefix": "mdate", - "body": "${1:FIELDNAME} = models.DateField(auto_now_add=${2:True}, auto_now=${3:False}})", - "description": "Django model ``DateField``" - }, - "Models DateTimeField":{ - "prefix": "mdatetime", - "body": "${1:FIELDNAME} = models.DateTimeField(auto_now_add=${2:True}, auto_now=${3:False})", - "description": "Django model ``DateTimeField``" - }, - "Models DecimalField":{ - "prefix": "mdecimal", - "body": "${1:FIELDNAME} = models.DecimalField(max_digits=${2}, decimal_places=${3})", - "description": "Django model ``DecimalField``" - }, - "Models EmailField":{ - "prefix": "memail", - "body": "${1:FIELDNAME} = models.EmailField(${2})", - "description": "Django model ``EmailField``" - }, - "Models FileField":{ - "prefix": "mfile", - "body": "${1:FIELDNAME} = models.FileField(upload_to=${2:path/for/upload})", - "description": "Django model ``FileField``" - }, - "Models FilePathField":{ - "prefix": "mfilepath", - "body": "${1:FIELDNAME} = models.FilePathField(path=${2:\"/abs/path/to/dir\"}${3:, max_length=100}${4:, match=\"*.ext\"}${4:, recursive=True})", - "description": "Django model ``FilePathField``" - }, - "Models FloatField":{ - "prefix": "mfloat", - "body": "${1:FIELDNAME} = models.FloatField(${2})", - "description": "Django model ``FloatField``" - }, - "Models ImageField":{ - "prefix": "mimg", - "body": "${1:FIELDNAME} = models.ImageField(upload_to=${2:path/for/upload}${3:, height_field=height, width_field=width}${4:, max_length=100})", - "description": "Django model ``ImageField``" - }, - "Models IntegerField":{ - "prefix": "mint", - "body": "${1:FIELDNAME} = models.IntegerField(${2})", - "description": "Django model ``IntegerField``" - }, - "Models IPAddressField":{ - "prefix": "mip", - "body": "${1:FIELDNAME} = models.IPAddressField(${2})", - "description": "Django model ``IPAddressField``" - }, - "Models NullBooleanField":{ - "prefix": "mnullboolean", - "body": "${1:FIELDNAME} = models.NullBooleanField(${2})", - "description": "Django model ``NullBooleanField``" - }, - "Models PositiveIntegerField":{ - "prefix": "mposint", - "body": "${1:FIELDNAME} = models.PositiveIntegerField(${2})", - "description": "Django model ``PositiveIntegerField``" - }, - "Models PositiveSmallIntegerField":{ - "prefix": "mpossmallint", - "body": "${1:FIELDNAME} = models.PositiveSmallIntegerField(${2})", - "description": "Django model ``PositiveSmallIntegerField``" - }, - "Models SlugField":{ - "prefix": "mslug", - "body": "${1:FIELDNAME} = models.SlugField(${2})", - "description": "Django model ``SlugField``" - }, - "Models SmallIntegerField":{ - "prefix": "msmallint", - "body": "${1:FIELDNAME} = models.SmallIntegerField(${2})", - "description": "Django model ``SmallIntegerField``" - }, - "Models TextField":{ - "prefix": "mtext", - "body": "${1:FIELDNAME} = models.TextField(${2})", - "description": "Django model ``TextField``" - }, - "Models TimeField":{ - "prefix": "mtime", - "body": "${1:FIELDNAME} = models.TimeField(auto_now_add=${2:True}, auto_now=${3:False})", - "description": "Django model ``TimeField``" - }, - "Models URLField":{ - "prefix": "murl", - "body": "${1:FIELDNAME} = models.URLField(verify_exists=${2:False})", - "description": "Django model ``URLField``" - }, - "Models XMLField":{ - "prefix": "mxml", - "body": "${1:FIELDNAME} = models.XMLField(schema_path=${2:None})", - "description": "Django model ``XMLField``" - }, - - "Models ForeignKey":{ - "prefix": "fk", - "body": "${1:FIELDNAME} = models.ForeignKey(${2:OtherModel}, on_delete=models.${3:CASCADE}, related_name=\"${4:RelatedName}\" ${0:, limit_choices_to=})", - "description": "Django model ``ForeignKey``" - }, - "Models ManyToManyField":{ - "prefix": "m2m", - "body": "${1:FIELDNAME} = models.ManyToManyField(${2:OtherModel}, related_name=\"${3:RelatedName}\" ${0:, limit_choices_to=})", - "description": "Django model ``ManyToManyField``" - }, - "Models OneToOneField":{ - "prefix": "o2o", - "body": "${1:FIELDNAME} = models.OneToOneField(${2:OtherModel}, related_name=\"${4:RelatedName}\"${0:, to_field=''})", - "description": "Django model ``OneToOneField``" - } -} - diff --git a/snippets/frameworks/django/views.json b/snippets/frameworks/django/views.json deleted file mode 100644 index 4faa917..0000000 --- a/snippets/frameworks/django/views.json +++ /dev/null @@ -1,243 +0,0 @@ -{ - "Django CreateView":{ - "prefix": "createview", - "body": [ - "class ${1:ModelName}CreateView(generic.CreateView):", - "\tmodel = ${2:$1}", - "\ttemplate_name = \"${3:$1/$1_form.html}\"", - "\tform_class = ${4:forms.$1Form}", - "\tsuccess_url = \"${5:.}\"" - ], - "description": "Django CBV ``CreateView``" - }, - "Django UpdateView":{ - "prefix": "updateview", - "body": [ - "class ${1:ModelName}UpdateView(generic.UpdateView):", - "\tmodel = ${2:$1}", - "\ttemplate_name = \"${3:$1/$1_form.html}\"", - "\tform_class = ${4:forms.$1Form}", - "\tsuccess_url = \"${5:.}\"", - "\n\tdef get_object(self):", - "\t\treturn $1.objects.get(pk=${6:self.kwargs.get(\"pk\")})" - ], - "description": "Django CBV ``UpdateView``" - }, - "Django DeleteView":{ - "prefix": "deleteview", - "body": [ - "class ${1:ModelName}DeleteView(generic.DeleteView):", - "\tmodel = ${2:$1}", - "\n\tdef get_success_url(self):", - "\t\treturn reverse(\"${3:$1:list}\")", - "\n\tdef get(self, request, *args, **kwargs):", - "\t\treturn post(request, *args, **kwargs)" - ], - "description": "Django CBV ``DeleteView``" - }, - "Django DetailView":{ - "prefix": "detailview", - "body": [ - "class ${1:ModelName}DetailView(generic.DetailView):", - "\tmodel = ${2:$1}", - "\ttemplate_name = \"${3:$1/$1_detail.html}\"", - "\n\tdef get_object(self):", - "\t\treturn $1.objects.get(pk=${4:self.kwargs.get(\"pk\")})", - "\n\tdef get_queryset(self):", - "\t\treturn $1.objects.filter(${5})" - ], - "description": "Django CBV ``DetailView``" - }, - "Django ListView":{ - "prefix": "listview", - "body": [ - "class ${1:ModelName}ListView(generic.ListView):", - "\tmodel = ${2:$1}", - "\ttemplate_name = \"${3:$1/$1_list.html}\"", - "\n\tdef get_queryset(self):", - "\t\treturn $1.objects.filter(${4})" - ], - "description": "Django CBV ``ListView``" - }, - "Django TemplateView":{ - "prefix": "templateview", - "body": [ - "class ${1:ModelName}TemplateView(generic.TemplateView):", - "\ttemplate_name = \"${2:$1/$1_list.html}\"", - "\n${3}" - ], - "description": "Django CBV ``TemplateView``" - }, - "Django FormView":{ - "prefix": "formview", - "body": [ - "class ${1:ModelName}FormView(generic.FormView):", - "\tform_class = ${2:forms.$1Form}", - "\ttemplate_name = \"${3}\"" - ], - "description": "Django CBV ``FormView``" - }, - "Django AdminView":{ - "prefix": "adminview", - "body": [ - "@admin.register($1)", - "class ${1:ModelName}Admin(admin.ModelAdmin):", - "\tlist_display = ${2:\"pk\",}", - "\tsearch_fields = ${3:\"pk\",}", - "\tlist_filter = ${4:\"FilterFields\",}" - ], - "description": "Django AdminView for ``admin.py``" - }, - "Django AdminTabularInline":{ - "prefix": "tabularinline", - "body": [ - "class ${1:ModelName}Inline(admin.TabularInline):", - "\tmodel = ${2:$1}", - "\tmin_num = ${4:0}", - "\tmax_num = ${4:8}", - "\textra = ${5:1}" - ], - "description": "Django TabularInline for ``admin.py``" - }, - "Django AdminStackedInline":{ - "prefix": "stackedinline", - "body": [ - "class ${1:ModelName}Inline(admin.StackedInline):", - "\tmodel = ${2:$1}", - "\tmin_num = ${4:0}", - "\tmax_num = ${4:8}", - "\textra = ${5:1}" - ], - "description": "Django StackedInline for ``admin.py``" - }, - - "Django Views get_context_data":{ - "prefix": "getcontextdata", - "body": [ - "def get_context_data(self, *args, **kwargs):", - "\tcontext = super().get_context_data(*args, **kwargs)", - "\treturn context" - ], - "description": "Django Views ``get_context_data`` method" - }, - "Django Views get_success_url":{ - "prefix": "getsuccessurl", - "body": [ - "def get_success_url(self):", - "\treturn reverse(\"${1:ViewName}\", kwargs={${2:\"pk\": self.get_object().pk}})" - ], - "description": "Django Views ``get_success_url`` method" - }, - "Django Views get_queryset":{ - "prefix": "getqueryset", - "body": [ - "def get_queryset(self):", - "\treturn ${1:ModelName}.objects.filter(${2})" - ], - "description": "Django Views ``get_queryset`` method" - }, - "Django Views get_object":{ - "prefix": "getobject", - "body": [ - "def get_object(self):", - "\treturn ${1:ModelName}.objects.get(${2})" - ], - "description": "Django Views ``get_object`` method" - }, - "Django Views form_valid":{ - "prefix": "formvalid", - "body": [ - "def form_valid(self, form):", - "\treturn super().form_valid(form)" - ], - "description": "Django Views ``form_valid`` method" - }, - "Django Views form_invalid":{ - "prefix": "forminvalid", - "body": [ - "def form_invalid(self, form):", - "\treturn super().form_invalid(form)" - ], - "description": "Django Views ``form_invalid`` method" - }, - "Django Views get_form_kwargs":{ - "prefix": "getformkwargs", - "body": [ - "def get_form_kwargs(self, form):", - "\tkwargs = super().get_form_kwargs()", - "\treturn kwargs" - ], - "description": "Django Views ``get_form_kwargs`` method" - }, - "Django Views dispatch":{ - "prefix": "dispatch", - "body": [ - "def dispatch(self, request, *args, **kwargs):", - "\treturn super().dispatch(request, *args, **kwargs)" - ], - "description": "Django Views ``dispatch`` method" - }, - "Django Views get_initial":{ - "prefix": "getinitial", - "body": [ - "def get_initial(self):", - "\tinit = super().get_initial()", - "\treturn init" - ], - "description": "Django Views ``get_initial`` method" - }, - "Django Views post":{ - "prefix": "post", - "body": [ - "def post(self, request, *args, **kwargs):", - "\treturn super().post(request, *args, **kwargs)" - ], - "description": "Django Views ``post`` method" - }, - "Django Views get":{ - "prefix": "get", - "body": [ - "def get(self, request, *args, **kwargs):", - "\treturn super().get(request, *args, **kwargs)" - ], - "description": "Django Views ``post`` method" - }, - - - "Django Forms field_clean":{ - "prefix": "cleanf", - "body": [ - "def clean_${1:FieldName}(self):", - "\t$1 = self.cleaned_data[\"$1\"]", - "\t${0}", - "\treturn $1" - ], - "description": "Django Views ``field_clean`` method" - }, - "Django Forms clean":{ - "prefix": "cleanff", - "body": [ - "def clean(self):", - "\tcleaned_data = super().clean()", - "\t${0}" - ], - "description": "Django Views ``clean`` method" - }, - - - "Django FBV Path":{ - "prefix": "fpath", - "body": "path(\"${1:Path}\", v.${2:View}, name=${0:PathName})", - "description": "Django Path For ``Function Based Views``" - }, - "Django CBV Path":{ - "prefix": "cpath", - "body": "path(\"${1:Path}\", v.${2:View}.as_viewJ(), name=${0:PathName})", - "description": "Django Path For ``Class Based Views``" - }, - "Django Path as Include":{ - "prefix": "ipath", - "body": "path(\"${1:Path}\", include(\"${2}.urls\", namespace=${0:Name})", - "description": "Django Path as ``Include``" - } -} diff --git a/snippets/frameworks/ejs.json b/snippets/frameworks/ejs.json deleted file mode 100644 index 477ecf5..0000000 --- a/snippets/frameworks/ejs.json +++ /dev/null @@ -1,87 +0,0 @@ -{ - "EJS No Output": { - "prefix": "ejs", - "body": [ - "<% $1 %> $2" - ], - "description": "EJS No Output" - }, - "EJS Output Value": { - "prefix": "ejsout", - "body": [ - "<%= $1 %> $2" - ], - "description": "EJS outputs no value" - }, - "EJS Output Escaped": { - "prefix": "ejsesc", - "body": [ - "<%- $1 %> $2" - ], - "description": "EJS outputs value" - }, - "EJS Comment": { - "prefix": "ejscom", - "body": [ - "<%# $1 %> $2" - ], - "description": "EJS comment tag with no output" - }, - "EJS Literal": { - "prefix": "ejslit", - "body": [ - "<%% $1 %> $2" - ], - "description": "EJS outputs a literal '<%'" - }, - "EJS Include": { - "prefix": "ejsinc", - "body": [ - "<% include $1 %> $2" - ], - "description": "EJS include statement" - }, - "EJS For Loop": { - "prefix": "ejsfor", - "body": [ - "<% for( let ${1:index} = 0; ${1:index} < ${2:array}.length; ${1:index}++ ) { %>", - "$3", - "<% } %>" - ], - "description": "EJS For Loop" - }, - "EJS ForEach": { - "prefix": "ejseach", - "body": [ - "<% ${1:array}.forEach(${2:element} => { %>", - " $3", - "<% }) %>" - ], - "description": "EJS ForEach Loop" - }, - "EJS If Statement": { - "prefix": "ejsif", - "body": [ - "<% if (${1:condition}) { %>", - " $2", - "<% } %>" - ], - "description": "EJS if statement" - }, - "EJS Else Statement": { - "prefix": "ejselse", - "body": [ - "<% } else { %>", - " $1" - ], - "description": "EJS if statement" - }, - "EJS Else If Statement": { - "prefix": "ejselif", - "body": [ - "<% } else if ({$1:condition}) { %>", - " $2" - ], - "description": "EJS if statement" - } -} diff --git a/snippets/frameworks/flutter.json b/snippets/frameworks/flutter.json deleted file mode 100644 index 594eeba..0000000 --- a/snippets/frameworks/flutter.json +++ /dev/null @@ -1,498 +0,0 @@ -{ - "Stateless Widget": { - "prefix": "statelessW", - "body": [ - "class ${1:name} extends StatelessWidget {", - " const ${1:name}({Key? key}) : super(key: key);\n", - " @override", - " Widget build(BuildContext context) {", - " return Container(", - " child: ${2:null},", - " );", - " }", - "}" - ], - "description": "Create a Stateless widget" - }, - "Stateful Widget": { - "prefix": "statefulW", - "body": [ - "class ${1:name} extends StatefulWidget {", - " ${1:name}({Key? key}) : super(key: key);\n", - " @override", - " _${1:WidgetName}State createState() => _${1:WidgetName}State();", - "}\n", - "class _${1:index}State extends State<${1:index}> {", - " @override", - " Widget build(BuildContext context) {", - " return Container(", - " child: ${2:null},", - " );", - " }", - "}" - ], - "description": "Create a Stateful widget" - }, - "Build Method": { - "prefix": "build", - "body": [ - "@override", - "Widget build(BuildContext context) {", - " return ${0:};", - "}" - ], - "description": "Describes the part of the user interface represented by this widget." - }, - "Custom Painter ": { - "prefix": "customPainter", - "body": [ - "class ${0:name}Painter extends CustomPainter {", - "", - " @override", - " void paint(Canvas canvas, Size size) {", - " }", - "", - " @override", - " bool shouldRepaint(${0:name}Painter oldDelegate) => false;", - "", - " @override", - " bool shouldRebuildSemantics(${0:name}Painter oldDelegate) => false;", - "}" - ], - "description": "Used for creating custom paint" - }, - "Custom Clipper ": { - "prefix": "customClipper", - "body": [ - "class ${0:name}Clipper extends CustomClipper {", - "", - " @override", - " Path getClip(Size size) {", - " }", - "", - " @override", - " bool shouldReclip(CustomClipper oldClipper) => false;", - "}" - ], - "description": "Used for creating custom shapes" - }, - "InitState ": { - "prefix": "initS", - "body": [ - "@override", - "void initState() { ", - " super.initState();", - " ${0:}", - "}" - ], - "description": "Called when this object is inserted into the tree. The framework will call this method exactly once for each State object it creates." - }, - "Dispose": { - "prefix": "dis", - "body": [ - "@override", - "void dispose() { ", - " ${0:}", - " super.dispose();", - "}" - ], - "description": "Called when this object is removed from the tree permanently. The framework calls this method when this State object will never build again." - }, - "Reassemble": { - "prefix": "reassemble", - "body": [ - "@override", - "void reassemble(){", - " super.reassemble();", - " ${0:}", - "}" - ], - "description": "Called whenever the application is reassembled during debugging, for example during hot reload." - }, - "didChangeDependencies": { - "prefix": "didChangeD", - "body": [ - "@override", - "void didChangeDependencies() {", - " super.didChangeDependencies();", - " ${0:}", - "}" - ], - "description": "Called when a dependency of this State object changes" - }, - "didUpdateWidget": { - "prefix": "didUpdateW", - "body": [ - "@override", - "void didUpdateWidget (${1:Type} ${2:oldWidget}) {", - " super.didUpdateWidget(${2:oldWidget});", - " ${0:}", - "}" - ], - "description": "Called whenever the widget configuration changes." - }, - "ListView.Builder": { - "prefix": "listViewB", - "body": [ - "ListView.builder(", - " itemCount: ${1:1},", - " itemBuilder: (BuildContext context, int index) {", - " return ${2:};", - " },", - ")," - ], - "description": "Creates a scrollable, linear array of widgets that are created on demand.Providing a non-null `itemCount` improves the ability of the [ListView] to estimate the maximum scroll extent." - }, - "ListView.Separated": { - "prefix": "listViewS", - "body": [ - "ListView.separated(", - " itemCount: ${1:1},", - " separatorBuilder: (BuildContext context, int index) {", - " return ${2:};", - " },", - " itemBuilder: (BuildContext context, int index) {", - " return ${3:};", - " },", - ")," - ], - "description": "Creates a fixed-length scrollable linear array of list 'items' separated by list item 'separators'." - }, - "GridView.Builder": { - "prefix": "gridViewB", - "body": [ - "GridView.builder(", - " gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(", - " crossAxisCount: ${1:2},", - " ),", - " itemCount: ${2:2},", - " itemBuilder: (BuildContext context, int index) {", - " return ${3:};", - " },", - ")," - ], - "description": "Creates a scrollable, 2D array of widgets that are created on demand. Providing a non-null `itemCount` improves the ability of the [GridView] to estimate the maximum scroll extent." - }, - "GridView.Count": { - "prefix": "gridViewC", - "body": [ - "GridView.count(", - " crossAxisSpacing: ${1:1},", - " mainAxisSpacing: ${2:2},", - " crossAxisCount: ${3:2},", - " children: [", - " ${4:}", - " ],", - ")," - ], - "description": "Creates a scrollable, 2D array of widgets with a fixed number of tiles in the cross axis." - }, - "GridView.Extent": { - "prefix": "gridViewE", - "body": [ - "GridView.extent(", - " maxCrossAxisExtent: ${1:2},", - " children: [", - " ${2:}", - " ],", - ")," - ], - "description": "Creates a scrollable, 2D array of widgets with tiles that each have a maximum cross-axis extent." - }, - "Custom Scroll View": { - "prefix": "customScrollV", - "body": [ - "CustomScrollView(", - " slivers: [", - " ${0:}", - " ],", - ")," - ], - "description": "Creates a `ScrollView` that creates custom scroll effects using slivers. If the `primary` argument is true, the `controller` must be null." - }, - "Stream Builder": { - "prefix": "streamBldr", - "body": [ - "StreamBuilder(", - " stream: ${1:stream},", - " initialData: ${2:initialData},", - " builder: (BuildContext context, AsyncSnapshot snapshot) {", - " return Container(", - " child: ${3:child},", - " );", - " },", - ")," - ], - "description": "Creates a new `StreamBuilder` that builds itself based on the latest snapshot of interaction with the specified `stream`" - }, - "Animated Builder": { - "prefix": "animatedBldr", - "body": [ - "AnimatedBuilder(", - " animation: ${1:animation},", - " child: ${2:child},", - " builder: (BuildContext context, Widget child) {", - " return ${3:};", - " },", - ")," - ], - "description": "Creates an Animated Builder. The widget specified to `child` is passed to the `builder` " - }, - "Stateful Builder": { - "prefix": "statefulBldr", - "body": [ - "StatefulBuilder(", - " builder: (BuildContext context, setState) {", - " return ${0:};", - " },", - ")," - ], - "description": "Creates a widget that both has state and delegates its build to a callback. Useful for rebuilding specific sections of the widget tree." - }, - "Orientation Builder": { - "prefix": "orientationBldr", - "body": [ - "OrientationBuilder(", - " builder: (BuildContext context, Orientation orientation) {", - " return Container(", - " child: ${3:child},", - " );", - " },", - ")," - ], - "description": "Creates a builder which allows for the orientation of the device to be specified and referenced" - }, - "Layout Builder": { - "prefix": "layoutBldr", - "body": [ - "LayoutBuilder(", - " builder: (BuildContext context, BoxConstraints constraints) {", - " return ${0:};", - " },", - ")," - ], - "description": "Similar to the Builder widget except that the framework calls the builder function at layout time and provides the parent widget's constraints." - }, - "Single Child ScrollView": { - "prefix": "singleChildSV", - "body": [ - "SingleChildScrollView(", - " controller: ${1:controller,}", - " child: Column(", - " ${0:}", - " ),", - ")," - ], - "description": "Creates a scroll view with a single child" - }, - "Future Builder": { - "prefix": "futureBldr", - "body": [ - "FutureBuilder(", - " future: ${1:Future},", - " initialData: ${2:InitialData},", - " builder: (BuildContext context, AsyncSnapshot snapshot) {", - " return ${3:};", - " },", - ")," - ], - "description": "Creates a Future Builder. This builds itself based on the latest snapshot of interaction with a Future." - }, - "No Such Method": { - "prefix": "nosm", - "body": [ - "@override", - "dynamic noSuchMethod(Invocation invocation) {", - " ${1:}", - "}" - ], - "description": "This method is invoked when a non-existent method or property is accessed." - }, - "Inherited Widget": { - "prefix": "inheritedW", - "body": [ - "class ${1:Name} extends InheritedWidget {", - " ${1:Name}({Key? key, required this.child}) : super(key: key, child: child);", - "", - " final Widget child;", - "", - " static ${1:Name}? of(BuildContext context) {", - " return context.dependOnInheritedWidgetOfExactType<${1:Name}>();", - " }", - "", - " @override", - " bool updateShouldNotify(${1:Name} oldWidget) {", - " return ${2:true};", - " }", - "}" - ], - "description": "Class used to propagate information down the widget tree" - }, - "Mounted": { - "prefix": "mounted", - "body": [ - "@override", - "bool get mounted {", - " ${0:}", - "}" - ], - "description": "Whether this State object is currently in a tree." - }, - "Sink": { - "prefix": "snk", - "body": [ - "Sink<${1:type}> get ${2:name} => _${2:name}Controller.sink;", - "final _${2:name}Controller = StreamController<${1:type}>();" - ], - "description": "A Sink is the input of a stream." - }, - "Stream": { - "prefix": "strm", - "body": [ - "Stream<${1:type}> get ${2:name} => _${2:name}Controller.stream;", - "final _${2:name}Controller = StreamController<${1:type}>();" - ], - "description": "A source of asynchronous data events. A stream can be of any data type " - }, - "Subject": { - "prefix": "subj", - "body": [ - "Stream<${1:type}> get ${2:name} => _${2:name}Subject.stream;", - "final _${2:name}Subject = BehaviorSubject<${1:type}>();" - ], - "description": "A BehaviorSubject is also a broadcast StreamController which returns an Observable rather than a Stream." - }, - "toString": { - "prefix": "toStr", - "body": [ - "@override", - "String toString() {", - "return ${1:toString};", - " }" - ], - "description": "Returns a string representation of this object." - }, - "debugPrint": { - "prefix": "debugP", - "body": [ - "debugPrint(${1:statement});" - ], - "description": "Prints a message to the console, which you can access using the flutter tool's `logs` command (flutter logs)." - }, - "Material Package": { - "prefix": "importM", - "body": "import 'package:flutter/material.dart';", - "description": "Import flutter material package" - }, - "Cupertino Package": { - "prefix": "importC", - "body": "import 'package:flutter/cupertino.dart';", - "description": "Import Flutter Cupertino package" - }, - "flutter_test Package": { - "prefix": "importFT", - "body": "import 'package:flutter_test/flutter_test.dart';", - "description": "Import flutter_test package" - }, - "Material App": { - "prefix": "mateapp", - "description": "Create a MaterialApp", - "body": [ - "import 'package:flutter/material.dart';", - " ", - "void main() => runApp(MyApp());", - " ", - "class MyApp extends StatelessWidget {", - " @override", - " Widget build(BuildContext context) {", - " return MaterialApp(", - " title: 'Material App',", - " home: Scaffold(", - " appBar: AppBar(", - " title: Text('Material App Bar'),", - " ),", - " body: Center(", - " child: Container(", - " child: Text('Hello World'),", - " ),", - " ),", - " ),", - " );", - " }", - "}" - ] - }, - "Cupertino App": { - "prefix": "cupeapp", - "description": "Create a CupertinoApp", - "body": [ - "import 'package:flutter/cupertino.dart';", - " ", - "void main() => runApp(MyApp());", - " ", - "class MyApp extends StatelessWidget {", - " @override", - " Widget build(BuildContext context) {", - " return CupertinoApp(", - " title: 'Cupertino App',", - " home: CupertinoPageScaffold(", - " navigationBar: CupertinoNavigationBar(", - " middle: Text('Cupertino App Bar'),", - " ),", - " child: Center(", - " child: Container(", - " child: Text('Hello World'),", - " ),", - " ),", - " ),", - " );", - " }", - "}" - ] - }, - "Tween Animation Builder": { - "prefix": "tweenAnimationBuilder", - "body": [ - "TweenAnimationBuilder(", - " duration: ${1:const Duration(),}", - " tween: ${2:Tween(),}", - " builder: (BuildContext context, ${3:dynamic} value, Widget? child) {", - " return ${4:Container();}", - " },", - " ), " - ], - "description": "Widget builder that animates a property of a Widget to a target value whenever the target value changes." - }, - "Value Listenable Builder": { - "prefix": "valueListenableBuilder", - "body": [ - "ValueListenableBuilder(", - " valueListenable: ${1: null},", - " builder: (BuildContext context, ${2:dynamic} value, Widget? child) {", - " return ${3: Container();}", - " },", - " )," - ], - "description": "Given a ValueListenable and a builder which builds widgets from concrete values of T, this class will automatically register itself as a listener of the ValueListenable and call the builder with updated values when the value changes." - }, - "Test": { - "prefix": "f-test", - "body": [ - "test(", - " \"${1:test description}\",", - " () {},", - ");" - ], - "description": "Create a test function" - }, - "Test Widgets": { - "prefix": "widgetTest", - "body": [ - "testWidgets(", - " \"${1:test description}\",", - " (WidgetTester tester) async {},", - ");" - ], - "description": "Create a testWidgets function" - } -} \ No newline at end of file diff --git a/snippets/frameworks/jekyll.json b/snippets/frameworks/jekyll.json deleted file mode 100644 index 9a11714..0000000 --- a/snippets/frameworks/jekyll.json +++ /dev/null @@ -1,526 +0,0 @@ -{ - "Show": { - "prefix": "show", - "description": "Output markup: {{ }}", - "body": "{{ $1 }}" - }, - - "Execute": { - "prefix": "execute", - "description": "Tag markup: {%- -%}", - "body": "{%- $1 -%}" - }, - - "Tag assign": { - "prefix": "assign", - "description": "Variable tag: assign", - "body": [ - "{%- assign ${variable} = ${value} -%}" - ] - }, - - "Tag break": { - "prefix": "break", - "description": "Iteration tag: break", - "body": [ - "{%- break -%}" - ] - }, - - "Tag capture": { - "prefix": "capture", - "description": "Variable tag: capture", - "body": [ - "{%- capture ${variable} -%}${code:}{%- endcapture -%}" - ] - }, - - "Tag case": { - "prefix": "case", - "description": "Control flow tag: case", - "body": [ - "{%- case ${variable} -%}", - "\t{%- when ${condition} -%}", - "\t\t${code1:}", - "\t{%- else -%}", - "\t\t${code2:}", - "{%- endcase -%}" - ] - }, - - "Tag comment": { - "prefix": "comment", - "description": "Control flow tag: case", - "body": [ - "{%- comment -%}${description:}{%- endcomment -%}" - ] - }, - - "Tag context variable": { - "prefix": "convar", - "description": "Context Variable", - "body": [ - "{{ ${variable:} }}" - ] - }, - - "Tag continue": { - "prefix": "continue", - "description": "Iteration tag: continue", - "body": [ - "{%- continue -%}" - ] - }, - - "Tag cycle": { - "prefix": "cycle", - "description": "Iteration tag: cycle", - "body": [ - "{%- cycle '${0:odd}', '${1:even}' -%}" - ] - }, - - "Tag collection directory": { - "prefix": "cdirp", - "description": "The full path to the collection's source direcotry", - "body": [ - "{{ site.${my_collection}.directory }}" - ] - }, - - "Tag collection relative path": { - "prefix": "crelp", - "description": "The path to the document's source file realtive to the site source", - "body": [ - "{{ site.collections.${my_collection}.relative_path }}" - ] - }, - - "Tag decrement": { - "prefix": "decrement", - "description": "Variable tag: decrement", - "body": [ - "{%- decrement ${variable} -%}" - ] - }, - - "Tag for": { - "prefix": "for", - "description": "Iteration tag: for", - "body": [ - "{%- for ${item} in ${collection} -%}", - "\t${code:}", - "{%- endfor -%}" - ] - }, - - "Tag increment": { - "prefix": "increment", - "description": "Variable tag: increment", - "body": [ - "{%- increment ${variable} -%}" - ] - }, - - "Tag if": { - "prefix": "if", - "description": "Control flow tag: if", - "body": [ - "{%- if ${condition} -%}", - "\t${code:}", - "{%- endif -%}" - ] - }, - - "Tag else": { - "prefix": "else", - "description": "Control flow tag: else", - "body": [ - "{%- else -%}" - ] - }, - - "Tag elsif": { - "prefix": "elsif", - "description": "Control flow tag: elsif", - "body": [ - "{%- elsif ${condition} -%}" - ] - }, - - "Tag if else": { - "prefix": "ifelse", - "description": "Control flow tag: if else", - "body": [ - "{%- if ${condition} -%}", - "\t${code1:}", - "{%- else -%}", - "\t${code2:}", - "{%- endif -%}" - ] - }, - - "Tag gist": { - "prefix": "gist", - "description": "Add a gist code block", - "body": [ - "{%- gist ${gist:user/gist-id} -%}" - ] - }, - - "Tag highlight": { - "prefix": "highlight", - "description": "Syntax tag: highlight", - "body": [ - "{%- highlight ${lang:javascript} -%}", - "\t\t${code:}", - "{%- endhighlight -%}" - ] - }, - - "Tag include": { - "prefix": "include", - "description": "Tag: include", - "body": [ - "{%- include ${snippet} -%}" - ] - }, - - "Site Vairable Date": { - "prefix": "date", - "description": "Tag: site.date", - "body": [ - "{{ site.date | date: '${format: %b %d, %Y}' }}" - ] - }, - - "Tag include relative": { - "prefix": "increl", - "description": "Tag: include relative", - "body": [ - "{%- include_relative '${file:}' -%}" - ] - }, - - "Tag Post URL": { - "prefix": "posturl", - "description": "Tag: post_url", - "body": [ - "{%- post_url ${url:} -%}" - ] - }, - - "Tag unless": { - "prefix": "unless", - "description": "Control flow tag: unless", - "body": [ - "{%- unless ${condition} -%}", - "\t${code:}", - "{%- endunless -%}" - ] - }, - - "Tag when": { - "prefix": "when", - "description": "Control flow tag: when", - "body": [ - "{%- when ${condition} -%}", - "${code:}" - ] - }, - - "Tag Option limit": { - "prefix": "limit", - "description": "For loops option", - "body": [ - "limit: ${limit:5}" - ] - }, - - "Tag Option offset": { - "prefix": "offset", - "description": "For loops option", - "body": [ - "offset: ${offset:0}" - ] - }, - - "Tag Option reversed": { - "prefix": "reversed", - "description": "For loops option", - "body": [ - "reversed" - ] - }, - - "Tag raw": { - "prefix": "raw", - "description": "Tag: raw", - "body": [ - "{%- raw -%}${code:}{%- endraw -%}" - ] - }, - - "Tag paginate next or previous page": { - "prefix": "paginate", - "description": "Tag: paginate next or previous page", - "body": [ - "{{ paginator.${next:previous}_page }}" - ] - }, - - "Filter jsonify": { - "prefix": "json", - "description": "Array filter: jsonify", - "body": "| jsonify }}'" - }, - - "Filter join": { - "prefix": "join", - "description": "Array filter: join", - "body": "| join: '${seperator:, }}'" - }, - - "Filter first": { - "prefix": "first", - "description": "Array filter: first", - "body": "| first" - }, - - "Filter last": { - "prefix": "last", - "description": "Array filter: last", - "body": "| last" - }, - - "Filter map": { - "prefix": "map", - "description": "Array filter: map", - "body": "| map: '${key}'" - }, - - "Filter size": { - "prefix": "size", - "description": "Array filter: size", - "body": "| size" - }, - - "Filter sort": { - "prefix": "sort", - "description": "Array filter: sort", - "body": "| sort" - }, - - "Filter uniq": { - "prefix": "uniq", - "description": "Array filter: uniq", - "body": "| uniq" - }, - - "Filter ceil": { - "prefix": "ceil", - "description": "Math filter: ceil", - "body": "| ceil" - }, - - "Filter divided by": { - "prefix": "divided_by", - "description": "Math filter: divided by", - "body": "| divided_by: ${divided_by:2}" - }, - - "Filter floor": { - "prefix": "floor", - "description": "Math filter: floor", - "body": "| floor" - }, - - "Filter minus": { - "prefix": "minus", - "description": "Math filter: minus", - "body": "| minus: ${minus:1}" - }, - - "Filter modulo": { - "prefix": "modulo", - "description": "Math filter: modulo", - "body": "| modulo: ${modulo:2}" - }, - - "Filter plus": { - "prefix": "plus", - "description": "Math filter: plus", - "body": "| plus: ${plus:1}" - }, - - "Filter round": { - "prefix": "round", - "description": "Math filter: round", - "body": "| round: ${round:0}" - }, - - "Filter times": { - "prefix": "times", - "description": "Math filter: times", - "body": "| times: ${times:1}" - }, - - "Filter append": { - "prefix": "append", - "description": "String filter: append", - "body": "| append: '${string}' }}" - }, - - "Filter capitalize": { - "prefix": "capitalize", - "description": "String filter: capitalize", - "body": "| capitalize }}" - }, - - "Filter downcase": { - "prefix": "downcase", - "description": "String filter: downcase", - "body": "| downcase }}" - }, - - "Filter escape": { - "prefix": "escape", - "description": "String filter: escape", - "body": "| escape }}" - }, - - "Filter markdownify": { - "prefix": "markdown", - "description": "String filter: markdownify", - "body": "| markdownify }}" - }, - - "Filter prepend": { - "prefix": "prepend", - "description": "String filter: prepend", - "body": "| prepend: '${string}' }}" - }, - - "Filter remove": { - "prefix": "remove", - "description": "String filter: remove", - "body": "| remove: '${string}' }}" - }, - - "Filter remove first": { - "prefix": "remove_first", - "description": "String filter: remove first", - "body": "| remove_first: '${string}' }}" - }, - - "Filter replace": { - "prefix": "replace", - "description": "String filter: replace", - "body": "| replace: '${target}', '${replace}' }}" - }, - - "Filter replace first": { - "prefix": "replace_first", - "description": "String filter: replace first", - "body": "| replace_first: '${target}', '${replace}' }}" - }, - - "Filter slice": { - "prefix": "slice", - "description": "String filter: slice", - "body": "| slice: ${from:0}, ${to:5} }}" - }, - - "Filter slice single character": { - "prefix": "slice_single", - "description": "String filter: slice with single parameter", - "body": "| slice: ${at} }}" - }, - - "Filter split": { - "prefix": "split", - "description": "String filter: split", - "body": "| split: '${splitter:,}' }}" - }, - - "Filter strip": { - "prefix": "strip", - "description": "String filter: strip", - "body": "| strip }}" - }, - - "Filter lstrip": { - "prefix": "lstrip", - "description": "String filter: lstrip", - "body": "| lstrip }}" - }, - - "Filter rstrip": { - "prefix": "rstrip", - "description": "String filter: rstrip", - "body": "| rstrip }}" - }, - - "Filter strip html": { - "prefix": "strip_html", - "description": "String filter: strip html", - "body": "| strip_html }}" - }, - - "Filter strip newlines": { - "prefix": "strip_newlines", - "description": "String filter: strip newlines", - "body": "| strip_newlines }}" - }, - - "Filter truncate": { - "prefix": "truncate", - "description": "String filter: truncate", - "body": "| truncate: ${length:20}, '${ellipsis:...}' }}" - }, - - "Filter truncatewords": { - "prefix": "truncatewords", - "description": "String filter: truncatewords", - "body": "| truncatewords: ${length:5}, '${ellipsis:...}' }}" - }, - - "Filter upcase": { - "prefix": "upcase", - "description": "String filter: upcase }}", - "body": "| upcase }}" - }, - - "Filter url encode": { - "prefix": "url_encode", - "description": "String filter: url encode", - "body": "| url_encode }}" - }, - - "Filter uri escape": { - "prefix": "uri_escape", - "description": "String filter: uri escape", - "body": "| uri_escape }}" - }, - - "Filter xml escape": { - "prefix": "xml_escape", - "description": "String filter: xml escape", - "body": "| xml_escape }}" - }, - - "Front Matter": { - "prefix": "fm", - "description": "Add front matter", - "body": [ - "---", - "layout: ${layout:default}", - "title: ${title}", - "categories: ${category}", - "permalink: ${path}", - "tags: ${tag}", - "excerpt: ${description}", - "---" - ] - } -} diff --git a/snippets/frameworks/rails.json b/snippets/frameworks/rails.json deleted file mode 100644 index db095a9..0000000 --- a/snippets/frameworks/rails.json +++ /dev/null @@ -1,294 +0,0 @@ -{ - "Before action": { - "prefix": "ba", - "body": [ - "before_action :${0:method}" - ], - "description": "before_action" - }, - "Before validation": { - "prefix": "bv", - "body": [ - "before_validation :${0:method}" - ], - "description": "before_validation" - }, - "Before create": { - "prefix": "bc", - "body": [ - "before_create :${0:method}" - ], - "description": "before_create" - }, - "Before update": { - "prefix": "bu", - "body": [ - "before_update :${0:method}" - ], - "description": "before_update" - }, - "Before save": { - "prefix": "bs", - "body": [ - "before_save :${0:method}" - ], - "description": "before_save" - }, - "Before destroy": { - "prefix": "bd", - "body": [ - "before_destroy :${0:method}" - ], - "description": "before_destroy" - }, - "After create": { - "prefix": "ac", - "body": [ - "after_create :${0:method}" - ], - "description": "after_create" - }, - "After validation": { - "prefix": "av", - "body": [ - "after_validation :${0:method}" - ], - "description": "after_validation" - }, - " update": { - "prefix": "au", - "body": [ - "after_update :${0:method}" - ], - "description": "after_update" - }, - " save": { - "prefix": "as", - "body": [ - "after_save :${0:method}" - ], - "description": "after_create" - }, - " destroy": { - "prefix": "ad", - "body": [ - "after_destroy :${0:method}" - ], - "description": "after_destroy" - }, - "Belongs to": { - "prefix": "bt", - "body": [ - "belongs_to :${0:association}" - ], - "description": "belongs_to assocation" - }, - "Belongs to polymorphic": { - "prefix": "btp", - "body": [ - "belongs_to :${0:association}, polymorphic: true" - ], - "description": "belongs_to polymorphic assocation" - }, - "Create action": { - "prefix": "create", - "body": [ - "def create", - "\t@${1:model_class_name} = ${2:ModelClassName}.new($1_params)", - "\trespond_to do |format|", - "\t\tif @$1.save", - "\t\t\tformat.html { redirect_to @$1, notice: '$2 created' }", - "\t\telse", - "\t\t\tformat.html { render :new, status: :unprocessable_entity }", - "\t\tend", - "\tend", - "end" - ], - "description": "def create" - }, - "Destroy action": { - "prefix": "destroy", - "body": [ - "def destroy", - "\t@${1:model_class_name} = ${2:ModelClassName}.find(params[:id])", - "\t@$1.destroy!", - "\tredirect_to $1s_path, notice: '$2 removed'", - "end" - ], - "description": "def destroy" - }, - "Edit action": { - "prefix": "edit", - "body": [ - "def edit", - "\t@${1:model_class_name} = ${2:ModelClassName}.find(params[:id])", - "end" - ], - "description": "def edit" - }, - "Index action": { - "prefix": "index", - "body": [ - "def index", - "\t@${1:model_class_name} = ${2:ModelClassName}.all", - "end" - ], - "description": "def index" - }, - "New action": { - "prefix": "new", - "body": [ - "def new", - "\t@${1:model_class_name} = ${2:ModelClassName}.new", - "end" - ], - "description": "def new" - }, - "Show action": { - "prefix": "show", - "body": [ - "def show", - "\t@${1:model_class_name} = ${2:ModelClassName}.find(params[:id])", - "end" - ], - "description": "def show" - }, - "Update action": { - "prefix": "update", - "body": [ - "def update", - "\t@${1:model_class_name} = ${2:ModelClassName}.find(params[:id])", - "\trespond_to do |format|", - "\t\tif @$1.update($1_params)", - "\t\t\tformat.html { redirect_to @$1, notice: '$2 updated' }", - "\t\telse", - "\t\t\tformat.html { render :edit, status: :unprocessable_entity }", - "\t\tend", - "\tend", - "end" - ], - "description": "def update" - }, - "Model Params": { - "prefix": "params", - "body": [ - "def ${1:model_class_name}_params", - "\tparams.require(:$1).permit(${2:attributes})", - "end" - ], - "description": "def model_params" - }, - "Getting Params": { - "prefix": "pa", - "body": [ - "params[:${1:id}]" - ], - "description": "getting params using attribute" - }, - "Delegate to": { - "prefix": "dt", - "body": [ - "delegate: :${1:method}, to: :${0:object}" - ], - "description": "delegate to" - }, - "Delegate to with prefix": { - "prefix": "dtp", - "body": [ - "delegate: :${1:method}, to: :${2:object}, prefix: :${3:prefix}, allow_nil: ${0:allow_nil}" - ], - "description": "delegate to" - }, - "Scope": { - "prefix": "scope", - "body": [ - "scope :${1:name}, -> { where(${2:field}: ${0:value}) }" - ], - "description": "AR scope" - }, - "Validate presence": { - "prefix": "vp", - "body": [ - "validates :${1:attribute}, presence: true" - ], - "description": "validates presence" - }, - "Validate uniqueness": { - "prefix": "vu", - "body": [ - "validates :${1:attribute}, uniqueness: true" - ], - "description": "validates presence" - }, - "Migration add column": { - "prefix": "mac", - "body": [ - "add_column :${1:table_name}, :${2:column_name}, :${0:data_type}" - ], - "description": "Migration add column" - }, - "Migration add index": { - "prefix": "mai", - "body": [ - "add_index :${1:table_name}, :${0:column_name}" - ], - "description": "Migration add index" - }, - "Migration remove column": { - "prefix": "mrc", - "body": [ - "remove_column :${1:table_name}, :${0:column_name}" - ], - "description": "Migration remove column" - }, - "Migration rename column": { - "prefix": "mrnc", - "body": [ - "rename_column :${1:table_name}, :${2:old_column_name}, :${0:new_column_name}" - ], - "description": "Migration rename column" - }, - "Migration change column": { - "prefix": "mcc", - "body": [ - "change_column :${1:table_name}, :${2:old_column_name}, :${0:data_type}" - ], - "description": "Migration change column" - }, - "Has many dependent": { - "prefix": "hmd", - "body": [ - "has_many :${1:object}, dependent: :${0:destroy}" - ], - "description": "has_many dependent" - }, - "Has many": { - "prefix": "hm", - "body": [ - "has_many :${0:object}" - ], - "description": "has_many association" - }, - "Has many through": { - "prefix": "hmt", - "body": [ - "has_many :${1:object}, through: :${0:object}" - ], - "description": "has_many through association" - }, - "Has one": { - "prefix": "ho", - "body": [ - "has_one :${0:object}" - ], - "description": "has_one association" - }, - "Has one dependent": { - "prefix": "hod", - "body": [ - "has_one :${1:object}, dependent: :${0:destroy}" - ], - "description": "has_one dependent" - } -} - diff --git a/snippets/frameworks/twig.json b/snippets/frameworks/twig.json deleted file mode 100644 index b9a7469..0000000 --- a/snippets/frameworks/twig.json +++ /dev/null @@ -1,536 +0,0 @@ -{ - "asset": { - "prefix": "asset", - "body": - "{% set asset = ${1:entry.assetFieldHandle}.one() %}\n\n{% if asset %}\n\t\"{{\n{% endif %}", - "description": "asset" - }, - "assets": { - "prefix": "assets", - "body": - "{% for image in craft.assets.\n\t.sourceId(\"${1:1}\")\n\t.kind(\"${2:image}\")\n\t.limit(${3:10})\n}).all() %}\n\t\"{{\n{% endfor %}\n$0", - "description": "craft.assets" - }, - "autoescape": { - "prefix": "autoescape", - "body": "{% autoescape \"${1:type}\" %}\n\t$0\n{% endautoescape %}", - "description": "autoescape" - }, - "blockb": { - "prefix": "blockb", - "body": "{% block ${1:name} %}\n\t$0\n{% endblock %}", - "description": "block (block)" - }, - "block": { - "prefix": "block", - "body": "{% block ${1:name} %}$0{% endblock %}", - "description": "block" - }, - "blockf": { - "prefix": "blockf", - "body": "{{ block(\"${1:name}\") }}$0", - "description": "blockf" - }, - "cache": { - "prefix": "cache", - "body": "{% cache %}\n\t$1\n{% endcache %}\n$0", - "description": "cache" - }, - "case": { - "prefix": "case", - "body": "{% case \"${1:value}\" %}\n\t$0", - "description": "case" - }, - "children": { - "prefix": "children", - "body": "{% children %}$0", - "description": "children" - }, - "ceil": { - "prefix": "ceil", - "body": "ceil($1)$0", - "description": "ceil" - }, - "assetso": { - "prefix": "assetso", - "body": - "{% set assets = craft.assets({\n\tsourceId: \"${1:1}\",\n\tkind: \"${2:image}\",\n\tlimit: ${3:10}\n}).all() %}\n\n{% for image in assets %}\n\t\"{{\n{% endfor %}\n$0", - "description": "craft.assets - object syntax" - }, - "categorieso": { - "prefix": "categorieso", - "body": - "{% set categories = craft.categories({\n\tgroup: \"${1:categoryGroupHandle}\",\n\tlimit: \"${2:11}\"\n}).all() %}\n\n
", - "description": "craft.categories - object syntax" - }, - "categories": { - "prefix": "categories", - "body": - "
    \n\t{% nav category in craft.categories\n\t\t.group(\"${1:categoryGroupHandle}\")\n\t\t.limit(${2:11})\n\t\t.all()\n\t%}\n\t\t
  • \n\t\t\t{{ category.title }}\n\t\t\t{% ifchildren %}\n\t\t\t\t
      \n\t\t\t\t\t{% children %}\n\t\t\t\t
    \n\t\t\t{% endifchildren %}\n\t\t
  • \n\t{% endnav %}\n
", - "description": "craft.categories" - }, - "entrieso": { - "prefix": "entrieso", - "body": - "{% set entries = craft.entries({\n\tsection: \"${1:sectionName}\",\n\tlimit: \"${2:10}\"\n}).all() %}\n\n{% for entry in entries %}\n\t{{ entry.title }}\n{% endfor %}\n$0", - "description": "craft.entries - object syntax" - }, - "entries": { - "prefix": "entries", - "body": - "{% for entry in craft.entries\n\t.section(\"${1:sectionName}\")\n\t.limit(${2:10})\n\t.all()\n%}\n\t{{ entry.title }}\n{% endfor %}\n$0", - "description": "craft.entries" - }, - "t": { - "prefix": "t", - "body": "{{ $1 | t }}$0", - "description": "translate with | t" - }, - "replace": { - "prefix": "replace", - "body": "{{ ${1:$TM_SELECTED_TEXT} | replace(\"search\", \"replace\") }}$0", - "description": "replace with | replace(\"search\", \"replace\")" - }, - "replacex": { - "prefix": "replacex", - "body": - "{{ ${1:$TM_SELECTED_TEXT} | replace(\"/(search)/i\", \"replace\") }}$0", - "description": "replace regex with | replace(\"/(search)/i\", \"replace\")" - }, - "split": { - "prefix": "split", - "body": "{{ ${1:$TM_SELECTED_TEXT} | split(\"\\n\") }}$0", - "description": "split on | split (\"\\n\")" - }, - "tagso": { - "prefix": "tagso", - "body": - "{% set tags = craft.tags({\n\tgroup: \"${1:tagGroupHandle}\"\n}).all() %}\n\n
    \n\t{% for tag in tags %}\n\t\t
  • {{ tag }}
  • \n\t{% endfor %}\n
\n$0", - "description": "craft.tags - object syntax" - }, - "tags": { - "prefix": "tags", - "body": - "
    \n\t{% for tag in craft.tags.group(\"${1:tagGroupHandle}\").all() %}\n\t\t
  • {{ tag }}
  • \n\t{% endfor %}\n
\n$0", - "description": "craft.tags" - }, - "userso": { - "prefix": "userso", - "body": - "{% set users = craft.users({\n\tgroup: \"${1:userGroupHandle}\"\n}).all() %}\n\n{% for user in users %}\n\t{{ user.firstName }} {{ user.lastName }}\n{% endfor %}\n$0", - "description": "craft.users - object syntax" - }, - "users": { - "prefix": "users", - "body": - "{% for user in craft.users.group(\"${1:userGroupHandle}\").all() %}\n\t{{ user.firstName }} {{ user.lastName }}\n{% endfor %}\n$0", - "description": "craft.users" - }, - "csrf": { - "prefix": "csrf", - "body": "{{ csrfInput() }}\n$0", - "description": "csrf" - }, - "dd": { - "prefix": "dd", - "body": "
\n\t{{ dump($1) }}\n
\n{% exit %}$0", - "description": "dump and die" - }, - "do": { - "prefix": "do", - "body": "{% do $1 %}$0", - "description": "do" - }, - "dojs": { - "prefix": "dojs", - "body": "{% do view.registerJsFile \"${1:url}\" %}$0", - "description": "do js" - }, - "docss": { - "prefix": "docss", - "body": "{% do view.registerCssFile \"${1:url}\" %}$0", - "description": "do css" - }, - "dump": { - "prefix": "dump", - "body": "
\n\t{{ dump($1) }}\n
", - "description": "dump" - }, - "else": { - "prefix": "else", - "body": "{% else %}\n\t$0", - "description": "else" - }, - "embed": { - "prefix": "embed", - "body": "{% embed \"${1:template}\" %}\n\t$0\n{% endembed %}", - "description": "embed" - }, - "endautoescape": { - "prefix": "endautoescape", - "body": "{% endautoescape %}$0", - "description": "endautoescape" - }, - "endblock": { - "prefix": "endblock", - "body": "{% endblock %}$0", - "description": "endblock" - }, - "endcache": { - "prefix": "endcache", - "body": "{% endcache %}$0", - "description": "endcache" - }, - "endembed": { - "prefix": "endembed", - "body": "{% endembed %}$0", - "description": "endembed" - }, - "endfilter": { - "prefix": "endfilter", - "body": "{% endfilter %}$0", - "description": "endfilter" - }, - "endfor": { - "prefix": "endfor", - "body": "{% endfor %}$0", - "description": "endfor" - }, - "endif": { - "prefix": "endif", - "body": "{% endif %}$0", - "description": "endif" - }, - "endifchildren": { - "prefix": "endifchildren", - "body": "{% endifchildren %}$0", - "description": "endifchildren" - }, - "endcss": { - "prefix": "endcss", - "body": "{% endcss %}$0", - "description": "endcss" - }, - "endjs": { - "prefix": "endjs", - "body": "{% endjs %}$0", - "description": "endjs" - }, - "endmacro": { - "prefix": "endmacro", - "body": "{% endmacro %}$0", - "description": "endmacro" - }, - "endnav": { - "prefix": "endnav", - "body": "{% endnav %}$0", - "description": "endnav" - }, - "endset": { - "prefix": "endset", - "body": "{% endset %}$0", - "description": "endset" - }, - "endspaceless": { - "prefix": "endspaceless", - "body": "{% endspaceless %}$0", - "description": "endspaceless" - }, - "endswitch": { - "prefix": "endswitch", - "body": "{% endswitch %}$0", - "description": "endswitch" - }, - "endtrans": { - "prefix": "endtrans", - "body": "{% endtrans %}$0", - "description": "endtrans" - }, - "endverbatim": { - "prefix": "endverbatim", - "body": "{% endverbatim %}$0", - "description": "endverbatim" - }, - "exit": { - "prefix": "exit", - "body": "{% exit ${1:404} %}", - "description": "exit" - }, - "extends": { - "prefix": "extends", - "body": "{% extends \"${1:template}\" %}$0", - "description": "extends" - }, - "filterb": { - "prefix": "filterb", - "body": "{% filter ${1:name} %}\n\t$0\n{% endfilter %}", - "description": "filter (block)" - }, - "filter": { - "prefix": "filter", - "body": "{% filter ${1:name} %}$0{% endfilter %}", - "description": "filter" - }, - "floor": { - "prefix": "floor", - "body": "floor($1)$0", - "description": "floor" - }, - "fore": { - "prefix": "fore", - "body": - "{% for ${1:item} in ${2:items} %}\n\t$3\n{% else %}\n\t$0\n{% endfor %}", - "description": "for ... else" - }, - "for": { - "prefix": "for", - "body": "{% for ${1:item} in ${2:items} %}\n\t$0\n{% endfor %}", - "description": "for" - }, - "from": { - "prefix": "from", - "body": "{% from \"${1:template}\" import \"${2:macro}\" %}$0", - "description": "from" - }, - "endbody": { - "prefix": "endbody", - "body": "{{ endBody() }}\n$0", - "description": "endBody" - }, - "head": { - "prefix": "head", - "body": "{{ head() }}\n$0", - "description": "head" - }, - "if": { - "prefix": "if", - "body": "{% if ${1:condition} %}$2{% endif %}\n$0", - "description": "if" - }, - "ifb": { - "prefix": "ifb", - "body": "{% if ${1:condition} %}\n\t$0\n{% endif %}", - "description": "if (block)" - }, - "ife": { - "prefix": "ife", - "body": "{% if ${1:condition} %}\n\t$2\n{% else %}\n\t$0\n{% endif %}", - "description": "if ... else" - }, - "if1": { - "prefix": "if", - "body": "{% if ${1:condition} %}$0{% endif %}", - "description": "if" - }, - "ifchildren": { - "prefix": "ifchildren", - "body": "{% ifchildren %}\n\t$1\n{% endifchildren %}\n$0", - "description": "ifchildren" - }, - "import": { - "prefix": "import", - "body": "{% import \"${1:template}\" as ${2:name} %}$0", - "description": "import" - }, - "importself": { - "prefix": "importself", - "body": "{% import _self as ${1:name} %}$0", - "description": "importself" - }, - "inckv": { - "prefix": "inckv", - "body": - "{% include \"${1:template}\" with {\n\t${2:key}: ${3:\"${4:value}\"}\n} %}\n$0", - "description": "include w/ key/value" - }, - "include": { - "prefix": "include", - "body": "{% include \"${1:template}\" %}$0", - "description": "include" - }, - "inc": { - "prefix": "inc", - "body": "{% include \"${1:template}\" %}$0", - "description": "inc" - }, - "incp": { - "prefix": "incp", - "body": "{% include \"${1:template}\"${2: with ${3:params} }%}$0", - "description": "include w/ params" - }, - "css1": { - "prefix": "css", - "body": "{% do view.registerCssFile(\"${1:/resources/css/global.css}\") %}\n$0", - "description": "registerCssFile" - }, - "js": { - "prefix": "js", - "body": "{% js %}\n\t$1\n{% endjs %}\n$0", - "description": "js" - }, - "js1": { - "prefix": "js", - "body": "{% do view.registerJsFile(\"${1:/resources/js/global.js}\") %}\n$0", - "description": "registerJsFile" - }, - "css": { - "prefix": "css", - "body": "{% css %}\n\t$1\n{% endcss %}\n$0", - "description": "css" - }, - "macro": { - "prefix": "macro", - "body": "{% macro ${1:name}(${2:params}) %}\n\t$0\n{% endmacro %}", - "description": "macro" - }, - "matrix": { - "prefix": "matrix", - "body": - "{% for block in ${1:entry.matrixFieldHandle}.all() %}\n\n\t{% if block.type == \"${2:blockHandle}\" %}\n\t\t{{ block.${3:fieldHandle} }}\n\t{% endif %}\n\n\t{% if block.type == \"${4:blockHandle}\" %}\n\t\t{{ block.${5:fieldHandle} }}\n\t{% endif %}\n\n{% endfor %}\n$0", - "description": "matrix" - }, - "matrixif": { - "prefix": "matrixif", - "body": - "{% for block in ${1:entry.matrixFieldHandle}.all() %}\n\n\t{% if block.type == \"${2:blockHandle}\" %}\n\t\t{{ block.${3:fieldHandle} }}\n\t{% endif %}\n\n\t{% if block.type == \"${4:blockHandle}\" %}\n\t\t{{ block.${5:fieldHandle} }}\n\t{% endif %}\n\n{% endfor %}\n$0", - "description": "matrixif" - }, - "matrixifelse": { - "prefix": "matrixifelse", - "body": - "{% for block in ${1:entry.matrixFieldHandle}.all() %}\n\n\t{% if block.type == \"${2:blockHandle}\" %}\n\n\t\t{{ block.${3:fieldHandle} }}\n\n\t{% elseif block.type == \"${4:blockHandle}\" %}\n\n\t\t$0\n\t\n\t{% endif %}\n\n{% endfor %}", - "description": "matrixifelse" - }, - "matrixswitch": { - "prefix": "matrixswitch", - "body": - "{% for block in ${1:entry.matrixFieldHandle}.all() %}\n\n\t{% switch block.type %}\n\n\t\t{% case \"${2:blockHandle}\" %}\n\n\t\t\t{{ block.${3:fieldHandle} }}\n\n\t\t{% case \"${4:blockHandle}\" %}\n\n\t\t\t$0\n\n\t{% endswitch %}\n\n{% endfor %}", - "description": "matrixswitch" - }, - "max": { - "prefix": "max", - "body": "max(${1:$2, $3})$0", - "description": "max" - }, - "min": { - "prefix": "min", - "body": "min(${1:$2, $3})$0", - "description": "min" - }, - "nav": { - "prefix": "nav", - "body": "{% nav ${1:item} in ${2:items} %}\n\t$3\n{% endnav %}\n$0", - "description": "nav" - }, - "paginate": { - "prefix": "paginate", - "body": - "{% paginate ${1:elements} as ${2:pageInfo}, ${3:pageEntries} %}\n\n{% for item in ${3:pageEntries} %}\n\t$0\n{% endfor %}\n\n{% if ${2:pageInfo}.prevUrl %}Previous Page{% endif %}\n{% if ${2:pageInfo}.nextUrl %}Next Page{% endif %}", - "description": "paginate simple" - }, - "paginate1": { - "prefix": "paginate", - "body": - "{# PAGINATION\n\t\t\nFor this pagination to work properly, we need to be sure to set\nthe paginateBase variable in the template we are including the \npagination in.\n\n{% set paginateBase = \"/blog/p\" %}\n#}\n\n{% if pageInfo.totalPages > 1 %}\n
    \n\t{% if pageInfo.currentPage != \"1\" %}\n\t\t
  • First Page
  • \n\t{% endif %}\n\n\t{% if pageInfo.prevUrl %}\n\t\t
  • Previous Page
  • \n\t{% endif %}\n\n\t{% for pageNumber in 1..pageInfo.totalPages %}\n\t\t
  • \n\t\t\t{{ pageNumber }}\n\t\t
  • \n\t{% endfor %}\n\n\t{% if pageInfo.nextUrl %}\n\t\t
  • Next Page
  • \n\t{% endif %}\n\n\t{% if pageInfo.currentPage != pageInfo.total %}\n\t\t
  • Last Page
  • \n\t{% endif %}\n
\n{% endif %}\n$0", - "description": "paginate advanced" - }, - "redirect": { - "prefix": "redirect", - "body": - "{% redirect \"${1:template/path or http://straightupcraft.com}\" %}\n$0", - "description": "redirect" - }, - "getparam": { - "prefix": "getparam", - "body": - "craft.app.request.getParam(${1:\"Query String or Post Variable Name\"})\n$0", - "description": "request getParam" - }, - "getbodyparam": { - "prefix": "getbodyparam", - "body": "craft.app.request.getBodyParam(${1:\"postVariableName\"})\n$0", - "description": "request getBodyParam" - }, - "getqueryparam": { - "prefix": "getqueryparam", - "body": "craft.app.request.getQueryParam(${1:\"queryStringName\"})\n$0", - "description": "request getQueryParam" - }, - "getsegment": { - "prefix": "getsegment", - "body": "craft.app.request.getSegment(${1:2})\n$0", - "description": "request getSegment" - }, - "requirelogin": { - "prefix": "requirelogin", - "body": "{% requireLogin %}\n$0", - "description": "requireLogin" - }, - "requirepermission": { - "prefix": "requirepermission", - "body": "{% requirePermission \"${1:spendTheNight}\" %}\n$0", - "description": "requirePermission" - }, - "round": { - "prefix": "round", - "body": "{{ $1 | round(1, 'floor') }}$0", - "description": "round" - }, - "setb": { - "prefix": "setb", - "body": "{% set ${1:var} %}\n\t$0\n{% endset %}", - "description": "set (block)" - }, - "set": { - "prefix": "set", - "body": "{% set ${1:var} = ${2:value} %}$0", - "description": "set" - }, - "shuffle": { - "prefix": "shuffle", - "body": "shuffle($1)$0", - "description": "shuffle" - }, - "random": { - "prefix": "random", - "body": "random($1)$0", - "description": "random" - }, - "spaceless": { - "prefix": "spaceless", - "body": "{% spaceless %}\n\t$0\n{% endspaceless %}", - "description": "spaceless" - }, - "switch": { - "prefix": "switch", - "body": - "{% switch ${1:variable} %}\n\n\t{% case \"${2:value1}\" %}\n\t\n\n\t{% case \"${3:value2}\" %}\n\t\n\n\t{% default %}\n\t\n\n{% endswitch %}\n$0", - "description": "switch" - }, - "trans": { - "prefix": "trans", - "body": "{% trans %}$0{% endtrans %}", - "description": "trans" - }, - "urla": { - "prefix": "urla", - "body": - "url(\"${1:path}\", ${2:{foo:\"1\", bar:\"2\"\\}}, ${3:\"http\"}, ${4:false})$0", - "description": "url w/ arguments" - }, - "url": { - "prefix": "url", - "body": "url(\"${1:path}\")$0", - "description": "url" - }, - "use": { - "prefix": "use", - "body": "{% use \"${1:template}\" %}$0", - "description": "use" - }, - "verbatim": { - "prefix": "verbatim", - "body": "{% verbatim %}\n\t$0\n{% endverbatim %}", - "description": "verbatim" - } -} diff --git a/snippets/frameworks/vue/html.json b/snippets/frameworks/vue/html.json deleted file mode 100644 index 9cb50ff..0000000 --- a/snippets/frameworks/vue/html.json +++ /dev/null @@ -1,397 +0,0 @@ -{ - "template": { - "prefix": "template", - "body": [ - "" - ], - "description": "template element" - }, - "v-text": { - "prefix": "vText", - "body": [ - "v-text=\"${1:msg}\"" - ], - "description": "Expects: string. Updates the element’s textContent." - }, - "v-html": { - "prefix": "vHtml", - "body": [ - "v-html=\"${1:html}\"" - ], - "description": "Expects: string. Updates the element’s innerHTML." - }, - "v-show": { - "prefix": "vShow", - "body": [ - "v-show=\"${1:condition}\"" - ], - "description": "Expects: any" - }, - "v-if": { - "prefix": "vIf", - "body": [ - "v-if=\"${1:condition}\"" - ], - "description": "Expects: any" - }, - "v-else": { - "prefix": "vElse", - "body": [ - "v-else" - ], - "description": "Does not expect expression. previous sibling element must have v-if or v-else-if." - }, - "v-else-if": { - "prefix": "vElseIf", - "body": [ - "v-else-if=\"${1:condition}\"" - ], - "description": "Expects: any. previous sibling element must have v-if or v-else-if." - }, - "v-for-without-key": { - "prefix": "vForWithoutKey", - "body": [ - "v-for=\"${1:item} in ${2:items}\"" - ], - "description": "Expects: Array | Object | number | string" - }, - "v-for": { - "prefix": "vFor", - "body": [ - "v-for=\"(${1:item}, ${2:index}) in ${3:items}\" :key=\"${4:index}\"" - ], - "description": "Expects: Array | Object | number | string" - }, - "v-on": { - "prefix": "vOn", - "body": [ - "v-on:${1:event}=\"${2:handle}\"" - ], - "description": "Expects: Function | Inline Statement" - }, - "v-bind": { - "prefix": "vBind", - "body": [ - "v-bind$1=\"${2}\"" - ], - "description": "Expects: any (with argument) | Object (without argument)" - }, - "v-model": { - "prefix": "vModel", - "body": [ - "v-model=\"${1:something}\"" - ], - "description": "Expects: varies based on value of form inputs element or output of components" - }, - "v-slot": { - "prefix": "vSlot", - "body": [ - "v-slot$1=\"${2}\"" - ], - "description": "Expects: JavaScript expression that is valid in a function argument position (supports destructuring in supported environments). Optional - only needed if expecting props to be passed to the slot." - }, - "v-pre": { - "prefix": "vPre", - "body": [ - "v-pre" - ], - "description": "Does not expect expression" - }, - "v-cloak": { - "prefix": "vCloak", - "body": [ - "v-cloak" - ], - "description": "Does not expect expression" - }, - "v-once": { - "prefix": "vOnce", - "body": [ - "v-once" - ], - "description": "Does not expect expression" - }, - "key": { - "prefix": "key", - "body": [ - ":key=\"${1:key}\"" - ], - "description": "Expects: string. Children of the same common parent must have unique keys. Duplicate keys will cause render errors." - }, - "ref": { - "prefix": "ref", - "body": [ - "ref=\"${1:reference}\"$0" - ], - "description": "Expects: string. ref is used to register a reference to an element or a child component. The reference will be registered under the parent component’s $refs object. If used on a plain DOM element, the reference will be that element; if used on a child component, the reference will be component instance." - }, - "slotA": { - "prefix": "slotA", - "body": [ - "slot=\"$1\"$0" - ], - "description": "slot=''. Expects: string. Used on content inserted into child components to indicate which named slot the content belongs to." - }, - "slotE": { - "prefix": "slotE", - "body": [ - "$2$0" - ], - "description": ". Expects: string. Used on content inserted into child components to indicate which named slot the content belongs to." - }, - "slotScope": { - "prefix": "slotScope", - "body": [ - "slot-scope=\"$1\"$0" - ], - "description": "Used to denote an element or component as a scoped slot. The attribute’s value should be a valid JavaScript expression that can appear in the argument position of a function signature. This means in supported environments you can also use ES2015 destructuring in the expression. Serves as a replacement for scope in 2.5.0+." - }, - "scope": { - "prefix": "scope", - "body": [ - "scope=\"${1:this api replaced by slot-scope in 2.5.0+}\"$0" - ], - "description": "Used to denote a