Pourquoi Vim ajoute-t-il une nouvelle ligne? Est-ce une convention?


22

Si j'ouvre Vim et que itest<Esc>:wqje tape, j'obtiens un fichier qui n'a pas de retour à la ligne dans Vim mais qui semble avoir une nouvelle ligne dans le code:

$ vim -u NONE test.txt
$ cat test.txt | hd
00000000  74 65 73 74 0a                    |test.|
00000005

Si j'ouvre Vim et que itest<Return><Esc>:wqje tape, j'obtiens un fichier qui a une nouvelle ligne dans Vim mais deux nouvelles lignes dans le code:

$ rm test.txt
$ vim -u NONE test.txt
$ cat test.txt | hd
00000000  74 65 73 74 0a 0a                 |test..|
00000006

Notez que j'ouvre Vim avec -u NONEdonc aucune configuration locale n'est utilisée. Notez également que cela pourrait être lié à une question précédente .

Voici mes informations système:

$ uname -a
Linux awsAlpha 3.2.0-60-virtual #91-Ubuntu SMP Wed Feb 19 04:13:28 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
$ vim --version
VIM - Vi IMproved 7.3 (2010 Aug 15, compiled May  4 2012 04:25:35)
Included patches: 1-429
Modified by pkg-vim-maintainers@lists.alioth.debian.org
Compiled by buildd@

Je peux également confirmer exactement le même comportement sur ce système:

$ uname -a
Linux bruno 3.5.0-48-generic #72-Ubuntu SMP Mon Mar 10 23:18:29 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
$ vim --version
VIM - Vi IMproved 7.3 (2010 Aug 15, compiled Oct 26 2012 16:45:33)
Included patches: 1-547
Modified by pkg-vim-maintainers@lists.alioth.debian.org
Compiled by buildd@

Pourquoi Vim ajoute-t-il une nouvelle ligne? Est-ce une convention?

Voici quelques précisions sur la hdcommande telle qu'elle est installée sur le serveur Ubuntu:

$ man hd | head -4
HEXDUMP(1)            BSD General Commands Manual            HEXDUMP(1)

NAME
     hexdump, hd — ASCII, decimal, hexadecimal, octal dump

8
Cela semble être une convention. Voici comment le désactiver si vous le souhaitez. Voici l'histoire de cela.
jliv902

Réponses:


28

La convention pour les fichiers texte Unix est que chaque ligne se termine par une nouvelle ligne et que les nouvelles lignes sont des terminateurs de ligne et non des séparateurs de ligne.

Lorsque Vim enregistre un tampon en tant que fichier, il termine chaque ligne avec la séquence de fin de ligne pour ce format de fichier, qui pour Unix est une nouvelle ligne. Voir

:help 'fileformat'

Si vous utilisez des outils de traitement de texte Unix, il est préférable de respecter cette convention. Cependant, si vous avez besoin de ne pas mettre de nouvelle ligne à la fin de la dernière ligne d'un fichier, vous pouvez le faire. Vim considère ces fichiers comme "binaires". Voir

:help 'binary'
:help edit-binary

1
Oh c'est intéressant. Donc en plus du fameux \ r \ n vs \ n. Windows utilise des séparateurs de ligne et unix utilise des terminateurs de ligne? et est-ce documenté quelque part? Je sais qu'il est défini ici s'appliquant vraisemblablement à unix "ISO / IEC 9899: 2011, Section §7.21.2 Streams dit: Un flux de texte est une séquence ordonnée de caractères composée de lignes, chaque ligne se composant de zéro ou plusieurs caractères plus une nouvelle terminaison -line character "
barlop

mais où est-il documenté que Windows utilise un séparateur de lignes?
barlop

2

Vim n'ajoute rien que vous n'ayez pas mis vous-même.

Un caractère "nouvelle ligne" n'est pas une "nouvelle ligne" et les deux exemples sont parfaitement normaux:

  • dans le premier, le fichier ne contient qu'une seule ligne, vous obtenez donc un caractère "nouvelle ligne",
  • dans le second, le fichier contient deux lignes, vous obtenez donc deux caractères de "nouvelle ligne".

2
Il ajoute la nouvelle ligne. Testez-le comme suit printf "\x41" > /tmp/test.txt:, puis vérifiez qu'il n'a qu'un seul caractère 'A' avec xxd /tmp/test.txt. Maintenant vim /tmp/test.txt<ENTER>:wq. Vérifiez à nouveau pour voir le fichier contenant deux octets: 'A \ n'.
Ruslan

Les lignes se terminent par un caractère de nouvelle ligne. Vous avez une ligne donc vous avez un caractère de nouvelle ligne.
romainl

Eh bien, après printfici, je n'avais pas de "lignes" bien formées. Après vim j'en ai un. Donc, cela ajoute quelque chose que je n'ai pas mis là-bas.
Ruslan

Ce que vous n'êtes printfpas une ligne, sauf si vous ajoutez \n. En tant qu'éditeur de texte, Vim gère les lignes par défaut, et tout texte que vous insérez dans le fichier se trouve , à tout le moins, sur une ligne, sauf si vous dites explicitement à Vim de ne pas le faire.
romainl

2

Les fichiers texte non terminés sont mauvais pour plusieurs raisons; en voici une que je n'ai pas encore vue mentionnée:

Dans un monde hypothétique où les fichiers texte sans retour à la ligne sont acceptables, il n'y aurait aucune différence entre un fichier contenant 0 lignes et un fichier contenant 1 ligne vierge. Ils seraient tous deux représentés par un fichier de 0 octet.

L'incapacité de décider du nombre de lignes dans un fichier serait mauvaise.


Les fichiers texte dans les systèmes non Unix contiennent zéro ou plusieurs lignes complètes, plus une ligne incomplète de zéro ou plusieurs caractères. Un fichier vide ne contient pas de ligne vierge; il contient zéro ligne complète et une ligne partielle de zéro caractère. Où est l'ambiguïté?
supercat

Cette "ligne partielle" est un concept désagréable. Vous ne pouvez pas en avoir un autre que la fin du fichier, et vous ne pouvez pas créer un fichier qui n'a pas de "ligne partielle". Cela ajoute plus de rupture à la concaténation de fichiers - même si vous insérez une nouvelle ligne entre les fichiers, vous vous retrouvez avec quelque chose qui n'est pas sémantiquement équivalent à la paire de fichiers d'origine (car avec 2 fichiers, vous aviez 2 lignes partielles, et l'un d'eux est devenu quelque chose différent.) Une proposition inélégante.

Le fait que la concaténation de fichiers entraîne l'ajout d'une ligne partielle à la fin du premier au fichier suivant est généralement délicat dans les cas où les deux fichiers contiennent des lignes complètes (il peut parfois être utile de concaténer des fichiers qui ne contiennent pas de lignes complètes ), mais c'est ce que c'est. Unix n'interdit pas la construction de fichiers texte se terminant par des lignes partielles, et je crois que la concaténation de tels fichiers se comportera comme dans MSDOS. La différence, je pense, est que de nombreux éditeurs basés sur DOS ont historiquement considéré que le chargement et l'enregistrement immédiat d'un fichier devraient produire un nouveau fichier ...
supercat

... qui est à peu près identique à l'ancien (les utilisateurs enregistrés des premières versions de PC-Write ont été invités à l'utiliser pour ouvrir une copie de l'exécutable, passer en mode d'écrasement, trouver une certaine chaîne et la remplacer par leur numéro de série!). Forcer les fichiers à se terminer par des sauts de ligne lors de leur enregistrement violerait cette contrainte.
supercat

2

Vim 8.0 prévoit désormais cela avec l' fixeoloption. Plus précisément si vous le faites:

:set nofixeol

alors Vim n'ajoutera pas de caractère de fin de ligne à la fin de la dernière ligne si le fichier n'en avait pas déjà un.

Cela pourrait aller dans un plugin de type de fichier, ou peut-être même dans votre .vimrc.

(Il s'agit d'une amélioration :set binarycar elle n'affecte que le caractère de saut de ligne final, tout en binarymodifiant également un tas d'autres comportements, ce que vous ne voulez probablement pas sauf si vous modifiez réellement un fichier binaire.)

Un fichier nouvellement créé aura toujours un caractère de saut de ligne de fin par défaut. Vous pouvez changer cela (et changer un fichier qui a déjà un retour à la ligne final pour n'en avoir pas) en faisant en outre:

:set noeol

Cela doit être défini spécifiquement pour chaque fichier que vous souhaitez modifier: le chargement d'un fichier dans un tampon sera toujours défini eolpour correspondre à l'état actuel du fichier.


1

En utilisant la commande «j», vous pouvez joindre toutes les lignes en une seule.

Si vous souhaitez également supprimer le LF ou le CRLF sur la dernière ligne, procédez comme suit en vi.

$ vi file
:set binary
:set noeol
:w!
:f          look for [noeol] on the status line
:q
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.