2016-01-15 10 views
8

dostałem ręką jakiegoś starszych kod i najpierw chcę zmienićJak przekonwertować C stylu obsady do C++ stylu obsady w vim

(int)a + b; 

do

static_cast<int>(a) + b; 

Istnieje wiele z nich i robienie ich ręcznie jest bardzo czasochłonne. Czy istnieje sposób na wykorzystanie vim, aby tak się stało?

Próbowałem coś podobnego

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

ale to nie działa. Proszę o poradę.

+0

chciałbym przekonwertować wskaźnik rzuca do nazwanych C++ odlewów, poprawności, ale te rozważania nie mają zastosowania do rodzaju numeru odlewy, które ja po prostu zostawić w miejscu lub ewentualnie konwertować na notację C++ 'int (a)' (co oznacza to samo). Np. Nie wprowadzaj * niepotrzebnej nowej gadatliwości *. –

+3

Prawdopodobnie uzyskasz lepsze wyniki, używając czegoś w stylu [clang-tidy] (http://clang.llvm.org/extra/clang-tidy/checks/google-readability-casting.html). – Jason

Odpowiedz

6

Spróbuj tego:

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

Ten regex, jak na swoje pytanie zakłada, że ​​nie będzie miejsca po nazwie zmiennej:

Przykład:
dla następujących danych testowych:

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

wynikiem będzie

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

Wyjaśniając regex

(\(.*\)) - Match, co jest wewnątrz () i uchwycić go
\([^ ]*\) - po którym następuje coś, co nie jest przestrzenią i uchwycić to

+0

Może to być nieco zbyt elastyczne, ponieważ wszystko w nawiasach, które nie są przeznaczone do obsady w stylu C, również zostanie zmienione, ale działa! – user3667089

+1

Jeśli dobrze rozumiem wyrażenie regularne, bit '[^]' (nie spacja) jest częścią, która określa terminy, które wchodzą w obsadę.Jest to w zasadzie problem z parsowaniem, niezwiązaną złożonością - regex nigdy nie może go rozwiązać. '(int) (p + q)' jest parsowane do 'static_cast ((p) + q)'. OTOH, jest całkiem oczywiste, że 'z + m' zostałoby lepiej sparsowane, gdybyśmy użyli' [^ + - * /%^& |?] '. Brak szybkiego rozwiązania dla '(int) arr [i]' – MSalters

+1

@ user3667089: To prawda, że ​​regex jest dość uproszczony. Ale można go łatwo rozszerzyć, aby pasował tylko do niektórych podstawowych typów danych, zmieniając wyrażenie regularne na takie ':% s/(\ (int \ | float \ | double \)) \ ([^] * \)/static_cast <\1> (\ 2)/g'. Ale cieszę się, że pomógł ci także w obecnej formie. – xk0der

0

Można to wykorzystać:

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

Przyjmuje nazwę zmiennej zawsze jest a. Jeśli nie, możesz zastąpić a przez [a-z].

+0

Problem polega na tym, że używasz wyrażeń, a nie zmiennych. Nie ma wyrażenia regularnego, które może przechwycić wszystkie wyrażenia i tylko wyrażenia. – MSalters

0

Mam kilka mapowania dla tego zadania w lh-cpp. W takim przypadku będzie to ,,sc lub ,,rc lub ,,dc. (tutaj, , jest w rzeczywistości moim <localleader>).

to faktycznie realizowane jako:

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 

... 
Powiązane problemy