* Refactored into separate files

* Baseline functionality
This commit is contained in:
Ellis Rahhal 2025-02-13 11:40:42 -08:00
parent e19a09f2df
commit e254433f2c
30 changed files with 1460 additions and 1135 deletions

View file

@ -5,11 +5,24 @@
Add the following to the `inputs` section of your flake.nix:
```nix
nixvim-config.url = "github:homefree/nixvim-config";
inputs = {
nixvim-config.url = "github:homefree/nixvim-config";
};
```
And add the following module:
And add the following to the outputs:
```nix
@TODO
outputs = { ... }@inputs: {
nixosConfigurations = {
<hostname> = inputs.nixpkgs.lib.nixosSystem {
modules = [
inputs.nixvim-config.nixosModules.default
{
nixvim-config.enable = true;
}
];
};
};
}
```

80
autocmd.nix Normal file
View file

@ -0,0 +1,80 @@
{ ... }:
{
programs.nixvim = {
autoCmd = [
## Close nvim on last buffer closed, not leaving neovim-tree open
{
event = [ "BufEnter" ];
pattern = [ "NvimTree_*" ];
callback = {
__raw = ''
function()
local layout = vim.api.nvim_call_function("winlayout", {})
if layout[1] == "leaf" and vim.api.nvim_buf_get_option(vim.api.nvim_win_get_buf(layout[2]), "filetype") == "NvimTree" and layout[3] == nil then vim.cmd("confirm quit") end
end
'';
};
}
## Go to same line in file next time it is open
{
event = [ "BufReadPost" ];
pattern = [ "*" ];
callback = {
__raw = ''
function()
if vim.fn.line("'\"") > 1 and vim.fn.line("'\"") <= vim.fn.line("$") then
vim.api.nvim_exec("normal! g'\"",false)
end
end
'';
};
}
## Highlight tabs and trailing whitespace
{
event = [ "BufEnter" ];
pattern = [ "*" ];
callback = {
__raw = ''
function()
vim.cmd([[
if exists('w:extratabs')
call matchdelete(w:extratabs)
unlet w:extratabs
endif
if exists('w:trailingwhitespace')
call matchdelete(w:trailingwhitespace)
unlet w:trailingwhitespace
endif
highlight ExtraTabs ctermbg=red guibg=red
highlight TrailingWhitespace ctermbg=red guibg=red
if &ft != 'help'
let w:extratabs=matchadd('ExtraTabs', '\t\+')
let w:trailingwhitespace=matchadd('TrailingWhitespace', '\s\+$')
endif
]])
end
'';
};
}
## Trim tailing whitespace on save
{
event = [ "BufWritePre" ];
pattern = [ "*" ];
callback = {
__raw = ''
function()
vim.cmd([[
if &ft =~ 'javascript\|html\|jade\|json\|css\|less\|php\|python\|sh\|c\|cpp\|markdown\|yaml\|vim\|nix'
:%s/\s\+$//e
elseif expand('%:t') =~ '\.gltf$' || expand('%:t') =~ '\.glsl$'
:%s/\s\+$//e
endif
]])
end
'';
};
}
];
};
}

View file

@ -1,6 +1,8 @@
{ ... }:
{ inputs, ... }:
{
imports = [
inputs.nixvim.nixosModules.nixvim
./module.nix
./nixvim.nix
];
}

22
flake.lock generated
View file

@ -1,26 +1,6 @@
{
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1738574474,
"narHash": "sha256-rvyfF49e/k6vkrRTV4ILrWd92W+nmBDfRYZgctOyolQ=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "fecfeb86328381268e29e998ddd3ebc70bbd7f7c",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-24.11",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"nixpkgs": "nixpkgs"
}
}
"root": {}
},
"root": "root",
"version": 7

View file

@ -3,33 +3,29 @@
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
};
outputs = { self, nixpkgs, ... } @ inputs:
# let
# system = "x86_64-linux";
# in
{
packages.x86_64-linux = let
pkgs = import "${nixpkgs}" {
# system = "x86_64-linux";
};
in with pkgs; {
nixvim-config = callPackage ./default.nix {
inherit builtins;
};
nixvim = {
url = "github:nix-community/nixvim";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs = { nixpkgs, ... } @ inputs:
let
# system = "x86_64-linux";
pkgs = import "${nixpkgs}" {
# system = "x86_64-linux";
};
in
{
nixosModules = rec {
homefree = import ./default.nix {
# inherit system;
};
imports = [ ];
default = homefree;
lan-client = import ./lan-client.nix {
nixvim-config = import ./default.nix {
inherit inputs;
# inherit system;
inherit pkgs;
};
default = nixvim-config;
};
};
}

259
keymaps.nix Normal file
View file

@ -0,0 +1,259 @@
{ ... }:
{
programs.nixvim = {
keymaps = [
# -----------------------------------------------------
# nvim-tree
# -----------------------------------------------------
## Go to current buffer's file in nvim-tree
{
mode = [ "n" ];
key = ",n";
action = ":NvimTreeFindFile<CR>";
}
## Toggle nvim-tree visibility
{
mode = [ "n" ];
key = ",m";
action = ":NvimTreeToggle<CR>";
}
# -----------------------------------------------------
# buffer manipulation
# -----------------------------------------------------
## Next Buffer
{
key = "<Tab>";
action = ":bn<CR>";
options = { noremap = true; };
}
## Previous Buffer
{
key = "<S-Tab>";
action = ":bp<CR>";
options = { noremap = true; };
}
## Close Buffer
{
key = "<leader><Tab>";
action = ":bd<CR>";
options = { noremap = true; };
}
## Force Close Buffer
{
key = "<leader><S-Tab>";
action = ":bd!<CR>";
options = { noremap = true; };
}
## New Tab
{
key = "<leader>t";
action = ":tabnew split<CR>";
options = { noremap = true; };
}
# -----------------------------------------------------
# Telescope
# -----------------------------------------------------
## Lists files in your current working directory, respects .gitignore
{
mode = [ "n" ];
key = "<leader>ff";
action = "<cmd>Telescope find_files<cr>";
options = { noremap = true; };
}
## Finds files by filename
{
mode = [ "n" ];
key = "<c-p>";
action = "<cmd>Telescope find_files<cr>";
# action = "<cmd>FzfLua files<cr>";
options = { noremap = true; };
}
# Search for a string in your current working directory and get results live as you type, respects .gitignore. (Requires ripgrep)
{
mode = [ "n" ];
key = "<leader>fg";
action = "<cmd>Telescope live_grep<cr>";
# action = "<cmd>FzfLua live_grep<cr>";
options = { noremap = true; };
}
# Search file contents
{
mode = [ "n" ];
key = "<c-s>";
action = "<cmd>Telescope live_grep<cr>";
# action = "<cmd>FzfLua live_grep<cr>";
options = { noremap = true; };
}
# Lists open buffers in current neovim instance
{
mode = [ "n" ];
key = "<leader>db";
action = "<cmd>Telescope buffers<cr>";
# action = "<cmd>FzfLua buffers<cr>";
options = { noremap = true; };
}
# Lists available help tags and opens a new window with the relevant help info on <cr>
{
mode = [ "n" ];
key = "<leader>fh";
action = "<cmd>Telescope help_tags<cr>";
# action = "<cmd>FzfLua helptags<cr>";
options = { noremap = true; };
}
# Lists manpage entries, opens them in a help window on <cr>
{
mode = [ "n" ];
key = "<leader>fm";
action = "<cmd>Telescope man_pages<cr>";
# action = "<cmd>FzfLua manpages<cr>";
options = { noremap = true; };
}
# Lists previously open files
{
mode = [ "n" ];
key = "<leader>fp";
action = "<cmd>Telescope oldfiles<cr>";
# action = "<cmd>FzfLua oldfiles<cr>";
options = { noremap = true; };
}
# Lists previously open files, Maps to ctrl-/
{
mode = [ "n" ];
key = "<c-_>";
action = "<cmd>Telescope oldfiles<cr>";
# action = "<cmd>FzfLua oldfiles<cr>";
options = { noremap = true; };
}
# Lists spelling suggestions for the current word under the cursor, replaces word with selected suggestion on <cr>
{
mode = [ "n" ];
key = "<leader>fs";
action = "<cmd>Telescope spell_suggest<cr>";
# action = "<cmd>FzfLua spell_suggest<cr>";
options = { noremap = true; };
}
# Lists LSP references for iword under the cursor
{
mode = [ "n" ];
key = "<leader>fr";
action = "<cmd>Telescope lsp_references<cr>";
# action = "<cmd>FzfLua lsp_references<cr>";
options = { noremap = true; };
}
# Lists LSP incoming calls for word under the cursor
{
mode = [ "n" ];
key = "<leader>fi";
action = "<cmd>Telescope lsp_incoming_calls<cr>";
# action = "<cmd>FzfLua lsp_incoming_calls<cr>";
options = { noremap = true; };
}
# Lists LSP outgoing calls for word under the cursor
{
mode = [ "n" ];
key = "<leader>fo";
action = "<cmd>Telescope lsp_outgoing_calls<cr>";
# action = "<cmd>FzfLua lsp_outgoing_calls<cr>";
options = { noremap = true; };
}
# Dynamically Lists LSP for all workspace symbols
{
mode = [ "n" ];
key = "<leader>fw";
action = "<cmd>Telescope lsp_dynamic_workspace_symbols<cr>";
# action = "<cmd>FzfLua lsp_workspace_symbols<cr>";
options = { noremap = true; };
}
# Goto the definition of the word under the cursor, if there's only one, otherwise show all options in Telescope
{
mode = [ "n" ];
key = "<leader>fd";
action = "<cmd>Telescope lsp_definitions<cr>";
options = { noremap = true; };
}
# Got to previous error
{
mode = [ "n" ];
key = "[d";
action = "<cmd>lua vim.diagnostic.goto_prev()<CR>";
options = { noremap = true; silent = true; };
}
{
mode = [ "n" ];
key = ",k";
action = "<cmd>lua vim.diagnostic.goto_prev()<CR>";
options = { noremap = true; silent = true; };
}
# Got to next error
{
mode = [ "n" ];
key = "]d";
action = "<cmd>lua vim.diagnostic.goto_next()<CR>";
options = { noremap = true; silent = true; };
}
{
mode = [ "n" ];
key = ",j";
action = "<cmd>lua vim.diagnostic.goto_next()<CR>";
options = { noremap = true; silent = true; };
}
## Other Telescope options:
## git_files search only files in git, respects .gitignore
## oldfiles previously opened files
## command_history
## search_history
## man_pages
## resume lists the results including multi-selections of the previous
## picker
# -----------------------------------------------------
# Diff
# -----------------------------------------------------
{
mode = [ "n" ];
key = ",d";
## @TODO: This doesn't work
action = ''
function()
if next(require('diffview.lib').views) == nil then
vim.cmd('DiffviewOpen origin')
else
vim.cmd('DiffviewClose')
end
end
'';
options = { noremap = true; };
}
# -----------------------------------------------------
# Bufferline
# -----------------------------------------------------
{
mode = [ "n" ];
key = "<A-h>";
action = ":BufferLineCyclePrev<CR>";
options = { noremap = true; silent = true; };
}
{
mode = [ "n" ];
key = "<A-l>";
action = ":BufferLineCycleNex<CR>";
options = { noremap = true; silent = true; };
}
{
mode = [ "n" ];
key = "<A-c>";
action = ":bdelete!<CR>";
options = { noremap = true; silent = true; };
}
];
};
}

6
module.nix Normal file
View file

@ -0,0 +1,6 @@
{ lib, ... }:
{
options.nixvim-config = {
enable = lib.mkEnableOption "Enable nixvim-config";
};
}

View file

@ -1,6 +1,13 @@
{ pkgs, ... }:
{ config, pkgs, ... }:
{
environment.systemPackages = with pkgs; [
imports = [
./options.nix
./keymaps.nix
./autocmd.nix
./plugins
];
environment.systemPackages = if config.nixvim-config.enable then with pkgs; [
ripgrep
## To get rid of checkhealth warnings
@ -9,912 +16,10 @@
mercurial
ueberzugpp
viu
];
] else [];
environment.interactiveShellInit = ''
environment.interactiveShellInit = if config.nixvim-config.enable then ''
alias vi='nvim'
alias vim='nvim'
'';
programs.nixvim = {
enable = true;
defaultEditor = true;
## ------------------------------------------------
## Options
## ------------------------------------------------
globals = {
mapleader = " "; # global
maplocalleader = " "; # per buffer, e.g. can change behavior per filetype
## To appropriately highlight codefences returned from denols
markdown_fenced_languages.__raw = ''
{
"ts=typescript"
}
'';
};
opts = {
number = true; # Show line numbers
relativenumber = true; # Show relative line numbers
ruler = true; # displays line, column, and cursor position at bottom
wrap = false; # don't wrap lines
signcolumn = "yes"; # always show two column sign column on left
cursorline = true; # Highlight line cursor sits on
undodir.__raw = "vim.fs.normalize('~/.local/share/nvim/undo/')";
undofile = true;
# -----------------------------------------------------
# Backspace settings
# indent allow backspacing over autoindent
# eol allow backspacing over line breaks (join lines)
# start allow backspacing over the start of insert; CTRL-W and CTRL-U
# 0 same as ":set backspace=" (Vi compatible)
# 1 same as ":set backspace=indent,eol"
# 2 same as ":set backspace=indent,eol,start"
# -----------------------------------------------------
bs = "2";
# -----------------------------------------------------
# Indentation settings
# -----------------------------------------------------
tabstop = 4; # number of spaces a tab counts for
shiftwidth = 4; # control how many columns text is indented with the reindent operations (<< and >>) and automatic C-style indentation.
expandtab = true; # Insert spaces when entering <Tab>
softtabstop = 4; # Number of spaces that a <Tab> counts for while performing editing operations, like inserting a <Tab> or using <BS>. It "feels" like a tab though
ai = true; # auto indent
};
keymaps = [
# -----------------------------------------------------
# nvim-tree
# -----------------------------------------------------
## Go to current buffer's file in nvim-tree
{
mode = [ "n" ];
key = ",n";
action = ":NvimTreeFindFile<CR>";
}
## Toggle nvim-tree visibility
{
mode = [ "n" ];
key = ",m";
action = ":NvimTreeToggle<CR>";
}
# -----------------------------------------------------
# buffer manipulation
# -----------------------------------------------------
## Next Buffer
{
key = "<Tab>";
action = ":bn<CR>";
options = { noremap = true; };
}
## Previous Buffer
{
key = "<S-Tab>";
action = ":bp<CR>";
options = { noremap = true; };
}
## Close Buffer
{
key = "<leader><Tab>";
action = ":bd<CR>";
options = { noremap = true; };
}
## Force Close Buffer
{
key = "<leader><S-Tab>";
action = ":bd!<CR>";
options = { noremap = true; };
}
## New Tab
{
key = "<leader>t";
action = ":tabnew split<CR>";
options = { noremap = true; };
}
# -----------------------------------------------------
# Telescope
# -----------------------------------------------------
## Lists files in your current working directory, respects .gitignore
{
mode = [ "n" ];
key = "<leader>ff";
action = "<cmd>Telescope find_files<cr>";
options = { noremap = true; };
}
## Finds files by filename
{
mode = [ "n" ];
key = "<c-p>";
action = "<cmd>Telescope find_files<cr>";
# action = "<cmd>FzfLua files<cr>";
options = { noremap = true; };
}
# Search for a string in your current working directory and get results live as you type, respects .gitignore. (Requires ripgrep)
{
mode = [ "n" ];
key = "<leader>fg";
action = "<cmd>Telescope live_grep<cr>";
# action = "<cmd>FzfLua live_grep<cr>";
options = { noremap = true; };
}
# Search file contents
{
mode = [ "n" ];
key = "<c-s>";
action = "<cmd>Telescope live_grep<cr>";
# action = "<cmd>FzfLua live_grep<cr>";
options = { noremap = true; };
}
# Lists open buffers in current neovim instance
{
mode = [ "n" ];
key = "<leader>db";
action = "<cmd>Telescope buffers<cr>";
# action = "<cmd>FzfLua buffers<cr>";
options = { noremap = true; };
}
# Lists available help tags and opens a new window with the relevant help info on <cr>
{
mode = [ "n" ];
key = "<leader>fh";
action = "<cmd>Telescope help_tags<cr>";
# action = "<cmd>FzfLua helptags<cr>";
options = { noremap = true; };
}
# Lists manpage entries, opens them in a help window on <cr>
{
mode = [ "n" ];
key = "<leader>fm";
action = "<cmd>Telescope man_pages<cr>";
# action = "<cmd>FzfLua manpages<cr>";
options = { noremap = true; };
}
# Lists previously open files
{
mode = [ "n" ];
key = "<leader>fp";
action = "<cmd>Telescope oldfiles<cr>";
# action = "<cmd>FzfLua oldfiles<cr>";
options = { noremap = true; };
}
# Lists previously open files, Maps to ctrl-/
{
mode = [ "n" ];
key = "<c-_>";
action = "<cmd>Telescope oldfiles<cr>";
# action = "<cmd>FzfLua oldfiles<cr>";
options = { noremap = true; };
}
# Lists spelling suggestions for the current word under the cursor, replaces word with selected suggestion on <cr>
{
mode = [ "n" ];
key = "<leader>fs";
action = "<cmd>Telescope spell_suggest<cr>";
# action = "<cmd>FzfLua spell_suggest<cr>";
options = { noremap = true; };
}
# Lists LSP references for iword under the cursor
{
mode = [ "n" ];
key = "<leader>fr";
action = "<cmd>Telescope lsp_references<cr>";
# action = "<cmd>FzfLua lsp_references<cr>";
options = { noremap = true; };
}
# Lists LSP incoming calls for word under the cursor
{
mode = [ "n" ];
key = "<leader>fi";
action = "<cmd>Telescope lsp_incoming_calls<cr>";
# action = "<cmd>FzfLua lsp_incoming_calls<cr>";
options = { noremap = true; };
}
# Lists LSP outgoing calls for word under the cursor
{
mode = [ "n" ];
key = "<leader>fo";
action = "<cmd>Telescope lsp_outgoing_calls<cr>";
# action = "<cmd>FzfLua lsp_outgoing_calls<cr>";
options = { noremap = true; };
}
# Dynamically Lists LSP for all workspace symbols
{
mode = [ "n" ];
key = "<leader>fw";
action = "<cmd>Telescope lsp_dynamic_workspace_symbols<cr>";
# action = "<cmd>FzfLua lsp_workspace_symbols<cr>";
options = { noremap = true; };
}
# Goto the definition of the word under the cursor, if there's only one, otherwise show all options in Telescope
{
mode = [ "n" ];
key = "<leader>fd";
action = "<cmd>Telescope lsp_definitions<cr>";
options = { noremap = true; };
}
# Got to previous error
{
mode = [ "n" ];
key = "[d";
action = "<cmd>lua vim.diagnostic.goto_prev()<CR>";
options = { noremap = true; silent = true; };
}
{
mode = [ "n" ];
key = ",k";
action = "<cmd>lua vim.diagnostic.goto_prev()<CR>";
options = { noremap = true; silent = true; };
}
# Got to next error
{
mode = [ "n" ];
key = "]d";
action = "<cmd>lua vim.diagnostic.goto_next()<CR>";
options = { noremap = true; silent = true; };
}
{
mode = [ "n" ];
key = ",j";
action = "<cmd>lua vim.diagnostic.goto_next()<CR>";
options = { noremap = true; silent = true; };
}
## Other Telescope options:
## git_files search only files in git, respects .gitignore
## oldfiles previously opened files
## command_history
## search_history
## man_pages
## resume lists the results including multi-selections of the previous
## picker
# -----------------------------------------------------
# Diff
# -----------------------------------------------------
{
mode = [ "n" ];
key = ",d";
## @TODO: This doesn't work
action = ''
function()
if next(require('diffview.lib').views) == nil then
vim.cmd('DiffviewOpen origin')
else
vim.cmd('DiffviewClose')
end
end
'';
options = { noremap = true; };
}
# -----------------------------------------------------
# Bufferline
# -----------------------------------------------------
{
mode = [ "n" ];
key = "<A-h>";
action = ":BufferLineCyclePrev<CR>";
options = { noremap = true; silent = true; };
}
{
mode = [ "n" ];
key = "<A-l>";
action = ":BufferLineCycleNex<CR>";
options = { noremap = true; silent = true; };
}
{
mode = [ "n" ];
key = "<A-c>";
action = ":bdelete!<CR>";
options = { noremap = true; silent = true; };
}
];
autoCmd = [
## Close nvim on last buffer closed, not leaving neovim-tree open
{
event = [ "BufEnter" ];
pattern = [ "NvimTree_*" ];
callback = {
__raw = ''
function()
local layout = vim.api.nvim_call_function("winlayout", {})
if layout[1] == "leaf" and vim.api.nvim_buf_get_option(vim.api.nvim_win_get_buf(layout[2]), "filetype") == "NvimTree" and layout[3] == nil then vim.cmd("confirm quit") end
end
'';
};
}
## Go to same line in file next time it is open
{
event = [ "BufReadPost" ];
pattern = [ "*" ];
callback = {
__raw = ''
function()
if vim.fn.line("'\"") > 1 and vim.fn.line("'\"") <= vim.fn.line("$") then
vim.api.nvim_exec("normal! g'\"",false)
end
end
'';
};
}
## Highlight tabs and trailing whitespace
{
event = [ "BufEnter" ];
pattern = [ "*" ];
callback = {
__raw = ''
function()
vim.cmd([[
if exists('w:extratabs')
call matchdelete(w:extratabs)
unlet w:extratabs
endif
if exists('w:trailingwhitespace')
call matchdelete(w:trailingwhitespace)
unlet w:trailingwhitespace
endif
highlight ExtraTabs ctermbg=red guibg=red
highlight TrailingWhitespace ctermbg=red guibg=red
if &ft != 'help'
let w:extratabs=matchadd('ExtraTabs', '\t\+')
let w:trailingwhitespace=matchadd('TrailingWhitespace', '\s\+$')
endif
]])
end
'';
};
}
## Trim tailing whitespace on save
{
event = [ "BufWritePre" ];
pattern = [ "*" ];
callback = {
__raw = ''
function()
vim.cmd([[
if &ft =~ 'javascript\|html\|jade\|json\|css\|less\|php\|python\|sh\|c\|cpp\|markdown\|yaml\|vim\|nix'
:%s/\s\+$//e
elseif expand('%:t') =~ '\.gltf$' || expand('%:t') =~ '\.glsl$'
:%s/\s\+$//e
endif
]])
end
'';
};
}
];
## ------------------------------------------------
## Theme
## ------------------------------------------------
colorschemes.tokyonight.enable = true;
# colorschemes.gruvbox.enable = true;
## Or:
# extraPlugins = [ pkgs.vimPlugins.gruvbox ];
# colorscheme = "gruvbox";
## ------------------------------------------------
## Included Plugins
## ------------------------------------------------
plugins.bufferline = {
enable = true;
# extraOptions = {
settings = {
options = {
tabpages = true;
sidebar_filetypes = {
NvimTree = true;
};
diagnostics = "nvim_lsp";
always_show_bufferline = true;
};
highlights = {
buffer_selected = {
# fg = "#ffffff";
bold = true;
};
};
};
};
plugins.comment.enable = true;
plugins.diffview = {
enable = true;
};
plugins.fugitive.enable = true;
plugins.gitsigns.enable = true;
plugins.lightline.enable = true;
plugins.lualine.enable = true;
plugins.nix.enable = true;
plugins.noice.enable = true;
plugins.notify = {
## disable, very annoying as notifications block content and
## are part of the buffer rotation
enable = false;
topDown = false;
};
plugins.nvim-autopairs.enable = true;
plugins.nvim-tree = {
enable = true;
extraOptions = {
actions = {
remove_file = {
close_window = false;
};
};
## Keep tree open if already open when opening a tab
tab = {
sync = {
open = true;
close = true;
};
};
view = {
width = 30;
};
renderer = {
group_empty = true;
};
git = {
enable = true;
ignore = false;
timeout = 500;
};
};
};
plugins.rainbow-delimiters.enable = true;
plugins.sleuth.enable = true;
plugins.telescope = {
enable = true;
extensions.ui-select.enable = true;
settings = {
defaults = {
mappings = {
i = {
# One instead of two esc taps to exit telescope
"<esc>" = {
__raw = "require('telescope.actions').close";
};
# Ctrl-space is used by Tmux, so remap to Ctrl-e
"<c-e>" = {
__raw = "require('telescope.actions').to_fuzzy_refine";
};
# "<c-o>" = {
# __raw = "require('trouble.sources.telescope').open";
# };
};
n = {
# "<c-o>" = {
# __raw = "require('trouble.sources.telescope').open";
# };
};
};
};
};
};
plugins.fzf-lua = {
enable = true;
# profile = "telescope";
settings = {
oldfiles = {
# In Telescope, when I used <leader>fr, it would load old buffers.
# fzf lua does the same, but by default buffers visited in the current
# session are not included. I use <leader>fr all the time to switch
# back to buffers I was just in. If you missed this from Telescope,
# give it a try.
include_current_session = true;
};
preview = {
vertical = "down:90%";
horizontal = "right:90%";
};
previewers = {
builtin = {
# fzf-lua is very fast, but it really struggled to preview a couple files
# in a repo. Those files were very big JavaScript files (1MB, minified, all on a single line).
# It turns out it was Treesitter having trouble parsing the files.
# With this change, the previewer will not add syntax highlighting to files larger than 100KB
# (Yes, I know you shouldn't have 100KB minified files in source control.)
syntax_limit_b = 1024 * 100; # 100KB
};
};
grep = {
# One thing I missed from Telescope was the ability to live_grep and the
# run a filter on the filenames.
# Ex: Find all occurrences of "enable" but only in the "plugins" directory.
# With this change, I can sort of get the same behaviour in live_grep.
# ex: > enable --*/plugins/*
# I still find this a bit cumbersome. There's probably a better way of doing this.
rg_glob = true; # enable glob parsing
glob_flag = "--iglob"; # case insensitive globs
glob_separator = "%s%-%-"; # query separator pattern (lua): ' --'
};
};
keymaps = {
"<C-p>" = {
action = "git_files";
options = {
desc = "Fzf-Lua Git Files";
silent = true;
};
settings = {
previewers = {
cat = {
cmd = "${pkgs.coreutils-full}/bin/cat";
};
};
# winopts = {
# height = 0.5;
# };
};
};
# "<C-s>" = "live_grep";
# "<C-_>" = "oldfiles";
# "<leader>fd" = "lsp_definitions";
# "<leader>fg" = "live_grep";
# "<leader>fh" = "helptags";
# "<leader>fi" = "lsp_incoming_calls";
# "<leader>fm" = "manpages";
# "<leader>fo" = "lsp_outgoing_calls";
# "<leader>fp" = "oldfiles";
# "<leader>fr" = "lsp_references";
# "<leader>fs" = "spell_suggest";
# "<leader>fw" = "lsp_workspace_symbols";
# "<leader>db" = "buffers";
# "<leader>ch" = "command_history";
};
};
plugins.treesitter.enable = false;
plugins.tmux-navigator.enable = true;
plugins.trouble.enable = true;
# ## Needed for telescope, nvim-tree, trouble, diffview, bufferline, and other plugins
# ## Only on unstable at the moment
plugins.web-devicons.enable = true;
## ------------------------------------------------
## LSP / Completion
## ------------------------------------------------
plugins.lsp = {
enable = true;
onAttach = ''
local active_clients = vim.lsp.get_active_clients()
if client.name == "denols" then
for _, client_ in pairs(active_clients) do
-- stop tsserver if denols is already active
if client_.name == "ts_ls" then
client_.stop()
end
end
elseif client.name == "ts_ls" then
for _, client_ in pairs(active_clients) do
-- prevent tsserver from starting if denols is already active
if client_.name == "denols" then
client.stop()
end
end
end
'';
servers = {
ts_ls = {
enable = true;
rootDir = "require('lspconfig').util.root_pattern('package.json')";
settings = {
single_file_support = false;
};
};
denols = {
enable = true;
rootDir = "require('lspconfig').util.root_pattern('deno.json', 'deno.jsonc')";
};
cssls.enable = true;
tailwindcss.enable = true;
html.enable = true;
phpactor.enable = true;
pyright.enable = true;
marksman.enable = true;
nil_ls.enable = true;
## Using nil_ls
# nixd.enable = true;
dockerls.enable = true; # Docker
bashls.enable = true; # Bash
clangd.enable = true; # C/C++
csharp_ls.enable = true; # C#
yamlls.enable = true; # YAML
ltex = {
enable = true;
settings = {
enabled = [ "astro" "html" "latex" "markdown" "text" "tex" "gitcommit" ];
completionEnabled = true;
language = "en-US de-DE nl";
# dictionary = {
# "nl-NL" = [
# ":/home/liv/.local/share/nvim/ltex/nl-NL.txt"
# ];
# "en-US" = [
# ":/home/liv/.local/share/nvim/ltex/en-US.txt"
# ];
# "de-DE" = [
# ":/home/liv/.local/share/nvim/ltex/de-DE.txt"
# ];
# };
};
};
gopls = { # Golang
enable = true;
autostart = true;
};
lua_ls = { # Lua
enable = true;
settings.telemetry.enable = false;
};
# Rust
rust_analyzer = {
enable = true;
installRustc = true;
installCargo = true;
};
};
};
## @TODO: Enable once stable
plugins.blink-cmp = {
enable = false;
};
plugins.cmp = {
enable = true;
autoEnableSources = true;
settings = {
enabled.__raw = ''
function()
-- local context = require("cmp.config.context")
-- local is_comment = context.in_treesitter_capture("comment") == true or context.in_syntax_group("Comment")
buftype = vim.api.nvim_buf_get_option(0, "buftype")
if buftype == "prompt" then
-- don't show in Telescope
return false
end
local col = vim.fn.col('.') - 1
local line = vim.fn.getline('.')
local char_under_cursor = string.sub(line, col, col)
if col == 0 or string.match(char_under_cursor, '%s') then
return false
end
return true
end
'';
sources = [
{ name = "nvim_lua"; }
{ name = "nvim_lsp"; }
{ name = "emoji"; }
{
name = "buffer"; # text within current buffer
option.get_bufnrs.__raw = "vim.api.nvim_list_bufs";
keywordLength = 3;
}
# { name = "copilot"; } # enable/disable copilot
{
name = "path"; # file system paths
keywordLength = 3;
}
{
name = "luasnip"; # snippets
keywordLength = 3;
}
{ name = "cmdline"; }
];
formatting = {
fields = [ "kind" "abbr" "menu" ];
format = ''
function(entry, vim_item)
local kind_icons = {
Text = "󰊄",
Method = "",
Function = "󰡱",
Constructor = "",
Field = "",
Variable = "󱀍",
Class = "",
Interface = "",
Module = "󰕳",
Property = "",
Unit = "",
Value = "",
Enum = "",
Keyword = "",
Snippet = "",
Color = "",
File = "",
Reference = "",
Folder = "",
EnumMember = "",
Constant = "",
Struct = "",
Event = "",
Operator = "",
TypeParameter = "",
}
vim_item.kind = string.format("%s", kind_icons[vim_item.kind])
vim_item.menu = ({
path = "[Path]",
nvim_lua = "[NVIM_LUA]",
nvim_lsp = "[LSP]",
luasnip = "[Snippet]",
buffer = "[Buffer]",
})[entry.source.name]
return vim_item
end
'';
};
completion = {
completeopt = "menuone,noselect";
};
autoEnableSources = true;
experimental = { ghost_text = true; };
performance = {
debounce = 60;
fetchingTimeout = 200;
maxViewEntries = 30;
};
snippet = {
expand = ''
function(args)
require('luasnip').lsp_expand(args.body)
end
'';
};
window = {
completion = { border = "solid"; };
documentation = { border = "solid"; };
};
mapping = {
"<C-j>" = "cmp.mapping.select_next_item()";
"<C-n>" = "cmp.mapping.select_next_item()";
"<C-k>" = "cmp.mapping.select_prev_item()";
"<C-p>" = "cmp.mapping.select_prev_item()";
"<C-e>" = "cmp.mapping.abort()";
"<C-b>" = "cmp.mapping.scroll_docs(-4)";
"<C-f>" = "cmp.mapping.scroll_docs(4)";
"<C-Space>" = "cmp.mapping.complete()";
"<Tab>" = "cmp.mapping.confirm({ select = true })";
# "<Tab>" = ''
# cmp.mapping(function(fallback)
# -- local context = require("cmp.config.context")
# -- local is_comment = context.in_treesitter_capture("comment") == true or context.in_syntax_group("Comment")
#
# local col = vim.fn.col('.') - 1
# local line = vim.fn.getline('.')
# local char_under_cursor = string.sub(line, col, col)
#
# if col == 0 or string.match(char_under_cursor, '%s') then
# fallback()
# elseif cmp.visible() then
# cmp.confirm({ select = true })
# else
# fallback()
# end
# end, { "i", "s" })
# '';
"<S-Tab>" = "cmp.mapping.confirm({ behavior = cmp.ConfirmBehavior.Replace, select = true })";
"<C-l>" = ''
cmp.mapping(function()
if luasnip.expand_or_locally_jumpable() then
luasnip.expand_or_jump()
end
end, { 'i', 's' })
'';
"<C-h>" = ''
cmp.mapping(function()
if luasnip.locally_jumpable(-1) then
luasnip.jump(-1)
end
end, { 'i', 's' })
'';
};
};
};
plugins.nvim-lightbulb = {
enable = true;
};
# config = ''
# lua << EOF
# require('nvim-lightbulb').setup({
# float = {
# -- "true" causes "invalid buffer id" error
# enabled = false,
# },
# autocmd = {
# enabled = true,
# },
# })
# EOF
# '';
plugins.lsp-signature = {
enable = true;
};
# config = ''
# lua << EOF
# require("lsp_signature").setup()
# EOF
# '';
## ------------------------------------------------
## Extra Plugins
## ------------------------------------------------
extraPlugins = with pkgs.vimPlugins; [
vim-dirdiff
{
plugin = vim-signify;
config = ''
let g:signify_vcs_cmds = { 'git': 'git diff --no-color --no-ext-diff -U0 master -- %f' }
let g:signify_priority = 1
highlight SignColumn ctermbg=237
'';
}
vim-surround
## focus-nvim only in unstable
# (pkgs.vimUtils.buildVimPlugin {
# name = "focus-nvim";
# src = pkgs.fetchFromGitHub {
# owner = "nvim-focus";
# repo = "focus.nvim";
# rev = "3841a38df972534567e85840d7ead20d3a26faa6";
# sha256 = "sha256-mgHk4u0ab2uSUNE+7DU22IO/xS5uop9iATfFRk6l6hs=";
# };
# })
];
};
'' else "";
}

View file

@ -1,166 +0,0 @@
#!/usr/bin/env python
import getopt
import inspect
import logging
import os
import psutil
import signal
import shutil
import subprocess
import sys
import time
import urllib
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.support.ui import WebDriverWait
from xdg_base_dirs import xdg_config_home
script_dir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
class OpenconnectPulseLauncher:
def signal_handler(self, _sig, _frame):
subprocess.run(['sudo', 'route', 'del', 'default', 'gw', self.vpn_gateway_ip])
while 'openconnect' in (i.name() for i in psutil.process_iter()):
subprocess.run(['sudo', 'pkill', '-SIGINT', 'openconnect'])
ps = subprocess.Popen(
['getent', 'hosts', self.hostname],
stdout=subprocess.PIPE,
)
output = subprocess.check_output(
['awk', '{print $1}'],
stdin=ps.stdout
)
ps.wait()
vpn_ip = output.decode().rstrip()
# This is normally deleted when the VPN is killed, but sometimes is left behind as there are two entries
subprocess.run(['sudo', 'route', 'del', vpn_ip])
sys.exit(0)
def __init__(self):
self.is_root = os.geteuid() == 0
self.chrome_profile_dir = os.path.join(xdg_config_home(), 'chromedriver', 'pulsevpn')
if not os.path.exists(self.chrome_profile_dir):
os.makedirs(self.chrome_profile_dir)
self.vpn_gateway_ip = None
signal.signal(signal.SIGINT, self.signal_handler)
def is_dsid_valid(self, dsid):
# Expiry is set to Session
return dsid is not None and 'value' in dsid
def connect(self, vpn_url, chromedriver_path, chromium_path, debug=False, script=None):
self.hostname = urllib.parse.urlparse(vpn_url).hostname
dsid = None
returncode = 0
while True:
if self.is_dsid_valid(dsid) and returncode != 2:
logging.info('Launching openconnect.')
## Run in background
## openconnect is built to already point to a pre-packaged vpnc-script, so no need to specify
# p = subprocess.run(['sudo', 'openconnect', '-b', '-C', dsid['value'], '--protocol=pulse', vpn_url, '-s', '${pkgs.unstable.vpnc-scripts}/bin/vpnc-script'])
## --no-dtls addresses VPN dying with "ESP detected dead peer", and also "ESP receive error: Message too long" error
## See: https://gitlab.com/openconnect/openconnect/-/issues/647
## Downside: lots of console spam
## Also, seems to die often with this error:
## Short packet received (2 bytes)
## Unrecoverable I/O error; exiting.
# p = subprocess.run(['sudo', 'openconnect', '--no-dtls', '-b', '-C', dsid['value'], '--protocol=pulse', vpn_url])
command_line = ['sudo', 'openconnect']
if debug:
command_line.extend(['-vvvv'])
if script is not None:
command_line.extend(['-s', script])
command_line.extend(['-b', '-C', dsid['value'], '--protocol=pulse', vpn_url])
if debug:
print('Command line:')
print(' {}'.format(' '.join(command_line)))
print('')
p = subprocess.run(command_line)
returncode = p.returncode
## Get tun0 IP and set as default GW (vpnc-script doesn't do this for some reason)
## Probably due to something like this:
## https://github.com/dlenski/openconnect/issues/125#issuecomment-426032102
## There is an error on the command line when openconnect is run:
## Error: argument "via" is wrong: use nexthop syntax to specify multiple via
## sleep to make sure tun0 is available
time.sleep(3)
ps = subprocess.Popen(
['ifconfig', 'tun0'],
stdout=subprocess.PIPE
)
output = subprocess.check_output(
['awk', '-F', ' *|:', '/inet /{print $3}'],
stdin=ps.stdout
)
ps.wait()
self.vpn_gateway_ip = output.decode().rstrip()
print('VPN IP: '+self.vpn_gateway_ip)
p = subprocess.run(['sudo', 'route', 'add', 'default', 'gw', self.vpn_gateway_ip])
# Wait for ctrl-c
signal.pause()
else:
returncode = 0
service = Service(executable_path=chromedriver_path)
options = webdriver.ChromeOptions()
options.binary_location = chromium_path
options.add_argument('--window-size=800,900')
# options.add_argument('--remote-debugging-pipe')
# options.add_argument('--remote-debugging-port=9222')
options.add_argument('user-data-dir=' + self.chrome_profile_dir)
logging.info('Starting browser.')
driver = webdriver.Chrome(service=service, options=options)
driver.get(vpn_url)
dsid = WebDriverWait(driver, float('inf')).until(lambda driver: driver.get_cookie('DSID'))
driver.quit()
logging.info('DSID cookie: %s', dsid)
def main(argv):
script_name = os.path.basename(__file__)
chromedriver_path = shutil.which('chromedriver')
chromium_path = shutil.which('chromium') or shutil.which('google-chrome')
help_message = '{} <vpn_url>'.format(script_name)
try:
opts, args = getopt.getopt(argv, 'hds:c:', ['help', 'debug', 'script=', 'chromedriver-path'])
except getopt.GetoptError:
print(help_message)
sys.exit(2)
if len(args) != 1:
print(help_message)
sys.exit(2)
debug = False
script = None
for o, a in opts:
if o in ('-h', '--help'):
print(help_message)
sys.exit()
elif o in ('-d', '--debug'):
debug = True
elif o in ('-s', '--script'):
if len(a):
script = a
elif o in ('-c', '--chromedriver-path'):
if len(a):
chromedriver_path = a
vpn_url = args[0]
launcher = OpenconnectPulseLauncher()
launcher.connect(vpn_url, chromedriver_path=chromedriver_path, chromium_path=chromium_path, debug=debug, script=script)
if __name__ == "__main__":
main(sys.argv[1:])

97
options.nix Normal file
View file

@ -0,0 +1,97 @@
{ config, ... }:
{
programs.nixvim = {
enable = config.nixvim-config.enable;
defaultEditor = true;
globals = {
mapleader = " "; # global
maplocalleader = " "; # per buffer, e.g. can change behavior per filetype
## To appropriately highlight codefences returned from denols
markdown_fenced_languages.__raw = ''
{
"ts=typescript"
}
'';
};
clipboard = {
register = "unnamedplus";
};
opts = {
undodir.__raw = "vim.fs.normalize('~/.local/share/nvim/undo/')";
undofile = true;
undolevels = 1000; # Increase undo levels
backup = false; # No file backup
number = true; # Show line numbers
relativenumber = true; # Show relative line numbers
ruler = true; # displays line, column, and cursor position at bottom
wrap = false; # don't wrap lines
signcolumn = "yes"; # always show two column sign column on left
cursorline = true; # Highlight line cursor sits on
## @TODO Review these
completeopt = ""; # Completion options
hidden = true; # Enable modified buffers in background
inccommand = "nosplit"; # Show effects of a command incrementally
joinspaces = false; # No double spaces with join after a dot
scrolloff = 4; # Lines of context
fileencoding = "utf-8"; # Encode files using UTF-8
termguicolors = true; # True color support
background = "dark"; # Always dark background
wildmenu = true; # Command-line completion mode
wildmode = "longest,list,full"; # Command-line completion mode
cmdheight = 2; # Command-line height
timeoutlen = 500; # to to wait for mapped sequence to complete
errorbells = false; # No sound on errors
visualbell = false;
mouse = "";
splitright = true;
winaltkeys = "no"; # Disable ALT keys for menu
autoindent = true;
smartindent = true;
colorcolumn = "121";
laststatus = 3;
# -----------------------------------------------------
# Backspace settings
# indent allow backspacing over autoindent
# eol allow backspacing over line breaks (join lines)
# start allow backspacing over the start of insert; CTRL-W and CTRL-U
# 0 same as ":set backspace=" (Vi compatible)
# 1 same as ":set backspace=indent,eol"
# 2 same as ":set backspace=indent,eol,start"
# -----------------------------------------------------
bs = "2";
# -----------------------------------------------------
# Indentation settings
# -----------------------------------------------------
tabstop = 4; # number of spaces a tab counts for
shiftwidth = 4; # control how many columns text is indented with the reindent operations (<< and >>) and automatic C-style indentation.
expandtab = true; # Insert spaces when entering <Tab>
softtabstop = 4; # Number of spaces that a <Tab> counts for while performing editing operations, like inserting a <Tab> or using <BS>. It "feels" like a tab though
ai = true; # auto indent
};
## ------------------------------------------------
## Theme
## ------------------------------------------------
colorschemes.tokyonight.enable = true;
# colorschemes.gruvbox.enable = true;
## Or:
# extraPlugins = [ pkgs.vimPlugins.gruvbox ];
# colorscheme = "gruvbox";
};
}

View file

@ -0,0 +1,8 @@
{ ... }:
{
programs.nixvim = {
plugins.blink-cmp-copilot = {
enable = true;
};
};
}

View file

@ -0,0 +1,33 @@
{ pkgs, lib, ... }:
let
## Remove flags from words
processHunspellDict = filename:
let
content = builtins.readFile filename;
# Remove first line, which is a word count, then split on newlines
lines = builtins.tail (lib.splitString "\n" content);
# Remove flags at the end of words
result = builtins.concatStringsSep "\n" (map (line:
builtins.head (lib.splitString "/" line)
) lines);
in
result;
in
{
programs.nixvim = {
plugins.blink-cmp-dictionary = {
enable = true;
};
extraPackages = with pkgs; [
wordnet
];
};
environment.etc = {
"dictionaries/english-words.txt" = {
text = processHunspellDict "${pkgs.hunspellDicts.en-us-large}/share/hunspell/en_US.dic";
mode = "0444";
};
};
}

166
plugins/blink-cmp.nix Normal file
View file

@ -0,0 +1,166 @@
{ ... }:
{
programs.nixvim = {
plugins = {
blink-cmp = {
enable = true;
settings = {
fuzzy.prebuilt_binaries = {
download = false;
ignore_version_mismatch = true;
};
keymap = {
preset = "enter";
};
signature = {
# handled by noice
enabled = false;
};
sources = {
default = [
"lsp"
"path"
"snippets"
"buffer"
"cmp_yanky"
"copilot"
"emoji"
"lazydev"
"codecompanion"
"dictionary"
];
providers = {
copilot = {
name = "Copilot";
async = true;
module = "blink-cmp-copilot";
score_offset = 50;
opts = {
max_completions = 2;
max_attemps = 3;
};
};
cmp_yanky = {
async = true;
name = "cmp_yanky";
module = "blink.compat.source";
score_offset = -5;
};
emoji = {
module = "blink-emoji";
name = "Emoji";
score_offset = -10;
opts = {
insert = true;
};
};
codecompanion = {
name = "CodeCompanion";
module = "codecompanion.providers.completion.blink";
};
dictionary = {
module = "blink-cmp-dictionary";
name = "Dict";
score_offset = -15;
min_keyword_length = 3;
opts = {
dictionary_directories = {
__unkeyed-1.__raw = ''vim.fn.expand("/etc/dictionaries/")'';
};
};
};
lazydev = {
name = "LazyDev";
module = "lazydev.integrations.blink";
score_offset = 100;
};
lsp = {
async = true;
score_offset = 60;
};
};
};
appearance = {
kind_icons = {
Copilot = "";
cmp_yanky = "";
emoji = "";
};
use_nvim_cmp_as_default = false;
};
completion = {
accept = {
auto_brackets = {
enabled = false;
};
};
list = {
selection = {
preselect.__raw = ''
function(ctx)
return ctx.mode ~= 'cmdline' and not require('blink.cmp').snippet_active({ direction = 1 })
end
'';
auto_insert = false;
};
};
documentation = {
auto_show = true;
auto_show_delay_ms = 500;
treesitter_highlighting = true;
};
menu = {
auto_show = true;
draw = {
treesitter = ["lsp"];
};
};
};
snippets = {
preset = "luasnip";
expand.__raw = ''
function(snippet) require('luasnip').lsp_expand(snippet) end
'';
active.__raw = ''
function(filter)
if filter and filter.direction then
return require('luasnip').jumpable(filter.direction)
end
return require('luasnip').in_snippet()
end
'';
jump.__raw = ''
function(direction) require('luasnip').jump(direction) end
'';
};
};
};
blink-compat = {
enable = true;
};
};
extraConfigLua = ''
vim.api.nvim_set_hl(0, 'BlinkCmpKindDict', { default = false, fg = '#a6e3a1' })
'';
};
}

10
plugins/blink-copilot.nix Normal file
View file

@ -0,0 +1,10 @@
{ ... }:
{
programs.nixvim = {
plugins.blink-copilot = {
enable = true;
};
};
}

8
plugins/blink-emoji.nix Normal file
View file

@ -0,0 +1,8 @@
{ ... }:
{
programs.nixvim = {
plugins.blink-emoji = {
enable = true;
};
};
}

25
plugins/bufferline.nix Normal file
View file

@ -0,0 +1,25 @@
{ ... }:
{
programs.nixvim = {
plugins.bufferline = {
enable = true;
# extraOptions = {
settings = {
options = {
tabpages = true;
sidebar_filetypes = {
NvimTree = true;
};
diagnostics = "nvim_lsp";
always_show_bufferline = true;
};
highlights = {
buffer_selected = {
# fg = "#ffffff";
bold = true;
};
};
};
};
};
}

158
plugins/cmp.nix Normal file
View file

@ -0,0 +1,158 @@
{ ... }:
{
programs.nixvim = {
plugins.cmp = {
enable = true;
autoEnableSources = true;
settings = {
enabled.__raw = ''
function()
local filetype = vim.api.nvim_buf_get_option(0, "filetype")
if filetype == "TelescopePrompt" then
return false
end
return true
end
'';
sources = [
{ name = "nvim_lua"; }
{ name = "nvim_lsp"; }
{ name = "emoji"; }
{
name = "buffer"; # text within current buffer
option.get_bufnrs.__raw = "vim.api.nvim_list_bufs";
keywordLength = 3;
}
# { name = "copilot"; } # enable/disable copilot
{
name = "path"; # file system paths
keywordLength = 3;
}
{
name = "luasnip"; # snippets
keywordLength = 3;
}
{ name = "cmdline"; }
];
formatting = {
fields = [ "kind" "abbr" "menu" ];
format = ''
function(entry, vim_item)
local kind_icons = {
Text = "󰊄",
Method = "",
Function = "󰡱",
Constructor = "",
Field = "",
Variable = "󱀍",
Class = "",
Interface = "",
Module = "󰕳",
Property = "",
Unit = "",
Value = "",
Enum = "",
Keyword = "",
Snippet = "",
Color = "",
File = "",
Reference = "",
Folder = "",
EnumMember = "",
Constant = "",
Struct = "",
Event = "",
Operator = "",
TypeParameter = "",
}
vim_item.kind = string.format("%s", kind_icons[vim_item.kind])
vim_item.menu = ({
path = "[Path]",
nvim_lua = "[NVIM_LUA]",
nvim_lsp = "[LSP]",
luasnip = "[Snippet]",
buffer = "[Buffer]",
})[entry.source.name]
return vim_item
end
'';
};
completion = {
# completeopt = "menuone,noselect";
completeopt = "";
};
autoEnableSources = true;
experimental = { ghost_text = true; };
performance = {
debounce = 60;
fetchingTimeout = 200;
maxViewEntries = 30;
};
snippet = {
expand = ''
function(args)
require('luasnip').lsp_expand(args.body)
end
'';
};
window = {
completion = { border = "solid"; };
documentation = { border = "solid"; };
};
mapping = {
"<C-j>" = "cmp.mapping.select_next_item()";
"<C-n>" = "cmp.mapping.select_next_item()";
"<C-k>" = "cmp.mapping.select_prev_item()";
"<C-p>" = "cmp.mapping.select_prev_item()";
"<C-e>" = "cmp.mapping.abort()";
"<C-b>" = "cmp.mapping.scroll_docs(-4)";
"<C-f>" = "cmp.mapping.scroll_docs(4)";
"<C-c>" = "cmp.mapping.complete()";
"<Tab>" = "cmp.mapping.confirm({ select = true })";
# "<Tab>" = ''
# cmp.mapping(function(fallback)
# -- local context = require("cmp.config.context")
# -- local is_comment = context.in_treesitter_capture("comment") == true or context.in_syntax_group("Comment")
#
# local col = vim.fn.col('.') - 1
# local line = vim.fn.getline('.')
# local char_under_cursor = string.sub(line, col, col)
#
# if col == 0 or string.match(char_under_cursor, '%s') then
# fallback()
# elseif cmp.visible() then
# cmp.confirm({ select = true })
# else
# fallback()
# end
# end, { "i", "s" })
# '';
"<S-Tab>" = "cmp.mapping.confirm({ behavior = cmp.ConfirmBehavior.Replace, select = true })";
"<C-l>" = ''
cmp.mapping(function()
if luasnip.expand_or_locally_jumpable() then
luasnip.expand_or_jump()
end
end, { 'i', 's' })
'';
"<C-h>" = ''
cmp.mapping(function()
if luasnip.locally_jumpable(-1) then
luasnip.jump(-1)
end
end, { 'i', 's' })
'';
};
};
};
};
}

94
plugins/codecompanion.nix Normal file
View file

@ -0,0 +1,94 @@
{ pkgs, ... }:
{
programs.nixvim.plugins = {
codecompanion = {
enable = true;
settings = {
adapters = {
anthropic.__raw = ''
function()
return require('codecompanion.adapters').extend('anthropic', {
env = {
api_key = "cmd:${pkgs.passage}/bin/passage /apis/ai/anthropic"
}
})
end
'';
copilot.__raw = ''
function()
return require('codecompanion.adapters').extend('copilot', {
env = {
-- api_key = "cmd:${pkgs.passage}/bin/passage /apis/ai/anthropic"
}
})
end
'';
openai.__raw = ''
function()
return require('codecompanion.adapters').extend('copilot', {
env = {
api_key = "cmd:${pkgs.passage}/bin/passage /apis/ai/openai"
}
})
end
'';
deepseek.__raw = ''
function()
return require('codecompanion.adapters').extend('deepseek', {
env = {
api_key = "cmd:${pkgs.passage}/bin/passage /apis/ai/deepseek"
},
schema = {
model = {
default = "deepseek-reasoner",
},
},
})
end
'';
ollama.__raw = ''
function()
return require('codecompanion.adapters').extend('ollama', {
env = {
url = "http://127.0.0.1:11434",
},
schema = {
model = {
default = 'hf.co/unsloth/DeepSeek-R1-Distill-Qwen-1.5B-GGUF',
},
temperature = {
default = 0.6,
},
num_ctx = {
default = 32768,
},
},
})
end
'';
};
opts = {
send_code = true;
use_default_actions = true;
use_default_prompts = true;
};
strategies = {
agent = {
adapter = "copilot";
};
chat = {
adapter = "copilot";
};
inline = {
adapter = "copilot";
};
};
};
};
};
}

14
plugins/copilot.nix Normal file
View file

@ -0,0 +1,14 @@
{ ... }:
{
programs.nixvim = {
plugins.copilot-lua = {
enable = true;
settings = {
suggestion.enabled = false;
panel.enabled = false;
};
};
};
}

71
plugins/default.nix Normal file
View file

@ -0,0 +1,71 @@
{ ... }:
{
imports = [
# ./blink-cmp.nix
# ./blink-cmp-copilot.nix
# ./blink-cmp-dictionary.nix
# ./blink-copilot.nix
# ./blink-emoji.nixd
./bufferline.nix
./cmp.nix
./codecompanion.nix
./copilot.nix
./fzf-lua.nix
./lazydev.nix
./lsp.nix
./luasnip.nix
./nvim-tree.nix
./telescope.nix
./vim-signify.nix
];
programs.nixvim.plugins = {
comment.enable = true;
diffview.enable = true;
fugitive.enable = true;
gitsigns.enable = true;
indent-blankline.enable = true;
lightline.enable = true;
lsp-signature.enable = true;
# config = ''
# lua << EOF
# require("lsp_signature").setup()
# EOF
# '';
lualine.enable = true;
nix.enable = true;
noice.enable = true;
## disable, very annoying as notifications block content and
## are part of the buffer rotation
notify = {
enable = false;
topDown = false;
};
nvim-autopairs.enable = true;
nvim-lightbulb.enable = true;
# config = ''
# lua << EOF
# require('nvim-lightbulb').setup({
# float = {
# -- "true" causes "invalid buffer id" error
# enabled = false,
# },
# autocmd = {
# enabled = true,
# },
# })
# EOF
# '';
rainbow-delimiters.enable = true;
sleuth.enable = true;
treesitter.enable = false;
tmux-navigator.enable = true;
trouble.enable = true;
# ## Needed for telescope, nvim-tree, trouble, diffview, bufferline, and other plugins
# ## Only on unstable at the moment
web-devicons.enable = true;
which-key.enable = true;
};
}

77
plugins/fzf-lua.nix Normal file
View file

@ -0,0 +1,77 @@
{ pkgs, ... }:
{
programs.nixvim = {
plugins.fzf-lua = {
enable = true;
# profile = "telescope";
settings = {
oldfiles = {
# In Telescope, when I used <leader>fr, it would load old buffers.
# fzf lua does the same, but by default buffers visited in the current
# session are not included. I use <leader>fr all the time to switch
# back to buffers I was just in. If you missed this from Telescope,
# give it a try.
include_current_session = true;
};
preview = {
vertical = "down:90%";
horizontal = "right:90%";
};
previewers = {
builtin = {
# fzf-lua is very fast, but it really struggled to preview a couple files
# in a repo. Those files were very big JavaScript files (1MB, minified, all on a single line).
# It turns out it was Treesitter having trouble parsing the files.
# With this change, the previewer will not add syntax highlighting to files larger than 100KB
# (Yes, I know you shouldn't have 100KB minified files in source control.)
syntax_limit_b = 1024 * 100; # 100KB
};
};
grep = {
# One thing I missed from Telescope was the ability to live_grep and the
# run a filter on the filenames.
# Ex: Find all occurrences of "enable" but only in the "plugins" directory.
# With this change, I can sort of get the same behaviour in live_grep.
# ex: > enable --*/plugins/*
# I still find this a bit cumbersome. There's probably a better way of doing this.
rg_glob = true; # enable glob parsing
glob_flag = "--iglob"; # case insensitive globs
glob_separator = "%s%-%-"; # query separator pattern (lua): ' --'
};
};
keymaps = {
"<C-p>" = {
action = "git_files";
options = {
desc = "Fzf-Lua Git Files";
silent = true;
};
settings = {
previewers = {
cat = {
cmd = "${pkgs.coreutils-full}/bin/cat";
};
};
# winopts = {
# height = 0.5;
# };
};
};
# "<C-s>" = "live_grep";
# "<C-_>" = "oldfiles";
# "<leader>fd" = "lsp_definitions";
# "<leader>fg" = "live_grep";
# "<leader>fh" = "helptags";
# "<leader>fi" = "lsp_incoming_calls";
# "<leader>fm" = "manpages";
# "<leader>fo" = "lsp_outgoing_calls";
# "<leader>fp" = "oldfiles";
# "<leader>fr" = "lsp_references";
# "<leader>fs" = "spell_suggest";
# "<leader>fw" = "lsp_workspace_symbols";
# "<leader>db" = "buffers";
# "<leader>ch" = "command_history";
};
};
};
}

12
plugins/lazydev.nix Normal file
View file

@ -0,0 +1,12 @@
{ pkgs, ... }:
{
programs.nixvim = {
extraConfigLua = ''
require("lazydev").setup({})
'';
extraPlugins = with pkgs.vimPlugins; [
lazydev-nvim
];
};
}

89
plugins/lsp.nix Normal file
View file

@ -0,0 +1,89 @@
{ ... }:
{
programs.nixvim = {
plugins.lsp = {
enable = true;
onAttach = ''
-- Set capabilities for the LSP client from blink-cmp
-- client.config.capabilities = require('blink.cmp').get_lsp_capabilities(client.config.capabilities)
local active_clients = vim.lsp.get_active_clients()
if client.name == "denols" then
for _, client_ in pairs(active_clients) do
-- stop tsserver if denols is already active
if client_.name == "ts_ls" then
client_.stop()
end
end
elseif client.name == "ts_ls" then
for _, client_ in pairs(active_clients) do
-- prevent tsserver from starting if denols is already active
if client_.name == "denols" then
client.stop()
end
end
end
'';
servers = {
ts_ls = {
enable = true;
rootDir = "require('lspconfig').util.root_pattern('package.json')";
settings = {
single_file_support = false;
};
};
denols = {
enable = true;
rootDir = "require('lspconfig').util.root_pattern('deno.json', 'deno.jsonc')";
};
cssls.enable = true;
tailwindcss.enable = true;
html.enable = true;
phpactor.enable = true;
pyright.enable = true;
marksman.enable = true;
nil_ls.enable = true;
## Using nil_ls
# nixd.enable = true;
dockerls.enable = true; # Docker
bashls.enable = true; # Bash
clangd.enable = true; # C/C++
csharp_ls.enable = true; # C#
yamlls.enable = true; # YAML
ltex = {
enable = true;
settings = {
enabled = [ "astro" "html" "latex" "markdown" "text" "tex" "gitcommit" ];
completionEnabled = true;
language = "en-US de-DE nl";
# dictionary = {
# "nl-NL" = [
# ":/home/liv/.local/share/nvim/ltex/nl-NL.txt"
# ];
# "en-US" = [
# ":/home/liv/.local/share/nvim/ltex/en-US.txt"
# ];
# "de-DE" = [
# ":/home/liv/.local/share/nvim/ltex/de-DE.txt"
# ];
# };
};
};
gopls = { # Golang
enable = true;
autostart = true;
};
lua_ls = { # Lua
enable = true;
settings.telemetry.enable = false;
};
# Rust
rust_analyzer = {
enable = true;
installRustc = true;
installCargo = true;
};
};
};
};
}

41
plugins/luasnip.nix Normal file
View file

@ -0,0 +1,41 @@
{ ... }:
{
programs.nixvim = {
plugins.luasnip = {
enable = true;
fromLua = [
{}
{
paths = ./snippets;
}
];
settings = {
history = true;
updateevents = ["TextChanged" "TextChangedI"];
region_check_events = "CursorHold";
delete_check_events = "InsertLeave";
# ext_opts.__raw = ''
# {
# [require('luasnip.util.types').choiceNode] = {
# active = {
# virt_text = { { 'choice <c-c>', 'Comment' } },
# hl_mode = 'combine',
# },
# },
# }
# '';
};
};
# keymaps = [
# {
# mode = "i";
# key = "<c-c>";
# action.__raw = ''function() require("luasnip.extras.select_choice")() end'';
# options.desc = "Search";
# }
# ];
};
}

33
plugins/nvim-tree.nix Normal file
View file

@ -0,0 +1,33 @@
{ ... }:
{
programs.nixvim = {
plugins.nvim-tree = {
enable = true;
extraOptions = {
actions = {
remove_file = {
close_window = false;
};
};
## Keep tree open if already open when opening a tab
tab = {
sync = {
open = true;
close = true;
};
};
view = {
width = 30;
};
renderer = {
group_empty = true;
};
git = {
enable = true;
ignore = false;
timeout = 500;
};
};
};
};
}

36
plugins/snippets/all.lua Normal file
View file

@ -0,0 +1,36 @@
--example:
--inc 20250209T133000Z - 20250209T140000Z # personal test
---@return string
local function get_timestamp()
local line_number = vim.api.nvim_win_get_cursor(vim.api.nvim_get_current_win())[1]
local line = vim.fn.getline(line_number - 1)
return vim.split(line, " ")[4]
end
---@return string
local function get_date()
local timestamp = get_timestamp()
return vim.split(timestamp, "T")[1]
end
return {
s(
{
trig = "tw-continue",
name = "Timewarior Continue From Previous Line",
desc = { "Start a new time tracking with end time from previous line." },
},
fmt(
[[
inc {} - {}T{}00Z # {} {}
]],
{
f(get_timestamp),
f(get_date),
i(1),
c(2, { t("work"), t("meeting"), t("other") }),
i(3),
}
)
),
}

44
plugins/snippets/yaml.lua Normal file
View file

@ -0,0 +1,44 @@
return {
s(
{
trig = "schema",
name = "Yaml Schema",
desc = { "Adds a yaml-language-server schema to current buffer." },
},
fmt(
[[
# yaml-language-server: $schema={}
]],
{
i(1),
}
)
),
s(
{ trig = "kustomize", name = "Kustomize", desc = { "Adds the kustomize boilerplate." } },
fmt(
[[
# yaml-language-server: $schema=https://json.schemastore.org/kustomization.json
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources: []
]],
{}
)
),
s(
{
trig = "m",
name = "directive end marker",
desc = { "Adds directive end parker." },
},
fmt(
[[
---
]],
{}
)
),
}

33
plugins/telescope.nix Normal file
View file

@ -0,0 +1,33 @@
{ ... }:
{
programs.nixvim = {
plugins.telescope = {
enable = true;
extensions.ui-select.enable = true;
settings = {
defaults = {
mappings = {
i = {
# One instead of two esc taps to exit telescope
"<esc>" = {
__raw = "require('telescope.actions').close";
};
# Ctrl-space is used by Tmux, so remap to Ctrl-e
"<c-e>" = {
__raw = "require('telescope.actions').to_fuzzy_refine";
};
# "<c-o>" = {
# __raw = "require('trouble.sources.telescope').open";
# };
};
n = {
# "<c-o>" = {
# __raw = "require('trouble.sources.telescope').open";
# };
};
};
};
};
};
};
}

17
plugins/vim-signify.nix Normal file
View file

@ -0,0 +1,17 @@
{ pkgs, ... }:
{
programs.nixvim = {
extraPlugins = with pkgs.vimPlugins; [
vim-dirdiff
{
plugin = vim-signify;
config = ''
let g:signify_vcs_cmds = { 'git': 'git diff --no-color --no-ext-diff -U0 master -- %f' }
let g:signify_priority = 1
highlight SignColumn ctermbg=237
'';
}
vim-surround
];
};
}

View file

@ -1,16 +0,0 @@
attrs==23.2.0
certifi==2024.2.2
h11==0.14.0
idna==3.6
outcome==1.3.0.post0
psutil==5.9.8
PySocks==1.7.1
selenium==4.19.0
sniffio==1.3.1
sortedcontainers==2.4.0
trio==0.25.0
trio-websocket==0.11.1
typing_extensions==4.11.0
urllib3==2.2.1
wsproto==1.2.0
xdg-base-dirs==6.0.1