Browse Source

feat: Added `user` modules + tutorial + example

my-config
connorgmeean 3 years ago
parent
commit
af69a951ba
  1. 3
      .gitignore
  2. 39
      README.md
  3. 3
      docs/api.md
  4. 67
      docs/modules.md
  5. 7
      lua/doom/core/config/init.lua
  6. 97
      lua/user/modules/char_counter/init.lua

3
.gitignore

@ -13,5 +13,8 @@ tags
contribute/doom-nvim-contrib
contribute/local-share-nvim
contribute/workspace
# User modules
user/modules/*
# Editor files
.luarc.json

39
README.md

@ -24,11 +24,11 @@
* [What is Doom Nvim?](#what-is-doom-nvim-)
* [Install](#install)
* [Configuring](#configuring)
+ [`modules.lua`](#-moduleslua-)
+ [Enabling features: `modules.lua`](#-moduleslua-)
- [What is a module?](#what-is-a-module-)
- [Enabing/disabling modules](#enabing-disabling-modules)
- [All modules](#all-modules)
+ [`config.lua`](#-configlua-)
+ [Configuring and personalising: `config.lua`](#-configlua-)
- [Modifying neovim and doom options](#modifying-neovim-and-doom-options)
* [Adding plugins](#adding-plugins)
* [Adding Keybinds](#adding-keybinds)
@ -44,15 +44,16 @@
Doom Nvim is a Neovim interpretation of the [doom-emacs](https://github.com/hlissner/doom-emacs) framework, adapted to Vim philosophy.
Its goal is to provide a configurable, extensible, performant and stable basis for any neovim configuration.
Our goal is to provide a configurable, extensible, performant and stable basis for any neovim configuration.
Some of the defining features that make this project unique are:
- **Fast** Rapid startup time without defer_fn, packages are lazy loaded and languages are only configured when opening the file type.
- **Fast** Rapid startup time without defer_fn, packages are lazy loaded and languages are only configured when opening its relevent file type.
- **Stable** Plugins are pinned to commit shas to avoid breaking between updates.
- **Scalable** Because of modular architecture you can disable any features you don't use. Your config is as simple or complex as you want it to be.
- **Configurable** All modules are 100% overridable and configurable, use a logical structure and have LSP completions.
- **Extensible** With a simple api you can easily add, and or contribute, your own modules.
- **Integrated** Desgined to handle and setup integrations between plugins for you. For example, whichkey will only show keybinds for
modules you have enabled (and will automatically handle your custom bindings).
- **Extensible** Take advantage of the modular architecture, enable only the features you need, customise or add your own modules.
## Install
@ -62,7 +63,7 @@ TODO: Add install docs here
Doom nvim is configured by enabling modules in the `modules.lua` file and then tweaking, overriding or adding new packages, keybinds and more within the `config.lua` module.
### `modules.lua`
### Enabling features: `modules.lua`
#### What is a module?
A module is a collection of packages, autocommands, keybinds and functions that add new capabilities or functionality to Doom Nvim.
@ -76,6 +77,7 @@ We organise modules into 3 categories:
You can enable or disable a module by going to `modules.lua` (`<leader>Dm`) and commenting or uncommenting the entry.
```lua
-- modules.lua
return {
features = {
'lsp'
@ -92,22 +94,18 @@ return {
#### All modules
Doom-nvim currently has 39 `features` modules and 14 `langs` modules. Some standout features are:
- `lsp` Code completions provided by `nvim-cmp`
- `linter` Formatting and linting provided by `null-ls.nvim`
- `whichkey` Interactive cheatsheet that integrates with our keybind management to **only show keybinds for modules you have active**
- `fidget` Shows LSP loading/indexing progress status
You can find a full list of modules (here)[#TODO: ].
Doom-nvim currently has 39 `features` modules and 14 `langs` modules.
You can find a full list of modules (here)[./docs/modules.md#all-modules]
### `config.lua`
### Configuring and personalising: `config.lua`
#### Modifying neovim and doom options
Doom nvim provides a number of config options, including wrapping some of vim's own options. See all available config options (here)[TODO:].
Doom nvim provides a number of config options, including wrapping some of vim's own options. See all available config options (in the API Reference)[./docs/api.md].
```lua
-- config.lua
doom.freeze_dependencies = false -- Don't use pinned packer dependencies
doom.logging = 'trace' -- Debug doom internal issues
doom.indent = 2 -- Sets vim.opt.shiftwith, vim.opt.softtabstop, vim.opt.tabstop to 2
@ -123,6 +121,8 @@ Additional packages can be imported with the `doom.use()` function.
This is a wrapper around `packer.use()` and provides the same API. [DOCS](https://github.com/wbthomason/packer.nvim#quickstart)
```lua
-- config.lua
-- Simple config
doom.use('sainnhe/sonokai', 'EdenEast/nightfox.nvim')
@ -140,6 +140,8 @@ Additional keybinds can be defined with the `doom.bind()` function.
This is a wrapper around a custom `nest.nvim` implementation and provides the same API. [DOCS](https://github.com/connorgmeehan/nest.nvim/tree/integrations-api#quickstart-guide)
```lua
-- config.lua
doom.bind({
{ '<leader>u', name = '+user', { -- Names this group in whichkey "+user"
{ 's', '<cmd>Telescope git_status<CR>', name = 'Git status' } -- Adds `<leader>us` keybind to trigger `Telescope git_status`
@ -154,6 +156,8 @@ doom.bind({
Additional autocommands can be defined with the `doom.autocmd()` function.
```lua
-- config.lua
doom.autcmd({
-- { "<event>", "<aupat>", "<command or function>"}
{ "FileType", "javascript", function() print('Yuck!') end}
@ -168,6 +172,7 @@ Here you can override the plugin git sources, pre-defined settings, keybinds or
```lua
-- modules.lua
return {
features = {
'whichkey' -- Whichkey module is enabled
@ -212,10 +217,6 @@ whichkey.configs["which-key.nvim"] = function ()
end
```
## FAQ
TODO: Add FAQ
## Contributing
For for information please see our [contributing docs](./docs/contributing.md).

3
docs/api.md

@ -0,0 +1,3 @@
# Doom API Reference
TODO: Autogenerate from config object.

67
docs/modules.md

@ -64,7 +64,7 @@ Modules are grouped into 3 categories:
- [`illuminate`](../lua/doom/modules/features/illuminate) Highlight other occurances of the hovered word
- [`indentlines`](../lua/doom/modules/features/indentlines) Explicitly show indentation
- [`range_highlight`](../lua/doom/modules/features/range_highlight) Highlight selected range as you type commands
- [`todo_comments`](../lua/doom/modules/features/todo_comments) Highlights TODO: comments and more
- [`todo_comments`](../lua/doom/modules/features/todo_comments) Highlights TODO comments and more
- **UI modules**
- [`fidget`](../lua/doom/modules/features/fidget) Shows LSP loading status
- [`tabline`](../lua/doom/modules/features/tabline) Tabbed buffer switcher
@ -241,7 +241,7 @@ module.autocmds = function()
end
```
## Implementing your own doom module
## Building your own module
I will use an example of implementing a module that counts the number of chars that you've typed.
This module will:
@ -253,21 +253,15 @@ This module will:
### 1. Setting up
> Modules are loaded from the `lua/doom/modules/` folder. Within this folder there is a `features/`, `langs/` and `core/` directory.
> If you look at [`modules.lua`](../modules.lua) you'll see that this maps 1:1 with the returned data structure (except for `core` modules which can't be disabled).
>
> Because modules are implemented as folders with an `init.lua` inside, they must be named after valid folder names.
> Best practices are:
> - Seperate words with an underscore, this is so the plugin can be represented as a lua variable
> - Name the module after the functionality rather than the plugin it uses.
>
> If you're adding language support, add a new folder module to `lua/doom/modules/langs/`, else if
> it's a new feature add a directory to `lua/doom/module/features/`.
For our example of adding char counting plugin I will add a folder called `lua/doom/modules/langs/char_counter/` and create a new `init.lua`
inside of it.
For our example of adding char counting plugin I will create a folder called `lua/user/modules/char_counter/`
and create a new `init.lua` inside of it.
```lua
-- lua/doom/modules/features/char_counter/init.lua
-- lua/user/modules/char_counter/init.lua
local char_counter = {}
return char_counter
@ -286,7 +280,7 @@ For our example we need to hook into the [InsertEnter](https://neovim.io/doc/use
and [InsertLeave](https://neovim.io/doc/user/autocmd.html#InsertLeave) auto commands.
```lua
-- lua/doom/modules/features/char_counter/init.lua
-- lua/user/modules/char_counter/init.lua
char_counter.autocmds = {
{ "InsertEnter", "*", function ()
print('Entered insert mode')
@ -299,6 +293,8 @@ char_counter.autocmds = {
### 3. Enabling and testing your module
Now you can enable the module in `modules.lua`! Once enabled, restart your doom-nvim instance and check
`:messages` to see if it's printing correctly.
@ -306,8 +302,15 @@ Now you can enable the module in `modules.lua`! Once enabled, restart your doom
-- modules.lua
return {
features = {
"char_counter" -- Must match the name of the folder i.e. `lua/doom/modules/features/char_counter`
}
...
},
langs = {
...
},
-- user field is optional and will read from the `lua/user/modules` folder in your `.nvim/` folder.
user = {
"char_counter" -- Must match the name of the folder i.e. `lua/user/modules/char_counter/init.lua`
},
}
```
@ -324,7 +327,7 @@ We will also check if the [`buftype`](https://neovim.io/doc/user/options.html#'b
means we wont count other interactive buffers like terminals, prompts or quick fix lists.
```lua
-- lua/doom/modules/features/char_counter/init.lua
-- lua/user/modules/char_counter/init.lua
local char_counter = {}
@ -371,7 +374,7 @@ Using the `module.cmds` property we can define and expose vim commands to the us
`:CountPrint` and `:CountReset` command.
```lua
-- lua/doom/modules/features/char_counter/init.lua
-- lua/user/modules/char_counter/init.lua
char_counter.cmds = {
{ "CountPrint", function ()
@ -390,12 +393,10 @@ Now restart doom nvim and run `:CountPrint` and `:CountReset` to test it out.
### 6. Adding keybinds
Keybinds are provided using the `module.binds` field. We use a modified [nest.nvim]() config that integrates with whichkey and nvim-mapper.
You can read more about it [here](https://github.com/connorgmeehan/nest.nvim/tree/integrations-api#quickstart-guide) but generally you should
provide the `name` field for all entries so it displays in whichkey.
Keybinds are provided using the `module.binds` field. We use a modified [nest.nvim]() config that integrates with whichkey and nvim-mapper. You can read more about it [here](https://github.com/connorgmeehan/nest.nvim/tree/integrations-api#quickstart-guide) but generally you should provide the `name` field for all entries so it displays in whichkey.
```lua
-- lua/doom/modules/features/char_counter/init.lua
-- lua/user/modules/char_counter/init.lua
char_counter.binds = {
{ '<leader>i', name = '+info', { -- Adds a new `whichkey` folder called `+info`
@ -416,7 +417,7 @@ In this example I will add [nui.nvim](https://github.com/MunifTanjim/nui.nvim) t
the user uses the `CountPrint` command.
```lua
-- lua/doom/modules/features/char_counter/init.lua
-- lua/user/modules/char_counter/init.lua
-- Add these two fields to `char_counter` at the top of the file.
char_counter.uses = {
@ -486,7 +487,7 @@ object. This will allow users to tweak the config in their `config.lua` file wi
```lua
-- lua/doom/modules/features/char_counter/init.lua
-- lua/user/modules/char_counter/init.lua
-- Copy the settings that are passed to the `Popup` function, place them in `char_counter.settings.popup`
char_counter.settings = {
@ -533,12 +534,30 @@ char_counter.cmds = {
}
```
### 9. You're done! Final output
### 9. Contributing your module upstream
> Builtin modules are loaded from the `lua/doom/modules/` folder. Within this folder there is a `features/`, `langs/` and `core/` directory.
> If you look at [`modules.lua`](../modules.lua) you'll see that the table fields are used to lookup the subfolder.
```lua
return {
features = {
"lsp" -- Maps to `lua/doom/modules/features/lsp/`,
},
langs = {
"lua" -- Maps to `lua/doom/modules/langs/lua/`
}
}
```
If you would like to contribute your module, just move it from `lua/user/modules/<module_name>` to
`lua/user/modules/<langs|features>/<module_name>` and create a PR in accordance with our [Contributing Guidelines](./contributing.md).
### 10. You're done! Final output
If you'd just like to look at the end result, or if you're comparing why your implementation didn't work, here is the final working output.
```lua
-- lua/doom/modules/features/char_counter/init.lua
-- lua/user/modules/char_counter/init.lua
local char_counter = {}
char_counter.settings = {

7
lua/doom/core/config/init.lua

@ -239,7 +239,12 @@ config.load = function()
for section_name, section_modules in pairs(all_modules) do
for _, module_name in pairs(section_modules) do
local ok, result = xpcall(require, debug.traceback, ("doom.modules.%s.%s"):format(section_name, module_name))
-- Special case for user folder, resolves to `lua/user/modules`
local root_folder = section_name == "user"
and "user.modules"
or ("doom.modules.%s"):format(section_name)
local ok, result = xpcall(require, debug.traceback, ("%s.%s"):format(root_folder, module_name))
if ok then
doom.modules[module_name] = result
else

97
lua/user/modules/char_counter/init.lua

@ -0,0 +1,97 @@
local char_counter = {}
char_counter.settings = {
popup = {
position = '50%',
size = {
width = 80,
height = 40,
},
border = {
padding = {
top = 2,
bottom = 2,
left = 3,
right = 3,
},
},
style = "rounded",
enter = true,
buf_options = {
modifiable = true,
readonly = true,
}
}
}
char_counter.uses = {
["nui.nvim"] = {
"MunifTanjim/nui.nvim",
cmd = { "CountPrint" },
}
}
char_counter.configs = {
["nui.nvim"] = function()
vim.notify("char_counter: nui.nvim loaded", "info")
end
}
char_counter._insert_enter_char_count = nil
char_counter._accumulated_difference = 0
char_counter._get_current_buffer_char_count = function()
local lines = vim.api.nvim_buf_line_count(0)
local chars = 0
for _, line in ipairs(vim.api.nvim_buf_get_lines(0, 0, lines, false)) do
chars = chars + #line
end
return chars
end
char_counter.autocmds = {
{ "InsertEnter", "*", function ()
-- Only operate on normal file buffers
print(("buftype: %s"):format(vim.bo.buftype))
if vim.bo.buftype == "" then
-- Store current char count
char_counter._insert_enter_char_count = char_counter._get_current_buffer_char_count()
end
end},
{ "InsertLeave", "*", function ()
-- Only operate on normal file buffers
if vim.bo.buftype == "" and char_counter._insert_enter_char_count then
-- Find the amount of chars added or removed
local new_count = char_counter._get_current_buffer_char_count()
local diff = new_count - char_counter._insert_enter_char_count
print(new_count, diff)
-- Add the difference to the accumulated total
char_counter._accumulated_difference = char_counter._accumulated_difference + diff
print(('Accumulated difference %s'):format(char_counter._accumulated_difference))
end
end},
}
char_counter.cmds = {
{ "CountPrint", function ()
local Popup = require('nui.popup')
local popup = Popup(char_counter.settings.popup)
popup:mount()
popup:map("n", "<esc>", function() popup:unmount() end)
local msg = ("char_counter: You have typed %s characters since I started counting."):format(char_counter._accumulated_difference)
vim.api.nvim_buf_set_lines(popup.bufnr, 0, 1, false, { msg })
end},
{ "CountReset", function ()
char_counter._accumulated_difference = 0
vim.notify("char_counter: Reset count!", "info")
end}
}
char_counter.binds = {
{ '<leader>i', name = '+info', { -- Adds a new `whichkey` folder called `+info`
{ 'c', '<cmd>:CountPrint<CR>', name = 'Print new chars' }, -- Binds `:CountPrint` to `<leader>ic`
{ 'r', '<cmd>:CountReset<CR>', name = 'Reset char count' } -- Binds `:CountPrint` to `<leader>ic`
} }
}
return char_counter
Loading…
Cancel
Save