Ctags: 通用 ctags 为某些文件插入无效的“utf-8”字符

创建于 2018-07-30  ·  7评论  ·  资料来源: universal-ctags/ctags

(
感谢您与我们联系。

如果您报告解析输出的问题,请填写
以下模板。 由于您的自定义 CTags 配置可以
影响结果,请始终使用--options=NONE作为第一个
运行ctags时的选项。

否则,删除模板并从头开始编写您的问题。
示例可以帮助开发人员更好地理解您的问题。

使用 GitHub Web 界面和 Markdown 符号。
使用邮件结果破坏文本渲染,使
开发商疯了。
)


解析器名称:

用于运行 ctags 的命令行:

$ ctags -R

我在.ctags或其他任何地方没有任何特殊配置。 这是运行此测试的新 VM。

输入文件内容: https :

您不满意的标签输出:

Universal-ctags在某些情况下会插入无效的utf-8字符。

您期望的标签输出:

所有有效utf-8字符的预期标签输出。

ctags的版本:

$ ctags --version
Universal Ctags 0.0.0(3522685), Copyright (C) 2015 Universal Ctags Team
Universal Ctags is derived from Exuberant Ctags.
Ctags 5.8, Copyright (C) 1996-2009 Darren Hiebert
  Compiled: July 27 1018, 23:16:36
  URL: https://ctags.io/
  Optional compiled features: +wildcards, +regex, +iconv, +option-directory, +xpath

你如何获得 ctags 二进制文件:

(
ctags 二进制文件构建在ubuntu-16.04 VM 上,除了安装必要的库(例如automateautoreconf用于编译ctags和编译vim必要库外,没有其他任何修改)
)

@lilydjwg向我指出ctags插入了无效的utf-8字符,即使用于生成标签的文件在此处具有所有有效的utf-8字符:
https://github.com/vim/vim/issues/3213#issuecomment -406961075

ctags的编译版本通常效果很好。

最近发现,原来ctags有一个错误导致
旧的Execuberant ctagssudo apt-get install ctags在 Ubuntu 上安装
16.04 不插入任何无效的utf-8字符,但如果我编译
Universal-ctags来自源代码,并根据此处的说明安装它:
https://github.com/universal-ctags/ctags/blob/master/docs/autotools.rst ,它
将插入无效的utf-8字符。 证据如下:

仅使用exuberant-ctags安装sudo apt-get install ctags

2018-07-29_19-03-44

在这篇文章中, Universal-ctags从源代码(最新提交)编译,
使用此处的说明编译:
https://github.com/universal-ctags/ctags/blob/master/docs/autotools.rst

2018-07-29_19-10-22

这会在vim中造成很多问题,因为如果无效的utf-8字符是
传递给vim.evalvim.eval中断,这导致没有标签返回
全部。 目前,只有一种方法可以传输viml包含的数据
变量到python-name空间,使用vim.eval 。 所以,任何其他插件
vim 或其他地方也会有类似的问题。 @ludovicchabant对于
示例必须对他的标签文件进行后处理以阻止此类问题:
https://ludovic.chabant.com/devblog/2017/02/25/aaa-gamedev-with-vim/

此外,他必须更改ctrl-py-matcher才能解决此问题。
https://github.com/ludovicchabant/ctrlp-py-matcher/blob/2f6947480203b734b069e5d9f69ba440db6b4698/autoload/pymatcher.py#L22

我还看到了多个其他文件也有类似的问题,但我
刚刚在这里提供了一个来缩小问题的范围。

我的猜测是这是一个错误,我不希望ctags会这样做
设计。 这可以纠正吗,因为这曾经在 Exuberant Ctags 中工作正常
Universal-ctags 基于哪个?

参考: https :

所有7条评论

对我来说听起来像#1275:新的pattern-length-limit选项在任意字节位置进行切割,该位置恰好位于字符序列的中间。 参见 #163、#640 和 #1018。

可能应该实施类似https://github.com/universal-ctags/ctags/issues/1275#issuecomment -274489859 之类的东西来解决这个问题。

@alphaCTzo7G参见#1807,这是否为您正确修复了它?

@b4n ,感谢您的快速回复...

在我在这里发布的文件_identifier.py ,使用 #1805 提交, ctags不再在任意位置插入无效字符/剪切。

在接下来的几天里,我将在我的真实系统上尝试这个 PR,看看它是否适用于我的整个存储库或发出其他错误

由于ctrlpctrlp-py-matcher是非常流行的插件,如果合并 #1807 那就太好了,这样vim和其他文本编辑器用户可以使用ctrlpctrlp-py-matcher而不必担心这个问题。

我发现还有另一个文件引起了问题, vim.eval ,它包含无效的utf-8字符,由grep -axv '.*' misc.html (https:/中的misc.html /github.com/alphaCTzo7G/test)。 我注意到ctags会将无效的utf-8字符插入到misc.html的标签文件中。

ctags检测文件中的无效字符并用@tonymec在这里建议的内容替换它们是否https :

IIUC,ctags(Exuberant ctags,我的意思是,它只是可用的 ctags 程序之一)与 Vim 分开分发(即使它的作者知道 Bram,即使它们偶尔一起工作以使 Vim 和 ctags 更好地协同工作。

从 ctags 的角度来看,将程序文本视为字节串是合理的:无论是 UTF-8、Latin1、Latin9 还是其他一些 ISO 8859 字符集,空格是 0x20,硬制表符是 0x09,换行符是 0x0A,前面可能是 0x0D,等等; 一个空字节,即 0x00,不应出现在文本文件中。 Ctags 以相同的方式处理每个程序,无论它是用哪种 ASCII 兼容编码编写的,因此它不需要关心哪个是哪个。 只有对于像 EBCDIC 这样一些古怪的字符集,它才需要将文本视为绝对非 ASCII(在 EBCDIC 中,IIRC,AI 是 0xC1-0xC9,JR 是 0xD1-0xD9,SZ 是 0xE2-0xE9,0-9 是 0xF0-0xF9 ,我不记得空格、制表符、换行符、破折号、下划线等的代码是什么;但你会发现从 ASCII 的角度来看,它真的很古怪)。

恕我直言,在 ctag 的情况下,古老的原则适用:垃圾进,垃圾出。

此致,
托尼。

@tonymec .. 有道理.. 我意识到可能还有其他标签生成程序,但universal-ctags是最受欢迎的,在使用universal-ctags的人中,我猜大部分是vim用户。

所以我想知道这两个是否可行,或者您对如何处理具有非法utf-8字符的文件有任何其他想法?

  1. 我还注意到ctags+iconv这个选项,它允许使用libiconv 。 在命令行中使用iconv可以删除非法的utf8字符。 所以我想知道如果我通过--input-enconding=utf-8--output-encoding=utf-8 ,那么所有非法的 utf-8 字符都会被更改为合法的utf-8字符。

这在https://media.readthedocs.org/pdf/ctags/latest/ctags.pdf 的第 1.3.4 节中有解释:

Two new options have been introduced (--input-encoding=IN and --output-encoding=OUT). Using the encoding specified with these options ctags converts input from IN to OUT. ctags uses the converted strings when writing the pattern parts of each tag line. As a result the tags output is encoded in OUT encoding. In addition OUT is specified at the top the tags file as the value for the TAG_FILE_ENCODING pseudo tag. The default value of OUT is UTF-8. NOTE: Converted input is NOT passed to language parsers. The parsers still deal with input as a byte sequence. With --input-encoding-<LANG>=IN, you can specify a specific input encoding for LANG. It overrides the global default value given with --input-encoding

  1. 让编辑器来处理非法的utf8字符。 在这种情况下,要么vim.eval必须被修复,要么必须有一个vimL函数可以解析和删除非法的utf-8字符,然后将其传递给vim.eval ..

@alphaCTzo7G我同意@tonymec和他的结论。

不幸的是,识别正确的编码很麻烦——我坚持

此外, ctags在这里处于一个困难的位置:许多(如果不是大多数)消费者不处理编码,并且生成的标签需要在字节级别进行匹配。 例如,grepping 标签模式甚至名称不会为您转换编码,因此标签应该在字节级别匹配文件。 当我们只关心 ASCII 时,这很容易,但我们不再那么幸运了…… UTF-8 没有得到足够早的采用。
这也适用于用占位符替换的想法:消费者可以用这样的替换字符做什么? 它至少必须以特定的方式处理它。

但是,如果您对用 U+FFFD 替换无效的 UTF-8 或剥离它们感到满意,也许您可​​以简单地对 ctags 的输出进行后处理?

@b4n ,感谢您的评论。 我实际上主要处理utf-8编码的文件,并为我创建的文件编码了utf-8 。 不幸的是,正如您提到的,我确实使用了有时具有任意编码的库。

我使用vim-gutentags ,它确实提供了后处理功能。 虽然我可以手动对标签文件进行后处理以生成utf-8字符的所有文件,但当我尝试在vim-gutentags使用post-processing功能时,它不起作用. 所以我认为找出一个更强大的解决方案可能会更好..但如果那不存在,我将不得不再次研究它..

要检测文件的编码,您不能使用以下选项之一背后的底层库: https :

例如encafileuchardetenguess ? 这些都是命令行实用程序..但必须有一些库可以在内部使用ctags可能。 我的猜测是因为编码的数量,正如你所提到的,可能永远不可能完美地预测编码,但是一个涵盖大部分编码的简单解决方案可能总比没有好..

我将尝试--input-encoding (and/or --input-encoding-<LANG>) and --output-encoding options .. 不确定它是否会一直工作,因为很可能某些文件在同一个存储库中有不同的编码,除非ctags弄清楚单独正确编码并以所需格式将其吐出。

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

jagjordi picture jagjordi  ·  9评论

fabiensabatie picture fabiensabatie  ·  3评论

lvc picture lvc  ·  8评论

fommil picture fommil  ·  19评论

blackb1rd picture blackb1rd  ·  8评论