down.lua
Intro
down.lua
is a simple ORM for Lua. It is designed to be simple to use and
Is it for you?
todo
Is it better than the alternatives?
todo
Other resources
About
Philosophy
Why?
I started down.lua
primarily due to my conflicting captivation and frustration with existing solutions like org-mode and, more recently in the burgeoning Neovim
ecosystem, neorg.
Comapare
To org-mode
To marksman
To neorg
Config
Setting up
Options
Commands
Autocommands
Keymaps
Basic Configuration
Advanced Configuration
Extending
Extending with plugins
inits
Extending keymaps
Extending with Autocommands
Modules
Example custom module
local down = require("down")
local mod, config, util = down.mod, down.config, down.util
local M = mod.create("user.example", {
--- @brief submodules
--- child directories containing
--- modules to load in tandem, relative
--- to this (parent) module.
--- "subexample",
--- "pre_example",
--- ...
})
M.setup = function()
return {
requires = {
---@brief required modules
--- modules from builtin or custom
--- modules that can be loaded in (same as
--- if calling `require 'module'`) as a dependency
--- for the module.
--- "ui.popup",
--- "edit.link",
--- "integration.treesitter",
--- ...
},
loaded = true,
}
end
---@class (exact) example.Config
M.config = {
--- @brief module config
--- the public facing config for this module that can be
--- set by the user from its default values here.
--- ...
}
---@class example.Data
M.data = {
--- @brief module data
--- the home of the module's internal data and methods
--- TODO: split up concerns
--- ...
}
M.load = function()
--- @brief module load
--- a set of functions to run whenever the
--- module is fist loaded upon startup.
--- TODO: maybe just merge in with setup()
--- ...
end
return M
Module Introduction
Examples of user custom modules
Example of a barebones module
---@brief Let's go through the most boilerplate, simple example of a module you may use.
---@brief This module will have no real functionality,
local mod = require "down.mod"
---@brief Let's say you want to create a module for Jupyter notebooks to run in Neovim.
---@brief We'll start by just creating a barebones module, with no functionality, just to show you how.
---@brief We will name this module "jupyter".
---@type down.Mod
local J = mod.create("jupyter", {
---@brief This is where we would automatically call any submodules underneath "jupyter" to be called in
---@brief simultaneously as it is loaded. Since we do not have any such submodules, we will leave this empty.
})
--[[ 1. Flow of functions:
+-------+ load mod +------------------+ +------+ +----------+
| setup |>----------->| cmds, opts, maps |>| load |>| postload |
+-------+ set data +------------------+ +------+ +----------+
--]]
---@brief This is where the module will first be `setup`. As you can see above, this occurs before a module has
---@brief fully loaded its data it needs to function. It may, however, perform important functionality during
---@brief this step, such as specifying dependencies it will need, setting up configuration, defining variables,
---@brief or even defining commands and autocommands that will invoke its functionality.
---@brief It must only return a table generally containing a confirmation it has loaded, as well as its
---@brief dependencies, except on rare occasions.
---@return down.mod.Setup
function J.setup()
---@class down.mod.Setup
return {
loaded = true,
---@brief For a jupyter module, we will likely need several dependencies, perhaps too many to list
---@brief through in such an early stage. Taking a guess, however, and knowing we can always change,
---@brief we'll just choose a few which we will likely need regardless.
requires = {
"data",
"workspace",
"data.code",
"ui.progress",
"ui.status",
"ui.notify",
"ui.vtext"
}
}
end
---@brief This is where we will set up the module's data and any methods it will call.
---@class down.jupyter.Data
J.data = {
---@brief One such piece of data you may wish to store is the ongoing collection of cells, as well
---@brief as their contents and type in the Juypyter notebook. You may even wish to leverage the
---@brief down.lua `lsp.notebook` module to hook into the LSP for Jupyter notebooks.
cells = {
},
---@brief To keep track of the notebook currently being interacted with
notebook = {
path = nil,
name = nil,
kernel = "python3",
}
}
---@brief Technically, we have now created a proper module that can be loaded into Neovim through down.lua.
---@brief However, we will be typically be best off at the beginning characterizing the module with any
---@brief setup, dependencies, configuration, commands, and even keymaps you believe it may one day need.
---@brief Each modue has a config table specified, which is where the user may set any configuration options
---@brief changing the behaviour of the module.
---@class down.jupyter.Config
---@field kernal string: The kernel to use for the Jupyter user interface. Default is `python3
J.config = {
---@brief The default directory you might want to specify for Jupyter notebooks to be stored in.
---@brief You may also wish to leverage the required "workspace" module to allow users to specify both
---@brief a specific workspace tey would like to associate with Jupyter notebooks, as well as a default
---@brief relative directory within that workspace.
---
---@brief Configuration details about created notebooks. While you are specifying default values here,
---@brief consider that a user will likely want to change several of the values.
notebook = {
default = "notebook.ipynb",
dir = {
workspace = "default",
default = "notes",
}
},
service = "jupyter",
command = "jupyterlab",
kernel = "python3",
kernels = {
"python3"
}
}
---@brief There are many more aspects to a module that can and should be defined as you begin to flesh it out,
---@brief even before you begin to test any major functionality. These include defining commands, options,
---@brief mappings, not to mention learning the interdependencies between your module and other modules,
---@brief whether builtin or custom-made by the community.
---
---@brief Regardless, I hope this has provided a good starting point to help you to take the very first steps
---@brief in creating an awesome module to extend and bless the down.lua ecosystem. Good luck and godspeed!
return J
Example custom module
Note that the below example is out of date and needs to be updated. Thanks!
local down = require("down")
local mod, config, util = down.mod, down.config, down.util
local M = mod.create("user.example", {
--- @brief submodules
--- child directories containing
--- modules to load in tandem, relative
--- to this (parent) module.
--- "subexample",
--- "pre_example",
--- ...
})
M.setup = function()
return {
requires = {
---@brief required modules
--- modules from builtin or custom
--- modules that can be loaded in (same as
--- if calling `require 'module'`) as a dependency
--- for the module.
--- "ui.popup",
--- "edit.link",
--- "integration.treesitter",
--- ...
},
loaded = true,
}
end
---@class (exact) example.Config
M.config = {
--- @brief module config
--- the public facing config for this module that can be
--- set by the user from its default values here.
--- ...
}
---@class example.Data
M.data = {
--- @brief module data
--- the home of the module's internal data and methods
--- TODO: split up concerns
--- ...
}
M.load = function()
--- @brief module load
--- a set of functions to run whenever the
--- module is fist loaded upon startup.
--- TODO: maybe just merge in with setup()
--- ...
end
return M
- See example.lua
---@brief Let's go through the most boilerplate, simple example of a module you may use. ---@brief This module will have no real functionality, local mod = require "down.mod"
---@brief Let's say you want to create a module for Jupyter notebooks to run in Neovim. ---@brief We'll start by just creating a barebones module, with no functionality, just to show you how. ---@brief We will name this module "jupyter". ---@type down.Mod local J = mod.create("jupyter", {
---@brief This is where we would automatically call any submodules underneath "jupyter" to be called in ---@brief simultaneously as it is loaded. Since we do not have any such submodules, we will leave this empty.
})
--[[ 1. Flow of functions:
+-------+ load mod +------------------+ +------+ +----------+
| setup |>----------->| cmds, opts, maps |>| load |>| postload |
+-------+ set data +------------------+ +------+ +----------+
--]]
---@brief This is where the module will first be setup
. As you can see above, this occurs before a module has
---@brief fully loaded its data it needs to function. It may, however, perform important functionality during
---@brief this step, such as specifying dependencies it will need, setting up configuration, defining variables,
---@brief or even defining commands and autocommands that will invoke its functionality.
---@brief It must only return a table generally containing a confirmation it has loaded, as well as its
---@brief dependencies, except on rare occasions.
---@return down.mod.Setup
function J.setup()
---@class down.mod.Setup
return {
loaded = true,
---@brief For a jupyter module, we will likely need several dependencies, perhaps too many to list
---@brief through in such an early stage. Taking a guess, however, and knowing we can always change,
---@brief we'll just choose a few which we will likely need regardless.
requires = {
"data",
"workspace",
"data.code",
"ui.progress",
"ui.status",
"ui.notify",
"ui.vtext"
}
}
end
---@brief This is where we will set up the module's data and any methods it will call. ---@class down.jupyter.Data J.data = {
---@brief One such piece of data you may wish to store is the ongoing collection of cells, as well
---@brief as their contents and type in the Juypyter notebook. You may even wish to leverage the
---@brief down.lua lsp.notebook
module to hook into the LSP for Jupyter notebooks.
cells = {
},
---@brief To keep track of the notebook currently being interacted with notebook = {
path = nil,
name = nil,
kernel = "python3",
}
}
---@brief Technically, we have now created a proper module that can be loaded into Neovim through down.lua. ---@brief However, we will be typically be best off at the beginning characterizing the module with any ---@brief setup, dependencies, configuration, commands, and even keymaps you believe it may one day need.
---@brief Each modue has a config table specified, which is where the user may set any configuration options ---@brief changing the behaviour of the module.
---@class down.jupyter.Config ---@field kernal string: The kernel to use for the Jupyter user interface. Default is `python3 J.config = {
---@brief The default directory you might want to specify for Jupyter notebooks to be stored in. ---@brief You may also wish to leverage the required "workspace" module to allow users to specify both ---@brief a specific workspace tey would like to associate with Jupyter notebooks, as well as a default ---@brief relative directory within that workspace.
---@brief Configuration details about created notebooks. While you are specifying default values here, ---@brief consider that a user will likely want to change several of the values. notebook = {
default = "notebook.ipynb",
dir = {
workspace = "default",
default = "notes",
}
},
service = "jupyter",
command = "jupyterlab",
kernel = "python3",
kernels = { "python3" }
}
---@brief There are many more aspects to a module that can and should be defined as you begin to flesh it out, ---@brief even before you begin to test any major functionality. These include defining commands, options, ---@brief mappings, not to mention learning the interdependencies between your module and other modules, ---@brief whether builtin or custom-made by the community.
---@brief Regardless, I hope this has provided a good starting point to help you to take the very first steps ---@brief in creating an awesome module to extend and bless the down.lua ecosystem. Good luck and godspeed! return J
-- TODO: do-over
--- @brief First, import the module class for type suggestions and checking local mod = require "down.mod"
---@brief Your first module will likely be a root (parentless) module.
--- Typically, a .
separates the name in the module name only if
--- it separates the parent module name (left) from the child (right).
--- However, you may choose to quickly
---@type word.Mod
local M = mod.create("user.mod", {
--- @brief submodules
--- child directories containing
--- modules to load in tandem, relative
--- to this (parent) module.
--- "subexample",
--- "pre_example",
--- ...
})
M.setup = function()
return {
requires = {
---@brief required modules
--- modules from builtin or custom
--- modules that can be loaded in (same as
--- if calling require 'module'
) as a dependency
--- for the module.
--- "ui.popup",
--- "edit.link",
--- "integration.treesitter",
--- ...
},
loaded = true,
}
end
---@class (exact) example.Config M.config = { --- @brief module config --- the public facing config for this module that can be --- set by the user from its default values here. --- ... }
---@class example.Data M.data = { --- @brief module data --- the home of the module's internal data and methods --- TODO: split up concerns --- ... }
M.load = function() --- @brief module load --- a set of functions to run whenever the --- module is fist loaded upon startup. --- TODO: maybe just merge in with setup() --- ... end
return M
Module quickstart
The core builtin module directory
Accurate as of December 15, 2024
Here is the full guide to all the modules, which I intend to keep largely perminantely in this arrangement so far as I can muster, and so far as it provides a good experience for everyone.
I will also not be changing the names to any of the modules, switching them around willy-nilly, etc., and especially not changing the name of the project, which is down.lua
, after its most recent overhaul.
This is a project in its extremely early days, so perhaps I may be laying this down too soon and without any real consequence, but I believe that the system, naming, etc. has congealed to the point where I can safely believe in the foundations it has laid.
[!Tip]
On a lighter note, working on this project for this long has been an incredible pleasure, and I hope I can impart some of the wonderful flights of fancy my mind would necessarily take when stumbling upon what I believed to be a great (at the moment, perhaps) idea. Building an extensible and dev-friendly environment like this, I hope this is something I can share!
The primary core modules are
Below, you will find a list of the primary root core modules builtin to down.lua
. There are a few things beyond the obvious that should be stated first:
-
While I have intended for all modules to be useful in their own right in a context not involving internal use, I do have to note that, like all things, there is a certain variance with regards how accessible a given builtin module is, as well as how much use it may serve to you. To that end, I have tried to begin scaffolding a per-module README.md that should (at some point) provide any others contributing or building on top of
down.lua
what they may and may not get out of the builtin modules here. -
The hierarchy of modules presented here is very important to understand, both with regards its structure and its purpose. This becomes especially important when considering the control flow of the setup process, both for the plugin as a whole and indeed to a lesser degree for the individual modules themselves. It can be easy to at first get lost in the weeds here, but I don't believe it is something that should hinder those exploring the codebase very long at all.
-
As you can see, nearly allo of the builtin base modules have a number of submodules. A creator of a module which has another module (builtin or external) as its parent may, with the ability to affect the code of the parent, the ability to choose whether the module shouuld be loaded in whenever the parent is loaded in, or to be specified by the user (or through other means: e.g. through configurations, dependencies, and other module interdependencies).
id | name | purpose | submodules | status |
---|---|---|---|---|
1 | cmd | provides the core logic to allow other moduless and users to create their own custom commands. | back , mod , rename , find | good! no changes anticipated at the moment besides a few possible refactors. |
2 | data | provides database and file-storage capabilities, through a variety of means and methods. | clipboard , code , dirs , encrypt , export , log , media , metadata , mod , save , sync , tag , template , time , todo | essential internally already, but will take time |
3 | edit | provides direct editing capabilities when interacting with files, and performs indirect analysis of files. | conceal , cursor , find , fold , hl , indent , rk inline , link , parse , syntax , toc , todo | essential internally already, but will take time |
4 | lsp | provides as much language-server-protocol-enabled functionality as possible without compromising rapidity. | command , completion , declaration , definition , document , implementation , moniker , notebook , refactor , reference , type , window , workspace | the lsp development process, not a surprise, will be a rather laborous endeavour |
5 | note | provides a journaling environment where notes can be created and leveraged in various powerful ways. | ... | while more will always be added, the note functionality is fortunately well under way |
5 | tool | provides interoperability with external tooling, enabling emergent possibilities. | blink , cmp , coq , dcmp , fzf , lualine , pandoc , telescope , treesitter , trouble | whie a few modules are well on their way, there are a few I'd like (blink, telescope, etc.) |
5 | ui | provides internal ui functionality, and may be leveraged by users or devs withing to expand their own environment. | calendar , chat , dashboard , icon , nav , popup , progress , prompt , render , sidebar , status , win | ui as a whole has not been an early priority, and it shows. |
5 | workspace | provides the core workspace or vault logic, keeping spaces compartmentalized appropriately. | ... | the workspace module has been without any issue thus far, although I would like to clean it up. |
5 | config | without configuration, will initalize a set of default modules most will use, but may be customized. | ... | Similarly, no problems with the ultra-simple config module, although I do wish to add meaningful options |
Accurate as of December 15, 2024
The full overview of the builtin modules
Hierarchy included!
The hierarchy of modules
...