Mengapa: bd # menghapus buffer saat ini ketika tidak ada buffer alternatif?

9

Inilah cara saya mereproduksi perilaku yang saya amati.

Pertama, saya masukkan perintah ini:

echo aaaaa > a
vim a

Di Vim, saya memasukkan perintah ini:

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

Ini adalah output dari tiga perintah di atas:

:ls
  1 %a   "a"                            line 1

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

:echo bufname('#')

The bufname('#')perintah tidak menghasilkan output.

Sekarang saya memasukkan perintah ini:

:bd #

Buffer saat ini dihapus dan diganti dengan buffer "[No Name]":

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

Saya mengharapkan untuk mendapatkan E194kesalahan pada eksekusi :bd #. Mengapa ia menghapus buffer saat ini?

Saya menggunakan VIM - Vi IMproved 8.0.

Lone Learner
sumber
1
Itu poin yang menarik. Anda dapat menyebutkan dalam pertanyaan Anda bahwa ini juga terjadi NVIM v0.3.0-dev, saya memeriksa.
klaus
@LoneLearner Saya tidak benar-benar menjawab ini karena karunia tetapi jika Anda akan menawarkan satu akan lebih baik jika Anda akan memberikannya pada jawaban yang layak ... sayangnya, Anda belum masuk hampir minggu dan masa hadiah berakhir ...
B Layer
1
@BLayer Maaf, saya lupa memberi hadiah. Anda telah menulis jawaban yang fantastis. Setelah saya memiliki cukup poin di situs Stack Exchange ini, saya akan memulai hadiah lain untuk pertanyaan ini dan memberikan hadiah itu kepada Anda. Saya berharap itu akan memperbaiki kesalahan saya. Terima kasih atas jawaban bagus yang telah Anda tulis.
Lone Learner
@LoneLearner Hei, sama-sama dan tidak perlu khawatir. Saya menghargai komentar Anda. Jangan khawatir tentang hadiahnya. Seperti saya katakan itu bukan tentang poin. Saya hanya ingin memberi Anda kepala untuk waktu berikutnya Anda memberikan hadiah. Letakkan poin dari sini ke sana. Bersulang!
B Layer

Jawaban:

7

Bukti

Karena tidak ada file alternatif, Anda sebenarnya hanya menjalankan file biasa :bd, menghapus buffer saat ini ... coba tanpa #dan Anda akan melihat hasilnya sama. Hal serupa terjadi dengan :buffer, :sbufferdan setidaknya beberapa perintah lain yang menerima #sebagai argumen: mereka diam-diam berperilaku seolah-olah tidak ada argumen yang disampaikan.

Sepanjang baris yang sama, jika Anda mencoba :bunload #Anda mendapatkan error ini: E90: Cannot unload last buffer. Jalankan :bunloadtanpa argumen dan, sekali lagi, Anda akan mendapatkan hasil yang sama.

The Documents

Jadi kami memiliki bukti yang #digantikan oleh "tidak ada" (mungkin string kosong). Kemana kita pergi dari sini? Saya mencari-cari file bantuan untuk sementara waktu berusaha menemukan penyebutan perilaku ini. Tidak ada yang eksplisit kecuali :h cmdline-linesmengatakan (gulir ke bawah satu atau dua halaman) ...

Ketika karakter '%' atau '#' digunakan di mana nama file diharapkan, mereka diperluas ke nama file saat ini dan alternatif.

Saya membaca bahwa sebagai Vim #melalui expand()fungsi (yaitu expand('#')) atau setidaknya kode dasar yang digunakan di sana.

:h expand() mengatakan:

Luaskan .. kata kunci khusus. .. Saat menggunakan '%' atau '#', dan nama file alternatif atau saat ini tidak ditentukan, string kosong digunakan.

Kedengarannya familiar.

Kode

Sekarang tidak satu pun di atas yang definitif atau memberikan petunjuk mengapa? jadi saya menghabiskan lebih banyak waktu untuk menggali ... kali ini dalam kode. C saya sangat berkarat dan saya tidak memiliki alat yang bagus diinstal tetapi saya berhasil menemukan fungsi yang melakukan beberapa pengaturan untuk :bdeletedipanggil do_bufdel(). Ini mengirimkan argumen baris perintah buflist_findpat()yang melaluinya , jika #ditemui, mengembalikan nilai curwin->w_alt_fnum. Itu adalah "nomor buffer" dari buffer alternatif ... yang tidak dapat menjadi nilai positif dalam skenario kami. (Tidak ada pemeriksaan apakah file alt valid / ada sebelum nilai pengembalian dipilih.)

Kembali dalam do_bufdel()pemeriksaan dibuat terhadap nilai kembali untuk nomor penyangga kurang dari 0 dalam hal loop pemrosesan parameter putus. Itu tidak akan menghasilkan parameter yang disajikan ke :bdeletekode inti ... yang sesuai dengan intuisi saya sebelumnya.

Apa berikutnya?

Tampaknya berfungsi sebagaimana dirancang dalam bahwa saya tidak melihat apa pun yang tampak seperti bug yang jelas. Mungkin dosa kelalaian, meskipun ... kasus sudut yang telah diabaikan dan dengan demikian tidak memiliki penanganan yang anggun. Tetapi hanya pengembang yang menulis ini yang tahu pasti. Jadi langkah terakhir adalah mencoba mendapatkan masukan dari mereka. Seperti kata Christian B. bertanya pada daftar vim-dev adalah jalan yang harus ditempuh.

(Perhatikan bahwa buflist_findpat()adalah fungsi utilitas sehingga tidak akan memerlukan imajinasi untuk mengasumsikan bahwa :bunload, :buffer, dll menggunakannya, juga ... yang akan menjelaskan perilaku umum mereka sehubungan dengan #.)

B Layer
sumber
Saya pikir satu lagi fungsi hanya untuk memeriksa apakah buffer yang diperluas ada atau tidak akan melakukan pekerjaan. Apakah Anda yakin ini seharusnya dirancang? Saya pikir ini harus terdaftar sebagai bug.
klaus
Saya pikir penelitian Anda benar. BTW: Saya rasa ini bukan bug.
Christian Brabandt
Saya hanya menulis ulang kesimpulan saya sedikit .... itu tidak terlihat seperti bug yang sulit. OTOH, jika dipikir-pikir orang bisa menyimpulkan bahwa itu perlu penanganan yang lebih baik. Mungkin hanya pengembang yang tahu pasti.
B Layer
Ya, orang bisa bertanya pada daftar vim-dev untuk memastikan.
Christian Brabandt