# `failwind.nvim`: Plugins *Continuation of [[failwind.nvim - Introduction]] and [[failwind.nvim - Options]]* Here we come to the culmination of all the features of `failwind.nvim` - Declaratively installing and configuring Neovim plugins with CSS. All of the plugins are installed in a separate directory so they are isolated from the rest of the plugins you install (so removing failwind will not load any of the plugins or configuration from failwind). Configuring plugins revolves around adding different selectors to the `plugins {}` tag. Failwind supports several different mechanisms of configuring plugins. # Plugins: Simple In the simplest case, you can just add a plugin and point to the github repo where it is hosted by using a class selector of `repo` and the string value of the repository. This will install tpope's "vim-sleuth" plugin. The plugin requires no configuration or setup, and is automatically loaded. ```neovim {"update":true,"path":"_/code/1724250861251.css","timestamp":1725472561978} <pre> <span class="Tag"><span class="-type">plugins</span></span> <span class="Delimiter">{</span> <span class="Delimiter">:</span><span class="-type"><span class="PreProc"><span class="-property">repo</span></span></span><span class="Delimiter">(</span><span class="String">&quot;tpope/vim-sleuth&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span><span class="Delimiter">}</span> <span class="Delimiter">}</span> </pre> ``` ^1724250861251 On startup, failwind will download, install and add this plugin to your runtimepath. If you remove it from the list of plugins, it will no longer get loaded anymore! # Plugins: `setup` Some plugins have a `require('plugin').setup()` function that should get called to load the plugin. We can use the `setup` property to instruct failwind to call these functions at startup. ```neovim {"update":true,"path":"_/code/1724250884275.css","timestamp":1725472453205} <pre> <span class="Tag"><span class="-type">plugins</span></span> <span class="Delimiter">{</span> <span class="Delimiter">:</span><span class="-type"><span class="PreProc"><span class="-property">repo</span></span></span><span class="Delimiter">(</span><span class="String">&quot;echasnovski/mini.nvim&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="-property">setup</span><span class="Delimiter">:</span> <span class="String">&quot;mini.trailspace&quot;</span> <span class="String">&quot;mini.ai&quot;</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> </pre> ``` ^1724250884275 This example is equivalent to: ```neovim {"update":true,"path":"_/code/1724250900115.lua","timestamp":1725472452972} <pre> <span class="Comment">-- (installed mini.nvim somehow)</span><span class="-variable"><span class="-function-call-lua"> require</span></span><span class="-function-bracket">(</span><span class="String">&quot;mini.trailspace&quot;</span><span class="-function-bracket">)</span><span class="Delimiter">.</span><span class="-variable"><span class="-function-call-lua">setup</span></span><span class="-function-bracket">(</span><span class="-function-bracket">)</span><span class="-variable"><span class="-function-call-lua"> require</span></span><span class="-function-bracket">(</span><span class="String">&quot;mini.ai&quot;</span><span class="-function-bracket">)</span><span class="Delimiter">.</span><span class="-variable"><span class="-function-call-lua">setup</span></span><span class="-function-bracket">(</span><span class="-function-bracket">)</span> </pre> ``` ^1724250900115 This makes it very easy to add plugins that have a good default configuration. # Plugins: Custom Setup However, sometimes you want to override the default configuration. Fortunately, setup can also be called as a class selector to declare how failwind should load the plugin. ```neovim {"update":true,"path":"_/code/1724250913708.css","timestamp":1725472452741} <pre> <span class="Tag"><span class="-type">plugins</span></span> <span class="Delimiter">{</span> <span class="Delimiter">:</span><span class="-type"><span class="PreProc"><span class="-property">repo</span></span></span><span class="Delimiter">(</span><span class="String">&quot;lewis6991/gitsigns.nvim&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Delimiter">:</span><span class="-type"><span class="PreProc"><span class="-property">setup</span></span></span><span class="Delimiter">(</span><span class="String">&quot;gitsigns&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Tag"><span class="-type">signs</span></span> <span class="Delimiter">{</span> <span class="Tag"><span class="-type">add</span></span> <span class="Delimiter">{</span> <span class="-property">text</span><span class="Delimiter">:</span> <span class="String">'+'</span> <span class="Delimiter">}</span> <span class="Tag"><span class="-type">change</span></span> <span class="Delimiter">{</span> <span class="-property">text</span><span class="Delimiter">:</span> <span class="String">'~'</span> <span class="Delimiter">}</span> <span class="Tag"><span class="-type">delete</span></span> <span class="Delimiter">{</span> <span class="-property">text</span><span class="Delimiter">:</span> <span class="String">'_'</span> <span class="Delimiter">}</span> <span class="Tag"><span class="-type">topdelete</span></span> <span class="Delimiter">{</span> <span class="-property">text</span><span class="Delimiter">:</span> <span class="String">'‾'</span> <span class="Delimiter">}</span> <span class="Tag"><span class="-type">changedelete</span></span> <span class="Delimiter">{</span> <span class="-property">text</span><span class="Delimiter">:</span> <span class="String">'~'</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> </pre> ``` ^1724250913708 This example is equivalent to calling this at startup: ```neovim {"update":true,"path":"_/code/1724250930380.lua","timestamp":1725472452509} <pre> <span class="Comment">-- (install gitsigns somehow)</span><span class="-variable"><span class="-function-call-lua"> require</span></span><span class="-function-bracket">(</span><span class="String">&quot;gitsigns&quot;</span><span class="-function-bracket">)</span><span class="Delimiter">.</span><span class="-variable">setup</span><span class="Delimiter"> {</span> <span class="-variable">signs</span> <span class="Operator">=</span> <span class="Delimiter">{</span> <span class="-variable">add</span> <span class="Operator">=</span> <span class="Delimiter">{</span> <span class="-variable">text</span> <span class="Operator">=</span> <span class="String">&quot;+&quot;</span> <span class="Delimiter">}</span><span class="Delimiter">,</span> <span class="-variable">change</span> <span class="Operator">=</span> <span class="Delimiter">{</span> <span class="-variable">text</span> <span class="Operator">=</span> <span class="String">&quot;~&quot;</span> <span class="Delimiter">}</span><span class="Delimiter">,</span> <span class="-variable">delete</span> <span class="Operator">=</span> <span class="Delimiter">{</span> <span class="-variable">text</span> <span class="Operator">=</span> <span class="String">&quot;_&quot;</span> <span class="Delimiter">}</span><span class="Delimiter">,</span> <span class="-variable">topdelete</span> <span class="Operator">=</span> <span class="Delimiter">{</span> <span class="-variable">text</span> <span class="Operator">=</span> <span class="String">&quot;‾&quot;</span> <span class="Delimiter">}</span><span class="Delimiter">,</span> <span class="-variable">changedelete</span> <span class="Operator">=</span> <span class="Delimiter">{</span> <span class="-variable">text</span> <span class="Operator">=</span> <span class="String">&quot;~&quot;</span> <span class="Delimiter">}</span><span class="Delimiter">,</span> <span class="Delimiter">}</span><span class="Delimiter">,</span> <span class="Delimiter">}</span> </pre> ``` ^1724250930380 There are times where you don't want to call `setup()`, but instead want to run arbitrary code after the plugin has been loaded. For that we can use the `config` property (you'll notice here we use a `kebab-cased` name, "vim-cmd-colorscheme", which is translated into "vim.cmd.colorscheme" when called: this is just a fun feature I added since CSS doesn't have namespaced functions. So I just made them). Anyway, this sets the colorscheme to "tokyonight" on loading this plugin. ```neovim {"update":true,"path":"_/code/1724251514281.css","timestamp":1725472452267} <pre> <span class="Tag"><span class="-type">plugins</span></span> <span class="Delimiter">{</span> <span class="Delimiter">:</span><span class="-type"><span class="PreProc"><span class="-property">repo</span></span></span><span class="Delimiter">(</span><span class="String">&quot;folke/tokyonight.nvim&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="-property">config</span><span class="Delimiter">:</span> <span class="-function">vim-cmd-colorscheme</span><span class="Delimiter">(</span><span class="String">'tokyonight'</span><span class="Delimiter">)</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> </pre> ``` ^1724251514281 So it's equivalent to: ```neovim {"update":true,"path":"_/code/17242535451814.lua","timestamp":1725472452027} <pre> <span class="Comment">-- (somehow install tokyonight)</span><span class="Comment"> -- After loading the plugin</span><span class="-variable"> vim</span><span class="Delimiter">.</span><span class="-variable">cmd</span><span class="Delimiter">.</span><span class="-variable">colorscheme</span><span class="-function-bracket">(</span><span class="String">'tokyonight'</span><span class="-function-bracket">)</span> </pre> ``` ^1724253545181 # Plugins: Advanced Of course, it wouldn't be Neovim without overly complicated keymaps and a litany of custom functions that only I like and will fight to the death about them being OBJECTIVELY BETTER than whatever naming scheme other people come up with. In this example, you will see the use of the `depends` property, which will ensure that other plugins are installed as dependencies. There is another usage of the `setup` property, which calls the default setup function. And after that, you'll see a variety of different options for configuring keymaps related to the plugin - some even using syntax to execute lua that is embedded into the keymap! ```neovim {"update":true,"path":"_/code/17242535451813.css","timestamp":1725472451796} <pre> <span class="Tag"><span class="-type">plugins</span></span> <span class="Delimiter">{</span> <span class="Delimiter">:</span><span class="-type"><span class="PreProc"><span class="-property">repo</span></span></span><span class="Delimiter">(</span><span class="String">&quot;nvim-telescope/telescope.nvim&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="-property">depends</span><span class="Delimiter">:</span> <span class="String">&quot;nvim-lua/plenary.nvim&quot;</span><span class="Delimiter">;</span> <span class="-property">setup</span><span class="Delimiter">:</span> <span class="String">'telescope'</span><span class="Delimiter">;</span> <span class="Tag"><span class="-type">keymaps</span></span> <span class="Delimiter">{</span> <span class="Tag"><span class="-type">normal</span></span> <span class="Delimiter">{</span> <span class="Delimiter">:</span><span class="Tag">key</span><span class="Delimiter">(</span><span class="String">'&lt;leader&gt;sh'</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="-property">command</span><span class="Delimiter">:</span> <span class="String">&quot;Telescope help_tags&quot;</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:</span><span class="Tag">key</span><span class="Delimiter">(</span><span class="String">'&lt;leader&gt;sk'</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="-property">command</span><span class="Delimiter">:</span> <span class="String">&quot;Telescope keymaps&quot;</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:</span><span class="Tag">key</span><span class="Delimiter">(</span><span class="String">'&lt;leader&gt;sf'</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="-property">command</span><span class="Delimiter">:</span> <span class="String">&quot;Telescope find_files&quot;</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:</span><span class="Tag">key</span><span class="Delimiter">(</span><span class="String">'&lt;leader&gt;ss'</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="-property">command</span><span class="Delimiter">:</span> <span class="String">&quot;Telescope builtin&quot;</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:</span><span class="Tag">key</span><span class="Delimiter">(</span><span class="String">'&lt;leader&gt;sw'</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="-property">command</span><span class="Delimiter">:</span> <span class="String">&quot;Telescope grep_string&quot;</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:</span><span class="Tag">key</span><span class="Delimiter">(</span><span class="String">'&lt;leader&gt;sg'</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="-property">command</span><span class="Delimiter">:</span> <span class="String">&quot;Telescope live_grep&quot;</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:</span><span class="Tag">key</span><span class="Delimiter">(</span><span class="String">'&lt;leader&gt;sd'</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="-property">command</span><span class="Delimiter">:</span> <span class="String">&quot;Telescope diagnostics&quot;</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:</span><span class="Tag">key</span><span class="Delimiter">(</span><span class="String">'&lt;leader&gt;sr'</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="-property">command</span><span class="Delimiter">:</span> <span class="String">&quot;Telescope resume&quot;</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:</span><span class="Tag">key</span><span class="Delimiter">(</span><span class="String">'&lt;leader&gt;s.'</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="-property">command</span><span class="Delimiter">:</span> <span class="String">&quot;Telescope oldfiles&quot;</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:</span><span class="Tag">key</span><span class="Delimiter">(</span><span class="String">'&lt;leader&gt;&lt;leader&gt;'</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="-property">command</span><span class="Delimiter">:</span> <span class="String">&quot;Telescope buffers&quot;</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:</span><span class="Tag">key</span><span class="Delimiter">(</span><span class="String">'s/'</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="-property">desc</span><span class="Delimiter">:</span> <span class="String">&quot;Search in Open Files&quot;</span><span class="Delimiter">;</span> <span class="-keyword">@call</span> <span class="-function">require</span><span class="Delimiter">(</span><span class="String">'telescope.builtin'</span><span class="Delimiter">)</span><span class="Delimiter">.</span><span class="-type"><span class="-property">live_grep</span></span> <span class="Delimiter">{</span> <span class="-property">grep_open_files</span><span class="Delimiter">:</span> <span class="String">true</span><span class="Delimiter">;</span> <span class="-property">prompt_title</span><span class="Delimiter">:</span> <span class="String">&quot;Live Grep in Open Files&quot;</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> <span class="Delimiter">:</span><span class="Tag">key</span><span class="Delimiter">(</span><span class="String">'&lt;leader&gt;sn'</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="-property">desc</span><span class="Delimiter">:</span> <span class="String">&quot;Search Neovim Files&quot;</span><span class="Delimiter">;</span> <span class="-keyword">@call</span> <span class="-function">require</span><span class="Delimiter">(</span><span class="String">'telescope.builtin'</span><span class="Delimiter">)</span><span class="Delimiter">.</span><span class="-type"><span class="-property">find_files</span></span> <span class="Delimiter">{</span> <span class="-property">prompt_title</span><span class="Delimiter">:</span> <span class="String">&quot;Search Neovim DotFiles&quot;</span><span class="Delimiter">;</span> <span class="-property">cwd</span><span class="Delimiter">:</span> <span class="-function">vim-fn-stdpath</span><span class="Delimiter">(</span><span class="String">&quot;config&quot;</span><span class="Delimiter">)</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> </pre> ``` ^1724253545181 # Plugins: Groups The only thing different about this last plugin configuration is that instead of the selector describing a particular repository that is being configured, it creates a `group` that is being configured. The main benefit of this is to create a logical name and grouping for a related set of plugins where there is not one "parent" plugin - for example for LSP. The below example sets up the LSP, installation and basic configuration for Lua and Golang out of the box. Keymaps could be added as well to provide all of the regular LSP goodies that are included in a Neovim distribution or starter kit. ```neovim {"update":true,"path":"_/code/17242535451802.css","timestamp":1725472451569} <pre> <span class="Tag"><span class="-type">plugins</span></span> <span class="Delimiter">{</span> <span class="Tag"><span class="-type">lsp</span></span> <span class="Delimiter">{</span> <span class="-property">depends</span><span class="Delimiter">:</span> <span class="String">&quot;neovim/nvim-lspconfig&quot;</span> <span class="String">&quot;williamboman/mason.nvim&quot;</span> <span class="String">&quot;williamboman/mason-lspconfig.nvim&quot;</span> <span class="String">&quot;WhoIsSethDaniel/mason-tool-installer.nvim&quot;</span><span class="Delimiter">;</span> <span class="-property">setup</span><span class="Delimiter">:</span> <span class="String">&quot;mason&quot;</span> <span class="String">&quot;mason-lspconfig&quot;</span><span class="Delimiter">;</span> <span class="Delimiter">:</span><span class="-type"><span class="PreProc"><span class="-property">setup</span></span></span><span class="Delimiter">(</span><span class="String">&quot;mason-tool-installer&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="-property">automatic_installation</span><span class="Delimiter">:</span> <span class="String">true</span><span class="Delimiter">;</span> <span class="-property">ensure_installed</span><span class="Delimiter">:</span> <span class="Delimiter">[</span><span class="String">&quot;lua_ls&quot;</span><span class="Delimiter">,</span> <span class="String">&quot;gopls&quot;</span><span class="Delimiter">]</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:</span><span class="-type"><span class="PreProc"><span class="-property">config</span></span></span> <span class="Delimiter">{</span> <span class="-keyword">@call</span> <span class="-function">require</span><span class="Delimiter">(</span><span class="String">'mason-lspconfig'</span><span class="Delimiter">)</span><span class="Delimiter">.</span><span class="-type"><span class="-property">setup_handlers</span></span> <span class="Delimiter">{</span> <span class="-property">lua_ls</span><span class="Delimiter">:</span> <span class="-function">lua</span><span class="Delimiter">(</span><span class="String">'require(&quot;lspconfig&quot;).lua_ls.setup {}'</span><span class="Delimiter">)</span><span class="Delimiter">;</span> <span class="-property">gopls</span><span class="Delimiter">:</span> <span class="-function">lua</span><span class="Delimiter">(</span><span class="String">'require(&quot;lspconfig&quot;).gopls.setup {}'</span><span class="Delimiter">)</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> </pre> ``` ^1724253545180 # Plugins: Import It's 2024 now and managing your own plugin configuration and installation is a chore. With failwind.nvim, we can outsource that management to other people (just like tailwind outsources knowing things and learning css to other people). Using css's builtin `@import` syntax and feature queries, we can instruct failwind to: 1. Download the corresponding repo 2. Find the `init.css` from that repo 3. Parse and load the filtered configuration 4. Use that configuration in your own file. So, when we have something like this: ```neovim {"update":true,"path":"_/code/17242535451791.css","timestamp":1725472451340} <pre> <span class="-keyword">@import</span> <span class="-function">url</span><span class="Delimiter">(</span><span class="String">&quot;tjdevries/kickstart.css&quot;</span><span class="Delimiter">)</span> plugins<span class="Delimiter">;</span> </pre> ``` ^1724253545179 This will take all of the plugins in my `kickstart.css` project and include them into my own configuration! But, we can take this one step further. We can filter the plugins that we want to install by using a feature query. So if we pass a list of plugin and/or group names, we can filter out what items we want to install. ```neovim {"update":true,"path":"_/code/17242535451780.css","timestamp":1725472451123} <pre> <span class="-keyword">@import</span> <span class="-function">url</span><span class="Delimiter">(</span><span class="String">&quot;tjdevries/kickstart.css&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">(</span><span class="-property">plugins</span><span class="Delimiter">:</span> <span class="Delimiter">[</span> <span class="String">&quot;lewis6991/gitsigns.nvim&quot;</span> <span class="Tag">lsp</span> <span class="Delimiter">]</span><span class="Delimiter">)</span><span class="Delimiter">;</span> </pre> ``` ^1724253545178 In this example, we install **ONLY** `gitsigns` and the `lsp` configuration (all associated plugins) from my `kickstart.css` project. # Conclusion There's a few more goodies I'll write about for failwind, but I hope you enjoyed reading about plugin configuration and importing other plugin configuration directly into your own config with failwind. Feel free to drop a follow or reach out with any questions! :)