kde-devel-vim.vim 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  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. " Don't include these in filename completions
  11. set suffixes+=.lo,.o,.moc,.la,.closure,.loT
  12. " Search for headers here
  13. set path=.,/usr/include,/usr/local/include,
  14. if $QTDIR != ''
  15. let &path = &path . $QTDIR . '/include/,'
  16. endif
  17. if $KDEDIR != ''
  18. let &path = &path . $KDEDIR . '/include/,'
  19. let &path = &path . $KDEDIR . '/include/arts/,'
  20. endif
  21. if $KDEDIRS != ''
  22. let &path = &path . substitute( $KDEDIRS, '\(:\|$\)', '/include,', 'g' )
  23. let &path = &path . substitute( $KDEDIRS, '\(:\|$\)', '/include/arts,', 'g' )
  24. endif
  25. set path+=,
  26. " Use makeobj to build
  27. set mp=makeobj
  28. " If TagList is Loaded then get a funny statusline
  29. " Only works if kde-devel-vim.vim is loaded after taglist.
  30. " Droping this script in ~/.vim/plugin works fine
  31. if exists('loaded_taglist')
  32. let Tlist_Process_File_Always=1
  33. set statusline=%<%f:[\ %{Tlist_Get_Tag_Prototype_By_Line()}\ ]\ %h%m%r%=%-14.(%l,%c%V%)\ %P
  34. endif
  35. " Insert tab character in whitespace-only lines, complete otherwise
  36. inoremap <Tab> <C-R>=SmartTab()<CR>
  37. if exists("EnableSmartParens")
  38. " Insert a space after ( or [ and before ] or ) unless preceded by a matching
  39. " paren/bracket or space or inside a string or comment. Comments are only
  40. " recognized as such if they start on the current line :-(
  41. inoremap ( <C-R>=SmartParens( '(' )<CR>
  42. inoremap [ <C-R>=SmartParens( '[' )<CR>
  43. inoremap ] <C-R>=SmartParens( ']', '[' )<CR>
  44. inoremap ) <C-R>=SmartParens( ')', '(' )<CR>
  45. endif
  46. " Insert an #include statement for the current/last symbol
  47. inoremap <F5> <C-O>:call AddHeader()<CR>
  48. " Insert a forward declaration for the current/last symbol
  49. " FIXME: not implemented yet
  50. " inoremap <S-F5> <C-O>:call AddForward()<CR>
  51. " Switch between header and implementation files on ,h
  52. nmap <silent> ,h :call SwitchHeaderImpl()<CR>
  53. " Comment selected lines on ,c in visual mode
  54. vmap ,c :s,^,//X ,<CR>:noh<CR>
  55. " Uncomment selected lines on ,u in visual mode
  56. vmap ,u :s,^//X ,,<CR>
  57. " Insert an include guard based on the file name on ,i
  58. nmap ,i :call IncludeGuard()<CR>o
  59. " Insert simple debug statements into each method
  60. nmap ,d :call InsertMethodTracer()<CR>
  61. " Expand #i to #include <.h> or #include ".h". The latter is chosen
  62. " if the character typed after #i is a dquote
  63. " If the character is > #include <> is inserted (standard C++ headers w/o .h)
  64. iab #i <C-R>=SmartInclude()<CR>
  65. " Insert a stripped down CVS diff
  66. iab DIFF <Esc>:call RunDiff()<CR>
  67. " mark 'misplaced' tab characters
  68. set listchars=tab:·\ ,trail:·
  69. set list
  70. set incsearch
  71. function! SmartTab()
  72. let col = col('.') - 1
  73. if !col || getline('.')[col-1] !~ '\k'
  74. return "\<Tab>"
  75. else
  76. return "\<C-P>"
  77. endif
  78. endfunction
  79. function! SmartParens( char, ... )
  80. if ! ( &syntax =~ '^\(c\|cpp\|java\)$' )
  81. return a:char
  82. endif
  83. let s = strpart( getline( '.' ), 0, col( '.' ) - 1 )
  84. if s =~ '//'
  85. return a:char
  86. endif
  87. let s = substitute( s, '/\*\([^*]\|\*\@!/\)*\*/', '', 'g' )
  88. let s = substitute( s, "'[^']*'", '', 'g' )
  89. let s = substitute( s, '"\(\\"\|[^"]\)*"', '', 'g' )
  90. if s =~ "\\([\"']\\|/\\*\\)"
  91. return a:char
  92. endif
  93. if a:0 > 0
  94. if strpart( getline( '.' ), col( '.' ) - 3, 2 ) == a:1 . ' '
  95. return "\<BS>" . a:char
  96. endif
  97. if strpart( getline( '.' ), col( '.' ) - 2, 1 ) == ' '
  98. return a:char
  99. endif
  100. return ' ' . a:char
  101. endif
  102. if a:char == '('
  103. if strpart( getline( '.' ), col( '.' ) - 3, 2 ) == 'if' ||
  104. \strpart( getline( '.' ), col( '.' ) - 4, 3 ) == 'for' ||
  105. \strpart( getline( '.' ), col( '.' ) - 6, 5 ) == 'while' ||
  106. \strpart( getline( '.' ), col( '.' ) - 7, 6 ) == 'switch'
  107. return ' ( '
  108. endif
  109. endif
  110. return a:char . ' '
  111. endfunction
  112. function! SwitchHeaderImpl()
  113. let headers = '\.\([hH]\|hpp\|hxx\)$'
  114. let impl = '\.\([cC]\|cpp\|cc\|cxx\)$'
  115. let fn = expand( '%' )
  116. if fn =~ headers
  117. let list = glob( substitute( fn, headers, '.*', '' ) )
  118. elseif fn =~ impl
  119. let list = glob( substitute( fn, impl, '.*', '' ) )
  120. endif
  121. while strlen( list ) > 0
  122. let file = substitute( list, "\n.*", '', '' )
  123. let list = substitute( list, "[^\n]*", '', '' )
  124. let list = substitute( list, "^\n", '', '' )
  125. if ( fn =~ headers && file =~ impl ) || ( fn =~ impl && file =~ headers )
  126. execute( "edit " . file )
  127. return
  128. endif
  129. endwhile
  130. echohl ErrorMsg
  131. echo "File switch failed!"
  132. echohl None
  133. endfunction
  134. function! IncludeGuard()
  135. let guard = toupper( substitute( expand( '%' ), '\([^.]*\)\.h', '\1_h', '' ) )
  136. call append( '^', '#define ' . guard )
  137. +
  138. call append( '^', '#ifndef ' . guard )
  139. call append( '$', '#endif // ' . guard )
  140. +
  141. endfunction
  142. function! SmartInclude()
  143. let next = nr2char( getchar( 0 ) )
  144. if next == '"'
  145. return "#include \".h\"\<Left>\<Left>\<Left>"
  146. endif
  147. if next == '>'
  148. return "#include <>\<Left>"
  149. endif
  150. return "#include <.h>\<Left>\<Left>\<Left>"
  151. endfunction
  152. function! MapIdentHeader( ident )
  153. " Qt stuff
  154. if a:ident =~ 'Q.*Layout'
  155. return '<qlayout.h>'
  156. elseif a:ident == 'QListViewItem' ||
  157. \a:ident == 'QCheckListItem' ||
  158. \a:ident == 'QListViewItemIterator'
  159. return '<qlistview.h>'
  160. elseif a:ident == 'QIconViewItem' ||
  161. \a:ident == 'QIconDragItem' ||
  162. \a:ident == 'QIconDrag'
  163. return '<qiconview.h>'
  164. elseif a:ident =~ 'Q.*Drag' ||
  165. \a:ident == 'QDragManager'
  166. return '<qdragobject.h>'
  167. elseif a:ident == 'QMimeSource' ||
  168. \a:ident == 'QMimeSourceFactory' ||
  169. \a:ident == 'QWindowsMime'
  170. return '<qmime.h>'
  171. elseif a:ident == 'QPtrListIterator'
  172. return '<qptrlist.h>'
  173. elseif a:ident =~ 'Q.*Event'
  174. return '<qevent.h>'
  175. elseif a:ident == 'QTime' ||
  176. \a:ident == 'QDate'
  177. return '<qdatetime.h>'
  178. elseif a:ident == 'QTimeEdit' ||
  179. \a:ident == 'QDateTimeEditBase' ||
  180. \a:ident == 'QDateEdit'
  181. return '<qdatetimeedit.h>'
  182. elseif a:ident == 'QByteArray'
  183. return '<qcstring.h>'
  184. elseif a:ident == 'QWidgetListIt'
  185. return '<qwidgetlist.h>'
  186. elseif a:ident == 'QTab'
  187. return '<qtabbar.h>'
  188. elseif a:ident == 'QColorGroup'
  189. return '<qpalette.h>'
  190. elseif a:ident == 'QActionGroup'
  191. return '<qaction.h>'
  192. elseif a:ident =~ 'Q.*Validator'
  193. return '<qvalidator.h>'
  194. elseif a:ident =~ 'QListBox.*'
  195. return '<qlistbox.h>'
  196. elseif a:ident == 'QChar' ||
  197. \a:ident == 'QCharRef' ||
  198. \a:ident == 'QConstString'
  199. return '<qstring.h>'
  200. elseif a:ident =~ 'QCanvas.*'
  201. return '<qcanvas.h>'
  202. elseif a:ident =~ 'QGL.*'
  203. return '<qgl.h>'
  204. elseif a:ident == 'QTableSelection' ||
  205. \a:ident == 'QTableItem' ||
  206. \a:ident == 'QComboTableItem' ||
  207. \a:ident == 'QCheckTableItem'
  208. return '<qtable.h>'
  209. elseif a:ident == 'qApp'
  210. return '<qapplication.h>'
  211. " KDE stuff
  212. elseif a:ident == 'K\(Double\|Int\)\(NumInput\|SpinBox\)'
  213. return '<knuminput.h>'
  214. elseif a:ident == 'KConfigGroup'
  215. return '<kconfigbase.h>'
  216. elseif a:ident == 'KListViewItem'
  217. return '<klistview.h>'
  218. elseif a:ident =~ 'kd\(Debug\|Warning\|Error\|Fatal\|Backtrace\)'
  219. return '<kdebug.h>'
  220. elseif a:ident == 'kapp'
  221. return '<kapplication.h>'
  222. elseif a:ident == 'i18n' ||
  223. \a:ident == 'I18N_NOOP'
  224. return '<klocale.h>'
  225. elseif a:ident == 'locate' ||
  226. \a:ident == 'locateLocal'
  227. return '<kstandarddirs.h>'
  228. " aRts stuff
  229. elseif a:ident =~ '\arts_\(debug\|info\|warning\|fatal\)'
  230. return '<debug.h>'
  231. " Standard Library stuff
  232. elseif a:ident =~ '\(std::\)\?\(cout\|cerr\|endl\)'
  233. return '<iostream>'
  234. elseif a:ident =~ '\(std::\)\?is\(alnum\|alpha\|ascii\|blank\|graph\|lower\|print\|punct\|space\|upper\|xdigit\)'
  235. return '<cctype>'
  236. endif
  237. let header = tolower( substitute( a:ident, '::', '/', 'g' ) ) . '.h'
  238. let check = header
  239. while 1
  240. if filereadable( check )
  241. return '"' . check . '"'
  242. endif
  243. let slash = match( check, '/' )
  244. if slash == -1
  245. return '<' . header . '>'
  246. endif
  247. let check = strpart( check, slash + 1 )
  248. endwhile
  249. endfunction
  250. " This is a rather dirty hack, but seems to work somehow :-) (malte)
  251. function! AddHeader()
  252. let s = getline( '.' )
  253. let i = col( '.' ) - 1
  254. while i > 0 && strpart( s, i, 1 ) !~ '[A-Za-z0-9_:]'
  255. let i = i - 1
  256. endwhile
  257. while i > 0 && strpart( s, i, 1 ) =~ '[A-Za-z0-9_:]'
  258. let i = i - 1
  259. endwhile
  260. let start = match( s, '[A-Za-z0-9_]\+\(::[A-Za-z0-9_]\+\)*', i )
  261. let end = matchend( s, '[A-Za-z0-9_]\+\(::[A-Za-z0-9_]\+\)*', i )
  262. if end > col( '.' )
  263. let end = matchend( s, '[A-Za-z0-9_]\+', i )
  264. endif
  265. let ident = strpart( s, start, end - start )
  266. let include = '#include ' . MapIdentHeader( ident )
  267. let line = 1
  268. let incomment = 0
  269. let appendpos = 0
  270. let codestart = 0
  271. while line <= line( '$' )
  272. let s = getline( line )
  273. if incomment == 1
  274. let end = matchend( s, '\*/' )
  275. if end == -1
  276. let line = line + 1
  277. continue
  278. else
  279. let s = strpart( s, end )
  280. let incomment = 0
  281. endif
  282. endif
  283. let s = substitute( s, '//.*', '', '' )
  284. let s = substitute( s, '/\*\([^*]\|\*\@!/\)*\*/', '', 'g' )
  285. if s =~ '/\*'
  286. let incomment = 1
  287. elseif s =~ '^' . include
  288. break
  289. elseif s =~ '^#include' && s !~ '\.moc"'
  290. let appendpos = line
  291. elseif codestart == 0 && s !~ '^$'
  292. let codestart = line
  293. endif
  294. let line = line + 1
  295. endwhile
  296. if line == line( '$' ) + 1
  297. if appendpos == 0
  298. call append( codestart - 1, include )
  299. call append( codestart, '' )
  300. else
  301. call append( appendpos, include )
  302. endif
  303. endif
  304. endfunction
  305. function! RunDiff()
  306. echo 'Diffing....'
  307. read! cvs diff -bB -I \\\#include | egrep -v '(^Index:|^=+$|^RCS file:|^retrieving revision|^diff -u|^[+-]{3})'
  308. endfunction
  309. function! CreateChangeLogEntry()
  310. let currentBuffer = expand( "%" )
  311. if exists( "g:EMAIL" )
  312. let mail = g:EMAIL
  313. elseif exists( "$EMAIL" )
  314. let mail = $EMAIL
  315. else
  316. let mail = inputdialog( "Enter Name/Email for Changelog entry: " )
  317. if mail == ""
  318. echo "Aborted ChangeLog edit..."
  319. return
  320. endif
  321. let g:EMAIL = mail
  322. endif
  323. if bufname( "ChangeLog" ) != "" && bufwinnr( bufname( "ChangeLog" ) ) != -1
  324. execute bufwinnr( bufname( "ChangeLog" ) ) . " wincmd w"
  325. else
  326. execute "split ChangeLog"
  327. endif
  328. let lastEntry = getline( nextnonblank( 1 ) )
  329. let newEntry = strftime("%Y-%m-%d") . " " . mail
  330. if lastEntry != newEntry
  331. call append( 0, "" )
  332. call append( 0, "" )
  333. call append( 0, newEntry )
  334. endif
  335. " like emacs, prepend the current buffer name to the entry. but unlike
  336. " emacs I have no idea how to figure out the current function name :(
  337. " (Simon)
  338. if currentBuffer != ""
  339. let newLine = "\t* " . currentBuffer . ": "
  340. else
  341. let newLine = "\t* "
  342. endif
  343. call append( 2, newLine )
  344. execute "normal 3G$"
  345. endfunction
  346. function! AddQtSyntax()
  347. if expand( "<amatch>" ) == "cpp"
  348. syn keyword qtKeywords signals slots emit foreach
  349. syn keyword qtMacros Q_OBJECT Q_WIDGET Q_PROPERTY Q_ENUMS Q_OVERRIDE Q_CLASSINFO Q_SETS SIGNAL SLOT
  350. syn keyword qtCast qt_cast qobject_cast qvariant_cast qstyleoption_cast
  351. 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
  352. syn keyword kdeKeywords k_dcop k_dcop_signals
  353. syn keyword kdeMacros K_DCOP ASYNC
  354. syn keyword cRepeat foreach
  355. syn keyword cRepeat forever
  356. hi def link qtKeywords Statement
  357. hi def link qtMacros Type
  358. hi def link qtCast Statement
  359. hi def link qtTypedef Type
  360. hi def link kdeKeywords Statement
  361. hi def link kdeMacros Type
  362. endif
  363. endfunction
  364. function! InsertMethodTracer()
  365. :normal [[kf(yBjokdDebug() << ""()" << endl;
  366. endfunction
  367. function! UpdateMocFiles()
  368. if &syntax == "cpp"
  369. let i = 1
  370. while i < 80
  371. let s = getline( i )
  372. if s =~ '^#include ".*\.moc"'
  373. let s = substitute( s, '.*"\(.*\)\.moc"', '\1.h', '' )
  374. if stridx( &complete, s ) == -1
  375. let &complete = &complete . ',k' . s
  376. endif
  377. break
  378. endif
  379. let i = i + 1
  380. endwhile
  381. endif
  382. endfunction
  383. autocmd Syntax * call AddQtSyntax()
  384. autocmd CursorHold * call UpdateMocFiles()
  385. " vim: sw=4 sts=4 et