From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on inbox.vuxu.org X-Spam-Level: X-Spam-Status: No, score=-3.4 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED, UNPARSEABLE_RELAY autolearn=ham autolearn_force=no version=3.4.4 Received: (qmail 2385 invoked from network); 24 Feb 2021 07:20:50 -0000 Received: from zero.zsh.org (2a02:898:31:0:48:4558:7a:7368) by inbox.vuxu.org with ESMTPUTF8; 24 Feb 2021 07:20:50 -0000 ARC-Seal: i=1; cv=none; a=rsa-sha256; d=zsh.org; s=rsa-20200801; t=1614151250; b=1DPJPP67wQyLLqfu5NNAScBdT04TSrFYpAfhK+4coOjsUaNcOXZILtrnR7ilDKTkUd6plQabRx Mh9qp3kFiv36npRe47dg/QgfJP1f9cxS2BeaCjI6OWiVoTxXUxMq52cKpXBLVRfFyWrKo7odZ3 kPBBDmwJ7oazcxxVP5LFuT203ijg6q4ib3Y4yy5HI1WGad+hW9DvFJPkFYBv48xrYjcPOOdr4L s18G31TRT/8S67tE+Bs/nBgbYom63wakqzBB2btNGfodfyxtb/rEcmZ4X510QYNkiMl7HqipyK Ulggxp4WMkSvnL7BVVEo9RcDiwn8pLV/yOaX44KktfKwtw==; ARC-Authentication-Results: i=1; zsh.org; iprev=pass (mail-ot1-f45.google.com) smtp.remote-ip=209.85.210.45; dkim=pass header.d=gmail.com header.s=20161025 header.a=rsa-sha256; dmarc=pass header.from=gmail.com; arc=none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed; d=zsh.org; s=rsa-20200801; t=1614151250; bh=gwYOyEQBT0CgH1FEI7xaZCUvZyAxFNCDhTh7gDi8phY=; h=List-Archive:List-Owner:List-Post:List-Unsubscribe:List-Subscribe:List-Help: List-Id:Sender:Message-ID:In-Reply-To:To:References:Date:Subject: MIME-Version:Content-Transfer-Encoding:Content-Type:From:DKIM-Signature: DKIM-Signature; b=bC3D4O3g4/FO/uM0eU4Ux/I9zu7qSTJjKbN7Lk0NWiCxw2uxSXPvqD3NbNvrKfGC9WEN095Frz 3xJsmzlA1JORFVGXU/+MaXKpWyF2g8JeDVk/vJdzj/Tb+8MFJbo4Pgt7EDolysGog2fUaXmR2X aRqgQmU1zY/+CkceU3VB9byMxqffq5sX+bBGJbULU1MWuyXI3yDfXFav4ov7uGJe3rk1lhSxFs Z5GqZdA94pM45ge4qj/vS+ifRXPjyKwUZe7hLuWxMWgZY92KoC/FBB1TGmFv/KC3jPkC8b0Huu Qb5/hybSkM+iu8Y7BsrsY/I33Zy2Gi0mF4uqkKGMx5OjQw==; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=zsh.org; s=rsa-20200801; h=List-Archive:List-Owner:List-Post:List-Unsubscribe: List-Subscribe:List-Help:List-Id:Sender:Message-Id:In-Reply-To:To:References: Date:Subject:Mime-Version:Content-Transfer-Encoding:Content-Type:From: Reply-To:Cc:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID; bh=htVMbp903W10RL++CaNllm7UkzCnQYUxoGeiv4n9wkk=; b=nkwmgAVUUs160tGKIpdokorRdF cV2m6Ei4mE0V1S7MMXXO2d2ILOs/OEo6lbq7zhSF0Uyhk8oRig+JI8o5IT+waUK4tjE2nHZB/e80I w4fQgfDWswP1NM/Fkp2UCrGQT7IJEAmXl+th9gUsjT63gSiRRG3z0Fkx6nV1InJkVYcdC8AuE/kqw ToDDFOj/0PI7f17Z/dHHbIG/bMkdpIndd0BvA/CChwH3kunN0N5EJcQr2gPV2QlKMGk7vJagcZ7xX bpdL5koenMXMR38+WIPcI5swVNRuTOxcX3T5TfUvb+uL4ttLmx4wri4KHJFqqaVbgh7vnOyX15Bbx GAIIuXkw==; Received: from authenticated user by zero.zsh.org with local id 1lEoTT-00025m-VF; Wed, 24 Feb 2021 07:20:44 +0000 Authentication-Results: zsh.org; iprev=pass (mail-ot1-f45.google.com) smtp.remote-ip=209.85.210.45; dkim=pass header.d=gmail.com header.s=20161025 header.a=rsa-sha256; dmarc=pass header.from=gmail.com; arc=none Received: from mail-ot1-f45.google.com ([209.85.210.45]:45824) by zero.zsh.org with esmtps (TLS1.3:TLS_AES_128_GCM_SHA256:128) id 1lEoTD-0001wu-Qr; Wed, 24 Feb 2021 07:20:28 +0000 Received: by mail-ot1-f45.google.com with SMTP id d9so1247747ote.12 for ; Tue, 23 Feb 2021 23:20:27 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:content-transfer-encoding:mime-version:subject:date:references :to:in-reply-to:message-id; bh=htVMbp903W10RL++CaNllm7UkzCnQYUxoGeiv4n9wkk=; b=ElcU34nAAdWfJ4e9OIw8pCcmIOq5KQoIamWbfqCM+1FBw2upfGirE7dNSH9xsENHMu wcLUNzl4je6K63OZ+hOiLPjhU+Zt1soP1pi2zKtCcJL94OoreNjWq7HViTdLChxHdivV CrPQWXS131g6tbLwvF9btqp26NUTMKz6RVy78jL04H+TlXYoRJjncprui+RxEQzOJco4 Tpt1s0uUDQxAcMo8nm/0BvXG8tkcnLZgiRHSuRUv1T8Wg9YmqJWWmjxZ+SQYv+mjksuV fRUUcdFFNlbEl7DBDS3quoKhJW3Q5ijsaPV108efvX8oQud2LgfU18VX8qsGOAI5ykn+ ySWw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:content-transfer-encoding:mime-version :subject:date:references:to:in-reply-to:message-id; bh=htVMbp903W10RL++CaNllm7UkzCnQYUxoGeiv4n9wkk=; b=DZ+zXNDiBh5HEvOkEgp3B0/ET0VT2DIy9KFMJAKCPSkaSnbw43kDqW4+VeNhBdaSnx 0+yH+nLy6+6BxUarnPmeZGKX5HDplLNoKc6YPY6hpHhWNMOC707pSDatiZNNyN0UA9kn 9M43/ZfQYesJwpYj0wSiKWKEzzLYWHyT5g+IzMYQyaMRhmPJWvAGN6j8dFmcu1nCmpJP aDvz+GNaWwCEkXBDwdUMz57n7FTZNGCTecf3mRP5vnvTLEo+Z1RETqqPXzWb7ZNOdpt/ 8C2E+kank9QAfVADtcqybFTTrXWrrCBJRuUh0WClW0ErsyRsbVJUBlrkHLVKfEWO8E9S pdsw== X-Gm-Message-State: AOAM53375QYY2E34Ia9Fr6MYgZaCzDhRgtMelJ9Wa4V6cin9C/X50fIx 1wLLPYH8KRZq20XlQWz7aoTP3FGy1vg= X-Google-Smtp-Source: ABdhPJy0lDXqlxIXgKORZGo5PJrot1hC6vbPjHKHUfQfn/4juYz5RA15+hGicqCl29hGwZWK7/EioQ== X-Received: by 2002:a05:6830:22fa:: with SMTP id t26mr5210551otc.143.1614151226010; Tue, 23 Feb 2021 23:20:26 -0800 (PST) Received: from ?IPv6:2601:2c3:ca81:7bc0:147a:84dc:a9b:ce74? ([2601:2c3:ca81:7bc0:147a:84dc:a9b:ce74]) by smtp.gmail.com with ESMTPSA id y143sm242726oie.50.2021.02.23.23.20.25 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Tue, 23 Feb 2021 23:20:25 -0800 (PST) From: Jacob Gelbman Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Mime-Version: 1.0 (Mac OS X Mail 13.4 \(3608.120.23.2.4\)) Subject: Re: Completion script for the ctags program Date: Wed, 24 Feb 2021 01:20:24 -0600 References: <31598-1614116362.902856@aI-l.maGv.3QD7> To: zsh-workers@zsh.org In-Reply-To: Message-Id: X-Mailer: Apple Mail (2.3608.120.23.2.4) X-Seq: 48105 Archived-At: X-Loop: zsh-workers@zsh.org Errors-To: zsh-workers-owner@zsh.org Precedence: list Precedence: bulk Sender: zsh-workers-request@zsh.org X-no-archive: yes List-Id: List-Help: List-Subscribe: List-Unsubscribe: List-Post: List-Owner: List-Archive: Archived-At: Here=E2=80=99s the updated script. It's now is able to detect if it=E2=80=99= 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=3D`ctags --version 2>&1` if [[ "$output" =3D *Universal\ Ctags* ]]; then _ctags_type=3D"universal" elif [[ "$output" =3D *Exuberant\ Ctags* ]]; then _ctags_type=3D"exuberant" elif [[ "$output" =3D *usage:\ ctags* ]]; then _ctags_type=3D"bsd" elif [[ "$output" =3D *Emacs* ]]; then _ctags_type=3D"etags" else _ctags_type=3D"universal" fi fi if [ "$_ctags_type" =3D "etags" ]; then _etags return $? fi local -a arguments if [ "$_ctags_type" =3D "universal" ]; then arguments=3D( "-?[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=3Dnumber]" "-N[equivalent to --excmd=3Dpattern]" "-o[alternative to -f]:file:_files" "-R[equivalent to --recurse]" "-u[equivalent to --sort=3Dno]" "-V[equivalent to --verbose]" "-x[print a tabular cross reference file to stdout]" "--alias-=3D[add a pattern detecting a name, can be used as an = alt name for lang]:pattern" "--append=3D[should tags be appended to existing tag file]:bool:(yes = no)" "--etags-include=3D[include reference to file in emacs style tag = file]:file:_files" "--exclude=3D[exclude files and directories matching = pattern]:pattern" "--exclude-exception=3D[don't exclude files and directories matching = pattern even if they match the pattern specified with = --exclude]:pattern" "--excmd=3D[uses the specified type of ex command to locate tags]:ex = command type:(number pattern mix combine)" "--extras=3D[include extra tag entries for selected information = (flags fFgpqrs)]:flags" "--extras-=3D[include own extra tag entries for = selected information]:flags" "--fields=3D[include selected extension fields (flags = aCeEfFikKlmnNpPrRsStxzZ)]:flags" "--fields-=3D[include selected own extension = fields]:flags" "--filter=3D[behave as a filter, reading file names from stdin and = writing tags to stdout]:bool:(yes no)" "--filter-terminator=3D[specify string to print to stdout following = the tags for each file parsed when --filter is enabled]:string" "--format=3D[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=3D[should code within #if 0 conditionals be parsed]:bool:(yes = no)" "--input-encoding=3D[specify encoding of all input files]:encoding" "--input-encoding-=3D[specify encoding of the input = files]:encoding" "--kinddef-=3D[define new kind for ]:kind" "--kinds-=3D[enable/disable tag kinds for ]:kind" "--langdef=3D[define a new language to be parsed with regular = expressions]:name" "--langmap=3D[override default mapping of language to input file = extension]:maps" "--language-force=3D[force all files to be interpreted using = specified language]:language:->language" "--languages=3D[restrict files scanned to these comma-separated = languages]:language:->languages" "--license[print details of software license]" "--line-directives=3D[should #line directives be = processed]:bool:(yes no)" "--links=3D[indicate whether symlinks should be followed]:bool:(yes = no)" "--list-aliases=3D[list of alias patterns]:language:->language" "--list-excludes[list of exclude patterns for files/dirs]" "--list-extras=3D[list of extra tag flags]:language:->language" "--list-features[list of compiled features]" "--list-fields=3D[list of fields]:language:->language" "--list-kinds=3D[list of all tag kinds for = lang]:language:->language" "--list-kinds-full=3D[list details of all tag kinds for = lang]:language:->language" "--list-languages[list of supported languages]" "--list-map-extensions=3D[list of language extensions in = mapping]:language:->language" "--list-map-patterns=3D[list of language patterns in = mapping]:language:->language" "--list-maps=3D[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=3D[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=3D[list of all roles of tag kinds specified for = langs]:language:->language" "--list-subparsers=3D[list of subparsers for the base = lang]:language:->language" "--machinable=3D[use tab separated representation in --list-* = output]:bool:(yes no)" "--map-=3D[set, add(+), or remove(-) the map for = ]:pattern" "--maxdepth=3D[specify maximum recursion depth]:depth" "--mline-regex-=3D[define multiline regex for locating tags in = ]:pattern" "--options=3D[specify file (or dir) from which command line options = should be read]:file:_files" "--options-maybe=3D[same as --options but doesn't = error]:file:_files" "--optlib-dir=3D[add or set dir to optlib search path]:dir:_files = -/" "--output-encoding=3D[the encoding to write the tag file = in]:encoding" "--output-format=3D[specify the output format]:format:(u-ctags = e-ctags etags xref)" "--param-=3D[set specific parameter]:argument" "--pattern-length-limit=3D[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=3D[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=3D[don't print notice class messages]:bool:(yes no)" "--recurse=3D[recurse]:bool:(yes no)" "--regex-=3D[define regex for locating tags in specific = lang]:pattern" "--roles-.=3D[enable/disable tag roles for kinds of = ]:role" "--sort=3D[should tags be sorted]:argument:(yes no foldcase)" "--tag-relative=3D[should paths be relative to location of tag = file]:argument:(yes no always never)" "--totals=3D[print stats about input and tag files]:arguments:(yes = no extra)" "--verbose=3D[enable verbose messages describing actions]:bool:(yes = no)" "--version[print version]" "--with-list-header=3D[prepend the column descriptions in --list-* = output]:bool:(yes no)" "*:file:_files" ) elif [ "$_ctags_type" =3D "exuberant" ]; then arguments=3D( "-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=3Dnumber]" "-N[equivalent to --excmd=3Dpattern]" "-o[alternative to -f]:file:_files" "-R[equivalent to --recurse]" "-u[equivalent to --sort=3Dno]" "-V[equivalent to --verbose]" "-x[print a tabular cross reference file to stdout]" "--append=3D[should tags be appended to existing tag file]:bool:(yes = no)" "--etags-include=3D[include reference to file in emacs style tag = file]:file:_files" "--exclude=3D[exclude files and directories matching = pattern]:pattern" "--excmd=3D[uses the specified type of ex command to locate tags]:ex = command type:(number pattern mix)" "--extra=3D[include extra tag entries for selected information = (flags fq)]:flags" "--fields=3D[include selected extension fields (flags = afmikKlnsStz)]:flags" "--file-scope=3D[should tags scoped only for a single file be = included in output]:bool:(yes no)" "--filter=3D[behave as a filter, reading file names from stdin and = writing tags to stdout]:bool:(yes no)" "--filter-terminator=3D[specify string to print to stdout following = the tags for each file parsed when --filter is enabled]:string" "--format=3D[force output of specified tag file format]:level" "--help[help text]" "--if0=3D[should code within #if 0 conditionals be parsed]:bool:(yes = no)" "---kinds=3D[enable/disable tag kinds for ]:kind" "--langdef=3D[define a new language to be parsed with regular = expressions]:name" "--langmap=3D[override default mapping of language to input file = extension]:maps" "--language-force=3D[force all files to be interpreted using = specified language]:language:->language" "--languages=3D[restrict files scanned to these comma-separated = languages]:language:->languages" "--license[print details of software license]" "--line-directives=3D[should #line directives be = processed]:bool:(yes no)" "--links=3D[indicate whether symlinks should be followed]:bool:(yes = no)" "--list-kinds=3D[list of all tag kinds for = lang]:language:->language" "--list-languages[list of supported languages]" "--list-maps=3D[list of language mappings (both extensions and = patterns)]:language:->language" "--options=3D[specify file (or dir) from which command line options = should be read]:file:_files" "--recurse=3D[recurse]:bool:(yes no)" "--regex-=3D[define regex for locating tags in specific = lang]:pattern" "--sort=3D[should tags be sorted]:argument:(yes no foldcase)" "--tag-relative=3D[should paths be relative to location of tag = file]:argument:(yes no)" "--totals=3D[print stats about input and tag files]:arguments:(yes = no)" "--verbose=3D[enable verbose messages describing actions]:bool:(yes = no)" "--version[print version]=E2=80=9D "*:file:_files" ) elif [ "$_ctags_type" =3D "bsd" ]; then arguments=3D( "-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" =3D language* ]]; then local -a languages languages=3D(`ctags --list-languages | cut -d" " -f1`) if [ "$state" =3D "language" ]; then _wanted languages expl language compadd $languages elif [ "$state" =3D "languages" ]; then _values -s , languages $languages fi fi return $(( compstate[nmatches] > 0 ? 0 : 1 )) > On Feb 23, 2021, at 10:45 PM, Jacob Gelbman wrote: >=20 > Hey, thanks for looking at the script and adding it to the repo, = although I think some of got pasted in wrong. There=E2=80=99s a lot to = writing completion functions and I=E2=80=99m still not 100% sure how to = do it right. >=20 >> On Feb 23, 2021, at 3:39 PM, Oliver Kiddle wrote: >>=20 >> Jacob Gelbman wrote: >>> I wrote a completion script for the ctags program. Someone might be = able to use it: >>=20 >> Which ctags!? >=20 > I have Universal Ctags 5.9.0 >=20 >> 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. >>=20 >=20 > 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=E2=80=99s = etags that comes with emacs. I can probably add an if statement based on = the output of ctags =E2=80=94version, and modify the function from that. = If it=E2=80=99s etags, I=E2=80=99ll just: >=20 > _comps[ctags]=3D=E2=80=9C_etags=E2=80=9D; _etags >=20 > And exit. >=20 >> 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. >>=20 >>> #compdef ctags >>>=20 >>> local state >>=20 >> 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. >=20 > The -C argument and the context/curcontext variables are confusing me, = a lot. >=20 >>=20 >>> "--alias-=3D[add a pattern detecting a name, can be used as = an alt name for lang]:pattern" \ >>> "--input-encoding-=3D[specify encoding of the input = files]:encoding" \ >>> "--kinddef-=3D[define new kind for ]:kind" \ >>> "--kinds-=3D[enable/disable tag kinds for ]:kind" \ >>=20 >> These would not complete especially helpfully. I suspect that = there is >> supposed to be substituted. >=20 > They=E2=80=99d show up in the menu when you press tab, but if I filled = in the actual values, the list would be too long. >=20 >>=20 >>> if [ "$state" =3D "language" ]; then >>> compadd `ctags --list-languages | cut -d" " -f1` >>=20 >> It would be nicer to use a description by calling for example, = _wanted >> here. >=20 > I can do that. >=20 >>=20 >>> elif [ "$state" =3D "languages" ]; then >>> _values -s , "languages" `ctags --list-languages | cut -d" " -f1` >>> fi >>=20 >> 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. >=20 > This too. >=20 >>=20 >> 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. >>=20 >> Oliver >=20