syntax highlight

Showing posts with label Vim. Show all posts
Showing posts with label Vim. Show all posts

Tuesday, 11 June 2019

The bestest autocomplete for Vim

TL;DR: I like YouCompleteMe

A post in Hacker News drew me to look at autocompletion in Vim. After trying a few plugins years before, I settled for the available-by-default autocomplete in Vim. It's pretty dumb, but pretty dumb covers 90% of what I need: autocompletionForReallyUglyOrLongNames.

Vim's omnifunc completer is enough if no fancy features are necessary: fast, available, trivial to setup. I have successfully used omnifunc in fairly large projects, and while it requires familiarity with the codebase, some may argue that's a feature and not a bug.

Now I confess: I don't understand Vundle, Pathogen or any other Vim plugin handler. Second extravagant opinion in this post: I don't see the point of a plugin manager for Vim. I like knowing the source code of every plugin I use well enough so I can troubleshoot it when it breaks (*). I prefer to #include (or, rather, source) them manually. Keeping everything in Github, I rarely need to set up a plugin twice. The effort to install and configure a plugin is usually not a lot more than learning how to use that plugin in the first place.

While being Vundle illiterate may have made my experience a bit more complicated than necessary, I still found the experience of installing autocompletion plugins quite horrible (#). Deoplete had me chasing dependencies all over the place and Conquer of Completion seems to require such specific setup of version and plugins that I didn't even attempt to install it.

YouCompleteMe, though, was a pleasant surprise: its documentation explained how to install in three steps, and it is a mostly self-contained plugin. While YCM has a compiled dependency, setting it up is pretty trivial. It just works out of the box.

Took me years but I'm very happy to finally find an autocomplete plugin that "just works" for my basic Vim setup.

(*) For some reason, I only feel this way about Vim
(#) Disclaimer: Re-reading my own text, it may appear as I'm somewhat belittling Deoplete, CoC, Vundle, Pathogen, etc. That's not my intention. I have the maximum respect for these projects. The engineering effort in them is amazing, and I know for a fact they make life easier for a lot of people. I'm just not one of them.

Thursday, 1 December 2016

Simple vim plugin IV: project greping

I recently wrote about some of the utilities I created for my Vim setup. Using someone else's Vim scripts is not nearly as fun as writing your own, so I decided to also write a short summary on what it takes to get started writting Vim plugins. For this task, I decided to start with greping.

Greping can be improved a bit: if you do it a lot in a project, you might find it's useful to also grep the results themselves, to further refine your search. If you have your grep results in vim itself, that is trivial.

Let's start hacking something in our .vimrc file. Try this:

function! FG_Search()
    let needle = input("Search for: ")
    tabnew
    setlocal buftype=nofile bufhidden=wipe nobuflisted noswapfile nowrap
    let grepbin = 'grep -nri '
    let cmd = grepbin . ' "' . needle . '" *'
    execute '$read !' . cmd
    setlocal nomodifiable
endfunction

map <leader>s :call FG_Search()<CR>

This function should be pretty clear: it will map <leader>s (in my case, ",s") to FG_Search(). FG_Search will prompt the user for a term to grep, then search for it executing the command. In the end the results are written to a new tab, which is declared as a temp non-modifiable buffer.

Just paste that in your .vimrc and you're good to grep.

Extra tip: integrate this with my fast grep cache and you have a nice and quick project search integration for vim that works even for very large projects with tools available in most default Linux installs.

Wednesday, 30 November 2016

Simple vim plugin III: a polymorphic project greper

We've recently seen a very basic function to integrate grep to vim. We can improve it a little bit with very simple changes. Using this tip to have different key binding for different modes we can do something a bit smarter . Let's create two functions, one for normal mode that should prompt the user what to search for, and another function to automagically pick whatever is selected:

function! FG_DoSearch(needle)
    let grepbin = 'grep -nri '

    tabnew
    setlocal buftype=nofile bufhidden=wipe nobuflisted noswapfile nowrap
    let cmd = grepbin . ' "' . a:needle . '" *'
    execute '$read !' . cmd
    setlocal nomodifiable
endfunction

function! FG_Search()
    let needle = input("Search for: ")
    call FG_DoSearch(needle)
endfunction

function! FG_Visual_Search()
    " Copy whatever is selected in visual mode
    try
        silent! let a_save = @a
        silent! normal! gv"ay
        silent! let needle = @a
    finally
        silent! let @a = a_save
    endtry

    call FG_DoSearch(needle)
endfunction

nmap <leader>s :call FG_Search()<CR>
vmap <leader>s :call FG_Visual_Search()<CR>

The magic here happens in the mapping: nmap will create a mapping that's only enabled when on "normal" mode, vmap when you're in visual mode. As usual, check :help map for more details.

Tuesday, 29 November 2016

Simple vim plugin II: a psychic project greper

We have been working on a quick grep integration for Vim, and it's looking decent enough for a quick plugin. There's one more easy thing we can improve, though: let's make it psychic! So far we had to tell grep what to look for, either by selecting the text in visual mode or by actually typing the search terms. Typing! That's so old fashioned. Let's make grep guess what to look for.

In vim you have a psychic function, expand(""). If you call expand(""), it will return whatever word is under the cursor. No need to visually select it. If you're still using the same vimrc definitions, you can do something like

nmap s :call FG_DoSearch(expand(""))

Let's clean things up a little bit:

" Wrap a grep command: search for needle, show results in a new window
function! FG_DoSearch(needle)
    let grepbin = 'grep -nri '

    tabnew
    setlocal buftype=nofile bufhidden=wipe nobuflisted noswapfile nowrap
    let cmd = grepbin . ' "' . a:needle . '" *'
    echom cmd
    execute '$read !' . cmd
    setlocal nomodifiable
endfunction

" Wrap a normal action: ask the user for input, then call func with it
function! FG_RequestInputAction(msg, func)
    let needle = input(a:msg)
    if strlen(needle) > 0
        execute 'call' a:func .'("'. needle . '")'
    endif
endfunction

" Wrap a visual action: call func with whatever is selected under the cursor
function! FG_VAction(func)
    " Copy whatever is selected in visual mode
    try
        silent! let a_save = @a
        silent! normal! gv"ay
        silent! let needle = @a
    finally
        silent! let @a = a_save
    endtry

    " Remove whitespaces
    let needle = substitute(needle, "\\n\\+","","g") 
    let needle = substitute(needle, "\\r\\+","","g") 
    let needle = substitute(needle, "^\\s\\+\\|\\s\\+$","","g") 

    if strlen(needle) > 0
        execute 'call' a:func .'("'. needle . '")'
    endif
endfunction

" Wrap a normal action: call func with whatever is under the cursor
function! FG_NAction(func)
    let needle = expand("<cword>")
    if strlen(needle) > 0
        execute 'call' a:func .'("'. needle . '")'
    endif
endfunction

nmap <leader>s :call FG_NAction("FG_DoSearchText")<CR>
vmap <leader>s :call FG_VAction("FG_DoSearchText")<CR>
map  <leader>S :call FG_RequestInputAction("Text search: ", "FG_DoSearchText")<CR>

Just copy paste that in your vimrc, now you can grep your project in three different ways: press s (,s) to look for the word currently under the cursor, S to type in a search term or select something in visual mode, then S to grep it.

Thursday, 24 November 2016

Simple vim plugin I: integrating new commands

TL;DR: Here's some code to integrate system commands into vim. You can just drop it in your vimrc, create a small wrapper function in your vimrc and configure a few key binding to make it work.

Longer version:
We can extend our quick grep integration to other commands, quite easily. Since we defined a few wrappers to request input, get it from visual mode or just guess it, we can also have a helper function to create a scratch buffer and read a system command into it:

" Find&amp;Grep command wrapper: execute cmd, shows the results in a scratch buffer
function! FG_EvalSysCmdInNewBuff(cmd)
    tabnew
    setlocal buftype=nofile bufhidden=wipe nobuflisted noswapfile nowrap
    execute '$read !' . a:cmd
    setlocal nomodifiable
endfunction

" Wrap a normal action: ask the user for input, then call func with it
function! FG_RequestInputAction(msg, func)
    let needle = input(a:msg)
    if strlen(needle) &gt; 0
        execute 'call' a:func .'("'. needle . '")'
    endif
endfunction

" Wrap a visual action: call func with whatever is selected under the cursor
function! FG_VAction(func)
    " Copy whatever is selected in visual mode
    try
        silent! let a_save = @a
        silent! normal! gv"ay
        silent! let needle = @a
    finally
        silent! let @a = a_save
    endtry

    " Remove whitespaces
    let needle = substitute(needle, "\\n\\+","","g")
    let needle = substitute(needle, "\\r\\+","","g")
    let needle = substitute(needle, "^\\s\\+\\|\\s\\+$","","g") 

    if strlen(needle) &gt; 0
        execute 'call' a:func .'("'. needle . '")'
    endif
endfunction

" Wrap a normal action: call func with whatever is under the cursor
function! FG_NAction(func)
    let needle = expand("&lt;cword&gt;")
    if strlen(needle) &gt; 0
        execute 'call' a:func .'("'. needle . '")'
    endif
endfunction

Integrating any new command into our plugin is now trivial. Let's do it for grep and for find:

" Wrap a find command: search for file "needle", show results in a new window
function! FG_DoFindFile(needle)
    let cmd = 'find -type f -iname "*' . a:needle . '*"'
    call FG_EvalSysCmdInNewBuff(cmd)
endfunction

" Wrap a grep command: search for needle, show results in a new window
function! FG_DoSearchText(needle)
    let cmd = 'grep -nri "' . a:needle . '" *'
    call FG_EvalSysCmdInNewBuff(cmd)
endfunction
Then just add a few key bindings and you're good to go:
gt;f :call FG_NAction("FG_DoFindFile")&lt;CR&gt;
vmap &lt;leader&gt;f :call FG_VAction("FG_DoFindFile")&lt;CR&gt;
map  &lt;leader&gt;S :call FG_RequestInputAction("Text search: ", "FG_DoSearchText")&lt;CR&gt;

nmap &lt;leader&gt;s :call FG_NAction("FG_DoSearchText")&lt;CR&gt;
vmap &lt;leader&gt;s :call FG_VAction("FG_DoSearchText")&lt;CR&gt;
map  &lt;leader&gt;F :call FG_RequestInputAction("Find file: ", "FG_DoFindFile")&lt;CR&gt;

This is an actual plugin I use in my Vim setup. You can grab the latest version from my Github repo.

Extra tip: add these too if you want to have a GUI menu for your new commands as well.

menu Project.Find\ File :call FG_RequestInputAction("FG_DoFindFile")
menu Project.Text\ Search :call FG_RequestInputAction("FG_DoSearchText")

Wednesday, 6 July 2016

Vim utilities: Findgrep & Fastgrep

I spent some time writing utility scripts for my Vim setup. I figured I can share them here, someone may even find them useful or at least get a laugh out of it. Last time I presented "Impl switcher", and "Better Tab New" before that. Today it's Findgrep & Fastgrep's turn.

I wrote about Fastgrep a long time ago. The idea behind it is to speed up the slowest part in a grep command, the disk seek time, by creating a huge blob file with all the files in a project concatenated.

Fastgrep works great. But it requires a context switch, going from your IDE to your console just to grep. Findgrep fills the gap between the IDE and the command line: this utility provides a few key bindings to let you quickly run some common commands, like searching for a selected string or finding a file in the project directory.

You can get Fastgrep here. Findgrep is available in Github, and you can easily replace Fastgrep with normal grep if you need to.

Monday, 4 July 2016

Vim utilities: Impl switcher

I spent some time writing utility scripts for my Vim setup. I figured I can share them here, someone may even find them useful or at least get a laugh out of it. Last time I presented "BTN: Better Tab New". Today it's the turn for "Impl switcher".

With its very imaginative name, "Impl switcher" has a very obvious purpose: it will just switch from a header file to an implementation file. So, between .h and .cpp. Surely there are lots of Vim plugins to do just that, why write another one?

Most impl-switcher plugins in the wild tend to, in my experience, require either a lot of configuration, a lot of dependencies, or a very specific project layout (or a combination of all three). They also seem to be huge and very complicated projects.

Impl switcher will recursively go up your directory hierarchy and use "find" to locate any files named like your base file but with a different extension. That makes it very simple and it requires minimal (if any) configuration: just drop it in your .vimrc file and you're good to go. OK, not exactly: it requires a Linux-like system with utilities like "find". Still, a good trade-off to keep the project's dependencies as small as possible.

Get "impl swicher" here:

Friday, 1 July 2016

Vim utilities: Better Tab New

I spent some time writing utility scripts for my Vim setup. I figured I can share them here, someone may even find them useful or at least get a laugh out of it. The first one is called "Better Tab New" and you can get it from my Github repo or from the script's Vim page.

Why would you want a better tab new, and what's wrong with the default one? Simple: tabnew, in Vim, will just open a file. For that to happen you need to specify the exact path of a file. That's usually perfectly fine, but sometimes you need tabnew to be a bit smarter: maybe you just grep'ed something and ended up with a path that looks like "/foo/bar/baz:my_text:42". Or maybe you want to open a file and go to a specific line. Those are things for which the default tabnew implementation isn't very good. BTN fills that niche and lets you create a simpler workflow when using grep.

Get BTN: Better Tab New here:

Thursday, 18 April 2013

Learning misspells: thanks Vim!

I just noticed a very silly "pattern" I usually fall into: since I like vim (perhaps a bit too much) to work with text, even free-form text like this blog post, most of the times I type a lot of text which then must be spell checked (so far I haven't found a spell checking extension I like for vim). While spell checking I correct the original text in vim, and to do this I usually search for the mispel in Vim, thus typing the wrong spelling one more time. This has the side effect of reinforcing the bad spell instead of forcing me to type the correct spelling.

I wonder how can I fix this problem without a spellchecker for vim.

Thursday, 12 May 2011

Just to remind you

It's been too long since the last time this image appeared on my blog:

Thursday, 2 September 2010

Vim Sexual Care

Vim bestows its users all sort of magical properties, among which now we can count increased sexual performance. I bet you didn't know, but Vim can help you keep your girl happy for days without end. Don't believe me? Check this page.

Wednesday, 23 June 2010

Nooooooooooo

(gvim:13664): Gdk-CRITICAL **: gdk_window_get_user_data: assertion `GDK_IS_WINDOW (window)' failed
Vim: capté una señal de muerte SEGV
Vim: finalizado.

Saturday, 4 July 2009

Sunday, 14 June 2009

Vim Tip: Easy Indent

Editing source code means you'll be doing a lot of indenting and reindenting. There's an easy way to indent or de-indent a block, using just "<" and ">".

Using ">" without anyother command will indent that line by itself; use visual mode (Shift + V) to select several lines and indent them in one keystroke. You could also press "v%>" while sitting at the beggining of a block to indent it. The same applies to "<".

 

Thursday, 11 June 2009

vimrc: Vim startup file

I usually create a partition for /home, so whenever I decide to foobar my OS (i.e. do a kernel update on Ubuntu, or start playing with compiz too much) there's no need to copy my home folder to another disk and back again. Regardless of this, there are some essential files which I'd be dead without. One of these is my .vimrc, the startup file for Vim.

My .vimrc file has been organically growing since I started using this editor, a couple of years ago, so I've decided to clean it up a little bit and post it here, just to be sure I won't be loosing it. It's got some tweaks to use Vim as an IDE, feel free to download it and change it or use it anyway you want.

colorscheme torte
set nocompatible
syntax on
set ruler
set number
set hls     " Highlight search results
set showmatch " Show matching () {} []
set wildmode=list:longest,full  " Use tab-completition
set mouse=a       " Always use the mouse
" Set the working directory to the directory of the current file.
autocmd BufEnter * lcd %:p:h

" Allow movement to another buffer without saving the current one
set hidden

" *********** Text formatting *************
set nowrap
set beautify
set shiftwidth=3
set tabstop=3

filetype on
filetype plugin indent on
" *********** Search & replace *************
set ignorecase " case insensitive
set smartcase " case insensitive only if there is no uppercase
set incsearch " incremental seach
set gdefault " default to /g on replace

" Load matchit (% to bounce from do to end, etc.)
runtime! macros/matchit.vim

augroup myfiletypes
 " Clear old autocmds in group
 autocmd!
 " autoindent with two spaces, always expand tabs
  autocmd FileType ruby,eruby,yaml set ai sw=2 sts=2 et
augroup END

" display the current mode and partially-typed commands in the status line:
set showmode
set showcmd

set autoindent
set smartindent
" Show an error window (if there are errors)
cwindow

" *********** Mappings *************
" Ctrl-t: Write tabnew (wait for filename and )
map  :tabnew
" Alt-R: Exec current file as script
map  :!.%
" Ctrl-Alt-R
map  :tabnew:make
" Spellcheck
map  :!ispell -x %:e!
" Comment a line
map  0i//
map  0xxx

" Build for a LaTeX file (assumes correct path and makefile)
autocmd filetype tex map  :w:make

" Automatic closing
kets
inoremap do{ do{}while();O
inoremap do{ do{}while();O
inoremap { {}O

Friday, 22 May 2009

Vim: Success

The other day I convinced someone Vim is THE true editor.



Success
Disclaimer: I love that image and would have found other excuse to use it