In Kakoune, is there a way to type something over and over? - vim

In Vim, you can go 30i=<esc> to type 30 = signs. (This is handy for taking notes, becaus I like to put a bunch of equals signs under different section headers.)
Is there a way to do this in Kakoune? A numerical prefix on an insert session only types the content once.

There's some discussion of this topic here, where the most relevant comment seems to be:
Since #4041, we can create overlapping selections with the + command and Alt + + to merge them.
Example – Insert 80 asterisks:
80+i*<esc><a-+>
I can't quite get this to work myself (it does create a line of 80 * characters, but I'm not able to exit whatever mode I've gotten myself into at that point), but I haven't used kak before, so perhaps it will be more obvious to you.

Related

How to quickly navigate function arg lists in vim

I have the following function definition:
def test(these, are=0, args=1):
pass
I want to find a quick and intuitive way to hop between each argument.
For example, pressing w/b is too slow because it will hit the commas, but even worse it is it will hit the =. W/B works great except with that first argument because test(these is a "WORD".
Is there an existing way to navigate this list that works the same for all arguments, or is there a common modification to do this? For example, can I redefine what a WORD is and make the (/) break up a WORD? I can't think of a good example of when I would have a legitimate WORD with a paren right in the middle.
The big complication with argument lists is complex expressions and nested function calls (e.g. foo(1, bar(2, 3), 4)). To handle those, at least some basic parsing is necessary; simple pattern matching (as can be done with built-in commands) won't do.
I personally use a combination of basic Vim commands, tailored to the current situation (i.e. w / W / f{char}), and the following plugins:
sideways has mappings to jump to next / previous arguments, to move arguments around, and corresponding text objects
fieldtrip builds on top of sideways and offers a submode, where individual keypresses can then be used to jump / move
Just try using ft f0 or f1 to see if these jumps can help you.

Is there a better method for find and replace in Vim?

Edit: I moved this over to the Vi and Vim site: https://vi.stackexchange.com/questions/13689/how-to-find-and-replace-in-vim-without-having-to-type-the-original-word
I'd like to optimize my "find and replace" workflow in Vim. It's something I do often, as I'm sure most of you do too. Usually something along the lines of -- copy a block and change the name of a variable in a few places. I know, I know, that probably triggers your "why are you copying and pasting code" reflex, but let's not go down that road... There are plenty of valid use cases :)
I'm well aware of the search and replace commands: :s or :%s but I don't like them. It forces me to type out both the full variable name I'm searching for and what I'm changing it to. Maybe there is a better way fix the the amount of typing with :%s? I often use long descriptive variable names, so that is really a deal breaker for me. I also don't like how typing out a variable name from scratch is typo prone and can consume time and brainpower hunting down typos. I much prefer typing it once, and then copying and pasting to just avoid this entirely if possible.
My current workflow uses some combination of movement/yank/select/search/put to move around the file and replace one by one. It is not great but has the benefit of avoiding typing out full variable names. I might just need to type the first few letters with / or use another movement command (i.e. fx) depending on what's around and then hit ve to select the whole word. I also don't mind that I have to repeat for every instance. I never do a full find replace without confirming each change. But it would be much preferable if I could repeat the replacement action with a single keystroke (which I can't do with this method). each replacement is usually something like n then ve then p (or even worse "0p)
Is there a faster way?
My own workflow is similar to yours:
To start, get the cursor on one instance, possibly with / or by navigation.
Hit * to find the next instance of that word.
Change one instance with cw and then the new variable name.
Then it's fast: n/N to get to the next/previous instance, and . to repeat the last edit.
This workflow gives me the same advantage as yours, in that I can review each case before applying the change, but it's just two keystrokes for each additional change.
Hope this helps.
I like the "visual highlight then edit" approach.
shift + v to highlight the region that you want to modify.
then :s/old/new/r where old is what word you want to replace with new.
r changes the first instance of that word old.
Note* There are options other than r which modify its behavior how you want to replace the word.

Toward Vim moves from conventional moves (<left> <right> <up> <down> <backspace>)

I am not trying to play golf with my editor. I am just trying to improve my editing skills with vim.
Let's consider this piece of assembly that I would like to convert to C. In order to do it methodically, I want to make small changes iteratively line after line.
dm(__abcd_bar_id + axis) = f4;
f1 = dm(_abcd_foo_id + axis);
f5 = f4 - f1;
The job with this example is:
Simplify the first line with abcd_bar_id[axis] = f4
Simplify the second line with f1 = abcd_foo_id[axis]
Replace f1 in the third line with the second line
Remove the second line
These steps are not negotiable. I know I can easily get rid of all my dm(__variable + index) with a regex like the one below but this is off topic.
:%s/dm\s*(\s*_\+\(\w\+\)\s\++\s\+\(\w\+\)\s*)/\1[\2]/g
So, to achieve these changes I traditionally do this:
▶▶▶▶DelDelDelDelDel▶▶▶▶▶▶▶▶▶▶▶▶[DelDelDel▶▶▶▶Right]
▼DeleteDelDel[▶▶▶▶]Del
Home▶▶▶▶RightDelDelDelDel
Shift+End Shift+◀ Ctrl+c
▼End◀◀BackspaceBackspace Ctrl+v
And the result should be this:
abcd_bar_id[axis] = f4;
f5 = f4 - abcd_foo_id[axis];
What saves me is I am quite fast hitting the same key multiple times. However I am sure I can be more productive if I use vi features
vfahd
wh3lxi[wr]
j:%s/dm(_//Enter
f+hv2lxi[Escwr]
$hvF2ay
jf1hhplxxx
Well, this seems to me much more complicated for my brain because a pre-processing bain-time is needed before each keystrokes.
For instance if I want to move to f1 I need to parse with my eyes if there is no other 1 on the way to f1.
I really feel I need years of training to be 'fluent' with vim.
So the questions are:
How a vim guru will treat this example?
Does a vim guru exist?
I definitely don't consider myself vim guru, although I use it on the daily basis. Answering your second question first, probably there's somebody who can be treated as a guru, there are simply so many options and possibilities in vim, that everybody can have their own way of doing things. Moreover, because you can tailor vim to your needs, it's easy to simplify regular tasks, and those configurations may differ a lot. Also people who are considered gurus by me (like, for instance, Derek Wyatt) claim that have still much to learn about vim, so it can definitely take years to become one.
But don't be discouraged, it takes only some practise to start thinking vim-way, and your editing tasks will become much easier :)
Back to your example. First of all, I'd edit the first line with slightly less keystrokes:
dta
f)r]
bdTd
i[
The difference isn't huge in terms of number of keystrokes, but it illustrates different approach. It allows, in my opinion, much less pre-processing, which is the problem you highlighted. I divided those keystrokes into sections to show you my thought process:
delete till a
find ) and replace it with ]
back one word and delete Till (backwards) d
insert [
I don't have to think much, when I apply those changes. You might think that this is counter-intuitive, that I jumped to ) character first, but it was much easier for me to spot closing bracket than count words or
hit h or l multiple times. Of course you might know the keystrokes but when you edit something you don't always remember all of them. This comes with practise and forcing yourself to use some of them (like t/T)
to put them firmly under your fingers. Also, print a cheat-sheet trying to make use of every key, until you'll learn it by heart. It won't take long ;)
As William already suggested in the comment, I'd also think about macro here. It's a powerful and easy-to-use tool, which can really automate your changes.
I already know how to edit first line. In your example, I know that in the second step I'll be doing the same thing, but in slightly different location, so instead of editing first line, I instantly record a macro, but I have to make it universal
for easier application. So I think about putting my cursor in proper location first, before making any changes. My macro would look like this:
qq
0fd dta f)r] bdTd i[
q
Notice, that I added 3 keystrokes at the beginning (not counting qq, which starts recording macro to q register). That might look redundant in the first line, but it ensures proper location of the cursor before making any changes.
That way I can easily apply this macro in the second line with #q
Now, you have to replace this f1 in the third line. You're still in the second line with your cursor, so you just yank with:
0fay$
and then paste it to the third line:
j$bPlD
Using macros mith look like a redundant thing when you edit just 3 lines, but when you get used to making changes in a vim way, you'll really feel you're taking advantage of it's power.
When it comes to remembering recorded macros it's not that hard, you have to have the proper attitude. First of all, you record your macros to registers, so typing :registers will show you also your macros. Secondly, you can edit them,
by pasting specific register, altering it and then saving to the same register. And then you can play it with #[register_letter]. And finally, don't get attached to specific macros. Save one or two, use them to make multiple changes at
once and forget about them. And then record another one under the same letter. For example, if you realize that you have to make some repetitive change across the file, use qq, because it's fast and intuitive. After making changes you rarely
need to play the same macro over again, because whole buffer is already in the right state. But if you know, that you'll need it, record next macro under another letter. If you'll get comfortable making changes intuitively vim way, so that
they can easily be repeted, you'll find that's much easier to record another macro than trying to remember under which letter you recorded previous one.
I hope that this answer will convince you, that you don't need years of training to get fluent, but of course it won't happen overnight ;)

How can I join (Shift+J) the next N words to current line, instead of the entire line?

Sometimes when doing things like reformatting a block comment in code, I find I need to move words up one line. In the below example say I want to move the word 'hopefully' to the first line. Usually I use Shift+J to join the entire line, move my cursor to after the word 'hopefully' and then press Enter to move the remainder of the line back down.
/* Line 1 of some large comment block,
hopefully it contains well written documentation. I'd
now like 'hopefully' to be on the first line.
*/
Even though it doesn't seem like much, the sequence of commands I'm currently doing gets tedious if a lot of lines need this sort of change. Is there a variation of the Join command that can only do it for the first N words in the next line? Something like "2wJ" to join the first two words of the next line would be great.
The Bad News
I'm not sure something like what you suggest exists, although it definitely could - Vim surprises me every day. I'm sure someone on SO knows.
The Good News
There's a better way to achieve what you want! Or, what I think you want. You can tell Vim to perform a formatting operation on a given region of text. All you have to do is set textwidth to the maximum width you'd like, then use gq{motion} to format the text that {motion} moves over. For your example:
/* Line 1 of some large comment block,
hopefully it contains well written documentation. I'd
now like 'hopefully' to be on the first line.
*/
You would simply set a reasonable textwidth – here it looks like you're going for about 50 – and then format the comment. Put your cursor on the first /, and
:set textwidth=50
gq%
The Catch
But wait, you say, that didn't work!
Whoops. You're right. What appears to have happened here is that Vim doesn't understand this format. When I followed my own instructions, I saw this, though your mileage may vary:
/* Line 1 of some large comment block,
hopefully it contains well written
documentation. I'd now like 'hopefully' to be on
the first line.
*/
That doesn't look right, and it isn't. However, if I reformat your block comment to something that Vim recognizes (this is how I write my block comments anyways), like so:
/*
* Line 1 of some large comment block,
* hopefully it contains well written documentation. I'd
* now like 'hopefully' to be on the first line.
*/
and then I gq% (with textwidth still 50) I get:
/*
* Line 1 of some large comment block, hopefully
* it contains well written documentation. I'd now
* like 'hopefully' to be on the first line.
*/
That seems like it worked. The word "now" was moved from the third line to the second, too, but I'd argue that that was a good decision on Vim's part. One more note: if you don't like those leading *s, Vim will also do a good job with this format:
/*
Line 1 of some large comment block,
hopefully it contains well written documentation. I'd
now like 'hopefully' to be on the first line.
*/
When I gq% this, I get:
/*
Line 1 of some large comment block, hopefully
it contains well written documentation. I'd now
like 'hopefully' to be on the first line.
*/
A little funny, but it makes sense. Looks more like a paragraph to me. Hopefully something in here is useful.
Edit:
As progo handily mentioned in another answer, you can use gqap everywhere I've used gq% above. Thanks!
How about letting vim handle the formatting of your comment blocks. gqap does one paragraph. If it doesn't do what you want out of the box, check out :help 'fo (format options) and especially :help 'fo-table. For instance, setting :set fo+=j might help with those C blocks (remove comment leader automatically when joining lines.)
There is no such thing built-in in vim.
think about 2wJ, vim will think you want to move two words forwardly, and then Join.
You could either do it in your old way: J2elr<cr> or create a mapping, receive the number of words you want to join as parameter, to make it easier:
nnoremap <expr> <leader>jw 'J' . nr2char(getchar()) . 'elr<CR>'
so with this mapping, if you press <leader>jw, vim waits for a further input key, which is the number of words you want to "join". however this is not a perfect solution, because:
it won't work if you want to join more than 9 words. the mapping expects single char.
it could do something completely unexpected, for example, if you press d, the two words would be removed.
if you want to make a better solution, you could write a function and make a mapping to call that. if it is worth to do.
I prefer to join and cut manually.

altering Vim's text input behavior

[Edit: after reading comments I realize that the Surround plugin is adequate for my needs after all, so I'll leave this question for purely academic purposes to gain a better understanding of vimscript's inner workings]
I'd like to make adding/deleting tags, quotes, braces, and other symmetrical text structures easier to do in Vim, and I find the surround.vim plugin a little too quirky and specialized for my needs.
What I really need is more generally a "mirrored" input mode and "mirrored" deletion mode, whereby I could visually select a block of text, then type onto or delete from both ends of the selection at once. As an example workflow, I'd like to:
select the word hello
hit some keystroke combo to enter "mirror mode"
type "
my text now says "hello"
In this example I only typed one character at each end, but it's important that in step three I could have typed many characters, not just one, for instance I should be able to type <b> to produce <b>hello<b> (I still would need to manually add the / in the closing tag, which I'm OK doing).
So is this even possible in Vim? Could someone provide a broad outline of functions that would be involved in the solution? Specifically, I don't know how to intercept text as it's being inserted and then alter the location where it appears so that it's tacked onto the beginning and ending of the selection block instead of the cursor location. And ditto for deletion.
Well, the behavior you describe is exactly what Surround does:
select the word hello
hit S
type "
my text now says "hello"
The difference with what you ask is the "live updating" or "live mirroring" which I have no idea how to do. You could probably take a look at SnipMate or UltiSnips for that part.

Resources