sponsor Vim development Vim logo Vim Book Ad

intermediate Tip #183: Select a buffer from those matching a pattern

 tip karma   Rating 4/1, Viewed by 1081 

created:   December 18, 2001 7:42      complexity:   intermediate
author:   Cory T. Echols      as of Vim:   6.0

The :bu command will take a pattern as an argument and jump to the matching buffer.  However, it's not very helpful if there is more than one buffer matching the pattern.  In that case, it will jump to the first match, which may not be what you want.  The following function and user-command will print a list of the matching buffers in the command-line area, and allow you to select one of the matching buffers by number.

"Select from buffers matching a certain pattern
"the 'pattern' argument shouldn't be prepended with a slash

function! BufSel(pattern)
   let bufcount = bufnr("$")
   let currbufnr = 1
   while currbufnr <= bufcount
      if(bufexists(currbufnr))
         let currbufname = bufname(currbufnr)
         if(match(currbufname, a:pattern) > -1)
               echo currbufnr . ":      ". bufname(currbufnr)
         endif
      endif
      let currbufnr = currbufnr + 1
   endwhile
   let desiredbufnr = input("Enter buffer number: ")
   if(strlen(desiredbufnr) != 0)
      exe ":bu ". desiredbufnr
   endif
endfunction

"Bind the BufSel() function to a user-command
command! -nargs=1 Bs :call BufSel("<args>")

 rate this tip  Life Changing Helpful Unfulfilling 

<<Keep your cursor centered vertically on the screen | How to obscure text instantaneously >>

Additional Notes

Cory T. Echols, December 18, 2001 8:02
I guess I should test my stuff more rigorously before posting.

The above function doesn't take into account the situation where no buffers match the supplied pattern.  The function below corrects the problem.

"Select from buffers matching a certain pattern
function! s:BufSel(pattern)
   let bufcount = bufnr("$")
   let currbufnr = 1

   "flag to determine if matches are found
   let foundmatch = 0
   while currbufnr <= bufcount
      if(bufexists(currbufnr))
         let currbufname = bufname(currbufnr)
         if(match(currbufname, a:pattern) > -1)
               echo currbufnr . ":      ". bufname(currbufnr)
               let foundmatch = 1
         endif
      endif
      let currbufnr = currbufnr + 1
   endwhile

   if(foundmatch > 0)
      let desiredbufnr = input("Enter buffer number: ")
      if(strlen(desiredbufnr) != 0)
         exe ":bu ". desiredbufnr
      endif
   else
      echo "No matching buffers"
   endif
endfunction
salmanhalim at hotmail.com, December 18, 2001 12:19
if precisely one match is found you needn't prompt the user -- just go to the one buffer that matched.  to accomplish this, use 'numMatches' instead of foundmatch and increment it instead of using it as a boolean.

also, if you do implement the above then, in the simple case, the behaviour is identical to that of :bu -- so you could completely replace :bu with yours:

:cab bu Bs

of course, this will affect all command-line/search etc. places where you have to search for or otherwise type 'bu' as a single word (i do this for 'sp' where i use 'Sp', a version i wrote that allows entering multiple filenames and opens them all -- the default behaviour is identical to 'sp' so i can replace 'sp' safely).
If you have questions or remarks about this site, visit the vimonline development pages. Please use this site responsibly.
Questions about Vim should go to vim@vim.org after searching the archive. Help Bram help Uganda.
Sponsored by Web Concept Group Inc. SourceForge Logo