Чому: bd # видаляє поточний буфер, коли не існує альтернативного буфера?


9

Ось як я відтворюю поведінку, яку я спостерігаю.

Спочатку я ввожу цю команду:

echo aaaaa > a
vim a

У Vim я ввожу ці команди:

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

Ось вихід із цих трьох команд:

:ls
  1 %a   "a"                            line 1

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

:echo bufname('#')

bufname('#')Команда не виробляє ніякого висновку.

Тепер я ввожу цю команду:

:bd #

Поточний буфер видаляється та замінюється буфером "[No Name]":

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

Я сподівався отримати E194помилку при виконанні :bd #. Чому замість цього видалили поточний буфер?

Я використовую VIM - Vi IMproved 8.0.


1
Це цікавий момент. Ви можете згадати у своєму питанні, що це теж справа NVIM v0.3.0-dev, я перевірив.
klaus

@LoneLearner Я не дуже відповів на це через виграш, але якщо ви збираєтесь запропонувати його, було б непогано, якби ви дали йому гідну відповідь ... на жаль, ви майже не ввійшли в систему тиждень, і термін щедрості закінчився ...
B Layer

1
@BLayer Вибачте, я забув нагородити. Ви написали фантастичну відповідь. Після того, як у мене буде достатньо балів на цьому сайті Stack Exchange, я розпочну ще одну винагороду за це питання і нагороджую вас. Я сподіваюся, що це виправить мою помилку. Дякую за чудову відповідь, яку ви написали.
Одинокий учень

@LoneLearner Привіт, ви не бажаєте хвилюватися. Я вдячний за ваш коментар. Не хвилюйтесь за щедрість. Наче я сказав, що справа не в питаннях. Я просто хотів дати тобі голову в наступний раз, коли ти виставив щедрість. Поставте пункти звідси до цього. Ура!
B Layer

Відповіді:


7

Докази

Оскільки немає альтернативного файлу, ви насправді просто запускаєте звичайний ol ' :bd, видаляючи поточний буфер ... спробуйте його без, #і ви побачите, що результат такий же. Щось подібне відбувається і з :buffer, :sbufferпринаймні , кілька інших команд , які беруть в #якості аргументу: вони мовчки ведуть себе , як якщо б не були передані аргументи.

У тому ж ключі, якщо ви спробуєте :bunload #ви отримаєте цю помилку: E90: Cannot unload last buffer. Запустіть :bunloadбез аргументів і, знову ж таки, ви отримаєте той самий результат.

Документи

Тож у нас є докази того, що #його замінюють на "нічого" (можливо, порожній рядок). Куди ми підемо звідси? Я деякий час обзивав файли довідки, намагаючись знайти згадку про цю поведінку. Не було нічого чіткого, але :h cmdline-linesсказано (прокрутіть сторінку або дві вниз) ...

Коли символ "%" або "#" використовується там, де очікується ім'я файлу, вони розширюються до поточного та альтернативного імені файлу.

Я читав, що як Vim, що #проходить через expand()функцію (тобто expand('#')) або хоча б той самий базовий код, який використовується там.

:h expand() каже:

Розгорніть .. спеціальні ключові слова. .. Коли використовується "%" або "#", а поточне або альтернативне ім'я файлу не визначено, використовується порожній рядок.

Звучить знайомо.

Код

Тепер жодне з перерахованого вище не є остаточним і не дає поняття, чому? тому я витратив ще трохи часу на копання ... цього разу в коді. Мій C дуже іржавий, і в мене не встановлено жодного хорошого інструменту, але мені вдалося знайти функцію, яка робить певну настройку для :bdeleteвиклику do_bufdel(). Це надсилає аргументи командного рядка, через buflist_findpat()які, якщо #виникає, повертає значення curwin->w_alt_fnum. Це "номер буфера" альтернативного буфера ... який не може бути позитивним значенням у нашому сценарії. (Немає перевірки на те, чи дійсний файл alt / існує до вибору цього повернутого значення.)

Відступ у do_bufdel()чеку робиться проти цього значення, що повертається, для буферного числа менше 0, і в цьому випадку цикл обробки параметрів виривається з. Це призвело б до того, що жоден параметр не буде представлений до основного :bdeleteкоду ..., що відповідає моїм інтуїціям.

Що далі?

Схоже, це працює так, як було розроблено, що я не бачив нічого, що було б схожим на явну помилку. Можливо, гріх упущення, хоча ... кутовий випадок, який було проігноровано і, таким чином, не має витонченого поводження. Але точно знають лише розробники, які це написали. Отже, завершальним кроком було б спробувати отримати їх внесок. Як сказав Крістіан Б., запитання у списку vim-dev - це шлях.

(Зверніть увагу , що buflist_findpat()це функція корисності , тому він не буде вимагати натяжки припустити , що :bunload, :bufferі т.д. використовує це теж ... що б пояснити їх загальна поведінка по відношенню до #.)


Я думаю, що ще одна функція для перевірки, чи існує розширений буфер, чи не зробить цю роботу. Ви впевнені, що це повинно було бути задумом? Я думаю, що це має бути зазначено як помилка.
klaus

Я думаю, що ваше дослідження правильне. BTW: Я не думаю, що це насправді помилка.
Крістіан Брабандт

Я просто переформулював свій висновок .... це не схоже на важку помилку. ОТОХ, якщо думати про це, можна зробити висновок, що воно потребує кращого поводження. Напевно, тільки розробник знає точно.
B Layer

Так, можна було б попросити у списку vim-dev переконатися.
Крістіан Брабандт
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.