Code Self Study Forum

Vim Tips Thread

If anyone hasn’t discovered it yet, gq is a useful Vim command for wrapping lines.

It lets you write long lines without thinking about the number of characters. When finished typing, visually highlight the lines (shift-v and move up or down to select the text to reformat), and then type gq to wrap it.


I also have this in my ~/.vimrc file:

" Use par for better `gq` formatting
" See
set formatprg=par
let $PARINIT = 'rTbgqR B=.,?_A_a Q=_s>|'

(gq should work in Emacs/Evil too.)

I’m writing some Python lately, and it’s useful, because PEP8 doesn’t like lines to be more than 79 characters long, and my editor complains…

I didn’t watch the video below, but I liked the auto-complete tips from the slides.

(in insert mode)

  • type ctrl-x ctrl-f to show a dropdown menu with auto-completed filenames.
  • ctrl-x ctrl-] completes from tags.
  • ctrl-x ctrl-n completes from names in the current file
  • ctrl-n completes for anything specified by the “complete” option

ctrl-p (previous) and ctrl-n (next) move up and down the menus.

The video might have more information.

I finally have Denite set up the way I want, and it’s great. I pasted my denite config from .vimrc below. RipGrep is installed.

" Denite ideas from and elsewhere.
" reset 50% winheight on window resize
augroup deniteresize
  autocmd VimResized,VimEnter * call denite#custom#option('default',
        \'winheight', winheight(0) / 2)
augroup end

call denite#custom#option('default', {
      \ 'prompt': '❯'
      \ })

call denite#custom#var('file_rec', 'command',
      \ ['rg', '--files', '--glob', '!.git', ''])
call denite#custom#var('grep', 'command', ['rg'])
call denite#custom#var('grep', 'default_opts',
      \ ['--hidden', '--vimgrep', '--no-heading', '-S'])
call denite#custom#var('grep', 'recursive_opts', [])
call denite#custom#var('grep', 'pattern_opt', ['--regexp'])
call denite#custom#var('grep', 'separator', ['--'])
call denite#custom#var('grep', 'final_opts', [])
call denite#custom#map('insert', '<Esc>', '<denite:enter_mode:normal>',
call denite#custom#map('normal', '<Esc>', '<NOP>',

" ctrl-v and ctrl-h to open files in vertical and horizontal splits
call denite#custom#map('insert', '<C-v>', '<denite:do_action:vsplit>',
call denite#custom#map('normal', '<C-v>', '<denite:do_action:vsplit>',
call denite#custom#map('insert', '<C-h>', '<denite:do_action:split>',
call denite#custom#map('normal', '<C-h>', '<denite:do_action:split>',
call denite#custom#map('normal', 'dw', '<denite:delete_word_after_caret>',

" ctrl-n and ctrl-p to move down and up the denite menus
call denite#custom#map('insert', '<C-n>', '<denite:move_to_next_line>', 'noremap')
call denite#custom#map('insert', '<C-p>', '<denite:move_to_previous_line>', 'noremap')

" ctrl-p to find files
nnoremap <C-p> :<C-u>Denite file_rec<CR>

" leader-s to find buffers
nnoremap <leader>s :<C-u>Denite buffer<CR>
nnoremap <leader><leader>s :<C-u>DeniteBufferDir buffer<CR>

" leader-8 to grep for current word
nnoremap <leader>8 :<C-u>DeniteCursorWord grep:. -mode=normal<CR>

" leader-/ to grep
nnoremap <leader>/ :<C-u>Denite grep:. -mode=normal<CR>
nnoremap <leader><leader>/ :<C-u>DeniteBufferDir grep:. -mode=normal<CR>
nnoremap <leader>d :<C-u>DeniteBufferDir file_rec<CR>
nnoremap <leader><leader>r :<C-u>Denite -resume -cursor-pos=+1<CR>

" leader-o to load custom menu
nnoremap <leader>o :<C-u>Denite menu<CR>

hi link deniteMatchedChar Special

" Add custom menus
let s:menus = {}

let s:menus.config_files = {
    \ 'description': 'Edit config files'
    \ }

" quick access to config files
let s:menus.config_files.file_candidates = [
    \ ['.aliases', '~/.aliases'],
    \ ['.zshenv', '~/.zshenv'],
    \ ['.zshrc', '~/.zshrc'],
    \ ['.vimrc', '~/.vimrc'],
    \ ['.i3conf', '~/.config/i3/config'],
    \ ['.i3status.conf', '~/.i3status.conf'],
    \ ['.ctags', '~/.ctags'],
    \ ['global .gitconfig', '~/.gitconfig'],
    \ ['global .gitignore', '~/.gitignore'],
    \ ['.muttrc', '~/.muttrc'],
    \ ['.npmrc', '~/.npmrc'],
    \ ['.mongojsrc.js', '~/.mongojsrc.js'],
    \ ['.psqlrc', '~/.psqlrc'],
    \ ['.pgpass', '~/.pgpass'],
    \ ['.pythonrc', '~/.pythonrc'],
    \ ['.tmux.conf', '~/.tmux.conf'],
    \ ['.tern-config', '~/.tern-config'],
    \ ['.vuerc', '~/.vuerc'],
    \ ['.xinitrc', '~/.xinitrc'],
    \ ['.Xmodmap', '~/.Xmodmap'],
    \ ['.taskbook.json', '~/.taskbook.json'],
    \ ]

" let s:menus.vim = {
"     \ 'description': 'Edit Vim config files'
"     \ }
" let s:menus.vim.file_candidates = [
"     \ ]

" let s:menus.vim.command_candidates = [
"     \ ['Split the window', 'vnew'],
"     \ ['Open zsh menu', 'Denite menu:zsh'],
"     \ ]

call denite#custom#var('menu', 'menus', s:menus)

These are all pretty interesting, but why are they in private discussions?

The forum was originally private. When I opened it up to the public, I moved most of the existing posts into a private section, because people may have posted with the assumption that their posts would not be exposed to search engines.

I can see that. In the case of this thread though, I think it is really informative, and seems to be only your posts, so I say make it public! :slight_smile:

1 Like

Done :slight_smile:

1 Like

A post was split to a new topic: Which-key for Vim and Emacs

Here’s another post with tips:

Security problem

It looks like it can be fixed by putting this in your .vimrc and updating vim/neovim:

set nomodeline

This cheatsheet looks good.

Have you seen exuberant ctags before? Navigation is identical to help file syntax, eg ctrl-} and ctrl-t will be 90% of what you need. Works better for static languages but I’ve had luck with Python and PHP as long as I’m not too clever. $ctags -R * will get you a “tags” file in the CWD and vim will automagically parse it when you open it in the same directory.

1 Like

I use them. One thing I wish I could do is get it to keep the tags files out of my project. I have a line in my default .gitignore, but sometimes I forget to keep them out of the build, or they use up a lot of hard drive space. One of my small browser extensions was 300 MB until I realized that it was copying the tags file into the build. :thinking:

I just ran this command to delete my tags files and freed up more than 3 GB on my hard drive.

$ find . -type f -name tags -exec rm -fv "{}" \;

(I’m not sure how safe the command is, because there might be other files named tags, but I haven’t broken anything with it yet.)

That seems unreasonably high:

rw-rw-r-- 1 dale dale 44K Jan 25 23:57 tags

Granted this project isn’t that large. Even a 300mb tag file seems weird. A character is probably a byte in your encoding so you’re looking at 300 million characters in a tag file? Or 3 BILLION characters on your machine. If that’s not in error, that’s just amazing.

Out of curiosity, exactly equivalent on my machine:
± |feature/dale/memoryattempt2 U:5 ✗| → wc -m tags
44928 tags

2020-01-26 00:02:48 :watch: dale-G3-3779 in ~/local/game
± |feature/dale/memoryattempt2 U:5 ✗| → ls -l tags
-rw-rw-r-- 1 dale dale 44928 Jan 25 23:57 tags

I just tried it in a new Gatsby JS site that I was using to test a Docker setup, and it went from 19 KB to 356 MB as soon as I opened the gatsby-config.js file. :grimacing:

ctags vim 356 MB

I’m guessing that it’s from the dependencies in the node_modules directory.

npm list | grep -v deduped | wc -l shows 2,097 lines of output.

Oh node, sigh

That’s amazing. I suppose if you are ctagging into the dependency code you may want to use this.

1 Like

I wonder if there is a way to ignore the node_modules directory.

It looks like I can do something like this, but I’ll have to figure out how vim is running the command.

$ ctags -R --exclude=.git --exclude=node_modules --exclude=test

I learned a Vim trick for inserting repeated characters in insert mode.

ctrl+o runs a normal mode command from insert mode. For example, to add a line of 80 slashes, you can do:

ctrl+o 80i/ESC

So to get a comment block like this (except 80 characters wide), use that above command to make the first line and then hit yypO:

// █

Then type your comment.

Reference for the commands used:

  • yy – copies the current line
  • p – pastes what you just copied
  • shift+o – opens a line in insert mode

Also, I usually open new Vim tabs with :tabnew, but in these videos I saw the instructor open a new tab with :tabe. So I looked at the help file (:h tabe) and there is a lot of interesting stuff in there. You can tell Vim exactly where you want the new tab to open (like :3tabe), or what kind of command to run in the new tab.

Just press ESC and type this for the docs:

:h tabe