我想将光标精确地放在我想要的位置。例如(
[x]
是光标位置):Lorem ipsum dolor sit amet[1], consectetur adipiscing elit,
sed do eiusmod tempor incididunt ut labore et dolore magna[2]
aliqua.
在Sublime Text中,我通常会放置第一个光标,然后使用箭头键转到下一个位置并放入第二个。
VIM中是否存在类似内容?
使用此插件或其他插件。
编辑
在发表评论后,尝试在
\section[My first section in this book]{My first section in this book}
文件中写入.tex
时,我对此感兴趣。我的第一个反应是编写
\section[]{}
,然后放置两个游标以便在[]
和{}
内写入相同的内容。 其他示例是在几个不同的变量名称后添加
_someStuff
。例如,将其:variable1 = 2
my_variable2 = 12
var3 = 14
变成这个:
variable1_someStuff = 2
my_variable2_someStuff = 12
var3_someStuff = 14
使用多个光标,我可以选择一个列游标,然后转到单词的末尾,然后插入,依此类推。但是我想我很容易选择准确的游标位置。
#1 楼
使用多个光标不是Vimmer的事情正如我在评论中所说的,使用多个光标(甚至带有插件)并不是真正的“遵循Vim方式”,我完全理解这很有吸引力对于那些来自Sublime-Text的人,但是您经常可以找到替代方案,这些替代方案至少与Vim内置功能等效。
当然,找到这些替代解决方案并不总是那么容易,有时会花费一些时间,但是随着Vim的使用,这会变得更加容易,并且您会发现随着时间的流逝,多个游标对您似乎完全没有用处。
太酷了,但是我怎么能找到另一种方法呢?
没有统一的答案,因为这在很大程度上取决于您要执行的操作,我会只需尝试一下就可以尝试一下:
dot命令
.
Dot命令可能是Vim中功能最强大的工具之一。 ,它只是使我们能够重复上一次更改。我无法比Drew
Neil在他的实用Vim中解释得更好。我
,每个Vimmer都应该考虑阅读这本书。
该命令的优点是最后的更改可以是对字符,行或行进行操作。整个文件。例如,更改可以由
进入插入模式的那一刻和回到正常模式的那一刻来定界。
考虑到这一点,很容易做你想做的事情使用多光标:
首先让我们设置环境:让我们按照您的建议进行编写
\section[]{}
然后进行可重复的更改
光标现在位于
}
上,按F[
返回[
字符。然后使用
i
进入插入模式并键入My first section in this book
并返回返回到带有
ESC
的正常模式:\section[My first section in this book]{}
神奇的部分到了:
让我们键入
f{
,将光标放在{
字符上并点击.
重复最后的更改:
\section[My first section in this book]{My first section in this book}
dot命令的所有挑战在于学习如何进行可重复的更改:
它会伴随咯咯作响Vim的基本知识是了解如何以可重复的方式进行您的更改。
例如,要在行尾插入分号,您最好使用
A;
而不是$a;
。为什么?因为
A;
创建了一个原子动作,所以当您在另一行上使用.
时,在行中的任何地方都不会在末尾插入半冒号。 当使用
$a;
时,您将更改分为两部分$a
和;
的插入,因此,如果使用
.
,它将在光标的当前位置插入分号。
注意Vim中的魔术公式是
n.
。一个非常酷的工作流程是:使用
/pattern
搜索要编辑的位置进行可重复的编辑
使用
n
进行编辑移至下一个要编辑的地方使用
.
重复编辑重复最后两个步骤:您是世界之王(或至少是
编辑)
<宏是Vim中另一个极为重要的工具,因为它可以记录
一系列击键并重复进行,就像再次键入一样。
/>
,我将以第二个用例为例:
variable1 = 2
my_variable2 = 12
var3 = 14
再次重要的是要学习如何使宏有效(我将在后面举一个反例):
将光标放在单词
variable1
上,并开始使用qq
录制宏。这意味着“开始将我以后所有的击键记录在名为q
的寄存器中”。开始进行编辑键入:
0
走在第一个单词的开头e
走在第一个单词的结尾a
在光标之后追加.someStuff
在想要的文本后面追加<Esc>
停止插入j
转到下一行/>
q
停止录制宏您将获得:
variable1.someStuff = 2
my_variable2 = 12
var3 = 14
现在,您可以使用宏重复进行编辑。当您在正确的位置进行编辑时,只需使用
@q
执行宏即可。因为我们要执行两次,所以可以使用2@q
,您将获得以下结果:variable1.someStuff = 2
my_variable2.someStuff = 12
var3.someStuff = 14
注意1如您所知,在开始时使用
0ea
宏非常重要确实,如果您在记录宏之前将光标放在第一个单词的末尾并再次执行它,结果将是
:
variable1.someStuff = 2
my_variable2 = 12.someStuff
var3 = 14.someStuff
作为您的光标,文本将在换行后插入到光标的位置
(在这种情况下,即行的结尾)
注意2宏是极其强大,当您习惯使用它们时,甚至可以创建递归
宏。在这里,您的宏可能是:
`0ea.someStuff<Esc>j@q`
最后的
@q
会自己调用该宏,而不是使用2@q
;您只需要使用@q
就可以完成所有工作。可视块
这里有另一个技巧直接应用于您的用例,但
同时编辑大量行可能非常有用。让我们获得这个
CSS代码摘录:
li.one a{ background-image: url('/images/sprite.png'); }
li.two a{ background-image: url('/images/sprite.png'); }
li.three a{ background-image: url('/images/sprite.png'); }
如果将精灵从
images
移到components
会怎样?可以将光标放在
i
的images
上,然后按<C-v>
。 将启动可视块模式,该模式允许选择块。现在您可以输入
t/
选择要更改的单词,然后选择
2j
选择所有出现的单词。之后,您只需键入
c
来更改单词,然后键入components
。退出插入模式后,您将看到:
li.one a{ background-image: url('/components/sprite.png'); }
li.two a{ background-image: url('/components/sprite.png'); }
li.three a{ background-image: url('/components/sprite.png'); }
全局命令
全局命令是一种工具,它允许在匹配模式的行上应用ex模式命令
,再一次,这是在不同位置应用相同更改而无需多个光标的好方法。
语法如下:
:[range] g / pattern / command
有关
[range]
参数的更多详细信息,请参见:h :range
。我不会在这里详述,我只想提醒一下,%
代表整个文件,'<,'>
1,5代表文件的第1至5行。
此参数定义将由global命令处理的行。如果未指定
范围,则默认情况下,全局命令将使用
%
。[pattern]参数是用于搜索的搜索模式
发动机。由于它集成了搜索历史记录,因此您可以将该字段保留为空白,然后
全局命令将使用搜索历史记录中的最后一个搜索模式。
最后,[command]参数是ex命令就像您可能习惯的那样。
现在,全局命令的行为非常简单:
遍历[range]参数中定义的所有行
如果当前行与定义的模式匹配,则应用命令
由于[command]参数是ex命令,因此您可以做很多事情。让我们
使用下面的不太有趣的伪代码,其中包含许多
调试消息:
var myList = null
var i = 0
myList = new List()
echo "List instantiated"
for (i=0; i<10; i++)
myList.Add(i)
echo i . " added to the list"
echo "end of for loop"
现在,假设您确保此代码有效,并且您要删除以下无用的
echo
语句:您可以在整个文件上应用全局命令,因此必须在命令前加上
%
(或因为%
是默认范围而没有任何内容)。您知道要删除的行匹配模式
echo
要删除这些行,因此必须使用命令
:delete
,也可以将其缩写为
d
,因此您只需要请使用以下功能:
:%global/echo/delete
也可以缩写为
:g/echo/d
请注意,
%
消失了, global
缩写为g
,delete
缩写为d
。您可能会想到结果是:var myList = null
var i = 0
myList = new List()
for (i=0; i<10; i++)
myList.Add(i)
注意1一个重要的观点花了我一些时间认识到
normal
命令是一个ex命令,这意味着您可以将其与global命令一起使用。这可能非常强大:假设我要复制所有包含回声的行,不需要宏,甚至不需要魔术公式
n.
。我可以简单地使用:g/echo/normal YP
瞧,
var myList = null
var i = 0
myList = new List()
echo "List instantiated"
echo "List instantiated"
for (i=0; i<10; i++)
myList.Add(i)
echo i . " added to the list"
echo i . " added to the list"
echo "end of for loop"
echo "end of for loop"
注意2“嘿,如果我想在与
特定模式不匹配的行上使用我的命令吗?”
global
具有相反的命令vglobal
缩写为v
,它与global
完全一样,除了该命令是应用于与[pattern]参数不匹配的行。这样,如果我们应用
:v/echo/d
在前面的示例中,我们得到:
echo "List instantiated"
echo i . " added to the list"
echo "end of for loop"
delete
命令具有应用于不包含echo
的行。在此,我希望这些提示能为您提供摆脱如何使用
多光标插件的想法。以Vim方式显示Vim ;-)
您可以想象这些示例非常简单,并且仅用于
证明当您按照Vim的方式使用时,您实际上很少需要几个光标。我的建议是,当您遇到认为有用的情况时,将其写下来,然后花一些时间来找到更好的解决方案。 99%的时间您最终会找到一种更快/更有效的方法
。
我还会再重复一遍,但我真的鼓励您阅读
Drew Neil撰写的实用Vim
,因为这本书不是关于“如何在Vim中做到这一点”,而是关于“如何
学习以Vim的方式思考”,这将使您能够建立您自己的
很好地解决了您将来的问题。
PS特别感谢@Alex Stragies的编辑工作和所做的更正
长帖子。
评论
非常完整的答案。实际上,我确实知道所有这些命令,但从未想过像那样使用它们……我想我需要更多的练习。但是,我必须说,有时'vim-way'所花的时间比仅使用某些插件要长(例如,使用我提到的插件可以更快地完成CSS示例),有时所需的时间要短得多(实际上,如果使用得当,vim通常比任何文本编辑器都快。
–tomasyany
15年8月13日在22:18
顺便说一句,我想你的答案已经很完整了。我会接受的,但是如果您想添加更多详细信息,请这样做,我们很高兴阅读它们。
–tomasyany
15年8月13日在22:20
@tomasyany:确实确实有时使用“ vim方式”可能看起来更长(我无法计算出创建工作宏所花的时间比手动完成更改要花费多少时间),但随着实践的发展,它最终会变得更快。我使用Vim仅仅一年了,我(非常)还不是专家,但是我可以感觉到,随着我的练习,我的编辑工作会不断提高。
–statox♦
15年8月14日在9:22
可能还应该提到gn文本对象。它解决了多个游标的一些用例。使用/搜索,然后搜索dgn或cgn,然后使用。重复搜索。
–贾斯汀·凯斯(Justin M. Keyes)
15年8月15日在1:17
@Justin我对gn并不是很熟悉,我会尝试一下并在之后添加它。谢谢你的抬头!
–statox♦
15年8月15日在7:52
#2 楼
给我的给定用例听起来想知道.
键盘命令(重复最后的编辑命令)转到第一位,按
i
,插入文本,<ESC>
移动到位置2,按
.
(点)==>插入相同的文本要在此处下移一行并再次插入(在插入连续行时),请按
<ALT>-j.
您为我创建的tex示例通过以下方式解决:
I\section[]{}<ESC>hhiMy first Sec...<ESC>lll.
评论
这是一个非常不错的解决方案。我完全知道。关键命令,但从未想过以这种方式使用它。我同意这是一个好方法。但是您的答案实际上并没有涉及真正的问题,因此我认为接受它是不合适的。
–tomasyany
15年8月13日在21:15
好吧,您的问题(在添加了所需的用例之后)使我想起“我非常喜欢我的剪刀,想用它们拧紧螺丝。告诉我如何做”。我指着您想起螺丝刀的妙用;)(我补充说,因为我不知道如何在注释中格式化)
– Alex Stragies
15年8月13日在21:24
#3 楼
更多Vim方式。第一个任务:
\section[foobar baz]{foobar baz}
工作流程:
\section[]{}
hh
ifoobar baz<Esc>
$.
>第二项任务:
variable1 = 2
my_variable2 = 12
var3 = 14
命令:
3:norm ea_somestuff
结果:
variable1_somestuff = 2
my_variable2_somestuff = 12
var3_somestuff = 14
评论
您可能会看到:github.com/terryma/vim-multiple-cursors/issues/86和vim.org/scripts/script.php?script_id=4467我认为要问的一个重要问题是为什么要这么做?你想做什么?使用多个游标并不是真正的“遵循Vim方式”,可能存在另一种使用内置功能来完成所需功能的方法,至少同样有效。
@statox。参见编辑。我举了两个例子。我可以使用vim-multiple-cursors插件完成第二个任务,但至少不能以简单的方式完成第一个任务。
@ Nobe4。谢谢,第二个脚本成功了。