是否有通过交织线合并两个文本块的专用方法,例如从以下传递:

a1
a2
a3
a4
  b1
  b2
  b3
  b4


到:

a1
  b1
a2
  b2
a3
  b3
a4
  b4


用几个命令?

编辑:我真的很喜欢佐藤桂的解决方案,这是我的实现方式:

function! Interleave()
    " retrieve last selected area position and size
    let start = line(".")
    execute "normal! gvo\<esc>"
    let end = line(".")
    let [start, end] = sort([start, end], "n")
    let size = (end - start + 1) / 2
    " and interleave!
    for i in range(size - 1)
        execute (start + size + i). 'm' .(start + 2 * i)
    endfor
endfunction

" Select your two contiguous, same-sized blocks, and use it to Interleave ;)
vnoremap <pickYourMap> <esc>:call Interleave()<CR>


评论

现在我很好奇-您的用例是什么?您是否在电视季中对字幕进行重命名?

@ lago-lito-感谢您的回答!是的,Vim非常通用:)您的表情“眼神分析”使我也想到了滚动绑定两个Vim窗口。

我在使用它时遇到麻烦,如何选择两个连续的块?他们需要相邻吗?

@cbcoutinho是的,他们有:)我不确定您是否可以同时选择它们。在我展示的示例中,我将光标放在(例如)b1上,然后按vip选择整个块,然后选择。它对您不利吗?

@ iago-lito我认为我的问题是我没有映射任何东西,而是试图通过选择块然后在可视模式下执行:'<,'> call Interleave()来手动调用函数。这引起了一堆从头到尾的错误以及E714:列出必需的错误。仔细研究一下映射,我现在看到应该在调用该函数之前按一次,该函数可以按预期工作

#1 楼

据我所知,没有专用的方法可以执行此操作,但是可以,可以使用以下命令来完成此操作: :call Interleave(5, 8, 1)。第一个参数是要移动的第一行,第二个参数是最后一行,第三个参数是要移动它们的位置。您可能想打开行号以查看正在执行的操作(:set number)。

这假定块不重叠。请参阅:help :move:help range()以了解该函数的工作原理。

可能有更好的方法来拾取两个块。有一个浮动的插件应该可以交换两个块。我不记得插件的名称,但是作者(也许是著名的Dr. Chip?)比我投入了更多的心思来寻找接口。 :)

评论


甜!我只需要两个参数,因为两个块是连续的并且具有相同的大小:start和size。借助自选功能可以从选择中检索这些值,这将是完美的。我在做这个工作。 :)

–iago-lito'考虑离开
15年8月29日在18:10

有趣的交叉链接? ;)

–iago-lito'考虑离开
16-2-24在9:02

#2 楼

这是另一种选择:

:g/^a/+4t .
:+,+5d 


首先将下面4行的行复制到当前行(:h :t)之后,然后删除连续的b行(:h :d) br />
这条命令甚至更好:到当前行下方。

评论


我在第二个命令中得到了“ E16:无效范围”。我尝试使用。+,$ d代替,并且有效(就像。+,。+ 4d一样)。

– Peter Lewerin
15年8月29日在21:50

不知道为什么会这样

–克里斯蒂安·布拉班德(Christian Brabandt)
15年8月30日在7:15

不,不是。阅读:h:range,您始终可以使用直接编号代替正则表达式搜索

–克里斯蒂安·布拉班德(Christian Brabandt)
15年8月30日在18:37

@ iago-lito第二个技巧始终有效,但是您需要将/ ^ \ s * b更改为另一个:range。例如:选择第一个程序段,执行'<,'> g / ^ /'> + 1m。

–dedowsdi
19年5月13日在3:35



@ iago-lito本质上与Christian的答案相同。如果您在视觉上选择第一个块,则不会进行硬编码,'> + 1标记第二个块的开始。

–dedowsdi
19年5月13日在7:45

#3 楼

如果您想对宏和标记有一点乐趣,可以尝试如下操作:


首先在包含aa1 < />转到包含ma的行,并用b1进行标记
开始用mb在所需的寄存器(这里是寄存器q)中记录宏
在以下宏中插入以下内容:qq
停止使用ddmb'apjma'b录制宏
根据需要用q播放它多次,其中X@q是播放它的时间。

要详细说明该宏: >
dd mb 'a p j ma 'b
 |  |  | | |    |
 |  |  | | |    go back to line marked `b`
 |  |  | | |
 |  |  | | move of one line and replace the mark `a`
 |  |  | insert the deleted line under the line marked `a`
 |  |  go to line marked `a`
 |  mark the future line to move with `b`
 delete the line to move


编辑正如lago-lito在评论中提到的那样,此方法将覆盖标记和缓冲区。


对于标记,我认为这是一个真正的问题:我很少在缓冲区中使用所有26个标记,而且我认为大多数时候都会找到2个空闲标记。
对于缓冲区,可以将其保存在一个临时变量中:在录制之前宏使用X保存寄存器,一旦完成操作,请使用:let saveReg=getreg('"')将寄存器恢复到之前的状态。最佳:我认为Christan的回答是最好的,应该接受,因为它不会弄乱缓冲区和标记,不会迫使用户创建函数并显示全局命令的功能。

评论


有趣。不幸的是,这会覆盖我可能正在使用的标记和寄存器的内容;)

–iago-lito'考虑离开
15年8月30日在15:11

@ lago-lito:确实覆盖标记和缓冲区。对于标记,我从未在缓冲区中使用所有26个标记,因此我认为这不是真正的问题。对于缓冲区,这可能是一个更大的问题,我认为您经常可以找到未使用的缓冲区,或者如果确实找不到,请使用临时变量以及函数getreg()和setreg()来保存缓冲区。但我同意这不是最佳解决方案:-)

–statox♦
15年8月30日在18:22

#4 楼

我刚刚看到了另一个类似的问题,解决方案包括:

跳转到中间加一个: br />
Mj


评论


有趣的是:)请注意,这会交错整个文件,而不仅仅是选定的段落!

–iago-lito'考虑离开
18/09/21在9:04