Por que: bd # exclui o buffer atual quando não existe um buffer alternativo?

9

Aqui está como reproduzo o comportamento que estou observando.

Primeiro, insiro este comando:

echo aaaaa > a
vim a

No Vim, insiro estes comandos:

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

Aqui está a saída dos três comandos acima:

:ls
  1 %a   "a"                            line 1

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

:echo bufname('#')

O bufname('#')comando não produz saída.

Agora insiro este comando:

:bd #

O buffer atual é excluído e substituído por um buffer "[No Name]":

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

Eu esperava receber o E194erro na execução :bd #. Por que ele excluiu o buffer atual?

Eu estou usando VIM - Vi IMproved 8.0.

Aluno Solitário
fonte
11
Esse é um ponto interessante. Você pode mencionar na sua pergunta que esse também é o caso NVIM v0.3.0-dev, verifiquei.
Klaus
@LoneLearner Eu realmente não respondi isso por causa da recompensa, mas se você oferecer uma, seria bom se você a premiasse com uma resposta merecedora ... infelizmente, você não fez login quase semana eo período de graça é mais ...
B Camada de
11
@ Blayer Desculpe, esqueci de conceder a recompensa. Você escreveu uma resposta fantástica. Quando tiver pontos suficientes neste site do Stack Exchange, começarei outra recompensa para esta pergunta e a recompensarei. Espero que isso conserte meu erro. Obrigado pela ótima resposta que você escreveu.
Lone Learner
@LoneLearner Ei, você é bem-vindo e não se preocupe. Agradeço seu comentário. Não se preocupe com a recompensa. Como eu disse, não era sobre os pontos. Eu só queria te avisar da próxima vez que você oferecer uma recompensa. Coloque os pontos daqui em direção a isso. Felicidades!
Camada B

Respostas:

7

Evidência

Como não há nenhum arquivo alternativo, você está apenas executando o simples :bd, excluindo o buffer atual ... tente sem #e verá que o resultado é o mesmo. Uma coisa semelhante acontece com :buffer, :sbuffere pelo menos alguns outros comandos que aceitam #como argumento: eles se comportam silenciosamente como se nenhum argumento fosse passado.

Na mesma linha, se você tentar :bunload #você receber esse erro: E90: Cannot unload last buffer. Execute :bunloadsem argumentos e, mais uma vez, você obterá o mesmo resultado.

Os documentos

Portanto, temos evidências de que #está sendo substituído por "nada" (provavelmente uma string vazia). Para onde vamos daqui? Examinei os arquivos de ajuda por um tempo tentando encontrar menções a esse comportamento. Não havia nada explícito, mas :h cmdline-linesdiz (role uma página ou duas) ...

Quando o caractere '%' ou '#' é usado onde um nome de arquivo é esperado, eles são expandidos para o nome atual e alternativo.

Eu li isso como Vim colocando #através da expand()função (ie expand('#')) ou pelo menos o mesmo código subjacente usado lá.

:h expand() diz:

Expanda .. palavras-chave especiais. .. Ao usar '%' ou '#', e o nome do arquivo atual ou alternativo não está definido, uma sequência de caracteres vazia é usada.

Soa familiar.

O código

Agora, nenhuma das opções acima é definitiva ou dá uma pista sobre o porquê? então passei mais tempo cavando ... dessa vez no código. Meu C está muito enferrujado e não tenho boas ferramentas instaladas, mas consegui encontrar uma função que faz algumas configurações para :bdeletechamadas do_bufdel(). Isso envia argumentos de linha de comando através dos buflist_findpat()quais, se #encontrado, retorna valor curwin->w_alt_fnum. Esse é o "número do buffer" do buffer alternativo ... que não pode ser um valor positivo em nosso cenário. (Não é possível verificar se o arquivo alt é válido / existe antes que esse valor de retorno seja selecionado.)

O retorno em do_bufdel()uma verificação é feito com relação ao valor de retorno para um número de buffer menor que 0; nesse caso, o loop de processamento de parâmetros é interrompido. Isso resultaria em nenhum parâmetro sendo apresentado ao :bdeletecódigo principal ... o que está de acordo com minhas intuições anteriores.

Qual é o próximo?

Parece estar funcionando como projetado, pois não vi nada que parecesse um bug claro. Possivelmente pecado de omissão, no entanto ... uma caixa de esquina que foi ignorada e, portanto, não tem manuseio gracioso. Mas apenas os desenvolvedores que escreveram isso sabem com certeza. Portanto, o passo final seria tentar obter sua contribuição. Como Christian B. disse, perguntar na lista vim-dev é o caminho a percorrer.

(Note-se que buflist_findpat()é uma função de utilidade por isso não seria necessário um esforço de imaginação para supor que :bunload, :bufferetc. estão usando-o, também ... isso explicaria seu comportamento comum com relação a #.)

Camada B
fonte
Eu acho que mais uma função para apenas verificar se o buffer expandido existe ou não faria o trabalho. Você tem certeza de que isso deveria acontecer por design? Eu acho que isso deve ser listado como um bug.
Klaus
Eu acho que sua pesquisa está correta. BTW: Eu não acho que isso seja realmente um bug.
Christian Brabandt
Acabei de reformular um pouco minha conclusão ... não parece um bug difícil. OTOH, se alguém pensar a respeito, poderá concluir que precisa de um tratamento melhor. Provavelmente, apenas o desenvolvedor sabe ao certo.
Camada B
Sim, pode-se perguntar na lista vim-dev para ter certeza.
Christian Brabandt