Hacker News new | comments | show | ask | jobs | submit login
Intermediate Vim tips (kinbiko.com)
200 points by kinbiko 6 months ago | hide | past | web | favorite | 77 comments



Whenever a Vim post mentions grep, ack or ag — especially in conjunction with fzf/fzy — I'll make sure to mention the even faster rg (ripgrep): https://github.com/BurntSushi/ripgrep BurntSushi's write-up about the internal workings of ripgrep is also super interesting: http://blog.burntsushi.net/ripgrep/)

It's a really amazing piece of software. It has also recently been included in Visual Studio Code to search in files.


Completely agree. I used to use ag, but its handling of .gitignore files is buggy and often returns a lot more results than it should. Switching to ripgrep made a pretty significant difference for me.


I use ripgrep and it's pretty great, but I don't know why Visual Studio Code would be using it. Why not just use Rust's Regex library instead?


I'm just guessing here, but ripgrep is an executable that they can bundle and write a simple wrapper around. VSCode isn't written in Rust so they'd have to write their own "grep" in Rust which most likely wouldn't be anywhere near as good as ripgrep.

Or am I misunderstanding your question?


Well, ripgrep uses Rust's regex library. If VS code used the regex library directly, then they would basically wind up re-creating ripgrep (or something very similar) itself.


Is it? Funny because I have tmux open in the side pane, and execute my searches that way.



I’m probably the minority here but I don’t like to customize my Vim too much. 1 - it takes time. 2 - half the reason I like Vim is because I can use it anywhere. If I’m so used to a highly customized setup, then I am going to feel out of place when I log on somewhere else.


It depends what you use Vim for. If Vim is your only code editor, it’s crazy that you’d leave tons of productivity enhancements on the table because you want that standardized, bottom-of-the-barrel experience. Nice things are nice!

I have tons of customizations in my Vim, and have very little trouble using vi or vanilla Vim when I log into production machines. It is frustrating to not have my magic this and that, but no less frustrating than it would be going from IntelliJ on my own box to Vim on someone else’s.


I wish I could upvote your comment many times. I wish the parent comment pointed out what use case they have for Vim, as this really dictates the "right" approach.

I wrote about this previously in the context of Vim vs Emacs, though it's similar to customized vimrc/plugins vs vanilla vimrc:

"One can reduce part of the [editor] debate down to a single question: how fully featured do you want your text editor out of the box? If you’re a DevOps engineer who spins up new environments constantly you’ll have different ideas about the best choice compared to a full stack engineer working in a single development environment that can be painstakingly setup. For the DevOps engineer, a light text editor that is installed by default is likely ideal, while for a developer with a single computer, a full-featured IDE (auto-completion, plug-ins, custom keys) is worth the high setup cost."

https://www.nemil.com/musings/betterdebates.html


> it’s crazy that you’d leave tons of productivity enhancements on the table because you want that standardized, bottom-of-the-barrel experience

Like what exactly and compared to what environment?


Same. I spend most of my time in a terminal and SSH into various boxes daily. I do customize my standard Unix toolset, but avoid plugins and non-standard configs that increase cognitive burden. It's very liberating to feel comfortable with shitty defaults. If you feel at home with the defaults, you feel at home anywhere.


You can remotely edit on any system accessible over ssh thanks to netrw:

    vim scp://some-remote-box/some/path
You can jump to a directory listing by including a trailing /

   :help netrw


> You can remotely edit on any system accessible over ssh thanks to netrw:

Yeah, and either lose all the goods of path completion or gain atrocious lag on each tab. Because of that, I rarely use netrw.


Emacs has Tramp, and you can do the same thing!


Is there a way to combine this with sudo, to edit root's files remotely? Apparently tramp is supposed to support this, but I prefer vim.


Most people store their dot files (including their vim config) in a git repo and just check out a copy on any machine they use. That's what I do (git+stow). I can be up and running on a new system in just a few seconds.


Does anybody know a saner way of doing this cross-platform? I've resorted to doing platform checks in my .bashrc and don't get me started on the OSX / Linux differences in .platform, .bash_platform, and .bashrc sourcing.

And when I tried termux on Android, oh dear lord. The whole thing breaks because of permissions issues. Had that issue on WSL too.


https://github.com/007/dotfiles

Lowest-common-denominator for linux and mac, mostly just "make it work if you notice it's broken". I have one file that's bash magic, and link it to everywhere it might be needed - bashrc, bash profile, etc. It's kind of monolithic, not great but at least 100% consistent for what ends up where, and avoids sourcing external stuff or requiring N different files to work. You'll see some of your pain in the repo history, change X to Y to make it osx or *nix compatible based on whichever is my primary platform.

Same goes for vim, just absolute basics for vimrc and a few very portable plugins and niceties hardwired. No package manager, just a bare directory.


Across linux and OS X, I use a solution based on the this HN comment and it's follow-up discussion: https://news.ycombinator.com/item?id=11071754

Lot of other suggestions on the same HN thread: https://news.ycombinator.com/item?id=11070797


I use vimswitch (http://vimswitch.org) to copy my vim settings over to new machines.

(Disclaimer: I am the author of vimswitch)


> I've resorted to doing platform checks in my .bashrc

This is what I do, too. Most of mine is portable, but I have a block in bashrc that branches on uname.


I was a heavy customizer and used it with all sorts of plugins, but maintaining it across computers with little incompatibilities between OS's and version just got to be too much. I finally came around to the tmux side and now use vim as the editor and unix as the IDE. Going to give kakoune another shot in the new year as well.


Right there with you. While the power of vim is to be able to customize it, I hate getting used to something and then not being able to use it everywhere. I've managed to get by with no extra .vimrc things whatsoever for quite some time :D Does it take me longer to do some things compared to using what's in this article? Yup. Does it prevent me from doing good, and still relatively quick, work? Nope.

When I want the power of formatting and and all the goods, I use visual editors with no shame or remorse (VS Code is my current poison of choice).


Just chiming in real fast that you can use ssh to edit files on remote systems even if they don't have emacs themselves via /user@host:~/filename.txt

So I also can use emacs almost anywhere. (I still advocate users and admins at least be functional in vi/vim regardless). Also don't forget GNU Nano isn't out of the game either as a small almost everywhere easy to use editor.


I used to have this mindset, but now that I've got all my dot files on github I can get a machine set up pretty quickly. And for those times where I'm SSHing into a machine for whatever reason, using plain old vi hasn't been a problem. I typically do avoid overriding any of the main key bindings though so that I don't get confused when I do have to use plain vanilla vi.


Leverage your tools. Don’t let them leverage you.

Reduce the friction of importing your vim config non-destructively and on demand.


My vim is pretty customized but I can't say I have any trouble personally with vims that aren't mine.


I agree with this, I use plain GVim on all my machines. I'm not interested in plugins that will slow it down - it's fine the way it is.


> I don't like excessively long lines of code (120+ in most languages)

Quick straw poll on this... How many people like a line length limit?

My personal preference is a fairly strict 80 (barring silly things like URLs), but I've always been met with resistance to ANY line length limit. Is it really that imposing?


I break lines if it looks like they’re getting too long, where it feels right to do so. Setting a fixed number of columns causes people to align hanging lines to the right in my experience:

  some_example_code = LongTypeName(argument_one=1,
                                   argument_two=2,
                                   argument_three=3)
(pretend that’s 80 columns), resulting in this mess when I try to look at it in a narrower view:

  some_example_code = LongTypeName(argument_on
  ↳ e=1,
                                   argument_tw
  ↳ o=2,
                                   argument_th
  ↳ ree=3)
Turning off word wrap doesn’t help, because then it’s an equally painful constant two-character scroll. What does help is creating indented blocks where it feels right, and letting other lines just naturally be long.

  some_example_code = LongTypeName(
      argument_one=1,
      argument_two=2,
      argument_three=3,
  )

  some_example_code = LongTypeName(
      "just a string that happens to be long; some people introduce acceptable percentages of string literals for long lines, but it’s really not necessary. let word wrap take care of it!")
(Plus: specific column counts depend on the size of your indentation.)


> What does help is creating indented blocks where it feels right

Over the years, I've come to believe that using a hanging indent for alignment is actually better in terms of readability as opposed to aligning at a column after the opening parenthesis, brace, or bracket. It's also easier to type as well even if the editor doesn't provide an auto-indent facility (or if it's not configured correctly for some reason) since you only have to press TAB the same number of times to correctly position each formal parameter in the function definition.

As a side benefit, it also takes care of any alignment issues regardless of whether one uses tabs or spaces.

> and letting other lines just naturally be long.

Using the language's feature for string concatenation still makes it as easy to read:

  some_example_code = LongTypeName(
        "just a string that happens to be long; some people introduce " +
        "acceptable percentages of string literals for long lines, but it's " +
        "really not necessary. let word wrap take care of it!")
Another benefit of doing this is that it makes a unified diff and side-by-side diffs easier to read. Contrast the wrapped version when I add another sentence to the end of your example:

  diff --git a/tmp/wrapped b/tmp/wrapped
  index 972537b..27e3e31 100644
  --- a/tmp/wrapped
  +++ b/tmp/wrapped
  @@ -1,4 +1,5 @@
     some_example_code = LongTypeName(
           "just a string that happens to be long; some people introduce " +
           "acceptable percentages of string literals for long lines, but it's " +
  -        "really not necessary. let word wrap take care of it!")
  +        "really not necessary. let word wrap take care of it! Though unified " +
  +        "and side-by-side diffs may be more difficult to read")
versus the unwrapped one:

  diff --git a/tmp/unwrapped b/tmp/unwrapped
  index 284ef1e..db47f46 100644
  --- a/tmp/unwrapped
  +++ b/tmp/unwrapped
  @@ -1,2 +1,2 @@
     some_example_code = LongTypeName(
  -      "just a string that happens to be long; some people introduce acceptable percentages of string literals for long lines, but it's really not necessary.  let word wrap take care of it!")
  +      "just a string that happens to be long; some people introduce acceptable percentages of string literals for long lines, but it's really not necessary.  let word wrap take care of it! Though unified and side-by-side diffs may be more difficult to read")
With the wrapped version, you can more easily see what I added to the end of the line in your example. In the unwrapped example, I most likely would have to either scroll horizontally to read the entire line. If the line is soft-wrapped, then I would have to realize that the second line is part of the previous line and not a different context line (soft-wrapping is simulated by hard-wrapping right after the "for long lines," comma and the space after "difficult to " based on how blockquoted text appears a rendered comment):

  diff --git a/tmp/unwrapped b/tmp/unwrapped
  index 284ef1e..db47f46 100644
  --- a/tmp/unwrapped
  +++ b/tmp/unwrapped_more
  @@ -1,2 +1,2 @@
     some_example_code = LongTypeName(
  -      "just a string that happens to be long; some people introduce acceptable percentages of string literals for long lines,
  but it's really not necessary.  let word wrap take care of it!")
  +      "just a string that happens to be long; some people introduce acceptable percentages of string literals for long lines,
  but it's really not necessary.  let word wrap take care of it! Though unified and side-by-side diffs may be more difficult to
  read")


> Over the years, I've come to believe that using a hanging indent for alignment is actually better in terms of readability as opposed to aligning at a column after the opening parenthesis, brace, or bracket. It's also easier to type as well even if the editor doesn't provide an auto-indent facility (or if it's not configured correctly for some reason) since you only have to press TAB the same number of times to correctly position each formal parameter in the function definition.

> As a side benefit, it also takes care of any alignment issues regardless of whether one uses tabs or spaces.

That’s exactly what I said.

> Another benefit of doing this is that it makes a unified diff and side-by-side diffs easier to read.

Until you rewrap and it adds noise to the diff. I recommend a combined word/line diff instead.

Concatenation also hides whitespace problems. Not a serious error, but a very common one.

  "This ends with a period." +
  "But this doesn’t start with a space."


I'm also at a fairly strict 80 (errm, 79 inclusive).

At work, I've managed to get a 99 column limit, with 79 columns for comments. But yeah, some people just don't like the limit. I like it because of monitor size/font size/distance from monitor/side-by-side editor windows. Autowrap doesn't cut it.


I don't get the 80 char limit at all. But then my display is 43" at 3810 pixels horizontally, so at my normal font size I would be able to fit, what, 7 or 8 windows side by side at 80 columns wide?


What don't you get about it? I can understand you having a different preference. That's normal, we all like different things. But not getting it at all? That's just weird.

I'll explain why for me. On my 24" 1920x1200 monitor, I want to be able comfortably fit two editor windows side-by-side where neither window auto-wraps the code. 79 columns works well for that. This is a function of my ability to read the text, which in turn is a function of font size, monitor size and viewing distance.

(I actually have many more horizontal pixels than you too, because I have three 24" 1920x1200 monitors. My center monitor typically is where my code lives, while my other monitors have other terminals open doing other things, like searching or compiling code.)


I suppose I phrased it badly - I meant I don't get why anyone would have a limit as low as 80 unless they're coding on an Apple II or a 10" netbook. But you fill your 24" 1920x1080 with 160 characters and change? That's like font size 18, just sounds huge to me. But hey, it's your display.

Also, I do quite a lot of numerical code where it's more important to me to line stuff up so that physical symmetries are reflected in the code, makes coding much easier and less bug prone. So I guess that also explains my bias.

But like you say, we all like different things.


I like an 80 column limit for C and python, but it starts to be a problem in C++. This says something about C++ and I don't think it's positive.

I actually also like a fairly small limit on the number of rows (around 40). If my functions and methods are too complex to understand in this much space then it's time to refactor. Of course, I usually have to work on existing code and the functions/methods are not always so compact.


I've often found that having all the code that's doing one thing in the same place is better than splitting it up into a bunch of functions just to keep rowcount low. It makes it easier to step through and reason about what is going on if all the steps of a logical sequence are actually laid out in a sequence (instead of intermittently jumping to other files). Whenever I find a function that I discover is only called in one place I just inline it, and in my opinion that improves the code every time. Abstraction is important, but understandability is more important.


The row and column limit is more of a guideline, not a hard and fast rule.


I render a column at 80 and rarely exceed it. Given that my font size is quite large, there's not much wasted space. A lot can happen in 80 chars though, especially in Clojure, so allowing 100, 120, or even more is asking for one-liners which are far too complex.


I prefer the 79 or 80 character line limit because it makes it much easier to read unified diffs pertaining to code changes. It also makes viewing files side by side much easier as well.


I think line limits are a good idea, though I sort of do them by feel usually. That said, 80 feels incredibly restrictive, a relic of bygone monitor sizes.


It's not just that, in fact the reason for limiting to 80 is mostly because short lines help readability because of how human eyes operate. Eyes prefer to stay within a small circular region located in the center of the visual field. Too much vertical or horizontal movement makes it harder to see, but vertical movement isn't an issue in text because of scroll, but horizontal movement is a problem.



This assumes that code should be read as prose. I posit that code should be skimmed, then the eye can track right if the code is relevant to the task at hand. This is all subjective, which is why I feel soft-wrapping is appropriate as it allows the coder to decide their preference.


Does anyone have rules that take into account indentation? I suppose too much indentation is its own issue, but seems like 80 could be flexible with your indentation.


I like 100 or 120 characters. I feel like 80 is far too restrictive, especially in “nesty” or “chainy” languages like JavaScript and Ruby. On a 30” display I can comfortably fit three or four columns at 100 chars in Vim.


I don't believe in hard limits, but if a line goes over about 120, I'll put its length under more scrutiny, to see if there's somewhere that it would make sense to split it. There almost always is, unless it's some kind of data table embedded in the code (or a long string).


I really don't care most of the time, mostly because I don't get long lines, and when I do ( like sometimes in tests I have a string that has some test data in it that's quite long ) I'm all good with it being long rather than wrapping.


I also will strictly use 80 character lines. I like that because it means I can have two vertical panes of code open at the same time even on my 12-inch MacBook (regular/not pro), which I love b/c of it's battery life and weight.


In python, 80 feels like reading a newspaper column. I use 4 spaces as an indent... with an indent for def():, try:, and couple if statements, I'm already 16 characters in.

Plus python seems to use super_descriptive_names_which_take_up_alot_of.space()


After years of Objective-C I don't blink unless a line is over 140 characters.

Some things just look better that way.


Ditto for C#. It's otherwise a fine language, but you're already 12 spaces into a line before you write any executable code (assuming tab = 4 spaces). 80 chars per line just doesn't work :-(


I just let them soft wrap.


I've done a similar thing with my whitespace, but prefer characters that I'm less likely to have typed myself (like a small arrow for tab).

  set listchars=tab:→\ ,nbsp:␣,trail:·


I am so glad that I can live without these tips. As I grow older, every year I feel the need to cut down on my essentials. My .vimrc gets shorter every year. Earlier, I was so annoyed by the default parentheses highlighting yet so dislike the solutions of adding more lines to my .vimrc, I was forced to do some research and found out that all I need to do is to delete the plugin from /usr/share/.... I deleted the entire plugins folder there. I felt like Picaaso.


Where have you been all my life, "set cursorcolumn"?


If you like the idea of cursorline, take a look at this snippet I found while searching dot files: https://github.com/darnir/dotfiles/blob/eb26d9a0f3df1650df0e...


LOL that was my exact thought. Added to .vimrc. But will never get back all the time lost trying to make sure I was at proper indent level.


I highly highly recommend always using a linter/formatter that just fixes this for you


Python. Indention matters. Unless there is a linter that can tell intent (and maybe there is on that offers an option?) indention can be the difference between once and forever.


Is it me, or does cursorcolumn really give Vim a bit of a sluggish feel?


It's not just you. I noticed it a few months ago and ended up disabling cursorline entirely. It seems to be caused by an intersection of cursorline and specific syntax highlighting rules (it happens for me in Elixir, but not in Ruby, for example). Honestly, while line highlighting is nice, I can't be bothered figuring out the way through it.

https://www.reddit.com/r/vim/comments/6onaui/vim_getting_slo...

is at least one exploration.


Having a free day, it's cold and rainy, but this actually made me come out of bed to crank up vim :-)


I use vim bindings in visual studio and do a lot of custom binding to resharper functionality. It's quite magic, the only thing I really miss from Vim is easy motion and the vim emulation is not complete so for some editing tasks I have to open a file in Vim.


For anyone wanting to peruse another large vim setup (mostly C++ and Clojure): https://github.com/jeaye/vimrc


I dont use fzf but CtrlP for vim is also very good at fuzzy search.


CtrlP enables my habit of having gazillions of buffers open when working on large projects. It’s great with splits.


CtrlP is nice but pretty slow. You can try ripgrep with CtrlP using:

if executable('rg')

  let g:ctrlp_user_command = 'rg %s --files --color=never --glob ""'

  let g:ctrlp_use_caching = 0
endif


CtrlP is much slower when indexing large directories.


When you say large, how large is that?


I have a directory with about 40,000 java files. It takes 11 seconds for ctrlp to finish indexing (without using cache). Fzf finished it before I start counting.


CtrlP works great with Windows VIM!


i find unite.vim very useful

https://github.com/Shougo/unite.vim

geezk7 6 months ago [flagged]

Do you even emacs bro?


We've banned this account for repeatedly posting unsubstantive and uncivil comments to HN.

If you don't want to be banned, you're welcome to email hn@ycombinator.com and give us reason to believe that you'll follow the rules in the future.




Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact

Search: