1

Я изо всех сил пытаюсь написать функцию автозаполнения ZSH. Моя цель - автозаполнение первого аргумента ta и tk с проектами, перечисленными в tmux list-sessions tmuxinator list .

Вот что у меня так далеко:

tmux list-sessions выводит данные, которые выглядят так:

dotfiles: 1 windows (created Tue Apr 15 21:54:51 2014) [123x48]
goodbye: 1 windows (created Tue Apr 15 21:51:34 2014) [123x48]
hello: 1 windows (created Tue Apr 15 21:42:03 2014) [123x48]

tmuxinator list :

tmuxinator projects:
dotfiles           landonschropp.com

Вот моя попытка:

tmux-list-sessions-autofill() {

  # get the tmux and tmuxinator sessions
  TMUX_SESSIONS=$( tmux list-sessions | cut -d: -f1 )
  TMUXINATOR_SESSIONS=$( tmuxinator list | tail -n +2 | gsed -e 's/\s\+/\n/g' )

  # remove duplicates
  SESSIONS=$( echo "$TMUX_SESSIONS\n$TMUXINATOR_SESSIONS" | sort | uniq )

  # set the autocomplete values
  reply=( $(echo $SESSIONS) )
}

compctl -K tmux-list-sessions-autofill ta
compctl -K tmux-list-sessions-autofill tk
  • tmux list-sessions | cut -d: -f1 удаляет все, кроме имен проектов.
  • tmuxinator list | tail -n +2 | gsed -e 's/\s\+/\n/g' удаляет первую строку и заменяет пробел символом новой строки.
  • echo "$TMUX_SESSIONS\n$TMUXINATOR_SESSIONS" | sort | uniq удаляет повторяющиеся строки.
  • Я использую gsed потому что я на OS X, а sed немного сумасшедший.

Моя функция работает, но она очень медленная. Я новичок в создании сценариев оболочки, поэтому я уверен, что есть более эффективный способ сделать это. Где мое узкое место и как я могу это исправить?

2 ответа2

2
  1. Чтобы отследить задержку, вы можете использовать встроенное time команды, которое может перечислить вклады всех команд в канале:

    zsh% time sleep 2 | date | sleep 1
    sleep 2  0.00s user 0.00s system 0% cpu 2.003 total
    date  0.00s user 0.00s system 0% cpu 0.004 total
    sleep 1  0.00s user 0.00s system 0% cpu 1.004 total
    
  2. Хотя (согласно вашему комментарию) список внешних команд tmuxinator list вызывает заметную задержку, тем не менее вы можете оптимизировать функцию завершения. Вы использовали много внешних команд (sed , cut , ...) для разбора вывода. Здесь я покажу один подход, который использует только встроенные возможности zsh.

    tmux-list-sessions-autofill() {
      local -aU SESSIONS
      SESSIONS=("${(@)${(f)$(tmux list-sessions)}/:*/}")
      SESSIONS+=("${(@)${(f)$(tmuxinator list-sessions)}[2,-1]/[ $'\t']*/}")
      reply=(${(i)SESSIONS})
    }
    

    На первый взгляд это может показаться сложным, но как только вы к этому привыкнете, расширение параметров zsh станет очень мощным. Сверху вниз:

    • local -aU объявляет локальный параметр SESSIONS , который является массивом (a), а U сохраняет значения массива уникальными. +
    • во-первых, получите сессии из списка сеансов tmux list-sessions , объяснив их изнутри наружу:
      • $(tmux list-sessions) получает выходные данные внешней команды
      • ${(f)$(tmux list-sessions)} разбивает результат на \n
      • ${(@)${(f)$(tmux list-sessions)}/:*/} работает с каждым элементом массива ((@)) и выполняет поиск и замену /from/to , т. е. удаляет все после и включает первый двоеточие
      • Теперь $SESSIONS будет включать (dotfiles goodbye hello) . Используйте print -l $SESSIONS чтобы напечатать каждый элемент массива в одной строке.
    • далее, почти та же процедура для tmuxinator list , с этими дополнениями:
      • использовать только второй до последнего элемента ([2,-1])
      • стереть все после (включая) space или символа tab ($'\t')
      • добавить эти элементы (+=) в массив SESSIONS
    • наконец, вернуть отсортированный массив SESSIONS учета регистра (i)

Все эти расширения используют более длинную общую форму ${parameter} вместо сокращенного обозначения $parameter . Смотрите man zshexpn для лучшего понимания синтаксиса и так называемых флагов расширения параметров (например, (f)).


+ Согласно Барту Шеферу, флаг U необязателен, потому что код завершения делает его внутренний список завершений уникальным, поэтому он не помогает заранее удалить избыточные записи из массивов, когда они используются только для завершения.

-1

Вот еще один вариант :)

tmux-list-sessions-autofill() {
    reply=( `tmux list-sessions | sed "s/:.*//g"` );
}

===== РЕДАКТИРОВАТЬ =====

Поэтому я переформулирую свой ответ здесь, в ответ на комментарий @NetworkKingPin.

В первоначальном посте @LandonSchropp вы просто должны изменить функцию tmux-list-sessions-autofill() session-autofill() на следующую:

tmux-list-sessions-autofill() {
    reply=( `tmux list-sessions -F '#{session_name}'` ); 
}

Обратите внимание, что в моем исходном сообщении я использовал sed для удаления любой другой информации, кроме имен сеансов. Но на этот раз я использую аргумент -F который говорит tmux печатать только имена сеансов и пропускать любую другую информацию.

Это прекрасно работает для меня. Надеюсь, это достаточно ясно.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .