VIM wyłącz automatyczną nową linię na końcu pliku


250

Więc pracuję w sklepie PHP i wszyscy używamy różnych edytorów i wszyscy musimy pracować na Windowsie. Używam vima i wszyscy w sklepie narzekają, że za każdym razem, gdy edytuję plik, na dole jest nowy wiersz. Szukałem wokoło i odkryłem, że jest to udokumentowane zachowanie vi & vim ... ale zastanawiałem się, czy istnieje jakiś sposób, aby wyłączyć tę funkcję. (Byłoby najlepiej, gdybym mógł to wyłączyć dla określonych rozszerzeń plików).

Jeśli ktoś o tym wie, byłoby świetnie!


23
należy im powiedzieć oni są głupie - jest rzeczywiście dobry powód, dlaczego robi to vim: stackoverflow.com/questions/729692/... . Sądzę jednak, że ma to znaczenie tylko w przypadku wdrażania na serwerach typu unix.
hdgarrood

5
Oficjalna zalecana praktyka PHP polega na pomijaniu ostatniego ?>tagu zamykającego, właśnie z tego powodu.
Sebastián Grignoli

to pytanie prawdopodobnie poprzedza superużytkownika ... ale powinno tam być.
gcb

20
Pytanie naprawdę powinno być: W jaki sposób możemy powiedzieć wszystkich innych redaktorów, że ludzie w sklepie w celu zapewnienia korzystania ostatni wiersz pliku ma końcówkę z EOL. ;-)
TJ Crowder

Odpowiedzi:


359

A dla wersji vim7.4+ możesz użyć (najlepiej na swoim .vimrc) (dzięki 罗泽轩 za ostatnie wiadomości!):

:set nofixendofline

Teraz dotyczy starszych wersji vim.

Nawet jeśli plik został już zapisany z nowymi liniami na końcu:

vim -b file i raz w vimie:

:set noeol
:wq

Gotowe.

alternatywnie możesz otwierać pliki w vimie za pomocą :e ++bin file

Jeszcze jedna alternatywa:

:set binary
:set noeol
:wq

6
Możesz także dodać set binaryiw set noeolswoim .vimrc
dryobs

17
Uwaga : binaryprzesłonięcia expandtab, które doprowadzą do uzyskania dosłownych zakładek w źródle.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

4
@CiroSantilli dziękuję! zawsze szukałem efektów ubocznych binarnych i zastanawiam się, dlaczego nie jest to domyślne! ponieważ uwielbiam moje zakładki, myślę, że rozważę tę dodatkową korzyść :)
gcb

11
Teraz możesz dodać, set nofixendoflineaby rozwiązać problem w Vimie 7.4+
罗泽轩

1
@TrevorBoydSmith tak, ponieważ historycznie POSIX (może się mylę co do rzeczywistego standardu) oczekuje nowej linii na końcu linii w pliku tekstowym. Dlatego większość rozwiązań wymagała traktowania go jako pliku binarnego. Prawdopodobnie było to wtedy bardzo wygodne i jest dziś zacofane, dlatego teraz jest wygodne ustawienie. Po prostu dodaj go do swojego vimrc. W innych edytorach są i tak gorsze problemy :)
gcb

23

Dodaj następujące polecenie do .vimrc, aby włączyć opcję końca linii:

autocmd FileType php setlocal noeol binary fileformat=dos

Jednak sam PHP zignoruje ten ostatni koniec linii - nie powinno to stanowić problemu. Jestem prawie pewien, że w twoim przypadku jest coś innego, co dodaje ostatni znak nowej linii, lub możliwe, że jest to mixup z typami końca linii Windows / Unix ( \nlub \r\nitp.).

Aktualizacja:

Alternatywnym rozwiązaniem może być po prostu dodanie tej linii do pliku .vimrc:

set fileformats+=dos

Wiem, że php nie analizuje tego źle ... Pokazałem to moim współpracownikom, ale winmerge widzi je jako różne ... Spróbuję tego i dam wam znać, jak to się potoczy.
Boushley,

W ten sposób pożądany efekt nie ma linii końcowej, ale konwertuje również plik na zakończenia linii uniksowej ... (nawet w oknie systemu Windows) ... Więc zrobiłem to wcześniej, przechodząc w tryb binarny ... ale potem zakończenia linii nie pokazują się w notatniku ... wszystko jest tylko jedną linią.
Boushley,

Niestety żadna z tych sugestii nie działa. Dodanie fileformat = dos do autocmd nie ma żadnego efektu, a ustawiony
typ

Przepraszam, pomyliłem się, użyj „ustaw typy plików + = dos”, a nie „ustaw formaty plików ...”
za dużo php

17

Istnieje inny sposób, aby podejść do tego, jeśli używasz Git do kontroli źródła. Zainspirowany odpowiedzią tutaj napisałem własny filtr do użycia w pliku gitattributes .

Aby zainstalować ten filtr, zapisz go noeol_filtergdzieś w swoim $PATH, ustaw go jako wykonywalny i uruchom następujące polecenia:

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

Aby zacząć korzystać z filtra tylko dla siebie, wstaw następujący wiersz w $GIT_DIR/info/attributes:

*.php filter=noeol

Zapewni to, że nie zatwierdzisz nowego wiersza na eof w .phppliku, bez względu na to, co zrobi Vim.

A teraz sam skrypt:

#!/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)

To świetne rozwiązanie ... chociaż niestety nie używałem git. Korzystałem z svn, chociaż podejrzewam, że można było zastosować podobne podejście. W każdym razie przeszedłem z tej pozycji i nie muszę się już o to martwić :)
Boushley,

12

Nie próbowałem tej opcji, ale w systemie pomocy vim podane są następujące informacje (tj. 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.  

Zwykle nie trzeba ustawiać ani resetować tej opcji. Gdy opcja „binarna” jest wyłączona, wartość nie jest używana podczas zapisywania pliku. Gdy włączona jest opcja „binarna”, używana jest do zapamiętania obecności dla ostatniego wiersza w pliku, dzięki czemu podczas zapisywania pliku można zachować sytuację z oryginalnego pliku. Ale możesz to zmienić, jeśli chcesz.

Możesz być również zainteresowany odpowiedzią na poprzednie pytanie: „ Dlaczego pliki powinny kończyć się nową linią ”.


Natrafiłem też na ustawienie eol ... ale to nie spełnia tego zadania. Jest to bardziej zmienna, która określa, czy została już umieszczona na końcu pliku, czy nie. Ponadto nie ma wpływu na pliki tekstowe, ale tylko na pliki binarne.
Boushley

3
Pomoc vima mówi również: „Gdy„ binarny ”jest wyłączony, wartość nie jest używana podczas zapisywania pliku. o eol
Boushley

1
+1 za odpowiedź VonC na to pytanie, która podkreśla, że ​​„newline” i EOL są skonfliktowane. Gorsze edytory niepoprawnie wyświetlają dodatkową nową linię z powodu EOL, vim nie dodaje „nowej linii”!
ches

9

Dodałem wskazówkę na wiki Vima dotyczącą podobnego (choć innego) problemu:

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


5
„Vim 7.4.785 dodaje fixeolopcję, którą można wyłączyć, aby automatycznie zachować brakujące EOL na końcu pliku. Ten skrypt staje się niepotrzebny w wersji Vim 7.4.785 i nowszych. ” (Źródło: ta sama strona wiki.) Dzięki, nie wiedziałem o tej nowej opcji.
Amir

1
Musiałem ustawić oba noeoli nofixeolosiągnąć pożądany rezultat.
selurvedu

8

OK, bycie w systemie Windows komplikuje sprawy;)

Ponieważ opcja „binarna” resetuje opcję „format pliku” (a pisanie za pomocą zestawu „binarnego” zawsze pisze z zakończeniami linii uniksowej), wyjmijmy wielki młot i zróbmy to na zewnątrz!

Co powiesz na zdefiniowanie autocommand (: help autocommand) dla zdarzenia BufWritePost? Ta komenda automatyczna jest wykonywana po każdym zapisaniu całego bufora. W tej komendzie automatycznej wywołaj małe narzędzie zewnętrzne (php, perl lub inny skrypt), które usuwa ostatnią nową linię właśnie zapisanego pliku.

Więc wyglądałoby to mniej więcej tak i przechodziłoby do twojego pliku .vimrc:

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

Przeczytaj całą dokumentację vim na temat komend automatycznych, jeśli po raz pierwszy masz do czynienia z komendami automatycznymi. Istnieją pewne zastrzeżenia, np. Zaleca się usunięcie wszystkich autocmds z .vimrc na wypadek, gdyby twoje .vimrc mogło uzyskać wiele źródeł.


Cóż ... miałem nadzieję, że istnieje lepsze rozwiązanie niż to ... ale to na pewno działa!
Boushley,

3
To działa świetnie! Tak! Mam jednak jedno pytanie ... czy istnieje sposób, aby to zrobić, więc nie muszę naciskać Enter dwa razy po każdym zapisaniu. Muszę wcisnąć enter w oknie cmd, które się pojawiło, a potem znowu, ponieważ vim mówi mi, że skrypt powrócił pomyślnie ... Czy jest jakiś sposób, aby wszystkie zniknęły?
Boushley,

2
Aby uniknąć podpowiedzi <Naciśnij Enter>, po prostu poprzedź polecenie silent. Np silent !your-script <afile>.
dash-tom-bang

6

Zaimplementowałem sugestie Blixtor z postprocessingiem Perla i Pythona, albo działając w Vimie (jeśli jest skompilowany z taką obsługą języków), albo przez zewnętrzny skrypt Perla. Jest dostępny jako wtyczka PreserveNoEOL na vim.org.


Nie przetestowałem tego dokładnie, ale wydaje się to lepszym rozwiązaniem.
Boushley,

Wtyczka działa, ale po instalacji musiałem umieścić let g:PreserveNoEOL = 1w swoim .vimrcpliku! Musiałem nauczyć się vimscript, aby dowiedzieć się o tym z opisu wtyczki! : D
DarthVanger

1
@DarthVanger: też :help PreserveNoEOL-usageby ci powiedział. RTFM :-)
Ingo Karkat

@IngoKarkat Oh, przepraszam. Szukałem tego pod INSTALLATIONi CONFIGURATION. Nawet nie zauważyłem USAGEsekcji w opisie, ponieważ jest ona powyżej instalacji :)
DarthVanger

3

Może mógłbyś sprawdzić, dlaczego narzekają. Jeśli plik php ma nowy wiersz po zakończeniu?>, Php wyświetli go jako część strony. Nie stanowi to problemu, chyba że spróbujesz wysłać nagłówki po dołączeniu pliku.

Jednak?> Na końcu pliku php jest opcjonalny. Bez końca?>, Nie ma problemu z nową linią na końcu pliku.


2
Masz rację, ale my jako sklep zdecydowaliśmy, że lepiej jest mieć zakończenie?> Wiem, że moglibyśmy przestać go używać ... ale wolę dostosować edytor do mojego stylu kodowania niż na odwrót.
Boushley

1
Ponadto, abyś wiedział, że php automatycznie parsuje twój znacznik końcowy jako?> Lub jako?> \ N (ponieważ w systemie Linux wszystkie prawidłowe pliki powinny kończyć się na \ n) ... Więc mój kod nie powoduje tych problemów ... po prostu nie lubią tego wyglądu.
Boushley,


2

Myślę, że znalazłem lepsze rozwiązanie niż zaakceptowana odpowiedź. Alternatywne rozwiązania nie działały dla mnie i nie chciałem cały czas pracować w trybie binarnym. Na szczęście wydaje się, że wykonało to zadanie i nie spotkałem się jeszcze z żadnymi nieprzyjemnymi skutkami ubocznymi: zachowaj brakujący koniec linii na końcu plików tekstowych . Właśnie dodałem całą rzecz do mojego ~ / .vimrc.


1

Czy byłoby możliwe użycie specjalnego polecenia do zapisywania tych plików?

Jeśli zrobisz: ustaw binarny,: w i: ustaw nobinary, plik zostanie zapisany bez nowej linii, jeśli nie było go na początku.

Oczywiście tę sekwencję poleceń można umieścić w poleceniu zdefiniowanym przez użytkownika lub w mapowaniu.


Niestety, ponieważ pracuję z systemem Windows, jeśli zapiszę go w trybie binarnym, wymusza to zapisywanie w trybie unixowym. Nawet gdy to zrobię: set binary: set fileformat = dos: w: set nobinary Po wyjściu zapisałem plik w formacie unixowym ... Nie mogę uwierzyć, że nie ma sposobu, aby to wyłączyć.
Boushley,


0

Odkryłem, że ta wtyczka vimscript jest pomocna w tej sytuacji.

Plugin 'vim-scripts/PreserveNoEOL'

Lub czytaj więcej na github

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.