Vim Tips Wiki
Tip 902 Printable Monobook Previous Next

created 2005 · complexity intermediate · author Feral · version 6.0

The Why[]

Some include paths (VC7 in particular) are very deep, so much so that I opted to "set complete-=i" (which is to say to not 'scan current and included files' during completion; see :help 'complete').

This allowed me to <ctrl+n>/<ctrl+p> without delay, and when I knew what I was trying to complete was in the system includes (sprintf for instance) I could use CTRL-X CTRL-I (see: :help i_CTRL-X_CTRL-I) as needed, for instance 'spr<ctrl-x><ctrl-i>'. This worked like a charm for many moons. Until recently when I've found a need to have a different set of includes to search and I wanted normal CTRL-N/CTRL-P to search these files and NOT the system include. I was also getting kind of tired of not searching the current directory via CTRL-N/CTRL-P as well.

Solution: aka Hair brained scheme #1[]

The concept is simple, search the path each time (i.e."set complete+=i", which is default) but limit what the path is.

I decided on a few global scoped variables to hold my paths and then a function/command to help set &path. Seemed easy enough. This is from my vimrc and as you can see it is a mess. It does (as far as I know!) function properly with no adverse effects, but I am very definitely not certain of that yet.

" Base path :".,,"
let g:feral_path_B = &path
" System include path
set path=C:/Program\\\ Files/Microsoft\\\ Visual\\\ Studio\\\ .NET\\\ 2003/Vc7/include/
set path+=C:/Program\\\ Files/Microsoft\\\ Visual\\\ Studio\\\ .NET\\\ 2003/Vc7/PlatformSDK/Include/
let g:feral_path_S = &path
" ClanLib include path
set path=C:/Program\\\ Files/ClanLib/include/
"" set path=C:/Program\\\ Files/ClanLib/ClanLib-0.7/Sources/
let g:feral_path_C = &path
" DirectX include path
set path=C:/Program\\\ Files/Microsoft\\\ DirectX\\\ 9.0\\\ SDK\\\ (February\\\ 2005)/Include
let g:feral_path_D = &path
" start off with base path
execute "set path=".g:feral_path_B
function Feral_Path(whichpaths)
  if strlen(a:whichpaths)
    let old_path = &path
    set path=
    let paths_to_use = toupper(a:whichpaths)
    while strlen(paths_to_use)
      if exists("g:feral_path_{paths_to_use[0]}")
        execute "set path+=".substitute(g:feral_path_{paths_to_use[0]}, "\\ ", "\\\\\\\\ ", "g")
        " remove the first char from paths_to_use now
        let paths_to_use = strpart(paths_to_use,1)
        " not found; remove this char and see if we can try again.
        let paths_to_use = strpart(paths_to_use,1)
    if strlen(&path) == 0
      execute "set path=".old_path
command -nargs=1 FP call Feral_Path(<q-args>)

Note that the chars you pass to the :FP command are upper cased (via call to toupper()) this may or may not be desirable for you.

The Usage[]

To use this the above code fragment must be sourced, in my case this is in my vimrc.

You need some paths to switch between, these global variables must start with "g:feral_path_" and the last character is used to identify (single char only!) the path.

For instance:

set path=C:/PROGRA~1/MICROS~1.NET/Vc7/include/**
" set path+=C:/Program\ Files/Microsoft\ Visual\ Studio\ .NET/Vc7/PlatformSDK/include/prerelease/**

Note how I use 'set path=' and thus can use this more or less naturally, including += to add an additional path. Not strickly necessary but does not hurt anything as far as I know.

let g:feral_path_S = &path

I then set my global variable (this one is referenced as 'S') to the current value of &path.

It is a bit messy but it is straight forward and to the point.

I also define the base path (referenced as 'B'), and my project path (referenced as 'P'). NOTE how 'B' is set to &path's initial value; which in my case is the default for the system.

" Base path :".,,"
let g:feral_path_B = &path
" System include path
set path=C:/PROGRA~1/MICROS~1.NET/Vc7/include/**
" set path+=C:/Program\ Files/Microsoft\ Visual\ Studio\ .NET/Vc7/PlatformSDK/include/prerelease/**
let g:feral_path_S = &path
" project include path
set path=C:/Program\ Files/ClanLib/include/**
"" set path=C:/Program\ Files/ClanLib/ClanLib-0.7/Sources/**
let g:feral_path_P = &path

So this gives us 3 paths to play with, B (base), S (system) and P (project).

I set &path to the default value I want directly:

" start off with base path
execute "set path=".g:feral_path_B

Now, to use this when you are coding away you can *easily* change &path via the :FP command.

The :FP command takes one argument, that argument is the one-word group of paths to set, use the one character to reference each path;


echo &path: .,,

to set path to basic and system, i.e.

echo &path: .,,,C:\PROGRA~1\MICROS~1.NET\Vc7\include**

or if I wanted system then basic:

echo &path: C:\PROGRA~1\MICROS~1.NET\Vc7\include**,.,,

As you can see it is pretty simple to manipulate &path now via the :FP command.

You can specify one or more paths to set:

echo &path: .,,,C:/Program Files/ClanLib/include/**,C:/PROGRA~1/MICROS~1.NET/Vc7/include/**

All in all this should be fairly simple to use, the major problem I see is forgetting the reference chars, but hopefully with clever naming this won't be a problem.

An alternative to the above mess:

You could of course forgot the above mess and just have menu entries/commands/mappings/what have you that sets &path directly.