zsh-workers
 help / color / mirror / code / Atom feed
From: Jacob Gelbman <gelbman@gmail.com>
To: zsh-workers@zsh.org
Subject: Re: Completion script for the ctags program
Date: Wed, 24 Feb 2021 01:20:24 -0600	[thread overview]
Message-ID: <E5F09F0C-6D10-4549-9220-E097948CCEB4@gmail.com> (raw)
In-Reply-To: <FB722402-2CF7-489A-A968-F79E529E33CF@gmail.com>

Here’s the updated script. It's now is able to detect if it’s the new universal ctags, the older exuberant ctags, bsd ctags that comes with the Mac, or a symlink to etags:

#compdef ctags

local context state line expl
local -A opt_args

if [ -z "$_ctags_type" ]; then
  local output=`ctags --version 2>&1`
  if [[ "$output" = *Universal\ Ctags* ]]; then
    _ctags_type="universal"
  elif [[ "$output" = *Exuberant\ Ctags* ]]; then
    _ctags_type="exuberant"
  elif [[ "$output" = *usage:\ ctags* ]]; then
    _ctags_type="bsd"
  elif [[ "$output" = *Emacs* ]]; then
    _ctags_type="etags"
  else
    _ctags_type="universal"
  fi
fi

if [ "$_ctags_type" = "etags" ]; then
  _etags
  return $?
fi

local -a arguments

if [ "$_ctags_type" = "universal" ]; then
  arguments=(
    "-?[help text]"
    "-a[append to tags file]"
    "-B[use backward searching patterns (?...?)]"
    "-D[give definition for macro]:macro definition:"
    "-e[output tag file for use with emacs]"
    "-f[write tags to specified file. - is stdout]:file:_files"
    "-F[use forward searching patterns (/.../)]"
    "-G[equivalent to --guess-language-eagerly]"
    "-h[specify list of file extensions to be treated as include files]:"
    "-I[a list of tokens to be specifically handled is read from either the command line or the specified file]:"
    "-L[a list of input file names is read from the specified file. - is stdin]:file:_files"
    "-n[equivalent to --excmd=number]"
    "-N[equivalent to --excmd=pattern]"
    "-o[alternative to -f]:file:_files"
    "-R[equivalent to --recurse]"
    "-u[equivalent to --sort=no]"
    "-V[equivalent to --verbose]"
    "-x[print a tabular cross reference file to stdout]"
    "--alias-<lang>=[add a pattern detecting a name, can be used as an alt name for lang]:pattern"
    "--append=[should tags be appended to existing tag file]:bool:(yes no)"
    "--etags-include=[include reference to file in emacs style tag file]:file:_files"
    "--exclude=[exclude files and directories matching pattern]:pattern"
    "--exclude-exception=[don't exclude files and directories matching pattern even if they match the pattern specified with --exclude]:pattern"
    "--excmd=[uses the specified type of ex command to locate tags]:ex command type:(number pattern mix combine)"
    "--extras=[include extra tag entries for selected information (flags fFgpqrs)]:flags"
    "--extras-<lang>=[include <lang> own extra tag entries for selected information]:flags"
    "--fields=[include selected extension fields (flags aCeEfFikKlmnNpPrRsStxzZ)]:flags"
    "--fields-<lang>=[include selected <lang> own extension fields]:flags"
    "--filter=[behave as a filter, reading file names from stdin and writing tags to stdout]:bool:(yes no)"
    "--filter-terminator=[specify string to print to stdout following the tags for each file parsed when --filter is enabled]:string"
    "--format=[force output of specified tag file format]:level"
    "--guess-language-eagerly[guess the language of input file more eagerly]"
    "--help[help text]"
    "--help-full[help text with experimental features]"
    "--if0=[should code within #if 0 conditionals be parsed]:bool:(yes no)"
    "--input-encoding=[specify encoding of all input files]:encoding"
    "--input-encoding-<lang>=[specify encoding of the <lang> input files]:encoding"
    "--kinddef-<lang>=[define new kind for <lang>]:kind"
    "--kinds-<lang>=[enable/disable tag kinds for <lang>]:kind"
    "--langdef=[define a new language to be parsed with regular expressions]:name"
    "--langmap=[override default mapping of language to input file extension]:maps"
    "--language-force=[force all files to be interpreted using specified language]:language:->language"
    "--languages=[restrict files scanned to these comma-separated languages]:language:->languages"
    "--license[print details of software license]"
    "--line-directives=[should #line directives be processed]:bool:(yes no)"
    "--links=[indicate whether symlinks should be followed]:bool:(yes no)"
    "--list-aliases=[list of alias patterns]:language:->language"
    "--list-excludes[list of exclude patterns for files/dirs]"
    "--list-extras=[list of extra tag flags]:language:->language"
    "--list-features[list of compiled features]"
    "--list-fields=[list of fields]:language:->language"
    "--list-kinds=[list of all tag kinds for lang]:language:->language"
    "--list-kinds-full=[list details of all tag kinds for lang]:language:->language"
    "--list-languages[list of supported languages]"
    "--list-map-extensions=[list of language extensions in mapping]:language:->language"
    "--list-map-patterns=[list of language patterns in mapping]:language:->language"
    "--list-maps=[list of language mappings (both extensions and patterns)]:language:->language"
    "--list-mline-regex-flags[list of flags which can be used in a multiline regex parser definition]"
    "--list-params=[list of language parameters. works with --machinable]:language:->language"
    "--list-pseudo-tags[list of pseudo tags]"
    "--list-regex-flags[list of flags which can be used in a regex parser definition]"
    "--list-roles=[list of all roles of tag kinds specified for langs]:language:->language"
    "--list-subparsers=[list of subparsers for the base lang]:language:->language"
    "--machinable=[use tab separated representation in --list-* output]:bool:(yes no)"
    "--map-<lang>=[set, add(+), or remove(-) the map for <lang>]:pattern"
    "--maxdepth=[specify maximum recursion depth]:depth"
    "--mline-regex-<lang>=[define multiline regex for locating tags in <lang>]:pattern"
    "--options=[specify file (or dir) from which command line options should be read]:file:_files"
    "--options-maybe=[same as --options but doesn't error]:file:_files"
    "--optlib-dir=[add or set dir to optlib search path]:dir:_files -/"
    "--output-encoding=[the encoding to write the tag file in]:encoding"
    "--output-format=[specify the output format]:format:(u-ctags e-ctags etags xref)"
    "--param-<lang>=[set <lang> specific parameter]:argument"
    "--pattern-length-limit=[cutoff patterns of tag entries after N characters]:number"
    "--print-language[don't make tags file but just print the guessed lang name for input file]"
    "--pseudo-tags=[enable/disable emitting pseudo tag named ptag. if *, enable emitting all pseudo tags]:ptag"
    "--put-field-prefix[put UCTAGS as prefix for the name of fields newly introducted in universal ctags]"
    "--quiet=[don't print notice class messages]:bool:(yes no)"
    "--recurse=[recurse]:bool:(yes no)"
    "--regex-<lang>=[define regex for locating tags in specific lang]:pattern"
    "--roles-<lang>.<kind>=[enable/disable tag roles for kinds of <lang>]:role"
    "--sort=[should tags be sorted]:argument:(yes no foldcase)"
    "--tag-relative=[should paths be relative to location of tag file]:argument:(yes no always never)"
    "--totals=[print stats about input and tag files]:arguments:(yes no extra)"
    "--verbose=[enable verbose messages describing actions]:bool:(yes no)"
    "--version[print version]"
    "--with-list-header=[prepend the column descriptions in --list-* output]:bool:(yes no)"
    "*:file:_files"
  )
elif [ "$_ctags_type" = "exuberant" ]; then
  arguments=(
    "-a[append to tags file]"
    "-B[use backward searching patterns (?...?)]"
    "-e[output tag file for use with emacs]"
    "-f[write tags to specified file. - is stdout]:file:_files"
    "-F[use forward searching patterns (/.../)]"
    "-h[specify list of file extensions to be treated as include files]:"
    "-I[a list of tokens to be specifically handled is read from either the command line or the specified file]:"
    "-L[a list of input file names is read from the specified file. - is stdin]:file:_files"
    "-n[equivalent to --excmd=number]"
    "-N[equivalent to --excmd=pattern]"
    "-o[alternative to -f]:file:_files"
    "-R[equivalent to --recurse]"
    "-u[equivalent to --sort=no]"
    "-V[equivalent to --verbose]"
    "-x[print a tabular cross reference file to stdout]"
    "--append=[should tags be appended to existing tag file]:bool:(yes no)"
    "--etags-include=[include reference to file in emacs style tag file]:file:_files"
    "--exclude=[exclude files and directories matching pattern]:pattern"
    "--excmd=[uses the specified type of ex command to locate tags]:ex command type:(number pattern mix)"
    "--extra=[include extra tag entries for selected information (flags fq)]:flags"
    "--fields=[include selected extension fields (flags afmikKlnsStz)]:flags"
    "--file-scope=[should tags scoped only for a single file be included in output]:bool:(yes no)"
    "--filter=[behave as a filter, reading file names from stdin and writing tags to stdout]:bool:(yes no)"
    "--filter-terminator=[specify string to print to stdout following the tags for each file parsed when --filter is enabled]:string"
    "--format=[force output of specified tag file format]:level"
    "--help[help text]"
    "--if0=[should code within #if 0 conditionals be parsed]:bool:(yes no)"
    "--<lang>-kinds=[enable/disable tag kinds for <lang>]:kind"
    "--langdef=[define a new language to be parsed with regular expressions]:name"
    "--langmap=[override default mapping of language to input file extension]:maps"
    "--language-force=[force all files to be interpreted using specified language]:language:->language"
    "--languages=[restrict files scanned to these comma-separated languages]:language:->languages"
    "--license[print details of software license]"
    "--line-directives=[should #line directives be processed]:bool:(yes no)"
    "--links=[indicate whether symlinks should be followed]:bool:(yes no)"
    "--list-kinds=[list of all tag kinds for lang]:language:->language"
    "--list-languages[list of supported languages]"
    "--list-maps=[list of language mappings (both extensions and patterns)]:language:->language"
    "--options=[specify file (or dir) from which command line options should be read]:file:_files"
    "--recurse=[recurse]:bool:(yes no)"
    "--regex-<lang>=[define regex for locating tags in specific lang]:pattern"
    "--sort=[should tags be sorted]:argument:(yes no foldcase)"
    "--tag-relative=[should paths be relative to location of tag file]:argument:(yes no)"
    "--totals=[print stats about input and tag files]:arguments:(yes no)"
    "--verbose=[enable verbose messages describing actions]:bool:(yes no)"
    "--version[print version]”
    "*:file:_files"
  )
elif [ "$_ctags_type" = "bsd" ]; then
  arguments=(
    "-a[append to tags file]"
    "-B[use backward searching patterns (?...?)]"
    "-d[create tags for #defines that don't take arguments]"
    "-F[use forward searching patterns (/.../)]"
    "-f[write tags to specified file]:file:_files"
    "-t[create tags for typedefs, structs, unions, and enums]"
    "-u[update the specified files in the tags file]"
    "-v[an index of the form expected by vgrind(1) is produced]"
    "-w[suppress warning diagnostics]"
    "-x[ctags produces a simple function index]"
    "*:file:_files"
  )
fi

_arguments $arguments

if [[ "$state" = language* ]]; then
  local -a languages
  languages=(`ctags --list-languages | cut -d" " -f1`)
  if [ "$state" = "language" ]; then
    _wanted languages expl language compadd $languages
  elif [ "$state" = "languages" ]; then
    _values -s , languages $languages
  fi
fi

return $(( compstate[nmatches] > 0 ? 0 : 1 ))







> On Feb 23, 2021, at 10:45 PM, Jacob Gelbman <gelbman@gmail.com> wrote:
> 
> Hey, thanks for looking at the script and adding it to the repo, although I think some of got pasted in wrong. There’s a lot to writing completion functions and I’m still not 100% sure how to do it right.
> 
>> On Feb 23, 2021, at 3:39 PM, Oliver Kiddle <opk@zsh.org> wrote:
>> 
>> Jacob Gelbman wrote:
>>> I wrote a completion script for the ctags program. Someone might be able to use it:
>> 
>> Which ctags!?
> 
> I have Universal Ctags 5.9.0
> 
>> This doesn't match what I have installed on any of my systems. There
>> are multiple implementations of ctags, with it often being just a link
>> to etags - for which there is a completion albeit not a well maintained
>> one. One of the main reasons, a completion doesn't already exist is
>> that it would ideally need to detect the variant and at least have sane
>> fallbacks for variants that aren't handled. It could be useful to check
>> what the existing _etags is handling - that might be the exhuberant or
>> emacs variant.
>> 
> 
> I located a few other ctags on my computers, I have BSD ctags that comes by default on the mac. Exuberant Ctags 5.8. and there’s etags that comes with emacs. I can probably add an if statement based on the output of ctags —version, and modify the function from that. If it’s etags, I’ll just:
> 
> _comps[ctags]=“_etags”; _etags
> 
> And exit.
> 
>> In general, please follow the conventions outlined in
>> Etc/completion-style-guide in the zsh source distribution. For example,
>> completion functions usually use just 2 spaces for indentation.
>> 
>>> #compdef ctags
>>> 
>>> local state
>> 
>> If you use states, you need to also handle the context which means
>> either passing -C to _arguments and setting up $curcontext or declaring
>> context local and passing it to later functions like _values.
> 
> The -C argument and the context/curcontext variables are confusing me, a lot.
> 
>> 
>>>   "--alias-<lang>=[add a pattern detecting a name, can be used as an alt name for lang]:pattern" \
>>>   "--input-encoding-<lang>=[specify encoding of the <lang> input files]:encoding" \
>>>   "--kinddef-<lang>=[define new kind for <lang>]:kind" \
>>>   "--kinds-<lang>=[enable/disable tag kinds for <lang>]:kind" \
>> 
>> These would not complete especially helpfully. I suspect that <lang> there is
>> supposed to be substituted.
> 
> They’d show up in the menu when you press tab, but if I filled in the actual values, the list would be too long.
> 
>> 
>>> if [ "$state" = "language" ]; then
>>>   compadd `ctags --list-languages | cut -d" " -f1`
>> 
>> It would be nicer to use a description by calling for example, _wanted
>> here.
> 
> I can do that.
> 
>> 
>>> elif [ "$state" = "languages" ]; then
>>>   _values -s , "languages" `ctags --list-languages | cut -d" " -f1`
>>> fi
>> 
>> I'd probably use _sequence here as it is smaller and simpler. But
>> _values is fine if none of the languages contain characters that need
>> quoting from it.
> 
> This too.
> 
>> 
>> The return status from this function will not be correct in all cases.
>> This can have effects like approximate completion being activated
>> despite matches having been added by earlier completers. Where states
>> are needed, you nearly always need to either save the status from
>> _arguments, typically via a ret variable or check $compstate[nmatches]
>> on exit.
>> 
>> Oliver
> 



  reply	other threads:[~2021-02-24  7:20 UTC|newest]

Thread overview: 38+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-02-23  3:11 Jacob Gelbman
2021-02-23 10:11 ` Peter Stephenson
2021-02-23 22:20   ` Oliver Kiddle
2021-02-23 22:45     ` Bart Schaefer
2021-02-23 23:51       ` Oliver Kiddle
2021-02-24  0:52         ` Bart Schaefer
2021-02-24 13:47           ` Daniel Shahaf
2021-02-23 23:05     ` Mikael Magnusson
2021-02-23 21:39 ` Oliver Kiddle
2021-02-24  4:45   ` Jacob Gelbman
2021-02-24  7:20     ` Jacob Gelbman [this message]
2021-02-24  9:26       ` Peter Stephenson
2021-02-24 14:24       ` Daniel Shahaf
2021-02-24 18:58         ` Jacob Gelbman
2021-02-24 19:01           ` Bart Schaefer
2021-03-03 20:02         ` Daniel Shahaf
2021-03-03 20:39           ` Jacob Gelbman
2021-03-03 21:40             ` Peter Stephenson
2021-03-03 22:06             ` Daniel Shahaf
2021-03-03 22:08           ` Jacob Gelbman
2021-03-03 23:28             ` Aaron Schrab
2021-03-03 23:43               ` Daniel Shahaf
2021-03-03 23:35             ` Daniel Shahaf
2021-03-07 19:18         ` Jacob Gelbman
2021-03-07 21:42           ` Daniel Shahaf
2021-03-07 21:57             ` Jacob Gelbman
2021-03-07 22:10               ` Daniel Shahaf
2021-03-11 16:15                 ` Daniel Shahaf
2021-03-11 17:08                   ` Jacob Gelbman
2021-03-20  1:43                     ` Lawrence Velázquez
2021-03-27 16:14                       ` Lawrence Velázquez
2021-03-27 20:43                         ` Daniel Shahaf
2021-03-28 23:29                     ` Oliver Kiddle
2021-03-29  8:54                       ` Peter Stephenson
2021-03-29 15:07                         ` EOL normalization? (Was: Completion script for the ctags program) Lawrence Velázquez
2021-03-29 15:34                           ` Daniel Shahaf
2021-03-29 15:41                             ` Lawrence Velázquez
2021-02-24 21:54       ` Completion script for the ctags program dana

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=E5F09F0C-6D10-4549-9220-E097948CCEB4@gmail.com \
    --to=gelbman@gmail.com \
    --cc=zsh-workers@zsh.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).