1

計算peを後方に視覚的に選択したい

200 + 3 This is my text -300 +2 + (9*3)
                        |-------------|*

This is text 0,25 + 2.000 + sqrt(15/1.5)
             |-------------------------|*

その理由は、挿入モードで使用するためです。計算を書いた後、(地図を使って)計算を選択し、計算結果をテキストに入れたいと思います。

正規表現が実行する必要があるのは次のとおりです。-
カーソル(*上記の例を参照)から計算の開始
(を含む\/-+*:.,^)まで逆方向に選択します。
-計算はlog/sqrt / abs / round / ceil / floor / sin / cos / tanまたは正または負の数
でのみ開始できます-計算は行の先頭から開始することもできますが、前の行

私はあらゆる方法で試しましたが、正しい正規表現を見つけることができませんでした。
後方検索は前方検索とは異なることに気づきました。

誰かが私を助けることができますか?

編集
忘れてしまった場合は、「=」が存在し、「=」がカーソルの前にある場合、またはカーソルと「=」の間にスペースしかない場合は、「=」も含める必要があります。
他の「=」記号を含めることはできません。

200 + 3 = 203 -300 +2 + (9*3) =
          |-------------------|<SPACES>*

200 + 3 = 203 -300 +2 + (9*3)
          |-----------------|<SPACES>*

*=カーソルがある場所

4

2 に答える 2

3

純粋なvimに近づく正規表現は

\v\c\s*\zs(\s{-}(((sqrt|log|sin|cos|tan|exp)?\(.{-}\))|(-?[0-9,.]+(e-?[0-9]+)?)|([-+*/%^]+)))+(\s*\=?)?\s*

制限があります:部分式(関数の引数を含む)は解析されません。これを行うには、適切な文法パーサーを使用する必要があります。純粋なvim1でこれを行うことはお勧めしません。

オペレーターマッピング

これをテキストオブジェクトのように使用できるようにするには、$MYVIMRCで次のようなものを使用します。

func! DetectExpr(flag)
    let regex = '\v\c\s*\zs(\s{-}(((sqrt|log|sin|cos|tan|exp)?\(.{-}\))|(-?[0-9,.]+(e-?[0-9]+)?)|([-+*/%^]+)))+(\s*\=?)?\s*' 
    return searchpos(regex, a:flag . 'ncW', line('.'))
endf

func! PositionLessThanEqual(a, b)
    "echo 'a: ' . string(a:a)
    "echo 'b: ' . string(a:b)
    if (a:a[0] == a:b[0])
        return (a:a[1] <= a:b[1]) ? 1 : 0
    else
        return (a:a[0] <= a:b[0]) ? 1 : 0
    endif
endf

func! SelectExpr(mustthrow)
    let cpos  = getpos(".")
    let cpos  = [cpos[1], cpos[2]] " use only [lnum,col] elements
    let begin = DetectExpr('b')
    if ( ((begin[0] == 0) && (begin[1] == 0))
      \ || !PositionLessThanEqual(begin, cpos) )
        if (a:mustthrow)
            throw "Cursor not inside a valid expression"
        else
            "echoerr "not satisfied: " . string(begin) . " < " . string(cpos)
        endif
        return 0
    endif
    "echo "satisfied: " . string(begin) . " < " . string(cpos)

    call setpos('.', [0, begin[0], begin[1], 0])
    let end = DetectExpr('e')
    if ( ((end[0] == 0) || (end[1] == 0))
      \ || !PositionLessThanEqual(cpos,  end) )
        call setpos('.', [0, cpos[0], cpos[1], 0])
        if (a:mustthrow)
            throw "Cursor not inside a valid expression"
        else
            "echoerr "not satisfied: " . string(begin) . " < " . string(cpos) . " < " . string(end) 
        endif
        return 0
    endif
    "echo "satisfied: " . string(begin) . " < " . string(cpos) . " < " . string(end) 

    norm! v
    call setpos('.', [0, end[0],   end[1],   0])
    return 1
endf

silent! unmap X
silent! unmap <M-.>

xnoremap <silent>X :<C-u>call SelectExpr(0)<CR>
onoremap <silent>X :<C-u>call SelectExpr(0)<CR>

これで、カーソル位置の前後(または後)の最も近い式を操作できます。

  • vX -[v]通常はe[X]pressionを選択します
  • dX -[d]現在のe[X]pressionを選択
  • yX -[y] ank current e [X] pression
  • "ayX --id。登録するためにa

トリックとして、以下を使用して、OPから正確なアスキーアートに到達します(デモの目的でvirtualeditを使用)。

挿入モードマッピング

チャットへの応答:

" if you want trailing spaces/equal sign to be eaten:
imap <M-.> <C-o>:let @e=""<CR><C-o>"edX<C-r>=substitute(@e, '^\v(.{-})(\s*\=?)?\s*$', '\=string(eval(submatch(1)))', '')<CR>

" but I'm assuming you wanted them preserved:
imap <M-.> <C-o>:let @e=""<CR><C-o>"edX<C-r>=substitute(@e, '^\v(.{-})(\s*\=?\s*)?$', '\=string(eval(submatch(1))) . submatch(2)', '')<CR>

挿入モード中にヒットAlt-.すると、現在の式がその評価に置き換えられます。カーソルは、挿入モードの結果の最後に移動します。

200 + 3 This is my text -300 +2 + (9*3)

This is text 0.25 + 2.000 + sqrt(15/1.5)

Alt-.インサートを3回押し込んでテスト:

203 This is my text -271

This is text 5.412278

楽しみのために:アスキーアート

vXoyoEsc`<jPvXr-r|e.

自分で簡単にテストするには:

:let @q="vXoyo\x1b`<jPvXr-r|e.a*\x1b"
:set virtualedit=all

今、あなたは@qどこでもできます、そしてそれは最も近い表現をアスキー-装飾します:)

200 + 3 = 203 -300 +2 + (9*3) =
|-------|*
          |-------------------|*

200 + 3 = 203 -300 +2 + (9*3)
          |-----------------|*
|-------|*

This is text 0,25 + 2.000 + sqrt(15/1.5)
             |-------------------------|*

1このような解析を行うためにVimのPython統合を使用することを検討してください

于 2012-05-08T23:51:25.740 に答える
1

結局のところ、これは正規表現で達成するのは非常に複雑な作業のように思われるので、何らかの方法でそれを回避できる場合は、そうするようにしてください。

いくつかの例で機能する正規表現を作成しました。試してみて、うまくいくかどうかを確認してください。

^(?:[A-Za-z]|\s)+((?:[^A-Za-z]+)?(?:log|sqrt|abs|round|ceil|floor|sin|cos|tan)[^A-Za-z]+)(?:[A-Za-z]|\s)*$

関心のある部分は、最初に一致するグループに含まれている必要があります。

説明が必要な場合はお知らせください。

編集:

^-行の先頭に一致します

(?:[A-Za-z]|\s)+-文字またはスペースであるすべてのものを1回以上一致させます

次の3つを一致させてキャプチャします
((?:[^A-Za-z]+)?。-文字以外のすべてを一致させます(つまり、ケース番号または演算子)

(?:log|sqrt|abs|round|ceil|floor|sin|cos|tan)-キーワードの1つに一致します

[^A-Za-z]+)-文字以外のすべてに一致します(つまり、ケース番号または演算子)

(?:[A-Za-z]|\s)*-文字またはスペースであるすべてのものに0回以上一致する

$-行の終わりに一致します

于 2012-05-08T11:58:34.753 に答える