git和vim中的空格键之谜

时间:2018-08-12 20:21:37

标签: bash git ubuntu vim

我在Ubuntu上使用Gvim。根据我的理解,我已将Tab设置为扩展到4个空格。我什至没有碰到create_namespace所在的行,但是git diff显示它被移动了一个字符。在编辑器中或当我运行cat时,一切似乎都很好。同样的问题是当我添加一行新的txt cluster_token时,它在git diff中显示为字符移位。我浪费了很多时间试图理解这个愚蠢的问题,但没有任何线索。问题是什么,我该如何解决?

-       echo "--create_namespace"
+        echo "--create_namespace" //Did not even touch this line
        echo "--all"
        echo "--custom_merge_pipeline_commands"
+        echo "--cluster_token" //Looks fine in editor

1 个答案:

答案 0 :(得分:4)

如果这是TL; DR,请跳到下面的加粗文本。

正如我在a comment中所指出的那样,空格与制表符的问题引发了火焰大战,因此我将尝试在主题上完全保持中立。 (请注意:我确实说过 attempt 。:-))这也值得介绍一下历史,例如,我们最初是如何到达这里的。另外,https://vi.stackexchange.com/上有一个完全独立的(尽管目前是beta版)StackExchange网站专用于vi / vim,所以我将不涉及此处提供的许多vim设置。

首先,请注意制表符可以追溯到机械打字机的时代(好吧,也许甚至早于 )。

mechanical typewriter

不同的模型具有不同的功能,但是大多数模型都有一个标记为 TAB 的键,当按下该键时,握住纸张的橡胶辊platen会向左滑动(假设从其当前位置到下一个制表位的西式左右移动打字机。凸耳挡块是机械设定的,因为所有这些都由金属丝和弹簧驱动。由于类型条总是会在色带抵住纸张的中心击中纸张,因此向左滑动压纸卷轴的效果是使下一个字符出现在右侧的某个位置。右边的取决于当前列,当然也取决于制表位设置。

早期使用的计算机界面或模拟的机械打字机-更准确地说是teletype接口-有时还具有完全相同的机械控制的制表位。当glass ttys出现时,他们倾向于模仿现有的TTY。随着时间的推移,终端变得越来越智能,以至于某些终端具有软件可调的制表位。

但是,其他人在软件中将制表符限制为仅“每N列”,其中N是可变的。 DEC为他们的一些早期系统选择了10个,但事实证明,有8个更受欢迎,并成为默认设置。在此,向显示终端发送ASCII TAB (十进制代码9字节)字节导致终端将光标从现在所在的列移动到一个最多但不超过N的列(通常是8个)字符。 (接近物理屏幕行末尾的光标的行为有所不同,并且在软件仿真中仍然有所不同,但是VT100的行为现在非常普遍。)

我们不再使用这些硬件中的任何一个(至少是not commonly),但是我们对它们进行了仿真。在编辑器中按 TAB 键可能会将光标移动到“下一个制表位”,无论该位置在哪里。终端仿真器将仿真任何终端,通常还是VT100,它具有可变的制表位(通过转义序列设置),但默认为每八列(第9、17、25列,依此类推,如果我们将第一列编号为1) —按照传统,而不是适当的数学列零:-)。

但是,为了将文本存储在文件中,有一个选择:我们可以存储文字ASCII TAB 字符(或等价的U + 0009 Unicode),或者我们可以存储许多空格,以获取到所选列。如果我们存储原义的 TAB ,则由显示文件决定选择哪一列是所需列。如果我们存储文字空格字符,则显示文件的任何内容都必须显示那么多空格字符。 1 结果是,如果我们存储文字 TAB s,则显示取决于先前的输出(因为光标列取决于先前的输出),但是如果我们存储文字空间,则不会。

同时, git diff显示行时,它会在每行前面插入一个字符。如果显示的行以文字 TAB 开头单词old,发生的情况是git diff写一个空格或正负字符,然后是 TAB ,然后是下一个字符。假设您的终端在第9、17、25列有其制表位,依此类推, TAB 之后的字符将出现在第9列:

0        1
1234567890123456789
-       old

另一方面,如果文件中的行以八个空格开头,后跟单词new,则您看到的是git diff字符,然后是八个空格,然后是列中的单词10:

0        1
1234567890123456789
+        new

将这些堆叠在一起,我们得到:

0        1
1234567890123456789
-       old
+        new

这就是您所看到的。这意味着您的索赔:

-       echo "--create_namespace"
+        echo "--create_namespace" //Did not even touch this line

最多是半正确的:可能没有碰到这条线,但您的编辑器却碰到了。它用空格替换了至少一个文字 TAB 字符。 (我们无法从此处得知更改了多少个这样的字符,例如,如果您已为使用第5列而进行了全部组装,它可能会用四个空格替换一个 TAB ,而将四个现有空格保留在适当的位置。 ,9、13、17等。)


1 现在是时候避免将固定字体与可变间距字体分开使用。 :-)