26

Some commands (kill-session and kill-server) have the same prefix.
When I type (prefix:kill-seTab), tmux won't give me any result.
Is there a option to show wildmenu for auto-completion inside tmux?

I'm using Ubuntu 12.04

  • What shell are you using? You can find it with echo $SHELL – éclairevoyant Apr 8 '13 at 5:31
  • 1
    It's /bin/bash – kev Apr 8 '13 at 7:29
  • 4
    How is shell related? When you type Ctrl+B,: in tmux, you're given a tmux command prompt (just like when you type : in VIM, you're not given a bash prompt.) This is a tmux question, not a shell question. – bobpaul May 8 '13 at 21:40
  • The bash completion answer is helpful, but doesn't answer the question for use inside tmux. I'm guessing that since tmux doesn't have an extra line of vertical space to work with, it just doesn't offer the tab completion options like bash does, though it does at least complete what you're typing up until there is ambiguity. So folks can use the bash option to learn, and use the tmux option for quickies where they know what they want. – nealmcb Dec 23 '14 at 20:02
11

The following script provides a bash completion for tmux, and I tested it out on my box just now, and it works great. Just copy the script to a file on your computer, and put

   source /path/to/tmux_completion.sh

in your .bashrc and you should be ready to go.


#!/bin/bash

# tmux completion
# See: http://www.debian-administration.org/articles/317 for how to write more.
# Usage: Put "source bash_completion_tmux.sh" into your .bashrc
# Based upon the example at http://paste-it.appspot.com/Pj4mLycDE

_tmux_expand () 
{ 
    [ "$cur" != "${cur%\\}" ] && cur="$cur"'\';
    if [[ "$cur" == \~*/* ]]; then
        eval cur=$cur;
    else
        if [[ "$cur" == \~* ]]; then
            cur=${cur#\~};
            COMPREPLY=($( compgen -P '~' -u $cur ));
            return ${#COMPREPLY[@]};
        fi;
    fi
}

_tmux_filedir () 
{ 
    local IFS='
';
    _tmux_expand || return 0;
    if [ "$1" = -d ]; then
        COMPREPLY=(${COMPREPLY[@]} $( compgen -d -- $cur ));
        return 0;
    fi;
    COMPREPLY=(${COMPREPLY[@]} $( eval compgen -f -- \"$cur\" ))
}

function _tmux_complete_client() {
    local IFS=$'\n'
    local cur="${1}"
    COMPREPLY=( ${COMPREPLY[@]:-} $(compgen -W "$(tmux -q list-clients | cut -f 1 -d ':')" -- "${cur}") )
}
function _tmux_complete_session() {
    local IFS=$'\n'
    local cur="${1}"
    COMPREPLY=( ${COMPREPLY[@]:-} $(compgen -W "$(tmux -q list-sessions | cut -f 1 -d ':')" -- "${cur}") )
}
function _tmux_complete_window() {
    local IFS=$'\n'
    local cur="${1}"
    local session_name="$(echo "${cur}" | sed 's/\\//g' | cut -d ':' -f 1)"
    local sessions

    sessions="$(tmux -q list-sessions | sed -re 's/([^:]+:).*$/\1/')"
    if [[ -n "${session_name}" ]]; then
        sessions="${sessions}
$(tmux -q list-windows -t "${session_name}" | sed -re 's/^([^:]+):.*$/'"${session_name}"':\1/')"
    fi
    cur="$(echo "${cur}" | sed -e 's/:/\\\\:/')"
    sessions="$(echo "${sessions}" | sed -e 's/:/\\\\:/')"
    COMPREPLY=( ${COMPREPLY[@]:-} $(compgen -W "${sessions}" -- "${cur}") )
}

_tmux() {
    local cur prev
    local i cmd cmd_index option option_index
    local opts=""
    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"
    prev="${COMP_WORDS[COMP_CWORD-1]}"

    if [ ${prev} == -f ]; then
        _tmux_filedir
    else
    # Search for the command
    local skip_next=0
    for ((i=1; $i<=$COMP_CWORD; i++)); do
        if [[ ${skip_next} -eq 1 ]]; then
            #echo "Skipping"
            skip_next=0;
        elif [[ ${COMP_WORDS[i]} != -* ]]; then
            cmd="${COMP_WORDS[i]}"
            cmd_index=${i}
            break
        elif [[ ${COMP_WORDS[i]} == -f ]]; then
            skip_next=1
        fi
    done

    # Search for the last option command
    skip_next=0
    for ((i=1; $i<=$COMP_CWORD; i++)); do
        if [[ ${skip_next} -eq 1 ]]; then
            #echo "Skipping"
            skip_next=0;
        elif [[ ${COMP_WORDS[i]} == -* ]]; then
            option="${COMP_WORDS[i]}"
            option_index=${i}
            if [[ ${COMP_WORDS[i]} == -- ]]; then
                break;
            fi
        elif [[ ${COMP_WORDS[i]} == -f ]]; then
            skip_next=1
        fi
    done

    if [[ $COMP_CWORD -le $cmd_index ]]; then
        # The user has not specified a command yet
        local all_commands="$(tmux -q list-commands | cut -f 1 -d ' ')"
        COMPREPLY=( ${COMPREPLY[@]:-} $(compgen -W "${all_commands}" -- "${cur}") )
    else        
        case ${cmd} in
            attach-session|attach)
            case "$prev" in
                -t) _tmux_complete_session "${cur}" ;;
                *) options="-t -d" ;;
            esac ;;
            detach-client|detach)
            case "$prev" in
                -t) _tmux_complete_client "${cur}" ;;
                *) options="-t" ;;
            esac ;;
            lock-client|lockc)
            case "$prev" in
                -t) _tmux_complete_client "${cur}" ;;
                *) options="-t" ;;
            esac ;;
            lock-session|locks)
            case "$prev" in
                -t) _tmux_complete_session "${cur}" ;;
                *) options="-t -d" ;;
            esac ;;
            new-session|new)
            case "$prev" in
                -t) _tmux_complete_session "${cur}" ;;
                -[n|d|s]) options="-d -n -s -t --" ;;
                *) 
                if [[ ${COMP_WORDS[option_index]} == -- ]]; then
                    _command_offset ${option_index}
                else
                    options="-d -n -s -t --"
                fi
                ;;
            esac
            ;;
            refresh-client|refresh)
            case "$prev" in
                -t) _tmux_complete_client "${cur}" ;;
                *) options="-t" ;;
            esac ;;
            rename-session|rename)
            case "$prev" in
                -t) _tmux_complete_session "${cur}" ;;
                *) options="-t" ;;
            esac ;;
            source-file|source) _tmux_filedir ;;
            has-session|has|kill-session)
            case "$prev" in
                -t) _tmux_complete_session "${cur}" ;;
                *) options="-t" ;;
            esac ;;
            suspend-client|suspendc)
            case "$prev" in
                -t) _tmux_complete_client "${cur}" ;;
                *) options="-t" ;;
            esac ;;
            switch-client|switchc)
            case "$prev" in
                -c) _tmux_complete_client "${cur}" ;;
                -t) _tmux_complete_session "${cur}" ;;
                *) options="-l -n -p -c -t" ;;
            esac ;;

            send-keys|send)
            case "$option" in
                -t) _tmux_complete_window "${cur}" ;;
                *) options="-t" ;;
            esac ;;
          esac # case ${cmd}
        fi # command specified
      fi # not -f 

      if [[ -n "${options}" ]]; then
          COMPREPLY=( ${COMPREPLY[@]:-} $(compgen -W "${options}" -- "${cur}") )
      fi

      return 0

}
complete -F _tmux tmux

# END tmux completion

Script Source

| improve this answer | |
  • 5
    I saved this script and sourced it from my .bashrc. I started tmux and hit "Ctrl+B, :" and then typed "detach-" and hit tab a bunch. Nothing. I added a c so it sayd "detach-c" and hit tab, it completed to "detach-client". This is the exact same behavior I experienced before the script. Nothing seems to have changed. – bobpaul May 8 '13 at 21:38
  • 7
    @bobpaul is asking for tab completion within tmux, not from in the shell like bash. – Jason Axelson Oct 30 '13 at 19:37
  • 1
    @kev is also asking for tab completion within tmux, not from bash. And note that some related (older?) code for this bash command completion approach is on github at github.com/aziz/dotfiles/blob/master/bash/completion/… but it isn't clear to me how their behavior differs. Perhaps luolimao might want to offer the diffs in a pull request? – nealmcb Dec 23 '14 at 19:58
  • 5
    I voted the answer down because OP is asking for auto-completion from within tmux, not for bash. This answer might be totally reasonable for the second inquiry (completion for bash), but it misleads people who come here through search engines to try to find a completion from within tmux. – thiagowfx Mar 6 '17 at 18:01
  • 1
    @thiagowfx You SHOULD NOT downvote a "totally reasonable" answer just because it is not exactly what "OP is asking". In that case you EDIT THE ANSWER and give it a better title. You only downvote an answer that is wrong, misleading, brittle, etc. Giving someone an alternative to what they asked for (especially when what they asked for is impossible) is not "misleading". I can't believe that 5 other people agreed with this! That's not the SO/SE culture. – Bruno Bronosky Jul 7 at 19:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.