38 votes

Exécuter une commande shell sans filtrage depuis Vim

Je veux sélectionner un bloc de texte (par exemple, V% ) et utiliser le texte comme entrée d'une commande shell (par exemple, wc o pbcopy ) - mais je Ne le fais pas. Je ne veux pas modifier le tampon actuel - je veux juste voir la sortie de la commande (s'il y en a une) puis continuer l'édition sans aucune modification.

Dactylographie V%!wc se traduit par :'<,'>!wc et commute le bloc de texte pour la sortie de la fonction wc commandement.

Comment transmettre un morceau de texte à une commande shell arbitraire sans affecter le tampon actuel ?

0 votes

Si vous souhaitez transférer votre sélection de texte dans le presse-papiers du système d'exploitation (pbcopy sous OS X), vous pouvez simplement utiliser le tampon * yank. En mode visuel, tapez : "*y

92voto

pixelearth Points 2948

Sélectionnez votre bloc de texte, puis tapez ces touches :w !sh

Le tout devrait ressembler à ça :

:'<,'>w !sh

C'est ça. Il ne m'a fallu que 8 ans pour l'apprendre : )

note : taper : après avoir sélectionné du texte produit :'<,'> une plage indiquant le début et la fin de la sélection.

Mise à jour 2016 : Il s'agit en réalité d'une seule utilisation du générique :

'<,'>w !cli_command

Ce qui vous permet essentiellement d'"envoyer" des parties arbitraires de votre fichier à des commandes externes et de voir les résultats dans une fenêtre vi temporaire sans altérer votre tampon. D'autres exemples utiles seraient :

'<,'>w !wc
'<,'>w !to_file my_file

Je trouve honnêtement qu'il est plus utile de modifier le tampon actuel. Cette variété est simplement :

'<,'>!wc
'<,'>!to_file my_file

2 votes

Génial, soigné et construit --- tout ce qu'on peut espérer.

1 votes

Documenté à :help :write_c pour les curieux.

4voto

DrAl Points 29528

Une possibilité serait d'utiliser system() dans une commande personnalisée, quelque chose comme ça :

command! -range -nargs=1 SendToCommand <line1>,<line2>call SendToCommand(<q-args>) 

function! SendToCommand(UserCommand) range
    " Get a list of lines containing the selected range
    let SelectedLines = getline(a:firstline,a:lastline)
    " Convert to a single string suitable for passing to the command
    let ScriptInput = join(SelectedLines, "\n") . "\n"
    " Run the command
    let result = system(a:UserCommand, ScriptInput)
    " Echo the result (could just do "echo system(....)")
    echo result
endfunction

Appelez cela avec (par exemple) :

:'<,'>SendToCommand wc -w

Notez que si vous appuyez sur V%: le :'<,'> sera saisie pour vous.

:help command
:help command-range
:help command-nargs
:help q-args
:help function
:help system()
:help function-range

1 votes

J'ai d'abord pensé que cela avait l'air vraiment lourd et verbeux, mais après l'avoir ajouté dans mon .vimrc et avoir ajouté un mappage, c'est parfait : vmap # :SendToCommand<Space> Maintenant je peux juste faire V%# et taper le nom de la commande. C'est exactement ce que je voulais.

1 votes

Content que ça vous plaise ! Votre mappage semble être une bonne idée (j'ai tendance à utiliser des noms de commandes longs et verbeux et à compter sur la complétion par tabulation pour m'épargner l'effort). Envisagez de le mettre dans ~/.vim/plugin/sendtocommand.vim o ~/.vim/autoload/sendtocommand.vim (ce dernier nécessitera quelques modifications) pour aider à garder votre vimrc gérable.

1voto

Niels Bom Points 1955

Mise à jour : ma réponse est absurde.

La réponse de @pixelearth est bonne, mais j'avais un peu de mal à comprendre ce qu'il faisait exactement, alors j'ai écrit ce qui suit. Cette séquence de commandes vous permet d'exécuter wc -l sur votre sélection visuelle. wc -l compte simplement le nombre de lignes qui lui sont passées.

  1. Dans Vim, passez en mode visuel en utilisant v
  2. Sélectionnez quelques lignes en descendant : jjjj
  3. Type : que Vim va traduire a :'<,'>
  4. Type w !wc -l votre ligne de commande complète devrait maintenant être :'<,'>w !wc -l
  5. Appuyez sur la touche Entrée pour obtenir le résultat de votre commande (dans cet exemple, il s'agit de 4).
  6. Appuyez sur Enter pour poursuivre l'édition

Je ne comprends pas ce qui se passe exactement aux étapes 3 et 4, mais je sais que cela fonctionne.

0 votes

Ce n'est pas du tout la même chose. Ce que vous faites est de taper manuellement la commande !wc -l, ce qui est fait ci-dessus est que la commande que vous voulez exécuter EST DÉJÀ DANS LE FICHIER VIM. Donc si vous aviez wc -l sur une ligne à part, vous pourriez utiliser la méthode ci-dessus pour envoyer CETTE commande à !sh (le shell).

0 votes

@pixelearth Vous avez raison, je n'ai simplement pas compris la question initiale.

1 votes

En réexaminant la question après plusieurs années, je constate que, même si ce que vous faites n'est pas exactement la même chose, c'est quand même très cool. En fait, vous utilisez le texte sélectionné comme entrée pour la commande suivante. Tout aussi utile.

0voto

Amber Points 159296

Je sais que ce n'est pas la solution idéale, mais si tout le reste échoue, vous pouvez toujours simplement appuyer sur u après avoir exécuté la commande pour annuler le changement de tampon.

0 votes

Bien sûr, c'est ce que je fais actuellement - j'espère juste que je rate quelque chose. Je suppose que s'il n'y a pas un moyen intégré de le faire, un petit <code>cmap</code> pourrait faire l'affaire - quelqu'un en a un tout prêt ?

0 votes

Après avoir jeté un coup d'œil sur meta-SO, en utilisant backticks around text est apparemment censé permettre le formatage du code dans les commentaires.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X