kien / ctrlp.vim

Fuzzy file, buffer, mru, tag, etc finder.
kien.github.com/ctrlp.vim
7.26k stars 676 forks source link

More flexible 'mixed' mode #310

Open teranex opened 11 years ago

teranex commented 11 years ago

I would really like to be able to search for files and tags (and lines, ...) at the same time, using some advanced 'mixed' mode. I know there is currently a 'mixed' mode but this only supports files, MRU and buffers and as you said in https://github.com/kien/ctrlp.vim/issues/101#issuecomment-5566998 it can not be extended to also include tags.

Now I'm wondering if it would be possible to modify CtrlP to support a more advanced 'mixed' mode which can work with all available extensions. In that case the user would be able to configure which modes should be active in mixed mode. (where the default would be 'files', 'mru' and 'buffers' to mimic the current mixed mode). I'm wondering if it would to possible to work somehow like this:

In fact, I already created a small (and dirty) 'proof of concept' which seems to work without any problems (combining 'line' + 'tag'). Do you see any possible problems with this approach? Maybe the syntax patterns might give troubles? If you think this can work I can try to modify the existing mixed extension to use this approach, work with any available extensions and make the enabled extensions configurable. I am however not very well known with how exactly CtrlP caches the file listing etc.

Here is my proof of concept extension:

" command:
" com! -bar CtrlPGTA      cal ctrlp#init(ctrlp#gotoanything#id())

if exists('g:loaded_ctrlp_gotany') && g:loaded_ctrlp_gotany
    finish
end

let g:loaded_ctrlp_gotany = 1

call add(g:ctrlp_ext_vars, {
    \ 'init': 'ctrlp#gotoanything#init()',
    \ 'accept': 'ctrlp#gotoanything#accept',
    \ 'lname': 'gotoanything',
    \ 'sname': 'gta',
    \ })

function! s:syntax()
    if !ctrlp#nosy()
        call ctrlp#hicheck('CtrlPGTAType', 'Type')
        syntax match CtrlPGTAType /\v\w+: /
    endif
endfunction

function! ctrlp#gotoanything#init()
    let g:ctrlp_gta_mixed = []

    let entries = ctrlp#tag#init()
    for entry in entries
        call add(g:ctrlp_gta_mixed, 'tag: '.entry)
    endfor

    let entries = ctrlp#line#init()
    for entry in entries
        call add(g:ctrlp_gta_mixed, 'line: '.entry)
    endfor

    call s:syntax()

    return g:ctrlp_gta_mixed
endfunction

function! ctrlp#gotoanything#accept(mode, str)
    call ctrlp#exit()

    if strpart(a:str, 0, 5) ==# "line:"
        let l:str = strpart(a:str, 6)
        return ctrlp#line#accept(a:mode, l:str)
    endif

    if strpart(a:str, 0, 4) ==# "tag:"
        let l:str = strpart(a:str, 5)
        return ctrlp#tag#accept(a:mode, l:str)
    endif
endfunction

" Give the extension an ID
let s:id = g:ctrlp_builtins + len(g:ctrlp_ext_vars)
" Allow it to be called later
function! ctrlp#gotoanything#id()
  return s:id
endfunction
kien commented 11 years ago

Good idea, but aside from the highlighting, there's still the problem with the matching. Matching a filename including path is different from matching a tag or a line entry.

Your proof works because coincidently the tag's and the line's lines have very similar formats. But if you throw files or buffers into the mix then filename-only mode won't work, and the entire tag line (the tagname and the extra infos) will be included when matching.

Originally, I also wanted the mixed mode to work with a command like this:

CtrlPMixed --mode=files,buffers,tags,...

But I didn't and still don't think it's worth making, at least until I can figure out how to solve all the major problems.

danemacmillan commented 9 years ago

Being able to define what mixed mode means would be awesome. I currently would like to specify "files" and "buffers" as a custom mixed mode, but it's not possible.

skrobul commented 8 years ago

Would it be worth opening separate issue with limited scope for just that? That's exactly what I need - just files and buffers, without risk of using wrong file from MRU.

MidStein commented 7 months ago

@danemacmillan @skrobul you can use let g:ctrlp_mruf_max = 0 as a workaround to achieve what you want.

skrobul commented 7 months ago

@MidStein thanks for the suggestion - it was ~7 years ago, so I won't be testing that since I've switched to telescope, but hopefully that's useful to someone :)