CTRLP
[my-vim-dotfolder.git] / PACKAGES / FSwitch-0.9.2.vba
blob46b66bc49ab846f237175b8502e9362eea4ef111
1 " Vimball Archiver by Charles E. Campbell, Jr., Ph.D.
2 UseVimball
3 finish
4 plugin/fswitch.vim      [[[1
5 293
6 " ============================================================================
7 " File:        fswitch.vim
9 " Description: Vim global plugin that provides decent companion source file
10 "              switching
12 " Maintainer:  Derek Wyatt <derek at myfirstnamemylastname dot org>
14 " Last Change: March 23rd 2009
16 " License:     This program is free software. It comes without any warranty,
17 "              to the extent permitted by applicable law. You can redistribute
18 "              it and/or modify it under the terms of the Do What The Fuck You
19 "              Want To Public License, Version 2, as published by Sam Hocevar.
20 "              See http://sam.zoy.org/wtfpl/COPYING for more details.
21 " ============================================================================
23 if exists("g:disable_fswitch")
24     finish
25 endif
27 " Version
28 let s:fswitch_version = '0.9.2'
30 " Get the path separator right
31 let s:os_slash = &ssl == 0 && (has("win16") || has("win32") || has("win64")) ? '\' : '/'
33 " Default locations - appended to buffer locations unless otherwise specified
34 let s:fswitch_global_locs = '.' . s:os_slash
37 " s:SetVariables
39 " There are two variables that need to be set in the buffer in order for things
40 " to work correctly.  Because we're using an autocmd to set things up we need to
41 " be sure that the user hasn't already set them for us explicitly so we have
42 " this function just to check and make sure.  If the user's autocmd runs after
43 " ours then they will override the value anyway.
45 function! s:SetVariables(dst, locs)
46     if !exists("b:fswitchdst")
47         let b:fswitchdst = a:dst
48     endif
49     if !exists("b:fswitchlocs")
50         let b:fswitchlocs = a:locs
51     endif
52 endfunction
55 " s:FSGetLocations
57 " Return the list of possible locations
59 function! s:FSGetLocations()
60     let locations = []
61     if exists("b:fswitchlocs")
62         let locations = split(b:fswitchlocs, ',')
63     endif
64     if !exists("b:fsdisablegloc") || b:fsdisablegloc == 0
65         let locations += split(s:fswitch_global_locs, ',')
66     endif
68     return locations
69 endfunction
72 " s:FSGetExtensions
74 " Return the list of destination extensions
76 function! s:FSGetExtensions()
77     return split(b:fswitchdst, ',')
78 endfunction
81 " s:FSGetMustMatch
83 " Return a boolean on whether or not the regex must match
85 function! s:FSGetMustMatch()
86     let mustmatch = 1
87     if exists("b:fsneednomatch") && b:fsneednomatch != 0
88         let mustmatch = 0
89     endif
91     return mustmatch
92 endfunction
95 " s:FSGetFullPathToDirectory
97 " Given the filename, return the fully qualified directory portion
99 function! s:FSGetFullPathToDirectory(filename)
100     return expand(a:filename . ':p:h')
101 endfunction
104 " s:FSGetFileExtension
106 " Given the filename, returns the extension
108 function! s:FSGetFileExtension(filename)
109     return expand(a:filename . ':e')
110 endfunction
113 " s:FSGetFileNameWithoutExtension
115 " Given the filename, returns just the file name without the path or extension
117 function! s:FSGetFileNameWithoutExtension(filename)
118     return expand(a:filename . ':t:r')
119 endfunction
122 " s:FSGetAlternateFilename
124 " Takes the path, name and extension of the file in the current buffer and
125 " applies the location to it.  If the location is a regular expression pattern
126 " then it will split that up and apply it accordingly.  If the location pattern
127 " is actually an explicit relative path or an implicit one (default) then it
128 " will simply apply that to the file directly.
130 function! s:FSGetAlternateFilename(filepath, filename, newextension, location, mustmatch)
131     let parts = split(a:location, ':')
132     let cmd = 'rel'
133     let directive = parts[0]
134     if len(parts) == 2
135         let cmd = parts[0]
136         let directive = parts[1]
137     endif
138     if cmd == 'reg' || cmd == 'ifrel' || cmd == 'ifabs'
139         if strlen(directive) < 3
140             throw 'Bad directive "' . a:location . '".'
141         else
142             let separator = strpart(directive, 0, 1)
143             let dirparts = split(strpart(directive, 1), separator)
144             if len(dirparts) < 2 || len(dirparts) > 3
145                 throw 'Bad directive "' . a:location . '".'
146             else
147                 let part1 = dirparts[0]
148                 let part2 = dirparts[1]
149                 let flags = ''
150                 if len(dirparts) == 3
151                     let flags = dirparts[2]
152                 endif
153                 if cmd == 'reg'
154                     if a:mustmatch == 1 && match(a:filepath, part1) == -1
155                         let path = ""
156                     else
157                         let path = substitute(a:filepath, part1, part2, flags) . s:os_slash .
158                                     \ a:filename . '.' . a:newextension
159                     endif
160                 elseif cmd == 'ifrel'
161                     if match(a:filepath, part1) == -1
162                         let path = ""
163                     else
164                         let path = a:filepath . s:os_slash . part2 . 
165                                      \ s:os_slash . a:filename . '.' . a:newextension
166                     endif
167                 elseif cmd == 'ifabs'
168                     if match(a:filepath, part1) == -1
169                         let path = ""
170                     else
171                         let path = part2 . s:os_slash . a:filename . '.' . a:newextension
172                     endif
173                 endif
174             endif
175         endif
176     elseif cmd == 'rel'
177         let path = a:filepath . s:os_slash . directive . s:os_slash . a:filename . '.' . a:newextension
178     elseif cmd == 'abs'
179         let path = directive . s:os_slash . a:filename . '.' . a:newextension
180     endif
182     return simplify(path)
183 endfunction
186 " s:FSReturnCompanionFilename
188 " This function will return a path that is the best candidate for the companion
189 " file to switch to.  If mustBeReadable == 1 when then the companion file will
190 " only be returned if it is readable on the filesystem, otherwise it will be
191 " returned so long as it is non-empty.
193 function! s:FSReturnCompanionFilename(filename, mustBeReadable)
194     let fullpath = s:FSGetFullPathToDirectory(a:filename)
195     let ext = s:FSGetFileExtension(a:filename)
196     let justfile = s:FSGetFileNameWithoutExtension(a:filename)
197     let extensions = s:FSGetExtensions()
198     let locations = s:FSGetLocations()
199     let mustmatch = s:FSGetMustMatch()
200     let newpath = ''
201     for currentExt in extensions
202         for loc in locations
203             let newpath = s:FSGetAlternateFilename(fullpath, justfile, currentExt, loc, mustmatch)
204             if a:mustBeReadable == 0 && newpath != ''
205                 return newpath
206             elseif a:mustBeReadable == 1
207                 let newpath = glob(newpath)
208                 if filereadable(newpath)
209                     return newpath
210                 endif
211             endif
212         endfor
213     endfor
215     return newpath
216 endfunction
219 " FSReturnReadableCompanionFilename
221 " This function will return a path that is the best candidate for the companion
222 " file to switch to, so long as that file actually exists on the filesystem and
223 " is readable.
225 function! FSReturnReadableCompanionFilename(filename)
226     return s:FSReturnCompanionFilename(a:filename, 1)
227 endfunction
230 " FSReturnCompanionFilenameString
232 " This function will return a path that is the best candidate for the companion
233 " file to switch to.  The file does not need to actually exist on the
234 " filesystem in order to qualify as a proper companion.
236 function! FSReturnCompanionFilenameString(filename)
237     return s:FSReturnCompanionFilename(a:filename, 0)
238 endfunction
241 " FSwitch
243 " This is the only externally accessible function and is what we use to switch
244 " to the alternate file.
246 function! FSwitch(filename, precmd)
247     if !exists("b:fswitchdst") || strlen(b:fswitchdst) == 0
248         throw 'b:fswitchdst not set - read :help fswitch'
249     endif
250     if (!exists("b:fswitchlocs")   || strlen(b:fswitchlocs) == 0) &&
251      \ (!exists("b:fsdisablegloc") || b:fsdisablegloc == 0)
252         throw "There are no locations defined (see :h fswitchlocs and :h fsdisablegloc)"
253     endif
254     let newpath = FSReturnReadableCompanionFilename(a:filename)
255     let openfile = 1
256     if !filereadable(newpath)
257         if exists("b:fsnonewfiles") || exists("g:fsnonewfiles")
258             let openfile = 0
259         else
260             let newpath = FSReturnCompanionFilenameString(a:filename)
261         endif
262     endif
263     if openfile == 1
264         if newpath != ''
265             if strlen(a:precmd) != 0
266                 execute a:precmd
267             endif
268             execute 'edit ' . fnameescape(newpath)
269         else
270             echoerr "Alternate has evaluated to nothing.  See :h fswitch-empty for more info."
271         endif
272     else
273         echoerr "No alternate file found.  'fsnonewfiles' is set which denies creation."
274     endif
275 endfunction
278 " The autocmds we set up to set up the buffer variables for us.
280 augroup fswitch_au_group
281     au!
282     au BufEnter *.h call s:SetVariables('cpp,c', 'reg:/include/src/,reg:/include.*/src/,ifrel:|/include/|../src|')
283     au BufEnter *.c,*.cpp call s:SetVariables('h', 'reg:/src/include/,reg:|src|include/**|,ifrel:|/src/|../include|')
284 augroup END
287 " The mappings used to do the good work
289 com! FSHere       :call FSwitch('%', '')
290 com! FSRight      :call FSwitch('%', 'wincmd l')
291 com! FSSplitRight :call FSwitch('%', 'vsplit | wincmd l')
292 com! FSLeft       :call FSwitch('%', 'wincmd h')
293 com! FSSplitLeft  :call FSwitch('%', 'vsplit | wincmd h')
294 com! FSAbove      :call FSwitch('%', 'wincmd k')
295 com! FSSplitAbove :call FSwitch('%', 'split | wincmd k')
296 com! FSBelow      :call FSwitch('%', 'wincmd j')
297 com! FSSplitBelow :call FSwitch('%', 'split | wincmd j')
299 doc/fswitch.txt [[[1
301 2fswitch.txt*   For Vim version 7.2 and above   Last change: 2009 Mar 23
303                                ---------------
304                                 File Switcher
305                                ---------------
307 Author:  Derek Wyatt (derek at myfirstnamemylastname dot org)
309                                                         *fswitch-copyright*
310 Copyright: The VIM LICENSE applies to fswitch.vim, and fswitch.txt
311            (see |copyright|) except use "fswitch" instead of "Vim".
312            No warranty, express or implied.
313            Use At-Your-Own-Risk!
315 ==============================================================================
316                                                 *fswitch* *fswitch-contents*
317 1. Contents~
319         1. Contents .............................: |fswitch-contents|
320         2. About ................................: |fswitch-about|
321         3. Features .............................: |fswitch-features|
322         4. Setup ................................: |fswitch-setup|
323         5. Configuration ........................: |fswitch-configure|
324         6. "Creating" the Alternate File ........: |fswitch-altcreate|
325         7. Useful Mappings ......................: |fswitch-mappings|
326         8. FSwitch() ............................: |fswitch-function|
327         9. FSReturnCompanionFilenameString().....: |fswitch-getcompanion|
328        10. FSReturnReadableCompanionFilename()...: |fswitch-getreadablecomp|
329        11. The Default Settings .................: |fswitch-defaults|
330        12. Examples .............................: |fswitch-examples|
331        13. Troubleshooting ......................: |fswitch-trouble|
332         A. Change History .......................: |fswitch-changes|
334 ==============================================================================
335                                                         *fswitch-about*
336 2. About~
338 FSwitch is designed to allow you to switch between companion files of source
339 code (e.g. "cpp" files and their corresponding "h" files).  The source for
340 this came from a home-grown script that was influenced later by the
341 "Alternate" (a.vim) script.
343 The original intention was to modify the existing a.vim script to do what the
344 home-grown version could do (choose to open the other file in an existing
345 window) but it was a rather complex script and modification looked difficult
346 so the choice was made to simply move the home-grown script forward a couple
347 of notches and produce a new plugin.  This doc file is twice the length of the
348 actual code at this point :)
350 ==============================================================================
351                                                         *fswitch-features*
352 3. Features~
354 FSwitch has the following features:
356   - Switches between a file and its companion file
357   - Ability to create a new file using a preferential location
358   - Simple configuration using buffer-local variables
359   - It's got a really long doc file (... seriously, why is this thing so
360     bloody long?)
361   - Umm... other stuff?
363 ==============================================================================
364                                                         *fswitch-setup*
365 4. Setup~
367 Most of the behaviour of FSwitch is customized via buffer-local variables.
368 You set up the variables with auto commands:
370   au! BufEnter *.cpp let b:fswitchdst = 'hpp,h' | let b:fswitchlocs = '../inc'
372 That |:autocmd| will set the 'fswitchdst' and 'fswitchlocs' variables when the
373 |BufEnter| event takes place on a file whose name matches {*.cpp} (e.g. when
374 you enter the buffer containing the {MyFile.cpp} file).
376 The variables above state that the alternate file to {MyFile.cpp} are
377 {MyFile.hpp} and {MyFile.h} preferred in that order, and located in the {inc}
378 directory at the same level as the current directory.
380 That should get you there but there's more capability here if you want.  To
381 get that move on to |fswitch-configure|.
383 ==============================================================================
384                                                         *fswitch-configure*
385 5. Configuration~
388                                                         *'fswitchdst'*
389 'fswitchdst'    string  (default depends on file in current buffer)
390                 local to buffer
392         The 'fswitchdst' variable denotes the file extension that is the
393         target extension of the current file's companion file.  For example:
395                 :let b:fswitchdst = 'cpp,cxx,C'
397         The above specifies that the current buffer's file has a companion
398         filename which can be found by replacing the current extension with
399         {cpp}, {cxx} or {C}.  The extensions will be tried in this order and
400         the first match wins.
402         'fswitchdst' is taken relative to directories that are found in the
403         'fswitchlocs' variable.
405                                                         *'fswitchlocs'*
406 'fswitchlocs'   string  (default depends on filen in current buffer)
407                 local to buffer
409         The 'fswitchlocs' variable contains a set of directives that indicate
410         directory names that should be formulated when trying to find the
411         alternate file.  For example:
413                 " Create the destination path by substituting any
414                 " 'include' string from the pathname with 'src'
415                 :let b:fswitchlocs = 'reg:/include/src/'
417                 " First try adding the relative path '../src' to the path
418                 " in which the file in the buffer exists and if that fails
419                 " then try using 'source' instead
420                 :let b:fswitchlocs = 'rel:../src,source'
422                 " Same as above but leaving off the optional 'rel:'
423                 :let b:fswitchlocs = '../src,../source'
425         The following types of directives are understood:
427                                                          *fswitch_reg*
428         reg:~
429                 A regular expression.  The regular expression takes the form:
431                         {delim}{pat}{delim}{globsub}{delim}
433                 Where:
434                 
435                 {delim}   is something that doesn't appear in {pat} or
436                           {globsub} used to delimit the {pat} and {globsub}
438                 {pat}     is a standard pattern to search on
440                 {globsub} is a substitution string that will be run through
441                           the |glob()| function.
443                                                          *fswitch_rel*
444         rel:~
445                 A relative path.  The {rel:} is actually optional.  If you
446                 leave this off, then FSwitch will assume that the string is
447                 denoting a relative path.
448         
449                                                          *fswitch_ifrel*
450         ifrel:~
451                 Takes the same form as {:reg} but the {globsub} part of the
452                 directive is a relative path.  The relative path is only used
453                 if the {pat} matches the existing path of the buffer.
454         
455                                                          *fswitch_abs*
456         abs:~
457                 An absolute path.  I have no idea why you'd ever want to do
458                 this, but it's there if you want it.
460                                                          *fswitch_ifabs*
461         ifabs:~
462                 Takes the same form as {:reg} but the {globsub} part of the
463                 directive is an absolute path.  The absolute path is only used
464                 if the {pat} matches the existing path of the buffer.
465         
466         Why use the "if" variants?
468         Here's the situation: You've got the following file:
470                 ~/code/MyFile.h
472         And you've set the following locations:
474                 For .h   -> reg:/include/src/,../src,./
475                 For .cpp -> reg:/src/include/,../include,./
477         Here's what happens when run the following commands:
479                 FSwitch('%')
480                 # Creates a new file ~/src/MyFile.cpp due to the first
481                 # relative path in the list for .h
482                 FSwitch('%')
483                 # Creates a new file ~/include/MyFile.h due to the first
484                 # regular expression in the list for .cpp
486         The problem is that you've unconditionally said you want to use
487         {../src} for the alternate file but in reality you probably wanted to
488         use {./}.  If you use {:ifrel} instead then you can say that you only
489         want to use {../src} if the path to the current buffer contains
490         {/include/} or something like that.  If you did this FSwitch would not
491         have taken {../src} for the new file but would have chosen {./}
493         So the "right" setup is:
495                 For .h   -> reg:/include/src/,ifrel:|/include/|../src|,./
496                 For .cpp -> reg:/src/include/,ifrel:|/src/|../include|,./
498                                                         *'fswitchdisablegloc'*
499 'fsdisablegloc'
500                 string  (default off)
501                 local to buffer
502         
503         Disables the appending of the default global locations to the local
504         buffer definition.  Normally when processing alternate file locations
505         FSwitch will append some default values to the list of locations.  If
506         you define this variable then this will not happen.
508         The default locations are currently set to "./" or ".\" depending on
509         what slash your configuration evaluates to.
511                                                         *'fswitchnonewfiles'*
512 'fsnonewfiles'
513                 string  (default off)
514                 local to buffer and global
515         
516         This variable is both global and local.  If you want to disable the
517         creation of the alternate file when it doesn't already exist you can
518         choose to do this on a per-extension basis or globally.  Set the
519         global one to shut it off all the time and use the buffer version to
520         shut it off locally.
522                                                         *'fsneednomatch'*
523 'fsneednomatch'
524                 string  (default off)
525                 local to buffer and global
526         
527         Normally when doing a regular expression alteration of the path (see
528         {reg:} in 'fswitchdst' the pattern you're going to substitute the
529         value with must actually match in the string.  When it doesn't matter
530         whether or not that the match actually takes place, you can set this
531         value.
533         If you do set this then the failure to match actually results in
534         nothing happening at all.  So if the right filename exists in the same
535         directory as the one you're switching from then that's the one that
536         will be switched to.
538         Example:
541                 If the b:fswitchlocs is set to
543                    reg:/src/include/,include
545                 and
547                   # This is the file we're editing
548                   ~/code/program/myfile.c
550                   # These choices exist for the header file
551                   ~/code/program/myfile.h
552                   ~/code/program/include/myfile.h
554         Then the first substitution will result in the first header file being
555         chosen, not the second.
557 ==============================================================================
558                                                         *fswitch-altcreate*
559 6. "Creating" the Alternate File~
561 If the file being switched to does not exist, and 'fsnonewfiles' has not been
562 set, then it will be created as a new, unwritten buffer.  If there are
563 multiple possibilities here, FSwitch prefers the first possible match.  For
564 example if the current buffer has a filename called {/code/src/a/b/MyFile.cpp}
565 and has the following set:
567         let b:fswitchdst = 'h,hpp'
568         let b:fswitchlocs = 'reg:/src/include/,../include,../inc'
570 then the created filename will be {/code/include/a/b/MyFile.cpp}.
572 As stated, this file hasn't actually been written to yet so you could easily
573 delete the buffer and there's no harm done but you also may not be able to
574 write the buffer very easily if the directory hierarchy doesn't yet exist.  In
575 this case, it's quite helpful to define a mapping for easily creating the
576 directory for you:
578         nmap <Leader>md :!mkdir -p %:p:h<cr>
580 Then it's pretty easy to create the directory before writing the file.
582 ==============================================================================
583                                                         *fswitch-mappings*
584 7. Useful Mappings~
586 I didn't bother putting mappings into the script directly as this might have
587 caused conflicts and I don't know how to avoid those.  I use the following
588 mappings myself:
590  - Switch to the file and load it into the current window >
591         nmap <silent> <Leader>of :FSHere<cr>
593  - Switch to the file and load it into the window on the right >
594         nmap <silent> <Leader>ol :FSRight<cr>
596  - Switch to the file and load it into a new window split on the right >
597         nmap <silent> <Leader>oL :FSSplitRight<cr>
599  - Switch to the file and load it into the window on the left >
600         nmap <silent> <Leader>oh :FSLeft<cr>
602  - Switch to the file and load it into a new window split on the left >
603         nmap <silent> <Leader>oH :FSSplitLeft<cr>
605  - Switch to the file and load it into the window above >
606         nmap <silent> <Leader>ok :FSAbove<cr>
608  - Switch to the file and load it into a new window split above >
609         nmap <silent> <Leader>oK :FSSplitAbove<cr>
611  - Switch to the file and load it into the window below >
612         nmap <silent> <Leader>oj :FSBelow<cr>
614  - Switch to the file and load it into a new window split below >
615         nmap <silent> <Leader>oJ :FSSplitBelow<cr>
617 ==============================================================================
618                                                         *FSwitch()*
619 8. FSwitch()~
621 The main work is done by the FSwitch() function.  The reason it's documented
622 here is because you can use it to do something more interesting if you wish.
623 As it stands now, you get the "Split Above and Switch" functionality by
624 calling FSwitch() like this:
626     FSwitch('%', 'split \| wincmd k')
628 There's probably not much to stop anyone from doing something more interesting
629 in the second argument.  If this string is non-empty then it will be run
630 through an |:execute| call.
632 ==============================================================================
633                      *fswitch-getcompanion* *FSReturnCompanionFilenameString()*
635 9. FSReturnCompanionFilenameString()~
637 This function is used by |FSwitch()| to return the pathname to the preferred
638 companion file.  In this case, the file need not actually exist on the
639 filesystem but would be the one created if you chose to do so.  As an
640 example:
642     let path = FSReturnCompanionFilenameString('%')
644 The resultant path string contains the preferred companion file or nothing if
645 no preferred file could be discovered.
647 ==============================================================================
648                 *fswitch-getreadablecomp* *FSReturnReadableCompanionFilename()*
650 10. FSReturnReadableCompanionFilename()~
652 This function returns the companion file, but the companion file must be
653 readable on the filesystem for it to be successfully returned.
655     let path = FSReturnReadableCompanionFilename('%')
657 The resultant path string contains the preferred companion file or nothing if
658 no preferred file could be found on the filesystem.
660 In order to see what created the need for this function, see
661 |fswitch-example3|.
663 ==============================================================================
664                                                         *fswitch-defaults*
665 11. The Default Settings~
667 By default FSwitch handles {c} and {cpp} files, favouring {cpp}.
669 For *.h files:
671     let b:fswitchdst  = 'cpp,c'
672     let b:fswitchlocs = 'reg:/include/src/,reg:/include.*/src/,../src'
674 For *.c
676     let b:fswitchdst  = 'h'
677     let b:fswitchlocs = 'reg:/src/include/,reg:|src|include/**|,../include'
680 For *.cpp
682     let b:fswitchdst  = 'h'
683     let b:fswitchlocs = 'reg:/src/include/,reg:|src|include/**|,../include'
686 ==============================================================================
687                                                         *fswitch-examples*
688 12. Examples~
689                                                         *fswitch-example1*
690 Let's say you have a C++ codebase and it has the following properties (this
691 level of insanity is a bit high but versions that are only slightly saner
692 exist in real life):
694         - Source files with {.cpp}, {.cc} and {.C} extensions
695         - Header files with {.h} extensions
696         - Source files and header files in the same directory
697         - Source files in the {src} directory and include files in the
698           {include} directory
699         - Source files in the {src} directory and include files in the
700           {include/name/space} directory (i.e. subdirectories denoted by the
701           namespace).
702         - Source files in {src/name/space} and header files in
703           {include/name/space} (i.e. subdirectories denoted by the namespace).
705 As a final part to this, the "new" way of doing things in this source tree is
706 to put header files in a directory noted by namespace and to do the same with
707 source files and to name source files with a {cpp} extension.
709 In order to switch between files organized like this, you could specify the
710 following:
712  augroup mycppfiles
713    au!
714    au BufEnter *.h let b:fswitchdst  = 'cpp,cc,C'
715    au BufEnter *.h let b:fswitchlocs = 'reg:/include/src/,reg:/include.*/src/'
716  augroup END
718 Here the setting of b:fswitchdst to {cpp,cc,C} handles the different C++
719 extensions, and prefers to use {cpp} and will create new files with that
720 extension.
722 The fswitchlocs setting allows for the following:
724         reg:/include/src/~
726                 Take the pathname to the file in the current buffer and
727                 substitute "src" for "include".  This handles the following
728                 possibilities:
730                 - Files are in {include} and {src} respectively
731                 - Files are in {include/name/space} and {src/name/space}
732                   respectively
734         reg:/include.*/src/~
736                 Take the pathname to the file in the current buffer and
737                 substitute "src" for "include.*".  This handles the following
738                 possibility:
740                 - Files are in {include/name/space} and {src} respectively
741         
742         ./~
743                 This one's a hiddden option.  The default location is the
744                 current directory already so we don't explicitly have to state
745                 this, but it is the last possibility:
747                 - Files are in the same directory
749                                                         *fswitch-example2*
750 Here we'll just show a quick example of making use of the globbing aspect of
751 the system.  Let's say you're working on a {cpp} file and you want to find the
752 matching header file, and you have your destination and locations set to the
753 following:
755         let b:fswitchdst = 'h'
756         let b:fswitchlocs = 'reg:|src|include/**|'
758 then if you have the a file {src/MyFile.cpp} then this will find the file
759 {include/name/space/MyFile.h}.
761                                                         *fswitch-example3*
762 At work I'm a Windows C++ programmer and at home I'm a OS X Objective-C
763 programmer.  There's a problem with this... C++ and Objective-C both use the
764 same extension for header files ({.h}).
766 At home I want to be able to use the XCode command line builder in the
767 'makeprg' setting when I'm working on the code.  I would like this to be set
768 when I am on a {.m} file or its companion {.h} file.  This is done with the
769 following function:
771     function! SetMakeForXCode(filename)
772         let isObjCFile = 0
773         let ext = expand(a:filename . ":e")
774         if ext == 'm' || ext == 'mm'
775             let isObjCFile = 1
776         elseif ext == 'h'
777             " Find the companion file
778             let companionfile = FSReturnReadableCompanionFilename('%')
779             " For some reason expand() doesn't work on the next line
780             let companionext = substitute(companionfile, '.*\.', '', '')
781             if companionext == 'm' || companionext == 'mm'
782                 let isObjCFile = 1
783             endif
784         endif
785         if isObjCFile == 1
786             setl makeprg=xcodebuild\ -configuration\ Debug
787         endif
788     endfunction
790 Yup, this could have been easier by using the 'filetype' or using some sort of
791 |grep| call but I wanted to use this particular hammer. :)  I'll probably end
792 up switching it to use the 'filetype' instead in the end...
794 ==============================================================================
795                                                         *fswitch-trouble*
796 13. TroubleShooting~
797                                                         *fswitch-empty*
798 You may get the following error:
800   Alternate has evaluated to nothing.  See :h fswitch-empty for more info.
802 It can happen... This is probably due to the fact that you've got a nicely
803 strict set of rules for your locations.  With |fswitch-reg| and
804 |fswitch-ifrel| and |fswitch-ifabs| you can get rather specific about whether
805 or not anything actually happens.  If you aren't letting anything really
806 happen, it's not going to happen and you're going to end up with an empty
807 path.
809 ==============================================================================
810                                                         *fswitch-changes*
811 A. Change History~
813 0.9.2
814         - Fix for the splitting commands (Thanks Michael Henry)
816 0.9.1
817         - Added :ifrel (|fswitch_ifrel|)
818         - Added :ifabs (|fswitch_ifabs|)
819         - Added |FSReturnReadableCompanionFilename()|
820         - Added |FSReturnCompanionFilenameString()|
821         - Changed default settings for .h to use :ifrel instead of :rel
822         - Changed default settings for .c and .cpp to use :ifrel instead of
823           :rel
825 0.9.0
826         - Initial release
828 vim:tw=78:sts=8:ts=8:sw=8:noet:ft=help: