Exuberant Ctags 未正确排除 Windows 上的文件
Exuberant Ctags is not excluding files properly on Windows
像这样执行Ctags时
ctags -V -R --exclude=*.js
它没有正确排除 *.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
这里是 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
我试过用双引号和单引号将模式括起来,还是不行。
如何通过 Windows 上的 Ctags 在解析目录树中的文件时排除 *.js
文件?
Exuberants Ctags Manual描述选项--exclude
:
... If appropriate support is available from the runtime library of your C compiler, then pattern may contain the usual shell wildcards (not regular expressions) common on Unix (...). You can determine if shell wildcards are available on your platform by examining the output of the --version option, which will include "+wildcards" in the compiled feature list; otherwise, pattern is matched against file names using a simple textual comparison.
接下来看看 ctags.exe
在 运行 上输出的最后一行 ctags.exe --version
:
Optional compiled features: +win32, +regex, +internal-sort
没有+wildcards
。这意味着根据手册,在 Windows 上使用的 ctags.exe
不支持像 *.js
这样的通配符模式。
在提供多种解决方案之前,让我们看看以 -R -V
和 -V -R
开始的选项列表。
Ctags 输出 ctags -V -R
首先完整的内部初始化与 listing
- 安装了哪些解析器,
- 哪些文件被解释为头文件,
- 设置了哪些语言映射,
- 使用哪些默认排除模式以及
- 搜索哪些目录和文件以加载默认选项。
但是在使用 -R -V
启动选项列表时,不会输出内部初始化。
所以当对内部初始化不感兴趣时,指定 -V
not 作为命令行的第一个选项。
要了解使用的命令以及它们在下面的批处理代码中的工作方式,请打开命令提示符 window,在其中执行以下命令,并仔细阅读每个命令显示的所有帮助页面。
del /?
dir /?
echo /?
endlocal /?
for /?
if /?
set /?
setlocal /?
另请阅读 Microsoft 文章 Using command redirection operators 以了解 >>
和 2>nul
以及 2^>nul
的解释,其中重定向运算符 >
被转义为脱字符 ^
在解析 FOR 命令行时被解释为文字字符,但在执行 DIR 命令行时作为重定向运算符命令 FOR.
解决方案 1:完全排除语言 JavaScript
排除 *.js 文件的一种解决方案是完全使用命令行排除语言 JavaScript:
ctags.exe -R -V --languages=-JavaScript
解决方案 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
只指定带文件扩展名而不带(相对)路径的文件名就足够了,因为在创建标签文件时应忽略所有 *.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
此解决方案的次要缺点:
不排除文件名中带有感叹号的*.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
此解决方案不需要延迟扩展,因此也适用于文件名中包含感叹号的 *.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
解决方案 4:使用临时创建的列表文件来解析所有文件
在命令行上使用通配符模式指定要解析的文件应该就足够了,因为为 Windows.[=62= 编译的 Ctags 支持这一点]
ctags.exe -R -V *.htm
此命令行应解析当前目录的整个目录树中的所有 *.htm 和 *.html 文件。 *.html 也与此通配符模式匹配,因为 *.html 文件的短 8.3 名称具有文件扩展名 HTM。 Windows 默认情况下用于搜索与通配符模式匹配的文件的内核函数始终将模式应用于长文件名和短文件名以确定模式是否与文件名匹配。
可以在命令行上指定多个文件扩展名,而不仅仅是 C/C++:
ctags.exe -R -V *.c *.cpp *.h
但是问题是Ctags5.8版本没有递归搜索或匹配此通配符模式的文件,尽管指定了选项 -R
。看起来编译器添加的用于创建 ctags.exe
的启动代码已经搜索了匹配通配符模式的文件,因此 Ctags 的 main
函数获得了一个参数列表参数 *.htm
已被多个参数替换,每个参数包含与当前文件夹中的通配符模式匹配的文件名。
在 Unix/Linux 上,通配符模式如 *.htm *.html
未包含在引号中将导致这两个模式被当前目录中匹配这两个模式的所有文件名替换为 shell (sh, bash, ksh, ...) 在调用 Ctags 可执行文件之前。
换句话说,在命令行上指定要解析的文件类型无法递归工作,因此这里没有解决方案,因为 -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
其次,由于使用 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
在两个批处理代码中,单个通配符模式 *.htm
可以替换为 space 分隔的通配符模式列表,其中 ?
和 *
如 *.c *.cpp *.h
甚至更复杂的模式。
DIR 选项 /ON
导致通过命令 DIR 按名称对每个文件夹的文件名进行排序,这是不必要的在作为新技术文件系统 returns 的 NTFS 驱动器上,文件名列表始终按名称排序以调用 Windows 内核函数,但 FAT(文件分配 Table)驱动器(FAT16、FAT32、 exFAT)不要。这在这里并不重要,但是当按与当前驱动器的文件系统无关的名称排序时,查看处理后的文件更容易。
这种使用包含要解析文件的文件名的临时列表文件的解决方案是文本编辑器和支持 built-in Ctags 的 IDE 使用的方法。
像这样执行Ctags时
ctags -V -R --exclude=*.js
它没有正确排除 *.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
这里是 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
我试过用双引号和单引号将模式括起来,还是不行。
如何通过 Windows 上的 Ctags 在解析目录树中的文件时排除 *.js
文件?
Exuberants Ctags Manual描述选项--exclude
:
... If appropriate support is available from the runtime library of your C compiler, then pattern may contain the usual shell wildcards (not regular expressions) common on Unix (...). You can determine if shell wildcards are available on your platform by examining the output of the --version option, which will include "+wildcards" in the compiled feature list; otherwise, pattern is matched against file names using a simple textual comparison.
接下来看看 ctags.exe
在 运行 上输出的最后一行 ctags.exe --version
:
Optional compiled features: +win32, +regex, +internal-sort
没有+wildcards
。这意味着根据手册,在 Windows 上使用的 ctags.exe
不支持像 *.js
这样的通配符模式。
在提供多种解决方案之前,让我们看看以 -R -V
和 -V -R
开始的选项列表。
Ctags 输出 ctags -V -R
首先完整的内部初始化与 listing
- 安装了哪些解析器,
- 哪些文件被解释为头文件,
- 设置了哪些语言映射,
- 使用哪些默认排除模式以及
- 搜索哪些目录和文件以加载默认选项。
但是在使用 -R -V
启动选项列表时,不会输出内部初始化。
所以当对内部初始化不感兴趣时,指定 -V
not 作为命令行的第一个选项。
要了解使用的命令以及它们在下面的批处理代码中的工作方式,请打开命令提示符 window,在其中执行以下命令,并仔细阅读每个命令显示的所有帮助页面。
del /?
dir /?
echo /?
endlocal /?
for /?
if /?
set /?
setlocal /?
另请阅读 Microsoft 文章 Using command redirection operators 以了解 >>
和 2>nul
以及 2^>nul
的解释,其中重定向运算符 >
被转义为脱字符 ^
在解析 FOR 命令行时被解释为文字字符,但在执行 DIR 命令行时作为重定向运算符命令 FOR.
解决方案 1:完全排除语言 JavaScript
排除 *.js 文件的一种解决方案是完全使用命令行排除语言 JavaScript:
ctags.exe -R -V --languages=-JavaScript
解决方案 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
只指定带文件扩展名而不带(相对)路径的文件名就足够了,因为在创建标签文件时应忽略所有 *.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
此解决方案的次要缺点:
不排除文件名中带有感叹号的*.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
此解决方案不需要延迟扩展,因此也适用于文件名中包含感叹号的 *.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
解决方案 4:使用临时创建的列表文件来解析所有文件
在命令行上使用通配符模式指定要解析的文件应该就足够了,因为为 Windows.[=62= 编译的 Ctags 支持这一点]
ctags.exe -R -V *.htm
此命令行应解析当前目录的整个目录树中的所有 *.htm 和 *.html 文件。 *.html 也与此通配符模式匹配,因为 *.html 文件的短 8.3 名称具有文件扩展名 HTM。 Windows 默认情况下用于搜索与通配符模式匹配的文件的内核函数始终将模式应用于长文件名和短文件名以确定模式是否与文件名匹配。
可以在命令行上指定多个文件扩展名,而不仅仅是 C/C++:
ctags.exe -R -V *.c *.cpp *.h
但是问题是Ctags5.8版本没有递归搜索或匹配此通配符模式的文件,尽管指定了选项 -R
。看起来编译器添加的用于创建 ctags.exe
的启动代码已经搜索了匹配通配符模式的文件,因此 Ctags 的 main
函数获得了一个参数列表参数 *.htm
已被多个参数替换,每个参数包含与当前文件夹中的通配符模式匹配的文件名。
在 Unix/Linux 上,通配符模式如 *.htm *.html
未包含在引号中将导致这两个模式被当前目录中匹配这两个模式的所有文件名替换为 shell (sh, bash, ksh, ...) 在调用 Ctags 可执行文件之前。
换句话说,在命令行上指定要解析的文件类型无法递归工作,因此这里没有解决方案,因为 -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
其次,由于使用 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
在两个批处理代码中,单个通配符模式 *.htm
可以替换为 space 分隔的通配符模式列表,其中 ?
和 *
如 *.c *.cpp *.h
甚至更复杂的模式。
DIR 选项 /ON
导致通过命令 DIR 按名称对每个文件夹的文件名进行排序,这是不必要的在作为新技术文件系统 returns 的 NTFS 驱动器上,文件名列表始终按名称排序以调用 Windows 内核函数,但 FAT(文件分配 Table)驱动器(FAT16、FAT32、 exFAT)不要。这在这里并不重要,但是当按与当前驱动器的文件系统无关的名称排序时,查看处理后的文件更容易。
这种使用包含要解析文件的文件名的临时列表文件的解决方案是文本编辑器和支持 built-in Ctags 的 IDE 使用的方法。