Initial commit

This commit is contained in:
Jiří Štefka 2024-03-06 02:24:31 +01:00 committed by GitHub
commit e2cff543d6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
29 changed files with 2701 additions and 0 deletions

1
.envrc Normal file

@ -0,0 +1 @@
use flake . -Lv

1
.github/FUNDING.yml vendored Normal file

@ -0,0 +1 @@
github: mrcjkb

3
.gitignore vendored Normal file

@ -0,0 +1,3 @@
result
.direnv
.luarc.json

6
.stylua.toml Normal file

@ -0,0 +1,6 @@
line_endings = "Unix"
indent_type = "Spaces"
indent_width = 2
quote_style = "AutoPreferSingle"
call_parentheses = "NoSingleTable"
# collapse_simple_statement = "Never"

339
LICENSE Normal file

@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

300
README.md Normal file

@ -0,0 +1,300 @@
<!-- markdownlint-disable -->
<br />
<div align="center">
<a href="https://github.com/mrcjkb/kickstart-nix.nvim">
<img src="./nvim-nix.svg" alt="kickstart-nix.nvim">
</a>
<!-- TODO: -->
<!-- <p align="center"> -->
<!-- <br /> -->
<!-- TODO: -->
<!-- <a href="./nvim/doc/kickstart-nix.txt"><strong>Explore the docs »</strong></a> -->
<!-- <br /> -->
<!-- <br /> -->
<!-- <a href="https://github.com/mrcjkb/kickstart-nix.nvim/issues/new?assignees=&labels=bug&projects=&template=bug_report.yml">Report Bug</a> -->
<!-- · -->
<!-- <a href="https://github.com/mrcjkb/kickstart-nix.nvim/issues/new?assignees=&labels=enhancement&projects=&template=feature_request.yml">Request Feature</a> -->
<!-- · -->
<!-- <a href="https://github.com/mrcjkb/kickstart-nix.nvim/discussions/new?category=q-a">Ask Question</a> -->
<!-- </p> -->
<p>❄️</p>
<p>
<strong>
A dead simple <a href="https://nixos.org/">Nix</a> flake template repository</br>
for <a href="https://neovim.io/">Neovim</a>
</strong>
</p>
</div>
<!-- markdownlint-restore -->
[![Neovim][neovim-shield]][neovim-url]
[![Nix][nix-shield]][nix-url]
[![Lua][lua-shield]][lua-url]
[![GPL2 License][license-shield]][license-url]
[![Issues][issues-shield]][issues-url]
![](https://github.com/mrcjkb/kickstart-nix.nvim/assets/12857160/84faa268-82de-4401-acf3-efddc26dd58a)
If Nix and Neovim have one thing in common,
it's that many new users don't know where to get started.
Most Nix-based Neovim setups assume deep expertise in both realms,
abstracting away Neovim's core functionalities
as well as the Nix internals used to build a Neovim config.
Frameworks and module-based DSLs are opinionated and difficult to diverge from
with one's own modifications.
`kickstart-nix.nvim` is different:
It's geared for users of all levels,
making the migration of Neovim configurations to Nix straightforward.
This project aims to be as simple as possible, while allowing
for maximum flexibility.
> [!NOTE]
>
> Similar to [`kickstart.nvim`](https://github.com/nvim-lua/kickstart.nvim),
> this repository is meant to be used by **you** to begin your
> **Nix**/Neovim journey; remove the things you don't use and add what you miss.
## Quick Links
- [Philosophy](#philosophy)
- [Features](#features)
- [Test drive](#test-drive)
- [Usage](#usage)
- [Installation](#installation)
- [Design](#design)
- [Pre-configured plugins](#pre-configured-plugins)
- [Syncing updates](#syncing-updates)
- [Alternative / similar projects](#alternative--similar-projects)
## Philosophy
- KISS principle with sane defaults.
- Manage plugins + external dependencies using Nix
(managing plugins shouldn't be the responsibility of a plugin).
- Configuration entirely in Lua[^1] (Vimscript is also possible).
This makes it easy to migrate from non-nix dotfiles.
- Use Neovim's built-in loading mechanisms. See:
- [`:h initialization`](https://neovim.io/doc/user/starting.html#initialization)
- [`:h runtimepath`](https://neovim.io/doc/user/options.html#'runtimepath')
- [`:h packadd`](https://neovim.io/doc/user/repeat.html#%3Apackadd)
- Use Neovim's built-in LSP client, with Nix managing language servers.
## Features
- Use either nixpkgs or flake inputs as plugin sources.
- Usable on any device with Neovim and Nix installed.
- Ability to create multiple derivations with different sets of plugins,
and simple regex filters to exclude config files.
- Uses Nix to generate a `.luarc.json` in the devShell's `shellHook`.
This sets up lua-language-server to recognize all plugins
and the Neovim API.
[^1]: The absence of a Nix module DSL for Neovim configuration is deliberate.
If you were to copy the `nvim` directory to `$XDG_CONFIG_HOME`,
and install the plugins, it would work out of the box.
## Test drive
If you have Nix installed (with [flakes](https://nixos.wiki/wiki/Flakes) enabled),
you can test drive this by running:
```console
nix run "github:mrcjkb/kickstart-nix.nvim"
```
## Usage
1. Click on [Use this template](https://github.com/mrcjkb/kickstart-nix.nvim/generate)
to start a repo based on this template. **Do _not_ fork it**.
1. Add/remove plugins to/from the [Neovim overlay](./nix/neovim-overlay.nix).
1. Add/remove plugin configs to/from the `nvim/plugin` directory.
1. Modify as you wish (you will probably want to add a color theme, ...).
See: [Design](#design).
1. You can create more than one package using the `mkNeovim` function by
- Passing different plugin lists.
- Adding `ignoreConfigRegexes` (e.g. `= [ "^ftplugin/.*.lua" ]`).
> [!TIP]
>
> The nix and lua files contain comments explaining
> what everything does in detail.
## Installation
### NixOS (with flakes)
1. Add your flake to you NixOS flake inputs.
1. Add the overlay provided by this flake.
```nix
nixpkgs.overlays = [
# replace <kickstart-nix-nvim> with the name you chose
<kickstart-nix-nvim>.overlays.default
];
```
You can then add the overlay's output(s) to the `systemPackages`:
```nix
environment.systemPackages = with pkgs; [
nvim-pkg # The default package added by the overlay
];
```
### Non-NixOS
With Nix installed (flakes enabled), from the repo root:
```console
nix profile install .#nvim
```
## Design
Directory structure:
```sh
── flake.nix
── nvim # Neovim configs (lua), equivalent to ~/.config/nvim
── nix # Nix configs
```
### Neovim configs
- Set options in `init.lua`.
- Source autocommands, user commands, keymaps,
and configure plugins in individual files within the `plugin` directory.
- Filetype-specific scripts (e.g. start LSP clients) in the `ftplugin` directory.
- Library modules in the `lua/user` directory.
Directory structure:
```sh
── nvim
├── ftplugin # Sourced when opening a file type
│ └── <filetype>.lua
├── init.lua # Always sourced
├── lua # Shared library modules
│ └── user
│ └── <lib>.lua
├── plugin # Automatically sourced at startup
│ ├── autocommands.lua
│ ├── commands.lua
│ ├── keymaps.lua
│ ├── plugins.lua # Plugins that require a `setup` call
│ └── <plugin-config>.lua # Plugin configurations
└── after # Empty in this template
├── plugin # Sourced at the very end of startup (rarely needed)
└── ftplugin # Sourced when opening a filetype, after sourcing ftplugin scripts
```
> [!IMPORTANT]
>
> - Configuration variables (e.g. `vim.g.<plugin_config>`) should go in `nvim/init.lua`
> or a module that is `require`d in `init.lua`.
> - Configurations for plugins that require explicit initialization
> (e.g. via a call to a `setup()` function) should go in `nvim/plugin/<plugin>.lua`
> or `nvim/plugin/plugins.lua`.
> - See [Initialization order](#initialization-order) for details.
### Nix
You can declare Neovim derivations in `nix/neovim-overlay.nix`.
There are two ways to add plugins:
- The traditional way, using `nixpkgs` as the source.
- By adding plugins as flake inputs (if you like living on the bleeding-edge).
Plugins added as flake inputs must be built in `nix/plugin-overlay.nix`.
Directory structure:
```sh
── flake.nix
── nix
├── mkNeovim.nix # Function for creating the Neovim derivation
└── neovim-overlay.nix # Overlay that adds Neovim derivation
```
### Initialization order
This derivation creates an `init.lua` as follows:
1. Add `nvim/lua` to the `runtimepath`.
1. Add the content of `nvim/init.lua`.
1. Add `nvim/*` to the `runtimepath`.
1. Add `nvim/after` to the `runtimepath`.
This means that modules in `nvim/lua` can be `require`d in `init.lua` and `nvim/*/*.lua`.
Modules in `nvim/plugin/` are sourced automatically, as if they were plugins.
Because they are added to the runtime path at the end of the resulting `init.lua`,
Neovim sources them _after_ loading plugins.
## Pre-configured plugins
This configuration comes with [a few plugins pre-configured](./nix/neovim-overlay.nix).
You can add or remove plugins by
- Adding/Removing them in the [Nix list](./nix/neovim-overlay.nix).
- Adding/Removing the config in `nvim/plugin/<plugin>.lua`.
## Syncing updates
If you have used this template and would like to fetch updates
that were added later...
Add this template as a remote:
```console
git remote add upstream git@github.com:mrcjkb/kickstart-nix.nvim.git
```
Fetch and merge changes:
```console
git fetch upstream
git merge upstream/main --allow-unrelated-histories
```
## Alternative / similar projects
- [`kickstart.nvim`](https://github.com/nvim-lua/kickstart.nvim):
Single-file Neovim configuration template with a similar philosophy to this project.
Does not use Nix to manage plugins.
- [`neovim-flake`](https://github.com/jordanisaacs/neovim-flake):
Configured using a Nix module DSL.
- [`NixVim`](https://github.com/nix-community/nixvim):
A Neovim distribution configured using a NixOS module.
- [`nixCats-nvim`](https://github.com/BirdeeHub/nixCats-nvim):
A project that organises plugins into categories.
It also separates lua and nix configuration.
- [`lazy-nix-helper.nvim`](https://github.com/b-src/lazy-nix-helper.nvim):
For lazy.nvim users who would like to manage plugins with Nix,
but load them with lazy.nvim.
> [!NOTE]
>
> When comparing with projects in the "non-Nix world", this
> repository would be more comparable to `kickstart.nvim` (hence the name),
> while the philosophies of `neovim-flake` and `NixVim` are more in line with
> a Neovim distribution like [`LunarVim`](https://www.lunarvim.org/)
> or [`LazyVim`](https://www.lazyvim.org/)
> (though they are more minimal by default).
<!-- MARKDOWN LINKS & IMAGES -->
[neovim-shield]: https://img.shields.io/badge/NeoVim-%2357A143.svg?&style=for-the-badge&logo=neovim&logoColor=white
[neovim-url]: https://neovim.io/
[nix-shield]: https://img.shields.io/badge/nix-0175C2?style=for-the-badge&logo=NixOS&logoColor=white
[nix-url]: https://nixos.org/
[lua-shield]: https://img.shields.io/badge/lua-%232C2D72.svg?style=for-the-badge&logo=lua&logoColor=white
[lua-url]: https://www.lua.org/
[license-shield]: https://img.shields.io/github/license/mrcjkb/kickstart-nix.nvim.svg?style=for-the-badge
[license-url]: https://github.com/mrcjkb/kickstart-nix.nvim/blob/master/LICENSE
[issues-shield]: https://img.shields.io/github/issues/mrcjkb/kickstart-nix.nvim.svg?style=for-the-badge
[issues-url]: https://github.com/mrcjkb/kickstart-nix.nvim/issues
[license-shield]: https://img.shields.io/github/license/mrcjkb/kickstart-nix.nvim.svg?style=for-the-badge
[license-url]: https://github.com/mrcjkb/kickstart-nix.nvim/blob/master/LICENSE

133
flake.lock generated Normal file

@ -0,0 +1,133 @@
{
"nodes": {
"flake-parts": {
"inputs": {
"nixpkgs-lib": "nixpkgs-lib"
},
"locked": {
"lastModified": 1706830856,
"narHash": "sha256-a0NYyp+h9hlb7ddVz4LUn1vT/PLwqfrWYcHMvFB1xYg=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "b253292d9c0a5ead9bc98c4e9a26c6312e27d69f",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1705309234,
"narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"gen-luarc": {
"inputs": {
"flake-parts": "flake-parts",
"nixpkgs": "nixpkgs"
},
"locked": {
"lastModified": 1708639673,
"narHash": "sha256-ZnwAKUm7wLalSdr1wdihYTODql0OD6HAxgWJKweu7Hk=",
"owner": "mrcjkb",
"repo": "nix-gen-luarc-json",
"rev": "6c5c893f0d1534dccafedaaf3ad1cf2968704a2e",
"type": "github"
},
"original": {
"owner": "mrcjkb",
"repo": "nix-gen-luarc-json",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1708475490,
"narHash": "sha256-g1v0TsWBQPX97ziznfJdWhgMyMGtoBFs102xSYO4syU=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "0e74ca98a74bc7270d28838369593635a5db3260",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-lib": {
"locked": {
"dir": "lib",
"lastModified": 1706550542,
"narHash": "sha256-UcsnCG6wx++23yeER4Hg18CXWbgNpqNXcHIo5/1Y+hc=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "97b17f32362e475016f942bbdfda4a4a72a8a652",
"type": "github"
},
"original": {
"dir": "lib",
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1708475490,
"narHash": "sha256-g1v0TsWBQPX97ziznfJdWhgMyMGtoBFs102xSYO4syU=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "0e74ca98a74bc7270d28838369593635a5db3260",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"flake-utils": "flake-utils",
"gen-luarc": "gen-luarc",
"nixpkgs": "nixpkgs_2"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

73
flake.nix Normal file

@ -0,0 +1,73 @@
{
description = "Neovim derivation";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
flake-utils.url = "github:numtide/flake-utils";
gen-luarc.url = "github:mrcjkb/nix-gen-luarc-json";
# Add bleeding-edge plugins here.
# They can be updated with `nix flake update` (make sure to commit the generated flake.lock)
# wf-nvim = {
# url = "github:Cassin01/wf.nvim";
# flake = false;
# };
};
outputs = inputs @ {
self,
nixpkgs,
flake-utils,
gen-luarc,
...
}: let
supportedSystems = [
"x86_64-linux"
"aarch64-linux"
"x86_64-darwin"
"aarch64-darwin"
];
# This is where the Neovim derivation is built.
neovim-overlay = import ./nix/neovim-overlay.nix {inherit inputs;};
in
flake-utils.lib.eachSystem supportedSystems (system: let
pkgs = import nixpkgs {
inherit system;
overlays = [
# Import the overlay, so that the final Neovim derivation(s) can be accessed via pkgs.<nvim-pkg>
neovim-overlay
# This adds a function can be used to generate a .luarc.json
# containing the Neovim API all plugins in the workspace directory.
# The generated file can be symlinked in the devShell's shellHook.
gen-luarc.overlays.default
];
};
shell = pkgs.mkShell {
name = "nvim-devShell";
buildInputs = with pkgs; [
# Tools for Lua and Nix development, useful for editing files in this repo
lua-language-server
nil
stylua
luajitPackages.luacheck
];
shellHook = ''
# symlink the .luarc.json generated in the overlay
ln -fs ${pkgs.nvim-luarc-json} .luarc.json
'';
};
in {
packages = rec {
default = nvim;
nvim = pkgs.nvim-pkg;
};
devShells = {
default = shell;
};
})
// {
# You can add this overlay to your NixOS configuration
overlays.default = neovim-overlay;
};
}

182
nix/mkNeovim.nix Normal file

@ -0,0 +1,182 @@
# Function for creating a Neovim derivation
{
pkgs,
lib,
stdenv,
}:
with lib;
{
appName ? null, # NVIM_APPNAME - Defaults to 'nvim'
plugins ? [], # List of plugins
# List of dev plugins (will be bootstrapped) - useful for plugin developers
# { name = <plugin-name>; url = <git-url>; }
devPlugins ? [],
# Regexes for config files to ignore, relative to the nvim directory.
# e.g. [ "^plugin/neogit.lua" "^ftplugin/.*.lua" ]
ignoreConfigRegexes ? [],
extraPackages ? [], # Extra runtime dependencies (e.g. ripgrep, ...)
# The below arguments can typically be left as their defaults
resolvedExtraLuaPackages ? [], # Additional lua packages (not plugins), e.g. from luarocks.org
extraPython3Packages ? p: [], # Additional python 3 packages
withPython3 ? true, # Build Neovim with Python 3 support?
withRuby ? false, # Build Neovim with Ruby support?
withNodeJs ? false, # Build Neovim with NodeJS support?
withSqlite ? true, # Add sqlite? This is a dependency for some plugins
# You probably don't want to create vi or vim aliases
# if the appName is something different than "nvim"
viAlias ? appName == "nvim", # Add a "vi" binary to the build output as an alias?
vimAlias ? appName == "nvim", # Add a "vim" binary to the build output as an alias?
}: let
# This is the structure of a plugin definition.
# Each plugin in the `plugins` argument list can also be defined as this attrset
defaultPlugin = {
plugin = null; # e.g. nvim-lspconfig
config = null; # plugin config
# If `optional` is set to `false`, the plugin is installed in the 'start' packpath
# set to `true`, it is installed in the 'opt' packpath, and can be lazy loaded with
# ':packadd! {plugin-name}
optional = false;
runtime = {};
};
externalPackages = extraPackages ++ (optionals withSqlite [pkgs.sqlite]);
# Map all plugins to an attrset { plugin = <plugin>; config = <config>; optional = <tf>; ... }
normalizedPlugins = map (x:
defaultPlugin
// (
if x ? plugin
then x
else {plugin = x;}
))
plugins;
# This nixpkgs util function creates an attrset
# that pkgs.wrapNeovimUnstable uses to configure the Neovim build.
neovimConfig = pkgs.neovimUtils.makeNeovimConfig {
inherit extraPython3Packages withPython3 withRuby withNodeJs viAlias vimAlias;
plugins = normalizedPlugins;
};
# This uses the ignoreConfigRegexes list to filter
# the nvim directory
nvimRtpSrc = let
src = ../nvim;
in
lib.cleanSourceWith {
inherit src;
name = "nvim-rtp-src";
filter = path: tyoe: let
srcPrefix = toString src + "/";
relPath = lib.removePrefix srcPrefix (toString path);
in
lib.all (regex: builtins.match regex relPath == null) ignoreConfigRegexes;
};
# Split runtimepath into 3 directories:
# - lua, to be prepended to the rtp at the beginning of init.lua
# - nvim, containing plugin, ftplugin, ... subdirectories
# - after, to be sourced last in the startup initialization
# See also: https://neovim.io/doc/user/starting.html
nvimRtp = stdenv.mkDerivation {
name = "nvim-rtp";
src = nvimRtpSrc;
buildPhase = ''
mkdir -p $out/nvim
mkdir -p $out/lua
rm init.lua
'';
installPhase = ''
cp -r after $out/after
rm -r after
cp -r lua $out/lua
rm -r lua
cp -r * $out/nvim
'';
};
# The final init.lua content that we pass to the Neovim wrapper.
# It wraps the user init.lua, prepends the lua lib directory to the RTP
# and appends the nvim and after directory to the RTP
# It also adds logic for bootstrapping dev plugins (for plugin developers)
initLua =
''
vim.loader.enable()
-- prepend lua directory
vim.opt.rtp:prepend('${nvimRtp}/lua')
''
# Wrap init.lua
+ (builtins.readFile ../nvim/init.lua)
# Bootstrap/load dev plugins
+ optionalString (devPlugins != []) (
''
local dev_pack_path = vim.fn.stdpath('data') .. '/site/pack/dev'
local dev_plugins_dir = dev_pack_path .. '/opt'
local dev_plugin_path
''
+ strings.concatMapStringsSep
"\n"
(plugin: ''
dev_plugin_path = dev_plugins_dir .. '/${plugin.name}'
if vim.fn.empty(vim.fn.glob(dev_plugin_path)) > 0 then
vim.notify('Bootstrapping dev plugin ${plugin.name} ...', vim.log.levels.INFO)
vim.cmd('!${pkgs.git}/bin/git clone ${plugin.url} ' .. dev_plugin_path)
end
vim.cmd('packadd! ${plugin.name}')
'')
devPlugins
)
# Append nvim and after directories to the runtimepath
+ ''
vim.opt.rtp:append('${nvimRtp}/nvim')
vim.opt.rtp:append('${nvimRtp}/after')
'';
# Add arguments to the Neovim wrapper script
extraMakeWrapperArgs = builtins.concatStringsSep " " (
# Set the NVIM_APPNAME environment variable
(optional (appName != "nvim" && appName != null && appName != "")
''--set NVIM_APPNAME "${appName}"'')
# Add external packages to the PATH
++ (optional (externalPackages != [])
''--prefix PATH : "${makeBinPath externalPackages}"'')
# Set the LIBSQLITE_CLIB_PATH if sqlite is enabled
++ (optional withSqlite
''--set LIBSQLITE_CLIB_PATH "${pkgs.sqlite.out}/lib/libsqlite3.so"'')
# Set the LIBSQLITE environment variable if sqlite is enabled
++ (optional withSqlite
''--set LIBSQLITE "${pkgs.sqlite.out}/lib/libsqlite3.so"'')
);
# Native Lua libraries
extraMakeWrapperLuaCArgs = optionalString (resolvedExtraLuaPackages != []) ''
--suffix LUA_CPATH ";" "${
lib.concatMapStringsSep ";" pkgs.luaPackages.getLuaCPath
resolvedExtraLuaPackages
}"'';
# Lua libraries
extraMakeWrapperLuaArgs =
optionalString (resolvedExtraLuaPackages != [])
''
--suffix LUA_PATH ";" "${
concatMapStringsSep ";" pkgs.luaPackages.getLuaPath
resolvedExtraLuaPackages
}"'';
in
# wrapNeovimUnstable is the nixpkgs utility function for building a Neovim derivation.
pkgs.wrapNeovimUnstable pkgs.neovim-unwrapped (neovimConfig
// {
luaRcContent = initLua;
wrapperArgs =
escapeShellArgs neovimConfig.wrapperArgs
+ " "
+ extraMakeWrapperArgs
+ " "
+ extraMakeWrapperLuaCArgs
+ " "
+ extraMakeWrapperLuaArgs;
wrapRc = true;
})

114
nix/neovim-overlay.nix Normal file

@ -0,0 +1,114 @@
# This overlay, when applied to nixpkgs, adds the final neovim derivation to nixpkgs.
{inputs}: final: prev:
with final.pkgs.lib; let
pkgs = final;
# Use this to create a plugin from a flake input
mkNvimPlugin = src: pname:
pkgs.vimUtils.buildVimPlugin {
inherit pname src;
version = src.lastModifiedDate;
};
# This is the helper function that builds the Neovim derivation.
mkNeovim = pkgs.callPackage ./mkNeovim.nix {};
# A plugin can either be a package or an attrset, such as
# { plugin = <plugin>; # the package, e.g. pkgs.vimPlugins.nvim-cmp
# config = <config>; # String; a config that will be loaded with the plugin
# # Boolean; Whether to automatically load the plugin as a 'start' plugin,
# # or as an 'opt' plugin, that can be loaded with `:packadd!`
# optional = <true|false>; # Default: false
# ...
# }
all-plugins = with pkgs.vimPlugins; [
# plugins from nixpkgs go in here.
# https://search.nixos.org/packages?channel=unstable&from=0&size=50&sort=relevance&type=packages&query=vimPlugins
nvim-treesitter.withAllGrammars
luasnip # snippets | https://github.com/l3mon4d3/luasnip/
# nvim-cmp (autocompletion) and extensions
nvim-cmp # https://github.com/hrsh7th/nvim-cmp
cmp_luasnip # snippets autocompletion extension for nvim-cmp | https://github.com/saadparwaiz1/cmp_luasnip/
lspkind-nvim # vscode-like LSP pictograms | https://github.com/onsails/lspkind.nvim/
cmp-nvim-lsp # LSP as completion source | https://github.com/hrsh7th/cmp-nvim-lsp/
cmp-nvim-lsp-signature-help # https://github.com/hrsh7th/cmp-nvim-lsp-signature-help/
cmp-buffer # current buffer as completion source | https://github.com/hrsh7th/cmp-buffer/
cmp-path # file paths as completion source | https://github.com/hrsh7th/cmp-path/
cmp-nvim-lua # neovim lua API as completion source | https://github.com/hrsh7th/cmp-nvim-lua/
cmp-cmdline # cmp command line suggestions
cmp-cmdline-history # cmp command line history suggestions
# ^ nvim-cmp extensions
# git integration plugins
diffview-nvim # https://github.com/sindrets/diffview.nvim/
neogit # https://github.com/TimUntersberger/neogit/
gitsigns-nvim # https://github.com/lewis6991/gitsigns.nvim/
vim-fugitive # https://github.com/tpope/vim-fugitive/
# ^ git integration plugins
# telescope and extensions
telescope-nvim # https://github.com/nvim-telescope/telescope.nvim/
telescope-fzy-native-nvim # https://github.com/nvim-telescope/telescope-fzy-native.nvim
# telescope-smart-history-nvim # https://github.com/nvim-telescope/telescope-smart-history.nvim
# ^ telescope and extensions
# UI
lualine-nvim # Status line | https://github.com/nvim-lualine/lualine.nvim/
nvim-navic # Add LSP location to lualine | https://github.com/SmiteshP/nvim-navic
statuscol-nvim # Status column | https://github.com/luukvbaal/statuscol.nvim/
nvim-treesitter-context # nvim-treesitter-context
# ^ UI
# language support
# ^ language support
# navigation/editing enhancement plugins
vim-unimpaired # predefined ] and [ navigation keymaps | https://github.com/tpope/vim-unimpaired/
eyeliner-nvim # Highlights unique characters for f/F and t/T motions | https://github.com/jinh0/eyeliner.nvim
nvim-surround # https://github.com/kylechui/nvim-surround/
nvim-treesitter-textobjects # https://github.com/nvim-treesitter/nvim-treesitter-textobjects/
nvim-ts-context-commentstring # https://github.com/joosepalviste/nvim-ts-context-commentstring/
# ^ navigation/editing enhancement plugins
# Useful utilities
nvim-unception # Prevent nested neovim sessions | nvim-unception
# ^ Useful utilities
# libraries that other plugins depend on
sqlite-lua
plenary-nvim
nvim-web-devicons
vim-repeat
# ^ libraries that other plugins depend on
# bleeding-edge plugins from flake inputs
# (mkNvimPlugin inputs.wf-nvim "wf.nvim") # (example) keymap hints | https://github.com/Cassin01/wf.nvim
# ^ bleeding-edge plugins from flake inputs
which-key-nvim
];
extraPackages = with pkgs; [
# language servers, etc.
lua-language-server
nil # nix LSP
];
in {
# This is the neovim derivation
# returned by the overlay
nvim-pkg = mkNeovim {
plugins = all-plugins;
inherit extraPackages;
};
# This can be symlinked in the devShell's shellHook
nvim-luarc-json = final.mk-luarc-json {
plugins = all-plugins;
};
# You can add as many derivations as you like.
# Use `ignoreConfigRegexes` to filter out config
# files you would not like to include.
#
# For example:
#
# nvim-pkg-no-telescope = mkNeovim {
# plugins = [];
# ignoreConfigRegexes = [
# "^plugin/telescope.lua"
# "^ftplugin/.*.lua"
# ];
# inherit extraPackages;
# };
}

317
nvim-nix.svg Normal file

@ -0,0 +1,317 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="600"
height="71.653839"
viewBox="0 0 600.00003 71.653839"
version="1.1"
id="svg95"
sodipodi:docname="nvim-nix.svg"
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<sodipodi:namedview
id="namedview97"
pagecolor="#505050"
bordercolor="#ffffff"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="1"
inkscape:deskcolor="#505050"
showgrid="false"
inkscape:zoom="3.7301328"
inkscape:cx="323.71502"
inkscape:cy="-34.583219"
inkscape:window-width="3580"
inkscape:window-height="1508"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="g8863" />
<title
id="title70">neovim-mark@2x</title>
<description>Created with Sketch (http://www.bohemiancoding.com/sketch)</description>
<defs
id="defs87">
<linearGradient
inkscape:collect="always"
id="linearGradient1782">
<stop
style="stop-color:#159ce0;stop-opacity:0.80000001;"
offset="0"
id="stop1778" />
<stop
style="stop-color:#105db5;stop-opacity:0.83529413;"
offset="1"
id="stop1780" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient1774">
<stop
style="stop-color:#7bb442;stop-opacity:0.80000001;"
offset="0"
id="stop1770" />
<stop
style="stop-color:#459440;stop-opacity:0.8392157;"
offset="1"
id="stop1772" />
</linearGradient>
<linearGradient
x1="167.95833"
y1="-0.46142399"
x2="167.95833"
y2="335.45523"
id="linearGradient-1"
gradientTransform="scale(0.46142398,2.1672042)"
gradientUnits="userSpaceOnUse">
<stop
stop-color="#16B0ED"
stop-opacity="0.800235524"
offset="0%"
id="stop72" />
<stop
stop-color="#0F59B2"
stop-opacity="0.83700023"
offset="100%"
id="stop74" />
</linearGradient>
<linearGradient
x1="1118.3427"
y1="-0.46586797"
x2="1118.3427"
y2="338.68604"
id="linearGradient-2"
gradientTransform="scale(0.46586797,2.1465309)"
gradientUnits="userSpaceOnUse">
<stop
stop-color="#7DB643"
offset="0%"
id="stop77" />
<stop
stop-color="#367533"
offset="100%"
id="stop79" />
</linearGradient>
<linearGradient
x1="356.33795"
y1="0"
x2="356.33795"
y2="612.90131"
id="linearGradient-3"
gradientTransform="scale(0.84189739,1.1877932)"
gradientUnits="userSpaceOnUse">
<stop
stop-color="#88C649"
stop-opacity="0.8"
offset="0%"
id="stop82" />
<stop
stop-color="#439240"
stop-opacity="0.84"
offset="100%"
id="stop84" />
</linearGradient>
<linearGradient
x1="49.021549"
y1="-0.079835393"
x2="49.021549"
y2="97.845657"
id="linearGradient-1-2"
gradientTransform="scale(0.46153975,2.1666606)"
gradientUnits="userSpaceOnUse">
<stop
stop-color="#16B0ED"
stop-opacity="0.800235524"
offset="0%"
id="stop5136" />
<stop
stop-color="#0F59B2"
stop-opacity="0.83700023"
offset="100%"
id="stop5138" />
</linearGradient>
<linearGradient
x1="326.17365"
y1="-0.069164939"
x2="326.17365"
y2="98.851547"
id="linearGradient-2-2"
gradientTransform="scale(0.46628455,2.1446132)"
gradientUnits="userSpaceOnUse">
<stop
stop-color="#7DB643"
offset="0%"
id="stop5141" />
<stop
stop-color="#367533"
offset="100%"
id="stop5143" />
</linearGradient>
<linearGradient
x1="103.88479"
y1="-0.11508822"
x2="103.88479"
y2="178.55785"
id="linearGradient-3-8"
gradientTransform="scale(0.84203823,1.1875945)"
gradientUnits="userSpaceOnUse">
<stop
stop-color="#88C649"
stop-opacity="0.8"
offset="0%"
id="stop5146" />
<stop
stop-color="#439240"
stop-opacity="0.84"
offset="100%"
id="stop5148" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient1774"
id="linearGradient1776"
x1="52.443624"
y1="-87.210322"
x2="119.70557"
y2="-87.210322"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.66190409,0,0,0.66190409,-85.433543,-23.706043)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient1782"
id="linearGradient1784"
x1="44.901705"
y1="-87.250641"
x2="112.14013"
y2="-87.250641"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.66190409,0,0,0.66190409,-85.433543,-23.706043)" />
</defs>
<metadata
id="metadata14713">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:title>neovim-mark@2x</dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
aria-label="haskell-tools.nvim"
id="text4483"
style="font-weight:bold;font-size:33.4748px;font-family:Lato;-inkscape-font-specification:'Lato Bold';fill:#1a1a1a;stroke-width:1.39478"
transform="translate(307.65719,89.970579)">
<g
id="g5925"
transform="matrix(1.6576683,0,0,1.6576683,-217.36825,0)">
<g
id="g8863"
transform="matrix(0.81614217,0,0,0.81614217,-10.014267,-7.820178)">
<g
aria-label="kickstart-nix.nvim"
id="text1840"
style="font-size:47.306px;font-family:Roboto;-inkscape-font-specification:Roboto;fill:#444444;stroke-width:1.03096"
transform="translate(2.5202188,76.281885)">
<path
d="m 33.747205,-123.78629 v 20.98021 h 1.088038 q 0.331142,0 0.614978,-0.0946 0.307489,-0.0946 0.662284,-0.44941 l 9.437547,-8.96449 q 0.23653,-0.28383 0.520366,-0.42575 0.283836,-0.16557 0.70959,-0.16557 h 1.986852 l -10.383667,9.8633 q -0.425754,0.49671 -0.922467,0.78055 0.378448,0.18922 0.638631,0.4494 0.283836,0.23653 0.544019,0.56768 l 10.904033,11.873802 H 47.58421 q -0.331142,0 -0.614978,-0.09461 -0.260183,-0.118265 -0.496713,-0.449407 l -9.886954,-10.596545 q -0.189224,-0.21288 -0.378448,-0.3548 -0.165571,-0.14191 -0.354795,-0.21287 -0.189224,-0.0946 -0.449407,-0.11827 -0.23653,-0.0473 -0.591325,-0.0473 h -1.064385 v 11.873804 h -2.270688 v -34.415114 z"
style="font-weight:300;font-family:Lato;-inkscape-font-specification:'Lato Light'"
id="path2262" />
<path
d="m 56.501384,-112.90591 v 23.534732 h -2.247035 v -23.534732 z m 0.969773,-8.11298 q 0,0.42575 -0.189224,0.8042 -0.165571,0.3548 -0.449407,0.63863 -0.283836,0.28384 -0.662284,0.44941 -0.378448,0.16557 -0.804202,0.16557 -0.425754,0 -0.804202,-0.16557 -0.378448,-0.16557 -0.662284,-0.44941 -0.283836,-0.28383 -0.449407,-0.63863 -0.165571,-0.37845 -0.165571,-0.8042 0,-0.42576 0.165571,-0.8042 0.165571,-0.4021 0.449407,-0.68594 0.283836,-0.28384 0.662284,-0.44941 0.378448,-0.16557 0.804202,-0.16557 0.425754,0 0.804202,0.16557 0.378448,0.16557 0.662284,0.44941 0.283836,0.28384 0.449407,0.68594 0.189224,0.37844 0.189224,0.8042 z"
style="font-weight:300;font-family:Lato;-inkscape-font-specification:'Lato Light'"
id="path2264" />
<path
d="m 80.343603,-109.76006 q -0.118265,0.11826 -0.23653,0.21287 -0.09461,0.071 -0.283836,0.071 -0.23653,0 -0.638631,-0.30749 -0.402101,-0.33114 -1.088038,-0.70959 -0.685937,-0.37844 -1.726669,-0.68593 -1.017079,-0.33115 -2.483565,-0.33115 -2.034158,0 -3.618909,0.73325 -1.561098,0.70959 -2.649136,2.05781 -1.088038,1.34822 -1.65571,3.26411 -0.544019,1.9159 -0.544019,4.30485 0,2.483563 0.567672,4.399456 0.591325,1.915893 1.65571,3.240461 1.064385,1.300915 2.578177,1.986852 1.513792,0.685937 3.358726,0.685937 1.703016,0 2.83836,-0.402101 1.158997,-0.402101 1.89224,-0.875161 0.756896,-0.47306 1.18265,-0.875161 0.425754,-0.402101 0.70959,-0.402101 0.283836,0 0.47306,0.23653 l 0.591325,0.756896 q -0.544019,0.70959 -1.371874,1.324568 -0.827855,0.614978 -1.868587,1.064385 -1.040732,0.449407 -2.270688,0.685937 -1.206303,0.260183 -2.530871,0.260183 -2.247035,0 -4.115622,-0.804202 -1.844934,-0.827855 -3.193155,-2.3653 -1.324568,-1.561098 -2.081464,-3.808133 -0.733243,-2.247035 -0.733243,-5.109046 0,-2.69644 0.70959,-4.91983 0.70959,-2.22338 2.081464,-3.83178 1.371874,-1.60841 3.335073,-2.48357 1.986852,-0.89881 4.541376,-0.89881 2.294341,0 4.068316,0.73324 1.773975,0.73325 3.098543,1.98685 z"
style="font-weight:300;font-family:Lato;-inkscape-font-specification:'Lato Light'"
id="path2266" />
<path
d="m 89.095228,-123.78629 v 20.98021 h 1.088038 q 0.331142,0 0.614978,-0.0946 0.307489,-0.0946 0.662284,-0.44941 l 9.437542,-8.96449 q 0.23653,-0.28383 0.52037,-0.42575 0.28384,-0.16557 0.70959,-0.16557 h 1.98685 l -10.383664,9.8633 q -0.425754,0.49671 -0.922467,0.78055 0.378448,0.18922 0.638631,0.4494 0.283836,0.23653 0.544019,0.56768 l 10.904031,11.873802 h -1.9632 q -0.33114,0 -0.61498,-0.09461 -0.26018,-0.118265 -0.49671,-0.449407 l -9.886952,-10.596545 q -0.189224,-0.21288 -0.378448,-0.3548 -0.165571,-0.14191 -0.354795,-0.21287 -0.189224,-0.0946 -0.449407,-0.11827 -0.23653,-0.0473 -0.591325,-0.0473 h -1.064385 v 11.873804 H 86.82454 v -34.415114 z"
style="font-weight:300;font-family:Lato;-inkscape-font-specification:'Lato Light'"
id="path2268" />
<path
d="m 122.28039,-109.99659 q -0.18923,0.33114 -0.54402,0.33114 -0.26019,0 -0.66229,-0.28384 -0.4021,-0.30749 -1.08804,-0.66228 -0.66228,-0.37845 -1.65571,-0.66229 -0.99342,-0.30748 -2.4126,-0.30748 -1.27726,0 -2.34165,0.37844 -1.04073,0.3548 -1.79763,0.96978 -0.73324,0.61497 -1.13534,1.44283 -0.4021,0.8042 -0.4021,1.70302 0,1.11169 0.56767,1.84493 0.56767,0.73324 1.46649,1.25361 0.92246,0.52036 2.10511,0.89881 1.18265,0.37845 2.38896,0.7569 1.22995,0.37845 2.4126,0.85151 1.18265,0.4494 2.08147,1.13534 0.92246,0.685937 1.49014,1.679363 0.56767,0.993426 0.56767,2.412606 0,1.537445 -0.54402,2.862013 -0.54402,1.324568 -1.60841,2.294341 -1.04073,0.969773 -2.57817,1.537445 -1.53745,0.567672 -3.5243,0.567672 -2.48356,0 -4.28119,-0.780549 -1.79763,-0.804202 -3.21681,-2.081464 l 0.52037,-0.804202 q 0.11826,-0.189224 0.26018,-0.283836 0.16557,-0.09461 0.42575,-0.09461 0.30749,0 0.73325,0.378448 0.4494,0.378448 1.18265,0.827855 0.73324,0.425754 1.79762,0.804202 1.08804,0.378448 2.67279,0.378448 1.49014,0 2.62549,-0.402101 1.13534,-0.425754 1.89224,-1.135344 0.75689,-0.70959 1.13534,-1.65571 0.4021,-0.969773 0.4021,-2.034158 0,-1.18265 -0.56767,-1.963199 -0.56767,-0.780549 -1.49014,-1.324568 -0.92247,-0.544019 -2.10512,-0.922472 -1.15899,-0.37844 -2.38895,-0.75689 -1.22996,-0.37845 -2.41261,-0.82786 -1.15899,-0.4494 -2.08146,-1.13534 -0.92247,-0.68594 -1.49014,-1.65571 -0.56767,-0.99343 -0.56767,-2.45991 0,-1.25361 0.54402,-2.41261 0.54402,-1.159 1.53744,-2.03416 1.01708,-0.87516 2.45991,-1.39552 1.44284,-0.52037 3.24047,-0.52037 2.15242,0 3.80813,0.61498 1.67936,0.61498 3.05124,1.89224 z"
style="font-weight:300;font-family:Lato;-inkscape-font-specification:'Lato Light'"
id="path2270" />
<path
d="m 135.88082,-88.99273 q -2.38895,0 -3.73717,-1.324568 -1.32457,-1.324568 -1.32457,-4.091969 v -16.084043 h -3.38238 q -0.26018,0 -0.42575,-0.14191 -0.16557,-0.14192 -0.16557,-0.40211 v -0.87516 l 4.02101,-0.28383 0.56767,-8.42047 q 0.0473,-0.21288 0.18922,-0.37845 0.14192,-0.16557 0.4021,-0.16557 h 1.06439 v 8.98814 h 7.42704 v 1.67936 h -7.42704 v 15.965778 q 0,0.969773 0.23653,1.679363 0.26018,0.685937 0.68593,1.135344 0.44941,0.449407 1.04074,0.662284 0.59132,0.212877 1.27726,0.212877 0.85151,0 1.46648,-0.23653 0.61498,-0.260183 1.06439,-0.544019 0.44941,-0.307489 0.73324,-0.544019 0.28384,-0.260183 0.44941,-0.260183 0.18922,0 0.37845,0.23653 l 0.61498,0.993426 q -0.89882,0.993426 -2.29435,1.608404 -1.37187,0.591325 -2.86201,0.591325 z"
style="font-weight:300;font-family:Lato;-inkscape-font-specification:'Lato Light'"
id="path2272" />
<path
d="m 158.82426,-100.74827 q -3.35873,0.11826 -5.79499,0.54402 -2.4126,0.402099 -3.99735,1.111689 -1.5611,0.70959 -2.318,1.703016 -0.75689,0.969773 -0.75689,2.223382 0,1.18265 0.37844,2.057811 0.4021,0.851508 1.04074,1.41918 0.66228,0.544019 1.51379,0.804202 0.85151,0.260183 1.77397,0.260183 1.37188,0 2.50722,-0.283836 1.159,-0.307489 2.12877,-0.827855 0.99343,-0.544019 1.84493,-1.277262 0.85151,-0.733243 1.67937,-1.584751 z m -13.83701,-8.82257 q 1.84494,-1.84493 3.87909,-2.79105 2.03416,-0.94612 4.61234,-0.94612 1.89224,0 3.31142,0.61497 1.41918,0.59133 2.34165,1.72667 0.94612,1.11169 1.41918,2.7201 0.47306,1.58475 0.47306,3.54795 v 15.327142 h -0.89882 q -0.70959,0 -0.87516,-0.662284 l -0.33114,-3.027584 q -0.96977,0.94612 -1.93955,1.703016 -0.94612,0.756896 -1.98685,1.277262 -1.04073,0.520366 -2.24703,0.804202 -1.20631,0.283836 -2.64914,0.283836 -1.2063,0 -2.34165,-0.354795 -1.13534,-0.354795 -2.03415,-1.088038 -0.87517,-0.733243 -1.41918,-1.868587 -0.52037,-1.158997 -0.52037,-2.767401 0,-1.490139 0.85151,-2.767401 0.85151,-1.277262 2.67279,-2.223378 1.82128,-0.94612 4.65964,-1.5138 2.86201,-0.56767 6.85937,-0.66228 v -2.45991 q 0,-3.26412 -1.41918,-5.01444 -1.39553,-1.77397 -4.16293,-1.77397 -1.70302,0 -2.90932,0.47306 -1.18265,0.47306 -2.0105,1.04073 -0.82786,0.56767 -1.34823,1.04073 -0.52036,0.47306 -0.87516,0.47306 -0.26018,0 -0.42575,-0.11826 -0.16557,-0.11827 -0.28384,-0.30749 z"
style="font-weight:300;font-family:Lato;-inkscape-font-specification:'Lato Light'"
id="path2274" />
<path
d="m 170.69803,-107.22919 q 0.54402,-1.44284 1.22996,-2.55453 0.70959,-1.13534 1.6084,-1.91589 0.92247,-0.78055 2.03416,-1.18265 1.13534,-0.42575 2.50722,-0.42575 0.73324,0 1.44283,0.14191 0.70959,0.11827 1.25361,0.44941 l -0.18922,1.5611 q -0.11827,0.37845 -0.44941,0.37845 -0.28384,0 -0.87516,-0.16557 -0.56767,-0.16557 -1.51379,-0.16557 -1.37188,0 -2.43626,0.42575 -1.04073,0.4021 -1.89224,1.22996 -0.82786,0.82785 -1.46649,2.05781 -0.61498,1.2063 -1.13534,2.79105 v 15.232532 h -2.27069 v -23.534732 h 1.2063 q 0.4021,0 0.56767,0.16557 0.16558,0.16557 0.21288,0.56767 z"
style="font-weight:300;font-family:Lato;-inkscape-font-specification:'Lato Light'"
id="path2276" />
<path
d="m 191.70191,-88.99273 q -2.38895,0 -3.73717,-1.324568 -1.32457,-1.324568 -1.32457,-4.091969 v -16.084043 h -3.38238 q -0.26018,0 -0.42575,-0.14191 -0.16557,-0.14192 -0.16557,-0.40211 v -0.87516 l 4.02101,-0.28383 0.56767,-8.42047 q 0.0473,-0.21288 0.18922,-0.37845 0.14192,-0.16557 0.4021,-0.16557 h 1.06439 v 8.98814 h 7.42704 v 1.67936 h -7.42704 v 15.965778 q 0,0.969773 0.23653,1.679363 0.26018,0.685937 0.68593,1.135344 0.44941,0.449407 1.04074,0.662284 0.59132,0.212877 1.27726,0.212877 0.85151,0 1.46648,-0.23653 0.61498,-0.260183 1.06439,-0.544019 0.44941,-0.307489 0.73324,-0.544019 0.28384,-0.260183 0.44941,-0.260183 0.18922,0 0.37845,0.23653 l 0.61498,0.993426 q -0.89882,0.993426 -2.29435,1.608404 -1.37187,0.591325 -2.86201,0.591325 z"
style="font-weight:300;font-family:Lato;-inkscape-font-specification:'Lato Light'"
id="path2278" />
<path
d="m 200.85565,-104.36718 h 10.99864 v 1.91589 h -10.99864 z"
style="font-weight:300;font-family:Lato;-inkscape-font-specification:'Lato Light'"
id="path2280" />
<path
d="m 221.12632,-108.79029 q 1.63205,-2.03416 3.76082,-3.26411 2.15243,-1.22996 4.77791,-1.22996 1.93954,0 3.40603,0.61498 1.49014,0.61498 2.45991,1.77397 0.96978,1.159 1.46649,2.79106 0.49671,1.63205 0.49671,3.68986 v 15.043312 h -2.27069 v -15.043312 q 0,-3.31142 -1.51379,-5.18 -1.51379,-1.89224 -4.61233,-1.89224 -2.29434,0 -4.30485,1.18265 -1.98685,1.15899 -3.54795,3.24046 v 17.692442 h -2.27069 v -23.534732 h 1.25361 q 0.59133,0 0.68594,0.59132 z"
style="font-weight:300;font-family:Lato;-inkscape-font-specification:'Lato Light'"
id="path2282" />
<path
d="m 247.49938,-112.90591 v 23.534732 h -2.24704 v -23.534732 z m 0.96977,-8.11298 q 0,0.42575 -0.18923,0.8042 -0.16557,0.3548 -0.4494,0.63863 -0.28384,0.28384 -0.66229,0.44941 -0.37844,0.16557 -0.8042,0.16557 -0.42575,0 -0.8042,-0.16557 -0.37845,-0.16557 -0.66228,-0.44941 -0.28384,-0.28383 -0.44941,-0.63863 -0.16557,-0.37845 -0.16557,-0.8042 0,-0.42576 0.16557,-0.8042 0.16557,-0.4021 0.44941,-0.68594 0.28383,-0.28384 0.66228,-0.44941 0.37845,-0.16557 0.8042,-0.16557 0.42576,0 0.8042,0.16557 0.37845,0.16557 0.66229,0.44941 0.28383,0.28384 0.4494,0.68594 0.18923,0.37844 0.18923,0.8042 z"
style="font-weight:300;font-family:Lato;-inkscape-font-specification:'Lato Light'"
id="path2284" />
<path
d="M 272.78442,-89.371178 H 270.632 q -0.33114,0 -0.52037,-0.189224 -0.18922,-0.212877 -0.30749,-0.402101 l -7.1432,-10.430977 q -0.0946,0.425758 -0.3548,0.827859 l -6.81206,9.603118 q -0.16557,0.212877 -0.3548,0.402101 -0.16557,0.189224 -0.4494,0.189224 h -2.03416 l 8.56238,-12.039372 -8.23124,-11.49536 h 2.15242 q 0.33115,0 0.49672,0.14192 0.16557,0.14191 0.28383,0.33114 l 6.90668,9.95791 q 0.0473,-0.18922 0.14192,-0.4021 0.11826,-0.21288 0.23653,-0.42575 l 6.45727,-9.10641 q 0.14191,-0.21288 0.30748,-0.35479 0.16558,-0.14192 0.42576,-0.14192 h 2.05781 l -8.20759,11.35344 z"
style="font-weight:300;font-family:Lato;-inkscape-font-specification:'Lato Light'"
id="path2286" />
<path
d="m 277.16022,-91.192459 q 0,-0.449407 0.16557,-0.851508 0.16557,-0.402101 0.44941,-0.685937 0.30749,-0.307489 0.68594,-0.47306 0.4021,-0.189224 0.87516,-0.189224 0.4494,0 0.8515,0.189224 0.40211,0.165571 0.68594,0.47306 0.30749,0.283836 0.47306,0.685937 0.18923,0.402101 0.18923,0.851508 0,0.47306 -0.18923,0.875161 -0.16557,0.378448 -0.47306,0.685937 -0.28383,0.283836 -0.68594,0.449407 -0.4021,0.165571 -0.8515,0.165571 -0.92247,0 -1.5611,-0.614978 -0.61498,-0.638631 -0.61498,-1.561098 z"
style="font-weight:300;font-family:Lato;-inkscape-font-specification:'Lato Light'"
id="path2288" />
<path
d="m 293.22059,-110.65888 q 0.73324,-0.73324 1.53744,-1.34822 0.82786,-0.63863 1.72667,-1.06438 0.92247,-0.44941 1.9632,-0.68594 1.04073,-0.26018 2.27069,-0.26018 1.98685,0 3.52429,0.68593 1.53745,0.66229 2.55453,1.89224 1.04073,1.20631 1.5611,2.90932 0.54401,1.67937 0.54401,3.71352 v 15.445412 h -5.84229 v -15.445412 q 0,-2.22338 -1.01708,-3.42968 -1.01707,-1.22996 -3.09854,-1.22996 -1.51379,0 -2.83836,0.68594 -1.32457,0.68594 -2.50722,1.86859 v 17.550522 h -5.84229 v -24.267982 h 3.57161 q 1.13534,0 1.49013,1.06439 z"
style="font-family:Lato;-inkscape-font-specification:'Lato Bold'"
id="path2290" />
<path
d="m 335.77233,-113.63916 -9.62677,24.267982 h -5.29827 l -9.62677,-24.267982 h 4.82521 q 0.66229,0 1.08804,0.30749 0.44941,0.30749 0.59132,0.78055 l 4.6833,12.961846 q 0.37845,1.135344 0.66228,2.223382 0.28384,1.088038 0.49672,2.176076 0.23653,-1.088038 0.52036,-2.176076 0.28384,-1.088038 0.68594,-2.223382 l 4.7779,-12.961846 q 0.16558,-0.47306 0.59133,-0.78055 0.42575,-0.30749 1.01708,-0.30749 z"
style="font-family:Lato;-inkscape-font-specification:'Lato Bold'"
id="path2292" />
<path
d="m 344.92602,-113.63916 v 24.267982 h -5.86595 v -24.267982 z m 0.8042,-7.07224 q 0,0.75689 -0.30749,1.41918 -0.30749,0.66228 -0.82786,1.15899 -0.49671,0.49672 -1.18265,0.80421 -0.68593,0.28383 -1.46648,0.28383 -0.7569,0 -1.44284,-0.28383 -0.66228,-0.30749 -1.15899,-0.80421 -0.49672,-0.49671 -0.8042,-1.15899 -0.28384,-0.66229 -0.28384,-1.41918 0,-0.78055 0.28384,-1.46649 0.30748,-0.68594 0.8042,-1.18265 0.49671,-0.49671 1.15899,-0.78055 0.68594,-0.30749 1.44284,-0.30749 0.78055,0 1.46648,0.30749 0.68594,0.28384 1.18265,0.78055 0.52037,0.49671 0.82786,1.18265 0.30749,0.68594 0.30749,1.46649 z"
style="font-family:Lato;-inkscape-font-specification:'Lato Bold'"
id="path2294" />
<path
d="m 350.88656,-89.371178 v -24.267982 h 3.57161 q 1.13534,0 1.49014,1.06439 l 0.37844,1.79763 q 0.63864,-0.70959 1.32457,-1.30092 0.70959,-0.59132 1.49014,-1.01708 0.8042,-0.42575 1.70302,-0.66228 0.92246,-0.26018 2.0105,-0.26018 2.29434,0 3.76083,1.25361 1.49014,1.22995 2.22338,3.28776 0.56767,-1.2063 1.41918,-2.05781 0.85151,-0.87516 1.86859,-1.41918 1.01708,-0.54402 2.15242,-0.8042 1.159,-0.26018 2.318,-0.26018 2.0105,0 3.5716,0.61497 1.5611,0.61498 2.62548,1.79763 1.06439,1.18265 1.60841,2.88567 0.56767,1.70301 0.56767,3.90274 v 15.445412 h -5.84229 v -15.445412 q 0,-2.31799 -1.01708,-3.47699 -1.01708,-1.18265 -2.98028,-1.18265 -0.89881,0 -1.67936,0.30749 -0.7569,0.30749 -1.34822,0.89882 -0.56768,0.56767 -0.89882,1.44283 -0.33114,0.87516 -0.33114,2.0105 v 15.445412 h -5.86594 v -15.445412 q 0,-2.43626 -0.99343,-3.54795 -0.96977,-1.11169 -2.86201,-1.11169 -1.27727,0 -2.38896,0.63863 -1.08803,0.61498 -2.03415,1.70302 v 17.763402 z"
style="font-family:Lato;-inkscape-font-specification:'Lato Bold'"
id="path2296" />
</g>
</g>
<g
id="g2301"
transform="translate(6.7950945,48.768295)">
<path
fill="#7ebae4"
d="m -36.254318,-89.55896 -12.061602,21.02585 -2.815852,-4.804756 3.250288,-5.631303 -6.455455,-0.01677 -1.375982,-2.40098 1.40513,-2.455691 9.189052,0.0292 3.302196,-5.73073 z m 0.925574,16.808062 24.121211,0.0012 -2.726012,4.857064 -6.470627,-0.01797 3.213152,5.636095 -1.377581,2.399783 -2.81505,0.0032 -4.569969,-8.024697 -6.581633,-0.01358 z m 14.039327,-9.213408 -12.059606,-21.027044 5.54226,-0.0523 3.219541,5.64927 3.242303,-5.61892 2.753959,6.6e-4 1.410325,2.45289 -4.619884,7.99555 3.279436,5.7443 z"
clip-rule="evenodd"
fill-rule="evenodd"
id="path830"
style="fill:url(#linearGradient1784);fill-opacity:1;stroke-width:0.556933" />
<path
fill="#5277c3"
d="m -40.607068,-80.897381 12.059606,21.027048 -5.54226,0.05231 -3.219542,-5.649272 -3.242302,5.618926 -2.75396,-7.95e-4 -1.410321,-2.452889 4.619881,-7.995549 -3.279437,-5.744305 z m 14.007383,-9.266509 -24.121209,-0.001 2.726409,-4.85667 6.470229,0.0179 -3.213153,-5.63609 1.377579,-2.39979 2.815452,-0.004 4.569569,8.0247 6.582033,0.0136 2.793491,4.84109 z m 0.941147,16.85677 12.061604,-21.02625 2.815853,4.80516 -3.25069,5.6309 6.455855,0.0172 1.375979,2.400982 -1.40513,2.455684 -9.189049,-0.02915 -3.302197,5.730729 z"
clip-rule="evenodd"
fill-rule="evenodd"
id="path832"
sodipodi:nodetypes="ccccccccccccccccccccccccccccccc"
style="fill:url(#linearGradient1776);fill-opacity:1;stroke-width:0.556933" />
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 23 KiB

8
nvim/after/README.md Normal file

@ -0,0 +1,8 @@
## `after` directory
Scripts put in
- `after/plugin` will be sourced *after* init.lua
or any other scripts are sourced during startup.
- `after/ftplugin` will be sourced when opening a
filetype, *after* any other `ftplugin` scripts are sourced.

55
nvim/ftplugin/lua.lua Normal file

@ -0,0 +1,55 @@
vim.bo.comments = ':---,:--'
local lua_ls_cmd = 'lua-language-server'
-- Check if lua-language-server is available
if vim.fn.executable(lua_ls_cmd) ~= 1 then
return
end
local root_files = {
'.luarc.json',
'.luarc.jsonc',
'.luacheckrc',
'.stylua.toml',
'stylua.toml',
'selene.toml',
'selene.yml',
'.git',
}
vim.lsp.start {
name = 'luals',
cmd = { lua_ls_cmd },
root_dir = vim.fs.dirname(vim.fs.find(root_files, { upward = true })[1]),
capabilities = require('user.lsp').make_client_capabilities(),
settings = {
Lua = {
runtime = {
version = 'LuaJIT',
},
diagnostics = {
-- Get the language server to recognize the `vim` global, etc.
globals = {
'vim',
'describe',
'it',
'assert',
'stub',
},
disable = {
'duplicate-set-field',
},
},
workspace = {
checkThirdParty = false,
},
telemetry = {
enable = false,
},
hint = { -- inlay hints (supported in Neovim >= 0.10)
enable = true,
},
},
},
}

18
nvim/ftplugin/nix.lua Normal file

@ -0,0 +1,18 @@
-- Exit if the language server isn't available
if vim.fn.executable('nil') ~= 1 then
return
end
local root_files = {
'flake.nix',
'default.nix',
'shell.nix',
'.git',
}
vim.lsp.start {
name = 'nil_ls',
cmd = { 'nil' },
root_dir = vim.fs.dirname(vim.fs.find(root_files, { upward = true })[1]),
capabilities = require('user.lsp').make_client_capabilities(),
}

115
nvim/init.lua Normal file

@ -0,0 +1,115 @@
local cmd = vim.cmd
local fn = vim.fn
local opt = vim.o
local g = vim.g
-- <leader> key. Defaults to `\`. Some people prefer space.
-- g.mapleader = ' '
-- g.maplocalleader = ' '
opt.compatible = false
-- Enable true colour support
if fn.has('termguicolors') then
opt.termguicolors = true
end
-- See :h <option> to see what the options do
-- Search down into subfolders
opt.path = vim.o.path .. '**'
opt.number = true
opt.relativenumber = true
opt.cursorline = true
opt.lazyredraw = true
opt.showmatch = true -- Highlight matching parentheses, etc
opt.incsearch = true
opt.hlsearch = true
opt.spell = true
opt.spelllang = 'en'
opt.expandtab = true
opt.tabstop = 2
opt.softtabstop = 2
opt.shiftwidth = 2
opt.foldenable = true
opt.history = 2000
opt.nrformats = 'bin,hex' -- 'octal'
opt.undofile = true
opt.splitright = true
opt.splitbelow = true
opt.cmdheight = 0
opt.fillchars = [[eob: ,fold: ,foldopen:,foldsep: ,foldclose:]]
-- Configure Neovim diagnostic messages
local function prefix_diagnostic(prefix, diagnostic)
return string.format(prefix .. ' %s', diagnostic.message)
end
local sign = function(opts)
fn.sign_define(opts.name, {
texthl = opts.name,
text = opts.text,
numhl = '',
})
end
-- Requires Nerd fonts
sign { name = 'DiagnosticSignError', text = '󰅚' }
sign { name = 'DiagnosticSignWarn', text = '' }
sign { name = 'DiagnosticSignInfo', text = '' }
sign { name = 'DiagnosticSignHint', text = '󰌶' }
vim.diagnostic.config {
virtual_text = {
prefix = '',
format = function(diagnostic)
local severity = diagnostic.severity
if severity == vim.diagnostic.severity.ERROR then
return prefix_diagnostic('󰅚', diagnostic)
end
if severity == vim.diagnostic.severity.WARN then
return prefix_diagnostic('', diagnostic)
end
if severity == vim.diagnostic.severity.INFO then
return prefix_diagnostic('', diagnostic)
end
if severity == vim.diagnostic.severity.HINT then
return prefix_diagnostic('󰌶', diagnostic)
end
return prefix_diagnostic('', diagnostic)
end,
},
signs = true,
update_in_insert = false,
underline = true,
severity_sort = true,
float = {
focusable = false,
style = 'minimal',
border = 'rounded',
source = 'always',
header = '',
prefix = '',
},
}
g.editorconfig = true
vim.opt.colorcolumn = '100'
-- Native plugins
cmd.filetype('plugin', 'indent', 'on')
cmd.packadd('cfilter') -- Allows filtering the quickfix list with :cfdo
-- let sqlite.lua (which some plugins depend on) know where to find sqlite
vim.g.sqlite_clib_path = require('luv').os_getenv('LIBSQLITE')
-- this should be at the end, because
-- it causes neovim to source ftplugins
-- on the packpath when passing a file to the nvim command
cmd.syntax('on')
cmd.syntax('enable')

23
nvim/lua/user/lsp.lua Normal file

@ -0,0 +1,23 @@
---@mod user.lsp
---
---@brief [[
---LSP related functions
---@brief ]]
local M = {}
---Gets a 'ClientCapabilities' object, describing the LSP client capabilities
---Extends the object with capabilities provided by plugins.
---@return lsp.ClientCapabilities
function M.make_client_capabilities()
local capabilities = vim.lsp.protocol.make_client_capabilities()
-- Add com_nvim_lsp capabilities
local cmp_lsp = require('cmp_nvim_lsp')
local cmp_lsp_capabilities = cmp_lsp.default_capabilities()
capabilities = vim.tbl_deep_extend('keep', capabilities, cmp_lsp_capabilities)
-- Add any additional plugin capabilities here.
-- Make sure to follow the instructions provided in the plugin's docs.
return capabilities
end
return M

@ -0,0 +1,154 @@
if vim.g.did_load_autocommands_plugin then
return
end
vim.g.did_load_autocommands_plugin = true
local api = vim.api
local tempdirgroup = api.nvim_create_augroup('tempdir', { clear = true })
-- Do not set undofile for files in /tmp
api.nvim_create_autocmd('BufWritePre', {
pattern = '/tmp/*',
group = tempdirgroup,
callback = function()
vim.cmd.setlocal('noundofile')
end,
})
-- Disable spell checking in terminal buffers
local nospell_group = api.nvim_create_augroup('nospell', { clear = true })
api.nvim_create_autocmd('TermOpen', {
group = nospell_group,
callback = function()
vim.wo[0].spell = false
end,
})
-- LSP
local keymap = vim.keymap
local function preview_location_callback(_, result)
if result == nil or vim.tbl_isempty(result) then
return nil
end
local buf, _ = vim.lsp.util.preview_location(result[1])
if buf then
local cur_buf = vim.api.nvim_get_current_buf()
vim.bo[buf].filetype = vim.bo[cur_buf].filetype
end
end
local function peek_definition()
local params = vim.lsp.util.make_position_params()
return vim.lsp.buf_request(0, 'textDocument/definition', params, preview_location_callback)
end
local function peek_type_definition()
local params = vim.lsp.util.make_position_params()
return vim.lsp.buf_request(0, 'textDocument/typeDefinition', params, preview_location_callback)
end
--- Don't create a comment string when hitting <Enter> on a comment line
vim.api.nvim_create_autocmd('BufEnter', {
group = vim.api.nvim_create_augroup('DisableNewLineAutoCommentString', {}),
callback = function()
vim.opt.formatoptions = vim.opt.formatoptions - { 'c', 'r', 'o' }
end,
})
vim.api.nvim_create_autocmd('LspAttach', {
group = vim.api.nvim_create_augroup('UserLspConfig', {}),
callback = function(ev)
local bufnr = ev.buf
local client = vim.lsp.get_client_by_id(ev.data.client_id)
-- Attach plugins
require('nvim-navic').attach(client, bufnr)
vim.cmd.setlocal('signcolumn=yes')
vim.bo[bufnr].bufhidden = 'hide'
-- Enable completion triggered by <c-x><c-o>
vim.bo[bufnr].omnifunc = 'v:lua.vim.lsp.omnifunc'
local function desc(description)
return { noremap = true, silent = true, buffer = bufnr, desc = description }
end
keymap.set('n', 'gD', vim.lsp.buf.declaration, desc('lsp [g]o to [D]eclaration'))
keymap.set('n', 'gd', vim.lsp.buf.definition, desc('lsp [g]o to [d]efinition'))
keymap.set('n', '<space>gt', vim.lsp.buf.type_definition, desc('lsp [g]o to [t]ype definition'))
keymap.set('n', 'K', vim.lsp.buf.hover, desc('[lsp] hover'))
keymap.set('n', '<space>pd', peek_definition, desc('lsp [p]eek [d]efinition'))
keymap.set('n', '<space>pt', peek_type_definition, desc('lsp [p]eek [t]ype definition'))
keymap.set('n', 'gi', vim.lsp.buf.implementation, desc('lsp [g]o to [i]mplementation'))
keymap.set('n', '<C-k>', vim.lsp.buf.signature_help, desc('[lsp] signature help'))
keymap.set('n', '<space>wa', vim.lsp.buf.add_workspace_folder, desc('lsp add [w]orksp[a]ce folder'))
keymap.set('n', '<space>wr', vim.lsp.buf.remove_workspace_folder, desc('lsp [w]orkspace folder [r]emove'))
keymap.set('n', '<space>wl', function()
vim.print(vim.lsp.buf.list_workspace_folders())
end, desc('[lsp] [w]orkspace folders [l]ist'))
keymap.set('n', '<space>rn', vim.lsp.buf.rename, desc('lsp [r]e[n]ame'))
keymap.set('n', '<space>wq', vim.lsp.buf.workspace_symbol, desc('lsp [w]orkspace symbol [q]'))
keymap.set('n', '<space>dd', vim.lsp.buf.document_symbol, desc('lsp [dd]ocument symbol'))
keymap.set('n', '<M-CR>', vim.lsp.buf.code_action, desc('[lsp] code action'))
keymap.set('n', '<M-l>', vim.lsp.codelens.run, desc('[lsp] run code lens'))
keymap.set('n', '<space>cr', vim.lsp.codelens.refresh, desc('lsp [c]ode lenses [r]efresh'))
keymap.set('n', 'gr', vim.lsp.buf.references, desc('lsp [g]et [r]eferences'))
keymap.set('n', '<space>f', function()
vim.lsp.buf.format { async = true }
end, desc('[lsp] [f]ormat buffer'))
if client.server_capabilities.inlayHintProvider then
keymap.set('n', '<space>h', function()
local current_setting = vim.lsp.inlay_hint.is_enabled(bufnr)
vim.lsp.inlay_hint.enable(bufnr, not current_setting)
end, desc('[lsp] toggle inlay hints'))
end
-- Auto-refresh code lenses
if not client then
return
end
local function buf_refresh_codeLens()
vim.schedule(function()
if client.server_capabilities.codeLensProvider then
vim.lsp.codelens.refresh()
return
end
end)
end
local group = api.nvim_create_augroup(string.format('lsp-%s-%s', bufnr, client.id), {})
if client.server_capabilities.codeLensProvider then
vim.api.nvim_create_autocmd({ 'InsertLeave', 'BufWritePost', 'TextChanged' }, {
group = group,
callback = buf_refresh_codeLens,
buffer = bufnr,
})
buf_refresh_codeLens()
end
end,
})
-- More examples, disabled by default
-- Toggle between relative/absolute line numbers
-- Show relative line numbers in the current buffer,
-- absolute line numbers in inactive buffers
-- local numbertoggle = api.nvim_create_augroup('numbertoggle', { clear = true })
-- api.nvim_create_autocmd({ 'BufEnter', 'FocusGained', 'InsertLeave', 'CmdlineLeave', 'WinEnter' }, {
-- pattern = '*',
-- group = numbertoggle,
-- callback = function()
-- if vim.o.nu and vim.api.nvim_get_mode().mode ~= 'i' then
-- vim.opt.relativenumber = true
-- end
-- end,
-- })
-- api.nvim_create_autocmd({ 'BufLeave', 'FocusLost', 'InsertEnter', 'CmdlineEnter', 'WinLeave' }, {
-- pattern = '*',
-- group = numbertoggle,
-- callback = function()
-- if vim.o.nu then
-- vim.opt.relativenumber = false
-- vim.cmd.redraw()
-- end
-- end,
-- })

9
nvim/plugin/commands.lua Normal file

@ -0,0 +1,9 @@
if vim.g.did_load_commands_plugin then
return
end
vim.g.did_load_commands_plugin = true
local api = vim.api
-- delete current buffer
api.nvim_create_user_command('Q', 'bd % <CR>', {})

163
nvim/plugin/completion.lua Normal file

@ -0,0 +1,163 @@
if vim.g.did_load_completion_plugin then
return
end
vim.g.did_load_completion_plugin = true
local cmp = require('cmp')
local lspkind = require('lspkind')
local luasnip = require('luasnip')
vim.opt.completeopt = { 'menu', 'menuone', 'noselect' }
local function has_words_before()
local unpack_ = unpack or table.unpack
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
---@param source string|table
local function complete_with_source(source)
if type(source) == 'string' then
cmp.complete { config = { sources = { { name = source } } } }
elseif type(source) == 'table' then
cmp.complete { config = { sources = { source } } }
end
end
cmp.setup {
completion = {
completeopt = 'menu,menuone,noinsert',
-- autocomplete = false,
},
formatting = {
format = lspkind.cmp_format {
mode = 'symbol_text',
with_text = true,
maxwidth = 50, -- prevent the popup from showing more than provided characters (e.g 50 will not show more than 50 characters)
ellipsis_char = '...', -- when popup menu exceed maxwidth, the truncated part would show ellipsis_char instead (must define maxwidth first)
menu = {
buffer = '[BUF]',
nvim_lsp = '[LSP]',
nvim_lsp_signature_help = '[LSP]',
nvim_lsp_document_symbol = '[LSP]',
nvim_lua = '[API]',
path = '[PATH]',
luasnip = '[SNIP]',
},
},
},
snippet = {
expand = function(args)
require('luasnip').lsp_expand(args.body) -- For `luasnip` users.
end,
},
mapping = {
['<C-b>'] = cmp.mapping(function(_)
if cmp.visible() then
cmp.scroll_docs(-4)
else
complete_with_source('buffer')
end
end, { 'i', 'c', 's' }),
['<C-f>'] = cmp.mapping(function(_)
if cmp.visible() then
cmp.scroll_docs(4)
else
complete_with_source('path')
end
end, { 'i', 'c', 's' }),
['<C-n>'] = cmp.mapping(function(fallback)
if cmp.visible() then
cmp.select_next_item()
-- expand_or_jumpable(): Jump outside the snippet region
-- expand_or_locally_jumpable(): Only jump inside the snippet region
elseif luasnip.expand_or_locally_jumpable() then
luasnip.expand_or_jump()
elseif has_words_before() then
cmp.complete()
else
fallback()
end
end, { 'i', 'c', 's' }),
['<C-p>'] = cmp.mapping(function(fallback)
if cmp.visible() then
cmp.select_prev_item()
elseif luasnip.jumpable(-1) then
luasnip.jump(-1)
else
fallback()
end
end, { 'i', 'c', 's' }),
-- toggle completion
['<C-e>'] = cmp.mapping(function(_)
if cmp.visible() then
cmp.close()
else
cmp.complete()
end
end, { 'i', 'c', 's' }),
['<C-y>'] = cmp.mapping.confirm {
select = true,
},
},
sources = cmp.config.sources {
-- The insertion order influences the priority of the sources
{ name = 'nvim_lsp', keyword_length = 3 },
{ name = 'nvim_lsp_signature_help', keyword_length = 3 },
{ name = 'buffer' },
{ name = 'path' },
},
enabled = function()
return vim.bo[0].buftype ~= 'prompt'
end,
experimental = {
native_menu = false,
ghost_text = true,
},
}
cmp.setup.filetype('lua', {
sources = cmp.config.sources {
{ name = 'nvim_lua' },
{ name = 'nvim_lsp', keyword_length = 3 },
{ name = 'path' },
},
})
-- Use buffer source for `/` and `?` (if you enabled `native_menu`, this won't work anymore).
cmp.setup.cmdline({ '/', '?' }, {
mapping = cmp.mapping.preset.cmdline(),
sources = {
{ name = 'nvim_lsp_document_symbol', keyword_length = 3 },
{ name = 'buffer' },
{ name = 'cmdline_history' },
},
view = {
entries = { name = 'wildmenu', separator = '|' },
},
})
-- Use cmdline & path source for ':' (if you enabled `native_menu`, this won't work anymore).
cmp.setup.cmdline(':', {
mapping = cmp.mapping.preset.cmdline(),
sources = cmp.config.sources {
{ name = 'cmdline' },
{ name = 'cmdline_history' },
{ name = 'path' },
},
})
vim.keymap.set({ 'i', 'c', 's' }, '<C-n>', cmp.complete, { noremap = false, desc = '[cmp] complete' })
vim.keymap.set({ 'i', 'c', 's' }, '<C-f>', function()
complete_with_source('path')
end, { noremap = false, desc = '[cmp] path' })
vim.keymap.set({ 'i', 'c', 's' }, '<C-o>', function()
complete_with_source('nvim_lsp')
end, { noremap = false, desc = '[cmp] lsp' })
vim.keymap.set({ 'c' }, '<C-h>', function()
complete_with_source('cmdline_history')
end, { noremap = false, desc = '[cmp] cmdline history' })
vim.keymap.set({ 'c' }, '<C-c>', function()
complete_with_source('cmdline')
end, { noremap = false, desc = '[cmp] cmdline' })

11
nvim/plugin/diffview.lua Normal file

@ -0,0 +1,11 @@
if vim.g.did_load_diffview_plugin then
return
end
vim.g.did_load_diffview_plugin = true
vim.keymap.set('n', '<leader>gfb', function()
vim.cmd.DiffviewFileHistory(vim.api.nvim_buf_get_name(0))
end, { desc = 'diffview [g]it [f]ile history (current [b]uffer)' })
vim.keymap.set('n', '<leader>gfc', vim.cmd.DiffviewFileHistory, { desc = 'diffview [g]it [f]ile history ([c]wd)' })
vim.keymap.set('n', '<leader>gd', vim.cmd.DiffviewOpen, { desc = '[g]it [d]iffview open' })
vim.keymap.set('n', '<leader>gft', vim.cmd.DiffviewToggleFiles, { desc = '[g]it [d]iffview [f]iles [t]oggle' })

10
nvim/plugin/eyeliner.lua Normal file

@ -0,0 +1,10 @@
if vim.g.did_load_eyeliner_plugin then
return
end
vim.g.did_load_eyeliner_plugin = true
-- Highlights unique characters for f/F and t/T motions
require('eyeliner').setup {
highlight_on_key = true, -- show highlights only after key press
dim = true, -- dim all other characters
}

66
nvim/plugin/gitsigns.lua Normal file

@ -0,0 +1,66 @@
if vim.g.did_load_gitsigns_plugin then
return
end
vim.g.did_load_gitsigns_plugin = true
vim.schedule(function()
require('gitsigns').setup {
current_line_blame = false,
current_line_blame_opts = {
ignore_whitespace = true,
},
on_attach = function(bufnr)
local gs = package.loaded.gitsigns
local function map(mode, l, r, opts)
opts = opts or {}
opts.buffer = bufnr
vim.keymap.set(mode, l, r, opts)
end
-- Navigation
map('n', ']g', function()
if vim.wo.diff then
return ']g'
end
vim.schedule(function()
gs.next_hunk()
end)
return '<Ignore>'
end, { expr = true, desc = '[g]it next hunk' })
map('n', '[g', function()
if vim.wo.diff then
return '[g'
end
vim.schedule(function()
gs.prev_hunk()
end)
return '<Ignore>'
end, { expr = true, desc = '[g]it previous hunk' })
-- Actions
map({ 'n', 'v' }, '<leader>hs', function()
vim.cmd.Gitsigns('stage_hunk')
end, { desc = 'git [h]unk [s]tage' })
map({ 'n', 'v' }, '<leader>hr', function()
vim.cmd.Gitsigns('reset_hunk')
end, { desc = 'git [h]unk [r]eset' })
map('n', '<leader>hS', gs.stage_buffer, { desc = 'git stage buffer' })
map('n', '<leader>hu', gs.undo_stage_hunk, { desc = 'git [h]unk [u]ndo stage' })
map('n', '<leader>hR', gs.reset_buffer, { desc = 'git [h] buffer [R]eset' })
map('n', '<leader>hp', gs.preview_hunk, { desc = 'git [h]unk [p]review' })
map('n', '<leader>hb', function()
gs.blame_line { full = true }
end, { desc = 'git [h] [b]lame line (full)' })
map('n', '<leader>glb', gs.toggle_current_line_blame, { desc = '[g]it toggle current [l]ine [b]lame' })
map('n', '<leader>hd', gs.diffthis, { desc = 'git [h] [d]iff this' })
map('n', '<leader>hD', function()
gs.diffthis('~')
end, { desc = 'git [h] [D]iff ~' })
map('n', '<leader>td', gs.toggle_deleted, { desc = 'git [t]oggle [d]eleted' })
-- Text object
map({ 'o', 'x' }, 'ih', ':<C-U>Gitsigns select_hunk<CR>', { desc = 'git stage buffer' })
end,
}
end)

200
nvim/plugin/keymaps.lua Normal file

@ -0,0 +1,200 @@
if vim.g.did_load_keymaps_plugin then
return
end
vim.g.did_load_keymaps_plugin = true
local api = vim.api
local fn = vim.fn
local keymap = vim.keymap
local diagnostic = vim.diagnostic
-- Yank from current position till end of current line
keymap.set('n', 'Y', 'y$', { silent = true, desc = '[Y]ank to end of line' })
-- Buffer list navigation
keymap.set('n', '[b', vim.cmd.bprevious, { silent = true, desc = 'previous [b]uffer' })
keymap.set('n', ']b', vim.cmd.bnext, { silent = true, desc = 'next [b]uffer' })
keymap.set('n', '[B', vim.cmd.bfirst, { silent = true, desc = 'first [B]uffer' })
keymap.set('n', ']B', vim.cmd.blast, { silent = true, desc = 'last [B]uffer' })
-- Toggle the quickfix list (only opens if it is populated)
local function toggle_qf_list()
local qf_exists = false
for _, win in pairs(fn.getwininfo() or {}) do
if win['quickfix'] == 1 then
qf_exists = true
end
end
if qf_exists == true then
vim.cmd.cclose()
return
end
if not vim.tbl_isempty(vim.fn.getqflist()) then
vim.cmd.copen()
end
end
keymap.set('n', '<C-c>', toggle_qf_list, { desc = 'toggle quickfix list' })
local function try_fallback_notify(opts)
local success, _ = pcall(opts.try)
if success then
return
end
success, _ = pcall(opts.fallback)
if success then
return
end
vim.notify(opts.notify, vim.log.levels.INFO)
end
-- Cycle the quickfix and location lists
local function cleft()
try_fallback_notify {
try = vim.cmd.cprev,
fallback = vim.cmd.clast,
notify = 'Quickfix list is empty!',
}
end
local function cright()
try_fallback_notify {
try = vim.cmd.cnext,
fallback = vim.cmd.cfirst,
notify = 'Quickfix list is empty!',
}
end
keymap.set('n', '[c', cleft, { silent = true, desc = '[c]ycle quickfix left' })
keymap.set('n', ']c', cright, { silent = true, desc = '[c]ycle quickfix right' })
keymap.set('n', '[C', vim.cmd.cfirst, { silent = true, desc = 'first quickfix entry' })
keymap.set('n', ']C', vim.cmd.clast, { silent = true, desc = 'last quickfix entry' })
local function lleft()
try_fallback_notify {
try = vim.cmd.lprev,
fallback = vim.cmd.llast,
notify = 'Location list is empty!',
}
end
local function lright()
try_fallback_notify {
try = vim.cmd.lnext,
fallback = vim.cmd.lfirst,
notify = 'Location list is empty!',
}
end
keymap.set('n', '[l', lleft, { silent = true, desc = 'cycle [l]oclist left' })
keymap.set('n', ']l', lright, { silent = true, desc = 'cycle [l]oclist right' })
keymap.set('n', '[L', vim.cmd.lfirst, { silent = true, desc = 'first [L]oclist entry' })
keymap.set('n', ']L', vim.cmd.llast, { silent = true, desc = 'last [L]oclist entry' })
-- Resize vertical splits
local toIntegral = math.ceil
keymap.set('n', '<leader>w+', function()
local curWinWidth = api.nvim_win_get_width(0)
api.nvim_win_set_width(0, toIntegral(curWinWidth * 3 / 2))
end, { silent = true, desc = 'inc window [w]idth' })
keymap.set('n', '<leader>w-', function()
local curWinWidth = api.nvim_win_get_width(0)
api.nvim_win_set_width(0, toIntegral(curWinWidth * 2 / 3))
end, { silent = true, desc = 'dec window [w]idth' })
keymap.set('n', '<leader>h+', function()
local curWinHeight = api.nvim_win_get_height(0)
api.nvim_win_set_height(0, toIntegral(curWinHeight * 3 / 2))
end, { silent = true, desc = 'inc window [h]eight' })
keymap.set('n', '<leader>h-', function()
local curWinHeight = api.nvim_win_get_height(0)
api.nvim_win_set_height(0, toIntegral(curWinHeight * 2 / 3))
end, { silent = true, desc = 'dec window [h]eight' })
-- Close floating windows [Neovim 0.10 and above]
keymap.set('n', '<leader>fq', function()
vim.cmd('fclose!')
end, { silent = true, desc = '[f]loating windows: [q]uit/close all' })
-- Remap Esc to switch to normal mode and Ctrl-Esc to pass Esc to terminal
keymap.set('t', '<Esc>', '<C-\\><C-n>', { desc = 'switch to normal mode' })
keymap.set('t', '<C-Esc>', '<Esc>', { desc = 'send Esc to terminal' })
-- Shortcut for expanding to current buffer's directory in command mode
keymap.set('c', '%%', function()
if fn.getcmdtype() == ':' then
return fn.expand('%:h') .. '/'
else
return '%%'
end
end, { expr = true, desc = "expand to current buffer's directory" })
keymap.set('n', '<space>tn', vim.cmd.tabnew, { desc = '[t]ab: [n]ew' })
keymap.set('n', '<space>tq', vim.cmd.tabclose, { desc = '[t]ab: [q]uit/close' })
local severity = diagnostic.severity
keymap.set('n', '<space>e', function()
local _, winid = diagnostic.open_float(nil, { scope = 'line' })
if not winid then
vim.notify('no diagnostics found', vim.log.levels.INFO)
return
end
vim.api.nvim_win_set_config(winid or 0, { focusable = true })
end, { noremap = true, silent = true, desc = 'diagnostics floating window' })
keymap.set('n', '[d', diagnostic.goto_prev, { noremap = true, silent = true, desc = 'previous [d]iagnostic' })
keymap.set('n', ']d', diagnostic.goto_next, { noremap = true, silent = true, desc = 'next [d]iagnostic' })
keymap.set('n', '[e', function()
diagnostic.goto_prev {
severity = severity.ERROR,
}
end, { noremap = true, silent = true, desc = 'previous [e]rror diagnostic' })
keymap.set('n', ']e', function()
diagnostic.goto_next {
severity = severity.ERROR,
}
end, { noremap = true, silent = true, desc = 'next [e]rror diagnostic' })
keymap.set('n', '[w', function()
diagnostic.goto_prev {
severity = severity.WARN,
}
end, { noremap = true, silent = true, desc = 'previous [w]arning diagnostic' })
keymap.set('n', ']w', function()
diagnostic.goto_next {
severity = severity.WARN,
}
end, { noremap = true, silent = true, desc = 'next [w]arning diagnostic' })
keymap.set('n', '[h', function()
diagnostic.goto_prev {
severity = severity.HINT,
}
end, { noremap = true, silent = true, desc = 'previous [h]int diagnostic' })
keymap.set('n', ']h', function()
diagnostic.goto_next {
severity = severity.HINT,
}
end, { noremap = true, silent = true, desc = 'next [h]int diagnostic' })
local function toggle_spell_check()
---@diagnostic disable-next-line: param-type-mismatch
vim.opt.spell = not (vim.opt.spell:get())
end
keymap.set('n', '<leader>S', toggle_spell_check, { noremap = true, silent = true, desc = 'toggle [S]pell' })
keymap.set('n', '<C-d>', '<C-d>zz', { desc = 'move [d]own half-page and center' })
keymap.set('n', '<C-u>', '<C-u>zz', { desc = 'move [u]p half-page and center' })
keymap.set('n', '<C-f>', '<C-f>zz', { desc = 'move DOWN [f]ull-page and center' })
keymap.set('n', '<C-b>', '<C-b>zz', { desc = 'move UP full-page and center' })
--- Disabled keymaps [enable at your own risk]
-- Automatic management of search highlight
-- XXX: This is not so nice if you use j/k for navigation
-- (you should be using <C-d>/<C-u> and relative line numbers instead ;)
--
-- local auto_hlsearch_namespace = vim.api.nvim_create_namespace('auto_hlsearch')
-- vim.on_key(function(char)
-- if vim.fn.mode() == 'n' then
-- vim.opt.hlsearch = vim.tbl_contains({ '<CR>', 'n', 'N', '*', '#', '?', '/' }, vim.fn.keytrans(char))
-- end
-- end, auto_hlsearch_namespace)

87
nvim/plugin/lualine.lua Normal file

@ -0,0 +1,87 @@
if vim.g.did_load_lualine_plugin then
return
end
vim.g.did_load_lualine_plugin = true
local navic = require('nvim-navic')
navic.setup {}
---Indicators for special modes,
---@return string status
local function extra_mode_status()
-- recording macros
local reg_recording = vim.fn.reg_recording()
if reg_recording ~= '' then
return ' @' .. reg_recording
end
-- executing macros
local reg_executing = vim.fn.reg_executing()
if reg_executing ~= '' then
return ' @' .. reg_executing
end
-- ix mode (<C-x> in insert mode to trigger different builtin completion sources)
local mode = vim.api.nvim_get_mode().mode
if mode == 'ix' then
return '^X: (^]^D^E^F^I^K^L^N^O^Ps^U^V^Y)'
end
return ''
end
require('lualine').setup {
globalstatus = true,
sections = {
lualine_c = {
-- nvim-navic
{ navic.get_location, cond = navic.is_available },
},
lualine_z = {
-- (see above)
{ extra_mode_status },
},
},
options = {
theme = 'auto',
},
-- Example top tabline configuration (this may clash with other plugins)
-- tabline = {
-- lualine_a = {
-- {
-- 'tabs',
-- mode = 1,
-- },
-- },
-- lualine_b = {
-- {
-- 'buffers',
-- show_filename_only = true,
-- show_bufnr = true,
-- mode = 4,
-- filetype_names = {
-- TelescopePrompt = 'Telescope',
-- dashboard = 'Dashboard',
-- fzf = 'FZF',
-- },
-- buffers_color = {
-- -- Same values as the general color option can be used here.
-- active = 'lualine_b_normal', -- Color for active buffer.
-- inactive = 'lualine_b_inactive', -- Color for inactive buffer.
-- },
-- },
-- },
-- lualine_c = {},
-- lualine_x = {},
-- lualine_y = {},
-- lualine_z = {},
-- },
winbar = {
lualine_z = {
{
'filename',
path = 1,
file_status = true,
newfile_status = true,
},
},
},
extensions = { 'fugitive', 'fzf', 'toggleterm', 'quickfix' },
}

29
nvim/plugin/neogit.lua Normal file

@ -0,0 +1,29 @@
if vim.g.did_load_neogit_plugin then
return
end
vim.g.did_load_neogit_plugin = true
local neogit = require('neogit')
neogit.setup {
disable_builtin_notifications = true,
disable_insert_on_commit = 'auto',
integrations = {
diffview = true,
telescope = true,
fzf_lua = true,
},
sections = {
---@diagnostic disable-next-line: missing-fields
recent = {
folded = false,
},
},
}
vim.keymap.set('n', '<leader>go', neogit.open, { noremap = true, silent = true, desc = 'neo[g]it [o]pen' })
vim.keymap.set('n', '<leader>gs', function()
neogit.open { kind = 'auto' }
end, { noremap = true, silent = true, desc = 'neo[g]it open [s]plit' })
vim.keymap.set('n', '<leader>gc', function()
neogit.open { 'commit' }
end, { noremap = true, silent = true, desc = 'neo[g]it [c]ommit' })

10
nvim/plugin/plugins.lua Normal file

@ -0,0 +1,10 @@
if vim.g.did_load_plugins_plugin then
return
end
vim.g.did_load_plugins_plugin = true
-- many plugins annoyingly require a call to a 'setup' function to be loaded,
-- even with default configs
require('nvim-surround').setup()
require('which-key').setup()

18
nvim/plugin/statuscol.lua Normal file

@ -0,0 +1,18 @@
if vim.g.did_load_statuscol_plugin then
return
end
vim.g.did_load_statuscol_plugin = true
local builtin = require('statuscol.builtin')
require('statuscol').setup {
setopt = true,
relculright = true,
segments = {
{ text = { '%s' }, click = 'v:lua.ScSa' },
{
text = { builtin.lnumfunc, ' ' },
condition = { true, builtin.not_empty },
click = 'v:lua.ScLa',
},
},
}

159
nvim/plugin/telescope.lua Normal file

@ -0,0 +1,159 @@
if vim.g.did_load_telescope_plugin then
return
end
vim.g.did_load_telescope_plugin = true
local telescope = require('telescope')
local actions = require('telescope.actions')
local builtin = require('telescope.builtin')
local layout_config = {
vertical = {
width = function(_, max_columns)
return math.floor(max_columns * 0.99)
end,
height = function(_, _, max_lines)
return math.floor(max_lines * 0.99)
end,
prompt_position = 'bottom',
preview_cutoff = 0,
},
}
-- Fall back to find_files if not in a git repo
local project_files = function()
local opts = {} -- define here if you want to define something
local ok = pcall(builtin.git_files, opts)
if not ok then
builtin.find_files(opts)
end
end
---@param picker function the telescope picker to use
local function grep_current_file_type(picker)
local current_file_ext = vim.fn.expand('%:e')
local additional_vimgrep_arguments = {}
if current_file_ext ~= '' then
additional_vimgrep_arguments = {
'--type',
current_file_ext,
}
end
local conf = require('telescope.config').values
picker {
vimgrep_arguments = vim.tbl_flatten {
conf.vimgrep_arguments,
additional_vimgrep_arguments,
},
}
end
--- Grep the string under the cursor, filtering for the current file type
local function grep_string_current_file_type()
grep_current_file_type(builtin.grep_string)
end
--- Live grep, filtering for the current file type
local function live_grep_current_file_type()
grep_current_file_type(builtin.live_grep)
end
--- Like live_grep, but fuzzy (and slower)
local function fuzzy_grep(opts)
opts = vim.tbl_extend('error', opts or {}, { search = '', prompt_title = 'Fuzzy grep' })
builtin.grep_string(opts)
end
local function fuzzy_grep_current_file_type()
grep_current_file_type(fuzzy_grep)
end
vim.keymap.set('n', '<leader>tp', function()
builtin.find_files()
end, { desc = '[t]elescope find files - ctrl[p] style' })
vim.keymap.set('n', '<M-p>', builtin.oldfiles, { desc = '[telescope] old files' })
vim.keymap.set('n', '<C-g>', builtin.live_grep, { desc = '[telescope] live grep' })
vim.keymap.set('n', '<leader>tf', fuzzy_grep, { desc = '[t]elescope [f]uzzy grep' })
vim.keymap.set('n', '<M-f>', fuzzy_grep_current_file_type, { desc = '[telescope] fuzzy grep filetype' })
vim.keymap.set('n', '<M-g>', live_grep_current_file_type, { desc = '[telescope] live grep filetype' })
vim.keymap.set(
'n',
'<leader>t*',
grep_string_current_file_type,
{ desc = '[t]elescope grep current string [*] in current filetype' }
)
vim.keymap.set('n', '<leader>*', builtin.grep_string, { desc = '[telescope] grep current string [*]' })
vim.keymap.set('n', '<leader>tg', project_files, { desc = '[t]elescope project files [g]' })
vim.keymap.set('n', '<leader>tc', builtin.quickfix, { desc = '[t]elescope quickfix list [c]' })
vim.keymap.set('n', '<leader>tq', builtin.command_history, { desc = '[t]elescope command history [q]' })
vim.keymap.set('n', '<leader>tl', builtin.loclist, { desc = '[t]elescope [l]oclist' })
vim.keymap.set('n', '<leader>tr', builtin.registers, { desc = '[t]elescope [r]egisters' })
vim.keymap.set('n', '<leader>tbb', builtin.buffers, { desc = '[t]elescope [b]uffers [b]' })
vim.keymap.set(
'n',
'<leader>tbf',
builtin.current_buffer_fuzzy_find,
{ desc = '[t]elescope current [b]uffer [f]uzzy find' }
)
vim.keymap.set('n', '<leader>td', builtin.lsp_document_symbols, { desc = '[t]elescope lsp [d]ocument symbols' })
vim.keymap.set(
'n',
'<leader>to',
builtin.lsp_dynamic_workspace_symbols,
{ desc = '[t]elescope lsp dynamic w[o]rkspace symbols' }
)
telescope.setup {
defaults = {
path_display = {
'truncate',
},
layout_strategy = 'vertical',
layout_config = layout_config,
mappings = {
i = {
['<C-q>'] = actions.send_to_qflist,
['<C-l>'] = actions.send_to_loclist,
-- ['<esc>'] = actions.close,
['<C-s>'] = actions.cycle_previewers_next,
['<C-a>'] = actions.cycle_previewers_prev,
},
n = {
q = actions.close,
},
},
preview = {
treesitter = true,
},
history = {
path = vim.fn.stdpath('data') .. '/telescope_history.sqlite3',
limit = 1000,
},
color_devicons = true,
set_env = { ['COLORTERM'] = 'truecolor' },
prompt_prefix = '',
selection_caret = ' ',
entry_prefix = ' ',
initial_mode = 'insert',
vimgrep_arguments = {
'rg',
'-L',
'--color=never',
'--no-heading',
'--with-filename',
'--line-number',
'--column',
'--smart-case',
},
},
extensions = {
fzy_native = {
override_generic_sorter = false,
override_file_sorter = true,
},
},
}
telescope.load_extension('fzy_native')
-- telescope.load_extension('smart_history')

@ -0,0 +1,97 @@
if vim.g.did_load_treesitter_plugin then
return
end
vim.g.did_load_treesitter_plugin = true
local configs = require('nvim-treesitter.configs')
vim.g.skip_ts_context_comment_string_module = true
---@diagnostic disable-next-line: missing-fields
configs.setup {
-- ensure_installed = 'all',
-- auto_install = false, -- Do not automatically install missing parsers when entering buffer
highlight = {
enable = true,
disable = function(_, buf)
local max_filesize = 100 * 1024 -- 100 KiB
local ok, stats = pcall(vim.loop.fs_stat, vim.api.nvim_buf_get_name(buf))
if ok and stats and stats.size > max_filesize then
return true
end
end,
},
textobjects = {
select = {
enable = true,
-- Automatically jump forward to textobject, similar to targets.vim
lookahead = true,
keymaps = {
['af'] = '@function.outer',
['if'] = '@function.inner',
['ac'] = '@class.outer',
['ic'] = '@class.inner',
['aC'] = '@call.outer',
['iC'] = '@call.inner',
['a#'] = '@comment.outer',
['i#'] = '@comment.outer',
['ai'] = '@conditional.outer',
['ii'] = '@conditional.outer',
['al'] = '@loop.outer',
['il'] = '@loop.inner',
['aP'] = '@parameter.outer',
['iP'] = '@parameter.inner',
},
selection_modes = {
['@parameter.outer'] = 'v', -- charwise
['@function.outer'] = 'V', -- linewise
['@class.outer'] = '<c-v>', -- blockwise
},
},
swap = {
enable = true,
swap_next = {
['<leader>a'] = '@parameter.inner',
},
swap_previous = {
['<leader>A'] = '@parameter.inner',
},
},
move = {
enable = true,
set_jumps = true, -- whether to set jumps in the jumplist
goto_next_start = {
[']m'] = '@function.outer',
[']P'] = '@parameter.outer',
},
goto_next_end = {
[']m'] = '@function.outer',
[']P'] = '@parameter.outer',
},
goto_previous_start = {
['[m'] = '@function.outer',
['[P'] = '@parameter.outer',
},
goto_previous_end = {
['[m'] = '@function.outer',
['[P'] = '@parameter.outer',
},
},
nsp_interop = {
enable = true,
peek_definition_code = {
['df'] = '@function.outer',
['dF'] = '@class.outer',
},
},
},
}
require('treesitter-context').setup {
max_lines = 3,
}
require('ts_context_commentstring').setup()
-- Tree-sitter based folding
-- vim.opt.foldmethod = 'expr'
vim.opt.foldexpr = 'nvim_treesitter#foldexpr()'