1行につき1つの文で動作するようにVimを設定する方法は?


17

現在、多くのプレーンテキスト(および段落内の最小限の書式設定を含むLaTeX)を書いていますが、各文を保持するようにvimをセットアップできたらいいと思います(簡単にするために、テキストは「。」、「!」 、または「?」;これは、VCS diffがより便利になるように、行末で句読点の後にスペースが続き、10進数での改行を避けるためです)。

最低限、gq次からテキストをフォーマットしたいと思います。

He lay flat on the brown, pine-needled floor of the forest, his chin on his
folded arms, and high overhead the wind blew in the tops of the pine trees.
The mountainside sloped gently where he lay; but below it was steep and he
could see the dark of the oiled road winding through the pass. There was a
stream alongside the road and far down the pass he saw a mill beside the
stream and the falling water of the dam, white in the summer sunlight. 

に:

He lay flat on the brown, pine-needled floor of the forest, his chin on his folded arms, and high overhead the wind blew in the tops of the pine trees.
The mountainside sloped gently where he lay; but below it was steep and he could see the dark of the oiled road winding through the pass.
There was a stream alongside the road and far down the pass he saw a mill beside the stream and the falling water of the dam, white in the summer sunlight.

ただし、vimが入力時にこの書式設定を実行する場合は(テキスト幅のリフローの場合と同様)便利です。これは可能ですか?

私の現在の解決策は、で段落を結合してJから実行する:'<,'>s/\. /.\r/gことです。感嘆符や疑問符がほとんどないのでかなり良いですが、gqを少し賢くすることができればはるかに良いでしょう。

回答:


23

'formatexpr'オプション

'formatexpr'オプションを使用してこれを達成できます。ヘルプから:

gq演算子または自動フォーマット用に行範囲をフォーマットするために評価される式(「formatoptions」を参照)。このオプションが空の場合、「formatprg」が使用されます。

'formatexpr'正しく設定するgqと、テキストを使用するときと挿入するときに機能します。

簡単な例

以下に、簡単なVimScript関数と'formatexpr'、ジョブを実行するための対応する値を示します。すべてのエッジケースでテストしたわけではありませんが、単純なテストではうまく機能しました。

function! MyFormatExpr(start, end)
    silent execute a:start.','.a:end.'s/[.!?]\zs /\r/g'
endfunction

set formatexpr=MyFormatExpr(v:lnum,v:lnum+v:count-1)

説明

式は、関数の呼び出しMyFormatExpr()であり、書式設定が適用される開始行と終了行を渡します。これらの行は、自動的に入力される変数v:lnum(フォーマットされる最初の行)およびv:count(フォーマットされる行の数)を使用して計算されます。

MyFormatExpr()機能構築物:substituteの範囲内に渡されたとコマンドを、および(エンド・オブ・文句読点次の空白を置き換える.!または?改行で)( \r)。

注意事項

  • このMyFormatExpr()関数は、先頭のインデントを保持しません。それを修正するには、より洗練されたロジックが必要です。
  • これがバラバラになる他のエッジケースがあるかもしれません。試運転して、必要に応じて調整してください!

ああ、ええ、これは完全に行く方法です、私の答えを無視してください。
スキマ

これはすごい!「次の文に進み、改行を挿入します。範囲の最後に達するまで繰り返します」などのマクロを実行する機能を使用したい)のです。次に、おそらくインデント規則を適用します。しかし、私のVim-fuは弱すぎます。:)
ネイサンロング

これは例えばe.g. blahに分かれてBlah et al. 2018おり、少し面倒です。のようなパターンを使用して、そのようなパターンの一致を解除でき's/\(e\.g\|\<al\)\@<![.!?]\zs /\r/g'ます。最初のグループにパターンを追加して、分割したくない他のことを避けます。それ以外の場合、これは非常に便利です、ありがとう。私はgq前に出会ったことがなくgqip、共著者のテキストエディターがマングルしたテキストのフォーマットに非常に便利です。
naught101

この動作をデフォルトの動作に追加する方法はありますか?私は...文章の最後に分割だけでなく、与えられたテキストの幅で折り返すことができるようにしたい
naught101

1

さて、いくつかのマップとオートコマンドをセットアップできます:

function! AddSentenceMaps()
  imap .<Space> .<CR>
  imap !<Space> !<CR>
  imap ?<Space> ?<CR>
  exec "nmap gq vipJ:s/\\([.!?]\\)\\s\\+/\\1\\r/g<CR>"
endfunction

autocmd Filetype customtxt call AddSentenceMaps()

次に、ファイルタイプをcustomtxtに設定するか、AddSentenceMaps関数を手動で呼び出します。


0

この問題についての考えを追加したいと思います。通常、このような機能が必要になるのは、Vimのデフォルトの動作であるコマンドjkコマンドを使用してコードをナビゲートするときに、折り返された行を飛び越えるためです。折り返された行のナビゲーションには、gj下に移動して上にgk移動します。また、g接頭辞の対応するものに標準jkコマンドを再マップする可能性がありますが、私見ではやり過ぎです。


またはのremapingことを行うためのキー持っているjkするgjgk、あなたがそれをしたいとき;-)
アンソニー

0

再フォーマットに関する特定の質問には答えませんが、「set wrap」と「set linebreak」を組み合わせることで、長い行の編集がはるかに快適になります。これをgjおよびgkと組み合わせて、ラップされた行内をナビゲートします。上矢印と下矢印をそれぞれgjとgkにマッピングして、実際の線と視覚的な線を上下に移動することを選択できるようにします。Home / End to g0 / g $のように賢明です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.