├── Makefile ├── nvim ├── after │ ├── ftplugin │ │ ├── jsonc.lua │ │ ├── mysql.lua │ │ ├── sql.lua │ │ ├── git.lua │ │ ├── go.lua │ │ └── lua.lua │ ├── syntax │ │ └── dbout.vim │ ├── queries │ │ └── typescript │ │ │ └── highlights.scm │ └── plugin │ │ ├── replace_pair.lua │ │ ├── simple_f.lua │ │ ├── find.lua │ │ ├── autocompletion.lua │ │ ├── search.lua │ │ └── tests.lua ├── spell │ ├── en.utf-8.add │ └── en.utf-8.add.spl ├── lua │ ├── partials │ │ ├── plugins │ │ │ ├── create_pr.lua │ │ │ ├── blame.lua │ │ │ ├── indentmini.lua │ │ │ ├── autopairs.lua │ │ │ ├── rest.lua │ │ │ ├── matchup.lua │ │ │ ├── autotag.lua │ │ │ ├── copilot.lua │ │ │ ├── template_string.lua │ │ │ ├── copilot_chat.lua │ │ │ ├── treesj.lua │ │ │ ├── quicker.lua │ │ │ ├── db.lua │ │ │ ├── workspaces.lua │ │ │ ├── fugitive.lua │ │ │ ├── vimspector.lua │ │ │ ├── flash.lua │ │ │ ├── diffview.lua │ │ │ ├── local_git_history.lua │ │ │ ├── codecompanion.lua │ │ │ ├── gitsigns.lua │ │ │ ├── nvim_tree.lua │ │ │ ├── treesitter.lua │ │ │ ├── orgmode.lua │ │ │ ├── blink.lua │ │ │ ├── colorscheme.lua │ │ │ ├── javascript.lua │ │ │ └── snacks.lua │ │ ├── packs │ │ │ ├── create_pr.lua │ │ │ ├── blame.lua │ │ │ ├── matchup.lua │ │ │ ├── indentmini.lua │ │ │ ├── autopairs.lua │ │ │ ├── template_string.lua │ │ │ ├── autotag.lua │ │ │ ├── copilot.lua │ │ │ ├── rest.lua │ │ │ ├── treesj.lua │ │ │ ├── db.lua │ │ │ ├── quicker.lua │ │ │ ├── fugitive.lua │ │ │ ├── workspaces.lua │ │ │ ├── flash.lua │ │ │ ├── diffview.lua │ │ │ ├── local_git_history.lua │ │ │ ├── codecompanion.lua │ │ │ ├── nvim_tree.lua │ │ │ ├── gitsigns.lua │ │ │ ├── treesitter.lua │ │ │ ├── orgmode.lua │ │ │ ├── colorscheme.lua │ │ │ ├── blink.lua │ │ │ ├── javascript.lua │ │ │ └── snacks.lua │ │ ├── orgmode_cron.lua │ │ ├── abbreviations.lua │ │ ├── plugins.lua │ │ ├── pack.lua │ │ ├── lazy.lua │ │ ├── utils │ │ │ └── init.lua │ │ ├── picker.lua │ │ ├── orgmode_config.lua │ │ └── settings.lua │ └── main.lua ├── init.lua ├── snippets │ ├── org.json │ ├── vim.json │ ├── sql.json │ ├── lua.json │ └── javascript.json └── minvimrc.vim ├── waybar ├── start.sh ├── weather.sh ├── style.css ├── cycle_audio_output.sh ├── show_audio_devices.sh ├── exchangerates.sh └── config ├── helix ├── languages.toml └── config.toml ├── stylua.toml ├── .gitignore ├── rofi ├── launch.sh ├── spotlight-dark.rasi ├── spotlight-light.rasi └── config.rasi ├── hypr ├── hypridle.conf ├── hyprlock.conf ├── record_screen.sh └── hyprland.conf ├── i3 └── polybar │ ├── dropbox.sh │ ├── start.sh │ ├── popup-calendar.sh │ ├── cycle_audio_output.sh │ ├── show_audio_devices.sh │ └── exchangerates.sh ├── sway ├── auto_exit_fullscreen.sh └── config ├── README.md ├── zsh ├── themes │ ├── cloud_kris.zsh-theme │ └── lambda-mod.zsh-theme └── zshrc ├── kitty ├── reload_colors.py └── kitty.conf ├── install.sh └── colors /Makefile: -------------------------------------------------------------------------------- 1 | format: 2 | stylua nvim/lua/ nvim/init.lua 3 | -------------------------------------------------------------------------------- /nvim/after/ftplugin/jsonc.lua: -------------------------------------------------------------------------------- 1 | vim.opt_local.conceallevel = 0 2 | -------------------------------------------------------------------------------- /waybar/start.sh: -------------------------------------------------------------------------------- 1 | killall -q waybar > /dev/null 2 | 3 | waybar &> /dev/null & 4 | -------------------------------------------------------------------------------- /nvim/spell/en.utf-8.add: -------------------------------------------------------------------------------- 1 | Neovim 2 | tmux 3 | lua 4 | zshrc 5 | zsh 6 | nvim 7 | github 8 | -------------------------------------------------------------------------------- /helix/languages.toml: -------------------------------------------------------------------------------- 1 | [language-server.lua-language-server.config.Lua.diagnostics] 2 | globals = ["vim"] 3 | -------------------------------------------------------------------------------- /nvim/lua/partials/plugins/create_pr.lua: -------------------------------------------------------------------------------- 1 | return { 2 | 'kristijanhusak/vim-create-pr', 3 | cmd = { 'PR' }, 4 | } 5 | -------------------------------------------------------------------------------- /nvim/spell/en.utf-8.add.spl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kristijanhusak/neovim-config/HEAD/nvim/spell/en.utf-8.add.spl -------------------------------------------------------------------------------- /nvim/after/syntax/dbout.vim: -------------------------------------------------------------------------------- 1 | syn match dbout_null /|\?\s\+\zs\ze\s*|\?/ 2 | hi default link dbout_null Comment 3 | -------------------------------------------------------------------------------- /nvim/lua/partials/packs/create_pr.lua: -------------------------------------------------------------------------------- 1 | vim.pack.load({ 2 | src = 'kristijanhusak/vim-create-pr', 3 | cmd = 'PR', 4 | }) 5 | -------------------------------------------------------------------------------- /nvim/after/ftplugin/mysql.lua: -------------------------------------------------------------------------------- 1 | vim.opt_local.omnifunc = 'vim_dadbod_completion#omni' 2 | vim.opt_local.formatprg = 'sql-formatter -l mysql' 3 | -------------------------------------------------------------------------------- /nvim/after/ftplugin/sql.lua: -------------------------------------------------------------------------------- 1 | vim.opt_local.omnifunc = 'vim_dadbod_completion#omni' 2 | vim.opt_local.formatprg = 'sql-formatter -l postgresql' 3 | -------------------------------------------------------------------------------- /nvim/lua/partials/plugins/blame.lua: -------------------------------------------------------------------------------- 1 | return { 2 | 'FabijanZulj/blame.nvim', 3 | opts = {}, 4 | cmd = { 5 | 'BlameToggle', 6 | }, 7 | } 8 | -------------------------------------------------------------------------------- /nvim/after/ftplugin/git.lua: -------------------------------------------------------------------------------- 1 | vim.wo.foldenable = true 2 | vim.wo.foldmethod = 'syntax' 3 | vim.keymap.set('n', '', 'za', { silent = true, buffer = true }) 4 | -------------------------------------------------------------------------------- /stylua.toml: -------------------------------------------------------------------------------- 1 | column_width = 120 2 | line_endings = "Unix" 3 | indent_type = "Spaces" 4 | indent_width = 2 5 | quote_style = "AutoPreferSingle" 6 | no_call_parentheses = false 7 | -------------------------------------------------------------------------------- /nvim/lua/partials/plugins/indentmini.lua: -------------------------------------------------------------------------------- 1 | return { 2 | 'nvimdev/indentmini.nvim', 3 | event = 'VeryLazy', 4 | opts = { 5 | char = '▏', 6 | exclude = { 'dbout' }, 7 | }, 8 | } 9 | -------------------------------------------------------------------------------- /nvim/lua/partials/packs/blame.lua: -------------------------------------------------------------------------------- 1 | vim.pack.load({ 2 | src = 'FabijanZulj/blame.nvim', 3 | cmd = 'BlameToggle', 4 | config = function() 5 | require('blame').setup() 6 | end, 7 | }) 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | nvim/pack 2 | kitty/local.conf 3 | kitty/local_color.conf 4 | waybar/local.css 5 | i3/polybar/local 6 | bspwm/bspwmrc.local 7 | lazygit/* 8 | !lazygit/config.yml 9 | nvim/nvim-pack-lock.json 10 | -------------------------------------------------------------------------------- /nvim/init.lua: -------------------------------------------------------------------------------- 1 | _G.kris = {} 2 | 3 | local ok, err = pcall(require, 'main') 4 | if not ok then 5 | vim.notify('Error loading main.lua, loading fallback.\n' .. err) 6 | vim.cmd.runtime('minvimrc.vim') 7 | end 8 | -------------------------------------------------------------------------------- /rofi/launch.sh: -------------------------------------------------------------------------------- 1 | colorscheme=$(grep -o -P '(?<=NVIM_COLORSCHEME_BG=).*' ~/.cache/main_colorscheme.conf) 2 | 3 | rofi -combi-modi window,run -show combi -modi combi -theme ~/.config/rofi/spotlight-$colorscheme.rasi 4 | -------------------------------------------------------------------------------- /nvim/after/queries/typescript/highlights.scm: -------------------------------------------------------------------------------- 1 | ; inherits: typescript 2 | 3 | (call_expression 4 | function: (identifier) @it_test (#any-of? @it_test "it" "describe") 5 | arguments: (arguments (string) @spell) 6 | ) 7 | -------------------------------------------------------------------------------- /nvim/lua/partials/orgmode_cron.lua: -------------------------------------------------------------------------------- 1 | local orgmode_config = require('partials.orgmode_config') 2 | vim.opt.runtimepath:append(vim.fn.fnamemodify('~/github/orgmode', ':p')) 3 | 4 | require('orgmode').cron(orgmode_config) 5 | -------------------------------------------------------------------------------- /nvim/lua/partials/plugins/autopairs.lua: -------------------------------------------------------------------------------- 1 | return { 2 | 'windwp/nvim-autopairs', 3 | event = 'InsertEnter', 4 | opts = { 5 | map_cr = not vim.g.builtin_autocompletion, 6 | map_bs = not vim.g.builtin_autocompletion, 7 | }, 8 | } 9 | -------------------------------------------------------------------------------- /waybar/weather.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | SHORT=$(curl -Ss --fail 'https://wttr.in?format=3') 5 | TOOLTIP=$(curl -s --fail 'https://wttr.in?dT') 6 | jq -c -n --arg text "$SHORT" --arg tooltip "$TOOLTIP" '{"text":$text,"tooltip":$tooltip}' 7 | -------------------------------------------------------------------------------- /nvim/lua/partials/packs/matchup.lua: -------------------------------------------------------------------------------- 1 | vim.g.matchup_matchparen_status_offscreen = 0 2 | vim.g.matchup_matchparen_nomode = 'ivV' 3 | vim.g.matchup_matchparen_deferred = 100 4 | 5 | vim.pack.load({ 6 | src = 'andymass/vim-matchup', 7 | event = 'VeryLazy', 8 | }) 9 | -------------------------------------------------------------------------------- /nvim/lua/partials/packs/indentmini.lua: -------------------------------------------------------------------------------- 1 | vim.pack.load({ 2 | src = 'nvimdev/indentmini.nvim', 3 | event = 'VeryLazy', 4 | config = function() 5 | require('indentmini').setup({ 6 | char = '▏', 7 | exclude = { 'dbout' }, 8 | }) 9 | end, 10 | }) 11 | -------------------------------------------------------------------------------- /nvim/lua/partials/plugins/rest.lua: -------------------------------------------------------------------------------- 1 | return { 2 | 'rest-nvim/rest.nvim', 3 | event = 'VeryLazy', 4 | init = function() 5 | vim.api.nvim_create_autocmd('BufWritePost', { 6 | pattern = '*.http', 7 | command = 'Rest run', 8 | }) 9 | end, 10 | } 11 | -------------------------------------------------------------------------------- /nvim/lua/partials/plugins/matchup.lua: -------------------------------------------------------------------------------- 1 | return { 2 | 'andymass/vim-matchup', 3 | event = 'VeryLazy', 4 | init = function() 5 | vim.g.matchup_matchparen_status_offscreen = 0 6 | vim.g.matchup_matchparen_nomode = 'ivV' 7 | vim.g.matchup_matchparen_deferred = 100 8 | end, 9 | } 10 | -------------------------------------------------------------------------------- /hypr/hypridle.conf: -------------------------------------------------------------------------------- 1 | # Lock screen after 10 minutes 2 | listener { 3 | timeout = 600 4 | on-timeout = hyprlock 5 | } 6 | 7 | # Shut down monitor after 20 minutes 8 | listener { 9 | timeout = 1200 10 | on-timeout = hyprctl dispatch dpms off 11 | on-resume = hyprctl dispatch dpms on 12 | } 13 | -------------------------------------------------------------------------------- /nvim/lua/partials/packs/autopairs.lua: -------------------------------------------------------------------------------- 1 | vim.pack.load({ 2 | src = 'windwp/nvim-autopairs', 3 | event = 'InsertEnter', 4 | config = function() 5 | require('nvim-autopairs').setup({ 6 | map_cr = not vim.g.builtin_autocompletion, 7 | map_bs = not vim.g.builtin_autocompletion, 8 | }) 9 | end, 10 | }) 11 | -------------------------------------------------------------------------------- /nvim/lua/partials/packs/template_string.lua: -------------------------------------------------------------------------------- 1 | vim.pack.load({ 2 | src = 'axelvc/template-string.nvim', 3 | ft = { 'javascript', 'javascriptreact', 'typescript', 'typescriptreact' }, 4 | config = function() 5 | require('template-string').setup({ 6 | remove_template_string = true, 7 | }) 8 | end, 9 | }) 10 | -------------------------------------------------------------------------------- /nvim/lua/partials/plugins/autotag.lua: -------------------------------------------------------------------------------- 1 | return { 2 | 'windwp/nvim-ts-autotag', 3 | ft = { 4 | 'html', 5 | 'javascriptreact', 6 | 'typescriptreact', 7 | 'svelte', 8 | 'vue', 9 | 'tsx', 10 | 'jsx', 11 | 'markdown', 12 | 'handlebars', 13 | 'hbs', 14 | }, 15 | opts = {}, 16 | } 17 | -------------------------------------------------------------------------------- /nvim/lua/partials/plugins/copilot.lua: -------------------------------------------------------------------------------- 1 | return { 2 | 'zbirenbaum/copilot.lua', 3 | event = 'InsertEnter', 4 | opts = { 5 | panel = { 6 | enabled = false, 7 | }, 8 | suggestion = { 9 | auto_trigger = true, 10 | hide_during_completion = false, 11 | debounce = 700, 12 | }, 13 | }, 14 | } 15 | -------------------------------------------------------------------------------- /hypr/hyprlock.conf: -------------------------------------------------------------------------------- 1 | label { 2 | text = cmd[update:500] echo "$(if [ $(cat /sys/class/leds/input*::capslock/brightness | head -n1) -eq 1 ]; then echo "Caps Lock ON"; else echo ""; fi)" 3 | color = rgba(255, 50, 50, 1.0) 4 | font_size = 18 5 | position = 0, 90 6 | } 7 | 8 | input-field { 9 | size = 100, 100 10 | hide_input = true 11 | } 12 | -------------------------------------------------------------------------------- /i3/polybar/dropbox.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | status=$(dropbox-cli status) 3 | 4 | if [[ "$status" == "Up to date" ]]; then 5 | echo "%{F#1f88ff}%{F-}" 6 | elif [[ "$status" == "Syncing"* ]]; then 7 | echo "%{F#1f88ff}󰜷%{F-}" 8 | elif [[ "$status" == "Connecting..." ]]; then 9 | echo "%{F#FFA500}󰇚%{F-}" 10 | else 11 | echo "%{F#FF0000}%{F-}" 12 | fi 13 | 14 | -------------------------------------------------------------------------------- /nvim/lua/partials/packs/autotag.lua: -------------------------------------------------------------------------------- 1 | vim.pack.load({ 2 | src = 'windwp/nvim-ts-autotag', 3 | ft = { 4 | 'html', 5 | 'javascriptreact', 6 | 'typescriptreact', 7 | 'svelte', 8 | 'vue', 9 | 'tsx', 10 | 'jsx', 11 | 'markdown', 12 | 'handlebars', 13 | 'hbs', 14 | }, 15 | config = function() 16 | require('nvim-ts-autotag').setup() 17 | end, 18 | }) 19 | -------------------------------------------------------------------------------- /nvim/lua/partials/abbreviations.lua: -------------------------------------------------------------------------------- 1 | local abbreviations = { 2 | Wq = 'wq', 3 | WQ = 'wq', 4 | Wqa = 'wqa', 5 | W = 'w', 6 | Q = 'q', 7 | Qa = 'qa', 8 | Bd = 'bd', 9 | E = 'e', 10 | Gco = 'Git checkout', 11 | Gcb = 'Git checkout -b', 12 | Gblame = 'Git blame', 13 | } 14 | 15 | for left, right in pairs(abbreviations) do 16 | vim.cmd.cnoreabbrev(('%s %s'):format(left, right)) 17 | end 18 | -------------------------------------------------------------------------------- /nvim/lua/partials/plugins/template_string.lua: -------------------------------------------------------------------------------- 1 | local filetypes = { 'javascript', 'javascriptreact', 'typescript', 'typescriptreact' } 2 | 3 | local template_string = { 4 | 'axelvc/template-string.nvim', 5 | ft = filetypes, 6 | } 7 | template_string.config = function() 8 | require('template-string').setup({ 9 | remove_template_string = true, 10 | }) 11 | end 12 | 13 | return template_string 14 | -------------------------------------------------------------------------------- /nvim/lua/partials/packs/copilot.lua: -------------------------------------------------------------------------------- 1 | vim.pack.load({ 2 | src = 'zbirenbaum/copilot.lua', 3 | event = 'InsertEnter', 4 | config = function() 5 | require('copilot').setup({ 6 | panel = { 7 | enabled = false, 8 | }, 9 | suggestion = { 10 | auto_trigger = true, 11 | hide_during_completion = false, 12 | debounce = 700, 13 | }, 14 | }) 15 | end, 16 | }) 17 | -------------------------------------------------------------------------------- /nvim/lua/partials/plugins.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { 'tpope/vim-repeat', event = 'VeryLazy' }, 3 | { 'tpope/vim-sleuth', event = 'VeryLazy' }, 4 | { 'tpope/vim-abolish', event = 'VeryLazy' }, 5 | { 'tpope/vim-surround', event = 'VeryLazy' }, 6 | { 'nvim-tree/nvim-web-devicons' }, 7 | { 'nvim-lua/plenary.nvim' }, 8 | { 9 | 'folke/which-key.nvim', 10 | event = 'VeryLazy', 11 | opts = { 12 | preset = 'helix', 13 | }, 14 | }, 15 | } 16 | -------------------------------------------------------------------------------- /nvim/lua/main.lua: -------------------------------------------------------------------------------- 1 | vim.g.builtin_autocompletion = false 2 | local use_vim_pack = vim.pack ~= nil 3 | 4 | if vim.fn.has('nvim-0.12') == 0 then 5 | vim.g.builtin_autocompletion = false 6 | end 7 | 8 | require('partials.abbreviations') 9 | require('partials.settings') 10 | if use_vim_pack then 11 | require('partials.pack') 12 | else 13 | require('partials.lazy') 14 | end 15 | require('partials.statusline') 16 | require('partials.mappings') 17 | require('partials.picker') 18 | -------------------------------------------------------------------------------- /nvim/lua/partials/packs/rest.lua: -------------------------------------------------------------------------------- 1 | vim.pack.load({ 2 | src = 'rest-nvim/rest.nvim', 3 | event = 'VeryLazy', 4 | build = function(data) 5 | vim.system({ 'luarocks', 'install', 'rest.nvim-scm-1.rockspec', '--local', '--lua-version=5.1', '--force' }, { 6 | cwd = data.path, 7 | }) 8 | end, 9 | config = function() 10 | vim.api.nvim_create_autocmd('BufWritePost', { 11 | pattern = '*.http', 12 | command = 'Rest run', 13 | }) 14 | end, 15 | }) 16 | -------------------------------------------------------------------------------- /nvim/lua/partials/plugins/copilot_chat.lua: -------------------------------------------------------------------------------- 1 | return { 2 | 'CopilotC-Nvim/CopilotChat.nvim', 3 | enabled = false, 4 | opts = { 5 | show_help = 'no', 6 | debug = false, 7 | disable_extra_info = 'no', 8 | language = 'English', 9 | }, 10 | cmd = { 'CopilotChat' }, 11 | keys = { 12 | { 13 | 'et', 14 | function() 15 | require('CopilotChat').toggle() 16 | end, 17 | desc = 'Open Copilot Chat', 18 | }, 19 | }, 20 | } 21 | -------------------------------------------------------------------------------- /sway/auto_exit_fullscreen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | swaymsg -t subscribe -m '[ "window" ]' | while read line 4 | do 5 | if [ "$(echo "$line" | jq -r '.change')" = "new" ]; then 6 | if [ "$(swaymsg -t get_tree | jq -r '.. | select(.type?) | select(.focused==true).fullscreen_mode')" -eq 1 ]; then 7 | sleep 0.15 8 | swaymsg fullscreen disable 9 | swaymsg [con_id=$(echo "$line" | jq -r '.container.id')] focus 10 | fi 11 | fi 12 | done 13 | -------------------------------------------------------------------------------- /nvim/lua/partials/plugins/treesj.lua: -------------------------------------------------------------------------------- 1 | return { 2 | 'Wansmer/treesj', 3 | cmd = { 'TSJSplit', 'TSJJoin' }, 4 | init = function() 5 | vim.keymap.set('n', 'gS', ':TSJSplit', { silent = true, desc = 'Split to lines' }) 6 | vim.keymap.set('n', 'gJ', ':TSJJoin', { silent = true, desc = 'Join lines' }) 7 | end, 8 | opts = { 9 | use_default_keymaps = false, 10 | check_syntax_error = true, 11 | max_join_length = 200, 12 | cursor_behavior = 'hold', 13 | notify = true, 14 | }, 15 | } 16 | -------------------------------------------------------------------------------- /i3/polybar/start.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | PRIMARY=$(xrandr --query | grep " connected" | grep "primary" | cut -d" " -f1) 4 | OTHERS=$(xrandr --query | grep " connected" | grep -v "primary" | cut -d" " -f1) 5 | 6 | # Terminate already running bar instances 7 | killall -q polybar > /dev/null 8 | 9 | # Wait until the processes have been shut down 10 | while pgrep -x polybar >/dev/null; do sleep 1; done 11 | MONITOR=$PRIMARY polybar bar &> /dev/null & 12 | 13 | sleep 3; 14 | 15 | for m in $OTHERS; do 16 | MONITOR=$m polybar bar &> /dev/null & 17 | done 18 | -------------------------------------------------------------------------------- /nvim/lua/partials/packs/treesj.lua: -------------------------------------------------------------------------------- 1 | vim.keymap.set('n', 'gS', ':TSJSplit', { silent = true, desc = 'Split to lines' }) 2 | vim.keymap.set('n', 'gJ', ':TSJJoin', { silent = true, desc = 'Join lines' }) 3 | 4 | vim.pack.load({ 5 | src = 'Wansmer/treesj', 6 | cmd = { 'TSJSplit', 'TSJJoin' }, 7 | config = function() 8 | require('treesj').setup({ 9 | use_default_keymaps = false, 10 | check_syntax_error = true, 11 | max_join_length = 200, 12 | cursor_behavior = 'hold', 13 | notify = true, 14 | }) 15 | end, 16 | }) 17 | -------------------------------------------------------------------------------- /nvim/snippets/org.json: -------------------------------------------------------------------------------- 1 | { 2 | "block": { 3 | "prefix" : ["block"], 4 | "body": [ 5 | "#+begin_src ${1:language}", 6 | "$0", 7 | "#+end_src" 8 | ] 9 | }, 10 | "note": { 11 | "prefix": ["note"], 12 | "body": [ 13 | "📝 NOTE: $0" 14 | ] 15 | }, 16 | "tip": { 17 | "prefix": ["tip"], 18 | "body": [ 19 | "💡 TIP: $0" 20 | ] 21 | }, 22 | "custom_id": { 23 | "prefix": ["cid"], 24 | "body": [ 25 | ":PROPERTIES:", 26 | ":CUSTOM_ID: ${0}", 27 | ":END:" 28 | ] 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Neovim and terminal configuration 2 | ------ 3 | 4 | This is my Neovim editor setup and other dotfiles, with zsh and Hyprland/Waybar configurations. 5 | Feel free to fork it and submit a pull request if you found any bug. 6 | 7 | 8 | Plugins 9 | ---------------- 10 | 11 | see [plugins.lua](./nvim/lua/partials/plugins.lua) and [plugins](./nvim/lua/partials/plugins/) folder. 12 | 13 | License 14 | ------- 15 | 16 | This project is licensed under MIT License (see LICENSE file for details). But 17 | each plugin has its own license, so check each one to see what you can do. 18 | -------------------------------------------------------------------------------- /nvim/lua/partials/plugins/quicker.lua: -------------------------------------------------------------------------------- 1 | return { 2 | 'stevearc/quicker.nvim', 3 | ft = 'qf', 4 | opts = { 5 | highlight = { 6 | lsp = false, 7 | treesitter = false, 8 | }, 9 | type_icons = { 10 | E = _G.kris.diagnostic_icons[vim.diagnostic.severity.ERROR], 11 | W = _G.kris.diagnostic_icons[vim.diagnostic.severity.WARN], 12 | I = _G.kris.diagnostic_icons[vim.diagnostic.severity.INFO], 13 | N = _G.kris.diagnostic_icons[vim.diagnostic.severity.HINT], 14 | H = _G.kris.diagnostic_icons[vim.diagnostic.severity.HINT], 15 | }, 16 | }, 17 | } 18 | -------------------------------------------------------------------------------- /nvim/snippets/vim.json: -------------------------------------------------------------------------------- 1 | { 2 | "function": { 3 | "prefix": ["fun"], 4 | "body": [ 5 | "function! $1(${2:args}) abort", 6 | "\t$0", 7 | "endfunction" 8 | ], 9 | "description": "Function" 10 | }, 11 | "autocmd": { 12 | "prefix": ["aut"], 13 | "body": [ 14 | "autocmd $1 ${2:* $0}" 15 | ], 16 | "description": "Function" 17 | }, 18 | "augroup": { 19 | "prefix": ["aug"], 20 | "body": [ 21 | "augroup $1", 22 | "\tautocmd!", 23 | "\tautocmd $2 ${3:* $0}", 24 | "augroup END" 25 | ], 26 | "description": "Function" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /nvim/lua/partials/packs/db.lua: -------------------------------------------------------------------------------- 1 | vim.g.db_ui_show_help = 0 2 | vim.g.db_ui_win_position = 'right' 3 | vim.g.db_ui_use_nerd_fonts = 1 4 | vim.g.db_ui_use_nvim_notify = 1 5 | 6 | vim.g.db_ui_save_location = '~/Dropbox/dbui' 7 | vim.g.db_ui_tmp_query_location = '~/code/queries' 8 | 9 | vim.g.db_ui_hide_schemas = { 'pg_toast_temp.*' } 10 | 11 | vim.pack.load({ 12 | src = 'kristijanhusak/vim-dadbod-ui', 13 | dependencies = { 14 | 'tpope/vim-dadbod', 15 | 'kristijanhusak/vim-dadbod-completion', 16 | }, 17 | cmd = { 18 | 'DBUI', 19 | 'DBUIToggle', 20 | 'DBUIAddConnection', 21 | 'DBUIFindBuffer', 22 | }, 23 | }) 24 | -------------------------------------------------------------------------------- /zsh/themes/cloud_kris.zsh-theme: -------------------------------------------------------------------------------- 1 | local ret_status="%(?:%{$fg_bold[cyan]%}▶:%{$fg_bold[red]%}▶)" 2 | 3 | vi_mode_prompt_info () { 4 | if [[ ${KEYMAP} = 'vicmd' ]] 5 | then 6 | echo "$MODE_INDICATOR " 7 | else 8 | echo "" 9 | fi 10 | } 11 | 12 | PROMPT='${ret_status} %{$fg_bold[green]%}%~ %{$fg_bold[cyan]%}$(git_prompt_info)%{$fg_bold[blue]%}%{$reset_color%}$(vi_mode_prompt_info)' 13 | 14 | ZSH_THEME_GIT_PROMPT_PREFIX="%{$fg[green]%}[%{$fg[cyan]%}" 15 | ZSH_THEME_GIT_PROMPT_SUFFIX="%{$reset_color%}" 16 | ZSH_THEME_GIT_PROMPT_DIRTY="%{$fg[green]%}]%{$fg[yellow]%} ✗ %{$reset_color%}" 17 | ZSH_THEME_GIT_PROMPT_CLEAN="%{$fg[green]%}] " 18 | -------------------------------------------------------------------------------- /nvim/lua/partials/pack.lua: -------------------------------------------------------------------------------- 1 | require('partials.utils.pack') 2 | 3 | vim.pack.load({ src = 'tpope/vim-repeat', event = 'VeryLazy' }) 4 | vim.pack.load({ src = 'tpope/vim-sleuth', event = 'VeryLazy' }) 5 | vim.pack.load({ src = 'tpope/vim-abolish', event = 'VeryLazy' }) 6 | vim.pack.load({ src = 'tpope/vim-surround', event = 'VeryLazy' }) 7 | vim.pack.load({ src = 'nvim-tree/nvim-web-devicons' }) 8 | vim.pack.load({ src = 'nvim-lua/plenary.nvim' }) 9 | vim.pack.load({ 10 | src = 'folke/which-key.nvim', 11 | event = 'VeryLazy', 12 | config = function() 13 | require('which-key').setup({ 14 | preset = 'helix', 15 | }) 16 | end, 17 | }) 18 | 19 | vim.pack.dir('./packs') 20 | -------------------------------------------------------------------------------- /nvim/lua/partials/packs/quicker.lua: -------------------------------------------------------------------------------- 1 | vim.pack.load({ 2 | src = 'stevearc/quicker.nvim', 3 | ft = 'qf', 4 | config = function() 5 | require('quicker').setup({ 6 | highlight = { 7 | lsp = false, 8 | treesitter = false, 9 | }, 10 | type_icons = { 11 | E = _G.kris.diagnostic_icons[vim.diagnostic.severity.ERROR], 12 | W = _G.kris.diagnostic_icons[vim.diagnostic.severity.WARN], 13 | I = _G.kris.diagnostic_icons[vim.diagnostic.severity.INFO], 14 | N = _G.kris.diagnostic_icons[vim.diagnostic.severity.HINT], 15 | H = _G.kris.diagnostic_icons[vim.diagnostic.severity.HINT], 16 | }, 17 | }) 18 | end, 19 | }) 20 | -------------------------------------------------------------------------------- /nvim/lua/partials/plugins/db.lua: -------------------------------------------------------------------------------- 1 | return { 2 | 'kristijanhusak/vim-dadbod-ui', 3 | dependencies = { 4 | { 'tpope/vim-dadbod' }, 5 | { 'kristijanhusak/vim-dadbod-completion', ft = { 'sql', 'mysql', 'plsql' } }, 6 | }, 7 | cmd = { 8 | 'DBUI', 9 | 'DBUIToggle', 10 | 'DBUIAddConnection', 11 | 'DBUIFindBuffer', 12 | }, 13 | init = function() 14 | vim.g.db_ui_show_help = 0 15 | vim.g.db_ui_win_position = 'right' 16 | vim.g.db_ui_use_nerd_fonts = 1 17 | vim.g.db_ui_use_nvim_notify = 1 18 | 19 | vim.g.db_ui_save_location = '~/Dropbox/dbui' 20 | vim.g.db_ui_tmp_query_location = '~/code/queries' 21 | 22 | vim.g.db_ui_hide_schemas = { 'pg_toast_temp.*' } 23 | end, 24 | } 25 | -------------------------------------------------------------------------------- /nvim/lua/partials/packs/fugitive.lua: -------------------------------------------------------------------------------- 1 | vim.pack.load({ 2 | src = 'tpope/vim-fugitive', 3 | cmd = { 'G', 'Git', 'Gdiffsplit', 'Gclog', 'GcLog', 'Gread' }, 4 | }) 5 | 6 | vim.keymap.set('n', 'gf', ':vert G', { silent = true, desc = 'Open fugitive' }) 7 | 8 | local git_group = vim.api.nvim_create_augroup('custom_fugitive', { clear = true }) 9 | vim.api.nvim_create_autocmd('FileType', { 10 | pattern = 'fugitive', 11 | callback = function() 12 | vim.keymap.set('n', '', '=zt', { remap = true, silent = true, buffer = true }) 13 | vim.keymap.set('n', '}', ']m=zt', { remap = true, silent = true, buffer = true }) 14 | vim.keymap.set('n', '{', '[m=zt', { remap = true, silent = true, buffer = true }) 15 | end, 16 | group = git_group, 17 | }) 18 | -------------------------------------------------------------------------------- /helix/config.toml: -------------------------------------------------------------------------------- 1 | theme = "tokyonight_moon" 2 | 3 | [editor] 4 | line-number = "relative" 5 | cursorline = true 6 | completion-timeout = 10 7 | 8 | [editor.cursor-shape] 9 | insert = "bar" 10 | 11 | [editor.file-picker] 12 | hidden = false 13 | 14 | [editor.indent-guides] 15 | render = true 16 | character = "▏" 17 | 18 | [editor.statusline] 19 | left = ["mode", "spacer", "spacer", "version-control", "file-name", "file-modification-indicator"] 20 | right = ["spinner", "spacer", "file-type", "separator", "position", "separator", "spacer", "position-percentage", "spacer", "diagnostics"] 21 | mode.normal = "NORMAL" 22 | mode.insert = "INSERT" 23 | mode.select = "SELECT" 24 | 25 | [keys.normal] 26 | "," = { "c" = "toggle_comments"} 27 | C-s = ":w" 28 | 29 | [keys.insert] 30 | "C-[" = "normal_mode" 31 | -------------------------------------------------------------------------------- /nvim/lua/partials/plugins/workspaces.lua: -------------------------------------------------------------------------------- 1 | return { 2 | 'natecraddock/workspaces.nvim', 3 | cmd = { 'WorkspacesAdd', 'WorkspacesOpen' }, 4 | config = function() 5 | require('workspaces').setup({ 6 | path = vim.fs.normalize('~/Dropbox/workspaces'), 7 | hooks = { 8 | open = function() 9 | local workspace_name = require('workspaces').name() 10 | local workspace_path = require('workspaces').path() 11 | vim.notify((' Switched to project: %s\n %s'):format(workspace_name, workspace_path), vim.log.levels.INFO, { 12 | title = 'Workspaces', 13 | }) 14 | local local_nvimrc = vim.fn.getcwd() .. '/.nvim.lua' 15 | if vim.secure.read(local_nvimrc) then 16 | vim.cmd.source(local_nvimrc) 17 | end 18 | end, 19 | }, 20 | }) 21 | end, 22 | } 23 | -------------------------------------------------------------------------------- /nvim/snippets/sql.json: -------------------------------------------------------------------------------- 1 | { 2 | "select": { 3 | "prefix": ["sel"], 4 | "body": [ 5 | "select * from ${1:table};" 6 | ], 7 | "description": "Select from table" 8 | }, 9 | "select-by-id": { 10 | "prefix": ["selid"], 11 | "body": [ 12 | "select * from \"${1:table}\" where \"${2:id}\" = '${3:id}';" 13 | ], 14 | "description": "Select from table by id" 15 | }, 16 | "delete-by-id": { 17 | "prefix": ["del"], 18 | "body": [ 19 | "delete from \"${1:table}\" where \"${2:id}\" = '${3:id}';" 20 | ], 21 | "description": "Delete from table by id" 22 | }, 23 | "cte": { 24 | "prefix": ["cte"], 25 | "body": [ 26 | "with ${1:cte} as (", 27 | "\tselect * from \"${2:table}\"", 28 | ")", 29 | "select * from ${1:cte}$0;" 30 | ], 31 | "description": "Cte" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /nvim/lua/partials/plugins/fugitive.lua: -------------------------------------------------------------------------------- 1 | local fugitive = { 2 | 'tpope/vim-fugitive', 3 | cmd = { 'G', 'Git', 'Gdiffsplit', 'Gclog', 'GcLog', 'Gread' }, 4 | } 5 | fugitive.init = function() 6 | vim.keymap.set('n', 'gf', ':vert G', { silent = true, desc = 'Open fugitive' }) 7 | end 8 | 9 | fugitive.config = function() 10 | local git_group = vim.api.nvim_create_augroup('custom_fugitive', { clear = true }) 11 | vim.api.nvim_create_autocmd('FileType', { 12 | pattern = 'fugitive', 13 | callback = function() 14 | vim.keymap.set('n', '', '=zt', { remap = true, silent = true, buffer = true }) 15 | vim.keymap.set('n', '}', ']m=zt', { remap = true, silent = true, buffer = true }) 16 | vim.keymap.set('n', '{', '[m=zt', { remap = true, silent = true, buffer = true }) 17 | end, 18 | group = git_group, 19 | }) 20 | 21 | return fugitive 22 | end 23 | 24 | return fugitive 25 | -------------------------------------------------------------------------------- /nvim/lua/partials/packs/workspaces.lua: -------------------------------------------------------------------------------- 1 | vim.pack.load({ 2 | src = 'natecraddock/workspaces.nvim', 3 | config = function() 4 | require('workspaces').setup({ 5 | path = vim.fs.normalize('~/Dropbox/workspaces'), 6 | hooks = { 7 | open = function() 8 | local workspace_name = require('workspaces').name() 9 | local workspace_path = require('workspaces').path() 10 | vim.notify((' Switched to project: %s\n %s'):format(workspace_name, workspace_path), vim.log.levels.INFO, { 11 | title = 'Workspaces', 12 | }) 13 | local local_nvimrc = vim.fn.getcwd() .. '/.nvim.lua' 14 | if vim.secure.read(local_nvimrc) then 15 | vim.cmd.source(local_nvimrc) 16 | end 17 | end, 18 | }, 19 | }) 20 | 21 | vim.keymap.set('n', 'w', function() 22 | return require('partials.picker').workspaces() 23 | end, { desc = 'Workspaces' }) 24 | end, 25 | }) 26 | -------------------------------------------------------------------------------- /nvim/lua/partials/plugins/vimspector.lua: -------------------------------------------------------------------------------- 1 | local vimspector = { 2 | 'puremourning/vimspector', 3 | keys = { '', '' }, 4 | } 5 | vimspector.config = function() 6 | vim.keymap.set('n', '', 'VimspectorToggleBreakpoint') 7 | vim.keymap.set('n', '', 'VimspectorToggleConditionalBreakpoint') 8 | vim.keymap.set('n', '', 'VimspectorAddFunctionBreakpoint') 9 | vim.keymap.set('n', '', 'VimspectorRunToCursor') 10 | vim.keymap.set('n', '', 'VimspectorContinue') 11 | vim.keymap.set('n', '', 'VimspectorStepOver') 12 | vim.keymap.set('n', '', 'VimspectorStepOut') 13 | vim.keymap.set('n', '', 'VimspectorStepInto') 14 | 15 | vim.api.nvim_create_user_command('VimspectorPause', 'vimspector#Pause()', { force = true }) 16 | vim.api.nvim_create_user_command('VimspectorStop', 'vimspector#Stop()', { force = true }) 17 | 18 | return vimspector 19 | end 20 | 21 | return vimspector 22 | -------------------------------------------------------------------------------- /nvim/lua/partials/packs/flash.lua: -------------------------------------------------------------------------------- 1 | vim.pack.load({ 2 | src = 'folke/flash.nvim', 3 | event = 'VeryLazy', 4 | config = function() 5 | vim.keymap.set({ 'n', 'x', 'o' }, 's', function() 6 | require('flash').jump() 7 | end, { desc = 'Flash' }) 8 | 9 | vim.keymap.set({ 'n', 'o' }, 'S', function() 10 | require('flash').treesitter() 11 | end, { desc = 'Flash Treesitter' }) 12 | 13 | vim.keymap.set('o', 'r', function() 14 | require('flash').remote() 15 | end, { desc = 'Remote Flash' }) 16 | 17 | vim.keymap.set({ 'o', 'x' }, 'R', function() 18 | require('flash').treesitter_search() 19 | end, { desc = 'Treesitter Search' }) 20 | 21 | vim.keymap.set('c', '', function() 22 | require('flash').toggle() 23 | end, { desc = 'Toggle Flash Search' }) 24 | 25 | require('flash').setup({ 26 | modes = { 27 | char = { 28 | jump_labels = true, 29 | }, 30 | }, 31 | }) 32 | end, 33 | }) 34 | -------------------------------------------------------------------------------- /nvim/lua/partials/packs/diffview.lua: -------------------------------------------------------------------------------- 1 | vim.pack.load({ 2 | src = 'sindrets/diffview.nvim', 3 | cmd = { 'DiffviewOpen', 'DiffviewClose', 'DiffviewFileHistory' }, 4 | }) 5 | 6 | vim.keymap.set('n', 'gd', function() 7 | if vim.t.diffview_view_initialized then 8 | return vim.cmd.DiffviewClose() 9 | end 10 | return vim.cmd.DiffviewOpen() 11 | end, { silent = true, desc = 'Toggle diffview' }) 12 | vim.keymap.set('n', 'gh', ':DiffviewFileHistory %', { silent = true, desc = 'Diffview file history' }) 13 | vim.keymap.set('n', 'gc', function() 14 | vim.cmd.DiffviewClose() 15 | vim.cmd('botright Git commit') 16 | end, { silent = true, desc = 'Git commit' }) 17 | vim.keymap.set('n', 'ga', function() 18 | vim.cmd.DiffviewClose() 19 | vim.cmd('botright Git commit --amend') 20 | end, { silent = true, desc = 'Git commit --amend' }) 21 | vim.keymap.set('n', 'gp', ':Git push', { silent = true, desc = 'Git push' }) 22 | vim.keymap.set( 23 | 'n', 24 | 'gF', 25 | ':Git push --force-with-lease', 26 | { silent = true, desc = 'Git push --force-with-lease' } 27 | ) 28 | -------------------------------------------------------------------------------- /nvim/lua/partials/plugins/flash.lua: -------------------------------------------------------------------------------- 1 | return { 2 | 'folke/flash.nvim', 3 | event = 'VeryLazy', 4 | opts = { 5 | modes = { 6 | char = { 7 | jump_labels = true, 8 | }, 9 | }, 10 | }, 11 | keys = { 12 | { 13 | 's', 14 | mode = { 'n', 'x', 'o' }, 15 | function() 16 | require('flash').jump() 17 | end, 18 | desc = 'Flash', 19 | }, 20 | { 21 | 'S', 22 | mode = { 'n', 'o' }, 23 | function() 24 | require('flash').treesitter() 25 | end, 26 | desc = 'Flash Treesitter', 27 | }, 28 | { 29 | 'r', 30 | mode = 'o', 31 | function() 32 | require('flash').remote() 33 | end, 34 | desc = 'Remote Flash', 35 | }, 36 | { 37 | 'R', 38 | mode = { 'o', 'x' }, 39 | function() 40 | require('flash').treesitter_search() 41 | end, 42 | desc = 'Treesitter Search', 43 | }, 44 | { 45 | '', 46 | mode = { 'c' }, 47 | function() 48 | require('flash').toggle() 49 | end, 50 | desc = 'Toggle Flash Search', 51 | }, 52 | }, 53 | } 54 | -------------------------------------------------------------------------------- /nvim/after/plugin/replace_pair.lua: -------------------------------------------------------------------------------- 1 | local replace_pair = {} 2 | local fn = vim.fn 3 | local chars = { 4 | ['{'] = { '}', 'left' }, 5 | ['}'] = { '{', 'right' }, 6 | ['['] = { ']', 'left' }, 7 | [']'] = { '[', 'right' }, 8 | ['('] = { ')', 'left' }, 9 | [')'] = { '(', 'right' }, 10 | } 11 | 12 | function replace_pair.run() 13 | if vim.wo.diff then 14 | return vim.cmd.diffupdate() 15 | end 16 | 17 | local char = fn.getline('.'):sub(fn.col('.'), fn.col('.')) 18 | if not chars[char] then 19 | return fn.feedkeys('R', 'n') 20 | end 21 | 22 | local new_char = fn.nr2char(fn.getchar()) 23 | local flags = 'nW' 24 | local search_char = char 25 | if chars[char][2] == 'right' then 26 | flags = flags .. 'b' 27 | search_char = chars[char][1] 28 | end 29 | local lnum, col = 30 | unpack(fn.searchpairpos(fn.escape(search_char, '[]'), '', fn.escape(chars[search_char][1], '[]'), flags)) 31 | vim.cmd('norm!r' .. new_char) 32 | local view = fn.winsaveview() 33 | vim.fn.cursor({ lnum, col }) 34 | vim.cmd('norm!r' .. chars[new_char][1]) 35 | return fn.winrestview(view) 36 | end 37 | 38 | vim.keymap.set('n', 'R', replace_pair.run, { silent = true }) 39 | -------------------------------------------------------------------------------- /kitty/reload_colors.py: -------------------------------------------------------------------------------- 1 | import os 2 | import signal 3 | from typing import (Iterable, List) 4 | 5 | def reload_all_kitty_terminals(): 6 | for pid in get_all_processes(): 7 | try: 8 | cmd = cmdline_of_pid(pid) 9 | except Exception: 10 | continue 11 | if cmd and is_kitty_gui_cmdline(*cmd): 12 | os.kill(pid, signal.SIGUSR1) 13 | 14 | def is_kitty_gui_cmdline(*cmd: str) -> bool: 15 | if not cmd: 16 | return False 17 | if os.path.basename(cmd[0]) != 'kitty': 18 | return False 19 | if len(cmd) == 1: 20 | return True 21 | s = cmd[1][:1] 22 | if s == '@': 23 | return False 24 | if s == '+': 25 | if cmd[1] == '+': 26 | return len(cmd) > 2 and cmd[2] == 'open' 27 | return cmd[1] == '+open' 28 | return True 29 | 30 | def get_all_processes() -> Iterable[int]: 31 | for c in os.listdir('/proc'): 32 | if c.isdigit(): 33 | yield int(c) 34 | 35 | def cmdline_of_pid(pid: int) -> List[str]: 36 | with open(f'/proc/{pid}/cmdline', 'rb') as f: 37 | return list(filter(None, f.read().decode('utf-8').split('\0'))) 38 | 39 | reload_all_kitty_terminals() 40 | -------------------------------------------------------------------------------- /nvim/lua/partials/plugins/diffview.lua: -------------------------------------------------------------------------------- 1 | local diffview = { 2 | 'sindrets/diffview.nvim', 3 | cmd = { 'DiffviewOpen', 'DiffviewClose', 'DiffviewFileHistory' }, 4 | } 5 | diffview.init = function() 6 | vim.keymap.set('n', 'gd', function() 7 | if vim.t.diffview_view_initialized then 8 | return vim.cmd.DiffviewClose() 9 | end 10 | return vim.cmd.DiffviewOpen() 11 | end, { silent = true, desc = 'Toggle diffview' }) 12 | vim.keymap.set('n', 'gh', ':DiffviewFileHistory %', { silent = true, desc = 'Diffview file history' }) 13 | vim.keymap.set('n', 'gc', function() 14 | vim.cmd.DiffviewClose() 15 | vim.cmd('botright Git commit') 16 | end, { silent = true, desc = 'Git commit' }) 17 | vim.keymap.set('n', 'ga', function() 18 | vim.cmd.DiffviewClose() 19 | vim.cmd('botright Git commit --amend') 20 | end, { silent = true, desc = 'Git commit --amend' }) 21 | vim.keymap.set('n', 'gp', ':Git push', { silent = true, desc = 'Git push' }) 22 | vim.keymap.set( 23 | 'n', 24 | 'gF', 25 | ':Git push --force-with-lease', 26 | { silent = true, desc = 'Git push --force-with-lease' } 27 | ) 28 | end 29 | 30 | return diffview 31 | -------------------------------------------------------------------------------- /nvim/lua/partials/lazy.lua: -------------------------------------------------------------------------------- 1 | local lazypath = vim.fn.stdpath('data') .. '/lazy/lazy.nvim' 2 | if not vim.loop.fs_stat(lazypath) then 3 | vim.fn.system({ 4 | 'git', 5 | 'clone', 6 | '--filter=blob:none', 7 | '--single-branch', 8 | 'https://github.com/folke/lazy.nvim.git', 9 | lazypath, 10 | }) 11 | end 12 | vim.opt.runtimepath:prepend(lazypath) 13 | 14 | require('lazy').setup('partials.plugins', { 15 | defaults = { 16 | lazy = true, 17 | }, 18 | ui = { 19 | border = 'rounded', 20 | custom_keys = { 21 | ['ll'] = function(plugin) 22 | require('lazy.util').float_term({ 'lazygit', 'log' }, { 23 | cwd = plugin.dir, 24 | }) 25 | end, 26 | }, 27 | }, 28 | dev = { 29 | path = '~/github', 30 | }, 31 | change_detection = { 32 | notify = false, 33 | }, 34 | install = { 35 | colorscheme = { 'tokyonight' }, 36 | }, 37 | performance = { 38 | rtp = { 39 | disabled_plugins = { 40 | 'gzip', 41 | 'matchit', 42 | 'matchparen', 43 | 'netrwPlugin', 44 | 'tarPlugin', 45 | 'tohtml', 46 | 'tutor', 47 | 'zipPlugin', 48 | }, 49 | }, 50 | }, 51 | lockfile = vim.fn.stdpath('data') .. '/lazy-lock.json', 52 | }) 53 | -------------------------------------------------------------------------------- /nvim/lua/partials/plugins/local_git_history.lua: -------------------------------------------------------------------------------- 1 | return { 2 | 'm42e/lgh.nvim', 3 | event = 'VeryLazy', 4 | config = function() 5 | local lgh = require('lgh') 6 | lgh.setup({}) 7 | 8 | local function on_open(file) 9 | vim.cmd(('vsplit %s'):format(file)) 10 | vim.bo.buftype = 'nofile' 11 | vim.bo.modifiable = false 12 | vim.bo.readonly = true 13 | end 14 | 15 | vim.api.nvim_create_user_command('LGHFind', function() 16 | local path = ('%s%s/%s'):format(lgh.config.basedir, vim.fn.hostname(), vim.uv.cwd()) 17 | Snacks.picker.files({ 18 | cwd = path, 19 | confirm = function(picker) 20 | local file = picker:current() 21 | picker:close() 22 | on_open(file._path) 23 | end, 24 | }) 25 | end, { 26 | nargs = 0, 27 | }) 28 | vim.api.nvim_create_user_command('LGH', function(args) 29 | local file = args.fargs[1] and vim.fn.fnamemodify(args.fargs[1], ':p') or vim.fn.expand('%:p') 30 | local path = ('%s%s/%s'):format(lgh.config.basedir, vim.fn.hostname(), file) 31 | if not vim.uv.fs_stat(path) then 32 | return vim.notify('No history found for this file', vim.log.levels.WARN) 33 | end 34 | on_open(path) 35 | end, { 36 | nargs = '?', 37 | complete = 'file', 38 | }) 39 | end, 40 | } 41 | -------------------------------------------------------------------------------- /nvim/lua/partials/packs/local_git_history.lua: -------------------------------------------------------------------------------- 1 | vim.pack.load({ 2 | src = 'm42e/lgh.nvim', 3 | event = 'VeryLazy', 4 | config = function() 5 | local lgh = require('lgh') 6 | lgh.setup({}) 7 | 8 | local function on_open(file) 9 | vim.cmd(('vsplit %s'):format(file)) 10 | vim.bo.buftype = 'nofile' 11 | vim.bo.modifiable = false 12 | vim.bo.readonly = true 13 | end 14 | 15 | vim.api.nvim_create_user_command('LGHFind', function() 16 | local path = ('%s%s/%s'):format(lgh.config.basedir, vim.fn.hostname(), vim.uv.cwd()) 17 | Snacks.picker.files({ 18 | cwd = path, 19 | confirm = function(picker) 20 | local file = picker:current() 21 | picker:close() 22 | on_open(file._path) 23 | end, 24 | }) 25 | end, { 26 | nargs = 0, 27 | }) 28 | vim.api.nvim_create_user_command('LGH', function(args) 29 | local file = args.fargs[1] and vim.fn.fnamemodify(args.fargs[1], ':p') or vim.fn.expand('%:p') 30 | local path = ('%s%s/%s'):format(lgh.config.basedir, vim.fn.hostname(), file) 31 | if not vim.uv.fs_stat(path) then 32 | return vim.notify('No history found for this file', vim.log.levels.WARN) 33 | end 34 | on_open(path) 35 | end, { 36 | nargs = '?', 37 | complete = 'file', 38 | }) 39 | end, 40 | }) 41 | -------------------------------------------------------------------------------- /i3/polybar/popup-calendar.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | BAR_HEIGHT=22 # polybar height 4 | BORDER_SIZE=50 # border size from your wm settings 5 | YAD_WIDTH=222 # 222 is minimum possible value 6 | YAD_HEIGHT=193 # 193 is minimum possible value 7 | DATE="$(date +"%A %d.%m.%Y")" 8 | LC_TIME="en_GB.utf8" 9 | 10 | case "$1" in 11 | --popup) 12 | if [ "$(xdotool getwindowfocus getwindowname)" = "yad-calendar" ]; then 13 | exit 0 14 | fi 15 | 16 | eval "$(xdotool getmouselocation --shell)" 17 | eval "$(xdotool getdisplaygeometry --shell)" 18 | 19 | # X 20 | if [ "$((X + YAD_WIDTH / 2 + BORDER_SIZE))" -gt "$WIDTH" ]; then #Right side 21 | : $((pos_x = WIDTH - YAD_WIDTH - BORDER_SIZE)) 22 | elif [ "$((X - YAD_WIDTH / 2 - BORDER_SIZE))" -lt 0 ]; then #Left side 23 | : $((pos_x = BORDER_SIZE)) 24 | else #Center 25 | : $((pos_x = X - YAD_WIDTH / 2)) 26 | fi 27 | 28 | # Y 29 | if [ "$Y" -gt "$((HEIGHT / 2))" ]; then #Bottom 30 | : $((pos_y = HEIGHT - YAD_HEIGHT - BAR_HEIGHT - BORDER_SIZE)) 31 | else #Top 32 | : $((pos_y = BAR_HEIGHT + BORDER_SIZE)) 33 | fi 34 | 35 | yad --calendar --undecorated --fixed --close-on-unfocus --no-buttons \ 36 | --width="$YAD_WIDTH" --height="$YAD_HEIGHT" --posx="$pos_x" --posy="$pos_y" \ 37 | --title="yad-calendar" --borders=0 >/dev/null & 38 | ;; 39 | *) 40 | echo "$DATE" 41 | ;; 42 | esac 43 | -------------------------------------------------------------------------------- /nvim/after/ftplugin/go.lua: -------------------------------------------------------------------------------- 1 | local go = {} 2 | 3 | function go.setup() 4 | vim.bo.expandtab = false 5 | vim.bo.tabstop = 4 6 | end 7 | 8 | function go.add_tags() 9 | local struct = vim.fn.expand('') 10 | local type = vim.fn.input('Type: ', 'json') 11 | local file = vim.fn.expand('%:p') 12 | local view = vim.fn.winsaveview() 13 | local response = vim.fn.systemlist(string.format('gomodifytags -file %s -struct %s -add-tags %s', file, struct, type)) 14 | vim.api.nvim_buf_set_lines(0, 0, -1, true, response) 15 | vim.fn.winrestview(view) 16 | end 17 | 18 | function go.format() 19 | local params = vim.lsp.util.make_range_params() 20 | params.context = { only = { 'source.organizeImports' } } 21 | local result = vim.lsp.buf_request_sync(0, 'textDocument/codeAction', params) 22 | for cid, res in pairs(result or {}) do 23 | for _, r in pairs(res.result or {}) do 24 | if r.edit then 25 | local enc = (vim.lsp.get_client_by_id(cid) or {}).offset_encoding or 'utf-16' 26 | vim.lsp.util.apply_workspace_edit(r.edit, enc) 27 | end 28 | end 29 | end 30 | vim.lsp.buf.format({ async = false }) 31 | end 32 | 33 | local go_group = vim.api.nvim_create_augroup('vimrc_go', { clear = true }) 34 | vim.api.nvim_create_autocmd('BufWritePre', { 35 | pattern = '*.go', 36 | callback = go.format, 37 | group = go_group, 38 | }) 39 | 40 | vim.api.nvim_create_user_command('GoAddTags', go.add_tags, { force = true }) 41 | go.setup() 42 | -------------------------------------------------------------------------------- /kitty/kitty.conf: -------------------------------------------------------------------------------- 1 | # font_family JetBrains Mono SemiBold 2 | # bold_font JetBrains Mono ExtraBold 3 | # italic_font JetBrains Mono SemiBold Italic 4 | # bold_italic_font JetBrains Mono ExtraBold Italic 5 | # text_composition_strategy 1.3 30 6 | # font_size 11.5 7 | 8 | font_family family='Cascadia Code' 9 | bold_font family='Cascadia Code' style=Bold 10 | italic_font family='Cascadia Code' features='+ss01' 11 | bold_italic_font family='Cascadia Code' style='Bold Italic' features='+ss01' 12 | font_size 12.0 13 | text_composition_strategy 1.7 30 14 | 15 | symbol_map U+e000-U+e00a,U+ea60-U+ebeb,U+e0a0-U+e0c8,U+e0ca,U+e0cc-U+e0d4,U+e200-U+e2a9,U+e300-U+e3e3,U+e5fa-U+e6b1,U+e700-U+e7c5,U+f000-U+f2e0,U+f300-U+f372,U+f400-U+f532,U+f0001-U+f1af0 Symbols Nerd Font Mono 16 | adjust_line_height 8 17 | cursor_shape beam 18 | cursor_blink_interval 0.5 19 | url_color #0087BD 20 | url_style curly 21 | open_url_with default 22 | copy_on_select no 23 | enable_audio_bell no 24 | window_border_width 0.0 25 | window_margin_width 0.0 26 | window_padding_width 0.0 27 | scrollback_lines 99999 28 | map alt+shift+enter new_os_window_with_cwd 29 | map ctrl+shift+equal change_font_size all +0.5 30 | map ctrl+shift+minus change_font_size all -0.5 31 | modify_font strikethrough_position 3px 32 | allow_remote_control yes 33 | scrollback_pager nvim --noplugin -u NONE -c 'runtime plugin/man.lua|Man!' -c "autocmd VimEnter * normal G" -c "nnoremap Q :qa!" - 34 | paste_actions no-op 35 | 36 | include ~/.cache/main_colorscheme.conf 37 | include local.conf 38 | -------------------------------------------------------------------------------- /waybar/style.css: -------------------------------------------------------------------------------- 1 | @import url("local.css"); 2 | 3 | * { 4 | font-family: "JetBrains Mono", "Symbols Nerd Font Mono", "Twemoji"; 5 | font-size: 12px; 6 | } 7 | 8 | window#waybar { 9 | background: @bg; 10 | color: @fg; 11 | margin-top: 5px; 12 | margin-bottom: 5px; 13 | } 14 | 15 | #cpu, #language { 16 | border-bottom: 3px solid #f90000; 17 | } 18 | 19 | #memory { 20 | border-bottom: 3px solid #4bffdc; 21 | min-width: 115px; 22 | } 23 | 24 | #workspaces button.focused, #workspaces button.active { 25 | background: @fg; 26 | color: @bg; 27 | border-bottom: 3px solid #ffb52a; 28 | padding: 0 6px; 29 | } 30 | 31 | #workspaces button.urgent { 32 | background: #bd2c40; 33 | color: @fg; 34 | } 35 | 36 | #workspaces button { 37 | background: transparent; 38 | color: @fg; 39 | padding: 1px 6px; 40 | } 41 | 42 | 43 | #keyboard-state label.locked, #submap.resize { 44 | background: #bd2c40; 45 | padding: 0 6px; 46 | color: white; 47 | font-weight: bold; 48 | } 49 | 50 | #clock { 51 | color: @fg; 52 | border-bottom: 3px solid #0a6cf5; 53 | } 54 | 55 | #clock calendar { 56 | font-size: 12px; 57 | } 58 | 59 | #pulseaudio.muted { 60 | color: #666; 61 | } 62 | 63 | #custom-notification { 64 | font-size: 16px; 65 | margin-right: 0; 66 | min-width: 20px; 67 | } 68 | 69 | #tray { 70 | padding-right: 6px; 71 | } 72 | 73 | #custom-exchangerates, 74 | #custom-weather, 75 | #disk, 76 | #memory, 77 | #cpu, 78 | #language, 79 | #battery, 80 | #pulseaudio, 81 | #clock { 82 | margin-right: 14px; 83 | } 84 | -------------------------------------------------------------------------------- /hypr/record_screen.sh: -------------------------------------------------------------------------------- 1 | RECORDINGS_DIR=~/Recordings 2 | 3 | if [ "$1" = "--start" ]; then 4 | REGION="$(slurp)" 5 | [ -z "$REGION" ] && notify-send -i dialog-error "No region selected" && exit 6 | 7 | FILENAME=$(zenity --entry --title="Recording name" --text="Enter file name (without extension):") 8 | if [ $? -ne 0 ]; then 9 | notify-send -i dialog-warning "Recording canceled" 10 | exit 11 | fi 12 | [ -z "$FILENAME" ] && FILENAME="recording" 13 | 14 | FULL_FILENAME="${FILENAME}_$(date +%Y-%m-%d_%H-%M-%S).mp4" 15 | nid=$(notify-send -i dialog-information "Recording $FULL_FILENAME" "Recording in 3..." -t 2800 --print-id) 16 | sleep 1 17 | notify-send -i dialog-information "Recording $FULL_FILENAME" "Recording in 2..." --replace-id=$nid 18 | sleep 1 19 | notify-send -i dialog-information "Recording $FULL_FILENAME" "Recording in 1..." --replace-id=$nid 20 | sleep 0.8 21 | notify-send -i dialog-information "Recording $FULL_FILENAME" "Recording!" --replace-id=$nid -t 150 22 | sleep 0.2 23 | wf-recorder -g "$REGION" -f "$RECORDINGS_DIR/${FILENAME}_$(date +%Y-%m-%d_%H-%M-%S).mp4" 24 | elif [ "$1" = "--stop" ]; then 25 | pkill wf-recorder \ 26 | && notify-send -i dialog-information --action="open:Open Recordings" "Recording stopped." "Click to open recordings folder." \ 27 | || notify-send -i dialog-warning --action="open:Open Recordings" "No recording was running." 28 | swaync-client --action=open && xdg-open "$RECORDINGS_DIR" & 29 | else 30 | echo "Usage: $0 --start|--stop" 31 | exit 1 32 | fi 33 | -------------------------------------------------------------------------------- /waybar/cycle_audio_output.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Get a list of all sinks by name and their corresponding descriptions 4 | mapfile -t SINK_DATA < <(pactl list sinks | awk '/^Sink #/ {sink_id=$2} /^\s*Name:/ {sink_name=$2} /^\s*Description:/ {gsub("^[ \t]*Description:[ \t]*", ""); sink_desc=$0; print sink_name "|" sink_desc}') 5 | 6 | # Parse the data into two separate arrays: names and descriptions 7 | SINK_NAMES=() 8 | SINK_DESCRIPTIONS=() 9 | for line in "${SINK_DATA[@]}"; do 10 | SINK_NAMES+=( "$(echo "$line" | cut -d'|' -f1)" ) 11 | SINK_DESCRIPTIONS+=( "$(echo "$line" | cut -d'|' -f2)" ) 12 | done 13 | 14 | # Get the current default sink name 15 | DEFAULT_SINK_NAME=$(pactl info | grep 'Default Sink' | awk '{print $3}') 16 | 17 | # Find the index of the current default sink 18 | CURRENT_INDEX=-1 19 | for i in "${!SINK_NAMES[@]}"; do 20 | if [[ "${SINK_NAMES[$i]}" == "$DEFAULT_SINK_NAME" ]]; then 21 | CURRENT_INDEX=$i 22 | break 23 | fi 24 | done 25 | 26 | # Calculate the next sink's index 27 | NEXT_INDEX=$(( (CURRENT_INDEX + 1) % ${#SINK_NAMES[@]} )) 28 | 29 | # Get the name and description of the next sink 30 | NEXT_SINK_NAME="${SINK_NAMES[$NEXT_INDEX]}" 31 | NEXT_SINK_DESC="${SINK_DESCRIPTIONS[$NEXT_INDEX]}" 32 | 33 | # Set the next sink as the default 34 | pactl set-default-sink "$NEXT_SINK_NAME" 35 | 36 | # Send a notification to confirm the switch with the human-readable description 37 | NOTIF_BODY="Switched default output to: $NEXT_SINK_DESC" 38 | notify-send "Audio Output Changed" "$NOTIF_BODY" -i audio-speakers -t 3000 39 | -------------------------------------------------------------------------------- /i3/polybar/cycle_audio_output.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Get a list of all sinks by name and their corresponding descriptions 4 | mapfile -t SINK_DATA < <(pactl list sinks | awk '/^Sink #/ {sink_id=$2} /^\s*Name:/ {sink_name=$2} /^\s*Description:/ {gsub("^[ \t]*Description:[ \t]*", ""); sink_desc=$0; print sink_name "|" sink_desc}') 5 | 6 | # Parse the data into two separate arrays: names and descriptions 7 | SINK_NAMES=() 8 | SINK_DESCRIPTIONS=() 9 | for line in "${SINK_DATA[@]}"; do 10 | SINK_NAMES+=( "$(echo "$line" | cut -d'|' -f1)" ) 11 | SINK_DESCRIPTIONS+=( "$(echo "$line" | cut -d'|' -f2)" ) 12 | done 13 | 14 | # Get the current default sink name 15 | DEFAULT_SINK_NAME=$(pactl info | grep 'Default Sink' | awk '{print $3}') 16 | 17 | # Find the index of the current default sink 18 | CURRENT_INDEX=-1 19 | for i in "${!SINK_NAMES[@]}"; do 20 | if [[ "${SINK_NAMES[$i]}" == "$DEFAULT_SINK_NAME" ]]; then 21 | CURRENT_INDEX=$i 22 | break 23 | fi 24 | done 25 | 26 | # Calculate the next sink's index 27 | NEXT_INDEX=$(( (CURRENT_INDEX + 1) % ${#SINK_NAMES[@]} )) 28 | 29 | # Get the name and description of the next sink 30 | NEXT_SINK_NAME="${SINK_NAMES[$NEXT_INDEX]}" 31 | NEXT_SINK_DESC="${SINK_DESCRIPTIONS[$NEXT_INDEX]}" 32 | 33 | # Set the next sink as the default 34 | pactl set-default-sink "$NEXT_SINK_NAME" 35 | 36 | # Send a notification to confirm the switch with the human-readable description 37 | NOTIF_BODY="Switched default output to: $NEXT_SINK_DESC" 38 | notify-send "Audio Output Changed" "$NOTIF_BODY" -i audio-speakers -t 3000 39 | -------------------------------------------------------------------------------- /waybar/show_audio_devices.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # --- Get Default Playback Output (Sink) --- 4 | DEFAULT_SINK_NAME=$(pactl info | grep 'Default Sink' | awk '{print $3}') 5 | DEFAULT_SINK_DESC="" 6 | 7 | # Try to get the friendly description of the sink 8 | if [[ -n "$DEFAULT_SINK_NAME" ]]; then 9 | DEFAULT_SINK_DESC=$(pactl list sinks | grep -A 5 "Name: $DEFAULT_SINK_NAME" | grep 'Description:' | sed 's/^[[:space:]]*Description:[[:space:]]*//') 10 | if [[ -z "$DEFAULT_SINK_DESC" ]]; then 11 | # Fallback to the name if description is not found (or empty) 12 | DEFAULT_SINK_DESC="$DEFAULT_SINK_NAME" 13 | fi 14 | else 15 | DEFAULT_SINK_DESC="N/A (No default sink found)" 16 | fi 17 | 18 | # --- Get Default Microphone Input (Source) --- 19 | DEFAULT_SOURCE_NAME=$(pactl info | grep 'Default Source' | awk '{print $3}') 20 | DEFAULT_SOURCE_DESC="" 21 | 22 | # Try to get the friendly description of the source 23 | if [[ -n "$DEFAULT_SOURCE_NAME" ]]; then 24 | DEFAULT_SOURCE_DESC=$(pactl list sources | grep -A 5 "Name: $DEFAULT_SOURCE_NAME" | grep 'Description:' | sed 's/^[[:space:]]*Description:[[:space:]]*//') 25 | if [[ -z "$DEFAULT_SOURCE_DESC" ]]; then 26 | # Fallback to the name if description is not found (or empty) 27 | DEFAULT_SOURCE_DESC="$DEFAULT_SOURCE_NAME" 28 | fi 29 | else 30 | DEFAULT_SOURCE_DESC="N/A (No default source found)" 31 | fi 32 | 33 | # --- Create and Send Notification --- 34 | NOTIFICATION_TITLE="Current Audio Devices" 35 | NOTIFICATION_BODY="Output: $DEFAULT_SINK_DESC\nInput: $DEFAULT_SOURCE_DESC" 36 | 37 | notify-send "$NOTIFICATION_TITLE" "$NOTIFICATION_BODY" -i audio-speakers -t 3000 38 | -------------------------------------------------------------------------------- /i3/polybar/show_audio_devices.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # --- Get Default Playback Output (Sink) --- 4 | DEFAULT_SINK_NAME=$(pactl info | grep 'Default Sink' | awk '{print $3}') 5 | DEFAULT_SINK_DESC="" 6 | 7 | # Try to get the friendly description of the sink 8 | if [[ -n "$DEFAULT_SINK_NAME" ]]; then 9 | DEFAULT_SINK_DESC=$(pactl list sinks | grep -A 5 "Name: $DEFAULT_SINK_NAME" | grep 'Description:' | sed 's/^[[:space:]]*Description:[[:space:]]*//') 10 | if [[ -z "$DEFAULT_SINK_DESC" ]]; then 11 | # Fallback to the name if description is not found (or empty) 12 | DEFAULT_SINK_DESC="$DEFAULT_SINK_NAME" 13 | fi 14 | else 15 | DEFAULT_SINK_DESC="N/A (No default sink found)" 16 | fi 17 | 18 | # --- Get Default Microphone Input (Source) --- 19 | DEFAULT_SOURCE_NAME=$(pactl info | grep 'Default Source' | awk '{print $3}') 20 | DEFAULT_SOURCE_DESC="" 21 | 22 | # Try to get the friendly description of the source 23 | if [[ -n "$DEFAULT_SOURCE_NAME" ]]; then 24 | DEFAULT_SOURCE_DESC=$(pactl list sources | grep -A 5 "Name: $DEFAULT_SOURCE_NAME" | grep 'Description:' | sed 's/^[[:space:]]*Description:[[:space:]]*//') 25 | if [[ -z "$DEFAULT_SOURCE_DESC" ]]; then 26 | # Fallback to the name if description is not found (or empty) 27 | DEFAULT_SOURCE_DESC="$DEFAULT_SOURCE_NAME" 28 | fi 29 | else 30 | DEFAULT_SOURCE_DESC="N/A (No default source found)" 31 | fi 32 | 33 | # --- Create and Send Notification --- 34 | NOTIFICATION_TITLE="Current Audio Devices" 35 | NOTIFICATION_BODY="Output: $DEFAULT_SINK_DESC\nInput: $DEFAULT_SOURCE_DESC" 36 | 37 | notify-send "$NOTIFICATION_TITLE" "$NOTIFICATION_BODY" -i audio-speakers -t 3000 38 | -------------------------------------------------------------------------------- /nvim/lua/partials/packs/codecompanion.lua: -------------------------------------------------------------------------------- 1 | vim.pack.load({ 2 | src = 'olimorris/codecompanion.nvim', 3 | event = 'VeryLazy', 4 | dependencies = { 5 | 'ravitemer/codecompanion-history.nvim', 6 | }, 7 | config = function() 8 | vim.keymap.set({ 'n', 'x' }, 'ea', function() 9 | vim.cmd('CodeCompanionActions') 10 | end, { desc = 'Open Code Companion Actions' }) 11 | vim.keymap.set({ 'n', 'x' }, 'ee', function() 12 | vim.cmd('CodeCompanionChat') 13 | end, { desc = 'Open Code Companion Chat' }) 14 | 15 | require('codecompanion').setup({ 16 | extensions = { 17 | history = { 18 | enabled = true, 19 | opts = { 20 | picker = 'default', 21 | }, 22 | }, 23 | }, 24 | interactions = { 25 | chat = { adapter = 'copilot' }, 26 | inline = { adapter = 'copilot' }, 27 | }, 28 | adapters = { 29 | http = { 30 | gemini = function() 31 | return require('codecompanion.adapters').extend('gemini', { 32 | env = { 33 | api_key = vim.env.GEMINI_API_KEY, 34 | }, 35 | }) 36 | end, 37 | }, 38 | }, 39 | }) 40 | 41 | vim.api.nvim_create_autocmd({ 'User' }, { 42 | pattern = 'CodeCompanionRequest*', 43 | group = vim.api.nvim_create_augroup('CodeCompanionStatus', { clear = true }), 44 | callback = function(request) 45 | if request.match == 'CodeCompanionRequestStarted' then 46 | Snacks.notify.info(' CodeCompanion Running...', { 47 | id = 'codecompanion_status', 48 | timeout = 0, 49 | }) 50 | elseif request.match == 'CodeCompanionRequestFinished' then 51 | Snacks.notifier.hide('codecompanion_status') 52 | end 53 | end, 54 | }) 55 | end, 56 | }) 57 | -------------------------------------------------------------------------------- /nvim/after/ftplugin/lua.lua: -------------------------------------------------------------------------------- 1 | local lua = {} 2 | local fn = vim.fn 3 | local utils = require('partials.utils') 4 | 5 | local function do_print() 6 | local view = fn.winsaveview() or {} 7 | local word = fn.expand('') 8 | local scope = utils.get_gps_scope(word) 9 | if not scope:match(vim.pesc(word) .. '$') then 10 | scope = ('%s > %s'):format(scope, word) 11 | end 12 | vim.cmd(string.format("keepjumps norm!oprint('%s', vim.inspect(%s))", scope, word)) 13 | fn.winrestview(view) 14 | end 15 | 16 | function lua.setup() 17 | vim.bo.keywordprg = ':help' 18 | vim.keymap.set('n', 'D', lua.generate_docblock, { buffer = true, desc = 'Generate docblock' }) 19 | vim.keymap.set('n', 'll', do_print, { buffer = true, desc = 'Print word under cursor' }) 20 | end 21 | 22 | function lua.generate_docblock() 23 | local node = vim.treesitter.get_node() 24 | assert(node) 25 | if node:type() ~= 'parameters' and node:parent():type() ~= 'parameters' then 26 | vim.notify('Put cursor on parameters', vim.log.levels.WARN) 27 | return 28 | end 29 | if node:type() ~= 'parameters' then 30 | node = node:parent() 31 | end 32 | assert(node) 33 | local method_name = vim.treesitter.get_node_text(node, 0) 34 | 35 | local content = {} 36 | 37 | if method_name:find('^_') then 38 | table.insert(content, '---@private') 39 | end 40 | 41 | local return_type = 'string' 42 | 43 | if method_name:find('^_?is_') or method_name:find('^_?has_') then 44 | return_type = 'boolean' 45 | end 46 | 47 | for child in node:iter_children() do 48 | if child:type() == 'identifier' then 49 | local node_text = vim.treesitter.get_node_text(child, 0) 50 | table.insert(content, string.format('---@param %s string', node_text)) 51 | end 52 | end 53 | 54 | table.insert(content, '---@return ' .. return_type) 55 | fn.append(fn.line('.') - 1, content) 56 | end 57 | 58 | lua.setup() 59 | -------------------------------------------------------------------------------- /nvim/after/plugin/simple_f.lua: -------------------------------------------------------------------------------- 1 | local ns = vim.api.nvim_create_namespace('custom_find') 2 | 3 | local function simple_ft(key, is_normal_mode) 4 | local is_forward = vim.tbl_contains({ 'f', 't' }, key) 5 | local col = vim.fn.col('.') 6 | local line = vim.fn.line('.') 7 | local chars = {} 8 | if is_forward then 9 | chars = vim.split(vim.fn.getline(line):sub(col + 1), '') 10 | else 11 | chars = vim.fn.reverse(vim.split(vim.fn.getline(line):sub(1, col - 1), '')) 12 | end 13 | local chars_map = {} 14 | for i, char in ipairs(chars) do 15 | local off = is_forward and (col + i) or (col - i) 16 | if char and char ~= '' and not chars_map[char] then 17 | chars_map[char] = i 18 | vim.api.nvim_buf_add_highlight(0, ns, 'SimpleF', line - 1, off - 1, off) 19 | end 20 | end 21 | 22 | -- Avoid error when canceling with 23 | local old_cc_keymap = vim.fn.maparg('', 'n') 24 | vim.keymap.set('n', '', '', { buffer = true }) 25 | 26 | local finish = function() 27 | vim.schedule(function() 28 | vim.api.nvim_buf_clear_namespace(0, ns, line - 1, line) 29 | if not old_cc_keymap or old_cc_keymap == '' then 30 | vim.keymap.del('n', '', { buffer = true }) 31 | else 32 | vim.keymap.set('n', '', old_cc_keymap, { buffer = true }) 33 | end 34 | end) 35 | end 36 | 37 | vim.cmd.redraw() 38 | 39 | if not is_normal_mode then 40 | finish() 41 | return key 42 | end 43 | 44 | local char = vim.fn.getchar() 45 | finish() 46 | return ('%d%s%s'):format(vim.v.count1, key, vim.fn.nr2char(char)) 47 | end 48 | 49 | -- for _, key in ipairs({ 'f', 't', 'F', 'T' }) do 50 | -- vim.keymap.set('n', key, function() 51 | -- return vim.cmd.normal({ simple_ft(key, true), bang = true }) 52 | -- end) 53 | -- vim.keymap.set({ 'x', 'o' }, key, function() 54 | -- return simple_ft(key) 55 | -- end, { expr = true, remap = true }) 56 | -- end 57 | -------------------------------------------------------------------------------- /nvim/snippets/lua.json: -------------------------------------------------------------------------------- 1 | { 2 | "print-inspect": { 3 | "prefix": ["ins"], 4 | "body": [ 5 | "print('${2:obj}', vim.inspect($1))$0" 6 | ], 7 | "description": "Print + vim.inspect" 8 | }, 9 | "snacks-inspect": { 10 | "prefix": ["dd"], 11 | "body": [ 12 | "Snacks.debug.inspect($0)" 13 | ], 14 | "description": "Snacks.debug.inspect" 15 | }, 16 | "local-function": { 17 | "prefix": ["lfun"], 18 | "body": [ 19 | "local ${1:funcname} = function(${2:args})", 20 | "\t$0", 21 | "end" 22 | ], 23 | "description": "function" 24 | }, 25 | "function": { 26 | "prefix": ["fun"], 27 | "body": [ 28 | "function(${1:args})", 29 | "\t$0", 30 | "end" 31 | ], 32 | "description": "function" 33 | }, 34 | "If": { 35 | "prefix": ["if"], 36 | "body": [ 37 | "if ${1:condition} then", 38 | "\t$0", 39 | "end" 40 | ], 41 | "description": "Console debug whole object" 42 | }, 43 | "If-else": { 44 | "prefix": ["ie"], 45 | "body": [ 46 | "if ${1:condition} then", 47 | "\t$2", 48 | "else", 49 | "\t$0", 50 | "end" 51 | ], 52 | "description": "Console debug whole object" 53 | }, 54 | "method": { 55 | "prefix": ["mtd"], 56 | "body": [ 57 | "function ${1:Class}:${2:method}(${3:args})", 58 | "\t$0", 59 | "end" 60 | ], 61 | "description": "method" 62 | }, 63 | "describe-test": { 64 | "prefix": ["desc"], 65 | "body": [ 66 | "describe('${1:description}', function()", 67 | "\tit('${2:test}', function()", 68 | "\t\t$0", 69 | "\tend)", 70 | "end)" 71 | ], 72 | "description": "describe + it" 73 | }, 74 | "it-test": { 75 | "prefix": ["it"], 76 | "body": [ 77 | "it('${1:description}', function()", 78 | "\t$0", 79 | "end)" 80 | ], 81 | "description": "it test" 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /nvim/lua/partials/plugins/codecompanion.lua: -------------------------------------------------------------------------------- 1 | return { 2 | 'olimorris/codecompanion.nvim', 3 | dependencies = { 4 | 'ravitemer/codecompanion-history.nvim', 5 | }, 6 | event = 'VeryLazy', 7 | keys = { 8 | { 9 | 'ea', 10 | mode = { 'n', 'x' }, 11 | function() 12 | vim.cmd('CodeCompanionActions') 13 | end, 14 | desc = 'Open Code Companion Actions', 15 | }, 16 | { 17 | 'ee', 18 | mode = { 'n', 'x' }, 19 | function() 20 | vim.cmd('CodeCompanionChat') 21 | end, 22 | desc = 'Open Code Companion Chat', 23 | }, 24 | }, 25 | config = function() 26 | require('codecompanion').setup({ 27 | extensions = { 28 | history = { 29 | enabled = true, 30 | opts = { 31 | picker = 'default', 32 | }, 33 | }, 34 | }, 35 | interactions = { 36 | chat = { adapter = 'copilot' }, 37 | inline = { adapter = 'copilot' }, 38 | }, 39 | adapters = { 40 | http = { 41 | gemini = function() 42 | return require('codecompanion.adapters').extend('gemini', { 43 | env = { 44 | api_key = vim.env.GEMINI_API_KEY, 45 | }, 46 | }) 47 | end, 48 | }, 49 | }, 50 | }) 51 | 52 | vim.api.nvim_create_autocmd({ 'User' }, { 53 | pattern = 'CodeCompanionRequest*', 54 | group = vim.api.nvim_create_augroup('CodeCompanionStatus', { clear = true }), 55 | callback = function(request) 56 | if request.match == 'CodeCompanionRequestStarted' then 57 | Snacks.notify.info(' CodeCompanion Running...', { 58 | id = 'codecompanion_status', 59 | timeout = 0, 60 | }) 61 | elseif request.match == 'CodeCompanionRequestFinished' then 62 | Snacks.notifier.hide('codecompanion_status') 63 | end 64 | end, 65 | }) 66 | end, 67 | } 68 | -------------------------------------------------------------------------------- /nvim/lua/partials/packs/nvim_tree.lua: -------------------------------------------------------------------------------- 1 | vim.keymap.set('n', 'n', ':NvimTreeToggle', { silent = true, desc = 'Toggle NvimTree' }) 2 | vim.keymap.set('n', 'hf', ':NvimTreeFindFile', { silent = true, desc = 'Toggle NvimTree on current file' }) 3 | 4 | vim.pack.load({ 5 | src = 'nvim-tree/nvim-tree.lua', 6 | dependencies = { 7 | 'antosha417/nvim-lsp-file-operations', 8 | }, 9 | cmd = { 'NvimTreeToggle', 'NvimTreeFindFile', 'NvimTreeOpen' }, 10 | config = function() 11 | require('nvim-tree').setup({ 12 | hijack_unnamed_buffer_when_opening = false, 13 | on_attach = function(bufnr) 14 | local api = require('nvim-tree.api') 15 | local opts = function(desc) 16 | return { buffer = bufnr, noremap = true, silent = true, nowait = true, desc = desc } 17 | end 18 | api.config.mappings.default_on_attach(bufnr) 19 | 20 | vim.keymap.set('n', 's', api.node.open.vertical, opts('Open in vertical split')) 21 | vim.keymap.set('n', '', api.tree.change_root_to_node, opts('Change root to node')) 22 | vim.keymap.set('n', '', api.node.run.system, opts('System run')) 23 | vim.keymap.set('n', 'S', api.tree.toggle_git_clean_filter, opts('Toggle git clean filter')) 24 | end, 25 | disable_netrw = true, 26 | update_focused_file = { 27 | enable = true, 28 | }, 29 | diagnostics = { 30 | enable = true, 31 | }, 32 | actions = { 33 | open_file = { 34 | resize_window = true, 35 | }, 36 | }, 37 | view = { 38 | width = 40, 39 | }, 40 | renderer = { 41 | full_name = true, 42 | highlight_git = true, 43 | icons = { 44 | glyphs = { 45 | default = '', 46 | git = { 47 | unstaged = '✹', 48 | }, 49 | }, 50 | }, 51 | }, 52 | }) 53 | require('lsp-file-operations').setup() 54 | end, 55 | }) 56 | -------------------------------------------------------------------------------- /i3/polybar/exchangerates.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | CACHE_FILE="$HOME/.local/share/exchange_rate_cache" 3 | URL="https://api.kursna-lista.info/3c43d44f8badfe38697ea0700c7485c8/kursna_lista" 4 | 5 | if [ ! -f "$CACHE_FILE" ]; then 6 | touch "$CACHE_FILE" 7 | fi 8 | 9 | force=0 10 | if [ "$1" = "--force" ]; then 11 | force=1 12 | fi 13 | 14 | # Get the latest entry for today 15 | today=$(date +%F) 16 | today_entry=$(grep "^$today " "$CACHE_FILE" | tail -n1) 17 | if [ -n "$today_entry" ] && [ "$force" -eq 0 ]; then 18 | cache_time=$(echo "$today_entry" | awk '{print $2}') 19 | cache_eur=$(echo "$today_entry" | awk '{print $3}') 20 | cache_usd=$(echo "$today_entry" | awk '{print $4}') 21 | cache_hour=$(echo "$cache_time" | cut -d: -f1) 22 | cache_min=$(echo "$cache_time" | cut -d: -f2) 23 | # If cache is after 09:00, use cache 24 | if [ "$cache_hour" -gt 9 ] || { [ "$cache_hour" -eq 9 ] && [ "$cache_min" -ge 0 ]; }; then 25 | echo "📈 USD: $cache_usd | EUR: $cache_eur" 26 | exit 0 27 | fi 28 | fi 29 | 30 | response=$(curl -s "$URL") 31 | eur=$(echo "$response" | jq -r '.result.eur.sre') 32 | usd=$(echo "$response" | jq -r '.result.usd.sre') 33 | now=$(date +%H:%M) 34 | 35 | last_entry=$(tail -n1 "$CACHE_FILE") 36 | if [ -n "$last_entry" ]; then 37 | cache_eur=$(echo "$last_entry" | awk '{print $3}') 38 | cache_usd=$(echo "$last_entry" | awk '{print $4}') 39 | if [ "$eur" != "$cache_eur" ] || [ "$usd" != "$cache_usd" ] || [ "$force" -eq 1 ]; then 40 | icon="dialog-information" 41 | if (( $(echo "$usd > $cache_usd" | bc -l) )); then 42 | icon="emblem-default" 43 | elif (( $(echo "$usd < $cache_usd" | bc -l) )); then 44 | icon="dialog-error" 45 | fi 46 | notify-send -i "$icon" -u critical "Exchange rates" "USD: $cache_usd → $usd\nEUR: $cache_eur → $eur" 47 | fi 48 | fi 49 | 50 | sed -i "/^$(date +%F) /d" "$CACHE_FILE" 51 | echo "$(date +%F) $now $eur $usd" >> "$CACHE_FILE" 52 | 53 | echo "📈 USD: $usd | EUR: $eur" 54 | -------------------------------------------------------------------------------- /nvim/lua/partials/plugins/gitsigns.lua: -------------------------------------------------------------------------------- 1 | local gitsigns_nvim = { 2 | 'lewis6991/gitsigns.nvim', 3 | event = 'VeryLazy', 4 | } 5 | gitsigns_nvim.config = function() 6 | require('gitsigns').setup({ 7 | signs = { 8 | add = { text = '▌' }, 9 | change = { text = '▌' }, 10 | delete = { text = '_' }, 11 | topdelete = { text = '‾' }, 12 | changedelete = { text = '▌' }, 13 | }, 14 | numhl = true, 15 | on_attach = function(bufnr) 16 | local gitsigns = require('gitsigns') 17 | 18 | local function map(mode, l, r, desc) 19 | vim.keymap.set(mode, l, r, { 20 | buffer = bufnr, 21 | desc = desc, 22 | }) 23 | end 24 | 25 | -- Navigation 26 | map('n', ']c', function() 27 | if vim.wo.diff then 28 | vim.cmd.normal({ ']c', bang = true }) 29 | else 30 | gitsigns.nav_hunk('next') 31 | end 32 | end, 'Next hunk') 33 | 34 | map('n', '[c', function() 35 | if vim.wo.diff then 36 | vim.cmd.normal({ '[c', bang = true }) 37 | else 38 | gitsigns.nav_hunk('prev') 39 | end 40 | end, 'Prev hunk') 41 | 42 | -- Actions 43 | map('n', 'ghp', gitsigns.preview_hunk, 'Preview hunk') 44 | map('n', 'ghr', gitsigns.reset_hunk, 'Reset hunk') 45 | map('n', 'ghb', function() 46 | gitsigns.blame_line({ full = true }) 47 | end, 'Blame whole file') 48 | map('n', 'ghB', gitsigns.toggle_current_line_blame, 'Toggle current line blame') 49 | map('n', 'ghd', gitsigns.diffthis, 'Diff this') 50 | map('n', 'ghD', function() 51 | gitsigns.diffthis('~') 52 | end, 'Diff this with parent commit') 53 | map('n', 'ghy', gitsigns.toggle_deleted, 'Toggle deleted sign') 54 | 55 | -- Text object 56 | map({ 'o', 'x' }, 'ih', ':Gitsigns select_hunk') 57 | end, 58 | }) 59 | 60 | return gitsigns_nvim 61 | end 62 | 63 | return gitsigns_nvim 64 | -------------------------------------------------------------------------------- /nvim/lua/partials/plugins/nvim_tree.lua: -------------------------------------------------------------------------------- 1 | local nvim_tree = { 2 | 'nvim-tree/nvim-tree.lua', 3 | dependencies = { 4 | 'antosha417/nvim-lsp-file-operations', 5 | }, 6 | cmd = { 'NvimTreeToggle', 'NvimTreeFindFile', 'NvimTreeOpen' }, 7 | } 8 | 9 | nvim_tree.init = function() 10 | vim.keymap.set('n', 'n', ':NvimTreeToggle', { silent = true, desc = 'Toggle NvimTree' }) 11 | vim.keymap.set( 12 | 'n', 13 | 'hf', 14 | ':NvimTreeFindFile', 15 | { silent = true, desc = 'Toggle NvimTree on current file' } 16 | ) 17 | end 18 | 19 | nvim_tree.config = function() 20 | require('nvim-tree').setup({ 21 | hijack_unnamed_buffer_when_opening = false, 22 | on_attach = function(bufnr) 23 | local api = require('nvim-tree.api') 24 | local opts = function(desc) 25 | return { buffer = bufnr, noremap = true, silent = true, nowait = true, desc = desc } 26 | end 27 | api.config.mappings.default_on_attach(bufnr) 28 | 29 | vim.keymap.set('n', 's', api.node.open.vertical, opts('Open in vertical split')) 30 | vim.keymap.set('n', '', api.tree.change_root_to_node, opts('Change root to node')) 31 | vim.keymap.set('n', '', api.node.run.system, opts('System run')) 32 | vim.keymap.set('n', 'S', api.tree.toggle_git_clean_filter, opts('Toggle git clean filter')) 33 | end, 34 | disable_netrw = true, 35 | update_focused_file = { 36 | enable = true, 37 | }, 38 | diagnostics = { 39 | enable = true, 40 | }, 41 | actions = { 42 | open_file = { 43 | resize_window = true, 44 | }, 45 | }, 46 | view = { 47 | width = 40, 48 | }, 49 | renderer = { 50 | full_name = true, 51 | highlight_git = true, 52 | icons = { 53 | glyphs = { 54 | default = '', 55 | git = { 56 | unstaged = '✹', 57 | }, 58 | }, 59 | }, 60 | }, 61 | }) 62 | require('lsp-file-operations').setup() 63 | end 64 | 65 | return nvim_tree 66 | -------------------------------------------------------------------------------- /nvim/lua/partials/packs/gitsigns.lua: -------------------------------------------------------------------------------- 1 | vim.pack.load({ 2 | src = 'lewis6991/gitsigns.nvim', 3 | event = 'VeryLazy', 4 | config = function() 5 | require('gitsigns').setup({ 6 | signs = { 7 | add = { text = '▌' }, 8 | change = { text = '▌' }, 9 | delete = { text = '_' }, 10 | topdelete = { text = '‾' }, 11 | changedelete = { text = '▌' }, 12 | }, 13 | numhl = true, 14 | on_attach = function(bufnr) 15 | local gitsigns = require('gitsigns') 16 | 17 | local function map(mode, l, r, desc) 18 | vim.keymap.set(mode, l, r, { 19 | buffer = bufnr, 20 | desc = desc, 21 | }) 22 | end 23 | 24 | -- Navigation 25 | map('n', ']c', function() 26 | if vim.wo.diff then 27 | vim.cmd.normal({ ']c', bang = true }) 28 | else 29 | gitsigns.nav_hunk('next') 30 | end 31 | end, 'Next hunk') 32 | 33 | map('n', '[c', function() 34 | if vim.wo.diff then 35 | vim.cmd.normal({ '[c', bang = true }) 36 | else 37 | gitsigns.nav_hunk('prev') 38 | end 39 | end, 'Prev hunk') 40 | 41 | -- Actions 42 | map('n', 'ghp', gitsigns.preview_hunk, 'Preview hunk') 43 | map('n', 'ghr', gitsigns.reset_hunk, 'Reset hunk') 44 | map('n', 'ghb', function() 45 | gitsigns.blame_line({ full = true }) 46 | end, 'Blame whole file') 47 | map('n', 'ghB', gitsigns.toggle_current_line_blame, 'Toggle current line blame') 48 | map('n', 'ghd', gitsigns.diffthis, 'Diff this') 49 | map('n', 'ghD', function() 50 | gitsigns.diffthis('~') 51 | end, 'Diff this with parent commit') 52 | map('n', 'ghy', gitsigns.toggle_deleted, 'Toggle deleted sign') 53 | 54 | -- Text object 55 | map({ 'o', 'x' }, 'ih', ':Gitsigns select_hunk') 56 | end, 57 | }) 58 | end, 59 | }) 60 | -------------------------------------------------------------------------------- /zsh/themes/lambda-mod.zsh-theme: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env zsh 2 | 3 | local LAMBDA="%(?,%{$fg_bold[green]%}λ,%{$fg_bold[red]%}λ)" 4 | if [[ "$USER" == "root" ]]; then USERCOLOR="red"; else USERCOLOR="yellow"; fi 5 | 6 | # Git sometimes goes into a detached head state. git_prompt_info doesn't 7 | # return anything in this case. So wrap it in another function and check 8 | # for an empty string. 9 | function check_git_prompt_info() { 10 | if git rev-parse --git-dir > /dev/null 2>&1; then 11 | if [[ -z $(git_prompt_info 2> /dev/null) ]]; then 12 | echo "%{$fg[blue]%}detached-head%{$reset_color%}) $(git_prompt_status) 13 | %{$fg[yellow]%}→ " 14 | else 15 | echo "$(git_prompt_info 2> /dev/null) $(git_prompt_status) 16 | %{$fg_bold[cyan]%}→ " 17 | fi 18 | else 19 | echo " 20 | %{$fg_bold[cyan]%}→ " 21 | fi 22 | } 23 | 24 | PROMPT=$''$LAMBDA'\ 25 | %{$fg_bold[$USERCOLOR]%}%n\ 26 | %{$fg_no_bold[cyan][%}%D{%d.%m.%Y} %*]\ 27 | %{$fg_no_bold[magenta]%}[%~]%(1j.  .)\ 28 | $(check_git_prompt_info)\ 29 | %{$reset_color%}' 30 | 31 | # RPROMPT="[%{$fg[blue]%}%D{%d.%m.%Y} %*%{$reset_color%}]" 32 | 33 | # Format for git_prompt_info() 34 | ZSH_THEME_GIT_PROMPT_PREFIX="at %{$fg[blue]%} " 35 | ZSH_THEME_GIT_PROMPT_SUFFIX="%{$reset_color%}" 36 | ZSH_THEME_GIT_PROMPT_DIRTY="" 37 | ZSH_THEME_GIT_PROMPT_CLEAN="%{$fg_bold[green]%} ✔" 38 | 39 | # Format for git_prompt_status() 40 | ZSH_THEME_GIT_PROMPT_ADDED="%{$fg_bold[green]%}+" 41 | ZSH_THEME_GIT_PROMPT_MODIFIED="%{$fg_bold[blue]%}!" 42 | ZSH_THEME_GIT_PROMPT_DELETED="%{$fg_bold[red]%}-" 43 | ZSH_THEME_GIT_PROMPT_RENAMED="%{$fg_bold[magenta]%}>" 44 | ZSH_THEME_GIT_PROMPT_UNMERGED="%{$fg_bold[yellow]%}#" 45 | ZSH_THEME_GIT_PROMPT_UNTRACKED="%{$fg_bold[cyan]%}?" 46 | 47 | # Format for git_prompt_ahead() 48 | ZSH_THEME_GIT_PROMPT_AHEAD=" %{$fg_bold[white]%}^" 49 | 50 | 51 | # Format for git_prompt_long_sha() and git_prompt_short_sha() 52 | ZSH_THEME_GIT_PROMPT_SHA_BEFORE=" %{$fg_bold[white]%}[%{$fg_bold[blue]%}" 53 | ZSH_THEME_GIT_PROMPT_SHA_AFTER="%{$fg_bold[white]%}]" 54 | -------------------------------------------------------------------------------- /nvim/after/plugin/find.lua: -------------------------------------------------------------------------------- 1 | local function find(opts) 2 | local path = vim.loop.fs_stat(opts.args) 3 | if path then 4 | return vim.cmd('edit ' .. opts.args) 5 | end 6 | vim.notify('File not found: ' .. opts.args, vim.log.levels.ERROR) 7 | end 8 | 9 | local function parse_results(items) 10 | return { unpack(items, 1, vim.o.lines / 2) } 11 | end 12 | 13 | local function get_filenames() 14 | local executables = { 15 | { 16 | name = 'fd', 17 | cmd = { 'fd', '--type', 'file', '--follow' }, 18 | }, 19 | { 20 | name = 'rg', 21 | cmd = { 'rg', '--files' }, 22 | }, 23 | { 24 | name = 'find', 25 | cmd = { 'find', '.', '-type', 'f' }, 26 | }, 27 | } 28 | 29 | for _, exec in ipairs(executables) do 30 | if vim.fn.executable(exec.name) > 0 then 31 | local result = vim.system(exec.cmd, { text = false }):wait() 32 | if result and result.code == 0 then 33 | return vim.split(result.stdout, '\n') 34 | end 35 | end 36 | end 37 | 38 | return vim.fn.glob('**', false, true) 39 | end 40 | 41 | local function complete(arg_lead) 42 | local files = get_filenames() 43 | 44 | if vim.trim(arg_lead or '') == '' then 45 | return parse_results(files) 46 | end 47 | return parse_results(vim.fn.matchfuzzy(files, arg_lead)) 48 | end 49 | 50 | vim.api.nvim_create_user_command('Find', find, { force = true, nargs = '?', complete = complete }) 51 | _G.kris = _G.kris or {} 52 | _G.kris.findfunc = function(cmd_arg) 53 | return complete(cmd_arg) 54 | end 55 | 56 | if vim.fn.exists('&findfunc') > 0 then 57 | vim.o.findfunc = 'v:lua.kris.findfunc' 58 | end 59 | 60 | if vim.fn.exists('*wildtrigger') > 0 then 61 | vim.opt.wildmode = 'noselect:full' 62 | 63 | vim.api.nvim_create_autocmd('CmdlineChanged', { 64 | group = vim.api.nvim_create_augroup('KrisFindCmdline', { clear = true }), 65 | callback = function() 66 | local first_arg = vim.fn.getcmdline() 67 | if first_arg:match('^[wWqQ][qQ]?a?!?$') then 68 | return 69 | end 70 | vim.fn.wildtrigger() 71 | end, 72 | }) 73 | end 74 | -------------------------------------------------------------------------------- /nvim/lua/partials/packs/treesitter.lua: -------------------------------------------------------------------------------- 1 | vim.pack.load({ 2 | src = 'nvim-treesitter/nvim-treesitter', 3 | version = 'main', 4 | build = 'TSUpdate', 5 | dependencies = { 6 | { src = 'nvim-treesitter/nvim-treesitter-textobjects', version = 'main' }, 7 | }, 8 | config = function() 9 | require('nvim-treesitter').setup() 10 | require('nvim-treesitter-textobjects').setup() 11 | require('nvim-treesitter').install(require('nvim-treesitter').get_available(2)) 12 | vim.api.nvim_create_autocmd('FileType', { 13 | pattern = { 14 | 'c', 15 | 'cpp', 16 | 'diff', 17 | 'dockerfile', 18 | 'gitdiff', 19 | 'gitignore', 20 | 'go', 21 | 'graphql', 22 | 'javascript', 23 | 'javascriptreact', 24 | 'lua', 25 | 'markdown', 26 | 'mysql', 27 | 'pgsql', 28 | 'php', 29 | 'python', 30 | 'ruby', 31 | 'sh', 32 | 'sql', 33 | 'terraform', 34 | 'toml', 35 | 'typescript', 36 | 'typescriptreact', 37 | 'vim', 38 | 'yaml', 39 | 'copilot-chat', 40 | 'http', 41 | 'codecompanion', 42 | }, 43 | group = vim.api.nvim_create_augroup('nvim-treesitter-fts', { clear = true }), 44 | callback = function(args) 45 | vim.treesitter.start(args.buf) 46 | end, 47 | }) 48 | 49 | -- Select 50 | vim.keymap.set({ 'x', 'o' }, 'af', function() 51 | require('nvim-treesitter-textobjects.select').select_textobject('@function.outer', 'textobjects') 52 | end) 53 | vim.keymap.set({ 'x', 'o' }, 'if', function() 54 | require('nvim-treesitter-textobjects.select').select_textobject('@function.inner', 'textobjects') 55 | end) 56 | 57 | -- Swap 58 | vim.keymap.set('n', 'a', function() 59 | require('nvim-treesitter-textobjects.swap').swap_next('@parameter.inner') 60 | end) 61 | vim.keymap.set('n', 'A', function() 62 | require('nvim-treesitter-textobjects.swap').swap_previous('@parameter.inner') 63 | end) 64 | end, 65 | }) 66 | -------------------------------------------------------------------------------- /nvim/lua/partials/plugins/treesitter.lua: -------------------------------------------------------------------------------- 1 | return { 2 | 'nvim-treesitter/nvim-treesitter', 3 | build = ':TSUpdate', 4 | branch = 'main', 5 | dependencies = { 6 | { 'nvim-treesitter/nvim-treesitter-textobjects', branch = 'main' }, 7 | }, 8 | lazy = false, 9 | config = function() 10 | require('nvim-treesitter').setup() 11 | require('nvim-treesitter-textobjects').setup() 12 | require('nvim-treesitter').install(require('nvim-treesitter').get_available(2)) 13 | vim.api.nvim_create_autocmd('FileType', { 14 | pattern = { 15 | 'c', 16 | 'cpp', 17 | 'diff', 18 | 'dockerfile', 19 | 'gitdiff', 20 | 'gitignore', 21 | 'go', 22 | 'graphql', 23 | 'javascript', 24 | 'javascriptreact', 25 | 'lua', 26 | 'markdown', 27 | 'mysql', 28 | 'pgsql', 29 | 'php', 30 | 'python', 31 | 'ruby', 32 | 'sh', 33 | 'sql', 34 | 'terraform', 35 | 'toml', 36 | 'typescript', 37 | 'typescriptreact', 38 | 'vim', 39 | 'yaml', 40 | 'copilot-chat', 41 | 'http', 42 | 'codecompanion', 43 | }, 44 | group = vim.api.nvim_create_augroup('nvim-treesitter-fts', { clear = true }), 45 | callback = function(args) 46 | vim.treesitter.start(args.buf) 47 | end, 48 | }) 49 | 50 | -- Select 51 | vim.keymap.set({ 'x', 'o' }, 'af', function() 52 | require('nvim-treesitter-textobjects.select').select_textobject('@function.outer', 'textobjects') 53 | end) 54 | vim.keymap.set({ 'x', 'o' }, 'if', function() 55 | require('nvim-treesitter-textobjects.select').select_textobject('@function.inner', 'textobjects') 56 | end) 57 | 58 | -- Swap 59 | vim.keymap.set('n', 'a', function() 60 | require('nvim-treesitter-textobjects.swap').swap_next('@parameter.inner') 61 | end) 62 | vim.keymap.set('n', 'A', function() 63 | require('nvim-treesitter-textobjects.swap').swap_previous('@parameter.inner') 64 | end) 65 | end, 66 | } 67 | -------------------------------------------------------------------------------- /rofi/spotlight-dark.rasi: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * MACOS SPOTLIGHT LIKE DARK THEME FOR ROFI 3 | * User : LR-Tech 4 | * Theme Repo : https://github.com/lr-tech/rofi-themes-collection 5 | *******************************************************************************/ 6 | 7 | * { 8 | font: "JetBrains Mono 11"; 9 | 10 | bg0: #2e3440EE; 11 | bg1: #7E7E7E80; 12 | bg2: #0860f2E6; 13 | 14 | fg0: #DEDEDE; 15 | fg1: #FFFFFF; 16 | fg2: #DEDEDE80; 17 | 18 | background-color: transparent; 19 | text-color: @fg0; 20 | 21 | margin: 0; 22 | padding: 0; 23 | spacing: 0; 24 | } 25 | 26 | window { 27 | background-color: @bg0; 28 | 29 | anchor: north; 30 | location: center; 31 | width: 800px; 32 | height: 40%; 33 | y-offset: -20%; 34 | border-radius: 0; 35 | } 36 | 37 | inputbar { 38 | font: "JetBrains Mono 12"; 39 | padding: 12px; 40 | spacing: 12px; 41 | children: [ icon-search, entry ]; 42 | } 43 | 44 | icon-search { 45 | expand: false; 46 | filename: "search"; 47 | size: 28px; 48 | } 49 | 50 | icon-search, entry, element-icon, element-text { 51 | vertical-align: 0.5; 52 | } 53 | 54 | entry { 55 | font: inherit; 56 | 57 | placeholder : "Search"; 58 | placeholder-color : @fg2; 59 | } 60 | 61 | message { 62 | border: 2px 0 0; 63 | border-color: @bg1; 64 | background-color: @bg1; 65 | } 66 | 67 | textbox { 68 | padding: 8px 24px; 69 | } 70 | 71 | listview { 72 | lines: 10; 73 | columns: 1; 74 | 75 | fixed-height: false; 76 | border: 1px 0 0; 77 | border-color: @bg1; 78 | } 79 | 80 | element { 81 | padding: 8px 16px; 82 | spacing: 16px; 83 | background-color: transparent; 84 | } 85 | 86 | element normal active { 87 | text-color: @bg2; 88 | } 89 | 90 | element selected normal, element selected active { 91 | background-color: @bg2; 92 | text-color: @fg1; 93 | } 94 | 95 | element-icon { 96 | size: 1em; 97 | } 98 | 99 | element-text { 100 | text-color: inherit; 101 | } 102 | -------------------------------------------------------------------------------- /rofi/spotlight-light.rasi: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * MACOS SPOTLIGHT LIKE THEME FOR ROFI 3 | * User : LR-Tech 4 | * Theme Repo : https://github.com/lr-tech/rofi-themes-collection 5 | *******************************************************************************/ 6 | 7 | * { 8 | font: "JetBrains Mono 11"; 9 | 10 | bg0: #F5F5F5EE; 11 | bg1: #7E7E7E80; 12 | bg2: #0860F2E6; 13 | 14 | fg0: #242424; 15 | fg1: #FFFFFF; 16 | fg2: #24242480; 17 | 18 | background-color: transparent; 19 | text-color: @fg0; 20 | 21 | margin: 0; 22 | padding: 0; 23 | spacing: 0; 24 | } 25 | 26 | window { 27 | background-color: @bg0; 28 | 29 | anchor: north; 30 | location: center; 31 | width: 800px; 32 | height: 40%; 33 | y-offset: -20%; 34 | border-radius: 0; 35 | } 36 | 37 | inputbar { 38 | font: "JetBrains Mono 12"; 39 | padding: 12px; 40 | spacing: 12px; 41 | children: [ icon-search, entry ]; 42 | } 43 | 44 | icon-search { 45 | expand: false; 46 | filename: "search"; 47 | size: 28px; 48 | } 49 | 50 | icon-search, entry, element-icon, element-text { 51 | vertical-align: 0.5; 52 | } 53 | 54 | entry { 55 | font: inherit; 56 | 57 | placeholder : "Search"; 58 | placeholder-color : @fg2; 59 | } 60 | 61 | message { 62 | border: 2px 0 0; 63 | border-color: @bg1; 64 | background-color: @bg1; 65 | } 66 | 67 | textbox { 68 | padding: 8px 24px; 69 | } 70 | 71 | listview { 72 | lines: 10; 73 | columns: 1; 74 | 75 | fixed-height: false; 76 | border: 1px 0 0; 77 | border-color: @bg1; 78 | } 79 | 80 | element { 81 | padding: 8px 16px; 82 | spacing: 16px; 83 | background-color: transparent; 84 | } 85 | 86 | element normal active { 87 | text-color: @bg2; 88 | } 89 | 90 | element selected normal, element selected active { 91 | background-color: @bg2; 92 | text-color: @fg1; 93 | } 94 | 95 | element-icon { 96 | size: 1em; 97 | } 98 | 99 | element-text { 100 | text-color: inherit; 101 | } 102 | -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | install_oh_my_zsh() { 4 | echo "Setting up zsh..." \ 5 | && rm -rf ~/.zshrc \ 6 | && ln -s $(pwd)/zsh/zshrc ~/.zshrc \ 7 | && git clone https://github.com/zsh-users/zsh-autosuggestions ~/.oh-my-zsh/custom/plugins/zsh-autosuggestions \ 8 | && git clone https://github.com/zsh-users/zsh-syntax-highlighting.git ~/.oh-my-zsh/custom/plugins/zsh-syntax-highlighting \ 9 | && git clone https://github.com/Aloxaf/fzf-tab ~/.oh-my-zsh/custom/plugins/fzf-tab \ 10 | && git clone --depth=1 https://github.com/romkatv/powerlevel10k.git ~/.oh-my-zsh/custom/themes/powerlevel10k \ 11 | && ln -s $(pwd)/zsh/themes/* ~/.oh-my-zsh/custom/themes \ 12 | && rm -rf ~/z.sh \ 13 | && curl -fLo ~/z.sh https://raw.githubusercontent.com/rupa/z/master/z.sh 14 | } 15 | 16 | install_neovim() { 17 | echo "Setting up neovim..." \ 18 | && rm -rf ~/.config/nvim ~/.fzf \ 19 | && ln -s $(pwd)/nvim ~/.config/nvim \ 20 | && yay -S ripgrep 21 | } 22 | 23 | install_emacs() { 24 | echo "Setting up emacs..." \ 25 | && mkdir -p ~/.config/emacs \ 26 | && rm -rf ~/.config/emacs/init.el \ 27 | && ln -s $(pwd)/emacs/init.el ~/.config/emacs 28 | } 29 | 30 | install_packages() { 31 | ehco"Installing packages..." \ 32 | && yay -S keychain go dropbox dropbox-cli meld cronie jq 33 | } 34 | 35 | install_diff_so_fancy() { 36 | echo "Installing diff-so-fancy..." \ 37 | && npm install -g diff-so-fancy \ 38 | && git config --global core.pager "diff-so-fancy | less --tabs=4 -R" 39 | } 40 | 41 | install_kitty() { 42 | echo "Installing kitty..." \ 43 | && rm -rf ~/.local/kitty.app ~/.config/kitty \ 44 | && yay -S kitty \ 45 | && ln -s $(pwd)/kitty ~/.config/kitty 46 | } 47 | 48 | install_i3() { 49 | rm -rf ~/.config/i3 \ 50 | && yay -S rofi polybar ttf-twemoji ttf-nerd-fonts-symbols-mono ttf-jetbrains-mono \ 51 | && ln -s $(pwd)/i3 ~/.config/i3 52 | } 53 | 54 | install_sway() { 55 | yay -S sway swaybg swaylock swaync swayidle xorg-wayland waybar grim slurp wl-clipboard rofi \ 56 | && rm -rf ~/.config/sway ~/.config/waybar \ 57 | && ln -s $(pwd)/sway ~/.config/sway \ 58 | && ln -s $(pwd)/waybar ~/.config/waybar 59 | } 60 | 61 | install_hyprland() { 62 | yay -S cmake meson cpio pkg-config g++ gcc zenity hyprlock swaync swaybg hypridle xorg-wayland waybar grim slurp wl-clipboard rofi-wayland hyprland wf-recorder \ 63 | && rm -rf ~/.config/hypr ~/.config/waybar \ 64 | && ln -s $(pwd)/hypr ~/.config/hypr \ 65 | && ln -s $(pwd)/waybar ~/.config/waybar \ 66 | && hyprpm update \ 67 | && hyprpm add https://github.com/outfoxxed/hy3 68 | } 69 | 70 | install_rofi() { 71 | yay -S rofi \ 72 | && rm -rf ~/.config/rofi \ 73 | && ln -s $(pwd)/rofi ~/.config/rofi 74 | } 75 | 76 | install_mutt() { 77 | yay -S neomutt mutt-wizard cyrus-sasl-xoauth2-git abook lynx 78 | } 79 | 80 | if [[ -z $1 ]]; then 81 | echo "Provide argument" 82 | exit 1 83 | else 84 | "install_$1" 85 | fi 86 | -------------------------------------------------------------------------------- /nvim/lua/partials/plugins/orgmode.lua: -------------------------------------------------------------------------------- 1 | local orgmode = { 2 | 'nvim-orgmode/orgmode', 3 | dev = true, 4 | dependencies = { 5 | { 'nvim-orgmode/org-bullets.nvim' }, 6 | }, 7 | ft = { 'org', 'orgagenda' }, 8 | keys = { 9 | { 10 | 'oa', 11 | function() 12 | return Org.agenda() 13 | end, 14 | }, 15 | { 16 | 'oc', 17 | function() 18 | return Org.capture() 19 | end, 20 | }, 21 | { 22 | 'op', 23 | function() 24 | Snacks.picker.files({ 25 | cwd = '~/orgfiles', 26 | ft = 'org', 27 | }) 28 | end, 29 | }, 30 | }, 31 | } 32 | 33 | orgmode.config = function() 34 | require('orgmode').setup(require('partials.orgmode_config')) 35 | require('org-bullets').setup({ 36 | concealcursor = true, 37 | symbols = { 38 | checkboxes = { 39 | half = { '', '@org.checkbox.halfchecked' }, 40 | done = { '✓', '@org.checkbox.checked' }, 41 | todo = { ' ', '@org.checkbox' }, 42 | }, 43 | }, 44 | }) 45 | 46 | local set_cr_mapping = function() 47 | vim.keymap.set('i', '', 'lua require("orgmode").action("org_mappings.meta_return")', { 48 | silent = true, 49 | buffer = true, 50 | }) 51 | end 52 | 53 | vim.api.nvim_create_autocmd('FileType', { 54 | pattern = 'org', 55 | callback = set_cr_mapping, 56 | }) 57 | 58 | if vim.bo.filetype == 'org' then 59 | set_cr_mapping() 60 | end 61 | 62 | vim.api.nvim_create_user_command('OrgGenerateToc', function(...) 63 | local file = require('orgmode').files:get_current_file() 64 | local toc = {} 65 | local min_level = tonumber(vim.fn.input('Min level: ', '2')) 66 | local max_level = tonumber(vim.fn.input('Max level: ', '10')) 67 | 68 | ---@param headline OrgHeadline 69 | ---@param level? number 70 | local function generate_toc(headline, level) 71 | if level > max_level then 72 | return 73 | end 74 | 75 | if level >= min_level then 76 | local content = {} 77 | table.insert(content, ('%s-'):format((' '):rep((level - min_level) * 2))) 78 | local custom_id = headline:get_property('CUSTOM_ID') 79 | local link = custom_id and ('#%s'):format(custom_id) or ('*%s'):format(headline:get_title()) 80 | local desc = headline:get_title() 81 | table.insert(content, ('[[%s][%s]]'):format(link, desc)) 82 | table.insert(toc, table.concat(content, ' ')) 83 | end 84 | 85 | for _, child in ipairs(headline:get_child_headlines()) do 86 | generate_toc(child, level + 1) 87 | end 88 | end 89 | 90 | for _, top_headline in ipairs(file:get_top_level_headlines()) do 91 | generate_toc(top_headline, 1) 92 | end 93 | 94 | vim.api.nvim_buf_set_lines(0, vim.fn.line('.') - 1, vim.fn.line('.') - 1, false, toc) 95 | end, { 96 | nargs = 0, 97 | }) 98 | 99 | return orgmode 100 | end 101 | 102 | return orgmode 103 | -------------------------------------------------------------------------------- /waybar/exchangerates.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | CACHE_FILE="$HOME/.local/share/exchange_rate_cache" 3 | USD_URL="https://kurs.resenje.org/api/v1/currencies/USD/rates/today" 4 | EUR_URL="https://kurs.resenje.org/api/v1/currencies/EUR/rates/today" 5 | 6 | if [ ! -f "$CACHE_FILE" ]; then 7 | touch "$CACHE_FILE" 8 | fi 9 | 10 | force=0 11 | if [ "$1" = "--force" ]; then 12 | force=1 13 | fi 14 | 15 | today=$(date +%F) 16 | 17 | # Get the latest entry for today 18 | today_entry=$(grep "^$today " "$CACHE_FILE" | tail -n1) 19 | 20 | get_last_seven_entries() { 21 | header="Date | USD | EUR\n--------------------------------" 22 | today="$(date +%Y-%m-%d)" 23 | filtered_entries=$(grep -v "^$today" "$CACHE_FILE") 24 | last_seven=$(echo "$filtered_entries" | tail -n7) 25 | formatted_entries=$(echo "$last_seven" | awk '{printf "%-10s | %-8s | %s\n", $1, $4, $3}') 26 | (echo -e "$header"; echo "$formatted_entries") | sed ':a;N;$!ba;s/\n/\\n/g' 27 | } 28 | 29 | if [ -n "$today_entry" ] && [ "$force" -eq 0 ]; then 30 | cache_time=$(echo "$today_entry" | awk '{print $2}') 31 | cache_eur=$(echo "$today_entry" | awk '{print $3}') 32 | cache_usd=$(echo "$today_entry" | awk '{print $4}') 33 | cache_hour=$(echo "$cache_time" | cut -d: -f1) 34 | cache_min=$(echo "$cache_time" | cut -d: -f2) 35 | # If cache is after 09:00, use cache 36 | if [ "$cache_hour" -gt 9 ] || { [ "$cache_hour" -eq 9 ] && [ "$cache_min" -ge 0 ]; }; then 37 | echo "{\"text\": \"📈 USD: $cache_usd | EUR: $cache_eur\", \"tooltip\": \"$(get_last_seven_entries)\"}" 38 | exit 0 39 | fi 40 | fi 41 | 42 | usd_response=$(curl -s "$USD_URL") 43 | eur_response=$(curl -s "$EUR_URL") 44 | eur=$(echo "$eur_response" | jq -r '.exchange_middle') 45 | usd=$(echo "$usd_response" | jq -r '.exchange_middle') 46 | now=$(date +%H:%M) 47 | 48 | last_entry=$(tail -n1 "$CACHE_FILE") 49 | if [ -n "$last_entry" ]; then 50 | cache_date=$(echo "$last_entry" | awk '{print $1}') 51 | cache_eur=$(echo "$last_entry" | awk '{print $3}') 52 | cache_usd=$(echo "$last_entry" | awk '{print $4}') 53 | 54 | # If api call fails or it's missing data, show the old one and notify user 55 | if [ -z "$eur" ] || [ -z "$usd" ]; then 56 | echo "{\"text\": \"📈 USD: $cache_usd | EUR: $cache_eur\", \"tooltip\": \"$(get_last_seven_entries)\"}" 57 | notify-send -i "dialog-error" -u critical "Exchange rates" "Failed to fetch exchange rates. Using cached value from $cache_date" 58 | exit 0 59 | fi 60 | 61 | 62 | if [ "$eur" != "$cache_eur" ] || [ "$usd" != "$cache_usd" ] || [ "$force" -eq 1 ]; then 63 | icon="dialog-information" 64 | if (( $(echo "$usd > $cache_usd" | bc -l) )); then 65 | icon="emblem-default" 66 | elif (( $(echo "$usd < $cache_usd" | bc -l) )); then 67 | icon="dialog-error" 68 | fi 69 | notify-send -i "$icon" -u critical "Exchange rates" "USD: $cache_usd → $usd\nEUR: $cache_eur → $eur" 70 | fi 71 | fi 72 | 73 | sed -i "/^$(date +%F) /d" "$CACHE_FILE" 74 | echo "$(date +%F) $now $eur $usd" >> "$CACHE_FILE" 75 | 76 | echo "{\"text\": \"📈 USD: $usd | EUR: $eur\", \"tooltip\": \"$(get_last_seven_entries)\"}" 77 | -------------------------------------------------------------------------------- /nvim/lua/partials/packs/orgmode.lua: -------------------------------------------------------------------------------- 1 | vim.pack.load({ 2 | src = '~/github/orgmode', 3 | dependencies = { 4 | 'nvim-orgmode/org-bullets.nvim', 5 | }, 6 | ft = { 'org' }, 7 | keys = { 8 | { 9 | 'n', 10 | 'oa', 11 | function() 12 | return Org.agenda() 13 | end, 14 | { desc = 'Org agenda' }, 15 | }, 16 | { 17 | 'n', 18 | 'oc', 19 | function() 20 | return Org.capture() 21 | end, 22 | { desc = 'Org capture' }, 23 | }, 24 | { 25 | 'n', 26 | 'op', 27 | function() 28 | Snacks.picker.files({ 29 | cwd = '~/orgfiles', 30 | ft = 'org', 31 | }) 32 | end, 33 | { desc = 'Org pick files' }, 34 | }, 35 | }, 36 | local_package = true, 37 | config = function() 38 | require('orgmode').setup(require('partials.orgmode_config')) 39 | require('org-bullets').setup({ 40 | concealcursor = true, 41 | symbols = { 42 | checkboxes = { 43 | half = { '', '@org.checkbox.halfchecked' }, 44 | done = { '✓', '@org.checkbox.checked' }, 45 | todo = { ' ', '@org.checkbox' }, 46 | }, 47 | }, 48 | }) 49 | 50 | local set_cr_mapping = function() 51 | vim.keymap.set('i', '', 'lua require("orgmode").action("org_mappings.meta_return")', { 52 | silent = true, 53 | buffer = true, 54 | }) 55 | end 56 | 57 | vim.api.nvim_create_autocmd('FileType', { 58 | pattern = 'org', 59 | callback = set_cr_mapping, 60 | }) 61 | 62 | if vim.bo.filetype == 'org' then 63 | set_cr_mapping() 64 | end 65 | 66 | vim.api.nvim_create_user_command('OrgGenerateToc', function(...) 67 | local file = require('orgmode').files:get_current_file() 68 | local toc = {} 69 | local min_level = tonumber(vim.fn.input('Min level: ', '2')) 70 | local max_level = tonumber(vim.fn.input('Max level: ', '10')) 71 | 72 | ---@param headline OrgHeadline 73 | ---@param level? number 74 | local function generate_toc(headline, level) 75 | if level > max_level then 76 | return 77 | end 78 | 79 | if level >= min_level then 80 | local content = {} 81 | table.insert(content, ('%s-'):format((' '):rep((level - min_level) * 2))) 82 | local custom_id = headline:get_property('CUSTOM_ID') 83 | local link = custom_id and ('#%s'):format(custom_id) or ('*%s'):format(headline:get_title()) 84 | local desc = headline:get_title() 85 | table.insert(content, ('[[%s][%s]]'):format(link, desc)) 86 | table.insert(toc, table.concat(content, ' ')) 87 | end 88 | 89 | for _, child in ipairs(headline:get_child_headlines()) do 90 | generate_toc(child, level + 1) 91 | end 92 | end 93 | 94 | for _, top_headline in ipairs(file:get_top_level_headlines()) do 95 | generate_toc(top_headline, 1) 96 | end 97 | 98 | vim.api.nvim_buf_set_lines(0, vim.fn.line('.') - 1, vim.fn.line('.') - 1, false, toc) 99 | end, { 100 | nargs = 0, 101 | }) 102 | end, 103 | }) 104 | -------------------------------------------------------------------------------- /nvim/lua/partials/utils/init.lua: -------------------------------------------------------------------------------- 1 | local M = {} 2 | 3 | function M.esc(cmd) 4 | return vim.api.nvim_replace_termcodes(cmd, true, false, true) 5 | end 6 | 7 | function M.feedkeys(key, mode) 8 | vim.fn.feedkeys(M.esc(key), mode or '') 9 | end 10 | 11 | function M.get_gps_scope(fallback) 12 | local gps = require('nvim-navic') 13 | if not gps.is_available() then 14 | return fallback 15 | end 16 | local scope_data = gps.get_data() 17 | if not scope_data or vim.tbl_isempty(scope_data) then 18 | return fallback 19 | end 20 | local scope_string = vim.tbl_map(function(t) 21 | return t.name:gsub('[\'"]', ''):gsub('%s+', ' ') 22 | end, scope_data) 23 | return table.concat(scope_string, ' > ') 24 | end 25 | 26 | function M.get_visual_selection() 27 | local s_start = vim.fn.getpos("'<") 28 | local s_end = vim.fn.getpos("'>") 29 | local n_lines = math.abs(s_end[2] - s_start[2]) + 1 30 | local lines = vim.api.nvim_buf_get_lines(0, s_start[2] - 1, s_end[2], false) 31 | lines[1] = string.sub(lines[1], s_start[3], -1) 32 | if n_lines == 1 then 33 | lines[n_lines] = string.sub(lines[n_lines], 1, s_end[3] - s_start[3] + 1) 34 | else 35 | lines[n_lines] = string.sub(lines[n_lines], 1, s_end[3]) 36 | end 37 | return table.concat(lines, '\n') 38 | end 39 | 40 | function M.has_words_before() 41 | local line, col = unpack(vim.api.nvim_win_get_cursor(0)) 42 | return col ~= 0 and vim.api.nvim_buf_get_lines(0, line - 1, line, true)[1]:sub(col, col):match('%s') == nil 43 | end 44 | 45 | function M.lsp_kind_icons() 46 | return { 47 | Text = '', 48 | Method = '󰆧', 49 | Function = '󰊕', 50 | Constructor = '', 51 | Field = '󰇽', 52 | Variable = '󰂡', 53 | Class = '󰠱', 54 | Interface = '', 55 | Module = '', 56 | Property = '󰜢', 57 | Unit = '', 58 | Value = '󰎠', 59 | Enum = '', 60 | Keyword = '󰌋', 61 | Snippet = '', 62 | Color = '󰏘', 63 | File = '󰈙', 64 | Reference = '', 65 | Folder = '󰉋', 66 | EnumMember = '', 67 | Constant = '󰏿', 68 | Struct = '', 69 | Event = '', 70 | Operator = '󰆕', 71 | TypeParameter = '󰅲', 72 | } 73 | end 74 | 75 | function M.expand_snippet() 76 | local filetype_map = { 77 | typescriptreact = 'javascript', 78 | typescript = 'javascript', 79 | javascriptreact = 'javascript', 80 | } 81 | local line_to_cursor = vim.fn.getline('.'):sub(1, vim.fn.col('.') - 1) 82 | local keyword = vim.fn.matchstr(line_to_cursor, [[\k\+$]]) 83 | local filetype = filetype_map[vim.bo.filetype] or vim.bo.filetype 84 | local path = vim.fn.stdpath('config') .. '/snippets/' .. filetype .. '.json' 85 | local fs_stat = vim.uv.fs_stat(path) 86 | if not fs_stat or fs_stat.type ~= 'file' then 87 | return 88 | end 89 | ---@type { prefix: string[], body: string[] }[] 90 | local data = vim.json.decode(table.concat(vim.fn.readfile(path), '\n')) 91 | 92 | for _, snippet in pairs(data) do 93 | if snippet.prefix[1] == keyword then 94 | vim.fn.feedkeys(M.esc(''), 'n') 95 | vim.schedule(function() 96 | vim.snippet.expand(table.concat(snippet.body, '\n')) 97 | end) 98 | return true 99 | end 100 | end 101 | end 102 | 103 | return M 104 | -------------------------------------------------------------------------------- /nvim/lua/partials/picker.lua: -------------------------------------------------------------------------------- 1 | local SnacksPicker = { 2 | files = function() 3 | return Snacks.picker.files_with_symbols() 4 | end, 5 | resume = function() 6 | return Snacks.picker.resume() 7 | end, 8 | buffers = function() 9 | return Snacks.picker.buffers() 10 | end, 11 | live_grep = function() 12 | return Snacks.picker.grep({ live = true }) 13 | end, 14 | recent_files = function() 15 | return Snacks.picker.recent() 16 | end, 17 | smart = function() 18 | return Snacks.picker.smart() 19 | end, 20 | git_status = function() 21 | return Snacks.picker.git_status() 22 | end, 23 | lsp_implementations = function() 24 | return Snacks.picker.lsp_implementations() 25 | end, 26 | lsp_definitions = function() 27 | return Snacks.picker.lsp_definitions() 28 | end, 29 | lsp_type_definitions = function() 30 | return Snacks.picker.lsp_type_definitions() 31 | end, 32 | lsp_document_symbols = function() 33 | Snacks.picker.lsp_symbols() 34 | end, 35 | lsp_references = function() 36 | return Snacks.picker.lsp_references() 37 | end, 38 | workspaces = function() 39 | local items = {} 40 | local longest_name = 0 41 | for i, workspace in ipairs(require('workspaces').get()) do 42 | table.insert(items, { 43 | idx = i, 44 | score = i, 45 | text = workspace.path, 46 | name = workspace.name, 47 | }) 48 | longest_name = math.max(longest_name, #workspace.name) 49 | end 50 | longest_name = longest_name + 2 51 | return Snacks.picker({ 52 | items = items, 53 | format = function(item) 54 | local ret = {} 55 | ret[#ret + 1] = { ('%-' .. longest_name .. 's'):format(item.name), 'SnacksPickerLabel' } 56 | ret[#ret + 1] = { item.text, 'SnacksPickerComment' } 57 | return ret 58 | end, 59 | confirm = function(picker, item) 60 | picker:close() 61 | vim.cmd(('WorkspacesOpen %s'):format(item.name)) 62 | end, 63 | }) 64 | end, 65 | rest = function() 66 | return Snacks.picker.files({ 67 | cwd = '~/code/requests', 68 | confirm = function(picker, item) 69 | if not item then 70 | return vim.cmd.edit(('~/code/requests/%s.http'):format(picker.finder.filter.pattern)) 71 | end 72 | return picker:action('jump') 73 | end, 74 | }) 75 | end, 76 | } 77 | 78 | local Picker = SnacksPicker 79 | 80 | vim.keymap.set('n', '', function() 81 | return Picker.files() 82 | end) 83 | vim.keymap.set('n', '', function() 84 | return Picker.resume() 85 | end) 86 | vim.keymap.set('n', 'b', function() 87 | return Picker.buffers() 88 | end, { desc = 'Buffers' }) 89 | vim.keymap.set('n', 'fg', function() 90 | return Picker.live_grep() 91 | end, { desc = 'Live grep' }) 92 | vim.keymap.set('n', 'm', function() 93 | return Picker.recent_files() 94 | end, { desc = 'Recent files' }) 95 | vim.keymap.set('n', 'r', function() 96 | return Picker.smart() 97 | end, { desc = 'Smart picker' }) 98 | vim.keymap.set('n', 'gs', function() 99 | return Picker.git_status() 100 | end, { desc = 'Git status' }) 101 | vim.keymap.set('n', 'R', function() 102 | return Picker.rest() 103 | end, { desc = 'Requests' }) 104 | 105 | return Picker 106 | -------------------------------------------------------------------------------- /colors: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | from pathlib import Path 4 | import time 5 | import sys 6 | import os 7 | import argparse 8 | import pynvim 9 | color_file = '/home/kristijan/.cache/main_colorscheme.conf' 10 | colorschemes = { 11 | 'dark': 'tokyonight', 12 | 'light': 'onenord', 13 | } 14 | 15 | 16 | parser = argparse.ArgumentParser() 17 | parser.add_argument('bg', nargs='?', default=None, 18 | choices=['dark', 'light', 'toggle']) 19 | 20 | args = parser.parse_args() 21 | bg = args.bg 22 | current_bg = os.getenv('NVIM_COLORSCHEME_BG') 23 | 24 | 25 | def set_env(background): 26 | os.system('kitty @ set-colors --all --configured ' + color_file) 27 | cmd = ['export NVIM_COLORSCHEME_BG=' + background] 28 | cmd += ['export NVIM_COLORSCHEME=' + colorschemes[background]] 29 | cmd += ['python ~/neovim-config/kitty/reload_colors.py'] 30 | return cmd 31 | 32 | 33 | if Path(color_file).exists(): 34 | cfile = open(color_file, 'r') 35 | first_line = cfile.readline().rstrip() 36 | current_bg = first_line.split('=')[1] 37 | elif not bg: 38 | print('You must provide background type argument on first run', file=sys.stderr) 39 | exit() 40 | 41 | if not bg: 42 | print(';'.join(set_env(current_bg))) 43 | exit() 44 | 45 | if bg == 'toggle': 46 | bg = 'dark' if current_bg == 'light' else 'light' 47 | 48 | 49 | os.environ['NVIM_COLORSCHEME_BG'] = bg 50 | os.environ['NVIM_COLORSCHEME'] = colorschemes[bg] 51 | nvim = pynvim.attach( 52 | 'child', argv=["/usr/bin/env", "nvim", "--embed", "--headless"]) 53 | 54 | 55 | def get_hl_color(name): 56 | hl_output = nvim.call('execute', 'hi ' + name) 57 | bgcolor = None 58 | fgcolor = None 59 | for item in hl_output.split('\n')[1].split(): 60 | if item.startswith('guifg'): 61 | fgcolor = item.split('=')[1] 62 | if item.startswith('guibg'): 63 | bgcolor = item.split('=')[1] 64 | return fgcolor or '', bgcolor or '' 65 | 66 | 67 | normal_fg, normal_bg = get_hl_color('Normal') 68 | cursor_fg, cursor_bg = get_hl_color('Cursor') 69 | selection_fg, selection_bg = get_hl_color('Visual') 70 | 71 | command = [ 72 | 'env NVIM_COLORSCHEME_BG=' + bg, 73 | 'env NVIM_COLORSCHEME=' + colorschemes[bg], 74 | 'foreground ' + normal_fg, 75 | 'background ' + normal_bg, 76 | 'cursor ' + (cursor_bg.startswith('#') and cursor_bg or normal_fg), 77 | 'cursor_text_color background', 78 | 'selection_foreground ' + 79 | (selection_fg.startswith('#') and selection_fg or 'none'), 80 | 'selection_background ' + 81 | (selection_bg.startswith('#') and selection_bg or normal_fg) 82 | ] 83 | for i in range(0, 16): 84 | command.append('color' + str(i) + ' ' + 85 | nvim.eval('g:terminal_color_' + str(i))) 86 | 87 | nvim.close() 88 | 89 | file = open(color_file, 'w') 90 | file.write('\n'.join(command)) 91 | file.close() 92 | 93 | cmd = set_env(bg) 94 | is_bg_changed = bg != current_bg 95 | if is_bg_changed: 96 | waybar_file = open('/home/kristijan/.config/waybar/local.css', 'w') 97 | waybar_file.write( 98 | '@define-color bg ' + normal_bg + ';\n' 99 | + '@define-color fg ' + normal_fg + ';') 100 | waybar_file.close() 101 | 102 | cmd += ['~/.config/waybar/start.sh'] 103 | cmd += ['source ~/.zshrc'] 104 | 105 | print(';'.join(cmd)) 106 | -------------------------------------------------------------------------------- /nvim/lua/partials/plugins/blink.lua: -------------------------------------------------------------------------------- 1 | return { 2 | 'saghen/blink.cmp', 3 | event = 'InsertEnter', 4 | enabled = not vim.g.builtin_autocompletion, 5 | version = '*', 6 | dependencies = { 7 | 'mikavilpas/blink-ripgrep.nvim', 8 | }, 9 | opts = { 10 | cmdline = { 11 | enabled = false, 12 | }, 13 | sources = { 14 | default = { 'lsp', 'path', 'buffer' }, 15 | per_filetype = { 16 | org = { 'orgmode', 'buffer' }, 17 | sql = { 'snippets', 'dadbod', 'buffer' }, 18 | }, 19 | providers = { 20 | dadbod = { 21 | name = 'Dadbod', 22 | module = 'vim_dadbod_completion.blink', 23 | }, 24 | orgmode = { 25 | name = 'Orgmode', 26 | module = 'orgmode.org.autocompletion.blink', 27 | }, 28 | ripgrep = { 29 | name = 'RG', 30 | module = 'blink-ripgrep', 31 | score_offset = -10, 32 | opts = { 33 | prefix_min_len = 4, 34 | project_root_marker = { 'package.json', '.git' }, 35 | backend = { 36 | use = 'gitgrep-or-ripgrep', 37 | }, 38 | }, 39 | }, 40 | snippets = { 41 | score_offset = -5, 42 | }, 43 | }, 44 | }, 45 | completion = { 46 | list = { 47 | selection = { 48 | auto_insert = true, 49 | preselect = false, 50 | }, 51 | }, 52 | menu = { 53 | draw = { 54 | treesitter = { 'lsp' }, 55 | gap = 2, 56 | columns = { { 'kind_icon' }, { 'label', 'kind', 'source_name', gap = 1 } }, 57 | components = { 58 | kind = { 59 | highlight = 'BlinkCmpSource', 60 | }, 61 | kind_icon = { 62 | highlight = function(ctx) 63 | return ('CmpItemKind%s'):format(ctx.kind) 64 | end, 65 | }, 66 | source_name = { 67 | text = function(ctx) 68 | return table.concat({ '[', ctx.source_name, ']' }, '') 69 | end, 70 | }, 71 | }, 72 | }, 73 | }, 74 | documentation = { 75 | auto_show = true, 76 | window = { 77 | border = 'rounded', 78 | }, 79 | }, 80 | }, 81 | keymap = { 82 | preset = 'enter', 83 | [''] = { 84 | function(cmp) 85 | if cmp.snippet_active() then 86 | return cmp.snippet_forward() 87 | end 88 | 89 | if require('partials.utils').expand_snippet() then 90 | return false 91 | end 92 | 93 | if require('copilot.suggestion').is_visible() then 94 | require('copilot.suggestion').accept() 95 | return true 96 | end 97 | 98 | if require('partials.utils').has_words_before() then 99 | require('copilot.suggestion').next() 100 | return true 101 | end 102 | 103 | return false 104 | end, 105 | 'fallback', 106 | }, 107 | [''] = { 108 | function(cmp) 109 | if cmp.is_menu_visible() then 110 | return cmp.select_next() 111 | end 112 | 113 | return cmp.show({ providers = { 'ripgrep' } }) 114 | end, 115 | }, 116 | }, 117 | }, 118 | } 119 | -------------------------------------------------------------------------------- /nvim/snippets/javascript.json: -------------------------------------------------------------------------------- 1 | { 2 | "Class": { 3 | "prefix": ["clax"], 4 | "body": [ 5 | "export class ${1:ClassName} {", 6 | "\tconstructor(${4:props}) {", 7 | "\t\tthis.$4 = $4", 8 | "\t}", 9 | "", 10 | "\t$0", 11 | "}" 12 | ], 13 | "description": "Class definition template." 14 | }, 15 | "test": { 16 | "prefix": ["it"], 17 | "body": [ 18 | "it('${1:should}', async () => {", 19 | "\texpect(true).toBe(true)", 20 | "\t$0", 21 | "})" 22 | ], 23 | "description": "Test template" 24 | }, 25 | "method": { 26 | "prefix": ["mtd"], 27 | "body": [ 28 | "${1:method}($2) {", 29 | "\t$0", 30 | "}" 31 | ], 32 | "description": "method" 33 | }, 34 | "async-method": { 35 | "prefix": ["amtd"], 36 | "body": [ 37 | "async ${1:method}($2) {", 38 | "\t$0", 39 | "}" 40 | ], 41 | "description": "method" 42 | }, 43 | "function": { 44 | "prefix": ["fun"], 45 | "body": [ 46 | "($1) => {$0}" 47 | ], 48 | "description": "function" 49 | }, 50 | "async-function": { 51 | "prefix": ["afun"], 52 | "body": [ 53 | "async ($1) => {$0}" 54 | ], 55 | "description": "function" 56 | }, 57 | "const": { 58 | "prefix": ["c"], 59 | "body": [ 60 | "const $1 = $0" 61 | ], 62 | "description": "const" 63 | }, 64 | "let": { 65 | "prefix": ["l"], 66 | "body": [ 67 | "let $1 = $0" 68 | ], 69 | "description": "let" 70 | }, 71 | "Console log": { 72 | "prefix": ["cl"], 73 | "body": [ 74 | "console.log($0)" 75 | ], 76 | "description": "Console log" 77 | }, 78 | "Console debug": { 79 | "prefix": ["cd"], 80 | "body": [ 81 | "console.debug($0)" 82 | ], 83 | "description": "Console debug" 84 | }, 85 | "Console log all": { 86 | "prefix": ["clj"], 87 | "body": [ 88 | "console.log(JSON.stringify($0, null, 2))" 89 | ], 90 | "description": "Console log whole object" 91 | }, 92 | "Console debug all": { 93 | "prefix": ["cdj"], 94 | "body": [ 95 | "console.debug(JSON.stringify($0, null, 2))" 96 | ], 97 | "description": "Console debug whole object" 98 | }, 99 | "If": { 100 | "prefix": ["if"], 101 | "body": [ 102 | "if (${1:condition}) {", 103 | "\t$0", 104 | "}" 105 | ], 106 | "description": "Console debug whole object" 107 | }, 108 | "If-else": { 109 | "prefix": ["ie"], 110 | "body": [ 111 | "if (${1:condition}) {", 112 | "\t$2", 113 | "} else {", 114 | "\t$0", 115 | "}" 116 | ], 117 | "description": "Console debug whole object" 118 | }, 119 | "docblock": { 120 | "prefix": ["/**"], 121 | "body": [ 122 | "/**", 123 | " * $0", 124 | " */" 125 | ] 126 | }, 127 | "trycatch": { 128 | "prefix": ["tc"], 129 | "body": [ 130 | "try {", 131 | "\t$0", 132 | "} catch (e) {", 133 | "\tthrow e", 134 | "}" 135 | ], 136 | "description": "Try catch block" 137 | }, 138 | "Describe test": { 139 | "prefix": ["desc"], 140 | "body": [ 141 | "describe('${1}', () => {", 142 | "\tbeforeEach(async () => {", 143 | "\t\t$0", 144 | "\t})", 145 | "})" 146 | ], 147 | "description": "Describe test" 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /nvim/lua/partials/orgmode_config.lua: -------------------------------------------------------------------------------- 1 | local org_path = function(path) 2 | local org_directory = '~/orgfiles' 3 | return ('%s/%s'):format(org_directory, path) 4 | end 5 | 6 | ---@type OrgConfigOpts 7 | return { 8 | org_agenda_files = org_path('**/*'), 9 | org_default_notes_file = org_path('refile.org'), 10 | org_hide_emphasis_markers = true, 11 | org_agenda_text_search_extra_files = { 'agenda-archives' }, 12 | org_agenda_start_on_weekday = false, 13 | org_agenda_time_grid = { 14 | type = { 'daily', 'today', 'require-timed', 'remove-match' }, 15 | }, 16 | org_startup_indented = true, 17 | org_log_into_drawer = 'LOGBOOK', 18 | org_todo_keywords = { 'TODO(t)', 'PROGRESS(p)', '|', 'DONE(d)', 'REJECTED(r)' }, 19 | org_agenda_hide_empty_blocks = true, 20 | org_agenda_custom_commands = { 21 | a = { 22 | description = 'Agenda', 23 | types = { 24 | { 25 | type = 'tags', 26 | match = 'REVISIT', 27 | org_agenda_overriding_header = 'Tasks to revisit', 28 | }, 29 | { 30 | type = 'tags_todo', 31 | match = 'DEADLINE>="<+1d>"&DEADLINE<"<+2d>"', 32 | org_agenda_overriding_header = 'Tomorrow', 33 | }, 34 | { 35 | type = 'tags_todo', 36 | match = 'DEADLINE<""|SCHEDULED<""', 37 | org_agenda_overriding_header = 'Overdue', 38 | }, 39 | { 40 | type = 'agenda', 41 | org_agenda_tag_filter_preset = '-REVISIT', 42 | }, 43 | }, 44 | }, 45 | }, 46 | org_capture_templates = { 47 | t = { 48 | description = 'Refile', 49 | template = '* TODO %?\nDEADLINE: %T', 50 | }, 51 | T = { 52 | description = 'Todo', 53 | template = '* TODO %?\nDEADLINE: %T', 54 | target = org_path('todos.org'), 55 | }, 56 | r = { 57 | description = 'Quick note', 58 | template = '* TODO %? :REVISIT:', 59 | }, 60 | w = { 61 | description = 'Work todo', 62 | template = '* TODO %?\nDEADLINE: %T', 63 | target = org_path('work.org'), 64 | }, 65 | n = { 66 | description = 'Code note', 67 | template = '* %(return _G.kris.get_workspace_name()) - %(return vim.fn.expand("%:t")) :CODENOTE:\n%a\n%?', 68 | target = org_path('code_notes.org'), 69 | }, 70 | b = { 71 | description = 'BP log', 72 | template = '* %<%H:%M> - %?', 73 | target = org_path('bp_log.org'), 74 | datetree = true, 75 | }, 76 | }, 77 | notifications = { 78 | reminder_time = { 0, 1, 5, 10 }, 79 | repeater_reminder_time = { 0, 1, 5, 10 }, 80 | deadline_warning_reminder_time = { 0 }, 81 | cron_notifier = function(tasks) 82 | for _, task in ipairs(tasks) do 83 | local title = string.format('%s (%s)', task.category, task.humanized_duration) 84 | local subtitle = string.format('%s %s %s', string.rep('*', task.level), task.todo, task.title) 85 | local date = string.format('%s: %s', task.type, task.time:to_string()) 86 | 87 | if vim.fn.executable('notify-send') then 88 | vim.system({ 89 | 'notify-send', 90 | '--icon=/home/kristijan/github/orgmode/assets/nvim-orgmode-small.png', 91 | '--app-name=orgmode', 92 | '--urgency=critical', 93 | title, 94 | string.format('%s\n%s', subtitle, date), 95 | }) 96 | end 97 | end 98 | end, 99 | }, 100 | ui = { 101 | agenda = { 102 | preview_window = { 103 | border = 'single', 104 | focusable = false, 105 | }, 106 | }, 107 | }, 108 | } 109 | -------------------------------------------------------------------------------- /nvim/lua/partials/packs/colorscheme.lua: -------------------------------------------------------------------------------- 1 | local colorscheme = {} 2 | 3 | colorscheme.onenord = function() 4 | local colors = require('onenord.colors').load() 5 | 6 | local picker_bg = '#eff0f2' 7 | local prompt = '#eaebed' 8 | 9 | require('onenord').setup({ 10 | styles = { 11 | diagnostics = 'undercurl', 12 | comments = 'italic', 13 | functions = 'bold', 14 | }, 15 | inverse = { 16 | match_paren = true, 17 | }, 18 | custom_highlights = { 19 | NvimTreeNormal = { fg = colors.fg, bg = colors.bg }, 20 | CurSearch = { fg = colors.cyan, bg = colors.selection, style = 'bold' }, 21 | MatchParenCur = { fg = colors.blue, style = 'inverse' }, 22 | NormalFloat = { bg = colors.bg }, 23 | FloatBorder = { bg = colors.bg }, 24 | SimpleF = { fg = colors.red, bg = colors.diff_add_bg, style = 'bold' }, 25 | fugitiveStagedHeading = { fg = colors.green }, 26 | fugitiveStagedSection = { fg = colors.blue }, 27 | fugitiveUntrackedSection = { fg = colors.blue }, 28 | fugitiveUnstagedSection = { fg = colors.blue }, 29 | IndentLine = { link = 'IndentBlanklineChar' }, 30 | IndentLineCurrent = { link = 'IndentBlanklineContextChar' }, 31 | LspReferenceRead = { bg = colors.highlight, style = 'NONE' }, 32 | LspReferenceWrite = { bg = colors.highlight, style = 'NONE' }, 33 | LspReferenceText = { bg = colors.highlight, style = 'NONE' }, 34 | BlinkCmpSource = { 35 | link = 'Comment', 36 | }, 37 | SnacksPicker = { 38 | bg = picker_bg, 39 | }, 40 | SnacksPickerBorder = { 41 | bg = picker_bg, 42 | }, 43 | SnacksPickerInput = { 44 | bg = prompt, 45 | }, 46 | SnacksPickerInputBorder = { 47 | bg = prompt, 48 | }, 49 | SnacksPickerInputTitle = { bg = prompt }, 50 | }, 51 | }) 52 | 53 | return colorscheme 54 | end 55 | 56 | colorscheme.tokyonight = function() 57 | ---@diagnostic disable-next-line: missing-fields 58 | require('tokyonight').setup({ 59 | terminal_colors = true, 60 | plugins = { 61 | cmp = true, 62 | }, 63 | on_highlights = function(hl, c) 64 | hl.SimpleF = { 65 | fg = c.red, 66 | reverse = true, 67 | bold = true, 68 | } 69 | 70 | local prompt = '#2d3149' 71 | hl.SnacksPickerInput = { 72 | bg = prompt, 73 | } 74 | hl.SnacksPickerInputBorder = { 75 | bg = prompt, 76 | } 77 | 78 | hl.SnacksPickerInputTitle = { 79 | bg = prompt, 80 | } 81 | 82 | hl['@org.agenda.scheduled'] = { 83 | fg = c.green1, 84 | } 85 | 86 | hl['@org.keyword.done'] = { 87 | fg = c.green1, 88 | bold = true, 89 | } 90 | 91 | hl.Folded = { 92 | bg = 'NONE', 93 | fg = '#82aaff', 94 | } 95 | hl.BlinkCmpSource = { 96 | link = 'Comment', 97 | } 98 | end, 99 | }) 100 | vim.cmd.colorscheme('tokyonight') 101 | end 102 | 103 | colorscheme.config = function() 104 | require('todo-comments').setup() 105 | vim.opt.background = vim.env.NVIM_COLORSCHEME_BG or 'dark' 106 | 107 | vim.cmd.filetype('plugin indent on') 108 | vim.cmd.syntax('on') 109 | if vim.opt.background:get() == 'dark' then 110 | colorscheme.tokyonight() 111 | else 112 | colorscheme.onenord() 113 | end 114 | end 115 | 116 | vim.pack.load({ 117 | src = 'folke/tokyonight.nvim', 118 | dependencies = { 119 | 'rmehri01/onenord.nvim', 120 | 'folke/todo-comments.nvim', 121 | }, 122 | config = function() 123 | colorscheme.config() 124 | end, 125 | }) 126 | -------------------------------------------------------------------------------- /nvim/lua/partials/plugins/colorscheme.lua: -------------------------------------------------------------------------------- 1 | local colorscheme = { 2 | 'folke/tokyonight.nvim', 3 | dependencies = { 4 | { 'rmehri01/onenord.nvim', lazy = false, priority = 1000 }, 5 | 'folke/todo-comments.nvim', 6 | }, 7 | lazy = false, 8 | priority = 1000, 9 | } 10 | 11 | colorscheme.onenord = function() 12 | local colors = require('onenord.colors').load() 13 | 14 | local picker_bg = '#eff0f2' 15 | local prompt = '#eaebed' 16 | 17 | require('onenord').setup({ 18 | styles = { 19 | diagnostics = 'undercurl', 20 | comments = 'italic', 21 | functions = 'bold', 22 | }, 23 | inverse = { 24 | match_paren = true, 25 | }, 26 | custom_highlights = { 27 | NvimTreeNormal = { fg = colors.fg, bg = colors.bg }, 28 | CurSearch = { fg = colors.cyan, bg = colors.selection, style = 'bold' }, 29 | MatchParenCur = { fg = colors.blue, style = 'inverse' }, 30 | NormalFloat = { bg = colors.bg }, 31 | FloatBorder = { bg = colors.bg }, 32 | SimpleF = { fg = colors.red, bg = colors.diff_add_bg, style = 'bold' }, 33 | fugitiveStagedHeading = { fg = colors.green }, 34 | fugitiveStagedSection = { fg = colors.blue }, 35 | fugitiveUntrackedSection = { fg = colors.blue }, 36 | fugitiveUnstagedSection = { fg = colors.blue }, 37 | IndentLine = { link = 'IndentBlanklineChar' }, 38 | IndentLineCurrent = { link = 'IndentBlanklineContextChar' }, 39 | LspReferenceRead = { bg = colors.highlight, style = 'NONE' }, 40 | LspReferenceWrite = { bg = colors.highlight, style = 'NONE' }, 41 | LspReferenceText = { bg = colors.highlight, style = 'NONE' }, 42 | BlinkCmpSource = { 43 | link = 'Comment', 44 | }, 45 | SnacksPicker = { 46 | bg = picker_bg, 47 | }, 48 | SnacksPickerBorder = { 49 | bg = picker_bg, 50 | }, 51 | SnacksPickerInput = { 52 | bg = prompt, 53 | }, 54 | SnacksPickerInputBorder = { 55 | bg = prompt, 56 | }, 57 | SnacksPickerInputTitle = { bg = prompt }, 58 | }, 59 | }) 60 | 61 | return colorscheme 62 | end 63 | 64 | colorscheme.tokyonight = function() 65 | ---@diagnostic disable-next-line: missing-fields 66 | require('tokyonight').setup({ 67 | terminal_colors = true, 68 | plugins = { 69 | cmp = true, 70 | }, 71 | on_highlights = function(hl, c) 72 | hl.SimpleF = { 73 | fg = c.red, 74 | reverse = true, 75 | bold = true, 76 | } 77 | 78 | local prompt = '#2d3149' 79 | hl.SnacksPickerInput = { 80 | bg = prompt, 81 | } 82 | hl.SnacksPickerInputBorder = { 83 | bg = prompt, 84 | } 85 | 86 | hl.SnacksPickerInputTitle = { 87 | bg = prompt, 88 | } 89 | 90 | hl['@org.agenda.scheduled'] = { 91 | fg = c.green1, 92 | } 93 | 94 | hl['@org.keyword.done'] = { 95 | fg = c.green1, 96 | bold = true, 97 | } 98 | 99 | hl.Folded = { 100 | bg = 'NONE', 101 | fg = '#82aaff', 102 | } 103 | hl.BlinkCmpSource = { 104 | link = 'Comment', 105 | } 106 | end, 107 | }) 108 | vim.cmd.colorscheme('tokyonight') 109 | end 110 | 111 | colorscheme.config = function() 112 | require('todo-comments').setup() 113 | vim.opt.background = vim.env.NVIM_COLORSCHEME_BG or 'dark' 114 | 115 | vim.cmd.filetype('plugin indent on') 116 | vim.cmd.syntax('on') 117 | if vim.opt.background:get() == 'dark' then 118 | colorscheme.tokyonight() 119 | else 120 | colorscheme.onenord() 121 | end 122 | end 123 | 124 | return colorscheme 125 | -------------------------------------------------------------------------------- /nvim/lua/partials/packs/blink.lua: -------------------------------------------------------------------------------- 1 | vim.pack.load({ 2 | src = 'saghen/blink.cmp', 3 | event = 'InsertEnter', 4 | enabled = not vim.g.builtin_autocompletion, 5 | version = vim.version.range('v1.*'), 6 | dependencies = { 7 | 'mikavilpas/blink-ripgrep.nvim', 8 | }, 9 | config = function() 10 | require('blink.cmp').setup({ 11 | cmdline = { 12 | enabled = false, 13 | }, 14 | sources = { 15 | default = { 'lsp', 'path', 'buffer' }, 16 | per_filetype = { 17 | org = { 'orgmode', 'buffer' }, 18 | sql = { 'snippets', 'dadbod', 'buffer' }, 19 | mysql = { 'snippets', 'dadbod', 'buffer' }, 20 | }, 21 | providers = { 22 | dadbod = { 23 | name = 'Dadbod', 24 | module = 'vim_dadbod_completion.blink', 25 | }, 26 | orgmode = { 27 | name = 'Orgmode', 28 | module = 'orgmode.org.autocompletion.blink', 29 | }, 30 | ripgrep = { 31 | name = 'RG', 32 | module = 'blink-ripgrep', 33 | score_offset = -10, 34 | opts = { 35 | prefix_min_len = 4, 36 | project_root_marker = { 'package.json', '.git' }, 37 | backend = { 38 | use = 'gitgrep-or-ripgrep', 39 | }, 40 | }, 41 | }, 42 | snippets = { 43 | score_offset = -5, 44 | }, 45 | }, 46 | }, 47 | completion = { 48 | list = { 49 | selection = { 50 | auto_insert = true, 51 | preselect = false, 52 | }, 53 | }, 54 | menu = { 55 | draw = { 56 | treesitter = { 'lsp' }, 57 | gap = 2, 58 | columns = { { 'kind_icon' }, { 'label', 'kind', 'source_name', gap = 1 } }, 59 | components = { 60 | kind = { 61 | highlight = 'BlinkCmpSource', 62 | }, 63 | kind_icon = { 64 | highlight = function(ctx) 65 | return ('CmpItemKind%s'):format(ctx.kind) 66 | end, 67 | }, 68 | source_name = { 69 | text = function(ctx) 70 | return table.concat({ '[', ctx.source_name, ']' }, '') 71 | end, 72 | }, 73 | }, 74 | }, 75 | }, 76 | documentation = { 77 | auto_show = true, 78 | window = { 79 | border = 'rounded', 80 | }, 81 | }, 82 | }, 83 | keymap = { 84 | preset = 'enter', 85 | [''] = { 86 | function(cmp) 87 | if cmp.snippet_active() then 88 | return cmp.snippet_forward() 89 | end 90 | 91 | if require('partials.utils').expand_snippet() then 92 | return false 93 | end 94 | 95 | if require('copilot.suggestion').is_visible() then 96 | require('copilot.suggestion').accept() 97 | return true 98 | end 99 | 100 | if require('partials.utils').has_words_before() then 101 | require('copilot.suggestion').next() 102 | return true 103 | end 104 | 105 | return false 106 | end, 107 | 'fallback', 108 | }, 109 | [''] = { 110 | function(cmp) 111 | if cmp.is_menu_visible() then 112 | return cmp.select_next() 113 | end 114 | 115 | return cmp.show({ providers = { 'ripgrep' } }) 116 | end, 117 | }, 118 | }, 119 | }) 120 | end, 121 | }) 122 | -------------------------------------------------------------------------------- /waybar/config: -------------------------------------------------------------------------------- 1 | { 2 | "layer": "bottom", 3 | "position": "bottom", 4 | "height": 28, 5 | "modules-left": [ 6 | "hyprland/workspaces", 7 | "sway/mode" 8 | ], 9 | "modules-center": [ 10 | "keyboard-state", 11 | "hyprland/submap" 12 | ], 13 | "modules-right": [ 14 | "custom/exchangerates", 15 | "custom/weather", 16 | "disk", 17 | "memory", 18 | "cpu", 19 | "hyprland/language", 20 | "battery", 21 | "pulseaudio", 22 | "clock", 23 | "custom/notification", 24 | "tray" 25 | ], 26 | "tray": { 27 | "spacing": 2 28 | }, 29 | "clock": { 30 | "format": "{:%d.%m.%Y %H:%M:%S}", 31 | "format-alt": "{:%d.%m.%Y %H:%M:%S}", 32 | "tooltip-format": "{calendar}", 33 | "interval": 5, 34 | "calendar": { 35 | "mode" : "month", 36 | "mode-mon-col" : 3, 37 | "weeks-pos" : "", 38 | "on-scroll" : 1, 39 | "format": { 40 | "months": "{}", 41 | "days": "{}", 42 | "weeks": "W{}", 43 | "weekdays": "{}", 44 | "today": "{}" 45 | } 46 | }, 47 | "actions": { 48 | "on-click-right": "mode", 49 | "on-scroll-up": "shift_down", 50 | "on-scroll-down": "shift_up" 51 | } 52 | }, 53 | "cpu": { 54 | "interval": 2, 55 | "format": "C: {usage}%" 56 | }, 57 | "memory": { 58 | "interval": 2, 59 | "format": "M: {used}G/{total}G" 60 | }, 61 | "hyprland/language": { 62 | "format": "{}", 63 | "format-en": "🇺🇸 EN", 64 | "format-sr": "🇷🇸 RS", 65 | "on-click": "hyprctl switchxkblayout \"$(hyprctl devices -j | jq -r '.keyboards[] | select(.main == true) | .name')\" next" 66 | }, 67 | "hyprland/submap": { 68 | "format": "{}" 69 | }, 70 | "disk": { 71 | "interval": 25, 72 | "format": "/: {free}", 73 | "markup": "pango" 74 | }, 75 | "battery": { 76 | "interval": 10, 77 | "format": "{icon} {capacity}%" 78 | }, 79 | "keyboard-state": { 80 | "capslock": true, 81 | "format": { 82 | "capslock": "{icon}" 83 | }, 84 | "format-icons": { 85 | "locked": " CAPSLOCK ", 86 | "unlocked": "" 87 | } 88 | }, 89 | "pulseaudio": { 90 | "format": "{icon} {volume}%", 91 | "format-muted": "🔇 muted", 92 | "max-volume": 100, 93 | "format-icons": { 94 | "default": ["🔈", "🔉", "🔊"] 95 | 96 | }, 97 | "scroll-step": 2, 98 | "on-click-right": "~/.config/waybar/show_audio_devices.sh", 99 | "on-click": "pactl set-sink-mute @DEFAULT_SINK@ toggle", 100 | "on-click-middle": "~/.config/waybar/cycle_audio_output.sh" 101 | }, 102 | "custom/exchangerates": { 103 | "exec": "~/.config/waybar/exchangerates.sh", 104 | "interval": 1800, 105 | "return-type": "json", 106 | "format": "{}" 107 | }, 108 | "custom/weather": { 109 | "exec": "~/.config/waybar/weather.sh", 110 | "interval": 3600, 111 | "return-type": "json", 112 | "format": "{}" 113 | }, 114 | "custom/notification": { 115 | "format": "{icon}", 116 | "format-icons": { 117 | "notification": " ", 118 | "none": "", 119 | "dnd-notification": "", 120 | "dnd-none": "", 121 | "inhibited-notification": "", 122 | "inhibited-none": "", 123 | "dnd-inhibited-notification": "", 124 | "dnd-inhibited-none": "" 125 | }, 126 | "return-type": "json", 127 | "exec-if": "which swaync-client", 128 | "exec": "swaync-client -swb", 129 | "on-click": "swaync-client -t -sw", 130 | "on-click-middle": "swaync-client -d -sw", 131 | "on-click-right": "swaync-client -C", 132 | "escape": true 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /nvim/lua/partials/packs/javascript.lua: -------------------------------------------------------------------------------- 1 | local js_group = vim.api.nvim_create_augroup('custom_javascript', { clear = true }) 2 | local utils = require('partials.utils') 3 | local fn = vim.fn 4 | 5 | local handlers = {} 6 | local filetypes = { 'javascript', 'javascriptreact', 'typescript', 'typescriptreact' } 7 | 8 | vim.g.js_file_import_omit_semicolon = 1 9 | 10 | vim.pack.load({ 11 | src = 'dmmulroy/tsc.nvim', 12 | dependencies = { 13 | 'kristijanhusak/vim-js-file-import', 14 | }, 15 | ft = filetypes, 16 | config = function() 17 | require('tsc').setup({ 18 | auto_close_qflist = true, 19 | }) 20 | vim.keymap.set('n', '(JsConsoleLog)', handlers.console_log) 21 | vim.keymap.set('n', '(JsGotoFile)', handlers.goto_file) 22 | 23 | vim.api.nvim_create_autocmd('FileType', { 24 | pattern = filetypes, 25 | callback = handlers.setup_buffer, 26 | group = js_group, 27 | }) 28 | 29 | if vim.tbl_contains(filetypes, vim.bo.filetype) then 30 | vim.cmd('doautocmd FileType ' .. vim.bo.filetype) 31 | end 32 | 33 | vim.api.nvim_create_autocmd('DirChanged', { 34 | callback = function() 35 | require('tsc').setup({ 36 | auto_close_qflist = true, 37 | bin_path = require('tsc.utils').find_tsc_bin(), 38 | }) 39 | end, 40 | }) 41 | end, 42 | }) 43 | 44 | function handlers.setup_buffer() 45 | vim.keymap.set('n', 'll', '(JsConsoleLog)', { remap = true, buffer = true, desc = 'Console log' }) 46 | vim.keymap.set('n', 'gf', '(JsGotoFile)', { remap = true, buffer = true, desc = 'Go to file' }) 47 | vim.keymap.set('n', '', handlers.setup_imports, { buffer = true, silent = true }) 48 | vim.keymap.set('n', '', handlers.setup_imports_and_lsp_format, { buffer = true, silent = true }) 49 | vim.opt_local.isfname:append('@-@') 50 | vim.cmd('compiler tsc') 51 | end 52 | 53 | function handlers.console_log() 54 | local view = fn.winsaveview() or {} 55 | local word = fn.expand('') 56 | local node = vim.treesitter.get_node() 57 | while node and node:type() ~= 'lexical_declaration' do 58 | node = node:parent() 59 | end 60 | if node then 61 | local _, _, end_line, _ = vim.treesitter.get_node_range(node) 62 | fn.cursor(end_line + 1, 0) 63 | end 64 | local scope = utils.get_gps_scope(word) 65 | if not scope:match(vim.pesc(word) .. '$') then 66 | scope = ('%s > %s'):format(scope, word) 67 | end 68 | vim.cmd(string.format("keepjumps norm!oconsole.log('%s', %s); // eslint-disable-line no-console", scope, word)) 69 | fn['repeat#set'](utils.esc('(JsConsoleLog)')) 70 | fn.winrestview(view) 71 | end 72 | 73 | function handlers.goto_file() 74 | local full_path = fn.printf('%s/%s', fn.expand('%:p:h'), fn.expand('')) 75 | local stats = vim.loop.fs_stat(full_path) 76 | if not stats or stats.type ~= 'directory' then 77 | return vim.cmd([[norm! gf]]) 78 | end 79 | 80 | for _, suffix in ipairs(fn.split(vim.bo.suffixesadd, ',')) do 81 | local index_file = full_path .. '/index' .. suffix 82 | if fn.filereadable(index_file) then 83 | return vim.cmd.edit(index_file) 84 | end 85 | end 86 | end 87 | 88 | function handlers.setup_imports_and_lsp_format() 89 | handlers.setup_imports() 90 | 91 | vim.wait(500, function() 92 | local client = vim.lsp.get_clients({ 93 | name = 'ts_ls', 94 | })[1] 95 | if client then 96 | return client.requests == 0 97 | end 98 | return true 99 | end) 100 | 101 | kris.lsp.format() 102 | end 103 | 104 | local function execute_code_action(code_action) 105 | local client = vim.lsp.get_clients({ name = 'ts_ls' })[1] 106 | local bufnr = vim.api.nvim_get_current_buf() 107 | 108 | local params = vim.lsp.util.make_range_params() 109 | params.context = { 110 | only = { code_action }, 111 | } 112 | local args = { vim.lsp.protocol.Methods.textDocument_codeAction, params, 5000, bufnr } 113 | if vim.fn.has('nvim-0.11') > 0 then 114 | table.insert(args, 1, client) 115 | end 116 | 117 | local res = client.request_sync(unpack(args)) 118 | 119 | if not res or #res.result == 0 then 120 | return 121 | end 122 | 123 | vim.lsp.util.apply_text_edits( 124 | res.result[1].edit.documentChanges[1].edits, 125 | vim.api.nvim_get_current_buf(), 126 | client.offset_encoding or 'utf-16' 127 | ) 128 | end 129 | 130 | function handlers.setup_imports(organize) 131 | local cmds = { 'source.addMissingImports.ts', 'source.removeUnusedImports.ts', 'source.fixAll.ts' } 132 | if organize then 133 | table.insert(cmds, 'source.organizeImports.ts') 134 | end 135 | for _, cmd in ipairs(cmds) do 136 | execute_code_action(cmd) 137 | end 138 | end 139 | -------------------------------------------------------------------------------- /nvim/after/plugin/autocompletion.lua: -------------------------------------------------------------------------------- 1 | if not vim.g.builtin_autocompletion then 2 | return 3 | end 4 | 5 | local utils = require('partials.utils') 6 | local augroup = vim.api.nvim_create_augroup('custom_lsp_completion', { clear = true }) 7 | local icons = utils.lsp_kind_icons() 8 | local protocol = vim.lsp.protocol 9 | vim.opt.complete = '.,w,b,o' 10 | 11 | vim.api.nvim_create_autocmd('InsertEnter', { 12 | pattern = '*', 13 | group = augroup, 14 | callback = function(ev) 15 | local is_valid_buffer = vim.bo[ev.buf].buftype ~= 'prompt' and vim.bo[ev.buf].filetype ~= 'snacks_input' 16 | vim.opt_local.autocomplete = is_valid_buffer 17 | end, 18 | }) 19 | 20 | local function on_complete_changed() 21 | local completed_item = vim.api.nvim_get_vvar('completed_item') 22 | if not completed_item or not completed_item.user_data or not completed_item.user_data.nvim then 23 | return 24 | end 25 | local completion_item = completed_item.user_data.nvim.lsp.completion_item --- @type lsp.CompletionItem 26 | local client_id = completed_item.user_data.nvim.lsp.client_id --- @type integer 27 | local client = vim.lsp.get_client_by_id(client_id) 28 | if not client then 29 | return 30 | end 31 | 32 | client:request(protocol.Methods.completionItem_resolve, completion_item, function(err, result) 33 | if err or not result then 34 | return 35 | end 36 | 37 | local text = {} 38 | 39 | if result and result.documentation then 40 | local docs = type(result.documentation) == 'string' and result.documentation or result.documentation.value 41 | vim.list_extend(text, vim.split(docs, '\n')) 42 | end 43 | 44 | if result.detail and not vim.startswith(text[1] or '', '```') then 45 | text = vim.list_extend({ '```' .. vim.bo.filetype, result.detail, '```' }, text) 46 | end 47 | 48 | if #text == 0 then 49 | return 50 | end 51 | 52 | local _, popup_winid = vim.lsp.util.open_floating_preview(text, 'markdown', { 53 | border = 'single', 54 | }) 55 | local pos = vim.fn.pum_getpos() 56 | if not pos or not pos.row or not pos.col then 57 | return 58 | end 59 | vim.api.nvim_win_set_config(popup_winid, { 60 | relative = 'editor', 61 | row = pos.row, 62 | col = pos.col + pos.width + (pos.scrollbar and 1 or 0), 63 | }) 64 | end) 65 | end 66 | 67 | vim.api.nvim_create_autocmd('LspAttach', { 68 | group = augroup, 69 | callback = function(ev) 70 | local client = vim.lsp.get_client_by_id(ev.data.client_id) 71 | if not client or not client:supports_method(protocol.Methods.textDocument_completion) then 72 | return 73 | end 74 | 75 | vim.lsp.completion.enable(true, client.id, ev.buf, { 76 | convert = function(item) 77 | local kind = vim.lsp.protocol.CompletionItemKind[item.kind] or 'Text' 78 | local menu = ('[%s]'):format(kind) 79 | if item.data and item.data.bufnames then 80 | menu = '[Buffer]' 81 | end 82 | return { 83 | kind = icons[kind], 84 | kind_hlgroup = ('CmpItemKind%s'):format(kind), 85 | menu = menu, 86 | } 87 | end, 88 | }) 89 | 90 | vim.api.nvim_create_autocmd('CompleteChanged', { 91 | group = augroup, 92 | buffer = ev.buf, 93 | callback = function() 94 | on_complete_changed() 95 | end, 96 | }) 97 | end, 98 | }) 99 | 100 | -- Keymaps 101 | vim.keymap.set('i', '', function() 102 | if vim.snippet.active({ direction = 1 }) then 103 | return vim.snippet.jump(1) 104 | end 105 | 106 | if utils.expand_snippet() then 107 | return 108 | end 109 | 110 | if require('copilot.suggestion').is_visible() then 111 | return require('copilot.suggestion').accept() 112 | end 113 | if utils.has_words_before() then 114 | return require('copilot.suggestion').next() 115 | end 116 | 117 | utils.feedkeys('', 'n') 118 | end, { silent = true }) 119 | 120 | vim.keymap.set({ 'i', 's' }, '', function() 121 | if vim.snippet.active({ direction = -1 }) then 122 | return vim.snippet.jump(-1) 123 | end 124 | 125 | return utils.feedkeys('', 'n') 126 | end, { silent = true }) 127 | 128 | vim.keymap.set('i', '', function() 129 | if vim.fn.pumvisible() > 0 then 130 | return utils.feedkeys('', 'n') 131 | end 132 | 133 | vim.lsp.completion.get() 134 | end) 135 | 136 | vim.keymap.set('i', '', function() 137 | local npairs = require('nvim-autopairs') 138 | 139 | if vim.fn.pumvisible() == 0 then 140 | return npairs.autopairs_cr() 141 | end 142 | 143 | if vim.fn.complete_info({ 'selected' }).selected ~= -1 then 144 | return npairs.esc('') 145 | end 146 | return npairs.esc('') .. npairs.autopairs_cr() 147 | end, { expr = true, noremap = true, replace_keycodes = false }) 148 | 149 | -------------------------------------------------------------------------------- /nvim/lua/partials/plugins/javascript.lua: -------------------------------------------------------------------------------- 1 | local js_group = vim.api.nvim_create_augroup('custom_javascript', { clear = true }) 2 | local utils = require('partials.utils') 3 | local fn = vim.fn 4 | 5 | local handlers = {} 6 | local filetypes = { 'javascript', 'javascriptreact', 'typescript', 'typescriptreact' } 7 | 8 | local javascript = { 9 | 'dmmulroy/tsc.nvim', 10 | dependencies = { 11 | 'kristijanhusak/vim-js-file-import', 12 | }, 13 | ft = filetypes, 14 | } 15 | 16 | javascript.init = function() 17 | vim.g.js_file_import_omit_semicolon = 1 18 | end 19 | 20 | javascript.config = function() 21 | require('tsc').setup({ 22 | auto_close_qflist = true, 23 | }) 24 | vim.keymap.set('n', '(JsConsoleLog)', handlers.console_log) 25 | vim.keymap.set('n', '(JsGotoFile)', handlers.goto_file) 26 | 27 | vim.api.nvim_create_autocmd('FileType', { 28 | pattern = { 'javascript', 'javascriptreact', 'typescript', 'typescriptreact' }, 29 | callback = handlers.setup_buffer, 30 | group = js_group, 31 | }) 32 | 33 | if vim.tbl_contains(filetypes, vim.bo.filetype) then 34 | vim.cmd('doautocmd FileType ' .. vim.bo.filetype) 35 | end 36 | 37 | vim.api.nvim_create_autocmd('DirChanged', { 38 | callback = function() 39 | require('tsc').setup({ 40 | auto_close_qflist = true, 41 | bin_path = require('tsc.utils').find_tsc_bin(), 42 | }) 43 | end, 44 | }) 45 | 46 | return javascript 47 | end 48 | 49 | function handlers.setup_buffer() 50 | vim.keymap.set('n', 'll', '(JsConsoleLog)', { remap = true, buffer = true, desc = 'Console log' }) 51 | vim.keymap.set('n', 'gf', '(JsGotoFile)', { remap = true, buffer = true, desc = 'Go to file' }) 52 | vim.keymap.set('n', '', handlers.setup_imports, { buffer = true, silent = true }) 53 | vim.keymap.set('n', '', handlers.setup_imports_and_lsp_format, { buffer = true, silent = true }) 54 | vim.opt_local.isfname:append('@-@') 55 | vim.cmd('compiler tsc') 56 | end 57 | 58 | function handlers.console_log() 59 | local view = fn.winsaveview() or {} 60 | local word = fn.expand('') 61 | local node = vim.treesitter.get_node() 62 | while node and node:type() ~= 'lexical_declaration' do 63 | node = node:parent() 64 | end 65 | if node then 66 | local _, _, end_line, _ = vim.treesitter.get_node_range(node) 67 | fn.cursor(end_line + 1, 0) 68 | end 69 | local scope = utils.get_gps_scope(word) 70 | if not scope:match(vim.pesc(word) .. '$') then 71 | scope = ('%s > %s'):format(scope, word) 72 | end 73 | vim.cmd(string.format("keepjumps norm!oconsole.log('%s', %s); // eslint-disable-line no-console", scope, word)) 74 | fn['repeat#set'](utils.esc('(JsConsoleLog)')) 75 | fn.winrestview(view) 76 | end 77 | 78 | function handlers.goto_file() 79 | local full_path = fn.printf('%s/%s', fn.expand('%:p:h'), fn.expand('')) 80 | local stats = vim.loop.fs_stat(full_path) 81 | if not stats or stats.type ~= 'directory' then 82 | return vim.cmd([[norm! gf]]) 83 | end 84 | 85 | for _, suffix in ipairs(fn.split(vim.bo.suffixesadd, ',')) do 86 | local index_file = full_path .. '/index' .. suffix 87 | if fn.filereadable(index_file) then 88 | return vim.cmd.edit(index_file) 89 | end 90 | end 91 | end 92 | 93 | function handlers.setup_imports_and_lsp_format() 94 | handlers.setup_imports() 95 | 96 | vim.wait(500, function() 97 | local client = vim.lsp.get_clients({ 98 | name = 'ts_ls', 99 | })[1] 100 | if client then 101 | return client.requests == 0 102 | end 103 | return true 104 | end) 105 | 106 | kris.lsp.format() 107 | end 108 | 109 | local function execute_code_action(code_action) 110 | local client = vim.lsp.get_clients({ name = 'ts_ls' })[1] 111 | local bufnr = vim.api.nvim_get_current_buf() 112 | 113 | local params = vim.lsp.util.make_range_params() 114 | params.context = { 115 | only = { code_action }, 116 | } 117 | local args = { vim.lsp.protocol.Methods.textDocument_codeAction, params, 5000, bufnr } 118 | if vim.fn.has('nvim-0.11') > 0 then 119 | table.insert(args, 1, client) 120 | end 121 | 122 | local res = client.request_sync(unpack(args)) 123 | 124 | if not res or #res.result == 0 then 125 | return 126 | end 127 | 128 | vim.lsp.util.apply_text_edits( 129 | res.result[1].edit.documentChanges[1].edits, 130 | vim.api.nvim_get_current_buf(), 131 | client.offset_encoding or 'utf-16' 132 | ) 133 | end 134 | 135 | function handlers.setup_imports(organize) 136 | local cmds = { 'source.addMissingImports.ts', 'source.removeUnusedImports.ts', 'source.fixAll.ts' } 137 | if organize then 138 | table.insert(cmds, 'source.organizeImports.ts') 139 | end 140 | for _, cmd in ipairs(cmds) do 141 | execute_code_action(cmd) 142 | end 143 | end 144 | 145 | return javascript 146 | -------------------------------------------------------------------------------- /nvim/after/plugin/search.lua: -------------------------------------------------------------------------------- 1 | _G.kris = _G.kris or {} 2 | 3 | local utils = require('partials.utils') 4 | local search = {} 5 | local is_toggle = false 6 | local mode = 'term' 7 | local last_search = '' 8 | local last_search_desc = '' 9 | 10 | local search_group = vim.api.nvim_create_augroup('init_vim_search', { clear = true }) 11 | vim.api.nvim_create_autocmd('FileType', { 12 | pattern = 'qf', 13 | callback = function() 14 | vim.b.matchup_matchparen_enabled = 0 15 | vim.keymap.set('n', 'r', ':cgetexpr v:lua.kris.search.do_search()', { 16 | silent = true, 17 | buffer = true, 18 | desc = 'Refresh search results', 19 | }) 20 | vim.cmd.wincmd('J') 21 | end, 22 | group = search_group, 23 | }) 24 | vim.api.nvim_create_autocmd('QuickFixCmdPost', { 25 | pattern = '[^l]*', 26 | command = 'cwindow', 27 | nested = true, 28 | group = search_group, 29 | }) 30 | vim.api.nvim_create_autocmd('QuickFixCmdPost', { 31 | pattern = 'l*', 32 | command = 'lwindow', 33 | nested = true, 34 | group = search_group, 35 | }) 36 | vim.api.nvim_create_autocmd('QuickFixCmdPost', { 37 | pattern = '[^l]*', 38 | group = search_group, 39 | nested = true, 40 | callback = function() 41 | vim.schedule(function() 42 | local wins = vim.api.nvim_list_wins() 43 | for _, win in ipairs(wins) do 44 | local buf = vim.api.nvim_win_get_buf(win) 45 | if vim.bo[buf].filetype == 'qf' then 46 | vim.api.nvim_win_set_var(win, 'quickfix_title', last_search_desc) 47 | end 48 | end 49 | end) 50 | end, 51 | }) 52 | 53 | vim.keymap.set('n', 'ff', ':call v:lua.kris.search.run("")', { silent = true, desc = 'Search' }) 54 | vim.keymap.set( 55 | 'n', 56 | 'fw', 57 | ':call v:lua.kris.search.run(expand(""))', 58 | { silent = true, desc = 'Search for word under cursor' } 59 | ) 60 | vim.keymap.set( 61 | 'v', 62 | 'fw', 63 | ':call v:lua.kris.search.run("", 1)', 64 | { silent = true, desc = 'Search visual selection' } 65 | ) 66 | 67 | local function cleanup(no_reset_mode) 68 | is_toggle = false 69 | if not no_reset_mode then 70 | mode = 'term' 71 | end 72 | return pcall(vim.keymap.del, 'c', '') 73 | end 74 | 75 | local function msg(txt) 76 | return vim.api.nvim_out_write(txt .. '\n') 77 | end 78 | 79 | function search.toggle_search_mode() 80 | is_toggle = true 81 | if mode == 'term' then 82 | mode = 'word' 83 | elseif mode == 'word' then 84 | mode = 'regex' 85 | else 86 | mode = 'term' 87 | end 88 | 89 | return vim.fn.getcmdline() 90 | end 91 | 92 | function search.run(search_term, is_visual) 93 | local term = search_term 94 | if is_visual then 95 | term = utils.get_visual_selection() 96 | end 97 | 98 | vim.keymap.set('c', '', 'ev:lua.kris.search.toggle_search_mode()', { remap = true }) 99 | 100 | local status, t = pcall(vim.fn.input, 'Enter ' .. mode .. ': ', term) 101 | if not status then 102 | return cleanup() 103 | end 104 | term = t 105 | 106 | if is_toggle then 107 | is_toggle = false 108 | return search.run(term) 109 | end 110 | 111 | cleanup('no_reset_mode') 112 | vim.cmd.redraw({ bang = true }) 113 | 114 | if term == '' then 115 | return msg('Empty search.') 116 | end 117 | 118 | msg('Searching for word -> ' .. term) 119 | local status_dir, dir = pcall(vim.fn.input, 'Path: ', '', 'file') 120 | if not status_dir then 121 | return cleanup() 122 | end 123 | 124 | local grepprg = vim.o.grepprg 125 | local cmd = nil 126 | if mode == 'term' then 127 | cmd = table.concat({ grepprg, '--fixed-strings', vim.fn.shellescape(term), dir }, ' ') 128 | elseif mode == 'regex' then 129 | cmd = table.concat({ grepprg, string.format("'%s'", term), dir }, ' ') 130 | elseif mode == 'word' then 131 | cmd = table.concat({ grepprg, string.format("'\\b%s\\b'", term), dir }, ' ') 132 | end 133 | 134 | if (not cmd or cmd == '') and last_search == '' then 135 | msg('Empty search.') 136 | return cleanup() 137 | end 138 | 139 | cmd = cmd and cmd ~= '' and cmd or last_search 140 | last_search = cmd 141 | last_search_desc = (' [%s] %s'):format(mode, term) 142 | 143 | local results = vim.fn.systemlist(cmd) 144 | vim.cmd.redraw() 145 | 146 | if #results <= 0 then 147 | msg('No results for search -> ' .. cmd) 148 | return cleanup() 149 | end 150 | 151 | if vim.v.shell_error and vim.v.shell_error > 0 and #results > 0 then 152 | msg('Search error (status: ' .. vim.v.shell_error .. '): ' .. table.concat(results, ' ')) 153 | return cleanup() 154 | end 155 | 156 | vim.cmd([[botright cgetexpr v:lua.kris.search.do_search()]]) 157 | return cleanup() 158 | end 159 | 160 | function search.do_search() 161 | return vim.fn.systemlist(last_search) 162 | end 163 | 164 | _G.kris.search = search 165 | return search 166 | -------------------------------------------------------------------------------- /nvim/minvimrc.vim: -------------------------------------------------------------------------------- 1 | " Fast install with this command 2 | " curl https://raw.githubusercontent.com/kristijanhusak/neovim-config/refs/heads/master/nvim/minvimrc.vim -o $HOME/.vimrc 3 | set nocompatible 4 | let g:mapleader = ',' 5 | 6 | filetype plugin indent on 7 | syntax on 8 | 9 | " Setup block and beam cursor in normal/insert mode 10 | let &t_VS = "\[ q" 11 | let &t_SI = "\[5 q" 12 | let &t_SR = "\[5 q" 13 | let &t_EI = "\[ q" 14 | 15 | set title 16 | set number 17 | set relativenumber 18 | set backspace=indent,eol,start 19 | set showcmd 20 | set noshowmode 21 | set gdefault 22 | set guicursor+=a:blinkon500-blinkoff100 23 | set cursorline 24 | set autoread 25 | set smartcase 26 | set ignorecase 27 | set hlsearch 28 | set incsearch 29 | set showmatch 30 | set mouse=a 31 | set nostartofline 32 | set timeoutlen=1000 ttimeoutlen=0 33 | set laststatus=2 34 | set fileencoding=utf-8 encoding=utf-8 35 | set wrap 36 | set linebreak 37 | set listchars=tab:\ \ ,trail:· 38 | set list 39 | set lazyredraw 40 | set fillchars=fold:\ ,vert:│ 41 | set completeopt-=preview 42 | set hidden 43 | set conceallevel=2 concealcursor=i 44 | set splitright 45 | set splitbelow 46 | set noswapfile 47 | set nobackup 48 | set nowb 49 | set undofile 50 | set statusline=\ %{toupper(mode())}\ ▏%f\ ▏%m\ %=\ %y\ ▏%4l:%-3c 51 | set smarttab 52 | set shiftwidth=2 53 | set softtabstop=2 54 | set tabstop=2 55 | set expandtab 56 | set smartindent 57 | set autoindent 58 | set nofoldenable 59 | set wildmenu 60 | set wildignore=*.o,*.obj,*~ 61 | set wildignore+=*logs* 62 | set wildignore+=*node_modules/** 63 | set wildignore+=*DS_Store* 64 | set wildignore+=*.gem 65 | set wildignore+=log/** 66 | set wildignore+=tmp/** 67 | set wildignore+=dist/** 68 | set wildignore+=*.png,*.jpg,*.gif 69 | 70 | set path=**/* 71 | 72 | if !has('nvim') 73 | set wildmode=list:full 74 | set undodir=~/.cache/vim/undo 75 | endif 76 | 77 | try 78 | colorscheme sorbet 79 | catch /^Vim\%((\a\+)\)\=:E185/ 80 | colorscheme slate 81 | endtry 82 | 83 | " Map save to Ctrl + S 84 | map :w 85 | imap :w 86 | " Also save with ,w and ,s 87 | nnoremap w :w 88 | nnoremap s :w 89 | 90 | " Easier window navigation 91 | nmap h 92 | nmap j 93 | nmap k 94 | nmap l 95 | " Open vertical split 96 | nnoremap v v 97 | 98 | " Down is really the next line 99 | nnoremap j gj 100 | nnoremap k gk 101 | 102 | nnoremap Y y$ 103 | 104 | vnoremap "+y 105 | " Paste from system clipboard with Ctrl + v 106 | inoremap "+p 107 | nnoremap p "0p 108 | 109 | " Move to the end of yanked text after yank and paste 110 | nnoremap p p`] 111 | vnoremap y y`] 112 | vnoremap p p`] 113 | 114 | " Move selected lines up and down 115 | vnoremap J :m '>+1gv=gv 116 | vnoremap K :m '<-2gv=gv 117 | 118 | " Clear search highlight 119 | nnoremap :noh 120 | 121 | nnoremap 122 | 123 | cnoreabbrev Wq wq 124 | cnoreabbrev WQ wq 125 | cnoreabbrev W w 126 | cnoreabbrev Q q 127 | cnoreabbrev Qa qa 128 | 129 | " Indenting in visual mode 130 | xnoremap >gv 132 | 133 | " Center highlighted search 134 | nnoremap n nzz 135 | nnoremap N Nzz 136 | 137 | nnoremap :call feedkeys(':find ') 138 | nnoremap f :vimgrep **/* 139 | nnoremap ]q :cnext 140 | nnoremap [q :cprev 141 | nnoremap ]b :bnext 142 | nnoremap [b :bprev 143 | 144 | 145 | function! ToggleComment() abort 146 | let l:cs = substitute(&commentstring, '%s', '', '') 147 | if getline('.') =~ '^\s*' . escape(l:cs, '#') 148 | execute 'normal! ^' . len(l:cs) . 'x' 149 | else 150 | execute 'normal! I' . l:cs 151 | endif 152 | endfunction 153 | nnoremap c :call ToggleComment() 154 | vnoremap c :call ToggleComment() 155 | 156 | let g:netrw_banner = 0 157 | let g:netrw_liststyle = 3 158 | let g:netrw_browse_split = 4 159 | let g:netrw_altv = 1 160 | let g:netrw_winsize = 15 161 | 162 | map n :Lexplore 163 | 164 | function! s:setup_paths() abort 165 | let cwd = getcwd() 166 | let entries = glob(cwd.'/*', 0, 1) 167 | let paths = ['.', ''] 168 | for entry in entries 169 | if isdirectory(entry) && stridx(&wildignore, fnamemodify(entry, ':t')) < 0 170 | call add(paths, entry.'/**') 171 | endif 172 | endfor 173 | let &path = join(paths, ',') 174 | endfunction 175 | 176 | augroup fallback_vimrc 177 | autocmd! 178 | autocmd FileType netrw nmap o | silent! unmap 179 | autocmd QuickFixCmdPost [^l]* cwindow 180 | autocmd InsertEnter * set nocul 181 | autocmd InsertLeave,BufEnter * set cul 182 | autocmd FocusGained,BufEnter * silent! exe checktime 183 | autocmd BufEnter,FocusGained,InsertLeave,WinEnter * if &nu | set rnu | endif 184 | autocmd BUfLeave,FocusLost,InsertEnter,WinLeave * if &nu | set nornu | endif 185 | autocmd VimEnter,DirChanged * call s:setup_paths() 186 | augroup end 187 | -------------------------------------------------------------------------------- /nvim/after/plugin/tests.lua: -------------------------------------------------------------------------------- 1 | local last_cmd = nil 2 | local augroup = vim.api.nvim_create_augroup('kris_test_runner', { clear = true }) 3 | 4 | local function is_terminal_buf(bufnr) 5 | return vim.bo[bufnr].buftype == 'terminal' and vim.b[bufnr].last_cmd ~= nil 6 | end 7 | 8 | local function get_terminal_bufnr() 9 | for _, win in ipairs(vim.fn.getwininfo()) do 10 | if is_terminal_buf(win.bufnr) then 11 | return win.bufnr, win.winid 12 | end 13 | end 14 | return nil, -1 15 | end 16 | 17 | local notify = function(msg, level) 18 | vim.notify(msg, level or vim.log.levels.WARN, { 19 | title = 'Test runner', 20 | id = 'kris_test_runner', 21 | }) 22 | end 23 | 24 | local win_config = function() 25 | return { 26 | width = math.max(95, math.floor(vim.o.columns * 0.25)), 27 | height = math.floor(vim.o.lines * 0.9), 28 | relative = 'editor', 29 | anchor = 'NE', 30 | row = 1, 31 | col = vim.o.columns - 1, 32 | focusable = true, 33 | border = 'rounded', 34 | } 35 | end 36 | 37 | local function exec(cmd) 38 | local bufnr = get_terminal_bufnr() 39 | local is_currently_in_terminal = false 40 | if bufnr then 41 | is_currently_in_terminal = vim.api.nvim_get_current_buf() == bufnr 42 | vim.cmd(bufnr .. 'bw!') 43 | end 44 | 45 | bufnr = vim.api.nvim_create_buf(false, is_currently_in_terminal) 46 | local win = vim.api.nvim_open_win(bufnr, true, win_config()) 47 | 48 | vim.keymap.set('n', 'q', function() 49 | vim.api.nvim_win_set_config(win, { hide = true }) 50 | vim.cmd('wincmd p') 51 | end, { buffer = bufnr }) 52 | 53 | notify('Running tests...', vim.log.levels.INFO) 54 | 55 | vim.fn.termopen(cmd, { 56 | on_exit = function(_, code) 57 | if code == 0 then 58 | return notify('✅ Tests passed!', vim.log.levels.INFO) 59 | end 60 | notify('❌ Tests failed.', vim.log.levels.ERROR) 61 | end, 62 | }) 63 | 64 | vim.b[bufnr].last_cmd = cmd 65 | last_cmd = cmd 66 | vim.cmd.norm({ 'G', bang = true }) 67 | if not is_currently_in_terminal then 68 | vim.cmd.wincmd('p') 69 | end 70 | end 71 | 72 | local function run_file(file_cmd) 73 | local filename = vim.fn.expand('%:.') 74 | 75 | if is_terminal_buf(vim.api.nvim_get_current_buf()) then 76 | return exec(vim.b.last_cmd) 77 | end 78 | 79 | local is_test_file_check = vim.tbl_get(vim.g.test_commands, 'is_test_file') or function() 80 | return true 81 | end 82 | 83 | local is_test_file = is_test_file_check(filename) 84 | 85 | if is_test_file then 86 | return exec(file_cmd:gsub('{file}', vim.fn.fnameescape(filename))) 87 | end 88 | 89 | if last_cmd then 90 | return exec(last_cmd) 91 | end 92 | 93 | return notify('Not a test file') 94 | end 95 | 96 | vim.keymap.set('n', 'xx', function() 97 | local file_cmd = vim.tbl_get(vim.g.test_commands, 'file') 98 | if not file_cmd then 99 | return notify('No test command for file') 100 | end 101 | return run_file(file_cmd) 102 | end, { desc = 'Run test file' }) 103 | 104 | vim.keymap.set('n', 'xw', function() 105 | local watch_cmd = vim.tbl_get(vim.g.test_commands, 'watch') 106 | if not watch_cmd then 107 | return notify('No test command for watch') 108 | end 109 | return run_file(watch_cmd) 110 | end, { desc = 'Watch test file' }) 111 | 112 | vim.keymap.set('n', 'xi', function() 113 | local single_test = vim.tbl_get(vim.g.test_commands, 'single_test') 114 | if not single_test then 115 | return notify('No test command for single test') 116 | end 117 | 118 | local cmd = single_test 119 | if type(single_test) == 'function' then 120 | cmd = single_test() 121 | end 122 | 123 | if not cmd then 124 | return notify('No tests found for single test') 125 | end 126 | 127 | return run_file(cmd) 128 | end, { desc = 'Run single test' }) 129 | 130 | vim.keymap.set('n', 'xt', function() 131 | local all_cmd = vim.tbl_get(vim.g.test_commands, 'all') 132 | if not all_cmd then 133 | return notify('No test command for all tests') 134 | end 135 | return exec(all_cmd) 136 | end, { desc = 'Run all tests' }) 137 | 138 | vim.keymap.set('n', 'xf', function() 139 | local bufnr, win_id = get_terminal_bufnr() 140 | if not bufnr then 141 | return 142 | end 143 | vim.api.nvim_win_set_config(win_id, { hide = false }) 144 | if vim.api.nvim_get_current_buf() == bufnr then 145 | return vim.cmd.wincmd('p') 146 | end 147 | vim.api.nvim_set_current_win(win_id) 148 | end, { desc = 'Focus test window' }) 149 | 150 | vim.keymap.set('n', 'X', function() 151 | local bufnr, winid = get_terminal_bufnr() 152 | if not bufnr then 153 | return 154 | end 155 | local config = vim.api.nvim_win_get_config(winid) 156 | vim.api.nvim_win_set_config(winid, { hide = not config.hide }) 157 | if vim.api.nvim_get_current_buf() == bufnr then 158 | vim.cmd('wincmd p') 159 | end 160 | end, { desc = 'Focus test window' }) 161 | 162 | vim.api.nvim_create_autocmd('VimResized', { 163 | group = augroup, 164 | callback = function() 165 | local bufnr, win = get_terminal_bufnr() 166 | if not bufnr then 167 | return 168 | end 169 | local config = vim.api.nvim_win_get_config(win) 170 | 171 | if config.hide then 172 | return 173 | end 174 | 175 | vim.api.nvim_win_set_config(win, win_config()) 176 | end, 177 | }) 178 | -------------------------------------------------------------------------------- /rofi/config.rasi: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * Author : Aditya Shakya (adi1090x) 4 | * Github : @adi1090x 5 | * 6 | * Configuration For Rofi Version: 1.7.3 7 | **/ 8 | 9 | configuration { 10 | /*---------- General setting ----------*/ 11 | modi: "drun,run,filebrowser,window"; 12 | case-sensitive: false; 13 | cycle: true; 14 | filter: ""; 15 | scroll-method: 0; 16 | normalize-match: true; 17 | show-icons: true; 18 | icon-theme: "Papirus"; 19 | /* cache-dir: ;*/ 20 | steal-focus: false; 21 | /* dpi: -1;*/ 22 | 23 | /*---------- Matching setting ----------*/ 24 | matching: "normal"; 25 | tokenize: true; 26 | 27 | /*---------- SSH settings ----------*/ 28 | ssh-client: "ssh"; 29 | ssh-command: "{terminal} -e {ssh-client} {host} [-p {port}]"; 30 | parse-hosts: true; 31 | parse-known-hosts: true; 32 | 33 | /*---------- Drun settings ----------*/ 34 | drun-categories: ""; 35 | drun-match-fields: "name,generic,exec,categories,keywords"; 36 | drun-display-format: "{name} [({generic})]"; 37 | drun-show-actions: false; 38 | drun-url-launcher: "xdg-open"; 39 | drun-use-desktop-cache: false; 40 | drun-reload-desktop-cache: false; 41 | drun { 42 | /** Parse user desktop files. */ 43 | parse-user: true; 44 | /** Parse system desktop files. */ 45 | parse-system: true; 46 | } 47 | 48 | /*---------- Run settings ----------*/ 49 | run-command: "{cmd}"; 50 | run-list-command: ""; 51 | run-shell-command: "{terminal} -e {cmd}"; 52 | 53 | /*---------- Window switcher settings ----------*/ 54 | window-match-fields: "title,class,role,name,desktop"; 55 | window-command: "wmctrl -i -R {window}"; 56 | window-format: "{w} - {c} - {t:0}"; 57 | window-thumbnail: false; 58 | 59 | /*---------- Combi settings ----------*/ 60 | /* combi-modi: "window,run";*/ 61 | /* combi-hide-mode-prefix: false;*/ 62 | /* combi-display-format: "{mode} {text}";*/ 63 | 64 | /*---------- History and Sorting ----------*/ 65 | disable-history: false; 66 | sorting-method: "normal"; 67 | max-history-size: 25; 68 | 69 | /*---------- Display setting ----------*/ 70 | display-window: "Windows"; 71 | display-windowcd: "Window CD"; 72 | display-run: "Run"; 73 | display-ssh: "SSH"; 74 | display-drun: "Apps"; 75 | display-combi: "Combi"; 76 | display-keys: "Keys"; 77 | display-filebrowser: "Files"; 78 | 79 | /*---------- Misc setting ----------*/ 80 | terminal: "rofi-sensible-terminal"; 81 | font: "Mono 12"; 82 | sort: false; 83 | threads: 0; 84 | click-to-exit: true; 85 | /* ignored-prefixes: "";*/ 86 | /* pid: "/run/user/1000/rofi.pid";*/ 87 | 88 | /*---------- File browser settings ----------*/ 89 | filebrowser { 90 | /* directory: "/home";*/ 91 | directories-first: true; 92 | sorting-method: "name"; 93 | } 94 | 95 | /*---------- Other settings ----------*/ 96 | timeout { 97 | action: "kb-cancel"; 98 | delay: 0; 99 | } 100 | 101 | /*---------- Keybindings ----------*/ 102 | /* 103 | kb-primary-paste: "Control+V,Shift+Insert"; 104 | kb-secondary-paste: "Control+v,Insert"; 105 | kb-clear-line: "Control+w"; 106 | kb-move-front: "Control+a"; 107 | kb-move-end: "Control+e"; 108 | kb-move-word-back: "Alt+b,Control+Left"; 109 | kb-move-word-forward: "Alt+f,Control+Right"; 110 | kb-move-char-back: "Left,Control+b"; 111 | kb-move-char-forward: "Right,Control+f"; 112 | kb-remove-word-back: "Control+Alt+h,Control+BackSpace"; 113 | kb-remove-word-forward: "Control+Alt+d"; 114 | kb-remove-char-forward: "Delete,Control+d"; 115 | kb-remove-char-back: "BackSpace,Shift+BackSpace,Control+h"; 116 | kb-remove-to-eol: "Control+k"; 117 | kb-remove-to-sol: "Control+u"; 118 | kb-accept-entry: "Control+j,Control+m,Return,KP_Enter"; 119 | kb-accept-custom: "Control+Return"; 120 | kb-accept-custom-alt: "Control+Shift+Return"; 121 | kb-accept-alt: "Shift+Return"; 122 | kb-delete-entry: "Shift+Delete"; 123 | kb-mode-next: "Shift+Right,Control+Tab"; 124 | kb-mode-previous: "Shift+Left,Control+ISO_Left_Tab"; 125 | kb-mode-complete: "Control+l"; 126 | kb-row-left: "Control+Page_Up"; 127 | kb-row-right: "Control+Page_Down"; 128 | kb-row-down: "Down,Control+n"; 129 | kb-page-prev: "Page_Up"; 130 | kb-page-next: "Page_Down"; 131 | kb-row-first: "Home,KP_Home"; 132 | kb-row-last: "End,KP_End"; 133 | kb-row-select: "Control+space"; 134 | kb-screenshot: "Alt+S"; 135 | kb-ellipsize: "Alt+period"; 136 | kb-toggle-case-sensitivity: "grave,dead_grave"; 137 | kb-toggle-sort: "Alt+grave"; 138 | kb-cancel: "Escape,Control+g,Control+bracketleft"; 139 | kb-custom-1: "Alt+1"; 140 | kb-custom-2: "Alt+2"; 141 | kb-custom-3: "Alt+3"; 142 | kb-custom-4: "Alt+4"; 143 | kb-custom-5: "Alt+5"; 144 | kb-custom-6: "Alt+6"; 145 | kb-custom-7: "Alt+7"; 146 | kb-custom-8: "Alt+8"; 147 | kb-custom-9: "Alt+9"; 148 | kb-custom-10: "Alt+0"; 149 | kb-custom-11: "Alt+exclam"; 150 | kb-custom-12: "Alt+at"; 151 | kb-custom-13: "Alt+numbersign"; 152 | kb-custom-14: "Alt+dollar"; 153 | kb-custom-15: "Alt+percent"; 154 | kb-custom-16: "Alt+dead_circumflex"; 155 | kb-custom-17: "Alt+ampersand"; 156 | kb-custom-18: "Alt+asterisk"; 157 | kb-custom-19: "Alt+parenleft"; 158 | kb-select-1: "Super+1"; 159 | kb-select-2: "Super+2"; 160 | kb-select-3: "Super+3"; 161 | kb-select-4: "Super+4"; 162 | kb-select-5: "Super+5"; 163 | kb-select-6: "Super+6"; 164 | kb-select-7: "Super+7"; 165 | kb-select-8: "Super+8"; 166 | kb-select-9: "Super+9"; 167 | kb-select-10: "Super+0"; 168 | ml-row-left: "ScrollLeft"; 169 | ml-row-right: "ScrollRight"; 170 | ml-row-up: "ScrollUp"; 171 | ml-row-down: "ScrollDown"; 172 | me-select-entry: "MousePrimary"; 173 | me-accept-entry: "MouseDPrimary"; 174 | me-accept-custom: "Control+MouseDPrimary"; 175 | */ 176 | } 177 | -------------------------------------------------------------------------------- /hypr/hyprland.conf: -------------------------------------------------------------------------------- 1 | # Use alt as mod 2 | $mod = ALT 3 | 4 | # General settings 5 | general { 6 | border_size = 2 7 | gaps_in = 4 8 | gaps_out = 4 9 | layout = hy3 10 | no_border_on_floating = true 11 | col.active_border = rgba(00ffffff) 12 | } 13 | 14 | # Language configuration 15 | input { 16 | kb_layout = us,rs(latin) 17 | kb_options = grp:lctrl_lwin_toggle 18 | repeat_delay = 350 19 | repeat_rate = 60 20 | follow_mouse = 2 21 | } 22 | 23 | # Disable animations 24 | animations { 25 | enabled = false 26 | } 27 | 28 | # Window decoration 29 | decoration { 30 | rounding = 6 31 | active_opacity = 1.0 32 | inactive_opacity = 1.0 33 | fullscreen_opacity = 1.0 34 | } 35 | 36 | plugin { 37 | hy3 { 38 | no_gaps_when_only = 1 39 | 40 | tabs { 41 | blur = false 42 | border_width = 1 43 | col.active = rgba(222436ff) 44 | col.active.border = rgba(00ffffff) 45 | col.active.text = rgba(c8d3f5ff) 46 | col.inactive = rgba(222436ff) 47 | col.inactive.border = rgba(222436ff) 48 | col.inactive.text = rgba(c8d3f5ff) 49 | col.focused = rgba(222436ff) 50 | col.focused.border = rgba(00ffffff) 51 | col.focused.text = rgba(c8d3f5ff) 52 | col.focused = rgba(ff0000ff) 53 | col.focused.border = rgba(00ffffff) 54 | col.focused.text = rgba(c8d3f5ff) 55 | } 56 | } 57 | 58 | autotile { 59 | enable = true 60 | } 61 | } 62 | 63 | # Output config 64 | monitor=DP-1,3440x1440@144,0x0,1 65 | 66 | # Exit fullscreen on new window and focus 67 | misc:new_window_takes_over_fullscreen = 2 68 | 69 | # Startup applications 70 | exec-once = hyprpm reload -n 71 | exec-once = hypridle 72 | exec-once = /usr/lib/polkit-gnome/polkit-gnome-authentication-agent-1 73 | exec-once = nm-applet 74 | exec-once = swaync 75 | exec-once = waypaper --restore 76 | exec-once = dropbox 77 | exec-once = google-chrome-stable 78 | exec-once = kitty 79 | exec-once = ~/.config/waybar/start.sh 80 | 81 | # QT Theme 82 | env = QT_QPA_PLATFORMTHEME,qt5ct 83 | env = QT_STYLE_OVERRIDE,Adwaita-dark 84 | 85 | # Keybindings 86 | bind = $mod,Return,exec,kitty 87 | bind = $mod,b,exec,google-chrome-stable 88 | bind = $mod,d,exec,~/.config/rofi/launch.sh 89 | 90 | # Reload and exit hyprland 91 | bind = $mod+SHIFT,e,exec,zenity --question --text="Do you really want to exit Hyprland?" && hyprctl dispatch exit 92 | bind = $mod+SHIFT,c,exec,hyprctl reload 93 | 94 | # Layout switch 95 | bind = $mod,w,hy3:changegroup,tab 96 | bind = $mod,e,hy3:changegroup,untab 97 | bind = $mod,n,exec,notify-send "Tile vertically" 98 | bind = $mod,n,hy3:makegroup,h,toggle 99 | bind = $mod,o,exec,notify-send "Tile horizontally" 100 | bind = $mod,o,hy3:makegroup,v,toggle 101 | 102 | # Workspace/window mappings 103 | bind = $mod,q,hy3:killactive 104 | bind = $mod,f,fullscreenstate, 1 105 | bind = $mod,h,hy3:movefocus,l 106 | bind = $mod,j,hy3:movefocus,d 107 | bind = $mod,k,hy3:movefocus,u 108 | bind = $mod,l,hy3:movefocus,r 109 | bind = $mod,left,hy3:movefocus,l 110 | bind = $mod,down,hy3:movefocus,d 111 | bind = $mod,up,hy3:movefocus,u 112 | bind = $mod,right,hy3:movefocus,r 113 | bind = $mod+SHIFT,h,hy3:movewindow,l 114 | bind = $mod+SHIFT,j,hy3:movewindow,d 115 | bind = $mod+SHIFT,k,hy3:movewindow,u 116 | bind = $mod+SHIFT,l,hy3:movewindow,r 117 | bind = $mod+SHIFT,left,hy3:movewindow,l 118 | bind = $mod+SHIFT,down,hy3:movewindow,d 119 | bind = $mod+SHIFT,up,hy3:movewindow,u 120 | bind = $mod+SHIFT,right,hy3:movewindow,r 121 | bind = $mod,1,workspace,1 122 | bind = $mod,2,workspace,2 123 | bind = $mod,3,workspace,3 124 | bind = $mod,4,workspace,4 125 | bind = $mod,5,workspace,5 126 | bind = $mod,6,workspace,6 127 | bind = $mod,7,workspace,7 128 | bind = $mod,8,workspace,8 129 | bind = $mod,9,workspace,9 130 | bind = $mod+SHIFT,1,hy3:movetoworkspace,1 131 | bind = $mod+SHIFT,2,hy3:movetoworkspace,2 132 | bind = $mod+SHIFT,3,hy3:movetoworkspace,3 133 | bind = $mod+SHIFT,4,hy3:movetoworkspace,4 134 | bind = $mod+SHIFT,5,hy3:movetoworkspace,5 135 | bind = $mod+SHIFT,6,hy3:movetoworkspace,6 136 | bind = $mod+SHIFT,7,hy3:movetoworkspace,7 137 | bind = $mod+SHIFT,8,hy3:movetoworkspace,8 138 | bind = $mod+SHIFT,9,hy3:movetoworkspace,9 139 | 140 | bindm=$mod,mouse:272,movewindow 141 | bindm=$mod,mouse:273,resizewindow 142 | 143 | # Screenshot bindings 144 | bind = ,Print,exec,sh -c 'sleep 0.2 && grim -g "$(slurp)" ~/Pictures/screenshots/screenshot_$(date +%Y_%m_%d_%H_%M_%S).png' 145 | 146 | # Resize mode (Hyprland uses resizeactive) 147 | bind = $mod,r,submap,resize 148 | submap=resize 149 | bind = ,h,resizeactive,-20 0 150 | bind = ,j,resizeactive,0 20 151 | bind = ,k,resizeactive,0 -20 152 | bind = ,l,resizeactive,20 0 153 | bind = ,Return,submap,reset 154 | bind = ,Escape,submap,reset 155 | submap=reset 156 | 157 | # Lock screen 158 | bind = CTRL+$mod,l,exec,hyprlock 159 | 160 | # Record screen 161 | bind = $mod+CTRL,r,exec,~/.config/hypr/record_screen.sh --start 162 | bind = $mod+CTRL,s,exec,~/.config/hypr/record_screen.sh --stop 163 | 164 | # Floating rules 165 | windowrule = float,class:^(org.gnome.Calculator)$ 166 | windowrule = float,class:^(google-chrome)$,title:^(Save File)$ 167 | windowrule = float,class:^(Thunar)$,title:^(Rename.*)$ 168 | windowrule = float,class:^(Thunar)$,title:^(File Operation Progress)$ 169 | 170 | #Viber notification configuration 171 | windowrule = float,title:^(ViberPC)$ 172 | windowrule = noinitialfocus,title:^(ViberPC)$ 173 | windowrule = pin,title:^(ViberPC)$ 174 | windowrule = move onscreen 100% 100%,title:^(ViberPC)$ 175 | 176 | windowrule = stayfocused,class:^(rofi)$ 177 | 178 | # Assign apps to workspaces 179 | windowrule = workspace 2, class:^(google-chrome|firefox|Brave-browser)$ 180 | windowrule = workspace 4, class:Slack 181 | windowrule = workspace 6, class:com.viber.Viber 182 | -------------------------------------------------------------------------------- /nvim/lua/partials/settings.lua: -------------------------------------------------------------------------------- 1 | local settings = {} 2 | 3 | _G.kris.diagnostic_icons = { 4 | [vim.diagnostic.severity.ERROR] = ' ', 5 | [vim.diagnostic.severity.WARN] = ' ', 6 | [vim.diagnostic.severity.INFO] = ' ', 7 | [vim.diagnostic.severity.HINT] = ' ', 8 | } 9 | 10 | vim.g.mapleader = ',' 11 | vim.opt.termguicolors = true 12 | vim.opt.title = true 13 | vim.opt.number = true 14 | vim.opt.relativenumber = true 15 | vim.opt.showmode = false 16 | vim.opt.gdefault = true 17 | vim.opt.cursorline = true 18 | vim.opt.smartcase = true 19 | vim.opt.ignorecase = true 20 | vim.opt.mouse = 'a' 21 | vim.opt.showmatch = true 22 | vim.opt.startofline = false 23 | vim.opt.timeoutlen = 1000 24 | vim.opt.ttimeoutlen = 0 25 | vim.opt.fileencoding = 'utf-8' 26 | vim.opt.wrap = false 27 | vim.opt.linebreak = true 28 | vim.opt.guicursor:append('a:blinkon500-blinkoff100') 29 | vim.opt.listchars = { 30 | tab = '▏ ', 31 | trail = '·', 32 | } 33 | vim.opt.list = true 34 | vim.opt.hidden = true 35 | vim.opt.conceallevel = 2 36 | vim.opt.concealcursor = 'nc' 37 | vim.opt.splitright = true 38 | vim.opt.splitbelow = true 39 | vim.opt.inccommand = 'nosplit' 40 | vim.opt.exrc = true 41 | vim.opt.grepprg = 'rg --smart-case --color=never --no-heading -H -n --column' 42 | vim.opt.tagcase = 'smart' 43 | vim.opt.updatetime = 100 44 | vim.opt.foldenable = false 45 | vim.opt.shortmess:append('c') 46 | vim.opt.undofile = true 47 | vim.opt.swapfile = false 48 | vim.opt.backup = false 49 | vim.opt.writebackup = false 50 | vim.opt.fillchars = 'fold: ,vert:│' 51 | vim.opt.breakindent = true 52 | vim.opt.smartindent = true 53 | vim.opt.expandtab = true 54 | vim.opt.shiftwidth = 2 55 | vim.opt.shiftround = true 56 | vim.opt.diffopt:append('vertical') 57 | vim.opt.scrolloff = 8 58 | vim.opt.sidescrolloff = 15 59 | vim.opt.sidescroll = 5 60 | vim.opt.pyxversion = 3 61 | vim.opt.matchtime = 0 62 | vim.g.python3_host_prog = '/usr/bin/python3' 63 | vim.opt.splitkeep = 'screen' 64 | vim.opt.diffopt:append('linematch:60') 65 | vim.opt.completeopt = { 'menu', 'menuone', 'noinsert', 'noselect', 'popup' } 66 | vim.opt.pumheight = 10 67 | if vim.fn.exists('&completeitemalign') > 0 then 68 | vim.opt.completeitemalign = { 'kind', 'abbr', 'menu' } 69 | end 70 | 71 | if vim.fn.has('nvim-0.11') > 0 then 72 | vim.opt.completeopt:append({ 'fuzzy' }) 73 | end 74 | 75 | if vim.fn.has('nvim-0.12') > 0 then 76 | vim.opt.pummaxwidth = 60 77 | end 78 | 79 | function settings.strip_trailing_whitespace() 80 | local editorconfig = vim.b.editorconfig or {} 81 | -- Handled by editorconfig 82 | if editorconfig.trim_trailing_whitespace then 83 | return 84 | end 85 | if vim.bo.modifiable and vim.bo.modified then 86 | local line = vim.fn.line('.') 87 | local col = vim.fn.col('.') 88 | vim.cmd([[%s/\s\+$//e]]) 89 | vim.fn.histdel('/', -1) 90 | vim.fn.cursor({ line, col }) 91 | end 92 | end 93 | 94 | vim.opt.wildignore = { 95 | '*.o', 96 | '*.obj,*~', 97 | '*.git*', 98 | '*.meteor*', 99 | '*vim/backups*', 100 | '*sass-cache*', 101 | '*mypy_cache*', 102 | '*__pycache__*', 103 | '*cache*', 104 | '*logs*', 105 | '*node_modules*', 106 | '**/node_modules/**', 107 | '*DS_Store*', 108 | '*.gem', 109 | 'log/**', 110 | 'tmp/**', 111 | '*package-lock.json*', 112 | '**/dist/**', 113 | '**/.next/**', 114 | '**/.nx/**', 115 | } 116 | 117 | local cwd = vim.fn.getcwd() 118 | local handle = vim.loop.fs_scandir(cwd) 119 | if type(handle) == 'string' then 120 | return 121 | end 122 | local paths = {} 123 | while true do 124 | local name, t = vim.loop.fs_scandir_next(handle) 125 | if not name then 126 | break 127 | end 128 | if t == 'directory' and not vim.o.wildignore:find(name) then 129 | table.insert(paths, name .. '/**') 130 | end 131 | end 132 | 133 | vim.o.path = vim.o.path .. table.concat(paths, ',') 134 | 135 | local vimrc_group = vim.api.nvim_create_augroup('vimrc', { clear = true }) 136 | vim.api.nvim_create_autocmd('VimResized', { 137 | group = vimrc_group, 138 | command = 'wincmd =', 139 | }) 140 | vim.api.nvim_create_autocmd('BufReadPost', { 141 | group = vimrc_group, 142 | callback = function(args) 143 | local mark = vim.api.nvim_buf_get_mark(args.buf, '"') 144 | local line_count = vim.api.nvim_buf_line_count(args.buf) 145 | if mark[1] > 0 and mark[1] <= line_count then 146 | vim.cmd('normal! g`"zz') 147 | end 148 | end, 149 | }) 150 | vim.api.nvim_create_autocmd('BufWritePre', { 151 | pattern = '*', 152 | callback = settings.strip_trailing_whitespace, 153 | group = vimrc_group, 154 | }) 155 | vim.api.nvim_create_autocmd('InsertEnter', { 156 | pattern = '*', 157 | command = 'set nocul', 158 | group = vimrc_group, 159 | }) 160 | vim.api.nvim_create_autocmd({ 'InsertLeave', 'BufEnter' }, { 161 | pattern = '*', 162 | command = 'set cul', 163 | group = vimrc_group, 164 | }) 165 | vim.api.nvim_create_autocmd({ 'FocusGained', 'BufEnter' }, { 166 | pattern = '*', 167 | command = [[silent! exe 'checktime']], 168 | group = vimrc_group, 169 | }) 170 | vim.api.nvim_create_autocmd('FileType', { 171 | pattern = 'markdown', 172 | command = 'setlocal spell', 173 | group = vimrc_group, 174 | }) 175 | vim.api.nvim_create_autocmd('FileType', { 176 | pattern = 'json', 177 | command = [[setlocal conceallevel=0 formatprg=python\ -m\ json.tool]], 178 | group = vimrc_group, 179 | }) 180 | vim.api.nvim_create_autocmd('TermOpen', { 181 | pattern = '*', 182 | command = [[setlocal nonumber norelativenumber]], 183 | group = vimrc_group, 184 | }) 185 | vim.api.nvim_create_autocmd({ 'BufEnter', 'FocusGained', 'InsertLeave', 'WinEnter' }, { 186 | pattern = '*', 187 | command = [[if &nu | set rnu | endif]], 188 | group = vimrc_group, 189 | }) 190 | vim.api.nvim_create_autocmd({ 'BufLeave', 'FocusLost', 'InsertEnter', 'WinLeave' }, { 191 | pattern = '*', 192 | command = [[if &nu | set nornu | endif]], 193 | group = vimrc_group, 194 | }) 195 | 196 | vim.filetype.add({ 197 | pattern = { 198 | ['.env*'] = 'conf', 199 | ['*.mjml'] = 'html', 200 | ['.*waybar/config'] = 'jsonc', 201 | }, 202 | }) 203 | 204 | return settings 205 | -------------------------------------------------------------------------------- /zsh/zshrc: -------------------------------------------------------------------------------- 1 | # Enable Powerlevel10k instant prompt. Should stay close to the top of ~/.zshrc. 2 | # Initialization code that may require console input (password prompts, [y/n] 3 | # confirmations, etc.) must go above this block; everything else may go below. 4 | if [[ -r "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh" ]]; then 5 | source "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh" 6 | fi 7 | 8 | # Path to your oh-my-zsh configuration. 9 | ZSH=$HOME/.oh-my-zsh 10 | 11 | ZSH_THEME="powerlevel10k/powerlevel10k" 12 | 13 | plugins=( 14 | git 15 | zsh-autosuggestions 16 | docker-compose 17 | z 18 | zsh-syntax-highlighting 19 | history-substring-search 20 | command-not-found 21 | copypath 22 | copyfile 23 | dircycle 24 | vi-mode 25 | jira 26 | ) 27 | 28 | ENABLE_CORRECTION="true" 29 | 30 | autoload -U compinit; compinit 31 | source ~/.oh-my-zsh/custom/plugins/fzf-tab/fzf-tab.plugin.zsh 32 | 33 | source $ZSH/oh-my-zsh.sh 34 | . ~/z.sh 35 | 36 | if [[ -r ~/.phpbrew/bashrc ]]; then 37 | source ~/.phpbrew/bashrc 38 | fi 39 | 40 | alias n='nvim' 41 | alias dc='docker compose' 42 | alias install='sudo pacman -S' 43 | alias search='sudo pacman -Ss' 44 | alias remove='sudo pacman -R' 45 | alias update='sudo pacman -Sy' 46 | alias yinstall='yay -S' 47 | alias ysearch='yay -Ss' 48 | alias yremove='yay -R' 49 | alias yupdate='yay -Sy' 50 | alias l="ls -l" 51 | alias c="clear" 52 | alias code="cd ~/code" 53 | alias lg="lazygit" 54 | alias resetbg="colors" 55 | alias togglebg="colors toggle" 56 | alias cdroot='cd $(git rev-parse --show-toplevel)' 57 | alias ggf=ggfl 58 | alias cpuavailablemodes='cat /sys/devices/system/cpu/cpu*/cpufreq/scaling_available_governors' 59 | alias cpucurrentmode='cat /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor' 60 | alias cpusetperformance='echo performance | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor' 61 | alias cpusetpowersave='echo powersave | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor' 62 | 63 | export PATH=$PATH:/usr/local/go/bin:~/go/bin:~/.local/bin:~/.cargo/bin:~/.local/share/bob/nvim-bin:~/.local/share/neovim/bin:/home/kristijan/.meteor:~/.yarn/bin:~/.luarocks/bin:~/.config/composer/vendor/bin 64 | export LESS=R 65 | export EDITOR=nvim 66 | export MANPAGER="nvim +Man!" 67 | export FZF_DEFAULT_COMMAND='fd --type f --follow' 68 | export LESS=R 69 | export HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_FOUND="fg=magenta,bold,underline" 70 | export GOPATH=$HOME/go 71 | setopt HIST_IGNORE_ALL_DUPS 72 | 73 | # use ctrl+t to toggle autosuggestions(hopefully this wont be needed as 74 | # zsh-autosuggestions is designed to be unobtrusive) 75 | NVIM_BG=${NVIM_COLORSCHEME_BG:-'light'} 76 | export BAT_THEME="ansi" 77 | export KEYTIMEOUT=1 78 | export ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE='fg=248' 79 | 80 | [ -f ~/.zsh_secret ] && source ~/.zsh_secret 81 | 82 | eval "$(fnm env)" 83 | 84 | eval $(keychain --eval --quiet ~/.ssh/id_rsa) 85 | 86 | bindkey '^[[Z' reverse-menu-complete # Use shift tab for backward autocompletion 87 | 88 | zle -N zle-line-init 89 | zle -N zle-line-finish 90 | zle -N zle-keymap-select 91 | 92 | ### Bind up and down keys for history-substring-search plugin 93 | bindkey '^[[A' history-substring-search-up 94 | bindkey '^[[B' history-substring-search-down 95 | bindkey '^k' history-substring-search-up 96 | bindkey '^j' history-substring-search-down 97 | bindkey '^X^E' edit-command-line 98 | 99 | ### Fix slowness of pastes with zsh-syntax-highlighting.zsh 100 | ### Source: https://gist.github.com/magicdude4eva/2d4748f8ef3e6bf7b1591964c201c1ab 101 | pasteinit() { 102 | OLD_SELF_INSERT=${${(s.:.)widgets[self-insert]}[2,3]} 103 | zle -N self-insert url-quote-magic # I wonder if you'd need `.url-quote-magic`? 104 | } 105 | 106 | pastefinish() { 107 | zle -N self-insert $OLD_SELF_INSERT 108 | } 109 | zstyle :bracketed-paste-magic paste-init pasteinit 110 | zstyle :bracketed-paste-magic paste-finish pastefinish 111 | ### Fix slowness of pastes 112 | 113 | ### Custom FZF functions 114 | ### @see: https://github.com/junegunn/fzf/wiki/examples 115 | # Open link from Chrome history 116 | chr() { 117 | local cols sep google_history 118 | cols=$(( COLUMNS / 3 )) 119 | sep='{::}' 120 | google_history="$HOME/.config/google-chrome/Default/History" 121 | 122 | cp -f "$google_history" /tmp/h 123 | sqlite3 -separator $sep /tmp/h \ 124 | "select substr(title, 1, $cols), url 125 | from urls order by last_visit_time desc" | 126 | awk -F $sep '{printf "%-'$cols's \x1b[36m%s\x1b[m\n", $1, $2}' | 127 | fzf --ansi --multi | sed 's#.*\(https*://\)#\1#' | xargs xdg-open > /dev/null 2> /dev/null 128 | } 129 | 130 | # fbr - checkout git branch (including remote branches) 131 | fbr() { 132 | local branches branch 133 | branches=$(git branch --all | grep -v HEAD) && 134 | branch=$(echo "$branches" | 135 | fzf -d $(( 2 + $(wc -l <<< "$branches") )) +m) && 136 | git checkout $(echo "$branch" | sed "s/.* //" | sed "s#remotes/[^/]*/##") 137 | } 138 | 139 | fst() { 140 | local files file 141 | files=$(git status --porcelain -u) && 142 | file=$(echo "$files" | 143 | fzf -d $(( 2 + $(wc -l <<< "$files") )) +m) && 144 | nvim $(echo $file | sed "s/^...//") 145 | } 146 | 147 | colors() { 148 | color_vars=$(~/neovim-config/colors $1) 149 | eval ${color_vars} 150 | } 151 | 152 | git_patch() { 153 | xclip -selection clipboard -o|git apply --ignore-whitespace 154 | } 155 | 156 | nt() { 157 | nvim -c "autocmd BufEnter * only" -c "lua require('orgmode').capture:open_template_by_shortcut('r')" 158 | } 159 | 160 | remove_gone_branches() { 161 | git fetch -p && for branch in $(git branch -vv | grep ': gone]' | awk '{print $1}'); do git branch -D $branch; done 162 | } 163 | 164 | # Autocomplete Z items 165 | unalias z 2> /dev/null 166 | z() { 167 | [ $# -gt 0 ] && _z "$*" && return 168 | cd "$(_z -l 2>&1 | fzf --height 40% --nth 2.. --reverse --inline-info +s --tac --query "${*##-* }" | sed 's/^[0-9,.]* *//')" 169 | } 170 | 171 | [[ $- == *i* ]] && source "/usr/share/fzf/completion.zsh" 2> /dev/null 172 | source "/usr/share/fzf/key-bindings.zsh" 173 | 174 | source ~/.oh-my-zsh/custom/plugins/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh 175 | source ~/.p10k.zsh 176 | -------------------------------------------------------------------------------- /sway/config: -------------------------------------------------------------------------------- 1 | # Set mod key (Mod1=, Mod4=) 2 | set $mod Mod1 3 | 4 | # Configure border style 5 | default_border pixel 2 6 | default_floating_border normal 7 | 8 | # Hide borders 9 | hide_edge_borders none 10 | 11 | # Font for window titles. Will also be used by the bar unless a different font 12 | # is used in the bar {} block below. 13 | font xft:URWGothic-Book 8 14 | 15 | # Use Mouse+$mod to drag floating windows 16 | floating_modifier $mod 17 | 18 | # start a terminal 19 | bindsym $mod+Return exec kitty 20 | 21 | # open a browser 22 | bindsym $mod+b exec google-chrome-stable 23 | 24 | bindsym $mod+equal resize grow width 1 px or 1 ppt 25 | bindsym $mod+minus resize shrink width 1 px or 1 ppt 26 | 27 | # kill focused window 28 | bindsym $mod+q kill 29 | 30 | # start program launcher 31 | bindsym $mod+d exec "~/.config/rofi/launch.sh" 32 | 33 | output DP-1 { 34 | mode 3440x1440@144Hz 35 | } 36 | 37 | ################################################################################################ 38 | ## sound-section - DO NOT EDIT if you wish to automatically upgrade Alsa -> Pulseaudio later! ## 39 | ################################################################################################ 40 | 41 | # Screen brightness controls 42 | # bindsym XF86MonBrightnessUp exec "xbacklight -inc 10; notify-send 'brightness up'" 43 | # bindsym XF86MonBrightnessDown exec "xbacklight -dec 10; notify-send 'brightness down'" 44 | 45 | # Start Applications 46 | bindsym Ctrl+Print exec imgur-screenshot 47 | bindsym Ctrl+Shift+Print exec "sleep 0.2 && grim -g \"$(slurp)\" ~/Pictures/screenshots/screenshot_$(date +%Y_%m_%d_%H_%M_%S).png" 48 | 49 | focus_follows_mouse no 50 | 51 | # change focus 52 | bindsym $mod+h focus left 53 | bindsym $mod+j focus down 54 | bindsym $mod+k focus up 55 | bindsym $mod+l focus right 56 | 57 | # move focused window 58 | bindsym $mod+Shift+h move left 59 | bindsym $mod+Shift+j move down 60 | bindsym $mod+Shift+k move up 61 | bindsym $mod+Shift+l move right 62 | bindsym $mod+Shift+left move left 63 | bindsym $mod+Shift+down move down 64 | bindsym $mod+Shift+up move up 65 | bindsym $mod+Shift+right move right 66 | 67 | # workspace back and forth (with/without active container) 68 | # workspace_auto_back_and_forth yes 69 | # bindsym $mod+b workspace back_and_forth 70 | # bindsym $mod+Shift+b move container to workspace back_and_forth; workspace back_and_forth 71 | 72 | # split orientation 73 | bindsym $mod+n split h;exec notify-send 'tile horizontally' 74 | bindsym $mod+o split v;exec notify-send 'tile vertically' 75 | 76 | # toggle fullscreen mode for the focused container 77 | bindsym $mod+f fullscreen toggle 78 | 79 | # change container layout (stacked, tabbed, toggle split) 80 | bindsym $mod+s layout stacking 81 | bindsym $mod+w layout tabbed 82 | bindsym $mod+e layout toggle split 83 | 84 | # toggle tiling / floating 85 | bindsym $mod+Shift+space floating toggle 86 | 87 | # change focus between tiling / floating windows 88 | bindsym $mod+space focus mode_toggle 89 | 90 | # toggle sticky 91 | bindsym $mod+Shift+s sticky toggle 92 | 93 | # focus the parent container 94 | bindsym $mod+a focus parent 95 | 96 | #navigate workspaces next / previous 97 | bindsym $mod+Ctrl+Right workspace next 98 | bindsym $mod+Ctrl+Left workspace prev 99 | 100 | # Workspace names 101 | # to display names or symbols instead of plain workspace numbers you can use 102 | # something like: set $ws1 1:mail 103 | # set $ws2 2: 104 | set $ws1 1 105 | set $ws2 2 106 | set $ws3 3 107 | set $ws4 4 108 | set $ws5 5 109 | set $ws6 6 110 | set $ws7 7 111 | set $ws8 8 112 | set $ws9 9 113 | 114 | # switch to workspace 115 | bindsym $mod+1 workspace $ws1 116 | bindsym $mod+2 workspace $ws2 117 | bindsym $mod+3 workspace $ws3 118 | bindsym $mod+4 workspace $ws4 119 | bindsym $mod+5 workspace $ws5 120 | bindsym $mod+6 workspace $ws6 121 | bindsym $mod+7 workspace $ws7 122 | bindsym $mod+8 workspace $ws8 123 | bindsym $mod+9 workspace $ws9 124 | 125 | workspace $ws1 output $output1 126 | workspace $ws2 output $output2 127 | workspace $ws3 output $output1 128 | workspace $ws4 output $output2 129 | workspace $ws5 output $output1 130 | workspace $ws6 output $output2 131 | workspace $ws7 output $output1 132 | workspace $ws8 output $output2 133 | workspace $ws9 output $output1 134 | 135 | # Move focused container to workspace 136 | bindsym $mod+Ctrl+1 move container to workspace $ws1 137 | bindsym $mod+Ctrl+2 move container to workspace $ws2 138 | bindsym $mod+Ctrl+3 move container to workspace $ws3 139 | bindsym $mod+Ctrl+4 move container to workspace $ws4 140 | bindsym $mod+Ctrl+5 move container to workspace $ws5 141 | bindsym $mod+Ctrl+6 move container to workspace $ws6 142 | bindsym $mod+Ctrl+7 move container to workspace $ws7 143 | bindsym $mod+Ctrl+8 move container to workspace $ws8 144 | 145 | # Move to workspace with focused container 146 | bindsym $mod+Shift+1 move container to workspace $ws1; workspace $ws1 147 | bindsym $mod+Shift+2 move container to workspace $ws2; workspace $ws2 148 | bindsym $mod+Shift+3 move container to workspace $ws3; workspace $ws3 149 | bindsym $mod+Shift+4 move container to workspace $ws4; workspace $ws4 150 | bindsym $mod+Shift+5 move container to workspace $ws5; workspace $ws5 151 | bindsym $mod+Shift+6 move container to workspace $ws6; workspace $ws6 152 | bindsym $mod+Shift+7 move container to workspace $ws7; workspace $ws7 153 | bindsym $mod+Shift+8 move container to workspace $ws8; workspace $ws8 154 | 155 | set { 156 | $float floating enable, border none 157 | } 158 | 159 | # Open specific applications in floating mode 160 | for_window [class="^.*"] border pixel 2 161 | for_window [app_id="org.gnome.Calculator"] $float 162 | for_window [title="File Transfer*"] $float 163 | for_window [window_role="pop-up"] $float 164 | for_window [window_role="bubble"] $float 165 | for_window [window_role="dialog"] $float 166 | for_window [window_role="task_dialog"] $float 167 | for_window [window_role="About"] $float 168 | for_window [window_type="dialog"] $float 169 | for_window [window_type="dialog"] $float 170 | for_window [window_type="utility"] $float 171 | for_window [window_type="toolbar"] $float 172 | for_window [window_type="splash"] $float 173 | for_window [window_type="menu"] $float 174 | for_window [window_type="dropdown_menu"] $float 175 | for_window [window_type="popup_menu"] $float 176 | for_window [window_type="tooltip"] $float 177 | for_window [window_type="notification"] $float 178 | for_window [title="(?:Open|Save) (?:File|Folder|As)"] $float 179 | for_window [app_id="com.viber.Viber" floating] move position 90ppt 90ppt, border none 180 | 181 | # switch to workspace with urgent window automatically 182 | for_window [urgent=latest] focus 183 | 184 | # reload the configuration file 185 | bindsym $mod+Shift+c reload 186 | 187 | bindsym $mod+Shift+r restart 188 | 189 | # exit sway (logs you out of your X session) 190 | bindsym $mod+Shift+e exec "swaynag -t warning -m 'You pressed the exit shortcut. Do you really want to exit sway? This will end your Wayland session.' -b 'Yes, exit sway' 'swaymsg exit'" 191 | 192 | # Resize window (you can also use the mouse for that) 193 | bindsym $mod+r mode "resize" 194 | mode "resize" { 195 | # These bindings trigger as soon as you enter the resize mode 196 | # Pressing left will shrink the window’s width. 197 | # Pressing right will grow the window’s width. 198 | # Pressing up will shrink the window’s height. 199 | # Pressing down will grow the window’s height. 200 | bindsym h resize shrink width 5 px or 5 ppt 201 | bindsym j resize grow height 5 px or 5 ppt 202 | bindsym k resize shrink height 5 px or 5 ppt 203 | bindsym l resize grow width 5 px or 5 ppt 204 | 205 | # same bindings, but for the arrow keys 206 | bindsym Left resize shrink width 10 px or 10 ppt 207 | bindsym Down resize grow height 10 px or 10 ppt 208 | bindsym Up resize shrink height 10 px or 10 ppt 209 | bindsym Right resize grow width 10 px or 10 ppt 210 | 211 | # exit resize mode: Enter or Escape 212 | bindsym Return mode "default" 213 | bindsym Escape mode "default" 214 | } 215 | 216 | # Lock screen 217 | bindsym Control+$mod+l exec swaylock -c 000000 218 | 219 | # Autostart applications 220 | exec /usr/lib/polkit-gnome/polkit-gnome-authentication-agent-1 221 | exec nitrogen --restore 222 | #exec manjaro-hello 223 | exec nm-applet 224 | exec xfce4-power-manager 225 | exec dropbox 226 | exec swaync 227 | exec google-chrome-stable 228 | exec swaymsg workspace 1; exec kitty 229 | exec swayidle -w timeout 1200 'swaylock -c 000000' 230 | exec /usr/lib/polkit-gnome/polkit-gnome-authentication-agent-1 231 | exec ~/.config/sway/auto_exit_fullscreen.sh 232 | exec ~/.azotebg 233 | exec_always ~/.config/waybar/start.sh 234 | 235 | 236 | set $qt_theme Adwaita-dark 237 | exec_always --no-startup-id env QT_QPA_PLATFORMTHEME=qt5ct QT_STYLE_OVERRIDE=$qt_theme 238 | 239 | # Theme colors 240 | # class border backgr. text indic. child_border 241 | client.focused #556064 #16a085 #80FFF9 #FDF6E3 #FF0000 242 | client.focused_inactive #2F3D44 #2F3D44 #1ABC9C #454948 243 | client.unfocused #2F3D44 #2F3D44 #1ABC9C #454948 244 | client.urgent #CB4B16 #FDF6E3 #1ABC9C #268BD2 245 | client.placeholder #000000 #0c0c0c #ffffff #000000 246 | 247 | client.background #2B2C2B 248 | 249 | assign [class="Google-chrome"] 2 250 | assign [class="firefox"] 2 251 | assign [class="Brave-browser"] 2 252 | assign [class="Slack"] 4 253 | assign [class="Microsoft Teams"] 4 254 | assign [class="DBeaver"] 5 255 | 256 | 257 | gaps inner 8 258 | gaps outer 0 259 | smart_gaps on 260 | smart_borders on 261 | 262 | input * repeat_delay 350 263 | input * repeat_rate 60 264 | 265 | input "type:keyboard" { 266 | xkb_layout us,rs(latin) 267 | xkb_options grp:lctrl_lwin_toggle 268 | } 269 | -------------------------------------------------------------------------------- /nvim/lua/partials/packs/snacks.lua: -------------------------------------------------------------------------------- 1 | vim.pack.load({ 2 | src = 'folke/snacks.nvim', 3 | config = function() 4 | vim.keymap.set('n', 'gl', function() 5 | return Snacks.lazygit() 6 | end, { silent = true, desc = 'Lazygit' }) 7 | 8 | vim.keymap.set('n', 'gr', function() 9 | return Snacks.picker.gh_pr() 10 | end, { silent = true, desc = 'Select Github PR' }) 11 | 12 | vim.keymap.set('n', 'Z', function() 13 | return Snacks.zen.zen() 14 | end, { silent = true, desc = 'Zen mode' }) 15 | vim.keymap.set({ 'n', 'v' }, 'gy', function() 16 | return Snacks.gitbrowse.open({ 17 | open = function(url) 18 | vim.fn.setreg('+', url) 19 | vim.ui.open(url) 20 | vim.notify('Opening url\n' .. url, vim.log.levels.INFO, { 21 | title = 'Git browse', 22 | }) 23 | end, 24 | notify = false, 25 | }) 26 | end, { silent = true, desc = 'Git browse' }) 27 | 28 | require('snacks').setup({ 29 | bigfile = { enabled = true }, 30 | statuscolumn = { enabled = true }, 31 | quickfile = { enabled = false }, 32 | input = { 33 | enabled = true, 34 | }, 35 | image = {}, 36 | notifier = { 37 | enabled = true, 38 | top_down = false, 39 | margin = { bottom = 1 }, 40 | }, 41 | dim = { 42 | animate = { 43 | enabled = false, 44 | duration = { 45 | total = 0, 46 | }, 47 | }, 48 | }, 49 | terminal = { 50 | win = { 51 | wo = { 52 | winbar = '', 53 | }, 54 | }, 55 | }, 56 | picker = { 57 | formatters = { 58 | file = { 59 | truncate = 80, 60 | }, 61 | }, 62 | previewers = { 63 | diff = { 64 | style = 'syntax', 65 | }, 66 | }, 67 | icons = { 68 | git = { 69 | staged = '✓', 70 | deleted = '', 71 | ignored = ' ', 72 | modified = '✗', 73 | renamed = '', 74 | unmerged = ' ', 75 | untracked = '★', 76 | }, 77 | }, 78 | sources = { 79 | lsp_symbols = { 80 | filter = { 81 | default = { 82 | 'Class', 83 | 'Constructor', 84 | 'Enum', 85 | 'Field', 86 | 'Function', 87 | 'Interface', 88 | 'Method', 89 | 'Module', 90 | 'Namespace', 91 | 'Package', 92 | 'Property', 93 | 'Struct', 94 | 'Trait', 95 | 'Constant', 96 | }, 97 | }, 98 | }, 99 | files_with_symbols = { 100 | title = 'Files', 101 | multi = { 'files', 'lsp_symbols' }, 102 | filter = { 103 | ---@param p snacks.Picker 104 | ---@param filter snacks.picker.Filter 105 | transform = function(p, filter) 106 | local symbol_pattern = filter.pattern:match('^.-@(.*)$') 107 | local line_nr_pattern = filter.pattern:match('^.-:(%d*)$') 108 | local search_pattern = filter.pattern:match('^.-#(.*)$') 109 | local pattern = symbol_pattern or line_nr_pattern or search_pattern 110 | 111 | if pattern then 112 | local item = p:current() 113 | if item and item.file then 114 | filter.meta.buf = vim.fn.bufadd(item.file) 115 | end 116 | end 117 | 118 | if not filter.meta.buf then 119 | filter.source_id = 1 120 | return 121 | end 122 | 123 | if symbol_pattern then 124 | filter.pattern = symbol_pattern 125 | filter.current_buf = filter.meta.buf 126 | filter.source_id = 2 127 | return 128 | end 129 | 130 | if line_nr_pattern then 131 | filter.pattern = filter.pattern:gsub(':%d*$', '') 132 | filter.current_buf = filter.meta.buf 133 | filter.source_id = 1 134 | local item = p:current() 135 | if item then 136 | item.pos = { tonumber(line_nr_pattern) or 1, 0 } 137 | p.preview:loc() 138 | end 139 | return 140 | end 141 | 142 | if search_pattern then 143 | filter.pattern = filter.pattern:gsub('#.*$', '') 144 | filter.current_buf = filter.meta.buf 145 | filter.source_id = 1 146 | if search_pattern == '' then 147 | return 148 | end 149 | local item = p:current() 150 | vim.api.nvim_buf_call(p.preview.win.buf, function() 151 | vim.api.nvim_win_set_cursor(0, { 1, 0 }) 152 | local search = vim.fn.search(search_pattern, 'ncW') 153 | if search > 0 then 154 | vim.cmd('/' .. search_pattern) 155 | if vim.fn.line('w$') < search then 156 | vim.api.nvim_win_set_cursor(0, { math.max(1, search - 8), 0 }) 157 | end 158 | item.pos = { search, 0 } 159 | end 160 | end) 161 | return 162 | end 163 | 164 | filter.source_id = 1 165 | end, 166 | }, 167 | }, 168 | }, 169 | ui_select = true, 170 | prompt = '  ', 171 | layout = 'custom_telescope', 172 | layouts = { 173 | custom_telescope = { 174 | layout = { 175 | box = 'horizontal', 176 | backdrop = false, 177 | width = 0.8, 178 | height = 0.9, 179 | border = 'none', 180 | { 181 | box = 'vertical', 182 | { 183 | win = 'input', 184 | height = 1, 185 | border = 'solid', 186 | -- title = '{title} {live} {flags}', 187 | -- title_pos = 'center', 188 | }, 189 | { win = 'list', border = 'solid' }, 190 | }, 191 | { 192 | win = 'preview', 193 | title = '{preview:Preview}', 194 | width = 0.45, 195 | border = 'solid', 196 | title_pos = 'center', 197 | }, 198 | }, 199 | }, 200 | select = { 201 | preview = false, 202 | layout = { 203 | backdrop = false, 204 | width = 70, 205 | row = 1, 206 | min_width = 0, 207 | height = 0.4, 208 | min_height = 3, 209 | box = 'vertical', 210 | relative = 'cursor', 211 | border = 'none', 212 | title = '{title}', 213 | title_pos = 'center', 214 | { win = 'input', height = 1, border = 'none' }, 215 | { win = 'list', border = 'none' }, 216 | { win = 'preview', title = '{preview}', height = 0.4, border = 'none' }, 217 | }, 218 | }, 219 | }, 220 | win = { 221 | input = { 222 | keys = { 223 | [''] = { 'close', mode = { 'n', 'i' } }, 224 | [''] = { 'preview_scroll_down', mode = { 'i', 'n' } }, 225 | [""] = { "cycle_win", mode = { "i", "n" } }, 226 | [''] = { 'preview_scroll_up', mode = { 'i', 'n' } }, 227 | }, 228 | }, 229 | list = { 230 | keys = { 231 | [""] = { "cycle_win", mode = { "i", "n" } }, 232 | }, 233 | }, 234 | preview = { 235 | keys = { 236 | [""] = { "cycle_win", mode = { "i", "n" } }, 237 | }, 238 | }, 239 | }, 240 | }, 241 | dashboard = { 242 | enabled = false, 243 | sections = { 244 | { section = 'header' }, 245 | { section = 'keys', gap = 1, padding = 1 }, 246 | { 247 | title = 'Orgmode', 248 | icon = ' ', 249 | }, 250 | { 251 | title = 'Agenda', 252 | indent = 3, 253 | action = ':lua require("orgmode").agenda:agenda()', 254 | key = 'a', 255 | }, 256 | { 257 | title = 'Capture', 258 | indent = 3, 259 | action = 'oc', 260 | key = 'C', 261 | padding = 1, 262 | }, 263 | { icon = ' ', title = 'Projects', section = 'projects', indent = 2, padding = 2 }, 264 | { section = 'startup' }, 265 | }, 266 | }, 267 | styles = { 268 | input = { 269 | relative = 'cursor', 270 | row = 1, 271 | col = 3, 272 | bo = { 273 | buftype = '', 274 | }, 275 | }, 276 | }, 277 | }) 278 | 279 | vim.api.nvim_create_user_command('Notifications', function() 280 | Snacks.notifier.show_history() 281 | end, { 282 | nargs = 0, 283 | }) 284 | 285 | vim.keymap.set('n', 'T', function() 286 | return Snacks.terminal.toggle() 287 | end, { desc = 'Toggle terminal' }) 288 | vim.keymap.set('t', 'T', function() 289 | vim.cmd('stopinsert') 290 | return Snacks.terminal.toggle() 291 | end, { desc = 'Close terminal' }) 292 | end, 293 | }) 294 | -------------------------------------------------------------------------------- /nvim/lua/partials/plugins/snacks.lua: -------------------------------------------------------------------------------- 1 | return { 2 | 'folke/snacks.nvim', 3 | priority = 1000, 4 | lazy = false, 5 | keys = { 6 | { 7 | 'gl', 8 | function() 9 | Snacks.lazygit() 10 | end, 11 | desc = 'Lazygit', 12 | }, 13 | { 14 | 'Z', 15 | function() 16 | Snacks.zen.zen() 17 | end, 18 | desc = 'Zen mode', 19 | }, 20 | { 21 | 'gy', 22 | function() 23 | Snacks.gitbrowse.open({ 24 | open = function(url) 25 | vim.fn.setreg('+', url) 26 | vim.ui.open(url) 27 | vim.notify('Opening url\n' .. url, vim.log.levels.INFO, { 28 | title = 'Git browse', 29 | }) 30 | end, 31 | notify = false, 32 | }) 33 | end, 34 | desc = 'Git browse', 35 | mode = { 'n', 'v' }, 36 | }, 37 | }, 38 | config = function() 39 | require('snacks').setup({ 40 | bigfile = { enabled = true }, 41 | statuscolumn = { enabled = true }, 42 | quickfile = { enabled = false }, 43 | input = { 44 | enabled = true, 45 | }, 46 | image = {}, 47 | notifier = { 48 | enabled = true, 49 | top_down = false, 50 | margin = { bottom = 1 }, 51 | }, 52 | dim = { 53 | animate = { 54 | enabled = false, 55 | duration = { 56 | total = 0, 57 | }, 58 | }, 59 | }, 60 | terminal = { 61 | win = { 62 | wo = { 63 | winbar = '', 64 | }, 65 | }, 66 | }, 67 | picker = { 68 | formatters = { 69 | file = { 70 | truncate = 80, 71 | }, 72 | }, 73 | icons = { 74 | git = { 75 | staged = '✓', 76 | deleted = '', 77 | ignored = ' ', 78 | modified = '✗', 79 | renamed = '', 80 | unmerged = ' ', 81 | untracked = '★', 82 | }, 83 | }, 84 | sources = { 85 | files_with_symbols = { 86 | title = 'Files', 87 | multi = { 'files', 'lsp_symbols' }, 88 | filter = { 89 | ---@param p snacks.Picker 90 | ---@param filter snacks.picker.Filter 91 | transform = function(p, filter) 92 | local symbol_pattern = filter.pattern:match('^.-@(.*)$') 93 | local line_nr_pattern = filter.pattern:match('^.-:(%d*)$') 94 | local search_pattern = filter.pattern:match('^.-#(.*)$') 95 | local pattern = symbol_pattern or line_nr_pattern or search_pattern 96 | 97 | if pattern then 98 | local item = p:current() 99 | if item and item.file then 100 | filter.meta.buf = vim.fn.bufadd(item.file) 101 | end 102 | end 103 | 104 | if not filter.meta.buf then 105 | filter.source_id = 1 106 | return 107 | end 108 | 109 | if symbol_pattern then 110 | filter.pattern = symbol_pattern 111 | filter.current_buf = filter.meta.buf 112 | filter.source_id = 2 113 | return 114 | end 115 | 116 | if line_nr_pattern then 117 | filter.pattern = filter.pattern:gsub(':%d*$', '') 118 | filter.current_buf = filter.meta.buf 119 | filter.source_id = 1 120 | local item = p:current() 121 | if item then 122 | item.pos = { tonumber(line_nr_pattern) or 1, 0 } 123 | p.preview:loc() 124 | end 125 | return 126 | end 127 | 128 | if search_pattern then 129 | filter.pattern = filter.pattern:gsub('#.*$', '') 130 | filter.current_buf = filter.meta.buf 131 | filter.source_id = 1 132 | if search_pattern == '' then 133 | return 134 | end 135 | local item = p:current() 136 | vim.api.nvim_buf_call(p.preview.win.buf, function() 137 | vim.api.nvim_win_set_cursor(0, { 1, 0 }) 138 | local search = vim.fn.search(search_pattern, 'ncW') 139 | if search > 0 then 140 | vim.cmd('/' .. search_pattern) 141 | if vim.fn.line('w$') < search then 142 | vim.api.nvim_win_set_cursor(0, { math.max(1, search - 8), 0 }) 143 | end 144 | item.pos = { search, 0 } 145 | end 146 | end) 147 | return 148 | end 149 | 150 | filter.source_id = 1 151 | end, 152 | }, 153 | }, 154 | }, 155 | ui_select = true, 156 | prompt = '  ', 157 | layout = 'custom_telescope', 158 | layouts = { 159 | custom_telescope = { 160 | layout = { 161 | box = 'horizontal', 162 | backdrop = false, 163 | width = 0.8, 164 | height = 0.9, 165 | border = 'none', 166 | { 167 | box = 'vertical', 168 | { 169 | win = 'input', 170 | height = 1, 171 | border = 'solid', 172 | -- title = '{title} {live} {flags}', 173 | -- title_pos = 'center', 174 | }, 175 | { win = 'list', border = 'solid' }, 176 | }, 177 | { 178 | win = 'preview', 179 | title = '{preview:Preview}', 180 | width = 0.45, 181 | border = 'solid', 182 | title_pos = 'center', 183 | }, 184 | }, 185 | }, 186 | select = { 187 | preview = false, 188 | layout = { 189 | backdrop = false, 190 | width = 70, 191 | row = 1, 192 | min_width = 0, 193 | height = 0.4, 194 | min_height = 3, 195 | box = 'vertical', 196 | relative = 'cursor', 197 | border = 'none', 198 | title = '{title}', 199 | title_pos = 'center', 200 | { win = 'input', height = 1, border = 'none' }, 201 | { win = 'list', border = 'none' }, 202 | { win = 'preview', title = '{preview}', height = 0.4, border = 'none' }, 203 | }, 204 | }, 205 | }, 206 | win = { 207 | input = { 208 | keys = { 209 | [''] = { 'close', mode = { 'n', 'i' } }, 210 | [''] = { 'preview_scroll_down', mode = { 'i', 'n' } }, 211 | [''] = { 'preview_scroll_up', mode = { 'i', 'n' } }, 212 | }, 213 | }, 214 | }, 215 | }, 216 | dashboard = { 217 | enabled = false, 218 | sections = { 219 | { section = 'header' }, 220 | { section = 'keys', gap = 1, padding = 1 }, 221 | { 222 | title = 'Orgmode', 223 | icon = ' ', 224 | }, 225 | { 226 | title = 'Agenda', 227 | indent = 3, 228 | action = ':lua require("orgmode").agenda:agenda()', 229 | key = 'a', 230 | }, 231 | { 232 | title = 'Capture', 233 | indent = 3, 234 | action = 'oc', 235 | key = 'C', 236 | padding = 1, 237 | }, 238 | { icon = ' ', title = 'Projects', section = 'projects', indent = 2, padding = 2 }, 239 | { section = 'startup' }, 240 | }, 241 | }, 242 | styles = { 243 | input = { 244 | relative = 'cursor', 245 | row = 1, 246 | col = 3, 247 | bo = { 248 | buftype = '', 249 | }, 250 | }, 251 | }, 252 | }) 253 | 254 | vim.api.nvim_create_user_command('Notifications', function() 255 | Snacks.notifier.show_history() 256 | end, { 257 | nargs = 0, 258 | }) 259 | 260 | vim.keymap.set('n', 'T', function() 261 | return Snacks.terminal.toggle() 262 | end, { desc = 'Toggle terminal' }) 263 | vim.keymap.set('t', 'T', function() 264 | vim.cmd('stopinsert') 265 | return Snacks.terminal.toggle() 266 | end, { desc = 'Close terminal' }) 267 | 268 | Snacks.picker.actions.qflist = function(picker, opts) 269 | picker:close() 270 | local sel = picker:selected() 271 | local items = #sel > 0 and sel or picker:items() 272 | local qf = {} 273 | for _, item in ipairs(items) do 274 | local text = item.text 275 | if vim.startswith(text, item.file) then 276 | text = text:sub(#item.file + 2) 277 | end 278 | qf[#qf + 1] = { 279 | filename = Snacks.picker.util.path(item), 280 | bufnr = item.buf, 281 | lnum = item.pos and item.pos[1] or 1, 282 | col = item.pos and item.pos[2] or 1, 283 | end_lnum = item.end_pos and item.end_pos[1] or nil, 284 | end_col = item.end_pos and item.end_pos[2] or nil, 285 | text = text, 286 | pattern = item.search, 287 | valid = true, 288 | } 289 | end 290 | if opts and opts.win then 291 | vim.fn.setloclist(opts.win, qf) 292 | vim.cmd('lopen') 293 | else 294 | vim.fn.setqflist(qf) 295 | vim.cmd('copen') 296 | end 297 | vim.schedule(function() 298 | vim.w.quickfix_title = picker.title 299 | end) 300 | end 301 | end, 302 | } 303 | --------------------------------------------------------------------------------