Skip to content

DrKJeff16/Jnvim

Repository files navigation

Jnvim

Table Of Contents

  1. About
  2. Requirements
  3. Structure
  4. Plugins
  5. The User API
  6. user_api.util
  7. user_api.opts
  8. user_api.check
  9. user_api.maps
    1. user_api.maps.keymap
    2. user_api.maps.wk
  10. user_api.highlight

About

This is a Nvim configuration, configured in a modular, obsessively documented, portable and platform-independent way. Typed documentation is included.

This configuration uses lazy.nvim as the default plugin manager. Please read the Plugins section to get an understanding of how this works.

This configuration has its core entirely dependant on the user_api module, which provides a customized API which includes module checking, type checking, highlighting functions, options setting, keymap functions, annotations, and more. For more info make sure to check the User API section.

Requirements

This config relies on essential plugins that improve the readability and understanding of how it works. For these to work, the following executables must be installed and in your $PATH:

Structure

/lua
├── config/  <==  Folder containing all Lua plugin configurations
│   ├── lazy.lua  <==  Plugin Installation. `plugin._spec` entry points are called here
│   └── util.lua  <==  Utilities used in the file above (env checks, etc.)
├── plugin/  <==   Plugins are configured in this directory
│   ├── _spec/  <==  Plugin categories are stored here in files serving as categories. `config.lazy` calls this  directory
│   │   ├── essentials.lua  <==  Essential plugins. TREAT THIS ONE WITH CARE
│   │   ├── colorschemes.lua  <==  Colorscheme plugins
│   │   ├── completion.lua  <==  Completion plugins
│   │   ├── editing.lua  <==  Editing enhancement plugins
│   │   ├── gui.lua  <==  GUI-related plugins
│   │   ├── lsp.lua  <==  LSP-related plugins
│   │   ├── neorg.lua  <==  Neorg-related plugins
│   │   ├── syntax.lua  <==  Syntax plugins
│   │   ├── telescope.lua  <==  Telescope-related plugins
│   │   ├── treesitter.lua  <==  Treesitter plugins
│   │   ├── ui.lua  <==  UI-related plugins
│   │   ├── utils.lua  <==  Utilities and other helpful plugins
│   │   └── vcs.lua  <==  Version Control plugins
│   ├── plugin1/  <==  Arbitrary plugin #1
│   │   └── submodule1.lua  <==  Extra module config
│   ├── plugin2/  <==  Arbitrary plugin #2
│   │   └── submodule1.lua  <==  Extra module config
│   │   └── submodule2.lua  <==  Extra module config
│   └── ...  <==   More plugin configs...
├── user_api.lua  <==  API entry points
├── user_api/  <==  User API module
│   ├── check.lua  <==  Entry points for `check/` are defined here
│   ├── check/  <==  Checker Functions
│   │   ├── exists.lua  <==  Existance checkers
│   │   └── value.lua  <==  Value checkers
│   ├── commands.lua  <==  User-defined commands
│   ├── config.lua  <==  Entry points for `config/` are defined here
│   ├── config/  <==  Configuration-related tools
│   │   ├── keymaps.lua  <==  `Keymap()` call
│   │   └── neovide.lua  <==  Neovide activation tools
│   ├── distro.lua  <==  Entry points for `distro/` are defined here
│   ├── distro/  <==  OS Utilities
│   │   ├── archlinux.lua  <==  Arch Linux utilities
│   │   └── termux.lua <==  Termux (Android) utilities
│   ├── highlight.lua  <==  Highlight Functions
│   ├── maps.lua  <==  Entry points for `maps/` are defined here
│   ├── maps/  <==  Mapping Utilities
│   │   ├── keymap.lua  <==  `vim.keymap.set` utilities
│   │   └── wk.lua  <==  `which_key` utilities (regardless if installed or not)
│   ├── opts.lua  <==  Entry points for `opts/` are defined here
│   ├── opts/  <==  Vim Option Utilities
│   │   ├── all_opts.lua  <==  Internal checking utility [DO NOT TOUCH]
│   │   └── config.lua  <==  Default options set here
│   ├── update.lua  <==  Update utilities
│   ├── util.lua  <==  Entry points for `util/` are defined here
│   ├── util/  <==  Misc Utils
│   │   ├── autocmd.lua  <==  Autocommand utilities
│   │   ├── notify.lua  <==  Notification utilities
└───└───└── string.lua  <==  String operators/pre-defined lists

Plugins

There's a lot of plugins included...

The plugins are installed based on the files in the lua/plugin/_spec/ directory. You can create your own category file or expand from the existant files in said directory. Just make sure to read the lazy.nvim documentation for more info on how to install plugins.

Some of the most important plugins used:


The User API

The user API can be found in lua/user_api. It provides a bunch of functionalities to give easier code structures and to simplify configuration. It's still at an experimental phase, but it works as-is.

user_api.opts

This submodule can be found at here. The options are defined in a default table to be processed by calling Opts().

To call the options:

local Opts1 = require('user_api.opts')
Opts1()
Opts1:setup_keys() -- Setup keymaps

--- Or by using the entry point:
local Opts2 = require('user_api').opts
Opts2()
Opts2:setup_keys() -- Setup keymaps

The setup() function optionally accepts a dictionary-like table with your own vim options. It overwrites some of the default options as defined in user_api.opts. MAKE SURE THEY CAN BE ACCEPTED BY vim.opt.

As an example:

local User = require('user_api')
local Opts = User.opts

Opts({
    completeopt = { 'menu', 'menuone', 'noselect', 'noinsert', 'preview' },
    nu = false, -- `:set nonumber`

    -- These equate to `:set tabstop=4 softtabstop=4 shiftwidth=4 expandtab`
    -- In the cmdline
    ts = 4,
    sts = 4,
    sw = 4,
    et = true,

    wrap = false,
})

user_api.check

This is the most important utility for this config. It currently provides a table with two sub-tables. Both used for many conditional checks, aswell as module handling.

These are the following:

  • user_api.check.value Used for value checking, differentiation and conditional code, aswell as for optional parameters in functions. It can be found in user_api/check/value.lua.

    Function description Parameter Types Return Type
    is_str Checks whether the input values are of string type.
    By default it checks for a single value,
    but can be told to check for multiple
    by setting the 2nd param as true.
    var: unknown|table, multiple: boolean (default: false) boolean
    is_num Checks whether the input values are of number type.
    By default it checks for a single value,
    but can be told to check for multiple
    by setting the 2nd param as true.
    var: unknown|table, multiple: boolean (default: false) boolean
    is_bool Checks whether the input values are of boolean type.
    By default it checks for a single value,
    but can be told to check for multiple
    by setting the 2nd param as true.
    var: unknown|table, multiple: boolean (default: false) boolean
    is_fun Checks whether the input values are of function type.
    By default it checks for a single value,
    but can be told to check for multiple
    by setting the 2nd param as true.
    var: unknown|table, multiple: boolean (default: false) boolean
    is_tbl Checks whether the input values are of table type.
    By default it checks for a single value,
    but can be told to check for multiple
    by setting the 2nd param as true.
    var: unknown|table, multiple: boolean (default: false) boolean
    is_int Checks whether the input values are integers.
    By default it checks for a single value,
    but can be told to check for multiple
    by setting the 2nd param as true.
    var: unknown|table, multiple: boolean (default: false) boolean
    empty If input is a string, checks for an empty string.
    If input is number, checks for value 0.
    If input is table, checks for an empty table.
    If other type return true.
    v: string|number|table boolean
    type_not_empty It essentially combines is_<type>() with empty() as
    both statements get used un conjuction a lot
    1. type_str: 'string'|'number'|'table'
    2. data: string|number|table
    boolean
  • user_api.check.exists Used for data existance checks, conditional module loading and fallback operations. It can be found in user_api/check/exists.lua.

    Function Description parameter types Return Type
    module Checks whether a require(...) statement is valid, given the input string mod: string boolean
    vim_exists Checks whether a string or multiple strings are true statements using the Vimscript exists() function.
    If a string array is given, check each string and if any string is invalid, return false. Otherwise return true when finished.
    expr: string|string[] boolean
    vim_has Checks whether a string or multiple are true statements when using the Vimscript has() function.
    If a string array is given, check each string and if any string is invalid, return false. Otherwise return true when finished.
    expr: string|string[] boolean
    vim_isdir Checks whether the string is a directory. path: string boolean
    executable Checks whether one or multiple strings are executables found in $PATH.
    If a string array is given, check each string and if any string is invalid and the fallback parameter is a function then execute the fallback function.
    This function will return the result regardless of whether fallback has been set or not.
    exe: string|string[], fallback: fun() (default: nil) boolean

user_api.maps

This module provides keymapping utilities in a more complete, extensible and (hopefully) smarter way for the end user.

There exists a maps.desc() method that returns an option table with a description field and other fields corresponding to each parameter.

--- Returns a `vim.keymap.set.Opts` table
---@param msg? string|'Unnamed Key' Defaults to `'Unnamed Key'`
---@param silent? boolean Defaults to `true`
---@param bufnr? integer|nil Not included in output table unless explicitly set
---@param noremap? boolean Defaults to `true`
---@param nowait? boolean Defaults to `true`
---@param expr? boolean Defaults to `false`
---@return vim.keymap.set.Opts
require('user_api.maps').desc(msg, silent, bufnr, noremap, nowait, expr)

The function returns this table:

-- DO NOT COPY THIS DIRECTLY
{
    ---@type string|'Unnamed Key'
    desc = msg or 'Unnamed Key', -- `'Unnamed Key'` is the fallback
    ---@type boolean
    silent = true or false, -- First option is the default
    ---@type boolean
    noremap = true or false, -- First option is the default
    ---@type boolean
    nowait = true or false, -- First option is the default
    ---@type boolean
    expr = false or true, -- First option is the default

    -- If buffer is passed as an argument:
    ---@type integer|nil
    buffer = nil or bufnr, -- First option is the default
}

user_api.maps.keymap

The maps.keymap module has the same function names for each mode:

  • maps.keymap.n(...): Same as :nmap
  • maps.keymap.i(...): Same as :imap
  • maps.keymap.v(...): Same as :vmap
  • maps.keymap.t(...): Same as :tmap
  • maps.keymap.o(...): Same as :omap
  • maps.keymap.x(...): Same as :xmap

user_api.maps.wk

The maps API also includes integration with which_key.nvim as user_api.maps.wk. It can be found found in user_api/maps.lua

This module creates mappings using custom-made functions that convert a specific type of mapping dictionary to a format compatible with which_key. To understand how this works refer to the aforementioned link to the which_key repository.

This module has the method wk.available(), which simply returns a boolean indicating whether which-key is installed and available to use. Use it, for example, to setup a fallback for setting keys, like in the following example:

local Keymap = require('user_api.maps.keymap')
local WK = require('user_api.maps.wk')

local my_keys = {
  --- Your maps go here...
}

if WK.available() then
  --- Use `WK`
else
  --- Use `Keymap`
end

If you try to use wk.register() despite not being available it'll return false and refuse to process your keymaps altogether.

If you want to convert a keymap table, you must first structure it as follows:

local desc = require('user_api.maps').desc

---This alias expands to `table<string, KeyMapRhsArr|RegKey|RegPfx>`
---@type AllMaps
local Keys1 = {
  ['lhs1'] = { 'rhs1', { desc('Keymap 1') } },
  ['lhs2'] = {
    function()
      vim.print('this is rhs2 and I\'m buffer-local!')
    end,
    desc('Keymap 1', 0),
  },
}

-- With modes
---@type AllModeMaps
local Keys2 = {
    -- Normal Mode Keys
    n = {
        ['n_lhs1'] = { 'n_rhs1', { desc = 'Keymap 1' } },
        ['n_lhs2'] = {
          function()
            vim.print('this is n_rhs2')
          end,
          { desc = 'Keymap 1', noremap = true } },
    },
    v = {
        ['v_lhs1'] = { 'v_rhs1', { desc = 'Keymap 1 (Visual Mode)' } },
    }
}

You can then pass this dictionary to user_api.maps.map_dict():

  • Example

    -- Following the code above...
    
    local map_dict = require('user_api.maps').map_dict
    
    -- NOTE: Third parameter is `false` because the `Keys1` table doesn't tell what mode to use
    map_dict(Keys1, 'wk.register', false, 'n')
    
    -- NOTE: Third parameter is `true` because the `Keys2` table tells us what modes to use,
    map_dict(Keys2, 'wk.register', true)
  • You can also process keymap groups the following way:

    ---@class RegPfx
    ---@field group string The map group name. Should look like `'+Group'`
    ---@field hidden? boolean Whether to show the map in `which-key`
    ---@field mode? MapModes
    
    ---@alias RegKeysNamed table<string, RegPfx>
    
    ---@type RegKeysNamed
    local Names = {
        ['<leader>X'] = { group = '+Group X' },
        ['<leader>X1'] = { group = '+Subgroup X1' },
    
        ['<leader>t'] = { group = '+Group t' },
    }
    
    -- If `which_key` is available
    if require('user_api.maps.wk').available() then
        require('user_api.maps').map_dict(Names, 'wk.register', false, 'n')
    end

This API component is in early design so it will be simpler and more complete in the future.


user_api.highlight

This module provides utilities for setting highlights in an easier way. It can be found in user_api/highlight.lua.

A description will be pending until further notice, i.e. when the module is structured in a satisfactory manner.