Oleg K
Oleg K

Reputation: 5268

Vim. set command line from a function

I'm trying to write a function that replaces text in all buffers. So I call Ack to search all the matches and next step I want to set into Quickfix command line this code

:QuickFixDoAll %s/foo/boo/gc

Seems like I can only call 'exec' function which runs this command immediately and there is no ablility to edit it or cancel at all

I also tried "input" function to read user input but got this error at runtime

not an editor command

Any ideas?

.vimrc:

function! ReplaceInFiles(o, n)                                                                                                       
    exec "Ack '" . a:o . "'"
    exec "QuickFixDoAll %s/" . a:o . "/" . a:n . "/gc"
endfunction

" QuickFixDoAll
function! QuickFixDoAll(command)
    if empty(getqflist())
        return
    endif
    let s:prev_val = ""
    for d in getqflist()
        let s:curr_val = bufname(d.bufnr)
        if (s:curr_val != s:prev_val)
            exec "edit " . s:curr_val
            exec a:command
        endif
        let s:prev_val = s:curr_val
    endfor
    exec "quit"
endfunction
command! -nargs=+ QuickFixDoAll call QuickFixDoAll(<f-args>)

Upvotes: 0

Views: 405

Answers (2)

Ingo Karkat
Ingo Karkat

Reputation: 172768

Using input()

This queries both values interactively:

function! ReplaceInFiles()                                                                                                       
    let l:o = input('search? ')
    let l:n = input('replace? ')
    exec "Ack '" . l:o . "'"
    exec "QuickFixDoAll %s/" . l:o . "/" . l:n . "/gc"
endfunction
nnoremap <Leader>r :call ReplaceInFiles()<CR>

Incomplete mapping

nnoremap <Leader>r :let o = ''<Bar>exec "Ack '" . o . "'"<Bar>exec "QuickFixDoAll %s/" . o . "//gc"<Home><Right><Right><Right><Right><Right><Right><Right><Right><Right>

This one puts the cursor on the right spot for the search. As this value is used twice (Ack and QuickFixDoAll), it is assigned to a variable. After that, move to the end of the command and fill in the replacement in between the //gc.

Custom parsing

The most comfortable option would be a custom command :AckAndSubstAll/search/replacement/. For that, you'd need to parse the two parts in the custom command (like :s does). You could do that with matchstr(), or use ingo#cmdargs#substitute#Parse() from my ingo-library plugin.

Upvotes: 1

Andy Ray
Andy Ray

Reputation: 32076

First use vim-qargs to copy all files from the quickfix window into Vim's arglist by calling :Qargs.

Then run your replace on all arguments in the arglist by doing :argdo %s/search/replace/gc

Upvotes: 0

Related Questions