1" To use this file, add this line to your ~/.vimrc:, w/o the dquote 2" source /path/to/kde/sources/kdesdk/scripts/kde-devel-vim.vim 3" 4" For CreateChangeLogEntry() : If you don't want to re-enter your 5" Name/Email in each vim session then make sure to have the viminfo 6" option enabled in your ~/.vimrc, with the '!' flag, enabling persistent 7" storage of global variables. Something along the line of 8" set viminfo=%,!,'50,\"100,:100,n~/.viminfo 9" should do the trick. 10" 11" To make use of the ,ll and ,lg shortcuts you need to have the files 12" GPLHEADER and LGPLHEADER in your home directory. Their content will be 13" copied as license header then. 14 15" Don't include these in filename completions 16set suffixes+=.lo,.o,.moc,.la,.closure,.loT 17 18" Search for headers here 19set path=.,/usr/include,/usr/local/include, 20if $QTDIR != '' 21 let &path = &path . $QTDIR . '/include/,' 22 let &path = &path . $QTDIR . '/include/Qt/,' 23 let &path = &path . $QTDIR . '/include/QtCore/,' 24 let &path = &path . $QTDIR . '/include/Qt3Support/,' 25 let &path = &path . $QTDIR . '/include/QtAssistant/,' 26 let &path = &path . $QTDIR . '/include/QtDBus/,' 27 let &path = &path . $QTDIR . '/include/QtDesigner/,' 28 let &path = &path . $QTDIR . '/include/QtGui/,' 29 let &path = &path . $QTDIR . '/include/QtNetwork/,' 30 let &path = &path . $QTDIR . '/include/QtOpenGL/,' 31 let &path = &path . $QTDIR . '/include/QtSql/,' 32 let &path = &path . $QTDIR . '/include/QtSvg/,' 33 let &path = &path . $QTDIR . '/include/QtTest/,' 34 let &path = &path . $QTDIR . '/include/QtUiTools/,' 35 let &path = &path . $QTDIR . '/include/QtXml/,' 36endif 37if $KDEDIR != '' 38 let &path = &path . $KDEDIR . '/include/,' 39endif 40if $KDEDIRS != '' 41 let &path = &path . substitute( $KDEDIRS, '\(:\|$\)', '/include,', 'g' ) 42endif 43set path+=, 44 45" Use makeobj to build 46set mp=makeobj 47 48" If TagList is Loaded then get a funny statusline 49" Only works if kde-devel-vim.vim is loaded after taglist. 50" Droping this script in ~/.vim/plugin works fine 51if exists('loaded_taglist') 52 let Tlist_Process_File_Always=1 53 set statusline=%<%f:[\ %{Tlist_Get_Tag_Prototype_By_Line()}\ ]\ %h%m%r%=%-14.(%l,%c%V%)\ %P 54endif 55 56" Insert tab character in whitespace-only lines, complete otherwise 57inoremap <Tab> <C-R>=SmartTab()<CR> 58 59if !exists("DisableSmartParens") 60" Insert a space after ( or [ and before ] or ) unless preceded by a matching 61" paren/bracket or space or inside a string or comment. Comments are only 62" recognized as such if they start on the current line :-( 63inoremap ( <C-R>=SmartParens( '(' )<CR> 64inoremap [ <C-R>=SmartParens( '[' )<CR> 65inoremap ] <C-R>=SmartParens( ']', '[' )<CR> 66inoremap ) <C-R>=SmartParens( ')', '(' )<CR> 67endif 68 69" Insert an #include statement for the current/last symbol 70inoremap <F5> <C-O>:call AddHeader()<CR> 71 72" Insert a forward declaration for the current/last symbol 73inoremap <S-F5> <C-O>:call AddForward()<CR> 74 75" Switch between header and implementation files on ,h 76nmap <silent> ,h :call SwitchHeaderImpl()<CR> 77nmap <silent> ,p :call SwitchPrivateHeaderImpl()<CR> 78 79" Comment selected lines on ,c in visual mode 80vmap ,c :s,^,//X ,<CR>:noh<CR> 81" Uncomment selected lines on ,u in visual mode 82vmap ,u :s,^//X ,,<CR> 83 84" Insert an include guard based on the file name on ,i 85nmap ,i :call IncludeGuard()<CR> 86 87" Insert license headers at the top of the file 88nmap ,lg :call LicenseHeader( "GPL" )<CR> 89nmap ,ll :call LicenseHeader( "LGPL" )<CR> 90nmap ,lm :call LicenseHeader( "MIT" )<CR> 91 92" Expand #i to #include <.h> or #include ".h". The latter is chosen 93" if the character typed after #i is a dquote 94" If the character is > #include <> is inserted (standard C++ headers w/o .h) 95iab #i <C-R>=SmartInclude()<CR> 96 97" Insert a stripped down CVS diff 98iab DIFF <Esc>:call RunDiff()<CR> 99 100" mark 'misplaced' tab characters 101set listchars=tab:�\ ,trail:� 102set list 103 104set incsearch 105 106function! SetCodingStyle() 107 if &syntax == 'cmake' 108 call SmartParensOff() 109 set sw=3 110 set ts=3 111 set et 112 set tw=0 113 return 114 endif 115 if ( &syntax !~ '^\(c\|cpp\|java\)$' ) 116 return 117 endif 118 "the path for the file 119 let pathfn = expand( '%:p:h' ) 120 if pathfn =~ 'nmm' 121 call SmartParensOff() 122 inoremap ( <C-R>=SpaceBetweenKeywordAndParens()<CR> 123 let g:need_brace_on_next_line = '\<\(class\|namespace\|struct\)\>' 124 let g:need_brace_on_same_line = '\<\(if\|else\|while\|switch\|do\|enum\|for\|try\|catch\)\>' 125 set sw=4 126 set ts=4 127 set noet 128 set tw=100 129 elseif pathfn =~ 'xine-lib' 130 call SmartParensOff() 131 let g:need_brace_on_next_line = '\<\(class\|namespace\|struct\)\>' 132 let g:need_brace_on_same_line = '\<\(if\|else\|while\|switch\|do\|foreach\|forever\|enum\|for\|try\|catch\)\>' 133 set sw=2 134 set sts=2 135 set ts=8 136 set noet 137 "set tw=100 138 elseif pathfn =~ 'kdemultimedia\/juk' 139 call SmartParensOff() 140 let g:need_brace_on_next_line = '\<\(class\|namespace\|struct\|if\|else\|while\|switch\|do\|foreach\|forever\|enum\|for\|try\|catch\)\>' 141 let g:need_brace_on_same_line = '' 142 set sw=4 143 set sts=4 144 set et 145 "set tw=100 146 elseif pathfn =~ 'kdenetwork\/kopete' 147 call SmartParensOff() 148 let g:need_brace_on_next_line = '\<\(class\|namespace\|struct\|if\|else\|while\|switch\|do\|foreach\|forever\|enum\|for\|try\|catch\)\>' 149 let g:need_brace_on_same_line = '' 150 set sw=4 151 set sts=4 152 set noet 153 "set tw=100 154 else " kdelibs/kf5/qt coding style 155 call SmartParensOff() 156 inoremap ( <C-R>=SpaceBetweenKeywordAndParens()<CR> 157 let g:need_brace_on_next_line = '\<\(class\|namespace\|struct\)\>' 158 let g:need_brace_on_same_line = '\<\(if\|else\|while\|switch\|do\|foreach\|forever\|enum\|for\|try\|catch\)\>' 159 set sw=4 160 set sts=4 161 set et 162 "set tw=100 163 endif 164 if ( !exists("g:noautobrace") ) 165 call EnableSmartLineBreak() 166 endif 167endfunction 168 169function! DisableSmartLineBreak() 170 iunmap <CR> 171 iuna else 172endfunction 173function! EnableSmartLineBreak() 174 if exists("*pumvisible") 175 inoremap <CR> <C-R>=pumvisible() ? "\<lt>CR>" : "\<lt>ESC>:call SmartLineBreak()\<lt>CR>a\<lt>CR>"<CR> 176 else 177 inoremap <CR> <ESC>:call SmartLineBreak()<CR>a<CR> 178 endif 179 iab else <C-R>=SmartElse()<CR> 180endfunction 181 182function! SmartElse() 183 "let next = nr2char( getchar( 0 ) ) 184 let prefix = '' 185 if strlen(g:need_brace_on_same_line) > 0 && 'else' =~ g:need_brace_on_same_line 186 if getline('.') =~ '^\s*$' 187 if getline(line('.') - 1) =~ '}$' 188 let prefix = prefix . "\<ESC>kmMjdd`MA " 189 elseif getline(line('.') - 1) =~ '}\s*$' 190 let prefix = prefix . "\<ESC>kmMjdd`MA" 191 endif 192 endif 193 endif 194 return prefix . "else\<Right>" 195endfunction 196 197" automatic indenting is required for SmartLineBreak to work correctly 198filetype indent on 199 200function! CreateMatchLine() 201 let linenum = line( '.' ) 202 let current_line = getline( linenum ) 203 " don't do magic if the cursor isn't at the end of the line or if it's 204 " inside a // comment 205 if col( '.' ) != strlen( current_line ) || match( current_line, '//' ) >= 0 206 return '' 207 endif 208 " remove whitespace at the end 209 if match( current_line, '\s\+$' ) >= 0 210 :execute ':s/\s*$//' 211 " the following is needed if return '' is called 212 :execute "normal $" 213 endif 214 let current_line = getline( linenum ) 215 " remove all /* */ comments 216 let current_line = substitute( current_line, '/\*.\{-}\*/', '', 'g' ) 217 " remove all strings 218 let current_line = substitute( current_line, "'[^']*'", '', 'g' ) 219 let current_line = substitute( current_line, '"\(\\"\|[^"]\)*"', '', 'g' ) 220 " remove all ( ) 221 while current_line =~ '(.*)' 222 let current_line = substitute( current_line, '([^()]*)', '', 'g' ) 223 endwhile 224 " prepend earlier lines until we find a ; or { 225 while linenum > 1 && current_line !~ ';' && current_line !~ '{.\+$' 226 let linenum = linenum - 1 227 let prev_line = getline(linenum) 228 if synIDattr(synID(linenum, 1, 1), "name") == 'cComment' "inside a /* */ comment at the beginning of the line 229 if stridx(prev_line, '*/') == -1 230 " next line please 231 let prev_line = '' 232 else 233 " remove everything before */ 234 let prev_line = substitute(prev_line, '^.*\*/', '*/', '') 235 endif 236 endif 237 " remove // comment 238 let prev_line = substitute(prev_line, '//.*$', '', '' ) 239 " concatenate the lines with a space in between 240 let current_line = prev_line.' '.current_line 241 " remove all /* */ comments 242 let current_line = substitute( current_line, '/\*.\{-}\*/', '', 'g' ) 243 " remove all strings 244 let current_line = substitute( current_line, "'[^']*'", '', 'g' ) 245 let current_line = substitute( current_line, '"\(\\"\|[^"]\)*"', '', 'g' ) 246 " remove all ( ) 247 while current_line =~ '(.*)' 248 let current_line = substitute( current_line, '([^()]*)', '', 'g' ) 249 endwhile 250 endwhile 251 " remove everything until the last ; 252 let current_line = substitute( current_line, '^.*;', '', '' ) 253 " remove everything until the last { which is not at the end of the line 254 let current_line = substitute( current_line, '^.*{\(.\+\)$', '\1', '' ) 255 " remove all [ ] 256 while current_line =~ '\[.*\]' 257 let current_line = substitute( current_line, '\[[^\[\]]*\]', '', 'g' ) 258 endwhile 259 " if <CR> was pressed inside ( ), [ ] or /* */ don't add braces 260 if current_line =~ '[(\[]' || current_line =~ '/\*' 261 return '' 262 endif 263 return current_line 264endfunction 265 266function! AddClosingBrace(current_line) 267 if a:current_line =~ '\<enum\|class\|struct\>' 268 :execute "normal o};\<ESC>k" 269 elseif a:current_line =~ '\<namespace\>' 270 let namespace = substitute( a:current_line, '^.*namespace\s\+', '', '' ) 271 let namespace = substitute( namespace, '\s.*$', '', '' ) 272 :execute "normal o} // namespace " . namespace . "\<ESC>k" 273 else 274 :execute "normal o}\<ESC>k" 275 endif 276endfunction 277 278function! SmartLineBreak() 279 if synIDattr(synID(line("."), col("."), 1), "name") == 'cComment' "inside a /* */ comment at the point where the line break occurs 280 return 281 endif 282 let match_line = CreateMatchLine() 283 if match_line == '' 284 return 285 endif 286 287 let match_position1 = -1 288 let match_position2 = -1 289 if strlen(g:need_brace_on_same_line) > 0 290 let match_position1 = match(match_line, g:need_brace_on_same_line) 291 if match_position1 > 0 292 while strpart(match_line, match_position1 - 1, 1) == '#' 293 let old_position = match_position1 294 let match_position1 = match(match_line, g:need_brace_on_same_line, match_position1 + 1) 295 if match_position1 == -1 296 if strpart(match_line, old_position, 2) == 'if' 297 :execute "normal o#endif\<ESC>k$" 298 endif 299 return 300 endif 301 endwhile 302 endif 303 endif 304 if strlen(g:need_brace_on_next_line) > 0 && match_position1 == -1 305 let match_position2 = match(match_line, g:need_brace_on_next_line) 306 if match_position2 > 0 307 while strpart(match_line, match_position2 - 1, 1) == '#' 308 let old_position = match_position2 309 let match_position2 = match(match_line, g:need_brace_on_same_line, match_position2 + 1) 310 if match_position2 == -1 311 if strpart(match_line, old_position, 2) == 'if' 312 :execute "normal o#endif\<ESC>k$" 313 endif 314 return 315 endif 316 endwhile 317 endif 318 endif 319 320 if match_position1 > -1 321 if match_line =~ '}\s*else\>' 322 " make sure else is on the same line as the closing brace 323 if getline('.') =~ '^\s*else' 324 if getline(line('.') - 1) =~ '}$' 325 :execute "normal kA \<ESC>J" 326 elseif getline(line('.') - 1) =~ '}\s*$' 327 :execute "normal kJ" 328 endif 329 endif 330 endif 331 while getline('.') =~ '^\s*{$' 332 " opening brace is on its own line: move it up 333 :execute "normal kJ" 334 endwhile 335 if match_line =~ '{$' 336 if getline('.') =~ '[^ ]{$' 337 :execute ':s/{$/ {/' 338 endif 339 else 340 :execute ':s/$/ {/' 341 endif 342 call AddClosingBrace(match_line) 343 elseif getline('.') =~ '^\s*{$' 344 call AddClosingBrace('') 345 elseif match_position2 > -1 346 if match_line =~ '{$' 347 :execute ':s/\s*{$//' 348 endif 349 :execute "normal o{" 350 call AddClosingBrace(match_line) 351 endif 352 :execute "normal $" 353endfunction 354 355function! SmartParensOn() 356 inoremap ( <C-R>=SmartParens( '(' )<CR> 357 inoremap [ <C-R>=SmartParens( '[' )<CR> 358 inoremap ] <C-R>=SmartParens( ']', '[' )<CR> 359 inoremap ) <C-R>=SmartParens( ')', '(' )<CR> 360endfunction 361 362function! SmartParensOff() 363 if strlen(mapcheck('[','i')) > 0 364 iunmap ( 365 iunmap [ 366 iunmap ] 367 iunmap ) 368 endif 369endfunction 370 371function! SmartTab() 372 let col = col('.') - 1 373 if !col || getline('.')[col-1] !~ '\k' 374 return "\<Tab>" 375 else 376 return "\<C-P>" 377 endif 378endfunction 379 380function! SmartParens( char, ... ) 381 if ! ( &syntax =~ '^\(c\|cpp\|java\)$' ) 382 return a:char 383 endif 384 let s = strpart( getline( '.' ), 0, col( '.' ) - 1 ) 385 if s =~ '//' 386 return a:char 387 endif 388 let s = substitute( s, '/\*\([^*]\|\*\@!/\)*\*/', '', 'g' ) 389 let s = substitute( s, "'[^']*'", '', 'g' ) 390 let s = substitute( s, '"\(\\"\|[^"]\)*"', '', 'g' ) 391 if s =~ "\\([\"']\\|/\\*\\)" 392 return a:char 393 endif 394 if a:0 > 0 395 if strpart( getline( '.' ), col( '.' ) - 3, 2 ) == a:1 . ' ' 396 return "\<BS>" . a:char 397 endif 398 if strpart( getline( '.' ), col( '.' ) - 2, 1 ) == ' ' 399 return a:char 400 endif 401 return ' ' . a:char 402 endif 403 if !exists("g:DisableSpaceBeforeParen") 404 if a:char == '(' 405 if strpart( getline( '.' ), col( '.' ) - 3, 2 ) == 'if' || 406 \strpart( getline( '.' ), col( '.' ) - 4, 3 ) == 'for' || 407 \strpart( getline( '.' ), col( '.' ) - 6, 5 ) == 'while' || 408 \strpart( getline( '.' ), col( '.' ) - 7, 6 ) == 'switch' 409 return ' ( ' 410 endif 411 endif 412 endif 413 return a:char . ' ' 414endfunction 415 416function! SpaceBetweenKeywordAndParens() 417 if ! ( &syntax =~ '^\(c\|cpp\|java\)$' ) 418 return '(' 419 endif 420 let s = strpart( getline( '.' ), 0, col( '.' ) - 1 ) 421 if s =~ '//' 422 " text inside a comment 423 return '(' 424 endif 425 let s = substitute( s, '/\*\([^*]\|\*\@!/\)*\*/', '', 'g' ) 426 let s = substitute( s, "'[^']*'", '', 'g' ) 427 let s = substitute( s, '"\(\\"\|[^"]\)*"', '', 'g' ) 428 if s =~ "\\([\"']\\|/\\*\\)" 429 " text inside a string 430 return '(' 431 endif 432 if a:0 > 0 433 if strpart( getline( '.' ), col( '.' ) - 3, 2 ) == a:1 . ' ' 434 return "\<BS>" . a:char 435 endif 436 if strpart( getline( '.' ), col( '.' ) - 2, 1 ) == ' ' 437 return a:char 438 endif 439 return ' ' . a:char 440 endif 441 if strpart( getline( '.' ), col( '.' ) - 3, 2 ) == 'if' || 442 \strpart( getline( '.' ), col( '.' ) - 4, 3 ) == 'for' || 443 \strpart( getline( '.' ), col( '.' ) - 6, 5 ) == 'while' || 444 \strpart( getline( '.' ), col( '.' ) - 7, 6 ) == 'switch' || 445 \strpart( getline( '.' ), col( '.' ) - 8, 7 ) == 'foreach' || 446 \strpart( getline( '.' ), col( '.' ) - 8, 7 ) == 'forever' 447 return ' (' 448 endif 449 return '(' 450endfunction 451 452function! SwitchHeaderImpl() 453 let privateheaders = '_p\.\([hH]\|hpp\|hxx\)$' 454 let headers = '\.\([hH]\|hpp\|hxx\)$' 455 let impl = '\.\([cC]\|cpp\|cc\|cxx\)$' 456 let fn = expand( '%' ) 457 if fn =~ privateheaders 458 let list = glob( substitute( fn, privateheaders, '.*', '' ) ) 459 elseif fn =~ headers 460 let list = glob( substitute( fn, headers, '.*', '' ) ) 461 elseif fn =~ impl 462 let list = glob( substitute( fn, impl, '.*', '' ) ) 463 endif 464 while strlen( list ) > 0 465 let file = substitute( list, "\n.*", '', '' ) 466 let list = substitute( list, "[^\n]*", '', '' ) 467 let list = substitute( list, "^\n", '', '' ) 468 if ( ( fn =~ headers || fn =~ privateheaders ) && file =~ impl ) || ( fn =~ impl && file =~ headers ) 469 call AskToSave() 470 execute( "edit " . file ) 471 return 472 endif 473 endwhile 474 if ( fn =~ headers ) 475 call AskToSave() 476 if exists( "$implextension" ) 477 let file = substitute( fn, headers, '.' . $implextension, '' ) 478 else 479 let file = substitute( fn, headers, '.cpp', '' ) 480 endif 481 " check for modified state of current buffer and if modified ask: 482 " save, discard, cancel 483 execute( 'edit '.file ) 484 call append( 0, "#include \"".fn."\"" ) 485 call append( 2, "// vim: sw=4 sts=4 et tw=100" ) 486 execute( "set sw=4" ) 487 execute( "set sts=4" ) 488 execute( "set et" ) 489 "execute( "set tw=100" ) 490 elseif fn =~ impl 491 call AskToSave() 492 let file = substitute( fn, impl, '.h', '' ) 493 execute( "edit ".file ) 494 endif 495endfunction 496 497function! SwitchPrivateHeaderImpl() 498 let privateheaders = '_p\.\([hH]\|hpp\|hxx\)$' 499 let headers = '\.\([hH]\|hpp\|hxx\)$' 500 let impl = '\.\([cC]\|cpp\|cc\|cxx\)$' 501 let fn = expand( '%' ) 502 if fn =~ privateheaders 503 let list = glob( substitute( fn, privateheaders, '.*', '' ) ) 504 elseif fn =~ headers 505 let list = glob( substitute( fn, headers, '_p.*', '' ) ) 506 elseif fn =~ impl 507 let list = glob( substitute( fn, impl, '_p.*', '' ) ) 508 endif 509 while strlen( list ) > 0 510 let file = substitute( list, "\n.*", '', '' ) 511 let list = substitute( list, "[^\n]*", '', '' ) 512 let list = substitute( list, "^\n", '', '' ) 513 if ( fn =~ privateheaders && file =~ impl ) || ( fn =~ impl && file =~ privateheaders ) || ( fn =~ headers && file =~ privateheaders ) 514 call AskToSave() 515 execute( "edit " . file ) 516 return 517 endif 518 endwhile 519 if ( fn =~ privateheaders ) 520 call AskToSave() 521 if exists( "$implextension" ) 522 let file = substitute( fn, privateheaders, '.' . $implextension, '' ) 523 else 524 let file = substitute( fn, privateheaders, '.cpp', '' ) 525 endif 526 " check for modified state of current buffer and if modified ask: 527 " save, discard, cancel 528 execute( 'edit '.file ) 529 call append( 0, "#include \"".fn."\"" ) 530 call append( 2, "// vim: sw=4 ts=4 noet" ) 531 execute( "set sw=4" ) 532 execute( "set ts=4" ) 533 elseif fn =~ impl 534 let file = substitute( fn, impl, '_p.h', '' ) 535 call CreatePrivateHeader( file ) 536 elseif fn =~ headers 537 let file = substitute( fn, headers, '_p.h', '' ) 538 call CreatePrivateHeader( file ) 539 endif 540endfunction 541 542function! AskToSave() 543 if &modified 544 let yesorno = input("Save changes before switching file? [Y/n]") 545 if yesorno == 'y' || yesorno == '' || yesorno == 'Y' 546 :execute 'w' 547 return 1 548 else 549 return 0 550 endif 551 endif 552 return 1 553endfunction 554 555function! CreatePrivateHeader( privateHeader ) 556 let privateheaders = '_p\.\([hH]\|hpp\|hxx\)$' 557 let headers = '\.\([hH]\|hpp\|hxx\)$' 558 let impl = '\.\([cC]\|cpp\|cc\|cxx\)$' 559 let fn = expand( '%' ) 560 if fn =~ headers 561 let className = ClassNameFromHeader() 562 elseif fn =~ impl 563 let className = ClassNameFromImpl() 564 endif 565 566 if AskToSave() && fn =~ headers 567 :normal gg 568 " check whether a Q_DECLARE_PRIVATE is needed 569 let dp = search( '\(^\|\s\+\)Q_DECLARE_PRIVATE\s*(\s*'.className.'\s*)' ) 570 if dp == 0 "nothing found 571 call search( '^\s*class\s\+\([A-Za-z0-9]\+_EXPORT\s\+\)\?[A-Za-z_]\+\s*\(:\s*[,\t A-Za-z_]\+\)\?\s*\n\?\s*{' ) 572 call search( '{' ) 573 let @c = className 574 if getline(line('.')+1) =~ 'Q_OBJECT' 575 :normal joQ_DECLARE_PRIVATE(c) 576 else 577 :normal oQ_DECLARE_PRIVATE(c) 578 endif 579 :execute 'w' 580 endif 581 endif 582 execute( "edit ".a:privateHeader ) 583 let privateClassName = className . 'Private' 584 let header = substitute( a:privateHeader, privateheaders, '.h', '' ) 585 586 call IncludeGuard() 587 " FIXME: find out what license to use 588 call LicenseHeader( "LGPL" ) 589 let @h = header 590 let @p = privateClassName 591 let @c = className 592 :normal Gkko 593#include "h" 594 595class p 596Q_DECLARE_PUBLIC(c) 597protected: 598c *q_ptr; 599endfunction 600 601function! ClassNameFromHeader() 602 :normal gg 603 call search( '^\s*class\s\+\([A-Za-z0-9]\+_EXPORT\s\+\)\?[A-Za-z_]\+\s*\(:\s*[,\t A-Za-z_]\+\)\?\s*\n\?\s*{' ) 604 "\zs and \ze mark start and end of the matching 605 return matchstr( getline('.'), '\s\+\zs\w\+\ze\s*\(:\|{\|$\)' ) 606endfunction 607 608function! ClassNameFromImpl() 609 :normal gg 610 call search( '\s*\([A-Za-z_]\+\)::\1\s*(' ) 611 :normal "cye 612 return @c 613endfunction 614 615function! IncludeGuard() 616 let guard = toupper( substitute( expand( '%' ), '[\./]', '_', 'g' ) ) 617 call append( '^', '#define ' . guard ) 618 + 619 call append( '^', '#ifndef ' . guard ) 620 call append( '$', '#endif // ' . guard ) 621 + 622endfunction 623 624function! LicenseHeader( license ) 625 let filename = $HOME . "/" . a:license . "HEADER" 626 execute ":0r " . filename 627" call append( 0, system( "cat " . filename ) ) 628endfunction 629 630function! SmartInclude() 631 let next = nr2char( getchar( 0 ) ) 632 if next == '"' 633 return "#include \".h\"\<Left>\<Left>\<Left>" 634 endif 635 if next == '>' 636 return "#include <>\<Left>" 637 endif 638 return "#include <.h>\<Left>\<Left>\<Left>" 639endfunction 640 641function! MapIdentHeader( ident ) 642 let header = tolower(substitute(a:ident, '::', '/', 'g')).'.h' 643 if a:ident =~ 'Private$' 644 let header = substitute(header, 'private', '_p', '') 645 endif 646 " always prefer the headers in the same directory 647 let check = header 648 let slash = 1 649 while slash != -1 650 if filereadable( check ) 651 return '"' . check . '"' 652 endif 653 let slash = match( check, '/' ) 654 let check = strpart( check, slash + 1 ) 655 endwhile 656 let check = tolower(substitute(a:ident, '::', '/', 'g')).'_p.h' 657 let slash = 1 658 while slash != -1 659 if filereadable(check) 660 return '"' . check . '"' 661 endif 662 let slash = match(check, '/') 663 let check = strpart(check, slash + 1) 664 endwhile 665 666 " Qt stuff 667 if a:ident =~ '^Q[A-Z]' 668 " let's try to find the module 669 let module = '' 670 if $QTDIR != '' 671 if filereadable($QTDIR.'/include/QtCore/'.a:ident) 672 let module = 'QtCore/' 673 elseif filereadable($QTDIR.'/include/QtGui/'.a:ident) 674 let module = 'QtGui/' 675 elseif filereadable($QTDIR.'/include/Qt3Support/'.a:ident) 676 let module = 'Qt3Support/' 677 elseif filereadable($QTDIR.'/include/QtAssistant/'.a:ident) 678 let module = 'QtAssistant/' 679 elseif filereadable($QTDIR.'/include/QtDBus/'.a:ident) 680 let module = 'QtDBus/' 681 elseif filereadable($QTDIR.'/include/QtDesigner/'.a:ident) 682 let module = 'QtDesigner/' 683 elseif filereadable($QTDIR.'/include/QtNetwork/'.a:ident) 684 let module = 'QtNetwork/' 685 elseif filereadable($QTDIR.'/include/QtOpenGL/'.a:ident) 686 let module = 'QtOpenGL/' 687 elseif filereadable($QTDIR.'/include/QtSql/'.a:ident) 688 let module = 'QtSql/' 689 elseif filereadable($QTDIR.'/include/QtSvg/'.a:ident) 690 let module = 'QtSvg/' 691 elseif filereadable($QTDIR.'/include/QtTest/'.a:ident) 692 let module = 'QtTest/' 693 elseif filereadable($QTDIR.'/include/QtUiTools/'.a:ident) 694 let module = 'QtUiTools/' 695 elseif filereadable($QTDIR.'/include/QtXml/'.a:ident) 696 let module = 'QtXml/' 697 endif 698 endif 699 return '<'.module.a:ident.'>' 700 elseif a:ident == 'qDebug' || 701 \a:ident == 'qWarning' || 702 \a:ident == 'qCritical' || 703 \a:ident == 'qFatal' 704 return '<QtCore/QtDebug>' 705 elseif a:ident == 'Q_EXPORT_PLUGIN2' 706 return '<QtCore/QtPlugin>' 707 elseif a:ident =~ 'Q_DECLARE_INTERFACE' 708 return '<QtCore/QObject>' 709 elseif a:ident =~ '^QT_VERSION' || 710 \a:ident =~ '^Q_\(W\|O\)S_' || 711 \a:ident =~ '^Q_CC_' || 712 \a:ident =~ '^Q_.*STRUCTOR_FUNCTION$' || 713 \a:ident =~ '^qu\?int' || 714 \a:ident =~ '^Q_.*_RESOURCE$' || 715 \a:ident == 'qreal' || 716 \a:ident == 'qAbs' || 717 \a:ident == 'qRound' || 718 \a:ident == 'qRound64' || 719 \a:ident == 'qMin' || 720 \a:ident == 'qMax' || 721 \a:ident == 'qBound' || 722 \a:ident == 'qVersion' || 723 \a:ident == 'qSharedBuild' || 724 \a:ident == 'Q_UNUSED' || 725 \a:ident == 'Q_ASSERT' || 726 \a:ident == 'qInstallMsgHandler' || 727 \a:ident == 'Q_GLOBAL_STATIC' || 728 \a:ident == 'Q_GLOBAL_STATIC_WITH_ARGS' || 729 \a:ident == 'qFuzzyCompare' || 730 \a:ident == 'qIsNull' || 731 \a:ident == 'qSwap' || 732 \a:ident =~ 'Q_DECLARE_\(FLAGS\|OPERATORS_FOR_FLAGS\|PRIVATE\|PUBLIC\)' || 733 \a:ident == 'Q_D' || 734 \a:ident == 'Q_Q' || 735 \a:ident == 'Q_DISABLE_COPY' || 736 \a:ident == 'qsrand' || 737 \a:ident == 'qrand' 738 return '<QtCore/QtGlobal>' 739 740 " Phonon stuff 741 elseif a:ident =~ '^Phonon::[A-Z]' 742 if a:ident =~ '^Phonon::\(NoDisc\|Cd\|Dvd\|Vcd\|.\+MetaData\|.*State\|.*Category\|.\+Error\)' 743 return '<Phonon/Global>' 744 endif 745 return '<'.substitute(a:ident, '::', '/', 'g').'>' 746 endif 747 748 " KDE stuff 749 let kdeincdir = substitute(system('kde4-config --prefix'), '[\n\r]*', '', 'g').'/include/KDE/' 750 let classname = substitute(a:ident, '^.*:', '', '') 751 let pathfn = expand('%:p:h') 752 if filereadable(kdeincdir.classname) && !pathfn =~ 'kdelibs' 753 return '<'.classname.'>' 754 elseif filereadable(kdeincdir.'Phonon/'.classname) 755 return '<Phonon/'.classname.'>' 756 elseif filereadable(kdeincdir.'Solid/'.classname) 757 return '<Solid/'.classname.'>' 758 elseif filereadable(kdeincdir.'KIO/'.classname) 759 return '<KIO/'.classname.'>' 760 elseif filereadable(kdeincdir.'KParts/'.classname) 761 return '<KParts/'.classname.'>' 762 elseif a:ident == 'K_GLOBAL_STATIC' 763 return '<KGlobal>' 764 elseif a:ident == 'K_EXPORT_PLUGIN' 765 return '<KPluginLoader>' 766 elseif a:ident =~ 'K_PLUGIN_FACTORY' 767 return '<KPluginFactory>' 768 elseif a:ident == 'K\(Double\|Int\)\(NumInput\|SpinBox\)' 769 return '<knuminput.h>' 770 elseif a:ident == 'KSharedConfig' 771 return '<kconfig.h>' 772 elseif a:ident == 'KConfigGroup' 773 return '<kconfiggroup.h>' 774 elseif a:ident == 'KListViewItem' 775 return '<klistview.h>' 776 elseif a:ident =~ 'kd\(Debug\|Warning\|Error\|Fatal\|Backtrace\)' 777 return '<kdebug.h>' 778 elseif a:ident == 'kapp' 779 return '<kapplication.h>' 780 elseif a:ident == 'i18n' || 781 \a:ident == 'I18N_NOOP' 782 return '<klocale.h>' 783 elseif a:ident == 'locate' || 784 \a:ident == 'locateLocal' 785 return '<kstandarddirs.h>' 786 elseif a:ident =~ '\(Small\|Desktop\|Bar\|MainBar\|User\)Icon\(Set\)\?' || 787 \a:ident == 'IconSize' 788 return '<kiconloader.h>' 789 790 " Standard Library stuff 791 elseif a:ident =~ '\(std::\)\?\(cout\|cerr\|endl\)' 792 return '<iostream>' 793 elseif a:ident =~ '\(std::\)\?is\(alnum\|alpha\|ascii\|blank\|graph\|lower\|print\|punct\|space\|upper\|xdigit\)' 794 return '<cctype>' 795 elseif a:ident == 'printf' 796 return '<cstdio>' 797 endif 798 799 let check = header 800 while 1 801 if filereadable( check ) 802 return '"' . check . '"' 803 endif 804 let slash = match( check, '/' ) 805 if slash == -1 806 return '<' . header . '>' 807 endif 808 let check = strpart( check, slash + 1 ) 809 endwhile 810endfunction 811 812" This is a rather dirty hack, but seems to work somehow :-) (malte) 813function! AddHeader() 814 let s = getline( '.' ) 815 let i = col( '.' ) - 1 816 while i > 0 && strpart( s, i, 1 ) !~ '[A-Za-z0-9_:]' 817 let i = i - 1 818 endwhile 819 while i > 0 && strpart( s, i, 1 ) =~ '[A-Za-z0-9_:]' 820 let i = i - 1 821 endwhile 822 let start = match( s, '[A-Za-z0-9_]\+\(::[A-Z][A-Za-z0-9_]*\)*', i ) 823 let end = matchend( s, '[A-Za-z0-9_]\+\(::[A-Z][A-Za-z0-9_]*\)*', i ) 824" if end > col( '.' ) 825" let end = matchend( s, '[A-Za-z0-9_]\+', i ) 826" endif 827 let ident = strpart( s, start, end - start ) 828 let header = MapIdentHeader(ident) 829 let include = '#include '.header 830 831 let line = 1 832 let incomment = 0 833 let appendpos = 0 834 let codestart = 0 835 let similarpos = 0 836 let similarity = 0 837 while line <= line( '$' ) 838 let s = getline( line ) 839 if incomment == 1 840 let end = matchend( s, '\*/' ) 841 if end == -1 842 let line = line + 1 843 continue 844 else 845 let s = strpart( s, end ) 846 let incomment = 0 847 endif 848 endif 849 let s = substitute( s, '//.*', '', '' ) 850 let s = substitute( s, '/\*\([^*]\|\*\@!/\)*\*/', '', 'g' ) 851 if s =~ '/\*' 852 let incomment = 1 853 elseif s =~ '^' . include 854 break 855 elseif s =~ '^#include' && s !~ '\.moc"' 856 let appendpos = line 857 if s =~ '^#include '.header[0:similarity+1] 858 let similarpos = line 859 let similarity = similarity + 1 860 while s =~ '^#include '.header[0:similarity+1] 861 let similarity = similarity + 1 862 endwhile 863 if s[9:strlen(s)-2] > header[0:strlen(header)-2] 864 let similarpos = similarpos - 1 865 let similarity = 100 "this include belongs one line higher (assuming the order of includes already is alphabetically) 866 endif 867 endif 868 elseif codestart == 0 && s !~ '^$' 869 let codestart = line 870 endif 871 let line = line + 1 872 endwhile 873 if similarpos > 0 874 let appendpos = similarpos 875 endif 876 if line == line( '$' ) + 1 877 if appendpos == 0 878 call append( codestart - 1, include ) 879 call append( codestart, '' ) 880 else 881 call append( appendpos, include ) 882 endif 883 endif 884endfunction 885 886function! AddForward() 887 let s = getline( '.' ) 888 let i = col( '.' ) - 1 889 while i > 0 && strpart( s, i, 1 ) !~ '[A-Za-z0-9_:]' 890 let i = i - 1 891 endwhile 892 while i > 0 && strpart( s, i, 1 ) =~ '[A-Za-z0-9_:]' 893 let i = i - 1 894 endwhile 895 let start = match( s, '[A-Za-z0-9_]\+\(::[A-Za-z0-9_]\+\)*', i ) 896 let end = matchend( s, '[A-Za-z0-9_]\+\(::[A-Za-z0-9_]\+\)*', i ) 897 if end > col( '.' ) 898 let end = matchend( s, '[A-Za-z0-9_]\+', i ) 899 endif 900 let ident = strpart( s, start, end - start ) 901 let forward = 'class ' . ident . ';' 902 903 let line = 1 904 let incomment = 0 905 let appendpos = 0 906 let codestart = 0 907 while line <= line( '$' ) 908 let s = getline( line ) 909 if incomment == 1 910 let end = matchend( s, '\*/' ) 911 if end == -1 912 let line = line + 1 913 continue 914 else 915 let s = strpart( s, end ) 916 let incomment = 0 917 endif 918 endif 919 let s = substitute( s, '//.*', '', '' ) 920 let s = substitute( s, '/\*\([^*]\|\*\@!/\)*\*/', '', 'g' ) 921 if s =~ '/\*' 922 let incomment = 1 923 elseif s =~ '^' . forward 924 break 925 elseif s =~ '^\s*class [A-za-z0-9_]\+;' || (s =~ '^#include' && s !~ '\.moc"') 926 let appendpos = line 927 elseif codestart == 0 && s !~ '^$' 928 let codestart = line 929 endif 930 let line = line + 1 931 endwhile 932 if line == line( '$' ) + 1 933 if appendpos == 0 934 call append( codestart - 1, forward ) 935 call append( codestart, '' ) 936 else 937 call append( appendpos, forward ) 938 endif 939 endif 940endfunction 941 942function! RunDiff() 943 echo 'Diffing....' 944 read! cvs diff -bB -I \\\#include | egrep -v '(^Index:|^=+$|^RCS file:|^retrieving revision|^diff -u|^[+-]{3})' 945endfunction 946 947function! CreateChangeLogEntry() 948 let currentBuffer = expand( "%" ) 949 950 if exists( "g:EMAIL" ) 951 let mail = g:EMAIL 952 elseif exists( "$EMAIL" ) 953 let mail = $EMAIL 954 else 955 let mail = inputdialog( "Enter Name/Email for Changelog entry: " ) 956 if mail == "" 957 echo "Aborted ChangeLog edit..." 958 return 959 endif 960 let g:EMAIL = mail 961 endif 962 963 if bufname( "ChangeLog" ) != "" && bufwinnr( bufname( "ChangeLog" ) ) != -1 964 execute bufwinnr( bufname( "ChangeLog" ) ) . " wincmd w" 965 else 966 execute "split ChangeLog" 967 endif 968 969 let lastEntry = getline( nextnonblank( 1 ) ) 970 let newEntry = strftime("%Y-%m-%d") . " " . mail 971 972 if lastEntry != newEntry 973 call append( 0, "" ) 974 call append( 0, "" ) 975 call append( 0, newEntry ) 976 endif 977 978 " like emacs, prepend the current buffer name to the entry. but unlike 979 " emacs I have no idea how to figure out the current function name :( 980 " (Simon) 981 if currentBuffer != "" 982 let newLine = "\t* " . currentBuffer . ": " 983 else 984 let newLine = "\t* " 985 endif 986 987 call append( 2, newLine ) 988 989 execute "normal 3G$" 990endfunction 991 992function! AddQtSyntax() 993 if expand( "<amatch>" ) == "cpp" 994 syn keyword qtKeywords signals slots emit Q_SLOTS Q_SIGNALS 995 syn keyword qtMacros Q_OBJECT Q_WIDGET Q_PROPERTY Q_ENUMS Q_OVERRIDE Q_CLASSINFO Q_SETS SIGNAL SLOT Q_DECLARE_PUBLIC Q_DECLARE_PRIVATE Q_D Q_Q Q_DISABLE_COPY Q_DECLARE_METATYPE Q_PRIVATE_SLOT Q_FLAGS Q_INTERFACES Q_DECLARE_INTERFACE Q_EXPORT_PLUGIN2 Q_GADGET Q_SCRIPTABLE Q_INVOKABLE METHOD Q_ARG Q_RETURN_ARG Q_GLOBAL_STATIC Q_GLOBAL_STATIC_WITH_ARGS 996 syn keyword qtCast qt_cast qobject_cast qvariant_cast qstyleoption_cast qgraphicsitem_cast 997 syn keyword qtTypedef uchar uint ushort ulong Q_INT8 Q_UINT8 Q_INT16 Q_UINT16 Q_INT32 Q_UINT32 Q_LONG Q_ULONG Q_INT64 Q_UINT64 Q_LLONG Q_ULLONG pchar puchar pcchar qint8 quint8 qint16 quint16 qint32 quint32 qint64 quint64 qlonglong qulonglong qreal 998 syn keyword kdeMacros ASYNC PHONON_ABSTRACTBASE PHONON_OBJECT PHONON_HEIR PHONON_ABSTRACTBASE_IMPL PHONON_OBJECT_IMPL PHONON_HEIR_IMPL PHONON_PRIVATECLASS PHONON_PRIVATEABSTRACTCLASS K_DECLARE_PRIVATE K_D K_EXPORT_PLUGIN K_PLUGIN_FACTORY K_PLUGIN_FACTORY_DEFINITION K_PLUGIN_FACTORY_DECLARATION K_GLOBAL_STATIC K_GLOBAL_STATIC_WITH_ARGS 999 syn keyword cRepeat foreach 1000 syn keyword cRepeat forever 1001 1002 hi def link qtKeywords Statement 1003 hi def link qtMacros Type 1004 hi def link qtCast Statement 1005 hi def link qtTypedef Type 1006 hi def link kdeMacros Type 1007 endif 1008endfunction 1009 1010function! UpdateMocFiles() 1011 if &syntax == "cpp" 1012 let i = 1 1013 while i < 80 1014 let s = getline( i ) 1015 if s =~ '^#include ".*\.moc"' 1016 let s = substitute( s, '.*"\(.*\)\.moc"', '\1.h', '' ) 1017 if stridx( &complete, s ) == -1 1018 let &complete = &complete . ',k' . s 1019 endif 1020 break 1021 endif 1022 let i = i + 1 1023 endwhile 1024 endif 1025endfunction 1026 1027autocmd Syntax * call AddQtSyntax() 1028autocmd CursorHold * call UpdateMocFiles() 1029autocmd BufNewFile,BufRead * call SetCodingStyle() 1030 1031" vim: sw=4 sts=4 et 1032