From 591831666f6fb43a43a059c900c818ad6a1eb558 Mon Sep 17 00:00:00 2001 From: duck Date: Wed, 17 Dec 2025 21:43:32 +0500 Subject: [PATCH] Initial commit --- home/apps/fish.nix | 24 ++ home/apps/fish/conf.d/abbreviations.fish | 40 ++++ home/apps/fish/config.fish | 30 +++ home/apps/fish/fish_variables | 32 +++ home/apps/nvim.nix | 25 ++ home/apps/nvim/init.lua | 89 +++++++ home/apps/nvim/lazy-lock.json | 39 ++++ home/apps/nvim/lua/center/init.lua | 92 ++++++++ home/apps/nvim/lua/digraphs.lua | 32 +++ home/apps/nvim/lua/globals.lua | 31 +++ home/apps/nvim/lua/marks.lua | 7 + home/apps/nvim/lua/multiline/init.lua | 210 +++++++++++++++++ home/apps/nvim/lua/plugins/colors.lua | 104 +++++++++ home/apps/nvim/lua/plugins/editing.lua | 107 +++++++++ home/apps/nvim/lua/plugins/lsp.lua | 217 ++++++++++++++++++ home/apps/nvim/lua/plugins/lualine.lua | 71 ++++++ home/apps/nvim/lua/plugins/markdown.lua | 31 +++ home/apps/nvim/lua/plugins/misc.lua | 175 ++++++++++++++ home/apps/nvim/lua/plugins/motion.lua | 89 +++++++ home/apps/nvim/lua/plugins/snip.lua | 29 +++ home/apps/nvim/lua/plugins/telescope.lua | 204 ++++++++++++++++ home/apps/nvim/lua/plugins/visual.lua | 40 ++++ home/apps/nvim/lua/scripter/init.lua | 142 ++++++++++++ home/apps/nvim/lua/scripter/presets/auto.lua | 22 ++ .../nvim/lua/scripter/presets/cyrillic.lua | 37 +++ home/apps/nvim/lua/scripter/presets/init.lua | 6 + home/apps/nvim/lua/scripter/presets/none.lua | 3 + home/apps/nvim/lua/winpad/init.lua | 93 ++++++++ home/apps/nvim/snippets/all.lua | 41 ++++ home/apps/nvim/snippets/zig.lua | 27 +++ home/apps/shell_common.nix | 13 ++ home/apps/starship.nix | 16 ++ home/apps/starship.toml | 65 ++++++ home/apps/tmux.nix | 16 ++ home/apps/tmux/tmux.conf | 88 +++++++ home/flake.lock | 48 ++++ home/flake.nix | 25 ++ home/main.nix | 22 ++ 38 files changed, 2382 insertions(+) create mode 100644 home/apps/fish.nix create mode 100644 home/apps/fish/conf.d/abbreviations.fish create mode 100644 home/apps/fish/config.fish create mode 100644 home/apps/fish/fish_variables create mode 100644 home/apps/nvim.nix create mode 100644 home/apps/nvim/init.lua create mode 100644 home/apps/nvim/lazy-lock.json create mode 100644 home/apps/nvim/lua/center/init.lua create mode 100644 home/apps/nvim/lua/digraphs.lua create mode 100644 home/apps/nvim/lua/globals.lua create mode 100644 home/apps/nvim/lua/marks.lua create mode 100644 home/apps/nvim/lua/multiline/init.lua create mode 100644 home/apps/nvim/lua/plugins/colors.lua create mode 100644 home/apps/nvim/lua/plugins/editing.lua create mode 100644 home/apps/nvim/lua/plugins/lsp.lua create mode 100644 home/apps/nvim/lua/plugins/lualine.lua create mode 100644 home/apps/nvim/lua/plugins/markdown.lua create mode 100644 home/apps/nvim/lua/plugins/misc.lua create mode 100644 home/apps/nvim/lua/plugins/motion.lua create mode 100644 home/apps/nvim/lua/plugins/snip.lua create mode 100644 home/apps/nvim/lua/plugins/telescope.lua create mode 100644 home/apps/nvim/lua/plugins/visual.lua create mode 100644 home/apps/nvim/lua/scripter/init.lua create mode 100644 home/apps/nvim/lua/scripter/presets/auto.lua create mode 100644 home/apps/nvim/lua/scripter/presets/cyrillic.lua create mode 100644 home/apps/nvim/lua/scripter/presets/init.lua create mode 100644 home/apps/nvim/lua/scripter/presets/none.lua create mode 100644 home/apps/nvim/lua/winpad/init.lua create mode 100644 home/apps/nvim/snippets/all.lua create mode 100644 home/apps/nvim/snippets/zig.lua create mode 100644 home/apps/shell_common.nix create mode 100644 home/apps/starship.nix create mode 100644 home/apps/starship.toml create mode 100644 home/apps/tmux.nix create mode 100644 home/apps/tmux/tmux.conf create mode 100644 home/flake.lock create mode 100644 home/flake.nix create mode 100644 home/main.nix diff --git a/home/apps/fish.nix b/home/apps/fish.nix new file mode 100644 index 0000000..ea21213 --- /dev/null +++ b/home/apps/fish.nix @@ -0,0 +1,24 @@ +{ + lib, config, pkgs, ... +}: let + cfg = config.fish; +in { + imports = [ + ./shell_common.nix + ]; + + options.fish = {}; + + config = { + home.packages = [ + pkgs.fish + ]; + home.file = { + ".config/fish" = { + source = ./fish; + # Fish creates it's config directory if there is none + force = true; + }; + }; + }; +} diff --git a/home/apps/fish/conf.d/abbreviations.fish b/home/apps/fish/conf.d/abbreviations.fish new file mode 100644 index 0000000..2829a36 --- /dev/null +++ b/home/apps/fish/conf.d/abbreviations.fish @@ -0,0 +1,40 @@ +# General +abbr -a nv nvim +abbr -a lg lazygit +abbr -a tx tmux +abbr -a pc pacman +abbr -a cl clear +function fastparentcd + echo cd (string repeat -n (math (string length -- $argv[1]) - 1) ../) +end +abbr -a dotdot -r "^\.\.+\$" -f fastparentcd + +# Git +abbr -a g git +abbr -a ga git add +abbr -a gs git status +abbr -a gss git status -s +abbr -a gc git commit +abbr -a gca git commit --amend +abbr -a gb git rebase +abbr -a gbc git rebase --continue +abbr -a gg git push +abbr -a gp git pull +abbr -a gw git switch +abbr -a go git restore +abbr -a gr git reset +abbr -a goo git restore -S +abbr -a gri git rebase -i +abbr -a ge git remote +abbr -a ger git remote remove +abbr -a gea git remote add +abbr -a ges git remote show -n +abbr -a gf git fetch +abbr -a gd git diff +abbr -a gds git diff --staged + +# Zig +abbr -a zb zig build +abbr -a zbr zig build run +abbr -a zbe zig build-exe +abbr -a zbt zig build test diff --git a/home/apps/fish/config.fish b/home/apps/fish/config.fish new file mode 100644 index 0000000..b794a63 --- /dev/null +++ b/home/apps/fish/config.fish @@ -0,0 +1,30 @@ +set -gx EDITOR nvim +set -gx MANPAGER nvim +Man! + +set -U fish_greeting +set history_ignore rm + +if test -n "$fish_private_mode" + function fish_title + echo "Private Shell" + end +end + +function ll + command exa -l $argv +end +function cat + command bat $argv +end + +function fish_should_add_to_history + for cmd in $history_ignore + string match -qr "^$cmd" -- $argv; and return 1 + end + return 0 +end + +if status is-interactive + starship init fish | source + zoxide init fish | source +end diff --git a/home/apps/fish/fish_variables b/home/apps/fish/fish_variables new file mode 100644 index 0000000..2f80356 --- /dev/null +++ b/home/apps/fish/fish_variables @@ -0,0 +1,32 @@ +# This file contains fish universal variable definitions. +# VERSION: 3.0 +SETUVAR __fish_initialized:3800 +SETUVAR fish_color_autosuggestion:brblack +SETUVAR fish_color_cancel:\x2dr +SETUVAR fish_color_command:brblue +SETUVAR fish_color_comment:red +SETUVAR fish_color_cwd:green +SETUVAR fish_color_cwd_root:red +SETUVAR fish_color_end:green +SETUVAR fish_color_error:brred +SETUVAR fish_color_escape:brcyan +SETUVAR fish_color_history_current:\x2d\x2dbold +SETUVAR fish_color_host:normal +SETUVAR fish_color_host_remote:yellow +SETUVAR fish_color_normal:normal +SETUVAR fish_color_operator:brcyan +SETUVAR fish_color_param:normal +SETUVAR fish_color_quote:brgreen +SETUVAR fish_color_redirection:cyan\x1e\x2d\x2dbold +SETUVAR fish_color_search_match:white\x1e\x2d\x2dbackground\x3dbrblack +SETUVAR fish_color_selection:white\x1e\x2d\x2dbold\x1e\x2d\x2dbackground\x3dbrblack +SETUVAR fish_color_status:red +SETUVAR fish_color_user:brgreen +SETUVAR fish_color_valid_path:brgreen +SETUVAR fish_greeting:\x1d +SETUVAR fish_key_bindings:fish_default_key_bindings +SETUVAR fish_pager_color_completion:brgreen +SETUVAR fish_pager_color_description:yellow\x1e\x2di +SETUVAR fish_pager_color_prefix:normal\x1e\x2d\x2dbold\x1e\x2d\x2dunderline +SETUVAR fish_pager_color_progress:brwhite\x1e\x2d\x2dbackground\x3dcyan +SETUVAR fish_pager_color_selected_background:\x2dr diff --git a/home/apps/nvim.nix b/home/apps/nvim.nix new file mode 100644 index 0000000..2e59a0f --- /dev/null +++ b/home/apps/nvim.nix @@ -0,0 +1,25 @@ +{ + lib, config, pkgs, ... +}: let + cfg = config.nvim; +in { + options.nvim = { + editor = lib.mkOption { type = lib.types.bool; default = false; }; + }; + + config = { + home.packages = [ + pkgs.neovim + pkgs.git + # Required to build neovim plugins like treesitter + pkgs.gcc + pkgs.gnumake + ]; + home.sessionVariables = lib.mkMerge [ + (lib.mkIf cfg.editor { EDITOR = "nvim"; }) + ]; + home.file = { + ".config/nvim".source = ./nvim; + }; + }; +} diff --git a/home/apps/nvim/init.lua b/home/apps/nvim/init.lua new file mode 100644 index 0000000..1e0cf24 --- /dev/null +++ b/home/apps/nvim/init.lua @@ -0,0 +1,89 @@ +vim.g.mapleader = " " +vim.g.maplocalleader = " " + +vim.g.loaded_netrw = 1 +vim.g.loaded_netrwPlugin = 1 + +local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim" +if not (vim.uv or vim.loop).fs_stat(lazypath) then + vim.fn.system({ + "git", + "clone", + "--filter=blob:none", + "https://github.com/folke/lazy.nvim.git", + "--branch=stable", -- latest stable release + lazypath, + }) +end +vim.opt.rtp:prepend(lazypath) + +vim.opt.autoread = true +vim.opt.tabstop = 4 +vim.opt.shiftwidth = 4 +vim.opt.expandtab = false +vim.opt.autoindent = true +vim.opt.softtabstop = 0 +vim.opt.preserveindent = true +vim.opt.number = true +vim.opt.wrap = false +vim.opt.sidescrolloff = 16 +vim.opt.list = true +vim.opt.listchars = { + tab = "┆ ", + leadmultispace = "│ ", + multispace = "·", + extends = "»", + precedes = "«", + trail = "─", +} +vim.opt.signcolumn = "yes" +vim.opt.hlsearch = false +vim.opt.cursorline = true +vim.opt.cursorlineopt = "number" +vim.opt.shortmess = "aoOstTWIcC" +vim.opt.smartcase = true +vim.opt.ignorecase = true +vim.opt.undofile = true +vim.opt.fillchars = { eob = " " } +vim.opt.virtualedit = "all" +vim.opt.timeout = false +vim.opt.showmode = false +vim.opt.pumheight = 7 +vim.diagnostic.config({ virtual_text = false, underline = false, signs = false }) + +-- FTPlugin, begone +vim.cmd("autocmd BufReadPre,BufNewFile * let b:did_ftplugin = 1") +vim.cmd("filetype plugin off") + +vim.keymap.set("n", "", ":m .+1==") -- move line up(n) +vim.keymap.set("n", "", ":m .-2==") -- move line down(n) +vim.keymap.set("v", "", ":m '>+1gv=gv") -- move line up(v) +vim.keymap.set("v", "", ":m '<-2gv=gv") -- move line down(v) +local buffer_action = function(prompt, command) + return function() + vim.ui.input({ prompt = prompt }, function(input) + vim.cmd(command .. input) + end) + end +end +vim.keymap.set("n", "bn", buffer_action("New buffer", ":edit ")) +vim.keymap.set("n", "bv", buffer_action("Vsplit: ", ":vnew ")) +vim.keymap.set("n", "bs", buffer_action("Hsplit: ", ":new ")) +vim.keymap.set("n", "br", buffer_action("Rename: ", ":file ")) + +vim.keymap.set({ "n", "v" }, "", "") +vim.keymap.set({ "n", "v" }, "H", "") +vim.keymap.set({ "n", "v" }, "", "") +vim.keymap.set({ "n", "v" }, "L", "") + +-- `s` shortcut is occupied by surround plugin +vim.keymap.set("n", "", "s") +vim.keymap.set("v", "s", "") + +vim.keymap.set("i", "", "") + +require("lazy").setup("plugins") + +vim.fn.digraph_setlist(require("digraphs")) + +require("marks") diff --git a/home/apps/nvim/lazy-lock.json b/home/apps/nvim/lazy-lock.json new file mode 100644 index 0000000..0fa06f3 --- /dev/null +++ b/home/apps/nvim/lazy-lock.json @@ -0,0 +1,39 @@ +{ + "Comment.nvim": { "branch": "master", "commit": "e30b7f2008e52442154b66f7c519bfd2f1e32acb" }, + "LuaSnip": { "branch": "master", "commit": "3732756842a2f7e0e76a7b0487e9692072857277" }, + "actions-preview.nvim": { "branch": "master", "commit": "cb938c25edaac38d362555f19244a9cb85d561e8" }, + "cmp-buffer": { "branch": "main", "commit": "b74fab3656eea9de20a9b8116afa3cfc4ec09657" }, + "cmp-cmdline": { "branch": "main", "commit": "d126061b624e0af6c3a556428712dd4d4194ec6d" }, + "cmp-emoji": { "branch": "main", "commit": "e8398e2adf512a03bb4e1728ca017ffeac670a9f" }, + "cmp-nvim-lsp": { "branch": "main", "commit": "cbc7b02bb99fae35cb42f514762b89b5126651ef" }, + "cmp-nvim-lsp-signature-help": { "branch": "main", "commit": "fd3e882e56956675c620898bf1ffcf4fcbe7ec84" }, + "cmp-path": { "branch": "main", "commit": "c642487086dbd9a93160e1679a1327be111cbc25" }, + "dressing.nvim": { "branch": "master", "commit": "2d7c2db2507fa3c4956142ee607431ddb2828639" }, + "gitsigns.nvim": { "branch": "main", "commit": "5813e4878748805f1518cee7abb50fd7205a3a48" }, + "global-note.nvim": { "branch": "main", "commit": "1e0d4bba425d971ed3ce40d182c574a25507115c" }, + "guess-indent.nvim": { "branch": "main", "commit": "84a4987ff36798c2fc1169cbaff67960aed9776f" }, + "harpoon": { "branch": "harpoon2", "commit": "87b1a3506211538f460786c23f98ec63ad9af4e5" }, + "harpoon-lualine": { "branch": "master", "commit": "215c0847dfb787b19268f7b42eed83bdcf06b966" }, + "kanagawa.nvim": { "branch": "master", "commit": "aef7f5cec0a40dbe7f3304214850c472e2264b10" }, + "lazy.nvim": { "branch": "main", "commit": "85c7ff3711b730b4030d03144f6db6375044ae82" }, + "leap.nvim": { "branch": "main", "commit": "f19d43590c4b6d31188ee1ea2954d2b7558a9e11" }, + "lualine.nvim": { "branch": "master", "commit": "47f91c416daef12db467145e16bed5bbfe00add8" }, + "mason-lspconfig.nvim": { "branch": "main", "commit": "c55bd8a8fb191e24176c206a7af1dd51ce7276a5" }, + "mason.nvim": { "branch": "main", "commit": "57e5a8addb8c71fb063ee4acda466c7cf6ad2800" }, + "mini.surround": { "branch": "main", "commit": "88c52297ed3e69ecf9f8652837888ecc727a28ee" }, + "nvim-cmp": { "branch": "main", "commit": "d97d85e01339f01b842e6ec1502f639b080cb0fc" }, + "nvim-lspconfig": { "branch": "master", "commit": "0044d0987ef7e624d04141d0f90d0481fd3c3663" }, + "nvim-treesitter": { "branch": "main", "commit": "d3218d988f72ed34414959c9ccd802d393432d6e" }, + "nvim-treesitter-textobjects": { "branch": "main", "commit": "0d7c800fadcfe2d33089f5726cb8907fc846eece" }, + "nvim-web-devicons": { "branch": "master", "commit": "8dcb311b0c92d460fac00eac706abd43d94d68af" }, + "oil.nvim": { "branch": "master", "commit": "cbcb3f997f6f261c577b943ec94e4ef55108dd95" }, + "plenary.nvim": { "branch": "master", "commit": "b9fd5226c2f76c951fc8ed5923d85e4de065e509" }, + "render-markdown.nvim": { "branch": "main", "commit": "26097a4eb95b391d0308c1b77cce89b28bbc9916" }, + "squirrel.nvim": { "branch": "main", "commit": "4f51ad87b2d35d04aaacb4aaa7c8a13449cb3d1a" }, + "telescope-fzf-native.nvim": { "branch": "main", "commit": "6fea601bd2b694c6f2ae08a6c6fab14930c60e2c" }, + "telescope.nvim": { "branch": "master", "commit": "e69b434b968a33815e2f02a5c7bd7b8dd4c7d4b2" }, + "todo-comments.nvim": { "branch": "main", "commit": "31e3c38ce9b29781e4422fc0322eb0a21f4e8668" }, + "toggleterm.nvim": { "branch": "main", "commit": "9a88eae817ef395952e08650b3283726786fb5fb" }, + "vim-bbye": { "branch": "master", "commit": "25ef93ac5a87526111f43e5110675032dbcacf56" }, + "vim-exchange": { "branch": "master", "commit": "d6c1e9790bcb8df27c483a37167459bbebe0112e" } +} diff --git a/home/apps/nvim/lua/center/init.lua b/home/apps/nvim/lua/center/init.lua new file mode 100644 index 0000000..4be07a4 --- /dev/null +++ b/home/apps/nvim/lua/center/init.lua @@ -0,0 +1,92 @@ +local M = {} + +M.cfg = { + skip_filetypes = {}, + enabled = true, +} + +M.setup = function(ctx) + if ctx == nil then + return + end + + M.cfg.skip_filetypes = ctx.skip_filetypes or {} + if type(ctx.enabled) == "boolean" then + M.cfg.enabled = ctx.enabled + end +end + +local function must_skip_file(skip_filetypes, current_type) + if skip_filetypes == nil then + return false + end + + for _, value in ipairs(skip_filetypes) do + if value == current_type then + return true + end + end + + return false +end + +local function stay_centered(ctx) + if not ctx.cfg.enabled then + return + end + if must_skip_file(ctx.cfg.skip_filetypes, vim.bo.filetype) then + return + end + + local line = vim.api.nvim_win_get_cursor(0)[1] + if line ~= vim.b.last_line then + vim.cmd("norm! zz") + -- vim.b.last_line = line + -- if ctx.mode == "insert" then + -- local column = vim.fn.getcurpos()[5] + -- vim.fn.cursor({ line, column }) + -- end + end +end + +local add_group = vim.api.nvim_create_augroup +local group = add_group("StayCentered", { clear = true }) + +local add_command = vim.api.nvim_create_autocmd +add_command("CursorMovedI", { + group = group, + callback = function() + stay_centered({ mode = "insert", cfg = M.cfg }) + end, +}) +add_command("CursorMoved", { + group = group, + callback = function() + stay_centered({ mode = "other", cfg = M.cfg }) + end, +}) +add_command("BufEnter", { + group = group, + callback = function() + stay_centered({ mode = "other", cfg = M.cfg }) + end, +}) + +M.enable = function() + M.cfg.enabled = true + stay_centered({ mode = "other", cfg = M.cfg }) +end + +M.disable = function() + M.cfg.enabled = false +end + +M.toggle = function() + if M.cfg.enabled then + M.disable() + else + M.enable() + end +end + +return M diff --git a/home/apps/nvim/lua/digraphs.lua b/home/apps/nvim/lua/digraphs.lua new file mode 100644 index 0000000..a653a6b --- /dev/null +++ b/home/apps/nvim/lua/digraphs.lua @@ -0,0 +1,32 @@ +return { + { "ps", "+" }, + { "ms", "-" }, + { "eq", "=" }, + { "pw", "^" }, + { "mt", "*" }, + { "hs", "#" }, + { "md", "%" }, + { "bt", "`" }, + { "pp", "|" }, + { "td", "~" }, + { "fs", "/" }, + { "bs", "\\" }, + { "us", "_" }, + { "qm", "?" }, + { "xm", "!" }, + { "at", "@" }, + { "sn", ";" }, + { "qt", "'" }, + { "dq", "\"" }, + { "cn", ":" }, + { "ds", "$" }, + { "as", "&" }, + { "lp", "(" }, + { "rp", ")" }, + { "lb", "{" }, + { "rb", "}" }, + { "ls", "[" }, + { "rs", "]" }, + { "la", "<" }, + { "ra", ">" }, +} diff --git a/home/apps/nvim/lua/globals.lua b/home/apps/nvim/lua/globals.lua new file mode 100644 index 0000000..a30bcce --- /dev/null +++ b/home/apps/nvim/lua/globals.lua @@ -0,0 +1,31 @@ +local M = {} + +local create_alternate = function(border_chars) + return { + border_chars[2], + border_chars[4], + border_chars[6], + border_chars[8], + border_chars[1], + border_chars[3], + border_chars[5], + border_chars[7], + } +end + +-- M.border_chars = { "┌", "─", "┐", "│", "┘", "─", "└", "│" } +-- M.border_chars_telescope_results = create_alternate({ "├", "─", "┤", "│", "┘", "─", "└", "│" }) +-- M.border_chars_telescope_prompt = create_alternate({ "┌", "─", "┐", "│", "┤", "─", "├", "│" }) + +M.border_chars = { "┏", "━", "┓", "┃", "┛", "━", "┗", "┃" } +M.border_chars_telescope_results = create_alternate({ "┣", "━", "┫", "┃", "┛", "━", "┗", "┃" }) +M.border_chars_telescope_prompt = create_alternate({ "┏", "━", "┓", "┃", "┫", "━", "┣", "┃" }) + +-- M.border_chars = { "╔", "═", "╗", "║", "╝", "═", "╚", "║" } +-- M.border_chars_telescope_results = create_alternate({ "╠", "═", "╣", "║", "╝", "═", "╚", "║" }) +-- M.border_chars_telescope_prompt = create_alternate({ "╔", "═", "╗", "║", "╣", "═", "╠", "║" }) + + +M.border_chars_alternate = create_alternate(M.border_chars) + +return M diff --git a/home/apps/nvim/lua/marks.lua b/home/apps/nvim/lua/marks.lua new file mode 100644 index 0000000..c8e98b1 --- /dev/null +++ b/home/apps/nvim/lua/marks.lua @@ -0,0 +1,7 @@ +local low = function(i) return string.char(string.byte("a")+i) end +local upp = function(i) return string.char(string.byte("A")+i) end + +for i=0,25 do vim.keymap.set("n", "m"..low(i), "m"..upp(i)) end +for i=0,25 do vim.keymap.set("n", "m"..upp(i), "m"..low(i)) end +for i=0,25 do vim.keymap.set("n", "'"..low(i), "'"..upp(i)) end +for i=0,25 do vim.keymap.set("n", "'"..upp(i), "'"..low(i)) end diff --git a/home/apps/nvim/lua/multiline/init.lua b/home/apps/nvim/lua/multiline/init.lua new file mode 100644 index 0000000..62664c3 --- /dev/null +++ b/home/apps/nvim/lua/multiline/init.lua @@ -0,0 +1,210 @@ +local M = {} + +M.setup = function(opts) + M.max_new_lines = opts.max_new_lines or 1000 + M.keep_existing = opts.keep_existing or true + M.void_bounds = opts.void_bounds or true +end + +M.nlines = function(count) + -- Please, tell me there is a better way + local output = {} + for _ = 1, count do + table.insert(output, "") + end + return output +end + +M.remove_surround = function() + local line = vim.api.nvim_win_get_cursor(0)[1] + local lines = vim.api.nvim_buf_line_count(0) + + local count = math.max(1, vim.v.count) + + -- Bottom pad + local delete_bottom = 0 + for _ = 1, count do + local delete_line = line + delete_bottom + if delete_line == lines then + break + end + local next_line = vim.api.nvim_buf_get_lines(0, delete_line, delete_line + 1, false)[1] + if vim.trim(next_line) ~= "" then + break + end + delete_bottom = delete_bottom + 1 + end + vim.api.nvim_buf_set_lines(0, line, line + delete_bottom, false, {}) + + -- Top pad + local delete_top = 0 + for _ = 1, count do + local delete_line = line - delete_top + if delete_line == 1 then + break + end + local prev_line = vim.api.nvim_buf_get_lines(0, delete_line - 2, delete_line - 1, false)[1] + if vim.trim(prev_line) ~= "" then + break + end + delete_top = delete_top + 1 + end + vim.api.nvim_buf_set_lines(0, line - delete_top - 1, line - 1, false, {}) +end + +M.remove_all_surround = function() + local line = vim.api.nvim_win_get_cursor(0)[1] + local lines = vim.api.nvim_buf_line_count(0) + + -- Bottom pad + local delete_bottom = 0 + while true do + local delete_line = line + delete_bottom + if delete_line == lines then + break + end + local next_line = vim.api.nvim_buf_get_lines(0, delete_line, delete_line + 1, false)[1] + if vim.trim(next_line) ~= "" then + break + end + delete_bottom = delete_bottom + 1 + end + vim.api.nvim_buf_set_lines(0, line, line + delete_bottom, false, {}) + + -- Top pad + local delete_top = 0 + while true do + local delete_line = line - delete_top + if delete_line == 1 then + break + end + local prev_line = vim.api.nvim_buf_get_lines(0, delete_line - 2, delete_line - 1, false)[1] + if vim.trim(prev_line) ~= "" then + break + end + delete_top = delete_top + 1 + end + vim.api.nvim_buf_set_lines(0, line - delete_top - 1, line - 1, false, {}) +end + +M.surround_newlines = function(input) + return function() + local line = vim.api.nvim_win_get_cursor(0)[1] + local lines = vim.api.nvim_buf_line_count(0) + + local count = math.min(math.max(1, vim.v.count), M.max_new_lines) + + -- Bottom pad + local add_bottom = count + if M.keep_existing then + for i = 1, count do + if line + i - 1 == lines then + if M.void_bounds then + add_bottom = 0 + end + break + end + local next_line = vim.api.nvim_buf_get_lines(0, line + i - 1, line + i, false)[1] + if vim.trim(next_line) == "" then + add_bottom = add_bottom - 1 + else + break + end + end + end + vim.api.nvim_buf_set_lines(0, line, line, false, M.nlines(add_bottom)) + + -- Top pad + local add_top = count + if M.keep_existing then + for i = 1, count do + if line - i + 1 == 1 then + if M.void_bounds then + add_top = 0 + end + break + end + local prev_line = vim.api.nvim_buf_get_lines(0, line - i - 1, line - i, false)[1] + if vim.trim(prev_line) == "" then + add_top = add_top - 1 + else + break + end + end + end + vim.api.nvim_buf_set_lines(0, line - 1, line - 1, false, M.nlines(add_top)) + + if input ~= "" then + vim.api.nvim_input(input) + end + end +end + +M.next_surround = function(input) + return function() + local line = vim.api.nvim_win_get_cursor(0)[1] + local count = math.min(math.max(1, vim.v.count), M.max_new_lines) + vim.api.nvim_buf_set_lines(0, line, line, false, M.nlines(count)) + vim.api.nvim_win_set_cursor(0, { line + count, 0 }) + if input ~= "" then + vim.api.nvim_input(input) + end + end +end + +M.prev_surround = function(input) + return function() + local line = vim.api.nvim_win_get_cursor(0)[1] + local count = math.min(math.max(1, vim.v.count), M.max_new_lines) + vim.api.nvim_buf_set_lines(0, line - 1, line - 1, false, M.nlines(count)) + vim.api.nvim_win_set_cursor(0, { line, 0 }) + if input ~= "" then + vim.api.nvim_input(input) + end + end +end + +M.set_surround = function() + M.remove_all_surround() + M.surround_newlines("")() +end + +-- Breaking lines with whitespace is a bit wonky but I don't care +M.break_into_lines = function() + local v_start = vim.fn.getpos("v") + local v_end = vim.fn.getpos(".") + if (v_end[2] < v_start[2]) or (v_end[2] == v_start[2] and v_end[3] < v_start[3]) then + v_start, v_end = v_end, v_start + end + + -- End split + local end_line = vim.api.nvim_buf_get_lines(0, v_end[2] - 1, v_end[2], false)[1] + if v_end[3] < #end_line then + local line_start = end_line:sub(1, v_end[3]):gsub("%s+$", "") + local line_end = end_line:sub(v_end[3] + 1):gsub("^%s+", "") + local pad = line_start:match("^%s+") or "" + vim.api.nvim_buf_set_lines(0, v_end[2] - 1, v_end[2], false, { + line_start, + pad .. line_end + }) + end + + -- Start split + local start_line = vim.api.nvim_buf_get_lines(0, v_start[2] - 1, v_start[2], false)[1] + if v_start[3] > 1 then + local line_start = start_line:sub(1, v_start[3] - 1):gsub("%s+$", "") + local line_end = start_line:sub(v_start[3]):gsub("^%s+", "") + local pad = line_start:match("^%s+") or "" + vim.api.nvim_buf_set_lines(0, v_end[2] - 1, v_end[2], false, { + line_start, + pad .. line_end + }) + vim.api.nvim_win_set_cursor(0, { v_start[2] + 1, vim.v.maxcol }) + else + vim.api.nvim_win_set_cursor(0, { v_start[2], vim.v.maxcol }) + end + + vim.api.nvim_input(">>") +end + +return M diff --git a/home/apps/nvim/lua/plugins/colors.lua b/home/apps/nvim/lua/plugins/colors.lua new file mode 100644 index 0000000..056ce8d --- /dev/null +++ b/home/apps/nvim/lua/plugins/colors.lua @@ -0,0 +1,104 @@ +return { + { + "rebelot/kanagawa.nvim", + lazy = false, + priority = 1024, + config = function() + local transparent = true + if vim.g.neovide then + transparent = false + end + local color_overrides = {} + if transparent then + color_overrides = { theme = { all = { ui = { bg_gutter = "NONE" } } } } + end + require("kanagawa").setup({ + transparent = transparent, + compile = false, + undercurl = false, + commentStyle = { italic = false, bold = false }, + keywordStyle = { italic = false, bold = false }, + statementStyle = { italic = false, bold = false }, + colors = color_overrides, + overrides = function(colors) + return { + ["Boolean"] = { bold = false }, + ["Todo"] = { bold = false }, + ["@variable.builtin"] = { italic = false }, + ["@string.escape"] = { bold = false }, + ["@keyword.operator"] = { bold = false }, + ["@comment.error"] = { bold = false }, + ["@comment.warning"] = { bold = false }, + ["@comment.note"] = { bold = false }, + ["Conceal"] = { bold = false }, + ["CursorLineNr"] = { bold = false }, + ["CurSearch"] = { bold = false }, + ["MatchParen"] = { bold = false }, + ["ModeMsg"] = { bold = false }, + ["FloatTitle"] = { bold = false }, + ["Title"] = { bold = false }, + ["LinePad"] = { fg = colors.theme.ui.nontext, bg = colors.theme.ui.bg_gutter }, + ["FloatBorder"] = { fg = colors.theme.ui.float.fg_border, bg = not transparent and colors.theme.ui.bg or "NONE" }, + ["CmdlineCommand"] = { fg = colors.theme.diag.warning, bg = colors.theme.ui.bg }, + ["Pmenu"] = { bg = colors.theme.ui.bg_m3 }, + ["PmenuSbar"] = { bg = colors.theme.ui.bg_m1 }, + ["PmenuThumb"] = { bg = colors.theme.term[9] }, + ["PmenuSel"] = { bg = colors.theme.bg_visual }, + ["NormalFloat"] = { bg = not transparent and colors.theme.ui.float.bg or "NONE" }, + ["Whitespace"] = { fg = "#606060" }, + ["NonText"] = { fg = "#606060" }, + -- Markdown + ["RenderMarkdownUnchecked"] = { fg = "#54546d" }, + ["RenderMarkdownChecked"] = { fg = "#54546D" }, + ["RenderMarkdownWip"] = { fg = "#7FB4CA" }, + ["RenderMarkdownCanceled"] = { fg = "#54546D" }, + ["RenderMarkdownImportant"] = { fg = "#FFA066" }, + ["RenderMarkdownUnknown"] = { fg = "#727169" }, + ["RenderMarkdownIdea"] = { fg = "#FFA066" }, + ["RenderMarkdownStar"] = { fg = "#FFA066" }, + ["RenderMarkdownPositive"] = { link = "@diff.plus" }, + ["RenderMarkdownNegative"] = { link = "@diff.minus" }, + ["RenderMarkdownCheckedScope"] = { fg = "#54546D", strikethrough = true }, + ["RenderMarkdownH1"] = { fg = "#957FB8", bg = "#2A2A37" }, + ["RenderMarkdownH1Bg"] = { fg = "#957FB8", bg = "#2A2A37" }, + ["RenderMarkdownH2"] = { fg = "#98BB6C", bg = "#2A2A37" }, + ["RenderMarkdownH2Bg"] = { fg = "#98BB6C", bg = "#2A2A37" }, + ["RenderMarkdownH3"] = { fg = "#7FB4CA", bg = "#2A2A37" }, + ["RenderMarkdownH3Bg"] = { fg = "#7FB4CA", bg = "#2A2A37" }, + ["RenderMarkdownH4"] = { fg = "#7FB4CA", bg = "#2A2A37" }, + ["RenderMarkdownH4Bg"] = { fg = "#7FB4CA", bg = "#2A2A37" }, + ["RenderMarkdownH5"] = { fg = "#7FB4CA", bg = "#2A2A37" }, + ["RenderMarkdownH5Bg"] = { fg = "#7FB4CA", bg = "#2A2A37" }, + ["RenderMarkdownH6"] = { fg = "#7FB4CA", bg = "#2A2A37" }, + ["RenderMarkdownH6Bg"] = { fg = "#7FB4CA", bg = "#2A2A37" }, + ["RenderMarkdownCode"] = { bg = "#24252D" }, + ["RenderMarkdownCodeInline"] = { bg = "#24252D" }, + } + end, + }) + local termcolors = { + "#282A2E", + "#A54242", + "#8C9440", + "#DE935F", + "#5F819D", + "#85678F", + "#5E8D87", + "#707880", + "#373B41", + "#FF5555", + "#B5BD68", + "#F0C674", + "#81A2BE", + "#B294BB", + "#8ABEB7", + "#C5C8C6", + } + vim.cmd("colorscheme kanagawa-wave") + for i, color in ipairs(termcolors) do + vim.g["terminal_color_" .. i - 1] = color + end + vim.api.nvim_set_hl(0, "ExchangeRegion", { link = "CursorLine" }) + end, + }, +} diff --git a/home/apps/nvim/lua/plugins/editing.lua b/home/apps/nvim/lua/plugins/editing.lua new file mode 100644 index 0000000..4eae12d --- /dev/null +++ b/home/apps/nvim/lua/plugins/editing.lua @@ -0,0 +1,107 @@ +return { + { + name = "scripter", + dir = vim.fn.stdpath("config") .. "/lua/scripter", + keys = { + { "ss", desc = "Reset Scripter" }, + { "sr", desc = "Temporarily Set Scripter to Cyrillic" }, + { "sR", desc = "Set Scripter to Cyrillic" }, + }, + config = function() + local scripter = require("scripter") + local presets = require("scripter.presets") + scripter.setup({ + consume = false, + }) + vim.keymap.set("n", "ss", scripter.mapping.set_script({})) + vim.keymap.set("n", "sr", scripter.mapping.set_script(presets.cyrillic, true)) + vim.keymap.set("n", "sR", scripter.mapping.set_script(presets.cyrillic, false)) + vim.keymap.set("i", "", function() + scripter.reset() + vim.api.nvim_feedkeys("\b", "n", false); + end) + end + }, + { + name = "multiline", + dir = vim.fn.stdpath("config") .. "/lua/multiline", + keys = { + { "", desc = "Surround with newlines" }, + { "o", desc = "Begin a new line below" }, + { "O", desc = "Begin a new line above" }, + { "yo", desc = "Begin a new line below and repeat it [count] times" }, + { "yO", desc = "Begin a new line above and repeat it [count] times" }, + { "d", desc = "Remove newline surround" }, + { "D", desc = "Remove all newline surround" }, + { "f", desc = "Set newline surround" }, + { "b", desc = "Break selection into a new line" }, + }, + config = function() + local multiline = require("multiline") + multiline.setup({}) + + vim.keymap.set({ "n", "v" }, "", multiline.surround_newlines(""), {}) + vim.keymap.set("n", "o", multiline.next_surround("\"_S"), {}) + vim.keymap.set("n", "O", multiline.prev_surround("\"_S"), {}) + vim.keymap.set("n", "yo", "o") + vim.keymap.set("n", "yO", "O") + vim.keymap.set("n", "d", multiline.remove_surround, {}) + vim.keymap.set("n", "D", multiline.remove_all_surround, {}) + vim.keymap.set("n", "f", multiline.set_surround, {}) + vim.keymap.set("v", "b", multiline.break_into_lines, {}) + end, + }, + { + "tommcdo/vim-exchange", + keys = { + { "cxx", desc = "Exchange line" }, + { "cx", desc = "Exchange motion" }, + { "X", desc = "Exchange selection" }, + { "cxc", desc = "Clear exchange" }, + }, + }, + { + "echasnovski/mini.surround", + keys = { + { "ss", desc = "Surround: Add", mode = { "n", "v" } }, + { "sd", desc = "Surround: Delete" }, + { "sf", desc = "Surround: Find (right)" }, + { "sF", desc = "Surround: Find (left)" }, + { "sr", desc = "Surround: Replace" }, + }, + opts = { + mappings = { + add = "ss", + delete = "sd", + find = "sf", + find_left = "sF", + highlight = "", + replace = "sr", + update_n_lines = "sn", + } + }, + }, + { + "numToStr/Comment.nvim", + event = "VeryLazy", + config = true, + }, + { + "nmac427/guess-indent.nvim", + lazy = false, + keys = { + { "gi", "GuessIndent", "Guess Indentation" }, + }, + opts = { + auto_cmd = true, + on_tab_options = { + ["expandtab"] = false, + }, + on_space_options = { + ["expandtab"] = true, + ["tabstop"] = "detected", + ["shiftwidth"] = "detected", + }, + }, + } +} diff --git a/home/apps/nvim/lua/plugins/lsp.lua b/home/apps/nvim/lua/plugins/lsp.lua new file mode 100644 index 0000000..5f35621 --- /dev/null +++ b/home/apps/nvim/lua/plugins/lsp.lua @@ -0,0 +1,217 @@ +return { + { + "nvim-treesitter/nvim-treesitter", + opts = {}, + build = ":TSUpdate", + }, + { + "neovim/nvim-lspconfig", + dependencies = { + "hrsh7th/cmp-nvim-lsp", + }, + lazy = false, + keys = { + { "w", "Format", desc = "Format" }, + { "W", "Formatwrite", desc = "Format & Write" }, + }, + config = function() + local capabilities = require("cmp_nvim_lsp").default_capabilities() + + -- TODO: Gotta make this into an quick toggle + + -- vim.api.nvim_create_autocmd("LspAttach", { + -- callback = function(args) + -- local client = vim.lsp.get_client_by_id(args.data.client_id) + -- + -- if client and client.server_capabilities.inlayHintProvider then + -- vim.lsp.inlay_hint.enable(true, { bufnr = args.buf }) + -- end + -- end + -- }) + require("lspconfig").lua_ls.setup({ + on_init = function(client) + client.config.settings.Lua = vim.tbl_deep_extend("force", client.config.settings.Lua, { + runtime = { version = "LuaJIT" }, + workspace = { + checkThirdParty = false, + library = { vim.env.VIMRUNTIME }, + }, + }) + end, + settings = { Lua = {} }, + capabilities = capabilities, + }) + local lsp_servers = { + "rust_analyzer", + "clangd", + "pylsp", + "marksman", + "taplo", + "zls", + "ts_ls", + "gopls", + "texlab", + "qmlls", + } + local lsp_config = require("lspconfig") + for _, lsp_server in ipairs(lsp_servers) do + lsp_config[lsp_server].setup({ + capabilities = capabilities, + }) + end + vim.api.nvim_create_autocmd("LspAttach", { + group = vim.api.nvim_create_augroup("UserLspConfig", {}), + callback = function(ev) + vim.api.nvim_buf_create_user_command(ev.buf, "Format", function(_) + vim.lsp.buf.format() + end, { desc = "Format current buffer with LSP" }) + end + }) + end, + }, + { + "hrsh7th/nvim-cmp", + dependencies = { + "nvim-tree/nvim-web-devicons", + "hrsh7th/cmp-buffer", + "hrsh7th/cmp-nvim-lsp-signature-help", + "hrsh7th/cmp-emoji", + "hrsh7th/cmp-path", + "hrsh7th/cmp-cmdline", + "L3MON4D3/LuaSnip", + }, + event = "VeryLazy", + config = function() + local cmp = require("cmp") + local kinds = { + Field = { " Field", "Identifier" }, + Class = { " Type", "Type" }, + Variable = { "󰽏 Variable", "Statement" }, + Method = { " Method", "Function" }, + Function = { "󰊕 Function", "Function" }, + Enum = { "󰷐 Enum", "Boolean" }, + Keyword = { " Keyword", "Keyword" }, + Constant = { "󰽏 Const", "Boolean" }, + Struct = { " Struct", "Type" }, + Interface = { "󱇯 Trait", "Type" }, + Module = { " Module", "Statement" }, + EnumMember = { "󰷐 Value", "Boolean" }, + File = { " File", "Statement" }, + Snippet = { " Snippet", "Keyword" }, + Value = { "󰎠 Value", "Number" }, + Property = { "󰜢 Field", "Identifier" }, + Reference = { " Reference", "Statement" }, + Text = { " Text", "String" }, + Folder = { "󰉋 Folder", "Statement" }, + -- Left as an exercise to the reader + -- Constructor = "", + -- Unit = "", + -- Color = "󰏘", + -- Event = "", + -- Operator = "󰆕", + -- TypeParameter = "󰅲", + } + for kind, link in pairs(kinds) do + vim.api.nvim_set_hl(0, "CmpItemKind" .. kind, { link = link[2] }) + end + local omnicomplete = function(fallback) + if cmp.visible() then + cmp.mapping.confirm({ select = true })(fallback) + else + cmp.mapping.complete()(fallback) + end + end + local formatting = { + format = function(_, vim_item) + local custom = kinds[vim_item.kind] + if custom then + vim_item.kind = string.format("%-12s", custom[1]) + else + vim_item.kind = string.format("%-12s", vim_item.kind) + end + if vim_item.abbr then + local content = vim_item.abbr + local fixed_width = 32 + if #content > fixed_width then + local ellipsis = "" + vim_item.abbr = " " .. vim.fn.strcharpart(content, 0, fixed_width - 1) .. ellipsis + else + vim_item.abbr = " " .. string.format("%-32s", content) + end + end + vim_item.menu = "" + return vim_item + end, + fields = { + "abbr", + "kind", + }, + } + local mapping = ({ + -- QWERTY mappings + [""] = { i = omnicomplete, c = omnicomplete }, + [""] = { i = cmp.mapping.select_next_item(), c = cmp.mapping.select_next_item() }, + [""] = { i = cmp.mapping.select_prev_item(), c = cmp.mapping.select_prev_item() }, + [""] = { i = cmp.mapping.abort(), c = cmp.mapping.abort() }, + [""] = { i = cmp.mapping.scroll_docs(6), c = cmp.mapping.scroll_docs(6) }, + [""] = { i = cmp.mapping.scroll_docs(-6), c = cmp.mapping.scroll_docs(-6) }, + -- Colemak mappings + [""] = { i = omnicomplete, c = omnicomplete }, + [""] = { i = cmp.mapping.select_next_item(), c = cmp.mapping.select_next_item() }, + [""] = { i = cmp.mapping.select_prev_item(), c = cmp.mapping.select_prev_item() }, + [""] = { i = cmp.mapping.abort(), c = cmp.mapping.abort() }, + [""] = { i = cmp.mapping.scroll_docs(6), c = cmp.mapping.scroll_docs(6) }, + [""] = { i = cmp.mapping.scroll_docs(-6), c = cmp.mapping.scroll_docs(-6) }, + }) + local window = { + completion = { + side_padding = 0, + }, + documentation = { + max_width = 64, + max_height = 16, + }, + } + cmp.setup({ + -- completion = { + -- autocomplete = true, + -- completeopt = "menu,menuone", + -- }, + formatting = formatting, + snippet = { + expand = function(args) + require('luasnip').lsp_expand(args.body) + end, + }, + sources = cmp.config.sources({ + -- FIXME: Suggestion sorting is bogus; + -- All the useful suggestions are at the bottom + { name = "nvim_lsp" }, + { name = "nvim_lsp_signature_help" }, + { name = "buffer" }, + { name = "render-markdown" }, + { name = "emoji" }, + { name = "path" }, + }), + mapping = mapping, + window = window, + }) + cmp.setup.cmdline("/", { + sources = cmp.config.sources({ + { name = "buffer" }, + }), + mapping = mapping, + }) + cmp.setup.cmdline(":", { + sources = cmp.config.sources({ + { name = "path" }, + { + name = 'cmdline', + option = { ignore_cmds = { 'Man', '!' } } + }, + }), + mapping = mapping, + }) + end, + }, +} diff --git a/home/apps/nvim/lua/plugins/lualine.lua b/home/apps/nvim/lua/plugins/lualine.lua new file mode 100644 index 0000000..d718a03 --- /dev/null +++ b/home/apps/nvim/lua/plugins/lualine.lua @@ -0,0 +1,71 @@ +local lualine_pad = { + "", + separator = { left = "", right = "" }, + padding = 0, + color = "Normal", + fmt = function(input, context) + local winnr = vim.fn.tabpagewinnr(context.tabnr) + return string.rep("⠀", require("winpad").get_pad_size(winnr)) .. input + end +} +return { + { + "letieu/harpoon-lualine", + dependencies = { + { + "ThePrimeagen/harpoon", + branch = "harpoon2", + } + }, + }, + { + "nvim-lualine/lualine.nvim", + dependencies = { + "nvim-tree/nvim-web-devicons", + "winpad", + "letieu/harpoon-lualine", + }, + config = true, + opts = { + options = { + theme = "auto", + refresh = { statusline = 1000, tabline = 1000, winbar = 1000 }, + section_separators = { left = "▌", right = "▐" }, + component_separators = { left = "", right = "" }, + }, + sections = { + lualine_a = { + lualine_pad, + { + "mode", + separator = { left = "" }, + }, + }, + lualine_b = { "filename", "diff" }, + lualine_c = {}, + lualine_x = { + { + "harpoon2", + icon = "󰀱", + indicators = { "1", "2", "3", "4", "5" }, + active_indicators = { "1", "2", "3", "4", "5" }, + color = { fg = "#a0a0c0" }, + color_active = { fg = "#fc6346" }, + }, + -- It's him! The legendary cat2! + { function() return "🐈" end }, "diagnostics" + }, + lualine_y = { "branch" }, + lualine_z = {}, + }, + inactive_sections = { + lualine_a = { lualine_pad }, + lualine_b = { "filename" }, + lualine_c = {}, + lualine_x = {}, + lualine_y = {}, + lualine_z = { function() return "👀" end }, + }, + }, + } +} diff --git a/home/apps/nvim/lua/plugins/markdown.lua b/home/apps/nvim/lua/plugins/markdown.lua new file mode 100644 index 0000000..2496482 --- /dev/null +++ b/home/apps/nvim/lua/plugins/markdown.lua @@ -0,0 +1,31 @@ +return { + "MeanderingProgrammer/render-markdown.nvim", + dependencies = { "nvim-treesitter/nvim-treesitter", "nvim-tree/nvim-web-devicons" }, + opts = { + checkbox = { + position = "inline", + unchecked = { + icon = "󰳟 [ ]", + }, + checked = { + icon = "󰳟 []", + scope_highlight = "RenderMarkdownCheckedScope", + }, + custom = { + in_progress = { raw = "[/]", rendered = "󰳟 []", highlight = "RenderMarkdownWip", scope_highlight = nil }, + todo = { raw = "[-]", rendered = "󰳟 []", highlight = "RenderMarkdownCanceled", scope_highlight = "RenderMarkdownCheckedScope" }, + important = { raw = "[!]", rendered = "󰳟 []", highlight = "RenderMarkdownImportant", scope_highlight = nil }, + unknown = { raw = "[?]", rendered = "󰳟 []", highlight = "RenderMarkdownUnknown", scope_highlight = nil }, + idea = { raw = "[@]", rendered = "󰳟 []", highlight = "RenderMarkdownIdea", scope_highlight = nil }, + starred = { raw = "[*]", rendered = "󰳟 []", highlight = "RenderMarkdownStar", scope_highlight = nil }, + positive = { raw = "[+]", rendered = "󰳟 [+]", highlight = "RenderMarkdownPositive", scope_highlight = nil }, + negative = { raw = "[=]", rendered = "󰳟 [-]", highlight = "RenderMarkdownNegative", scope_highlight = nil }, + }, + }, + code = { + above = "█", + below = "█", + inline_pad = 1, + }, + }, +} diff --git a/home/apps/nvim/lua/plugins/misc.lua b/home/apps/nvim/lua/plugins/misc.lua new file mode 100644 index 0000000..40f65b0 --- /dev/null +++ b/home/apps/nvim/lua/plugins/misc.lua @@ -0,0 +1,175 @@ +return { + { + "akinsho/toggleterm.nvim", + keys = { + { "", desc = "Toggle Terminal" }, + { "mr", "TermExec cmd=\"make run\"", desc = "Make (run)" }, + { "mb", "TermExec cmd=\"make build\"", desc = "Make (build)" }, + { "mc", "TermExec cmd=\"make clean\"", desc = "Make (clean)" }, + { "mt", "TermExec cmd=\"make test\"", desc = "Make (test)" }, + }, + opts = { + autochdir = true, + open_mapping = "", + direction = "float", + shade_terminals = false, + float_opts = { + border = require("globals").border_chars, + }, + highlights = { + ["FloatBorder"] = { + link = "FloatBorder" + } + }, + }, + }, + { + name = "winpad", + dir = vim.fn.stdpath("config") .. "/lua/winpad", + config = function() + local winpad = require("winpad") + winpad.setup({ + enabled = true, + }) + vim.keymap.set("n", "x", winpad.toggle, { desc = "Toggle Window Padding" }) + end + }, + { + "backdround/global-note.nvim", + keys = { + { "nn", "ProjectNote", desc = "Project Note" }, + { "nf", "FileNote", desc = "File Note" }, + { "N", "GlobalNote", desc = "Global Note" }, + }, + config = function() + local global_note = require("global-note") + global_note.setup({ + title = "Global Note", + directory = "~/Documents/Notes/Repos", + filename = "global_note.md", + command_name = "GlobalNote", + window_config = function() + local window_height = vim.api.nvim_list_uis()[1].height + local window_width = vim.api.nvim_list_uis()[1].width + return { + relative = "editor", + border = require("globals").border_chars, + title = "Note", + title_pos = "center", + width = math.floor(0.7 * window_width), + height = math.floor(0.85 * window_height), + row = math.floor(0.05 * window_height), + col = math.floor(0.15 * window_width), + } + end, + additional_presets = { + project = { + title = "Project Note", + command_name = "ProjectNote", + filename = function() + local repo = vim.system({ + "git", + "rev-parse", + "--show-toplevel", + }, { + text = true, + }):wait() + if repo.stderr ~= "" then + vim.notify(repo.stderr, vim.log.levels.WARN) + return nil + end + + local project_name = vim.fs.basename(repo.stdout:gsub("\n", "")) + if project_name == nil then + vim.notify("Unable to get project name ", vim.log.levels.WARN) + return nil + end + + return project_name .. ".md" + end, + }, + file = { + title = "File Note", + command_name = "FileNote", + directory = vim.fn.getcwd, + filename = "notes.md", + }, + }, + }) + end + }, + { + "moll/vim-bbye", + keys = { + { "bd", "Bdelete", desc = "Delete current buffer" }, + { "bD", "Bwipeout", desc = "Delete all buffers" }, + { "bc", desc = "Clean buffers" }, -- TODO: Implement the thing + }, + }, + { + "stevearc/oil.nvim", + dependencies = { "nvim-tree/nvim-web-devicons" }, + keys = { + { "e", "Oil", desc = "File Explorer" }, + { "E", "Oil ./", desc = "CWD Explorer" }, + }, + opts = {}, + }, + { + "ThePrimeagen/harpoon", + branch = "harpoon2", + requires = { "nvim-lua/plenary.nvim" }, + keys = { + { "za", desc = "Add buffer to harpoon" }, + { "zs", desc = "Seek harpoon buffers" }, + { "zd", desc = "Remove buffer from harpoon" }, + { "zx", desc = "Previous harpoon buffer" }, + { "zc", desc = "Next harpoon buffer" }, + { "1" }, + { "2" }, + { "3" }, + { "4" }, + }, + config = function() + local harpoon = require("harpoon") + harpoon:setup({ + settings = { save_on_ui_close = true, save_on_toggle = true }, + }) + vim.keymap.set("n", "za", function() harpoon:list():add() end) + vim.keymap.set("n", "zs", + function() + harpoon.ui:toggle_quick_menu(harpoon:list(), { + border = require("globals").border_chars, + title = " Buffers ", + title_pos = "center", + }) + end) + vim.keymap.set("n", "zd", function() harpoon:list():remove() end) + vim.keymap.set("n", "zx", function() harpoon:list():prev() end) + vim.keymap.set("n", "zc", function() harpoon:list():next() end) + local keys = "1234567890" + for i = 1, #keys do + local key = keys:sub(i, i) + vim.keymap.set("n", string.format("%s", key), function() + harpoon:list():select(i) + end) + end + harpoon:extend({ + UI_CREATE = function(cx) + for i = 1, #keys do + local key = keys:sub(i, i) + vim.keymap.set("n", key, function() + harpoon:list():select(i) + end, { buffer = cx.bufnr }) + end + vim.keymap.set("n", "", function() + harpoon.ui:select_menu_item({ vsplit = true }) + end, { buffer = cx.bufnr }) + vim.keymap.set("n", "", function() + harpoon.ui:select_menu_item({ split = true }) + end, { buffer = cx.bufnr }) + end, + }) + end, + } +} diff --git a/home/apps/nvim/lua/plugins/motion.lua b/home/apps/nvim/lua/plugins/motion.lua new file mode 100644 index 0000000..3025943 --- /dev/null +++ b/home/apps/nvim/lua/plugins/motion.lua @@ -0,0 +1,89 @@ +return { + { + "xiaoshihou514/squirrel.nvim", + keys = { + { "", desc = "Hop" }, + }, + config = function() + require("squirrel.utils").key_iter.keys = "ntesiroa" + vim.keymap.set({ "n", "v" }, "", function() + vim.cmd(".mark '") + require("squirrel.hop").hop() + end) + end, + }, + { + "ggandor/leap.nvim", + keys = { + { "M", "(leap)", desc = "Leap" }, + }, + config = function() + local leap = require("leap") + leap.opts.safe_lables = "" + end, + }, + { + "nvim-treesitter/nvim-treesitter-textobjects", + branch = "main", + config = function() + local move_actions = { + ["f"] = "function", + ["t"] = "class", + ["r"] = "return", + ["a"] = "parameter", + ["d"] = "comment", + } + local goto_next_start = {} + local goto_next_end = {} + local goto_previous_start = {} + local goto_previous_end = {} + for letter, action in pairs(move_actions) do + local letter_lower = string.lower(letter) + local letter_upper = string.upper(letter) + goto_next_start["]" .. letter_lower] = { + query = string.format("@%s.outer", action), + desc = string.format("Next %s start", action), + } + goto_next_end["]" .. letter_upper] = { + query = string.format("@%s.outer", action), + desc = string.format("Next %s end", action), + } + goto_previous_start["[" .. letter_lower] = { + query = string.format("@%s.outer", action), + desc = string.format("Previous %s start", action), + } + goto_previous_end["[" .. letter_upper] = { + query = string.format("@%s.outer", action), + desc = string.format("Previous %s end", action), + } + end + require("nvim-treesitter-textobjects").setup({ + select = { + enable = true, + lookahead = true, + keymaps = { + ["af"] = { query = "@function.outer", desc = "function" }, + ["if"] = { query = "@function.inner", desc = "function" }, + ["at"] = { query = "@class.outer", desc = "type" }, + ["it"] = { query = "@class.inner", desc = "type" }, + ["aa"] = { query = "@parameter.outer", desc = "parameter" }, + ["ia"] = { query = "@parameter.inner", desc = "parameter" }, + ["ac"] = { query = "@call.outer", desc = "call" }, + ["ic"] = { query = "@call.inner", desc = "call" }, + ["ad"] = { query = "@comment.outer", desc = "comment" }, + ["id"] = { query = "@comment.inner", desc = "comment" }, + }, + include_surrounding_whitespace = true, + }, + move = { + enable = true, + set_jumps = true, + goto_next_start = goto_next_start, + goto_next_end = goto_next_end, + goto_previous_start = goto_previous_start, + goto_previous_end = goto_previous_end, + }, + }) + end, + }, +} diff --git a/home/apps/nvim/lua/plugins/snip.lua b/home/apps/nvim/lua/plugins/snip.lua new file mode 100644 index 0000000..40ebdeb --- /dev/null +++ b/home/apps/nvim/lua/plugins/snip.lua @@ -0,0 +1,29 @@ +return { + "L3MON4D3/LuaSnip", + keys = { + { "", desc = "Expand Snippet", mode = "i" }, + }, + config = function() + local ls = require("luasnip") + + vim.keymap.set({ "i", "s" }, "", function() ls.expand_or_jump() end, { silent = true }) + -- vim.keymap.set({ "i", "s" }, "", function() ls.jump(1) end, { silent = true }) + -- vim.keymap.set({ "i", "s" }, "", function() ls.jump(-1) end, { silent = true }) + + vim.keymap.set({ "i", "s" }, "", function() + if ls.choice_active() then + ls.change_choice(1) + else + vim.api.nvim_feedkeys("\t", "n", false); + end + end, { silent = true }) + + ls.setup({ + link_roots = true, + keep_roots = true, + delete_check_events = "TextChanged", + }) + + require("luasnip.loaders.from_lua").load({ paths = vim.fn.stdpath('config') .. "/snippets" }) + end, +} diff --git a/home/apps/nvim/lua/plugins/telescope.lua b/home/apps/nvim/lua/plugins/telescope.lua new file mode 100644 index 0000000..7d522ac --- /dev/null +++ b/home/apps/nvim/lua/plugins/telescope.lua @@ -0,0 +1,204 @@ +return { + { "nvim-telescope/telescope-fzf-native.nvim", build = "make" }, + { + "nvim-telescope/telescope.nvim", + dependencies = { + "nvim-lua/plenary.nvim", + "nvim-telescope/telescope-fzf-native.nvim", + }, + keys = { + { "t", desc = "Resume Search" }, + { "f", desc = "Find All Files" }, + { "F", desc = "Find Git Files" }, + { "/", desc = "FZF In File" }, + { "G", desc = "Grep Text" }, + { "Z", desc = "Buffer Telescope Menu" }, + { "d", desc = "Local Diagnostics" }, + { "D", desc = "Global Diagnostics" }, + { "gc", desc = "List Commits" }, + { "gC", desc = "List All Commits" }, + { "gs", desc = "Git Status" }, + { "hk", desc = "Search keymaps" }, + { "gO", desc = "Local Symbols" }, + { "gS", desc = "Global Symbols" }, + { "grr", desc = "References" }, + { "gri", desc = "Definitions" }, + }, + config = function() + local actions = require("telescope.actions") + + require('telescope.pickers.layout_strategies').horizontal_merged = + function(picker, max_columns, max_lines, layout_config) + local layout = require('telescope.pickers.layout_strategies').horizontal(picker, max_columns, + max_lines, + layout_config) + local overdraw_chars = require("globals").border_chars_joined + + layout.results.line = layout.results.line - 1 + layout.results.height = layout.results.height + 1 + layout.results.title = '' + layout.results.borderchars = require("globals").border_chars_telescope_results + + layout.prompt.borderchars = require("globals").border_chars_telescope_prompt + + if layout.preview then + layout.preview.title = '' + end + return layout + end + + require("telescope").setup({ + defaults = { + prompt_prefix = " ", + selection_caret = "👉", + sorting_strategy = "ascending", + layout_config = { + width = 0.90, + height = 0.90, + prompt_position = "top", + preview_width = 0.5, + }, + layout_strategy = "horizontal_merged", + wrap_results = true, + borderchars = require("globals").border_chars_alternate, + default_mappings = { + n = { + [""] = actions.close, + ["j"] = actions.move_selection_next, + ["k"] = actions.move_selection_previous, + ["h"] = actions.select_default, + ["l"] = actions.close, + ["H"] = actions.move_to_top, + ["L"] = actions.move_to_bottom, + [""] = actions.preview_scrolling_down, + [""] = actions.preview_scrolling_up, + [""] = actions.preview_scrolling_left, + [""] = actions.preview_scrolling_right, + }, + i = { + [""] = false, + [""] = false, + -- QWERTY mappings + [""] = actions.select_default, + [""] = actions.move_selection_next, + [""] = actions.move_selection_previous, + [""] = actions.close, + [""] = actions.preview_scrolling_down, + [""] = actions.preview_scrolling_up, + [""] = actions.preview_scrolling_left, + [""] = actions.preview_scrolling_right, + -- Colemak mappings + [""] = actions.select_default, + [""] = actions.move_selection_next, + [""] = actions.move_selection_previous, + [""] = actions.close, + [""] = actions.preview_scrolling_down, + [""] = actions.preview_scrolling_up, + [""] = actions.preview_scrolling_left, + [""] = actions.preview_scrolling_right, + -- TODO: actions.select_{horizontal, vertical, tab} + }, + }, + initial_mode = "insert", + }, + pickers = { + diagnostics = { + disable_coordinates = true, + }, + find_files = { + hidden = true, + file_ignore_patterns = { "^%.git" }, + }, + }, + }) + require("telescope").load_extension("fzf") + local builtin = require("telescope.builtin") + vim.keymap.set("n", "t", builtin.resume, {}) + vim.keymap.set("n", "f", builtin.find_files, {}) + vim.keymap.set("n", "F", builtin.git_files, {}) + vim.keymap.set("n", "/", builtin.current_buffer_fuzzy_find, {}) + vim.keymap.set("n", "G", builtin.live_grep, {}) + vim.keymap.set("n", "Z", builtin.buffers, {}) + vim.keymap.set("n", "d", function() + builtin.diagnostics({ + bufnr = 0, + severity_bound = 0, + }) + end, {}) + vim.keymap.set("n", "D", builtin.diagnostics, {}) + vim.keymap.set("n", "gc", builtin.git_bcommits, {}) + vim.keymap.set("n", "gC", builtin.git_commits, {}) + vim.keymap.set("n", "gs", builtin.git_status, {}) + vim.keymap.set("n", "hk", builtin.keymaps, {}) + vim.keymap.set("n", "gO", builtin.lsp_document_symbols, {}) + vim.keymap.set("n", "gS", builtin.lsp_workspace_symbols, {}) + vim.keymap.set("n", "grr", builtin.lsp_references, {}) + vim.keymap.set("n", "gri", builtin.lsp_definitions, {}) + vim.api.nvim_set_hl(0, "TelescopeBorder", { link = "FloatBorder" }) + end, + }, + { + "aznhe21/actions-preview.nvim", + dependencies = { + "nvim-telescope/telescope.nvim", + }, + keys = { + { "gra", desc = "Code Actions" }, + }, + config = function() + require("actions-preview").setup({ + diff = { + ctxlen = 2, + algorithm = "histogram", + }, + backend = { "telescope" }, + telescope = { + sorting_strategy = "ascending", + layout_strategy = "cursor", + layout_config = { + preview_width = 0.6, + width = 0.8, + height = 16, + }, + }, + }) + vim.keymap.set({ "n", "v" }, "gra", require("actions-preview").code_actions) + end, + }, + { + "folke/todo-comments.nvim", + dependencies = { + "nvim-lua/plenary.nvim", + "nvim-telescope/telescope.nvim", + }, + event = "BufEnter", + opts = { + signs = true, + keywords = { + ERROR = { + icon = "🐈", + color = "error", + alt = { "ISSUE", "FUCK" }, + }, + TODO = { + icon = "📝", + color = "info", + alt = { "NOTE" }, + }, + FIX = { + icon = "👀", + color = "warning", + alt = { "WARN", "FIXME" }, + }, + }, + color = { + error = { "DiagnosticError" }, + warning = { "DiagnosticWarning" }, + info = { "DiagnosticInfo" }, + }, + highlight = { + keyword = "fg", + }, + }, + }, +} diff --git a/home/apps/nvim/lua/plugins/visual.lua b/home/apps/nvim/lua/plugins/visual.lua new file mode 100644 index 0000000..bd841c2 --- /dev/null +++ b/home/apps/nvim/lua/plugins/visual.lua @@ -0,0 +1,40 @@ +return { + { + "lewis6991/gitsigns.nvim", + event = "VeryLazy", + config = true, + }, + { + name = "center", + dir = vim.fn.stdpath("config") .. "/lua/center", + config = function() + require("center").setup({ + enabled = true, + skip_filetypes = { + "buffer_manager", + }, + }) + end + }, + { + "stevearc/dressing.nvim", + event = "VeryLazy", + opts = { + input = { + border = require("globals").border_chars, + }, + select = { + builtin = { + border = require("globals").border_chars, + }, + }, + }, + }, + { + "nvim-tree/nvim-web-devicons", + opts = { + color_icons = true, + default = true, + }, + }, +} diff --git a/home/apps/nvim/lua/scripter/init.lua b/home/apps/nvim/lua/scripter/init.lua new file mode 100644 index 0000000..eb09a5e --- /dev/null +++ b/home/apps/nvim/lua/scripter/init.lua @@ -0,0 +1,142 @@ +local presets = require("scripter.presets") + +local M = {} + +M.resolve = function(char) + local check = string.lower(char) + if check ~= char then + M.upper = true + end + local next = M.current_script[check] + if type(next) == "table" then + if next.stop then + local stopper = next.stopper + if stopper then + M.backlog = "" + M.current_script = M.script + local upper = M.upper + M.upper = false + return stopper[upper and 2 or 1] + else + M.current_script = M.script + M.upper = false + if M.consume then + M.backlog = "" + return "" + else + local backlog = M.backlog + M.backlog = "" + return backlog .. char + end + end + else + M.backlog = M.backlog .. char + M.current_script = next + return "" + end + end + if type(next) == "nil" then + local stopper = M.current_script.stopper + if stopper then + M.backlog = "" + M.current_script = M.script + local upper = M.upper + M.upper = false + return stopper[upper and 2 or 1] .. M.resolve(char) + else + M.current_script = M.script + M.upper = false + if M.consume then + M.backlog = "" + return "" + else + local backlog = M.backlog + M.backlog = "" + return backlog .. char + end + end + end +end + +M.setup = function(opts) + M.default = opts.default or presets.none + M.script = M.default + M.current_script = M.default + M.consume = opts.consume or false + M.backlog = "" + M.mark_namespace = vim.api.nvim_create_namespace("Scripter") + M.mark_id = nil + M.highlight = opts.highlight or "@comment" + M.temporary = false + local group = vim.api.nvim_create_augroup("Scripter", {}) + M.group = group + vim.api.nvim_create_autocmd({ "InsertCharPre" }, { + group = group, + callback = function(_) + vim.v.char = M.resolve(vim.v.char) + M.upadte_mark() + end + }) + vim.api.nvim_create_autocmd({ "InsertLeavePre" }, { + group = group, + callback = function(_) + M.reset() + end + }) +end + +M.disable = function() + vim.api.nvim_buf_del_extmark(0, M.mark_namespace, M.mark_id) + vim.api.nvim_del_augroup_by_id(M.group) + M.group = nil +end + +M.upadte_mark = function() + if M.mark_id ~= nil then + vim.api.nvim_buf_del_extmark(0, M.mark_namespace, M.mark_id) + M.mark_id = nil + end + if M.current_script.stopper ~= nil then + local cursor = vim.api.nvim_win_get_cursor(0) + M.mark_id = vim.api.nvim_buf_set_extmark( + 0, + M.mark_namespace, + cursor[1] - 1, + cursor[2], + { + virt_text = { { M.current_script.stopper[M.upper and 2 or 1], M.highlight } }, + virt_text_pos = "overlay", + } + ) + end +end + +M.reset = function() + if M.current_script.stopper then + vim.api.nvim_put({ M.current_script.stopper[M.upper and 2 or 1] }, "c", false, true) + print(M.current_script.stopper) + end + if M.temporary then + M.script = M.default + M.temporary = false + end + M.current_script = M.script + M.backlog = "" + M.upper = false + M.upadte_mark() +end + +M.set_script = function(script, temporary) + M.script = script + M.current_script = script + M.temporary = temporary +end + +M.mapping = {} +M.mapping.set_script = function(script, temporary) + return function() + M.set_script(script, temporary) + end +end + +return M diff --git a/home/apps/nvim/lua/scripter/presets/auto.lua b/home/apps/nvim/lua/scripter/presets/auto.lua new file mode 100644 index 0000000..114e6a7 --- /dev/null +++ b/home/apps/nvim/lua/scripter/presets/auto.lua @@ -0,0 +1,22 @@ +local M = {} + +M.autoscript = function(table) + local output = {} + for i = 1, #table, 3 do + local path = table[i] + local cmod = output + for j = 1, string.len(path) do + local dir = string.sub(path, j, j) + if cmod[dir] == nil then + cmod[dir] = { stop = string.len(path) == j } + else + cmod[dir].stop = false + end + cmod = cmod[dir] + end + cmod.stopper = { table[i + 1], table[i + 2] } + end + return output +end + +return M diff --git a/home/apps/nvim/lua/scripter/presets/cyrillic.lua b/home/apps/nvim/lua/scripter/presets/cyrillic.lua new file mode 100644 index 0000000..7f6dbc4 --- /dev/null +++ b/home/apps/nvim/lua/scripter/presets/cyrillic.lua @@ -0,0 +1,37 @@ +local auto = require("scripter.presets.auto") + +return auto.autoscript({ + "zh", "ж", "Ж", + "ch", "ч", "Ч", + "sh", "ш", "Ш", + "sh'", "щ", "Щ", + "yi", "ы", "Ы", + "j", "ë", "Ë", + "''", "ъ", "Ъ", + "c", "ц", "Ц", + "ye", "э", "Э", + "yu", "ю", "Ю", + "ya", "я", "Я", + "a", "а", "А", + "b", "б", "Б", + "v", "в", "В", + "g", "г", "Г", + "d", "д", "Д", + "e", "е", "Е", + "z", "з", "З", + "i", "и", "И", + "y", "й", "Й", + "k", "к", "К", + "l", "л", "Л", + "m", "м", "М", + "n", "н", "Н", + "o", "о", "О", + "p", "п", "П", + "r", "р", "Р", + "s", "с", "С", + "t", "т", "Т", + "u", "у", "У", + "f", "ф", "Ф", + "h", "х", "Х", + "'", "ь", "Ь", +}) diff --git a/home/apps/nvim/lua/scripter/presets/init.lua b/home/apps/nvim/lua/scripter/presets/init.lua new file mode 100644 index 0000000..fe0a4c0 --- /dev/null +++ b/home/apps/nvim/lua/scripter/presets/init.lua @@ -0,0 +1,6 @@ +local M = {} + +M.cyrillic = require("scripter.presets.cyrillic") +M.none = require("scripter.presets.none") + +return M diff --git a/home/apps/nvim/lua/scripter/presets/none.lua b/home/apps/nvim/lua/scripter/presets/none.lua new file mode 100644 index 0000000..91bcd90 --- /dev/null +++ b/home/apps/nvim/lua/scripter/presets/none.lua @@ -0,0 +1,3 @@ +return { + stop = true, +} diff --git a/home/apps/nvim/lua/winpad/init.lua b/home/apps/nvim/lua/winpad/init.lua new file mode 100644 index 0000000..4cfe491 --- /dev/null +++ b/home/apps/nvim/lua/winpad/init.lua @@ -0,0 +1,93 @@ +local M = {} + +M.setup = function(opts) + M.enabled = false + M.pad_target = opts.pad_target or 35 + M.pad_min_width = opts.pad_min_width or 120 + if opts.enabled then + M.enable_pad() + end +end + +M.toggle = function() + if M.enabled then + M.disable_pad() + else + M.enable_pad() + end +end + +M.disable_pad = function() + if not M.enabled then + return + end + vim.api.nvim_del_augroup_by_id(M.group) + M.enabled = false + M.pad_all_windows() +end + +M.enable_pad = function() + if M.enabled then + return + end + local group = vim.api.nvim_create_augroup("PadGroup", {}) + M.group = group + vim.api.nvim_create_autocmd({ "WinResized", "WinNew", "VimEnter", "BufEnter" }, { + group = group, + callback = function(ev) + if ev.event == "WinResized" then + for _, window in ipairs(vim.v.event.windows) do + M.pad_window(window) + end + else + M.pad_all_windows() + end + end + }) + M.enabled = true + M.pad_all_windows() +end + +M.update_pad_size = function(win) + local position = vim.api.nvim_win_get_position(win) + local target_pad = math.max(0, M.pad_target - position[2]) + local width = vim.api.nvim_win_get_width(win) + local ui_width = vim.api.nvim_list_uis()[1].width + local min_left = math.max(math.floor(ui_width / 2), M.pad_min_width) + local max_pad = math.max(0, width - min_left) + local total_pad = math.min(max_pad, target_pad) + M.set_pad_size(win, total_pad) + return total_pad +end + +M.set_pad_size = function(win, pad) + vim.api.nvim_win_set_var(win, "pad_size", pad) +end +M.get_pad_size = function(win) + return vim.api.nvim_win_get_var(win, "pad_size") or 0 +end + +M.pad_window = function(win) + if #vim.api.nvim_win_get_config(win).relative > 0 then + return + end + if not M.enabled then + M.set_pad_size(win, 0) + vim.api.nvim_set_option_value("statuscolumn", "%#LineNr#%2.2s%4.4l%#LinePad#%{\"┃\"}", { win = win }) + else + local total_pad = M.update_pad_size(win) + vim.api.nvim_set_option_value("statuscolumn", + "%#Normal#%{\"" .. + -- Sometimes I feel like I shouldn't be allowed to touch computers... + string.rep("⠀", total_pad) .. "\"}%#LineNr# %2.2s%4.4l%#LinePad#%{v:virtnum<=0?\"┃\":\"⠀⠀⠀⠀┃\"}", + { win = win }) + end +end + +M.pad_all_windows = function() + for _, window in ipairs(vim.api.nvim_list_wins()) do + M.pad_window(window) + end +end + +return M diff --git a/home/apps/nvim/snippets/all.lua b/home/apps/nvim/snippets/all.lua new file mode 100644 index 0000000..2bf17f2 --- /dev/null +++ b/home/apps/nvim/snippets/all.lua @@ -0,0 +1,41 @@ +return { + -- Blocks + s({ trig = "ppb", wordTrig = false }, { t({ "(", "\t" }), i(1), t({ "", ")" }), i(0) }), + s({ trig = "ssb", wordTrig = false }, { t({ "[", "\t" }), i(1), t({ "", "]" }), i(0) }), + s({ trig = "bbb", wordTrig = false }, { t({ "{", "\t" }), i(1), t({ "", "}" }), i(0) }), + s({ trig = "aab", wordTrig = false }, { t({ "<", "\t" }), i(1), t({ "", ">" }), i(0) }), + -- Pairs + s({ trig = "pp", wordTrig = false }, { t("("), i(1), t(")"), i(0) }), + s({ trig = "ss", wordTrig = false }, { t("["), i(1), t("]"), i(0) }), + s({ trig = "bb", wordTrig = false }, { t("{"), i(1), t("}"), i(0) }), + s({ trig = "aa", wordTrig = false }, { t("<"), i(1), t(">"), i(0) }), + s({ trig = "qq", wordTrig = false }, { t("'"), i(1), t("'"), i(0) }), + s({ trig = "dd", wordTrig = false }, { t("\""), i(1), t("\""), i(0) }), + s({ trig = "co", wordTrig = false }, { t("```"), i(1), t({ "", "```" }), i(0) }), + -- Misc + s({ trig = "ca", wordTrig = false }, { t("("), i(1), t(");"), i(0) }), + -- Emoji + s( + { trig = "emo%w+", regTrig = true }, + f(function(_, snip) + local output = "" + local emojis = { + c = "🐈", + k = "🔪", + f = "🔥", + m = "💪", + s = "💀", + t = "🎉", + h = "❤️", + b = "‼️", + e = "👀", + y = "😋", + p = "😔", + } + for i = 4, string.len(snip.trigger), 1 do + output = output .. (emojis[string.sub(snip.trigger, i, i)] or "") + end + return output + end, {}) + ), +} diff --git a/home/apps/nvim/snippets/zig.lua b/home/apps/nvim/snippets/zig.lua new file mode 100644 index 0000000..9a61e00 --- /dev/null +++ b/home/apps/nvim/snippets/zig.lua @@ -0,0 +1,27 @@ +return { + -- Lazy pasta + s("opt", t("@setFloatMode(.optimized);")), + s("pt", t("?*")), + s("dis", t("_ = ")), + s("disp", t("_ = &")), + -- Builtin functions + s("as", { t("@as("), i(1, "type"), t(", "), i(2, "{}"), t(")"), i(0) }), + s("vec", { t("@Vector("), i(1, "count"), t(", "), i(2, "type"), t(")"), i(0) }), + s({ trig = "vec%d+", regTrig = true }, { t("@Vector("), f(function(_, snip) return string.sub(snip.trigger, 4) end), t(", "), i(1, "type"), t(")"), i(0) }), + s({ trig = "vec%d+f", regTrig = true }, { t("@Vector("), f(function(_, snip) return string.sub(snip.trigger, 4, string.len(snip.trigger) - 1) end), t(", f32)") }), + s("tof", { t("@TypeOf("), i(1), t(")"), i(0) }), + s("tin", { t("@typeInfo("), i(1), t(")"), i(0) }), + s("splat", { t("@splat("), i(1), t(")"), i(0) }), + s("sqrt", { t("@sqrt("), i(1), t(")"), i(0) }), + s("panic", { t("@panic("), i(1), t(")"), i(0) }), + s("ffi", { t("@floatFromInt("), i(1), t(")"), i(0) }), + s("iff", { t("@intFromFloat("), i(1), t(")"), i(0) }), + s("this", { t("@This()"), i(0) }), + -- Syntax pasta + s({ trig = "pr", wordTrig = false }, { i(1), t(" => "), n(2, "|"), i(2), n(2, "| "), t("{"), i(3), t("},"), i(0) }), + s({ trig = "prb", wordTrig = false }, { i(1), t(" => "), n(2, "|"), i(2), n(2, "| "), t({ "{", "\t" }), i(3), t({ "", "}," }), i(0) }), + s("im", { t("const "), i(1), t(" = @import(\""), i(2), t("\");"), i(0), }), + s("fn", { t("fn "), i(1), t("("), i(2), t(") "), i(3), t({ " {", "\t" }), i(0), t({ "", "}" }) }), + s("str", { t({ "struct {", "\t" }), i(1), t({ "", "}" }), i(0) }), + s("union", { t({ "union(" }), i(1), t({ ") {", "\t" }), i(2), t({ "", "}" }), i(0) }), +} diff --git a/home/apps/shell_common.nix b/home/apps/shell_common.nix new file mode 100644 index 0000000..2f5882b --- /dev/null +++ b/home/apps/shell_common.nix @@ -0,0 +1,13 @@ +{ + lib, config, pkgs, ... +}: let + cfg = config.shell; +in { + imports = [ + ./starship.nix + ]; + + home.packages = [ + pkgs.zoxide + ]; +} diff --git a/home/apps/starship.nix b/home/apps/starship.nix new file mode 100644 index 0000000..92fcbc9 --- /dev/null +++ b/home/apps/starship.nix @@ -0,0 +1,16 @@ +{ + lib, config, pkgs, ... +}: let + cfg = config.starship; +in { + options.starship = {}; + + config = { + home.packages = [ + pkgs.starship + ]; + home.file = { + ".config/starship.toml".source = ./starship.toml; + }; + }; +} diff --git a/home/apps/starship.toml b/home/apps/starship.toml new file mode 100644 index 0000000..bb3b8c1 --- /dev/null +++ b/home/apps/starship.toml @@ -0,0 +1,65 @@ +format = ''' +[\[$username@$hostname\]:\[$directory$git_branch\]$git_status$git_state +- $character ](fg:white) +''' + +[username] +style_root = "bright-red" +style_user = "bright-blue" +format = "[$user]($style)" +show_always = true + +[hostname] +ssh_only = false +ssh_symbol = "-@" +format = "$ssh_symbol[$hostname]($style)" +style = "bright-blue" + +[directory] +format = '[$read_only]($read_only_style)[$path]($style)' +style = "fg:bright-blue" +truncation_symbol = "*/" + +read_only = "!" +repo_root_style = "fg:bright-yellow" +repo_root_format = '[$read_only]($read_only_style)[$repo_root]($repo_root_style)[$path]($style)' + +[git_branch] +ignore_branches = ["main"] +style = "fg:bright-purple" +truncation_length = 16 +truncation_symbol = "*" +format = "@[$branch(:$remote_branch)]($style)" +only_attached = true + +[git_status] +format = '( \[[$all_status$ahead_behind]($style)\])' +style = "fg:bright-white" +conflicted = "[X](fg:bright-red)" +stashed = "[T](fg:bright-black)" +deleted = "[D](fg:bright-yellow)" +renamed = "[R](fg:bright-yellow)" +modified = "[M](fg:bright-yellow)" +staged = "[S](fg:bright-green)" +untracked = "[U](fg:bright-purple)" + +diverged = "/" +ahead = "+" +behind = "-" +up_to_date = "" + +[git_state] +format = ' \[[$state]($style)(:[$progress_current/$progress_total](fg:bright-white))\]' +rebase = "[REBASING](fg:bright-red)" +merge = "[MERGING](fg:bright-red)" +revert = "[REVERTING](fg:bright-purple)" +cherry_pick = "[PICKING](fg:bright-red)" +bisect = "[BISECTING](fg:bright-green)" +am = "APPLYING" +am_or_rebase = "APPLYING/REBASING" +style = "fg:bright-white" + +[character] +format = "$symbol" +success_symbol = '[\$](fg:bright-white)' +error_symbol = '[\$](fg:bright-red)' diff --git a/home/apps/tmux.nix b/home/apps/tmux.nix new file mode 100644 index 0000000..c35854e --- /dev/null +++ b/home/apps/tmux.nix @@ -0,0 +1,16 @@ +{ + lib, config, pkgs, ... +}: let + cfg = config.tmux; +in { + options.tmux = {}; + + config = { + home.packages = [ + pkgs.tmux + ]; + home.file = { + ".config/tmux".source = ./tmux; + }; + }; +} diff --git a/home/apps/tmux/tmux.conf b/home/apps/tmux/tmux.conf new file mode 100644 index 0000000..177d1ec --- /dev/null +++ b/home/apps/tmux/tmux.conf @@ -0,0 +1,88 @@ +### Misc +set -as terminal-features "*:RGB" +set -g base-index 1 +setw -g pane-base-index 1 +set -g buffer-limit 16 + +### Appearance +set -g status-position "top" +set -g status-style "bg=#181820,fg=#dcd7ba" +set -g status on +set -g status-format[0] \ +"\ +#[align=left]\ +#{?#{==:#{client_key_table},root},#{l:#[bg=#c5c9c5,fg=#0d0c0c]} NORMAL ,}\ +#{?#{==:#{client_key_table},prefix},#{l:#[bg=#6e915f,fg=#0d0c0c]} PREFIX ,}\ +#{?#{==:#{client_key_table},create},#{l:#[bg=#ffa066,fg=#0d0c0c]} CREATE ,}\ +#{?#{==:#{client_key_table},delete},#{l:#[bg=#e46876,fg=#0d0c0c]} DELETE ,}\ +#{?#{==:#{client_key_table},choose},#{l:#[bg=#b8b4d0,fg=#0d0c0c]} CHOOSE ,}\ +#[default]\ + #{W:#{?#{window_active},#{l:#[bg=#393836,fg=#dcd7ba]},#{l:#[bg=#282727,fg=#625e5a]}} #{window_index}:#{window_name} }\ +#[align=right]\ +#{?#{client_readonly},#{l:#[bg=#ff5d62,fg=#0d0c0c] R },}\ +#{?#{session_many_attached},#{l:#[bg=#8ea4a2,fg=#0d0c0c] M },}\ +#{?#{window_zoomed_flag},#{l:#[bg=#957fb8,fg=#0d0c0c] Z },}\ +#{?#{window_bigger},#{l:#[bg=#dca561,fg=#0d0c0c] S },}\ +#[default] %I:%M%P %D \ +#[bg=#282727,fg=#dcd7ba] #{session_name} #[default] \ +\ +" +# Does not work atm: #{?#{==:#{client_key_table},copy-mode-vi},#{l:#[bg=#957fb8,fg=#0d0c0c]} VISUAL ,}\ + +set -g message-line 0 +set -g message-style "bg=#181616,fg=#98bb6c" +set -g message-command-style "bg=#181616,fg=#7e9cd8" # vi normal mode + +set -g pane-border-lines single +set -g pane-active-border-style "fg=#54546d" +set -g pane-border-style "fg=#363646" + +set -g popup-border-style "fg=#54546d" +set -g popup-border-lines single + +### Shortcuts +unbind-key -a +bind-key C-b send-prefix + +bind-key h select-pane -L +bind-key j select-pane -D +bind-key k select-pane -U +bind-key l select-pane -R +bind-key 1 select-window -t:=1 +bind-key 2 select-window -t:=2 +bind-key 3 select-window -t:=3 +bind-key 4 select-window -t:=4 +bind-key 5 select-window -t:=5 +bind-key 6 select-window -t:=6 +bind-key 7 select-window -t:=7 +bind-key 8 select-window -t:=8 +bind-key 9 select-window -t:=9 +bind-key 0 select-window -t:=10 +bind-key r command-prompt -I "#W" { rename-window "%%" } +bind-key R command-prompt -I "#S" { rename-session "%%" } +bind-key z resize-pane -Z +bind-key : command-prompt +bind-key Space last-pane +bind-key y copy-mode +bind-key p paste-buffer -p +bind-key P choose-buffer -Z +bind-key q detach-client +bind-key '"' list-buffers + +bind-key n switch-client -T create +bind-key -T create h { split-window -h; swap-pane -U } +bind-key -T create j split-window +bind-key -T create k { split-window; swap-pane -U } +bind-key -T create l split-window -h +bind-key -T create n new-window +bind-key -T create b break-pane + +bind-key d switch-client -T delete +bind-key -T delete d confirm-before -p "Kill pane #P?" kill-pane +bind-key -T delete w confirm-before -p "Kill window #W?" kill-window +bind-key -T delete s confirm-before -p "Kill session #S?" kill-session +bind-key -T delete S confirm-before -p "Kill server?" kill-server + +bind-key f switch-client -T choose +bind-key -T choose s choose-tree -Zs +bind-key -T choose w choose-tree -Zw diff --git a/home/flake.lock b/home/flake.lock new file mode 100644 index 0000000..6d0f9d6 --- /dev/null +++ b/home/flake.lock @@ -0,0 +1,48 @@ +{ + "nodes": { + "home-manager": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1765682243, + "narHash": "sha256-yeCxFV/905Wr91yKt5zrVvK6O2CVXWRMSrxqlAZnLp0=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "58bf3ecb2d0bba7bdf363fc8a6c4d49b4d509d03", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "home-manager", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1765472234, + "narHash": "sha256-9VvC20PJPsleGMewwcWYKGzDIyjckEz8uWmT0vCDYK0=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "2fbfb1d73d239d2402a8fe03963e37aab15abe8b", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "home-manager": "home-manager", + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/home/flake.nix b/home/flake.nix new file mode 100644 index 0000000..64f86c6 --- /dev/null +++ b/home/flake.nix @@ -0,0 +1,25 @@ +{ + description = "Home Manager configuration of duck"; + + inputs = { + nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; + home-manager = { + url = "github:nix-community/home-manager"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + }; + + outputs = { + nixpkgs, home-manager, ... + }: let + system = "x86_64-linux"; + pkgs = nixpkgs.legacyPackages.${system}; + in + { + homeConfigurations."duck" = home-manager.lib.homeManagerConfiguration { + inherit pkgs; + + modules = [ ./main.nix ]; + }; + }; +} diff --git a/home/main.nix b/home/main.nix new file mode 100644 index 0000000..2218d34 --- /dev/null +++ b/home/main.nix @@ -0,0 +1,22 @@ +{ config, pkgs, ... }: + +{ + home.username = "duck"; + home.homeDirectory = "/home/duck"; + + imports = [ + ./apps/nvim.nix + ./apps/fish.nix + ./apps/tmux.nix + ]; + nvim.editor = true; + + home.packages = [ + pkgs.git + pkgs.lazygit + ]; + + programs.home-manager.enable = true; + + home.stateVersion = "25.11"; +}