From f8312a59c775c740d9af173fafa65ab7e731e03e Mon Sep 17 00:00:00 2001 From: pablu Date: Thu, 17 Sep 2026 17:05:03 +0200 Subject: update codex config to not contain local project dirs, update .tmux.conf only for gentoo, make tmux work with hyprland --- .chezmoiignore | 2 + codex/config.toml | 56 ++++++++ dot_codex/AGENTS.md | 15 ++- dot_codex/modify_private_config.toml | 3 + dot_codex/private_config.toml | 66 ---------- dot_config/herdr/config.toml | 6 +- dot_config/hypr/config/binds.lua | 58 ++++++--- dot_config/hypr/config/rules.lua | 10 ++ dot_config/hypr/scripts/executable_herdr-smart-nav | 143 +++++++++++++++++++++ dot_config/hypr/scripts/executable_tmux-smart-nav | 105 +++++++++++++++ dot_config/nvim/lua/hypr-nav.lua | 2 +- dot_config/nvim/lua/plugins/lsp.lua | 3 +- dot_config/private_jj/config.toml | 3 + dot_config/waybar/config | 2 +- dot_tmux.conf | 57 -------- dot_tmux.conf.tmpl | 5 + dot_zshrc.tmpl | 2 + tmux/common.conf | 57 ++++++++ tmux/gentoo.conf | 69 ++++++++++ 19 files changed, 516 insertions(+), 148 deletions(-) create mode 100644 codex/config.toml create mode 100644 dot_codex/modify_private_config.toml delete mode 100644 dot_codex/private_config.toml create mode 100644 dot_config/hypr/scripts/executable_herdr-smart-nav create mode 100644 dot_config/hypr/scripts/executable_tmux-smart-nav delete mode 100644 dot_tmux.conf create mode 100644 dot_tmux.conf.tmpl create mode 100644 tmux/common.conf create mode 100644 tmux/gentoo.conf diff --git a/.chezmoiignore b/.chezmoiignore index 7fda614..176db0a 100644 --- a/.chezmoiignore +++ b/.chezmoiignore @@ -1,4 +1,6 @@ README.md +codex +tmux {{- if ne .chezmoi.hostname "gentoo" }} .config/nvim/lua/hypr-nav.lua .wallpaper diff --git a/codex/config.toml b/codex/config.toml new file mode 100644 index 0000000..ff7a423 --- /dev/null +++ b/codex/config.toml @@ -0,0 +1,56 @@ +model = "gpt-5.6-terra" +model_reasoning_effort = "medium" + +approval_request = "on-request" +sandbox_mode = "read-only" +model_verbosity = "low" +web_search = "cached" +allow_login_shell = false + +developer_instructions = """ +All manual filesystem modifications must use Codex's apply_patch mechanism. + +Never create, modify, rename, or delete project files using Python, Python scripts, +shell redirection, heredocs, sed -i, perl, awk, tee, dd, cat, printf, or another +general-purpose command. + +Do not use a shell or programming-language interpreter as a workaround for +apply_patch. + +If apply_patch cannot perform a requested edit, stop and explain the problem +instead of using another mechanism to modify the filesystem. + +The purpose of this rule is that every manual code change must be presented as +a reviewable file patch/diff before it is applied. + +Commands whose purpose is to generate files as their normal operation, such as +formatters, compilers, code generators, or package managers, are exempt when +the user has authorized running that command. +""" + +[shell_environment_policy] +inherit = "core" + +[features] +hooks = false +multi_agent = false +# shell_snapshot = false +# shell_tool = false +memories = true +deafult_mode_request_user_input = true +code_mode_host = true + +[tui] +theme = "catppuccin-mocha" +status_line = ["model-with-reasoning", "current-dir", "git-branch", "run-state", "permissions", "context-used"] +status_line_use_colors = true +pet = "disabled" + +[tui.model_availability_nux] +"gpt-5.5" = 4 +"gpt-5.6-sol" = 4 +gpt-6-astra = 4 + +[notice] +hide_rate_limit_model_nudge = true + diff --git a/dot_codex/AGENTS.md b/dot_codex/AGENTS.md index d316b57..58c0b69 100644 --- a/dot_codex/AGENTS.md +++ b/dot_codex/AGENTS.md @@ -4,19 +4,24 @@ Your role: - Explain architecture and tradeoffs clearly. - Critically review code for correctness and maintainability. - Challenge assumptions when appropriate. -- Suggest improvements, but do not rewrite working code unnecessarily. +- Suggest improvements and explain their tradeoffs. Strict rules: -- Do NOT modify files unless explicitly asked. -- Do NOT run git commands unless explicitly asked. -- Do NOT assume the user wants implementation. -- Prefer discussion, reasoning, and review over code generation. +- Default to discussion and review. Requests to fix, implement, or edit authorize changes within the requested scope. Questions about possible improvements do not authorize edits. +- Do NOT write or modify production code unless explicitly asked. Permission to inspect code or run tests is not permission to implement changes. +- Do NOT modify files outside the authorized scope. +- Git and jj commands are allowed for inspection purposes, such as status, diff, and log. Other version-control operations require explicit authorization. NEVER create commits or push. +- Relevant local tests are allowed. Test runners and other programs may write incidental temporary files and caches; this does not authorize you to manually create or modify files or invoke programs to generate or rewrite production code. +- Keep authorized changes focused on the requested outcome. Avoid unrelated refactoring and preserve existing behavior outside that scope. When reviewing: - Focus on correctness first. - Then API design and consistency. - Then maintainability. - Ignore formatting unless it impacts clarity. +- Ground findings in the current code. Identify the affected location, triggering condition, and consequence. +- Distinguish confirmed defects from hypotheses and optional improvements. +- State what was verified and what remains unverified. Never imply tests passed unless they were run successfully. Prefer idiomatic, simple solutions. Avoid unnecessary abstractions. diff --git a/dot_codex/modify_private_config.toml b/dot_codex/modify_private_config.toml new file mode 100644 index 0000000..a5c2db2 --- /dev/null +++ b/dot_codex/modify_private_config.toml @@ -0,0 +1,3 @@ +{{/* chezmoi:modify-template */}} +{{ include "codex/config.toml" -}} +{{- regexFindAll `(?m)^\[projects\.[^\n]+\]\n(?:[^\[]*\n?)*` .chezmoi.stdin -1 | join "" -}} diff --git a/dot_codex/private_config.toml b/dot_codex/private_config.toml deleted file mode 100644 index e15610f..0000000 --- a/dot_codex/private_config.toml +++ /dev/null @@ -1,66 +0,0 @@ -model = "gpt-5.6-sol" -model_reasoning_effort = "medium" - -approval_request = "on-request" -sandbox_mode = "read-only" -model_verbosity = "low" -web_search = "cached" -allow_login_shell = false - -[shell_environment_policy] -inherit = "core" - -[features] -hooks = false -multi_agent = false -# shell_snapshot = false -# shell_tool = false -memories = true - -[projects."/home/pablu/projects/zw"] -trust_level = "trusted" - -[projects."/home/pablu/.config/nvim"] -trust_level = "trusted" - -[projects."/home/pablu/projects/suchoi"] -trust_level = "trusted" - -[projects."/home/pablu/projects/Logprep"] -trust_level = "trusted" - -[projects."/home/pablu/.config/hypr"] -trust_level = "trusted" - -[projects."/home/pablu/projects/qview"] -trust_level = "trusted" - -[projects."/home/pablu/projects/tokonoma"] -trust_level = "trusted" - -[projects."/home/pablu/projects/logprep-data-server"] -trust_level = "trusted" - -[projects."/home/pablu/.codex"] -trust_level = "trusted" - -[projects."/home/pablu"] -trust_level = "trusted" - -[projects."/home/pablu/projects/domain-router"] -trust_level = "trusted" - -[projects."/home/pablu/projects/pybug"] -trust_level = "trusted" - -[projects."/home/pablu/projects/suchoi-v2"] -trust_level = "trusted" - -[tui] -theme = "catppuccin-mocha" -status_line = ["model-with-reasoning", "current-dir", "git-branch", "run-state", "permissions", "context-used"] -status_line_use_colors = true - -[tui.model_availability_nux] -"gpt-5.5" = 4 -"gpt-5.6-sol" = 4 diff --git a/dot_config/herdr/config.toml b/dot_config/herdr/config.toml index e117738..dc1ddd1 100644 --- a/dot_config/herdr/config.toml +++ b/dot_config/herdr/config.toml @@ -57,7 +57,11 @@ focus_pane_down = "prefix+j" focus_pane_up = "prefix+k" focus_pane_right = "prefix+l" -# Direct Ctrl+HJKL is handled by herdr-splits below. +# Direct pane swapping, local to Herdr. +swap_pane_left = "ctrl+h" +swap_pane_down = "ctrl+j" +swap_pane_up = "ctrl+k" +swap_pane_right = "ctrl+l" # [[keys.command]] # key = "ctrl+h" diff --git a/dot_config/hypr/config/binds.lua b/dot_config/hypr/config/binds.lua index a5a9e6b..a72777f 100644 --- a/dot_config/hypr/config/binds.lua +++ b/dot_config/hypr/config/binds.lua @@ -52,6 +52,28 @@ local function ask_direct_nvim(win, direction) return response:find("success", 1, true) ~= nil end +local function ask_tmux(win, direction) + local pid = tonumber(win.pid) + + if not pid then + return false + end + + local helper = (os.getenv("HOME") or "") + .. "/.config/hypr/scripts/tmux-smart-nav" + + local handle = io.popen(string.format("%s %s %d", helper, direction, pid)) + + if not handle then + return false + end + + local result = handle:read("*a") + handle:close() + + return result:find("handled", 1, true) ~= nil +end + local function smart_nav(direction) return function() local win = hl.get_active_window() @@ -67,25 +89,29 @@ local function smart_nav(direction) local title = (win.title or ""):lower() - if title == "herdr" then + if ask_tmux(win, direction) then + return + end + + -- Herdr now uses changing window titles. The helper checks whether its + -- foreground client belongs to this terminal before attempting navigation. + local pid = tonumber(win.pid) + if pid 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) + local handle = io.popen(string.format("%q %s %d", helper, direction, pid)) + + if handle then + local result = handle:read("*a"):match("^%s*(.-)%s*$") + handle:close() + + if result == "handled" then + return + elseif result == "hyprland" then + focus_hyprland(direction) + return + end end - - return end if is_direct_nvim(title) and ask_direct_nvim(win, direction) then diff --git a/dot_config/hypr/config/rules.lua b/dot_config/hypr/config/rules.lua index 0e17e4a..ca5fe88 100644 --- a/dot_config/hypr/config/rules.lua +++ b/dot_config/hypr/config/rules.lua @@ -73,3 +73,13 @@ hl.window_rule({ no_blur = true, no_shadow = true, }) + +hl.window_rule({ + name = "ghostty-fullscreen-opaque", + match = { + class = "com.mitchellh.ghostty", + fullscreen = true, + }, + force_rgbx = true, + no_blur = true, +}) diff --git a/dot_config/hypr/scripts/executable_herdr-smart-nav b/dot_config/hypr/scripts/executable_herdr-smart-nav new file mode 100644 index 0000000..36d27aa --- /dev/null +++ b/dot_config/hypr/scripts/executable_herdr-smart-nav @@ -0,0 +1,143 @@ +#!/usr/bin/env bash + +set -u + +direction="${1:-}" +terminal_pid="${2:-}" + +case "$direction" in + left|right|up|down) + ;; + *) + printf 'usage: %s \n' "$0" >&2 + exit 2 + ;; +esac + +# Window titles can change with the workspace. Find a foreground Herdr +# process belonging to this terminal instead of relying on its title. +is_in_terminal() { + local pid="$1" + local parent + + while [[ "$pid" =~ ^[0-9]+$ && "$pid" -gt 1 ]]; do + [[ "$pid" == "$terminal_pid" ]] && return 0 + parent="$(ps -o ppid= -p "$pid" 2>/dev/null | tr -d '[:space:]')" + [[ -n "$parent" && "$parent" != "$pid" ]] || return 1 + pid="$parent" + done + + return 1 +} + +herdr_found=false +if [[ "$terminal_pid" =~ ^[0-9]+$ ]]; then + while read -r pid process_group foreground_group; do + # The server has no foreground terminal; a suspended client is not active. + if [[ "$foreground_group" -gt 0 && "$process_group" == "$foreground_group" ]] && + is_in_terminal "$pid"; then + herdr_found=true + break + fi + done < <(ps -C herdr -o pid=,pgid=,tpgid= 2>/dev/null) +fi + +if [[ "$herdr_found" != true ]]; then + printf 'not-herdr\n' + exit +fi + +herdr_bin="${HERDR_BIN_PATH:-$HOME/.local/share/mise/installs/herdr/latest/herdr}" + +if [[ ! -x "$herdr_bin" ]]; then + printf 'hyprland\n' + exit +fi + +handled() { + printf 'handled\n' + exit +} + +fall_through() { + printf 'hyprland\n' + exit +} + +current="$("$herdr_bin" pane current --current 2>/dev/null)" || { + fall_through +} + +pane_id="$(jq -r '.result.pane.pane_id // empty' <<<"$current")" + +if [[ -z "$pane_id" ]]; then + fall_through +fi + +process_info="$( + "$herdr_bin" pane process-info --pane "$pane_id" 2>/dev/null || true +)" + +nvim_pid="$( + jq -r ' + [ + (.result.process_info.foreground_processes // [])[] + | select( + ((.name // "") | ascii_downcase) == "nvim" + or ((.name // "") | ascii_downcase) == "vim" + ) + | .pid + ][0] // empty + ' <<<"$process_info" 2>/dev/null +)" + +if [[ -n "$nvim_pid" ]]; then + safe_pane_id="${pane_id//[^a-zA-Z0-9_.-]/_}" + runtime_dir="${XDG_RUNTIME_DIR:-/tmp}" + + socket_path="$runtime_dir/nvim-hypr-nav-pane-$safe_pane_id.sock" + + response="$( + printf 'nav:%s\n' "$direction" | + socat -T 0.25 -,ignoreeof "UNIX-CONNECT:$socket_path" 2>/dev/null || + true + )" + + if [[ "$response" == *success* ]]; then + handled + fi +fi + +neighbor="$( + "$herdr_bin" pane neighbor \ + --pane "$pane_id" \ + --direction "$direction" \ + 2>/dev/null +)" || { + fall_through +} + +# A zoomed pane deliberately falls through to Hyprland. Do not expose or +# navigate to another Herdr pane. +if jq -e '.result.neighbor.layout.zoomed == true' \ + >/dev/null 2>&1 <<<"$neighbor"; then + fall_through +fi + +neighbor_id="$( + jq -r '.result.neighbor.neighbor_pane_id // empty' <<<"$neighbor" +)" + +# Herdr 0.7.5 returns the current pane itself when there is no neighbour. +if [[ -z "$neighbor_id" || "$neighbor_id" == "$pane_id" ]]; then + fall_through +fi + +if "$herdr_bin" pane focus \ + --pane "$pane_id" \ + --direction "$direction" \ + >/dev/null 2>&1; then + handled +else + fall_through +fi diff --git a/dot_config/hypr/scripts/executable_tmux-smart-nav b/dot_config/hypr/scripts/executable_tmux-smart-nav new file mode 100644 index 0000000..4275462 --- /dev/null +++ b/dot_config/hypr/scripts/executable_tmux-smart-nav @@ -0,0 +1,105 @@ +#!/usr/bin/env bash + +set -u + +direction="${1:-}" +terminal_pid="${2:-}" + +case "$direction" in + left) + tmux_key="C-h" + ;; + right) + tmux_key="C-l" + ;; + up) + tmux_key="C-k" + ;; + down) + tmux_key="C-j" + ;; + *) + printf 'usage: %s \n' "$0" >&2 + exit 2 + ;; +esac + +if [[ ! "$terminal_pid" =~ ^[0-9]+$ ]] || ! command -v tmux >/dev/null 2>&1; then + printf 'hyprland\n' + exit +fi + +# A tmux client is a descendant of the terminal process that owns it. This +# avoids acting on a client in another Ghostty window. +is_descendant_of() { + local pid="$1" + local parent + + while [[ "$pid" =~ ^[0-9]+$ && "$pid" -gt 1 ]]; do + if [[ "$pid" == "$terminal_pid" ]]; then + return 0 + fi + + parent="$(ps -o ppid= -p "$pid" 2>/dev/null | tr -d '[:space:]')" + [[ -n "$parent" && "$parent" != "$pid" ]] || return 1 + pid="$parent" + done + + return 1 +} + +client_tty="" +while read -r client_pid tty; do + if is_descendant_of "$client_pid"; then + client_tty="$tty" + break + fi +done < <(tmux list-clients -F '#{client_pid} #{client_tty}' 2>/dev/null) + +if [[ -z "$client_tty" ]]; then + printf 'hyprland\n' + exit +fi + +pane_id="$(tmux display-message -p -c "$client_tty" '#{pane_id}' 2>/dev/null)" +pane_command="$(tmux display-message -p -c "$client_tty" '#{pane_current_command}' 2>/dev/null)" + +# Ghostty has one title for the whole tmux window, so it cannot identify the +# focused pane's process. Ask Neovim through a pane-specific socket only when +# tmux says this exact pane is running it. +case "${pane_command,,}" in + nvim|vim) + safe_pane_id="${pane_id//[^a-zA-Z0-9_.-]/_}" + socket_path="${XDG_RUNTIME_DIR:-/tmp}/nvim-hypr-nav-pane-${safe_pane_id}.sock" + response="$( + printf 'nav:%s\n' "$direction" | + socat -T 0.25 -,ignoreeof "UNIX-CONNECT:$socket_path" 2>/dev/null || true + )" + + if [[ "$response" == *success* ]]; then + printf 'handled\n' + exit + fi + ;; +esac + +# Send the directional key through the matching client so tmux resolves it +# against that client's own active pane. Its existing C-h/j/k/l bindings also +# retain the configured Neovim handoff. +at_edge="$(tmux display-message -p -c "$client_tty" "#{pane_at_${direction}}" 2>/dev/null)" + +if [[ -z "$pane_id" || "$at_edge" == "1" ]]; then + printf 'hyprland\n' + exit +fi + +if tmux send-keys -c "$client_tty" -K "$tmux_key" >/dev/null 2>&1; then + selected_pane_id="$(tmux display-message -p -c "$client_tty" '#{pane_id}' 2>/dev/null)" + + if [[ "$selected_pane_id" != "$pane_id" ]]; then + printf 'handled\n' + exit + fi +fi + +printf 'hyprland\n' diff --git a/dot_config/nvim/lua/hypr-nav.lua b/dot_config/nvim/lua/hypr-nav.lua index 3224b1d..102072a 100644 --- a/dot_config/nvim/lua/hypr-nav.lua +++ b/dot_config/nvim/lua/hypr-nav.lua @@ -31,7 +31,7 @@ local function get_hyprland_stable_id() end local function get_socket_path() - local pane_id = vim.env.HERDR_PANE_ID + local pane_id = vim.env.HERDR_PANE_ID or vim.env.TMUX_PANE if pane_id and pane_id ~= "" then return string.format( diff --git a/dot_config/nvim/lua/plugins/lsp.lua b/dot_config/nvim/lua/plugins/lsp.lua index 746a48b..57ec231 100644 --- a/dot_config/nvim/lua/plugins/lsp.lua +++ b/dot_config/nvim/lua/plugins/lsp.lua @@ -18,7 +18,8 @@ return { "nil_ls", "gleam", "ty", - "buf_ls" + "buf_ls", + "ts_ls" }) diff --git a/dot_config/private_jj/config.toml b/dot_config/private_jj/config.toml index a619a67..6f16d0b 100644 --- a/dot_config/private_jj/config.toml +++ b/dot_config/private_jj/config.toml @@ -6,3 +6,6 @@ email = "me@pablu.de" [aliases] push = ["util", "exec", "--", "jj-push"] + +[ui] +diff-editor = ":builtin" diff --git a/dot_config/waybar/config b/dot_config/waybar/config index c89753d..0139993 100644 --- a/dot_config/waybar/config +++ b/dot_config/waybar/config @@ -1,7 +1,7 @@ { "layer": "top", "position": "top", - "height": 28, + "height": 24, "modules-left": ["hyprland/workspaces"], "modules-center": ["hyprland/window"], diff --git a/dot_tmux.conf b/dot_tmux.conf deleted file mode 100644 index f3c03bd..0000000 --- a/dot_tmux.conf +++ /dev/null @@ -1,57 +0,0 @@ -# remap prefix -set-option -g prefix C-Space -unbind C-Space -bind-key C-Space send-prefix - -set -g mouse on - -set -g base-index 1 -setw -g pane-base-index 1 - -set -sg escape-time 10 - -set -g renumber-windows on - -# split panes -bind / split-window -hc "#{pane_current_path}" -bind - split-window -vc "#{pane_current_path}" - -bind c new-window - -bind -r "<" swap-window -d -t -1 -bind -r ">" swap-window -d -t +1 - -bind r source-file ~/.tmux.conf - -bind -n C-h select-pane -L -bind -n C-j select-pane -D -bind -n C-k select-pane -U -bind -n C-l select-pane -R - -# Smart pane switching with awareness of Vim splits. -# See: https://github.com/christoomey/vim-tmux-navigator - -# decide whether we're in a Vim process -is_vim="ps -o state= -o comm= -t '#{pane_tty}' \ - | grep -iqE '^[^TXZ ]+ +(\\S+\\/)?g?(view|n?vim?x?)(diff)?$'" - -bind-key -n 'C-h' if-shell "$is_vim" 'send-keys C-h' 'select-pane -L' -bind-key -n 'C-j' if-shell "$is_vim" 'send-keys C-j' 'select-pane -D' -bind-key -n 'C-k' if-shell "$is_vim" 'send-keys C-k' 'select-pane -U' -bind-key -n 'C-l' if-shell "$is_vim" 'send-keys C-l' 'select-pane -R' - -tmux_version='$(tmux -V | sed -En "s/^tmux ([0-9]+(.[0-9]+)?).*/\1/p")' - -if-shell -b '[ "$(echo "$tmux_version < 3.0" | bc)" = 1 ]' \ - "bind-key -n 'C-\\' if-shell \"$is_vim\" 'send-keys C-\\' 'select-pane -l'" -if-shell -b '[ "$(echo "$tmux_version >= 3.0" | bc)" = 1 ]' \ - "bind-key -n 'C-\\' if-shell \"$is_vim\" 'send-keys C-\\\\' 'select-pane -l'" - -bind-key -n 'C-Space' if-shell "$is_vim" 'send-keys C-Space' 'select-pane -t:.+' - -bind-key -T copy-mode-vi 'C-h' select-pane -L -bind-key -T copy-mode-vi 'C-j' select-pane -D -bind-key -T copy-mode-vi 'C-k' select-pane -U -bind-key -T copy-mode-vi 'C-l' select-pane -R -bind-key -T copy-mode-vi 'C-\' select-pane -l -bind-key -T copy-mode-vi 'C-Space' select-pane -t:.+ diff --git a/dot_tmux.conf.tmpl b/dot_tmux.conf.tmpl new file mode 100644 index 0000000..6c53841 --- /dev/null +++ b/dot_tmux.conf.tmpl @@ -0,0 +1,5 @@ +{{- if eq .chezmoi.hostname "gentoo" -}} +{{ include "tmux/gentoo.conf" -}} +{{- else -}} +{{ include "tmux/common.conf" -}} +{{- end -}} diff --git a/dot_zshrc.tmpl b/dot_zshrc.tmpl index 302201d..7ca280e 100644 --- a/dot_zshrc.tmpl +++ b/dot_zshrc.tmpl @@ -49,6 +49,8 @@ alias ls='eza --icons=always' eval "$(mise activate zsh)" +[[ -r ~/.config/secrets/openrouter.env ]] && source ~/.config/secrets/openrouter.env + path+=("/home/pablu/.cargo/bin") export PATH {{ else if eq .chezmoi.os "darwin" }} diff --git a/tmux/common.conf b/tmux/common.conf new file mode 100644 index 0000000..f3c03bd --- /dev/null +++ b/tmux/common.conf @@ -0,0 +1,57 @@ +# remap prefix +set-option -g prefix C-Space +unbind C-Space +bind-key C-Space send-prefix + +set -g mouse on + +set -g base-index 1 +setw -g pane-base-index 1 + +set -sg escape-time 10 + +set -g renumber-windows on + +# split panes +bind / split-window -hc "#{pane_current_path}" +bind - split-window -vc "#{pane_current_path}" + +bind c new-window + +bind -r "<" swap-window -d -t -1 +bind -r ">" swap-window -d -t +1 + +bind r source-file ~/.tmux.conf + +bind -n C-h select-pane -L +bind -n C-j select-pane -D +bind -n C-k select-pane -U +bind -n C-l select-pane -R + +# Smart pane switching with awareness of Vim splits. +# See: https://github.com/christoomey/vim-tmux-navigator + +# decide whether we're in a Vim process +is_vim="ps -o state= -o comm= -t '#{pane_tty}' \ + | grep -iqE '^[^TXZ ]+ +(\\S+\\/)?g?(view|n?vim?x?)(diff)?$'" + +bind-key -n 'C-h' if-shell "$is_vim" 'send-keys C-h' 'select-pane -L' +bind-key -n 'C-j' if-shell "$is_vim" 'send-keys C-j' 'select-pane -D' +bind-key -n 'C-k' if-shell "$is_vim" 'send-keys C-k' 'select-pane -U' +bind-key -n 'C-l' if-shell "$is_vim" 'send-keys C-l' 'select-pane -R' + +tmux_version='$(tmux -V | sed -En "s/^tmux ([0-9]+(.[0-9]+)?).*/\1/p")' + +if-shell -b '[ "$(echo "$tmux_version < 3.0" | bc)" = 1 ]' \ + "bind-key -n 'C-\\' if-shell \"$is_vim\" 'send-keys C-\\' 'select-pane -l'" +if-shell -b '[ "$(echo "$tmux_version >= 3.0" | bc)" = 1 ]' \ + "bind-key -n 'C-\\' if-shell \"$is_vim\" 'send-keys C-\\\\' 'select-pane -l'" + +bind-key -n 'C-Space' if-shell "$is_vim" 'send-keys C-Space' 'select-pane -t:.+' + +bind-key -T copy-mode-vi 'C-h' select-pane -L +bind-key -T copy-mode-vi 'C-j' select-pane -D +bind-key -T copy-mode-vi 'C-k' select-pane -U +bind-key -T copy-mode-vi 'C-l' select-pane -R +bind-key -T copy-mode-vi 'C-\' select-pane -l +bind-key -T copy-mode-vi 'C-Space' select-pane -t:.+ diff --git a/tmux/gentoo.conf b/tmux/gentoo.conf new file mode 100644 index 0000000..9643dc6 --- /dev/null +++ b/tmux/gentoo.conf @@ -0,0 +1,69 @@ +# remap prefix +set-option -g prefix C-Space +unbind C-Space +bind-key C-Space send-prefix + +set -g mouse on + +set -g base-index 1 +setw -g pane-base-index 1 + +set -g renumber-windows on +set -g set-clipboard on +set -g pane-border-status off +set -g history-limit 100000 + +set -g set-titles on +set -g set-titles-string "#S:#W" +# Keep project-style session names intact in the default status-left format. +set -g status-left-length 30 + +set -g automatic-rename off +set -g allow-rename off + +# Proper RGB/truecolor support in Ghostty. +set -as terminal-features ",xterm-ghostty:RGB" +set -as terminal-features ',*:hyperlinks' + +# Forward terminal focus changes to applications. +# Useful for Neovim FocusGained/FocusLost, auto-reloading files, etc. +set -g focus-events on + +# Don't introduce noticeable Escape latency. +set -sg escape-time 10 + +# split panes +bind / split-window -hc "#{pane_current_path}" +bind - split-window -vc "#{pane_current_path}" +bind c new-window -c "#{pane_current_path}" +bind z resize-pane -Z +bind x kill-pane +bind Tab last-window +# Return to the previously used session/project. +bind B switch-client -l +# Choose or create a project session in a compact popup picker. +bind w display-popup -E -B "~/.local/bin/tmux-project-switcher" + +bind -r "<" swap-pane -d -t -1 +bind -r ">" swap-pane -d -t +1 + +bind r source-file ~/.tmux.conf + +bind -n C-h select-pane -L +bind -n C-j select-pane -D +bind -n C-k select-pane -U +bind -n C-l select-pane -R + +# Plugins +set -g @plugin 'tmux-plugins/tpm' +set -g @plugin 'tmux-plugins/tmux-resurrect' +set -g @plugin 'tmux-plugins/tmux-continuum' + +# Automatically restore the latest saved environment +set -g @continuum-restore 'on' + +# Save every 5 minutes instead of the default 15. +set -g @continuum-save-interval '5' + +# Keep TPM last +run '~/.tmux/plugins/tpm/tpm' -- cgit 1.3.1