ChatGPT解决这个技术问题 Extra ChatGPT

如何阻止vim在文件末尾添加换行符?

所以我在一家 PHP 商店工作,我们都使用不同的编辑器,而且我们都必须在 Windows 上工作。我使用 vim,店里的每个人都在抱怨每当我编辑文件时,底部都会有一个换行符。我四处搜索,发现这是 vi 和 vim 的记录行为......但我想知道是否有某种方法可以禁用此功能。 (如果我可以为特定的文件扩展名禁用它,那将是最好的)。

如果有人知道这一点,那就太好了!

你应该告诉他们他们很傻——vim 这样做实际上是有充分理由的: stackoverflow.com/questions/729692/… 。不过,我想这只有在您部署在类似 unix 的服务器上时才有意义。
官方 PHP 推荐的做法是省略最后一个 ?> 结束标记,正是出于这个原因。
这个问题可能早于超级用户......但它应该在那里。
真正的问题应该是:我们如何告诉所有其他编辑您店里的人正在使用的所有其他编辑,以确保文件的最后一行确实以 EOL 结尾。 ;-)

C
Community

对于 vim 7.4+,您可以使用(最好在您的 .vimrc 上)(感谢罗泽轩的最后一点消息!):

:set nofixendofline

现在关于旧版本的 vim

即使文件最后已经用新行保存:

vim -b file 和一次在 vim 中:

:set noeol
:wq

完毕。

或者,您可以使用 :e ++bin file 在 vim 中打开文件

还有另一种选择:

:set binary
:set noeol
:wq

Why do I need vim in binary mode for 'noeol' to work? 上查看更多详细信息


您还可以在 .vimrc 中添加 set binaryset noeol
注意binary 会覆盖 expandtab,这将导致您在源代码中获得文字标签。
@CiroSantilli 谢谢!我一直在寻找二进制的副作用,并想知道为什么它不是默认值!因为我喜欢我的标签,我想我会考虑这个额外的好处:)
现在您可以添加 set nofixendofline 来解决 Vim 7.4+ 中的问题
@TrevorBoydSmith 是的,因为从历史上看,POSIX(我在实际标准上可能是错误的)期望在文本文件中的行尾有一个新行。这就是为什么大多数解决方案需要将其视为二进制文件的原因。那时候应该很方便,今天落后了,所以才有了方便的设置。只需将其添加到您的 vimrc。无论如何,其他编辑器存在更严重的问题:)
t
too much php

将以下命令添加到您的 .vimrc 以关闭行尾选项:

autocmd FileType php setlocal noeol binary fileformat=dos

然而,PHP 本身会忽略最后一行 - 这应该不是问题。我几乎可以肯定,在您的情况下,还有其他东西正在添加最后一个换行符,或者可能与 windows/unix 行尾类型(\n\r\n 等)混淆。

更新:

另一种解决方案可能是将此行添加到您的 .vimrc 中:

set fileformats+=dos

我知道 php 并没有解析错误...我已经向我的同事展示了这一点,但 winmerge 认为它们是不同的...我会尝试并让您知道结果如何。
这样做会产生没有最后一行的预期效果,但它也会将文件转换为 unix 行结尾......(即使在 Windows 盒子上)......所以我之前通过切换到二进制模式来做到这一点......但是后来行尾不显示在记事本中写...一切都只是一行。
不幸的是,这些建议都不起作用。在 autocmd 中添加 fileformat=dos 没有效果,而 set filetype+=dos 仍然会添加尾随 \n
抱歉,我错了,使用“设置文件类型+=dos”,而不是“设置文件格式...”
C
Community

如果您使用 Git 进行源代码控制,还有另一种方法可以解决这个问题。受 an answer here 的启发,我编写了自己的过滤器以在 gitattributes 文件中使用。

要安装此过滤器,请将其另存为 $PATH 中的某个位置,使其可执行,然后运行以下命令:

git config --global filter.noeol.clean noeol_filter
git config --global filter.noeol.smudge cat

要开始仅为您自己使用过滤器,请将以下行放入您的 $GIT_DIR/info/attributes

*.php filter=noeol

这将确保您不会在 .php 文件的 eof 处提交任何换行符,无论 Vim 做什么。

现在,脚本本身:

#!/usr/bin/python

# a filter that strips newline from last line of its stdin
# if the last line is empty, leave it as-is, to make the operation idempotent
# inspired by: https://stackoverflow.com/questions/1654021/how-can-i-delete-a-newline-if-it-is-the-last-character-in-a-file/1663283#1663283

import sys

if __name__ == '__main__':
    try:
        pline = sys.stdin.next()
    except StopIteration:
        # no input, nothing to do
        sys.exit(0)

    # spit out all but the last line
    for line in sys.stdin:
        sys.stdout.write(pline)
        pline = line

    # strip newline from last line before spitting it out
    if len(pline) > 2 and pline.endswith("\r\n"):
        sys.stdout.write(pline[:-2])
    elif len(pline) > 1 and pline.endswith("\n"):
        sys.stdout.write(pline[:-1])
    else:
        sys.stdout.write(pline)

这是一个很好的解决方案......虽然不幸的是我没有使用 git。我使用的是 svn,尽管我怀疑可以采用类似的方法。无论如何,我已经从那个位置继续前进,不必再担心了:)
C
Community

这个选项我没试过,但是vim帮助系统中给出了以下信息(即help eol):

'endofline' 'eol'   boolean (default on)
            local to buffer
            {not in Vi}

When writing a file and this option is off and the 'binary' option
is on, no <EOL> will be written for the last line in the file.  This
option is automatically set when starting to edit a new file, unless
the file does not have an <EOL> for the last line in the file, in
which case it is reset.  

通常您不必设置或重置此选项。当 'binary' 关闭时,写入文件时不使用该值。当 'binary' 开启时,它用于记住文件中最后一行的 a 的存在,以便在您写入文件时可以保留原始文件中的情况。但如果你愿意,你可以改变它。

您可能也对上一个问题的答案感兴趣:“Why should files end with a newline”。


我也遇到过 eol 设置......但它并没有完成这项任务。它更像是一个变量,用于确定是否已经将一个变量放在文件末尾。此外,它对文本文件没有影响,而仅对二进制文件有影响。
vim 帮助还说“当 'binary' 关闭时,写入文件时不使用该值。”关于eol
+1 表示 VonC 对该问题的回答,强调“换行符”和 EOL 被混为一谈。由于 EOL,劣质编辑器错误地显示了额外的换行符,vim 没有添加“换行符”!
J
Jo Liss

我在 Vim wiki 上添加了一个针对类似(尽管不同)问题的提示:

http://vim.wikia.com/wiki/Do_not_auto-add_a_newline_at_EOF


“Vim 7.4.785 添加了 fixeol 选项,可以禁用该选项以在文件末尾自动保留任何丢失的 EOL。对于 Vim 7.4.785 和更高版本,这个脚本变得不必要了。” (来源:同一个维基页面。)谢谢,我不知道这个新选项。
我必须同时设置 noeolnofixeol 才能获得理想的结果。
B
Blixtor

好的,你在 Windows 上会使事情复杂化;)

由于 'binary' 选项重置了 'fileformat' 选项(并且使用 'binary' 设置写入总是使用 unix 行结尾),让我们拿出大锤子,在外部进行!

为 BufWritePost 事件定义一个自动命令(:help autocommand)怎么样?每次写入整个缓冲区后都会执行此自动命令。在这个自动命令中,调用一个小的外部工具(php、perl 或任何脚本)来去除刚刚写入的文件的最后一个换行符。

所以这看起来像这样,并会进入你的 .vimrc 文件:

autocmd!   "Remove all autocmds (for current group), see below"
autocmd BufWritePost *.php !your-script <afile>

如果这是您第一次处理自动命令,请务必阅读有关自动命令的整个 vim 文档。有一些注意事项,例如建议删除 .vimrc 中的所有自动命令,以防 .vimrc 可能被多次获取。


嗯......我希望有比这更好的解决方案......但这绝对有效!
这很好用!耶!但是我有一个问题......有没有办法做到这一点,所以我不必在每次保存后按两次输入。我必须在弹出的 cmd 窗口中按回车键,然后再按一次,因为 vim 告诉我脚本返回成功......有什么方法可以让它们全部消失吗?
为了避免 <Press Enter>提示只需在命令前加上 silent。例如silent !your-script <afile>
I
Ingo Karkat

我已经使用 Perl 和 Python 后处理实现了 Blixtor 的建议,或者在 Vim 中运行(如果它是使用这种语言支持编译的),或者通过外部 Perl 脚本。它在 vim.org 上以 PreserveNoEOL plugin 的形式提供。


我还没有彻底测试它,但这似乎是一个更好的解决方案。
插件有效,但安装后我必须将 let g:PreserveNoEOL = 1 放入我的 .vimrc 文件中!必须学习 vimscript 才能从插件描述中弄清楚! :D
@DarthVanger::help PreserveNoEOL-usage 也会告诉你的。实时调频 :-)
@IngoKarkat 哦,对不起。在 INSTALLATIONCONFIGURATION 下寻找这个。甚至没有注意到描述中的 USAGE 部分,因为它在安装之上:)
V
Victor Yarema

vim v7.4 开始,您可以使用

:set nofixendofline

此处提供了有关该更改的一些信息:http://ftp.vim.org/vim/patches/7.4/7.4.785


K
Ken

也许你可以看看他们为什么抱怨。如果一个 php 文件在结尾 ?> 之后有一个换行符,php 会将它作为页面的一部分输出。除非您在包含文件后尝试发送标头,否则这不是问题。

但是,php 文件末尾的 ?> 是可选的。没有结尾?>,文件末尾的换行符没有问题。


您是对的,但作为一家商店,我们认为结尾更好看?> 我知道我们可以停止使用它……但我更愿意调整我的编辑器以适应我的编码风格,而不是相反。
另外,所以你知道 php 会自动将你的结束标记解析为 ?> 或 ?>\n (因为在 linux 中所有有效文件都应该以 \n 结尾)......所以我的代码不会导致这些问题......他们只是不喜欢这个样子。
I
IvanM

尝试添加 .vimrc

set binary

J
Jay Paroline

我想我找到了比公认答案更好的解决方案。替代解决方案对我不起作用,我不想一直在二进制模式下工作。幸运的是,这似乎完成了工作,而且我还没有遇到任何令人讨厌的副作用:preserve missing end-of-line at end of text files。我刚刚将整个内容添加到我的 ~/.vimrc 中。


B
Blixtor

您是否可以使用特殊命令来保存这些文件?

如果你这样做 :set binary, :w 和 :set nobinary 如果没有新行,则文件将在没有换行符的情况下写入。

当然,这个命令序列可以放入用户定义的命令或映射中。


不幸的是,因为我正在使用 Windows,如果我以二进制模式保存它,它会强制保存为 unix 模式。即使我这样做 :set binary :set fileformat=dos :w :set nobinary 一旦我退出,它就会以 unix 格式保存文件...我不敢相信没有什么方法可以关闭它。
A
Alan Dong

我发现这个 vimscript 插件对这种情况很有帮助。

Plugin 'vim-scripts/PreserveNoEOL'

或在 github 阅读更多信息