That's because you're doing it wrong! Hjkl are fallbacks to move a few characters, it has only a minor advantage over arrow keys are is probably not worth the effort of re-learning how to move a cursor.
I would not recommend learning that as your first vim move. Just stick to cursors for moving individual characters at first.
The real magic is in going back/forward words (b/w/e) without needing to reach for control at the edge of your keyboard, jumping to an exact point you need (f/F/t/T) if it has a unique character (like the ')' within 'if (uid == 0)'), moving between paragraphs ({/}), going to matching parens/braces/brackets (%), going to the next/previous word under the cursor (*/#), etc. This is what will make you faster, not the switching from arrows to hjkl.
And that's just cursor moving. For editing, things like S to replace the line or C to replace the rest of the line after the cursor, di) to cut the part within parentheses and p (paste) it elsewhere, repeating the previous action with dot, searching with n/N instead of a function key, all those things are what makes vim nicer as a text editor. One of the least-appreciated things that I also use a lot is filename completion with ctrl+xf (sysadmins, take note!).
But I don't recommend learning everything at once. If you know how to go into insert mode (i), how to leave insert mode (escape), and how to save a file, then you basically have the equivalent of a text editor, especially with mouse mode enabled (the default nowadays, I think). From there, learn one command every week. Takes 1 minute per week and you'll know more vim than 99% of developers within a year.
Or go a bit faster and try to learn one command every morning, or every second day perhaps. Try it for one month and see if you want to go back to standard editors. Odds are, you'll want the best of both worlds, start looking for vim key binding plugins in IDEs, and end up like me with missing vim after all because those keybind plugins are usually not so great ^^'
> mostly using Java IDEs, and lately some vscode (for go, typescript, rust)
Do you need intelligent autocompletion, debugging, and other such IDE features?
There are plugins that, so far as I know, can do a lot of what an IDE can do, but I have never bothered to set them up myself. It all seems hacky and niche, but others can tell you more if this is the type of things you're looking for. I am not a real developer myself but I write a lot of scripts (things small enough to keep a full understanding in my head) as well as documents (reports for pentests) in vim, and for that it is perfect.
what is this barbaric default binding, s/S shall be bound to the indispensable vim-surround! ;)
built in text objects are already nice combined with modifiers (e.g cw, ciw, caw, cW, ciW, caW), ramping it up a little bit with argument (ca, cia, daa), surround (cs"', cs([, ci", ca", viWS<tag>, dst), and indent (vii>) is stupidly powerful.
Once the [verb][modifier]{object} pattern clicked for me my mind was hopelessly infected and I could not ever go back to non-vim editors.
To me that's the risk of learning vim: if it starts clicking for you (which it may not, as pure personal fit, not elitism) then it becomes excruciatingly annoying to edit non trivial amounts of text and not have vim.
>it becomes excruciatingly annoying to edit non trivial amounts of text and not have vim.
I can relate to this. Writing code without Vim feels like punching in a dream. Make sure you're working in an environment where you're allowed to use such tools.. I'm currently not and it stinks.
Most people I know (including many linux users) regard me as a vim pro relative to them, and I still have barely an idea what most of these do. Or what surround is. Might want to explain a little for the rest of us mortals ;)
Sure. Here's a quick rundown of how it works (in my mind at least, might not be 100% technically exact):
Vim normal mode commands have something like this structure, a bit like a sentence:
[verb][modifier]{object}
There can be a bit of implicit in this sentence, e.g [verb] and [modifier] are optional. {object} is mandatory, final, and "commits" the normal mode command without having to press something such as Return.
Let's look at some basic movements:
w => word (== [A-Za-z0-9_]), forward lookup
W => Word (== \S i.e not whitespace), forward lookup
b => word, backward lookup
B => Word, backward lookup
Without [verb] it's like the implicit [verb] of the sentence is "move", so typing just these indeed results in pure movement:
w => move (from cursor position to) one word forward
W => move (from cursor position to) one Word forward
b => move (from cursor position to) one word backward
B => move (from cursor position to) one Word backward
With a count modifier
2w => move (from cursor position to) two words forward
2W => move (from cursor position to) two Words forward
2b => move (from cursor position to) two words backward
2B => move (from cursor position to) two Words backward
With [verb], things are applied to the object. Let's look at some verbs:
d => delete
c => change (== "delete + enter insert mode", exit with ESC)
A repeated verb is a shortcut to mean "whole line"
dd => delete line
cc => replace line
d2d => delete two lines
Back to the sentence. It's a bit like the movement implicitly defines a "text range" object: "from current cursor position to movement target". So:
dw => delete (from cursor position to) one word forward
dW => delete (from cursor position to) one Word forward
db => delete (from cursor position to) word backward
dB => delete (from cursor position to) one Word backward
The interesting part about c instead of doing d+i is that it is going to be "atomic" (end these with ESC to exit insert mode):
cwfoo => replace (from cursor position to) one word forward with "foo"
cWfoo => replace (from cursor position to) one Word forward with "foo"
cbfoo => replace (from cursor position to) word backward with "foo"
cBfoo => replace (from cursor position to) one Word backward with "foo"
Which is really cool because now you can move to another position and press . (dot) and it will repeat the last normal mode command, dynamically/semantically, like a mini macro. Combine that with search, and incremental search/apply is n to go to the next occurence and . to apply, or n again when I want to skip. Also, u for undo goes back from atomic change to atomic change.
Similar to wWbB there's "find" and "find until" (n is an optional count, defaults to 1):
[n]f{char} => find nth occurence of character, forward lookup, after character
[n]F{char} => find nth occurence of character, backward lookup, after character
[n]t{char} => find nth occurence of character, forward lookup, before character
[n]T{char} => find nth occurence of character, backward lookup, before character
So e.g some examples, combining two sentences:
F,dt) => move back to previous comma, then delete (from cursor position to) until next parens
t)dF, => move to last parens, then delete (from cursor position to) up to previous comma
These are useful to e.g delete arguments! e.g with the cursor somewhere inside parens here:
foo(42, 123, 345)
Note that depending on what the initial cursor position is within parentheses the result will differ. Also note that this is good for simple arguments, we'll address more complex ones later.
Words can receive a "inside" or "around" modifier:
iw => one word, up to word boundaries
iW => one Word, up to Word boundaries
aw => one word, up to word boundaries, plus trailing whitespace
aW => one word, up to word boundaries, plus trailing whitespace
What's cool about this is: you don't have to position at word beginning, and it can handle whitespace as you see fit.
So given this text:
foo bar baz
Doing diw with the cursor inside bar would delete "bar" but leave you with two spaces while doing daw would delete "bar " thus leaving you with only one.
ds" => delete surrounding quotes
cs"' => change double quotes to single quotes
cs(( => change closest parens around to parens with one space inside
cs() => change closest parens around to parens without space inside
cs2() => change 2nd level outwards parens to parens without space inside
dst => delete surrounding tag
cst<foo> => change surrounding tag to be "<foo>" (closed by "</foo>")
None of these affect the enclosed text, only the surrounding items.
Visual mode is entered by pressing v (or V for visual line mode, or ^v for visual block mode) then moving around, and the object will be the highlighted area. Since {object} is what ends the vim normal mode sentence things are a bit different in visual mode:
viWS( => surround Word with parens + inner space
viWS<foo> => surround Word with <foo> and </foo>
Usage of visual mode and visual line mode is greatly improved with % (move to matching delimiter), especially with vim-endwise (which makes % work on more per-filetype things such as tags in HTML, and def/end in Ruby)
Other nice plugins are argtextobj:
dia => delete argument but not comma, properly handling parens and commas as argument delimiters as well as nesting
daa => delete argument + one comma (leading comma, unless first arg then trailing comma) + surrounding whitespace
and vim-indent-object (cool in general, but stellar on yaml or python):
cii => replace indented block, leaving out surrounding lines
cai => replace indented block + surrounding lines + one line above
caI => replace indented block + surrounding lines + one line above + one line below
vii> => visual line select indented block, then increase indent
vii< => visual line select indented block, then increase indent
viigc => visual line select indented block, then comment (using vim-commentary)
vii:norm i# => visual line select indented block, then prepend line with # (pure vim)
via= => fix indentation
viagq => hard wrap lines
I often do the "comment" one using visual block mode (^v) and moving around with % then do I# (insert # at line beginning) when I can rely on delimiters. Same for indent increase/decrease and fix, only with visual line mode.
Wrapping one's head around this vim interactive "sentence" dialect of normal mode is not that hard but usually badly explained (I hope I did a slightly less bad job at that!), but it's key to unlock some of vim's insanely composable superpowers.
The nice thing is that by understanding how these work together, I can replicate the behaviour of these plugins in a plugin-less vim (at a cost of a bit more thinking+typing), so I save time when I have the plugins but gracefully degrade to something still more efficient than painstakingly moving my cursor around and deleting/changing every text character by hand.
Next step: macros!
qa => start recording macro in register "a" (can be about any other key)
q => end macro recording
@a => play macro in register "a"
@@ => play last macro again (such a timesaver)
And a little bonus:
"ap => paste macro from register "a" (which you can then edit!)
"ayy => yank line back in register "a"
All of this combined is ridiculously powerful, to the point I can barely hold nervous laughter at some hilariously complex refactoring I did.
> There are plugins that, so far as I know, can do a lot of what an IDE can do
I want to add that the converse is true too: there are a lot of plugins (for IDEs) that do a lot of what Vim can do. I personally use the neovim integration for VSCode and it's really nice.
Have you used the real vim a lot in the past? More than a few days of trying it out, I mean.
Probably you replied around the same time as I edited in:
>> Try it for one month and see if you want to go back to standard editors. Odds are, you'll want the best of both worlds, start looking for vim key binding plugins in IDEs, and end up like me with missing vim after all because those keybind plugins are usually not so great
It might just be me who got too used to vim bindings by now so that the suboptimal implementations are annoying. Or maybe the vim bindings in VSCode are particularly good, I haven't tried those. (I've tried them in real visual studio in ~2015 and it was so bad that I ended up using plain visual studio instead, then went back to plain vim on linux after my C# internship.)
The VSCode neovim plugin is really good because under the hood it's just using neovim to manage the buffer, so everything that works on Neovim works on VSCode. It's true that some plugins are suboptimal but the VSCode one (and the one for Sublime when I used it) are really good.
That's because you're doing it wrong! Hjkl are fallbacks to move a few characters, it has only a minor advantage over arrow keys are is probably not worth the effort of re-learning how to move a cursor.
I would not recommend learning that as your first vim move. Just stick to cursors for moving individual characters at first.
The real magic is in going back/forward words (b/w/e) without needing to reach for control at the edge of your keyboard, jumping to an exact point you need (f/F/t/T) if it has a unique character (like the ')' within 'if (uid == 0)'), moving between paragraphs ({/}), going to matching parens/braces/brackets (%), going to the next/previous word under the cursor (*/#), etc. This is what will make you faster, not the switching from arrows to hjkl.
And that's just cursor moving. For editing, things like S to replace the line or C to replace the rest of the line after the cursor, di) to cut the part within parentheses and p (paste) it elsewhere, repeating the previous action with dot, searching with n/N instead of a function key, all those things are what makes vim nicer as a text editor. One of the least-appreciated things that I also use a lot is filename completion with ctrl+xf (sysadmins, take note!).
But I don't recommend learning everything at once. If you know how to go into insert mode (i), how to leave insert mode (escape), and how to save a file, then you basically have the equivalent of a text editor, especially with mouse mode enabled (the default nowadays, I think). From there, learn one command every week. Takes 1 minute per week and you'll know more vim than 99% of developers within a year.
Or go a bit faster and try to learn one command every morning, or every second day perhaps. Try it for one month and see if you want to go back to standard editors. Odds are, you'll want the best of both worlds, start looking for vim key binding plugins in IDEs, and end up like me with missing vim after all because those keybind plugins are usually not so great ^^'
> mostly using Java IDEs, and lately some vscode (for go, typescript, rust)
Do you need intelligent autocompletion, debugging, and other such IDE features?
There are plugins that, so far as I know, can do a lot of what an IDE can do, but I have never bothered to set them up myself. It all seems hacky and niche, but others can tell you more if this is the type of things you're looking for. I am not a real developer myself but I write a lot of scripts (things small enough to keep a full understanding in my head) as well as documents (reports for pentests) in vim, and for that it is perfect.