Mailing-List: contact zsh-workers-help@zsh.org; run by ezmlm
Precedence: bulk
X-No-Archive: yes
List-Id: Zsh Workers List <zsh-workers.zsh.org>
List-Post: <mailto:zsh-workers@zsh.org>
List-Help: <mailto:zsh-workers-help@zsh.org>
X-Qmail-Scanner-Diagnostics: from nm1.bullet.mail.ir2.yahoo.com by f.primenet.com.au (envelope-from <okiddle@yahoo.co.uk>, uid 7791) with qmail-scanner-2.11 
 (clamdscan: 0.99.2/21882. spamassassin: 3.4.1.  
 Clear:RC:0(212.82.96.32):SA:0(0.0/5.0):. 
 Processed in 0.644621 secs); 24 Jul 2016 21:54:31 -0000
X-Spam-Checker-Version: SpamAssassin 3.4.1 (2015-04-28) on f.primenet.com.au
X-Spam-Level: 
X-Spam-Status: No, score=0.0 required=5.0 tests=FREEMAIL_FROM,SPF_PASS,
	T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.1
X-Envelope-From: okiddle@yahoo.co.uk
X-Qmail-Scanner-Mime-Attachments: |
X-Qmail-Scanner-Zip-Files: |
Received-SPF: pass (ns1.primenet.com.au: SPF record at _spf.mail.yahoo.com designates 212.82.96.32 as permitted sender)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.co.uk; s=s2048; t=1469396920; bh=loW7qZ/mcWDy94T7ukfvK+Rd7g8c7r36dzuZF/dw6yM=; h=From:To:Subject:Date:From:Subject; b=U5f92da2jRWvUTLILAK2wA6Ge74hKJiemyRxbxkk84kTkNc8pXewzYAK0ks5gCv2iAaI51FnJaCzNwgaUn6Pu+a+AEMZb115MI/rbMHpCFI36vMxqyEX1cT6ZPAqjuGeCzB14JcfCbmTZ0v9jyXkJduwwueQuSg+QsQ9VNIZ62mTr436ggirw6id2wGstoigR6WsowJaTPGycSPYca18Q6OwhijbF86SHz1gp79emXxfZzgwg07BAjFoughjkz6zf3lzo0rFNcjZYJI0jF554IQOm/1xQRka83WttDUZC0LlW2rvQHytAC7iRDfMGMLvFjU0Oik0LAtomk3Uky03sA==
X-Yahoo-Newman-Id: 288404.54758.bm@smtp140.mail.ir2.yahoo.com
X-Yahoo-Newman-Property: ymail-3
X-YMail-OSG: rLyCc5MVM1lkZjLGfPlyHy62mqEjQMK3y5sX15akAOfO0tr
 N9mv47L3dHjsp7gpi9o0HfxD3m_Xp6rinNcdOAekdhAFpLHTPFEsi1_.oq8L
 NBkpZUqV5AhAjc3adhBIZ_X6g0RxFsZceXyrU.2UkmFQ.FZH9q7SQ7tTyD.D
 Braa_RGFJuws4_8Z7MSOFIyYJudmOi6vcbS1Wm_dzja5LtWMU8rGibumZ6bw
 DPAbyXIGRlbDdVz4t3eiEB0evK_QFcmNjG0XhZmq2Bv25sRvPyGWtI2Ubrob
 YWGDF7WwgEUnzE4c6MLyLUtl_Bo.BmbHl05pZQ4qSA1nVTYrBMSNZrywk5R7
 g6V4TRsfhDLkQVFYk.d7uoI6oI1aTteUk8stoaKlckN8HX21GkOj0Llb.7CN
 T.BOv8b.bPVMzGVqNTZTQ6E8yp5HclgJFUmIts1OXWfBGgYYd761EeNZTLSI
 ruVQZQAJJJuxRnoTMyu_go6LP6nvuvD9ffzlKfDYGanHNSSnxw.VPNml2ggi
 VLSdk0XRVIWhy8kYyvpLX9xkAxDIoVgrMoyR11xqHSjI-
X-Yahoo-SMTP: opAkk_CswBAce_kJ3nIPlH80cJI-
From: Oliver Kiddle <okiddle@yahoo.co.uk>
To: Zsh workers <zsh-workers@zsh.org>
Subject: PATCH: update texinfo completion
MIME-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-ID: <23727.1469396919.1@hydra.kiddle.eu>
Content-Transfer-Encoding: quoted-printable
Date: Sun, 24 Jul 2016 23:48:39 +0200
Message-ID: <23728.1469396919@hydra.kiddle.eu>
X-Seq: zsh-workers 38943

Completion for info parses the output for menu entries and adds
descriptions. In practice the descriptions tend to just repeat the
menu entries and complicates the parsing. Anyone object to losing
them?

In exchange, this additionally uses info -k '' to extract a load
of extra nodes that aren't available from the initial menu. That
can be a little slow so the cache mechanism is used. The output
depends on $INFOPATH plus any directories specified with -d so a
single cache file doesn't suffice. So this hashes the list of
directories and puts the hash at the end of the cache file name.

Also now handled is references in the form (file)Node
Plus updates to the list of options though I'm not sure how useful that
is as there are now so many options that the important ones get buried.

Oliver

diff --git a/Completion/Unix/Command/_texinfo b/Completion/Unix/Command/_t=
exinfo
index 12d964e..7b66d63 100644
--- a/Completion/Unix/Command/_texinfo
+++ b/Completion/Unix/Command/_texinfo
@@ -1,29 +1,65 @@
-#compdef info tkinfo install-info makeinfo texi2dvi texindex
+#compdef info tkinfo install-info makeinfo texi2any texi2dvi pdftexi2dvi =
texi2pdf texindex
 =

-local curcontext=3D"$curcontext" state line ret=3D1
-local -A opt_args
-local -a info
+_info_nodes_caching_policy() {
+  local dir oldp
+  for dir in $^infopath/usr/share/info}/dir(.N); do
+    # rebuild if any dir file is newer than cache
+    [[ $dir -nt $1 ]] && return
+  done
+  # and if we didn't find a dir file, rebuild if cache older than a month
+  if [[ -z $dir ]]; then
+    oldp=3D( "$1"(mM+1) )
+    (( $#oldp )) && return
+  fi
+  return 1
+}
+
+_info_retrieve_nodes() {
+  # expects $cmd, $hash and $infopath to be set
+  local update_policy
+  zstyle -s ":completion:${curcontext}:" cache-policy update_policy
+  if [[ -z "$update_policy" ]]; then
+    zstyle ":completion:${curcontext}:" cache-policy \
+      _info_nodes_caching_policy
+  fi
+
+  if _cache_invalid info-nodes-$hash || ! _retrieve_cache info-nodes-$has=
h; then
+    set -A _cache_info_nodes_$hash \
+      ${${${${(f)"$(INFOPATH=3D"${(j.:.)infopath}" _call_program info-nod=
es $cmd -k '')"}%%\" --*}#??}/\)/:}
+    _store_cache info-nodes-$hash _cache_info_nodes_$hash
+  fi
+}
+
+local curcontext=3D"$curcontext" state line cmd ret=3D1
+local -A opt_args infodirs
 =

 case $service in
   info)
-    info=3D( _call_program info ${words[1]} )
+    cmd=3D${words[1]}
     _arguments -C -s \
-      '(: -)--apropos=3D[look up string in indices]:search string: ' \
-      '(-f --file)'{\*-d,\*--directory=3D}'[add directory to infopath]:in=
fo dir:_files -/' \
+      '(-a --all)'{-a,--all}'[use all matching manuals]' \
+      '(: -)'{-k+,--apropos=3D}'[look up string in indices]:search string=
: ' \
+      \*{-d+,--directory=3D}'[add directory to infopath]:info dir:_files =
-/' \
       '--dribble=3D[record keystrokes]:file with keystrokes:_files' \
-      '(-f --file -d --directory)'{-f,--file=3D}'[info file to show]:info=
 file:_files -g "*.info(|.gz|.bz2)(-.)"' \
+      '(-f --file 1)'{-f+,--file=3D}'[specify Info manual to visit]:info =
manual:->infofiles' \
       '(: - -h --help)'{-h,--help}'[display usage]' \
       '(-o --output -O)--index-search=3D[go directly to node if found]:se=
arch string: ' \
-      '(--index-search -o --output -O)'{-o,--output=3D}'[dump selected no=
des to filename]:filename:_files -g "*(-.)"' \
-      '(-R --raw-escapes)'{-R,--raw-escapes}'[do not remove ANSI escapes =
from man pages]' \
+      '(--index-search -o --output -O)'{-o+,--output=3D}'[dump selected n=
odes to filename]:filename:_files -g "*(-.)"' \
+      '(-n --node)'{-n+,--node=3D}'[specify nodes in first visited Info f=
ile]:node:->nodes' \
+      '--no-raw-escapes[output escapes as literal text]' \
       '--restore=3D[read keystrokes from file]:filename:_files -g "*(-.)"=
' \
       '(--index-search -o --output -O --show-options --usage)'{-O,--show-=
options,--usage}'[go to command-line options node]' \
+      '--strict-node-location[(for debugging) use Info file pointers as-i=
s]' \
       '--subnodes[recursively output menu items]' \
+      \*{-v,--variable}'[assign to Info variable]:variable' \
       '--vi-keys[use Vi-like key bindings]' \
       '(: -)--version[display version information]' \
-      '(--apropos -h --help -O --output --version)*::menu item:->item' &&=
 ret=3D0
+      '(-w --where --location)'{-w,--where,--location}'[print physical lo=
cation of Info file]' \
+      '(-x --debug)'{-x+,--debug=3D}'[set debugging level]:number' \
+      '1:menu item:->infomanuals' \
+      '2:node:->nodes' && ret=3D0
 =

-    info=3D( $info {(kv)opt_args[(I)(-d|--directory|-f|--file)]} )
+    infodirs=3D( "${(@Qkv)opt_args[(I)(-d|--directory)]}" )
   ;;
   install-info)
     if _pick_variant debian=3DDebian gnu --version; then
@@ -41,131 +77,216 @@ case $service in
         '--description=3D[specify description for menu entry]:description=
' \
         '--menuentry=3D[specify the menu entry for dir file]:menu entry' =
\
         '--keep-old=3D[inhibit replacement of existing entries/removal of=
 empty sections]' \
-        '--test[do not update dir file]' \
+        "--test[don't update dir file]" \
         '--debug[enable debugging]' \
         '*:info file:_files -g "*.info(-.)"'
 	return
     else
       _arguments \
+	'--add-once[add only to first matching section]' \
+	'--align=3D[specify minimum indentation for description]:indentation' \
+	'--calign=3D[specify minimum indentation for continuation lines of descr=
iption]:indentation' \
+        '--debug[report what is being done]' \
         '(--delete --remove)'{--delete,--remove}'[delete existing entries=
]' \
+        '--description=3D[specify description for menu entry]:description=
' \
         '(2)--dir-file=3D[specify dir file]:dir file:_files -g "dir(-.)"'=
 \
+	'(--test --dry-run)'{--dry-run,--test}"[don't update dir file]" \
         \*{--entry,--info}'[specify directory entry to add]:text' \
+	'--defsection=3D[like --section, but only use text if no sections presen=
t in info file]:text' \
+	{--maxwidth,--max-width}'=3D[specify maximum width of dir file]:width' \
         '(- 1 2)--help[display help information]' \
         '(1)--info-file=3D[specify info file to install in the directory]=
:info file:_files -g "*.info(-.)"' \
         '(2)--info-dir=3D[specify directory containing dir file]:info dir=
ectory:_files -/' \
+        '--keep-old=3D[inhibit replacement of existing entries/removal of=
 empty sections]' \
+	'(--name --menuentry)'{--name,--menuentry}'=3D[specify the menu entry fo=
r dir file]:menu entry' \
+	"--no-indent[don't format new entries in the DIR file]"
         '--quiet[suppress warnings]' \
-        '(--delete --remove)--section=3D[put new entries in specified sec=
tion]' \
+	'--regex=3D[specify sections for file entries using a regex]:regex' \
+        '(--delete --remove)--section=3D[put new entries in specified sec=
tion]:section' \
+        '--silent[no output except errors]' \
         '(- 1 2)--version[display version information]' \
         '1:info file:_files -g "*.info(-.)"' \
         '2:dir file:_files -g "dir(-.)"'
 	return
     fi
   ;;
-  makeinfo)
+  makeinfo|texi2any)
     _arguments -s \
-      '--error-limit=3D[specify number of errors to quit after]:number' \
+      '--error-limit=3D[specify number of errors to quit after]:number [1=
00]' \
+      '--document-language=3D[specify locale to use in translating Texinf=
o keywords]:locale [C]:_locales' \
       '--force[preserve output even if errors]' \
       '(* -)--help[display help]' \
       '--no-validate[suppress node cross-reference validation]' \
       '--no-warn[suppress warnings]' \
-      '--reference-limit=3D[warn about at most specified number of refere=
nces]:number' \
+      '--conf-dir=3D[specify additional directory for configuration files=
]:directory:_directories' \
+      '--init-file=3D[specify initialisation file]:file:_files' \
+      \*{-c+,--set-customization-variable=3D}'[set customization variable=
]:variable' \
       '(-v --verbose)'{-v,--verbose}'[explain what is being done]' \
       '(* -)--version[display version info]' \
-      '(--html --xml)--docbook[output in DocBook format]' \
-      '(--docbook --xml)--html[output in HTML format]' \
+      '(--html --xml --plaintext)--docbook[output in DocBook XML format]'=
 \
+      '(--docbook --xml --plaintext)--html[output in HTML format]' \
       '--no-headers[suppress node separators and menus]' \
-      '(--docbook --html)--xml[output in XML (TexinfoML) format]' \
+      '(--docbook --html --plaintext)--xml[output in XML (TexinfoML) form=
at]' \
+      '(--docbook --html --xml)--plaintext[output in plain text format]' =
\
+      '--dvi[output in dvi format]' \
+      '--dvipdf[output in pdf format]' \
+      '--ps[output in ps format]' \
+      '--pdf[output in pdf format]' \
       '(-E --macro-expand)'{-E,--macro-expand}'[output macro-expanded sou=
rce to specified file]:file:_files' \
       '(--docbook --xml)--no-split[suppress splitting of output]' \
-      '--number-sections[output chapter and section numbers]' \
+      '--no-number-sections[output chapter and section numbers]' \
       '(-o --output=3D)'{-o,--output}'[specify output file]:output file:_=
files' \
-      '(--docbook --html --xml)--enable-encoding[output special character=
s]' \
+      '(--docbook --html --xml)--disable-encoding[output special characte=
rs]' \
       '(--docbook --html --xml)--fill-column=3D[specify width to break li=
nes at]:width' \
       '(--docbook --html --xml)--footnote-style=3D[specify style for outp=
ut of footnotes]:((separate\:in\ own\ node end\:at\ end\ of\ node))' \
       '(--docbook --html --xml)--paragraph-indent=3D[specify spaces to in=
dent paragraphs by]' \
-      '(--docbook --html --xml)--split-size=3D[split Info files at specif=
ied size]:size' \
-      '--commands-in-node-names[allow @ commands in node names]' \
+      '(--docbook --html --xml)--split-size=3D[split Info files at specif=
ied size]:size [300000]' \
+      '(--docbook --xml --plaintext)--css-include=3D[specify file in incl=
ude in HTML <style> output]:file:_files' \
+      '(--docbook --xml --plaintext)--css-ref=3D[generate reference to a =
CSS file]:URL:_urls' \
+      '(--docbook --xml --plaintext)--internal-links=3D[produce list of i=
nternal links in a file]:file:_files' \
+      '(--docbook --xml --plaintext)--split=3D[split output at specified =
boundary]:split boundary:(chapter section node)' \
+      '(--docbook --xml --plaintext)--transliterate-file-names[produce fi=
le names in ASCII transliteration]' \
+      '(--docbook --xml --plaintext)--node-files[produce redirection file=
s for nodes]' \
+      '-Xopt=3D[specify option to texi2dvi]:options' \
       '-D[define variable]:variable' \
       '-I[specify directory to append to @include search path]:directory:=
_files -/' \
       '-P[specify directory to prepend to @include search path]:directory=
:_files -/' \
       '-U[undefine variable]:variable' \
+      '(--docbook --no-ifdocbook)--ifdocbook[process @ifdocbook and @docb=
ook even when not generating Docbook]' \
       '(--html --no-ifhtml)--ifhtml[process @ifhtml and @html when not ge=
nerating HTML]' \
       '(--no-ifinfo)--ifinfo[process @ifinfo even when not generating Inf=
o]' \
+      '(--plaintext --no-ifplaintext)--ifplaintext[process @ifplaintext e=
ven when not generating plain text]' \
       '(--no-iftex)--iftex[process @iftex and @tex text]' \
-      '(--no-ifplaintext)--ifplaintext[process @ifplaintext even when not=
 generating plain text]' \
-      '(--ifhtml)--no-ifhtml[do not process @ifhtml and @html text]' \
-      '(--ifinfo)--no-ifinfo[do not process @ifinfo text]' \
-      '(--ifplaintext)--no-ifplaintext[do not process @ifplaintext text]'=
 \
-      '(--iftex)--no-iftex[do not process @iftex and @tex text]' \
+      '(--xml --no-ifxml)--ifxml[process @ifxml and @xml]' \
+      "(--ifdocbook --html --xml --plaintext)--no-ifdocbook[don't process=
 @ifdocbook and @docbook text]" \
+      "(--ifhtml --docbook --xml --plaintext)--no-ifhtml[don't process @i=
fhtml and @html text]" \
+      "(--ifinfo --docbook --html --xml --plaintext)--no-ifinfo[don't pro=
cess @ifinfo text]" \
+      "(--ifplaintext --docbook --html --xml)--no-ifplaintext[don't proce=
ss @ifplaintext text]" \
+      "(--iftex --docbook --html --xml --plaintext)--no-iftex[don't proce=
ss @iftex and @tex text]" \
+      "(--ifxml --docbook --html --xml --plaintext)--no-ifxml[don't proce=
ss @ifxml and @xml text]" \
       '*:texinfo file:_texi'
       return
   ;;
-  texi2dvi)
+  (pdf|)texi2(dvi|pdf))
     _arguments -s \
       '(-b --batch)'{-b,--batch}'[no interaction]' \
-      '(-c --clean)'{-c,--clean}'[remove all auxiliary files]' \
       '(-D --debug)'{-D,--debug}'[turn on shell debugging (set -x)]' \
       '(- *)'{-h,--help}'[display help information]' \
       '(-o --output)'{-o,--output=3D}'[specify output file]:output file:_=
files' \
       '(-q -s --quiet --silent -V --verbose)'{-q,-s,--silent,--quiet}'[no=
 output except errors]' \
       '(-q -s --quiet --silent -V --verbose)'{-V,--verbose}'[report on wh=
at is done]' \
       '(- *)'{-v,--version}'[display version information]' \
+      "--max-iterations=3D[don't process files more than specified times]=
:iterations [7]" \
+      '--mostly-clean[remove the auxiliary files and directories]' \
       '-@[use @input instead of \input; for preloaded Texinfo]' \
-      '(-e --expand)'{-e,--expand}'[force macro expansion using makeinfo]=
' \
+      '(-p --pdf --dvipdf --html --info --ps --text)--dvi[output a DVI fi=
le]' \
+      '(-p --pdf --dvi --html --info --ps --text)--dvipdf[output a PDF fi=
le via DVI]' \
+      '(-p --pdf --dvi --dvipdf --info --ps --text)--html[output an HTML =
file]' \
+      '(-p --pdf --dvi --dvipdf --html --ps --text)--info[output an Info =
file]' \
+      '(-p --pdf --dvi --dvipdf --html --info --ps --text)'{-p,--pdf}'[us=
e pdftex or pdflatex for processing]' \
+      '(-p --pdf --dvi --dvipdf --html --info --text)--ps[output a PostSc=
ript file]' \
+      '(-p --pdf --dvi --dvipdf --html --info --ps)--text[output a plain =
text file]' \
+      '(-e -E --expand)'{-e,-E,--expand}'[force macro expansion using mak=
einfo]' \
       '-I[specify search dir for texinfo files]:directory:_files -/' \
       '(-l --language)'{-l,--language}'[specify language of input file]:l=
anguage:(LaTeX Texinfo)' \
-      '(-p --pdf)'{-p,--pdf}'[use pdftex or pdflatex for processing]' \
-      \*{-t,--texinfo}'[specify command to insert after @setfilename]:com=
mand' \
+      "--no-line-error[don't pass --file-line-error to TeX]" \
+      '--shell-escape[pass --shell-escape to TeX]' \
+      '--src-specials[pass --src-specials to TeX]' \
+      \*{-t,--command,--texinfo}'[specify command to insert after @setfil=
ename]:command' \
+      '--translate-file=3D[use given charset translation file for TeX]:fi=
le:_files' \
+      '(--tidy -c --clean)--build=3D[specify build mode]:build mode:(loca=
l tidy clean)' \
+      '(--tidy -c --clean --build)--tidy[same as --build=3Dtidy]' \
+      '(--tidy -c --clean --build)'{--tidy,-c,--clean}'[same as --build=3D=
clean]' \
+      '--build-dir=3D[specify build directory]:directory:_directories' \
       '*:file:_texi'
       return
   ;;
   texindex)
-    _arguments \
+    _arguments -S \
       '(* -)--help[display help]' \
       '(* -)--version[display version info]' \
-      '(--no-keep)--keep[keep temporary files around after processing]' \
-      '(--keep)--no-keep[do not keep temporary files (default)]' \
-      '(-o --output)'{-o,--output=3D}'[specify output file]:file:_files' =
\
       '*:texinfo file:_texi'
       return
   ;;
   tkinfo)
+    cmd=3D$commands[info]
     _x_arguments -C \
+      '(-)--help' \
       '-+'{headers,buttons,balloons,scrollthrough,pagesep,showdir} \
       '-linklook:menu display:(color font underline)' \
       '-highlight:link display:(color inverse underline)' \
       '-searchlook:search match display:(color inverse underline)' \
       '-iconic' \
       '-dir:info path:_dir_list' \
-      '-file:info file:_files -g "*.info(|.gz|.bz2)(-.)"' \
-      '-node:info node:->item' \
-      '*::menu items:->item' && ret=3D0
-    info=3D( _call_program info info ${(kv)opt_args[(I)-file]/-file/-f} )
+      '-file:info file:->infofiles' \
+      '-node:info node:->nodes' \
+      '*::menu items:->infomanuals' && ret=3D0
+    info=3D( info ${(kv)opt_args[(I)-file]/-file/-f} )
   ;;
 esac
 =

-case $state in
-  item )
-    local -a items tags expl infopath
-    (( $#INFOPATH )) && infopath=3D( -W ${s/:/INFOPATH} )
+if [[ -n $state ]]; then
+  local chr cache file q
+  local -a suf tags
+  local -i36 hash=3D5381
+  local -aU infopath=3D( /usr/share/info ${commands[info]:h:h}/share/info=
 ${(s.:.)INFOPATH} $infodirs )
+  infopath=3D( $^infopath(N) )
+  # run simple hash function on infopath
+  for chr in "${(s..)infopath}"; do
+    (( hash +=3D (hash << 5) + ##$chr ))
+  done
+  typeset +i -l hash=3D${hash#*\#}
+  cache=3D_cache_info_nodes_$hash
+  typeset -gHU $cache
 =

-    tags=3D(items)
-    if [[ $CURRENT -eq 1 ]]; then
-	tags+=3Dfiles
+  if [[ $state =3D infomanuals ]]; then
+    [[ -z $compstate[quote] ]] && q=3D'\\'
+    if compset -P "${q}\("; then
+      if [[ -prefix *\) ]]; then
+	file=3D"${PREFIX%%\)*}"
+	compset -P 1 '*\)'
+	state=3Dnodes
+      else
+	compset -S "${q}\)*" || suf=3D( -S "${q[1]})" )
+	state=3Dinfofiles
+      fi
     fi
+  fi
 =

-    _tags $tags
-    while _tags; do
-	if _requested files expl 'info file'; then
-	    _files "$expl[@]" $infopath -g '*.info(-.)' && ret=3D0
-	fi
-	if _requested items; then
-	    items=3D(${${(M)${${(f)"$(${info} --output - ${words[1,CURRENT-1]} 2=
>/dev/null)"}[1,(r)[[:space:]]#--- The Detailed Node Listing ---[[:space:]=
]#]}:#\* *~\* Menu:*}:/(#b)\*[[:space:]]##([^:]##):(#B)( \(?##\)[^.]#.|(:|=
))[[:space:]]#(#b)(*)[[:space:]]#/$match[1]${match[2]:+:}$match[2]})
+  [[ -z $file ]] && file=3D${opt_args[-f]:-$line[1]}
+  if [[ $state =3D info* ]]; then
+    local -aU files=3D( $^infopath/*.info(|.gz|.bz2)(-.:t:s/.gz//:s/.bz2/=
/:r) )
+    local items
+    if (( ! $#files )); then
+      _info_retrieve_nodes
+      files=3D( ${(P)cache%%:*} )
+    fi
+    items=3D( ${${${(M)${(f)"$(_call_program menu-items info -o-)"}:#(#s)=
\* *: \(*}#??}%%\)*} )
+    files+=3D( ${items##*\(} )
+    tags=3D( info-files )
+    if [[ $state !=3D infofiles ]]; then
+      tags+=3D( menu-items )
+      items=3D( ${items%:*} )
+    fi
+  elif [[ $state =3D nodes ]]; then
+    tags=3D( menu-items )
+    if [[ -n $file ]]; then
+      _info_retrieve_nodes
+      nodes=3D( ${(@PM)cache:#${file}:*} )
+      tags+=3D( info-nodes )
+    fi
+    items=3D( ${${${(M)${(f)"$(_call_program menu-items info -o- $file)"}=
:#(#s)\* *::*}%%::*}#??} )
+  fi
 =

-	    _describe -t items "menu item" items && ret=3D0
-	fi
-    done
-  ;;
-esac
+  _tags $tags
+
+  while _tags; do
+    _requested info-files expl 'info file' compadd $suf -M 'm:{a-zA-Z}=3D=
{A-Za-z}' -a files && ret=3D0
+    _requested menu-items expl 'menu item' compadd -M 'm:{a-zA-Z}=3D{A-Za=
-z}' -a items && ret=3D0
+    _requested info-nodes expl 'node' compadd -M 'm:{a-zA-Z}=3D{A-Za-z}' =
${nodes#*:} && ret=3D0
+
+    (( ret )) || break
+  done
+fi
 =

 return ret

