Vimで外部コマンドを使用して、選択した単語や行を変更する方法は?


22

私が他のエディターで有用だと感じたのは、次の機能です。

  • 選択したテキストを取ります
  • 外部コマンドを実行し、選択をそのに渡します stdin
  • 外部コマンドstdoutを使用して、現在の選択をそれに置き換えます。

このようにして、基本的なioを実行できる任意の言語を使用して選択範囲を操作する便利なテキストツールを作成できます。

選択を使用してvimでこれをどのように行うことができますか?...単一の文字、単語、段落など。

(直接コマンドラインで、またはキーバインディングを介して?)


注意

!sort行レベルで動作するなどのコマンド、この質問をしている理由は、選択範囲を操作したいからです。(つまり、x押された場合に削除されるテキスト)。

回答:


17

多くの場合、最も簡単な方法は、ビジュアルモードv(または大文字Vを使用して行全体を選択)を使用し、パイプするテキストを選択することです。

次に入力します:

:!cat

このように、これは何の役に立つこともしません。私がよく使う便利なコマンドは次のとおりです。

:!python -m json.tool

JSONをフォーマットします。

次のように入力することもできます(ビジュアルモードなし)。

:<range>!command

たとえば、ファイル全体の場合:

:%!python -m json.tool

または、現在の行の場合:

:.!python -m json.tool

これで使用する別の本当に便利なツールはsortコマンドです。
コーディポール

4
@CodyPoll Vimの何が問題になってい:sortますか?
マーティントゥルノイ

5
@Carpetsmoker外部のsortコマンドにはさらに多くのオプションがあり、(ロケールなどに応じて)異なる順序を生成します。
デロバート

1
これは、行内の単一の単語を選択する場合は機能しません。(質問は単語レベルの選択について言及しています)
-ideasman42

ideasman42右...私はもともと「線として、この質問を読んだと思う@ または代わりに」行の言葉「の言葉」...ライン上のいずれの場合でも、言葉でこれを行うことは非自明である、UNIXプログラムは仕事、とのVim例外ではありません。私はいくつかの実験を行い、解決策を持っていますが、それはあまりうまくいきません...多分私のアプローチが間違っているので、数日間そのままにして後で戻ってきます。
マーティントゥルノイ

7

これを支援できるexpress.vimというプラグインを作成しました。プラグインは、g=モーション(またはビジュアル選択)でVimScript式を評価できる演算子を定義します。式の入力を求められます。この式ではv:val、モーション(または、再びビジュアル選択)で覆われたテキストのプレースホルダーとして使用できます。

この場合、便利な式はsystem()外部コマンドを実行する関数を使用します。

system('tr a-z A-Z', v:val)

(ここではtr、外部コマンドの簡単な例として使用しました。)

この問題にexpress.vimを使用する方法は、ビジュアルモードでテキストを選択し、次にg=その式を入力してからヒットすることEnterです。

g=system('tr a-z A-Z', v:val)<CR>

私は認めます、それは使いにくいです。(実際、私はこのプラグインを自分で使用することはめったにありません!)外部コマンドを起動するためのショートカットを追加することを検討してい!ます。最終的には更新をここに投稿します。

編集

express.vimを変更して!、で始まる式を外部コマンドとして扱うようにしました。そのため、tr例に固執すると、上記ははるかに簡単になります。ビジュアル選択後、次を入力します。

g=!tr a-z A-Z<CR>

説明:

  1. エクスプレス演算子を呼び出します g=
  2. !tr a-z A-Z式として入力
  3. 押す Enter

4

Vimでフィルターコマンドを探しています。を参照してください:help filter。関連ドキュメントは次のとおりです。

!{motion}{filter}   Filter {motion} text lines through the external
                    program {filter}.
!!{filter}          Filter [count] lines through the external program
                    {filter}.
{Visual}!{filter}   Filter the highlighted lines through the external
                    program {filter} (for {Visual} see |Visual-mode|).
                    {not in Vi}

:{range}![!]{filter} [!][arg]               *:range!*
                    Filter {range} lines through the external program
                   {filter}.  ...[See documentation for details]

したがって、入力5!!sortすると、カーソルから始まる次の5行がソートされます。


単一の単語をフィルタリングすることは可能ですか?(ラインレベルではない)
ideasman42

はい。3番目のオプション(視覚モード)は、強調表示されているもの(単語、部分行、複数行、長方形ブロックなど)に対して機能します。
サミール

1
3番目のオプションは、行全体もフィルタリングします。単一の単語を選択して、たとえばを介してフィルタリングすると、tr [:lower:] [:upper]vimはこの単語だけでなく行全体を大文字にします。
マリアの

0

次の方法で実行できることに注意してください。

  1. 希望するものを視覚的に選択する
  2. s^R=system('tr a-z A-Z', @")[:-2]^M^RCTRL + Rであり、^ MがENTERである場合)

また、選択+置換のようなものでも動作しci"^R=...ます。


vカーソルを押して移動した後)複数行のテキスト選択でこれを実行すると、エラーが発生しますE16: Invalid range\nE16: Invalid range\nE476: Invalid command(Linuxではso trおよびその他の基本的なコマンドが存在します)。
-ideasman42

s挿入モードまたは:sコマンドに入るボタンを押しましたか?
リュックエルミット

疑わないが、どういう意味かわからない、おそらくこの例はこれをキーにバインドする方法を示すことができますか?
ideasman42

sビジュアルモードから直接ヒットしますか、それとも:最初にヒットしますか?:私が書いた一連のキーには関係ありません。マッピングは次のようになりますvnoremap µ s<c-r>=system('tr a-z A-Z', @")[:-2]<cr>
リュックエルミット
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.