Compare commits

..

No commits in common. "c0b2ec9e0153789f125f838ba60710488960452b" and "c3ee469ed568578632c1127dc391774edd2c637b" have entirely different histories.

11 changed files with 348 additions and 301 deletions

24
LICENSE
View file

@ -1,24 +0,0 @@
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <https://unlicense.org>

View file

@ -1,59 +1,7 @@
# viminal2 # neovim config in progress
This is my second attempt at creating a Neovim configuration intended for ```lua
NixOS. The [first](https://github.com/youwen5/viminal) was configured using local test = test
[Nixvim](https://github.com/nix-community/nixvim). This mostly worked, except
you often had to escape into raw Lua strings to get precise customization.
Enter [nixCats](https://github.com/BirdeeHub/nixCats-nvim). It provides the
tools needed to mix Nix and Lua in your configurations. For advanced users,
configuring Neovim with Nix expressions doesn't really make sense, since the
whole point of Neovim is to be extremely hackable ("hyperextensible") and it
provides ergonomic Lua bindings for that purpose.
This setup provides not just a usable but a "great" Neovim configuration for
NixOS. That is, it has features that make it _better_ on _all distros_, not
just on NixOS. Why? Instead of using ad-hoc package managers written for Neovim
like `lazy.nvim`, `Mason`, etc, all external dependencies are fetched and built
by Nix. Mason and lazy are good for what they are meant for, but Nix can make
strong guarantees that practically no other package management tool can,
period. Namely, it can ensure the presence of runtime dependencies (like `rg`,
`fd`, LSPs, formatters, etc), and guarantee builds are successful. If your
editor works today, it'll work tomorrow. It won't break from system upgrades or
files randomly getting broken. Nix is purpose built to handle pretty much
everything that a text editor's plugins shouldn't, and it's a perfect match.
## Try it
You can test drive the configuration (even if you aren't on NixOS) if you have
the Nix package manager available (with flakes).
```bash
nix run 'github:youwen5/viminal2'
``` ```
## Design [test](lsdjkfsdf)
As this is my second configuration from scratch (if you count Nixvim as "from
scratch"), I wanted to do it right (so I could stop wasting my time configuring
my editor).
For completion, I use [blink.cmp](https://github.com/Saghen/blink.cmp). This
plugin is much, much faster than `nvim-cmp` thanks to optimized `SIMD`
instructions (and Rust), has a better fuzzy search, and comes with more out of
the box.
`lz.n` is used to load plugins after they have been downloaded by Nix. `lz.n`
is a lazy loading plugin by the authors of `Rocks.nvim`, a plugin manager based
on Luarocks. As they are designed to be decoupled, `Rocks.nvim` can simply be
replaced by Nix. Most plugins are lazy loaded, but generally performance is
good enough that it is not even strictly necessary.
The keybinds have gotten a lot more idiosyncratic. Instead of focusing on
mnemonic keys that can be easily committed to memory, highly efficient ones
were chosen instead.
## License
Feel free to copy any code from here or use it as an example. It's [public
domain](./LICENSE).

150
flake.nix
View file

@ -1,3 +1,22 @@
# Copyright (c) 2023 BirdeeHub
# Licensed under the MIT license
# This is an empty nixCats config.
# you may import this template directly into your nvim folder
# and then add plugins to categories here,
# and call the plugins with their default functions
# within your lua, rather than through the nvim package manager's method.
# Use the help, and the example repository https://github.com/BirdeeHub/nixCats-nvim
# It allows for easy adoption of nix,
# while still providing all the extra nix features immediately.
# Configure in lua, check for a few categories, set a few settings,
# output packages with combinations of those categories and settings.
# All the same options you make here will be automatically exported in a form available
# in home manager and in nixosModules, as well as from other flakes.
# each section is tagged with its relevant help section.
{ {
description = "A Lua-natic's neovim flake, with extra cats! nixCats!"; description = "A Lua-natic's neovim flake, with extra cats! nixCats!";
@ -19,7 +38,20 @@
url = "github:linrongbin16/lsp-progress.nvim"; url = "github:linrongbin16/lsp-progress.nvim";
flake = false; flake = false;
}; };
# see :help nixCats.flake.inputs
# If you want your plugin to be loaded by the standard overlay,
# i.e. if it wasnt on nixpkgs, but doesnt have an extra build step.
# Then you should name it "plugins-something"
# If you wish to define a custom build step not handled by nixpkgs,
# then you should name it in a different format, and deal with that in the
# overlay defined for custom builds in the overlays directory.
# for specific tags, branches and commits, see:
# https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-flake.html#examples
}; };
# see :help nixCats.flake.outputs
outputs = outputs =
{ {
self, self,
@ -31,14 +63,33 @@
inherit (nixCats) utils; inherit (nixCats) utils;
luaPath = "${./.}"; luaPath = "${./.}";
forEachSystem = utils.eachSystem nixpkgs.lib.platforms.all; forEachSystem = utils.eachSystem nixpkgs.lib.platforms.all;
# the following extra_pkg_config contains any values
# which you want to pass to the config set of nixpkgs
# import nixpkgs { config = extra_pkg_config; inherit system; }
# will not apply to module imports
# as that will have your system values
extra_pkg_config = { extra_pkg_config = {
# allowUnfree = true; # allowUnfree = true;
}; };
# sometimes our overlays require a ${system} to access the overlay.
# management of this variable is one of the harder parts of using flakes.
# so I have done it here in an interesting way to keep it out of the way.
# First, we will define just our overlays per system.
# later we will pass them into the builder, and the resulting pkgs set
# will get passed to the categoryDefinitions and packageDefinitions
# which follow this section.
# this allows you to use ${pkgs.system} whenever you want in those sections
# without fear.
inherit inherit
(forEachSystem ( (forEachSystem (
system: system:
let let
dependencyOverlays = (import ./nix/overlays.nix) ++ [ # see :help nixCats.flake.outputs.overlays
dependencyOverlays = # (import ./overlays inputs) ++
[
# This overlay grabs all the inputs named in the format # This overlay grabs all the inputs named in the format
# `plugins-<pluginName>` # `plugins-<pluginName>`
# Once we add this overlay to our nixpkgs, we are able to # Once we add this overlay to our nixpkgs, we are able to
@ -68,9 +119,27 @@
... ...
}@packageDef: }@packageDef:
{ {
# lspsAndRuntimeDeps: this section is for dependencies that should be # to define and use a new category, simply add a new list to a set here,
# available at RUN TIME for plugins. Will be available to PATH within # and later, you will include categoryname = true; in the set you
# neovim terminal this includes LSPs # provide when you build the package using this builder function.
# see :help nixCats.flake.outputs.packageDefinitions for info on that section.
# propagatedBuildInputs:
# this section is for dependencies that should be available
# at BUILD TIME for plugins. WILL NOT be available to PATH
# However, they WILL be available to the shell
# and neovim path when using nix develop
propagatedBuildInputs = {
general =
with pkgs;
[
];
};
# lspsAndRuntimeDeps:
# this section is for dependencies that should be available
# at RUN TIME for plugins. Will be available to PATH within neovim terminal
# this includes LSPs
lspsAndRuntimeDeps = { lspsAndRuntimeDeps = {
general = with pkgs; [ general = with pkgs; [
# essential # essential
@ -88,8 +157,6 @@
rustfmt rustfmt
black black
stylua stylua
marksman
tinymist
]; ];
}; };
@ -121,7 +188,6 @@
vim vim
bash bash
make make
gitcommit
]) ])
)) ))
]; ];
@ -177,19 +243,67 @@
# libgit2 # libgit2
]; ];
}; };
# environmentVariables:
# this section is for environmentVariables that should be available
# at RUN TIME for plugins. Will be available to path within neovim terminal
# environmentVariables = {
# test = {
# CATTESTVAR = "It worked!";
# };
# };
# If you know what these are, you can provide custom ones by category here.
# If you dont, check this link out:
# https://github.com/NixOS/nixpkgs/blob/master/pkgs/build-support/setup-hooks/make-wrapper.sh
# extraWrapperArgs = {
# test = [
# ''--set CATTESTVAR2 "It worked again!"''
# ];
# };
# lists of the functions you would have passed to
# python.withPackages or lua.withPackages
# get the path to this python environment
# in your lua config via
# vim.g.python3_host_prog
# or run from nvim terminal via :!<packagename>-python3
# extraPython3Packages = {
# test = (_: [ ]);
# };
# # populates $LUA_PATH and $LUA_CPATH
# extraLuaPackages = {
# test = [ (_: [ ]) ];
# };
}; };
# And then build a package with specific categories from above here:
# All categories you wish to include must be marked true,
# but false may be omitted.
# This entire set is also passed to nixCats for querying within the lua.
# see :help nixCats.flake.outputs.packageDefinitions
packageDefinitions = { packageDefinitions = {
# These are the names of your packages
# you can include as many as you wish.
nvim = nvim =
{ pkgs, ... }: { pkgs, ... }:
{ {
# they contain a settings set defined above
# see :help nixCats.flake.outputs.settings
settings = { settings = {
wrapRc = true; wrapRc = true;
# IMPORTANT:
# your alias may not conflict with your other packages.
aliases = [ aliases = [
"vim" "vim"
"vi" "vi"
]; ];
neovim-unwrapped = pkgs.neovim-unwrapped; # neovim-unwrapped = inputs.neovim-nightly-overlay.packages.${pkgs.system}.neovim;
}; };
# and a set of categories that you want
# (and other information to pass to lua)
categories = { categories = {
general = true; general = true;
gitPlugins = true; gitPlugins = true;
@ -201,8 +315,12 @@
}; };
}; };
}; };
# In this section, the main thing you will need to do is change the default package name
# to the name of the packageDefinitions entry you wish to use as the default.
defaultPackageName = "nvim"; defaultPackageName = "nvim";
in in
# see :help nixCats.flake.outputs.exports
forEachSystem ( forEachSystem (
system: system:
let let
@ -215,11 +333,20 @@
; ;
} categoryDefinitions packageDefinitions; } categoryDefinitions packageDefinitions;
defaultPackage = nixCatsBuilder defaultPackageName; defaultPackage = nixCatsBuilder defaultPackageName;
# this is just for using utils such as pkgs.mkShell
# The one used to build neovim is resolved inside the builder
# and is passed to our categoryDefinitions and packageDefinitions
pkgs = import nixpkgs { inherit system; }; pkgs = import nixpkgs { inherit system; };
in in
{ {
# these outputs will be wrapped with ${system} by utils.eachSystem
# this will make a package out of each of the packageDefinitions defined above
# and set the default package to the one passed in here.
packages = utils.mkAllWithDefault defaultPackage; packages = utils.mkAllWithDefault defaultPackage;
# choose your package for devShell
# and add whatever else you want in it.
devShells = { devShells = {
default = pkgs.mkShell { default = pkgs.mkShell {
name = defaultPackageName; name = defaultPackageName;
@ -235,10 +362,16 @@
} }
) )
// { // {
# these outputs will be NOT wrapped with ${system}
# this will make an overlay out of each of the packageDefinitions defined above
# and set the default overlay to the one named here.
overlays = utils.makeOverlays luaPath { overlays = utils.makeOverlays luaPath {
inherit nixpkgs dependencyOverlays extra_pkg_config; inherit nixpkgs dependencyOverlays extra_pkg_config;
} categoryDefinitions packageDefinitions defaultPackageName; } categoryDefinitions packageDefinitions defaultPackageName;
# we also export a nixos module to allow reconfiguration from configuration.nix
nixosModules.default = utils.mkNixosModules { nixosModules.default = utils.mkNixosModules {
inherit inherit
defaultPackageName defaultPackageName
@ -250,6 +383,7 @@
nixpkgs nixpkgs
; ;
}; };
# and the same for home manager
homeModule = utils.mkHomeModules { homeModule = utils.mkHomeModules {
inherit inherit
defaultPackageName defaultPackageName

View file

@ -57,5 +57,3 @@ vim.keymap.set({ "n", "v" }, "<leader>cbf", function()
vim.b[0].disable_autoformat = true vim.b[0].disable_autoformat = true
end end
end, { desc = "Disable autoformat on save buffer" }) end, { desc = "Disable autoformat on save buffer" })
vim.keymap.set("i", "<Tab>", require("scripts.intellitab").indent)

View file

@ -24,5 +24,3 @@ lspconfig.lua_ls.setup({
}) })
lspconfig.nixd.setup({}) lspconfig.nixd.setup({})
lspconfig.marksman.setup({})
lspconfig.tinymist.setup({})

View file

@ -1,7 +0,0 @@
return {
"nvim-autopairs",
event = "BufEnter",
after = function()
require("nvim-autopairs").setup()
end,
}

View file

@ -1,60 +0,0 @@
return {
"gitsigns.nvim",
event = "BufEnter",
after = function()
require("gitsigns").setup({
on_attach = function(bufnr)
local gitsigns = require("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", "]c", function()
if vim.wo.diff then
vim.cmd.normal({ "]c", bang = true })
else
gitsigns.nav_hunk("next")
end
end)
map("n", "[c", function()
if vim.wo.diff then
vim.cmd.normal({ "[c", bang = true })
else
gitsigns.nav_hunk("prev")
end
end)
-- Actions
map("n", "<leader>gs", gitsigns.stage_hunk)
map("n", "<leader>gr", gitsigns.reset_hunk)
map("v", "<leader>gs", function()
gitsigns.stage_hunk({ vim.fn.line("."), vim.fn.line("v") })
end)
map("v", "<leader>gr", function()
gitsigns.reset_hunk({ vim.fn.line("."), vim.fn.line("v") })
end)
map("n", "<leader>gS", gitsigns.stage_buffer)
map("n", "<leader>gu", gitsigns.undo_stage_hunk)
map("n", "<leader>gR", gitsigns.reset_buffer)
map("n", "<leader>gp", gitsigns.preview_hunk)
map("n", "<leader>gb", function()
gitsigns.blame_line({ full = true })
end)
map("n", "<leader>gb", gitsigns.toggle_current_line_blame)
map("n", "<leader>gd", gitsigns.diffthis)
map("n", "<leader>gD", function()
gitsigns.diffthis("~")
end)
map("n", "<leader>gtd", gitsigns.toggle_deleted)
-- Text object
map({ "o", "x" }, "ih", ":<C-U>Gitsigns select_hunk<CR>")
end,
})
end,
}

View file

@ -1,51 +0,0 @@
return {
"lsp-progress",
after = function()
require("lsp-progress").setup({
client_format = function(client_name, spinner, series_messages)
if #series_messages == 0 then
return nil
end
return {
name = client_name,
body = spinner .. " " .. table.concat(series_messages, ", "),
}
end,
format = function(client_messages)
--- @param name string
--- @param msg string?
--- @return string
local function stringify(name, msg)
return msg and string.format("%s %s", name, msg) or name
end
local sign = "󰆧" -- nf-fa-gear \uf013
local lsp_clients = vim.lsp.get_clients()
local messages_map = {}
for _, climsg in ipairs(client_messages) do
messages_map[climsg.name] = climsg.body
end
if #lsp_clients > 0 then
table.sort(lsp_clients, function(a, b)
return a.name < b.name
end)
local builder = {}
for _, cli in ipairs(lsp_clients) do
if type(cli) == "table" and type(cli.name) == "string" and string.len(cli.name) > 0 then
if messages_map[cli.name] then
table.insert(builder, stringify(cli.name, messages_map[cli.name]))
else
table.insert(builder, stringify(cli.name))
end
end
end
if #builder > 0 then
return sign .. " " .. table.concat(builder, ", ")
end
end
return ""
end,
})
end,
}

View file

@ -5,10 +5,65 @@ return {
require("plugins.harpoon"), require("plugins.harpoon"),
require("plugins.lualine"), require("plugins.lualine"),
require("plugins.conform"), require("plugins.conform"),
require("plugins.lsp-progress"), {
require("plugins.gitsigns"), "lsp-progress",
require("plugins.autopairs"), after = function()
require("lsp-progress").setup({
client_format = function(client_name, spinner, series_messages)
if #series_messages == 0 then
return nil
end
return {
name = client_name,
body = spinner .. " " .. table.concat(series_messages, ", "),
}
end,
format = function(client_messages)
--- @param name string
--- @param msg string?
--- @return string
local function stringify(name, msg)
return msg and string.format("%s %s", name, msg) or name
end
local sign = "󰆧" -- nf-fa-gear \uf013
local lsp_clients = vim.lsp.get_clients()
local messages_map = {}
for _, climsg in ipairs(client_messages) do
messages_map[climsg.name] = climsg.body
end
if #lsp_clients > 0 then
table.sort(lsp_clients, function(a, b)
return a.name < b.name
end)
local builder = {}
for _, cli in ipairs(lsp_clients) do
if type(cli) == "table" and type(cli.name) == "string" and string.len(cli.name) > 0 then
if messages_map[cli.name] then
table.insert(builder, stringify(cli.name, messages_map[cli.name]))
else
table.insert(builder, stringify(cli.name))
end
end
end
if #builder > 0 then
return sign .. " " .. table.concat(builder, ", ")
end
end
return ""
end,
})
end,
},
{ "telescope-ui-select.nvim", priority = 70 }, { "telescope-ui-select.nvim", priority = 70 },
{
"nvim-autopairs",
event = "BufEnter",
after = function()
require("nvim-autopairs").setup()
end,
},
{ {
"nvim-lspconfig", "nvim-lspconfig",
event = "BufEnter", event = "BufEnter",
@ -56,7 +111,6 @@ return {
}, },
{ {
"typst-preview", "typst-preview",
filetypes = { "*.typ" },
after = function() after = function()
require("typst-preview").setup({ require("typst-preview").setup({
dependencies_bin = { dependencies_bin = {
@ -166,6 +220,66 @@ return {
require("mini.hipatterns").setup() require("mini.hipatterns").setup()
end, end,
}, },
{
"gitsigns.nvim",
event = "BufEnter",
after = function()
require("gitsigns").setup({
on_attach = function(bufnr)
local gitsigns = require("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", "]c", function()
if vim.wo.diff then
vim.cmd.normal({ "]c", bang = true })
else
gitsigns.nav_hunk("next")
end
end)
map("n", "[c", function()
if vim.wo.diff then
vim.cmd.normal({ "[c", bang = true })
else
gitsigns.nav_hunk("prev")
end
end)
-- Actions
map("n", "<leader>gs", gitsigns.stage_hunk)
map("n", "<leader>gr", gitsigns.reset_hunk)
map("v", "<leader>gs", function()
gitsigns.stage_hunk({ vim.fn.line("."), vim.fn.line("v") })
end)
map("v", "<leader>gr", function()
gitsigns.reset_hunk({ vim.fn.line("."), vim.fn.line("v") })
end)
map("n", "<leader>gS", gitsigns.stage_buffer)
map("n", "<leader>gu", gitsigns.undo_stage_hunk)
map("n", "<leader>gR", gitsigns.reset_buffer)
map("n", "<leader>gp", gitsigns.preview_hunk)
map("n", "<leader>gb", function()
gitsigns.blame_line({ full = true })
end)
map("n", "<leader>gb", gitsigns.toggle_current_line_blame)
map("n", "<leader>gd", gitsigns.diffthis)
map("n", "<leader>gD", function()
gitsigns.diffthis("~")
end)
map("n", "<leader>gtd", gitsigns.toggle_deleted)
-- Text object
map({ "o", "x" }, "ih", ":<C-U>Gitsigns select_hunk<CR>")
end,
})
end,
},
{ {
"neogit", "neogit",
cmd = "Neogit", cmd = "Neogit",

View file

@ -24,8 +24,8 @@ local function indent()
local cursor = v.nvim_win_get_cursor(0) local cursor = v.nvim_win_get_cursor(0)
local line = v.nvim_buf_get_lines(0, cursor[1] - 1, cursor[1], false)[1] local line = v.nvim_buf_get_lines(0, cursor[1] - 1, cursor[1], false)[1]
local indentexpr = v.nvim_get_option_value("indentexpr", { buf = 0 }) local indentexpr = v.nvim_buf_get_option(0, "indentexpr")
local expand = v.nvim_get_option_value("expandtab", { buf = 0 }) local expand = v.nvim_buf_get_option(0, "expandtab")
local shiftwidth = v.nvim_eval("shiftwidth()") local shiftwidth = v.nvim_eval("shiftwidth()")
local tab_char = v.nvim_replace_termcodes("<Tab>", true, true, true) local tab_char = v.nvim_replace_termcodes("<Tab>", true, true, true)
local indent_goal local indent_goal
@ -37,7 +37,7 @@ local function indent()
if indent_goal == nil or indent_goal < 0 then if indent_goal == nil or indent_goal < 0 then
if indentexpr ~= "" then if indentexpr ~= "" then
indent_goal = v.nvim_eval(indentexpr) indent_goal = v.nvim_eval(indentexpr)
elseif v.nvim_get_option_value("cindent", { buf = 0 }) then elseif v.nvim_buf_get_option(0, "cindent") then
indent_goal = v.nvim_call_function("cindent", { cursor[1] }) indent_goal = v.nvim_call_function("cindent", { cursor[1] })
else else
indent_goal = v.nvim_call_function("indent", { cursor[1] }) indent_goal = v.nvim_call_function("indent", { cursor[1] })

View file

@ -1,3 +0,0 @@
# Overlays for building custom non-trivial plugins
[ (self: super: { }) ]