Executar um comando usando um nome de arquivo do buffer vim

0

Estou trabalhando com alguns arquivos do DokuWiki . Os arquivos possuem arquivos PNG complementares no mesmo diretório. Eles são referenciados na seguinte sintaxe:

{{filename.png}}

Eu quero escrever uma macro que pegue o filename.png e, idealmente, o caminho do arquivo que está sendo editado, e passe esses parâmetros para xdg-open .

O mais próximo que consegui até agora é o seguinte:

:'<,'>!sed s/\{\\|\}//g|xargs xdg-open

que é grosseiro, oblitera a linha atual, requer que eu esteja no caminho do arquivo e requer que eu use o modo visual para destacar o texto .... mas funciona.

Estou tendo problemas para encontrar a documentação que pode me ajudar a analisar com segurança a linha atual do nome do arquivo, depois passar o caminho do arquivo atual e o nome do arquivo de destino para xdg-open na linha de comando do vim.

Quando terminar ... isso idealmente permitirá que eu inicie a macro para visualizar o arquivo incorporado.

Por resposta do G-Man e alguns mexericos, o seguinte funciona bem:

:.w !sed -e 's|.*{{|%{{|' -e 's|[^/]*{{||' -e 's/^/"/' -e 's/}}.*/"/' | xargs xdg-open

Isso insere caracteres de aspas duplas ( " ) no início e no final do caminho / nome do arquivo, então ele suporta nomes que incluem espaços, apóstrofos (aspas simples) e alguns outros caracteres especiais.

    
por mgjk 24.02.2017 / 18:52

1 resposta

1
  • :range!command

    escreve o texto do intervalo para um pipe (excluindo-o do buffer de arquivo), executa o comando no pipe, lê a saída padrão do comando e insere-o no buffer onde o intervalo era. Essa é a função vim que você está usando. Esta função é muito útil com o comando sort . Não me lembro de ter visto outra situação onde esta função vim é útil; isso não parece ser um.

    Você quer

    :range w !command
    que grava o intervalo em um canal (mas não o exclui do buffer de arquivo), executa o comando no pipe, e deixa a saída padrão do comando (se houver) basta ir para a tela (ou seja, a saída padrão de vim ). (O espaço entre o intervalo e o w são opcionais.)
  • O intervalo pode ser de uma marca para outra ( '< e '> são efetivamente marcas), uma linha para outra ou apenas uma linha. Contanto que você tenha apenas um {{…}} em uma linha, você pode simplesmente ir até a linha (você não precisa realçá-lo) e use . como seu intervalo. Se você tiver apenas um {{…}} no arquivo, você pode usar /{{.*}}/ (ou até /{{/ , se for exclusivo) como seu intervalo. Então seu comando se torna
    :/{{/w !sed blah blah blah
  • Eu prefiro citar strings que precisam ser citadas com aspas , em vez de jogar um milhão de barras invertidas para eles. Eu acho que é apenas uma preferência pessoal; Se as barras invertidas funcionarem para você, use-as.
  • Expressões regulares extravagantes (usando | para procurar um padrão ou outro) tem o seu lugar no mundo. Eu me inclino para usar vários comandos sed . Mais uma vez, qualquer que seja.
  • Então, minha versão do que você está fazendo agora seria algo como isto:
    :/{{/w !sed -e 's/.*{{//' -e 's/}}.*//' | xargs xdg-open
    , que remove o {{ e tudo antes dele e remove o }} e tudo depois dele. Mas isso ainda requer que você esteja no diretório onde está o arquivo PNG.
  • O arquivo PNG está no mesmo diretório do arquivo de texto. É útil notar que, quando você executa um comando shell com ! de vim , um % sem escape na linha de comando é substituído pelo nome do arquivo que você está editando no momento. (Experimente: digite :!echo abc%def .) Podemos usar isso para determinar o nome do caminho para o diretório onde estão os arquivos. Assim, podemos melhorar o comando acima para:

    :/{{/w !sed -e 's|.*{{|%{{|' -e 's|[^/]*{{||' -e 's|}}.*||' | xargs xdg-open
    O primeiro subcomando sed, s|.*{{|%{{| , remove tudo antes do {{ e o substitui pelo nome do arquivo, e deixa o {{ . Note que este subcomando deve usar um delimitador (não em branco) que não aparecerá no caminho / nome de arquivo, por isso não podemos usar / . Se você tiver nomes de diretório ou nomes de arquivos com barras verticais, escolha outro caractere para usar como seu delimitador. O segundo subcomando, s|[^/]*{{|| , remove a parte nome do arquivo do nome do arquivo % , deixando a parte do diretório (se houver) e remove o {{ . O terceiro subcomando, s|}}.*|| , é o mesmo que o segundo subcomando ( s/}}.*// ) do comando anterior; remove o }} e tudo depois dele.

    Enquanto os comandos s/pattern/replacement/ sempre precisa usar um delimitador que não aparece no texto pattern ou replacement (ou escape do caractere delimitador quando ele aparecer), isso é um problema apenas para o primeiro comando s . Eu usei | em todos os três apenas por consistência.

TL; DR

Uso:

:/{{/w !sed -e 's|.*{{|%{{|' -e 's|[^/]*{{||' -e 's|}}.*||' | xargs xdg-open

P.S. Eu presumo que você perceba que isso não vai funcionar se o nome do arquivo contém espaço (s).

    
por 25.02.2017 / 05:32