Frage

Problem: ein Tabulatorvervollständigung haben, die zwei Worte nehmen und berechnet die beste Übereinstimmung von ihnen für einen Mann, und gibt dann die besten Übereinstimmungen

Beispiel: Der folgende Pseudo-Code soll mir geben zumindest Zsh des Reverse-Menü-complete -command. Gerade jetzt, ich kann nicht Handbücher innerhalb Handbücher ohne zgrep suchen.

man zsh:reverse <TAB>

Dabei steht ":". Ist das Trennzeichen, das ich will

Initial Problem: Welche Dateien funktioniert die TAB Abschluss laufen, wenn ich TAB für ein Wort drücke in Handbuch von Zsh Suche

War es hilfreich?

Lösung

Ich werde versuchen, einen Einblick zu geben, wie zsh Komplettierungssystem arbeitet und ein unvollständiges gehen auf dieses Problem.

Die Datei, die ausgeführt wird, wenn Sie die TAB-Abschluss für man in zsh verwenden wird unter dem /usr/share/zsh/${ZSH_VERSION}/functions Verzeichnis. Der Baum ist je nach Distributionen, aber die Datei wird _man benannt und bietet Fertigstellung für man, apropos und whatis.

Nach _man aufgerufen wird, funktioniert es wie folgt (grobe Beschreibung):

  1. , wenn für man und --local-file Abschluss als erster Flag angegeben wurde, rufen Sie Standarddateien Abschluss (_files)
  2. manpath Variable aus einem Satz von defaults / $MANPATH konstruieren. Hier werden die manpages durchsucht
  3. bestimmen, ob wir man mit einer Abschnittsnummer Parameter aufgerufen, wenn ja - nur diese Abschnitte durchsucht werden
  4. , wenn der zstyle ':completion:*:manuals' separate-sections true verwendet wurde, separate Abschnitte in der Ausgabe (es zwischen ihnen nicht mische)
  5. aufrufen _man_pages eine Liste der Manpages für das Spiel zur Verfügung zu stellen
  6. _man_pages hat jetzt ein wenig Magie mit compfiles -p pages '' '' "$matcher" '' dummy '*'. pages ist die Variable mit allen Verzeichnissen manpages für angeforderten Abschnitt (en) enthält. Die tatsächlichen Globbing Muster sind von der impliziten Parameter $PREFIX und dem letzten Parameter konstruiert compfiles - * in diesem Fall. Dies führt zu /usr/share/man/man1 umgewandelt in /usr/share/man/man1/foo* werden
  7. Die neue Liste von glob Muster wird globbed, alle Dateien zu erhalten, die das Muster
  8. entsprechen
  9. _man_pages Streifen dann alle Suffixe aus den Dateien und fügt sich die Abschluss-Widget Auswahlliste von compadd mit

Nun, wie Sie sehen können, wird die Liste der Man-Pages direkt von $PREFIX Variable bestimmt. Um zsh:foo zur Liste nur Manpages von zsh*, die enthalten das Wort foo zu machen, muss es über : Charakter (falls vorhanden) aufgeteilt werden.

Der folgende Zusatz in _man_pages löst teilweise das Problem (zsh 4.3.4):

Original:

_man_pages() {
  local matcher pages dummy sopt

  zparseopts -E M+:=matcher

  if (( $#matcher )); then
    matcher=( ${matcher:#-M} )
    matcher="$matcher"
  else
    matcher=
  fi

  pages=( ${(M)dirs:#*$sect/} )

  compfiles -p pages '' '' "$matcher" '' dummy '*'
  pages=( ${^~pages}(N:t) )

  (($#mrd)) && pages[$#pages+1]=($(awk $awk $mrd))

  # Remove any compression suffix, then remove the minimum possible string
  # beginning with .<->: that handles problem cases like files called
  # `POSIX.1.5'.

  [[ $OSTYPE = solaris* ]] && sopt='-s '
  if ((CURRENT > 2)) ||
      ! zstyle -t ":completion:${curcontext}:manuals.$sect" insert-sections
  then
    compadd "$@" - ${pages%.(?|<->*(|.gz|.bz2|.Z))}
  else
    compadd "$@" -P "$sopt$sect " - ${pages%.(?|<->*(|.gz|.bz2|.Z))}
  fi
}

Modified (suchen Sie nach ## mod Kommentare):

_man_pages() {
  local matcher pages dummy sopt

  zparseopts -E M+:=matcher

  if (( $#matcher )); then
    matcher=( ${matcher:#-M} )
    matcher="$matcher"
  else
    matcher=
  fi

  pages=( ${(M)dirs:#*$sect/} )

  ##mod
  # split components by the ":" character
  local pref_words manpage_grep orig_prefix
  # save original prefix (just in case)
  orig_prefix=${PREFIX}
  # split $PREFIX by ':' and make it an array
  pref_words=${PREFIX//:/ }
  set -A pref_words ${=pref_words}
  # if there are both manpage name and grep string, use both
  if (( $#pref_words == 2 )); then
      manpage_grep=$pref_words[2]
      # PREFIX is used internally by compfiles
      PREFIX=$pref_words[1]
  elif (( $#pref_words == 1 )) && [[ ${PREFIX[1,1]} == ":" ]]; then
      # otherwise, prefix is empty and only grep string exists
      PREFIX=
      manpage_grep=$pref_words[1]
  fi


  compfiles -p pages '' '' "$matcher" '' dummy '*'
  ##mod: complete, but don't strip path names
  pages=( ${^~pages} )

  (($#mrd)) && pages[$#pages+1]=($(awk $awk $mrd))

  ##mod: grep pages
  # Build a list of matching pages that pass the grep
  local matching_pages
  typeset -a matching_pages

  # manpage_grep exists and not empty 
  if (( ${#manpage_grep} > 0 )); then
      for p in ${pages}; do
          zgrep "${manpage_grep}" $p > /dev/null
          if (( $? == 0 )); then
              #echo "$p matched $manpage_grep"
              matching_pages+=($p)
          fi
      done
  else
  # there's no manpage_grep, so all pages match
      matching_pages=( ${pages} )
  fi

  #echo "\nmatching manpages: "${matching_pages}
  pages=( ${matching_pages}(N:t) )
  # keep the stripped prefix for now
  #PREFIX=${orig_prefix}


  # Remove any compression suffix, then remove the minimum possible string
  # beginning with .<->: that handles problem cases like files called
  # `POSIX.1.5'.


  [[ $OSTYPE = solaris* ]] && sopt='-s '
  if ((CURRENT > 2)) ||
      ! zstyle -t ":completion:${curcontext}:manuals.$sect" insert-sections
  then
    compadd "$@" - ${pages%.(?|<->*(|.gz|.bz2|.Z))}
  else
    compadd "$@" -P "$sopt$sect " - ${pages%.(?|<->*(|.gz|.bz2|.Z))}
  fi
}

Es ist jedoch noch nicht vollständig funktioniert (wenn Sie die #echo "$p matched $manpage_grep" Linie Kommentar-, können Sie sehen, dass es die Liste bauen) - Ich vermute, dass irgendwo intern, das Komplettierungssystem sieht, dass zum Beispiel „zshcompctl“ nicht abgestimmt ist durch Vorsilbe „zsh: foo“, und zeigt nicht die daraus resultierenden Ergebnissen geführt. Ich habe versucht, $PREFIX zu halten, wie es nach dem Abziehen des grep String ist, aber es will noch nicht arbeiten.

Auf jeden Fall diese zumindest sollten Sie beginnen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top