Merge branch 'main' into add-hcl-not-terraform

This commit is contained in:
ppenguin 2024-10-31 17:28:28 +01:00
commit 3d426881ba
No known key found for this signature in database
GPG key ID: 7E7143B546BB17A7
151 changed files with 5385 additions and 2580 deletions

View file

@ -16,7 +16,7 @@ If you have any questions regarding those files, feel free to open an issue or [
## Contributing ## Contributing
The contribution process is mostly documented in the [pull request template](.github/pull_request_template.md). You will find a checklist of items to complete before submitting a pull request. Please make sure you complete it before submitting a pull request. If you are unsure about any of the items, please ask. The contribution process is mostly documented in the [pull request template](pull_request_template.md). You will find a checklist of items to complete before submitting a pull request. Please make sure you complete it before submitting a pull request. If you are unsure about any of the items, please ask.
### Guidelines ### Guidelines

View file

@ -1,39 +0,0 @@
# Description
A clear and concise description of the aim of your Pull Request.
**If your pull request aims to fix an open issue or a present bug, please link the relevant issue below. If not, please remove this section**
Fixes #(issue)
## Type of change
Please delete any options that are not relevant.
- Bug fix (non-breaking change which fixes an issue)
- New feature (non-breaking change which adds functionality)
- Breaking change (fix or feature that would cause existing functionality to not work as expected)
- Translation/Language update
- Docs
- Other
## Checklist
Please try to check at least a majority of the checklist before opening your pull request. Exceptions to this will be reviewed on a case by case basis.
- [ ] My code follows the style and contributing guidelines of this project.
- [ ] I ran Alejandra to format my code (`nix fmt`).
- [ ] I have performed a self-review of my own code and tested it.
- [ ] I have commented my code, particularly in hard-to-understand areas.
- [ ] My changes generate no new warnings.
- [ ] This change requires a documentation update.
- [ ] I have updated the documentation accordingly.
## Screenshots & Logs
You are kindly requested to attach screenshots of your changes in actions and preferably your build/run logs for all available packages. If you are not sure how to do this, you can refer to the [documentation](https://notashelf.github.io/neovim-flake/).
**Please do not use any external image service. Instead, just paste in or drag and drop the image here, and it will be uploaded automatically.**
```console
# Paste your logs here
```

198
.github/README.md vendored
View file

@ -33,10 +33,9 @@
<div align="center"> <div align="center">
<a> <a>
A highly modular, configurable, extensible and easy to use Neovim configuration nvf is a highly modular, configurable, extensible and easy to use Neovim configuration
framework in Nix. Designed for flexibility and ease of use, this flake in Nix. Designed for flexibility and ease of use, nvf allows you to easily configure
allows you to easily configure your Neovim instance with a few lines of your fully featured Neovim instance with a few lines of Nix.
Nix code.
</a> </a>
</div> </div>
@ -44,6 +43,7 @@
<div align="center"><p> <div align="center"><p>
[Features]: #features
[Get Started]: #get-started [Get Started]: #get-started
[Documentation]: #documentation [Documentation]: #documentation
[Help]: #help [Help]: #help
@ -51,119 +51,156 @@
[FAQ]: #faq [FAQ]: #faq
[Credits]: #credits [Credits]: #credits
**[<kbd><br>Get Started<br></kbd>][Get Started]** **[<kbd><br>Features <br></kbd>][Features]**
**[<kbd><br>Documentation<br></kbd>][Documentation]** **[<kbd><br>Get Started<br></kbd>][Get Started]**
**[<kbd><br>Help<br></kbd>][Help]** **[<kbd><br>Documentation<br></kbd>][Documentation]**
**[<kbd><br>Contribute<br></kbd>][Contribute]** **[<kbd><br>Help<br></kbd>][Help]**
**[<kbd><br>FAQ<br></kbd>][Faq]** **[<kbd><br>Contribute<br></kbd>][Contribute]**
**[<kbd><br>Credits<br></kbd>][Credits]** **[<kbd><br>FAQ<br></kbd>][Faq]** **[<kbd><br>Credits<br></kbd>][Credits]**
</p></div> </p></div>
--- ---
## Features
- **Reproducible**: Your configuration will behave the same _anywhere_. No
surprises, promise!
- **Portable**: nvf depends _solely_ on your Nix store, and nothing else. No
more global binaries! Works on all platforms, without hassle.
- **Customizable**: There are _almost no defaults_ to annoy you. nvf is fully
customizable through the Nix module system.
- **Well-documented**: Documentation is priority. You will _never_ face
undocumented, obscure behaviour.
- **Idiomatic**: nvf does things ✨ _the right way_ ✨ - the codebase is, and
will, remain maintainable for myself and any contributors.
## Get Started ## Get Started
### Using `nix` CLI [nvf manual]: https://notashelf.github.io/nvf/
[issue tracker]: https://github.com/NotAShelf/nvf/issues
If you would like to try out the configuration before even thinking about If you are not sold on the concepts of **nvf**, and would like to try out the
installing it, you can run the following command default configuration before even _thinking about_ installing it, you may run
the following in order to take **nvf** out for a spin.
```console ```bash
# Run the default package
nix run github:notashelf/nvf nix run github:notashelf/nvf
``` ```
This will get you a feel for the base configuration and UI design. This will get you a feel for the base configuration and UI design. Though, none
The flake exposes `#nix` as the default package, providing minimal of the configuration options are final as **nvf** is designed to be modular and
language support and various utilities.You may also use `#nix`, configurable.
`#tidal` or `#maximal` to get try out different configurations.
It is as simple as changing the target output to get a different > [!TIP]
configuration. For example, to get a configuration with `tidal` support, run: > The flake exposes `#nix` as the default package, providing minimal language
> support and various utilities. You may also use the `#nix` or `#maximal`
> packages provided by the this flake to get try out different configurations.
```console It is as simple as changing the target output to get a different configuration.
nix run github:notashelf/nvf#tidal For example, to get a configuration with large language coverage, run:
```bash
# Run the maximal package
nix run github:notashelf/nvf#maximal
``` ```
Similar instructions will apply for `nix profile install`. However, you are Similar instructions will apply for `nix profile install`. However, you are
recommended to instead use the module system as described in the manual. recommended to instead use the module system as described in the manual.
> [!NOTE] > [!NOTE]
> The `maximal` configuration is _massive_ and will take a while to build. > The `maximal` configuration is quite large, and might take a while to build.
> To get a feel for the configuration, use the default `nix` or `tidal` > To get a feel for the configuration, use the default `nix` configuration.
> configurations. Should you choose to try out the `maximal` configuration, > Should you choose to try out the `maximal` configuration, using the binary
> using the binary cache as described in the manual is _strongly_ recommended. > cache as described in the manual is _strongly_ recommended.
If you are convinced, proceed to the next section to view the installation
instructions.
## Documentation ## Documentation
See the [**nvf** Manual](https://notashelf.github.io/nvf/) for The _recommended_ way of installing **nvf** is using either the NixOS or the
detailed installation guides, configurations, available options, release notes Home-Manager module, though it is completely possible and no less supported to
and more. Tips for installing userspace plugins is also contained in the install **nvf** as a standalone package, or a flake output.
documentation.
If you want to dive right into trying **nvf** you can get a fully See the rendered [nvf manual] for detailed and up-to-date installation guides,
featured configuration with `nix` language support by running: configurations, available options, release notes and more. Tips for installing
userspace plugins is also contained in the documentation.
```console > [!TIP]
nix run github:notashelf/nvf#nix > While using NixOS or Home-Manager modules,
``` > `programs.nvf.enableManpages = true;` will allow you to view option
> documentation from the comfort of your terminal via `man 5 nvf`. The more you
> know.
[Issues]: https://github.com/NotAShelf/nvf/issues Please create an issue on the [issue tracker] if you find the documentation
lacking or confusing. Any improvements to the documentation through pull
Please create an issue on the [issue tracker](issues) if you find requests are also welcome, and appreciated.
the documentation lacking or confusing. I also appreciate any contributions
to the documentation.
## Help ## Help
You can create an issue on the [issue tracker](issues) to ask questions You can create an issue on the [issue tracker] to ask questions or report bugs.
or report bugs. I am not yet on spaces like matrix or IRC, so please use the issue I am not yet on spaces like matrix or IRC, so please use the issue tracker for
tracker for now. now.
## Contributing ## Contributing
I am always looking for new ways to help improve this flake. If you would like I am always looking for new ways to help improve this flake. If you would like
to contribute, please read the [contributing guide](CONTRIBUTING.md) before to contribute, please read the [contributing guide](CONTRIBUTING.md) before
submitting a pull request. You can also create an issue on the submitting a pull request. You can also create an issue on the [issue tracker]
[issue tracker](issues) before submitting a pull request if you would before submitting a pull request if you would like to discuss a feature or bug
like to discuss a feature or bug fix. fix.
## FAQ ## FAQ
[appropriate issue template]: https://github.com/NotAShelf/nvf/issues/new/choose
[list of branches]: https://github.com/NotAShelf/nvf/branches
[list of open pull requests]: https://github.com/NotAShelf/nvf/pulls
**Q**: What platforms are supported?
<br/> **A**: nvf actively supports Linux and Darwin platforms using standalone
Nix, NixOS or Home-Manager. Please take a look at the
**Q**: Can you add _X_? **Q**: Can you add _X_?
<br/> <br/> **A**: Maybe! It is not one of our goals to support each and every Neovim
**A**: Maybe! It is not one of our goals to support each and every Neovim plugin, however, I am always open to new modules and plugin setup additions to
plugin, however, I am always open to new modules and plugin setup additions **nvf**. Use the [appropriate issue template] and I will consider a module
to **nvf**. Use the [appropritate issue template](issues/new/choose) and I will addition. As mentioned before, PRs adding new features are also welcome.
consider a module addition.
**Q**: A plugin I need is not available in **nvf**. What to do? **Q**: A plugin I need is not available in **nvf**. What to do?
<br/> <br/> **A**: **nvf** exposes several APIs for you to be able to add your own
**A**: **nvf** exposes several APIs for you to be able to add your own plugin configurations! Please see the documentation on how you may do this.
plugin configurations! Please see the documentation on how you may do
this.
**Q**: Main branch is awfully silent, is the project dead? **Q**: Main branch is awfully silent, is the project dead?
<br/> <br/> **A**: No! Sometimes we branch out (e.g. `v0.6`) to avoid breaking
**A**: No! Sometimes we branch out (e.g. v0.6) to avoid breaking userspace userspace and work in a separate branch until we make sure the new additions are
and work in a separate branch until we make sure the new additions are implemented in the most comfortable way possible for the end user. If you have
implemented in the most comfortable way available to the end user. If you have not noticed any activity on the main branch, consider taking a look at the
not noticed any activity on the main branch, consider taking a look at the [list [list of branches] or the [list of open pull requests]. You may also consider
of branches](https://github.com/NotAShelf/nvf/branches=) or the [list of open _testing_ those release branches to get access to new features ahead of time and
pull requests](https://github.com/NotAShelf/nvf) better prepare to breaking changes.
## Credits ## Credits
### Contributors ### Contributors
Special thanks to Special, heart-felt thanks to
- [@fufexan](https://github.com/fufexan) - For the transition to flake-parts - [@fufexan](https://github.com/fufexan) - For the transition to flake-parts
- [@FlafyDev](https://github.com/FlafyDev) - For getting the home-manager to work - [@FlafyDev](https://github.com/FlafyDev) - For getting the home-manager to
- [@n3oney](https://github.com/n3oney) - For making custom keybinds finally possible work
- [@horriblename](https://github.com/horriblename) - For actively implementing planned features and quality of life updates - [@n3oney](https://github.com/n3oney) - For making custom keybinds finally
possible
- [@horriblename](https://github.com/horriblename) - For actively implementing
planned features and quality of life updates
- [@Yavko](https://github.com/Yavko) - For the amazing **nvf** logo - [@Yavko](https://github.com/Yavko) - For the amazing **nvf** logo
- [@FrothyMarrow](https://github.com/FrothyMarrow) - For seeing mistakes that I could not - [@FrothyMarrow](https://github.com/FrothyMarrow) - For seeing mistakes that I
could not
- [@Diniamo](https://github.com/Diniamo) - For actively submitting PRs, pull
requests and overall assistence
- [@Gerg-l](https://github.com/gerg-l) - For the modern Neovim wrapper, mnw and
occasional code improvements
and everyone who has submitted issues or pull requests! and everyone who has submitted issues or pull requests!
@ -172,10 +209,18 @@ and everyone who has submitted issues or pull requests!
This configuration borrows from and is based on a few other configurations, This configuration borrows from and is based on a few other configurations,
including: including:
- [@jordanisaacs's](https://github.com/jordanisaacs) [neovim-flake](https://github.com/jordanisaacs/neovim-flake) that this flake is originally based on. - [@jordanisaacs's](https://github.com/jordanisaacs)
- [@sioodmy's](https://github.com/sioodmy) [dotfiles](https://github.com/sioodmy/dotfiles) that inspired the design choices. [neovim-flake](https://github.com/jordanisaacs/neovim-flake) that this flake
- [@wiltaylor's](https://github.com/wiltaylor) [neovim-flake](https://github.com/wiltaylor/neovim-flake) for plugin and design ideas. is originally based on.
- [@gvolpe's](https://github.com/gvolpe) [neovim-flake](https://github.com/gvolpe/neovim-flake) for plugin, design and nix concepts. - [@sioodmy's](https://github.com/sioodmy)
[dotfiles](https://github.com/sioodmy/dotfiles) that inspired the design
choices.
- [@wiltaylor's](https://github.com/wiltaylor)
[neovim-flake](https://github.com/wiltaylor/neovim-flake) for plugin and
design ideas.
- [@gvolpe's](https://github.com/gvolpe)
[neovim-flake](https://github.com/gvolpe/neovim-flake) for plugin, design and
nix concepts.
I am grateful for their previous work and inspiration, and I wholeheartedly I am grateful for their previous work and inspiration, and I wholeheartedly
recommend checking their work out. recommend checking their work out.
@ -183,11 +228,14 @@ recommend checking their work out.
## License ## License
Following the license of the [original neovim-flake](https://github.com/jordanisaacs/neovim-flake), Following the license of the
**nvf** has been made available under the [**MIT License**](LICENSE). However, all assets [original neovim-flake](https://github.com/jordanisaacs/neovim-flake), **nvf**
and documentation are published under the has been made available under the [**MIT License**](LICENSE). However, all
assets and documentation are published under the
[**CC BY License**](https://github.com/NotAShelf/nvf/blob/main/.github/assets/LICENSE). [**CC BY License**](https://github.com/NotAShelf/nvf/blob/main/.github/assets/LICENSE).
<h6 align="center">Yes, this includes the logo work too. Stop taking artwork that is not yours!</h6>
--- ---
<div align="right"> <div align="right">

57
.github/pull_request_template.md vendored Normal file
View file

@ -0,0 +1,57 @@
<!--
^ Please include a clear and concise description of the aim of your Pull Request above this line ^
For plugin dependency/module additions, please make sure to link the source link of the added plugin
or dependency in this section.
If your pull request aims to fix an open issue or a please bug, please also link the relevant issue
below this line. You may attach an issue to your pull request with `Fixes #<issue number>` outside
this comment.
-->
## Sanity Checking
<!--
Please check all that apply. As before, this section is not a hard requirement but checklists with more checked
items are likely to be merged faster. You may save some time in maintainer review by performing self-reviews here
before submitting your pull request.
If your pull request includes any change or unexpected behaviour not covered below, please do make sure to include
it above in your description.
-->
[editorconfig]: https://editorconfig.org
[changelog]: https://github.com/NotAShelf/nvf/tree/main/docs/release-notes
- [ ] I have updated the [changelog] as per my changes.
- [ ] I have tested, and self-reviewed my code.
- Style and consistency
- [ ] I ran **Alejandra** to format my code (`nix fmt`).
- [ ] My code conforms to the [editorconfig] configuration of the project.
- [ ] My changes are consistent with the rest of the codebase.
- If new changes are particularly complex:
- [ ] My code includes comments in particularly complex areas
- [ ] I have added a section in the manual.
- [ ] _(For breaking changes)_ I have included a migration guide.
- Package(s) built:
- [ ] `.#nix` (default package)
- [ ] `.#maximal`
- [ ] `.#docs-html`
- Tested on platform(s)
- [ ] `x86_64-linux`
- [ ] `aarch64-linux`
- [ ] `x86_64-darwin`
- [ ] `aarch64-darwin`
<!--
If your changes touch upon a portion of the codebase that you do not understand well, please make sure to consult
the maintainers on your changes. In most cases, making an issue before creating your PR will help you avoid duplicate
efforts in the long run.
-->
---
Add a :+1: [reaction] to [pull requests you find important].
[reaction]: https://github.blog/2016-03-10-add-reactions-to-pull-requests-issues-and-comments/
[pull requests you find important]: https://github.com/NixOS/nixpkgs/pulls?q=is%3Aopen+sort%3Areactions-%2B1-desc

22
.github/workflows/cleanup.yml vendored Normal file
View file

@ -0,0 +1,22 @@
name: Cleanup
on:
workflow_dispatch:
schedule:
- cron: "0 4 1 * *" # 4AM on 1st of every month
- cron: "0 4 15 * *" # 4AM on the 15th of every month
jobs:
branches:
name: Cleanup old branches
runs-on: ubuntu-latest
steps:
- name: "Checkout"
uses: actions/checkout@v4
- name: "Delete old branches"
uses: beatlabs/delete-old-branches-action@v0.0.10
with:
repo_token: "${{ secrets.GITHUB_TOKEN }}"
date: "1 months ago"
dry_run: false
delete_tags: false
exclude_open_pr_branches: true

View file

@ -1,4 +1,5 @@
name: "Build and deploy documentation" name: "Build and deploy documentation"
on: on:
workflow_dispatch: workflow_dispatch:
push: push:
@ -7,6 +8,7 @@ on:
paths: paths:
# build the manuals only when docs directory is updated # build the manuals only when docs directory is updated
- docs/** - docs/**
- modules/**
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions: permissions:
@ -20,23 +22,34 @@ concurrency:
cancel-in-progress: true cancel-in-progress: true
jobs: jobs:
check_date:
runs-on: ubuntu-latest
name: Check latest commit
outputs:
should_run: ${{ steps.should_run.outputs.should_run }}
steps:
- uses: actions/checkout@v4.1.7
- name: print latest_commit
run: echo ${{ github.sha }}
- id: should_run
continue-on-error: true
name: check latest commit is less than a day
if: ${{ github.event_name == 'schedule' }}
run: test -z $(git rev-list --after="24 hours" ${{ github.sha }}) && echo "::set-output name=should_run::false"
publish: publish:
needs: check_date
if: ${{ needs.check_date.outputs.should_run != 'false' }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - uses: actions/checkout@v4.1.7
uses: actions/checkout@v4 - uses: DeterminateSystems/nix-installer-action@main
- name: Install Nix
uses: DeterminateSystems/nix-installer-action@main
- uses: DeterminateSystems/magic-nix-cache-action@main - uses: DeterminateSystems/magic-nix-cache-action@main
- run: |
- name: Build nix build .#docs
run: |
nix build '.#docs'
cp -r result/share/doc/nvf public cp -r result/share/doc/nvf public
- uses: peaceiris/actions-gh-pages@v4
- name: Deploy
uses: peaceiris/actions-gh-pages@v4
with: with:
github_token: ${{ secrets.GITHUB_TOKEN }} github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./public publish_dir: ./public

View file

@ -19,6 +19,7 @@ isMaximal: {
lspsaga.enable = false; lspsaga.enable = false;
trouble.enable = true; trouble.enable = true;
lspSignature.enable = true; lspSignature.enable = true;
otter-nvim.enable = isMaximal;
lsplines.enable = isMaximal; lsplines.enable = isMaximal;
nvim-docs-view.enable = isMaximal; nvim-docs-view.enable = isMaximal;
}; };
@ -45,48 +46,50 @@ isMaximal: {
nix.enable = true; nix.enable = true;
# Assembly is not common, and the asm LSP is a major hit-or-miss
assembly.enable = false;
markdown.enable = isMaximal; markdown.enable = isMaximal;
html.enable = isMaximal; html.enable = isMaximal;
css.enable = isMaximal; css.enable = isMaximal;
sql.enable = isMaximal; sql.enable = isMaximal;
java.enable = isMaximal; java.enable = isMaximal;
kotlin.enable = isMaximal;
ts.enable = isMaximal; ts.enable = isMaximal;
svelte.enable = isMaximal; svelte.enable = isMaximal;
go.enable = isMaximal; go.enable = isMaximal;
lua.enable = isMaximal;
elixir.enable = isMaximal; elixir.enable = isMaximal;
zig.enable = isMaximal; zig.enable = isMaximal;
ocaml.enable = isMaximal; ocaml.enable = isMaximal;
python.enable = isMaximal; python.enable = isMaximal;
dart.enable = isMaximal; dart.enable = isMaximal;
bash.enable = isMaximal; bash.enable = isMaximal;
r.enable = isMaximal;
tailwind.enable = isMaximal; tailwind.enable = isMaximal;
typst.enable = isMaximal; typst.enable = isMaximal;
clang = { clang.enable = isMaximal;
enable = isMaximal; scala.enable = isMaximal;
lsp.server = "clangd";
};
rust = { rust = {
enable = isMaximal; enable = isMaximal;
crates.enable = isMaximal; crates.enable = isMaximal;
}; };
csharp.enable = isMaximal;
julia.enable = isMaximal;
vala.enable = isMaximal;
}; };
visuals = { visuals = {
enable = true; nvim-scrollbar.enable = isMaximal;
nvimWebDevicons.enable = true; nvim-web-devicons.enable = true;
scrollBar.enable = isMaximal; nvim-cursorline.enable = true;
smoothScroll.enable = true; cinnamon-nvim.enable = true;
cellularAutomaton.enable = false;
fidget-nvim.enable = true; fidget-nvim.enable = true;
highlight-undo.enable = true; highlight-undo.enable = true;
indent-blankline.enable = true;
indentBlankline.enable = true; # Fun
cellular-automaton.enable = false;
cursorline = {
enable = true;
lineTimeout = 0;
};
}; };
statusline = { statusline = {
@ -103,15 +106,13 @@ isMaximal: {
transparent = false; transparent = false;
}; };
autopairs.enable = true; autopairs.nvim-autopairs.enable = true;
autocomplete = { autocomplete.nvim-cmp.enable = true;
enable = true; snippets.luasnip.enable = true;
type = "nvim-cmp";
};
filetree = { filetree = {
nvimTree = { neo-tree = {
enable = true; enable = true;
}; };
}; };
@ -154,7 +155,7 @@ isMaximal: {
}; };
utility = { utility = {
ccc.enable = isMaximal; ccc.enable = false;
vim-wakatime.enable = false; vim-wakatime.enable = false;
icon-picker.enable = isMaximal; icon-picker.enable = isMaximal;
surround.enable = isMaximal; surround.enable = isMaximal;
@ -162,6 +163,7 @@ isMaximal: {
motion = { motion = {
hop.enable = true; hop.enable = true;
leap.enable = true; leap.enable = true;
precognition.enable = isMaximal;
}; };
images = { images = {
@ -171,6 +173,7 @@ isMaximal: {
notes = { notes = {
obsidian.enable = false; # FIXME: neovim fails to build if obsidian is enabled obsidian.enable = false; # FIXME: neovim fails to build if obsidian is enabled
neorg.enable = false;
orgmode.enable = false; orgmode.enable = false;
mind-nvim.enable = isMaximal; mind-nvim.enable = isMaximal;
todo-comments.enable = true; todo-comments.enable = true;

View file

@ -2,131 +2,131 @@
inputs, inputs,
pkgs, pkgs,
lib, lib,
manpageUrls ? pkgs.path + "/doc/manpage-urls.json",
...
}: let }: let
inherit (lib.modules) mkForce evalModules; inherit ((lib.importJSON ../release.json)) release;
inherit (lib.strings) hasPrefix removePrefix;
inherit (lib.attrsets) isAttrs mapAttrs optionalAttrs recursiveUpdate isDerivation;
inherit (builtins) fromJSON readFile;
# release data nvimModuleDocs = pkgs.nixosOptionsDoc {
release-config = fromJSON (readFile ../release.json);
revision = release-config.release;
# From home-manager:
#
# Recursively replace each derivation in the given attribute set
# with the same derivation but with the `outPath` attribute set to
# the string `"\${pkgs.attribute.path}"`. This allows the
# documentation to refer to derivations through their values without
# establishing an actual dependency on the derivation output.
#
# This is not perfect, but it seems to cover a vast majority of use
# cases.
#
# Caveat: even if the package is reached by a different means, the
# path above will be shown and not e.g.
# `${config.services.foo.package}`.
scrubDerivations = prefixPath: attrs: let
scrubDerivation = name: value: let
pkgAttrName = prefixPath + "." + name;
in
if isAttrs value
then
scrubDerivations pkgAttrName value
// optionalAttrs (isDerivation value) {
outPath = "\${${pkgAttrName}}";
}
else value;
in
mapAttrs scrubDerivation attrs;
# Make sure the used package is scrubbed to avoid actually
# instantiating derivations.
scrubbedPkgsModule = {
imports = [
{
_module.args = {
pkgs = mkForce (scrubDerivations "pkgs" pkgs);
pkgs_i686 = mkForce {};
};
}
];
};
# Specify the path to the module entrypoint
nvimPath = toString ./..;
buildOptionsDocs = args @ {
modules,
includeModuleSystemOptions ? true,
warningsAreErrors ? true,
...
}: let
inherit ((evalModules {inherit modules;})) options;
# Declaration of the Github site URL.
# Takes a user, repo, and subpath, and returns a declaration site
# as a string.
githubDeclaration = user: repo: subpath: let
urlRef = "github.com";
branch = "main";
in {
url = "https://${urlRef}/${user}/${repo}/blob/${branch}/${subpath}";
name = "<${repo}/${subpath}>";
};
in
pkgs.buildPackages.nixosOptionsDoc ({
inherit warningsAreErrors;
options =
if includeModuleSystemOptions
then options
else builtins.removeAttrs options ["_module"];
transformOptions = opt:
recursiveUpdate opt {
# Clean up declaration sites to not refer to the nvf
# source tree.
declarations = map (decl:
if hasPrefix nvimPath (toString decl)
then
githubDeclaration "notashelf" "nvf"
(removePrefix "/" (removePrefix nvimPath (toString decl)))
else if decl == "lib/modules.nix"
then
# TODO: handle this in a better way (may require upstream
# changes to nixpkgs)
githubDeclaration "NixOS" "nixpkgs" decl
else decl)
opt.declarations;
};
}
// builtins.removeAttrs args ["modules" "includeModuleSystemOptions"]);
nvimModuleDocs = buildOptionsDocs {
variablelistId = "nvf-options"; variablelistId = "nvf-options";
warningsAreErrors = true;
modules = inherit
import ../modules/modules.nix { (
inherit lib pkgs; (lib.evalModules {
check = false; modules =
} import ../modules/modules.nix {
++ [scrubbedPkgsModule]; inherit lib pkgs;
}
++ [
(
let
# From nixpkgs:
#
# Recursively replace each derivation in the given attribute set
# with the same derivation but with the `outPath` attribute set to
# the string `"\${pkgs.attribute.path}"`. This allows the
# documentation to refer to derivations through their values without
# establishing an actual dependency on the derivation output.
#
# This is not perfect, but it seems to cover a vast majority of use
# cases.
#
# Caveat: even if the package is reached by a different means, the
# path above will be shown and not e.g.
# `${config.services.foo.package}`.
scrubDerivations = namePrefix: pkgSet:
builtins.mapAttrs (
name: value: let
wholeName = "${namePrefix}.${name}";
in
if builtins.isAttrs value
then
scrubDerivations wholeName value
// lib.optionalAttrs (lib.isDerivation value) {
inherit (value) drvPath;
outPath = "\${${wholeName}}";
}
else value
)
pkgSet;
in {
_module = {
check = false;
args.pkgs = lib.mkForce (scrubDerivations "pkgs" pkgs);
};
}
)
];
})
)
options
;
transformOptions = opt:
opt
// {
declarations =
map (
decl:
if lib.hasPrefix (toString ../.) (toString decl)
then
lib.pipe decl [
toString
(lib.removePrefix (toString ../.))
(lib.removePrefix "/")
(x: {
url = "https://github.com/NotAShelf/nvf/blob/main/${x}";
name = "<nvf/${x}>";
})
]
else if decl == "lib/modules.nix"
then {
url = "https://github.com/NixOS/nixpkgs/blob/master/${decl}";
name = "<nixpkgs/lib/modules.nix>";
}
else decl
)
opt.declarations;
};
}; };
# Generate the HTML manual pages
html = pkgs.callPackage ./manual.nix {
inherit release;
inherit (nvimModuleDocs) optionsJSON;
};
in {
inherit (inputs) nmd;
# TODO: Use `hmOptionsDocs.optionsJSON` directly once upstream
# `nixosOptionsDoc` is more customizable.
options.json =
pkgs.runCommand "options.json" {
meta.description = "List of nvf options in JSON format";
} ''
mkdir -p $out/{share/doc,nix-support}
cp -a ${nvimModuleDocs.optionsJSON}/share/doc/nixos $out/share/doc/nvf
substitute \
${nvimModuleDocs.optionsJSON}/nix-support/hydra-build-products \
$out/nix-support/hydra-build-products \
--replace \
'${nvimModuleDocs.optionsJSON}/share/doc/nixos' \
"$out/share/doc/nvf"
'';
# Generate the `man home-configuration.nix` package # Generate the `man home-configuration.nix` package
nvf-configuration-manual = manPages =
pkgs.runCommand "nvf-reference-manpage" { pkgs.runCommand "nvf-reference-manpage" {
nativeBuildInputs = [pkgs.buildPackages.installShellFiles pkgs.nixos-render-docs]; nativeBuildInputs = [
pkgs.buildPackages.installShellFiles
pkgs.nixos-render-docs
];
allowedReferences = ["out"]; allowedReferences = ["out"];
} '' } ''
# Generate manpages. # Generate manpages.
mkdir -p $out/share/man/man5 mkdir -p $out/share/man/{man5,man1}
mkdir -p $out/share/man/man1
nixos-render-docs -j $NIX_BUILD_CORES options manpage \ nixos-render-docs -j $NIX_BUILD_CORES options manpage \
--revision ${revision} \ --revision ${release} \
--header ${./man/header.5} \ --header ${./man/header.5} \
--footer ${./man/footer.5} \ --footer ${./man/footer.5} \
${nvimModuleDocs.optionsJSON}/share/doc/nixos/options.json \ ${nvimModuleDocs.optionsJSON}/share/doc/nixos/options.json \
@ -135,38 +135,8 @@
cp ${./man/nvf.1} $out/share/man/man1/nvf.1 cp ${./man/nvf.1} $out/share/man/man1/nvf.1
''; '';
# Generate the HTML manual pages manual = {
nvf-manual = pkgs.callPackage ./manual.nix { inherit html;
inherit revision manpageUrls; htmlOpenTool = pkgs.callPackage ./html-open-tool.nix {inherit html;};
outputPath = "share/doc/nvf";
options = {
nvf = nvimModuleDocs.optionsJSON;
};
}; };
html = nvf-manual;
htmlOpenTool = pkgs.callPackage ./html-open-tool.nix {} {inherit html;};
in {
inherit (inputs) nmd;
options = {
# TODO: Use `hmOptionsDocs.optionsJSON` directly once upstream
# `nixosOptionsDoc` is more customizable.
json =
pkgs.runCommand "options.json" {
meta.description = "List of nvf options in JSON format";
} ''
mkdir -p $out/{share/doc,nix-support}
cp -a ${nvimModuleDocs.optionsJSON}/share/doc/nixos $out/share/doc/nvf
substitute \
${nvimModuleDocs.optionsJSON}/nix-support/hydra-build-products \
$out/nix-support/hydra-build-products \
--replace \
'${nvimModuleDocs.optionsJSON}/share/doc/nixos' \
"$out/share/doc/nvf"
'';
};
manPages = nvf-configuration-manual;
manual = {inherit html htmlOpenTool;};
} }

View file

@ -2,13 +2,9 @@
writeShellScriptBin, writeShellScriptBin,
makeDesktopItem, makeDesktopItem,
symlinkJoin, symlinkJoin,
}: {
html, html,
pathName ? "nvf",
projectName ? pathName,
name ? "${pathName}-help",
}: let }: let
helpScript = writeShellScriptBin name '' helpScript = writeShellScriptBin "nvf-help" ''
set -euo pipefail set -euo pipefail
if [[ ! -v BROWSER || -z $BROWSER ]]; then if [[ ! -v BROWSER || -z $BROWSER ]]; then
@ -24,20 +20,23 @@
echo "$0: unable to start a web browser; please set \$BROWSER" echo "$0: unable to start a web browser; please set \$BROWSER"
exit 1 exit 1
else else
exec "$BROWSER" "${html}/share/doc/${pathName}/index.xhtml" exec "$BROWSER" "${html}/share/doc/nvf/index.xhtml"
fi fi
''; '';
desktopItem = makeDesktopItem { desktopItem = makeDesktopItem {
name = "${pathName}-manual"; name = "nvf-manual";
desktopName = "${projectName} Manual"; desktopName = "nvf Manual";
genericName = "View ${projectName} documentation in a web browser"; genericName = "View nvf documentation in a web browser";
icon = "nix-snowflake"; icon = "nix-snowflake";
exec = "${helpScript}/bin/${name}"; exec = "${helpScript}/bin/nvf-help";
categories = ["System"]; categories = ["System"];
}; };
in in
symlinkJoin { symlinkJoin {
inherit name; name = "nvf-help";
paths = [helpScript desktopItem]; paths = [
helpScript
desktopItem
];
} }

View file

@ -4,11 +4,10 @@
# build inputs # build inputs
nixos-render-docs, nixos-render-docs,
documentation-highlighter, documentation-highlighter,
path,
# nrd configuration # nrd configuration
manpageUrls, release,
revision, optionsJSON,
options,
outputPath ? "share/doc/nvf",
}: }:
stdenvNoCC.mkDerivation { stdenvNoCC.mkDerivation {
name = "nvf-manual"; name = "nvf-manual";
@ -20,9 +19,11 @@ stdenvNoCC.mkDerivation {
nativeBuildInputs = [nixos-render-docs]; nativeBuildInputs = [nixos-render-docs];
buildPhase = '' buildPhase = ''
mkdir -p out/{highlightjs,media} dest="$out/share/doc/nvf"
mkdir -p "$(dirname "$dest")"
mkdir -p $dest/{highlightjs,media}
cp -vt out/highlightjs \ cp -vt $dest/highlightjs \
${documentation-highlighter}/highlight.pack.js \ ${documentation-highlighter}/highlight.pack.js \
${documentation-highlighter}/LICENSE \ ${documentation-highlighter}/LICENSE \
${documentation-highlighter}/mono-blue.css \ ${documentation-highlighter}/mono-blue.css \
@ -31,38 +32,32 @@ stdenvNoCC.mkDerivation {
substituteInPlace ./options.md \ substituteInPlace ./options.md \
--subst-var-by \ --subst-var-by \
OPTIONS_JSON \ OPTIONS_JSON \
${options.nvf}/share/doc/nixos/options.json ${optionsJSON}/share/doc/nixos/options.json
substituteInPlace ./manual.md \ substituteInPlace ./manual.md \
--subst-var-by \ --subst-var-by \
NVF_VERSION \ NVF_VERSION \
${revision} ${release}
# copy stylesheet # copy stylesheet
cp ${./static/style.css} out/style.css cp ${./static/style.css} "$dest/style.css"
# copy release notes # copy release notes
cp -vr ${./release-notes} release-notes cp -vr ${./release-notes} release-notes
# generate manual from # generate manual from
nixos-render-docs manual html \ nixos-render-docs manual html \
--manpage-urls ${manpageUrls} \ --manpage-urls ${path + "/doc/manpage-urls.json"} \
--revision ${lib.trivial.revisionWithDefault revision} \ --revision ${lib.trivial.revisionWithDefault release} \
--stylesheet style.css \ --stylesheet style.css \
--script highlightjs/highlight.pack.js \ --script highlightjs/highlight.pack.js \
--script highlightjs/loader.js \ --script highlightjs/loader.js \
--toc-depth 2 \ --toc-depth 2 \
--section-toc-depth 1 \ --section-toc-depth 1 \
manual.md \ manual.md \
out/index.xhtml "$dest/index.xhtml"
'';
installPhase = '' mkdir -p $out/nix-support/
dest="$out/${outputPath}" echo "doc manual $dest index.html" >> $out/nix-support/hydra-build-products
mkdir -p "$(dirname "$dest")"
mv out "$dest"
mkdir -p $out/nix-support/
echo "doc manual $dest index.html" >> $out/nix-support/hydra-build-products
''; '';
} }

View file

@ -20,6 +20,7 @@ custom plugins that you might have added to your configuration.
```{=include=} sections ```{=include=} sections
custom-plugins/configuring.md custom-plugins/configuring.md
custom-plugins/new-method.md custom-plugins/lazy-method.md
custom-plugins/old-method.md custom-plugins/non-lazy-method.md
custom-plugins/legacy-method.md
``` ```

View file

@ -1,12 +1,32 @@
# Configuring {#sec-configuring-plugins} # Configuring {#sec-configuring-plugins}
Just making the plugin to your Neovim configuration available might not always Just making the plugin to your Neovim configuration available might not always be enough. In that
be enough. In that case, you can write custom lua config using either case, you can write custom lua config using either `config.vim.lazy.plugins.*.setupOpts`
`config.vim.extraPlugins` (which has the `setup` field) or `config.vim.extraPlugins.*.setup` or `config.vim.luaConfigRC`.
`config.vim.luaConfigRC`. The first option uses an attribute set, which maps DAG
section names to a custom type, which has the fields `package`, `after`, The first option uses an extended version of `lz.n`'s PluginSpec. `setupModule` and `setupOpt` can
`setup`. They allow you to set the package of the plugin, the sections its setup be used if the plugin uses a `require('module').setup(...)` pattern. Otherwise, the `before` and
code should be after (note that the `extraPlugins` option has its own DAG `after` hooks should do what you need.
```nix
{
config.vim.lazy.plugins = {
aerial.nvim = {
# ^^^^^^^^^ this name should match the package.pname or package.name
package = aerial-nvim;
setupModule = "aerial";
setupOpts = {option_name = false;};
after = "print('aerial loaded')";
};
};
}
```
The second option uses an attribute set, which maps DAG section names to a custom type, which has
the fields `package`, `after`, `setup`. They allow you to set the package of the plugin, the
sections its setup code should be after (note that the `extraPlugins` option has its own DAG
scope), and the its setup code respectively. For example: scope), and the its setup code respectively. For example:
```nix ```nix
@ -24,7 +44,7 @@ config.vim.extraPlugins = with pkgs.vimPlugins; {
} }
``` ```
The second option also uses an attribute set, but this one is resolved as a DAG The third option also uses an attribute set, but this one is resolved as a DAG
directly. The attribute names denote the section names, and the values lua code. directly. The attribute names denote the section names, and the values lua code.
For example: For example:

View file

@ -0,0 +1,40 @@
# Lazy Method {#sec-lazy-method}
As of version **0.7**, we exposed an API for configuring lazy-loaded plugins via
`lz.n` and `lzn-auto-require`.
```nix
{
config.vim.lazy.plugins = {
"aerial.nvim" = {
package = pkgs.vimPlugins.aerial-nvim;
setupModule = "aerial";
setupOpts = {
option_name = true;
};
after = ''
-- custom lua code to run after plugin is loaded
print('aerial loaded')
'';
# Explicitly mark plugin as lazy. You don't need this if you define one of
# the trigger "events" below
lazy = true;
# load on command
cmd = ["AerialOpen"];
# load on event
event = ["BufEnter"];
# load on keymap
keys = [
{
key = "<leader>a";
action = ":AerialToggle<CR>";
}
];
};
};
}
```

View file

@ -1,4 +1,4 @@
# Old Method {#sec-old-method} # Legacy Method {#sec-legacy-method}
Prior to version 0.5, the method of adding new plugins was adding the plugin Prior to version 0.5, the method of adding new plugins was adding the plugin
package to `vim.startPlugins` and add its configuration as a DAG under one of package to `vim.startPlugins` and add its configuration as a DAG under one of

View file

@ -1,4 +1,4 @@
# New Method {#sec-new-method} # Non-lazy Method {#sec-non-lazy-method}
As of version **0.5**, we have a more extensive API for configuring plugins, As of version **0.5**, we have a more extensive API for configuring plugins,
under `vim.extraPlugins`. Instead of using DAGs exposed by the library, you may under `vim.extraPlugins`. Instead of using DAGs exposed by the library, you may

View file

@ -5,16 +5,21 @@ can add code that relies on other code. However, if you don't know what the
entries are called, it's hard to do that, so here is a list of the internal entries are called, it's hard to do that, so here is a list of the internal
entries in nvf: entries in nvf:
`vim.luaConfigRC` (top-level DAG): ## `vim.luaConfigRC` (top-level DAG) {#ch-vim-luaconfigrc}
1. (`luaConfigPre`) - not a part of the actual DAG, instead, it's simply 1. (`luaConfigPre`) - not a part of the actual DAG, instead, it's simply
inserted before the rest of the DAG inserted before the rest of the DAG
2. `globalsScript` - used to set globals defined in `vim.globals` 2. `globalsScript` - used to set globals defined in `vim.globals`
3. `basic` - used to set basic configuration options 3. `basic` - used to set basic configuration options
4. `theme` (this is simply placed before `pluginConfigs`, meaning that surrounding entries don't depend on it) - used to set up the theme, which has to be done before other plugins 4. `optionsScript` - used to set options defined in `vim.o`
5. `pluginConfigs` - the result of the nested `vim.pluginRC` (internal option, 5. `theme` (this is simply placed before `pluginConfigs` and `lazyConfigs`, meaning that
see the [Custom Plugins](/index.xhtml#ch-custom-plugins) page for adding your own surrounding entries don't depend on it) - used to set up the theme, which has to be done before
plugins) DAG, used to set up internal plugins other plugins
6. `extraPluginConfigs` - the result of `vim.extraPlugins`, which is not a 6. `lazyConfigs` - `lz.n` and `lzn-auto-require` configs. If `vim.lazy.enable`
is false, this will contain each plugin's config instead.
7. `pluginConfigs` - the result of the nested `vim.pluginRC` (internal option,
see the [Custom Plugins](/index.xhtml#ch-custom-plugins) page for adding your
own plugins) DAG, used to set up internal plugins
8. `extraPluginConfigs` - the result of `vim.extraPlugins`, which is not a
direct DAG, but is converted to, and resolved as one internally direct DAG, but is converted to, and resolved as one internally
7. `mappings` - the result of `vim.maps` 9. `mappings` - the result of `vim.maps`

View file

@ -124,3 +124,61 @@ vim.your-plugin.setupOpts = {
''; '';
} }
``` ```
## Lazy plugins {#sec-lazy-plugins}
If the plugin can be lazy-loaded, `vim.lazy.plugins` should be used to add it. Lazy
plugins are managed by `lz.n`.
```nix
# in modules/.../your-plugin/config.nix
{lib, config, ...}:
let
cfg = config.vim.your-plugin;
in {
vim.lazy.plugins.your-plugin = {
# instead of vim.startPlugins, use this:
package = "your-plugin";
# if your plugin uses the `require('your-plugin').setup{...}` pattern
setupModule = "your-plugin";
inherit (cfg) setupOpts;
# events that trigger this plugin to be loaded
event = ["DirChanged"];
cmd = ["YourPluginCommand"];
# keymaps
keys = [
# we'll cover this in detail in the keymaps section
{
key = "<leader>d";
mode = "n";
action = ":YourPluginCommand";
}
];
};
;
}
```
This results in the following lua code:
```lua
require('lz.n').load({
{
"name-of-your-plugin",
after = function()
require('your-plugin').setup({--[[ your setupOpts ]]})
end,
event = {"DirChanged"},
cmd = {"YourPluginCommand"},
keys = {
{"<leader>d", ":YourPluginCommand", mode = {"n"}},
},
}
})
```
A full list of options can be found
[here](https://notashelf.github.io/nvf/options.html#opt-vim.lazy.plugins

View file

@ -7,37 +7,26 @@ section contains a general overview to how you may utilize said functions.
## Custom Key Mappings Support for a Plugin {#sec-custom-key-mappings} ## Custom Key Mappings Support for a Plugin {#sec-custom-key-mappings}
To set a mapping, you should define it in `vim.maps.<<mode>>`. To set a mapping, you should define it in `vim.keymaps`.
The available modes are:
- normal
- insert
- select
- visual
- terminal
- normalVisualOp
- visualOnly
- operator
- insertCommand
- lang
- command
An example, simple keybinding, can look like this: An example, simple keybinding, can look like this:
```nix ```nix
{ {
vim.maps.normal = { vim.keymaps = [
"<leader>wq" = { {
key = "<leader>wq";
mode = ["n"];
action = ":wq<CR>"; action = ":wq<CR>";
silent = true; silent = true;
desc = "Save file and quit"; desc = "Save file and quit";
}; }
}; ];
} }
``` ```
There are many settings available in the options. Please refer to the There are many settings available in the options. Please refer to the
[documentation](https://notashelf.github.io/nvf/options.html#opt-vim.maps.command._name_.action) [documentation](https://notashelf.github.io/nvf/options.html#opt-vim.keymaps)
to see a list of them. to see a list of them.
**nvf** provides a list of helper commands, so that you don't have to write the **nvf** provides a list of helper commands, so that you don't have to write the

View file

@ -26,6 +26,32 @@ making good use of its extensive Lua API. Additionally, Vimscript is slow and
brings unnecessary performance overhead while working with different brings unnecessary performance overhead while working with different
configuration formats. configuration formats.
### `vim.maps` rewrite {#sec-vim-maps-rewrite}
Instead of specifying map modes using submodules (eg.: `vim.maps.normal`), a new
`vim.keymaps` submodule with support for a `mode` option has been introduced. It
can be either a string, or a list of strings, where a string represents the
short-name of the map mode(s), that the mapping should be set for. See
`:help map-modes` for more information.
For example:
```nix
vim.maps.normal."<leader>m" = { ... };
```
has to be replaced by
```nix
vim.keymaps = [
{
key = "<leader>m";
mode = "n";
}
...
];
```
### `vim.lsp.nvimCodeActionMenu` removed in favor of `vim.ui.fastaction` {#sec-nvim-code-action-menu-deprecation} ### `vim.lsp.nvimCodeActionMenu` removed in favor of `vim.ui.fastaction` {#sec-nvim-code-action-menu-deprecation}
The nvim-code-action-menu plugin has been archived and broken for a long time, The nvim-code-action-menu plugin has been archived and broken for a long time,
@ -37,6 +63,24 @@ Note that we are looking to add more alternatives in the future like
dressing.nvim and actions-preview.nvim, in case fastaction doesn't work for dressing.nvim and actions-preview.nvim, in case fastaction doesn't work for
everyone. everyone.
### `type` based modules removed {#sec-type-based-modules-removed}
As part of the autocompletion rewrite, modules that used to use a `type` option
have been replaced by per-plugin modules instead. Since both modules only had
one type, you can simply change
- `vim.autocomplete.*` -> `vim.autocomplete.nvim-cmp.*`
- `vim.autopairs.enable` -> `vim.autopairs.nvim-autopairs.enable`
### `nixpkgs-fmt` removed in favor of `nixfmt` {#sec-nixpkgs-fmt-deprecation}
`nixpkgs-fmt` has been archived for a while, and it's finally being removed in
favor of nixfmt (more information can be found
[here](https://github.com/nix-community/nixpkgs-fmt?tab=readme-ov-file#nixpkgs-fmt---nix-code-formatter-for-nixpkgs).
To migrate to `nixfmt`, simply change `vim.languages.nix.format.type` to
`nixfmt`.
## Changelog {#sec-release-0.7-changelog} ## Changelog {#sec-release-0.7-changelog}
[ItsSorae](https://github.com/ItsSorae): [ItsSorae](https://github.com/ItsSorae):
@ -67,6 +111,9 @@ everyone.
- Add dap-go for better dap configurations - Add dap-go for better dap configurations
- Make noice.nvim customizable - Make noice.nvim customizable
- Standardize border style options and add custom borders - Standardize border style options and add custom borders
- Remove `vim.disableDefaultRuntimePaths` in wrapper options.
- As nvf uses `$NVIM_APP_NAME` as of recent changes, we can safely assume any
configuration in `$XDG_CONFIG_HOME/nvf` is intentional.
[rust-tools.nvim]: https://github.com/simrat39/rust-tools.nvim [rust-tools.nvim]: https://github.com/simrat39/rust-tools.nvim
[rustaceanvim]: https://github.com/mrcjkb/rustaceanvim [rustaceanvim]: https://github.com/mrcjkb/rustaceanvim
@ -76,17 +123,25 @@ everyone.
recommended to go through rustacean.nvim's README to take a closer look at its recommended to go through rustacean.nvim's README to take a closer look at its
features and usage features and usage
- Add [lz.n] support and lazy-load some builtin plugins.
[lz.n]: https://github.com/mrcjkb/lz.n
[jacekpoz](https://jacekpoz.pl): [jacekpoz](https://jacekpoz.pl):
[ocaml-lsp]: https://github.com/ocaml/ocaml-lsp [ocaml-lsp]: https://github.com/ocaml/ocaml-lsp
[new-file-template.nvim]: https://github.com/otavioschwanck/new-file-template.nvim [new-file-template.nvim]: https://github.com/otavioschwanck/new-file-template.nvim
[neo-tree.nvim]: https://github.com/nvim-neo-tree/neo-tree.nvim
- Add [ocaml-lsp] support - Add [ocaml-lsp] support
- Fix "Emac" typo - Fix "Emac" typo
- Add [new-file-template.nvim] to automatically fill new file contents using - Add [new-file-template.nvim] to automatically fill new file contents using
templates. templates
- Make [neo-tree.nvim] display file icons properly by enabling
`visuals.nvimWebDevicons`
[diniamo](https://github.com/diniamo): [diniamo](https://github.com/diniamo):
@ -108,6 +163,7 @@ everyone.
plugin's options can now be found under `indentBlankline.setupOpts`, the plugin's options can now be found under `indentBlankline.setupOpts`, the
previous iteration of the module also included out of place/broken options, previous iteration of the module also included out of place/broken options,
which have been removed for the time being. These are: which have been removed for the time being. These are:
- `listChar` - this was already unused - `listChar` - this was already unused
- `fillChar` - this had nothing to do with the plugin, please configure it - `fillChar` - this had nothing to do with the plugin, please configure it
yourself by adding `vim.opt.listchars:append({ space = '<char>' })` to your yourself by adding `vim.opt.listchars:append({ space = '<char>' })` to your
@ -119,10 +175,37 @@ everyone.
- Replace `vim.lsp.nvimCodeActionMenu` with `vim.ui.fastaction`, see the - Replace `vim.lsp.nvimCodeActionMenu` with `vim.ui.fastaction`, see the
breaking changes section above for more details breaking changes section above for more details
- Add a `setupOpts` option to nvim-surround, which allows modifying options that
aren't defined in nvf. Move the alternate nvim-surround keybinds to use
`setupOpts`.
- Remove `autopairs.type`, and rename `autopairs.enable` to
`autopairs.nvim-autopairs.enable`. The new
[](#opt-vim.autopairs.nvim-autopairs.enable) supports `setupOpts` format by
default.
- Refactor of `nvim-cmp` and completion related modules
- Remove `autocomplete.type` in favor of per-plugin enable options such as
[](#opt-vim.autocomplete.nvim-cmp.enable).
- Deprecate legacy Vimsnip in favor of Luasnip, and integrate
friendly-snippets for bundled snippets. [](#opt-vim.snippets.luasnip.enable)
can be used to toggle Luasnip.
- Add sorting function options for completion sources under
[](#opt-vim.autocomplete.nvim-cmp.setupOpts.sorting.comparators)
- Add C# support under `vim.languages.csharp`, with support for both
omnisharp-roslyn and csharp-language-server.
- Add Julia support under `vim.languages.julia`. Note that the entirety of Julia
is bundled with nvf, if you enable the module, since there is no way to
provide only the LSP server.
[Neovim documentation on `vim.cmd`]: https://neovim.io/doc/user/lua.html#vim.cmd() [Neovim documentation on `vim.cmd`]: https://neovim.io/doc/user/lua.html#vim.cmd()
- Make Neovim's configuration file entirely Lua based. This comes with a few - Make Neovim's configuration file entirely Lua based. This comes with a few
breaking changes: breaking changes:
- `vim.configRC` has been removed. You will need to migrate your entries to - `vim.configRC` has been removed. You will need to migrate your entries to
Neovim-compliant Lua code, and add them to `vim.luaConfigRC` instead. Neovim-compliant Lua code, and add them to `vim.luaConfigRC` instead.
Existing vimscript configurations may be preserved in `vim.cmd` functions. Existing vimscript configurations may be preserved in `vim.cmd` functions.
@ -131,10 +214,13 @@ everyone.
has been introduced for setting up internal plugins. See the "DAG entries in has been introduced for setting up internal plugins. See the "DAG entries in
nvf" manual page for more information. nvf" manual page for more information.
- Rewrite `vim.maps`, see the breaking changes section above.
[NotAShelf](https://github.com/notashelf): [NotAShelf](https://github.com/notashelf):
[ts-error-translator.nvim]: https://github.com/dmmulroy/ts-error-translator.nvim [ts-error-translator.nvim]: https://github.com/dmmulroy/ts-error-translator.nvim
[credo]: https://github.com/rrrene/credo [credo]: https://github.com/rrrene/credo
[tiny-devicons-auto-colors]: https://github.com/rachartier/tiny-devicons-auto-colors.nvim
- Add `deno fmt` as the default Markdown formatter. This will be enabled - Add `deno fmt` as the default Markdown formatter. This will be enabled
automatically if you have autoformatting enabled, but can be disabled manually automatically if you have autoformatting enabled, but can be disabled manually
@ -186,8 +272,69 @@ everyone.
- Add [python-lsp-server](https://github.com/python-lsp/python-lsp-server) as an - Add [python-lsp-server](https://github.com/python-lsp/python-lsp-server) as an
additional Python LSP server. additional Python LSP server.
- Add [](#opt-vim.options) to set `vim.o` values in in your nvf configuration
without using additional Lua. See option documentation for more details.
- Add [](#opt-vim.dashboard.dashboard-nvim.setupOpts) to allow user
configuration for [dashboard.nvim](https://github.com/nvimdev/dashboard-nvim)
- Update `lualine.nvim` input and add missing themes:
- Adds `ayu`, `gruvbox_dark`, `iceberg`, `moonfly`, `onedark`,
`powerline_dark` and `solarized_light` themes.
- Add [](#opt-vim.spellcheck.extraSpellWords) to allow adding arbitrary
spellfiles to Neovim's runtime with ease.
- Add combined nvf configuration (`config.vim`) into the final package's
passthru as `passthru.neovimConfiguration` for easier debugging.
- Add support for [tiny-devicons-auto-colors] under
`vim.visuals.tiny-devicons-auto-colors`
[ppenguin](https://github.com/ppenguin): [ppenguin](https://github.com/ppenguin):
- Telescope: - Telescope:
- Fixed `project-nvim` command and keybinding - Fixed `project-nvim` command and keybinding
- Added default ikeybind/command for `Telescope resume` (`<leader>fr`) - Added default ikeybind/command for `Telescope resume` (`<leader>fr`)
[Soliprem](https://github.com/Soliprem):
- Add LSP and Treesitter support for R under `vim.languages.R`.
- Add formatter suppoort for R, with styler and formatR as options
- Add Otter support under `vim.lsp.otter` and an assert to prevent conflict with
ccc
- Fixed typo in Otter's setupOpts
- Add Neorg support under `vim.notes.neorg`
- Add LSP, diagnostics, formatter and Treesitter support for Kotlin under
`vim.languages.kotlin`
- changed default keybinds for leap.nvim to avoid altering expected behavior
- Add LSP, formatter and Treesitter support for Vala under `vim.languages.vala`
- Add [Tinymist](https://github.com/Myriad-Dreamin/tinymist] as a formatter for
the Typst language module.
- Add LSP and Treesitter support for Assembly under `vim.languages.assembly`
- Move [which-key](https://github.com/folke/which-key.nvim) to the new spec
[Bloxx12](https://github.com/Bloxx12)
- Add support for [base16 theming](https://github.com/RRethy/base16-nvim) under
`vim.theme`
- Fix internal breakage in `elixir-tools` setup.
[ksonj](https://github.com/ksonj):
- Add LSP support for Scala via
[nvim-metals](https://github.com/scalameta/nvim-metals)
[nezia1](https://github.com/nezia1):
- Add [biome](https://github.com/biomejs/biome) support for Typescript, CSS and
Svelte. Enable them via [](#opt-vim.languages.ts.format.type),
[](#opt-vim.languages.css.format.type) and
[](#opt-vim.languages.svelte.format.type) respectively.
- Replace [nixpkgs-fmt](https://github.com/nix-community/nixpkgs-fmt) with
[nixfmt](https://github.com/NixOS/nixfmt) (nixfmt-rfc-style).
[Nowaaru](https://github.com/Nowaaru):
- Add `precognition-nvim`.

914
flake.lock generated

File diff suppressed because it is too large Load diff

129
flake.nix
View file

@ -13,14 +13,15 @@
inherit inputs; inherit inputs;
specialArgs = {inherit lib;}; specialArgs = {inherit lib;};
} { } {
# provide overridable systems # Allow users to bring their own systems.
# https://github.com/nix-systems/nix-systems # «https://github.com/nix-systems/nix-systems»
systems = import inputs.systems; systems = import inputs.systems;
imports = [ imports = [
./flake/apps.nix ./flake/apps.nix
./flake/legacyPackages.nix ./flake/legacyPackages.nix
./flake/overlays.nix ./flake/overlays.nix
./flake/packages.nix ./flake/packages.nix
./flake/develop.nix
]; ];
flake = { flake = {
@ -56,19 +57,20 @@
}; };
}; };
perSystem = { perSystem = {pkgs, ...}: {
self', # Provide the default formatter. `nix fmt` in project root
config, # will format available files with the correct formatter.
pkgs, # P.S: Please do not format with nixfmt! It messes with many
... # syntax elements and results in unreadable code.
}: {
formatter = pkgs.alejandra; formatter = pkgs.alejandra;
devShells = {
default = self'.devShells.lsp; # Check if codebase is properly formatted.
nvim-nix = pkgs.mkShell {packages = [config.packages.nix];}; # This can be initiated with `nix build .#checks.<system>.nix-fmt`
lsp = pkgs.mkShell { # or with `nix flake check`
packages = with pkgs; [nil statix deadnix alejandra]; checks = {
}; nix-fmt = pkgs.runCommand "nix-fmt-check" {nativeBuildInputs = [pkgs.alejandra];} ''
alejandra --check ${self} < /dev/null | tee $out
'';
}; };
}; };
}; };
@ -90,10 +92,7 @@
flake = false; flake = false;
}; };
# TODO: get zig from the zig overlay instead of nixpkgs # Language servers (use master instead of nixpkgs)
zig.url = "github:mitchellh/zig-overlay";
# Langauge server (use master instead of nixpkgs)
rnix-lsp.url = "github:nix-community/rnix-lsp"; rnix-lsp.url = "github:nix-community/rnix-lsp";
nil = { nil = {
url = "github:oxalica/nil"; url = "github:oxalica/nil";
@ -102,6 +101,22 @@
}; };
## Plugins ## Plugins
# Lazy loading
plugin-lz-n = {
url = "github:nvim-neorocks/lz.n";
flake = false;
};
plugin-lzn-auto-require = {
url = "github:horriblename/lzn-auto-require/require-rewrite";
flake = false;
};
plugin-rtp-nvim = {
url = "github:nvim-neorocks/rtp.nvim";
flake = false;
};
# LSP plugins # LSP plugins
plugin-nvim-lspconfig = { plugin-nvim-lspconfig = {
url = "github:neovim/nvim-lspconfig"; url = "github:neovim/nvim-lspconfig";
@ -159,7 +174,12 @@
flake = false; flake = false;
}; };
# language support plugin-otter-nvim = {
url = "github:jmbuhr/otter.nvim";
flake = false;
};
# Language support
plugin-sqls-nvim = { plugin-sqls-nvim = {
url = "github:nanotee/sqls.nvim"; url = "github:nanotee/sqls.nvim";
flake = false; flake = false;
@ -190,6 +210,21 @@
flake = false; flake = false;
}; };
plugin-nvim-metals = {
url = "github:scalameta/nvim-metals";
flake = false;
};
plugin-omnisharp-extended = {
url = "github:Hoffs/omnisharp-extended-lsp.nvim";
flake = false;
};
plugin-csharpls-extended = {
url = "github:Decodetalkers/csharpls-extended-lsp.nvim";
flake = false;
};
# Copying/Registers # Copying/Registers
plugin-registers = { plugin-registers = {
url = "github:tversteeg/registers.nvim"; url = "github:tversteeg/registers.nvim";
@ -261,11 +296,6 @@
flake = false; flake = false;
}; };
plugin-cmp-vsnip = {
url = "github:hrsh7th/cmp-vsnip";
flake = false;
};
plugin-cmp-path = { plugin-cmp-path = {
url = "github:hrsh7th/cmp-path"; url = "github:hrsh7th/cmp-path";
flake = false; flake = false;
@ -276,9 +306,19 @@
flake = false; flake = false;
}; };
plugin-cmp-luasnip = {
url = "github:saadparwaiz1/cmp_luasnip";
flake = false;
};
# snippets # snippets
plugin-vim-vsnip = { plugin-luasnip = {
url = "github:hrsh7th/vim-vsnip"; url = "github:L3MON4D3/LuaSnip";
flake = false;
};
plugin-friendly-snippets = {
url = "github:rafamadriz/friendly-snippets";
flake = false; flake = false;
}; };
@ -333,6 +373,11 @@
}; };
# Themes # Themes
plugin-base16 = {
url = "github:rrethy/base16-nvim";
flake = false;
};
plugin-tokyonight = { plugin-tokyonight = {
url = "github:folke/tokyonight.nvim"; url = "github:folke/tokyonight.nvim";
flake = false; flake = false;
@ -386,7 +431,7 @@
flake = false; flake = false;
}; };
plugin-scrollbar-nvim = { plugin-nvim-scrollbar = {
url = "github:petertriho/nvim-scrollbar"; url = "github:petertriho/nvim-scrollbar";
flake = false; flake = false;
}; };
@ -411,6 +456,11 @@
flake = false; flake = false;
}; };
plugin-tiny-devicons-auto-colors = {
url = "github:rachartier/tiny-devicons-auto-colors.nvim";
flake = false;
};
plugin-gitsigns-nvim = { plugin-gitsigns-nvim = {
url = "github:lewis6991/gitsigns.nvim"; url = "github:lewis6991/gitsigns.nvim";
flake = false; flake = false;
@ -509,6 +559,11 @@
flake = false; flake = false;
}; };
plugin-precognition-nvim = {
url = "github:tris203/precognition.nvim";
flake = false;
};
# Note-taking # Note-taking
plugin-obsidian-nvim = { plugin-obsidian-nvim = {
url = "github:epwalsh/obsidian.nvim"; url = "github:epwalsh/obsidian.nvim";
@ -615,6 +670,26 @@
flake = false; flake = false;
}; };
plugin-lua-utils-nvim = {
url = "github:nvim-neorg/lua-utils.nvim";
flake = false;
};
plugin-pathlib-nvim = {
url = "github:pysan3/pathlib.nvim";
flake = false;
};
plugin-neorg = {
url = "github:nvim-neorg/neorg";
flake = false;
};
plugin-neorg-telescope = {
url = "github:nvim-neorg/neorg-telescope";
flake = false;
};
plugin-nui-nvim = { plugin-nui-nvim = {
# (required by noice.nvim) # (required by noice.nvim)
url = "github:MunifTanjim/nui.nvim"; url = "github:MunifTanjim/nui.nvim";

30
flake/develop.nix Normal file
View file

@ -0,0 +1,30 @@
{lib, ...}: {
perSystem = {
pkgs,
config,
self',
...
}: {
devShells = {
default = self'.devShells.lsp;
nvim-nix = pkgs.mkShellNoCC {packages = [config.packages.nix];};
lsp = pkgs.mkShellNoCC {
packages = with pkgs; [nil statix deadnix alejandra];
};
};
# This package exists to make development easier by providing the place and
# boilerplate to build a test nvf configuration. Feel free to use this for
# testing, but make sure to discard the changes before creating a pull
# request.
packages.dev = let
configuration = {};
customNeovim = lib.nvim.neovimConfiguration {
inherit pkgs;
modules = [configuration];
};
in
customNeovim.neovim;
};
}

View file

@ -8,6 +8,7 @@
docs = import ../docs {inherit pkgs inputs lib;}; docs = import ../docs {inherit pkgs inputs lib;};
in { in {
packages = { packages = {
inherit (docs.manual) htmlOpenTool;
# Documentation # Documentation
docs = docs.manual.html; docs = docs.manual.html;
docs-html = docs.manual.html; docs-html = docs.manual.html;
@ -18,7 +19,7 @@
docs-html-wrapped = pkgs.writeScriptBin "docs-html-wrapped" '' docs-html-wrapped = pkgs.writeScriptBin "docs-html-wrapped" ''
#!${pkgs.stdenv.shell} #!${pkgs.stdenv.shell}
# use xdg-open to open the docs in the browser # use xdg-open to open the docs in the browser
${pkgs.xdg_utils}/bin/xdg-open ${docs.manual.html} ${pkgs.xdg-utils}/bin/xdg-open ${docs.manual.html}
''; '';
# Exposed neovim configurations # Exposed neovim configurations
@ -28,10 +29,10 @@
# Published docker images # Published docker images
docker-nix = let docker-nix = let
inherit (pkgs) bash gitFull buildEnv dockerTools; inherit (pkgs) bash gitFull buildEnv;
inherit (config.legacyPackages) neovim-nix; inherit (config.legacyPackages) neovim-nix;
in in
dockerTools.buildImage { pkgs.dockerTools.buildImage {
name = "nvf"; name = "nvf";
tag = "latest"; tag = "latest";

5
lib/attrsets.nix Normal file
View file

@ -0,0 +1,5 @@
{lib}: let
inherit (builtins) listToAttrs;
in {
mapListToAttrs = f: list: listToAttrs (map f list);
}

View file

@ -67,6 +67,30 @@
mkLuaBinding binding.value action binding.description; mkLuaBinding binding.value action binding.description;
pushDownDefault = attr: mapAttrs (_: mkDefault) attr; pushDownDefault = attr: mapAttrs (_: mkDefault) attr;
mkLznBinding = mode: key: action: desc: {
inherit mode desc key action;
};
mkLznExprBinding = mode: key: action: desc: {
inherit mode desc key action;
lua = true;
silent = true;
expr = true;
};
mkSetLznBinding = mode: binding: action: {
inherit action mode;
key = binding.value;
desc = binding.description;
};
mkSetLuaLznBinding = mode: binding: action: {
inherit action mode;
key = binding.value;
lua = true;
desc = binding.description;
};
}; };
in in
binds binds

View file

@ -1,18 +0,0 @@
{
inputs,
lib,
}: let
modulesWithInputs = import ../modules inputs;
in
{
modules ? [],
pkgs,
check ? true,
extraSpecialArgs ? {},
extraModules ? [],
...
}:
modulesWithInputs {
inherit pkgs lib check extraSpecialArgs extraModules;
configuration.imports = modules;
}

View file

@ -10,6 +10,7 @@
dag = import ./dag.nix {inherit lib;}; dag = import ./dag.nix {inherit lib;};
languages = import ./languages.nix {inherit lib;}; languages = import ./languages.nix {inherit lib;};
lists = import ./lists.nix {inherit lib;}; lists = import ./lists.nix {inherit lib;};
attrsets = import ./attrsets.nix {inherit lib;};
lua = import ./lua.nix {inherit lib;}; lua = import ./lua.nix {inherit lib;};
neovimConfiguration = import ./configuration.nix {inherit inputs lib;}; neovimConfiguration = import ../modules {inherit inputs lib;};
} }

View file

@ -2,8 +2,8 @@
{lib}: let {lib}: let
inherit (builtins) isString getAttr; inherit (builtins) isString getAttr;
inherit (lib.options) mkOption; inherit (lib.options) mkOption;
inherit (lib.attrsets) listToAttrs;
inherit (lib.types) bool; inherit (lib.types) bool;
inherit (lib.nvim.attrsets) mapListToAttrs;
in { in {
# Converts a boolean to a yes/no string. This is used in lots of # Converts a boolean to a yes/no string. This is used in lots of
# configuration formats. # configuration formats.
@ -12,21 +12,21 @@ in {
config, config,
diagnosticsProviders, diagnosticsProviders,
}: }:
listToAttrs mapListToAttrs
(map (v: let (v: let
type = type =
if isString v if isString v
then v then v
else getAttr v.type; else getAttr v.type;
package = package =
if isString v if isString v
then diagnosticsProviders.${type}.package then diagnosticsProviders.${type}.package
else v.package; else v.package;
in { in {
name = "${lang}-diagnostics-${type}"; name = "${lang}-diagnostics-${type}";
value = diagnosticsProviders.${type}.nullConfig package; value = diagnosticsProviders.${type}.nullConfig package;
}) })
config); config;
mkEnable = desc: mkEnable = desc:
mkOption { mkOption {

View file

@ -1,8 +1,9 @@
{lib}: let {lib}: let
inherit (lib) isStringLike showOption showFiles getFiles mergeOneOption mergeEqualOption mkOptionType; inherit (lib.options) showOption showFiles getFiles mergeOneOption mergeEqualOption;
inherit (lib.types) anything attrsOf; inherit (lib.strings) isString isStringLike;
inherit (lib.types) anything attrsOf listOf mkOptionType;
inherit (lib.nvim.types) anythingConcatLists; inherit (lib.nvim.types) anythingConcatLists;
inherit (builtins) typeOf isAttrs any head concatLists stringLength; inherit (builtins) typeOf isAttrs any head concatLists stringLength match;
in { in {
# HACK: Does this break anything in our case? # HACK: Does this break anything in our case?
# A modified version of the nixpkgs anything type that concatenates lists # A modified version of the nixpkgs anything type that concatenates lists
@ -51,6 +52,16 @@ in {
(mergeFunctions.${commonType} or mergeEqualOption) loc defs; (mergeFunctions.${commonType} or mergeEqualOption) loc defs;
}; };
mergelessListOf = elemType: let
super = listOf elemType;
in
super
// {
name = "mergelessListOf";
description = "mergeless ${super.description}";
merge = mergeEqualOption;
};
char = mkOptionType { char = mkOptionType {
name = "char"; name = "char";
description = "character"; description = "character";
@ -58,4 +69,11 @@ in {
check = value: stringLength value < 2; check = value: stringLength value < 2;
merge = mergeEqualOption; merge = mergeEqualOption;
}; };
hexColor = mkOptionType {
name = "hex-color";
descriptionClass = "noun";
description = "RGB color in hex format";
check = v: isString v && (match "#?[0-9a-fA-F]{6}" v) != null;
};
} }

View file

@ -6,10 +6,10 @@
typesDag = import ./dag.nix {inherit lib;}; typesDag = import ./dag.nix {inherit lib;};
typesPlugin = import ./plugins.nix {inherit inputs lib;}; typesPlugin = import ./plugins.nix {inherit inputs lib;};
typesLanguage = import ./languages.nix {inherit lib;}; typesLanguage = import ./languages.nix {inherit lib;};
typesCustom = import ./custom.nix {inherit lib;}; customTypes = import ./custom.nix {inherit lib;};
in { in {
inherit (typesDag) dagOf; inherit (typesDag) dagOf;
inherit (typesPlugin) pluginsOpt extraPluginType mkPluginSetupOption luaInline pluginType borderType; inherit (typesPlugin) pluginsOpt extraPluginType mkPluginSetupOption luaInline pluginType borderType;
inherit (typesLanguage) diagnostics mkGrammarOption; inherit (typesLanguage) diagnostics mkGrammarOption;
inherit (typesCustom) anythingConcatLists char; inherit (customTypes) anythingConcatLists char hexColor mergelessListOf;
} }

View file

@ -97,7 +97,7 @@ in {
default = {}; default = {};
type = submodule { type = submodule {
freeformType = attrsOf anything; freeformType = anything;
options = opts; options = opts;
}; };
}; };

View file

@ -1,10 +1,13 @@
inputs: { {
configuration, inputs,
pkgs,
lib, lib,
check ? true, }: {
pkgs,
extraSpecialArgs ? {}, extraSpecialArgs ? {},
modules ? [],
# deprecated
extraModules ? [], extraModules ? [],
configuration ? {},
}: let }: let
inherit (pkgs) vimPlugins; inherit (pkgs) vimPlugins;
inherit (lib.strings) isString toString; inherit (lib.strings) isString toString;
@ -13,13 +16,25 @@ inputs: {
# import modules.nix with `check`, `pkgs` and `lib` as arguments # import modules.nix with `check`, `pkgs` and `lib` as arguments
# check can be disabled while calling this file is called # check can be disabled while calling this file is called
# to avoid checking in all modules # to avoid checking in all modules
nvimModules = import ./modules.nix {inherit pkgs check lib;}; nvimModules = import ./modules.nix {inherit pkgs lib;};
# evaluate the extended library with the modules # evaluate the extended library with the modules
# optionally with any additional modules passed by the user # optionally with any additional modules passed by the user
module = lib.evalModules { module = lib.evalModules {
specialArgs = extraSpecialArgs // {modulesPath = toString ./.;}; specialArgs = extraSpecialArgs // {modulesPath = toString ./.;};
modules = concatLists [[configuration] nvimModules extraModules]; modules = concatLists [
nvimModules
modules
(lib.optional (configuration != {}) (lib.warn ''
nvf: passing 'configuration' to lib.neovimConfiguration is deprecated.
''
configuration))
(lib.optionals (extraModules != []) (lib.warn ''
nvf: passing 'extraModules' to lib.neovimConfiguration is deprecated, use 'modules' instead.
''
extraModules))
];
}; };
# alias to the internal configuration # alias to the internal configuration
@ -69,10 +84,7 @@ inputs: {
# built (or "normalized") plugins that are modified # built (or "normalized") plugins that are modified
builtStartPlugins = buildConfigPlugins vimOptions.startPlugins; builtStartPlugins = buildConfigPlugins vimOptions.startPlugins;
builtOptPlugins = map (package: { builtOptPlugins = map (package: package // {optional = true;}) (buildConfigPlugins vimOptions.optPlugins);
plugin = package;
optional = true;
}) (buildConfigPlugins vimOptions.optPlugins);
# additional Lua and Python3 packages, mapped to their respective functions # additional Lua and Python3 packages, mapped to their respective functions
# to conform to the format mnw expects. end user should # to conform to the format mnw expects. end user should
@ -111,9 +123,15 @@ in {
paths = [neovim-wrapped printConfig printConfigPath]; paths = [neovim-wrapped printConfig printConfigPath];
postBuild = "echo Helpers added"; postBuild = "echo Helpers added";
meta = { # Allow evaluating vimOptions, i.e., config.vim from the packages' passthru
description = "Wrapped version of Neovim with additional helper scripts"; # attribute. For example, packages.x86_64-linux.neovim.passthru.neovimConfig
mainProgram = "nvim"; # will return the configuration in full.
}; passthru.neovimConfig = vimOptions;
meta =
neovim-wrapped.meta
// {
description = "Wrapped Neovim package with helper scripts to print the config (path)";
};
}; };
} }

View file

@ -1,5 +1,5 @@
{lib, ...}: let {lib, ...}: let
inherit (lib.modules) mkRemovedOptionModule; inherit (lib.modules) mkRemovedOptionModule mkRenamedOptionModule;
in { in {
imports = [ imports = [
# 2024-06-06 # 2024-06-06
@ -14,5 +14,50 @@ in {
available under `vim.ui.fastaction` as a replacement. Simply remove everything under available under `vim.ui.fastaction` as a replacement. Simply remove everything under
`vim.lsp.nvimCodeActionMenu`, and set `vim.ui.fastaction.enable` to `true`. `vim.lsp.nvimCodeActionMenu`, and set `vim.ui.fastaction.enable` to `true`.
'') '')
(mkRemovedOptionModule ["vim" "autopairs" "enable"] ''
vim.autopairs.enable has been removed in favor of per-plugin modules.
You can enable nvim-autopairs with vim.autopairs.nvim-autopairs.enable instead.
'')
(mkRemovedOptionModule ["vim" "autopairs" "type"] ''
vim.autopairs.type has been removed in favor of per-plugin modules.
You can enable nvim-autopairs with vim.autopairs.nvim-autopairs.enable instead.
'')
(mkRemovedOptionModule ["vim" "autocomplete" "enable"] ''
vim.autocomplete.enable has been removed in favor of per-plugin modules.
You can enable nvim-cmp with vim.autocomplete.nvim-cmp.enable instead.
'')
(mkRemovedOptionModule ["vim" "autocomplete" "type"] ''
vim.autocomplete.type has been removed in favor of per-plugin modules.
You can enable nvim-cmp with vim.autocomplete.nvim-cmp.enable instead.
'')
(mkRemovedOptionModule ["vim" "autocomplete" "sources"] ''
vim.autocomplete.sources has been removed in favor of per-plugin modules.
You can add nvim-cmp sources with vim.autocomplete.nvim-cmp.sources
instead.
'')
(mkRemovedOptionModule ["vim" "snippets" "vsnip" "enable"] ''
vim.snippets.vsnip.enable has been removed in favor of the more modern luasnip.
'')
(mkRenamedOptionModule ["vim" "lsp" "lspkind" "mode"] ["vim" "lsp" "lspkind" "setupOpts" "mode"])
# 2024-10-14
(mkRemovedOptionModule ["vim" "configRC"] ''
Please migrate your configRC sections to Neovim's Lua format, and
add them to `vim.luaConfigRC`.
See the v0.7 release notes for more information on why and how to
migrate your existing configurations to the new format.
'')
(mkRemovedOptionModule ["vim" "disableDefaultRuntimePaths"] ''
Nvf now uses $NVIM_APP_NAME so there is no longer the problem of
(accidental) leaking of user configuration.
'')
(mkRemovedOptionModule ["vim" "lsp" "trouble" "mappings" "toggle"] ''
With Trouble having so many different modes, and breaking changes
upstream, it no longer makes sense, nor works, to toggle only Trouble.
'')
]; ];
} }

View file

@ -1,77 +1,73 @@
{ {
check ? true,
pkgs, pkgs,
lib, lib,
}: let }: let
inherit (lib.modules) mkDefault; inherit (lib.modules) mkDefault;
inherit (lib.lists) concatLists; inherit (lib.lists) concatLists;
allModules = let
# The core neovim modules.
# Contains configuration for core neovim features
# such as spellchecking, mappings, and the init script (init.vim).
neovim = map (p: ./neovim + "/${p}") [
"init"
"mappings"
];
# The core neovim modules. # Individual plugin modules, separated by the type of plugin.
# Contains configuration for core neovim features # While adding a new type, you must make sure your type is
# such as spellchecking, mappings, and the init script (init.vim). # included in the list below.
neovim = map (p: ./neovim + "/${p}") [ plugins = map (p: ./plugins + "/${p}") [
"init" "assistant"
"mappings" "autopairs"
]; "comments"
"completion"
"dashboard"
"debugger"
"filetree"
"git"
"languages"
"lsp"
"minimap"
"notes"
"projects"
"rich-presence"
"session"
"snippets"
# "spellcheck" # FIXME: see neovim/init/spellcheck.nix
"statusline"
"tabline"
"terminal"
"theme"
"treesitter"
"ui"
"utility"
"visuals"
];
# Individual plugin modules, separated by the type of plugin. # The neovim wrapper, used to build a wrapped neovim package
# While adding a new type, you must make sure your type is # using the configuration passed in `neovim` and `plugins` modules.
# included in the list below. wrapper = map (p: ./wrapper + "/${p}") [
plugins = map (p: ./plugins + "/${p}") [ "build"
"assistant" "rc"
"autopairs" "warnings"
"comments" "lazy"
"completion" ];
"dashboard"
"debugger"
"filetree"
"git"
"languages"
"lsp"
"minimap"
"notes"
"projects"
"rich-presence"
"session"
"snippets"
# "spellcheck" # FIXME: see neovim/init/spellcheck.nix
"statusline"
"tabline"
"terminal"
"theme"
"treesitter"
"ui"
"utility"
"visuals"
];
# The neovim wrapper, used to build a wrapped neovim package # Extra modules, such as deprecation warnings
# using the configuration passed in `neovim` and `plugins` modules. # or renames in one place.
wrapper = map (p: ./wrapper + "/${p}") [ extra = map (p: ./extra + "/${p}") [
"build" "deprecations.nix"
"rc" ];
"warnings" in
]; concatLists [neovim plugins wrapper extra];
# Extra modules, such as deprecation warnings
# or renames in one place.
extra = map (p: ./extra + "/${p}") [
"deprecations.nix"
];
allModules = concatLists [neovim plugins wrapper extra];
pkgsModule = {config, ...}: {
config = {
_module = {
inherit check;
args = {
baseModules = allModules;
pkgsPath = mkDefault pkgs.path;
pkgs = mkDefault pkgs;
};
};
};
};
in in
allModules ++ [pkgsModule] allModules
++ [
{
_module.args = {
baseModules = allModules;
pkgsPath = mkDefault pkgs.path;
pkgs = mkDefault pkgs;
};
}
]

View file

@ -1,11 +1,14 @@
{ {
config, config,
pkgs,
lib, lib,
... ...
}: let }: let
inherit (lib.modules) mkIf mkRenamedOptionModule; inherit (lib.modules) mkIf mkRenamedOptionModule;
inherit (lib.options) mkOption mkEnableOption literalExpression; inherit (lib.options) mkOption mkEnableOption literalExpression;
inherit (lib.types) listOf str; inherit (lib.strings) concatLines;
inherit (lib.attrsets) mapAttrsToList;
inherit (lib.types) listOf str attrsOf;
inherit (lib.nvim.lua) listToLuaTable; inherit (lib.nvim.lua) listToLuaTable;
inherit (lib.nvim.dag) entryAfter; inherit (lib.nvim.dag) entryAfter;
@ -24,10 +27,48 @@ in {
description = '' description = ''
A list of languages that should be used for spellchecking. A list of languages that should be used for spellchecking.
To add your own language files, you may place your `spell` To add your own language files, you may place your `spell` directory in either
directory in either `~/.config/nvim` or the {file}`$XDG_CONFIG_HOME/nvf` or in a path that is included in the
[additionalRuntimePaths](#opt-vim.additionalRuntimePaths) [additionalRuntimePaths](#opt-vim.additionalRuntimePaths) list provided by nvf.
directory provided by **nvf**. '';
};
extraSpellWords = mkOption {
type = attrsOf (listOf str);
default = {};
example = literalExpression ''{"en.utf-8" = ["nvf" "word_you_want_to_add"];}'';
description = ''
Additional words to be used for spellchecking. The names of each key will be
used as the language code for the spell file. For example
```nix
"en.utf-8" = [ ... ];
```
will result in `en.utf-8.add.spl` being added to Neovim's runtime in the
{file}`spell` directory.
::: {.warning}
The attribute keys must be in `"<name>.<encoding>"` format for Neovim to
compile your spellfiles without mangling the resulting file names. Please
make sure that you enter the correct value, as nvf does not do any kind of
internal checking. Please see {command}`:help mkspell` for more details.
Example:
```nix
# "en" is the name, and "utf-8" is the encoding. For most use cases, utf-8
# will be enough, however, you may change it to any encoding format Neovim
# accepts, e.g., utf-16.
"en.utf-8" = ["nvf" "word_you_want_to_add"];
=> $out/spell/en-utf-8.add.spl
```
:::
Note that while adding a new language, you will still need to add the name of
the language (e.g. "en") to the {option}`vim.spellcheck.languages` list by name
in order to enable spellchecking for the language. By default only `"en"` is in
the list.
''; '';
}; };
@ -38,38 +79,75 @@ in {
description = '' description = ''
A list of filetypes for which spellchecking will be disabled. A list of filetypes for which spellchecking will be disabled.
You may use `echo &filetype` in Neovim to find out the ::: {.tip}
You may use {command}`:echo &filetype` in Neovim to find out the
filetype for a specific buffer. filetype for a specific buffer.
:::
''; '';
}; };
/*
# FIXME: This needs to be revisited. It tries to install
# the spellfile to an user directory, but it cannot do so
# as we sanitize runtime paths.
programmingWordlist.enable = mkEnableOption '' programmingWordlist.enable = mkEnableOption ''
vim-dirtytalk, a wordlist for programmers containing vim-dirtytalk, a wordlist for programmers containing
common programming terms. common programming terms.
Setting this value as `true` has the same effect ::: {.note}
as setting {option}`vim.spellCheck.enable` Enabling this option will unconditionally set
{option}`vim.spellcheck.enable` to true as vim-dirtytalk
depends on spellchecking having been set up.
:::
''; '';
*/
}; };
config = mkIf cfg.enable { config = mkIf cfg.enable {
vim.luaConfigRC.spellcheck = entryAfter ["basic"] '' vim = {
vim.opt.spell = true additionalRuntimePaths = let
vim.opt.spelllang = ${listToLuaTable cfg.languages} compileJoinedSpellfiles =
pkgs.runCommandLocal "nvf-compile-spellfiles" {
# Use the same version of Neovim as the user's configuration
nativeBuildInputs = [config.vim.package];
-- Disable spellchecking for certain filetypes spellfilesJoined = pkgs.symlinkJoin {
-- as configured by `vim.spellcheck.ignoredFiletypes` name = "nvf-spellfiles-joined";
vim.api.nvim_create_autocmd({ "FileType" }, { paths = mapAttrsToList (name: value: pkgs.writeTextDir "spell/${name}.add" (concatLines value)) cfg.extraSpellWords;
pattern = ${listToLuaTable cfg.ignoredFiletypes}, postBuild = "echo Spellfiles joined";
callback = function() };
vim.opt_local.spell = false } ''
end, # Fail on unset variables and non-zero exit codes
}) # this might be the only way to trace when `nvim --headless`
''; # fails in batch mode
set -eu
mkdir -p "$out/spell"
for spellfile in "$spellfilesJoined"/spell/*.add; do
name="$(basename "$spellfile" ".add")"
echo "Compiling spellfile: $spellfile"
nvim --headless --clean \
--cmd "mkspell $out/spell/$name.add.spl $spellfile" -Es -n
done
'';
in
mkIf (cfg.extraSpellWords != {}) [
# If .outPath is missing, additionalRuntimePaths receives the *function*
# instead of a path, causing errors.
compileJoinedSpellfiles.outPath
];
luaConfigRC.spellcheck = entryAfter ["basic"] ''
vim.opt.spell = true
vim.opt.spelllang = ${listToLuaTable cfg.languages}
-- Disable spellchecking for certain filetypes
-- as configured by `vim.spellcheck.ignoredFiletypes`
vim.api.nvim_create_augroup("nvf_autocmds", {clear = false})
vim.api.nvim_create_autocmd({ "FileType" }, {
group = "nvf_autocmds",
pattern = ${listToLuaTable cfg.ignoredFiletypes},
callback = function()
vim.opt_local.spell = false
end,
})
'';
};
}; };
} }

View file

@ -3,51 +3,75 @@
lib, lib,
... ...
}: let }: let
inherit (lib.modules) mkIf; inherit (lib.modules) mkIf mkMerge;
inherit (lib.trivial) pipe;
inherit (lib.attrsets) mapAttrsToList;
inherit (lib.lists) flatten;
legacyMapModes = {
normal = ["n"];
insert = ["i"];
select = ["s"];
visual = ["v"];
terminal = ["t"];
normalVisualOp = ["n" "v" "o"];
visualOnly = ["n" "x"];
operator = ["o"];
insertCommand = ["i" "c"];
lang = ["l"];
command = ["c"];
};
cfg = config.vim; cfg = config.vim;
in { in {
config = { config = {
vim.maps = { vim.keymaps = mkMerge [
normal = mkIf cfg.disableArrows { (
"<up>" = { mkIf cfg.disableArrows [
action = "<nop>"; {
key = "<up>";
noremap = false; mode = ["n" "i"];
}; action = "<nop>";
"<down>" = { noremap = false;
action = "<nop>"; }
{
noremap = false; key = "<down>";
}; mode = ["n" "i"];
"<left>" = { action = "<nop>";
action = "<nop>"; noremap = false;
noremap = false; }
}; {
"<right>" = { key = "<left>";
action = "<nop>"; mode = ["n" "i"];
noremap = false; action = "<nop>";
}; noremap = false;
}; }
{
insert = mkIf cfg.disableArrows { key = "<right>";
"<up>" = { mode = ["n" "i"];
action = "<nop>"; action = "<nop>";
noremap = false; noremap = false;
}; }
"<down>" = { ]
action = "<nop>"; )
noremap = false; (
}; pipe cfg.maps
"<left>" = { [
action = "<nop>"; (mapAttrsToList (
noremap = false; oldMode: keybinds:
}; mapAttrsToList (
"<right>" = { key: bind:
action = "<nop>"; bind
noremap = false; // {
}; inherit key;
}; mode = legacyMapModes.${oldMode};
}; }
)
keybinds
))
flatten
]
)
];
}; };
} }

View file

@ -1,101 +1,97 @@
{lib, ...}: let {lib, ...}: let
inherit (lib.options) mkOption; inherit (lib.options) mkOption literalMD;
inherit (lib.types) bool str attrsOf nullOr submodule; inherit (lib.types) either str listOf attrsOf nullOr submodule;
inherit (lib.nvim.config) mkBool; inherit (lib.nvim.config) mkBool;
# Most of the keybindings code is highly inspired by pta2002/nixvim.
# Thank you!
mapConfigOptions = { mapConfigOptions = {
silent =
mkBool false
"Whether this mapping should be silent. Equivalent to adding <silent> to a map.";
nowait =
mkBool false
"Whether to wait for extra input on ambiguous mappings. Equivalent to adding <nowait> to a map.";
script =
mkBool false
"Equivalent to adding <script> to a map.";
expr =
mkBool false
"Means that the action is actually an expression. Equivalent to adding <expr> to a map.";
unique =
mkBool false
"Whether to fail if the map is already defined. Equivalent to adding <unique> to a map.";
noremap =
mkBool true
"Whether to use the 'noremap' variant of the command, ignoring any custom mappings on the defined action. It is highly advised to keep this on, which is the default.";
desc = mkOption { desc = mkOption {
type = nullOr str; type = nullOr str;
default = null; default = null;
description = "A description of this keybind, to be shown in which-key, if you have it enabled."; description = "A description of this keybind, to be shown in which-key, if you have it enabled.";
}; };
action = mkOption {
type = str;
description = "The command to execute.";
};
lua = mkBool false ''
If true, `action` is considered to be lua code.
Thus, it will not be wrapped in `""`.
'';
silent = mkBool true "Whether this mapping should be silent. Equivalent to adding <silent> to a map.";
nowait = mkBool false "Whether to wait for extra input on ambiguous mappings. Equivalent to adding <nowait> to a map.";
script = mkBool false "Equivalent to adding <script> to a map.";
expr = mkBool false "Means that the action is actually an expression. Equivalent to adding <expr> to a map.";
unique = mkBool false "Whether to fail if the map is already defined. Equivalent to adding <unique> to a map.";
noremap = mkBool true "Whether to use the 'noremap' variant of the command, ignoring any custom mappings on the defined action. It is highly advised to keep this on, which is the default.";
}; };
mapOption = submodule { mapType = submodule {
options = options =
mapConfigOptions mapConfigOptions
// { // {
action = mkOption { key = mkOption {
type = str; type = str;
description = "The action to execute."; description = "The key that triggers this keybind.";
}; };
mode = mkOption {
lua = mkOption { type = either str (listOf str);
type = bool;
description = '' description = ''
If true, `action` is considered to be lua code. The short-name of the mode to set the keymapping for. Passing an empty string is the equivalent of `:map`.
Thus, it will not be wrapped in `""`.
See `:help map-modes` for a list of modes.
''; '';
default = false; example = literalMD ''`["n" "v" "c"]` for normal, visual and command mode'';
}; };
}; };
}; };
mapOptions = mode: legacyMapOption = mode:
mkOption { mkOption {
description = "Mappings for ${mode} mode"; description = "Mappings for ${mode} mode";
type = attrsOf mapOption; type = attrsOf (submodule {
options = mapConfigOptions;
});
default = {}; default = {};
}; };
in { in {
options.vim = { options.vim = {
maps = mkOption { keymaps = mkOption {
type = submodule { type = listOf mapType;
options = { description = "Custom keybindings.";
normal = mapOptions "normal";
insert = mapOptions "insert";
select = mapOptions "select";
visual = mapOptions "visual and select";
terminal = mapOptions "terminal";
normalVisualOp = mapOptions "normal, visual, select and operator-pending (same as plain 'map')";
visualOnly = mapOptions "visual only";
operator = mapOptions "operator-pending";
insertCommand = mapOptions "insert and command-line";
lang = mapOptions "insert, command-line and lang-arg";
command = mapOptions "command-line";
};
};
default = {};
description = ''
Custom keybindings for any mode.
For plain maps (e.g. just 'map' or 'remap') use `maps.normalVisualOp`.
'';
example = '' example = ''
maps = { vim.keymaps = [
normal."<leader>m" = { {
key = "<leader>m";
mode = "n";
silent = true; silent = true;
action = "<cmd>make<CR>"; action = ":make<CR>";
}; # Same as nnoremap <leader>m <silent> <cmd>make<CR> }
}; {
key = "<leader>l";
mode = ["n" "x"];
silent = true;
action = "<cmd>cnext<CR>";
}
];
''; '';
default = {};
};
maps = {
normal = legacyMapOption "normal";
insert = legacyMapOption "insert";
select = legacyMapOption "select";
visual = legacyMapOption "visual and select";
terminal = legacyMapOption "terminal";
normalVisualOp = legacyMapOption "normal, visual, select and operator-pending (same as plain 'map')";
visualOnly = legacyMapOption "visual only";
operator = legacyMapOption "operator-pending";
insertCommand = legacyMapOption "insert and command-line";
lang = legacyMapOption "insert, command-line and lang-arg";
command = legacyMapOption "command-line";
}; };
}; };
} }

View file

@ -4,11 +4,8 @@
... ...
}: let }: let
inherit (builtins) toJSON; inherit (builtins) toJSON;
inherit (lib.nvim.lua) toLuaObject; inherit (lib.modules) mkIf;
inherit (lib.modules) mkIf mkMerge; inherit (lib.strings) optionalString;
inherit (lib.nvim.dag) entryAnywhere;
inherit (lib.lists) optionals;
inherit (lib.nvim.binds) mkLuaBinding;
cfg = config.vim.assistant.copilot; cfg = config.vim.assistant.copilot;
@ -23,63 +20,68 @@
end end
end end
''; '';
mkLuaKeymap = mode: key: action: desc: opts:
opts
// {
inherit mode key action desc;
lua = true;
};
in { in {
config = mkIf cfg.enable { config = mkIf cfg.enable {
vim.startPlugins = vim = {
[ lazy.plugins = {
"copilot-lua" copilot-lua = {
# cfg.copilotNodePackage package = "copilot-lua";
] setupModule = "copilot";
++ optionals cfg.cmp.enable [ inherit (cfg) setupOpts;
"copilot-cmp" after = mkIf cfg.cmp.enable "require('copilot_cmp').setup()";
];
vim.pluginRC.copilot = entryAnywhere '' cmd = ["Copilot" "CopilotAuth" "CopilotDetach" "CopilotPanel" "CopilotStop"];
require("copilot").setup(${toLuaObject cfg.setupOpts}) keys = [
(mkLuaKeymap ["n"] cfg.mappings.panel.accept (wrapPanelBinding ''require("copilot.panel").accept'' cfg.mappings.panel.accept) "[copilot] Accept suggestion" {})
(mkLuaKeymap ["n"] cfg.mappings.panel.jumpNext (wrapPanelBinding "require(\"copilot.panel\").jump_next" cfg.mappings.panel.jumpNext) "[copilot] Next panel suggestion" {})
(mkLuaKeymap ["n"] cfg.mappings.panel.jumpPrev (wrapPanelBinding "require(\"copilot.panel\").jump_prev" cfg.mappings.panel.jumpPrev) "[copilot] Previous panel suggestion" {})
(mkLuaKeymap ["n"] cfg.mappings.panel.refresh (wrapPanelBinding "require(\"copilot.panel\").refresh" cfg.mappings.panel.refresh) "[copilot] Refresh suggestion" {})
(mkLuaKeymap ["n"] cfg.mappings.panel.open (wrapPanelBinding ''
function() require("copilot.panel").open({ position = "${cfg.setupOpts.panel.layout.position}", ratio = ${toString cfg.setupOpts.panel.layout.ratio}, }) end
''
cfg.mappings.panel.open) "[copilot] Open Panel" {})
${lib.optionalString cfg.cmp.enable '' (mkLuaKeymap ["i"] cfg.mappings.suggestion.accept "function() require('copilot.suggestion').accept() end" "[copilot] Accept suggestion" {})
require("copilot_cmp").setup() (mkLuaKeymap ["i"] cfg.mappings.suggestion.acceptLine "function() require('copilot.suggestion').accept_line() end" "[copilot] Accept suggestion (line)" {})
''} (mkLuaKeymap ["i"] cfg.mappings.suggestion.acceptWord "function() require('copilot.suggestion').accept_word() end" "[copilot] Accept suggestion (word)" {})
''; (mkLuaKeymap ["i"] cfg.mappings.suggestion.dismiss "function() require('copilot.suggestion').dismiss() end" "[copilot] dismiss suggestion" {})
(mkLuaKeymap ["i"] cfg.mappings.suggestion.next "function() require('copilot.suggestion').next() end" "[copilot] next suggestion" {})
# Disable plugin handled keymaps. (mkLuaKeymap ["i"] cfg.mappings.suggestion.prev "function() require('copilot.suggestion').prev() end" "[copilot] previous suggestion" {})
# Setting it here so that it doesn't show up in user docs ];
vim.assistant.copilot.setupOpts = { };
panel.keymap = {
jump_prev = lib.mkDefault false;
jump_next = lib.mkDefault false;
accept = lib.mkDefault false;
refresh = lib.mkDefault false;
open = lib.mkDefault false;
}; };
suggestion.keymap = {
accept = lib.mkDefault false; autocomplete.nvim-cmp = {
accept_word = lib.mkDefault false; sources = {copilot = "[Copilot]";};
accept_line = lib.mkDefault false; sourcePlugins = ["copilot-cmp"];
next = lib.mkDefault false; };
prev = lib.mkDefault false;
dismiss = lib.mkDefault false; # Disable plugin handled keymaps.
# Setting it here so that it doesn't show up in user docs
assistant.copilot.setupOpts = {
panel.keymap = {
jump_prev = lib.mkDefault false;
jump_next = lib.mkDefault false;
accept = lib.mkDefault false;
refresh = lib.mkDefault false;
open = lib.mkDefault false;
};
suggestion.keymap = {
accept = lib.mkDefault false;
accept_word = lib.mkDefault false;
accept_line = lib.mkDefault false;
next = lib.mkDefault false;
prev = lib.mkDefault false;
dismiss = lib.mkDefault false;
};
}; };
}; };
vim.maps.normal = mkMerge [
(mkLuaBinding cfg.mappings.panel.jumpPrev (wrapPanelBinding "require(\"copilot.panel\").jump_prev" cfg.mappings.panel.jumpPrev) "[copilot] Accept suggestion")
(mkLuaBinding cfg.mappings.panel.jumpNext (wrapPanelBinding "require(\"copilot.panel\").jump_next" cfg.mappings.panel.jumpNext) "[copilot] Accept suggestion")
(mkLuaBinding cfg.mappings.panel.accept (wrapPanelBinding ''require("copilot.panel").accept'' cfg.mappings.panel.accept) "[copilot] Accept suggestion")
(mkLuaBinding cfg.mappings.panel.refresh (wrapPanelBinding "require(\"copilot.panel\").refresh" cfg.mappings.panel.refresh) "[copilot] Accept suggestion")
(mkLuaBinding cfg.mappings.panel.open (wrapPanelBinding ''
function() require("copilot.panel").open({ position = "${cfg.setupOpts.panel.layout.position}", ratio = ${toString cfg.setupOpts.panel.layout.ratio}, }) end
''
cfg.mappings.panel.open) "[copilot] Accept suggestion")
];
vim.maps.insert = mkMerge [
(mkLuaBinding cfg.mappings.suggestion.accept "require(\"copilot.suggestion\").accept" "[copilot] Accept suggestion")
(mkLuaBinding cfg.mappings.suggestion.acceptLine "require(\"copilot.suggestion\").accept_line" "[copilot] Accept suggestion (line)")
(mkLuaBinding cfg.mappings.suggestion.acceptWord "require(\"copilot.suggestion\").accept_word" "[copilot] Accept suggestion (word)")
(mkLuaBinding cfg.mappings.suggestion.next "require(\"copilot.suggestion\").next" "[copilot] next suggestion")
(mkLuaBinding cfg.mappings.suggestion.prev "require(\"copilot.suggestion\").prev" "[copilot] previous suggestion")
(mkLuaBinding cfg.mappings.suggestion.dismiss "require(\"copilot.suggestion\").dismiss" "[copilot] dismiss suggestion")
];
}; };
} }

View file

@ -4,16 +4,17 @@
... ...
}: let }: let
inherit (lib.modules) mkIf; inherit (lib.modules) mkIf;
inherit (lib.trivial) boolToString;
inherit (lib.nvim.dag) entryAnywhere; inherit (lib.nvim.dag) entryAnywhere;
inherit (lib.nvim.lua) toLuaObject;
cfg = config.vim.autopairs; cfg = config.vim.autopairs.nvim-autopairs;
in { in {
config = mkIf cfg.enable { config = mkIf cfg.enable {
vim.startPlugins = ["nvim-autopairs"]; vim = {
startPlugins = ["nvim-autopairs"];
vim.pluginRC.autopairs = entryAnywhere '' pluginRC.autopairs = entryAnywhere ''
require("nvim-autopairs").setup({ map_cr = ${boolToString (!config.vim.autocomplete.enable)} }) require('nvim-autopairs').setup(${toLuaObject cfg.setupOpts})
''; '';
};
}; };
} }

View file

@ -1,21 +1,14 @@
{lib, ...}: let {lib, ...}: let
inherit (lib) mkRemovedOptionModule; inherit (lib) mkRemovedOptionModule;
inherit (lib.options) mkEnableOption mkOption; inherit (lib.options) mkEnableOption;
inherit (lib.types) enum; inherit (lib.nvim.types) mkPluginSetupOption;
in { in {
imports = [ imports = [
(mkRemovedOptionModule ["vim" "autopairs" "nvim-compe"] "nvim-compe is deprecated and no longer suported.") (mkRemovedOptionModule ["vim" "autopairs" "nvim-compe"] "nvim-compe is deprecated and no longer suported.")
]; ];
options.vim = { options.vim.autopairs.nvim-autopairs = {
autopairs = { enable = mkEnableOption "autopairs";
enable = mkEnableOption "autopairs" // {default = false;}; setupOpts = mkPluginSetupOption "nvim-autopairs" {};
type = mkOption {
type = enum ["nvim-autopairs"];
default = "nvim-autopairs";
description = "Set the autopairs type. Options: nvim-autopairs [nvim-autopairs]";
};
};
}; };
} }

View file

@ -1,6 +1,7 @@
{lib, ...}: let {lib, ...}: let
inherit (lib.options) mkEnableOption; inherit (lib.options) mkEnableOption;
inherit (lib.nvim.binds) mkMappingOption; inherit (lib.nvim.binds) mkMappingOption;
inherit (lib.nvim.types) mkPluginSetupOption;
in { in {
options.vim.comments.comment-nvim = { options.vim.comments.comment-nvim = {
enable = mkEnableOption "smart and powerful comment plugin for neovim comment-nvim"; enable = mkEnableOption "smart and powerful comment plugin for neovim comment-nvim";
@ -15,5 +16,12 @@ in {
toggleSelectedLine = mkMappingOption "Toggle selected comment" "gc"; toggleSelectedLine = mkMappingOption "Toggle selected comment" "gc";
toggleSelectedBlock = mkMappingOption "Toggle selected block" "gb"; toggleSelectedBlock = mkMappingOption "Toggle selected block" "gb";
}; };
setupOpts = mkPluginSetupOption "Comment-nvim" {
mappings = {
basic = mkEnableOption "basic mappings";
extra = mkEnableOption "extra mappings";
};
};
}; };
} }

View file

@ -3,48 +3,38 @@
lib, lib,
... ...
}: let }: let
inherit (lib.modules) mkIf mkMerge; inherit (lib.modules) mkIf;
inherit (lib.nvim.binds) mkExprBinding mkBinding; inherit (lib.nvim.binds) mkLznExprBinding mkLznBinding;
inherit (lib.nvim.dag) entryAnywhere;
cfg = config.vim.comments.comment-nvim; cfg = config.vim.comments.comment-nvim;
self = import ./comment-nvim.nix {inherit lib;}; self = import ./comment-nvim.nix {inherit lib;};
inherit (self.options.vim.comments.comment-nvim) mappings; inherit (self.options.vim.comments.comment-nvim) mappings;
in { in {
config = mkIf cfg.enable { config = mkIf cfg.enable {
vim.startPlugins = [ vim.lazy.plugins.comment-nvim = {
"comment-nvim" package = "comment-nvim";
]; setupModule = "Comment";
inherit (cfg) setupOpts;
vim.maps.normal = mkMerge [ keys = [
(mkBinding cfg.mappings.toggleOpLeaderLine "<Plug>(comment_toggle_linewise)" mappings.toggleOpLeaderLine.description) (mkLznBinding ["n"] cfg.mappings.toggleOpLeaderLine "<Plug>(comment_toggle_linewise)" mappings.toggleOpLeaderLine.description)
(mkBinding cfg.mappings.toggleOpLeaderBlock "<Plug>(comment_toggle_blockwise)" mappings.toggleOpLeaderBlock.description) (mkLznBinding ["n"] cfg.mappings.toggleOpLeaderBlock "<Plug>(comment_toggle_blockwise)" mappings.toggleOpLeaderBlock.description)
(mkLznExprBinding ["n"] cfg.mappings.toggleCurrentLine ''
(mkExprBinding cfg.mappings.toggleCurrentLine '' function()
function() return vim.api.nvim_get_vvar('count') == 0 and '<Plug>(comment_toggle_linewise_current)'
return vim.api.nvim_get_vvar('count') == 0 and '<Plug>(comment_toggle_linewise_current)' or '<Plug>(comment_toggle_linewise_count)'
or '<Plug>(comment_toggle_linewise_count)' end
end ''
'' mappings.toggleCurrentLine.description)
mappings.toggleCurrentLine.description) (mkLznExprBinding ["n"] cfg.mappings.toggleCurrentBlock ''
(mkExprBinding cfg.mappings.toggleCurrentBlock '' function()
function() return vim.api.nvim_get_vvar('count') == 0 and '<Plug>(comment_toggle_blockwise_current)'
return vim.api.nvim_get_vvar('count') == 0 and '<Plug>(comment_toggle_blockwise_current)' or '<Plug>(comment_toggle_blockwise_count)'
or '<Plug>(comment_toggle_blockwise_count)' end
end ''
'' mappings.toggleCurrentBlock.description)
mappings.toggleCurrentBlock.description) (mkLznBinding ["x"] cfg.mappings.toggleSelectedLine "<Plug>(comment_toggle_linewise_visual)" mappings.toggleSelectedLine.description)
]; (mkLznBinding ["x"] cfg.mappings.toggleSelectedBlock "<Plug>(comment_toggle_blockwise_visual)" mappings.toggleSelectedBlock.description)
];
vim.maps.visualOnly = mkMerge [ };
(mkBinding cfg.mappings.toggleSelectedLine "<Plug>(comment_toggle_linewise_visual)" mappings.toggleSelectedLine.description)
(mkBinding cfg.mappings.toggleSelectedBlock "<Plug>(comment_toggle_blockwise_visual)" mappings.toggleSelectedBlock.description)
];
vim.pluginRC.comment-nvim = entryAnywhere ''
require('Comment').setup({
mappings = { basic = false, extra = false, },
})
'';
}; };
} }

View file

@ -3,246 +3,138 @@
config, config,
... ...
}: let }: let
inherit (builtins) toJSON;
inherit (lib.modules) mkIf mkMerge; inherit (lib.modules) mkIf mkMerge;
inherit (lib.attrsets) attrNames mapAttrsToList; inherit (lib.strings) optionalString;
inherit (lib.strings) concatMapStringsSep concatStringsSep optionalString; inherit (lib.generators) mkLuaInline;
inherit (lib.nvim.binds) addDescriptionsToMappings mkSetLuaBinding; inherit (lib.nvim.lua) toLuaObject;
inherit (lib.nvim.dag) entryAnywhere entryAfter; inherit (lib.nvim.attrsets) mapListToAttrs;
inherit (builtins) attrNames typeOf tryEval concatStringsSep;
cfg = config.vim.autocomplete; borders = config.vim.ui.borders.plugins.nvim-cmp;
lspkindEnabled = config.vim.lsp.enable && config.vim.lsp.lspkind.enable;
self = import ./nvim-cmp.nix {inherit lib;}; cfg = config.vim.autocomplete.nvim-cmp;
mappingDefinitions = self.options.vim.autocomplete.mappings; luasnipEnable = config.vim.snippets.luasnip.enable;
getPluginName = plugin:
mappings = addDescriptionsToMappings cfg.mappings mappingDefinitions; if typeOf plugin == "string"
then plugin
builtSources = else if (plugin ? pname && (tryEval plugin.pname).success)
concatMapStringsSep then plugin.pname
"\n" else plugin.name;
(n: "{ name = '${n}'},") inherit (cfg) mappings;
(attrNames cfg.sources);
builtMaps =
concatStringsSep
"\n"
(mapAttrsToList
(n: v:
if v == null
then ""
else "${n} = '${v}',")
cfg.sources);
dagPlacement =
if lspkindEnabled
then entryAfter ["lspkind"]
else entryAnywhere;
in { in {
config = mkIf cfg.enable { config = mkIf cfg.enable {
vim.startPlugins = [ vim = {
"nvim-cmp" startPlugins = ["rtp-nvim"];
"cmp-buffer" lazy.plugins = mkMerge [
"cmp-vsnip" (mapListToAttrs (package: {
"cmp-path" name = getPluginName package;
"vim-vsnip" value = {
]; inherit package;
lazy = true;
after = ''
local path = vim.fn.globpath(vim.o.packpath, 'pack/*/opt/${getPluginName package}')
require("rtp_nvim").source_after_plugin_dir(path)
'';
};
})
cfg.sourcePlugins)
{
nvim-cmp = {
package = "nvim-cmp";
after = ''
${optionalString luasnipEnable "local luasnip = require('luasnip')"}
local cmp = require("cmp")
vim.autocomplete.sources = { local kinds = require("cmp.types").lsp.CompletionItemKind
"nvim-cmp" = null; local deprio = function(kind)
"vsnip" = "[VSnip]"; return function(e1, e2)
"buffer" = "[Buffer]"; if e1:get_kind() == kind then
"crates" = "[Crates]"; return false
"path" = "[Path]"; end
"copilot" = "[Copilot]"; if e2:get_kind() == kind then
}; return true
end
return nil
end
end
vim.maps.insert = mkMerge [ cmp.setup(${toLuaObject cfg.setupOpts})
(mkSetLuaBinding mappings.complete ''
require('cmp').complete
'')
(let
defaultKeys =
if config.vim.autopairs.enable
then "require('nvim-autopairs').autopairs_cr()"
else "vim.api.nvim_replace_termcodes(${toJSON mappings.confirm.value}, true, false, true)";
in
mkSetLuaBinding mappings.confirm ''
function()
if not require('cmp').confirm({ select = true }) then
vim.fn.feedkeys(${defaultKeys}, 'n')
end
end
'')
(mkSetLuaBinding mappings.next ''
function()
local has_words_before = function()
local line, col = unpack(vim.api.nvim_win_get_cursor(0))
return col ~= 0 and vim.api.nvim_buf_get_lines(0, line - 1, line, true)[1]:sub(col, col):match("%s") == nil
end
local cmp = require('cmp') ${optionalString config.vim.lazy.enable
(concatStringsSep "\n" (map
(package: "require('lz.n').trigger_load(${toLuaObject (getPluginName package)})")
cfg.sourcePlugins))}
'';
local feedkey = function(key, mode) event = ["InsertEnter" "CmdlineEnter"];
vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes(key, true, true, true), mode, true) };
end
if cmp.visible() then
cmp.select_next_item()
elseif vim.fn['vsnip#available'](1) == 1 then
feedkey("<Plug>(vsnip-expand-or-jump)", "")
elseif has_words_before() then
cmp.complete()
else
local termcode = vim.api.nvim_replace_termcodes(${toJSON mappings.next.value}, true, false, true)
vim.fn.feedkeys(termcode, 'n')
end
end
'')
(mkSetLuaBinding mappings.previous ''
function()
local cmp = require('cmp')
local feedkey = function(key, mode)
vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes(key, true, true, true), mode, true)
end
if cmp.visible() then
cmp.select_prev_item()
elseif vim.fn['vsnip#available'](-1) == 1 then
feedkeys("<Plug>(vsnip-jump-prev)", "")
end
end
'')
(mkSetLuaBinding mappings.close ''
require('cmp').mapping.abort()
'')
(mkSetLuaBinding mappings.scrollDocsUp ''
require('cmp').mapping.scroll_docs(-4)
'')
(mkSetLuaBinding mappings.scrollDocsDown ''
require('cmp').mapping.scroll_docs(4)
'')
];
vim.maps.command = mkMerge [
(mkSetLuaBinding mappings.complete ''
require('cmp').complete
'')
(mkSetLuaBinding mappings.close ''
require('cmp').mapping.close()
'')
(mkSetLuaBinding mappings.scrollDocsUp ''
require('cmp').mapping.scroll_docs(-4)
'')
(mkSetLuaBinding mappings.scrollDocsDown ''
require('cmp').mapping.scroll_docs(4)
'')
];
vim.maps.select = mkMerge [
(mkSetLuaBinding mappings.next ''
function()
local cmp = require('cmp')
local has_words_before = function()
local line, col = unpack(vim.api.nvim_win_get_cursor(0))
return col ~= 0 and vim.api.nvim_buf_get_lines(0, line - 1, line, true)[1]:sub(col, col):match("%s") == nil
end
local feedkey = function(key, mode)
vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes(key, true, true, true), mode, true)
end
if cmp.visible() then
cmp.select_next_item()
elseif vim.fn['vsnip#available'](1) == 1 then
feedkey("<Plug>(vsnip-expand-or-jump)", "")
elseif has_words_before() then
cmp.complete()
else
local termcode = vim.api.nvim_replace_termcodes(${toJSON mappings.next.value}, true, false, true)
vim.fn.feedkeys(termcode, 'n')
end
end
'')
(mkSetLuaBinding mappings.previous ''
function()
local cmp = require('cmp')
local feedkey = function(key, mode)
vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes(key, true, true, true), mode, true)
end
if cmp.visible() then
cmp.select_prev_item()
elseif vim.fn['vsnip#available'](-1) == 1 then
feedkeys("<Plug>(vsnip-jump-prev)", "")
end
end
'')
];
# TODO: alternative snippet engines to vsnip
# https://github.com/hrsh7th/nvim-cmp/blob/main/doc/cmp.txt#L82
vim.pluginRC.completion = mkIf (cfg.type == "nvim-cmp") (dagPlacement ''
local nvim_cmp_menu_map = function(entry, vim_item)
-- name for each source
vim_item.menu = ({
${builtMaps}
})[entry.source.name]
return vim_item
end
${optionalString lspkindEnabled ''
lspkind_opts.before = ${cfg.formatting.format}
''}
local cmp = require'cmp'
cmp.setup({
${optionalString config.vim.ui.borders.enable ''
-- explicitly enabled by setting ui.borders.enable = true
-- TODO: try to get nvim-cmp to follow global border style
window = {
completion = cmp.config.window.bordered(),
documentation = cmp.config.window.bordered(),
},
''}
snippet = {
expand = function(args)
vim.fn["vsnip#anonymous"](args.body)
end,
},
sources = {
${builtSources}
},
completion = {
completeopt = 'menu,menuone,noinsert',
${optionalString (!cfg.alwaysComplete) "autocomplete = false"}
},
formatting = {
format =
${
if lspkindEnabled
then "lspkind.cmp_format(lspkind_opts)"
else cfg.formatting.format
},
} }
}) ];
${optionalString (config.vim.autopairs.enable && config.vim.autopairs.type == "nvim-autopairs") ''
local cmp_autopairs = require('nvim-autopairs.completion.cmp')
cmp.event:on('confirm_done', cmp_autopairs.on_confirm_done({ map_char = { text = ""} }))
''}
'');
vim.snippets.vsnip.enable = autocomplete.nvim-cmp = {
if (cfg.type == "nvim-cmp") sources = {
then true nvim-cmp = null;
else config.vim.snippets.vsnip.enable; buffer = "[Buffer]";
path = "[Path]";
};
sourcePlugins = ["cmp-buffer" "cmp-path"];
setupOpts = {
sources = map (s: {name = s;}) (attrNames cfg.sources);
window = mkIf borders.enable {
completion.border = borders.style;
documentation.border = borders.style;
};
formatting.format = cfg.format;
# `cmp` and `luasnip` are defined above, in the `nvim-cmp` section
mapping = {
${mappings.complete} = mkLuaInline "cmp.mapping.complete()";
${mappings.close} = mkLuaInline "cmp.mapping.abort()";
${mappings.scrollDocsUp} = mkLuaInline "cmp.mapping.scroll_docs(-4)";
${mappings.scrollDocsDown} = mkLuaInline "cmp.mapping.scroll_docs(4)";
${mappings.confirm} = mkLuaInline "cmp.mapping.confirm({ select = true })";
${mappings.next} = mkLuaInline ''
cmp.mapping(function(fallback)
local has_words_before = function()
local line, col = unpack(vim.api.nvim_win_get_cursor(0))
return col ~= 0 and vim.api.nvim_buf_get_lines(0, line - 1, line, true)[1]:sub(col, col):match("%s") == nil
end
if cmp.visible() then
cmp.select_next_item()
${optionalString luasnipEnable ''
elseif luasnip.locally_jumpable(1) then
luasnip.jump(1)
''}
elseif has_words_before() then
cmp.complete()
else
fallback()
end
end)
'';
${mappings.previous} = mkLuaInline ''
cmp.mapping(function(fallback)
if cmp.visible() then
cmp.select_prev_item()
${optionalString luasnipEnable ''
elseif luasnip.locally_jumpable(-1) then
luasnip.jump(-1)
''}
else
fallback()
end
end)
'';
};
};
};
};
}; };
} }

View file

@ -1,4 +1,4 @@
_: { {
imports = [ imports = [
./config.nix ./config.nix
./nvim-cmp.nix ./nvim-cmp.nix

View file

@ -1,72 +1,117 @@
{lib, ...}: let {
inherit (lib.options) mkEnableOption mkOption literalMD; lib,
config,
...
}: let
inherit (lib.options) mkEnableOption mkOption literalExpression literalMD;
inherit (lib.types) str attrsOf nullOr either listOf;
inherit (lib.generators) mkLuaInline;
inherit (lib.nvim.binds) mkMappingOption; inherit (lib.nvim.binds) mkMappingOption;
inherit (lib.types) enum attrsOf nullOr str bool; inherit (lib.nvim.types) mkPluginSetupOption luaInline mergelessListOf pluginType;
inherit (lib.nvim.lua) toLuaObject;
inherit (builtins) isString;
cfg = config.vim.autocomplete.nvim-cmp;
in { in {
options.vim = { options.vim.autocomplete.nvim-cmp = {
autocomplete = { enable = mkEnableOption "nvim-cmp";
enable = mkEnableOption "autocomplete" // {default = false;}; setupOpts = mkPluginSetupOption "the autocomplete plugin" {
completion.completeopt = mkOption {
alwaysComplete = mkOption { type = str;
type = bool; default = "menu,menuone,noinsert";
description = "Automatically show completion.";
default = true;
};
mappings = {
complete = mkMappingOption "Complete [nvim-cmp]" "<C-Space>";
confirm = mkMappingOption "Confirm [nvim-cmp]" "<CR>";
next = mkMappingOption "Next item [nvim-cmp]" "<Tab>";
previous = mkMappingOption "Previous item [nvim-cmp]" "<S-Tab>";
close = mkMappingOption "Close [nvim-cmp]" "<C-e>";
scrollDocsUp = mkMappingOption "Scroll docs up [nvim-cmp]" "<C-d>";
scrollDocsDown = mkMappingOption "Scroll docs down [nvim-cmp]" "<C-f>";
};
type = mkOption {
type = enum ["nvim-cmp"];
default = "nvim-cmp";
description = "Set the autocomplete plugin. Options: [nvim-cmp]";
};
sources = mkOption {
description = '' description = ''
Attribute set of source names for nvim-cmp. A comma-separated list of options for completion.
If an attribute set is provided, then the menu value of See `:help completeopt` for the complete list.
`vim_item` in the format will be set to the value (if
utilizing the `nvim_cmp_menu_map` function).
Note: only use a single attribute name per attribute set
'';
type = attrsOf (nullOr str);
default = {};
example = ''
{nvim-cmp = null; buffer = "[Buffer]";}
''; '';
}; };
formatting = { sorting.comparators = mkOption {
format = mkOption { type = mergelessListOf (either str luaInline);
description = '' default = [
The function used to customize the appearance of the completion menu. (mkLuaInline "deprio(kinds.Text)")
(mkLuaInline "deprio(kinds.Snippet)")
"offset"
"exact"
"score"
"kind"
"length"
"sort_text"
];
description = ''
The comparator functions used for sorting completions.
If [](#opt-vim.lsp.lspkind.enable) is true, then the function You can either pass a valid inline lua function
will be called before modifications from lspkind. (see `:help cmp-config.sorting.comparators`),
or a string, in which case the builtin comparator with that name will
be used.
Default is to call the menu mapping function. A `deprio` function and a `kinds`
''; (`require("cmp.types").lsp.CompletionItemKind`) variable is provided
type = str; above `setupOpts`. By passing a type to the funcion, the returned
default = "nvim_cmp_menu_map"; function will be a comparator that always ranks the specified kind the
example = literalMD '' lowest.
```lua '';
function(entry, vim_item) apply = map (
return vim_item c:
end if isString c
``` then mkLuaInline ("cmp.config.compare." + c)
''; else c
}; );
}; };
}; };
mappings = {
complete = mkMappingOption "Complete [nvim-cmp]" "<C-Space>";
confirm = mkMappingOption "Confirm [nvim-cmp]" "<CR>";
next = mkMappingOption "Next item [nvim-cmp]" "<Tab>";
previous = mkMappingOption "Previous item [nvim-cmp]" "<S-Tab>";
close = mkMappingOption "Close [nvim-cmp]" "<C-e>";
scrollDocsUp = mkMappingOption "Scroll docs up [nvim-cmp]" "<C-d>";
scrollDocsDown = mkMappingOption "Scroll docs down [nvim-cmp]" "<C-f>";
};
format = mkOption {
type = nullOr luaInline;
default = mkLuaInline ''
function(entry, vim_item)
vim_item.menu = (${toLuaObject cfg.sources})[entry.source.name]
return vim_item
end
'';
defaultText = literalMD ''
```lua
function(entry, vim_item)
vim_item.menu = (''${toLuaObject config.vim.autocomplete.nvim-cmp.sources})[entry.source.name]
return vim_item
end
```
'';
description = ''
The function used to customize the completion menu entires. This is
outside of `setupOpts` to allow for an easier integration with
lspkind.nvim.
See `:help cmp-config.formatting.format`.
'';
};
sources = mkOption {
type = attrsOf (nullOr str);
default = {};
description = "The list of sources used by nvim-cmp";
example = literalExpression ''
{
nvim-cmp = null;
buffer = "[Buffer]";
}
'';
};
sourcePlugins = mkOption {
type = listOf pluginType;
default = [];
description = "List of source plugins used by nvim-cmp.";
};
}; };
} }

View file

@ -5,16 +5,17 @@
}: let }: let
inherit (lib.modules) mkIf; inherit (lib.modules) mkIf;
inherit (lib.nvim.dag) entryAnywhere; inherit (lib.nvim.dag) entryAnywhere;
inherit (lib.nvim.lua) toLuaObject;
cfg = config.vim.dashboard.dashboard-nvim; cfg = config.vim.dashboard.dashboard-nvim;
in { in {
config = mkIf cfg.enable { config = mkIf cfg.enable {
vim.startPlugins = [ vim = {
"dashboard-nvim" startPlugins = ["dashboard-nvim"];
];
vim.pluginRC.dashboard-nvim = entryAnywhere '' pluginRC.dashboard-nvim = entryAnywhere ''
require("dashboard").setup{} require("dashboard").setup(${toLuaObject cfg.setupOpts})
''; '';
};
}; };
} }

View file

@ -1,7 +1,9 @@
{lib, ...}: let {lib, ...}: let
inherit (lib.options) mkEnableOption; inherit (lib.options) mkEnableOption;
inherit (lib.nvim.types) mkPluginSetupOption;
in { in {
options.vim.dashboard.dashboard-nvim = { options.vim.dashboard.dashboard-nvim = {
enable = mkEnableOption "Fancy and Blazing Fast start screen plugin of neovim [dashboard.nvim]"; enable = mkEnableOption "Fancy and Blazing Fast start screen plugin of neovim [dashboard.nvim]";
setupOpts = mkPluginSetupOption "dashboard.nvim" {};
}; };
} }

View file

@ -6,7 +6,7 @@
inherit (lib.strings) optionalString; inherit (lib.strings) optionalString;
inherit (lib.modules) mkIf mkMerge; inherit (lib.modules) mkIf mkMerge;
inherit (lib.attrsets) mapAttrs; inherit (lib.attrsets) mapAttrs;
inherit (lib.nvim.binds) addDescriptionsToMappings mkSetLuaBinding; inherit (lib.nvim.binds) addDescriptionsToMappings mkSetLuaBinding mkSetLuaLznBinding;
inherit (lib.nvim.dag) entryAnywhere entryAfter; inherit (lib.nvim.dag) entryAnywhere entryAfter;
cfg = config.vim.debugger.nvim-dap; cfg = config.vim.debugger.nvim-dap;
@ -16,57 +16,68 @@
in { in {
config = mkMerge [ config = mkMerge [
(mkIf cfg.enable { (mkIf cfg.enable {
vim.startPlugins = ["nvim-dap"]; vim = {
startPlugins = ["nvim-dap"];
vim.pluginRC = pluginRC =
{ {
# TODO customizable keymaps # TODO customizable keymaps
nvim-dap = entryAnywhere '' nvim-dap = entryAnywhere ''
local dap = require("dap") local dap = require("dap")
vim.fn.sign_define("DapBreakpoint", { text = "🛑", texthl = "ErrorMsg", linehl = "", numhl = "" }) vim.fn.sign_define("DapBreakpoint", { text = "🛑", texthl = "ErrorMsg", linehl = "", numhl = "" })
''; '';
} }
// mapAttrs (_: v: (entryAfter ["nvim-dap"] v)) cfg.sources; // mapAttrs (_: v: (entryAfter ["nvim-dap"] v)) cfg.sources;
vim.maps.normal = mkMerge [ maps.normal = mkMerge [
(mkSetLuaBinding mappings.continue "require('dap').continue") (mkSetLuaBinding mappings.continue "require('dap').continue")
(mkSetLuaBinding mappings.restart "require('dap').restart") (mkSetLuaBinding mappings.restart "require('dap').restart")
(mkSetLuaBinding mappings.terminate "require('dap').terminate") (mkSetLuaBinding mappings.terminate "require('dap').terminate")
(mkSetLuaBinding mappings.runLast "require('dap').run_last") (mkSetLuaBinding mappings.runLast "require('dap').run_last")
(mkSetLuaBinding mappings.toggleRepl "require('dap').repl.toggle") (mkSetLuaBinding mappings.toggleRepl "require('dap').repl.toggle")
(mkSetLuaBinding mappings.hover "require('dap.ui.widgets').hover") (mkSetLuaBinding mappings.hover "require('dap.ui.widgets').hover")
(mkSetLuaBinding mappings.toggleBreakpoint "require('dap').toggle_breakpoint") (mkSetLuaBinding mappings.toggleBreakpoint "require('dap').toggle_breakpoint")
(mkSetLuaBinding mappings.runToCursor "require('dap').run_to_cursor") (mkSetLuaBinding mappings.runToCursor "require('dap').run_to_cursor")
(mkSetLuaBinding mappings.stepInto "require('dap').step_into") (mkSetLuaBinding mappings.stepInto "require('dap').step_into")
(mkSetLuaBinding mappings.stepOut "require('dap').step_out") (mkSetLuaBinding mappings.stepOut "require('dap').step_out")
(mkSetLuaBinding mappings.stepOver "require('dap').step_over") (mkSetLuaBinding mappings.stepOver "require('dap').step_over")
(mkSetLuaBinding mappings.stepBack "require('dap').step_back") (mkSetLuaBinding mappings.stepBack "require('dap').step_back")
(mkSetLuaBinding mappings.goUp "require('dap').up") (mkSetLuaBinding mappings.goUp "require('dap').up")
(mkSetLuaBinding mappings.goDown "require('dap').down") (mkSetLuaBinding mappings.goDown "require('dap').down")
]; ];
};
}) })
(mkIf (cfg.enable && cfg.ui.enable) { (mkIf (cfg.enable && cfg.ui.enable) {
vim.startPlugins = ["nvim-dap-ui" "nvim-nio"]; vim = {
startPlugins = ["nvim-nio"];
vim.pluginRC.nvim-dap-ui = entryAfter ["nvim-dap"] ('' lazy.plugins.nvim-dap-ui = {
local dapui = require("dapui") package = "nvim-dap-ui";
dapui.setup() setupModule = "dapui";
'' inherit (cfg.ui) setupOpts;
+ optionalString cfg.ui.autoStart ''
dap.listeners.after.event_initialized["dapui_config"] = function() keys = [
dapui.open() (mkSetLuaLznBinding "n" mappings.toggleDapUI "function() require('dapui').toggle() end")
end ];
dap.listeners.before.event_terminated["dapui_config"] = function() };
dapui.close()
end pluginRC.nvim-dap-ui = entryAfter ["nvim-dap"] (
dap.listeners.before.event_exited["dapui_config"] = function() optionalString cfg.ui.autoStart ''
dapui.close() dap.listeners.after.event_initialized["dapui_config"] = function()
end require("dapui").open()
''); end
vim.maps.normal = mkSetLuaBinding mappings.toggleDapUI "require('dapui').toggle"; dap.listeners.before.event_terminated["dapui_config"] = function()
require("dapui").close()
end
dap.listeners.before.event_exited["dapui_config"] = function()
require("dapui").close()
end
''
);
};
}) })
]; ];
} }

View file

@ -2,12 +2,16 @@
inherit (lib.options) mkEnableOption mkOption; inherit (lib.options) mkEnableOption mkOption;
inherit (lib.types) bool attrsOf str; inherit (lib.types) bool attrsOf str;
inherit (lib.nvim.binds) mkMappingOption; inherit (lib.nvim.binds) mkMappingOption;
inherit (lib.nvim.types) mkPluginSetupOption;
in { in {
options.vim.debugger.nvim-dap = { options.vim.debugger.nvim-dap = {
enable = mkEnableOption "debugging via nvim-dap"; enable = mkEnableOption "debugging via nvim-dap";
ui = { ui = {
enable = mkEnableOption "UI extension for nvim-dap"; enable = mkEnableOption "UI extension for nvim-dap";
setupOpts = mkPluginSetupOption "nvim-dap-ui" {};
autoStart = mkOption { autoStart = mkOption {
type = bool; type = bool;
default = true; default = true;

View file

@ -5,7 +5,6 @@
}: let }: let
inherit (lib.modules) mkIf; inherit (lib.modules) mkIf;
inherit (lib.nvim.dag) entryAnywhere; inherit (lib.nvim.dag) entryAnywhere;
inherit (lib.nvim.lua) toLuaObject;
cfg = config.vim.filetree.neo-tree; cfg = config.vim.filetree.neo-tree;
in { in {
@ -16,13 +15,37 @@ in {
"plenary-nvim" # commons library "plenary-nvim" # commons library
"image-nvim" # optional for image previews "image-nvim" # optional for image previews
"nui-nvim" # ui library "nui-nvim" # ui library
# neotree
"neo-tree-nvim"
]; ];
pluginRC.neo-tree = entryAnywhere '' lazy.plugins.neo-tree-nvim = {
require("neo-tree").setup(${toLuaObject cfg.setupOpts}) package = "neo-tree-nvim";
''; setupModule = "neo-tree";
inherit (cfg) setupOpts;
cmd = ["Neotree"];
};
visuals.nvim-web-devicons.enable = true;
# from https://github.com/nvim-neo-tree/neo-tree.nvim/discussions/1326
pluginRC.neo-tree =
mkIf (cfg.setupOpts.filesystem.hijack_netrw_behavior != "disabled" && config.vim.lazy.enable)
(entryAnywhere ''
vim.api.nvim_create_autocmd("BufEnter", {
group = vim.api.nvim_create_augroup("load_neo_tree", {}),
desc = "Loads neo-tree when openning a directory",
callback = function(args)
local stats = vim.uv.fs_stat(args.file)
if not stats or stats.type ~= "directory" then
return
end
require("lz.n").trigger_load("neo-tree-nvim")
return true
end,
})
'');
}; };
}; };
} }

View file

@ -1,5 +1,5 @@
{lib, ...}: let {lib, ...}: let
inherit (lib.types) bool str int submodule enum either listOf; inherit (lib.types) bool str enum either listOf;
inherit (lib.options) mkOption mkEnableOption literalExpression; inherit (lib.options) mkOption mkEnableOption literalExpression;
inherit (lib.nvim.types) mkPluginSetupOption; inherit (lib.nvim.types) mkPluginSetupOption;
in { in {
@ -150,6 +150,14 @@ in {
A list of filetypes that should not be replaced when opening a file A list of filetypes that should not be replaced when opening a file
''; '';
}; };
filesystem = {
hijack_netrw_behavior = mkOption {
type = enum ["disabled" "open_default" "open_current"];
default = "open_default";
description = "Hijack Netrw behavior";
};
};
}; };
}; };
} }

View file

@ -5,10 +5,9 @@
... ...
}: let }: let
inherit (lib.strings) optionalString; inherit (lib.strings) optionalString;
inherit (lib.modules) mkIf mkMerge; inherit (lib.modules) mkIf;
inherit (lib.nvim.binds) mkBinding; inherit (lib.nvim.binds) mkLznBinding;
inherit (lib.nvim.dag) entryAnywhere; inherit (lib.nvim.dag) entryAnywhere;
inherit (lib.nvim.lua) toLuaObject;
inherit (lib.nvim.binds) pushDownDefault; inherit (lib.nvim.binds) pushDownDefault;
cfg = config.vim.filetree.nvimTree; cfg = config.vim.filetree.nvimTree;
@ -16,69 +15,93 @@
inherit (self.options.vim.filetree.nvimTree) mappings; inherit (self.options.vim.filetree.nvimTree) mappings;
in { in {
config = mkIf cfg.enable { config = mkIf cfg.enable {
vim.startPlugins = ["nvim-tree-lua"]; vim = {
binds.whichKey.register = pushDownDefault {
"<leader>t" = "+NvimTree";
};
vim.maps.normal = mkMerge [ lazy.plugins.nvim-tree-lua = {
(mkBinding cfg.mappings.toggle ":NvimTreeToggle<cr>" mappings.toggle.description) package = "nvim-tree-lua";
(mkBinding cfg.mappings.refresh ":NvimTreeRefresh<cr>" mappings.refresh.description) setupModule = "nvim-tree";
(mkBinding cfg.mappings.findFile ":NvimTreeFindFile<cr>" mappings.findFile.description) inherit (cfg) setupOpts;
(mkBinding cfg.mappings.focus ":NvimTreeFocus<cr>" mappings.focus.description)
];
vim.binds.whichKey.register = pushDownDefault { cmd = ["NvimTreeClipboard" "NvimTreeClose" "NvimTreeCollapse" "NvimTreeCollapseKeepBuffers" "NvimTreeFindFile" "NvimTreeFindFileToggle" "NvimTreeFocus" "NvimTreeHiTest" "NvimTreeOpen" "NvimTreeRefresh" "NvimTreeResize" "NvimTreeToggle"];
"<leader>t" = "+NvimTree"; keys = [
(mkLznBinding ["n"] cfg.mappings.toggle ":NvimTreeToggle<cr>" mappings.toggle.description)
(mkLznBinding ["n"] cfg.mappings.refresh ":NvimTreeRefresh<cr>" mappings.refresh.description)
(mkLznBinding ["n"] cfg.mappings.findFile ":NvimTreeFindFile<cr>" mappings.findFile.description)
(mkLznBinding ["n"] cfg.mappings.focus ":NvimTreeFocus<cr>" mappings.focus.description)
];
};
pluginRC.nvim-tree = entryAnywhere ''
${
optionalString cfg.setupOpts.disable_netrw ''
-- disable netrew completely
vim.g.loaded_netrw = 1
vim.g.loaded_netrwPlugin = 1
''
}
${optionalString (config.vim.lazy.enable && cfg.setupOpts.hijack_netrw && !cfg.openOnSetup) ''
vim.api.nvim_create_autocmd("BufEnter", {
group = vim.api.nvim_create_augroup("load_nvim_tree", {}),
desc = "Loads nvim-tree when openning a directory",
callback = function(args)
local stats = vim.uv.fs_stat(args.file)
if not stats or stats.type ~= "directory" then
return
end
require("lz.n").trigger_load("nvim-tree-lua")
return true
end,
})
''}
${
optionalString cfg.openOnSetup ''
${optionalString config.vim.lazy.enable ''require('lz.n').trigger_load("nvim-tree-lua")''}
-- autostart behaviour
-- Open on startup has been deprecated
-- see https://github.com/nvim-tree/nvim-tree.lua/wiki/Open-At-Startup
-- use a nix eval to dynamically insert the open on startup function
local function open_nvim_tree(data)
local IGNORED_FT = {
"markdown",
}
-- buffer is a real file on the disk
local real_file = vim.fn.filereadable(data.file) == 1
-- buffer is a [No Name]
local no_name = data.file == "" and vim.bo[data.buf].buftype == ""
-- &ft
local filetype = vim.bo[data.buf].ft
-- only files please
if not real_file and not no_name then
return
end
-- skip ignored filetypes
if vim.tbl_contains(IGNORED_FT, filetype) then
return
end
-- open the tree but don't focus it
require("nvim-tree.api").tree.toggle({ focus = false })
end
-- function to automatically open the tree on VimEnter
vim.api.nvim_create_autocmd({ "VimEnter" }, { callback = open_nvim_tree })
''
}
'';
}; };
vim.pluginRC.nvimtreelua = entryAnywhere ''
${
optionalString cfg.setupOpts.disable_netrw ''
-- disable netrew completely
vim.g.loaded_netrw = 1
vim.g.loaded_netrwPlugin = 1
''
}
require'nvim-tree'.setup(${toLuaObject cfg.setupOpts})
${
optionalString cfg.openOnSetup ''
-- autostart behaviour
-- Open on startup has been deprecated
-- see https://github.com/nvim-tree/nvim-tree.lua/wiki/Open-At-Startup
-- use a nix eval to dynamically insert the open on startup function
local function open_nvim_tree(data)
local IGNORED_FT = {
"markdown",
}
-- buffer is a real file on the disk
local real_file = vim.fn.filereadable(data.file) == 1
-- buffer is a [No Name]
local no_name = data.file == "" and vim.bo[data.buf].buftype == ""
-- &ft
local filetype = vim.bo[data.buf].ft
-- only files please
if not real_file and not no_name then
return
end
-- skip ignored filetypes
if vim.tbl_contains(IGNORED_FT, filetype) then
return
end
-- open the tree but don't focus it
require("nvim-tree.api").tree.toggle({ focus = false })
end
-- function to automatically open the tree on VimEnter
vim.api.nvim_create_autocmd({ "VimEnter" }, { callback = open_nvim_tree })
''
}
'';
}; };
} }

View file

@ -0,0 +1,49 @@
{
config,
pkgs,
lib,
...
}: let
inherit (lib.options) mkEnableOption mkOption;
inherit (lib.modules) mkIf mkMerge;
inherit (lib.types) package;
inherit (lib.nvim.types) mkGrammarOption;
cfg = config.vim.languages.assembly;
in {
options.vim.languages.assembly = {
enable = mkEnableOption "Assembly support";
treesitter = {
enable = mkEnableOption "Assembly treesitter" // {default = config.vim.languages.enableTreesitter;};
package = mkGrammarOption pkgs "asm";
};
lsp = {
enable = mkEnableOption "Assembly LSP support (asm-lsp)" // {default = config.vim.languages.enableLSP;};
package = mkOption {
type = package;
default = pkgs.asm-lsp;
description = "asm-lsp package";
};
};
};
config = mkIf cfg.enable (mkMerge [
(mkIf cfg.treesitter.enable {
vim.treesitter.enable = true;
vim.treesitter.grammars = [cfg.treesitter.package];
})
(mkIf cfg.lsp.enable {
vim.lsp.lspconfig.enable = true;
vim.lsp.lspconfig.sources.asm-lsp = ''
lspconfig.asm_lsp.setup {
capabilities = capabilities,
on_attach = default_on_attach,
cmd = {"${cfg.lsp.package}/bin/asm-lsp"},
}
'';
})
]);
}

View file

@ -0,0 +1,122 @@
{
lib,
pkgs,
config,
options,
...
}: let
inherit (builtins) attrNames;
inherit (lib.options) mkEnableOption mkOption;
inherit (lib.types) either listOf package str enum;
inherit (lib.modules) mkIf mkMerge;
inherit (lib.lists) isList;
inherit (lib.strings) optionalString;
inherit (lib.nvim.types) mkGrammarOption;
inherit (lib.nvim.lua) expToLua;
lspKeyConfig = config.vim.lsp.mappings;
lspKeyOptions = options.vim.lsp.mappings;
mkLspBinding = optionName: action: let
key = lspKeyConfig.${optionName};
desc = lspKeyOptions.${optionName}.description;
in
optionalString (key != null) "vim.keymap.set('n', '${key}', ${action}, {buffer=bufnr, noremap=true, silent=true, desc='${desc}'})";
# Omnisharp doesn't have colors in popup docs for some reason, and I've also
# seen mentions of it being way slower, so until someone finds missing
# functionality, this will be the default.
defaultServer = "csharp_ls";
servers = {
omnisharp = {
package = pkgs.omnisharp-roslyn;
internalFormatter = true;
lspConfig = ''
lspconfig.omnisharp.setup {
capabilities = capabilities,
on_attach = function(client, bufnr)
default_on_attach(client, bufnr)
local oe = require("omnisharp_extended")
${mkLspBinding "goToDefinition" "oe.lsp_definition"}
${mkLspBinding "goToType" "oe.lsp_type_definition"}
${mkLspBinding "listReferences" "oe.lsp_references"}
${mkLspBinding "listImplementations" "oe.lsp_implementation"}
end,
cmd = ${
if isList cfg.lsp.package
then expToLua cfg.lsp.package
else "{'${cfg.lsp.package}/bin/OmniSharp'}"
}
}
'';
};
csharp_ls = {
package = pkgs.csharp-ls;
internalFormatter = true;
lspConfig = ''
local extended_handler = require("csharpls_extended").handler
lspconfig.csharp_ls.setup {
capabilities = capabilities,
on_attach = default_on_attach,
handlers = {
["textDocument/definition"] = extended_handler,
["textDocument/typeDefinition"] = extended_handler
},
cmd = ${
if isList cfg.lsp.package
then expToLua cfg.lsp.package
else "{'${cfg.lsp.package}/bin/csharp-ls'}"
}
}
'';
};
};
extraServerPlugins = {
omnisharp = ["omnisharp-extended"];
csharp_ls = ["csharpls-extended"];
};
cfg = config.vim.languages.csharp;
in {
options = {
vim.languages.csharp = {
enable = mkEnableOption "C# language support";
treesitter = {
enable = mkEnableOption "C# treesitter" // {default = config.vim.languages.enableTreesitter;};
package = mkGrammarOption pkgs "c-sharp";
};
lsp = {
enable = mkEnableOption "C# LSP support" // {default = config.vim.languages.enableLSP;};
server = mkOption {
description = "C# LSP server to use";
type = enum (attrNames servers);
default = defaultServer;
};
package = mkOption {
description = "C# LSP server package, or the command to run as a list of strings";
type = either package (listOf str);
default = servers.${cfg.lsp.server}.package;
};
};
};
};
config = mkIf cfg.enable (mkMerge [
(mkIf cfg.treesitter.enable {
vim.treesitter.enable = true;
vim.treesitter.grammars = [cfg.treesitter.package];
})
(mkIf cfg.lsp.enable {
vim.startPlugins = extraServerPlugins.${cfg.lsp.server} or [];
vim.lsp.lspconfig.enable = true;
vim.lsp.lspconfig.sources.csharp-lsp = servers.${cfg.lsp.server}.lspConfig;
})
]);
}

View file

@ -63,6 +63,18 @@
) )
''; '';
}; };
biome = {
package = pkgs.biome;
nullConfig = ''
table.insert(
ls_sources,
null_ls.builtins.formatting.biome.with({
command = "${cfg.format.package}/bin/biome",
})
)
'';
};
}; };
in { in {
options.vim.languages.css = { options.vim.languages.css = {

View file

@ -2,6 +2,7 @@
inherit (lib.nvim.languages) mkEnable; inherit (lib.nvim.languages) mkEnable;
in { in {
imports = [ imports = [
./asm.nix
./bash.nix ./bash.nix
./dart.nix ./dart.nix
./clang.nix ./clang.nix
@ -9,16 +10,20 @@ in {
./elixir.nix ./elixir.nix
./go.nix ./go.nix
./hcl.nix ./hcl.nix
./kotlin.nix
./html.nix ./html.nix
./java.nix ./java.nix
./lua.nix ./lua.nix
./markdown.nix ./markdown.nix
./nim.nix ./nim.nix
./vala.nix
./nix.nix ./nix.nix
./ocaml.nix ./ocaml.nix
./php.nix ./php.nix
./python.nix ./python.nix
./r.nix
./rust.nix ./rust.nix
./scala.nix
./sql.nix ./sql.nix
./svelte.nix ./svelte.nix
./tailwind.nix ./tailwind.nix
@ -26,6 +31,8 @@ in {
./ts.nix ./ts.nix
./typst.nix ./typst.nix
./zig.nix ./zig.nix
./csharp.nix
./julia.nix
]; ];
options.vim.languages = { options.vim.languages = {

View file

@ -114,12 +114,12 @@ in {
(mkIf cfg.elixir-tools.enable { (mkIf cfg.elixir-tools.enable {
vim.startPlugins = ["elixir-tools"]; vim.startPlugins = ["elixir-tools"];
vim.pluginRC.elixir-tools = entryAnywhere '' vim.pluginRC.elixir-tools = entryAnywhere ''
local elixir-tools = require("elixir") local elixir = require("elixir")
local elixirls = require("elixir-tools.elixirls") local elixirls = require("elixir.elixirls")
-- disable imperative insstallations of various -- disable imperative insstallations of various
-- elixir related tools installed by elixir-tools -- elixir related tools installed by elixir-tools
elixir-tools.setup { elixir.setup {
nextls = { nextls = {
enable = false -- defaults to false enable = false -- defaults to false
}, },

View file

@ -0,0 +1,126 @@
{
lib,
pkgs,
config,
...
}: let
inherit (builtins) attrNames isList;
inherit (lib.options) mkEnableOption mkOption;
inherit (lib.types) either listOf package str enum bool nullOr;
inherit (lib.modules) mkIf mkMerge;
inherit (lib.strings) optionalString;
inherit (lib.nvim.types) mkGrammarOption;
inherit (lib.nvim.lua) expToLua;
defaultServer = "julials";
servers = {
julials = {
package = pkgs.julia.withPackages ["LanguageServer"];
internalFormatter = true;
lspConfig = ''
lspconfig.julials.setup {
capabilities = capabilities,
on_attach = default_on_attach,
cmd = ${
if isList cfg.lsp.package
then expToLua cfg.lsp.package
else ''
{
"${optionalString (cfg.lsp.package != null) "${cfg.lsp.package}/bin/"}julia",
"--startup-file=no",
"--history-file=no",
"--eval",
[[
using LanguageServer
depot_path = get(ENV, "JULIA_DEPOT_PATH", "")
project_path = let
dirname(something(
## 1. Finds an explicitly set project (JULIA_PROJECT)
Base.load_path_expand((
p = get(ENV, "JULIA_PROJECT", nothing);
p === nothing ? nothing : isempty(p) ? nothing : p
)),
## 2. Look for a Project.toml file in the current working directory,
## or parent directories, with $HOME as an upper boundary
Base.current_project(),
## 3. First entry in the load path
get(Base.load_path(), 1, nothing),
## 4. Fallback to default global environment,
## this is more or less unreachable
Base.load_path_expand("@v#.#"),
))
end
@info "Running language server" VERSION pwd() project_path depot_path
server = LanguageServer.LanguageServerInstance(stdin, stdout, project_path, depot_path)
server.runlinter = true
run(server)
]]
}
''
}
}
'';
};
};
cfg = config.vim.languages.julia;
in {
options = {
vim.languages.julia = {
enable = mkEnableOption "Julia language support";
treesitter = {
enable = mkEnableOption "Julia treesitter" // {default = config.vim.languages.enableTreesitter;};
package = mkGrammarOption pkgs "julia";
};
lsp = {
enable = mkOption {
type = bool;
default = config.vim.languages.enableLSP;
description = ''
Whether to enable Julia LSP support.
::: {.note}
The entirety of Julia is bundled with nvf, if you enable this
option, since there is no way to provide only the LSP server.
If you want to avoid that, you have to change
[](#opt-vim.languages.julia.lsp.package) to use the Julia binary
in {env}`PATH` (set it to `null`), and add the `LanguageServer` package to
Julia in your devshells.
:::
'';
};
server = mkOption {
type = enum (attrNames servers);
default = defaultServer;
description = "Julia LSP server to use";
};
package = mkOption {
description = ''
Julia LSP server package, `null` to use the Julia binary in {env}`PATH`, or
the command to run as a list of strings.
'';
type = nullOr (either package (listOf str));
default = servers.${cfg.lsp.server}.package;
};
};
};
};
config = mkIf cfg.enable (mkMerge [
(mkIf cfg.treesitter.enable {
vim.treesitter.enable = true;
vim.treesitter.grammars = [cfg.treesitter.package];
})
(mkIf cfg.lsp.enable {
vim.lsp.lspconfig.enable = true;
vim.lsp.lspconfig.sources.julia-lsp = servers.${cfg.lsp.server}.lspConfig;
})
]);
}

View file

@ -0,0 +1,107 @@
{
config,
pkgs,
lib,
...
}: let
inherit (lib.options) mkEnableOption mkOption literalExpression;
inherit (lib.modules) mkIf mkMerge;
inherit (lib.meta) getExe;
inherit (lib.nvim.languages) diagnosticsToLua;
inherit (lib.types) either package listOf str;
inherit (lib.nvim.types) mkGrammarOption diagnostics;
inherit (lib.lists) isList;
inherit (lib.nvim.lua) expToLua;
cfg = config.vim.languages.kotlin;
defaultDiagnosticsProvider = ["ktlint"];
diagnosticsProviders = {
ktlint = {
package = pkgs.ktlint;
nullConfig = pkg: ''
table.insert(
ls_sources,
null_ls.builtins.diagnostics.ktlint.with({
command = "${getExe pkg}",
})
)
'';
};
};
in {
options.vim.languages.kotlin = {
enable = mkEnableOption "Kotlin/HCL support";
treesitter = {
enable = mkEnableOption "Kotlin treesitter" // {default = config.vim.languages.enableTreesitter;};
package = mkGrammarOption pkgs "kotlin";
};
lsp = {
enable = mkEnableOption "Kotlin LSP support" // {default = config.vim.languages.enableLSP;};
package = mkOption {
description = "kotlin_language_server package with Kotlin runtime";
type = either package (listOf str);
example = literalExpression ''
pkgs.symlinkJoin {
name = "kotlin-language-server-wrapped";
paths = [pkgs.kotlin-language-server];
nativeBuildInputs = [pkgs.makeBinaryWrapper];
postBuild = '''
wrapProgram $out/bin/kotlin-language-server \
--prefix PATH : ''${pkgs.kotlin}/bin
''';
};
'';
default = pkgs.kotlin-language-server;
};
};
extraDiagnostics = {
enable = mkEnableOption "extra Kotlin diagnostics" // {default = config.vim.languages.enableExtraDiagnostics;};
types = diagnostics {
langDesc = "Kotlin";
inherit diagnosticsProviders;
inherit defaultDiagnosticsProvider;
};
};
};
config = mkIf cfg.enable (mkMerge [
(mkIf cfg.treesitter.enable {
vim.treesitter.enable = true;
vim.treesitter.grammars = [cfg.treesitter.package];
})
(mkIf cfg.extraDiagnostics.enable {
vim.lsp.null-ls.enable = true;
vim.lsp.null-ls.sources = diagnosticsToLua {
lang = "kotlin";
config = cfg.extraDiagnostics.types;
inherit diagnosticsProviders;
};
})
(mkIf cfg.lsp.enable {
vim.lsp.lspconfig.enable = true;
vim.lsp.lspconfig.sources.kotlin_language_server = ''
lspconfig.kotlin_language_server.setup {
capabilities = capabilities,
root_dir = lspconfig.util.root_pattern("main.kt", ".git"),
on_attach=default_on_attach,
init_options = {
-- speeds up the startup time for the LSP
storagePath = vim.fn.stdpath('state') .. '/kotlin',
},
cmd = ${
if isList cfg.lsp.package
then expToLua cfg.lsp.package
else ''{"${cfg.lsp.package}/bin/kotlin-language-server"}''
},
}
'';
})
]);
}

View file

@ -5,6 +5,7 @@
... ...
}: let }: let
inherit (builtins) attrNames; inherit (builtins) attrNames;
inherit (lib) concatStringsSep;
inherit (lib.options) mkEnableOption mkOption; inherit (lib.options) mkEnableOption mkOption;
inherit (lib.modules) mkIf mkMerge; inherit (lib.modules) mkIf mkMerge;
inherit (lib.lists) isList; inherit (lib.lists) isList;
@ -62,10 +63,10 @@
command = {"${cfg.format.package}/bin/alejandra", "--quiet"}, command = {"${cfg.format.package}/bin/alejandra", "--quiet"},
}, },
''} ''}
${optionalString (cfg.format.type == "nixpkgs-fmt") ${optionalString (cfg.format.type == "nixfmt")
'' ''
formatting = { formatting = {
command = {"${cfg.format.package}/bin/nixpkgs-fmt"}, command = {"${cfg.format.package}/bin/nixfmt"},
}, },
''} ''}
}, },
@ -90,10 +91,19 @@
''; '';
}; };
nixpkgs-fmt = { nixfmt = {
package = pkgs.nixpkgs-fmt; package = pkgs.nixfmt-rfc-style;
# Never need to use null-ls for nixpkgs-fmt nullConfig = ''
table.insert(
ls_sources,
null_ls.builtins.formatting.nixfmt.with({
command = "${cfg.format.package}/bin/nixfmt"
})
)
'';
}; };
nixpkgs-fmt = null; # removed
}; };
defaultDiagnosticsProvider = ["statix" "deadnix"]; defaultDiagnosticsProvider = ["statix" "deadnix"];
@ -135,7 +145,7 @@ in {
enable = mkEnableOption "Nix LSP support" // {default = config.vim.languages.enableLSP;}; enable = mkEnableOption "Nix LSP support" // {default = config.vim.languages.enableLSP;};
server = mkOption { server = mkOption {
description = "Nix LSP server to use"; description = "Nix LSP server to use";
type = str; type = enum (attrNames servers);
default = defaultServer; default = defaultServer;
}; };
@ -175,6 +185,12 @@ in {
config = mkIf cfg.enable (mkMerge [ config = mkIf cfg.enable (mkMerge [
{ {
assertions = [
{
assertion = cfg.format.type != "nixpkgs-fmt";
message = "nixpkgs-fmt has been archived upstream. Please use one of the following instead: ${concatStringsSep ", " (attrNames formats)}";
}
];
vim.pluginRC.nix = '' vim.pluginRC.nix = ''
vim.api.nvim_create_autocmd("FileType", { vim.api.nvim_create_autocmd("FileType", {
pattern = "nix", pattern = "nix",

View file

@ -0,0 +1,130 @@
{
config,
pkgs,
lib,
...
}: let
inherit (builtins) attrNames;
inherit (lib.options) mkEnableOption mkOption literalExpression;
inherit (lib.modules) mkIf mkMerge;
inherit (lib.lists) isList;
inherit (lib.types) enum either listOf package str;
inherit (lib.nvim.lua) expToLua;
inherit (lib.nvim.types) mkGrammarOption;
cfg = config.vim.languages.r;
r-with-languageserver = pkgs.rWrapper.override {
packages = [pkgs.rPackages.languageserver];
};
defaultFormat = "format_r";
formats = {
styler = {
package = pkgs.rWrapper.override {
packages = [pkgs.rPackages.styler];
};
nullConfig = ''
table.insert(
ls_sources,
null_ls.builtins.formatting.styler.with({
command = "${cfg.format.package}/bin/R",
})
)
'';
};
format_r = {
package = pkgs.rWrapper.override {
packages = [pkgs.rPackages.formatR];
};
nullConfig = ''
table.insert(
ls_sources,
null_ls.builtins.formatting.format_r.with({
command = "${cfg.format.package}/bin/R",
})
)
'';
};
};
defaultServer = "r_language_server";
servers = {
r_language_server = {
package = pkgs.writeShellScriptBin "r_lsp" ''
${r-with-languageserver}/bin/R --slave -e "languageserver::run()"
'';
lspConfig = ''
lspconfig.r_language_server.setup{
capabilities = capabilities;
on_attach = default_on_attach;
cmd = ${
if isList cfg.lsp.package
then expToLua cfg.lsp.package
else ''{"${lib.getExe cfg.lsp.package}"}''
}
}
'';
};
};
in {
options.vim.languages.r = {
enable = mkEnableOption "R language support";
treesitter = {
enable = mkEnableOption "R treesitter" // {default = config.vim.languages.enableTreesitter;};
package = mkGrammarOption pkgs "r";
};
lsp = {
enable = mkEnableOption "R LSP support" // {default = config.vim.languages.enableLSP;};
server = mkOption {
description = "R LSP server to use";
type = enum (attrNames servers);
default = defaultServer;
};
package = mkOption {
description = "R LSP server package, or the command to run as a list of strings";
example = literalExpression "[ (lib.getExe pkgs.jdt-language-server) \"-data\" \"~/.cache/jdtls/workspace\" ]";
type = either package (listOf str);
default = servers.${cfg.lsp.server}.package;
};
};
format = {
enable = mkEnableOption "R formatting" // {default = config.vim.languages.enableFormat;};
type = mkOption {
type = enum (attrNames formats);
default = defaultFormat;
description = "R formatter to use";
};
package = mkOption {
type = package;
default = formats.${cfg.format.type}.package;
description = "R formatter package";
};
};
};
config = mkIf cfg.enable (mkMerge [
(mkIf cfg.treesitter.enable {
vim.treesitter.enable = true;
vim.treesitter.grammars = [cfg.treesitter.package];
})
(mkIf cfg.format.enable {
vim.lsp.null-ls.enable = true;
vim.lsp.null-ls.sources.r-format = formats.${cfg.format.type}.nullConfig;
})
(mkIf cfg.lsp.enable {
vim.lsp.lspconfig.enable = true;
vim.lsp.lspconfig.sources.r-lsp = servers.${cfg.lsp.server}.lspConfig;
})
]);
}

View file

@ -9,7 +9,7 @@
inherit (lib.options) mkOption mkEnableOption; inherit (lib.options) mkOption mkEnableOption;
inherit (lib.strings) optionalString; inherit (lib.strings) optionalString;
inherit (lib.trivial) boolToString; inherit (lib.trivial) boolToString;
inherit (lib.lists) isList optionals; inherit (lib.lists) isList;
inherit (lib.types) bool package str listOf either enum; inherit (lib.types) bool package str listOf either enum;
inherit (lib.nvim.types) mkGrammarOption; inherit (lib.nvim.types) mkGrammarOption;
inherit (lib.nvim.lua) expToLua; inherit (lib.nvim.lua) expToLua;
@ -101,7 +101,7 @@ in {
vim = { vim = {
startPlugins = ["crates-nvim"]; startPlugins = ["crates-nvim"];
lsp.null-ls.enable = mkIf cfg.crates.codeActions true; lsp.null-ls.enable = mkIf cfg.crates.codeActions true;
autocomplete.sources = {"crates" = "[Crates]";}; autocomplete.nvim-cmp.sources = {crates = "[Crates]";};
pluginRC.rust-crates = entryAnywhere '' pluginRC.rust-crates = entryAnywhere ''
require('crates').setup { require('crates').setup {
null_ls = { null_ls = {

View file

@ -0,0 +1,149 @@
{
config,
pkgs,
lib,
...
}: let
inherit (lib.generators) mkLuaInline;
inherit (lib.modules) mkIf mkMerge;
inherit (lib.nvim.binds) mkMappingOption;
inherit (lib.nvim.dag) entryAfter;
inherit (lib.nvim.lua) toLuaObject;
inherit (lib.nvim.types) mkGrammarOption luaInline;
inherit (lib.options) mkOption mkEnableOption mkPackageOption;
inherit (lib.strings) optionalString;
inherit (lib.types) attrsOf anything bool;
listCommandsAction =
if config.vim.telescope.enable
then ''require("telescope").extensions.metals.commands()''
else ''require("metals").commands()'';
cfg = config.vim.languages.scala;
usingDap = config.vim.debugger.nvim-dap.enable && cfg.dap.enable;
usingLualine = config.vim.statusline.lualine.enable;
in {
options.vim.languages.scala = {
enable = mkEnableOption "Scala language support";
treesitter = {
enable = mkEnableOption "Scala treesitter" // {default = config.vim.languages.enableTreesitter;};
package = mkGrammarOption pkgs "scala";
};
lsp = {
enable = mkEnableOption "Scala LSP support (metals)" // {default = config.vim.languages.enableLSP;};
package = mkPackageOption pkgs "metals" {
default = ["metals"];
};
extraMappings = {
listCommands = mkMappingOption "List Metals commands" "<leader>lc";
};
extraSettings = mkOption {
type = attrsOf anything;
description = "Extra settings passed to the metals config. Check nvim-metals docs for available options";
default = {
showImplicitArguments = true;
showImplicitConversionsAndClasses = true;
showInferredType = true;
excludedPackages = [
"akka.actor.typed.javadsl"
"com.github.swagger.akka.javadsl"
];
};
};
};
dap = {
enable = mkEnableOption "Scala Debug Adapter support (metals)" // {default = config.vim.languages.enableDAP;};
config = mkOption {
description = "Lua configuration for dap";
type = luaInline;
default = mkLuaInline ''
dap.configurations.scala = {
{
type = "scala",
request = "launch",
name = "RunOrTest",
metals = {
runType = "runOrTestFile",
--args = { "firstArg", "secondArg", "thirdArg" }, -- here just as an example
},
},
{
type = "scala",
request = "launch",
name = "Test Target",
metals = {
runType = "testTarget",
},
},
}
'';
};
};
fixShortmess = mkOption {
type = bool;
description = "Remove the 'F' flag from shortmess to allow messages to be shown. Without doing this, autocommands that deal with filetypes prohibit messages from being shown";
default = true;
};
};
config = mkIf cfg.enable (
mkMerge [
(mkIf cfg.treesitter.enable {
vim.treesitter.enable = true;
vim.treesitter.grammars = [cfg.treesitter.package];
})
(mkIf (cfg.lsp.enable || cfg.dap.enable) {
vim = {
startPlugins = ["nvim-metals"];
pluginRC.nvim-metals = entryAfter ["lsp-setup"] ''
local metals_caps = capabilities -- from lsp-setup
local attach_metals_keymaps = function(client, bufnr)
attach_keymaps(client, bufnr) -- from lsp-setup
vim.api.nvim_buf_set_keymap(bufnr, 'n', '${cfg.lsp.extraMappings.listCommands}', '<cmd>lua ${listCommandsAction}<CR>', {noremap=true, silent=true, desc='Show all Metals commands'})
end
metals_config = require('metals').bare_config()
${optionalString usingLualine "metals_config.init_options.statusBarProvider = 'on'"}
metals_config.capabilities = metals_caps
metals_config.on_attach = function(client, bufnr)
${optionalString usingDap "require('metals').setup_dap()"}
attach_metals_keymaps(client, bufnr)
end
metals_config.settings = ${toLuaObject cfg.lsp.extraSettings}
metals_config.settings.metalsBinaryPath = "${cfg.lsp.package}/bin/metals"
metals_config.handlers["textDocument/publishDiagnostics"] = vim.lsp.with(
vim.lsp.diagnostic.on_publish_diagnostics, {
virtual_text = {
prefix = '',
}
}
)
${optionalString cfg.fixShortmess ''vim.opt_global.shortmess:remove("F")''}
local lsp_group = vim.api.nvim_create_augroup('lsp', { clear = true })
vim.api.nvim_create_autocmd('FileType', {
group = lsp_group,
pattern = {'java', 'scala', 'sbt'},
callback = function()
require('metals').initialize_or_attach(metals_config)
end,
})
'';
};
})
]
);
}

View file

@ -48,6 +48,18 @@
) )
''; '';
}; };
biome = {
package = pkgs.biome;
nullConfig = ''
table.insert(
ls_sources,
null_ls.builtins.formatting.biome.with({
command = "${cfg.format.package}/bin/biome",
})
)
'';
};
}; };
# TODO: specify packages # TODO: specify packages

View file

@ -17,12 +17,12 @@
cfg = config.vim.languages.ts; cfg = config.vim.languages.ts;
defaultServer = "tsserver"; defaultServer = "ts_ls";
servers = { servers = {
tsserver = { ts_ls = {
package = pkgs.typescript-language-server; package = pkgs.typescript-language-server;
lspConfig = '' lspConfig = ''
lspconfig.tsserver.setup { lspconfig.ts_ls.setup {
capabilities = capabilities; capabilities = capabilities;
on_attach = attach_keymaps, on_attach = attach_keymaps,
cmd = ${ cmd = ${
@ -49,6 +49,24 @@
} }
''; '';
}; };
# Here for backwards compatibility. Still consider tsserver a valid
# configuration in the enum, but assert if it's set to *properly*
# redirect the user to the correct server.
tsserver = {
package = pkgs.typescript-language-server;
lspConfig = ''
lspconfig.ts_ls.setup {
capabilities = capabilities;
on_attach = attach_keymaps,
cmd = ${
if isList cfg.lsp.package
then expToLua cfg.lsp.package
else ''{"${cfg.lsp.package}/bin/typescript-language-server", "--stdio"}''
}
}
'';
};
}; };
# TODO: specify packages # TODO: specify packages
@ -65,6 +83,7 @@
) )
''; '';
}; };
prettierd = { prettierd = {
package = pkgs.prettierd; package = pkgs.prettierd;
nullConfig = '' nullConfig = ''
@ -76,6 +95,18 @@
) )
''; '';
}; };
biome = {
package = pkgs.biome;
nullConfig = ''
table.insert(
ls_sources,
null_ls.builtins.formatting.biome.with({
command = "${cfg.format.package}/bin/biome",
})
)
'';
};
}; };
# TODO: specify packages # TODO: specify packages
@ -94,6 +125,7 @@
}; };
}; };
in { in {
_file = ./ts.nix;
options.vim.languages.ts = { options.vim.languages.ts = {
enable = mkEnableOption "Typescript/Javascript language support"; enable = mkEnableOption "Typescript/Javascript language support";
@ -190,11 +222,32 @@ in {
}; };
}) })
# Extensions
(mkIf cfg.extensions."ts-error-translator".enable { (mkIf cfg.extensions."ts-error-translator".enable {
vim.startPlugins = ["ts-error-translator"]; vim.startPlugins = ["ts-error-translator"];
vim.pluginRC.ts-error-translator = entryAnywhere '' vim.pluginRC.ts-error-translator = entryAnywhere ''
require("ts-error-translator").setup(${toLuaObject cfg.extensions.ts-error-translator.setupOpts}) require("ts-error-translator").setup(${toLuaObject cfg.extensions.ts-error-translator.setupOpts})
''; '';
}) })
# Warn the user if they have set the default server name to tsserver to match upstream (us)
# The name "tsserver" has been deprecated in lspconfig, and now should be called ts_ls. This
# is a purely cosmetic change, but emits a warning if not accounted for.
{
assertions = [
{
assertion = cfg.lsp.enable -> cfg.lsp.server != "tsserver";
message = ''
As of a recent lspconfig update, the `tsserver` configuration has been renamed
to `ts_ls` to match upstream behaviour of `lspconfig`, and the name `tsserver`
is no longer considered valid by nvf. Please set `vim.languages.ts.lsp.server`
to `"ts_ls"` instead of to `${cfg.lsp.server}`
Please see <https://github.com/neovim/nvim-lspconfig/pull/3232> for more details
about this change.
'';
}
];
}
]); ]);
} }

View file

@ -14,6 +14,39 @@
cfg = config.vim.languages.typst; cfg = config.vim.languages.typst;
defaultServer = "tinymist";
servers = {
typst-lsp = {
package = pkgs.typst-lsp;
lspConfig = ''
lspconfig.typst_lsp.setup {
capabilities = capabilities,
on_attach = default_on_attach,
cmd = ${
if isList cfg.lsp.package
then expToLua cfg.lsp.package
else ''{"${cfg.lsp.package}/bin/typst-lsp"}''
},
}
'';
};
tinymist = {
package = pkgs.tinymist;
lspConfig = ''
lspconfig.tinymist.setup {
capabilities = capabilities,
single_file_support = true,
on_attach = default_on_attach,
cmd = ${
if isList cfg.lsp.package
then expToLua cfg.lsp.package
else ''{"${cfg.lsp.package}/bin/tinymist"}''
},
}
'';
};
};
defaultFormat = "typstfmt"; defaultFormat = "typstfmt";
formats = { formats = {
typstfmt = { typstfmt = {
@ -52,11 +85,17 @@ in {
lsp = { lsp = {
enable = mkEnableOption "Typst LSP support (typst-lsp)" // {default = config.vim.languages.enableLSP;}; enable = mkEnableOption "Typst LSP support (typst-lsp)" // {default = config.vim.languages.enableLSP;};
server = mkOption {
description = "Typst LSP server to use";
type = enum (attrNames servers);
default = defaultServer;
};
package = mkOption { package = mkOption {
description = "typst-lsp package, or the command to run as a list of strings"; description = "typst-lsp package, or the command to run as a list of strings";
example = ''[lib.getExe pkgs.jdt-language-server "-data" "~/.cache/jdtls/workspace"]''; example = ''[lib.getExe pkgs.jdt-language-server "-data" "~/.cache/jdtls/workspace"]'';
type = either package (listOf str); type = either package (listOf str);
default = pkgs.typst-lsp; default = servers.${cfg.lsp.server}.package;
}; };
}; };
@ -82,19 +121,14 @@ in {
vim.treesitter.grammars = [cfg.treesitter.package]; vim.treesitter.grammars = [cfg.treesitter.package];
}) })
(mkIf cfg.format.enable {
vim.lsp.null-ls.enable = true;
vim.lsp.null-ls.sources.typst-format = formats.${cfg.format.type}.nullConfig;
})
(mkIf cfg.lsp.enable { (mkIf cfg.lsp.enable {
vim.lsp.lspconfig.enable = true; vim.lsp.lspconfig.enable = true;
vim.lsp.lspconfig.sources.typst-lsp = '' vim.lsp.lspconfig.sources.typst-lsp = servers.${cfg.lsp.server}.lspConfig;
lspconfig.typst_lsp.setup {
capabilities = capabilities,
on_attach=default_on_attach,
cmd = ${
if isList cfg.lsp.package
then expToLua cfg.lsp.package
else ''{"${cfg.lsp.package}/bin/typst-lsp"}''
},
}
'';
}) })
]); ]);
} }

View file

@ -0,0 +1,79 @@
{
config,
pkgs,
lib,
...
}: let
inherit (builtins) attrNames;
inherit (lib.options) mkEnableOption mkOption;
inherit (lib.modules) mkIf mkMerge;
inherit (lib.lists) isList;
inherit (lib.types) enum either listOf package str;
inherit (lib.nvim.types) mkGrammarOption;
inherit (lib.nvim.lua) expToLua;
cfg = config.vim.languages.vala;
defaultServer = "vala_ls";
servers = {
vala_ls = {
package = pkgs.symlinkJoin {
name = "vala-language-server-wrapper";
paths = [pkgs.vala-language-server];
buildInputs = [pkgs.makeBinaryWrapper];
postBuild = ''
wrapProgram $out/bin/vala-language-server \
--prefix PATH : ${pkgs.uncrustify}/bin
'';
};
internalFormatter = true;
lspConfig = ''
lspconfig.vala_ls.setup {
capabilities = capabilities;
on_attach = default_on_attach;
cmd = ${
if isList cfg.lsp.package
then expToLua cfg.lsp.package
else ''{"${cfg.lsp.package}/bin/vala-language-server"}''
},
}
'';
};
};
in {
options.vim.languages.vala = {
enable = mkEnableOption "Vala language support";
treesitter = {
enable = mkEnableOption "Vala treesitter" // {default = config.vim.languages.enableTreesitter;};
package = mkGrammarOption pkgs "vala";
};
lsp = {
enable = mkEnableOption "Vala LSP support" // {default = config.vim.languages.enableLSP;};
server = mkOption {
description = "Vala LSP server to use";
type = enum (attrNames servers);
default = defaultServer;
};
package = mkOption {
description = "Vala LSP server package, or the command to run as a list of strings";
type = either package (listOf str);
default = servers.${cfg.lsp.server}.package;
};
};
};
config = mkIf cfg.enable (mkMerge [
(mkIf cfg.treesitter.enable {
vim.treesitter.enable = true;
vim.treesitter.grammars = [cfg.treesitter.package];
})
(mkIf cfg.lsp.enable {
vim.lsp.lspconfig.enable = true;
vim.lsp.lspconfig.sources.vala_ls = servers.${cfg.lsp.server}.lspConfig;
})
]);
}

View file

@ -4,13 +4,33 @@
lib, lib,
... ...
}: let }: let
inherit (builtins) attrNames;
inherit (lib.options) mkEnableOption mkOption; inherit (lib.options) mkEnableOption mkOption;
inherit (lib.modules) mkIf mkMerge; inherit (lib.modules) mkIf mkMerge;
inherit (lib.lists) isList; inherit (lib.lists) isList;
inherit (lib.types) either listOf package str; inherit (lib.types) either listOf package str enum;
inherit (lib.nvim.lua) expToLua; inherit (lib.nvim.lua) expToLua;
inherit (lib.nvim.types) mkGrammarOption; inherit (lib.nvim.types) mkGrammarOption;
defaultServer = "zls";
servers = {
zls = {
package = pkgs.zls;
internalFormatter = true;
lspConfig = ''
lspconfig.zls.setup {
capabilities = capabilities,
on_attach = default_on_attach,
cmd = ${
if isList cfg.lsp.package
then expToLua cfg.lsp.package
else "{'${cfg.lsp.package}/bin/zls'}"
}
}
'';
};
};
cfg = config.vim.languages.zig; cfg = config.vim.languages.zig;
in { in {
options.vim.languages.zig = { options.vim.languages.zig = {
@ -22,20 +42,19 @@ in {
}; };
lsp = { lsp = {
enable = mkEnableOption "Zig LSP support (zls)" // {default = config.vim.languages.enableLSP;}; enable = mkEnableOption "Zig LSP support" // {default = config.vim.languages.enableLSP;};
server = mkOption {
type = enum (attrNames servers);
default = defaultServer;
description = "Zig LSP server to use";
};
package = mkOption { package = mkOption {
description = "ZLS package, or the command to run as a list of strings"; description = "ZLS package, or the command to run as a list of strings";
example = ''[lib.getExe pkgs.jdt-language-server "-data" "~/.cache/jdtls/workspace"]'';
type = either package (listOf str); type = either package (listOf str);
default = pkgs.zls; default = pkgs.zls;
}; };
zigPackage = mkOption {
description = "Zig package used by ZLS";
type = package;
default = pkgs.zig;
};
}; };
}; };
config = mkIf cfg.enable (mkMerge [ config = mkIf cfg.enable (mkMerge [
@ -46,23 +65,7 @@ in {
(mkIf cfg.lsp.enable { (mkIf cfg.lsp.enable {
vim.lsp.lspconfig.enable = true; vim.lsp.lspconfig.enable = true;
vim.lsp.lspconfig.sources.zig-lsp = '' vim.lsp.lspconfig.sources.zig-lsp = servers.${cfg.lsp.server}.lspConfig;
lspconfig.zls.setup {
capabilities = capabilities,
on_attach=default_on_attach,
cmd = ${
if isList cfg.lsp.package
then expToLua cfg.lsp.package
else ''{"${cfg.lsp.package}/bin/zls"}''
},
settings = {
["zls"] = {
zig_exe_path = "${cfg.lsp.zigPackage}/bin/zig",
zig_lib_path = "${cfg.lsp.zigPackage}/lib/zig",
}
}
}
'';
}) })
]); ]);
} }

View file

@ -5,52 +5,52 @@
... ...
}: let }: let
inherit (lib.modules) mkIf; inherit (lib.modules) mkIf;
inherit (lib.lists) optional;
inherit (lib.strings) optionalString; inherit (lib.strings) optionalString;
inherit (lib.trivial) boolToString; inherit (lib.trivial) boolToString;
inherit (lib.nvim.binds) addDescriptionsToMappings; inherit (lib.nvim.binds) addDescriptionsToMappings;
cfg = config.vim.lsp; cfg = config.vim.lsp;
usingNvimCmp = config.vim.autocomplete.enable && config.vim.autocomplete.type == "nvim-cmp"; usingNvimCmp = config.vim.autocomplete.nvim-cmp.enable;
self = import ./module.nix {inherit config lib pkgs;}; self = import ./module.nix {inherit config lib pkgs;};
mappingDefinitions = self.options.vim.lsp.mappings; mappingDefinitions = self.options.vim.lsp.mappings;
mappings = addDescriptionsToMappings cfg.mappings mappingDefinitions; mappings = addDescriptionsToMappings cfg.mappings mappingDefinitions;
mkBinding = binding: action: mkBinding = binding: action:
if binding.value != null if binding.value != null
then "vim.api.nvim_buf_set_keymap(bufnr, 'n', '${binding.value}', '<cmd>lua ${action}<CR>', {noremap=true, silent=true, desc='${binding.description}'})" then "vim.keymap.set('n', '${binding.value}', ${action}, {buffer=bufnr, noremap=true, silent=true, desc='${binding.description}'})"
else ""; else "";
in { in {
config = mkIf cfg.enable { config = mkIf cfg.enable {
vim = { vim = {
startPlugins = optional usingNvimCmp "cmp-nvim-lsp"; autocomplete.nvim-cmp = {
sources = {nvim_lsp = "[LSP]";};
autocomplete.sources = {"nvim_lsp" = "[LSP]";}; sourcePlugins = ["cmp-nvim-lsp"];
};
pluginRC.lsp-setup = '' pluginRC.lsp-setup = ''
vim.g.formatsave = ${boolToString cfg.formatOnSave}; vim.g.formatsave = ${boolToString cfg.formatOnSave};
local attach_keymaps = function(client, bufnr) local attach_keymaps = function(client, bufnr)
${mkBinding mappings.goToDeclaration "vim.lsp.buf.declaration()"} ${mkBinding mappings.goToDeclaration "vim.lsp.buf.declaration"}
${mkBinding mappings.goToDefinition "vim.lsp.buf.definition()"} ${mkBinding mappings.goToDefinition "vim.lsp.buf.definition"}
${mkBinding mappings.goToType "vim.lsp.buf.type_definition()"} ${mkBinding mappings.goToType "vim.lsp.buf.type_definition"}
${mkBinding mappings.listImplementations "vim.lsp.buf.implementation()"} ${mkBinding mappings.listImplementations "vim.lsp.buf.implementation"}
${mkBinding mappings.listReferences "vim.lsp.buf.references()"} ${mkBinding mappings.listReferences "vim.lsp.buf.references"}
${mkBinding mappings.nextDiagnostic "vim.diagnostic.goto_next()"} ${mkBinding mappings.nextDiagnostic "vim.diagnostic.goto_next"}
${mkBinding mappings.previousDiagnostic "vim.diagnostic.goto_prev()"} ${mkBinding mappings.previousDiagnostic "vim.diagnostic.goto_prev"}
${mkBinding mappings.openDiagnosticFloat "vim.diagnostic.open_float()"} ${mkBinding mappings.openDiagnosticFloat "vim.diagnostic.open_float"}
${mkBinding mappings.documentHighlight "vim.lsp.buf.document_highlight()"} ${mkBinding mappings.documentHighlight "vim.lsp.buf.document_highlight"}
${mkBinding mappings.listDocumentSymbols "vim.lsp.buf.document_symbol()"} ${mkBinding mappings.listDocumentSymbols "vim.lsp.buf.document_symbol"}
${mkBinding mappings.addWorkspaceFolder "vim.lsp.buf.add_workspace_folder()"} ${mkBinding mappings.addWorkspaceFolder "vim.lsp.buf.add_workspace_folder"}
${mkBinding mappings.removeWorkspaceFolder "vim.lsp.buf.remove_workspace_folder()"} ${mkBinding mappings.removeWorkspaceFolder "vim.lsp.buf.remove_workspace_folder"}
${mkBinding mappings.listWorkspaceFolders "print(vim.inspect(vim.lsp.buf.list_workspace_folders()))"} ${mkBinding mappings.listWorkspaceFolders "function() vim.notify(vim.inspect(vim.lsp.buf.list_workspace_folders())) end"}
${mkBinding mappings.listWorkspaceSymbols "vim.lsp.buf.workspace_symbol()"} ${mkBinding mappings.listWorkspaceSymbols "vim.lsp.buf.workspace_symbol"}
${mkBinding mappings.hover "vim.lsp.buf.hover()"} ${mkBinding mappings.hover "vim.lsp.buf.hover"}
${mkBinding mappings.signatureHelp "vim.lsp.buf.signature_help()"} ${mkBinding mappings.signatureHelp "vim.lsp.buf.signature_help"}
${mkBinding mappings.renameSymbol "vim.lsp.buf.rename()"} ${mkBinding mappings.renameSymbol "vim.lsp.buf.rename"}
${mkBinding mappings.codeAction "vim.lsp.buf.code_action()"} ${mkBinding mappings.codeAction "vim.lsp.buf.code_action"}
${mkBinding mappings.format "vim.lsp.buf.format()"} ${mkBinding mappings.format "vim.lsp.buf.format"}
${mkBinding mappings.toggleFormatOnSave "vim.b.disableFormatSave = not vim.b.disableFormatSave"} ${mkBinding mappings.toggleFormatOnSave "function() vim.b.disableFormatSave = not vim.b.disableFormatSave end"}
end end
-- Enable formatting -- Enable formatting
@ -116,7 +116,60 @@ in {
end end
local capabilities = vim.lsp.protocol.make_client_capabilities() local capabilities = vim.lsp.protocol.make_client_capabilities()
${optionalString usingNvimCmp "capabilities = require('cmp_nvim_lsp').default_capabilities()"} ${optionalString usingNvimCmp ''
-- HACK: copied from cmp-nvim-lsp. If we ever lazy load lspconfig we
-- should re-evaluate whether we can just use `default_capabilities`
capabilities = {
textDocument = {
completion = {
dynamicRegistration = false,
completionItem = {
snippetSupport = true,
commitCharactersSupport = true,
deprecatedSupport = true,
preselectSupport = true,
tagSupport = {
valueSet = {
1, -- Deprecated
}
},
insertReplaceSupport = true,
resolveSupport = {
properties = {
"documentation",
"detail",
"additionalTextEdits",
"sortText",
"filterText",
"insertText",
"textEdit",
"insertTextFormat",
"insertTextMode",
},
},
insertTextModeSupport = {
valueSet = {
1, -- asIs
2, -- adjustIndentation
}
},
labelDetailsSupport = true,
},
contextSupport = true,
insertTextMode = 1,
completionList = {
itemDefaults = {
'commitCharacters',
'editRange',
'insertTextFormat',
'insertTextMode',
'data',
}
}
},
},
}
''}
''; '';
}; };
}; };

View file

@ -13,6 +13,7 @@
./trouble ./trouble
./lsp-signature ./lsp-signature
./lightbulb ./lightbulb
./otter
./lspkind ./lspkind
./lsplines ./lsplines
./nvim-docs-view ./nvim-docs-view

View file

@ -3,18 +3,32 @@
lib, lib,
... ...
}: let }: let
inherit (lib.modules) mkIf; inherit (lib.modules) mkIf mkForce;
inherit (lib.nvim.dag) entryAnywhere; inherit (lib.generators) mkLuaInline;
inherit (lib.nvim.lua) toLuaObject;
cfg = config.vim.lsp; cfg = config.vim.lsp.lspkind;
in { in {
config = mkIf (cfg.enable && cfg.lspkind.enable) { config = mkIf cfg.enable {
vim.startPlugins = ["lspkind"]; assertions = [
vim.pluginRC.lspkind = entryAnywhere '' {
local lspkind = require'lspkind' assertion = config.vim.autocomplete.nvim-cmp.enable;
local lspkind_opts = { message = ''
mode = '${cfg.lspkind.mode}' While lspkind supports Neovim's native lsp upstream, using that over
nvim-cmp isn't recommended, nor supported by nvf.
Please migrate to nvim-cmp if you want to use lspkind.
'';
} }
''; ];
vim = {
startPlugins = ["lspkind"];
lsp.lspkind.setupOpts.before = config.vim.autocomplete.nvim-cmp.format;
autocomplete.nvim-cmp.setupOpts.formatting.format = mkForce (mkLuaInline ''
require("lspkind").cmp_format(${toLuaObject cfg.setupOpts})
'');
};
}; };
} }

View file

@ -1,16 +1,22 @@
{lib, ...}: let {lib, ...}: let
inherit (lib.options) mkEnableOption mkOption; inherit (lib.options) mkEnableOption mkOption;
inherit (lib.types) enum; inherit (lib.types) enum nullOr;
inherit (lib.nvim.types) mkPluginSetupOption luaInline;
in { in {
options.vim.lsp = { options.vim.lsp.lspkind = {
lspkind = { enable = mkEnableOption "vscode-like pictograms for lsp [lspkind]";
enable = mkEnableOption "vscode-like pictograms for lsp [lspkind]"; setupOpts = mkPluginSetupOption "lspkind.nvim" {
mode = mkOption { mode = mkOption {
description = "Defines how annotations are shown"; description = "Defines how annotations are shown";
type = enum ["text" "text_symbol" "symbol_text" "symbol"]; type = enum ["text" "text_symbol" "symbol_text" "symbol"];
default = "symbol_text"; default = "symbol_text";
}; };
before = mkOption {
description = "The function that will be called before lspkind's modifications are applied";
type = nullOr luaInline;
default = null;
};
}; };
}; };
} }

View file

@ -0,0 +1,39 @@
{
config,
lib,
...
}: let
inherit (lib.modules) mkIf mkMerge;
inherit (lib.nvim.dag) entryAnywhere;
inherit (lib.nvim.lua) toLuaObject;
inherit (lib.nvim.binds) addDescriptionsToMappings mkSetBinding;
cfg = config.vim.lsp;
self = import ./otter.nix {inherit lib;};
mappingDefinitions = self.options.vim.lsp.otter-nvim.mappings;
mappings = addDescriptionsToMappings cfg.otter-nvim.mappings mappingDefinitions;
in {
config = mkIf (cfg.enable && cfg.otter-nvim.enable) {
assertions = [
{
assertion = !config.vim.utility.ccc.enable;
message = ''
ccc and otter have a breaking conflict. It's been reported upstream. Until it's fixed, disable one of them
'';
}
];
vim = {
startPlugins = ["otter-nvim"];
maps.normal = mkMerge [
(mkSetBinding mappings.toggle "<cmd>lua require'otter'.activate()<CR>")
];
pluginRC.otter-nvim = entryAnywhere ''
-- Enable otter diagnostics viewer
require("otter").setup(${toLuaObject cfg.otter-nvim.setupOpts})
'';
};
};
}

View file

@ -0,0 +1,6 @@
{
imports = [
./otter.nix
./config.nix
];
}

View file

@ -0,0 +1,64 @@
{lib, ...}: let
inherit (lib.options) mkOption mkEnableOption;
inherit (lib.nvim.binds) mkMappingOption;
inherit (lib.types) bool str listOf;
inherit (lib.nvim.types) mkPluginSetupOption;
in {
options.vim.lsp = {
otter-nvim = {
enable = mkEnableOption ''
lsp features and a code completion source for code embedded in other documents [otter-nvim]
'';
mappings = {
toggle = mkMappingOption "Activate LSP on Cursor Position [otter-nvim]" "<leader>lo";
};
setupOpts = mkPluginSetupOption "otter.nvim" {
lsp = {
diagnostic_update_event = mkOption {
type = listOf str;
default = ["BufWritePost"];
description = ''
`:h events` that cause the diagnostic to update.
Set to: {"BufWritePost", "InsertLeave", "TextChanged" }
for less performant but more instant diagnostic updates
'';
};
};
buffers = {
set_filetype = mkOption {
type = bool;
default = false;
description = ''
if set to true, the filetype of the otterbuffers will be set. Other wide only
the autocommand of lspconfig that attaches the language server will be
executed without stting the filetype
'';
};
write_to_disk = mkOption {
type = bool;
default = false;
description = ''
write <path>.otter.<embedded language extension> files to disk on save of main buffer.
Useful for some linters that require actual files.
Otter files are deleted on quit or main buffer close
'';
};
};
strip_wrapping_quote_characters = mkOption {
type = listOf str;
default = ["'" ''"'' "`"];
description = ''
'';
};
handle_leading_whitespace = mkOption {
type = bool;
default = false;
description = ''
otter may not work the way you expect when entire code blocks are indented
(eg. in Org files) When true, otter handles these cases fully.
'';
};
};
};
};
}

View file

@ -1,41 +1,39 @@
{ {
config, config,
lib, lib,
options,
... ...
}: let }: let
inherit (lib.modules) mkIf mkMerge; inherit (lib.modules) mkIf;
inherit (lib.nvim.dag) entryAnywhere; inherit (lib.nvim.binds) addDescriptionsToMappings mkSetLznBinding pushDownDefault;
inherit (lib.nvim.binds) addDescriptionsToMappings mkSetBinding pushDownDefault;
cfg = config.vim.lsp; cfg = config.vim.lsp;
self = import ./trouble.nix {inherit lib;}; mappingDefinitions = options.vim.lsp.trouble.mappings;
mappingDefinitions = self.options.vim.lsp.trouble.mappings;
mappings = addDescriptionsToMappings cfg.trouble.mappings mappingDefinitions; mappings = addDescriptionsToMappings cfg.trouble.mappings mappingDefinitions;
in { in {
config = mkIf (cfg.enable && cfg.trouble.enable) { config = mkIf (cfg.enable && cfg.trouble.enable) {
vim = { vim = {
startPlugins = ["trouble"]; lazy.plugins.trouble = {
package = "trouble";
setupModule = "trouble";
inherit (cfg.trouble) setupOpts;
maps.normal = mkMerge [ cmd = "Trouble";
(mkSetBinding mappings.toggle "<cmd>TroubleToggle<CR>") keys = [
(mkSetBinding mappings.workspaceDiagnostics "<cmd>TroubleToggle workspace_diagnostics<CR>") (mkSetLznBinding "n" mappings.workspaceDiagnostics "<cmd>Trouble toggle diagnostics<CR>")
(mkSetBinding mappings.documentDiagnostics "<cmd>TroubleToggle document_diagnostics<CR>") (mkSetLznBinding "n" mappings.documentDiagnostics "<cmd>Trouble toggle diagnostics filter.buf=0<CR>")
(mkSetBinding mappings.lspReferences "<cmd>TroubleToggle lsp_references<CR>") (mkSetLznBinding "n" mappings.lspReferences "<cmd>Trouble toggle lsp_references<CR>")
(mkSetBinding mappings.quickfix "<cmd>TroubleToggle quickfix<CR>") (mkSetLznBinding "n" mappings.quickfix "<cmd>Trouble toggle quickfix<CR>")
(mkSetBinding mappings.locList "<cmd>TroubleToggle loclist<CR>") (mkSetLznBinding "n" mappings.locList "<cmd>Trouble toggle loclist<CR>")
]; (mkSetLznBinding "n" mappings.symbols "<cmd>Trouble toggle symbols<CR>")
];
binds.whichKey.register = pushDownDefault {
"<leader>l" = "Trouble";
"<leader>x" = "+Trouble";
"<leader>lw" = "Workspace";
}; };
pluginRC.trouble = entryAnywhere '' binds.whichKey.register = pushDownDefault {
-- Enable trouble diagnostics viewer "<leader>x" = "+Trouble";
require("trouble").setup {} "<leader>lw" = "+Workspace";
''; };
}; };
}; };
} }

View file

@ -1,18 +1,21 @@
{lib, ...}: let {lib, ...}: let
inherit (lib.options) mkEnableOption; inherit (lib.options) mkEnableOption;
inherit (lib.nvim.binds) mkMappingOption; inherit (lib.nvim.binds) mkMappingOption;
inherit (lib.nvim.types) mkPluginSetupOption;
in { in {
options.vim.lsp = { options.vim.lsp = {
trouble = { trouble = {
enable = mkEnableOption "trouble diagnostics viewer"; enable = mkEnableOption "trouble diagnostics viewer";
setupOpts = mkPluginSetupOption "Trouble" {};
mappings = { mappings = {
toggle = mkMappingOption "Toggle trouble [trouble]" "<leader>xx";
workspaceDiagnostics = mkMappingOption "Workspace diagnostics [trouble]" "<leader>lwd"; workspaceDiagnostics = mkMappingOption "Workspace diagnostics [trouble]" "<leader>lwd";
documentDiagnostics = mkMappingOption "Document diagnostics [trouble]" "<leader>ld"; documentDiagnostics = mkMappingOption "Document diagnostics [trouble]" "<leader>ld";
lspReferences = mkMappingOption "LSP References [trouble]" "<leader>lr"; lspReferences = mkMappingOption "LSP References [trouble]" "<leader>lr";
quickfix = mkMappingOption "QuickFix [trouble]" "<leader>xq"; quickfix = mkMappingOption "QuickFix [trouble]" "<leader>xq";
locList = mkMappingOption "LOCList [trouble]" "<leader>xl"; locList = mkMappingOption "LOCList [trouble]" "<leader>xl";
symbols = mkMappingOption "Symbols [trouble]" "<leader>xs";
}; };
}; };
}; };

View file

@ -2,6 +2,7 @@
imports = [ imports = [
./obsidian ./obsidian
./orgmode ./orgmode
./neorg
./mind-nvim ./mind-nvim
./todo-comments ./todo-comments
]; ];

View file

@ -0,0 +1,41 @@
{
config,
lib,
...
}: let
inherit (lib.modules) mkIf mkMerge;
inherit (lib.nvim.dag) entryAnywhere;
inherit (lib.nvim.binds) pushDownDefault;
inherit (lib.nvim.lua) toLuaObject;
cfg = config.vim.notes.neorg;
in {
config = mkIf cfg.enable (mkMerge [
{
vim = {
startPlugins = [
"lua-utils-nvim"
"nui-nvim"
"nvim-nio"
"pathlib-nvim"
"plenary-nvim"
"neorg"
"neorg-telescope"
];
binds.whichKey.register = pushDownDefault {
"<leader>o" = "+Notes";
};
pluginRC.neorg = entryAnywhere ''
require('neorg').setup(${toLuaObject cfg.setupOpts})
'';
};
}
(mkIf cfg.treesitter.enable {
vim.treesitter.enable = true;
vim.treesitter.grammars = [cfg.treesitter.norgPackage];
})
]);
}

View file

@ -0,0 +1,6 @@
{
imports = [
./neorg.nix
./config.nix
];
}

View file

@ -0,0 +1,50 @@
{
config,
lib,
pkgs,
...
}: let
inherit (lib.options) mkEnableOption mkOption;
inherit (lib.types) submodule listOf str;
inherit (lib.nvim.types) mkGrammarOption mkPluginSetupOption;
in {
options.vim.notes.neorg = {
enable = mkEnableOption ''
Neorg: An intuitive note-taking and organization tool with a structured nested syntax.
'';
setupOpts = mkPluginSetupOption "Neorg" {
load = {
"core.defaults" = mkOption {
default = {};
description = ''
all of the most important modules that any user would want to have a "just works" experience
'';
type = submodule {
options = {
enable = mkEnableOption ''
all of the most important modules that any user would want to have a "just works" experience
'';
config = {
disable = mkOption {
description = ''
list of modules from to be disabled from core.defaults
'';
type = listOf str;
default = [];
example = ["core.autocommands" "core.itero"];
};
};
};
};
};
};
};
treesitter = {
enable = mkEnableOption "Neorg treesitter" // {default = config.vim.languages.enableTreesitter;};
norgPackage = mkGrammarOption pkgs "norg";
};
};
}

View file

@ -45,10 +45,10 @@ in {
completion = { completion = {
nvim_cmp = mkOption { nvim_cmp = mkOption {
# if using nvim-cmp, otherwise set to false # If using nvim-cmp, otherwise set to false
type = bool; type = bool;
description = "If using nvim-cmp, otherwise set to false"; description = "If using nvim-cmp, otherwise set to false";
default = config.vim.autocomplete.type == "nvim-cmp"; default = config.vim.autocomplete.nvim-cmp.enable;
}; };
}; };
}; };

View file

@ -1,5 +1,5 @@
{ {
imports = [ imports = [
./vsnip ./luasnip
]; ];
} }

View file

@ -0,0 +1,26 @@
{
config,
lib,
...
}: let
inherit (lib.modules) mkIf;
cfg = config.vim.snippets.luasnip;
in {
config = mkIf cfg.enable {
vim = {
lazy.plugins = {
luasnip = {
package = "luasnip";
lazy = true;
after = cfg.loaders;
};
};
startPlugins = cfg.providers;
autocomplete.nvim-cmp = {
sources = {luasnip = "[LuaSnip]";};
sourcePlugins = ["cmp-luasnip"];
};
};
};
}

View file

@ -0,0 +1,6 @@
{
imports = [
./luasnip.nix
./config.nix
];
}

View file

@ -0,0 +1,36 @@
{lib, ...}: let
inherit (lib.options) mkEnableOption mkOption literalExpression literalMD;
inherit (lib.types) listOf lines;
inherit (lib.nvim.types) pluginType;
in {
options.vim.snippets.luasnip = {
enable = mkEnableOption "luasnip";
providers = mkOption {
type = listOf pluginType;
default = ["friendly-snippets"];
description = ''
The snippet provider packages.
::: {.note}
These are simply appended to {option} `vim.startPlugins`.
:::
'';
example = literalExpression "[\"vimPlugins.vim-snippets\"]";
};
loaders = mkOption {
type = lines;
default = "require('luasnip.loaders.from_vscode').lazy_load()";
defaultText = literalMD ''
```lua
require('luasnip.loaders.from_vscode').lazy_load()
```
'';
description = "Lua code used to load snippet providers.";
example = literalMD ''
```lua
require("luasnip.loaders.from_snipmate").lazy_load()
```
'';
};
};
}

View file

@ -1,13 +0,0 @@
{
config,
lib,
...
}: let
inherit (lib.modules) mkIf;
cfg = config.vim.snippets.vsnip;
in {
config = mkIf cfg.enable {
vim.startPlugins = ["vim-vsnip"];
};
}

View file

@ -1,5 +0,0 @@
{
imports = [
./vsnip.nix
];
}

View file

@ -1,7 +0,0 @@
{lib, ...}: let
inherit (lib.options) mkEnableOption;
in {
options.vim.snippets.vsnip = {
enable = mkEnableOption "vim-vsnip: snippet LSP/VSCode's format";
};
}

View file

@ -7,16 +7,26 @@
inherit (lib.nvim.dag) entryAfter; inherit (lib.nvim.dag) entryAfter;
cfg = config.vim.spellcheck; cfg = config.vim.spellcheck;
in { in {
config = mkIf (cfg.enable && cfg.programmingWordlist.enable) { config = mkIf cfg.programmingWordlist.enable {
vim = { vim = {
startPlugins = ["vim-dirtytalk"]; startPlugins = ["vim-dirtytalk"];
# vim-dirtytalk doesn't have any setup spellcheck.enable = true;
# but we would like to append programming to spelllang
# as soon as possible while the plugin is enabled # vim-dirtytalk doesn't have any setup but we would
pluginRC.vim-dirtytalk = entryAfter ["basic"] '' # like to append programming to spelllangs as soon as
-- append programming to spelllang # possible while the plugin is enabled and the state
vim.opt.spelllang:append("programming") # directory can be found.
pluginRC.vim-dirtytalk = entryAfter ["spellcheck"] ''
-- If Neovim can find (or access) the state directory
-- then append "programming" wordlist from vim-dirtytalk
-- to spelllang table. If path cannot be found, display
-- an error and avoid appending the programming words
if vim.fn.isdirectory(vim.fn.stdpath('state')) == 1 then
vim.opt.spelllang:append("programming")
else
vim.notify("State path does not exist: " .. state_path, vim.log.levels.ERROR)
end
''; '';
}; };
}; };

View file

@ -17,29 +17,36 @@
"ayu_dark" "ayu_dark"
"ayu_light" "ayu_light"
"ayu_mirage" "ayu_mirage"
"ayu"
"codedark" "codedark"
"dracula" "dracula"
"everforest" "everforest"
"gruvbox" "gruvbox"
"gruvbox_dark"
"gruvbox_light" "gruvbox_light"
"gruvbox_material" "gruvbox_material"
"horizon" "horizon"
"iceberg_dark" "iceberg_dark"
"iceberg_light" "iceberg_light"
"iceberg"
"jellybeans" "jellybeans"
"material" "material"
"modus_vivendi" "modus_vivendi"
"molokai" "molokai"
"moonfly"
"nightfly" "nightfly"
"nord" "nord"
"oceanicnext" "oceanicnext"
"onedark"
"onelight" "onelight"
"palenight" "palenight"
"papercolor_dark" "papercolor_dark"
"papercolor_light" "papercolor_light"
"powerline_dark"
"powerline" "powerline"
"seoul256" "seoul256"
"solarized_dark" "solarized_dark"
"solarized_light"
"tomorrow" "tomorrow"
"wombat" "wombat"
]; ];
@ -224,7 +231,7 @@ in {
local buf_ft = vim.api.nvim_get_option_value('filetype', {}) local buf_ft = vim.api.nvim_get_option_value('filetype', {})
-- List of buffer types to exclude -- List of buffer types to exclude
local excluded_buf_ft = {"toggleterm", "NvimTree", "TelescopePrompt"} local excluded_buf_ft = {"toggleterm", "NvimTree", "neo-tree", "TelescopePrompt"}
-- Check if the current buffer type is in the excluded list -- Check if the current buffer type is in the excluded list
for _, excluded_type in ipairs(excluded_buf_ft) do for _, excluded_type in ipairs(excluded_buf_ft) do

View file

@ -15,10 +15,14 @@ in {
config = mkIf cfg.enable { config = mkIf cfg.enable {
vim = { vim = {
startPlugins = [ startPlugins = [
(assert config.vim.visuals.nvimWebDevicons.enable; "nvim-bufferline-lua") "nvim-bufferline-lua"
"bufdelete-nvim" "bufdelete-nvim"
]; ];
# Soft-dependency for bufferline.
# Recommended by upstream, so enabled here.
visuals.nvim-web-devicons.enable = true;
maps.normal = mkMerge [ maps.normal = mkMerge [
(mkLuaBinding cfg.mappings.closeCurrent "require(\"bufdelete\").bufdelete" mappings.closeCurrent.description) (mkLuaBinding cfg.mappings.closeCurrent "require(\"bufdelete\").bufdelete" mappings.closeCurrent.description)
(mkBinding cfg.mappings.cycleNext ":BufferLineCycleNext<CR>" mappings.cycleNext.description) (mkBinding cfg.mappings.cycleNext ":BufferLineCycleNext<CR>" mappings.cycleNext.description)

View file

@ -3,39 +3,32 @@
lib, lib,
... ...
}: let }: let
inherit (builtins) toJSON; inherit (lib.strings) optionalString;
inherit (lib.lists) optionals; inherit (lib.lists) optional;
inherit (lib.modules) mkIf mkMerge; inherit (lib.modules) mkIf;
inherit (lib.meta) getExe; inherit (lib.meta) getExe;
inherit (lib.nvim.binds) mkBinding; inherit (lib.nvim.binds) mkLznBinding;
inherit (lib.nvim.dag) entryAnywhere entryAfter;
inherit (lib.nvim.lua) toLuaObject; inherit (lib.nvim.lua) toLuaObject;
cfg = config.vim.terminal.toggleterm; cfg = config.vim.terminal.toggleterm;
lazygitMapDesc = "Open lazygit [toggleterm]";
in { in {
config = mkMerge [ config = mkIf cfg.enable {
( vim = {
mkIf cfg.enable { lazy.plugins.toggleterm-nvim = {
vim = { package = "toggleterm-nvim";
startPlugins = [ cmd = ["ToggleTerm" "ToggleTermSendCurrentLine" "ToggleTermSendVisualLines" "ToggleTermSendVisualSelection" "ToggleTermSetName" "ToggleTermToggleAll"];
"toggleterm-nvim" keys =
]; [(mkLznBinding ["n"] cfg.mappings.open "<Cmd>execute v:count . \"ToggleTerm\"<CR>" "Toggle terminal")]
++ optional cfg.lazygit.enable {
key = cfg.lazygit.mappings.open;
mode = "n";
desc = lazygitMapDesc;
};
maps.normal = mkBinding cfg.mappings.open "<Cmd>execute v:count . \"ToggleTerm\"<CR>" "Toggle terminal"; setupModule = "toggleterm";
inherit (cfg) setupOpts;
pluginRC.toggleterm = entryAnywhere '' after = optionalString cfg.lazygit.enable ''
require("toggleterm").setup(${toLuaObject cfg.setupOpts})
'';
};
}
)
(
mkIf (cfg.enable && cfg.lazygit.enable)
{
vim.startPlugins = optionals (cfg.lazygit.package != null) [
cfg.lazygit.package
];
vim.pluginRC.toggleterm-lazygit = entryAfter ["toggleterm"] ''
local terminal = require 'toggleterm.terminal' local terminal = require 'toggleterm.terminal'
local lazygit = terminal.Terminal:new({ local lazygit = terminal.Terminal:new({
cmd = '${ cmd = '${
@ -50,9 +43,9 @@ in {
end end
}) })
vim.keymap.set('n', ${toJSON cfg.lazygit.mappings.open}, function() lazygit:toggle() end, {silent = true, noremap = true, desc = 'Open lazygit [toggleterm]'}) vim.keymap.set('n', ${toLuaObject cfg.lazygit.mappings.open}, function() lazygit:toggle() end, {silent = true, noremap = true, desc = '${lazygitMapDesc}'})
''; '';
} };
) };
]; };
} }

View file

@ -4,7 +4,14 @@
}: let }: let
inherit (lib.strings) optionalString; inherit (lib.strings) optionalString;
inherit (lib.trivial) boolToString warnIf; inherit (lib.trivial) boolToString warnIf;
inherit (lib.nvim.lua) toLuaObject;
in { in {
base16 = {
setup = {base16-colors, ...}: ''
-- Base16 theme
require('base16-colorscheme').setup(${toLuaObject base16-colors})
'';
};
onedark = { onedark = {
setup = {style ? "dark", ...}: '' setup = {style ? "dark", ...}: ''
-- OneDark theme -- OneDark theme
@ -20,6 +27,7 @@ in {
setup = { setup = {
style ? "night", style ? "night",
transparent, transparent,
...
}: '' }: ''
require('tokyonight').setup { require('tokyonight').setup {
transparent = ${boolToString transparent}; transparent = ${boolToString transparent};
@ -42,6 +50,7 @@ in {
setup = { setup = {
style ? "mocha", style ? "mocha",
transparent ? false, transparent ? false,
...
}: '' }: ''
-- Catppuccin theme -- Catppuccin theme
require('catppuccin').setup { require('catppuccin').setup {
@ -69,7 +78,7 @@ in {
notify = true, -- nvim-notify notify = true, -- nvim-notify
which_key = true, which_key = true,
navic = { navic = {
enabled = false, enabled = true,
custom_bg = "NONE", -- "lualine" will set background to mantle custom_bg = "NONE", -- "lualine" will set background to mantle
}, },
}, },
@ -84,6 +93,7 @@ in {
setup = { setup = {
style ? "dark", style ? "dark",
transparent ? false, transparent ? false,
...
}: let }: let
style' = style' =
warnIf (style == "light") "oxocarbon: light theme is not well-supported" style; warnIf (style == "light") "oxocarbon: light theme is not well-supported" style;
@ -108,6 +118,7 @@ in {
setup = { setup = {
style ? "dark", style ? "dark",
transparent ? false, transparent ? false,
...
}: '' }: ''
-- Gruvbox theme -- Gruvbox theme
require("gruvbox").setup({ require("gruvbox").setup({
@ -143,6 +154,7 @@ in {
setup = { setup = {
style ? "main", style ? "main",
transparent ? false, transparent ? false,
...
}: '' }: ''
require("rose-pine").setup({ require("rose-pine").setup({
dark_variant = "${style}", -- main, moon, or dawn dark_variant = "${style}", -- main, moon, or dawn

View file

@ -5,31 +5,52 @@
}: let }: let
inherit (lib.options) mkOption; inherit (lib.options) mkOption;
inherit (lib.attrsets) attrNames; inherit (lib.attrsets) attrNames;
inherit (lib.strings) hasPrefix;
inherit (lib.types) bool lines enum; inherit (lib.types) bool lines enum;
inherit (lib.modules) mkIf; inherit (lib.modules) mkIf;
inherit (lib.nvim.attrsets) mapListToAttrs;
inherit (lib.nvim.dag) entryBefore; inherit (lib.nvim.dag) entryBefore;
inherit (lib.nvim.types) hexColor;
cfg = config.vim.theme; cfg = config.vim.theme;
supportedThemes = import ./supported-themes.nix { supportedThemes = import ./supported-themes.nix {
inherit lib config; inherit lib config;
}; };
numbers = ["0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "A" "B" "C" "D" "E" "F"];
base16Options =
mapListToAttrs (n: {
name = "base0${n}";
value = mkOption {
description = "The base0${n} color to use";
type = hexColor;
apply = v:
if hasPrefix "#" v
then v
else "#${v}";
};
})
numbers;
in { in {
options.vim.theme = { options.vim.theme = {
enable = mkOption { enable = mkOption {
type = bool; type = bool;
description = "Enable theming"; description = "Enable theming";
}; };
name = mkOption { name = mkOption {
type = enum (attrNames supportedThemes); type = enum (attrNames supportedThemes);
description = "Supported themes can be found in `supportedThemes.nix`"; description = ''
Supported themes can be found in {file}`supportedThemes.nix`.
Setting the theme to "base16" enables base16 theming and
requires all of the colors in {option}`vim.theme.base16-colors` to be set.
'';
}; };
base16-colors = base16Options;
style = mkOption { style = mkOption {
type = enum supportedThemes.${cfg.name}.styles; type = enum supportedThemes.${cfg.name}.styles;
description = "Specific style for theme if it supports it"; description = "Specific style for theme if it supports it";
}; };
transparent = mkOption { transparent = mkOption {
type = bool; type = bool;
default = false; default = false;
@ -45,9 +66,9 @@ in {
config = mkIf cfg.enable { config = mkIf cfg.enable {
vim = { vim = {
startPlugins = [cfg.name]; startPlugins = [cfg.name];
luaConfigRC.theme = entryBefore ["pluginConfigs"] '' luaConfigRC.theme = entryBefore ["pluginConfigs" "lazyConfigs"] ''
${cfg.extraConfig} ${cfg.extraConfig}
${supportedThemes.${cfg.name}.setup {inherit (cfg) style transparent;}} ${supportedThemes.${cfg.name}.setup {inherit (cfg) style transparent base16-colors;}}
''; '';
}; };
}; };

View file

@ -5,13 +5,12 @@
... ...
}: let }: let
inherit (lib.modules) mkIf mkMerge; inherit (lib.modules) mkIf mkMerge;
inherit (lib.lists) optional optionals; inherit (lib.lists) optionals;
inherit (lib.nvim.binds) mkSetBinding addDescriptionsToMappings; inherit (lib.nvim.binds) mkSetBinding addDescriptionsToMappings;
inherit (lib.nvim.lua) toLuaObject; inherit (lib.nvim.lua) toLuaObject;
inherit (lib.nvim.dag) entryBefore entryAfter; inherit (lib.nvim.dag) entryBefore entryAfter;
cfg = config.vim.treesitter; cfg = config.vim.treesitter;
usingNvimCmp = config.vim.autocomplete.enable && config.vim.autocomplete.type == "nvim-cmp";
self = import ./treesitter.nix {inherit pkgs lib;}; self = import ./treesitter.nix {inherit pkgs lib;};
mappingDefinitions = self.options.vim.treesitter.mappings; mappingDefinitions = self.options.vim.treesitter.mappings;
@ -19,9 +18,13 @@
in { in {
config = mkIf cfg.enable { config = mkIf cfg.enable {
vim = { vim = {
startPlugins = ["nvim-treesitter"] ++ optional usingNvimCmp "cmp-treesitter"; startPlugins = ["nvim-treesitter"];
autocomplete.nvim-cmp = {
sources = {treesitter = "[Treesitter]";};
sourcePlugins = ["cmp-treesitter"];
};
autocomplete.sources = {"treesitter" = "[Treesitter]";};
treesitter.grammars = optionals cfg.addDefaultGrammars cfg.defaultGrammars; treesitter.grammars = optionals cfg.addDefaultGrammars cfg.defaultGrammars;
maps = { maps = {

View file

@ -21,7 +21,7 @@ in {
mkBool true "override the lsp markdown formatter with Noice"; mkBool true "override the lsp markdown formatter with Noice";
"cmp.entry.get_documentation" = "cmp.entry.get_documentation" =
mkBool (config.vim.autocomplete.type == "nvim-cmp") "override cmp documentation with Noice"; mkBool config.vim.autocomplete.nvim-cmp.enable "override cmp documentation with Noice";
}; };
signature = { signature = {

View file

@ -4,15 +4,18 @@
... ...
}: let }: let
inherit (lib.modules) mkIf; inherit (lib.modules) mkIf;
inherit (lib.nvim.dag) entryAnywhere; inherit (lib.strings) optionalString;
cfg = config.vim.binds.cheatsheet; cfg = config.vim.binds.cheatsheet;
in { in {
config = mkIf cfg.enable { config = mkIf cfg.enable {
vim.startPlugins = ["cheatsheet-nvim"]; vim.lazy.plugins.cheatsheet-nvim = {
package = "cheatsheet-nvim";
setupModule = "cheatsheet";
setupOpts = {};
cmd = ["Cheatsheet" "CheatsheetEdit"];
vim.pluginRC.cheaetsheet-nvim = entryAnywhere '' before = optionalString config.vim.lazy.enable "require('lz.n').trigger_load('telescope')";
require('cheatsheet').setup({}) };
'';
}; };
} }

View file

@ -4,33 +4,23 @@
... ...
}: let }: let
inherit (lib.modules) mkIf; inherit (lib.modules) mkIf;
inherit (lib.strings) optionalString;
inherit (lib.nvim.lua) toLuaObject; inherit (lib.nvim.lua) toLuaObject;
inherit (lib.attrsets) mapAttrsToList;
inherit (lib.generators) mkLuaInline;
inherit (lib.nvim.dag) entryAnywhere; inherit (lib.nvim.dag) entryAnywhere;
cfg = config.vim.binds.whichKey; cfg = config.vim.binds.whichKey;
register = mapAttrsToList (n: v: mkLuaInline "{ '${n}', desc = '${v}' }") cfg.register;
in { in {
config = mkIf cfg.enable { config = mkIf cfg.enable {
vim.startPlugins = ["which-key"]; vim = {
startPlugins = ["which-key"];
vim.pluginRC.whichkey = entryAnywhere '' pluginRC.whichkey = entryAnywhere ''
local wk = require("which-key") local wk = require("which-key")
wk.setup ({ wk.setup (${toLuaObject cfg.setupOpts})
key_labels = { wk.add(${toLuaObject register})
["<space>"] = "SPACE", '';
["<leader>"] = "SPACE", };
["<cr>"] = "RETURN",
["<tab>"] = "TAB",
},
${optionalString config.vim.ui.borders.plugins.which-key.enable ''
window = {
border = ${toLuaObject config.vim.ui.borders.plugins.which-key.style},
},
''}
})
wk.register(${toLuaObject cfg.register})
'';
}; };
} }

View file

@ -1,4 +1,4 @@
_: { {
imports = [ imports = [
./which-key.nix ./which-key.nix
./config.nix ./config.nix

Some files were not shown because too many files have changed in this diff Show more