Hacker News new | ask | show | jobs
by q7xvh97o2pDhNrh 1106 days ago
Wow, this is fascinating to hear. Other than the standard baseline of not touching the arrow keys, I use vim pretty differently:

- 'j' and 'k' to move up and down, with '{' or '}' or even something like '20j' to move quickly

- 'w' and '$' and '0' to move horizontally, with things like '5w' to move quickly

I also rely heavily on 'v' and ctrl+'v' to select arbitrary shapes of text for yanking/deleting. I'm not sure what the exact takeaway is from comparing our styles, but it's interesting to realize about how much of coding comes down to just navigating up/down/left/right.

I agree with your last couple paragraphs almost verbatim though! That StackOverflow answer is exactly the reason I decided to try vim and stuck with it.

The verb/noun nature of vim makes it so easy to enter a flow state. The text editor fades into muscle memory, and you can surf waves of code with no bottleneck between mind and machine. (To write this comment, I actually had to open a random file and navigate around it while watching my hands — it's been years since I've thought about it!)

3 comments

I might be a perfect complement to the grandparent.

I use w b $ and ^ to move horizontally. I like using w and b because then I can hit cw to make a small change. For vertical (I don't really think in terms of horizontal and vertical, I think about it as a streams of "words" and "spaces") I usually do a search (/ or ? to go up or down) or for some files I do 20j like you. Shamefully, I do sometimes use the mouse out of habit from other programs.

I can't remember the last time I used f.

f I use second most. It has so many uses all of which could be done with / command, but definitely you come to prefer f. I use f( to scan forward to the next open paren. Then I use di( to delete in parens for example to remove the arguments. Uppercase F does the same but backward up the text. Often I use f, to go to a comma. df, to delete up to the next comma as in removing just 1 argument. The only draw back is that f does not have any repeat shortcut like n for next or . for reapply, those do nothing for f. I should mention also that f works on a single line at a time unlike /
> The only draw back is that f does not have any repeat shortcut like n for next or . for reapply, those do nothing for f.

Boy, do I have news for you :) ; will repeat an f/t/F/T motion forwards, and , will move back. Having it separate from n/N means that they have a separate history and you can combine them to repeat motions.

Also, if you’re not bound to using Vim without plugins, then the CleverF plugin lets you repeat with f/F instead of ;/,

It’s IMO easier to hit f again than to reach for the semicolon, and moreover this frees ; and , for usage in your own mappings (e.g. leader and localleader)

After this I am going to try to work in f to my routine.

The only issue is (content warning: controversial remap) I have ; nnoremap'd to : and : to ; so it would be awkward to advance multiple matches. I would hate to lose my one key :, but perhaps there is a workaround if f is useful enough (for those unfamiliar, with / or ? you use n to go to the next match).

I specifically avoided making that ; and : swap for decades as tempting as it has always been. Repeating with ; is just too useful.

However, I'm using Doom Emacs these days (with evil, of course) and while it emulates vim's command mode with colon, it's designed to drive most "commands" with space as a sort of leader key. I could imagine space being a nice remap for : in vanilla vim since it does nothing in normal mode.

I use both vim and doom-emacs almost daily and jump between the two. I like using <spacebar> to call command mode in vim to do things like :tabe or :bd or :ls etc. (I have <leader> set to , ). I have this remap in my .vimrc > cmap w<space> :w<cr>. This allows <space>w<space> to write the buffer. The second space acts as <cr> meaning I don't need to press <enter>. Lovely.

Now, turning to doom-emacs, SPACE is the modal for getting the list of next available commands. To save a buffer in doom-emacs I use SPACE w SPACE. Et voila, the same muscle memory works for both. BTW I also set up :ww to write/quit so SPACE W W does this in both editors. Well, it works for me!

That sounds great! It actually only dawned on me that I could have a setup like you describe as I was writing my comment above. Thanks for sharing your details!

The only downside for me, and I've been reluctant about this for years, is I ssh into a lot of Linux machines that usually just have the standard stuff and default configs. This has kept me from experimenting with a lot things so as to keep my muscle memory also standard (thus avoiding i.e.: zsh, extensive .vimrc with plugins, etc).

Isn't dt, to delete up until and df, to include. I'm guess either you have config or it's so ingrained in muscle memory that there is a mismatch between what you type and what you think it is.

When I played piano there was a point where I could play a piece without thought but couldn't parse the sheet music or know what my fingers were doing anymore.

> The only draw back is that f does not have any repeat shortcut like n for next or . for reapply, those do nothing for f.

As I just learned browsing through the book linked in this thread, there is!

Use ; to go to the next match or , to go to the previous one.

Great find.

cf) - change everything to the closing paren

df: - delete to the next colon

2f, - move cursor forward to the 2nd comma

I find cause to use f fairly regularly.

Note that cf) will change everything up to and including the closing paren.

ct) (change to) will change everything from the cursor up to, but not including the paren.

But if you're trying to change everything in parens, you can simply use: ci(, regardless of where your cursor is as long as it's somewhere in a matched set. ci{, ci[, etc... also work. I find it pretty useful when working with code that uses a lot of those.

I have 2 use cases for cf), but I don't use it a lot in the end:

One is when inside a parenthesis, and wanting to really delete till the closing parenthesis. But that would leave an unbalanced open paren. So in this case, I use ct) most of the times.

The other is when the cursor is before the opening parenthesis, and I want to delete the whole block. In that case, I found c% to be easier to me. The advantage being that it works with other delimiters ({[]}) handles nesting better, and it's multiline friendly.

If instead of c%, we speak about d%, another plus is that dot (.) will repeat the generic command, so

    if (is_foo()) {

      return 1;
    }
can be cleared with `d%.` from the beginning of the first line.
ca( and ci( might be what you’re looking for.
Yep, good point. They are useful when you want to change the whole text inside the delimiters (and IME, it's most of the times), but they do different things than cf( because they also change/delete text behind the cursor.

The % approach works only on one direction.

And all of that works after pressing v so you can see what you are about to delete or change before doing it.

Quite helpful if you have multiple of the same character and you want to go beyond the first one without needing to count.

Oh! I do df but for whatever reason I don't think of it as using f.

Muscle memory is a weird thing.

I usually go for “ciw“ to make changes from wherever I am in the word. It lets me use w or e because I’m not usually paying attention to which one I’m smashing. :)
{ and } pollute your location list! So your C-o will also jump through points where you pressed them. Also, for terse (whitespace-wise) codebases, they become useless. I used to use them a lot but now I use C-u/C-d for most vertical movement (and {} in those super rare cases where whitespace is just right).

To move horizontally, simple 'f' might be faster quite often (some prefer combining it with leap-like plugins like flit if using nvim).

Interesting. I almost never use ctrl-o except if I navigate to another file and want to go back, happens intentionally and by accident but in any case rarely.
I never used it either before I started seriously using neovim for Rust development with a near-perfect LSP. You quite often 'gr' (go to reference), to check what some function does or how something is defined, then gr again and again.. and at some point you need to go back (yes, there's gi and c-t etc but C-o is less specific and works in many other cases; you can also set marks and harpoons and the like but most of the time you don't).
Interesting. I thought neovim is the reason I don't use ctrl-o, because it has floats. With my config I can gd to go to definition (and then sometimes ctrl-o back) but often do gpd to peek it in a tiny mini window.

By the way even without { and } which I never used really my ctrl-o history seems to be too verbose, I wonder what I am doing wrong.

My own usage is very close to yours.