VIM は Windows の改行を追加しますか?

VIM は Windows の改行を追加しますか?

次の行末に注意してくださいgit diff:

-   IP_ADDR: 'http://1.2.3.4:143'
+   IP_ADDR: 'http://2.4.6.8:143'^M

このファイルを編集するには、カーソルを に置いて1を押しct:、新しい IP アドレスを入力します。ファイルから行が完全に追加または削除されたわけではありません。ただし、ファイルが VIM でタイプとして表示されることには気付きましたdos

ドキュメントのその部分を明示的に編集していないのに、なぜ VIM は行末を変更するのでしょうか? また、元の行に何もdiffなかったことが示されています^Mが、他にどのようにして VIM がこれがファイルであると判断できたのでしょうかdos?

答え1

Vim は ( で設定されているものの中から) 元のファイル形式を検出し'fileformats'、同じ形式で書き込みます。Vim が切り替える唯一の方法 (たとえば、Unix スタイルから Windows スタイルへ) は、​​明示的な を使用することです:setlocal fileformat=dos。設定にその形式が含まれている可能性は低いので、:verbose setl ff?が教えてくれるでしょう。

Gitのdiff自体については、あまり気にしないほうがいいと思います(全て行が変更されたように見える場合、実際には行末が切り替わっていることになりますが、コミットされたものは問題ありません。

Git 設定ではautocrlf = true、Git はファイルをチェックアウトするときに改行をシステム標準に変換し、コミットするときに LF 改行に変換することに注意してください。したがって、すべてがうまくいっている可能性があり、Git の diff 出力だけが混乱を招きます。

答え2

これは、私たち全員がマトリックスの中で生きている証拠です。もしこれが本当に 21 世紀であるなら、私たちはまだ異なる行末と格闘していることはないはずです。

Vimは行末を正しく処理する点でかなり優れています。詳細は で説明します:help 'ffs'。もちろん、vimはあなたの考えを読むことはできません。ファイルが矛盾した行末がない場合、vim は期待どおりに動作しない可能性があります。

vimでファイルを開いてから

:e! ++ff=unix

これにより、ファイルがディスクから再ロードされ、vim は UNIX スタイルの行末を使用するようになります。その後、行末が raw^M文字で終わるため、どの行に CRLF があるのか​​正確にわかるはずです。

私は git が大好きですが、vim ほどは理解も信頼もしていません。git のcrlf設定については、「設定して忘れる」構成を推奨する人もいると思いますが、これは混乱を招く可能性があります。私は @Ingo Karkat が回答で言及した設定は避けたいと考えています。チェックインされたのと同じファイルを git でチェックアウトし、行末の処理は私 (および vim) に任せたいのです。

答え3

git diff追加された行にのみ改行 ( ) が表示され、削除された行や変更されていない行には表示されません。フラグを使用すると、差分が逆に表示されるため、^Mこれを確認できます。-R

$ git diff -R:

-   IP_ADDR: 'http://2.4.6.8:143'
+   IP_ADDR: 'http://1.2.3.4:143'^M

したがって、vim は何も追加しません。特に、1 行だけの場合は追加しません。Vim は、ファイルを開くときにファイル内で見つかった行末を使用します。

答え4

Vim は、fileformat オプションの値に基づいて、現在開いているファイルが DOS または UNIX ファイルであるか、それとも Mac ファイルであるかを判断します。fileformat オプションの値は、fileformats オプションの値によって決まります。

vim がファイルを開くと、vim は現在のファイル形式オプションの値に基づいて、現在のバッファの有効なファイル形式オプション値を決定します。以下は、vim がファイル形式オプションの値によって現在のバッファのファイル形式オプションの値を決定する方法に関する vim マニュアルの説明です。

'fileformats' 'ffs' string (default:
                Vim+Vi  MS-DOS, MS-Windows OS/2: "dos,unix",
                Vim Unix: "unix,dos",
                Vim Mac: "mac,unix,dos",
                Vi  Cygwin: "unix,dos",
                Vi  others: "")
            global
            {not in Vi}
    This gives the end-of-line (<EOL>) formats that will be tried when
    starting to edit a new buffer and when reading a file into an existing
    buffer:
    - When empty, the format defined with 'fileformat' will be used
      always.  It is not set automatically.
    - When set to one name, that format will be used whenever a new buffer
      is opened.  'fileformat' is set accordingly for that buffer.  The
      'fileformats' name will be used when a file is read into an existing
      buffer, no matter what 'fileformat' for that buffer is set to.
    - When more than one name is present, separated by commas, automatic
      <EOL> detection will be done when reading a file.  When starting to
      edit a file, a check is done for the <EOL>:
      1. If all lines end in <CR><NL>, and 'fileformats' includes "dos",
         'fileformat' is set to "dos".
      2. If a <NL> is found and 'fileformats' includes "unix", 'fileformat'
         is set to "unix".  Note that when a <NL> is found without a
         preceding <CR>, "unix" is preferred over "dos".
      3. If 'fileformat' has not yet been set, and if a <CR> is found, and
         if 'fileformats' includes "mac", 'fileformat' is set to "mac".
         This means that "mac" is only chosen when:
          "unix" is not present or no <NL> is found in the file, and
          "dos" is not present or no <CR><NL> is found in the file.
         Except: if "unix" was chosen, but there is a <CR> before
         the first <NL>, and there appear to be more <CR>s than <NL>s in
         the first few lines, "mac" is used.
      4. If 'fileformat' is still not set, the first name from
         'fileformats' is used.
      When reading a file into an existing buffer, the same is done, but
      this happens like 'fileformat' has been set appropriately for that
      file only, the option is not changed.
    When 'binary' is set, the value of 'fileformats' is not used.

    When Vim starts up with an empty buffer the first item is used.  You
    can overrule this by setting 'fileformat' in your .vimrc.

    For systems with a Dos-like <EOL> (<CR><NL>), when reading files that
    are ":source"ed and for vimrc files, automatic <EOL> detection may be
    done:
    - When 'fileformats' is empty, there is no automatic detection.  Dos
      format will be used.
    - When 'fileformats' is set to one or more names, automatic detection
      is done.  This is based on the first <NL> in the file: If there is a
      <CR> in front of it, Dos format is used, otherwise Unix format is
      used.
    Also see |file-formats|.
    For backwards compatibility: When this option is set to an empty
    string or one format (no comma is included), 'textauto' is reset,
    otherwise 'textauto' is set.
    NOTE: This option is set to the Vi default value when 'compatible' is
    set and to the Vim default value when 'compatible' is reset.

質問に戻ると、ファイルは vim で dos ファイルとして識別されるため、ファイルを保存して vim を終了すると、vim は自動的に改行文字を dos スタイルの改行に置き換えます。

Git 作業ディレクトリ ツリーでは、このファイルは DOS ファイルですが、Git インデックス ツリーではこのファイルは Unix ファイルなので、 を使用するとgit diff、ファイルが変更されたことがわかります。Unix 形式のファイルの場合、余分な部分は ^M 文字として表示されます。

関連情報