Warning, /sdk/kde-dev-scripts/kde-devel-vim.vim is written in an unsupported language. File is not indexed.
0001 " To use this file, add this line to your ~/.vimrc:, w/o the dquote
0002 " source /path/to/kde/sources/kdesdk/scripts/kde-devel-vim.vim
0003 "
0004 " For CreateChangeLogEntry() : If you don't want to re-enter your
0005 " Name/Email in each vim session then make sure to have the viminfo
0006 " option enabled in your ~/.vimrc, with the '!' flag, enabling persistent
0007 " storage of global variables. Something along the line of
0008 " set viminfo=%,!,'50,\"100,:100,n~/.viminfo
0009 " should do the trick.
0010 "
0011 " To make use of the ,ll and ,lg shortcuts you need to have the files
0012 " GPLHEADER and LGPLHEADER in your home directory. Their content will be
0013 " copied as license header then.
0014
0015 " Don't include these in filename completions
0016 set suffixes+=.lo,.o,.moc,.la,.closure,.loT
0017
0018 " Search for headers here
0019 set path=.,/usr/include,/usr/local/include,
0020 if $QTDIR != ''
0021 let &path = &path . $QTDIR . '/include/,'
0022 let &path = &path . $QTDIR . '/include/Qt/,'
0023 let &path = &path . $QTDIR . '/include/QtCore/,'
0024 let &path = &path . $QTDIR . '/include/Qt3Support/,'
0025 let &path = &path . $QTDIR . '/include/QtAssistant/,'
0026 let &path = &path . $QTDIR . '/include/QtDBus/,'
0027 let &path = &path . $QTDIR . '/include/QtDesigner/,'
0028 let &path = &path . $QTDIR . '/include/QtGui/,'
0029 let &path = &path . $QTDIR . '/include/QtNetwork/,'
0030 let &path = &path . $QTDIR . '/include/QtOpenGL/,'
0031 let &path = &path . $QTDIR . '/include/QtSql/,'
0032 let &path = &path . $QTDIR . '/include/QtSvg/,'
0033 let &path = &path . $QTDIR . '/include/QtTest/,'
0034 let &path = &path . $QTDIR . '/include/QtUiTools/,'
0035 let &path = &path . $QTDIR . '/include/QtXml/,'
0036 endif
0037 if $KDEDIR != ''
0038 let &path = &path . $KDEDIR . '/include/,'
0039 endif
0040 if $KDEDIRS != ''
0041 let &path = &path . substitute( $KDEDIRS, '\(:\|$\)', '/include,', 'g' )
0042 endif
0043 set path+=,
0044
0045 " Use makeobj to build
0046 set mp=makeobj
0047
0048 " If TagList is Loaded then get a funny statusline
0049 " Only works if kde-devel-vim.vim is loaded after taglist.
0050 " Droping this script in ~/.vim/plugin works fine
0051 if exists('loaded_taglist')
0052 let Tlist_Process_File_Always=1
0053 set statusline=%<%f:[\ %{Tlist_Get_Tag_Prototype_By_Line()}\ ]\ %h%m%r%=%-14.(%l,%c%V%)\ %P
0054 endif
0055
0056 " Insert tab character in whitespace-only lines, complete otherwise
0057 inoremap <Tab> <C-R>=SmartTab()<CR>
0058
0059 if !exists("DisableSmartParens")
0060 " Insert a space after ( or [ and before ] or ) unless preceded by a matching
0061 " paren/bracket or space or inside a string or comment. Comments are only
0062 " recognized as such if they start on the current line :-(
0063 inoremap ( <C-R>=SmartParens( '(' )<CR>
0064 inoremap [ <C-R>=SmartParens( '[' )<CR>
0065 inoremap ] <C-R>=SmartParens( ']', '[' )<CR>
0066 inoremap ) <C-R>=SmartParens( ')', '(' )<CR>
0067 endif
0068
0069 " Insert an #include statement for the current/last symbol
0070 inoremap <F5> <C-O>:call AddHeader()<CR>
0071
0072 " Insert a forward declaration for the current/last symbol
0073 inoremap <S-F5> <C-O>:call AddForward()<CR>
0074
0075 " Switch between header and implementation files on ,h
0076 nmap <silent> ,h :call SwitchHeaderImpl()<CR>
0077 nmap <silent> ,p :call SwitchPrivateHeaderImpl()<CR>
0078
0079 " Comment selected lines on ,c in visual mode
0080 vmap ,c :s,^,//X ,<CR>:noh<CR>
0081 " Uncomment selected lines on ,u in visual mode
0082 vmap ,u :s,^//X ,,<CR>
0083
0084 " Insert an include guard based on the file name on ,i
0085 nmap ,i :call IncludeGuard()<CR>
0086
0087 " Insert license headers at the top of the file
0088 nmap ,lg :call LicenseHeader( "GPL" )<CR>
0089 nmap ,ll :call LicenseHeader( "LGPL" )<CR>
0090 nmap ,lm :call LicenseHeader( "MIT" )<CR>
0091
0092 " Expand #i to #include <.h> or #include ".h". The latter is chosen
0093 " if the character typed after #i is a dquote
0094 " If the character is > #include <> is inserted (standard C++ headers w/o .h)
0095 iab #i <C-R>=SmartInclude()<CR>
0096
0097 " Insert a stripped down CVS diff
0098 iab DIFF <Esc>:call RunDiff()<CR>
0099
0100 " mark 'misplaced' tab characters
0101 set listchars=tab:·\ ,trail:·
0102 set list
0103
0104 set incsearch
0105
0106 function! SetCodingStyle()
0107 if &syntax == 'cmake'
0108 call SmartParensOff()
0109 set sw=3
0110 set ts=3
0111 set et
0112 set tw=0
0113 return
0114 endif
0115 if ( &syntax !~ '^\(c\|cpp\|java\)$' )
0116 return
0117 endif
0118 "the path for the file
0119 let pathfn = expand( '%:p:h' )
0120 if pathfn =~ 'nmm'
0121 call SmartParensOff()
0122 inoremap ( <C-R>=SpaceBetweenKeywordAndParens()<CR>
0123 let g:need_brace_on_next_line = '\<\(class\|namespace\|struct\)\>'
0124 let g:need_brace_on_same_line = '\<\(if\|else\|while\|switch\|do\|enum\|for\|try\|catch\)\>'
0125 set sw=4
0126 set ts=4
0127 set noet
0128 set tw=100
0129 elseif pathfn =~ 'xine-lib'
0130 call SmartParensOff()
0131 let g:need_brace_on_next_line = '\<\(class\|namespace\|struct\)\>'
0132 let g:need_brace_on_same_line = '\<\(if\|else\|while\|switch\|do\|foreach\|forever\|enum\|for\|try\|catch\)\>'
0133 set sw=2
0134 set sts=2
0135 set ts=8
0136 set noet
0137 "set tw=100
0138 elseif pathfn =~ 'kdemultimedia\/juk'
0139 call SmartParensOff()
0140 let g:need_brace_on_next_line = '\<\(class\|namespace\|struct\|if\|else\|while\|switch\|do\|foreach\|forever\|enum\|for\|try\|catch\)\>'
0141 let g:need_brace_on_same_line = ''
0142 set sw=4
0143 set sts=4
0144 set et
0145 "set tw=100
0146 elseif pathfn =~ 'kdenetwork\/kopete'
0147 call SmartParensOff()
0148 let g:need_brace_on_next_line = '\<\(class\|namespace\|struct\|if\|else\|while\|switch\|do\|foreach\|forever\|enum\|for\|try\|catch\)\>'
0149 let g:need_brace_on_same_line = ''
0150 set sw=4
0151 set sts=4
0152 set noet
0153 "set tw=100
0154 else " kdelibs/kf5/qt coding style
0155 call SmartParensOff()
0156 inoremap ( <C-R>=SpaceBetweenKeywordAndParens()<CR>
0157 let g:need_brace_on_next_line = '\<\(class\|namespace\|struct\)\>'
0158 let g:need_brace_on_same_line = '\<\(if\|else\|while\|switch\|do\|foreach\|forever\|enum\|for\|try\|catch\)\>'
0159 set sw=4
0160 set sts=4
0161 set et
0162 "set tw=100
0163 endif
0164 if ( !exists("g:noautobrace") )
0165 call EnableSmartLineBreak()
0166 endif
0167 endfunction
0168
0169 function! DisableSmartLineBreak()
0170 iunmap <CR>
0171 iuna else
0172 endfunction
0173 function! EnableSmartLineBreak()
0174 if exists("*pumvisible")
0175 inoremap <CR> <C-R>=pumvisible() ? "\<lt>CR>" : "\<lt>ESC>:call SmartLineBreak()\<lt>CR>a\<lt>CR>"<CR>
0176 else
0177 inoremap <CR> <ESC>:call SmartLineBreak()<CR>a<CR>
0178 endif
0179 iab else <C-R>=SmartElse()<CR>
0180 endfunction
0181
0182 function! SmartElse()
0183 "let next = nr2char( getchar( 0 ) )
0184 let prefix = ''
0185 if strlen(g:need_brace_on_same_line) > 0 && 'else' =~ g:need_brace_on_same_line
0186 if getline('.') =~ '^\s*$'
0187 if getline(line('.') - 1) =~ '}$'
0188 let prefix = prefix . "\<ESC>kmMjdd`MA "
0189 elseif getline(line('.') - 1) =~ '}\s*$'
0190 let prefix = prefix . "\<ESC>kmMjdd`MA"
0191 endif
0192 endif
0193 endif
0194 return prefix . "else\<Right>"
0195 endfunction
0196
0197 " automatic indenting is required for SmartLineBreak to work correctly
0198 filetype indent on
0199
0200 function! CreateMatchLine()
0201 let linenum = line( '.' )
0202 let current_line = getline( linenum )
0203 " don't do magic if the cursor isn't at the end of the line or if it's
0204 " inside a // comment
0205 if col( '.' ) != strlen( current_line ) || match( current_line, '//' ) >= 0
0206 return ''
0207 endif
0208 " remove whitespace at the end
0209 if match( current_line, '\s\+$' ) >= 0
0210 :execute ':s/\s*$//'
0211 " the following is needed if return '' is called
0212 :execute "normal $"
0213 endif
0214 let current_line = getline( linenum )
0215 " remove all /* */ comments
0216 let current_line = substitute( current_line, '/\*.\{-}\*/', '', 'g' )
0217 " remove all strings
0218 let current_line = substitute( current_line, "'[^']*'", '', 'g' )
0219 let current_line = substitute( current_line, '"\(\\"\|[^"]\)*"', '', 'g' )
0220 " remove all ( )
0221 while current_line =~ '(.*)'
0222 let current_line = substitute( current_line, '([^()]*)', '', 'g' )
0223 endwhile
0224 " prepend earlier lines until we find a ; or {
0225 while linenum > 1 && current_line !~ ';' && current_line !~ '{.\+$'
0226 let linenum = linenum - 1
0227 let prev_line = getline(linenum)
0228 if synIDattr(synID(linenum, 1, 1), "name") == 'cComment' "inside a /* */ comment at the beginning of the line
0229 if stridx(prev_line, '*/') == -1
0230 " next line please
0231 let prev_line = ''
0232 else
0233 " remove everything before */
0234 let prev_line = substitute(prev_line, '^.*\*/', '*/', '')
0235 endif
0236 endif
0237 " remove // comment
0238 let prev_line = substitute(prev_line, '//.*$', '', '' )
0239 " concatenate the lines with a space in between
0240 let current_line = prev_line.' '.current_line
0241 " remove all /* */ comments
0242 let current_line = substitute( current_line, '/\*.\{-}\*/', '', 'g' )
0243 " remove all strings
0244 let current_line = substitute( current_line, "'[^']*'", '', 'g' )
0245 let current_line = substitute( current_line, '"\(\\"\|[^"]\)*"', '', 'g' )
0246 " remove all ( )
0247 while current_line =~ '(.*)'
0248 let current_line = substitute( current_line, '([^()]*)', '', 'g' )
0249 endwhile
0250 endwhile
0251 " remove everything until the last ;
0252 let current_line = substitute( current_line, '^.*;', '', '' )
0253 " remove everything until the last { which is not at the end of the line
0254 let current_line = substitute( current_line, '^.*{\(.\+\)$', '\1', '' )
0255 " remove all [ ]
0256 while current_line =~ '\[.*\]'
0257 let current_line = substitute( current_line, '\[[^\[\]]*\]', '', 'g' )
0258 endwhile
0259 " if <CR> was pressed inside ( ), [ ] or /* */ don't add braces
0260 if current_line =~ '[(\[]' || current_line =~ '/\*'
0261 return ''
0262 endif
0263 return current_line
0264 endfunction
0265
0266 function! AddClosingBrace(current_line)
0267 if a:current_line =~ '\<enum\|class\|struct\>'
0268 :execute "normal o};\<ESC>k"
0269 elseif a:current_line =~ '\<namespace\>'
0270 let namespace = substitute( a:current_line, '^.*namespace\s\+', '', '' )
0271 let namespace = substitute( namespace, '\s.*$', '', '' )
0272 :execute "normal o} // namespace " . namespace . "\<ESC>k"
0273 else
0274 :execute "normal o}\<ESC>k"
0275 endif
0276 endfunction
0277
0278 function! SmartLineBreak()
0279 if synIDattr(synID(line("."), col("."), 1), "name") == 'cComment' "inside a /* */ comment at the point where the line break occurs
0280 return
0281 endif
0282 let match_line = CreateMatchLine()
0283 if match_line == ''
0284 return
0285 endif
0286
0287 let match_position1 = -1
0288 let match_position2 = -1
0289 if strlen(g:need_brace_on_same_line) > 0
0290 let match_position1 = match(match_line, g:need_brace_on_same_line)
0291 if match_position1 > 0
0292 while strpart(match_line, match_position1 - 1, 1) == '#'
0293 let old_position = match_position1
0294 let match_position1 = match(match_line, g:need_brace_on_same_line, match_position1 + 1)
0295 if match_position1 == -1
0296 if strpart(match_line, old_position, 2) == 'if'
0297 :execute "normal o#endif\<ESC>k$"
0298 endif
0299 return
0300 endif
0301 endwhile
0302 endif
0303 endif
0304 if strlen(g:need_brace_on_next_line) > 0 && match_position1 == -1
0305 let match_position2 = match(match_line, g:need_brace_on_next_line)
0306 if match_position2 > 0
0307 while strpart(match_line, match_position2 - 1, 1) == '#'
0308 let old_position = match_position2
0309 let match_position2 = match(match_line, g:need_brace_on_same_line, match_position2 + 1)
0310 if match_position2 == -1
0311 if strpart(match_line, old_position, 2) == 'if'
0312 :execute "normal o#endif\<ESC>k$"
0313 endif
0314 return
0315 endif
0316 endwhile
0317 endif
0318 endif
0319
0320 if match_position1 > -1
0321 if match_line =~ '}\s*else\>'
0322 " make sure else is on the same line as the closing brace
0323 if getline('.') =~ '^\s*else'
0324 if getline(line('.') - 1) =~ '}$'
0325 :execute "normal kA \<ESC>J"
0326 elseif getline(line('.') - 1) =~ '}\s*$'
0327 :execute "normal kJ"
0328 endif
0329 endif
0330 endif
0331 while getline('.') =~ '^\s*{$'
0332 " opening brace is on its own line: move it up
0333 :execute "normal kJ"
0334 endwhile
0335 if match_line =~ '{$'
0336 if getline('.') =~ '[^ ]{$'
0337 :execute ':s/{$/ {/'
0338 endif
0339 else
0340 :execute ':s/$/ {/'
0341 endif
0342 call AddClosingBrace(match_line)
0343 elseif getline('.') =~ '^\s*{$'
0344 call AddClosingBrace('')
0345 elseif match_position2 > -1
0346 if match_line =~ '{$'
0347 :execute ':s/\s*{$//'
0348 endif
0349 :execute "normal o{"
0350 call AddClosingBrace(match_line)
0351 endif
0352 :execute "normal $"
0353 endfunction
0354
0355 function! SmartParensOn()
0356 inoremap ( <C-R>=SmartParens( '(' )<CR>
0357 inoremap [ <C-R>=SmartParens( '[' )<CR>
0358 inoremap ] <C-R>=SmartParens( ']', '[' )<CR>
0359 inoremap ) <C-R>=SmartParens( ')', '(' )<CR>
0360 endfunction
0361
0362 function! SmartParensOff()
0363 if strlen(mapcheck('[','i')) > 0
0364 iunmap (
0365 iunmap [
0366 iunmap ]
0367 iunmap )
0368 endif
0369 endfunction
0370
0371 function! SmartTab()
0372 let col = col('.') - 1
0373 if !col || getline('.')[col-1] !~ '\k'
0374 return "\<Tab>"
0375 else
0376 return "\<C-P>"
0377 endif
0378 endfunction
0379
0380 function! SmartParens( char, ... )
0381 if ! ( &syntax =~ '^\(c\|cpp\|java\)$' )
0382 return a:char
0383 endif
0384 let s = strpart( getline( '.' ), 0, col( '.' ) - 1 )
0385 if s =~ '//'
0386 return a:char
0387 endif
0388 let s = substitute( s, '/\*\([^*]\|\*\@!/\)*\*/', '', 'g' )
0389 let s = substitute( s, "'[^']*'", '', 'g' )
0390 let s = substitute( s, '"\(\\"\|[^"]\)*"', '', 'g' )
0391 if s =~ "\\([\"']\\|/\\*\\)"
0392 return a:char
0393 endif
0394 if a:0 > 0
0395 if strpart( getline( '.' ), col( '.' ) - 3, 2 ) == a:1 . ' '
0396 return "\<BS>" . a:char
0397 endif
0398 if strpart( getline( '.' ), col( '.' ) - 2, 1 ) == ' '
0399 return a:char
0400 endif
0401 return ' ' . a:char
0402 endif
0403 if !exists("g:DisableSpaceBeforeParen")
0404 if a:char == '('
0405 if strpart( getline( '.' ), col( '.' ) - 3, 2 ) == 'if' ||
0406 \strpart( getline( '.' ), col( '.' ) - 4, 3 ) == 'for' ||
0407 \strpart( getline( '.' ), col( '.' ) - 6, 5 ) == 'while' ||
0408 \strpart( getline( '.' ), col( '.' ) - 7, 6 ) == 'switch'
0409 return ' ( '
0410 endif
0411 endif
0412 endif
0413 return a:char . ' '
0414 endfunction
0415
0416 function! SpaceBetweenKeywordAndParens()
0417 if ! ( &syntax =~ '^\(c\|cpp\|java\)$' )
0418 return '('
0419 endif
0420 let s = strpart( getline( '.' ), 0, col( '.' ) - 1 )
0421 if s =~ '//'
0422 " text inside a comment
0423 return '('
0424 endif
0425 let s = substitute( s, '/\*\([^*]\|\*\@!/\)*\*/', '', 'g' )
0426 let s = substitute( s, "'[^']*'", '', 'g' )
0427 let s = substitute( s, '"\(\\"\|[^"]\)*"', '', 'g' )
0428 if s =~ "\\([\"']\\|/\\*\\)"
0429 " text inside a string
0430 return '('
0431 endif
0432 if a:0 > 0
0433 if strpart( getline( '.' ), col( '.' ) - 3, 2 ) == a:1 . ' '
0434 return "\<BS>" . a:char
0435 endif
0436 if strpart( getline( '.' ), col( '.' ) - 2, 1 ) == ' '
0437 return a:char
0438 endif
0439 return ' ' . a:char
0440 endif
0441 if strpart( getline( '.' ), col( '.' ) - 3, 2 ) == 'if' ||
0442 \strpart( getline( '.' ), col( '.' ) - 4, 3 ) == 'for' ||
0443 \strpart( getline( '.' ), col( '.' ) - 6, 5 ) == 'while' ||
0444 \strpart( getline( '.' ), col( '.' ) - 7, 6 ) == 'switch' ||
0445 \strpart( getline( '.' ), col( '.' ) - 8, 7 ) == 'foreach' ||
0446 \strpart( getline( '.' ), col( '.' ) - 8, 7 ) == 'forever'
0447 return ' ('
0448 endif
0449 return '('
0450 endfunction
0451
0452 function! SwitchHeaderImpl()
0453 let privateheaders = '_p\.\([hH]\|hpp\|hxx\)$'
0454 let headers = '\.\([hH]\|hpp\|hxx\)$'
0455 let impl = '\.\([cC]\|cpp\|cc\|cxx\)$'
0456 let fn = expand( '%' )
0457 if fn =~ privateheaders
0458 let list = glob( substitute( fn, privateheaders, '.*', '' ) )
0459 elseif fn =~ headers
0460 let list = glob( substitute( fn, headers, '.*', '' ) )
0461 elseif fn =~ impl
0462 let list = glob( substitute( fn, impl, '.*', '' ) )
0463 endif
0464 while strlen( list ) > 0
0465 let file = substitute( list, "\n.*", '', '' )
0466 let list = substitute( list, "[^\n]*", '', '' )
0467 let list = substitute( list, "^\n", '', '' )
0468 if ( ( fn =~ headers || fn =~ privateheaders ) && file =~ impl ) || ( fn =~ impl && file =~ headers )
0469 call AskToSave()
0470 execute( "edit " . file )
0471 return
0472 endif
0473 endwhile
0474 if ( fn =~ headers )
0475 call AskToSave()
0476 if exists( "$implextension" )
0477 let file = substitute( fn, headers, '.' . $implextension, '' )
0478 else
0479 let file = substitute( fn, headers, '.cpp', '' )
0480 endif
0481 " check for modified state of current buffer and if modified ask:
0482 " save, discard, cancel
0483 execute( 'edit '.file )
0484 call append( 0, "#include \"".fn."\"" )
0485 call append( 2, "// vim: sw=4 sts=4 et tw=100" )
0486 execute( "set sw=4" )
0487 execute( "set sts=4" )
0488 execute( "set et" )
0489 "execute( "set tw=100" )
0490 elseif fn =~ impl
0491 call AskToSave()
0492 let file = substitute( fn, impl, '.h', '' )
0493 execute( "edit ".file )
0494 endif
0495 endfunction
0496
0497 function! SwitchPrivateHeaderImpl()
0498 let privateheaders = '_p\.\([hH]\|hpp\|hxx\)$'
0499 let headers = '\.\([hH]\|hpp\|hxx\)$'
0500 let impl = '\.\([cC]\|cpp\|cc\|cxx\)$'
0501 let fn = expand( '%' )
0502 if fn =~ privateheaders
0503 let list = glob( substitute( fn, privateheaders, '.*', '' ) )
0504 elseif fn =~ headers
0505 let list = glob( substitute( fn, headers, '_p.*', '' ) )
0506 elseif fn =~ impl
0507 let list = glob( substitute( fn, impl, '_p.*', '' ) )
0508 endif
0509 while strlen( list ) > 0
0510 let file = substitute( list, "\n.*", '', '' )
0511 let list = substitute( list, "[^\n]*", '', '' )
0512 let list = substitute( list, "^\n", '', '' )
0513 if ( fn =~ privateheaders && file =~ impl ) || ( fn =~ impl && file =~ privateheaders ) || ( fn =~ headers && file =~ privateheaders )
0514 call AskToSave()
0515 execute( "edit " . file )
0516 return
0517 endif
0518 endwhile
0519 if ( fn =~ privateheaders )
0520 call AskToSave()
0521 if exists( "$implextension" )
0522 let file = substitute( fn, privateheaders, '.' . $implextension, '' )
0523 else
0524 let file = substitute( fn, privateheaders, '.cpp', '' )
0525 endif
0526 " check for modified state of current buffer and if modified ask:
0527 " save, discard, cancel
0528 execute( 'edit '.file )
0529 call append( 0, "#include \"".fn."\"" )
0530 call append( 2, "// vim: sw=4 ts=4 noet" )
0531 execute( "set sw=4" )
0532 execute( "set ts=4" )
0533 elseif fn =~ impl
0534 let file = substitute( fn, impl, '_p.h', '' )
0535 call CreatePrivateHeader( file )
0536 elseif fn =~ headers
0537 let file = substitute( fn, headers, '_p.h', '' )
0538 call CreatePrivateHeader( file )
0539 endif
0540 endfunction
0541
0542 function! AskToSave()
0543 if &modified
0544 let yesorno = input("Save changes before switching file? [Y/n]")
0545 if yesorno == 'y' || yesorno == '' || yesorno == 'Y'
0546 :execute 'w'
0547 return 1
0548 else
0549 return 0
0550 endif
0551 endif
0552 return 1
0553 endfunction
0554
0555 function! CreatePrivateHeader( privateHeader )
0556 let privateheaders = '_p\.\([hH]\|hpp\|hxx\)$'
0557 let headers = '\.\([hH]\|hpp\|hxx\)$'
0558 let impl = '\.\([cC]\|cpp\|cc\|cxx\)$'
0559 let fn = expand( '%' )
0560 if fn =~ headers
0561 let className = ClassNameFromHeader()
0562 elseif fn =~ impl
0563 let className = ClassNameFromImpl()
0564 endif
0565
0566 if AskToSave() && fn =~ headers
0567 :normal gg
0568 " check whether a Q_DECLARE_PRIVATE is needed
0569 let dp = search( '\(^\|\s\+\)Q_DECLARE_PRIVATE\s*(\s*'.className.'\s*)' )
0570 if dp == 0 "nothing found
0571 call search( '^\s*class\s\+\([A-Za-z0-9]\+_EXPORT\s\+\)\?[A-Za-z_]\+\s*\(:\s*[,\t A-Za-z_]\+\)\?\s*\n\?\s*{' )
0572 call search( '{' )
0573 let @c = className
0574 if getline(line('.')+1) =~ 'Q_OBJECT'
0575 :normal joQ_DECLARE_PRIVATE(c)
0576 else
0577 :normal oQ_DECLARE_PRIVATE(c)
0578 endif
0579 :execute 'w'
0580 endif
0581 endif
0582 execute( "edit ".a:privateHeader )
0583 let privateClassName = className . 'Private'
0584 let header = substitute( a:privateHeader, privateheaders, '.h', '' )
0585
0586 call IncludeGuard()
0587 " FIXME: find out what license to use
0588 call LicenseHeader( "LGPL" )
0589 let @h = header
0590 let @p = privateClassName
0591 let @c = className
0592 :normal Gkko
#include "h"
class p
Q_DECLARE_PUBLIC(c)
protected:
c *q_ptr;
0593 endfunction
0594
0595 function! ClassNameFromHeader()
0596 :normal gg
0597 call search( '^\s*class\s\+\([A-Za-z0-9]\+_EXPORT\s\+\)\?[A-Za-z_]\+\s*\(:\s*[,\t A-Za-z_]\+\)\?\s*\n\?\s*{' )
0598 "\zs and \ze mark start and end of the matching
0599 return matchstr( getline('.'), '\s\+\zs\w\+\ze\s*\(:\|{\|$\)' )
0600 endfunction
0601
0602 function! ClassNameFromImpl()
0603 :normal gg
0604 call search( '\s*\([A-Za-z_]\+\)::\1\s*(' )
0605 :normal "cye
0606 return @c
0607 endfunction
0608
0609 function! IncludeGuard()
0610 let guard = toupper( substitute( expand( '%' ), '[\./]', '_', 'g' ) )
0611 call append( '^', '#define ' . guard )
0612 +
0613 call append( '^', '#ifndef ' . guard )
0614 call append( '$', '#endif // ' . guard )
0615 +
0616 endfunction
0617
0618 function! LicenseHeader( license )
0619 let filename = $HOME . "/" . a:license . "HEADER"
0620 execute ":0r " . filename
0621 " call append( 0, system( "cat " . filename ) )
0622 endfunction
0623
0624 function! SmartInclude()
0625 let next = nr2char( getchar( 0 ) )
0626 if next == '"'
0627 return "#include \".h\"\<Left>\<Left>\<Left>"
0628 endif
0629 if next == '>'
0630 return "#include <>\<Left>"
0631 endif
0632 return "#include <.h>\<Left>\<Left>\<Left>"
0633 endfunction
0634
0635 function! MapIdentHeader( ident )
0636 let header = tolower(substitute(a:ident, '::', '/', 'g')).'.h'
0637 if a:ident =~ 'Private$'
0638 let header = substitute(header, 'private', '_p', '')
0639 endif
0640 " always prefer the headers in the same directory
0641 let check = header
0642 let slash = 1
0643 while slash != -1
0644 if filereadable( check )
0645 return '"' . check . '"'
0646 endif
0647 let slash = match( check, '/' )
0648 let check = strpart( check, slash + 1 )
0649 endwhile
0650 let check = tolower(substitute(a:ident, '::', '/', 'g')).'_p.h'
0651 let slash = 1
0652 while slash != -1
0653 if filereadable(check)
0654 return '"' . check . '"'
0655 endif
0656 let slash = match(check, '/')
0657 let check = strpart(check, slash + 1)
0658 endwhile
0659
0660 " Qt stuff
0661 if a:ident =~ '^Q[A-Z]'
0662 " let's try to find the module
0663 let module = ''
0664 if $QTDIR != ''
0665 if filereadable($QTDIR.'/include/QtCore/'.a:ident)
0666 let module = 'QtCore/'
0667 elseif filereadable($QTDIR.'/include/QtGui/'.a:ident)
0668 let module = 'QtGui/'
0669 elseif filereadable($QTDIR.'/include/Qt3Support/'.a:ident)
0670 let module = 'Qt3Support/'
0671 elseif filereadable($QTDIR.'/include/QtAssistant/'.a:ident)
0672 let module = 'QtAssistant/'
0673 elseif filereadable($QTDIR.'/include/QtDBus/'.a:ident)
0674 let module = 'QtDBus/'
0675 elseif filereadable($QTDIR.'/include/QtDesigner/'.a:ident)
0676 let module = 'QtDesigner/'
0677 elseif filereadable($QTDIR.'/include/QtNetwork/'.a:ident)
0678 let module = 'QtNetwork/'
0679 elseif filereadable($QTDIR.'/include/QtOpenGL/'.a:ident)
0680 let module = 'QtOpenGL/'
0681 elseif filereadable($QTDIR.'/include/QtSql/'.a:ident)
0682 let module = 'QtSql/'
0683 elseif filereadable($QTDIR.'/include/QtSvg/'.a:ident)
0684 let module = 'QtSvg/'
0685 elseif filereadable($QTDIR.'/include/QtTest/'.a:ident)
0686 let module = 'QtTest/'
0687 elseif filereadable($QTDIR.'/include/QtUiTools/'.a:ident)
0688 let module = 'QtUiTools/'
0689 elseif filereadable($QTDIR.'/include/QtXml/'.a:ident)
0690 let module = 'QtXml/'
0691 endif
0692 endif
0693 return '<'.module.a:ident.'>'
0694 elseif a:ident == 'qDebug' ||
0695 \a:ident == 'qWarning' ||
0696 \a:ident == 'qCritical' ||
0697 \a:ident == 'qFatal'
0698 return '<QtCore/QtDebug>'
0699 elseif a:ident == 'Q_EXPORT_PLUGIN2'
0700 return '<QtCore/QtPlugin>'
0701 elseif a:ident =~ 'Q_DECLARE_INTERFACE'
0702 return '<QtCore/QObject>'
0703 elseif a:ident =~ '^QT_VERSION' ||
0704 \a:ident =~ '^Q_\(W\|O\)S_' ||
0705 \a:ident =~ '^Q_CC_' ||
0706 \a:ident =~ '^Q_.*STRUCTOR_FUNCTION$' ||
0707 \a:ident =~ '^qu\?int' ||
0708 \a:ident =~ '^Q_.*_RESOURCE$' ||
0709 \a:ident == 'qreal' ||
0710 \a:ident == 'qAbs' ||
0711 \a:ident == 'qRound' ||
0712 \a:ident == 'qRound64' ||
0713 \a:ident == 'qMin' ||
0714 \a:ident == 'qMax' ||
0715 \a:ident == 'qBound' ||
0716 \a:ident == 'qVersion' ||
0717 \a:ident == 'qSharedBuild' ||
0718 \a:ident == 'Q_UNUSED' ||
0719 \a:ident == 'Q_ASSERT' ||
0720 \a:ident == 'qInstallMsgHandler' ||
0721 \a:ident == 'Q_GLOBAL_STATIC' ||
0722 \a:ident == 'Q_GLOBAL_STATIC_WITH_ARGS' ||
0723 \a:ident == 'qFuzzyCompare' ||
0724 \a:ident == 'qIsNull' ||
0725 \a:ident == 'qSwap' ||
0726 \a:ident =~ 'Q_DECLARE_\(FLAGS\|OPERATORS_FOR_FLAGS\|PRIVATE\|PUBLIC\)' ||
0727 \a:ident == 'Q_D' ||
0728 \a:ident == 'Q_Q' ||
0729 \a:ident == 'Q_DISABLE_COPY' ||
0730 \a:ident == 'qsrand' ||
0731 \a:ident == 'qrand'
0732 return '<QtCore/QtGlobal>'
0733
0734 " Phonon stuff
0735 elseif a:ident =~ '^Phonon::[A-Z]'
0736 if a:ident =~ '^Phonon::\(NoDisc\|Cd\|Dvd\|Vcd\|.\+MetaData\|.*State\|.*Category\|.\+Error\)'
0737 return '<Phonon/Global>'
0738 endif
0739 return '<'.substitute(a:ident, '::', '/', 'g').'>'
0740 endif
0741
0742 " KDE stuff
0743 let kdeincdir = substitute(system('kde4-config --prefix'), '[\n\r]*', '', 'g').'/include/KDE/'
0744 let classname = substitute(a:ident, '^.*:', '', '')
0745 let pathfn = expand('%:p:h')
0746 if filereadable(kdeincdir.classname) && !pathfn =~ 'kdelibs'
0747 return '<'.classname.'>'
0748 elseif filereadable(kdeincdir.'Phonon/'.classname)
0749 return '<Phonon/'.classname.'>'
0750 elseif filereadable(kdeincdir.'Solid/'.classname)
0751 return '<Solid/'.classname.'>'
0752 elseif filereadable(kdeincdir.'KIO/'.classname)
0753 return '<KIO/'.classname.'>'
0754 elseif filereadable(kdeincdir.'KParts/'.classname)
0755 return '<KParts/'.classname.'>'
0756 elseif a:ident == 'K_GLOBAL_STATIC'
0757 return '<KGlobal>'
0758 elseif a:ident == 'K_EXPORT_PLUGIN'
0759 return '<KPluginLoader>'
0760 elseif a:ident =~ 'K_PLUGIN_FACTORY'
0761 return '<KPluginFactory>'
0762 elseif a:ident == 'K\(Double\|Int\)\(NumInput\|SpinBox\)'
0763 return '<knuminput.h>'
0764 elseif a:ident == 'KSharedConfig'
0765 return '<kconfig.h>'
0766 elseif a:ident == 'KConfigGroup'
0767 return '<kconfiggroup.h>'
0768 elseif a:ident == 'KListViewItem'
0769 return '<klistview.h>'
0770 elseif a:ident =~ 'kd\(Debug\|Warning\|Error\|Fatal\|Backtrace\)'
0771 return '<kdebug.h>'
0772 elseif a:ident == 'kapp'
0773 return '<kapplication.h>'
0774 elseif a:ident == 'i18n' ||
0775 \a:ident == 'I18N_NOOP'
0776 return '<klocale.h>'
0777 elseif a:ident == 'locate' ||
0778 \a:ident == 'locateLocal'
0779 return '<kstandarddirs.h>'
0780 elseif a:ident =~ '\(Small\|Desktop\|Bar\|MainBar\|User\)Icon\(Set\)\?' ||
0781 \a:ident == 'IconSize'
0782 return '<kiconloader.h>'
0783
0784 " Standard Library stuff
0785 elseif a:ident =~ '\(std::\)\?\(cout\|cerr\|endl\)'
0786 return '<iostream>'
0787 elseif a:ident =~ '\(std::\)\?is\(alnum\|alpha\|ascii\|blank\|graph\|lower\|print\|punct\|space\|upper\|xdigit\)'
0788 return '<cctype>'
0789 elseif a:ident == 'printf'
0790 return '<cstdio>'
0791 endif
0792
0793 let check = header
0794 while 1
0795 if filereadable( check )
0796 return '"' . check . '"'
0797 endif
0798 let slash = match( check, '/' )
0799 if slash == -1
0800 return '<' . header . '>'
0801 endif
0802 let check = strpart( check, slash + 1 )
0803 endwhile
0804 endfunction
0805
0806 " This is a rather dirty hack, but seems to work somehow :-) (malte)
0807 function! AddHeader()
0808 let s = getline( '.' )
0809 let i = col( '.' ) - 1
0810 while i > 0 && strpart( s, i, 1 ) !~ '[A-Za-z0-9_:]'
0811 let i = i - 1
0812 endwhile
0813 while i > 0 && strpart( s, i, 1 ) =~ '[A-Za-z0-9_:]'
0814 let i = i - 1
0815 endwhile
0816 let start = match( s, '[A-Za-z0-9_]\+\(::[A-Z][A-Za-z0-9_]*\)*', i )
0817 let end = matchend( s, '[A-Za-z0-9_]\+\(::[A-Z][A-Za-z0-9_]*\)*', i )
0818 " if end > col( '.' )
0819 " let end = matchend( s, '[A-Za-z0-9_]\+', i )
0820 " endif
0821 let ident = strpart( s, start, end - start )
0822 let header = MapIdentHeader(ident)
0823 let include = '#include '.header
0824
0825 let line = 1
0826 let incomment = 0
0827 let appendpos = 0
0828 let codestart = 0
0829 let similarpos = 0
0830 let similarity = 0
0831 while line <= line( '$' )
0832 let s = getline( line )
0833 if incomment == 1
0834 let end = matchend( s, '\*/' )
0835 if end == -1
0836 let line = line + 1
0837 continue
0838 else
0839 let s = strpart( s, end )
0840 let incomment = 0
0841 endif
0842 endif
0843 let s = substitute( s, '//.*', '', '' )
0844 let s = substitute( s, '/\*\([^*]\|\*\@!/\)*\*/', '', 'g' )
0845 if s =~ '/\*'
0846 let incomment = 1
0847 elseif s =~ '^' . include
0848 break
0849 elseif s =~ '^#include' && s !~ '\.moc"'
0850 let appendpos = line
0851 if s =~ '^#include '.header[0:similarity+1]
0852 let similarpos = line
0853 let similarity = similarity + 1
0854 while s =~ '^#include '.header[0:similarity+1]
0855 let similarity = similarity + 1
0856 endwhile
0857 if s[9:strlen(s)-2] > header[0:strlen(header)-2]
0858 let similarpos = similarpos - 1
0859 let similarity = 100 "this include belongs one line higher (assuming the order of includes already is alphabetically)
0860 endif
0861 endif
0862 elseif codestart == 0 && s !~ '^$'
0863 let codestart = line
0864 endif
0865 let line = line + 1
0866 endwhile
0867 if similarpos > 0
0868 let appendpos = similarpos
0869 endif
0870 if line == line( '$' ) + 1
0871 if appendpos == 0
0872 call append( codestart - 1, include )
0873 call append( codestart, '' )
0874 else
0875 call append( appendpos, include )
0876 endif
0877 endif
0878 endfunction
0879
0880 function! AddForward()
0881 let s = getline( '.' )
0882 let i = col( '.' ) - 1
0883 while i > 0 && strpart( s, i, 1 ) !~ '[A-Za-z0-9_:]'
0884 let i = i - 1
0885 endwhile
0886 while i > 0 && strpart( s, i, 1 ) =~ '[A-Za-z0-9_:]'
0887 let i = i - 1
0888 endwhile
0889 let start = match( s, '[A-Za-z0-9_]\+\(::[A-Za-z0-9_]\+\)*', i )
0890 let end = matchend( s, '[A-Za-z0-9_]\+\(::[A-Za-z0-9_]\+\)*', i )
0891 if end > col( '.' )
0892 let end = matchend( s, '[A-Za-z0-9_]\+', i )
0893 endif
0894 let ident = strpart( s, start, end - start )
0895 let forward = 'class ' . ident . ';'
0896
0897 let line = 1
0898 let incomment = 0
0899 let appendpos = 0
0900 let codestart = 0
0901 while line <= line( '$' )
0902 let s = getline( line )
0903 if incomment == 1
0904 let end = matchend( s, '\*/' )
0905 if end == -1
0906 let line = line + 1
0907 continue
0908 else
0909 let s = strpart( s, end )
0910 let incomment = 0
0911 endif
0912 endif
0913 let s = substitute( s, '//.*', '', '' )
0914 let s = substitute( s, '/\*\([^*]\|\*\@!/\)*\*/', '', 'g' )
0915 if s =~ '/\*'
0916 let incomment = 1
0917 elseif s =~ '^' . forward
0918 break
0919 elseif s =~ '^\s*class [A-za-z0-9_]\+;' || (s =~ '^#include' && s !~ '\.moc"')
0920 let appendpos = line
0921 elseif codestart == 0 && s !~ '^$'
0922 let codestart = line
0923 endif
0924 let line = line + 1
0925 endwhile
0926 if line == line( '$' ) + 1
0927 if appendpos == 0
0928 call append( codestart - 1, forward )
0929 call append( codestart, '' )
0930 else
0931 call append( appendpos, forward )
0932 endif
0933 endif
0934 endfunction
0935
0936 function! RunDiff()
0937 echo 'Diffing....'
0938 read! cvs diff -bB -I \\\#include | egrep -v '(^Index:|^=+$|^RCS file:|^retrieving revision|^diff -u|^[+-]{3})'
0939 endfunction
0940
0941 function! CreateChangeLogEntry()
0942 let currentBuffer = expand( "%" )
0943
0944 if exists( "g:EMAIL" )
0945 let mail = g:EMAIL
0946 elseif exists( "$EMAIL" )
0947 let mail = $EMAIL
0948 else
0949 let mail = inputdialog( "Enter Name/Email for Changelog entry: " )
0950 if mail == ""
0951 echo "Aborted ChangeLog edit..."
0952 return
0953 endif
0954 let g:EMAIL = mail
0955 endif
0956
0957 if bufname( "ChangeLog" ) != "" && bufwinnr( bufname( "ChangeLog" ) ) != -1
0958 execute bufwinnr( bufname( "ChangeLog" ) ) . " wincmd w"
0959 else
0960 execute "split ChangeLog"
0961 endif
0962
0963 let lastEntry = getline( nextnonblank( 1 ) )
0964 let newEntry = strftime("%Y-%m-%d") . " " . mail
0965
0966 if lastEntry != newEntry
0967 call append( 0, "" )
0968 call append( 0, "" )
0969 call append( 0, newEntry )
0970 endif
0971
0972 " like emacs, prepend the current buffer name to the entry. but unlike
0973 " emacs I have no idea how to figure out the current function name :(
0974 " (Simon)
0975 if currentBuffer != ""
0976 let newLine = "\t* " . currentBuffer . ": "
0977 else
0978 let newLine = "\t* "
0979 endif
0980
0981 call append( 2, newLine )
0982
0983 execute "normal 3G$"
0984 endfunction
0985
0986 function! AddQtSyntax()
0987 if expand( "<amatch>" ) == "cpp"
0988 syn keyword qtKeywords signals slots emit Q_SLOTS Q_SIGNALS
0989 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
0990 syn keyword qtCast qt_cast qobject_cast qvariant_cast qstyleoption_cast qgraphicsitem_cast
0991 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
0992 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
0993 syn keyword cRepeat foreach
0994 syn keyword cRepeat forever
0995
0996 hi def link qtKeywords Statement
0997 hi def link qtMacros Type
0998 hi def link qtCast Statement
0999 hi def link qtTypedef Type
1000 hi def link kdeMacros Type
1001 endif
1002 endfunction
1003
1004 function! UpdateMocFiles()
1005 if &syntax == "cpp"
1006 let i = 1
1007 while i < 80
1008 let s = getline( i )
1009 if s =~ '^#include ".*\.moc"'
1010 let s = substitute( s, '.*"\(.*\)\.moc"', '\1.h', '' )
1011 if stridx( &complete, s ) == -1
1012 let &complete = &complete . ',k' . s
1013 endif
1014 break
1015 endif
1016 let i = i + 1
1017 endwhile
1018 endif
1019 endfunction
1020
1021 autocmd Syntax * call AddQtSyntax()
1022 autocmd CursorHold * call UpdateMocFiles()
1023 autocmd BufNewFile,BufRead * call SetCodingStyle()
1024
1025 " vim: sw=4 sts=4 et