/usr/share/vim-scripts/plugin/a.vim is in vim-scripts 20121007.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 | " Copyright (c) 1998-2006
" Michael Sharpe <feline@irendi.com>
"
" We grant permission to use, copy modify, distribute, and sell this
" software for any purpose without fee, provided that the above copyright
" notice and this text are not removed. We make no guarantee about the
" suitability of this software for any purpose and we are not liable
" for any damages resulting from its use. Further, we are under no
" obligation to maintain or extend this software. It is provided on an
" "as is" basis without any expressed or implied warranty.
" Directory & regex enhancements added by Bindu Wavell who is well known on
" vim.sf.net
"
" Patch for spaces in files/directories from Nathan Stien (also reported by
" Soeren Sonnenburg)
" Do not load a.vim if is has already been loaded.
if exists("loaded_alternateFile")
finish
endif
if (v:progname == "ex")
finish
endif
let loaded_alternateFile = 1
let alternateExtensionsDict = {}
" setup the default set of alternate extensions. The user can override in thier
" .vimrc if the defaults are not suitable. To override in a .vimrc simply set a
" g:alternateExtensions_<EXT> variable to a comma separated list of alternates,
" where <EXT> is the extension to map.
" E.g. let g:alternateExtensions_CPP = "inc,h,H,HPP,hpp"
" let g:alternateExtensions_{'aspx.cs'} = "aspx"
" This variable will be increased when an extension with greater number of dots
" is added by the AddAlternateExtensionMapping call.
let s:maxDotsInExtension = 1
" Function : AddAlternateExtensionMapping (PRIVATE)
" Purpose : simple helper function to add the default alternate extension
" mappings.
" Args : extension -- the extension to map
" alternates -- comma separated list of alternates extensions
" Returns : nothing
" Author : Michael Sharpe <feline@irendi.com>
function! <SID>AddAlternateExtensionMapping(extension, alternates)
" This code does not actually work for variables like foo{'a.b.c.d.e'}
"let varName = "g:alternateExtensions_" . a:extension
"if (!exists(varName))
" let g:alternateExtensions_{a:extension} = a:alternates
"endif
" This code handles extensions which contains a dot. exists() fails with
" such names.
"let v:errmsg = ""
" FIXME this line causes ex to return 1 instead of 0 for some reason??
"silent! echo g:alternateExtensions_{a:extension}
"if (v:errmsg != "")
"let g:alternateExtensions_{a:extension} = a:alternates
"endif
let g:alternateExtensionsDict[a:extension] = a:alternates
let dotsNumber = strlen(substitute(a:extension, "[^.]", "", "g"))
if s:maxDotsInExtension < dotsNumber
let s:maxDotsInExtension = dotsNumber
endif
endfunction
" Add all the default extensions
" Mappings for C and C++
call <SID>AddAlternateExtensionMapping('h',"c,cpp,cxx,cc,CC")
call <SID>AddAlternateExtensionMapping('H',"C,CPP,CXX,CC")
call <SID>AddAlternateExtensionMapping('hpp',"cpp,c")
call <SID>AddAlternateExtensionMapping('HPP',"CPP,C")
call <SID>AddAlternateExtensionMapping('c',"h")
call <SID>AddAlternateExtensionMapping('C',"H")
call <SID>AddAlternateExtensionMapping('cpp',"h,hpp")
call <SID>AddAlternateExtensionMapping('CPP',"H,HPP")
call <SID>AddAlternateExtensionMapping('cc',"h")
call <SID>AddAlternateExtensionMapping('CC',"H,h")
call <SID>AddAlternateExtensionMapping('cxx',"h")
call <SID>AddAlternateExtensionMapping('CXX',"H")
" Mappings for PSL7
call <SID>AddAlternateExtensionMapping('psl',"ph")
call <SID>AddAlternateExtensionMapping('ph',"psl")
" Mappings for ADA
call <SID>AddAlternateExtensionMapping('adb',"ads")
call <SID>AddAlternateExtensionMapping('ads',"adb")
" Mappings for lex and yacc files
call <SID>AddAlternateExtensionMapping('l',"y,yacc,ypp")
call <SID>AddAlternateExtensionMapping('lex',"yacc,y,ypp")
call <SID>AddAlternateExtensionMapping('lpp',"ypp,y,yacc")
call <SID>AddAlternateExtensionMapping('y',"l,lex,lpp")
call <SID>AddAlternateExtensionMapping('yacc',"lex,l,lpp")
call <SID>AddAlternateExtensionMapping('ypp',"lpp,l,lex")
" Mappings for OCaml
call <SID>AddAlternateExtensionMapping('ml',"mli")
call <SID>AddAlternateExtensionMapping('mli',"ml")
" ASP stuff
call <SID>AddAlternateExtensionMapping('aspx.cs', 'aspx')
call <SID>AddAlternateExtensionMapping('aspx.vb', 'aspx')
call <SID>AddAlternateExtensionMapping('aspx', 'aspx.cs,aspx.vb')
" Setup default search path, unless the user has specified
" a path in their [._]vimrc.
if (!exists('g:alternateSearchPath'))
let g:alternateSearchPath = 'sfr:../source,sfr:../src,sfr:../include,sfr:../inc'
endif
" If this variable is true then a.vim will not alternate to a file/buffer which
" does not exist. E.g while editing a.c and the :A will not swtich to a.h
" unless it exists.
if (!exists('g:alternateNoDefaultAlternate'))
" by default a.vim will alternate to a file which does not exist
let g:alternateNoDefaultAlternate = 0
endif
" If this variable is true then a.vim will convert the alternate filename to a
" filename relative to the current working directory.
" Feature by Nathan Huizinga
if (!exists('g:alternateRelativeFiles'))
" by default a.vim will not convert the filename to one relative to the
" current working directory
let g:alternateRelativeFiles = 0
endif
" Function : GetNthItemFromList (PRIVATE)
" Purpose : Support reading items from a comma seperated list
" Used to iterate all the extensions in an extension spec
" Used to iterate all path prefixes
" Args : list -- the list (extension spec, file paths) to iterate
" n -- the extension to get
" Returns : the nth item (extension, path) from the list (extension
" spec), or "" for failure
" Author : Michael Sharpe <feline@irendi.com>
" History : Renamed from GetNthExtensionFromSpec to GetNthItemFromList
" to reflect a more generic use of this function. -- Bindu
function! <SID>GetNthItemFromList(list, n)
let itemStart = 0
let itemEnd = -1
let pos = 0
let item = ""
let i = 0
while (i != a:n)
let itemStart = itemEnd + 1
let itemEnd = match(a:list, ",", itemStart)
let i = i + 1
if (itemEnd == -1)
if (i == a:n)
let itemEnd = strlen(a:list)
endif
break
endif
endwhile
if (itemEnd != -1)
let item = strpart(a:list, itemStart, itemEnd - itemStart)
endif
return item
endfunction
" Function : ExpandAlternatePath (PRIVATE)
" Purpose : Expand path info. A path with a prefix of "wdr:" will be
" treated as relative to the working directory (i.e. the
" directory where vim was started.) A path prefix of "abs:" will
" be treated as absolute. No prefix or "sfr:" will result in the
" path being treated as relative to the source file (see sfPath
" argument).
"
" A prefix of "reg:" will treat the pathSpec as a regular
" expression substitution that is applied to the source file
" path. The format is:
"
" reg:<sep><pattern><sep><subst><sep><flag><sep>
"
" <sep> seperator character, we often use one of [/|%#]
" <pattern> is what you are looking for
" <subst> is the output pattern
" <flag> can be g for global replace or empty
"
" EXAMPLE: 'reg:/inc/src/g/' will replace every instance
" of 'inc' with 'src' in the source file path. It is possible
" to use match variables so you could do something like:
" 'reg:|src/\([^/]*\)|inc/\1||' (see 'help :substitute',
" 'help pattern' and 'help sub-replace-special' for more details
"
" NOTE: a.vim uses ',' (comma) internally so DON'T use it
" in your regular expressions or other pathSpecs unless you update
" the rest of the a.vim code to use some other seperator.
"
" Args : pathSpec -- path component (or substitution patterns)
" sfPath -- source file path
" Returns : a path that can be used by AlternateFile()
" Author : Bindu Wavell <bindu@wavell.net>
function! <SID>ExpandAlternatePath(pathSpec, sfPath)
let prfx = strpart(a:pathSpec, 0, 4)
if (prfx == "wdr:" || prfx == "abs:")
let path = strpart(a:pathSpec, 4)
elseif (prfx == "reg:")
let re = strpart(a:pathSpec, 4)
let sep = strpart(re, 0, 1)
let patend = match(re, sep, 1)
let pat = strpart(re, 1, patend - 1)
let subend = match(re, sep, patend + 1)
let sub = strpart(re, patend+1, subend - patend - 1)
let flag = strpart(re, strlen(re) - 2)
if (flag == sep)
let flag = ''
endif
let path = substitute(a:sfPath, pat, sub, flag)
"call confirm('PAT: [' . pat . '] SUB: [' . sub . ']')
"call confirm(a:sfPath . ' => ' . path)
else
let path = a:pathSpec
if (prfx == "sfr:")
let path = strpart(path, 4)
endif
let path = a:sfPath . "/" . path
endif
return path
endfunction
" Function : FindFileInSearchPath (PRIVATE)
" Purpose : Searches for a file in the search path list
" Args : filename -- name of the file to search for
" pathList -- the path list to search
" relPathBase -- the path which relative paths are expanded from
" Returns : An expanded filename if found, the empty string otherwise
" Author : Michael Sharpe (feline@irendi.com)
" History : inline code written by Bindu Wavell originally
function! <SID>FindFileInSearchPath(fileName, pathList, relPathBase)
let filepath = ""
let m = 1
let pathListLen = strlen(a:pathList)
if (pathListLen > 0)
while (1)
let pathSpec = <SID>GetNthItemFromList(a:pathList, m)
if (pathSpec != "")
let path = <SID>ExpandAlternatePath(pathSpec, a:relPathBase)
let fullname = path . "/" . a:fileName
let foundMatch = <SID>BufferOrFileExists(fullname)
if (foundMatch)
let filepath = fullname
break
endif
else
break
endif
let m = m + 1
endwhile
endif
return filepath
endfunction
" Function : FindFileInSearchPathEx (PRIVATE)
" Purpose : Searches for a file in the search path list
" Args : filename -- name of the file to search for
" pathList -- the path list to search
" relPathBase -- the path which relative paths are expanded from
" count -- find the count'th occurence of the file on the path
" Returns : An expanded filename if found, the empty string otherwise
" Author : Michael Sharpe (feline@irendi.com)
" History : Based on <SID>FindFileInSearchPath() but with extensions
function! <SID>FindFileInSearchPathEx(fileName, pathList, relPathBase, count)
let filepath = ""
let m = 1
let spath = ""
let pathListLen = strlen(a:pathList)
if (pathListLen > 0)
while (1)
let pathSpec = <SID>GetNthItemFromList(a:pathList, m)
if (pathSpec != "")
let path = <SID>ExpandAlternatePath(pathSpec, a:relPathBase)
if (spath != "")
let spath = spath . ','
endif
let spath = spath . path
else
break
endif
let m = m + 1
endwhile
endif
if (&path != "")
if (spath != "")
let spath = spath . ','
endif
let spath = spath . &path
endif
let filepath = findfile(a:fileName, spath, a:count)
return filepath
endfunction
" Function : EnumerateFilesByExtension (PRIVATE)
" Purpose : enumerates all files by a particular list of alternate extensions.
" Args : path -- path of a file (not including the file)
" baseName -- base name of the file to be expanded
" extension -- extension whose alternates are to be enumerated
" Returns : comma separated list of files with extensions
" Author : Michael Sharpe <feline@irendi.com>
function! EnumerateFilesByExtension(path, baseName, extension)
let enumeration = ""
let extSpec = ""
let v:errmsg = ""
silent! echo g:alternateExtensions_{a:extension}
if (v:errmsg == "")
let extSpec = g:alternateExtensions_{a:extension}
endif
if (extSpec == "")
if (has_key(g:alternateExtensionsDict, a:extension))
let extSpec = g:alternateExtensionsDict[a:extension]
endif
endif
if (extSpec != "")
let n = 1
let done = 0
while (!done)
let ext = <SID>GetNthItemFromList(extSpec, n)
if (ext != "")
if (a:path != "")
let newFilename = a:path . "/" . a:baseName . "." . ext
else
let newFilename = a:baseName . "." . ext
endif
if (enumeration == "")
let enumeration = newFilename
else
let enumeration = enumeration . "," . newFilename
endif
else
let done = 1
endif
let n = n + 1
endwhile
endif
return enumeration
endfunction
" Function : EnumerateFilesByExtensionInPath (PRIVATE)
" Purpose : enumerates all files by expanding the path list and the extension
" list.
" Args : baseName -- base name of the file
" extension -- extension whose alternates are to be enumerated
" pathList -- the list of paths to enumerate
" relPath -- the path of the current file for expansion of relative
" paths in the path list.
" Returns : A comma separated list of paths with extensions
" Author : Michael Sharpe <feline@irendi.com>
function! EnumerateFilesByExtensionInPath(baseName, extension, pathList, relPathBase)
let enumeration = ""
let filepath = ""
let m = 1
let pathListLen = strlen(a:pathList)
if (pathListLen > 0)
while (1)
let pathSpec = <SID>GetNthItemFromList(a:pathList, m)
if (pathSpec != "")
let path = <SID>ExpandAlternatePath(pathSpec, a:relPathBase)
let pe = EnumerateFilesByExtension(path, a:baseName, a:extension)
if (enumeration == "")
let enumeration = pe
else
let enumeration = enumeration . "," . pe
endif
else
break
endif
let m = m + 1
endwhile
endif
return enumeration
endfunction
" Function : DetermineExtension (PRIVATE)
" Purpose : Determines the extension of a filename based on the register
" alternate extension. This allow extension which contain dots to
" be considered. E.g. foo.aspx.cs to foo.aspx where an alternate
" exists for the aspx.cs extension. Note that this will only accept
" extensions which contain less than 5 dots. This is only
" implemented in this manner for simplicity...it is doubtful that
" this will be a restriction in non-contrived situations.
" Args : The path to the file to find the extension in
" Returns : The matched extension if any
" Author : Michael Sharpe (feline@irendi.com)
" History : idea from Tom-Erik Duestad
" Notes : there is some magic occuring here. The exists() function does not
" work well when the curly brace variable has dots in it. And why
" should it, dots are not valid in variable names. But the exists
" function is wierd too. Lets say foo_c does exist. Then
" exists("foo_c.e.f") will be true...even though the variable does
" not exist. However the curly brace variables do work when the
" variable has dots in it. E.g foo_{'c'} is different from
" foo_{'c.d.e'}...and foo_{'c'} is identical to foo_c and
" foo_{'c.d.e'} is identical to foo_c.d.e right? Yes in the current
" implementation of vim. To trick vim to test for existence of such
" variables echo the curly brace variable and look for an error
" message.
function! DetermineExtension(path)
let mods = ":t"
let i = 0
while i <= s:maxDotsInExtension
let mods = mods . ":e"
let extension = fnamemodify(a:path, mods)
if (has_key(g:alternateExtensionsDict, extension))
return extension
endif
let v:errmsg = ""
silent! echo g:alternateExtensions_{extension}
if (v:errmsg == "")
return extension
endif
let i = i + 1
endwhile
return ""
endfunction
" Function : AlternateFile (PUBLIC)
" Purpose : Opens a new buffer by looking at the extension of the current
" buffer and finding the corresponding file. E.g. foo.c <--> foo.h
" Args : accepts one argument. If present it used the argument as the new
" extension.
" Returns : nothing
" Author : Michael Sharpe <feline@irendi.com>
" History : + When an alternate can't be found in the same directory as the
" source file, a search path will be traversed looking for the
" alternates.
" + Moved some code into a separate function, minor optimization
" + rework to favor files in memory based on complete enumeration of
" all files extensions and paths
function! AlternateFile(splitWindow, ...)
let extension = DetermineExtension(expand("%:p"))
let baseName = substitute(expand("%:t"), "\." . extension . '$', "", "")
let currentPath = expand("%:p:h")
if (a:0 != 0)
let newFullname = currentPath . "/" . baseName . "." . a:1
call <SID>FindOrCreateBuffer(newFullname, a:splitWindow, 0)
else
let allfiles = ""
if (extension != "")
let allfiles1 = EnumerateFilesByExtension(currentPath, baseName, extension)
let allfiles2 = EnumerateFilesByExtensionInPath(baseName, extension, g:alternateSearchPath, currentPath)
if (allfiles1 != "")
if (allfiles2 != "")
let allfiles = allfiles1 . ',' . allfiles2
else
let allfiles = allfiles1
endif
else
let allfiles = allfiles2
endif
endif
if (allfiles != "")
let bestFile = ""
let bestScore = 0
let score = 0
let n = 1
let onefile = <SID>GetNthItemFromList(allfiles, n)
let bestFile = onefile
while (onefile != "" && score < 2)
let score = <SID>BufferOrFileExists(onefile)
if (score > bestScore)
let bestScore = score
let bestFile = onefile
endif
let n = n + 1
let onefile = <SID>GetNthItemFromList(allfiles, n)
endwhile
if (bestScore == 0 && g:alternateNoDefaultAlternate == 1)
echo "No existing alternate available"
else
call <SID>FindOrCreateBuffer(bestFile, a:splitWindow, 1)
let b:AlternateAllFiles = allfiles
endif
else
echo "No alternate file/buffer available"
endif
endif
endfunction
" Function : AlternateOpenFileUnderCursor (PUBLIC)
" Purpose : Opens file under the cursor
" Args : splitWindow -- indicates how to open the file
" Returns : Nothing
" Author : Michael Sharpe (feline@irendi.com) www.irendi.com
function! AlternateOpenFileUnderCursor(splitWindow,...)
let cursorFile = (a:0 > 0) ? a:1 : expand("<cfile>")
let currentPath = expand("%:p:h")
let openCount = 1
let fileName = <SID>FindFileInSearchPathEx(cursorFile, g:alternateSearchPath, currentPath, openCount)
if (fileName != "")
call <SID>FindOrCreateBuffer(fileName, a:splitWindow, 1)
let b:openCount = openCount
let b:cursorFile = cursorFile
let b:currentPath = currentPath
else
echo "Can't find file"
endif
endfunction
" Function : AlternateOpenNextFile (PUBLIC)
" Purpose : Opens the next file corresponding to the search which found the
" current file
" Args : bang -- indicates what to do if the current file has not been
" saved
" Returns : nothing
" Author : Michael Sharpe (feline@irendi.com) www.irendi.com
function! AlternateOpenNextFile(bang)
let cursorFile = ""
if (exists("b:cursorFile"))
let cursorFile = b:cursorFile
endif
let currentPath = ""
if (exists("b:currentPath"))
let currentPath = b:currentPath
endif
let openCount = 0
if (exists("b:openCount"))
let openCount = b:openCount + 1
endif
if (cursorFile != "" && currentPath != "" && openCount != 0)
let fileName = <SID>FindFileInSearchPathEx(cursorFile, g:alternateSearchPath, currentPath, openCount)
if (fileName != "")
call <SID>FindOrCreateBuffer(fileName, "n".a:bang, 0)
let b:openCount = openCount
let b:cursorFile = cursorFile
let b:currentPath = currentPath
else
let fileName = <SID>FindFileInSearchPathEx(cursorFile, g:alternateSearchPath, currentPath, 1)
if (fileName != "")
call <SID>FindOrCreateBuffer(fileName, "n".a:bang, 0)
let b:openCount = 1
let b:cursorFile = cursorFile
let b:currentPath = currentPath
else
echo "Can't find next file"
endif
endif
endif
endfunction
comm! -nargs=? -bang IH call AlternateOpenFileUnderCursor("n<bang>", <f-args>)
comm! -nargs=? -bang IHS call AlternateOpenFileUnderCursor("h<bang>", <f-args>)
comm! -nargs=? -bang IHV call AlternateOpenFileUnderCursor("v<bang>", <f-args>)
comm! -nargs=? -bang IHT call AlternateOpenFileUnderCursor("t<bang>", <f-args>)
comm! -nargs=? -bang IHN call AlternateOpenNextFile("<bang>")
imap <Leader>ih <ESC>:IHS<CR>
nmap <Leader>ih :IHS<CR>
imap <Leader>is <ESC>:IHS<CR>:A<CR>
nmap <Leader>is :IHS<CR>:A<CR>
imap <Leader>ihn <ESC>:IHN<CR>
nmap <Leader>ihn :IHN<CR>
"function! <SID>PrintList(theList)
" let n = 1
" let oneFile = <SID>GetNthItemFromList(a:theList, n)
" while (oneFile != "")
" let n = n + 1
" let oneFile = <SID>GetNthItemFromList(a:theList, n)
" endwhile
"endfunction
" Function : NextAlternate (PUBLIC)
" Purpose : Used to cycle through any other alternate file which existed on
" the search path.
" Args : bang (IN) - used to implement the AN vs AN! functionality
" Returns : nothing
" Author : Michael Sharpe <feline@irendi.com>
function! NextAlternate(bang)
if (exists('b:AlternateAllFiles'))
let currentFile = expand("%")
let n = 1
let onefile = <SID>GetNthItemFromList(b:AlternateAllFiles, n)
while (onefile != "" && !<SID>EqualFilePaths(fnamemodify(onefile,":p"), fnamemodify(currentFile,":p")))
let n = n + 1
let onefile = <SID>GetNthItemFromList(b:AlternateAllFiles, n)
endwhile
if (onefile != "")
let stop = n
let n = n + 1
let foundAlternate = 0
let nextAlternate = ""
while (n != stop)
let nextAlternate = <SID>GetNthItemFromList(b:AlternateAllFiles, n)
if (nextAlternate == "")
let n = 1
continue
endif
let n = n + 1
if (<SID>EqualFilePaths(fnamemodify(nextAlternate, ":p"), fnamemodify(currentFile, ":p")))
continue
endif
if (filereadable(nextAlternate))
" on cygwin filereadable("foo.H") returns true if "foo.h" exists
if (has("unix") && $WINDIR != "" && fnamemodify(nextAlternate, ":p") ==? fnamemodify(currentFile, ":p"))
continue
endif
let foundAlternate = 1
break
endif
endwhile
if (foundAlternate == 1)
let s:AlternateAllFiles = b:AlternateAllFiles
"silent! execute ":e".a:bang." " . nextAlternate
call <SID>FindOrCreateBuffer(nextAlternate, "n".a:bang, 0)
let b:AlternateAllFiles = s:AlternateAllFiles
else
echo "Only this alternate file exists"
endif
else
echo "Could not find current file in alternates list"
endif
else
echo "No other alternate files exist"
endif
endfunction
comm! -nargs=? -bang A call AlternateFile("n<bang>", <f-args>)
comm! -nargs=? -bang AS call AlternateFile("h<bang>", <f-args>)
comm! -nargs=? -bang AV call AlternateFile("v<bang>", <f-args>)
comm! -nargs=? -bang AT call AlternateFile("t<bang>", <f-args>)
comm! -nargs=? -bang AN call NextAlternate("<bang>")
" Function : BufferOrFileExists (PRIVATE)
" Purpose : determines if a buffer or a readable file exists
" Args : fileName (IN) - name of the file to check
" Returns : 2 if it exists in memory, 1 if it exists, 0 otherwise
" Author : Michael Sharpe <feline@irendi.com>
" History : Updated code to handle buffernames using just the
" filename and not the path.
function! <SID>BufferOrFileExists(fileName)
let result = 0
let lastBuffer = bufnr("$")
let i = 1
while i <= lastBuffer
if <SID>EqualFilePaths(expand("#".i.":p"), a:fileName)
let result = 2
break
endif
let i = i + 1
endwhile
if (!result)
let bufName = fnamemodify(a:fileName,":t")
let memBufName = bufname(bufName)
if (memBufName != "")
let memBufBasename = fnamemodify(memBufName, ":t")
if (bufName == memBufBasename)
let result = 2
endif
endif
if (!result)
let result = bufexists(bufName) || bufexists(a:fileName) || filereadable(a:fileName)
endif
endif
if (!result)
let result = filereadable(a:fileName)
endif
return result
endfunction
" Function : FindOrCreateBuffer (PRIVATE)
" Purpose : searches the buffer list (:ls) for the specified filename. If
" found, checks the window list for the buffer. If the buffer is in
" an already open window, it switches to the window. If the buffer
" was not in a window, it switches to that buffer. If the buffer did
" not exist, it creates it.
" Args : filename (IN) -- the name of the file
" doSplit (IN) -- indicates whether the window should be split
" ("v", "h", "n", "v!", "h!", "n!", "t", "t!")
" findSimilar (IN) -- indicate weather existing buffers should be
" prefered
" Returns : nothing
" Author : Michael Sharpe <feline@irendi.com>
" History : + bufname() was not working very well with the possibly strange
" paths that can abound with the search path so updated this
" slightly. -- Bindu
" + updated window switching code to make it more efficient -- Bindu
" Allow ! to be applied to buffer/split/editing commands for more
" vim/vi like consistency
" + implemented fix from Matt Perry
function! <SID>FindOrCreateBuffer(fileName, doSplit, findSimilar)
" Check to see if the buffer is already open before re-opening it.
let FILENAME = escape(a:fileName, ' ')
let bufNr = -1
let lastBuffer = bufnr("$")
let i = 1
if (a:findSimilar)
while i <= lastBuffer
if <SID>EqualFilePaths(expand("#".i.":p"), a:fileName)
let bufNr = i
break
endif
let i = i + 1
endwhile
if (bufNr == -1)
let bufName = bufname(a:fileName)
let bufFilename = fnamemodify(a:fileName,":t")
if (bufName == "")
let bufName = bufname(bufFilename)
endif
if (bufName != "")
let tail = fnamemodify(bufName, ":t")
if (tail != bufFilename)
let bufName = ""
endif
endif
if (bufName != "")
let bufNr = bufnr(bufName)
let FILENAME = bufName
endif
endif
endif
if (g:alternateRelativeFiles == 1)
let FILENAME = fnamemodify(FILENAME, ":p:.")
endif
let splitType = a:doSplit[0]
let bang = a:doSplit[1]
if (bufNr == -1)
" Buffer did not exist....create it
let v:errmsg=""
if (splitType == "h")
silent! execute ":split".bang." " . FILENAME
elseif (splitType == "v")
silent! execute ":vsplit".bang." " . FILENAME
elseif (splitType == "t")
silent! execute ":tab split".bang." " . FILENAME
else
silent! execute ":e".bang." " . FILENAME
endif
if (v:errmsg != "")
echo v:errmsg
endif
else
" Find the correct tab corresponding to the existing buffer
let tabNr = -1
" iterate tab pages
for i in range(tabpagenr('$'))
" get the list of buffers in the tab
let tabList = tabpagebuflist(i + 1)
let idx = 0
" iterate each buffer in the list
while idx < len(tabList)
" if it matches the buffer we are looking for...
if (tabList[idx] == bufNr)
" ... save the number
let tabNr = i + 1
break
endif
let idx = idx + 1
endwhile
if (tabNr != -1)
break
endif
endfor
" switch the the tab containing the buffer
if (tabNr != -1)
execute "tabn ".tabNr
endif
" Buffer was already open......check to see if it is in a window
let bufWindow = bufwinnr(bufNr)
if (bufWindow == -1)
" Buffer was not in a window so open one
let v:errmsg=""
if (splitType == "h")
silent! execute ":sbuffer".bang." " . FILENAME
elseif (splitType == "v")
silent! execute ":vert sbuffer " . FILENAME
elseif (splitType == "t")
silent! execute ":tab sbuffer " . FILENAME
else
silent! execute ":buffer".bang." " . FILENAME
endif
if (v:errmsg != "")
echo v:errmsg
endif
else
" Buffer is already in a window so switch to the window
execute bufWindow."wincmd w"
if (bufWindow != winnr())
" something wierd happened...open the buffer
let v:errmsg=""
if (splitType == "h")
silent! execute ":split".bang." " . FILENAME
elseif (splitType == "v")
silent! execute ":vsplit".bang." " . FILENAME
elseif (splitType == "t")
silent! execute ":tab split".bang." " . FILENAME
else
silent! execute ":e".bang." " . FILENAME
endif
if (v:errmsg != "")
echo v:errmsg
endif
endif
endif
endif
endfunction
" Function : EqualFilePaths (PRIVATE)
" Purpose : Compares two paths. Do simple string comparison anywhere but on
" Windows. On Windows take into account that file paths could differ
" in usage of separators and the fact that case does not matter.
" "c:\WINDOWS" is the same path as "c:/windows". has("win32unix") Vim
" version does not count as one having Windows path rules.
" Args : path1 (IN) -- first path
" path2 (IN) -- second path
" Returns : 1 if path1 is equal to path2, 0 otherwise.
" Author : Ilya Bobir <ilya@po4ta.com>
function! <SID>EqualFilePaths(path1, path2)
if has("win16") || has("win32") || has("win64") || has("win95")
return substitute(a:path1, "\/", "\\", "g") ==? substitute(a:path2, "\/", "\\", "g")
else
return a:path1 == a:path2
endif
endfunction
|