VIM在文件末尾禁用自动换行


250

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

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


23
您应该告诉他们他们很愚蠢-实际上vim这么做的理由很充分:stackoverflow.com/questions/729692/…。不过,我猜这仅与要在类似Unix的服务器上进行部署有关。
hdgarrood13年

5
?>出于这个原因,PHP官方建议的做法是省略最后一个结束标记。
塞巴斯蒂安·格里尼亚利

这个问题可能早于超级用户...但是应该在那里。
gcb

20
问题实际上应该是:我们如何告诉所有其他编辑者您的商店中的人正在使用以确保文件的最后一行确实以EOL结尾。;-)
TJ Crowder 2014年

Answers:


359

对于vim7.4+,您可以使用(最好在您的.vimrc上使用)(感谢罗泽轩提供的最新消息!):

:set nofixendofline

现在关于的旧版本vim

即使文件已经用结尾的新行保存:

vim -b file 并在vim中:

:set noeol
:wq

完成。

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

另一个选择:

:set binary
:set noeol
:wq

6
您还可以添加set binaryset noeol在.vimrc
dryobs

17
当心binary覆盖expandtab,这将导致您在源代码中获取文字标签。
西罗Santilli郝海东冠状病六四事件法轮功

4
@CiroSantilli谢谢!我一直在寻找二进制的副作用,想知道为什么它不是默认值!由于我喜欢我的标签,我认为我会考虑这种额外的好处:)
gcb

11
现在您可以添加set nofixendofline解决Vim 7.4+中的问题
罗泽轩

1
@TrevorBoydSmith是的,因为从历史上讲POSIX(在实际标准上我可能是错的)期望文本文件中一行的末尾有新行。这就是为什么大多数解决方案都需要将其视为二进制文件。那时可能很方便,而且今天很落后,所以现在有了方便的设置。只需将其添加到您的vimrc中即可。无论如何,在其他编辑器中还有更严重的问题:)
gcb

23

将以下命令添加到您的.vimrc中,以结束行尾选项:

autocmd FileType php setlocal noeol binary fileformat=dos

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

更新:

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

set fileformats+=dos

我知道php不会解析错误...我已经向同事展示了这一点,但是winmerge认为它们是不同的...我会尽力而为,让你知道结果如何。
Boushley

这样做具有没有最后一行的预期效果,但是它也可以将文件转换为unix行结尾...(甚至在Windows框上)...所以我之前通过切换到二进制模式来做到这一点...但是行尾没有显示在记事本中...一切都只是一行。
Boushley

不幸的是,这些建议都不起作用。将fileformat = dos添加到autocmd无效,并且设置filetype + = dos仍会添加尾随\ n
Boushley,2009年

对不起,我得到了错误,使用“文件类型集合+ = DOS”,而不是“集fileformats ......”
太多的PHP

17

如果您使用Git进行源代码控制,还有另一种方法可以解决此问题。受到这里答案的启发,我编写了自己的过滤器供gitattributes使用文件。

要安装此过滤器,请将其保存noeol_filter在您的某处$PATH,使其可执行,然后运行以下命令:

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

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

*.php filter=noeol

这样可以确保您不会在eof中提交任何换行符 .php无论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: /programming/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,尽管我怀疑可以采取类似的方法。无论如何,我已经从那个位置继续前进,不必再担心了:)
Boushley 2011年

12

我没有尝试过该选项,但是vim帮助系统(即帮助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”打开时,它用于记住文件最后一行的a的存在,因此当您写入文件时,可以保留原始文件中的情况。但是您可以根据需要进行更改。

您可能也对上一个问题的答案感兴趣:“ 文件为什么要以换行符结尾 ”。


我也遇到过eol设置...但是它不能完成此任务。它更多是一个变量,用于确定是否已将其放置在文件末尾。此外,它对文本文件没有影响,而仅对二进制文件有影响。
Boushley

3
vim帮助中还显示“关闭'binary'时,写入文件时不使用该值”。关于eol
Boushley

1
VonC在该问题上的答案为+1,这突出表明“换行符”和EOL正在混用。由于EOL,劣等的编辑器错误地显示了多余的换行符,vim没有添加“换行符”!
ches 2012年

9

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

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


5
“ Vim 7.4.785添加了fixeol可以禁用的选项,以自动在文件末尾保留所有丢失的EOL。对于Vim 7.4.785及更高版本,该脚本不再需要。” (来源:同一个Wiki页面。)谢谢,我不知道这个新选项。
阿米尔

1
我必须同时设置两者noeolnofixeol达到理想的结果。
selurvedu

8

OK,您在Windows上使事情变得复杂了;)

当'binary'选项重置'fileformat'选项时(并且使用'binary'设置进行写操作时总是使用unix行尾进行写操作),让我们拿起大锤子从外部进行操作!

如何为BufWritePost事件定义自动命令(:help自动命令)?每次您写入整个缓冲区后,都会执行此自动命令。在此自动命令调用中,将使用一个小的外部工具(php,perl或任何脚本)剥离刚刚写入的文件的最后一个换行符。

因此,这看起来像这样,并将进入您的.vimrc文件:

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

如果您是第一次处理自动命令,请确保阅读有关自动命令的整个vim文档。有一些警告,例如,建议删除.vimrc中的所有autocmd,以防您的.vimrc可能多次获得。


好吧……我希望有个比这更好的解决方案……但这肯定行得通!
Boushley

3
这很棒!好极了!但是我有一个问题...是否有办法做到这一点,所以我不必在每次保存后都按回车两次。我必须在弹出的cmd窗口中按Enter键,然后再次单击,因为vim告诉我脚本已成功返回...有什么办法可以使它们全部消失?
Boushley

2
为避免<Press Enter>提示,只需在命令前加上silent。例如silent !your-script <afile>
破烂不堪

6

我已经在Perl和Python后处理中实现了Blixtor的建议,这些后处理既可以在Vim中运行(如果使用这种语言支持进行编译),也可以通过外部Perl脚本运行。它可以作为vim.org上的PreserveNoEOL插件使用。


我尚未对其进行彻底的测试,但这似乎是一个更好的解决方案。
Boushley

插件可以工作,但是安装后我必须将其let g:PreserveNoEOL = 1放入.vimrc文件中!必须学习vimscript从插件描述中找出答案!:D
DarthVanger '16

1
@DarthVanger::help PreserveNoEOL-usage也会告诉你的。RTFM :-)
Ingo Karkat,2016年

@IngoKarkat哦,对不起。在INSTALLATION和下寻找这个CONFIGURATION。甚至没有注意到USAGE描述中的部分,因为它位于安装之上:)
DarthVanger

3

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

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


2
您是正确的,但是我们作为一家商店决定以结尾结尾看起来更好吗?
Boushley 2009年

1
此外,所以您知道php会自动将结尾标记解析为?>或?> \ n(因为在Linux中,所有有效文件都应以\ n结尾)...所以我的代码不会引起这些问题...他们只是不喜欢它的外观。
Boushley,2010年

2

我添加.vimrc

set binary

它可以帮助您尝试


2

我认为我找到了比可接受答案更好的解决方案。替代解决方案不适用于我,我也不想一直都在二进制模式下工作。幸运的是,这似乎可以完成工作,而且我还没有遇到任何讨厌的副作用:在文本文件末尾保留丢失的行尾。我只是将整个内容添加到我的〜/ .vimrc中。


1

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

如果执行:set binary,:w和:set nobinary,则如果没有开头,则文件将不使用换行符写入。

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


不幸的是,因为我正在使用Windows,所以如果将其保存为二进制模式,则会强制将其保存为Unix模式。即使当我执行:set binary:set fileformat = dos:w:set nobinary退出后,它也以Unix格式保存了文件...我不敢相信没有某种方法可以将其关闭。
Boushley


0

我发现此vimscript插件有助于解决这种情况。

Plugin 'vim-scripts/PreserveNoEOL'

或在github上阅读更多内容

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.