vim - 如何将单行数组文字拆分为多行?

vim - How to Split single line Array literal into multiple lines?

假设我有这个:

[ |"TypeScript", "HTML", "CSS", "SQL", "JavaScript" ]

有什么快速方法可以让我做到这一点:

[ 
  |"TypeScript", 
  "HTML", 
  "CSS", 
  "SQL", 
  "JavaScript" 
]

我真的不关心光标在哪里结束,我只是想高效地切换to/from单行到多行。

我在网上找到的一种解决方案是进行搜索和替换。到目前为止,这对我没有帮助,因为不遵守缩进规则。如果我能找到尊重缩进的搜索和替换技术,我会很乐意制作映射并使用它。到目前为止,我发现的搜索和替换看起来像 '<,'>s/,/,\r/g,并且使用上面的示例,将导致:

[ 
|"TypeScript", 
"HTML", 
"CSS", 
"SQL", 
"JavaScript" 
]

我知道有一种方法可以做到这一点,因为我过去曾 不小心 按过任何组合键并看到了预期的效果,但不知道我不小心按了什么按下。它可能在我的一个插件中,所以我在下面发布了我的插件。

我的插件:

'tpope/vim-commentary'
'tpope/vim-fugitive'
'tpope/vim-rhubarb'
'shumphrey/fugitive-gitlab.vim'
'terryma/vim-multiple-cursors'
'rhysd/committia.vim'
'tommcdo/vim-lion'
'elmcast/elm-vim'
'sheerun/vim-polyglot'
'tmsvg/pear-tree'
'tpope/vim-surround'
'Valloric/YouCompleteMe',
'ctrlpvim/ctrlp.vim',
'scrooloose/nerdtree',
'nathanaelkane/vim-indent-guides'
'fholgado/minibufexpl.vim'
'SirVer/ultisnips'
'honza/vim-snippets'

我也很乐意接触另一个具有所需行为的插件。

谢谢!

嗯,'<,'>s/,/,\r/g 实际上导致:

[ "TypeScript",
 "HTML",
 "CSS",
 "SQL",
 "JavaScript" ]

与您发布的结果相比,与期望的结果相去甚远。

如果我们坚持简单的替换,这里的逗号是无关紧要的。必须替换的是 spaces:

:s/\s/\r/g

这导致:

[
"TypeScript",
"HTML",
"CSS",
"SQL",
"JavaScript"
]

with,光标在].

下一步是重新缩进您刚刚更改的行:

='[

这给了你想要的结果:

[
    "TypeScript",
    "HTML",
    "CSS",
    "SQL",
    "JavaScript"
]

参见 :help =:help '[

这很容易映射到更短的内容:

nnoremap <key> :s/\s/\r/g<CR>='[

但在与您问题中的情况不同甚至略有不同的情况下,它弊大于利。

我们可以做些什么来让它更通用?

首先,我们可以进行视觉选择并将替换限制在该视觉选择中,而不是对整行进行替换:

vi[                   " visually select what's between the brackets
:'<,'>s/\%V\s/\r/g    " substitute spaces contained in the visual
                      " selection with \r

遗憾的是,这不起作用,因为在我们进行替换时,\%V 的边界不会随文本移动。一旦第一个 space 被替换,其余的就会在选择下方一行,并且在可视区域中没有 space 可以替换。无赖。

仍然保持我们的替换简短,我们可以通过两个步骤来解决这种情况:

  1. 将 spaces 替换为不太可能出现在该行其他地方的奇异字符,

  2. \r 替换那个花哨的字符。

    vi[
    :'<,'>s/\%V\s/§/g
    :s/§/\r/g
    ='[
    

这个效果比较好,所以我们可以更改之前的映射:

function! ExpandList()
    silent s/\%V\s/§/g
    silent s/§/\r/g
    silent normal ='[
endfunction
xnoremap <key> :<C-u>call ExpandList()<CR>
  • 我们的普通模式映射变成了视觉模式映射,
  • 我们调用一个函数来完成繁重的工作,而不是使用复杂的 RHS,
  • 该函数处理前面描述的三个步骤而不会弄乱 :help 'hlsearch'
  • 命令静音以提高舒适度。

此时,我们可以通过以下方式解决我们的问题:

  1. 进行视觉选择,
  2. 按上面的映射,

不算太破旧。

请注意,仍有改进空间:

  • 初始模式,\s,不能很好地处理不均匀的间距,
  • 我们可以创建自定义运算符 of/as 以及视觉模式映射。

第一个“问题”可以通过在我们的替换中添加一点 vimscript 来解决:

function! ExpandList()
    silent s/\%V.*\%V/\="\r" . submatch(0)
            \ ->split(',')
            \ ->map({ i, v -> v->trim() })
            \ ->join(",\r") . "\r"/g
    silent normal ='[
endfunction
  • 而不是之前的 two-steps hack,我们在整个视觉选择上使用单个替换,
  • 替换的替换部分是一个表达式,其中...
    • submatch(0)代表整场比赛,
    • split(',') 将逗号上的字符串(再次变得相关!)拆分为列表,
    • map({ i, v -> v->trim() }) 从列表中的每个条目中删除任何白色 space 填充,这样做是为了解决原始文本中可能存在的不均匀性(想想 ["foo","bar" , "baz" ]),
    • join(",\r") 将其全部放回一个字符串中,用逗号和 \r,
    • 分隔
    • 在替换字符串的开头和结尾添加了额外的 \r,以确保括号在它们自己的行上。

参见 :help sub-replace-expression:help split():help map():help trim():help join()

既然已经到了,为什么不处理第二个“问题”呢?

“操作员+运动”模型是 life-changing Vim 功能之一。而不是

select some text and then do something with it

这是我们目前所在的位置,我们

do something with some text

它设法同时做到简洁 表达。

而 Vim 确实让我们可以创建自己的运算符::help map-operator.

根据上面的文档,我们只需要对我们的函数定义做一些小的修改:

function! ExpandList(type, ...)
    silent s/\%V.*\%V/\="\r" . submatch(0)
            \ ->split(',')
            \ ->map({ i, v -> v->trim()})
            \ ->join(",\r") . "\r"/g
    silent normal ='[
endfunction

以及我们的映射:

nnoremap <key> :set opfunc=ExpandList<CR>g@

而且我们有一个非常简洁和惯用的解决方案:我们自己的“扩展列表”运算符:

有一个插件可以做到这一点:splitjoin.vim。 它支持各种文件类型,包括 javascipt 和 JSON.

来自

[ |"TypeScript", "HTML", "CSS", "SQL", "JavaScript" ]

点击gS获得

[ 
  "TypeScript", 
  "HTML", 
  "CSS", 
  "SQL", 
  "JavaScript" 
]

要将其重新合并成一行,请将光标放在第一项上并点击 gJ