Loading ...
Sorry, an error occurred while loading the content.

Re: Searchin in open buffers

Expand Messages
  • A.Politz
    ... Maybe not. The logic, once it is defined, is simple and easiely doable with vimscript. The only sligthly difficult parts are parsing the new commands
    Message 1 of 14 , Apr 30 9:27 AM
    • 0 Attachment
      Erik Falor wrote:

      >On 4/29/08, Nico Weber <nicolasweber@...> wrote:
      >
      >
      >>Hi all,
      >>
      >>is there a way to search for a given string in all open buffers,
      >>preferably in a way that all matches show up in `:cw`?
      >>
      >>
      >
      >
      >This is a feature that I've oft wished for. I've been meaning to write a
      >plugin that executes :vimgrep /pat/ for the first file in the buffer list,
      >and
      >then[...]
      >
      >
      >Maybe one more for the todo list?
      >
      >
      Maybe not. The logic, once it is defined, is simple
      and easiely doable with vimscript. The only sligthly difficult parts
      are parsing the new commands arguments and defining some
      usefull behaviour (Like you mentioned, bufnr or names or regex etc.).

      -ap

      >Thanks,
      >
      >
      >>Nico
      >>
      >>ps: I know about :vimgrep. It searches in files, not in buffers.
      >>
      >>
      >Erik
      >
      >
      >


      --
      :wq


      --~--~---------~--~----~------------~-------~--~----~
      You received this message from the "vim_use" maillist.
      For more information, visit http://www.vim.org/maillist.php
      -~----------~----~----~----~------~----~------~--~---
    • Erik Falor
      ... I fixed this so that it will accept patterns with regexes and backslashes. Now the command operates as a drop-in replacement for :vimgrep Search in open
      Message 2 of 14 , Apr 30 10:22 AM
      • 0 Attachment
        On 4/30/08, Nico Weber <nicolasweber@...> wrote:

        > See the earlier thread entitled "2Qs: tab-specific buffers and buffer grep"
        >
        > This link might work:
        >

        > http://groups.google.com/group/vim_use/browse_thread/thread/c4c970b42...

        Thanks, that did help. I added the following to my vimrc, it seems to
        work fine (hits show up in :cw, jumps to the first hit automatically):

        " Search in open buffers
        fun! BufSearch(pattern)
          call setqflist([])
          exec 'silent bufdo g/' . a:pattern .
                \ '/caddexpr expand("%") . ":" . line(".") .  ":" .
        getline(".")'
          cc
        endfun
        command -nargs=1 Bgrep call BufSearch("<args>")

        I fixed this so that it will accept patterns with regexes and backslashes.
        Now the command operates as a drop-in replacement for :vimgrep

        " Search in open buffers
        fun! BufSearch(pattern)
        call setqflist([])
        exec 'silent bufdo g' . a:pattern .
        \ 'caddexpr expand("%") . ":" . line(".") . ":" . getline(".")'
        cc
        endfun
        command! -nargs=1 Bgrep call BufSearch(<q-args>)

        The only kink that I can't overcome is that if you run this command with an open quickfix list, the last quickfix
        item is a copy of the very first quickfix item, but with ":1:" prepended to the filename.  I think it is caused by
        :bufdo traversing the quickfix list itself.

        Otherwise, this works swell. 

        Nico

        --~--~---------~--~----~------------~-------~--~----~
        You received this message from the "vim_use" maillist.
        For more information, visit http://www.vim.org/maillist.php
        -~----------~----~----~----~------~----~------~--~---

      • Ben Schmidt
        ... Perhaps you can fix this by changing the function so that it does bufdo if &buftype =~ ^quickfix$ |^help$ | what it did before | endif Ben.
        Message 3 of 14 , May 1, 2008
        • 0 Attachment
          > On 4/30/08, *Nico Weber* <nicolasweber@...
          > <mailto:nicolasweber@...>> wrote:
          >
          >
          > > See the earlier thread entitled "2Qs: tab-specific buffers and
          > buffer grep"
          > >
          > > This link might work:
          > >
          >
          > >
          > http://groups.google.com/group/vim_use/browse_thread/thread/c4c970b42...
          >
          > Thanks, that did help. I added the following to my vimrc, it seems to
          > work fine (hits show up in :cw, jumps to the first hit automatically):
          >
          > " Search in open buffers
          > fun! BufSearch(pattern)
          > call setqflist([])
          > exec 'silent bufdo g/' . a:pattern .
          > \ '/caddexpr expand("%") . ":" . line(".") . ":" .
          > getline(".")'
          > cc
          > endfun
          > command -nargs=1 Bgrep call BufSearch("<args>")
          >
          >
          > I fixed this so that it will accept patterns with regexes and backslashes.
          > Now the command operates as a drop-in replacement for :vimgrep
          >
          > " Search in open buffers
          > fun! BufSearch(pattern)
          > call setqflist([])
          > exec 'silent bufdo g' . a:pattern .
          > \ 'caddexpr expand("%") . ":" . line(".") . ":" . getline(".")'
          > cc
          > endfun
          > command! -nargs=1 Bgrep call BufSearch(<q-args>)
          >
          > The only kink that I can't overcome is that if you run this command with
          > an open quickfix list, the last quickfix
          > item is a copy of the very first quickfix item, but with ":1:" prepended
          > to the filename. I think it is caused by
          > :bufdo traversing the quickfix list itself.
          >
          > Otherwise, this works swell.

          Perhaps you can fix this by changing the function so that it does

          bufdo if &buftype =~ '^quickfix$\|^help$' | what it did before | endif

          Ben.




          --~--~---------~--~----~------------~-------~--~----~
          You received this message from the "vim_use" maillist.
          For more information, visit http://www.vim.org/maillist.php
          -~----------~----~----~----~------~----~------~--~---
        • Erik Falor
          ... Tried that, but it didn t work out so well. The what it did before part is a :global// command; it doesn t seem to play nice with bars. You get a bunch
          Message 4 of 14 , May 1, 2008
          • 0 Attachment
            On 5/1/08, Ben Schmidt <mail_ben_schmidt@...> wrote:

            > On 4/30/08, *Nico Weber* <nicolasweber@...

            > <mailto:nicolasweber@...>> wrote:
            >
            >
            >      > See the earlier thread entitled "2Qs: tab-specific buffers and
            >     buffer grep"
            >      >
            >      > This link might work:
            >      >
            >
            >      >
            >     http://groups.google.com/group/vim_use/browse_thread/thread/c4c970b42...
            >
            >     Thanks, that did help. I added the following to my vimrc, it seems to
            >     work fine (hits show up in :cw, jumps to the first hit automatically):
            >
            >     " Search in open buffers
            >     fun! BufSearch(pattern)
            >       call setqflist([])
            >       exec 'silent bufdo g/' . a:pattern .
            >             \ '/caddexpr expand("%") . ":" . line(".") .  ":" .
            >     getline(".")'
            >       cc
            >     endfun
            >     command -nargs=1 Bgrep call BufSearch("<args>")
            >
            >
            > I fixed this so that it will accept patterns with regexes and backslashes.
            > Now the command operates as a drop-in replacement for :vimgrep
            >
            > " Search in open buffers
            > fun! BufSearch(pattern)
            > call setqflist([])
            > exec 'silent bufdo g' . a:pattern .
            > \ 'caddexpr expand("%") . ":" . line(".") . ":" . getline(".")'
            > cc
            > endfun
            > command! -nargs=1 Bgrep call BufSearch(<q-args>)
            >
            > The only kink that I can't overcome is that if you run this command with
            > an open quickfix list, the last quickfix
            > item is a copy of the very first quickfix item, but with ":1:" prepended
            > to the filename.  I think it is caused by
            > :bufdo traversing the quickfix list itself.
            >
            > Otherwise, this works swell.


            Perhaps you can fix this by changing the function so that it does

            bufdo if &buftype =~ '^quickfix$\|^help$' | what it did before | endif

            Tried that, but it didn't work out so well.  The "what it did before" part is a :global// command; it doesn't seem
            to play nice with bars.  You get a bunch of E580's this way.

            I've been working on a function that does what :vimgrep does, but only looks in listed buffers.
            Check this out:

            function! BufSearch(pattern, bang)
            ""detect whether the user passed any :vimgrep flags
            "the pattern delimiter is the first char provided in a:pattern
            let patEnd = stridx(a:pattern, strpart(a:pattern, 0, 1), 1)
            let flags = strpart(a:pattern, patEnd + 1)
            "grab the pattern, sans the flags
            let trimPat = strpart(a:pattern, 0, patEnd + 1)

            let [global, nojump] = [0, 0]
            if -1 < stridx(flags, 'g') | let global = 'g' | endif
            if -1 < stridx(flags, 'j') | let nojump = 1 | endif

            "save the original view
            let [origbuf, origview] = [bufnr("%"), winsaveview()]
            let foldenableSave = &foldenable
            set nofoldenable

            "create a new, empty quickfix list
            call setqflist([])

            "find the last unlisted buffer
            blast
            let lastbuf = bufnr("%")

            "loop through all buffers reachable with bnext
            bfirst
            while 1
            if &buftype !~ '^help$|^quickfix$|^unlisted$'
            try
            exec "silent vimgrepadd" . a:bang . " " . a:pattern . global ."j %"
            catch /^Vim\%((\a\+)\)\=:E480/ " No Match
            "ignore it, and move on to the next file
            catch /^Vim\%((\a\+)\)\=:E499/ " Empty file name for %
            "shouldn't happen; but we'll just move on to the next
            endtry
            endif
            if bufnr("%") == lastbuf
            break
            else
            bnext
            endif
            endwhile

            "restore the original view for the active window or jump to first match
            exec "buffer " . origbuf
            let &foldenable = foldenableSave
            call winrestview(origview)
            if !nojump
            cc
            endif
            endfunction
            command! -nargs=1 -bang Bgrep call BufSearch(<q-args>, "<bang>")

            """"EOF""""

            It's much, much longer, but I'm liking how it works.  The pattern works just like with :vimgrep, even to the point
            where you can use 'weirder' pattern delimiters like <, [, *, etc.  And you can use the 'g' and 'j' flags after the
            pattern with behavior congruent with :vimgrep.

            Let me know what you think.

            PS. Sorry about the lack of indentation.

            Ben.






            --~--~---------~--~----~------------~-------~--~----~
            You received this message from the "vim_use" maillist.
            For more information, visit http://www.vim.org/maillist.php
            -~----------~----~----~----~------~----~------~--~---

          • Ben Schmidt
            ... Perhaps exec silent bufdo if &buftype =~ ^quickfix$ |^help$ | exec g . substitute(a:pattern, , , g ) . caddexpr expand( % ) . : .
            Message 5 of 14 , May 1, 2008
            • 0 Attachment
              Erik Falor wrote:
              > On 5/1/08, *Ben Schmidt* <mail_ben_schmidt@...
              > <mailto:mail_ben_schmidt@...>> wrote:
              >
              >
              > > On 4/30/08, *Nico Weber* <nicolasweber@...
              > <mailto:nicolasweber@...>
              >
              > > <mailto:nicolasweber@... <mailto:nicolasweber@...>>> wrote:
              > >
              > >
              > > > See the earlier thread entitled "2Qs: tab-specific buffers and
              > > buffer grep"
              > > >
              > > > This link might work:
              > > >
              > >
              > > >
              > >
              > http://groups.google.com/group/vim_use/browse_thread/thread/c4c970b42...
              > >
              > > Thanks, that did help. I added the following to my vimrc, it
              > seems to
              > > work fine (hits show up in :cw, jumps to the first hit
              > automatically):
              > >
              > > " Search in open buffers
              > > fun! BufSearch(pattern)
              > > call setqflist([])
              > > exec 'silent bufdo g/' . a:pattern .
              > > \ '/caddexpr expand("%") . ":" . line(".") . ":" .
              > > getline(".")'
              > > cc
              > > endfun
              > > command -nargs=1 Bgrep call BufSearch("<args>")
              > >
              > >
              > > I fixed this so that it will accept patterns with regexes and
              > backslashes.
              > > Now the command operates as a drop-in replacement for :vimgrep
              > >
              > > " Search in open buffers
              > > fun! BufSearch(pattern)
              > > call setqflist([])
              > > exec 'silent bufdo g' . a:pattern .
              > > \ 'caddexpr expand("%") . ":" . line(".") . ":" . getline(".")'
              > > cc
              > > endfun
              > > command! -nargs=1 Bgrep call BufSearch(<q-args>)
              > >
              > > The only kink that I can't overcome is that if you run this
              > command with
              > > an open quickfix list, the last quickfix
              > > item is a copy of the very first quickfix item, but with ":1:"
              > prepended
              > > to the filename. I think it is caused by
              > > :bufdo traversing the quickfix list itself.
              > >
              > > Otherwise, this works swell.
              >
              >
              > Perhaps you can fix this by changing the function so that it does
              >
              > bufdo if &buftype =~ '^quickfix$\|^help$' | what it did before | endif
              >
              >
              > Tried that, but it didn't work out so well. The "what it did before" part is a :global// command; it doesn't seem
              > to play nice with bars. You get a bunch of E580's this way.

              Perhaps

              exec 'silent bufdo if &buftype =~ ''^quickfix$\|^help$'' | exec ''g' .
              \ substitute(a:pattern,"'","''","g") .
              \ 'caddexpr expand("%") . ":" . line(".") . ":" . getline(".")'' | endif'

              [snip]

              > It's much, much longer, but I'm liking how it works. The pattern works
              > just like with :vimgrep, even to the point
              > where you can use 'weirder' pattern delimiters like <, [, *, etc. And
              > you can use the 'g' and 'j' flags after the
              > pattern with behavior congruent with :vimgrep.
              >
              > Let me know what you think.

              I don't have time to look in detail at the moment (1:20 AM now and I have to leave
              the house at 6:20--eek!), but I like the idea of a command that can work as a
              drop-in replacement for vimgrep. I want a version that works with the arglist,
              though, rather than the buffer list, though it should use the text in loaded
              buffers not the current disk file contents. And windo and tabdo ones, and probably
              a combination one, since it needs to be smart so if there are multiple windows
              with the same buffer, matches are only added once. I use windo and argdo quite a
              lot, but bufdo almost never!

              Smiles,

              Ben.



              --~--~---------~--~----~------------~-------~--~----~
              You received this message from the "vim_use" maillist.
              For more information, visit http://www.vim.org/maillist.php
              -~----------~----~----~----~------~----~------~--~---
            • Erik Falor
              ... Ben, if you re reading this and it s earlier than 6:20 AM, go back to bed! Making an Arglist grep is as simple as changing removing some b s from the
              Message 6 of 14 , May 1, 2008
              • 0 Attachment
                On 5/1/08, Ben Schmidt <mail_ben_schmidt@...> wrote:

                Erik Falor wrote:
                > On 5/1/08, *Ben Schmidt* <mail_ben_schmidt@...

                > <mailto:mail_ben_schmidt@...>> wrote:
                >
                >
                >      > On 4/30/08, *Nico Weber* <nicolasweber@...
                >     <mailto:nicolasweber@...>
                >

                >      > <mailto:nicolasweber@... <mailto:nicolasweber@...>>> wrote:
                >      >
                >      >
                >      >      > See the earlier thread entitled "2Qs: tab-specific buffers and
                >      >     buffer grep"
                >      >      >
                >      >      > This link might work:
                >      >      >
                >      >
                >      >      >
                >      >
                >     http://groups.google.com/group/vim_use/browse_thread/thread/c4c970b42...
                >      >
                >      >     Thanks, that did help. I added the following to my vimrc, it
                >     seems to
                >      >     work fine (hits show up in :cw, jumps to the first hit
                >     automatically):
                >      >
                >      >     " Search in open buffers
                >      >     fun! BufSearch(pattern)
                >      >       call setqflist([])
                >      >       exec 'silent bufdo g/' . a:pattern .
                >      >             \ '/caddexpr expand("%") . ":" . line(".") .  ":" .
                >      >     getline(".")'
                >      >       cc
                >      >     endfun
                >      >     command -nargs=1 Bgrep call BufSearch("<args>")
                >      >
                >      >
                >      > I fixed this so that it will accept patterns with regexes and
                >     backslashes.
                >      > Now the command operates as a drop-in replacement for :vimgrep
                >      >
                >      > " Search in open buffers
                >      > fun! BufSearch(pattern)
                >      > call setqflist([])
                >      > exec 'silent bufdo g' . a:pattern .
                >      > \ 'caddexpr expand("%") . ":" . line(".") . ":" . getline(".")'
                >      > cc
                >      > endfun
                >      > command! -nargs=1 Bgrep call BufSearch(<q-args>)
                >      >
                >      > The only kink that I can't overcome is that if you run this
                >     command with
                >      > an open quickfix list, the last quickfix
                >      > item is a copy of the very first quickfix item, but with ":1:"
                >     prepended
                >      > to the filename.  I think it is caused by
                >      > :bufdo traversing the quickfix list itself.
                >      >
                >      > Otherwise, this works swell.
                >
                >
                >     Perhaps you can fix this by changing the function so that it does
                >
                >     bufdo if &buftype =~ '^quickfix$\|^help$' | what it did before | endif
                >
                >
                > Tried that, but it didn't work out so well.  The "what it did before" part is a :global// command; it doesn't seem
                > to play nice with bars.  You get a bunch of E580's this way.


                Perhaps

                exec 'silent bufdo if &buftype =~ ''^quickfix$\|^help$'' | exec ''g' .
                \ substitute(a:pattern,"'","''","g") .
                \ 'caddexpr expand("%") . ":" . line(".") . ":" . getline(".")'' | endif'

                [snip]


                > It's much, much longer, but I'm liking how it works.  The pattern works
                > just like with :vimgrep, even to the point
                > where you can use 'weirder' pattern delimiters like <, [, *, etc.  And
                > you can use the 'g' and 'j' flags after the
                > pattern with behavior congruent with :vimgrep.
                >
                > Let me know what you think.


                I don't have time to look in detail at the moment (1:20 AM now and I have to leave
                the house at 6:20--eek!), but I like the idea of a command that can work as a
                drop-in replacement for vimgrep. I want a version that works with the arglist,
                though, rather than the buffer list, though it should use the text in loaded
                buffers not the current disk file contents. And windo and tabdo ones, and probably
                a combination one, since it needs to be smart so if there are multiple windows
                with the same buffer, matches are only added once. I use windo and argdo quite a
                lot, but bufdo almost never!

                Ben, if you're reading this and it's earlier than 6:20 AM, go back to bed!

                Making an Arglist grep is as simple as changing removing some 'b's from the function posted previously:

                function! ArgSearch(pattern, bang)
                ""detect whether the user passed any :vimgrep flags
                "the pattern delimiter is the first char provided in a:pattern
                let patEnd = stridx(a:pattern, strpart(a:pattern, 0, 1), 1)
                let flags = strpart(a:pattern, patEnd + 1)
                "grab the pattern, sans the flags
                let trimPat = strpart(a:pattern, 0, patEnd + 1)

                let [global, nojump] = [0, 0]
                if -1 < stridx(flags, 'g') | let global = 'g' | endif
                if -1 < stridx(flags, 'j') | let nojump = 1 | endif

                "save the original view
                let [origbuf, origview] = [bufnr("%"), winsaveview()]
                let foldenableSave = &foldenable
                set nofoldenable

                "create a new, empty quickfix list
                call setqflist([])

                "find the last file argument
                last
                let lastbuf = bufnr("%")

                "loop through all arguments
                first
                while 1
                if &buftype !~ '^help$|^quickfix$|^unlisted$'
                try
                exec "silent vimgrepadd" . a:bang . " " . a:pattern . global ."j %"
                catch /^Vim\%((\a\+)\)\=:E480/ " No Match
                "ignore it, and move on to the next file
                catch /^Vim\%((\a\+)\)\=:E499/ " Empty file name for %
                "shouldn't happen; but we'll just move on to the next
                endtry
                endif
                if bufnr("%") == lastbuf
                break
                else
                next
                endif
                endwhile

                "restore the original view for the active window or jump to first match
                exec "buffer " . origbuf
                let &foldenable = foldenableSave
                call winrestview(origview)
                if !nojump
                cc
                endif
                endfunction
                command! -nargs=1 -bang Agrep call ArgSearch(<q-args>, "<bang>")

                """"EOF""""
                But we can avoid the code duplication and roll these into one function easily enough.

                It looks as though one file can appear in the args list more than once; I'll have to check for this in version 0.2.
                Can one file appear in the buffers list more than once?

                Since this uses the built-in :vimgrep command, it looks at the contents of the buffer rather than the disk file.

                Now, a vimgrep that operates on all the visible windows a la :windo would be kinda handy.  "Show me all instances of /regexp/ in all of the buffers I can see now".  This would need the same kind of smarts as the :argdo version, so as not to scan the same file more than once.

                What would you expect the :tabdo version of this to do?  I think it should find /regexp/ in all windows visible in all tabpages.  Is that what you had in mind?


                Smiles,


                Ben.




                --~--~---------~--~----~------------~-------~--~----~
                You received this message from the "vim_use" maillist.
                For more information, visit http://www.vim.org/maillist.php
                -~----------~----~----~----~------~----~------~--~---

              • Nico Weber
                ... Thanks. Sadly, that function doesn t seem to work for me. When I search for a string that is in an open buffer (just not in the current buffer), I get some
                Message 7 of 14 , May 2, 2008
                • 0 Attachment
                  > It's much, much longer, but I'm liking how it works.  The pattern works just
                  > like with :vimgrep, even to the point
                  > where you can use 'weirder' pattern delimiters like <, [, *, etc.  And you
                  > can use the 'g' and 'j' flags after the
                  > pattern with behavior congruent with :vimgrep.

                  Thanks. Sadly, that function doesn't seem to work for me. When I
                  search for a string that is in an open buffer (just not in the current
                  buffer), I get some error, and if I search for a text that is in no
                  buffer, the script doesn't terminate. I'm probably doing something
                  wrong.

                  The simpler version is good enough for me anyways (and it's much
                  shorter. I'm going to use that).

                  Nico
                  --~--~---------~--~----~------------~-------~--~----~
                  You received this message from the "vim_use" maillist.
                  For more information, visit http://www.vim.org/maillist.php
                  -~----------~----~----~----~------~----~------~--~---
                Your message has been successfully submitted and would be delivered to recipients shortly.