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>
#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 楼
如果您想对宏和标记有一点乐趣,可以尝试如下操作:首先在包含
a
和a1
< />转到包含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
评论
现在我很好奇-您的用例是什么?您是否在电视季中对字幕进行重命名?@ lago-lito-感谢您的回答!是的,Vim非常通用:)您的表情“眼神分析”使我也想到了滚动绑定两个Vim窗口。
我在使用它时遇到麻烦,如何选择两个连续的块?他们需要相邻吗?
@cbcoutinho是的,他们有:)我不确定您是否可以同时选择它们。在我展示的示例中,我将光标放在(例如)b1上,然后按vip选择整个块,然后选择
@ iago-lito我认为我的问题是我没有映射任何东西,而是试图通过选择块然后在可视模式下执行:'<,'> call Interleave()来手动调用函数。这引起了一堆从头到尾的错误以及E714:列出必需的错误。仔细研究一下映射,我现在看到应该在调用该函数之前按一次