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

Aar*_*van 2 vim

假设我有这个:

[ |"TypeScript", "HTML", "CSS", "SQL", "JavaScript" ]
Run Code Online (Sandbox Code Playgroud)

有没有一种快速的方法可以让我做到这一点:

[ 
  |"TypeScript", 
  "HTML", 
  "CSS", 
  "SQL", 
  "JavaScript" 
]
Run Code Online (Sandbox Code Playgroud)

我并不真正关心光标最终在哪里,我只是想有效地切换到单行到多行。

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

[ 
|"TypeScript", 
"HTML", 
"CSS", 
"SQL", 
"JavaScript" 
]
Run Code Online (Sandbox Code Playgroud)

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

我的插件:

'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'
Run Code Online (Sandbox Code Playgroud)

我也很高兴能够接触到另一个具有所需行为的插件。

谢谢!

rom*_*inl 5

嗯,\'<,\'>s/,/,\\r/g实际上结果是:

\n
[ "TypeScript",\n "HTML",\n "CSS",\n "SQL",\n "JavaScript" ]\n
Run Code Online (Sandbox Code Playgroud)\n

这比您发布的结果更远离期望的结果。

\n

如果我们坚持简单的替换,那么逗号在这里就无关紧要了。这是必须替换的空格:

\n
:s/\\s/\\r/g\n
Run Code Online (Sandbox Code Playgroud)\n

结果是:

\n
[\n"TypeScript",\n"HTML",\n"CSS",\n"SQL",\n"JavaScript"\n]\n
Run Code Online (Sandbox Code Playgroud)\n

时,光标位于 上]

\n

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

\n
=\'[\n
Run Code Online (Sandbox Code Playgroud)\n

这会给你想要的结果:

\n
[\n    "TypeScript",\n    "HTML",\n    "CSS",\n    "SQL",\n    "JavaScript"\n]\n
Run Code Online (Sandbox Code Playgroud)\n

参见:help =:help \'[

\n

这很容易映射到更短的东西:

\n
nnoremap <key> :s/\\s/\\r/g<CR>=\'[\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n

我们可以做些什么来使其更通用?

\n

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

\n
vi[                   " visually select what\'s between the brackets\n:\'<,\'>s/\\%V\\s/\\r/g    " substitute spaces contained in the visual\n                      " selection with \\r\n
Run Code Online (Sandbox Code Playgroud)\n

遗憾的是,这不起作用,因为\\%V当我们进行替换时, 的边界不会随文本移动。一旦第一个空格被替换,其余空格就会在所选内容下方一行,并且视觉区域中没有剩余空间可供替换。真糟糕。

\n

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

\n
    \n
  1. 用不太可能出现在行中其他地方的奇异字符替换空格,

    \n
  2. \n
  3. 将那个奇特的字符替换为\\r.

    \n
    vi[\n:\'<,\'>s/\\%V\\s/\xc2\xa7/g\n:s/\xc2\xa7/\\r/g\n=\'[\n
    Run Code Online (Sandbox Code Playgroud)\n
  4. \n
\n

这相对有效,因此我们可以更改之前的映射:

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

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

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

这还不算太寒酸。

\n

请注意,仍有改进的空间:

\n
    \n
  • 初始模式,\\s不能很好地处理不均匀的间距,
  • \n
  • 我们可以制作一个自定义运算符来代替/以及视觉模式映射。
  • \n
\n

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

\n
function! ExpandList()\n    silent s/\\%V.*\\%V/\\="\\r" . submatch(0)\n            \\ ->split(\',\')\n            \\ ->map({ i, v -> v->trim() })\n            \\ ->join(",\\r") . "\\r"/g\n    silent normal =\'[\nendfunction\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  • 我们没有使用之前的两步破解,而是对整个视觉选择使用单一替换,
  • \n
  • 替换的替换部分是一个表达式,其中\xe2\x80\xa6\n
      \n
    • submatch(0)代表整场比赛,
    • \n
    • split(\',\')将逗号上的字符串(再次变得相关!)分割成一个列表,
    • \n
    • map({ i, v -> v->trim() })从列表中的每个条目中删除任何空白填充,这样做是为了解决原始文本中可能存在的不均匀性(认为["foo","bar" , "baz" ]),
    • \n
    • join(",\\r")将其全部放回单个字符串中,并用逗号分隔\\r,分隔
    • \n
    • 额外的\\r在替换字符串的开头和结尾添加
    • \n
    \n
  • \n
\n

请参阅:help sub-replace-expression、、、、和:help split():help map():help trim():help join()

\n

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

\n

“操作符+动作”模型是改变生活的 Vim 功能之一。代替

\n
\n

选择一些文本,然后对其执行某些操作

\n
\n

这就是我们目前所处的位置,我们

\n
\n

用一些文本做某事

\n
\n

它设法既简洁同时

\n

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

\n

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

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

以及我们的映射:

\n
nnoremap <key> :set opfunc=ExpandList<CR>g@\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n

自定义运算符

\n