如何在Vim中按ALT+J/K实现代码块整体移动

本文介绍了如何在Vim编辑器中通过自定义脚本实现类似VsCode的Alt+J/K快捷键功能,用于代码块的上下移动。作者提供了四个函数,分别处理普通模式、插入模式下的单行移动和可视模式下的多行移动,并给出了相应的键盘映射配置。通过将脚本添加到vimrc文件中,用户可以在Vim中便捷地移动代码行或块,提高编辑效率。
摘要由CSDN通过智能技术生成

如何在Vim中按ALT+J/K实现代码块整体移动

引言

曾经使用过一段时间的VsCode,发现选中需要移动的代码段以后,再按ALT+方向键,就可以实现代码块上下整体移动,感觉这个功能非常实用。
于是想,能不能在Vim利用脚本实现这个快捷功能呢?在网上搜索了一下,发现已经有以下办法,参考移动一行或一段代码,这个办法是vimrc配置文件中添加:

nmap <M-j> mz:m+<cr>`z
nmap <M-k> mz:m-2<cr>`z
vmap <M-j> :m'>+<cr>`<my`>mzgv`yo`z
vmap <M-k> :m'<-2<cr>`>my`<mzgv`yo`z 

但经过实验,发现这个办法在移动多行到顶行或底行后,如果再多按几下Alt+J/K,就会出错,导致代码顺序混乱,那么有没有其他更完美的办法呢?研究了一下vimscript的内置函数setline()和getpos()后,采用了下面的办法可以完美实现。

总体功能描述是这样的:

  • 普通模式和插入模式时,按Alt+J/K实现光标所在行上下移动;
  • 在可视模式时,选中多行,然后按Alt+J/K实现整段代码上下移动。

1. 脚本代码

function! s:moveup_line()
	let cur_pos = getpos('.')	"获取当前光标位置
	"如果已经是最上一行,则直接返回
	if cur_pos[1] == 1
		return
	endif
	let tgt_line = cur_pos[1] - 1	"获得上一行的行号
	let tmp = getline(tgt_line)		"将上一行的内容临时存储
	call setline(tgt_line,getline(cur_pos[1]))	"将上一行的内容替换成当前行
	call setline(cur_pos[1],tmp)	"将当前行的内容替换成上一行
	let cur_pos[1] -= 1	"将当前光标的行号减1,得到目标位置"
	call setpos('.',cur_pos)	"修改当前光标位置
endfunction

function! s:movedown_line()
	let cur_pos = getpos('.')	"获取当前光标位置
	"如果已经是最底一行,则直接返回
	if cur_pos[1] == line('$')
		return
	endif
	let tgt_line = cur_pos[1] + 1	"获得下一行的行号
	let tmp = getline(tgt_line)		"将下一行的内容临时存储
	call setline(tgt_line,getline(cur_pos[1]))	"将下一行的内容替换成当前行
	call setline(cur_pos[1],tmp)	"将当前行的内容替换成下一行
	let cur_pos[1] += 1	"将当前光标的行号+1,得到目标位置"
	call setpos('.',cur_pos)	"修改当前光标位置
endfunction

function! s:moveup_multlines() range
	"获取选择范围的端点的位置信息
	let start_mark = getpos("'<")
	let end_mark = getpos("'>")
	"对代码块的位置进行判断,当已经为最顶层时,直接退出函数
	if start_mark[1] == 1
		return
	endif
	"利用getling()和setline()内置函数实现代码块整体移动
	let save_curpos = getpos('.')
	let buffer_lines = getline(start_mark[1],end_mark[1])
	call add(buffer_lines, getline(start_mark[1] - 1))
	call setline(start_mark[1]-1,buffer_lines)
	"调整选区范围和当前光标的位置
	let start_mark[1] -= 1
	let end_mark[1] -= 1
	let save_curpos[1] -= 1
	call setpos("'<",start_mark)
	call setpos("'>",end_mark)
	call setpos('.',save_curpos)
endfunction

function! s:movedown_multlines() range
	"获取选择范围的端点的位置信息
	let start_mark = getpos("'<")
	let end_mark = getpos("'>")
	"对代码块的位置进行判断,当已经为最底层时,直接退出函数
	if end_mark[1] == line('$')
		return
	endif
	"利用getling()和setline()内置函数实现代码块整体移动
	let save_curpos = getpos('.')
	let buffer_lines = [getline(end_mark[1] + 1)]
	call extend(buffer_lines, getline(start_mark[1],end_mark[1]) )
	call setline(start_mark[1],buffer_lines)
	"调整选区范围和当前光标的位置
	let start_mark[1] += 1
	let end_mark[1] += 1
	let save_curpos[1] += 1
		call setpos("'<",start_mark)
	call setpos("'>",end_mark)
	call setpos('.',save_curpos)
endfunction

2. 键盘映射配置

noremap <silent> <M-k> :call <SID>moveup_line()<CR>
noremap <silent> <M-j> :call <SID>movedown_line()<CR>
inoremap <silent> <M-k> <ESC>:call <SID>moveup_line()<CR>a
inoremap <silent> <M-j> <ESC>:call <SID>movedown_line()<CR>a
vnoremap <silent> <M-k> :call <SID>moveup_multlines()<CR>gv	"后面必须添加‘gv’才可重新进入可视模式
vnoremap <silent> <M-j> :call <SID>movedown_multlines()<CR>gv

3. 使用脚本

啰嗦几句,将上述的脚本代码和键盘配置写到vimrc文件中。
Windows中:vimrc文件在 “C:\users\改成自己的用户名\_vimrc“或“Vim安装目录\_vimrc"
Linux中:~/.vimrc
重启Vim,就可以愉快的使用ALT+J/K实现代码的上下移动了。
如果Alt键映射有问题的,请参考知乎Vim大佬韦易笑的文章
Vim 中正确使用 Alt映射

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值