2012-01-25 6 views
12

Ho scritto uno strumento della riga di comando che utilizza comandi secondari molto simile Mercurial, Git, Subversion & c, in quanto il suo utilizzo generale è:.Completamento quando il programma è sotto-comandi

>myapp [OPTS] SUBCOMMAND [SUBCOMMAND-OPTS] [ARGS] 

Ad es

>myapp --verbose speak --voice=samantha --quickly "hello there" 

Sono ora nel processo di costruzione di completamento Zsh per esso, ma hanno rapidamente scoperto che si tratta di una bestia molto complessa. Ho dato un'occhiata ai completamenti _hg e _git ma sono molto complessi e diversi nell'approccio (faccio fatica a capirli), ma entrambi sembrano gestire separatamente ciascun sottocomando.

Qualcuno sa se c'è un modo con il costruito nel funzioni (_arguments, _values, pick_variant & c.) Per gestire correttamente il concetto di comandi secondari, tra cui la gestione delle opzioni generali e le opzioni specifiche sub-comando in modo appropriato? O l'approccio migliore sarebbe gestire manualmente le opzioni generali e il sottocomando?

Un esempio di noddy sarebbe molto apprezzato.

Molte grazie.

risposta

21

avete ragione in quanto gli script di completamento di scrittura per zsh possono essere abbastanza difficili. La soluzione migliore è utilizzare uno esistente come guida. Quello per git è troppo per un principiante, imo. È possibile utilizzare questa repo:

https://github.com/zsh-users/zsh-completions

Per quanto riguarda la tua domanda, è necessario utilizzare il concetto di Stato . Si definiscono i sottocomandi in un elenco e quindi si identifica tramite lo stato $ in cui si trova il comando. Quindi si definiscono le opzioni per ciascun comando. Puoi vedere questo nello script di completamento per play. Una versione semplificata è qui sotto:

_play() { 
    local ret=1 

    _arguments -C \ 
    '1: :_play_cmds' \ 
    '*::arg:->args' \ 
    && ret=0 

    case $state in 
    (args) 
     case $line[1] in 
     (build-module|list-modules|lm|check|id) 
      _message 'no more arguments' && ret=0 
     ;; 
     (dependencies|deps) 
      _arguments \ 
      '1:: :_play_apps' \ 
      '(--debug)--debug[Debug mode (even more informations logged than in verbose mode)]' \ 
      '(--jpda)--jpda[Listen for JPDA connection. The process will suspended until a client is plugged to the JPDA port.]' \ 
      '(--sync)--sync[Keep lib/ and modules/ directory synced. Delete unknow dependencies.]' \ 
      '(--verbose)--verbose[Verbose Mode]' \ 
      && ret=0 
     ;; 
     esac 
    esac 

(Se avete intenzione di incollare questo, utilizzare la fonte originale, in quanto questo non funzionerà).

Sembra scoraggiante, ma l'idea generale non è così complicata. Il sottocomando viene prima (_play_cmds è una lista di sottocomandi con una descrizione per ciascuno), quindi vengono gli argomenti. Gli argomenti vengono creati in base al sottocomando scelto. Si noti che è possibile raggruppare più sottocomandi, se condividono argomenti.

con man zshcompsys è possibile trovare più informazioni sull'intero sistema, anche se è un po 'denso.

+1

Questo è fantastico grazie mille. Mi fa piacere che tu abbia detto che "zshcompsys" è denso dato che stavo iniziando a pensare che ero io;) –

+0

In 20 anni questo codice apparirà come un file binario per me oggi. – aaaaaa