Dlaczego: bd # usuwa bieżący bufor, gdy nie istnieje alternatywny bufor?

9

Oto jak odtwarzam zachowanie, które obserwuję.

Najpierw wpisuję to polecenie:

echo aaaaa > a
vim a

W Vimie wprowadzam następujące polecenia:

:ls
:e #
:echo bufname('#')

Oto wynik powyższych trzech poleceń:

:ls
  1 %a   "a"                            line 1

:e #
E194: No alternate file name to substitute for '#'

:echo bufname('#')

bufname('#')Polecenie tworzy żadnego wyjścia.

Teraz wprowadzam to polecenie:

:bd #

Bieżący bufor zostanie usunięty i zastąpiony buforem „[Brak nazwy]”:

:ls
  2 %a   "[No Name]"                    line 1

Spodziewałem się E194błędu podczas wykonywania :bd #. Dlaczego zamiast tego usunął bieżący bufor?

Używam VIM - Vi IMproved 8.0.

Samotny uczeń
źródło
1
To interesujący punkt. Możesz wspomnieć w swoim pytaniu, że tak też jest w przypadku NVIM v0.3.0-dev, sprawdziłem.
klaus
@LoneLearner Naprawdę nie odpowiedziałem na to z powodu nagrody, ale jeśli masz zamiar ją zaoferować, byłoby miło, gdybyś udzielił jej zasłużonej odpowiedzi ... niestety, nie zalogowałeś się prawie tydzień, a okres nagród się skończył ...
B Layer
1
@BLayer Przepraszam, zapomniałem przyznać nagrodę. Napisałeś fantastyczną odpowiedź. Kiedy zdobędę wystarczającą liczbę punktów na tej stronie wymiany stosów, zacznę kolejną nagrodę za to pytanie i przyznam nagrodę. Mam nadzieję, że naprawi to mój błąd. Dziękuję za wspaniałą odpowiedź, którą napisałeś.
Lone Learner
@LoneLearner Hej, proszę bardzo i nie martw się. Doceniam twój komentarz. Nie martw się o nagrodę. Tak jak powiedziałem, nie chodziło o punkty. Chciałem tylko dać ci głowę na następny raz, kiedy wystawisz nagrodę. Skieruj stąd punkty na to. Twoje zdrowie!
B warstwa

Odpowiedzi:

7

Dowód

Ponieważ nie ma alternatywnego pliku, w rzeczywistości po prostu używasz zwykłego :bd, usuwając bieżący bufor ... wypróbuj go bez, #a zobaczysz, że wynik jest taki sam. Podobna rzecz dzieje się :buffer, :sbuffera co najmniej kilka innych poleceń, które akceptują #jako argument: oni cicho zachowywać się tak, jakby były przekazywane żadne argumenty.

Według tych samych zasad, jeśli starają :bunload #się ten błąd: E90: Cannot unload last buffer. Uruchom :bunloadbez argumentów i ponownie otrzymasz ten sam wynik.

The Docs

Mamy więc dowody, które #są zastępowane przez „nic” (prawdopodobnie pusty ciąg znaków). Dokąd zmierzamy? Przez chwilę przeglądałem pliki pomocy, próbując znaleźć wzmiankę o tym zachowaniu. Nie było nic wyraźnego oprócz :h cmdline-linespowiedzenia (przewiń stronę lub dwie) ...

Gdy znak „%” lub „#” zostanie użyty tam, gdzie oczekiwana jest nazwa pliku, są one rozwijane do bieżącej i alternatywnej nazwy pliku.

Czytałem, że jak Vim oddanie #przez expand()funkcję (np expand('#')) lub przynajmniej tego samego kodu bazowego tam wykorzystywane.

:h expand() mówi:

Rozwiń .. specjalne słowa kluczowe. .. Gdy używasz „%” lub „#”, a bieżąca lub alternatywna nazwa pliku nie jest zdefiniowana, używany jest pusty ciąg.

Brzmi znajomo.

Kod

Teraz żadne z powyższych nie jest ostateczne ani nie daje wskazówek, dlaczego? więc poświęciłem trochę więcej czasu na kopanie ... tym razem w kodzie. Moje C jest bardzo zardzewiałe i nie mam zainstalowanych żadnych dobrych narzędzi, ale udało mi się znaleźć funkcję, która wykonuje pewne :bdeletewywołanie do_bufdel(). To wysyła argumenty wiersza poleceń, przez buflist_findpat()które, jeśli #zostanie napotkany, zwraca wartość curwin->w_alt_fnum. To jest „numer bufora” alternatywnego bufora ... który nie może być wartością dodatnią w naszym scenariuszu. (Nie jest sprawdzane, czy plik alt jest prawidłowy / istnieje przed wybraniem tej wartości zwracanej).

Wycofywanie w do_bufdel()celu sprawdzenia jest wykonywane względem tej wartości zwracanej dla numeru bufora mniejszego niż 0, w którym to przypadku pętla przetwarzania parametrów jest przerywana. Spowodowałoby to, że żadne parametry nie byłyby prezentowane w :bdeletekodzie podstawowym ... co jest zgodne z moimi wcześniejszymi intuicjami.

Co dalej?

Wygląda na to, że działa zgodnie z przeznaczeniem, ponieważ nie widziałem niczego, co wyglądałoby jak wyraźny błąd. Być może grzech zaniedbania, choć ... narożny przypadek, który został przeoczony, a zatem nie ma wdzięcznego sposobu obsługi. Ale tylko programiści, którzy to napisali, wiedzą na pewno. Ostatnim krokiem będzie próba uzyskania ich wkładu. Jak powiedział Christian B., pytaniem na liście vim-dev jest droga.

(Należy pamiętać, że buflist_findpat()jest to funkcja użyteczności więc nie wymagałby odcinek wyobraźni, aby przypuszczać, że :bunload, :bufferitp używasz go też ... to by tłumaczyło ich wspólne zachowanie względem #).

Warstwa B.
źródło
Sądzę, że jeszcze jedna funkcja sprawdzania, czy istnieje rozszerzony bufor, wykona zadanie. Czy jesteś pewien, że tak powinno być? Myślę, że powinien to być błąd.
klaus
Myślę, że twoje badania są poprawne. BTW: Nie sądzę, że to właściwie błąd.
Christian Brabandt,
Właśnie przerobiłem nieco moją konkluzję ... to nie wygląda na twardy błąd. OTOH, jeśli się nad tym zastanowić, można dojść do wniosku, że wymaga to lepszej obsługi. Prawdopodobnie tylko programista wie na pewno.
B Warstwa
Tak, można się upewnić na liście vim-dev.
Christian Brabandt,