diff --git a/dot_config/herdr/config.toml b/dot_config/herdr/config.toml index 3a5e277..e117738 100644 --- a/dot_config/herdr/config.toml +++ b/dot_config/herdr/config.toml @@ -1,5 +1,8 @@ onboarding = false +[theme] +name = "catppuccin" + [terminal] # New panes inherit the focused pane's working directory. new_cwd = "follow" @@ -12,7 +15,7 @@ sidebar_max_width = 38 # Visually distinguish Herdr panes without wasting much space. pane_borders = true -pane_gaps = false +pane_gaps = true # Hide the tab bar when a workspace only has one tab. hide_tab_bar_when_single_tab = true @@ -21,6 +24,8 @@ hide_tab_bar_when_single_tab = true mouse_capture = true copy_on_select = true +show_agent_labels_on_pane_borders = false +agent_panel_sort = "spaces" [keys] prefix = "ctrl+space" @@ -54,53 +59,56 @@ focus_pane_right = "prefix+l" # Direct Ctrl+HJKL is handled by herdr-splits below. -[[keys.command]] -key = "ctrl+h" -type = "plugin_action" -command = "herdr-splits.nav-left" -description = "navigate left through Neovim and Herdr" - -[[keys.command]] -key = "ctrl+j" -type = "plugin_action" -command = "herdr-splits.nav-down" -description = "navigate down through Neovim and Herdr" - -[[keys.command]] -key = "ctrl+k" -type = "plugin_action" -command = "herdr-splits.nav-up" -description = "navigate up through Neovim and Herdr" - -[[keys.command]] -key = "ctrl+l" -type = "plugin_action" -command = "herdr-splits.nav-right" -description = "navigate right through Neovim and Herdr" - -[[keys.command]] -key = "alt+h" -type = "plugin_action" -command = "herdr-splits.resize-left" -description = "resize left" - -[[keys.command]] -key = "alt+j" -type = "plugin_action" -command = "herdr-splits.resize-down" -description = "resize down" - -[[keys.command]] -key = "alt+k" -type = "plugin_action" -command = "herdr-splits.resize-up" -description = "resize up" - -[[keys.command]] -key = "alt+l" -type = "plugin_action" -command = "herdr-splits.resize-right" -description = "resize right" +# [[keys.command]] +# key = "ctrl+h" +# type = "plugin_action" +# command = "herdr-splits.nav-left" +# description = "navigate left through Neovim and Herdr" +# +# [[keys.command]] +# key = "ctrl+j" +# type = "plugin_action" +# command = "herdr-splits.nav-down" +# description = "navigate down through Neovim and Herdr" +# +# [[keys.command]] +# key = "ctrl+k" +# type = "plugin_action" +# command = "herdr-splits.nav-up" +# description = "navigate up through Neovim and Herdr" +# +# [[keys.command]] +# key = "ctrl+l" +# type = "plugin_action" +# command = "herdr-splits.nav-right" +# description = "navigate right through Neovim and Herdr" +# +# [[keys.command]] +# key = "alt+h" +# type = "plugin_action" +# command = "herdr-splits.resize-left" +# description = "resize left" +# +# [[keys.command]] +# key = "alt+j" +# type = "plugin_action" +# command = "herdr-splits.resize-down" +# description = "resize down" +# +# [[keys.command]] +# key = "alt+k" +# type = "plugin_action" +# command = "herdr-splits.resize-up" +# description = "resize up" +# +# [[keys.command]] +# key = "alt+l" +# type = "plugin_action" +# command = "herdr-splits.resize-right" +# description = "resize right" [ui.toast] delivery = "herdr" + +[experimental] +kitty_graphics = true diff --git a/dot_config/hypr/config/binds.lua b/dot_config/hypr/config/binds.lua index 06b64f7..a5a9e6b 100644 --- a/dot_config/hypr/config/binds.lua +++ b/dot_config/hypr/config/binds.lua @@ -14,35 +14,85 @@ hl.bind(mainMod .. " + S", hl.dsp.exec_cmd("grim -o" .. MAIN_DISPLAY .. " \"${HOME}/screenshots/screenshot-$(date +%F-%T).png\"")) hl.bind(mainMod .. " + SHIFT + S", hl.dsp.exec_cmd("grim -g \"$(slurp)\" - | wl-copy")) +local function focus_hyprland(direction) + hl.dispatch(hl.dsp.focus({ direction = direction })) +end + +local function is_direct_nvim(title) + title = (title or ""):lower() + + return title:find("^nvim") + or title:find(" - nvim", 1, true) + or title:find("^vim") + or title:find(" - vim", 1, true) +end + +local function ask_direct_nvim(win, direction) + local runtime_dir = os.getenv("XDG_RUNTIME_DIR") or "/tmp" + + local socket_path = string.format( + "%s/nvim-hypr-nav-%x.sock", + runtime_dir, + tostring(win.stable_id) + ) + + local handle = io.popen(string.format( + "printf 'nav:%s\\n' | socat -T 0.25 -,ignoreeof UNIX-CONNECT:%s 2>/dev/null", + direction, + socket_path + )) + + if not handle then + return false + end + + local response = handle:read("*a") + handle:close() + + return response:find("success", 1, true) ~= nil +end + local function smart_nav(direction) return function() local win = hl.get_active_window() - if not win - or win.class ~= "com.mitchellh.ghostty" - or not ( - (win.title or ""):lower():find("^nvim") - or (win.title or ""):lower():find(" - nvim") - or (win.title or ""):lower():find("^vim") - or (win.title or ""):lower():find(" - vim")) - then - hl.dispatch(hl.dsp.focus({ direction = direction })) + if not win then return end - local runtime_dir = os.getenv("XDG_RUNTIME_DIR") or "/tmp" - local socket_path = string.format("%s/nvim-hypr-nav-%x.sock", runtime_dir, tostring(win.stable_id)) - - local handle = io.popen( - string.format("echo nav:%s | socat - UNIX-CONNECT:%s", - direction, socket_path)) - - local response = handle:read("*a") - handle:close() - - if response:find("failed") then - hl.dispatch(hl.dsp.focus({ direction = direction })) + if win.class ~= "com.mitchellh.ghostty" then + focus_hyprland(direction) + return end + + local title = (win.title or ""):lower() + + if title == "herdr" then + local helper = (os.getenv("HOME") or "") + .. "/.config/hypr/scripts/herdr-smart-nav" + + local handle = io.popen(helper .. " " .. direction) + + if not handle then + focus_hyprland(direction) + return + end + + local result = handle:read("*a") + handle:close() + + if result:find("hyprland", 1, true) then + focus_hyprland(direction) + end + + return + end + + if is_direct_nvim(title) and ask_direct_nvim(win, direction) then + return + end + + focus_hyprland(direction) end end diff --git a/dot_config/hypr/executable_games.py b/dot_config/hypr/executable_games.py deleted file mode 100644 index 3d59232..0000000 --- a/dot_config/hypr/executable_games.py +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/python3 - -games = [ - ("all", "Stardew Valley"), - ("ic", "steam_app_.*", "tile", "max"), - ("all", "ffxiv*", "sf"), - ("all", "Hollow Knight"), - ("all", "HELLDIVERS*"), - ("all", "CS", "tile", "max"), - ("title", "Warhammer 40.000: Darktide", "tile", "max") -] - -def main(): - f = open("config/games.conf", "w") - conf: str = "# Auto generated window rules for Games\n\n" - for game in games: - if type(game) is not tuple: - continue - - name = game[1] - match game[0]: - case "ic": - selector = f"match:initial_class \"{name}\"" - case "title": - selector = f"match:title \"{name}\"" - case "class": - selector = f"match:class \"{name}\"" - case "all": - selector = f"match:title \"{name}\", match:class \"{name}\"" - case s: - print(f"Could not find selector for \"{s}\"") - continue - - for setting in game[2::]: - match setting: - case "sf": - conf += f"windowrule = stay_focused on, {selector}\n" - case "tile": - conf += f"windowrule = tile on, {selector}\n" - case "max": - conf += f"windowrule = maximize on, {selector}\n" - case s: - print(f"Could not find setting \"{s}\"") - - - conf += f"""windowrule = fullscreen on, {selector} -windowrule = monitor DP-3, {selector} -windowrule = allows_input on, {selector}\n -""" - f.write(conf) - f.close() - - -if __name__ == "__main__": - main() - diff --git a/dot_config/nvim/lazy-lock.json b/dot_config/nvim/lazy-lock.json index ec89ccb..0db6bd0 100644 --- a/dot_config/nvim/lazy-lock.json +++ b/dot_config/nvim/lazy-lock.json @@ -7,6 +7,7 @@ "fidget.nvim": { "branch": "main", "commit": "82404b196e73a00b1727a91903beef5ddc319d22" }, "flash.nvim": { "branch": "main", "commit": "fcea7ff883235d9024dc41e638f164a450c14ca2" }, "friendly-snippets": { "branch": "main", "commit": "6cd7280adead7f586db6fccbd15d2cac7e2188b9" }, + "herdr-splits.nvim": { "branch": "main", "commit": "107273e004e4f7ef07f13c83164d2cb2c51df65d" }, "lazy.nvim": { "branch": "main", "commit": "306a05526ada86a7b30af95c5cc81ffba93fef97" }, "lazydev.nvim": { "branch": "main", "commit": "ff2cbcba459b637ec3fd165a2be59b7bbaeedf0d" }, "lualine.nvim": { "branch": "master", "commit": "221ce6b2d999187044529f49da6554a92f740a96" }, @@ -23,9 +24,9 @@ "nvim-lint": { "branch": "master", "commit": "d48f3a76189d03b2239f6df1b2f7e3fa8353743b" }, "nvim-lspconfig": { "branch": "master", "commit": "229b79051b380377664edc4cbd534930154921a1" }, "nvim-nio": { "branch": "master", "commit": "21f5324bfac14e22ba26553caf69ec76ae8a7662" }, - "nvim-tmux-navigation": { "branch": "main", "commit": "4898c98702954439233fdaf764c39636681e2861" }, "nvim-treesitter": { "branch": "main", "commit": "4916d6592ede8c07973490d9322f187e07dfefac" }, "nvim-web-devicons": { "branch": "master", "commit": "dfbfaa967a6f7ec50789bead7ef87e336c1fa63c" }, + "octo.nvim": { "branch": "master", "commit": "d05b852ad7eba6e34ffe38ee2db430f0fd6f6225" }, "oil.nvim": { "branch": "master", "commit": "b73018b75affd13fa38e2fc94ef753b465f770d7" }, "plenary.nvim": { "branch": "master", "commit": "74b06c6c75e4eeb3108ec01852001636d85a932b" }, "ripgrep": { "branch": "master", "commit": "82313cf95849bfe425109ad9506a52154879b1b1" }, diff --git a/dot_config/nvim/lua/hypr-nav.lua b/dot_config/nvim/lua/hypr-nav.lua index fc05495..3224b1d 100644 --- a/dot_config/nvim/lua/hypr-nav.lua +++ b/dot_config/nvim/lua/hypr-nav.lua @@ -2,55 +2,124 @@ local direction_map = { left = "h", right = "l", up = "k", - down = "j" + down = "j", } local runtime_dir = os.getenv("XDG_RUNTIME_DIR") or "/tmp" -local function get_stable_id() + +local function sanitize(value) + return value:gsub("[^%w_.-]", "_") +end + +local function get_hyprland_stable_id() local handle = io.popen("hyprctl activewindow -j 2>/dev/null") + + if not handle then + return "unknown" + end + local data = handle:read("*a") handle:close() + local ok, json = pcall(vim.json.decode, data) + if ok and json and json.stableId then return tostring(json.stableId) end + return "unknown" end -local stable_id = get_stable_id() +local function get_socket_path() + local pane_id = vim.env.HERDR_PANE_ID -local socket_path = string.format("%s/nvim-hypr-nav-%s.sock", runtime_dir, stable_id) + if pane_id and pane_id ~= "" then + return string.format( + "%s/nvim-hypr-nav-pane-%s.sock", + runtime_dir, + sanitize(pane_id) + ) + end + return string.format( + "%s/nvim-hypr-nav-%s.sock", + runtime_dir, + get_hyprland_stable_id() + ) +end + +local socket_path = get_socket_path() local server = vim.uv.new_pipe(false) + +local function reply(connection, response) + local ok = pcall(function() + connection:write(response, function() + pcall(function() + connection:close() + end) + end) + end) + + if not ok then + pcall(function() + connection:close() + end) + end +end + +-- Normally unnecessary because Herdr sockets contain the process ID, but it +-- also cleans up an ungracefully terminated direct-Neovim instance if the PID +-- happened to be reused. +vim.uv.fs_unlink(socket_path) + server:bind(socket_path) + server:listen(128, function(err) - if err then vim.notify("hypr-nav: " .. err, vim.log.levels.ERROR) end + if err then + vim.schedule(function() + vim.notify("hypr-nav: " .. err, vim.log.levels.ERROR) + end) + return + end - local conn = vim.uv.new_pipe(false) - server:accept(conn) + local connection = vim.uv.new_pipe(false) + server:accept(connection) - conn:read_start(function(err, data) - if not data then - pcall(function() conn:close() end) + connection:read_start(function(read_err, data) + if read_err or not data then + pcall(function() + connection:close() + end) return end - local direction = data:match("nav:(%a+)") - if not direction then - pcall(function() conn:write("invalid\n") end) - pcall(function() conn:close() end) + local direction = data:match("nav:(%a+)") + + if not direction or not direction_map[direction] then + reply(connection, "invalid\n") return end vim.schedule(function() local before = vim.api.nvim_get_current_win() - local wincmd_dir = direction_map[direction] or direction:sub(1, 1) - vim.cmd("wincmd " .. wincmd_dir) - local after = vim.api.nvim_get_current_win() - local response = (before == after) and "failed\n" or "success\n" - pcall(function() conn:write(response) end) - pcall(function() conn:close() end) + vim.cmd("wincmd " .. direction_map[direction]) + + local after = vim.api.nvim_get_current_win() + local response = before == after and "failed\n" or "success\n" + + reply(connection, response) end) end) end) + +vim.api.nvim_create_autocmd("VimLeavePre", { + once = true, + callback = function() + pcall(function() + server:close() + end) + + vim.uv.fs_unlink(socket_path) + end, +}) diff --git a/dot_config/nvim/lua/plugins/catppuccin.lua b/dot_config/nvim/lua/plugins/catppuccin.lua index 86af49a..0734554 100644 --- a/dot_config/nvim/lua/plugins/catppuccin.lua +++ b/dot_config/nvim/lua/plugins/catppuccin.lua @@ -6,17 +6,14 @@ return lazy = false, config = function() require("catppuccin").setup({ - transparent_background = false, + transparent_background = true, custom_highlights = function(colors) return { - Normal = { bg = colors.base }, - NormalNC = { bg = colors.mantle }, - - WinSeparator = { fg = colors.surface1, bg = colors.mantle }, + WinSeparator = { fg = colors.surface1 }, StatusLine = { fg = colors.text, bg = colors.surface0 }, - StatusLineNC = { fg = colors.overlay0, bg = colors.mantle }, + StatusLineNC = { fg = colors.overlay0 }, CursorLine = { bg = colors.surface0 }, } diff --git a/dot_config/nvim/lua/plugins/lsp.lua b/dot_config/nvim/lua/plugins/lsp.lua index 9f049fe..746a48b 100644 --- a/dot_config/nvim/lua/plugins/lsp.lua +++ b/dot_config/nvim/lua/plugins/lsp.lua @@ -17,7 +17,8 @@ return { "templ", "nil_ls", "gleam", - "ty" + "ty", + "buf_ls" }) diff --git a/dot_config/private_jj/config.toml b/dot_config/private_jj/config.toml index cda9781..a619a67 100644 --- a/dot_config/private_jj/config.toml +++ b/dot_config/private_jj/config.toml @@ -3,3 +3,6 @@ [user] name = "pablu" email = "me@pablu.de" + +[aliases] +push = ["util", "exec", "--", "jj-push"] diff --git a/dot_zshrc.tmpl b/dot_zshrc.tmpl index 2395fa2..302201d 100644 --- a/dot_zshrc.tmpl +++ b/dot_zshrc.tmpl @@ -46,6 +46,9 @@ alias cd='z' alias ls='eza --icons=always' {{ if eq .chezmoi.hostname "gentoo" }} + +eval "$(mise activate zsh)" + path+=("/home/pablu/.cargo/bin") export PATH {{ else if eq .chezmoi.os "darwin" }} @@ -63,12 +66,18 @@ source <(chezmoi completion zsh) eval "$(starship init zsh)" eval "$(zoxide init zsh)" +{{ if ne .chezmoi.hostname "ubuntu" }} +source <(herdr completion zsh) +source <(COMPLETE=zsh jj) +{{ end }} + {{ if eq .chezmoi.hostname "gentoo" }} eval "$(direnv hook zsh)" source /usr/share/zsh/site-functions/zsh-autosuggestions.zsh source /usr/share/zsh/site-functions/zsh-syntax-highlighting.zsh -source <(COMPLETE=zsh jj) +source <(diple completion zsh) +source <(zw completion zsh) {{ else if eq .chezmoi.os "darwin" }} @@ -77,8 +86,6 @@ source <(kubectl completion zsh) source <(kubebuilder completion zsh) source $(brew --prefix)/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh -source <(COMPLETE=zsh jj) - {{ else if eq .chezmoi.hostname "ubuntu" }} eval "$(direnv hook zsh)"