Compare commits

...

33 Commits
0.0.6 ... main

Author SHA1 Message Date
LeMarsu a4cc5d9b9c feat: can declare extra lua packages 2024-06-18 01:12:08 +02:00
LeMarsu b5a3526f8a chore: bump version 2024-06-10 01:14:35 +02:00
LeMarsu 23c9863c97 feat: add option init config object to generate `init.lua` 2024-06-10 01:08:56 +02:00
LeMarsu b6630684fb feat!: `init.lua` configuration is now a `mkNeovimPkg`'s option
BREAKING CHANGE: The init configuration has moved out of runtime
configuration. It is now in the mkNeovimPkg confuguration.
2024-06-10 01:08:50 +02:00
LeMarsu 815a099805 feat: runtime is now optional
as it should be according to docs...
2024-06-10 00:36:56 +02:00
LeMarsu 3d20bc0ade chore: add alejandra to nix shell 2024-06-09 04:01:18 +02:00
LeMarsu 182c7cd83d chore: bump version 2024-06-09 02:02:47 +02:00
LeMarsu af9565fa95 feat: introduce mkPluginsFromInputs function
This permit creation of plugin before declaration of dependencies. The
biggest benefit is using those on-the-fly plugins in dependencies.
2024-06-09 00:00:56 +02:00
LeMarsu 6c499b1441 fix: plugins with init are now loaded as they should be 2024-06-08 23:57:29 +02:00
LeMarsu cbd08e5258 chore: move back to flake-utils 2024-06-08 20:03:23 +02:00
LeMarsu b36722bfe6 chore: remove sourcesWith fn, using lib.fileset 2024-06-07 20:22:01 +02:00
LeMarsu 61381e2ba0 fix: init/config are loaded to on-the-fly build plugins 2024-06-07 16:20:46 +02:00
LeMarsu da637930bc feat: add describe subcommand 2024-06-05 02:47:46 +02:00
LeMarsu c20336ee60 refactor: filters are now fully dynamic 2024-06-05 02:02:57 +02:00
LeMarsu f50f314c98 feat: Sloth command has now completion 2024-06-05 01:54:41 +02:00
LeMarsu 459eadfae4 chore: bump version 2024-06-04 03:37:08 +02:00
LeMarsu ada07e10d6 chore: switch from nixpkgs `23.11` to `unstable` 2024-06-04 03:35:08 +02:00
LeMarsu f52525abd1 feat: can load lazy plugins on keymaps 2024-06-04 03:26:27 +02:00
LeMarsu 70484e221f feat: can load lazy plugins on events 2024-06-04 03:26:24 +02:00
LeMarsu eb11cfbe1a fix: Sloth list was broken since refactoring 2024-06-04 00:48:37 +02:00
LeMarsu 3d35555ef7 fix: move files instead of copying them
There was left over files in sloth-flake in the store.
2024-06-04 00:47:37 +02:00
LeMarsu cf036bd26c chore: bump version 2024-06-03 03:43:06 +02:00
LeMarsu 2eaecf17a0 fix: init function is called before plugin is loaded 2024-06-03 03:18:44 +02:00
LeMarsu 3732144c33 refactor: deps are now loaded via a FSM 2024-06-03 02:59:42 +02:00
LeMarsu a2bc77f229 refactor: deps provides accessors via metatables 2024-06-03 02:59:42 +02:00
LeMarsu 29e8841a3d refactor: split Sloth subcommands in their own files 2024-06-03 02:59:42 +02:00
LeMarsu ab361c86b4 refactor: extract Sloth command code in its own module 2024-06-03 02:59:42 +02:00
LeMarsu 3204b5a39d refactor: extract all dep logic in Dep object 2024-06-03 02:59:29 +02:00
LeMarsu 9cb43cfd1f flake.lock: Update
Flake lock file updates:

• Updated input 'nil':
    'github:oxalica/nil/2f3ed6348bbf1440fcd1ab0411271497a0fbbfa4' (2024-05-01)
  → 'github:oxalica/nil/ab3ddb8f063774cf7e22eb610f5ecfdb77309f3c' (2024-05-30)
• Updated input 'nil/nixpkgs':
    'github:nixos/nixpkgs/cf8cc1201be8bc71b7cbbbdaf349b22f4f99c7ae' (2024-04-28)
  → 'github:nixos/nixpkgs/ac82a513e55582291805d6f09d35b6d8b60637a1' (2024-05-29)
• Updated input 'nil/rust-overlay':
    'github:oxalica/rust-overlay/9ca720fdcf7865385ae3b93ecdf65f1a64cb475e' (2024-05-01)
  → 'github:oxalica/rust-overlay/095702e63a40e86f339d11864da9dc965b70a01e' (2024-05-30)
• Updated input 'nixpkgs':
    'github:nixos/nixpkgs/9d29cd266cebf80234c98dd0b87256b6be0af44e' (2024-05-25)
  → 'github:nixos/nixpkgs/25cf937a30bf0801447f6bf544fc7486c6309234' (2024-05-29)
2024-05-31 18:19:05 +02:00
LeMarsu a396afc2c4 feat: add `vimdiffAlias` and `nvimdiffAlias` mkNeovimPkg options 2024-05-31 02:56:27 +02:00
LeMarsu 359462b075 feat: add `viAlias` and `vimAlias` mkNeovimPkg options 2024-05-31 02:44:08 +02:00
LeMarsu 2903d288e2 feat: add `version` Sloth subcommand 2024-05-30 23:44:34 +02:00
LeMarsu d9ba9c8232 doc: fix url in the import example 2024-05-30 03:55:41 +02:00
20 changed files with 1143 additions and 365 deletions

View File

@ -2,6 +2,80 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
## [0.0.10] - 2024-06-09
### Features
- Runtime is now optional
- [**breaking**] `init.lua` configuration is now a `mkNeovimPkg`'s option
- Add option init config object to generate `init.lua`
### Miscellaneous Tasks
- Add alejandra to nix shell
## [0.0.9] - 2024-06-09
### Features
- Sloth command has now completion
- Add describe subcommand
- Introduce mkPluginsFromInputs function
### Bug Fixes
- Init/config are loaded to on-the-fly build plugins
- Plugins with init are now loaded as they should be
### Refactor
- Filters are now fully dynamic
### Miscellaneous Tasks
- Remove sourcesWith fn, using lib.fileset
- Move back to flake-utils
## [0.0.8] - 2024-06-04
### Features
- Can load lazy plugins on events
- Can load lazy plugins on keymaps
### Bug Fixes
- Move files instead of copying them
- Sloth list was broken since refactoring
### Miscellaneous Tasks
- Switch from nixpkgs `23.11` to `unstable`
## [0.0.7] - 2024-06-03
### Features
- Add `version` Sloth subcommand
- Add `viAlias` and `vimAlias` mkNeovimPkg options
- Add `vimdiffAlias` and `nvimdiffAlias` mkNeovimPkg options
### Bug Fixes
- Init function is called before plugin is loaded
### Documentation
- Fix url in the import example
### Refactor
- Extract all dep logic in Dep object
- Extract Sloth command code in its own module
- Split Sloth subcommands in their own files
- Deps provides accessors via metatables
- Deps are now loaded via a FSM
## [0.0.6] - 2024-05-30 ## [0.0.6] - 2024-05-30
### Features ### Features

169
README.md
View File

@ -8,18 +8,20 @@ A [neovim] plugin and configuration management plugin, highly inspired by [lazy]
- [Features](#features) - [Features](#features)
- [SemVer](#semver) - [SemVer](#semver)
- [Installation](#installation) - [Installation](#installation)
- [Flake installation](#flake-installation) - [Flake installation](#flake-installation)
- [Usage](#usage) - [Usage](#usage)
- [Documentation](#documentation) - [Documentation](#documentation)
- [nix](#nix) - [nix](#nix)
- [`mkNeovimPkg`](#mkneovimpkg) - [`mkPluginsFromInputs`](#mkpluginsfrominputs)
- [neovim (lua)](#neovim-lua) - [`mkNeovimPkg`](#mkneovimpkg)
- [Using default `init.lua`](#using-default-initlua) - [neovim (lua)](#neovim-lua)
- [Using your own `init.lua`](#using-your-own-initlua) - [Using default `init.lua`](#using-default-initlua)
- [`:Sloth` command](#sloth-command) - [Using your own `init.lua`](#using-your-own-initlua)
- [`list` subcommand](#list-subcommand) - [`:Sloth` command](#sloth-command)
- [`load` subcommand](#load-subcommand) - [`list` subcommand](#list-subcommand)
- [API](#api) - [`load` subcommand](#load-subcommand)
- [`version` subcommand](#version-subcommand)
- [API](#api)
<!-- TOC --> <!-- TOC -->
@ -43,8 +45,8 @@ A [neovim] plugin and configuration management plugin, highly inspired by [lazy]
- [X] Lazy load your plugins - [X] Lazy load your plugins
- [X] on command - [X] on command
- [X] on filetype - [X] on filetype
- [ ] on event - [X] on event
- [ ] on keybinding - [X] on keybinding
- [X] load plugins in order (via plugin `dependencies` property) - [X] load plugins in order (via plugin `dependencies` property)
- [X] Have a `:Sloth` command to load or query your plugins - [X] Have a `:Sloth` command to load or query your plugins
- [ ] Generate spell files on build (maybe) - [ ] Generate spell files on build (maybe)
@ -79,7 +81,7 @@ inputs.sloth-flake.url = "github:lemarsu/sloth-flake.nvim";
You can give a specific version: You can give a specific version:
```nix ```nix
inputs.sloth-flake.url = "github:lemarsu/sloth-flake.nvim?ref=0.0.5"; inputs.sloth-flake.url = "github:lemarsu/sloth-flake.nvim?tag=0.0.5";
``` ```
## Usage ## Usage
@ -91,6 +93,8 @@ Once installed, you can call the `sloth-flake.lib.mkNeovimPkg` to build your neo
```nix ```nix
sloth-flake.lib.mkNeovimPkg { sloth-flake.lib.mkNeovimPkg {
inherit pkgs; inherit pkgs;
viAlias = true;
vimAlias = true;
runtime = { runtime = {
version = "0.1"; version = "0.1";
src = sloth-flake.lib.sourcesWith ./. [ src = sloth-flake.lib.sourcesWith ./. [
@ -119,30 +123,95 @@ sloth-flake.lib.mkNeovimPkg {
### nix ### nix
#### `mkPluginsFromInputs`
`mkPluginsFromInputs` is a helper function that converts flake inputs (starting by `"plugin-"` by default) into vimPlugins.
Example:
```nix
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
sloth-flake.url = "github:lemarsu/sloth-flake.nvim";
utils.url = "github:numtide/flake-utils";
plugin-base64 = {
url = "github:moevis/base64.nvim";
flake = false;
};
plugin-cellular-automaton = {
url = "github:eandrju/cellular-automaton.nvim";
flake = false;
};
};
outputs = {utils, sloth-flake, ...}@inputs: let
fu = utils.lib;
in fu.eachDefaultSystem (system: let
plugins = sloth-flake.lib.mkPluginsFromInputs {
inherit pkgs inputs;
};
in {
packages = rec {
default = neovim;
neovim = pkgs.callPackage ./package.nix {
# By adding `plugins` here, we can use `with plugins; base64 cellular-automaton`,
inherit plugins sloth-flake;
};
};
};
}
```
The function accepts the following attributes:
- `pkgs` **REQUIRED** the nixpkgs set.
- `inputs` **REQUIRED** the inputs from a flake.
- `predicate` **optional** predicate to filter input by name. By default, it's
filter inputs with `hasPrefix "plugin-"`.
- `nameMap` **optional** function to change the key of the input in the resulting
set. By default, the 7 first letters are removed, so to remove the "plugin-"
prefix.
- `buildVimPlugin` **optional** function used to build the plugin. Defaults to
`pkgs.vimUtils.buildVimPlugin`.
#### `mkNeovimPkg` #### `mkNeovimPkg`
`mkNeovimPkg` requires only the `pkgs` argument. `mkNeovimPkg` requires only the `pkgs` argument.
Here's a list of all accepted arguments Here's a list of all accepted arguments
| name | default | description | | name | default | description |
|-------------------------|-------------------------|----------------------------------------------------------| |-------------------------|-------------------------|---------------------------------------------------------------------|
| `pkgs` | N/A | The nixpkgs set. **REQUIRED** | | `pkgs` | N/A | The nixpkgs set. **REQUIRED** |
| `package` | `pkgs.neovim-unwrapped` | The unwrapped neovim package to use | | `package` | `pkgs.neovim-unwrapped` | The unwrapped neovim package to use |
| `runtime` | `{}` | Your Runtime configuration (see below) | | `init` | `null` | The `init.lua` of your config (string, path or init config object)¹ |
| `dependencies` | `[]` | A list of your dependencies (see below) | | `runtime` | `{}` | Your Runtime configuration (see below) |
| `dependenciesExtraArgs` | `{}` | Extra arguments to load your dependencies in other files | | `dependencies` | `[]` | A list of your dependencies (see below) |
| `dependenciesExtraArgs` | `{}` | Extra arguments to load your dependencies in other files |
| `extraLuaPackages` | `null` | Extra lua packages needed for the plugin |
| `viAlias` | `false` | Wether to create a `vi` alias to run neovim |
| `vimAlias` | `false` | Wether to create a `vim` alias to run neovim |
| `vimdiffAlias` | `false` | Wether to create a `vimdiff` alias to run neovim in diff mode |
| `nvimdiffAlias` | `false` | Wether to create a `nvimdiff` alias to run neovim in diff mode |
> ¹ If you give your own `init.lua` as string or path, you'll have to call `sloth-flake` lua plugin yourself. See more below.
The init configuration object accepts the following properties:
| name | default | description |
|------------|---------|----------------------------------------------------------------------------|
| `init` | `null` | Lua code call before plugins init. String or path. |
| `postInit` | `null` | Lua code call after plugins init and before plugin config. String or path. |
| `config` | `null` | Luas cod call after plugins config. String or path. |
The Runtime configuration object accepts the following properties: The Runtime configuration object accepts the following properties:
| name | default | description | | name | default | description |
|-----------|---------|--------------------------------| |-----------|---------|--------------------------------|
| `version` | `null` | The version of your runtime | | `version` | `null` | The version of your runtime |
| `init` | `null` | The `init.lua` of your config¹ |
| `src` | `null` | The content of your runtime | | `src` | `null` | The content of your runtime |
> ¹ If you give your own `init.lua`, you'll have to call `sloth-flake` lua plugin yourself. See more below.
The dependencies is a list of element of either: The dependencies is a list of element of either:
- path: the path of the file to load other dependencies - path: the path of the file to load other dependencies
- package: a nix package of a neovim/vim plugin - package: a nix package of a neovim/vim plugin
@ -150,29 +219,49 @@ The dependencies is a list of element of either:
The Plugin configuration object accepts the following properties: The Plugin configuration object accepts the following properties:
| name | default | description | | name | default | description |
|----------------|---------|-----------------------------------------------------------------| |--------------------|---------|----------------------------------------------------------------|
| `plugin` | N/A | The plugin to load² **REQUIRED** | | `plugin` | N/A | The plugin to load² **REQUIRED** |
| `init` | `null` | Lua code (as string of path) to call before loading the plugin³ | | `init` | `null` | Lua code (as string of path) to call before loading the plugin |
| `config` | `null` | Lua code (as string of path) to call after loading the plugin | | `config` | `null` | Lua code (as string of path) to call after loading the plugin |
| `dependencies` | `[]` | The plugin dependencies⁴ | | `dependencies` | `[]` | The plugin dependencies³ |
| `lazy` | `false` | Should the plugin be loaded lazily | | `extraLuaPackages` | `null` | Extra lua packages needed for the plugin |
| `cmd` | `[]` | Command to put as place_holder to lazy load the plugin⁵ | | `lazy` | `false` | Should the plugin be loaded lazily |
| `ft` | `[]` | Filetype to watch to lazy load the plugin⁵ | | `cmd` | `[]` | Command to put as place_holder to load the lazy plugin⁴ |
| `ft` | `[]` | Filetype to watch to load the lazy plugin⁴ |
| `events` | `[]` | Events to watch to load the lazy plugin⁴⁵ |
| `keymaps` | `[]` | Keymaps that when press will load the lazy plugin⁴⁶ |
> ² The plugin can be either a nix package or an object with only `name` and > ² The plugin can be either a nix package or an object with only `name` and
> `src` as properties. The latter will be used to create a nix package of your > `src` as properties. The latter will be used to create a nix package of your
> plugin on the fly. > plugin on the fly.
> ³ When the plugin is not lazy, the `init` function is called after the plugin > ³ `nix` handles the installation of your plugin, therefore, this list is
> is loaded as all non lazy plugin are loaded automatically.
> ⁴ `nix` handles the installation of your plugin, therefore, this list is
> **NOT** to declare dependencies that the nix package of the plugin doesn't > **NOT** to declare dependencies that the nix package of the plugin doesn't
> know. This will tell `sloth-flake` in what order your plugins should be > know. This will tell `sloth-flake` in what order your plugins should be
> loaded. > loaded.
> ⁵ Setting this property implicitly set `lazy` to `true`. > ⁴ Setting this property implicitly set `lazy` to `true`.
> ⁵ Events can be a string, an Event object or a list of either. You can
> represent a simple event name and pattern with the following string format :
> "BufRead *.md".
> ⁶ Keymaps can be a string, an Keymap object or a list of either.
The Event configuration object accepts the following properties:
| name | default | description |
|-----------|---------|----------------------------------------------------------------|
| `name` | N/A | The name of the event as string or list of string **REQUIRED** |
| `pattern` | `null` | Pattern (as string or list of string) associated to the event |
The Keymap configuration object accepts the following properties:
| name | default | description |
|-----------|---------|----------------------------------------------------|
| `mode` | `"n"` | The mode of the keymap as string or list of string |
| `mapping` | N/A | The actual mapping **REQUIRED** |
### neovim (lua) ### neovim (lua)
@ -231,6 +320,12 @@ Summary: Load lazy plugins.
Usage: `Sloth load <plugin> [plugin [...]]` Usage: `Sloth load <plugin> [plugin [...]]`
- `plugin`: a plugin to load - `plugin`: a plugin to load
##### `version` subcommand
Summary: Return Sloth version
Usage: `Sloth version`
#### API #### API
The lua API is not really defined yet. This documentation will be completed then. The lua API is not really defined yet. This documentation will be completed then.

View File

@ -1 +1 @@
0.0.6 0.0.10

View File

@ -63,24 +63,6 @@
"type": "github" "type": "github"
} }
}, },
"flake-utils_2": {
"inputs": {
"systems": "systems_2"
},
"locked": {
"lastModified": 1694529238,
"narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "ff7b65b44d01cf9ba6a71320833626af21126384",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flakeCompat": { "flakeCompat": {
"flake": false, "flake": false,
"locked": { "locked": {
@ -104,11 +86,11 @@
"rust-overlay": "rust-overlay" "rust-overlay": "rust-overlay"
}, },
"locked": { "locked": {
"lastModified": 1714571717, "lastModified": 1717086091,
"narHash": "sha256-o4tqlTzi9kcVub167kTGXgCac9jM3kW4+v9MH/ue4Hk=", "narHash": "sha256-GmsEQa4HZeMfec37LZnwG/Lt/XmqFLXsjv5QWojeNiM=",
"owner": "oxalica", "owner": "oxalica",
"repo": "nil", "repo": "nil",
"rev": "2f3ed6348bbf1440fcd1ab0411271497a0fbbfa4", "rev": "ab3ddb8f063774cf7e22eb610f5ecfdb77309f3c",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -119,11 +101,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1714314149, "lastModified": 1716977081,
"narHash": "sha256-yNAevSKF4krRWacmLUsLK7D7PlfuY3zF0lYnGYNi9vQ=", "narHash": "sha256-pFe5jLeIPlKEln5n2h998d7cpzXFdbrBMRe3suz4K1o=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "cf8cc1201be8bc71b7cbbbdaf349b22f4f99c7ae", "rev": "ac82a513e55582291805d6f09d35b6d8b60637a1",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -135,16 +117,16 @@
}, },
"nixpkgs_2": { "nixpkgs_2": {
"locked": { "locked": {
"lastModified": 1716633019, "lastModified": 1717196966,
"narHash": "sha256-xim1b5/HZYbWaZKyI7cn9TJCM6ewNVZnesRr00mXeS4=", "narHash": "sha256-yZKhxVIKd2lsbOqYd5iDoUIwsRZFqE87smE2Vzf6Ck0=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "9d29cd266cebf80234c98dd0b87256b6be0af44e", "rev": "57610d2f8f0937f39dbd72251e9614b1561942d8",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "nixos", "owner": "nixos",
"ref": "nixos-23.11", "ref": "nixos-unstable",
"repo": "nixpkgs", "repo": "nixpkgs",
"type": "github" "type": "github"
} }
@ -202,11 +184,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1714529851, "lastModified": 1717035469,
"narHash": "sha256-YMKJW880f7LHXVRzu93xa6Ek+QLECIu0IRQbXbzZe38=", "narHash": "sha256-MzH+yjKULH3HCRj9QCTwBvqq4LZkR0ZqRE/QfGOGC2E=",
"owner": "oxalica", "owner": "oxalica",
"repo": "rust-overlay", "repo": "rust-overlay",
"rev": "9ca720fdcf7865385ae3b93ecdf65f1a64cb475e", "rev": "095702e63a40e86f339d11864da9dc965b70a01e",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -247,20 +229,19 @@
}, },
"utils": { "utils": {
"inputs": { "inputs": {
"flake-utils": "flake-utils_2" "systems": "systems_2"
}, },
"locked": { "locked": {
"lastModified": 1696281284, "lastModified": 1710146030,
"narHash": "sha256-xcmtTmoiiAOSk4abifbtqVZk0iwBcqJfg47iUbkwhcE=", "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
"owner": "gytis-ivaskevicius", "owner": "numtide",
"repo": "flake-utils-plus", "repo": "flake-utils",
"rev": "6cf1e312fb259693c4930d07ca3cbe1d07ef4a48", "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "gytis-ivaskevicius", "owner": "numtide",
"ref": "v1.4.0", "repo": "flake-utils",
"repo": "flake-utils-plus",
"type": "github" "type": "github"
} }
}, },

View File

@ -2,8 +2,8 @@
description = "My neovim configuration"; description = "My neovim configuration";
inputs = { inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-23.11"; nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
utils.url = "github:gytis-ivaskevicius/flake-utils-plus/v1.4.0"; utils.url = "github:numtide/flake-utils";
nil.url = "github:oxalica/nil"; nil.url = "github:oxalica/nil";
yants.url = "github:divnix/yants"; yants.url = "github:divnix/yants";
alejandra = { alejandra = {
@ -20,24 +20,25 @@
yants, yants,
... ...
} @ inputs: let } @ inputs: let
versionFile = builtins.replaceStrings ["\n"] [""] (builtins.readFile ./VERSION); inherit (builtins) readFile replaceStrings;
fu = utils.lib;
versionFile = replaceStrings ["\n"] [""] (readFile ./VERSION);
version =
if self.sourceInfo ? dirtyShortRev
then "${versionFile}-${self.sourceInfo.dirtyShortRev}"
else versionFile;
version = if self.sourceInfo ? dirtyShortRev forSystem = system: let
then "${versionFile}-${self.sourceInfo.dirtyShortRev}" pkgs = nixpkgs.legacyPackages.${system};
else versionFile; formatter = alejandra.defaultPackage.${system};
in inherit (inputs.nil.packages.${system}) nil;
utils.lib.mkFlake { in {
inherit self inputs; inherit formatter;
outputsBuilder = channel: let devShells.default = import ./shell.nix {
system = channel.nixpkgs.system; inherit pkgs nil formatter;
in {
formatter = alejandra.defaultPackage.${channel.nixpkgs.system};
devShells.default = import ./shell.nix {
pkgs = channel.nixpkgs;
inherit (inputs.nil.packages.${system}) nil;
};
}; };
lib = import ./lib {inherit version yants;};
}; };
in
(fu.eachDefaultSystem forSystem)
// {lib = import ./lib {inherit version yants;};};
} }

View File

@ -1,18 +1,9 @@
{version, yants}: let {
version,
yants,
}: let
types = import ./types.nix {inherit yants;}; types = import ./types.nix {inherit yants;};
in { in {
mkNeovimPkg = import ./mkNeovimPkg.nix {inherit version types;}; mkNeovimPkg = import ./mkNeovimPkg.nix {inherit version types;};
mkPluginsFromInputs = import ./mkPluginsFromInputs.nix;
sourcesWith = path: paths: let
samePath = a: let a' = builtins.toString a; in b: a' == builtins.toString b;
isRoot = samePath "/";
isInPath = path: subPath:
if isRoot subPath
then false
else (samePath path subPath) || (isInPath path (builtins.dirOf subPath));
filter = src: _type: builtins.any (includePath: isInPath includePath src) paths;
in
builtins.path {
inherit path filter;
};
} }

View File

@ -6,14 +6,19 @@
types, types,
... ...
}: let }: let
inherit (builtins) isPath foldl'; inherit (builtins) foldl' isPath isList isString mapAttrs match elemAt;
inherit (lib.attrsets) attrNames optionalAttrs; inherit (lib.attrsets) attrNames optionalAttrs;
inherit (lib.lists) concatMap; inherit (lib.lists) concatMap;
inherit (lib.strings) fileContents; inherit (lib.strings) fileContents splitString;
lua = callPackage ./lua.nix {}; lua = callPackage ./lua.nix {};
callPackage = lib.callPackageWith (pkgs // dependenciesExtraArgs); callPackage = lib.callPackageWith (pkgs // dependenciesExtraArgs);
hasMatch = pattern: str: isList (match pattern str);
wrapArray = value:
if isList value
then value
else [value];
defaultPlugin = { defaultPlugin = {
enabled = true; enabled = true;
init = null; init = null;
@ -22,6 +27,8 @@
lazy = false; lazy = false;
cmd = []; cmd = [];
ft = []; ft = [];
events = [];
keymaps = [];
}; };
remotePluginToNeovimPlugin = p: remotePluginToNeovimPlugin = p:
@ -30,6 +37,39 @@
pname = name; pname = name;
}; };
defaultKeymap = {mode = "n";};
normalizeKeymap = keymap: let
value = (
if isString keymap
then {mapping = keymap;}
else keymap
);
in
mapAttrs (_: wrapArray) (defaultKeymap // value);
normalizeKeymaps = keymaps:
if isList keymaps
then map normalizeKeymap keymaps
else [(normalizeKeymap keymaps)];
normalizeEvent = event: let
value =
if ! isString event
then event
else if ! hasMatch ".* .*" event
then {name = event;}
else let
part = elemAt (splitString " " event);
in {
name = part 0;
pattern = part 1;
};
in
mapAttrs (_: wrapArray) value;
normalizeEvents = events:
if isList events
then map normalizeEvent events
else [(normalizeEvent events)];
withPluginDefaults = dep: defaultPlugin // dep; withPluginDefaults = dep: defaultPlugin // dep;
normalizePlugin = d: let normalizePlugin = d: let
dep = types.dependency d; dep = types.dependency d;
@ -40,7 +80,7 @@
inherit (dep) plugin; inherit (dep) plugin;
in in
if attrNames plugin == ["name" "src"] if attrNames plugin == ["name" "src"]
then {plugin = remotePluginToNeovimPlugin plugin;} then dep // {plugin = remotePluginToNeovimPlugin plugin;}
else dep; else dep;
p = withPluginDefaults plugin; p = withPluginDefaults plugin;
in in
@ -48,7 +88,12 @@
// rec { // rec {
hasCommands = p.cmd != []; hasCommands = p.cmd != [];
hasFileTypes = p.ft != []; hasFileTypes = p.ft != [];
lazy = p.lazy || hasCommands || hasFileTypes; keymaps = normalizeKeymaps p.keymaps;
hasKeymaps = p.keymaps != [];
events = normalizeEvents p.events;
hasEvents = p.events != [];
lazy = p.lazy || hasCommands || hasFileTypes || hasEvents || hasKeymaps;
optional = lazy || p.init != null;
}; };
normalizeOrImportPlugin = dep: normalizeOrImportPlugin = dep:
@ -77,25 +122,32 @@
vimUtils.buildVimPlugin { vimUtils.buildVimPlugin {
inherit version; inherit version;
pname = "sloth-flake"; pname = "sloth-flake";
src = ../lua/sloth-flake; src = with lib.fileset;
toSource {
root = ../.;
fileset = ../lua/sloth-flake;
};
buildPhase = '' buildPhase = ''
dir=lua/sloth-flake dir=lua/sloth-flake
mkdir -p $dir
mv init.lua $dir
cat <<'LUA' > $dir/deps.lua cat <<'LUA' > $dir/dependencies.lua
return ${pluginsLuaDef plugins} ${pluginsLuaDef plugins}
LUA
cat <<'LUA' > $dir/version.lua
${versionLua version}
LUA LUA
''; '';
}; };
versionLua = version: with lua; nix2lua (return (lambda (return version)));
textOrContent = content: textOrContent = content:
if isPath content if isPath content
then fileContents content then fileContents content
else content; else content;
pluginLuaDef = memo: plugin: let pluginLuaDef = memo: plugin: let
# plugin = builtins.removeAttrs plugin ["dependencies" "plugin"];
mkTypeFn = type: let mkTypeFn = type: let
content = textOrContent plugin.${type}; content = textOrContent plugin.${type};
in in
@ -125,9 +177,16 @@
}) })
// (optionalAttrs plugin.hasFileTypes { // (optionalAttrs plugin.hasFileTypes {
inherit (plugin) ft; inherit (plugin) ft;
})
// (optionalAttrs plugin.hasEvents {
inherit (plugin) events;
})
// (optionalAttrs plugin.hasKeymaps {
inherit (plugin) keymaps;
}); });
}; };
pluginsLuaDef = plugins: lua.nix2lua (foldl' pluginLuaDef {} plugins); pluginsLuaDef = plugins:
with lua; nix2lua (return (foldl' pluginLuaDef {} plugins));
in { in {
inherit normalizePlugin; inherit normalizePlugin;
inherit normalizePlugins; inherit normalizePlugins;

View File

@ -6,15 +6,21 @@
package ? pkgs.neovim-unwrapped, package ? pkgs.neovim-unwrapped,
dependencies ? [], dependencies ? [],
dependenciesExtraArgs ? {}, dependenciesExtraArgs ? {},
runtime ? {}, extraLuaPackages ? (_: []),
runtime ? null,
init ? null,
viAlias ? false,
vimAlias ? false,
vimdiffAlias ? false,
nvimdiffAlias ? false,
... ...
} @ config: let } @ config: let
inherit (builtins) map; inherit (builtins) isString isPath map;
inherit (pkgs) callPackage; inherit (pkgs) callPackage bash lib;
# inherit (lib.lists) concatMap filter foldl' map optional reverseList; inherit (lib.strings) optionalString;
# inherit (lib.attrsets) attrNames optionalAttrs; inherit (lib.lists) concatMap optional;
# inherit (lib.strings) concatStringsSep fileContents hasSuffix removePrefix removeSuffix replaceStrings; inherit (lib.trivial) flip;
# inherit (lib.debug) traceIf traceSeq traceVal traceValSeq traceValFn; inherit (lib.attrsets) optionalAttrs;
deps = callPackage ./deps.nix {inherit dependenciesExtraArgs types;}; deps = callPackage ./deps.nix {inherit dependenciesExtraArgs types;};
@ -23,25 +29,87 @@
runtimePlugin = deps.mkRuntimePlugin runtime; runtimePlugin = deps.mkRuntimePlugin runtime;
plugins = plugins =
normalizedPlugins normalizedPlugins
++ (deps.normalizePlugins [runtimePlugin sloth-flake]); ++ (
deps.normalizePlugins
([sloth-flake] ++ (optional (runtime != null) runtimePlugin))
);
extractPlugin = p: { extractPlugin = p: {inherit (p) optional plugin;};
inherit (p) plugin;
optional = p.lazy;
};
extractPlugins = map extractPlugin; extractPlugins = map extractPlugin;
customRC = let extractLuaPackageFn = plugin:
rc = ({init ? ../lua/default_init.lua, ...}: init) runtime; optional (plugin ? extraLuaPackages) plugin.extraLuaPackages;
extractLuaPackagesFn = plugins: let
fnList = concatMap extractLuaPackageFn plugins;
concatPackages = ps: fn: fn ps;
in in
deps.textOrContent rc; ps: concatMap (concatPackages ps) fnList;
buildInit = {
init ? null,
postInit ? null,
config ? null,
}: let
initStr = optionalString (! isNull init) ''
(function()
${deps.textOrContent init}
end)();
'';
slothCall =
if isNull postInit
then "require('sloth-flake').setup {}"
else ''
require('sloth-flake').setup {
post_init = function()
${deps.textOrContent postInit}
end,
};
'';
configStr = optionalString (! isNull config) ''
(function()
${deps.textOrContent config}
end)()
'';
in ''
-- Generated by sloth-flake
${initStr}
${slothCall}
${configStr}
'';
customRC =
if isString init || isPath init
then deps.textOrContent init
else buildInit (optionalAttrs (! isNull init) init);
neovimConfig = neovimConfig =
pkgs.neovimUtils.makeNeovimConfig { pkgs.neovimUtils.makeNeovimConfig {
inherit customRC; inherit customRC;
plugins = extractPlugins plugins; plugins = extractPlugins plugins;
extraLuaPackages = ps:
(extractLuaPackagesFn plugins ps) ++ (extraLuaPackages ps);
} }
// {luaRcContent = customRC;}; // {luaRcContent = customRC;};
pkg = pkgs.wrapNeovimUnstable package (removeAttrs neovimConfig ["manifestRc" "neovimRcContent"]); params =
removeAttrs neovimConfig ["manifestRc" "neovimRcContent"]
// {inherit viAlias vimAlias;};
pkg = pkgs.wrapNeovimUnstable package params;
mkDiffAlias = name:
(flip optionalString) ''
cat <<SH > $out/bin/${name}
#!${bash}/bin/bash
exec $out/bin/nvim -d "\''${@}"
SH
chmod 555 $out/bin/${name}
'';
in in
builtins.seq (types.mkNeovimPkgOptions config) pkg builtins.seq (types.mkNeovimPkgOptions config) (pkg.overrideAttrs (final: super: {
postBuild =
super.postBuild
+ (mkDiffAlias "vimdiff" vimdiffAlias)
+ (mkDiffAlias "nvimdiff" nvimdiffAlias);
}))

View File

@ -0,0 +1,20 @@
{
pkgs,
inputs,
predicate ? pkgs.lib.strings.hasPrefix "plugin-",
nameMap ? builtins.substring 7 (-1),
buildVimPlugin ? pkgs.vimUtils.buildVimPlugin,
}: let
inherit (builtins) attrNames filter foldl' mapAttrs;
names = filter predicate (attrNames inputs);
mkPlugin = m: k: let
name = nameMap k;
pluginDef = {
inherit name;
src = inputs.${k};
};
in
m // {${name} = pluginDef;};
plugins = foldl' mkPlugin {} names;
in
mapAttrs (_: buildVimPlugin) plugins

View File

@ -1,17 +1,30 @@
{yants, ...}: rec { {yants, ...}: let
stringList = with yants; list string;
stringOrStringList = with yants; either string stringList;
stringOrStringListOr = type:
with yants;
option (eitherN [string type (list (either string type))]);
in rec {
# The runtime object # The runtime object
runtimeType = with yants; runtimeType = with yants;
struct "runtime" { struct "runtime" {
# The version of the runtime # The version of the runtime
version = option string; version = option string;
# The init configuration file
init = option (either path string);
# The content of the runtime directory # The content of the runtime directory
src = any; src = any;
}; };
neovimInitType = with yants;
struct "neovimInit" {
# Lua code to call before plugins loaded
init = option (either string path);
# Lua code called after init but before import
postInit = option (either string path);
# Lua code called after all plugins are loaded
config = option (either string path);
};
# As simple remote plugin definition # As simple remote plugin definition
basicPluginType = with yants; basicPluginType = with yants;
struct "basicPlugin" { struct "basicPlugin" {
@ -22,10 +35,24 @@
src = any; src = any;
}; };
eventType = with yants;
struct "event" {
# The name of the event
name = stringOrStringList;
# The pattern of the event
pattern = stringOrStringList;
};
keymapType = with yants;
struct "keymap" {
# The mode of the keymap
mode = option stringOrStringList;
# The mapping of the keymap
mapping = stringOrStringList;
};
# The plugin type of dependencies # The plugin type of dependencies
pluginType = with yants; let pluginType = with yants;
stringList = list string;
in
struct "plugin" { struct "plugin" {
# Whether this plugin should be enabled. This option allows specific # Whether this plugin should be enabled. This option allows specific
# plugins to be disabled. # plugins to be disabled.
@ -45,11 +72,14 @@
# Ensure thoses plugins are loaded before the current one # Ensure thoses plugins are loaded before the current one
dependencies = option (list drv); dependencies = option (list drv);
# Ensure those packages are available
extraLuaPackages = option function;
# Should this plugin be load lazily ? # Should this plugin be load lazily ?
lazy = option bool; lazy = option bool;
# List of events on which the plugin should be loaded # List of events on which the plugin should be loaded
# events = option stringList; events = option (stringOrStringListOr eventType);
# List of commands on which the plugin should be loaded # List of commands on which the plugin should be loaded
cmd = option stringList; cmd = option stringList;
@ -58,7 +88,7 @@
ft = option stringList; ft = option stringList;
# List of keystrokes on which the plugin should be loaded # List of keystrokes on which the plugin should be loaded
# keys = option stringList; keymaps = option (stringOrStringListOr keymapType);
# Priority of the module. Influence the order of loading plugins. # Priority of the module. Influence the order of loading plugins.
# Highest values get loaded before. # Highest values get loaded before.
@ -78,13 +108,31 @@
# Default is pkgs.neovim-unwrapped # Default is pkgs.neovim-unwrapped
package = option drv; package = option drv;
# init.lua configuration
init = option (eitherN [string path neovimInitType]);
# An array of dependencies. # An array of dependencies.
dependencies = list dependency; dependencies = option (list dependency);
# Extra argument to pass to dependencies files # Extra argument to pass to dependencies files
dependenciesExtraArgs = attrs any; dependenciesExtraArgs = option (attrs any);
# Ensure those packages are available
extraLuaPackages = option function;
# Runtime configuration # Runtime configuration
runtime = runtimeType; runtime = option runtimeType;
# Create a vi alias
viAlias = option bool;
# Create a vim alias
vimAlias = option bool;
# Create a vimdiff alias to run neovim in diff mode
vimdiffAlias = option bool;
# Create a nvimdiff alias to run neovim in diff mode
nvimdiffAlias = option bool;
}; };
} }

View File

@ -0,0 +1,74 @@
local Dep = require 'sloth-flake.dep'
local utils = require 'sloth-flake.utils'
local function yesno(value)
return value and "Yes" or "No"
end
local function list(items)
if items == nil or #items == 0 then
return "None"
end
return vim.iter(items):join(', ')
end
local function describe(dep)
utils.info('Name: %s', dep.name)
utils.info('Is loaded: %s', yesno(dep.is_loaded))
utils.info('Is lazy: %s', yesno(dep.is_lazy))
utils.info('Has init: %s', yesno(dep.init))
utils.info('Has config: %s', yesno(dep.config))
utils.info('Dependencies: %s', list(dep.dependency_names))
utils.info('Filetypes: %s', list(dep.ft))
utils.info('Commands: %s', list(dep.cmd))
if dep.events == nil then
utils.info('Events: None')
else
utils.info('Events:')
for _, event in ipairs(dep.events) do
for _, name in ipairs(event.name) do
for _, pattern in ipairs(event.pattern) do
utils.info(' - %s %s', name, pattern)
end
end
end
end
if dep.keymaps == nil then
utils.info('Keymaps: None')
else
utils.info('Keymaps:')
for _, keymap in ipairs(dep.keymaps) do
for _, mode in ipairs(keymap.mode) do
for _, mapping in ipairs(keymap.mapping) do
utils.info(' - %s %s', mode, mapping)
end
end
end
end
end
return {
complete = function(line)
if line.arg_idx == 3 then
local prefix = line.args[line.arg_idx].arg
return vim.iter(Dep.all()):map(function(name)
return name
end):filter(function(name)
return vim.startswith(name, prefix)
end):totable()
end
end,
cmd = function(plugins)
if #plugins == 0 then
utils.error("You should at least give a plugin to describe!")
return
end
local plugin = plugins[1]
local dep = Dep.get(plugin)
if dep == nil then
return utils.error([[Unknown plugin "%s"]], plugin)
end
describe(dep)
end,
}

View File

@ -0,0 +1,87 @@
local Dep = require 'sloth-flake.dep'
local M = {}
local commands = {
list = require 'sloth-flake.command.list',
load = require 'sloth-flake.command.load',
version = require 'sloth-flake.command.version',
describe = require 'sloth-flake.command.describe',
}
local function parse_line(line, cursor_pos)
local raw_args = vim.split(line, ' +', { trimempty = true })
local parse_pos = 1
local args = vim.iter(raw_args):map(function(arg)
local start, stop = string.find(line, arg, parse_pos, { plain = true })
parse_pos = stop
return {
arg = arg,
start = start,
stop = stop,
}
end):totable()
parse_pos = 1
local arg_idx = 1
vim.iter(args):find(function(arg)
if cursor_pos < arg.start then
arg_idx = arg_idx - 1
return true
elseif cursor_pos <= arg.stop then
return true
end
arg_idx = arg_idx + 1
return false
end)
arg_idx = arg_idx < 1 and 1 or arg_idx
if arg_idx > #args then
args[#args + 1] = {
arg = "",
start = line:len(),
stop = line:len(),
}
end
return {
line = line,
args = args,
arg_idx = arg_idx,
pos = cursor_pos,
in_arg_pos = args[arg_idx] and cursor_pos - args[arg_idx].start + 1,
}
end
-- print(vim.inspect(parse_line('Sloth ', 6)))
local function sloth_cmd_complete(arg_lead, cmd_line, cursor_pos)
local parsed_line = parse_line(cmd_line, cursor_pos)
local arg = parsed_line.args[parsed_line.arg_idx]
if parsed_line.arg_idx == 2 then
return vim.iter(commands):map(function(name, command)
return vim.startswith(name, arg.arg) and name or nil
end):totable()
elseif parsed_line.arg_idx > 2 then
local cmd = parsed_line.args[2].arg
local command = commands[cmd]
return command and command.complete(parsed_line)
end
end
local function sloth_cmd(param)
local args = param.fargs
local cmd = args[1] or "list";
table.remove(args, 1)
local command = commands[cmd]
if command then
command.cmd(args)
else
vim.api.nvim_err_writeln(string.format([[No Sloth subcommand "%s"]], cmd))
end
end
function M.register()
vim.api.nvim_create_user_command('Sloth', sloth_cmd, {
nargs = '*',
complete = sloth_cmd_complete
})
end
return M

View File

@ -0,0 +1,55 @@
local Dep = require 'sloth-flake.dep'
local utils = require 'sloth-flake.utils'
local filters = {
all = {
filter = function(iter)
-- Nothing to do
return iter
end
},
loaded = {
filter = function(iter)
return iter:filter(function(dep)
return Dep.get(dep).is_loaded
end)
end
},
notloaded = {
filter = function(iter)
return iter:filter(function(dep)
return not Dep.get(dep).is_loaded
end)
end
},
}
return {
complete = function(line)
if line.arg_idx == 3 then
local prefix = line.args[3].arg
return vim.iter(vim.tbl_keys(filters)):filter(function(name)
return vim.startswith(name, prefix)
end):totable()
end
end,
cmd = function(args)
local filter_name = args[1] or "all"
local filter = filters[filter_name]
if not filter then
utils.error([[No Sloth list filter "%s".]], cmd)
utils.error("Filters are: %s", vim.iter(vim.tbl_keys(filters)):join(', '))
return
end
local deps = vim.iter(Dep.all()):map(function(_, dep)
return dep.name
end)
deps = filter.filter(deps):totable()
table.sort(deps)
for _, dep in ipairs(deps) do
print(string.format("- %s", dep))
end
end,
}

View File

@ -0,0 +1,32 @@
local Dep = require 'sloth-flake.dep'
local utils = require 'sloth-flake.utils'
return {
complete = function(line)
local previous_deps = vim.iter(line.args):enumerate():map(function(i, arg)
if i < 3 or i > line.arg_idx then return end
return arg.arg
end):totable()
local prefix = line.args[line.arg_idx].arg
return vim.iter(Dep.all()):filter(function(name, dep)
return vim.startswith(name, prefix) and not dep.is_loaded
and not vim.list_contains(previous_deps, name)
end):map(function(name)
return name
end):totable()
end,
cmd = function(plugins)
if #plugins == 0 then
utils.error("You should at least give a plugin to load!")
return
end
for _, plugin in ipairs(plugins) do
local dep = Dep.get(plugin)
if dep ~= nil then
dep:load()
end
end
end,
}

View File

@ -0,0 +1,7 @@
return {
complete = function() end,
cmd = function()
local version = require('sloth-flake.version')
print(string.format('Sloth v%s', version()))
end,
}

268
lua/sloth-flake/dep.lua Normal file
View File

@ -0,0 +1,268 @@
local raw_deps = require 'sloth-flake.dependencies'
local state_machine = require 'sloth-flake.state_machine'
local M = {}
local State = state_machine.build_states {
'NotLoaded',
'Shimed',
'Inited',
'Imported',
'Loaded',
}
function M.new(values)
local self = {
values = values,
}
self.sm = state_machine.build(State, {
enter = {
[State.Shimed] = function()
return self:_shim()
end,
[State.Inited] = function()
for _, dep in ipairs(self.dependencies) do
dep:init()
end
local init = self.values.init or function() end
init()
end,
[State.Imported] = function()
for _, dep in ipairs(self.dependencies) do
dep:import()
end
if self.is_lazy or self.values.init then
vim.cmd("packadd " .. self.name)
end
end,
[State.Loaded] = function()
for _, dep in ipairs(self.dependencies) do
dep:config()
end
local config = self.values.config or function() end
config()
end
},
exit = {
[State.Shimed] = function()
self:_unshim()
end,
},
events = {
shim = { from = State.NotLoaded, to = State.Shimed, },
init = { from = { State.NotLoaded, State.Shimed }, to = State.Inited, },
import = { from = State.Inited, to = State.Imported, },
config = { from = State.Imported, to = State.Loaded, },
},
})
return setmetatable(self, {
__index = function(self, k)
local fn = M[k]
if fn then
return fn
end
fn = M['get_' .. k]
if fn then
return fn(self)
end
end,
__newindex = function(self, k, v)
-- Ignore new values
end
})
end
function M:get_name()
return self.values.name
end
function M:get_dependencies()
local ret = {}
for _, name in ipairs(self.values.dependencies) do
local dep = M.get(name)
if dep ~= nil then
ret[#ret + 1] = dep
end
end
return ret
end
function M:get_dependency_names()
local ret = {}
for _, name in ipairs(self.values.dependencies) do
ret[#ret + 1] = name
end
return ret
end
function M:get_cmd()
return self.values.cmd
end
function M:get_ft()
return self.values.ft
end
function M:get_events()
return self.values.events
end
function M:get_keymaps()
return self.values.keymaps
end
function M:get_is_lazy()
return self.values.lazy or false
end
function M:get_state()
return self.sm.state
end
function M:get_is_imported()
return self.state >= State.Imported
end
function M:get_is_loaded()
return self.state >= State.Loaded
end
function M:get_has_events()
return self.ft or self.events
end
function M:get_augroup_name()
return "Sloth-plugin-" .. self.name
end
function M:shim()
return self.sm:shim()
end
function M:_shim()
if self.cmd then
for _, cmd in ipairs(self.cmd) do
vim.api.nvim_create_user_command(cmd, self:lazy_load_cmd(cmd), {
desc = "Sloth-flake placeholder for plugin " .. self.name,
nargs = '*',
bang = true,
})
end
end
if self.has_events then
local group_id = vim.api.nvim_create_augroup(self.augroup_name, {
clear = true,
})
if self.ft then
vim.api.nvim_create_autocmd('FileType', {
group = group_id,
pattern = self.ft,
callback = self:lazy_load_event('FileType')
})
end
if self.events then
for _, event in ipairs(self.events) do
vim.api.nvim_create_autocmd(event.name, {
group = group_id,
pattern = event.pattern,
callback = self:lazy_load_event(event.name)
})
end
end
end
if self.keymaps then
for _, keymap in ipairs(self.keymaps) do
for _, mapping in ipairs(keymap.mapping) do
vim.keymap.set(keymap.mode, mapping, self:lazy_load_mapping(mapping))
end
end
end
end
function M:_unshim()
if self.cmd then
for _, cmd in ipairs(self.cmd) do
vim.api.nvim_del_user_command(cmd)
end
end
if self.has_events then
vim.api.nvim_del_augroup_by_name(self.augroup_name)
end
if self.keymaps then
for _, keymap in ipairs(self.keymaps) do
for _, mapping in ipairs(keymap.mapping) do
vim.keymap.del(keymap.mode, mapping)
end
end
end
end
function M:init()
return self.sm:init()
end
function M:import()
self:init()
return self.sm:import()
end
function M:config()
self:init()
self:import()
return self.sm:config()
end
function M:load()
self:init()
self:import()
return self:config()
end
function M:lazy_load_cmd(cmd)
return function(param)
self:load()
local bang = param.bang and '!' or ''
vim.cmd(cmd .. bang .. ' ' .. param.args)
end
end
function M:lazy_load_event(name)
return function(param)
self:load()
vim.api.nvim_exec_autocmds(name, {
pattern = param.match,
})
end
end
function M:lazy_load_mapping(mapping)
return function(param)
self:load()
vim.cmd.normal(mapping)
end
end
local deps = {}
for k, v in pairs(raw_deps) do
deps[k] = M.new(v)
end
function M.get(name)
return deps[name]
end
function M.all()
return deps
end
return M

View File

@ -1,256 +1,57 @@
local deps = require 'sloth-flake.deps' local Dep = require 'sloth-flake.dep'
local command = require 'sloth-flake.command'
local priv = { local priv = {
setup_called = false, setup_called = false,
is = {
init = {},
import = {},
config = {},
shim = {},
},
} }
local M = {} local M = {}
function M.get(name) function M.get(name)
return deps[name] return Dep.get(name)
end end
function M.init_non_lazy() function M.init_non_lazy()
for _, dep in ipairs(M.non_lazy_deps()) do for _, dep in ipairs(M.non_lazy_deps()) do
M.init(dep.name) dep:init()
end end
end end
function M.import_non_lazy() function M.import_non_lazy()
for _, dep in ipairs(M.non_lazy_deps()) do for _, dep in ipairs(M.non_lazy_deps()) do
M.import(dep.name) dep:import()
end end
end end
function M.config_non_lazy() function M.config_non_lazy()
for _, dep in ipairs(M.non_lazy_deps()) do for _, dep in ipairs(M.non_lazy_deps()) do
M.config(dep.name) dep:config()
end end
end end
function load_fn(type)
local function fn(name)
local dep = M.get(name)
if dep == nil then
-- TODO Handle missing deps
return
end
if priv.is[type][name] then
return
end
priv.is[type][name] = true
if dep[type] ~= nil then
for _, child in ipairs(dep.dependencies) do
fn(child)
end
dep[type]()
end
end
return fn
end
M.init = load_fn('init')
M.config = load_fn('config')
function M.import(name)
if M.is_imported(name) then
return
end
local plugin = M.get(name)
if plugin == nil then
-- TODO Handle missing deps
return
end
priv.is.import[name] = true
if plugin.lazy then
for _, dep in ipairs(plugin.dependencies) do
M.import(dep)
end
vim.cmd("packadd " .. name)
end
end
function M.is_imported(name)
return priv.is.import[name] or false
end
function M.is_loaded(name)
return priv.is.config[name] or false
end
function M.load(name)
unshim_plugin(name)
M.init(name)
M.import(name)
M.config(name)
end
function M.dep_names() function M.dep_names()
return M.dep_names_by(function() return true end):totable() return M.dep_names_by(function() return true end):totable()
end end
function M.dep_names_by(fn) function M.dep_names_by(fn)
return M.deps_iter_by(fn):map(function(v) return v.name end) return M.deps_iter_by(fn):map(function(v) return v:name() end)
end end
function M.deps_iter_by(fn) function M.deps_iter_by(fn)
return vim.iter(deps):map(function(k, v) return v end):filter(fn) return vim.iter(Dep.all()):map(function(k, v) return v end):filter(fn)
end end
function M.non_lazy_deps() function M.non_lazy_deps()
return M.deps_iter_by(function(dep) return M.deps_iter_by(function(dep)
return not dep.lazy return not dep.is_lazy
end):totable() end):totable()
end end
function M.lazy_deps() function M.lazy_deps()
return M.deps_iter_by(function(dep) return M.deps_iter_by(function(dep)
return dep.lazy return dep.is_lazy
end):totable() end):totable()
end end
function lazy_load_cmd(dep, cmd)
return function(param)
M.load(dep.name)
local bang = param.bang and '!' or ''
vim.cmd(cmd .. bang .. ' ' .. param.args)
end
end
function lazy_load_ft(dep)
return function(param)
M.load(dep.name)
print(param.match)
vim.api.nvim_exec_autocmds('FileType', {
pattern = param.match,
})
end
end
function augroup_name(dep)
return "Sloth-plugin-" .. dep.name
end
function shim_plugin(dep)
if priv.is.shim[dep.name] then
return
end
priv.is.shim[dep.name] = true
if dep.cmd then
for _, cmd in ipairs(dep.cmd) do
vim.api.nvim_create_user_command(cmd, lazy_load_cmd(dep, cmd), {
desc = "Sloth-flake placeholder for plugin " .. dep.name,
nargs = '*',
bang = true,
})
end
end
if dep.ft then
local group_id = vim.api.nvim_create_augroup(augroup_name(dep), {
clear = true,
})
vim.api.nvim_create_autocmd('FileType', {
group = group_id,
pattern = dep.ft,
callback = lazy_load_ft(dep)
})
end
end
function unshim_plugin(name)
local dep = M.get(name)
if not priv.is.shim[name] then
return
end
priv.is.shim[name] = nil
if dep.cmd then
for _, cmd in ipairs(dep.cmd) do
vim.api.nvim_del_user_command(cmd)
end
end
if dep.ft then
vim.api.nvim_del_augroup_by_name(augroup_name(dep))
end
end
function name_compare(a, b)
if a < b then
return -1
elseif a > b then
return 1
else
return 0
end
end
local function vim_error(...)
vim.api.nvim_err_writeln(string.format(...))
end
local commands = {
list = function(args)
local filter = args[1] or "all"
local deps = vim.iter(M.dep_names())
if filter == "all" then
-- Nothing to do
elseif filter == "loaded" then
deps = deps:filter(function (dep)
return M.is_loaded(dep)
end)
elseif filter == "notloaded" then
deps = deps:filter(function (dep)
return not M.is_loaded(dep)
end)
else
vim_error([[No Sloth list filter "%s".]], cmd)
vim_error("Filters are: all, loaded, notloaded")
return
end
deps = deps:totable()
table.sort(deps, dep_name_compare)
for _, dep in ipairs(deps) do
print(string.format("- %s", dep))
end
end,
load = function(plugins)
if #plugins == 0 then
vim_error("You should at least give a plugin to load!")
return
end
for _, plugin in ipairs(plugins) do
M.load(plugin)
end
end
}
function sloth_cmd(param)
local args = param.fargs
local cmd = args[1] or "list";
table.remove(args, 1)
local fn = commands[cmd]
if fn then
fn(args)
else
vim.api.nvim_err_writeln(string.format([[No Sloth subcommand "%s"]], cmd))
end
end
function register_command()
vim.api.nvim_create_user_command('Sloth', sloth_cmd, {
nargs = '*',
})
end
function M.setup(config) function M.setup(config)
if priv.setup_called then if priv.setup_called then
return return
@ -266,10 +67,10 @@ function M.setup(config)
local lazy_deps = M.lazy_deps() local lazy_deps = M.lazy_deps()
for _, dep in ipairs(lazy_deps) do for _, dep in ipairs(lazy_deps) do
shim_plugin(dep) dep:shim()
end end
register_command() command.register()
end end
return M return M

View File

@ -0,0 +1,104 @@
local M = {}
local stateMeta
local function are_both_states(a, b)
return a.is_state and b.is_state
end
stateMeta = {
__tostring = function(v)
return v.name
end,
__le = function(self, other)
if not are_both_states(self, other) then
return false
end
return self.idx <= other.idx
end,
__lt = function(self, other)
if not are_both_states(self, other) then
return false
end
return self.idx < other.idx
end,
__index = function(self, name)
if name == 'is_state' then
return true
end
end
}
function M.build_states(defs)
local states = {}
for i, name in ipairs(defs) do
local state = setmetatable({ idx = i, name = name }, stateMeta)
states[i] = state
states[name] = state
end
return states
end
local SM = {}
local function empty_fn()
end
function SM:run_enter_state(state)
local enter_fn = self.defs.enter and self.defs.enter[state] or empty_fn
enter_fn(self.state)
end
function SM:run_exit_state(state)
local exit_fn = self.defs.exit and self.defs.exit[state] or empty_fn
exit_fn(self.state)
end
local function wrap_state_array(val)
return val.is_state and { val } or val
end
local function canonicalize_event(event)
return {
from = wrap_state_array(event.from),
to = event.to,
transition = event.transition or function() end,
}
end
function M.build(states, defs)
local machine = {
state = states[1],
defs = defs,
}
local prototype = {}
for name, infos in pairs(defs.events) do
local event = canonicalize_event(infos)
prototype[name] = function(self)
if not vim.list_contains(event.from, self.state) then
return false
end
local previous = self.state
self:run_exit_state(previous)
self.state = event.to
event.transition(previous, self.state)
self:run_enter_state(self.state)
return true
end
end
local ret = setmetatable(machine, { __index = vim.tbl_extend('error', SM, prototype)})
ret:run_enter_state(states[1])
return ret
end
local State = M.build_states {
'NotLoaded',
'Shimed',
'Inited',
'Imported',
'Loaded',
}
return M

11
lua/sloth-flake/utils.lua Normal file
View File

@ -0,0 +1,11 @@
local M = {}
function M.info(...)
print(string.format(...))
end
function M.error(...)
vim.api.nvim_err_writeln(string.format(...))
end
return M

View File

@ -1,13 +1,15 @@
{ {
pkgs, formatter,
nil, nil,
pkgs,
... ...
}: }:
with pkgs; with pkgs;
mkShell { mkShell {
buildInputs = [ buildInputs = [
formatter
git-cliff
nil nil
sumneko-lua-language-server sumneko-lua-language-server
git-cliff
]; ];
} }