windows - 旺盛的Ctags无法在Windows上正确排除文件

标签 windows ctags exuberant-ctags

当执行时,像这样的tags

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上使用的*.js不支持像ctags.exe这样的通配符模式。

在提供多种解决方案之前,让我们来看一下使用-R -V-V -R来启动选项列表。

首先使用ctags -V -R Ctags 输出,并进行完整的内部初始化并列出
  • 安装了哪些解析器,
  • 哪些文件被解释为头文件
  • 设置了哪些语言映射
  • 使用默认排除模式和
  • 搜索哪些目录和文件以加载默认选项。

  • 但是在使用-R -V启动选项列表时,不会输出内部初始化。

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

    为了了解所使用的命令及其在下面的批处理代码中的工作方式,请打开命令提示符窗口,在其中执行以下命令,并非常仔细地阅读每个命令显示的所有帮助页面。
  • 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编译的Ctags 支持。
    ctags.exe -R -V *.htm
    

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

    可以在命令行上指定多个文件扩展名,而不仅仅是C/C++:
    ctags.exe -R -V *.c *.cpp *.h
    

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

    在Unix/Linux上,如*.htm *.html之类的通配符模式未用引号引起来,将导致在调用 Ctags之前,用当前目录中与这两种模式匹配的所有文件名替换这两种模式(由shell(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
    

    其次,由于使用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可以用空格分隔的带有?*的通配符模式列表替换,例如*.c *.cpp *.h或更复杂的模式。

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

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

    关于windows - 旺盛的Ctags无法在Windows上正确排除文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41967893/

    相关文章:

    Vim 选择 Cscope 命令而不是 ctags?

    javascript - 如何使用 ctags 索引简单的 javascript 哈希/对象?

    c - 如何为 linux C 开发设置 ctags?

    Ctags 作为创建标签文件的库

    python - shutil.rmtree 在 Windows 上失败并显示 'Access is denied'

    windows - 检测确切的 Windows 10 版本以在批处理文件中回显彩色文本

    c++ - 怎么知道哪段内存全为零

    使用 ctags 的 Vim Markdown 导航 : using 'tagbar' + 'markdown2ctags' with 'vim-pandoc'

    mysql - 将 Windows 路径传递给 MySQL 存储过程

    javascript - Jsctags 不工作