função de autocompletar Zsh com sed

1

Estou com dificuldades para escrever uma função de preenchimento automático do ZSH. Meu objetivo é autocompletar o primeiro argumento de ta e tk com os projetos listados em tmux list-sessions e tmuxinator list .

Aqui está o que eu tenho até agora:

tmux list-sessions gera dados semelhantes a este:

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 de saídas:

tmuxinator projects:
dotfiles           landonschropp.com

Aqui está minha tentativa:

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 remove tudo, menos os nomes dos projetos.
  • tmuxinator list | tail -n +2 | gsed -e 's/\s\+/\n/g' remove a primeira linha e substitui o espaço em branco por novas linhas.
  • echo "$TMUX_SESSIONS\n$TMUXINATOR_SESSIONS" | sort | uniq remove linhas duplicadas.
  • Estou usando gsed porque estou no OS X e sed é um pouco maluco.

Minha função funciona, mas é muito lenta. Eu sou um novato em scripts de shell, então tenho certeza que há uma maneira mais eficiente de conseguir isso. Onde está o meu gargalo e como posso consertá-lo?

    
por LandonSchropp 16.04.2014 / 06:59

2 respostas

2
  1. Para rastrear o atraso, você pode usar o comando incorporado time , que pode listar as contribuições de todos os comandos em um canal:

    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. Enquanto (de acordo com o seu comentário) é o comando externo tmuxinator list que causa o atraso perceptível, você pode, no entanto, otimizar sua função de conclusão. Você usou muitos comandos externos ( sed , cut , ...) para analisar a saída. Aqui mostrarei uma abordagem que usa apenas os recursos internos do zsh.

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

    Isso pode parecer complicado à primeira vista, mas uma vez que você se acostumar com isso, a expansão de parâmetros do zsh é muito poderosa. De cima para baixo:

    • local -aU declara um parâmetro local SESSIONS , que é uma matriz ( a ) e U mantém valores de matriz exclusivos . +
    • primeiro, obtenha as sessões de tmux list-sessions , explicadas de dentro para fora:
      • $(tmux list-sessions) obtém a saída do comando externo
      • ${(f)$(tmux list-sessions)} divide o resultado em \n
      • ${(@)${(f)$(tmux list-sessions)}/:*/} opera em todos os elementos da matriz ( (@) ) e faz uma pesquisa & substitua /from/to , ou seja, remover everthing depois de incluir os primeiros dois pontos.
      • Agora, $SESSIONS incluirá (dotfiles goodbye hello) . Use print -l $SESSIONS para imprimir todos os elementos da matriz em uma única linha.
    • em seguida, quase o mesmo procedimento para tmuxinator list , com estas adições:
      • use apenas o segundo para o último elemento ( [2,-1] )
      • apaga tudo depois (e incluindo) um caractere space ou tab ( $'\t' )
      • adicione esses elementos ( += ) à matriz SESSIONS
    • finalmente, retorne a matriz SESSIONS classificada sem distinção entre maiúsculas e minúsculas (i)

Todas essas expansões usam a forma geral mais longa de ${parameter} em vez da notação abreviada $parameter . Veja man zshexpn para uma explicação muito melhor da sintaxe e dos chamados Flags de Expansão de Parâmetros (como (f) ).

+ De acordo com Bart Schaefer , o U sinalizador não é necessário, porque o código de conclusão torna sua lista interna de conclusões exclusiva, por isso não ajuda realmente a remover as entradas redundantes de matrizes com antecedência, quando usá-los apenas para conclusão.

    
por 18.04.2014 / 14:30
-1

Aqui está outra alternativa:)

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

===== EDIT =====

Então eu reformulo minha resposta aqui, em resposta ao comentário da @NetworkKingPin.

Na postagem original de @LandonSchropp, você deve apenas alterar sua função tmux-list-sessions-autofill() para esta:

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

Observe que, em minha postagem original, eu estava usando sed para excluir outras informações além dos nomes das sessões. Mas desta vez estou usando um argumento -F , que informa tmux a apenas imprime os nomes das sessões e pula qualquer outra informação.

Isso funciona muito bem para mim. Espero que isso esteja claro o suficiente.

    
por 18.04.2016 / 18:34