Como inserir o resultado de um comando no texto no vim?

42

Por exemplo, :echo strftime(%c)mostrará a hora atual na parte inferior, mas como inserir essa sequência de horas no texto (logo após o cursor)?

xzhu
fonte
1
Eu acredito que o OP significa "Como inserir o resultado de uma expressão Vim no texto?"
Alastair Irvine
Também vale a pena mencionar que essa não é a mesma pergunta que Escrever uma função vim para inserir um bloco de texto estático , no entanto, algumas das respostas ainda se aplicam.
Alastair Irvine
Seu exemplo é literalmente meu caso de uso e eu o saúdo.
Joe
Veja também redirecionando para um registro: stackoverflow.com/questions/2573021/…
NeilG

Respostas:

49

É possível utilizar o registo expressão, "=, com p(ou P) no modo normal ou <C-R>no modo de inserção:

No modo normal:
( <C-M>aqui significa Control+ M, ou apenas pressione Enter/ Return)

"=strftime('%c')<C-M>p

No modo de inserção:
( <C-M>tem o mesmo significado que acima, <C-R>significa Control+ R)

<C-R>=strftime('%c')<C-M>

Se você deseja inserir o resultado da mesma expressão várias vezes, mapeá-lo nas chaves .vimrc:
(aqui o <C-M>e <C-R>deve ser digitado literalmente (uma sequência de cinco caracteres imprimíveis - o Vim os traduzirá internamente))

:nmap <F2> "=strftime('%c')<C-M>p
:imap <F2> <C-R>=strftime('%c')<C-M>
Chris Johnsen
fonte
2
+1 fora do curso! O "=registro. : - /
Eelvex 25/02
2
para obter o valor de uma variável vim (por exemplo, opções de sessão): <C-R>=&sessionoptions- ele ainda completa a tabulação de modo selvagem!
26612 Justin Bieber Keyes
2
: put = strftime ('% c') <CM>
brunch875 13/08/2015
No modo de inserção, o uso <c-r>=é lento para o comando, que pode ter muita saída e também pode quebrar o recuo para que o texto de saída seja ilegível. Por exemplo, <c-r>=execute('nmap')a saída será escrita linha por linha, o que é muito lento.
jdhao 24/04
22

:r!date +\%c

Vejo :help :r!

Glenn Jackman
fonte
1
dateé um comando externo e !chama comandos externos enquanto o OP solicita comandos vim.
Eelvex
@eelvex não, ele não fez. e a ! é um comando vim e vi. Este é o método canônico. Funciona para muitas outras coisas também.
Keith
5
@ Keith: yes !é um comando vi (m) que chama comandos externos . Você pode estar certo no OP, não desejando emitir apenas comandos vim, mas se ele o fizer, !não o fará.
Eelvex
11

Estes comandos irão inserir a saída strftime("%c")exatamente onde está o cursor:

:exe ":normal i" . strftime("%c")

e

:call feedkeys("i". strftime("%c"))

Existem outras maneiras de fazer o que você deseja (como, por exemplo, as da resposta de Mikel ).

Editar : Melhor ainda, para inserção no local, use o =registro como Chris Johnsen descreve

Eelvex
fonte
10

Se você deseja inserir a saída de um comando vim (em oposição ao valor de retorno de uma chamada de função ), é necessário capturá-lo. Isso é realizado através do :redircomando, que permite redirecionar o equivalente do vim à saída padrão para uma variável, arquivo, registro ou outro destino.

:rediré meio dolorosamente inconveniente de usar; Eu escreveria uma função para encapsular sua funcionalidade de uma maneira mais conveniente, algo como

funct! Exec(command)
    redir =>output
    silent exec a:command
    redir END
    return output
endfunct!

Depois de declarar essa função, você pode usar o registro de expressão (como explicado por Chris Johnsen) para inserir a saída de um comando na posição do cursor. Portanto, no modo normal, pressione i^R=Exec('ls')para inserir a lista dos buffers atuais do vim.

Esteja ciente de que o comando será executado no namespace da função; portanto, se você usar uma variável global, precisará explicitamente dar um namespace ao prefixá-lo g:. Observe também que Exec(), conforme escrito acima, anexará uma nova linha final até a saída de uma linha. Você pode querer adicionar uma chamada à substitute()função para evitar isso.

Consulte também https://stackoverflow.com/questions/2573021/vim-how-to-redirect-ex-command-output-into-current-buffer-or-file/2573054#2573054 para obter mais reclamações redire sobre um link para um comando relacionado.

intuído
fonte
2
Isso funciona muito bem. Adicionei um set pastecomando antes de retornar a saída e um set nopastedepois, para evitar o recuo da escada quando as linhas começarem com espaços em branco. Na verdade, eu queria salvar o valor da opção de colar atual e devolvê-lo, mas não consegui fazê-lo.
Juan Lanus
1
@JuanLanus O set nopastenão deve funcionar depois return output, porque a instrução de retorno é um ponto de saída da função. Coloquei minha solução para esse problema como uma resposta separada nesta página.
Evgeni Sergeev
4
:call append(line('.'), strftime("%c"))

Colocará na próxima linha, e você poderá pressionar J( Shift+ J) para associá-lo à posição atual.

Ou, se você precisar de tudo em um comando, poderá fazer

:call setline(line('.'), getline(line('.')) . strftime("%c"))

ou

:call setline(line('.'), getline(line('.')) . " " . strftime("%c"))

dependendo se você deseja um espaço inserido antes da data ou não.

Mikel
fonte
4

Melhorando a resposta @intuited para evitar o problema com espaços em branco à esquerda e recuo crescente:

"Examples:
":call Exec('buffers')
"This will include the output of :buffers into the current buffer.
"
"Also try:
":call Exec('ls')
":call Exec('autocmd')
"
funct! Exec(command)
    redir =>output
    silent exec a:command
    redir END
    let @o = output
    execute "put o"
    return ''
endfunct!

Isso simplesmente será inserido no local atual do arquivo quando você :call Exec('command')sair do modo normal. Conforme observado no comentário , a =Exec('command')abordagem Ctrl + R original (modo de inserção) com o Exec(..)retorno de uma sequência de caracteres pode ser parcialmente corrigida usando set paste, mas não oferece a oportunidade de colocar o local em set nopastequalquer lugar.

A let @o = outputsintaxe define o registro opara o conteúdo da variável output, conforme explicado aqui: https://stackoverflow.com/a/22738310/1143274

A return ''linha é para que o valor de retorno padrão de 0não seja inserido no buffer.

Evgeni Sergeev
fonte
2

É assim que eu faço. Ele coloca logo após o cursor, porque ele usa p.

" save previous yank
let reg_save = @@

" save your text to the '@' register
let @@ = strftime('%c')
" paste it after the cursor
exec "normal! p"

" restore previous yank
let @@ = reg_save
Juan Ibiapina
fonte