Skip to content

Commit

Permalink
Merge pull request universal-ctags#4152 from masatake/nulltag
Browse files Browse the repository at this point in the history
main: add nulltag/z, a new extra
  • Loading branch information
masatake authored Dec 24, 2024
2 parents 43ca055 + a82df36 commit a484466
Show file tree
Hide file tree
Showing 46 changed files with 420 additions and 60 deletions.
5 changes: 5 additions & 0 deletions Tmain/extras-long.d/stdout-expected.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ p pseudo no NONE no Include pseudo tags
q qualified no NONE no Include an extra class-qualified tag entry for each tag
r reference no NONE no Include reference tags
s subparser yes NONE no Include tags generated by subparsers
z nulltag no NONE no Include tags with empty strings as their names
- canonicalizedName yes Automake no Include canonicalized object name like libctags_a
- linkName no Fortran no Linking name used in foreign languages
- implicitClass no GDScript no Include tag for the implicitly defined unnamed class
Expand All @@ -25,6 +26,7 @@ p pseudo yes NONE no Include pseudo tags
q qualified no NONE no Include an extra class-qualified tag entry for each tag
r reference no NONE no Include reference tags
s subparser yes NONE no Include tags generated by subparsers
z nulltag no NONE no Include tags with empty strings as their names
- canonicalizedName yes Automake no Include canonicalized object name like libctags_a
- linkName no Fortran no Linking name used in foreign languages
- implicitClass no GDScript no Include tag for the implicitly defined unnamed class
Expand All @@ -43,6 +45,7 @@ p pseudo yes NONE no Include pseudo tags
q qualified no NONE no Include an extra class-qualified tag entry for each tag
r reference no NONE no Include reference tags
s subparser yes NONE no Include tags generated by subparsers
z nulltag no NONE no Include tags with empty strings as their names
- canonicalizedName yes Automake no Include canonicalized object name like libctags_a
- linkName no Fortran no Linking name used in foreign languages
- implicitClass no GDScript no Include tag for the implicitly defined unnamed class
Expand All @@ -61,6 +64,7 @@ p pseudo yes NONE no Include pseudo tags
q qualified no NONE no Include an extra class-qualified tag entry for each tag
r reference yes NONE no Include reference tags
s subparser yes NONE no Include tags generated by subparsers
z nulltag no NONE no Include tags with empty strings as their names
- canonicalizedName yes Automake no Include canonicalized object name like libctags_a
- linkName no Fortran no Linking name used in foreign languages
- implicitClass no GDScript no Include tag for the implicitly defined unnamed class
Expand All @@ -79,6 +83,7 @@ p pseudo yes NONE no Include pseudo tags
q qualified yes NONE no Include an extra class-qualified tag entry for each tag
r reference yes NONE no Include reference tags
s subparser yes NONE no Include tags generated by subparsers
z nulltag no NONE no Include tags with empty strings as their names
- canonicalizedName yes Automake no Include canonicalized object name like libctags_a
- linkName no Fortran no Linking name used in foreign languages
- implicitClass no GDScript no Include tag for the implicitly defined unnamed class
Expand Down
1 change: 1 addition & 0 deletions Tmain/json-output-format.d/stdout-expected.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
{"_type": "ptag", "name": "TAG_EXTRA_DESCRIPTION", "path": "fileScope", "pattern": "Include tags of file scope"}
{"_type": "ptag", "name": "TAG_EXTRA_DESCRIPTION", "path": "guest", "pattern": "Include tags generated by guest parsers"}
{"_type": "ptag", "name": "TAG_EXTRA_DESCRIPTION", "path": "inputFile", "pattern": "Include an entry for the base file name of every input file"}
{"_type": "ptag", "name": "TAG_EXTRA_DESCRIPTION", "path": "nulltag", "pattern": "Include tags with empty strings as their names"}
{"_type": "ptag", "name": "TAG_EXTRA_DESCRIPTION", "path": "pseudo", "pattern": "Include pseudo tags"}
{"_type": "ptag", "name": "TAG_EXTRA_DESCRIPTION", "path": "qualified", "pattern": "Include an extra class-qualified tag entry for each tag"}
{"_type": "ptag", "name": "TAG_EXTRA_DESCRIPTION", "path": "reference", "pattern": "Include reference tags"}
Expand Down
4 changes: 4 additions & 0 deletions Tmain/kind-abnormal-spec.d/stdout-expected.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ r emit a tag with multi roles
R emit a tag with multi roles(disabled by default) [off]
f tag for testing field:
n trigger notice output
z emit a tag having an empty string
Z don't emit a tag having an empty string

# list kinds-full
#LETTER NAME ENABLED REFONLY NROLES MASTER DESCRIPTION
Expand All @@ -22,12 +24,14 @@ L ThisShouldNotBePrintedKindNameMustBeGiven yes no 0 NONE
N nothingSpecial yes no 0 NONE emit a normal tag
Q quit yes no 0 NONE stop the parsing
R rolesDisabled no yes 2 NONE emit a tag with multi roles(disabled by default)
Z dontEmitNullTag yes no 0 NONE don't emit a tag having an empty string
b broken tag yes no 1 NONE name with unwanted characters
d disabled no no 2 NONE a kind disabled by default
e enabled yes no 2 NONE a kind enabled by default
f fieldMaker yes no 0 NONE tag for testing field:
n triggerNotice yes no 0 NONE trigger notice output
r roles yes yes 4 NONE emit a tag with multi roles
z emitNullTag yes no 0 NONE emit a tag having an empty string

# +K
abnormal kindDefinition testing (no letter) input.x /^@$/;" no letter
Expand Down
3 changes: 3 additions & 0 deletions Tmain/list-extras.d/stdout-expected.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ p pseudo yes NONE no Include pseudo tags
q qualified yes NONE no Include an extra class-qualified tag entry for each tag
r reference yes NONE no Include reference tags
s subparser yes NONE no Include tags generated by subparsers
z nulltag yes NONE no Include tags with empty strings as their names
- canonicalizedName yes Automake no Include canonicalized object name like libctags_a
- linkName no Fortran no Linking name used in foreign languages
- implicitClass no GDScript no Include tag for the implicitly defined unnamed class
Expand All @@ -25,6 +26,7 @@ p pseudo yes NONE no Include pseudo tags
q qualified yes NONE no Include an extra class-qualified tag entry for each tag
r reference yes NONE no Include reference tags
s subparser yes NONE no Include tags generated by subparsers
z nulltag yes NONE no Include tags with empty strings as their names
- canonicalizedName yes Automake no Include canonicalized object name like libctags_a
- linkName no Fortran no Linking name used in foreign languages
- implicitClass no GDScript no Include tag for the implicitly defined unnamed class
Expand All @@ -43,3 +45,4 @@ p pseudo no NONE no Include pseudo tags
q qualified no NONE no Include an extra class-qualified tag entry for each tag
r reference no NONE no Include reference tags
s subparser no NONE no Include tags generated by subparsers
z nulltag no NONE no Include tags with empty strings as their names
1 change: 1 addition & 0 deletions Tmain/list-output-formats.d/exit-expected.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0
7 changes: 7 additions & 0 deletions Tmain/list-output-formats.d/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Copyright: 2024 Masatake YAMATO
# License: GPL-2

CTAGS=$1

$CTAGS --quiet --options=NONE --machinable --with-list-header \
--list-output-formats | grep -v '^json'
Empty file.
5 changes: 5 additions & 0 deletions Tmain/list-output-formats.d/stdout-expected.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#OFORMAT DEFAULT AVAILABLE NULLTAG
e-ctags no yes no
etags no yes no
u-ctags yes yes no
xref no yes yes
3 changes: 3 additions & 0 deletions Tmain/nulltag-extra.d/input.cst
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Z
z

30 changes: 30 additions & 0 deletions Tmain/nulltag-extra.d/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Copyright: 2024 Masatake YAMATO
# License: GPL-2

CTAGS=$1

. ../utils.sh

# The order of stdout and stderr lines is not stable.
exit_if_win32 "$CTAGS"

# is_feature_available $CTAGS json

O="--options=NONE --language-force=CTagsSelfTest"

for fmt in xref; do
echo "# no extra ($fmt)"
${CTAGS} $O -o - --output-format="$fmt" input.cst 2>&1

echo "# drop '0' extra ($fmt)"
${CTAGS} $O -o - --output-format="$fmt" --extras=-z input.cst 2>&1

echo "# drop '{nulltag}' extra ($fmt)"
${CTAGS} $O -o - --output-format="$fmt" --extras=-'{nulltag}' input.cst 2>&1

echo '# with --extras=+0 ($fmt)'
${CTAGS} $O -o - --output-format="$fmt" --extras=+z input.cst 2>&1

echo "# with --extras=+{nulltag}' ($fmt)"
${CTAGS} $O -o - --output-format="$fmt" --extras=+'{nulltag}' input.cst 2>&1
done | sed -e 's/\.exe//'
Empty file.
17 changes: 17 additions & 0 deletions Tmain/nulltag-extra.d/stdout-expected.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# no extra (xref)
ctags: Notice: No options will be read from files or environment
ctags: Notice: ignoring null tag in input.cst(line: 1, language: CTagsSelfTest)
# drop '0' extra (xref)
ctags: Notice: No options will be read from files or environment
ctags: Notice: ignoring null tag in input.cst(line: 1, language: CTagsSelfTest)
# drop '{nulltag}' extra (xref)
ctags: Notice: No options will be read from files or environment
ctags: Notice: ignoring null tag in input.cst(line: 1, language: CTagsSelfTest)
# with --extras=+0 ($fmt)
ctags: Notice: No options will be read from files or environment
ctags: Notice: ignoring null tag in input.cst(line: 1, language: CTagsSelfTest)
emitNullTag 2 input.cst z
# with --extras=+{nulltag}' (xref)
ctags: Notice: No options will be read from files or environment
ctags: Notice: ignoring null tag in input.cst(line: 1, language: CTagsSelfTest)
emitNullTag 2 input.cst z
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
--sort=no
--extras=+{nulltag}
--fields=+{extras}
--output-format=json
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
{"_type": "tag", "name": "", "path": "input.js", "pattern": "/^var variable = { \"\": \"value\" };$/", "kind": "property", "scope": "variable", "scopeKind": "variable", "extras": "nulltag"}
{"_type": "tag", "name": "variable", "path": "input.js", "pattern": "/^var variable = { \"\": \"value\" };$/", "kind": "variable"}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
var variable = { "": "value" };
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
--sort=no
--extras=+{nulltag}
--fields=+{extras}
-x
--_xformat=%-16N %-10K %4n input.js %C
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
property 1 input.js var variable = { "": "value" };
variable variable 1 input.js var variable = { "": "value" };
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
var variable = { "": "value" };
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
--sort=no
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
variable input.js /^var variable = { "": "value" };$/;" v
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
var variable = { "": "value" };
20 changes: 20 additions & 0 deletions docs/internal.rst
Original file line number Diff line number Diff line change
Expand Up @@ -964,6 +964,26 @@ Refer `peg/valink.peg
<https://github.com/universal-ctags/ctags/blob/master/peg/varlink.peg>`_ as a
sample of a parser using PackCC.

Null tags
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*Null tag* is a tag having an empty string as its name.

Universal Ctags supports null tags cautiously.
See the description for ``nulltag``/``z`` extra in :ref:`ctags(1) <ctags(1)>`.

If you want to make a null tag, set 1 to ``allowNullTag`` of
``tagEtnryInfo`` before calling ``makeTagEntry``. ``makeTagEntry``
evaluates the member. The following pseudo code doesn't work:

.. code-block:: C
tagEntryInfo e;
/* ... */
int corkIndex = makeTagEntry (&e);
/* ... */
tagEntryInfo *p = getEntryInCorkQueue (corkIndex);
p->allowNullTag = 1;
Automatic parser guessing (TBW)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Expand Down
33 changes: 33 additions & 0 deletions docs/man/ctags.1.rst
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,8 @@ Output Format Options
the ctags executable is built with ``libjansson``.
See :ref:`ctags-json-output(5) <ctags-json-output(5)>` for more about ``json`` format.

See also ``--list-output-formats``.

``-e``
Same as ``--output-format=etags``.
Enable etags mode, which will create a tag file for use with the Emacs
Expand Down Expand Up @@ -1236,6 +1238,14 @@ Listing Options
definition.
See :ref:`ctags-optlib(7) <ctags-optlib(7)>`.

``--list-output-formats``
Lists the output formats that can be used in ``--output-format`` option.

``NULLTAG`` column represetns whether the format supports *null tags* or
not. See ``nulltag``/``z`` in "`Extras`_" about the null tags.

(since verison 6.2.0)

``--list-params[=(<language>|all)]``
Lists the parameters for either the specified *<language>* or ``all``
languages, and then exits.
Expand Down Expand Up @@ -1835,6 +1845,8 @@ roles of tags to include in the output file for a particular language.
Inquire the output of "``ctags --list-roles``" for the list of
roles.

.. _extras:

Extras
~~~~~~

Expand Down Expand Up @@ -1927,6 +1939,25 @@ The meaning of major extras is as follows (long-name flag/one-letter flag):

The etags mode enables the ``Unknown`` parser implicitly.

``nulltag``/``z``
Include tags (*null tags*) having empty strings as their names.
Generally speaking, trying to make a null tag is a sign of a parser bug
or broken input. ctags warns such trying or throws the
null tag away. To suppress the warnings, use ``--quiet`` option.

On the other hand, null tags are valid in some languages.
Consider ``{"": val}`` in a JavaScript sourece code. The empty string is
valid as a key. If a parser intentionally makes a null tag (a valid null tag),
ctags doesn't warn but discard it by default.

The discards are due because some output formats may not consider null tags.

With ``nulltag``/``z`` extra, you can force ctags to emit the nulltags. This extra
is effective only if the output format supports null tags. ``--list-output-formats``
option tells you which output formats support null tags.

(since version 6.2.0)

``pseudo``/``p``
Include pseudo-tags. Enabled by default unless the tag file is
written to standard output. See :ref:`ctags-client-tools(7) <ctags-client-tools(7)>` about
Expand Down Expand Up @@ -2273,6 +2304,8 @@ The official Universal Ctags web site at: https://ctags.io/
Also ``ex(1)``, ``vi(1)``, ``elvis(1)``, or, better yet, ``vim(1)``, the official editor of ctags.
For more information on ``vim(1)``, see the Vim web site at: https://www.vim.org/

About the file format for ``TAGS``, see `emacs git
<https://git.savannah.gnu.org/cgit/emacs.git/tree/etc/ETAGS.EBNF>`_.

AUTHOR
------
Expand Down
14 changes: 14 additions & 0 deletions docs/news/HEAD.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,20 @@ Changes in 6.?.0
New and extended options and their flags
---------------------------------------------------------------------

``--list-output-formats`` option
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
See :ref:`option_listing` in :ref:`ctags(1) <ctags(1)>`.

``nulltag``/``z`` extra
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Universal Ctags now supports tags (*null tags*) having empty strings as their names.
See :ref:`extras` in :ref:`ctags(1) <ctags(1)>`.

.. note::

* ``libreadtags`` and ``readtags`` do not support the null tags yet.
* ``json`` and ``xref`` output formats support the null tags.

Incompatible changes
---------------------------------------------------------------------

Expand Down
8 changes: 2 additions & 6 deletions docs/output-format.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,8 @@ Supported *format* are ``u-ctags``, ``e-ctags``, ``etags``, ``xref``, and ``json

``etags``
Output format for Emacs etags.
``--output-format=etags`` can be abbreviated as ``-e``.

See `emacs git
<https://git.savannah.gnu.org/cgit/emacs.git/tree/etc/ETAGS.EBNF>`_ for
details.
See the description of ``-e`` option in :ref:`ctags(1) <ctags(1)>`.

``xref``
A tabular, human-readable cross reference (xref) format.
Expand All @@ -38,7 +35,7 @@ Supported *format* are ``u-ctags``, ``e-ctags``, ``etags``, ``xref``, and ``json
``json``
JSON format.

See section :ref:`output-json` for details.
See :ref:`ctags-client-tools(7) <ctags-client-tools(7)>`.

*********

Expand All @@ -47,4 +44,3 @@ Supported *format* are ``u-ctags``, ``e-ctags``, ``etags``, ``xref``, and ``json

output-tags.rst
output-xref.rst
output-json.rst
6 changes: 0 additions & 6 deletions docs/output-json.rst

This file was deleted.

18 changes: 9 additions & 9 deletions main/colprint.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@


enum colprintJustification {
COLPRINT_LEFT, /* L:... */
COLPRINT_RIGHT, /* R:... */
COLPRINT_LAST,
COLPRINT_LEFT = 0,
COLPRINT_RIGHT = 1,
COLPRINT_JUST = 1 << 0,
COLPRINT_LAST = 1 << 1, /* private use */
};

struct colprintHeaderColumn {
Expand Down Expand Up @@ -101,7 +102,7 @@ struct colprintTable *colprintTableNew (const char* columnHeader, ... /* NULL TE

struct colprintHeaderColumn *last_col = ptrArrayLast (table->header);
if (last_col)
last_col->justification = COLPRINT_LAST;
last_col->justification |= COLPRINT_LAST;

return table;
}
Expand Down Expand Up @@ -130,7 +131,7 @@ static void colprintColumnPrintGeneric (vString *column, struct colprintHeaderCo
if (machinable)
{
fputs (vStringValue (column), fp);
if (spec->justification != COLPRINT_LAST)
if (! (spec->justification & COLPRINT_LAST))
fputc ('\t', fp);
}
else
Expand All @@ -139,17 +140,16 @@ static void colprintColumnPrintGeneric (vString *column, struct colprintHeaderCo
size_t colLen = vStringLength (column);
if (colLen < maxWidth)
padLen = maxWidth - colLen;
if (spec->justification == COLPRINT_LEFT
|| spec->justification == COLPRINT_LAST)
if ((spec->justification & COLPRINT_JUST) == COLPRINT_LEFT)
{
fputs (vStringValue (column), fp);
if (spec->justification != COLPRINT_LAST)
if (! (spec->justification & COLPRINT_LAST))
{
fillWithWhitespaces (padLen, fp);
fputc (' ', fp);
}
}
else
else if ((spec->justification & COLPRINT_JUST) == COLPRINT_RIGHT)
{
fillWithWhitespaces (padLen, fp);
fputs (vStringValue (column), fp);
Expand Down
Loading

0 comments on commit a484466

Please sign in to comment.