Comment insérer le résultat d'une commande dans le texte de vim?

42

Par exemple, :echo strftime(%c)affichera l'heure actuelle en bas, mais comment insérer cette chaîne temporelle dans le texte (juste après le curseur)?

Xzhu
la source
1
Je pense que l'OP signifie "Comment insérer le résultat d'une expression Vim dans le texte?"
Alastair Irvine le
Il est également intéressant de noter qu'il ne s'agit pas de la même question que d' écrire une fonction vim pour insérer un bloc de texte statique , mais certaines des réponses s'appliquent toujours.
Alastair Irvine le
Votre exemple est littéralement mon cas d'utilisation et je vous en félicite.
Joe
Voir aussi la redirection dans un registre: stackoverflow.com/questions/2573021/…
NeilG

Réponses:

49

Vous pouvez utiliser le registre d’expression "=, avec p(ou P) en mode normal ou <C-R>en mode insertion:

En mode normal:
( <C-M>ici signifie Control+ M, ou appuyez simplement sur Enter/ Return)

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

En mode insertion:
( <C-M>a la même signification que ci-dessus, <C-R>signifie Control+ R)

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

Si vous voulez insérer le résultat de la même expression plusieurs fois, vous pouvez les mapper sur les clés de votre .vimrc:
(ici, le <C-M>et <C-R>devrait être tapé littéralement (une séquence de cinq caractères imprimables - Vim les traduira en interne))

:nmap <F2> "=strftime('%c')<C-M>p
:imap <F2> <C-R>=strftime('%c')<C-M>
Chris Johnsen
la source
2
+1 Bien sûr! Le "=registre. : - /
Eelvex le
2
pour obtenir la valeur d'une variable vim (par exemple, sessionoptions): <C-R>=&sessionoptions- il exécute même Wild-mode tab-complete!
Justin M. Keyes
2
: put = strftime ('% c') <CM>
brunch875 Le
En mode insertion, l'utilisation <c-r>=est lente pour une commande qui peut avoir beaucoup de sortie et peut également rompre l'indentation de sorte que le texte de sortie soit illisible. Par exemple, <c-r>=execute('nmap')la sortie sera écrite ligne par ligne, ce qui est très lent.
Jdhao le
22

:r!date +\%c

voir :help :r!

Glenn Jackman
la source
1
dateest une commande externe et !appelle des commandes externes tandis que OP demande des commandes vim.
Eelvex
@eelvex non, il ne l'a pas fait. et le ! est un vim et vi, commande. C'est la méthode canonique. Fonctionne pour beaucoup d'autres choses aussi.
Keith
5
@ Keith: yes !est une commande vi (m) qui appelle des commandes externes . Vous avez peut-être raison, OP ne souhaitant pas afficher uniquement des commandes vim, mais s’il le fait, il ne le !fera pas.
Eelvex
11

Ces commandes vont insérer la sortie de strftime("%c")droite là où se trouve votre curseur:

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

et

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

Il y a d'autres façons de faire ce que vous voulez (comme, par exemple, celles sur la réponse de Mikel ).

Edit : Mieux encore, pour l'insertion sur place, utilisez le =registre décrit par Chris Johnsen.

Eelvex
la source
10

Si vous souhaitez insérer le résultat d'une commande vim (par opposition à la valeur de retour d'un appel de fonction ), vous devez le capturer. Ceci est accompli via la :redircommande, qui vous permet de rediriger l'équivalent de la sortie standard de vim dans une variable, un fichier, un registre ou une autre cible.

:redirest en quelque sorte douloureusement incommode à utiliser; Je voudrais écrire une fonction pour encapsuler sa fonctionnalité d'une manière plus pratique, quelque chose comme

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

Une fois que vous avez déclaré une telle fonction, vous pouvez utiliser le registre d’expression (comme expliqué par Chris Johnsen) pour insérer le résultat d’une commande à la position du curseur. Donc, en mode normal, cliquez i^R=Exec('ls')pour insérer la liste des tampons actuels de vim.

Sachez que la commande s'exécutera dans l'espace de nom de la fonction. Par conséquent, si vous utilisez une variable globale, vous devrez explicitement le nommer en le préfixant avec g:. Notez également que Exec(), comme indiqué ci-dessus, ajoutera une nouvelle ligne de terminaison à la sortie même d'une ligne. Vous voudrez peut-être ajouter un appel à substitute()dans la fonction pour éviter cela.

Voir également https://stackoverflow.com/questions/2573021/vim-how-to-redirect-ex-command-output-into-current-buffer-or-file/2573054#2573054 pour plus d'informations sur le sujet rediret un lien vers une commande associée.

intuitif
la source
2
Cela fonctionne très bien. J'ai ajouté une set pastecommande avant de renvoyer la sortie et un set nopasteaprès pour éviter le retrait de l'escalier lorsque les lignes commencent par des blancs. En fait, je voulais sauvegarder la valeur de l’option coller actuelle et la renvoyer, mais j’ai été incapable de le faire.
Juan Lanus
1
@JuanLanus Le set nopastene devrait pas fonctionner après return output, car l'instruction return est un point de sortie de la fonction. J'ai mis ma solution à ce problème comme une réponse séparée sur cette page.
Evgeni Sergeev
4
:call append(line('.'), strftime("%c"))

Le mettra sur la ligne suivante, puis vous pourrez appuyer sur J( Shift+ J) pour le rejoindre jusqu'à la position actuelle.

Ou si vous avez besoin de tout cela en une seule commande, vous pouvez le faire

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

ou

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

selon que vous souhaitiez ou non insérer un espace avant la date.

Mikel
la source
4

Amélioration de la réponse @intuited pour éviter le problème de l’espacement des blancs et du retrait croissant:

"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!

Cela va simplement insérer à l'emplacement actuel dans le fichier lorsque vous :call Exec('command')quittez le mode normal. Comme indiqué dans le commentaire , l' =Exec('command')approche Ctrl + R d'origine (mode insertion) permettant de Exec(..)renvoyer une chaîne peut être partiellement corrigée à l'aide de set paste, mais n'offre pas la possibilité de placer le caractère set nopasten'importe où.

La let @o = outputsyntaxe définit le registre osur le contenu de la variable output, comme expliqué ici: https://stackoverflow.com/a/22738310/1143274

La return ''ligne est telle que la valeur de retour par défaut de 0ne soit pas insérée dans le tampon.

Evgeni Sergeev
la source
2

C'est comme ça que je le fais. Il le place juste après le curseur car il utilise 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
la source