diff options
author | Nicholas Marriott <nicholas.marriott@gmail.com> | 2021-08-30 08:24:43 +0100 |
---|---|---|
committer | Nicholas Marriott <nicholas.marriott@gmail.com> | 2021-08-30 08:24:43 +0100 |
commit | d62aee506b9b9868b806319502f2b753cafe96ef (patch) | |
tree | 1641fb43ffc226732abb9e381ccf09eec97faada /regress | |
parent | 388f0fe973869baeb06982ecaaf2a263c6f8fd2c (diff) |
Regress conf from https://raw.githubusercontent.com/lacygoill/config/master/.config/tmux/tmux.conf.
Diffstat (limited to 'regress')
-rw-r--r-- | regress/conf/01840240e807e837dbf76d85b4b938de.conf | 1496 |
1 files changed, 1496 insertions, 0 deletions
diff --git a/regress/conf/01840240e807e837dbf76d85b4b938de.conf b/regress/conf/01840240e807e837dbf76d85b4b938de.conf new file mode 100644 index 00000000..dcd4899e --- /dev/null +++ b/regress/conf/01840240e807e837dbf76d85b4b938de.conf @@ -0,0 +1,1496 @@ +# Options {{{1 +# Server {{{2 + +# Don't pile up more than 10 buffers (down from 50 by default).{{{ +# +# Rationale: Keeping a tidy stack, with relevant information, could help us +# integrate tmux buffers in our workflow more often. +# +# However, maybe we could keep a big stack of buffers, and filter them by +# pressing `f` in the window opened by `choose-buffer`. +# Alternatively, we could also try to use fzf to fuzzy search through their +# contents... +#}}} +set -s buffer-limit 10 + + +# What does this option control?{{{ +# +# It sets the time in milliseconds for which tmux waits after an escape is input +# to determine if it is part of a function or meta key sequences. +# The default is 500 millisec onds. +#}}} +# Why do you reset it?{{{ +# +# The default value introduces lag when we use Vim and escape from insert to +# normal mode. We want to reduce the timeout. +#}}} +# Why don't you set it to 0 ?{{{ +# +# > Some people set it to zero but I consider that risky if you're connecting +# > over a wide-area network or there is anything else that might insert small +# > delays between the delivery of chars in such a sequence. +# +# Source: https://github.com/tmux/tmux/issues/353#issuecomment-294570322 +# +# Basically, we should still let a few ms to be sure all the keys in a control +# sequence will have enough time to reach tmux. +#}}} +set -s escape-time 10 + +# If the terminal supports focus events, they will be requested by the tmux +# client and passed through to the tmux server, then to the programs it runs. +# Necessary to be able to listen to `FocusGained` and `FocusLost`. +# Also necessary for `pane-focus-[in|out]` hooks. +set -s focus-events on + +# history of tmux commands (pfx :) +set -s history-file "$HOME/.tmux/command_history" + +# What does this do?{{{ +# +# It makes tmux sometimes send an OSC 52 sequence – which sets the terminal +# clipboard content – if there is an `Ms` entry in the terminfo description of +# the outer terminal. +#}}} +# What are the possible values of this option?{{{ +# +# - `on` +# - `external` +# - `off` +# +# --- +# +# There are 3 ways to create a tmux buffer: +# +# 1. invoke the `set-buffer` or `load-buffer` tmux commands +# 2. copy text in copy mode (`send -X copy-selection`, `copy-pipe`, ...) +# 3. send an OSC 52 sequence from an application inside tmux (e.g. `$ printf ...`) +# +# `1.` always creates a tmux buffer; never sets the X clipboard. +# `2.` always creates a tmux buffer; sets the X clipboard via OSC 52 iff `set-clipboard` is not `off`. +# `3.` creates a tmux buffer *and* sets the X clipboard via OSC 52 iff `set-clipboard` is `on`. +# +# IOW, `external` makes tmux *automatically* set the X clipboard when you yank +# sth in copy mode via OSC 52, while `on` does the same, but also allows an +# application to *manually* set a tmux buffer/the X clipboard via a OSC 52. +# +# Source: https://unix.stackexchange.com/a/560464/289772 +#}}} +# What is the possible drawback of the value `on`?{{{ +# +# https://github.com/tmux/tmux/wiki/Clipboard#security-concerns +#}}} +# How to disable OSC 52 for some terminals, but not all?{{{ +# +# # or use 'external' +# set -s set-clipboard on +# set -as terminal-overrides 'yourTERMname:Ms@' +# ^ +# man terminfo /Similar Terminals/;/canceled +#}}} +set -s set-clipboard external + +# Why do you move your 'terminal-overrides' settings in another file?{{{ +# +# It makes it easier to source the settings only when the tmux server is started; +# not when we manually re-source `tmux.conf`. +#}}} +# Why do you need them to be sourced only once?{{{ +# +# We *append* strings to the value of the 'terminal-overrides' option. +# I don't want to append the same strings again and again every time I re-source +# `tmux.conf`. +#}}} +# Why don't you simply reset the option before appending a value?{{{ +# +# That would make us lose the default value of the option: +# +# terminal-overrides[0] "xterm*:XT:Ms=\\E]52;%p1%s;%p2%s\\007:Cs=\\E]12;%p1%s\\007:Cr=\\E]112\\007:Ss=\\E[%p1%d q:Se=\\E[2 q" +# terminal-overrides[1] screen*:XT +# +# --- +# +# Besides, one of the value we append to 'terminal-overrides' depends on the value of `$TERM`. +# +# if '[ "$TERM" != "st-256color" ]' 'set -as terminal-overrides ",*:Cr=\\E]112\\007"' +# ^----------------------^ +# +# And the value of `$TERM` will be correct only the first time we source `tmux.conf`. +#}}} + +# What's the value of `$TERM` here?{{{ +# +# The first time our `tmux.conf` is sourced, it matches the `$TERM` of the +# outer terminal; the next times, it's the value of 'default-terminal' (i.e. +# 'tmux-256color'). +#}}} +# What's the meaning of this `if` guard?{{{ +# +# The condition `[ "$TERM" != "tmux-256color" ]` is true only the first time our +# `tmux.conf` is sourced. +# So, this part of the guard means: “if this is the first time the file is sourced”. +# This is equivalent to `has('vim_starting')` in Vim. +# +# The condition `[ -n "$DISPLAY" ]` is true only in a GUI environment. +# So, this part of the guard means: “don't source the file if we are in a console”. +# Indeed, I doubt a linux console is able to understand any sequence we might +# want to use. +#}}} +# Could we use `%if` instead of `if`?{{{ +# +# You could try this: +# +# %if "#{!=:$TERM,#{default-terminal}}" +# source-file "$HOME/.config/tmux/terminal-overrides.conf" +# %endif +# +# But it doesn't seem to work; the guard would not prevent the file from being re-sourced. +# I think that's because, in this case, `$TERM` refers to the value in the +# environment of the tmux server process; and for the latter, `TERM` always +# matches the outer terminal. +#}}} +if '[ "$TERM" != "#{default-terminal}" -a -n "$DISPLAY" ]' { source "$HOME/.config/tmux/terminal-overrides.conf" } + +# Leave `default-terminal` at the end.{{{ +# +# In my limited testing, moving it above would not cause an issue, but better be +# safe than sorry. +# In particular, I want to be sure that the value of `$TERM` is not +# 'tmux-256color' the first time our `tmux.conf` is sourced; otherwise +# `terminal-overrides.conf` would never be sourced. +#}}} +# Why `-s` instead of `-g`? {{{ +# +# Since tmux 2.1, `default-terminal` is a server option, not a session option. +# +# > As a side effect this changes default-terminal to be a server rather than a +# > session option. +# +# https://github.com/tmux/tmux/commit/7382ba82c5b366be84ca55c7842426bcf3d1f521 +# Confirmed by the fact that `default-terminal` is described in the section of +# the server options in the man page. +# Also confirmed by the fact that it's listed in the output of: +# +# tmux show -s +# +# However, according to nicm: +# +# > You do not have to use -s or -w for set-option except for user options. +# > tmux can work it out from the option name. +# > For show-option you do need it. +# +# So, we could omit `-s`, but I prefer to be explicit. +#}}} +# Why not let tmux use the default value `screen` (for `$TERM`)?{{{ +# +# By default, most terminals set `$TERM` to `xterm` because the `xterm` entry is +# present and set in the terminfo db of most machines. +# tmux sets it to `screen`, again, because it's a popular entry (more than the +# `tmux` one). +# The `xterm`/`screen` value implies that the terminal will declare supporting +# only 8 colors; confirmed by `$ tput colors`. +# +# Because of this, the theme of some programs might be off (including Vim and +# the terminal itself). We want the terminal to declare it supports 256 colors, +# which anyway is usually true. +#}}} +# Do we need `$TERM` to contain `tmux`?{{{ +# +# Yes. To support italics: +# +# The `screen-256color` entry in the terminfo db doesn't have a `sitm` field. +# IOW, the db reports that screen is unable to support italics, which is true. +# So, if we set `$TERM` to `screen-256color`, when an application will want to +# make some text appear italicized, it will think it's not possible. +# But it *is* possible, because we use tmux, not screen. And tmux *does* +# support the italics style. +# The solution is to set `$TERM` to `tmux-256color` so that when an application +# queries the terminfo db, it finds the field `sitm` with the right value +# `\E[3m`. +# +# See also: +# https://github.com/tmux/tmux/wiki/FAQ#i-dont-see-italics-or-italics-and-reverse-are-the-wrong-way-round +# https://github.com/tmux/tmux/issues/175#issuecomment-152719805 +#}}} +# `256color`?{{{ +# +# For a Vim color scheme to be correctly applied, no. +# Because it seems that our current theme automatically sets the number of +# colors to 256: +# +# :runtime colors/seoul256.vim +# :echo &t_Co +# +# But, for the color schemes of other programs, maybe. +#}}} +set -s default-terminal tmux-256color + +# Session {{{2 + +# Don't ring the bell in the current window. +set -g bell-action other + +# Why?{{{ +# +# If a new window is created without any command to execute, tmux reads the +# session option `default-command` to find one. +# By default, its value is an empty string which instructs tmux to create a +# *login* shell using the value of the default-shell option. +# The default value of the latter is `$SHELL` (atm: `/usr/local/bin/zsh`). +# +# When we create a new window, we want a *non*-login shell, because a login zsh +# shell sources `~/.zprofile`, which we use to execute code specific to a +# virtual *console* (set the background to white in the console). +# This code is not suited to a virtual *terminal*. +# +# More generally, we don't want a *non*-login shell to source login files +# (`.profile`, `.zprofile`, `.zlogin`). +# +# So, we give the value zsh to `default-command` to prevent tmux from starting a +# login shell. +#}}} +set -g default-command "$SHELL" + +# Don't detach the client when the current session is killed. +set -g detach-on-destroy off + +# display status line messages and other on-screen indicators for 1s +# (or until a key is pressed) +set -g display-time 1000 +# display the indicators shown by the display-panes command for 5s +set -g display-panes-time 5000 + +# increase scrollback buffer (2000 → 50000) +# +# `history-limit` has nothing to do with the history of executed tmux commands. +# It controls the amount of lines you can scroll back when you enter copy mode. +set -g history-limit 50000 + +# Index options +# When we create a new window, tmux looks for an unused index, starting from 0.{{{ +# +# I prefer 1, because: +# +# - I usually count from 1, not 0 +# - this lets us run `:movew -t :0` to move the current window in first position +# +# Note that you can't run `:movew -t :1` to move the window in first position, +# because 1 is already taken by the first window. +# `:movew` expects an index which is “free” (i.e. not used by any existing window). +# +# Also, note that when running `:movew -t :0`, tmux renumbers all windows +# automatically from whatever value is assigned to the 'base-index' option. +#}}} +set -g base-index 1 +# │ +# └ must be applied globally to all sessions +# +# same thing for the panes +set -gw pane-base-index 1 +# ││ +# │└ window option +# └ must be applied globally to all windows + +# make tmux capture the mouse and allow mouse events to be bound as key bindings +set -g mouse on + +# use `M-space` as a prefix +set -g prefix M-space + +# renumber windows, when:{{{ +# +# - we destroy one of them +# - we move the first window (index 1) at the end (index 99), by running `movew -t :99` +# +# to prevent holes in the sequence of indexes +#}}} +set -g renumber-windows on + +# time for repeating of a hotkey bound using the -r flag without having to type the prefix again; default: 500 +set -g repeat-time 1000 + +# Some consoles don't like attempts to set the window title. +# This might cause tmux to freeze the terminal when you attach to a session. +# https://github.com/tmux/tmux/wiki/FAQ#tmux-freezes-my-terminal-when-i-attach-to-a-session-i-have-to-kill--9-the-shell-it-was-started-from-to-recover +set -g set-titles off + +# update the status line every 5 seconds (instead of 15s by default) +set -g status-interval 5 + +# emacs key bindings in tmux command prompt (prefix + :) are better than vi keys, +# even for vim users. +set -g status-keys emacs + +# color of status line +set -g -F status-style "bg=#{?#{==:$DISPLAY,},blue,colour138}" + +# Center the position of the window list component of the status line +set -g status-justify centre + +# cache the number of cpu cores in `~/.ncore`, which a shell command in 'status-right' is going to need +if '[ ! -s "${HOME}/.ncore" ]' \ + { run "lscpu | awk '/^CPU\\(s\\):\\s*[0-9]/ { print $2 }' >\"${HOME}/.ncore\"" } + +# set the contents of the status line +# What's `#[...]`?{{{ +# +# It lets you embed some styles. +# If you want to apply the same style all over the left part or the right part +# of the status line, you can also use `status-left-style` or `status-right-style`: +# +# set -g status-left '#[fg=colour15,bold] #S' +# ⇔ +# set -g status-left ' #S' +# set -g status-left-style '#[fg=colour15,bold]' +# +# However, I prefer embedding the styles inside the value of `status-left` and +# `status-right`, because: +# +# - it's more concise +# - it's more powerful: you can set the style of an arbitrary *portion* of the status line +# +# --- +# +# Note that you can use this syntax only in the value of an option which sets +# the *contents* of sth, not its style. +# So, this is *not* a valid syntax: +# +# # ✘ +# set -g status-left-style '#[fg=colour15,bold]' +# +# Here, you must get rid of `#[...]`: +# +# # ✔ +# set -g status-left-style 'fg=colour15,bold' +#}}} +# What's `#{?...}`?{{{ +# +# A conditional: +# +# #{?test,val1,val2} +# +# For example: +# +# {?client_prefix,#[bold],} +# +# This will be evaluated into the style `bold` if the prefix has been pressed, +# or nothing otherwise. +#}}} +# Why do you use `nobold`?{{{ +# +# We set the style `bold` for some part of the status line. +# But a style applies to *all* the remaining text in the status line. +# We need `nobold` to reset the style. +#}}} +# How can I include the time of the day or the hour in the status line?{{{ +# +# Use `date(1)` and `%` items: +# +# %a = day of week +# %d = day of month +# %b = month +# %R = hour +# +# See `man date`. +#}}} +set -g status-left ' #[fg=colour7]#{?client_prefix,#[fg=colour0],}#S#[fg=colour7]' + +# Which alternative could I use to get the cpu load?{{{ +# +# $ uptime|awk '{split(substr($0, index($0, "load")), a, ":"); print a[2]}' +# +# https://github.com/tmux/tmux/wiki/FAQ#what-is-the-best-way-to-display-the-load-average-why-no-l +#}}} +# Why don't you write the code in a script and invoke it with `#(my-script.sh)`?{{{ +# +# A script needs another shell to be interpreted. +# The latter adds overhead, which would almost double the time the code needs to +# be run. +# +# Check this: +# +# $ cat <<'EOF' >/tmp/sh.sh +# awk 'BEGIN { getline load <"/proc/loadavg"; getline ncore <(ENVIRON["HOME"]"/.ncore"); printf("%d", 100 * load / ncore) }' +# EOF +# $ chmod +x /tmp/sh.sh +# +# $ time zsh -c 'repeat 100 /tmp/sh.sh' +# ... 0,420 total˜ +# $ time zsh -c 'repeat 100 awk '\''BEGIN { getline load <"/proc/loadavg"; getline ncore <(ENVIRON["HOME"]"/.ncore"); printf("%d", 100 * load / ncore) }'\''' +# ... 0,193 total˜ +#}}} +# Why do you double the percent sign in `printf("%%d", ...)`?{{{ +# +# The code is going to be expanded inside the value of 'status-right'. +# And the latter is always passed to `strftime(3)` for which the percent sign +# has a special meaning. +# As a result, if you don't double the percent sign – to make it literal – `%d` +# will be replaced with the current day of the month (01, 02, ..., 31). +# +# From `man tmux /status-right`: +# +# > As with status-left, string will be passed to strftime(3) and character +# > pairs are replaced. +#}}} +cpu='awk '\''BEGIN { \ + getline load <"/proc/loadavg"; \ + getline ncore <(ENVIRON["HOME"]"/.ncore"); \ + printf("%%d", 100 * load / ncore) }'\''' + +mem='free | awk '\''/Mem/ { total = $2; used = $3 }; \ + END { printf("%%d", 100 * used / total) }'\''' +# TODO: Maybe we could get rid of `free(1)`, by inspecting `/proc/meminfo`. +# However, I can find the second field ("total") of `free(1)` in this file +# (first line: "MemTotal"), but not the third one ("used"). +# +# Update: From `man free`: +# +# used Used memory (calculated as total - free - buffers - cache) +# +# You would have to read 4 files to compute the `used` field. +# Make some tests (with `time(1)`) to see whether the resulting `awk(1)` command +# is slower than what we currently run. + +# TODO: Color the numbers in red if they exceed some threshold. +# Try to capture the output of the 2 shell commands in tmux variables, so that +# we can test them in a conditional. +set -g status-right '#[fg=colour235]M #[fg=colour15,bold]' +set -ga status-right "#($mem) " +set -ga status-right '#[fg=colour235,nobold]C #[fg=colour15,bold]' +set -ga status-right "#($cpu) " + +setenv -gu cpu +setenv -gu mem + +# Why do you want `COLORTERM` to be automatically updated?{{{ +# +# It can be useful to detect a terminal which lies about its identity. +# E.g., xfce4-terminal advertises itself as `xterm-256color`, but the value of +# its `COLORTERM` variable is 'xfce4-terminal'. +# +# So, the more reliable `COLORTERM` is, the better we can detect that we're in +# xfce4-terminal, and react appropriately. +# This can be useful, for example, to prevent vim-term from sending `CSI 2 SPC q` +# when we're leaving Vim from xfce4-terminal on Ubuntu 16.04. +# The latter doesn't understand this sequence, and once sent to the terminal, +# tmux will regularly reprint the sequence wherever our cursor is. +#}}} +# Why could I be tempted to run the same command for `LESSOPEN`, `LESSCLOSE`, `LS_COLORS`?{{{ +# +# setenv -gu LESSOPEN +# setenv -gu LESSCLOSE +# setenv -gu LS_COLORS +# +# These environment variables are set in `~/.zshenv`, but only on the condition +# they've not been set yet. +# The purpose of the condition is to make the shell quicker to start. +# Indeed, setting these variables adds around 8ms to the shell's startup time. +# However, if they are set in the tmux global environment, then they'll never be +# reset when we start a new shell, because the condition will never be +# satisfied. +# +# This means that we can't change the value of these variables by simply editing +# `~/.zshenv`, which can be an issue. +#}}} +# Why don't you do it?{{{ +# +# Because it would add around 8ms to the startup time of every shell we ask tmux +# to open. +#}}} +# Isn't this an issue?{{{ +# +# No. +# If you want to modify one of these variables, and if you want the change to be +# applied immediately without restarting the tmux server, do it in the context +# of the tmux global environment: +# +# $ tmux setenv -g LESSOPEN new_value +#}}} +if '[ "$TERM" != "#{default-terminal}" ]' { set -ga update-environment COLORTERM } +# TODO: We have several similar `if` conditions. Maybe we should write only one, +# and put inside all the commands we want to run. +# This would make tmux start a little faster. + +# display a message when activity is detected in a window +# Why?{{{ +# +# We haven't customized the status line to include an indicator when some +# activity is detected in a window, because by default we don't monitor activity +# ('monitor-activity' is off). +# Indeed, generally, most windows will produce some output and have some activity. +# Seeing a lot of indicators in the status line, all the time, is meaningless. +# +# But we do have a key binding to temporarily toggle 'monitor-activity' in the +# current window; so, we need a way to be notified when some activity is later +# detected in it. +#}}} +set -g visual-activity on + +# Window {{{2 + +# Use vi key bindings in copy mode. +set -gw mode-keys vi + +# colors of *borders* of focused and non-focused panes +set -gw pane-active-border-style 'fg=colour138,bg=#cacaca' +set -gw pane-border-style 'fg=colour138,bg=#cacaca' + +# How to insert the index of a window?{{{ +# +# Use the alias `#I`. +#}}} +# How to insert its flags, like `Z` for a zoomed window?{{{ +# +# Use the alias `#F`. +#}}} +# Set what to display for the current window (then for the other ones), and how, +# in the status line window list. +# See: https://github.com/tmux/tmux/issues/74#issuecomment-129130023 +set -gw window-status-current-format '#[fg=colour232,bg=colour253]#W#F#{?window_zoomed_flag, #[fg=blue]#P/#{window_panes},}' +set -gw window-status-format '#[fg=colour232#,bg=colour248]#W#F#[bg=default]' + +# Pane {{{2 + +# colors of focused and non-focused panes +# Because we use `-gw`, the colors will affect any pane.{{{ +# +# But, at runtime, you could use `-p` to set the color of a given pane when it's +# (un)focused differently. +#}}} +set -gw window-active-style 'bg=#dbd6d1' +set -gw window-style 'bg=#cacaca' +# }}}1 +# Key Bindings {{{1 +# root {{{2 + +# `F1`, ..., `F10` are used in `htop(1)`. +# `F11` and `F12` are used in WeeChat to scroll in the nicklist bar. +bind -T root S-F8 run -b 'tmux_log' + +# Why do you rebind `command-prompt` to `pfx + ;`? It's already bound to `pfx + :`...{{{ +# +# We often press the prefix key by accident, then press `:` to open Vim's +# command-line. As a result, we open tmux command-line; it's distracting. +#}}} +bind ';' command-prompt +unbind : +# Do *not* bind `command-prompt` to `M-:`; we press it by accident too frequently. + +# focus next/previous window +# I'm frequently pressing these key bindings in Vim's insert mode. It's distracting!{{{ +# +# Idea1: Use `pfx w` to focus an arbitrary window, and supercharge `pfx h/l` to +# focus the next/previous pane or window. +# +# bind -r h if -F '#{pane_at_left}' 'prev' 'selectp -L' +# bind -r l if -F '#{pane_at_right}' 'next' 'selectp -R' +# +# Idea2: Use `M-h/l` twice when the current pane is running Vim. +# +# set -g @foo 0 +# bind -T root M-l if -F '#{m:*vim,#{pane_current_command}}' { if -F '#{@foo}' { set -g @foo 0 ; next } { set -g @foo 1 } } { next } +# bind -T root M-h if -F '#{m:*vim,#{pane_current_command}}' { if -F '#{@foo}' { set -g @foo 0 ; prev } { set -g @foo 1 } } { prev } +# +# Idea3: Make tmux send `M-h` or `M-l` when Vim is running in the current pane, +# and let Vim decide what to do, based on whether we're in insert mode or normal +# mode. +# +# noremap! <expr> <m-h> <sid>m_hl('h') +# noremap! <expr> <m-l> <sid>m_hl('l') +# nno <expr> <m-h> <sid>m_hl('h') +# nno <expr> <m-l> <sid>m_hl('l') +# xno <expr> <m-h> <sid>m_hl('h') +# xno <expr> <m-l> <sid>m_hl('l') +# +# fu s:m_hl(seq) abort +# if mode() =~# '^[ic]$' +# return '' +# endif +# call system('tmux '..(a:seq is# 'l' ? 'next' : 'prev')) +# return '' +# endfu +# bind -T root M-l if -F '#{m:*vim,#{pane_current_command}}' 'send M-l' 'next' +# bind -T root M-h if -F '#{m:*vim,#{pane_current_command}}' 'send M-h' 'prev' +# +# Problem: When we're running Vim without config (`-Nu NONE`), we can't focus another tmux window. +# This is because those custom mappings are not installed then. +#}}} +# Why do you inspect these window flags?{{{ +# +# To prevent the commands from wrapping around the edges. +# They do that by default, and that bothers me at the moment. +# +# For example, I often want to focus the next window, and press `¹` by accident +# instead of `²`. It still works, because we only have 2 windows, but that +# prevents me from learning to press the correct keys. +# +# Once you're confident that those keys are well-chosen, and they've passed into +# your muscle memory, you could just install: +# +# bind -T root ¹ prev +# bind -T root ² next +#}}} +bind -T root ¹ if -F '#{window_start_flag}' {} { prev } +bind -T root ² if -F '#{window_end_flag}' {} { next } +# TODO: Sometimes, we press these keys by accident. Find better ones?{{{ +# +# In particular, when we press `[ox` (where `x` is some character) to toggle +# some Vim setting, we need to press `AltGr` to produce `[`; but sometimes, we +# don't release the key before pressing `o`. +# As a result, we press `AltGr + o` which produce `²`; tmux intercepts the +# keypress, and tries to visit the previous window, while in reality, we wanted +# to toggle some Vim setting. +#}}} + +# `M-s` to enter copy mode +# Do *not* bind `M-s` to anything while in copy mode!{{{ +# +# This would make you lose an interesting feature of the `copy-mode` command +# while you're already in copy mode, reading the output of some command such as +# `list-keys`. +# +# The default behavior makes tmux show you the contents of the original window: +# +# # you're reading a file +# :list-keys +# :copy-mode +# # the window shows again the file you were reading +# # press `q`, and you get back the output of `:list-keys` +# +# I don't know where this is documented. +# And I don't know why the `copy-mode` command is invoked when we press `M-s` +# while in copy mode. +# We only have one key binding using `M-s` as its lhs, and it's in the root +# table, not in the copy-mode table. +# +# Note that this feature is not specific to our `M-s` key binding. +# I can reproduce with no config (and `C-b [` instead of `M-s`). +#}}} +bind -T root M-s copy-mode + +bind -T root M-z resize-pane -Z +bind -T root M-Z lastp \; resize-pane -Z + +# Do *not* exit copy mode when when we reach the bottom of the scrollback buffer.{{{ +# +# We remove the `-e` flag which is passed to `copy-mode` by default, so that if +# we enter copy mode by scrolling the mouse wheel upward, and we press a key +# which reaches the bottom of the scrollback buffer, we don't quit copy mode. +# +# If you leave `-e` in the default key binding, here's what could happen: +# you scroll the wheel upward to enter copy mode; at one point, you keep +# pressing `C-d` to scroll toward the bottom; once you reach the bottom, you'll +# quit copy mode, and `C-d` will close the shell if the command-line is empty. +#}}} +# Where did you find the code?{{{ +# +# $ tmux -Lx -f/dev/null start \; lsk | grep 'root.*WheelUpPane' +#}}} +bind -T root WheelUpPane \ + if -F -t= '#{mouse_any_flag}' \ + { send -M } \ + { if -Ft= '#{pane_in_mode}' 'send -M' 'copy-mode -t=' } + +# But *do* exit copy mode if we scroll downward with the mouse wheel and reach the bottom of the buffer. +bind -T copy-mode-vi WheelDownPane \ + selectp \; \ + send -X -N 5 scroll-down \; \ + if -F '#{scroll_position}' '' 'send -X cancel' + +# copy-mode-vi {{{2 + +bind -T copy-mode-vi C-Space send -X set-mark +# actually, it should be named "exchange-point-and-mark"... +bind -T copy-mode-vi C-x send -X jump-to-mark + +# jump Back to the Beginning of the previous shell command{{{ +# +# Look for the previous shell prompt, to get to the beginning of the last +# command output. After pressing the key binding, you can visit all the other +# prompts by pressing `n` or `N`. +# +# Inspiration: https://www.youtube.com/watch?v=uglorjY0Ntg +#}}} +bind -T copy-mode-vi ! send -X start-of-line \; send -X search-backward '٪' + +# Make tmux use the prefix 'buf_' instead of 'buffer' when naming the buffer +# storing the copied selection. +bind -T copy-mode-vi Enter send -X copy-selection-and-cancel 'buf_' + +bind -T copy-mode-vi g switchc -T g-prefix +bind -T g-prefix g send -X history-top +# Open a visually selected text (filepath or url) by pressing `gf` or `gx`. +# TODO: The key binding will break if the file name contains double quotes.{{{ +# +# Find a way to escape special characters. +# +# I tried `$ tmux display -p '#{q:#(tmux pasteb)}'`, but it doesn't work. +# You probably need `q:`, but a modifier needs to be followed by the name of a +# replacement variable and `#(tmux pasteb)` is not one. +# +# Update: +# I don't think you should use `q:`. +# Maybe you should try to find a shell utility which quotes special characters +# in a given text. +# Does such a tool exist? +# If it does, maybe you could try: `#(magic_tool $(tmux pasteb))`. +# +# Update: +# `#{}` can be used for a user option (`@foo`). +# You could temporarily set a user option with the the filepath/url, and quote +# it with `q:`. +# +# Make some tests on that: +# +# http://example.org/foo/bar"baz.html +# http://example.org/foo/bar'baz.html +# https://www.reddit.com/r/Fantasy/ +# +# bind -T copy-mode-vi x send -X copy-selection-and-cancel \; \ +# run 'tmux set @copied_url "$(tmux showb)"' \; \ +# run 'xdg-open "#{q:@copied_url}"' +# +# For some reason, we need 2 `run-shell`, otherwise, it seems that the key +# binding doesn't update the url, when we try a new one. +# +# For some reason, when we try to open this: +# +# http://example.org/a'b.html +# +# tmux opens this instead: +# +# http://example.org/a/'b.html +# ^ +# ✘ +# +# For some reason, when we try to open this: +# +# http://example.org/a"b.html +# +# tmux doesn't escape the double quote. +# +# Text ended before matching quote was found for ".˜ +# (The text was '/usr/bin/firefox "http://example.org/foo/bar"baz.html"')˜ +# +# $ tmux set @foo "a'b" \; display -p '#{q:@foo}' +# a\'b˜ +# +# $ tmux set @foo "a'b" \; run 'echo #{q:@foo}' +# a'b˜ +# +# Why doesn't `run-shell` expand the `#{q:}` format? +# +# Update: you need to quote the format: +# +# $ tmux set @foo "a'b" \; run 'echo "#{q:@foo}"' +# a\'b˜ +# +# Update: +# I don't think it's possible. +# Try to open the urls via `urlscan(1)`. +# The latter fails for the first urls. +# If a specialized tool fails, I doubt we can do better. +#}}} +# FIXME: `gf` fails to open a file path starting with `~/`. +bind -T g-prefix f send -X pipe "xargs -I {} tmux run 'xdg-open \"{}\"'" +bind -T g-prefix x send -X pipe "xargs -I {} tmux run 'xdg-open \"{}\"'" + +bind -T copy-mode-vi v if -F '#{selection_present}' { send -X clear-selection } { send -X begin-selection } +bind -T copy-mode-vi V if -F '#{selection_present}' { send -X clear-selection } { send -X select-line } +bind -T copy-mode-vi C-v if -F '#{selection_present}' \ + { if -F '#{rectangle_toggle}' \ + { send -X rectangle-toggle ; send -X clear-selection } \ + { send -X rectangle-toggle } \ + } { send -X begin-selection ; send -X rectangle-toggle } + +# set -s copy-command 'xsel -i' +# if there's a selection, make `y` yank it +# without selection, make `yy` yank the current line and `yiw` the current word +bind -T copy-mode-vi y if -F '#{selection_present}' \ + { send -X copy-pipe-and-cancel 'xsel -i -b' 'buf_' } \ + { switchc -T operator-pending-and-cancel } +# y**y** +bind -T operator-pending-and-cancel y send -X copy-line 'buf_' +# y**iw** +bind -T operator-pending-and-cancel i switchc -T text-object-and-cancel +# Do *not* use `select-word`: https://github.com/tmux/tmux/issues/2126 +bind -T text-object-and-cancel w \ + { send -X cursor-right + send -X previous-word + send -X begin-selection + send -X next-word-end + send -X copy-selection-and-cancel 'buf_' } + +bind -T copy-mode-vi . run "zsh -c \"tmux source =(sed -n '/^# #{@dot_command}/,/^$/p' $HOME/.config/tmux/repeat.conf)\"" + +# **"A**yiw **"A**yy v_**"A**y +bind -T copy-mode-vi '"' switchc -T specify-register +bind -T specify-register A switchc -T operate-on-register +# Why the `if 'tmux showb'`?{{{ +# +# `append-selection` doesn't accept the optional prefix buffer name argument. +# If there's no buffer, `append-selection` will create a buffer with the prefix +# name `buffer`; we want the prefix `buf_`. +#}}} +# "A**y**iw "A**y**y v_"A**y** +bind -T operate-on-register y if -F '#{selection_present}' \ + { if 'tmux showb' { send -X append-selection } { send -X copy-selection 'buf_' }} \ + { switchc -T operator-pending } +# "Ay**i**w +bind -T operator-pending i switchc -T text-object +# "Ay**y** +bind -T operator-pending y { run "zsh -c \"tmux source =(sed -n '/^# yy/,/^$/p' $HOME/.config/tmux/repeat.conf)\"" } + +# v**i**w +bind -T copy-mode-vi i switchc -T text-object +# Why pass a second command to the first `if`?{{{ +# +# To support `"Ayiw`. +#}}} +# vi**w** "Ayi**w** +bind -T text-object w if -F '#{selection_present}' \ + { send -X stop-selection + send -X cursor-right + send -X previous-word + send -X begin-selection + send -X next-word-end } \ + { run "zsh -c \"tmux source =(sed -n '/^# yiw/,/^$/p' $HOME/.config/tmux/repeat.conf)\"" } + +bind -T copy-mode-vi Y send -X copy-end-of-line 'buf_' + +# Why don't you pass `-b` to run?{{{ +# +# There's no need to. +# `pipe-and-cancel` doesn't block. +# The shell command passed as an argument is forked. +#}}} +bind -T copy-mode-vi S send -X pipe-and-cancel \ + "xargs -I {} tmux run 'xdg-open \"https://www.startpage.com/do/dsearch?query={}\"'" + +# Why? {{{ +# +# `search-backward-incremental` is better than `search-forward`, because it +# highlights all the matches as you type (like in Vim when 'hlsearch' and +# 'incsearch' are both set); you need to pass `-i` to `command-prompt` for it to work. +# +# Also, these key bindings make the prompt less noisy (`/` is shorter than `search down`). +# +# Inspired from the default emacs key bindings in copy mode. +# }}} +bind -T copy-mode-vi / command-prompt -ip '/' { send -X search-forward-incremental '%%' } +bind -T copy-mode-vi ? command-prompt -ip '?' { send -X search-backward-incremental '%%' } + +bind -T copy-mode-vi % send -X next-matching-bracket +bind -T copy-mode-vi _ send -X start-of-line + +# move current window position forward/backward +# Why not using `h` and `l`, or `j` and `k`?{{{ +# +# `M-C-[jk]` could be more useful for something else (WeeChat?), and doesn't +# match a horizontal motion. +# `M-C-[hl]` conflicts with our window manager (move virtual desktop). +# `M-C-[HL]` is hard to press. +#}}} +bind -r > if -F '#{window_end_flag}' { movew -t :0 } { swapw -t :+ ; selectw -n } +bind -r < if -F '#{window_start_flag}' { movew -t :99 } { swapw -t :- ; selectw -p } +# If you don't like `:99`, you could write this instead:{{{ +# +# bind -r < if -F '#{window_start_flag}' \ +# { run 'tmux movew -t:$((#{W:#{?window_end_flag,#I,}}+1))' } \ +# { swapw -t :- ; selectw -p } +#}}} + +# prefix {{{2 + +# NOTE: `C-\` is free. + +# cycle through predefined layouts +# Do *not* pass `-r` to `bind`!{{{ +# +# We use Space in Vim as a prefix key. +# If you use `-r` here, when you're in Vim there's a risk that when you press +# Space as a prefix key, it's consumed by tmux to run `nextl` instead. +#}}} +bind Space nextl + +# focus last pane, without breaking the zoomed state of the window +bind M-Space lastp -Z + +# display short description for the next keypress (inspired from a default key binding) +bind M-h command-prompt -k -p key { lsk -1N '%%' } +# ├┘ ├─┘{{{ +# │ └ -N instead show keys and attached notes in the root and prefix key tables; +# │ with -1 only the first matching key and note is shown +# └ -k is like -1 but the key press is translated to a key name +#}}} +# What is the side effect of `-1`?{{{ +# +# Not only does it limit the output of the command to the first matching key and +# note, but it also redirects where it's displayed. +# Without `-1`, it's displayed on the terminal in copy-mode. +# With `-1`, it's displayed as a message on the tmux status line. +#}}} + +# display short description for the next 2 keypresses +bind M-l command-prompt -1p 'key1,key2' \ + { run "tmux lsk | awk '/-T prefix\s+%1\s+/ { print \$NF }' | xargs -I {} tmux lsk -1N -P 'M-Space %1 ' -T {} '%2'" } + +# repeat last shell command in last active pane +# Warning: This overrides a default key binding:{{{ +# +# bind-key -T prefix . command-prompt -T target "move-window -t '%%'" +#}}} +bind . if -F -t '{last}' '#{m:*sh,#{pane_current_command}}' { send -t '{last}' Up Enter } + +# copy clipboard selection into tmux buffer +# Why `run`?{{{ +# +# To make the shell evaluate the command substitution. +#}}} +# `--`?{{{ +# +# The evaluation of the substitution command could start with a hyphen. +# And if that happens, tmux could parse the text as an option passed to +# `set-buffer` (i.e. `-a`, `-b`, or `-n`). +#}}} +# `-o`?{{{ +# +# To make `xsel(1x)` output something. +#}}} +bind b switchc -T buffer +bind -T buffer -N 'copy clipboard into tmux buffer' > run 'tmux setb -- "$(xsel -ob)"' \; display 'clipboard copied into tmux buffer' +bind -T buffer -N 'copy tmux buffer into clipboard' < choose-buffer -F '#{buffer_sample}' \ + { run 'tmux showb -b "%%" | xsel -ib' ; display 'tmux buffer copie |