我一直致力于在Vim中实现一个简单的实用程序,它允许我在视觉上选择一些文本,计算结果,然后用结果替换原始文本。但是,我遇到了一个问题:似乎某种方式将substitute
与printf
结合使用会改变我的视觉选择。
这是代码:
vnoremap <leader>C y<ESC>:call setreg( '"', printf( '%f', eval( substitute( substitute( getreg( '"' ), '\n', '', 'g' ), '\(\d\+\.\=\d*\)\s*\^\s*\(\d\+\.\=\d*\)', 'pow( \1, \2 )', 'g' ) ) ), getregtype( '"' ) )<CR>gvp
现在,它的位很长,但我正在努力解决这个问题。基本上,它采用视觉选择的文本,猛拉它,然后设置"
寄存器以包含评估的响应,然后重新选择最后的视觉选择,然后粘贴它,用结果替换视觉选择。
举个例子,假设我有这一行:a = 32 - 2
。视觉选择32 - 2
,然后点击<leader>C
。该行最终为a = 30.0000002 - 2
。
问题出在最后一次替换的最后一位:'\(\d\+\.\=\d*\)\s*\^\s*\(\d\+\.\=\d*\)'
bit没有最后\.\=\d*
,代码运行正常(假设指数/索引不是浮点数)。如果没有printf
,它就可以正常工作,因为没有浮点数。使用printf
和最后一位,只替换第一个字符,但输出正确。
我需要使用printf
,因为这允许我使用浮点数。我还需要做替换,因为它允许我使用指数。
发生了什么,我该如何解决?它没有做,因为只需在printf中使用该代码就可以改变视觉区域。我只是遗漏了一些非常明显的东西吗?
答案 0 :(得分:1)
显然,未命名的寄存器不会在模式更改后存活。但是,根据手册:
写入“”寄存器写入寄存器“0。
事实上,将gvp
更改为gv"0p
会使您的宏工作。但是,我建议使用更安全的版本:
function! s:expr_eval()
let old_expr = @"
let reg_type = getregtype('"')
let expr = substitute(old_expr, '\n', '', 'g')
let expr = substitute(expr, '\v(\d+%(\.\d*)?)\s*\^\s*(\d+%(\.\d*)?)', 'pow(\1, \2)', 'g')
try
let expr = printf('%f', eval(expr))
catch
let expr = old_expr
endtry
call setreg('"', expr, reg_type)
endfunction
vnoremap <silent> <leader>C y:<C-u>call <SID>expr_eval()<CR>gv"0p