2016-01-15 4 views
8

ho preso la mano sopra un certo codice legacy e prima voglio cambiareCome convertire ghisa stile C a C getto stile ++ in vim

(int)a + b; 

in

static_cast<int>(a) + b; 

Ci sono un sacco di loro e eseguirli manualmente richiede molto tempo. C'è un modo per usare vim per far sì che questo accada?

ho provato qualcosa di simile

:%s/\(int\).* /static_cast<int>(\2)/g 

ma non funziona. Per favore consiglio

+0

vorrei convertire il puntatore getta al denominata C++ calchi, per correttezza, ma queste considerazioni non si applicano al tipo di numero calchi, che avevo appena lasciato al suo posto o possibilmente convertire in notazione C++ 'int (a)' (che significa lo stesso). I.e., non introdurre * inutili nuove verbosità *. –

+3

Probabilmente otterresti risultati migliori usando qualcosa come [clang-tidy] (http://clang.llvm.org/extra/clang-tidy/checks/google-readability-casting.html). – Jason

risposta

6

Prova questo:

:%s/(\(.*\))\([^ ]*\)/static_cast<\1>(\2)/g 

Questa espressione regolare, secondo la vostra domanda, presuppone che ci sarà uno spazio dopo il nome della variabile:

Esempio:
Per seguenti dati di test:

(int)a + b 
(float)x * y 
(int)z+m 

il risultato sarà

static_cast<int>(a) + b 
static_cast<float>(x) * y 
static_cast<int>(z+m) 

Spiegando l'espressione regolare

(\(.*\)) - Partita tutto ciò che è dentro () e catturarla
\([^ ]*\) - seguito da tutto ciò che non è uno spazio e catturarlo

+0

Potrebbe essere un po 'troppo flessibile dato che qualsiasi cosa tra parentesi non intesa come cast di stile C verrà anch'essa modificata, ma funziona! – user3667089

+1

Se capisco correttamente la regex, il bit '[^]' (non lo spazio) è la parte che determina i termini che entrano nel cast.Questo è essenzialmente un problema di analisi, di complessità non associata: una regex non può mai risolverlo. '(int) (p + q)' viene analizzato a 'static_cast ((p) + q)'. OTOH, è abbastanza ovvio che 'z + m' sarebbe stato meglio analizzato se avessimo usato' [^ + - * /%^& |?] '. Nessuna soluzione rapida per '(int) arr [i]' – MSalters

+1

@ user3667089: true, l'espressione regolare è piuttosto semplicistica. Ma può essere facilmente esteso per abbinare solo alcuni dei tipi di dati di base cambiando la regex a questo::% s/(\ (int \ | float \ | double \)) \ ([^] * \)/static_cast <\1> (\ 2)/g'. Ma felice che ti abbia aiutato anche nella sua forma attuale. – xk0der

0

È possibile utilizzare questo:

%s/(int)\(a\)/static_cast<int>(\1)/g 

Questo sta assumendo il nome della variabile sempre è a. Se non lo è, puoi sostituire a con [a-z].

+0

Il problema è che si inviano espressioni, non variabili. Non esiste un'espressione regolare in grado di catturare tutte le espressioni e solo le espressioni. – MSalters

0

Ho diversi mapping per questa attività in lh-cpp.

In tal caso, sarà ,,sc o ,,rc o ,,dc. (qui, , è in realtà il mio <localleader>).

In realtà è implementato come:

function! s:ConvertToCPPCast(cast_type) 
    " Extract text to convert 
    let save_a = @a 
    normal! gv"ay 
    " Strip the possible brackets around the expression 
    let expr = matchstr(@a, '^(.\{-})\zs.*$') 
    let expr = substitute(expr, '^(\(.*\))$', '\1', '') 
    " 
    " Build the C++-casting from the C casting 
    let new_cast = substitute(@a, '(\(.\{-}\)).*', 
    \ a:cast_type.'<\1>('.escape(expr, '\&').')', '') 
    " Do the replacement 
    exe "normal! gvs".new_cast."\<esc>" 
    let @a = save_a 
endfunction 

vnoremap <buffer> <LocalLeader><LocalLeader>dc 
    \ <c-\><c-n>:'<,'>call <sid>ConvertToCPPCast('dynamic_cast')<cr> 
    nmap <buffer> <LocalLeader><LocalLeader>dc viw<LocalLeader><LocalLeader>dc 

...