2012-10-09 72 views
2

簡而言之,寫了一些功能來保存輸入我試圖設置一個vmap [ping],這將允許我選擇我輸入的內容,並將此選項傳遞給一個函數(因爲在命令行上鍵入函數調用,鍵入參數(帶引號)和轉義反斜槓等......抵消通過調用函數節省的大部分時間)Vim vmap,發送選定的文本作爲參數功能

對於(一個簡單的)示例,假設我有以下功能

func Test(iStr) 
if a:iStr[0] =~ [a-zA-z] 
    echo "hello" 
else 
    echo "hello world" 
endif 
endfunc 

我希望能夠可視化選擇一些文本,然後用一些按鍵映射,F2說,它會調用測試(ISTR)與選擇作爲參數iStr

我相信,與更多的工作(即一些方法來指定我所選擇的應該是內部測試()),以下

vmap <F2> :call Test() 

是我後。事情是我已經嘗試了一些變體(猜測加上一些有趣的推理:help map),我沒有得到任何有用的東西。更新,我一直在使用一個輔助函數的Test2()只

call Test(<C-W>) 

爲它的身體試圖...我總覺得我需要我的光標(以某種方式)下搶字的保持,那麼我做了 - 因爲我可以從內部的Test2


傳遞到測試(......)至於功能我要打電話,以下(但不完全)函數(和輔助功能)的實際例子允許我轉換表格的形式,比方說,

f_k^{(j)}g 

f_1^{(j)}g, f_2^{(j)}g, \dots, f_{n-1}^{(j)}g, f_n^{(j)}g 

在我想要一個程序方面

a) type the repeated term in vim 
b) visually select it 
c) hit some mapping key that will call SumOrSequence(iExpression, iIndex) 
d) provide "k" as a parameter 
e) press enter 
f) see the change made by SumOrSequence(...) 

爲SumOrSequence(...)的代碼如下:

func SumOrSequence(iExpression, iIndex) 
"need to check validity of these - maybe set a default 
let default = Interrogate("do with defaults? yes [y] (2,1,n,0,\",\"), yes but specify last term [d[a-Z]], no [n]") 
if default == "y" 
    let leftTerms = 2 
    let rightTerms = 1 
    let lastTermIndex = "n" 
    let firstTermIndex = 0 
    let operator = "," 
    let dotType = "\\dots" 
elseif default =~ 'd[a-zA-Z]' 
    let leftTerms = 2 
    let rightTerms = 1 
    let lastTermIndex = default[1] 
    let firstTermIndex = 0 
    let operator = Interrogate("what separates terms? add [+], subtract [-], times [*], comma [,], ampersand [&]?") 
    let dotType = "\\cdots" 
else "so n or anything else 
    let leftTerms = InterrogateNumber("how many terms before dots? ") 
    let rightTerms = InterrogateNumber("how many terms after dots? ") 
    let lastTermIndex = Interrogate("what is last term index?") 
    let firstTermIndex = Interrogate("what is first term index?") 
    let operator = Interrogate("what separates terms? add [+], subtract [-], times [*], comma [,], ampersand [&]?") "need to check only any of these provided 
    let dotType = "\\cdots" 
endif 
if operator == "," 
    let dotType = "\\dots" 
endif 
if operator == "*" 
    let operator = "\\times" 
endif 
let leftCount = 0 
let oExpression = "" 
while leftCount < leftTerms 
    if leftCount > 0 
     let oExpression .= operator . " " 
    endif 
    let oExpression .= ReplaceIndex(a:iExpression, a:iIndex, leftCount,1) 
    let leftCount += 1 
endwhile 
let oExpression .= operator . " " . dotType . " " 
let rightCount = rightTerms-1 
while rightCount > 0 
    "here we are going to be counting backwards from some number denoting number of terms - may need to know if we actually have a number! 
    echo "decrement: " . HandleDecrement(lastTermIndex, rightCount) 
    let oExpression .= operator . " " . ReplaceIndex(a:iExpression, a:iIndex, HandleDecrement(lastTermIndex, rightCount),1) 
    let rightCount -= 1 
endwhile 
let oExpression .= operator . " " . ReplaceIndex(a:iExpression, a:iIndex, lastTermIndex,0) 
echo oExpression 
endfunc 

func ReplaceIndex(iExpression, iIndex, iReplacement, iInsertBraces) 
"the game we play here is to search for iIndex in such form that it is not part of any other string 
"We should expect this to be the case if the character to the left or right of the index is not in [A-z] (or just to the right if a greek char) 
let oExpression = "" 
let strEndPosition = strlen(a:iExpression) - 1 
let currPosition = 0 
let indexLen = strlen(a:iIndex) 
while currPosition <= strEndPosition 
    let indexCounter = 0 
    let foundIndex = 1 
    while indexCounter < indexLen 
     if a:iExpression[currPosition + indexCounter] == a:iIndex[indexCounter] 
      if a:iExpression[currPosition + indexLen] =~ '[a-zA-Z]' 
       let foundIndex = 0 
       let indexCounter = indexLen 
      elseif a:iExpression[currPosition -1] =~ '[a-zA-Z]' && a:iExpression[currPosition] != "\\" 
       let foundIndex = 0 
       let indexCounter = indexLen 
      else 
       let indexCounter+=1 
      endif 
     else 
      let indexCounter = indexLen 
      let foundIndex = 0 
     endif 
    endwhile 
    if foundIndex == 0 
     let oExpression .= a:iExpression[currPosition] 
     let currPosition+=1 
    else 
     if a:iInsertBraces == 1 
      let oExpression .= "{" . a:iReplacement . "}" 
     else 
      let oExpression .= a:iReplacement 
     endif 
     let currPosition+=indexLen 
    endif 
endwhile 
    echo "oExpression: " . oExpression 
return oExpression 
endfunc 

func HandleIncrement(iExpression, iIncrement) 
"and what about negative numbers for iExpression!??? not handling these yet :[ 
let oExpression = "" 
if !(a:iExpression[0] =~ '[0-9]') || a:iExpression < 10 && strlen(a:iExpression) > 1 
    let oExpression = a:iExpression . " + " . a:iIncrement 
else 
    let oExpression = a:iExpression + a:iIncrement 
endif 
echo oExpression 
return oExpression 
endfunc 

func HandleDecrement(iExpression, iIncrement) 
"TODO and what about negative numbers for iExpression!??? not handling these yet :[ 
let oExpression = "" 
if !(a:iExpression[0] =~ '[0-9]') || a:iExpression < 10 && strlen(a:iExpression) > 1 
    let oExpression = a:iExpression . " - " . a:iIncrement 
else 
    let oExpression = a:iExpression - a:iIncrement 
endif 
echo oExpression 
return oExpression 
endfunc 


func Interrogate(iQuestion) 
    call inputsave() 
    let answer = input(a:iQuestion) 
    call inputrestore() 
    return answer 
endfunc 

func InterrogateNumber(iQuestion) 
    call inputsave() 
    let answer = input(a:iQuestion) 
    call inputrestore() 
    "TODO what if negative number?? 
    if !(answer[0] =~ '[0-9]') 
     let answer = InterrogateNumber(a:iQuestion . " you didn't enter a numerical value ") 
    endif 
    return answer 
endfunc 

至於映射位,我知道看起來我沒有做太多的工作,但假設我有更多的東西在挖掘我自己找到答案,任何人都可以幫忙嗎?


更新。好吧,我有事情,在一個笨拙的方式排序的工作,也就是說,如果我定義以下helperfunction:

func SumOrSequenceHelper() 
    let oIndex = Interrogate("index variable? ") 
    "go to last thing visually selected (I think!), yank it (putting it in the " register), then fetch it via oParam. Then pass this off to SumOrSequence 
    execute "normal! gvy" 
    let oExpression = getreg('"') 
    call SumOrSequence(oExpression, oIndex) 
endfunc 

vnoremap <F6> :call SumOrSequenceHelper() 

那麼一切都很好,我可以做一個執行命令來替換我與我的選擇從SumOrSequence獲得(...)

將是任何改善,但爲這一個解決所有意圖和目的感激:]

回答

1

你可以使用一個輔助函數是這樣的:

func! GetSelectedText() 
    normal gv"xy 
    let result = getreg("x") 
    normal gv 
    return result 
endfunc 

vnoremap <F6> :call MyFunc(GetSelectedText())<cr> 

還有:com -range,它可以註冊一個對選擇進行操作的自定義命令,但界面是面向行的。

+0

您的解決方案比我的雨衣...感謝的! (我無法投票這一個尚未)如此確定我怎麼會使用com -range的想法,但看看com的幫助和嘗試:com我看到該範圍不是一個定義的命令 – HexedAgain

+0

有一個例子一個範圍命令在這裏: http://www.adp-gmbh.ch/vim/user_commands.html(在底部) – zah

+0

這是偉大的 - 我只知道到目前爲止的縮寫和映射;通過(簡短)命令(易於輸入參數(無引號))執行正是我想要的! – HexedAgain

1

使用選擇寄存器來調用與視覺選擇的任何功能。

vnoremap <F6> :call Test(@*)<CR> 

如果你只是想光標在普通模式下,你可以使用這個,這猛拉到選擇寄存器下搶字保存,則使用的值。 (你可以抽出任意命名寄存器來代替,例如在a寄存器與"ay@a

noremap <S-F6> "*yaw:call Test(@*)<CR> 

通過這些不與你的測試功能的工作方式,而只是調用它不似乎也有效?

:call Test("fred") 
Error detected while processing function Test: 
line 1: 
E121: Undefined variable: a 
E15: Invalid expression: a:iStr[0] =~ [a-zA-z] 

他們用這個測試功能工作:

function Test(iStr) 
    echo a:iStr 
endfunction 
+0

感謝您的建議 - 我知道我的問題的答案可能很簡單,我只是不知道語法!至於測試功能,我忘了在[a-zA-Z]上鍵入單引號 – HexedAgain

相關問題