mirror of
https://github.com/prdlk/dotfiles.git
synced 2026-11-02 11:32:42 +00:00
feat(config): add television cable integration and related keybindings across shells
This commit is contained in:
1 parent
f033b29a7d
commit
3c4af515fa
12 files changed
+137
-21
No files matched your search
@@ -12,6 +12,10 @@ bun.lock
|
|||||||
public
|
public
|
||||||
dist
|
dist
|
||||||
|
|
||||||
|
# Linked, not copied: ~/.config/television is a symlink to this directory
|
||||||
|
# (dot_config/symlink_television.tmpl), so edits apply without chezmoi apply.
|
||||||
|
television
|
||||||
|
|
||||||
# Runtime/plugin state living inside managed trees — not managed
|
# Runtime/plugin state living inside managed trees — not managed
|
||||||
.config/lazygit/.omc/**
|
.config/lazygit/.omc/**
|
||||||
.config/yazi/plugins/**
|
.config/yazi/plugins/**
|
||||||
|
|||||||
+11
@@ -16,6 +16,11 @@ export GOPATH="$HOME/.local/share/go"
|
|||||||
export GOBIN="$GOPATH/bin"
|
export GOBIN="$GOPATH/bin"
|
||||||
case ":$PATH:" in *":$GOBIN:"*) ;; *) PATH="$GOBIN:$PATH" ;; esac
|
case ":$PATH:" in *":$GOBIN:"*) ;; *) PATH="$GOBIN:$PATH" ;; esac
|
||||||
|
|
||||||
|
# Repo roots (ghq) — same as fish's conf.d/10-env.fish; the ghq-repos tv
|
||||||
|
# cable (ctrl-o) lists this root.
|
||||||
|
export GHQ_ROOT="$HOME/Code"
|
||||||
|
export CODE_ROOT="$HOME/Code"
|
||||||
|
|
||||||
# Android SDK — relocated under ~/.local/share/android.
|
# Android SDK — relocated under ~/.local/share/android.
|
||||||
export ANDROID_HOME="$HOME/.local/share/android"
|
export ANDROID_HOME="$HOME/.local/share/android"
|
||||||
export ANDROID_SDK_ROOT="$ANDROID_HOME"
|
export ANDROID_SDK_ROOT="$ANDROID_HOME"
|
||||||
@@ -46,5 +51,11 @@ fi
|
|||||||
# Prompt — starship, consistent with fish
|
# Prompt — starship, consistent with fish
|
||||||
command -v starship >/dev/null 2>&1 && eval "$(starship init bash)"
|
command -v starship >/dev/null 2>&1 && eval "$(starship init bash)"
|
||||||
|
|
||||||
|
# television: _tv completion (its ctrl-r is taken over by atuin below)
|
||||||
|
command -v tv >/dev/null 2>&1 && eval "$(tv init bash)"
|
||||||
|
|
||||||
|
# Readline keybinds — bash ports of fish_user_key_bindings.fish (tv cables)
|
||||||
|
[ -f "$HOME/.config/bash/keybinds.bash" ] && . "$HOME/.config/bash/keybinds.bash"
|
||||||
|
|
||||||
. "$HOME/.atuin/bin/env"
|
. "$HOME/.atuin/bin/env"
|
||||||
eval "$(atuin init bash)"
|
eval "$(atuin init bash)"
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
# Pick a ghq repo / Obsidian vault + cd; picker lives in ~/.local/bin/gho.
|
# Pick a ghq repo / Obsidian vault with tv (ghq-repos cable) + cd.
|
||||||
gho() {
|
gho() {
|
||||||
local dir
|
local dir
|
||||||
dir=$(command gho) || return
|
dir=$(tv ghq-repos) || return
|
||||||
|
[ -n "$dir" ] || return
|
||||||
cd "$dir" || return
|
cd "$dir" || return
|
||||||
clear
|
clear
|
||||||
if [ -d .git ]; then
|
if [ -d .git ]; then
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
# ~/.config/bash/keybinds.bash — readline ports of the television keys in
|
||||||
|
# fish_user_key_bindings.fish / zsh keybinds.zsh:
|
||||||
|
# ctrl-o → gho (ghq-repos cable, cd) ctrl-e → tv git-files (nvim)
|
||||||
|
# ctrl-p → pj (pj cable) down → pj on an empty prompt
|
||||||
|
# ctrl-t → tv smart autocomplete (tv init bash ships no ctrl-t)
|
||||||
|
# Keys owned by kitty.conf never reach the shell: ctrl-h/j/k/l (pass_keys.py).
|
||||||
|
|
||||||
|
# bind -x runs in the shell process, so gho's cd persists — but readline keeps
|
||||||
|
# drawing the prompt it started with. Each key is therefore a macro: \C-xN
|
||||||
|
# stashes the typed line and runs the command, \C-m accepts the now-empty
|
||||||
|
# line (bash prints a fresh prompt for the new cwd; nothing reaches history),
|
||||||
|
# and \C-x0 restores the stash into the new line.
|
||||||
|
_kb_run() {
|
||||||
|
_kb_line=$READLINE_LINE _kb_point=$READLINE_POINT
|
||||||
|
READLINE_LINE='' READLINE_POINT=0
|
||||||
|
"$@" </dev/tty
|
||||||
|
}
|
||||||
|
_kb_restore() {
|
||||||
|
READLINE_LINE=${_kb_line-} READLINE_POINT=${_kb_point-0}
|
||||||
|
unset _kb_line _kb_point
|
||||||
|
}
|
||||||
|
bind -x '"\C-x0": _kb_restore'
|
||||||
|
|
||||||
|
# _kb_bind KEY SLOT COMMAND…
|
||||||
|
_kb_bind() {
|
||||||
|
local key=$1 slot=$2
|
||||||
|
shift 2
|
||||||
|
bind -x "\"\\C-x$slot\": _kb_run $*"
|
||||||
|
bind "\"$key\": \"\\C-x$slot\\C-m\\C-x0\""
|
||||||
|
}
|
||||||
|
_kb_bind '\C-o' 1 gho
|
||||||
|
_kb_bind '\C-e' 2 tv git-files
|
||||||
|
_kb_bind '\C-p' 3 pj
|
||||||
|
|
||||||
|
# down: the pj cable on an idle, empty prompt, otherwise history search
|
||||||
|
# (fish's _pj_bind_down). bind -x can't call readline functions, so _kb_down
|
||||||
|
# rebinds \C-x5, which the macro sends right after it.
|
||||||
|
_kb_down() {
|
||||||
|
if [ -n "$READLINE_LINE" ]; then
|
||||||
|
bind '"\C-x5": history-search-forward'
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
PJ_QUIET=1 pj </dev/tty
|
||||||
|
bind '"\C-x5": redraw-current-line'
|
||||||
|
}
|
||||||
|
bind -x '"\C-x4": _kb_down'
|
||||||
|
bind '"\e[B": "\C-x4\C-x5"'
|
||||||
|
bind '"\eOB": "\C-x4\C-x5"'
|
||||||
|
|
||||||
|
# ctrl-t: pick with the channel tv guesses from the text left of the cursor
|
||||||
|
# (shell_integration.channel_triggers) and insert the picks there, quoted.
|
||||||
|
_kb_tv_autocomplete() {
|
||||||
|
local pre=${READLINE_LINE:0:READLINE_POINT} out item ins=''
|
||||||
|
out=$(tv --autocomplete-prompt "$pre" </dev/tty) || return
|
||||||
|
while IFS= read -r item; do
|
||||||
|
[ -n "$item" ] && ins+="$(printf '%q' "$item") "
|
||||||
|
done <<<"$out"
|
||||||
|
READLINE_LINE=$pre$ins${READLINE_LINE:READLINE_POINT}
|
||||||
|
READLINE_POINT=$((${#pre} + ${#ins}))
|
||||||
|
}
|
||||||
|
bind -x '"\C-t": _kb_tv_autocomplete'
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
function _pj_bind_down --description "down arrow: pj on an idle empty prompt, else fish's down-or-search"
|
function _pj_bind_down --description "down arrow: pj tv cable on an idle empty prompt, else fish's down-or-search"
|
||||||
# Mirror of atuin's up binding (atuin owns up, this owns down). Everything
|
# Mirror of atuin's up binding (atuin owns up, this owns down). Everything
|
||||||
# that legitimately needs the arrow keys keeps them:
|
# that legitimately needs the arrow keys keeps them:
|
||||||
# - non-empty buffer → multiline cursor movement / forward history search
|
# - non-empty buffer → multiline cursor movement / forward history search
|
||||||
@@ -13,9 +13,9 @@ function _pj_bind_down --description "down arrow: pj on an idle empty prompt, el
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
# pj is ~/.local/bin/pj (shared with the zsh ctrl-p binding). PJ_QUIET
|
# pj is ~/.local/bin/pj (also ctrl-p), which opens the `pj` tv cable.
|
||||||
# keeps it silent when the tree has no task source at all, so down is a
|
# PJ_QUIET keeps it silent when the tree has no task source at all, so
|
||||||
# no-op outside projects instead of printing an error on every press.
|
# down is a no-op outside projects instead of printing an error per press.
|
||||||
PJ_QUIET=1 pj
|
PJ_QUIET=1 pj
|
||||||
commandline -f repaint
|
commandline -f repaint
|
||||||
end
|
end
|
||||||
@@ -10,8 +10,9 @@ function fish_user_key_bindings
|
|||||||
# Keys owned by kitty.conf never reach fish and are NOT bound here:
|
# Keys owned by kitty.conf never reach fish and are NOT bound here:
|
||||||
# ctrl-g → lazygit overlay, ctrl-a → omp hsplit, ctrl-y → yazi vsplit,
|
# ctrl-g → lazygit overlay, ctrl-a → omp hsplit, ctrl-y → yazi vsplit,
|
||||||
# ctrl-h/j/k/l → vim-aware split nav (pass_keys.py).
|
# ctrl-h/j/k/l → vim-aware split nav (pass_keys.py).
|
||||||
# ctrl-e: yazi, same as ctrl-f (cd's to yazi's exit dir on quit).
|
# ctrl-e: tv git-files (bat preview, enter opens nvim). ctrl-o, ctrl-p
|
||||||
bind -M $mode ctrl-e 'yy; commandline -f repaint'
|
# and down also open tv cables — same keys in zsh and bash.
|
||||||
|
bind -M $mode ctrl-e 'tv git-files; commandline -f repaint'
|
||||||
bind -M $mode ctrl-b purple repaint
|
bind -M $mode ctrl-b purple repaint
|
||||||
bind -M $mode ctrl-y clip-last
|
bind -M $mode ctrl-y clip-last
|
||||||
|
|
||||||
@@ -22,10 +23,11 @@ function fish_user_key_bindings
|
|||||||
|
|
||||||
# Arrow keys: atuin owns up (bound from config.fish, survives the
|
# Arrow keys: atuin owns up (bound from config.fish, survives the
|
||||||
# fish_vi_key_bindings reset above because that only erases presets),
|
# fish_vi_key_bindings reset above because that only erases presets),
|
||||||
# down runs pj — but only on an idle, empty prompt; see _pj_bind_down.
|
# down opens the pj tv cable — but only on an idle, empty prompt; see
|
||||||
|
# _pj_bind_down.
|
||||||
bind -M $mode down _pj_bind_down
|
bind -M $mode down _pj_bind_down
|
||||||
|
|
||||||
# ctrl-f: pick file(s) with television and open in nvim.
|
# ctrl-f: yazi (cd's to yazi's exit dir on quit).
|
||||||
bind -M $mode ctrl-f 'yy; commandline -f repaint'
|
bind -M $mode ctrl-f 'yy; commandline -f repaint'
|
||||||
bind -M $mode ctrl-g 'lazygit; commandline -f repaint'
|
bind -M $mode ctrl-g 'lazygit; commandline -f repaint'
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
function gho --description 'pick ghq repo / Obsidian vault + cd (picker in ~/.local/bin/gho)'
|
function gho --description 'pick a ghq repo / Obsidian vault (tv ghq-repos cable) + cd'
|
||||||
set -l dir (command gho); or return
|
set -l dir (tv ghq-repos); or return
|
||||||
|
test -n "$dir"; or return
|
||||||
cd $dir; or return
|
cd $dir; or return
|
||||||
clear
|
clear
|
||||||
if test -d .git
|
if test -d .git
|
||||||
|
|||||||
@@ -4,10 +4,11 @@ from kittens.tui.handler import result_handler
|
|||||||
from kitty.key_encoding import KeyEvent, parse_shortcut
|
from kitty.key_encoding import KeyEvent, parse_shortcut
|
||||||
|
|
||||||
# Windows whose foreground process owns <C-h/j/k/l> itself: (n)vim and fzf move
|
# Windows whose foreground process owns <C-h/j/k/l> itself: (n)vim and fzf move
|
||||||
# their own splits/selection, and tmux/herdr run the same vim-aware handoff one
|
# their own splits/selection, tv binds ctrl-h to goto_parent_dir, and tmux/herdr
|
||||||
# layer down (tmux.conf `is_vim`, vim-herdr-navigation). Anything else means
|
# run the same vim-aware handoff one layer down (tmux.conf `is_vim`,
|
||||||
# kitty owns the panes, so kitty moves its own window.
|
# vim-herdr-navigation). Anything else means kitty owns the panes, so kitty
|
||||||
PASSTHROUGH = r'\b(vim|nvim|fzf|tmux|herdr)\b'
|
# moves its own window.
|
||||||
|
PASSTHROUGH = r'\b(vim|nvim|fzf|tv|tmux|herdr)\b'
|
||||||
|
|
||||||
|
|
||||||
# Return True if any foreground process in the window matches PASSTHROUGH
|
# Return True if any foreground process in the window matches PASSTHROUGH
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
{{ .chezmoi.sourceDir }}/television
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
# Pick a ghq repo / Obsidian vault + cd; picker lives in ~/.local/bin/gho.
|
# Pick a ghq repo / Obsidian vault with tv (ghq-repos cable) + cd.
|
||||||
gho() {
|
gho() {
|
||||||
local dir
|
local dir
|
||||||
dir=$(command gho) || return
|
dir=$(tv ghq-repos) || return
|
||||||
|
[ -n "$dir" ] || return
|
||||||
cd "$dir" || return
|
cd "$dir" || return
|
||||||
clear
|
clear
|
||||||
if [ -d .git ]; then
|
if [ -d .git ]; then
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ unsetopt flow_control # free ^Q/^S in zle so the ctrl-q exit bind fires
|
|||||||
# Generic runner: widget `run-<cmd>` executes <cmd> (function or binary) with
|
# Generic runner: widget `run-<cmd>` executes <cmd> (function or binary) with
|
||||||
# the tty as stdin, then repaints — fish's `commandline -f repaint`.
|
# the tty as stdin, then repaints — fish's `commandline -f repaint`.
|
||||||
# cwd changes from gho/yy persist: widgets run in the shell process.
|
# cwd changes from gho/yy persist: widgets run in the shell process.
|
||||||
|
# gho, pj and `tv git-files` open television cables (~/.config/television/
|
||||||
|
# cable) — the same keys do the same in fish and bash.
|
||||||
_zle-run() {
|
_zle-run() {
|
||||||
local cmd=${WIDGET#run-}
|
local cmd=${WIDGET#run-}
|
||||||
zle -I
|
zle -I
|
||||||
@@ -19,17 +21,39 @@ for _cmd in purple clip-last gho pj omp yy lazygit; do
|
|||||||
done
|
done
|
||||||
unset _cmd
|
unset _cmd
|
||||||
|
|
||||||
# ctrl-e: yazi, same as ctrl-f (cd's to yazi's exit dir on quit).
|
# ctrl-e: tv git-files (bat preview, enter opens nvim).
|
||||||
bindkey '^E' run-yy
|
_zle-tv-git-files() {
|
||||||
|
zle -I
|
||||||
|
tv git-files </dev/tty
|
||||||
|
zle reset-prompt
|
||||||
|
}
|
||||||
|
zle -N tv-git-files _zle-tv-git-files
|
||||||
|
bindkey '^E' tv-git-files
|
||||||
bindkey '^B' run-purple
|
bindkey '^B' run-purple
|
||||||
bindkey '^Y' run-clip-last
|
bindkey '^Y' run-clip-last
|
||||||
bindkey '^O' run-gho
|
bindkey '^O' run-gho
|
||||||
bindkey '^P' run-pj
|
bindkey '^P' run-pj
|
||||||
bindkey '^A' run-omp
|
bindkey '^A' run-omp
|
||||||
# ctrl-f: pick file(s) and open in nvim; yy also cd's to yazi's exit dir.
|
# ctrl-f: yazi; yy cd's to yazi's exit dir on quit.
|
||||||
bindkey '^F' run-yy
|
bindkey '^F' run-yy
|
||||||
bindkey '^G' run-lazygit
|
bindkey '^G' run-lazygit
|
||||||
|
|
||||||
|
# down: the pj cable on an idle, empty prompt; otherwise normal history /
|
||||||
|
# multiline movement (fish's _pj_bind_down). PJ_QUIET makes it a silent no-op
|
||||||
|
# outside projects.
|
||||||
|
_zle-pj-down() {
|
||||||
|
if [[ -n $BUFFER ]]; then
|
||||||
|
zle down-line-or-history
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
zle -I
|
||||||
|
PJ_QUIET=1 pj </dev/tty
|
||||||
|
zle reset-prompt
|
||||||
|
}
|
||||||
|
zle -N pj-down _zle-pj-down
|
||||||
|
bindkey '^[[B' pj-down
|
||||||
|
bindkey '^[OB' pj-down
|
||||||
|
|
||||||
# ctrl-q mirrors ctrl-d's preset (`exit`) — quit the shell.
|
# ctrl-q mirrors ctrl-d's preset (`exit`) — quit the shell.
|
||||||
_zle-exit() { exit }
|
_zle-exit() { exit }
|
||||||
zle -N _zle-exit
|
zle -N _zle-exit
|
||||||
|
|||||||
@@ -20,6 +20,11 @@ export GOPATH="$HOME/.local/share/go"
|
|||||||
export GOBIN="$GOPATH/bin"
|
export GOBIN="$GOPATH/bin"
|
||||||
case ":$PATH:" in *":$GOBIN:"*) ;; *) PATH="$GOBIN:$PATH" ;; esac
|
case ":$PATH:" in *":$GOBIN:"*) ;; *) PATH="$GOBIN:$PATH" ;; esac
|
||||||
|
|
||||||
|
# Repo roots (ghq) — same as fish's conf.d/10-env.fish; the ghq-repos tv
|
||||||
|
# cable (ctrl-o) lists this root.
|
||||||
|
export GHQ_ROOT="$HOME/Code"
|
||||||
|
export CODE_ROOT="$HOME/Code"
|
||||||
|
|
||||||
# Android SDK — relocated under ~/.local/share/android.
|
# Android SDK — relocated under ~/.local/share/android.
|
||||||
export ANDROID_HOME="$HOME/.local/share/android"
|
export ANDROID_HOME="$HOME/.local/share/android"
|
||||||
export ANDROID_SDK_ROOT="$ANDROID_HOME"
|
export ANDROID_SDK_ROOT="$ANDROID_HOME"
|
||||||
@@ -52,6 +57,10 @@ command -v suv >/dev/null 2>&1 && eval "$(suv init zsh)"
|
|||||||
# Prompt — starship, consistent with fish
|
# Prompt — starship, consistent with fish
|
||||||
command -v starship >/dev/null 2>&1 && eval "$(starship init zsh)"
|
command -v starship >/dev/null 2>&1 && eval "$(starship init zsh)"
|
||||||
|
|
||||||
|
# television: ctrl-t smart autocomplete (its ctrl-r is taken over by atuin
|
||||||
|
# below, as in fish)
|
||||||
|
command -v tv >/dev/null 2>&1 && eval "$(tv init zsh)"
|
||||||
|
|
||||||
# Fish-style syntax highlighting (zsh-users/zsh-syntax-highlighting).
|
# Fish-style syntax highlighting (zsh-users/zsh-syntax-highlighting).
|
||||||
# MUST stay last in .zshrc: it wraps every zle widget defined above
|
# MUST stay last in .zshrc: it wraps every zle widget defined above
|
||||||
# (keybinds, compinit, suv/starship hooks).
|
# (keybinds, compinit, suv/starship hooks).
|
||||||
|
|||||||
Reference in new issue
Block a user