2017-09-15 8 views
1

J'écris actuellement une fonction de remplacement dont j'ai souvent besoin pour programmer dans vim.vim: échapper des chaînes pour la substitution (vimscript)

Les fonctions que j'ai déjà écrites ressemblent à ceci et fonctionnent normalement bien pour rechercher et remplacer des chaînes qui n'ont aucun caractère spécial à l'intérieur. J'ai déjà réalisé pour échapper le "/" automatiquement. Ma question est, comment dois-je adapter la fonction d'échappement() dans la ligne

execute ':silent :argdo %s/' . escape(searchPattern, '/') . '/' . escape(replacePattern, '/') . '/ge' 

Alors que automatiquement tous les caractères qui doivent être échappé à échapper?

" MAIN FUNCTION 
" inspired by http://vimcasts.org/episodes/project-wide-find-and-replace/ 
function! SubstituteProjectwide(searchInput) 
    :set hidden 
    let cwd = getcwd() 
    let filename=expand('%:p') 
    call inputsave() 
    let searchPattern = input('Search for: ', a:searchInput) 
    let replacePattern = input('Replace "' . searchPattern . '" with: ') 
    let filePattern = input('Filepattern: ', cwd . '/**/*.*') 
    call inputrestore() 
    execute ':silent :args ' . filePattern 
    execute ':silent :vimgrep /' . searchPattern . '/g ##' 
    execute ':silent :Qargs' 
    execute ':silent :argdo %s/' . escape(searchPattern, '/\') . '/' . escape(replacePattern, '/\') . '/ge' 
    execute ':silent :edit ' . filename 
    echo 'Replaced "' . searchPattern . '" with "' . replacePattern . '" in ' . filePattern 
endfunction 

" VISUAL ENTRYPOINT WITH SELECTED TEXT 
function! SubstituteProjectwideVisual() 
    let v = @* 
    call SubstituteProjectwide(GetVisualSelectedText()) 
endfunction 
:vnoremap <F6> :call SubstituteProjectwideVisual()<cr> 

" NORMAL ENTRYPOINT WIHT WORD UNDER CURSOR 
function! SubstituteProjectwideNormal() 
    let wordUnderCursor = expand("<cword>") 
    call SubsituteProjectwide(wordUnderCursor) 
endfunction 
:nnoremap <F6> :call SubstituteProjectwideNormal()<cr> 

" GETTING THE FILES WICH CONTAIN SEARCH PATTERN 
" copied from http://vimcasts.org/episodes/project-wide-find-and-replace/ 
command! -nargs=0 -bar Qargs execute 'args' QuickfixFilenames() 
function! QuickfixFilenames() 
    let buffer_numbers = {} 
    for quickfix_item in getqflist() 
    let buffer_numbers[quickfix_item['bufnr']] = bufname(quickfix_item['bufnr']) 
    endfor 
    return join(map(values(buffer_numbers), 'fnameescape(v:val)')) 
endfunction 

" GETTING THE CURRENT VISUAL SELECTION 
" copied from: https://stackoverflow.com/questions/1533565/how-to-get-visually-selected-text-in-vimscript 
function! GetVisualSelectedText() 
    let [line_start, column_start] = getpos("'<")[1:2] 
    let [line_end, column_end] = getpos("'>")[1:2] 
    let lines = getline(line_start, line_end) 
    if len(lines) == 0 
    return '' 
    endif 
    let lines[-1] = lines[-1][: column_end - (&selection == 'inclusive' ? 1 : 2)] 
    let lines[0] = lines[0][column_start - 1:] 
    return join(lines, "\n") 
endfunction 

MISE À JOUR

J'ai réussi à échapper à de nombreux personnages comme ça

escape(searchPattern, '/\') . '/' . escape(replacePattern, '/\') 

Mais comment puis-je savoir quelle liste des personnages que je dois échapper, quand il est en principe possible, que chaque personnage peut être à l'intérieur de la recherche et aussi la chaîne de remplacement?

Répondre

1

Pour faire une substitution littérale, spécifiez "très nomagic" (:help /\V), et échapper à la séparation (/) et \ dans la source.

Dans le remplacement, & et ~ doivent également être échappés si l'option 'magic' est définie. (\V ne fonctionne pas ici.)

execute ':silent :argdo %s/\V' . escape(searchPattern, '/\') . '/' . escape(replacePattern, '/\' . (&magic ? '&~' : '')) . '/ge' 

sauts de ligne (si possible) doit être changé ^M-\n:

execute ':silent :argdo %s/\V' . substitute(escape(searchPattern, '/\'),"\n",'\\n','ge') . '/' . escape(replacePattern, '/\' . (&magic ? '&~' : '')) . '/ge' 
+0

il semble fonctionner. Je dois le tester avec des termes de recherche plus complexes – divramod

+0

@divramod Rappelez-vous que vous devez également échapper '&' et '~', au moins dans le modèle de remplacement. Voir la fin de la dernière ligne dans la réponse de @ ingo-karkat. –

1

Cela ne répond pas exactement à votre question, mais est une autre façon de regardant le problème que vous essayez de résoudre. Je ne suis pas tout à fait ce que l'installation :args fait pour vous puisque le quickfix a toutes les informations dont vous avez besoin après le :vimgrep.

J'ai dans mon vimrc:

nnoremap <F3> :vimgrep // $PROJECT_ROOT_DIR/src/**/*.{cpp,h,c,inl,msg}<C-Left><C-Left><Right> 

Évidemment, vous aurez envie de personnaliser le chemin de recherche, car cela se concentre uniquement sur les cinq extensions de fichier ci-dessus dans la hiérarchie de fichiers spécifique qui a été configuré chaque fois que je lancé Vim ...

De toute façon, une fois que vous avez cela, :cr s'assure que vous êtes au début, puis faites la recherche & remplacer vous voulez à l'intérieur d'une macro. Vous pouvez réellement le tester sur les premières trouvailles si vous voulez, mais alors ...

qbq Effacer le registre «b».

qa Lancez l'enregistrement 'a' macro »

:%s/this/that/g Démarrer la macro et remplacer 'que' pour 'ceci'.(Appuyez sur Entrée)

:w|cnf écrire le fichier et passez à la suivante (Appuyez sur Entrée)

q arrêter l'enregistrement « une » macro.

Puis [email protected]@bq exécutera la macro une fois, en l'enregistrant dans @b. Ensuite, exécutez (tapez) @b une fois de plus et il continuera à s'appeler jusqu'à ce que ce soit fait.