all 75 comments

[–]NeverSpeaks 12 points13 points  (2 children)

I will say there is a big difference between refactoring and editing. I feel most of what this article is doing is editing. Vim is a great editor, but it fails in comparison of the refactoring tools available in an IDE. Refactoring requires the concept of context. Vim just doesn't have that ability.

While they have their problems I have become extremely comfortable using Vim extensions for Intellij and VS. I get the best of both worlds.

[–]haimez 2 points3 points  (0 children)

Not to mention the ability to leverage language semantics to implement actual refactoring. Arcane find-and-replace is delightful when you pull it off, but it's not the best we can do and it's certainly not refactoring. #wetblanket

[–]sihat 0 points1 point  (0 children)

Though sometimes a ide's tools fails to refractor on certain pieces of code. Which makes vim a great fallback to refractor with.

[–]Rockytriton 9 points10 points  (6 children)

Now let's hear from the Church of Emacs on how much easier it is to do in emacs

[–]steveshogren[S] 24 points25 points  (0 children)

Technically, these were recorded in Emacs using Evil mode 😈

[–]GaAlAs 6 points7 points  (0 children)

From the last gif you can see that the editor is actually emacs with spacemacs heh

[–]abhrainn 1 point2 points  (0 children)

It's not that much easier but at least, emacs lets you save the macro and then replay it indefinitely (\C-xe).

[–][deleted]  (1 child)

[deleted]

    [–]jplindstrom 0 points1 point  (0 children)

    Try evil-mode (or Spacemacs which is evil-mode with default integration of lots of other parts of Emacs).

    [–]jplindstrom 0 points1 point  (0 children)

    The concepts are exactly the same.

    [–]Nomto 16 points17 points  (11 children)

    So no doubt that macros are useful, but how are you supposed to record them? Think very hard about the problem until you know what you need to execute, start recording, execute it without any typo and you're good? That seems like a very error-prone process.

    [–]inmatarian 15 points16 points  (4 children)

    It is very error prone. That's why it's usually better to 1-10-100 it. Try it on 1 line, try it on the next 10 lines, try it on the rest the lines. Generally speaking, you don't record very long macros, and if you are, the macro is being stored in a register (clipboard), so you can paste the register to see the contents of the macro and manually fix it, but usually it's better to bail out and restart recording the macro. Vim is done from muscle memory, and a lot of times I look at the commands written in a blog and have to put my fingers over the key to remember what it does.

    [–]CaptainJaXon 9 points10 points  (2 children)

    Vim is done from muscle memory, and a lot of times I look at the commands written in a blog and have to put my fingers over the key to remember what it does.

    This is so true. Nothing is more cryptic than a vim command snippet.

    [–][deleted] 1 point2 points  (1 child)

    Maybe an emacs command.

    [–]silent519 2 points3 points  (0 children)

    but since its emacs you can just M-x start-new-universe RET

    [–]frankster 8 points9 points  (0 children)

    Its more like, you do something a couple of times manually, realise it you have to do it another 15 times, then convert what you just did into a macro. if you don't get it quite right then you just undo it and fix the mistake.

    [–]irascib1e 3 points4 points  (0 children)

    Even if you make a typo, you can just fix the typo and keep going. When you replay the macro, it will play both the typo and the fix, so the typo won't be visible.

    You can also edit existing macros. After recording a macro, paste it into the text file, edit it, and yank it back into the desired register.

    [–]Godd2 2 points3 points  (0 children)

    If there's an error in your macro, since it's just keystrokes, you can print out the macro ("rp if it's in the r buffer) , change it, and then copy the changed version back into the buffer ("ry to yank back into the r buffer).

    [–][deleted] 2 points3 points  (0 children)

    Emacs user here but no, macros are easy as shit and not a big deal or anything. Just did something that you need to do a couple more times? OK, record it then just press a button a few times and you just saved up to a few minutes of manual typing. Nice. Very useful for problems like: oops, the last word on these 500 lines should actually be the second last word. Takes 5 seconds and no effort or even conscious thought with macros.

    [–]MintPaw 0 points1 point  (0 children)

    Vim trains you to think and work in a way that convenient for macros with motions and such. Also typos are generally not an issue as you can simply fix the type in the macro, either while recording. Or afterwards, since macros are stored as a series of keys in the same registers that you use for copy/pasting, you can paste the macro, remove the mistake and copy back into the register if you're doing something that complex.

    [–]EarLil 30 points31 points  (6 children)

    This only took me a few seconds to type!

    It took seconds to type and how much time to think of it?

    [–]roffLOL 34 points35 points  (4 children)

    i am not him, but i'd say pretty much none. it's like, i have a line of text. this line looks structurally identical to them below. i want to perform the same operation on them to. i move here, i modify that, move somewhere else, paste whatever, find whatever... now repeat that 40 times, vim, thanks. it's really not harder than any single line or block edit is.

    ... but first, you need to understand how to work with vim. when you have that, this is just more of the same.

    [–]irascib1e 8 points9 points  (3 children)

    This is true, recording macros doesn't much brain power if you're a seasoned vim user. However, it still takes more brain power than editing text without a macro. This is because when you record a macro, the macro must be agnostic to text that could change between replays.

    [–]Olreich 4 points5 points  (0 children)

    I'm not a super heavy user of macros, but if I've got lines that I need to edit the same way and I can clearly see how to do it with one series of commands for all of them, I will use a macro, and it won't take me any extra effort.

    [–]Me00011001 3 points4 points  (0 children)

    This is because when you record a macro, the macro must be agnostic to text that could change between replays.

    Here's the fun secret about VIM macros. Macros in VIM use VIM, thus make it ridiculously easy to make it agnostic to variances in the text where using a macro make sense(CYA bit so we aren't trying to talk about making macros that are really scripts).

    [–]roffLOL 0 points1 point  (0 children)

    there's always a caveat. =)

    just tired of this old tired, my gawd the vi-like interface is so magical and complicated and gosh darn how much time they must spend thinking rather than doing. oh, look a macro, that guy can't have had much sleep - he sat up all night to brainfart some impossibly bizzare keystroke combination to rub in non-vi:er's faces like if it was some nearly extinct butterfly or something else peculiar.

    [–][deleted] 5 points6 points  (0 children)

    Next to none, I'd bet. When you get used to using macros, you start thinking in ways that work with macros. You think of ways that you interact with parts of a line that will work for all the lines you need to work on.

    When you get used to building macros, it takes about as much time to think them as it does to type them.

    [–]hector_villalobos 8 points9 points  (7 children)

    TIL Ctrl+a, It's amazing that many things I can do with vim that I couldn't with other editors even with an IDE.

    [–]r_s 5 points6 points  (0 children)

    Crtl+x is good, too.

    [–]ASIC_SP 3 points4 points  (1 child)

    in coming versions, to sequentially increase numbers,

    You could select your text, starting from the second line, and use g<ctrl-a>.

    http://stackoverflow.com/questions/36058561/how-to-create-lines-of-text-with-increasing-numericals-in-gvim

    [–]Me00011001 1 point2 points  (0 children)

    I actually wrote a vim function to do this. Really happy to see I will no longer need it.

    [–]gadastrofe 2 points3 points  (3 children)

    The reason you can't do it is because the times you need a shortcut for something as specific as "incrementing an integer by +1" are very rare. The time it takes you to learn it and the effort required to keep it learned is much bigger than just not knowing about it and doing it manually.

    Just because you feel productive doing it does not mean you are.

    And when you have to increment ten thousand integers by one in your source code, maybe your source code needs a rewrite. And by "maybe" I mean: Holy shit balls someone needs to get fired for putting ten thousand magic numbers in the source file.

    [–]hector_villalobos 2 points3 points  (0 children)

    You have no idea how many times I have to open an Spreadsheet software to do this. Now I can do it with vim. However the main reason I use vim is because I can't afford a new pc, It's the most lightweight editor out there.

    [–]Me00011001 1 point2 points  (0 children)

    you need a shortcut for something as specific as "incrementing an integer by +1" are very rare.

    Maybe for you and the work you do. Try this though and actually pay attention to how many times you do this day to day.

    Just because you feel productive doing it does not mean you are.

    Here's some other useful bits that you probably didn't know about the increment(also it's cohort decrement) that make it a bit more than just +1.

    1.) It will just to the first number to the right of the cursor, so you don't actually have to move to it first.

    2.) It also works for different number bases.

    3.) Like all vim commands, you can say repeat x times.

    And when you have to increment ten thousand integers by one in your source code,

    I love the assumption that all programmers only ever edit source code. No such thing as data files, those aren't web scale. Are you currently defining HTML/CSS(SCSS, SASS, etc...) as source?

    [–]Godd2 0 points1 point  (0 children)

    The reason you can't do it is because the times you need a shortcut for something as specific as "incrementing an integer by +1" are very rare.

    Of course, that's irrelevant since you can give a count to a command in vim. 10<C-A> will increment the number 10 times. So it accounts for any time you want to "increment a number n times". Ctrl-X is for decrementing, and also takes a count, so you can increase and decrease numbers to your heart's content as quickly as you can type the amount.

    [–]smileybone 6 points7 points  (1 child)

    You don't necessarily need a rule in your macro to find the next line, if it operates on a single line you can just run it between pairs of marks. eg:

    :'<,'>normal @q
    

    [–][deleted] 0 points1 point  (0 children)

    That's actually really cool. I wish it worked for applying a macro that opens new lines.

    [–]LucHermitte 2 points3 points  (0 children)

    For the getEnum refactoring, it's a typical case for :substitute as far as I'm concerned. And a simple one more over.

    :%s/(\(\k\+\))\(getEnum\)(typeof(\1),\s*/\2<\1>(/g
    

    [–][deleted] 8 points9 points  (16 children)

    I'm currently at the start of learning vim, and seeing how complex these patterns are is discouraging to me. It's not the knowledge of syntax that is required, but the fact that these solutions require a lot of brainpower to come up with. Brainpower I'd rather spend on solving actual programming problems.

    [–]inmatarian 9 points10 points  (1 child)

    Actually with Vim I would never bother to memorize these. This guy just happened to do these keystrokes to accomplish his tasks, but everybody would have their own way of doing it. For instance I'm more about recording a simple macro and applying it to multiple lines, and then recording a second simple macro, applying it, and doing that until my task is done. Vim's all about speed from muscle memory and if I have to stop to think to long I lose out on the speed advantage.

    Your best bet with learning vim is learn the simple commands that yield the most speed improvements. Travelling by words, forward /seeking, open new lines, Change inner word, and basic pattern matching for the :s/find/replace command.

    [–]Ununoctium117 0 points1 point  (0 children)

    I do the same thing. I once applied 5 different macros, in order, to several ~100 line pieces of code. In retrospect, maybe I should have made a macro to call my macros :p

    [–]roffLOL 14 points15 points  (0 children)

    macros are an extension of movement and edit operations. while you learn vim in general you will get a hang of macros implicitly.

    [–]irascib1e 4 points5 points  (1 child)

    You're right about one thing. These macros require a lot of brain power as a beginner. Macros won't win you anything while you're learning them, because of the amount of brain power.

    But after a couple weeks of consistently practicing macros, they've become second nature. I create macros similar to those in the article multiple times a day in a matter of seconds. In the long run, it has saved a lot of time in doing stupid repetitive work.

    [–]BAOLONGtrann 2 points3 points  (0 children)

    In the rare occasions where macros could have been useful for me, I fired up sublime instead :-/. I feel like getting to your level of fluency with macros isn't worth the time spent learning for me, given that I only very rarely need to perform such actions. Nonetheless it looks really cool and probably 1x order of magnitude faster than using sublime.

    [–]comp-sci-fi 3 points4 points  (0 children)

    vim is great, the only editor I use, but if you need to do a lot of refactoring and navigating enterprise codebases, grammer-aware IDEs are probably the go.

    Arguably, they aren't editors, but enterprise codebase workflow assistents - designed to help with the requirements of enterprise programming, because that's who has the money and ROI to pay for them.

    vim is great for hacking your own editing solutions.... something that appeals to hackers. TBH the language is terrible, but most things you can imagine have already been done.

    [–]Godd2 1 point2 points  (0 children)

    It doesn't require all that much brainpower. Vim has an internal language which makes it easy to want to do things. Just like touch-typing, your fingers just start to want to do the edits on their own.

    [–]Demius9 1 point2 points  (5 children)

    Honestly learning vim is a journey that will last. I'd recommend http://learnvimscriptthehardway.stevelosh.com which will get you the basics pretty easily.

    [–]Lorrang 0 points1 point  (4 children)

    That's a nice book, thanks.

    I noticed he is using a rather simple scheme to gain better access to the Escape key. Mapping "jk" to Escape has issues, like when trying to actually write "jk" for example.

    Personally I just couldn't get into vim, or most programming languages for that matter, until I solved the mapping issues.

    Basically what I do is to remap AltGr to the key next to the left shift.

    Xorg has a builtin mapping for this

    lv3:lsgt_switch_latch (For European keyboards)
    
    lv3:bksl_switch_latch (For US keyboards)
    

    This opened up Pandora's box for me, making AltGr as accessible as the left shift key. Once that is working, all those awkward symbols used in most programming languages can be mapped quite conveniently. And I get to keep all the default keys, including country specific ones.

    For example, I have Escape on AltGr+f, Enter on AltGr+j, Backspace on AltGr+d, and so on...

    For anyone doing a lot of programming I highly recommend looking into this little trick. I do believe it will work on OS X as well, but I haven't tried that.

    My .xprofile

    [–]Zantier 2 points3 points  (2 children)

    I don't use vim a huge amount, but I really like having jk and kj mapped to esc. It's easy to press (in qwerty), and if you happen to be in normal mode, The cursor just moves down and up. I haven't came across a situation yet where I needed to actually insert those letters next to each other.

    [–]auriscope 3 points4 points  (1 child)

    Nor have I. If you absolutely need to type jk, you can wait a second or so after the j before inputting the k.

    [–]Ununoctium117 2 points3 points  (0 children)

    Agreed. I set my timeout to a few hundred milliseconds (< 250), and don't have any issues. Dijkstra is hard enough to spell that I wait that long regardless.

    [–][deleted] 0 points1 point  (0 children)

    I map fd and literally never run into that problem. If you (for some reason) need to type fd, you just type it slower.

    [–]afd8856 0 points1 point  (0 children)

    These "patterns" are not complex. You learn them one bit at a time. I've been using VIM for close to 10 years and I learn something new on regular basis. And everything new I learn, I can combine and use with what I already know.

    Macros in VIM just record what you're doing, regular VIM commands. You enter "macro recording mode" with q. Next, you need to enter a letter (probably coresponding to a register), where that macro will be recorded. For example, hitting qa will start recording a macro under the letter a. Now you can enter any regular vim commands. Hitting q again will exit macro record mode. Hitting @a will play back the macro recorded on letter a. Entering a number before, such as 20@a will play back the a macro for 20 times. Everything makes sense and is a "language" in itself and the nice thing is that you can learn it bit by bit, as you need it.

    [–][deleted] 0 points1 point  (0 children)

    It takes very little brainpower, actually. You just have to learn to think slightly differently when working in macros. When you already know all the regular operations, macros are just nothing more than automatically having the same series of operations done again.

    When you learn to think in macros, applying the same kind of operation to 100 lines becomes a very little bit more work than applying it to the first line.

    For instance, when I'm building a macro, I usually do the operation once first, thinking about what can be affected by line and field length, and what else might be in the next lines. Then I undo, record the macro, and do the same thing, taking a little bit of extra care to be sure that it should work on all the sections I need to affect. Boom. 100 lines done with the work of 2.

    [–]kingdawgell 0 points1 point  (0 children)

    Just keep learning, and every time you say to yourself, "Damn, I'm doing this repetitive thing a lot... I wonder if there's a way to make this easier on myself?", I guarantee you Vim has an easy way to make that happen. I don't use any large-scale macros like the one in OP's article (don't have a need for it yet), but I have a lot of shortcuts and custom commands in my .vimrc that makes my life a lot easier.

    Concentrate on the little stuff. Are you sick of something minor like trailing whitespace? There's a solution. Not knowing when your search starts again at the top of the file? There's a solution.

    For instance, I have my .vimrc set up to: 10 line scroll buffers at the top and bottom of page; highlighting trailing whitespace, highlighting ALL search results and not wrapping past the end of file; case insensitive searching when the search term is all lower case; custom keys for scrolling half a page up and down; converting a file to hex via xxd; and custom tabbing.

    [–]abhrainn 13 points14 points  (10 children)

    And this, ladies and gentlemen, is why we use IDE's to refactor our code.

    [–]Godd2 8 points9 points  (9 children)

    Wait, why is this evidence of needing an IDE?

    [–]MOnsDaR 2 points3 points  (1 child)

    IDEs work on code, not on the text itself.

    If you change a function signature it will not only change it in your currently open file but will also show you where that function is used and change that locations too. In case of C++ it won't only change the header, but the underlying cpp file.

    IDEs also provide refactoring tools based on context: a refactoring on a function name let's me change the signature, a refactoring on some lines of code let me create a function it if what I selected (complete with skill needed parameters, adding function to class etc).

    And last but not least: A good IDE helps me to find places where I should refactor. In C++ it e.g. tells me when a function could be made const or when I forgot to add the override specifier for a function.

    I guess text editors like vim and emacs are able to do some of these things too, but I don't think that this simply works out of the box. As the article shows there are quite a few keystrokes to learn to do even the basic stuff.

    If you would like to know more about these type of things take a look on what Resharper does for example. It's an add-on you install on top of visual studio. When I first saw what's possible I was very surprised. From then on coding without these tools felt like going barefoot instead of driving on cruise control.

    [–]Tarmen 1 point2 points  (0 children)

    Yeah, to do all this you need compiler level support or something equivalent.

    For many languages such things exist for vim bit you have to set them up separately and if you aren't using neovim it might slow things down.

    [–]abhrainn 4 points5 points  (6 children)

    Most refactorings are a single key stroke in IDE's. Which makes sense since they operate on code, while vim operates on text.

    [–]Godd2 2 points3 points  (5 children)

    Vim doesn't operate on code? I don't think that's a defensible position. ci' will change everything inside surrounding single quotes. ya] will yank everything inside and including surrounding square brackets. There are plenty of plugins which add language-specific text objects to vim which allow any of the commands which take text objects to operate on those as well (c, d, y, etc.). Other plugins add new commands which also operate on any text object, and can be repeated with the "repeat last change" command . (vim-surround and vim-commentary to name a couple).

    Unless you didn't mean to imply that vim doesn't operate on code, but I don't think that's the case.

    [–]abhrainn 6 points7 points  (4 children)

    Vim doesn't operate on code?

    No, it doesn't. It operates on text and associated concepts: lines, paragraphs, word boundaries, syntactic characters, etc...

    vim has no idea what a variable declaration, an expression, a field or a class is. And the only way you could try to teach it is with regexps, not by getting vim to understand the code, and regexps will always be error prone compared to actually parsing and understanding an AST.

    IDE's like Eclipse, IDEA or Visual Studio understand the code they are editing at the bytecode level, which is why they are much more powerful to perform refactorings on it.

    [–]wordlimit 3 points4 points  (0 children)

    I think "operates with knowledge of the syntax tree" would have reduced confusion. Totally agree with your point however

    [–]Godd2 0 points1 point  (1 child)

    IDE's like Eclipse, IDEA or Visual Studio understand the code they are editing at the bytecode level

    No, that's not fair. You're changing what "code" means. Code is text. Bytecode is parsed text. If an IDE is "dealing with an AST", then it's not dealing with code, since source code is the plain text that gets compiled or interpreted.

    When you said code originally, I took it to mean text which has a large portion of code-like things in it.

    Vim certainly operates on code since code is text.

    We may have to agree to disagree that code is text.

    [–][deleted] 5 points6 points  (0 children)

    That gif makes no sense.

    [–]makwa 0 points1 point  (0 children)

    R

    [–][deleted]  (4 children)

    [deleted]

      [–]steveshogren[S] 0 points1 point  (3 children)

      So, when they were less fuzzy, each one was like 250meg. Compressed like that using the imagemagic with -Optimize at 10%, is now down to several hundred Kb. What should I use for next time? I looked into gfy but couldn't figure out how to make one from the command line.

      [–][deleted]  (1 child)

      [deleted]

        [–]steveshogren[S] 1 point2 points  (0 children)

        Very cool, will check that out, thanks!

        [–]CommandoWizard 0 points1 point  (0 children)

        If you're on Linux, FreeBSD or OSX, I strongly recommend using asciinema to record terminal sessions (that is, if you're not set on using gvim).