Friday, October 29, 2010

Keep your VIM updated with VAM

I'm a huge fan of VIM. In fact, that's one of the main reason I've developed VoraX. However, I still feel that I have a lot to learn, but that's the beauty of this beast.

One thing that I always considered annoying is the installation of a fresh VIM. I use Unix and Windows boxes. On both VIM is a MUST-HAVE editor. To install the standard package is not a big deal: you just use your distro repository or, on Windows, you download the installer, next, next, next and you're done! But, wait a minute! Where are my killer plugins, and those neat mappings I customized for myself? And hey, I don't want the default color-scheme either. Okey, it's clear I have a problem because the installation of VIM cannot be considered finished until I have all my plugins and settings in place.

The quick and dirty method would be to copy all plugins along with the .vimrc file from a computer where's everything is in place. Whiles this always work without a problem it has a major drawback: it's difficult to maintain all these files across many computers. For example, at work it happens to discover a new cool vim setting which I put it right away in my .vimrc. Then I go home and when I open VIM from my personal computer I discover it looks different. This means I have to access the .vimrc file from my office and then to manually synchronize those files. That's so ugly!

So, at that point was clear that I needed a central repository to put those files and to access them in a shared way. I goggled to see how other people solved that and I find out that many prefer using a SCM repository. That seemed to be a solution, so I subscribed to a free SVN account on http://www.xp-dev.com/ and I put all my plugins and my .vimrc file there. This approach was fine but I found it cumbersome to use. First of all, installation of a new plugin was not so easy because you had to download it, to put it into the right location under your vim runtime path and then to also add those files to the SVN and then to commit. As far as .vimrc was concerned it also happened to change something and then to simply forget to commit the change. A SCM is the right solution for source code but not so good for my VIM plugins/.vimrc management... so I kept searching...

The good news is that I ended up with a nice solution I want to share with you. First of all, forget SVN and other source repositories and give a shot to Dropbox. It is a file sharing repository with automatic synchronization across computers. You may access your files from Windows, Unix, Mac... basically from everywhere. A change on a file maintained by Dropbox is automatically synchronized so there's no need to commit anything. And the basic functionality is provided for free. So, we have a nice shared repository where we are going to put our .vimrc file.

Usually vim expects to find .vimrc in a certain location which, for sure, is not into the Dropbox folder. Nevertheless, you can always create a symbolic link for your .vimrc to the one from your Dropbox folder. For example, on my Ubuntu box I can use:
cd ~
ln -s Dropbox/.vimrc .vimrc
On Windows it's not so easy because of the leak of the symbolic link functionality for files. The only option you have is to create hard links. For example, on my XP system I've downloaded the coreutils package and then I've created a link like this:
ln "c:\Documents and Settings\alec.FITS\My Documents\My Dropbox\.vimrc" "c:\Documents and Settings\alec.FITS\.vimrc"
It's also possible to use fsutil tool:
cd %HOME%
fsutil hardlink create .vimrc "C:\Documents and Settings\alec.FITS\My Documents\My Dropbox\.vimrc"
There is a problem however with this hard link on Windows: the changes on the underlying dropbox file are not correctly propagated. My assumption is that Dropbox synchronize the changed files by deleting the old file and recreating it afterwords. The side effect is that our hard link is broken and will not point to the dropbox .vimrc file anymore. The only solution I found is to create a dummy .vimrc file which source the .vimrc file from my dropbox folder. For example, you may put this into your $HOME/.vimrc:
exe 'source ' . expand('$HOME') . '\My Documents\My Dropbox\.vimrc'
Great! Now, we have one single copy of the .vimrc, shared by more than one computer. You might say: hey, let's put the plugins too into our nice Dropbox. We can, but I have a better solution. Let's use a plugin management engine for Vim.

There are a few such vim addons which provide plugins management like: Vimana, Vim Script Management System or Vundle. However, the best I like is VAM (Vim Addons Management). It's actively developed and you get quick feedback in case of troubles. Mark Weber has done a great job with this add-on. You can automatically install/update various plugins and because VAM puts every new installed plugin into its own directory is quite easy to uninstall them by simply deleting the corresponding folder. Those who already use Pathogen should be familiar with this concept.

Now, the best thing out of this is the fact that you can basically have just the .vimrc around and the rest will be done by VAM, even when you are running a fresh installation of Vim. If you're using plugins published on vim.org then a plain curl and the proper tools to unpack the downloaded archives are enough, but VAM also provides the possibility to install plugins via git, mercurial or subversion. However, all these are nicely explained by the VAM documentation.

Another cool feature of VAM is that it maintains a so-called well known plugins repository. Using it you may install whatever plugin you want without knowing where it's located, if is provided as a zip archive or as a vba etc. You simply don't care. Whiles this repository is very handy to install and to experiment with various plugins I tend to avoid it on my “production” Vim. The main reason is because some bundles have ugly names. For example, SQLUtilities plugin can be found under the “SQLUtilities_-_SQL_utilities_-_Formatting_generate” name which means it will be installed into that long ugly directory. That's not VAM fault, it's because the list of vim plugins is automatically generated based on the script names provided by their own developers on vim.org site.

So, instead of relying to the well know plugins repository I like to stick to a fixed list of plugins, manually specified into my .vimrc file. Below is how my .vimrc starts:

" Maintainer: talek
" Version: 2.0 - 29/10/10 10:45:58
" Description: configuration for vim

" We don't want vi compatibility.
set nocompatible

" Activate Addons Management
let g:vim_script_manager = { 'known_repos_activation_policy' : 'never', 'auto_install' : 1, 'plugin_sources' : {} }
let g:vim_script_manager.plugin_sources['nerd_commenter'] = {'type': 'git', 'url': 'git://github.com/scrooloose/nerdcommenter.git'}
let g:vim_script_manager.plugin_sources['surround'] = {'type': 'git', 'url': 'git://github.com/tpope/vim-surround.git'}
let g:vim_script_manager.plugin_sources['repeat'] = {'type': 'git', 'url': 'git://github.com/tpope/vim-repeat.git'}
let g:vim_script_manager.plugin_sources['supertab'] = {'type': 'git', 'url': 'git://github.com/ervandew/supertab.git'}
let g:vim_script_manager.plugin_sources['align'] = {'version': '35/41', 'url': 'http://www.vim.org/scripts/download_script.php?src_id=10110', 'vim_version': '7.0', 'date': '2009-03-04', 'vim_script_nr': 294, 'type': 'archive', 'script-type': 'utility', 'archive_name': 'Align.vba.gz', 'author': 'Charles Campbell'}
let g:vim_script_manager.plugin_sources['sqlutil'] = {'version': '4.00', 'url': 'http://www.vim.org/scripts/download_script.php?src_id=13576', 'vim_version': '7.0', 'date': '2010-08-15', 'vim_script_nr': 492, 'type': 'archive', 'script-type': 'utility', 'archive_name': 'sqlutil_400.zip', 'author': 'David Fishburn'}
let g:vim_script_manager.plugin_sources['taglist'] = {'version': '4.5', 'url': 'http://www.vim.org/scripts/download_script.php?src_id=7701', 'vim_version': '6.0', 'date': '2007-09-21', 'vim_script_nr': 273, 'type': 'archive', 'script-type': 'utility', 'archive_name': 'taglist_45.zip', 'author': 'Yegappan Lakshmanan'}
let g:vim_script_manager.plugin_sources['fuzzyfinder'] = {'type': 'hg', 'url': 'http://bitbucket.org/ns9tks/vim-fuzzyfinder'}
let g:vim_script_manager.plugin_sources['nerd_tree'] = {'version': '4.1.0', 'url': 'http://www.vim.org/scripts/download_script.php?src_id=11834', 'vim_version': '7.0', 'date': '2009-12-01', 'vim_script_nr': 1658, 'type': 'archive', 'script-type': 'utility', 'archive_name': 'NERD_tree.zip', 'author': 'Marty Grenfell'}
let g:vim_script_manager.plugin_sources['L9'] = {'type': 'hg', 'url': 'http://bitbucket.org/ns9tks/vim-l9'}
let g:vim_script_manager.plugin_sources['xptemplate'] = {'version': '0.4.8-r994', 'url': 'http://www.vim.org/scripts/download_script.php?src_id=13740', 'vim_version': '7.2', 'date': '2010-09-01', 'vim_script_nr': 2611, 'type': 'archive', 'script-type': 'utility', 'archive_name': 'xpt-0.4.8-r994.tgz', 'author': 'drdr xp'}
let g:vim_script_manager.plugin_sources['xptemplate']['strip-components'] = 0
let g:vim_script_manager.plugin_sources['command-T'] = { 'type' : 'git', 'url' : 'git://git.wincent.com/command-t.git' }
let g:vim_script_manager.plugin_sources['tcalc'] = {'version': '0.11', 'url': 'http://www.vim.org/scripts/download_script.php?src_id=8028', 'vim_version': '7.0', 'date': '2007-12-05', 'vim_script_nr': 2040, 'type': 'archive', 'script-type': 'utility', 'archive_name': 'tcalc.zip', 'author': 'Tom Link'}
let g:vim_script_manager.plugin_sources['bufexplorer'] = {'version': '7.2.7', 'url': 'http://www.vim.org/scripts/download_script.php?src_id=12904', 'vim_version': '7.0', 'date': '2010-04-26', 'vim_script_nr': 42, 'type': 'archive', 'script-type': 'utility', 'archive_name': 'bufexplorer.zip', 'author': 'jeff lanzarotta'}
let g:vim_script_manager.plugin_sources['ack'] = {'type': 'git', 'url': 'http://github.com/mileszs/ack.vim.git' }
let g:vim_script_manager.plugin_sources['genutils'] = {'version': '2.5', 'url': 'http://www.vim.org/scripts/download_script.php?src_id=11399', 'vim_version': '7.0', 'date': '2009-09-17', 'vim_script_nr': 197, 'type': 'archive', 'script-type': 'utility', 'archive_name': 'genutils-2.5.zip', 'author': 'Hari Krishna Dara'}
let g:vim_script_manager.plugin_sources['matchit'] = {'version': '1.13.2', 'url': 'http://www.vim.org/scripts/download_script.php?src_id=8196', 'vim_version': '6.0', 'date': '2008-01-29', 'vim_script_nr': 39, 'type': 'archive', 'script-type': 'utility', 'archive_name': 'matchit.zip', 'author': 'Benji Fisher'}
let g:vim_script_manager.plugin_sources['arpeggio'] = {'type': 'git', 'url': 'http://github.com/kana/vim-arpeggio.git' }
let g:vim_script_manager.plugin_sources['minibufexplorer'] = {'version': '6.3.3', 'url': 'http://www.vim.org/scripts/download_script.php?src_id=13838', 'vim_version': '7.0', 'date': '2010-09-15', 'vim_script_nr': 3239, 'type': 'archive', 'script-type': 'plugin', 'archive_name': 'minibufexplpp.vim', 'author': 'Oliver Uvman'}
let g:vim_script_manager.plugin_sources['vorax'] = {'title': 'vorax', 'version': '2.5', 'url': 'http://www.vim.org/scripts/download_script.php?src_id=14147', 'vim_version': '7.0', 'date': '2010-10-02', 'vim_script_nr': 3154, 'type': 'archive', 'script-type': 'utility', 'archive_name': 'vorax-2.5.zip', 'author': 'Alexandru Tica'} 

func ActivateMyAddons()
let addons_base = substitute(expand('$HOME') . '/vim-addons', '\\\\\|\\', '/', 'g')
" check if addons_base folder is there
if finddir(addons_base, '') == ''
call mkdir(addons_base, '')
endif
let addons_manager = addons_base . '/vim-addon-manager'
exe 'set runtimepath+=' . escape(addons_manager, ' ')
if finddir(addons_manager) == ''
" The addons manager is not installed. Install it now!
exe 'cd ' . addons_base
exe '!git clone git://github.com/MarcWeber/vim-addon-manager.git'
endif
call scriptmanager#Activate(['nerd_commenter',
\  'surround',
\  'repeat',
\  'supertab',
\  'align',
\  'sqlutil',
\  'vorax',
\  'taglist',
\  'L9',
\  'fuzzyfinder',
\  'nerd_tree',
\  'genutils',
\  'bufexplorer',
\  'matchit',
\  'command-T',
\  'minibufexplorer',
\  'vorax',
\  'tcalc',
\  'arpeggio',
\  'ack',
\  'xptemplate'])
endfunc
call ActivateMyAddons()
As you can see I have a list of plugins I always want to have them installed. I just extracted their definition from the well know plugins repository and I've tailored the names to look nicer. For the complete list you may check this list.

If you rather want to go with the know-addons-repository and get up-to-date plugins then the following code should do the job:
" Maintainer: talek
" Version: 2.0 - 29/10/10 10:45:58 
" Description: configuration for vim

" We don't want vi compatibility.
set nocompatible 

" Activate Addons Management
let g:vim_script_manager = { 'known_repos_activation_policy' : 'autoload', 'auto_install' : 1 }

func ActivateMyAddons()
  let addons_base = substitute(expand('$HOME') . '/vim-addons', '\\\\\|\\', '/', 'g')
  " check if addons_base folder is there
  if finddir(addons_base, '') == ''
    call mkdir(addons_base, '') 
  endif
  let addons_manager = addons_base . '/vim-addon-manager'
  exe 'set runtimepath+=' . escape(addons_manager, ' ')
  if finddir(addons_manager) == ''
    " The addons manager is not installed. Install it now!
    exe 'cd ' . addons_base
    exe '!git clone git://github.com/MarcWeber/vim-addon-manager.git'
  endif
  call scriptmanager#Activate(['The_NERD_Commenter', 
                              \  'surround', 
                              \  'repeat', 
                              \  'supertab',
                              \  'Align294', 
                              \  'SQLUtilities_-_SQL_utilities_-_Formatting_generate',
                              \  'vorax',
                              \  'taglist',
                              \  'L9',
                              \  'fuzzyfinder',
                              \  'The_NERD_tree',
                              \  'genutils',
                              \  'bufexplorer.zip',
                              \  'matchit.zip',
                              \  'Command-T',
                              \  'minibufexpl.vim_-_Elegant_buffer_explorer',
                              \  'vorax',
                              \  'tcalc',
                              \  'arpeggio',
                              \  'ack',
                              \  'xptemplate'])
endfunc
call ActivateMyAddons()
Both methods above check if VAM is already installed and if not than it is fetched using git which, by the way, is the recommended way. This means git has to be available on your platform. So before going on, let's have a look at the external tools needed by VAM:
  1. on UNIX:
    • curl (e.g. apt-get install curl)
    • git-core (e.g. apt-get install git-core)
    • mercurial (e.g. apt-get install mercurial)
    • subversion (e.g. apt-get install subversion)
  1. on Windows:
That's it! If all of the above dependencies are installed and they are working fine then VAM should automatically install the specified plugins. This is huge because, from now on, you'll simply need to have just your .vimrc and VAM will do all the rest.

VoraX 2.5 Released

Hi guys! A new version of VoraX is available for download. As usual, I'm gonna post here what's new in this version.

First of all, VoraX is now able to display the output of a query using a vertical column layout. For those of you who don't like to horizontally scroll through very long lines (e.g. V$SESSION) this is, indeed, a nice feature. But, beyond this, there is also a practical need for such a functionality. It's kind of funny that the implementation of this vertical column layout feature was started because of an issue reported by Spratek, issue which has nothing to do with this "fancy" layout.

As you already know, Sqlplus is very peaky when comes to display BLOB content. The main issue is this stupid "SP2-0678: Column or attribute type can not be displayed by SQL*Plus" error. Damn it! It's a very annoying limitation and apparently this can't be solved that easy. Excluding BLOB columns using "column ... noprint" does not work therefore the only solution is to manually exclude those BLOB columns from your query which it means, of course, that you have to manually specify all the others. Bleah! The last solution was to use the DBMS_SQL package which helped to dynamically process the output of the query and get rid of the BLOB content, if any is present. So, if you have tables with BLOBs keep in mind that this might be your only solution to query them. The shortcut is <Leader>v1 (it's "one" not L) and you should use it only for single queries. Executing multiple queries within the same block is not supported.

Another improvement in this version is that you can now browse materialized views inside VoraX DbExplorer. This was requested by Ingo Olbrigh and might prove to be quite handy if you are working with these kind of objects.

There are also a few other minor improvements. One of them is that you can now control where to leave the focus after something is executed. Until now, the default behavior was to leave the focus into the results window. Starting with this version you may tell VoraX to return to the window from where the statement was executed (thanks Koelner.r for this suggestion). And that's not all. In addition you may now use matchit within your plsql buffers.

VoraX 2.5 comes also with a few bug fixes, already detailed in the changelog.

Have fun!

Update: Starting with 11.1, Sqlplus is smart enough to display BLOB columns without raising SP2-0678 errors. According to the Oracle documentation (New Features in SQL*Plus 11.1):
SQL*Plus supports standard querying of tables and objects containing BLOB and BFILE datatypes.

Saturday, October 2, 2010

VoraX 2.4

I've just released VoraX 2.4. It doesn't contain any new features, just a few bug fixes. You may take a look into the changelog if you are interested in more details.