Exuberant Ctags 未在 Windows 上正确排除文件

aus*_*rft 3 windows ctags exuberant-ctags

像这样执行Ctags时

ctags -V -R --exclude=*.js
Run Code Online (Sandbox Code Playgroud)

*.js正如您在日志中看到的那样,它没有正确排除文件

Reading initial options from command line
  Option: --exclude=*.js
adding exclude pattern: *.js
Reading command line arguments
OPENING app.js as JavaScript language file
sorting tag file
Run Code Online (Sandbox Code Playgroud)

这是Ctags版本:

Exuberant Ctags 5.8, Copyright (C) 1996-2009 Darren Hiebert
  Compiled: Jul  9 2009, 17:05:35
  Addresses: <dhiebert@users.sourceforge.net>, http://ctags.sourceforge.net
  Optional compiled features: +win32, +regex, +internal-sort
Run Code Online (Sandbox Code Playgroud)

我已经尝试用双引号和单引号包围该模式,但它仍然不起作用。

如何在Windows上通过Ctags*.js解析目录树中的文件时排除文件?

Mof*_*ofi 6

Exuberants Ctags 手册描述了选项--exclude

...如果 C 编译器的运行时库提供适当的支持,则模式可能包含 Unix 上常见的 shell 通配符(不是正则表达式)(...)。您可以通过检查 --version 选项的输出来确定 shell 通配符在您的平台上是否可用,该输出将在编译的功能列表中包含“+wildcards”;否则,使用简单的文本比较将模式与文件名进行匹配。

接下来看看ctags.exe运行时的最后一行输出ctags.exe --version

可选编译功能:+win32、+regex、+internal-sort

没有+wildcards。这意味着根据手册,Windows 上*.js不支持使用类似的通配符模式。ctags.exe

在提供多种解决方案之前,让我们看看以-R -Vvs开头的选项列表-V -R

Ctags首先输出ctags -V -R完整的内部初始化和列表

  • 安装了哪些解析器,
  • 哪些文件被解释为头文件,
  • 设置了哪些语言映射,
  • 使用哪些默认排除模式以及
  • 搜索哪些目录和文件以加载默认选项。

但在启动带有内部初始化的选项列表时,-R -V不会输出。

因此,当对内部初始化不感兴趣时​​,请-V在命令行上指定 not 作为第一个选项。

要了解所使用的命令及其工作原理,请打开命令提示符窗口,执行以下命令,并完整、仔细地阅读每个命令显示的帮助页面。

  • del /?
  • dir /?
  • echo /?
  • endlocal /?
  • for /?
  • if /?
  • set /?
  • setlocal /?

请阅读有关使用命令重定向运算符的Microsoft 文档,了解>>和的说明2>nul。当 Windows 命令解释器在执行命令FOR之前处理此命令行时,>重定向运算符必须^FOR命令行上使用脱字符进行转义,以便将其解释为文字字符,该命令使用在后台启动的单独命令进程和DIR来执行嵌入式命令行命令行作为附加参数附加。dir%ComSpec% /c

解决方案 1:完全排除 JavaScript 语言

排除 *.js 文件的一种解决方案是使用命令行完全排除 JavaScript 语言:

ctags.exe -R -V --languages=-JavaScript
Run Code Online (Sandbox Code Playgroud)

解决方案 2:在命令行上指定要排除的每个 *.js 文件的名称

另一个解决方案是使用批处理文件,该文件将当前目录树中找到的每个 *.js 文件的名称添加--exclude到命令行中:

@echo off
setlocal EnableExtensions EnableDelayedExpansion
set "ExcludeOptions="

for /R %%I in (*.js) do (
    if not defined JS_%%~nxI (
        set "JS_%%~nxI=1"
        set "ExcludeOptions=!ExcludeOptions! "--exclude=%%~nxI""
    )
)

ctags.exe -R -V%ExcludeOptions%
endlocal
Run Code Online (Sandbox Code Playgroud)

仅指定带有文件扩展名而不带(相对)路径的文件名就足够了,因为在创建独立于 *.js 文件所在目录的标签文件时,应忽略所有 *.js 文件。

编写代码是为了避免命令行上的重复,从而使命令行尽可能短。

命令FOR会忽略设置了隐藏文件属性的 *.js 文件以及设置了隐藏属性的目录。但Ctags不会忽略设置了隐藏属性的文件和文件夹。使用命令DIR的以下代码还可用于为隐藏的 *.js 文件和隐藏文件夹中的 *.js 文件添加排除选项。

@echo off
setlocal EnableExtensions EnableDelayedExpansion
set "ExcludeOptions="

for /F "delims=" %%I in ('dir /A-D /B /S *.js 2^>nul') do (
    if not defined JS_%%~nxI (
        set "JS_%%~nxI=1"
        set "ExcludeOptions=!ExcludeOptions! "--exclude=%%~nxI""
    )
)

ctags.exe -R -V%ExcludeOptions%
endlocal
Run Code Online (Sandbox Code Playgroud)

该解决方案的小缺点:
不排除文件名中带有感叹号的 *.js 文件,因为在分别扩展后,单个感叹号从文件名中删除,%%~nxI两个感叹号之间的字符串被完全删除或替换为由于启用了延迟扩展而需要匹配的环境变量。

解决方案 3:使用临时创建的列表文件,其中包含要排除的所有 *.js 文件的名称

对于许多 *.js 文件,最好将其文件名写入临时列表文件,Ctags从中读取要排除的文件的名称。

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "ExcludeListFile=%TEMP%\ExcludeList.tmp"
del "%ExcludeListFile%" 2>nul

for /R %%I in (*.js) do (
    if not defined JS_%%~nxI (
        set "JS_%%~nxI=1"
        echo %%~nxI>>"%ExcludeListFile%"
    )
)

set "ExcludeOption="
if exist "%ExcludeListFile%" set "ExcludeOption= "--exclude=@%ExcludeListFile%""

ctags.exe -R -V%ExcludeOption%

del "%ExcludeListFile%" 2>nul
endlocal
Run Code Online (Sandbox Code Playgroud)

此解决方案不需要延迟扩展,因此也适用于文件名中包含感叹号的 *.js 文件。

同样,与上面的代码几乎相同,不忽略设置了隐藏文件属性或位于隐藏文件夹中的 *.js 文件:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "ExcludeListFile=%TEMP%\ExcludeList.tmp"
del "%ExcludeListFile%" 2>nul

for /F "delims=" %%I in ('dir /A-D /B /S *.js 2^>nul') do (
    if not defined JS_%%~nxI (
        set "JS_%%~nxI=1"
        echo %%~nxI>>"%ExcludeListFile%"
    )
)

set "ExcludeOption="
if exist "%ExcludeListFile%" set "ExcludeOption= "--exclude=@%ExcludeListFile%""

ctags.exe -R -V%ExcludeOption%

del "%ExcludeListFile%" 2>nul
endlocal
Run Code Online (Sandbox Code Playgroud)

解决方案 4:使用临时创建的列表文件以及要解析的所有文件

在命令行上指定要使用通配符模式解析的文件应该足够了,因为为 Windows 编译的Ctags支持这一点。

ctags.exe -R -V *.htm
Run Code Online (Sandbox Code Playgroud)

此命令行应导致解析当前目录的整个目录树中的所有 *.htm 和 *.html 文件。*.html 也与此通配符模式匹配,因为 *.html 文件的短 8.3 名称具有文件扩展名 HTM。默认情况下,用于搜索与通配符模式匹配的文件的 Windows 内核函数始终将模式应用于长文件名和短文件名,以确定该模式是否与文件名匹配。

可以在命令行上指定多个文件扩展名,而不仅仅是 C/C++ 中的一个:

ctags.exe -R -V *.c *.cpp *.h
Run Code Online (Sandbox Code Playgroud)

但问题是,尽管指定了选项, Ctags 5.8 版本不会递归搜索与此通配符模式匹配的文件。-R看起来编译器添加的启动代码用于创建ctags.exe已匹配通配符模式的文件的搜索,因此Ctagsmain的函数获取一个参数列表,其中参数已被多个参数替换,每个参数都包含与当前文件夹中的通配符模式匹配的文件名。*.htm

在 Unix/Linux 上,通配符模式(例如*.htm *.html不包含在引号中)将导致在调用Ctags可执行文件之前,将这两个模式替换为当前目录中与 shell 的这 2 个模式匹配的所有文件名(sh、bash、ksh...)。

换句话说,在命令行上指定要解析的文件类型不能递归工作,因此这里没有解决方案,因为-R显然需要对文件进行递归解析。

但工作是创建一个临时列表文件,其中包含文件名、文件扩展名和所有文件的完整路径,以便在命令行上解析和指定该列表文件的文件名。

首先由于使用而忽略具有隐藏属性集的文件和目录for /R

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "IncludeListFile=%TEMP%\IncludeList.tmp"
del "%IncludeListFile%" 2>nul

for /R %%I in (*.htm) do echo %%I>>"%IncludeListFile%"

if exist "%IncludeListFile%" (
    ctags.exe -L "%IncludeListFile%" -V
    del "%IncludeListFile%" 2>nul
)
endlocal
Run Code Online (Sandbox Code Playgroud)

其次,还包括隐藏文件和隐藏目录中的文件,因为使用dir /A-D

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "IncludeListFile=%TEMP%\IncludeList.tmp"
del "%IncludeListFile%" 2>nul

for /F "delims=" %%I in ('dir /A-D /B /ON /S *.htm 2^>nul') do echo %%I>>"%IncludeListFile%"

if exist "%IncludeListFile%" (
    ctags.exe -L "%IncludeListFile%" -V
    del "%IncludeListFile%" 2>nul
)
endlocal
Run Code Online (Sandbox Code Playgroud)

在两个批处理代码中,单个通配符模式*.htm可以替换为空格分隔的通配符模式列表,这些通配符模式具有类似?甚至更复杂的模式。**.c *.cpp *.h

DIR选项导致通过命令DIR按名称对每个文件夹的文件名进行排序,这在 NTFS 驱动器上是不必要的,因为新技术文件系统返回始终按名称排序的文件列表来调用 Windows 内核函数,但 FAT(文件分配表)驱动器(FAT16、FAT32、exFAT)则不然。这在这里并不重要,但是当按独立于当前驱动器的文件系统的名称排序时,更容易查看已处理的文件。/ON

此解决方案使用包含要解析的文件的文件名的临时列表文件,是内置支持Ctags的文本编辑器和 IDE 使用的方法。