2009-05-07 6 views
2

j'ai des fichiers qui ressemblent à ce qui suit:Suppression des « blocs » de texte dans vim

>>Start-pattern 
some text 
some more text 
>>Start-pattern 
some other text 

some more other text 
>>Start-pattern 
[and so on] 

Ce que je voudrais avoir est une application qui me permet de supprimer le « bloc » de texte en cours. Où "block" est défini comme toutes les lignes allant de ">> Start-pattern" jusqu'à avant la ligne ">> Start-pattern" suivante.

Ce que j'est la suivante:

nnoremap ,d $:?^>>Start-pattern?,/^>>Start-pattern/-1delete<CR> 

qui fonctionne à moins que je suis debout sur le dernier « bloc » dans un fichier.

Comment puis-je obtenir cette carte (ou une carte complètement différente qui fait la même chose) pour travailler sur tous les "blocs" du fichier?

Répondre

7

Je pense, encore une fois, que nous repoussons les limites des expressions régulières au-delà de leurs limites. Ils sont bons pour échanger une chaîne avec une autre, c'est un effet secondaire que vous pouvez supprimer du texte avec eux.

Pourquoi ne pas profiter du charme du langage de script fourni par vim? C'est plus facile et comme un voyage sur la machine de retour. Si vous ajoutez la fonction suivante à votre fichier vimrc, il fera ce que vous voulez et être plus réutilisable/souple:

fun! DelBlock(thePattern) 
    let origLineNumber = line(".") 
    let lineNumber = origLineNumber 

    let lineString = getline(lineNumber) 
    while lineString !~ a:thePattern 
    let lineNumber = lineNumber - 1 
    if lineNumber < 0 
     echo "Function not found :/" 
    endif 
    let lineString = getline(lineNumber) 
    endwhile 
    let startLine = lineNumber 

    let lastLineInFile = line("$") 
    let lineNumber = origLineNumber + 1 
    let lineString = getline(lineNumber) 
    while lineNumber != lastLineInFile && lineString !~ a:thePattern 
    let lineNumber = lineNumber + 1 
    let lineString = getline(lineNumber) 
    endwhile 
    let endLine = lineNumber 
    if endLine != lastLineInFile 
    let endLine = endLine - 1 
    end 

    execute startLine.","endLine."d" 
endfunction 

map ,d :call DelBlock("^>>Start-pattern")<CR> 
+2

Dans le passé, j'ai joué avec getline pour faire des recherches, et c'est beaucoup trop lent. Préférez simplement utiliser search(). D'abord en arrière, puis en avant. –

3

Voici un hack possible.

nnoremap ,d maGo>>Start-pattern<Esc>'a$?^>>Start-pattern<CR>dNmaGdd'a 

ma      - mark your current position 
G      - go to the end of the file 
o>>Start-pattern<Esc> - append your pattern line 
'a      - go back to your prior position 
$      - go to the end of the current line 
?^>>Start-pattern<CR> - find the previous occurrence of the pattern 
dN      - delete until the next occurence 
ma      - mark your current position 
G      - go to the end of the file 
dd      - delete the last line of the file 
'a      - return to your previous position 

Je l'origine essayé d'obtenir \%$ (fin de fichier) pour travailler, mais je ne pouvais pas obtenir la suppression pour inclure le dernier caractère dans le fichier. J'ai donc essayé de cette façon à la place.

J'ai fait quelques tests, et cela semble fonctionner pour moi (blocs intermédiaires et dernier bloc).

+0

astuce de Nice travail autour du problème à la fin du fichier en insérant le modèle! J'ai eu un problème, cependant, avec la suppression d'un dernier bloc: J'ai "autoindent" ensemble, puis le bit "o >> Start-pattern " (potentiellement) met le >> Start-pattern avec indentation. Il y a une solution de contournement en faisant "o0 >> Démarrer-modèle ". – user55400

6

Vous pouvez le faire avec un seul regex:

nnoremap ,d :1,.s/\v%(%(.*%#&(\>\>Start-pattern))%(\[email protected]!\_.)+)\|%((\>\>Start-pattern)%(\[email protected]!\_.)*%#%(\[email protected]!\_.)+)//

Que vous devrait est une autre question ...

+0

Nice! que '\ |' devrait être un '|', cependant (puisque c'est très magique) – rampion

+1

Je l'aurais pensé aussi, mais c'est en fait que le mapping ne mange pas la barre. (: h map_bar) –

+0

* frémit * - mais fait son travail sans faille! Cependant, je ne l'ai pas complètement compris, même après avoir lu beaucoup de fonctionnalités intéressantes de vim regex. – user55400

2

Merci beaucoup pour les réponses belles, les gars! En fin de compte, je suis allé pour le plus maintenable/robuste. S'appuyant sur la réponse de Whaledawg et de prendre le commentaire de Luc Hermitte compte je me suis retrouvé avec:

fun! DelBlock(pat) 
    let startLine = search(a:pat, "nbcW") 
    let endLine = search(a:pat, "nW") 

    if startLine == 0 
    echo "Block '".a:pat."' not found" 
    return 
    end 

    if endLine == 0 
    let endLine = line("$") 
    else 
    let endLine = endLine-1 
    end 

    execute startLine.","endLine."delete" 
endfunction 

nmap ,d :call DelBlock("^>>Start-pattern")<CR> 
Questions connexes