Vim:在一个垂直对齐的引号的文本块周围创建一个C字符串文字?

时间:2010-06-30 18:31:41

标签: vim

我想在Vim中创建一个宏或脚本来执行以下操作:

  1. 用双引号
  2. 包装一段文字
  3. 转义文本中出现的任何引号
  4. 在垂直对齐的右侧有引号
  5. 例如:

    <html>
    <head></head>
    <body>
    <h1>High Score Server</h1>
    <table>
    ROWS
    </table>
    </body>
    </html>
    

    会变成:

    "<html>                    "
    "<head></head>             "
    "<body>                    "
    "<h1>High Score Server</h1>"
    "<table>                   "
    "ROWS                      "
    "</table>                  "
    "</body>                   "
    "</html>                   ";
    

    我可以通过宏来实现这一点,但是没有右侧引号的垂直对齐。任何人都可以帮我这个吗?

7 个答案:

答案 0 :(得分:5)

我要做什么:

使用“环绕”和“对齐”插件:

1)将光标放在第一行(0,0)上,键入<C-V>)$s" 2)然后<S-V>):Align "<Enter>

没有插件的另一种解决方案:

1)设置虚拟模式

:set ve=all

2)<C-V>进行逐块选择,光标位于0,0

3)向下翻到文本底部,然后Shift-I,输入"Esc。这应该在引号之前。

4)现在进入左端(因为ve = all,你可以去没有文字的地方) 5)<C-V>,向下到底,输入r"

这很难解释,但很容易做和重现。在许多情况下也很有用。

答案 1 :(得分:2)

function Enquote()
    let [startline, endline]=sort([line("'<"), line("'>")])
    let lines=getline(startline, endline)
    let lengths=map(copy(lines), 'len(split(v:val, ''\zs''))')
    let maxlen=max(lengths)
    call map(lines, '''"''.v:val.repeat(" ", maxlen-lengths[v:key]).''"''')
    return setline(startline, lines)
endfunction

说明:

line("'<")line("'>")获取上次视觉选择的开头和结尾的行号。

sort([...])对此行号进行排序,因为您可能已经开始从所选内容中选择行。

let [a, b]=[c, d]是并行分配:sort将生成两个项目的排序列表,其中第一个项目小于或等于第二个项目。显然,较小的是第一个选定的行。

len(split(v:val, '\zs'))是一个支持unicode的高级strlen()

max(list)找到最大值。明显。

因此,map(copy(lines), 'len(split(v:val, ''\zs''))')将此strlen应用于列表中的所有项目。 copy()是必需的,因为我们不希望修改列表。

map(lines, '''"''.v:val.repeat(" ", maxlen-lengths[v:key]).''"''')以您需要的方式修改线条。我从printf切换到repeat因为printf没有正确处理多字节字符(通过«正确»我的意思是«¥»是一个字符长,而printf认为它长两个字节)。

setlines(linenumber, listoflines)实际上修改了缓冲区。

答案 2 :(得分:1)

利用unix程序“par”来做到这一点可能很好地解决了你的问题。有一个Vimcast显示如何在http://vimcasts.org/episodes/formatting-text-with-par/

将其集成到vim中

答案 3 :(得分:0)

是否可以在vim脚本中的行列表上进行两次传递?然后你可以做这样的事情(伪代码):

let N = length of longest line
for each line L:
    insert a " character at the beginning
    append N - len(L) spaces
    append a " character

答案 4 :(得分:0)

我得到的最好的是3遍正则表达式。

在可视模式下选择块,然后使用:

:'<,'>s#^#"#
:'<,'>s#$#                                                #
:'<,'>s#\(.\{28\}\).*#\1"

28是你最长线的长度。

答案 5 :(得分:0)

一定要注意以前的答案,让你的vim-fu成型。或者安装/修改/ poke这个插件的作者:

http://www.vim.org/scripts/script.php?script_id=4727

从插件页面:

  

此脚本将C ++文件中的多行文本转换为多行   字符串文字,转义引号和制表符。它也有   反向转换,取消一些字符。它不是   现在已经完成,但如果有需要,它将在某一天完成。

如果您需要进行更改,请使用源代码存储库:

https://bitbucket.org/dsign/stringliteral.vim

答案 6 :(得分:-1)

两遍:

let l = max(map(getline("'<", "'>"), 'strwidth(v:val)'))
'<,'>s/.*/\=('"'.submatch(0).repeat(' ', l-strwidth(submatch(0)) )).'"'