2 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
4 " File_Name__: srcexpl.vim "
5 " Abstract___: A (G)VIM plugin for exploring the source code based on 'tags' "
6 " and 'quickfix'. It works like the context window in 'Source "
8 " Author_____: Wenlong Che <chewenlong AT buaa.edu.cn> "
10 " Last_Change: March 16, 2009 "
11 " Licence____: This program is free software; you can redistribute it and / or "
12 " modify it under the terms of the GNU General Public License as "
13 " published by the Free Software Foundation; either version 2, or "
14 " any later version. "
16 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
18 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
19 " NOTE: The graph below shows my work platform with some VIM plugins, "
20 " including 'Source Explorer', 'Taglist' and 'NERD tree'. And I usually "
21 " use a plugin named 'trinity.vim' to manage them. "
23 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
25 " +----------------------------------------------------------------------------+
26 " | File | Edit | Tools | Syntax | Buffers | Window | Help | |
27 " +----------------------------------------------------------------------------+
28 " |-demo.c-------- |-----------------------------------------|-/home/myprj/----|
29 " |function | 1 void foo(void) /* function 1 */ ||~ src/ |
30 " | foo | 2 { || `-demo.c |
31 " | bar | 3 } |`-tags |
32 " | | 4 void bar(void) /* function 2 */ | |
33 " |~ +----------+ | 5 { |~ +-----------+ |
34 " |~ | Tag List |\ | 6 } |~ | NERD Tree |\ |
35 " |~ +__________+ ||~ +-----------------+ |~ +___________+ ||
36 " |~ \___________\||~ | The Main Editor |\ |~ \____________\||
37 " |~ |~ +_________________+ | |~ |
38 " |~ |~ \__________________\| |~ |
40 " |-__Tag_List__---|-demo.c----------------------------------|-_NERD_tree_-----|
41 " |Source Explorer v4.2 |
42 " |~ +-----------------+ |
43 " |~ | Source Explorer |\ |
44 " |~ +_________________+ | |
45 " |~ \__________________\| |
46 " |-Source_Explorer[Preview]---------------------------------------------------|
47 " |:TrinityToggleAll |
48 " +----------------------------------------------------------------------------+
50 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
52 " The_setting_example_in_my_vimrc_file:-) "
54 " // The switch of the Source Explorer "
55 " nmap <F8> :SrcExplToggle<CR>
57 " // Set the height of Source Explorer window "
58 " let g:SrcExpl_winHeight = 8
60 " // Set 100 ms for refreshing the Source Explorer "
61 " let g:SrcExpl_refreshTime = 100
63 " // Set "Enter" key to jump into the exact definition context "
64 " let g:SrcExpl_jumpKey = "<ENTER>"
66 " // Set "Space" key for back from the definition context "
67 " let g:SrcExpl_gobackKey = "<SPACE>"
69 " // In order to Avoid conflicts, the Source Explorer should know what plugins "
70 " // are using buffers. And you need add their bufname into the list below "
71 " // according to the command ":buffers!" "
72 " let g:SrcExpl_pluginList = [
78 " // Enable/Disable the local definition searching, and note that this is not "
79 " // guaranteed to work, the Source Explorer doesn't check the syntax for now. "
80 " // It only searches for a match with the keyword according to command 'gd' "
81 " let g:SrcExpl_searchLocalDef = 1
83 " // Do not let the Source Explorer update the tags file when opening "
84 " let g:SrcExpl_isUpdateTags = 0
86 " // Use program 'ctags' with argument '--sort=foldcase -R' to create or "
87 " // update a tags file "
88 " let g:SrcExpl_updateTagsCmd = "ctags --sort=foldcase -R ."
90 " // Set "<F12>" key for updating the tags file artificially "
91 " let g:SrcExpl_updateTagsKey = "<F12>"
93 " Just_change_above_of_them_by_yourself:-) "
95 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
99 if exists('loaded_srcexpl')
103 let loaded_srcexpl = 1
104 let s:save_cpo = &cpoptions
108 " VIM version control {{{
110 " The VIM version control for running the Source Explorer
114 echo "SrcExpl: Require VIM 7.0 or above for running the Source Explorer."
123 " User interfaces {{{
125 " User interface for opening the Source Explorer
127 command! -nargs=0 -bar SrcExpl
128 \ call <SID>SrcExpl()
130 " User interface for closing the Source Explorer
132 command! -nargs=0 -bar SrcExplClose
133 \ call <SID>SrcExpl_Close()
135 " User interface for switching the Source Explorer
137 command! -nargs=0 -bar SrcExplToggle
138 \ call <SID>SrcExpl_Toggle()
140 " User interface for changing the height of the Source Explorer window
141 if !exists('g:SrcExpl_winHeight')
142 let g:SrcExpl_winHeight = 8
145 " User interface for setting the update time interval for each refreshing
146 if !exists('g:SrcExpl_refreshTime')
147 let g:SrcExpl_refreshTime = 100
150 " User interface to jump into the exact definition context
151 if !exists('g:SrcExpl_jumpKey')
152 let g:SrcExpl_jumpKey = '<CR>'
155 " User interface to go back from the definition context
156 if !exists('g:SrcExpl_gobackKey')
157 let g:SrcExpl_gobackKey = '<SPACE>'
160 " User interface for handling the conflicts between the
161 " Source Explorer and other plugins
162 if !exists('g:SrcExpl_pluginList')
163 let g:SrcExpl_pluginList = [
170 " User interface to enable local declaration searching
171 " according to command 'gd'
172 if !exists('g:SrcExpl_searchLocalDef')
173 let g:SrcExpl_searchLocalDef = 1
176 " User interface to control if update the 'tags' file when loading
177 " the Source Explorer, 0 for false, others for true
178 if !exists('g:SrcExpl_isUpdateTags')
179 let g:SrcExpl_isUpdateTags = 1
182 " User interface to create a 'tags' file using exact ctags
183 " utility, 'ctags --sort=foldcase -R .' as default
184 if !exists('g:SrcExpl_updateTagsCmd')
185 let g:SrcExpl_updateTagsCmd = "ctags --sort=foldcase -R ."
188 " User interface to update tags file artificially
189 if !exists('g:SrcExpl_updateTagsKey')
190 let g:SrcExpl_updateTagsKey = ''
195 " Global variables {{{
197 " Buffer caption for identifying myself among all the plugins
198 let s:SrcExpl_pluginCaption = 'Source_Explorer'
201 let s:SrcExpl_isRunning = 0
205 " SrcExpl_UpdateTags() {{{
207 " Update tags file with the 'ctags' utility
209 function! g:SrcExpl_UpdateTags()
211 " Go to the current work directory
212 silent! exe "cd " . expand('%:p:h')
213 " Get the amount of tags files
214 let l:tmp = len(tagfiles())
216 " No tags file or not found one
218 " Ask user if or not create a tags file
220 \ | let l:tmp = <SID>SrcExpl_GetInput("\nSrcExpl: "
221 \ . "The 'tags' file was not found in your PATH.\n"
222 \ . "Create one in the current directory now? (y)es/(n)o?") |
225 if l:tmp == "y" || l:tmp == "yes"
226 " We tell user where we create a tags file
228 echo "SrcExpl: Creating 'tags' file in (". expand('%:p:h') . ")"
230 " Call the external 'ctags' utility program
231 exe "!" . g:SrcExpl_updateTagsCmd
232 " Rejudge the tags file if existed
233 if !filereadable("tags")
234 " Tell them what happened
235 call <SID>SrcExpl_ReportErr("Execute 'ctags' utility program failed")
243 " More than one tags file
245 call <SID>SrcExpl_ReportErr("More than one tags file in your PATH")
247 " Found one successfully
249 " Is the tags file in the current directory ?
250 if tagfiles()[0] ==# "tags"
251 " Prompt the current work directory
253 echo "SrcExpl: Updating 'tags' file in (". expand('%:p:h') . ")"
255 " Call the external 'ctags' utility program
256 exe "!" . g:SrcExpl_updateTagsCmd
257 " Up to other directories
259 " Prompt the whole path of the tags file
261 echo "SrcExpl: Updating 'tags' file in (". tagfiles()[0][:-6] . ")"
263 " Store the current word directory at first
265 " Go to the directory that contains the old tags file
266 silent! exe "cd " . tagfiles()[0][:-5]
267 " Call the external 'ctags' utility program
268 exe "!" . g:SrcExpl_updateTagsCmd
269 " Go back to the original work directory
270 silent! exe "cd " . l:tmp
279 " SrcExpl_GoBack() {{{
281 " Move the cursor to the previous location in the mark history
283 function! g:SrcExpl_GoBack()
285 " If or not the cursor is on the main editor window
286 if &previewwindow || <SID>SrcExpl_AdaptPlugins()
290 " Just go back to the previous position
291 return <SID>SrcExpl_GetMarkList()
297 " Jump to the main editor window and point to the definition
299 function! g:SrcExpl_Jump()
301 " Only do the operation on the Source Explorer
307 " Do we get the definition already?
308 if bufname("%") == s:SrcExpl_pluginCaption
310 if s:SrcExpl_status == 0
312 " Multiple definitions
313 elseif s:SrcExpl_status == 2
314 " If point to the jump list head, just avoid that
321 if g:SrcExpl_searchLocalDef != 0
322 " We have already jumped to the main editor window
323 let s:SrcExpl_isJumped = 1
325 " Indeed go back to the main editor window
326 silent! exe s:SrcExpl_editWin . "wincmd w"
327 " Set the mark for recording the current position
328 call <SID>SrcExpl_SetMarkList()
330 " We got multiple definitions
331 if s:SrcExpl_status == 2
332 " Select the exact one and jump to its context
333 call <SID>SrcExpl_SelToJump()
334 " Set the mark for recording the current position
335 call <SID>SrcExpl_SetMarkList()
339 " Open the buffer using main editor window
340 exe "edit " . s:SrcExpl_currMark[0]
341 " Jump to the context line of that symbol
342 call cursor(s:SrcExpl_currMark[1], s:SrcExpl_currMark[2])
343 " Match the symbol of definition
344 call <SID>SrcExpl_MatchExpr()
345 " Set the mark for recording the current position
346 call <SID>SrcExpl_SetMarkList()
348 " We got one local definition
349 if s:SrcExpl_status == 3
350 " Get the cursor line number
351 let s:SrcExpl_csrLine = line(".")
352 " Try to tag the symbol again
353 let l:expr = '\<' . s:SrcExpl_symbol . '\>' . '\C'
354 " Try to tag something
355 call <SID>SrcExpl_TagSth(l:expr)
363 " SrcExpl_Refresh() {{{
365 " Refresh the Source Explorer window and update the status
367 function! g:SrcExpl_Refresh()
369 " Tab page must be invalid
370 if s:SrcExpl_tabPage != tabpagenr()
374 " If or not the cursor is on the main editor window
375 if &previewwindow || <SID>SrcExpl_AdaptPlugins()
379 " Avoid errors of multi-buffers
381 call <SID>SrcExpl_ReportErr("This modified file is not saved")
385 " Get the ID of main editor window
386 let s:SrcExpl_editWin = winnr()
388 " Get the symbol under the cursor
389 if <SID>SrcExpl_GetSymbol()
393 let l:expr = '\<' . s:SrcExpl_symbol . '\>' . '\C'
395 " Try to Go to local declaration
396 if g:SrcExpl_searchLocalDef != 0
397 if !<SID>SrcExpl_GoDecl(l:expr)
402 " Try to tag something
403 call <SID>SrcExpl_TagSth(l:expr)
410 " SrcExpl_AdaptPlugins() {{{
412 " The Source Explorer window will not work when the cursor on the
414 " window of other plugins, such as 'Taglist', 'NERD tree' etc.
416 function! <SID>SrcExpl_AdaptPlugins()
418 " Traversal the list of other plugins
419 for item in g:SrcExpl_pluginList
420 " If they acted as a split window
421 if bufname("%") ==# item
422 " Just avoid this operation
432 " SrcExpl_ReportErr() {{{
434 " Output the message when we get an error situation
436 function! <SID>SrcExpl_ReportErr(err)
438 " Highlight the error prompt
440 echo "SrcExpl: " . a:err
445 " SrcExpl_EnterWin() {{{
447 " Operation when 'WinEnter' event happens
449 function! <SID>SrcExpl_EnterWin()
451 " In the Source Explorer window
453 if has("gui_running")
454 " Delete the SrcExplGoBack item in Popup menu
455 silent! nunmenu 1.01 PopUp.&SrcExplGoBack
457 " Unmap the go-back key
458 if maparg(g:SrcExpl_gobackKey, 'n') ==
459 \ ":call g:SrcExpl_GoBack()<CR>"
460 exe "nunmap " . g:SrcExpl_gobackKey
462 " Do the mapping for 'double-click'
463 if maparg('<2-LeftMouse>', 'n') == ''
464 nnoremap <silent> <2-LeftMouse>
465 \ :call g:SrcExpl_Jump()<CR>
467 " Map the user's key to jump into the exact definition context
468 if g:SrcExpl_jumpKey != ""
469 exe "nnoremap " . g:SrcExpl_jumpKey .
470 \ " :call g:SrcExpl_Jump()<CR>"
472 " In other plugin windows
473 elseif <SID>SrcExpl_AdaptPlugins()
474 if has("gui_running")
475 " Delete the SrcExplGoBack item in Popup menu
476 silent! nunmenu 1.01 PopUp.&SrcExplGoBack
478 " Unmap the go-back key
479 if maparg(g:SrcExpl_gobackKey, 'n') ==
480 \ ":call g:SrcExpl_GoBack()<CR>"
481 exe "nunmap " . g:SrcExpl_gobackKey
483 " Unmap the exact mapping of 'double-click'
484 if maparg("<2-LeftMouse>", "n") ==
485 \ ":call g:SrcExpl_Jump()<CR>"
486 nunmap <silent> <2-LeftMouse>
489 if maparg(g:SrcExpl_jumpKey, 'n') ==
490 \ ":call g:SrcExpl_Jump()<CR>"
491 exe "nunmap " . g:SrcExpl_jumpKey
493 " In the main editor window
495 if has("gui_running")
496 " You can use SrcExplGoBack item in Popup menu
497 " to go back from the definition
498 silent! nnoremenu 1.01 PopUp.&SrcExplGoBack
499 \ :call g:SrcExpl_GoBack()<CR>
501 " Map the user's key to go back from the definition context
502 if g:SrcExpl_gobackKey != ""
503 exe "nnoremap " . g:SrcExpl_gobackKey .
504 \ " :call g:SrcExpl_GoBack()<CR>"
506 " Unmap the exact mapping of 'double-click'
507 if maparg("<2-LeftMouse>", "n") ==
508 \ ":call g:SrcExpl_Jump()<CR>"
509 nunmap <silent> <2-LeftMouse>
512 if maparg(g:SrcExpl_jumpKey, 'n') ==
513 \ ":call g:SrcExpl_Jump()<CR>"
514 exe "nunmap " . g:SrcExpl_jumpKey
520 " SrcExpl_SetMarkList() {{{
522 " Set a new mark for back to the previous position
524 function! <SID>SrcExpl_SetMarkList()
526 " Add one new mark into the tail of Mark List
527 call add(s:SrcExpl_markList, [expand("%:p"), line("."), col(".")])
531 " SrcExpl_GetMarkList() {{{
533 " Get the mark for back to the previous position
535 function! <SID>SrcExpl_GetMarkList()
537 " If or not the mark list is empty
538 if !len(s:SrcExpl_markList)
539 call <SID>SrcExpl_ReportErr("Mark stack is empty")
543 " Avoid the same situation
544 if get(s:SrcExpl_markList, -1)[0] == expand("%:p")
545 \ && get(s:SrcExpl_markList, -1)[1] == line(".")
546 \ && get(s:SrcExpl_markList, -1)[2] == col(".")
547 " Remove the latest mark
548 call remove(s:SrcExpl_markList, -1)
549 " Get the latest mark again
550 return <SID>SrcExpl_GetMarkList()
553 " Load the buffer content into the main editor window
554 exe "edit " . get(s:SrcExpl_markList, -1)[0]
555 " Jump to the context position of that symbol
556 call cursor(get(s:SrcExpl_markList, -1)[1], get(s:SrcExpl_markList, -1)[2])
557 " Remove the latest mark now
558 call remove(s:SrcExpl_markList, -1)
565 " SrcExpl_SelToJump() {{{
567 " Select one of multi-definitions, and jump to there
569 function! <SID>SrcExpl_SelToJump()
576 " If or not in the Source Explorer window
581 " Get the item data that the user selected just now
582 let l:list = getline(".")
583 " Traverse the prompt string until get the file path
584 while !((l:list[l:index] == ']') &&
585 \ (l:list[l:index + 1] == ':'))
591 " Get the whole file path of the exact definition
592 while !((l:list[l:index] == ' ') &&
593 \ (l:list[l:index + 1] == '['))
594 let l:fpath = l:fpath . l:list[l:index]
600 " Traverse the prompt string until get the symbol
601 while !((l:list[l:index] == ']') &&
602 \ (l:list[l:index + 1] == ':'))
608 " Get the EX command string
609 while l:list[l:index] != ''
610 let l:excmd = l:excmd . l:list[l:index]
614 " Indeed go back to the main editor window
615 silent! exe s:SrcExpl_editWin . "wincmd w"
616 " Open the file containing the definition context
617 exe "edit " . l:fpath
619 " Modify the EX Command to locate the tag exactly
620 let l:expr = substitute(l:excmd, '/^', '/^\\C', 'g')
621 let l:expr = substitute(l:expr, '\*', '\\\*', 'g')
622 let l:expr = substitute(l:expr, '\[', '\\\[', 'g')
623 let l:expr = substitute(l:expr, '\]', '\\\]', 'g')
624 " Use EX Command to Jump to the exact position of the definition
628 call <SID>SrcExpl_MatchExpr()
632 " SrcExpl_SetCurrMark() {{{
634 " Save the current buf-win file path, line number and column number
636 function! <SID>SrcExpl_SetCurrMark()
638 " Store the curretn position for exploring
639 let s:SrcExpl_currMark = [expand("%:p"), line("."), col(".")]
643 " SrcExpl_ColorExpr() {{{
645 " Highlight the symbol of definition
647 function! <SID>SrcExpl_ColorExpr()
649 " Set the highlight color
650 hi SrcExpl_HighLight term=bold guifg=Black guibg=Magenta ctermfg=Black ctermbg=Magenta
652 exe 'match SrcExpl_HighLight "\%' . line(".") . 'l\%' .
657 " SrcExpl_MatchExpr() {{{
659 " Match the symbol of definition
661 function! <SID>SrcExpl_MatchExpr()
663 call search("$", "b")
664 let s:SrcExpl_symbol = substitute(s:SrcExpl_symbol,
666 call search('\<' . s:SrcExpl_symbol . '\>' . '\C')
670 " SrcExpl_PromptNoDef() {{{
672 " Tell users there is no tag that be found in your PATH
674 function! <SID>SrcExpl_PromptNoDef()
676 " Do the Source Explorer existed already?
677 let l:bufnum = bufnr(s:SrcExpl_pluginCaption)
678 " Not existed, create a new buffer
680 " Create a new buffer
681 let l:wcmd = s:SrcExpl_pluginCaption
683 " Edit the existing buffer
684 let l:wcmd = '+buffer' . l:bufnum
687 " Reopen the Source Explorer idle window
688 exe "silent " . "pedit " . l:wcmd
694 " First make it modifiable
696 " Not show its name on the buffer list
699 setlocal buftype=nofile
700 " Report the reason why the Source Explorer
701 " can not point to the definition
702 " Delete all lines in buffer.
704 " Go to the end of the buffer put the buffer list
706 " Display the version of the Source Explorer
707 put! ='Definition Not Found'
708 " Cancel all the highlighted words
710 " Delete the extra trailing blank line
712 " Make it unmodifiable again
713 setlocal nomodifiable
714 " Go back to the main editor window
715 silent! exe s:SrcExpl_editWin . "wincmd w"
720 " SrcExpl_ListMultiDefs() {{{
722 " List multiple definitions into the preview window
724 function! <SID>SrcExpl_ListMultiDefs(list, len)
726 " The Source Explorer existed already ?
727 let l:bufnum = bufnr(s:SrcExpl_pluginCaption)
728 " Not existed, create a new buffer
730 " Create a new buffer
731 let l:wcmd = s:SrcExpl_pluginCaption
733 " Edit the existing buffer
734 let l:wcmd = '+buffer' . l:bufnum
737 " Is the tags file in the current directory ?
738 if tagfiles()[0] ==# "tags"
739 " We'll get the operating system environment
740 " in order to judge the slash type
741 if s:SrcExpl_isWinOS == 1
742 " With the backward slash
743 let l:path = expand('%:p:h') . '\'
745 " With the forward slash
746 let l:path = expand('%:p:h') . '/'
752 " Reopen the Source Explorer idle window
753 exe "silent " . "pedit " . l:wcmd
754 " Return to the preview window
758 " Reset the attribute of the Source Explorer
760 " Not show its name on the buffer list
763 setlocal buftype=nofile
764 " Delete all lines in buffer
766 " Get the tags dictionary array
767 " Begin build the Jump List for exploring the tags
768 put! = '[Jump List]: '. s:SrcExpl_symbol . ' (' . a:len . ') '
770 call <SID>SrcExpl_MatchExpr()
771 " Highlight the symbol
772 call <SID>SrcExpl_ColorExpr()
775 " Loop for listing each tag from tags file
777 " First get each tag list
778 let l:dict = get(a:list, l:indx, {})
781 " Go to the end of the buffer put the buffer list
783 " We should avoid the './' or '.\' in the whole file path
784 if l:dict['filename'][0] == '.'
785 put! ='[File Path]: ' . l:path . l:dict['filename'][2:]
786 \ . ' ' . '[EX Command]: ' . l:dict['cmd']
788 put! ='[File Path]: ' . l:path . l:dict['filename']
789 \ . ' ' . '[EX Command]: ' . l:dict['cmd']
799 " Delete the extra trailing blank line
801 " Move the cursor to the top of the Source Explorer window
802 exe "normal! " . "gg"
803 " Back to the first line
804 setlocal nomodifiable
805 " Go back to the main editor window
806 silent! exe s:SrcExpl_editWin . "wincmd w"
810 " SrcExpl_ViewOneDef() {{{
812 " Display the definition of the symbol into the preview window
814 function! <SID>SrcExpl_ViewOneDef(fpath, excmd)
818 " Is the tags file in the current directory ?
819 if tagfiles()[0] ==# "tags"
820 exe "silent " . "pedit " . expand('%:p:h') . '/' . a:fpath
821 " Up to other directories
823 exe "silent " . "pedit " . a:fpath
826 " Go to the Source Explorer window
828 " Indeed back to the preview window
830 " Modify the EX Command to locate the tag exactly
831 let l:expr = substitute(a:excmd, '/^', '/^\\C', 'g')
832 let l:expr = substitute(l:expr, '\*', '\\\*', 'g')
833 let l:expr = substitute(l:expr, '\[', '\\\[', 'g')
834 let l:expr = substitute(l:expr, '\]', '\\\]', 'g')
835 " Execute EX command according to the parameter
838 call <SID>SrcExpl_MatchExpr()
839 " Highlight the symbol
840 call <SID>SrcExpl_ColorExpr()
841 " Set the current buf-win attribute
842 call <SID>SrcExpl_SetCurrMark()
843 " Refresh all the screen
845 " Go back to the main editor window
846 silent! exe s:SrcExpl_editWin . "wincmd w"
851 " SrcExpl_TagSth() {{{
853 " Just try to find the tag under the cursor
855 function! <SID>SrcExpl_TagSth(expr)
859 " Is the symbol valid ?
860 if a:expr != '\<\>\C'
861 " We get the tag list of the expression
862 let l:list = taglist(a:expr)
863 " Then get the length of taglist
864 let l:len = len(l:list)
869 " Get dictionary to load tag's file path and ex command
870 let l:dict = get(l:list, 0, {})
871 call <SID>SrcExpl_ViewOneDef(l:dict['filename'], l:dict['cmd'])
873 let s:SrcExpl_status = 1
876 call <SID>SrcExpl_ListMultiDefs(l:list, l:len)
877 " Multiple definitions
878 let s:SrcExpl_status = 2
881 " Ignore the repetitious situation
882 if s:SrcExpl_status > 0
883 call <SID>SrcExpl_PromptNoDef()
885 let s:SrcExpl_status = 0
891 " SrcExpl_GoDecl() {{{
893 " Search the local declaration using 'gd' command
895 function! <SID>SrcExpl_GoDecl(expr)
897 " Get the original cursor position
898 let l:oldline = line(".")
899 let l:oldcol = col(".")
901 " Try to search the local declaration
902 if searchdecl(a:expr, 0, 1) != 0
907 " Get the new cursor position
908 let l:newline = line(".")
909 let l:newcol = col(".")
910 " Go back to the original cursor position
911 call cursor(l:oldline, l:oldcol)
913 " Preview the context
914 exe "silent " . "pedit " . expand("%:p")
915 " Go to the Preview window
917 " Indeed in the Preview window
919 " Go to the new cursor position
920 call cursor(l:newline, l:newcol)
922 call <SID>SrcExpl_MatchExpr()
923 " Highlight the symbol
924 call <SID>SrcExpl_ColorExpr()
925 " Set the current buf-win attribute
926 call <SID>SrcExpl_SetCurrMark()
927 " Refresh all the screen
929 " Go back to the main editor window
930 silent! exe s:SrcExpl_editWin . "wincmd w"
931 " We got a local definition
932 let s:SrcExpl_status = 3
940 " SrcExpl_GetSymbol() {{{
942 " Get the valid symbol under the current cursor
944 function! <SID>SrcExpl_GetSymbol()
946 " Get the current character under the cursor
947 let l:cchar = getline(".")[col(".") - 1]
948 " Get the current word under the cursor
949 let l:cword = expand("<cword>")
951 " Judge that if or not the character is invalid,
952 " because only 0-9, a-z, A-Z, and '_' are valid
953 if l:cchar =~ '\w' && l:cword =~ '\w'
954 " If the key word symbol has been explored
955 " just now, we will not explore that again
956 if s:SrcExpl_symbol ==# l:cword
957 " Not in Local definition searching mode
958 if g:SrcExpl_searchLocalDef == 0
961 " Do not refresh when jumping to the main editor window
962 if s:SrcExpl_isJumped == 1
963 " Get the cursor line number
964 let s:SrcExpl_csrLine = line(".")
965 " Reset the jump flag
966 let s:SrcExpl_isJumped = 0
969 " The cursor is not moved actually
970 if s:SrcExpl_csrLine == line(".")
975 " Get the cursor line number
976 let s:SrcExpl_csrLine = line(".")
977 " Get the symbol word under the cursor
978 let s:SrcExpl_symbol = l:cword
981 if s:SrcExpl_symbol == ''
982 return -4 " Second, third ...
984 let s:SrcExpl_symbol = ''
993 " SrcExpl_GetInput() {{{
995 " Get the word inputed by user on the command line window
997 function! <SID>SrcExpl_GetInput(note)
999 " Be sure synchronize
1001 " Get the input content
1002 let l:input = input(a:note)
1005 " Tell the Source Explorer
1010 " SrcExpl_GetEditWin() {{{
1012 " Get the main editor window index
1014 function! <SID>SrcExpl_GetEditWin()
1019 " Loop for searching the main editor window
1021 " Traverse the plugin list for each sub-window
1022 for item in g:SrcExpl_pluginList
1023 if bufname(winbufnr(l:i)) ==# item
1024 \ || getwinvar(l:i, '&previewwindow')
1031 if j >= len(g:SrcExpl_pluginList)
1045 " SrcExpl_InitVimEnv() {{{
1047 " Initialize Vim environment
1049 function! <SID>SrcExpl_InitVimEnv()
1051 " Not highlight the word that had been searched
1052 " Because execute EX command will active a search event
1053 " exe "set nohlsearch"
1054 " Auto change current work directory
1055 " exe "set autochdir"
1056 " Let Vim find the possible tags file
1057 " exe "set tags=tags;" ZOMG
1059 " First set the height of preview window
1060 exe "set previewheight=". string(g:SrcExpl_winHeight)
1061 " Set the actual update time according to user's requestion
1062 " 100 milliseconds by default
1063 exe "set updatetime=" . string(g:SrcExpl_refreshTime)
1065 " Open all the folds
1067 " Open this file at first
1068 exe "normal " . "zR"
1069 " Let it works during the whole editing session
1070 exe "set foldlevelstart=" . "99"
1075 " SrcExpl_InitGlbVal() {{{
1077 " Initialize global variables
1079 function! <SID>SrcExpl_InitGlbVal()
1081 " We'll get the operating system environment
1082 " in order to judge the slash type (backward
1084 if has("win16") || has("win32")
1086 let s:SrcExpl_isWinOS = 1
1088 let s:SrcExpl_isWinOS = 0
1090 " Have we jumped to the main editor window ?
1091 let s:SrcExpl_isJumped = 0
1092 " Line number of the current cursor
1093 let s:SrcExpl_csrLine = 0
1094 " The ID of main editor window
1095 let s:SrcExpl_editWin = 0
1096 " The tab page number
1097 let s:SrcExpl_tabPage = 0
1098 " Source Explorer status:
1099 " 0: Definition not found
1100 " 1: Only one definition
1101 " 2: Multiple definitions
1102 " 3: Local declaration
1103 let s:SrcExpl_status = 0
1104 " The mark for the current position
1105 let s:SrcExpl_currMark = []
1106 " The mark list for exploring the source code
1107 let s:SrcExpl_markList = []
1108 " The key word symbol for exploring
1109 let s:SrcExpl_symbol = ''
1113 " SrcExpl_CloseWin() {{{
1115 " Close the Source Explorer window
1117 function! <SID>SrcExpl_CloseWin()
1119 " Just close the preview window
1124 " SrcExpl_OpenWin() {{{
1126 " Open the Source Explorer window under the bottom of (G)Vim,
1127 " and set the buffer's attribute of the Source Explorer
1129 function! <SID>SrcExpl_OpenWin()
1131 " Get the ID of main editor window
1132 let s:SrcExpl_editWin = winnr()
1133 " Get the tab page number
1134 let s:SrcExpl_tabPage = tabpagenr()
1136 " Has the Source Explorer existed already?
1137 let l:bufnum = bufnr(s:SrcExpl_pluginCaption)
1138 " Not existed, create a new buffer
1140 " Create a new buffer
1141 let l:wcmd = s:SrcExpl_pluginCaption
1143 " Edit the existing buffer
1144 let l:wcmd = '+buffer' . l:bufnum
1147 " Reopen the Source Explorer idle window
1148 exe "silent " . "pedit " . l:wcmd
1149 " Jump to the Source Explorer
1151 " Open successfully and jump to it indeed
1153 " First make it modifiable
1155 " Not show its name on the buffer list
1156 setlocal nobuflisted
1158 setlocal buftype=nofile
1159 " Delete all lines in buffer
1161 " Go to the end of the buffer
1163 " Display the version of the Source Explorer
1164 put! ='Source Explorer v4.2'
1165 " Delete the extra trailing blank line
1167 " Make it no modifiable
1168 setlocal nomodifiable
1169 " Put it on the bottom of (G)Vim
1173 " Indeed go back to the main editor window
1174 silent! exe s:SrcExpl_editWin . "wincmd w"
1178 " SrcExpl_CleanUp() {{{
1180 " Clean up the rubbish and free the mapping resources
1182 function! <SID>SrcExpl_CleanUp()
1185 if has("gui_running")
1186 " Delete the SrcExplGoBack item in Popup menu
1187 silent! nunmenu 1.01 PopUp.&SrcExplGoBack
1190 " Make the 'double-click' for nothing
1191 if maparg('<2-LeftMouse>', 'n') != ''
1192 nunmap <silent> <2-LeftMouse>
1195 " Unmap the jump key
1196 if maparg(g:SrcExpl_jumpKey, 'n') ==
1197 \ ":call g:SrcExpl_Jump()<CR>"
1198 exe "nunmap " . g:SrcExpl_jumpKey
1201 " Unmap the go-back key
1202 if maparg(g:SrcExpl_gobackKey, 'n') ==
1203 \ ":call g:SrcExpl_GoBack()<CR>"
1204 exe "nunmap " . g:SrcExpl_gobackKey
1207 " Unmap the update-tags key
1208 if maparg(g:SrcExpl_updateTagsKey, 'n') ==
1209 \ ":call g:SrcExpl_UpdateTags()<CR>"
1210 exe "nunmap " . g:SrcExpl_updateTagsKey
1213 " Unload the autocmd group
1214 silent! autocmd! SrcExpl_AutoCmd
1218 " SrcExpl_Init() {{{
1220 " Initialize the Source Explorer properties
1222 function! <SID>SrcExpl_Init()
1224 " Initialize script global variables
1225 call <SID>SrcExpl_InitGlbVal()
1227 " Initialize Vim environment
1228 call <SID>SrcExpl_InitVimEnv()
1230 " We must get the ID of main editor window
1231 let l:tmp = <SID>SrcExpl_GetEditWin()
1234 " Can not find the main editor window
1235 call <SID>SrcExpl_ReportErr("Can not Found the editor window")
1239 silent! exe l:tmp . "wincmd w"
1241 if g:SrcExpl_isUpdateTags != 0
1242 " Update the tags file right now
1243 if g:SrcExpl_UpdateTags()
1248 if g:SrcExpl_updateTagsKey != ""
1249 exe "nnoremap " . g:SrcExpl_updateTagsKey .
1250 \ " :call g:SrcExpl_UpdateTags()<CR>"
1253 " Then we set the routine function when the event happens
1254 augroup SrcExpl_AutoCmd
1256 au! CursorHold * nested call g:SrcExpl_Refresh()
1257 au! WinEnter * nested call <SID>SrcExpl_EnterWin()
1265 " SrcExpl_Toggle() {{{
1267 " The user interface function to open / close the Source Explorer
1269 function! <SID>SrcExpl_Toggle()
1272 if s:SrcExpl_isRunning == 0
1273 " Initialize the properties
1274 if <SID>SrcExpl_Init()
1278 call <SID>SrcExpl_OpenWin()
1279 " We change the flag to true
1280 let s:SrcExpl_isRunning = 1
1282 " Not in the exact tab page
1283 if s:SrcExpl_tabPage != tabpagenr()
1284 call <SID>SrcExpl_ReportErr("Not support multiple tab pages")
1287 " Set the switch flag off
1288 let s:SrcExpl_isOpen = 0
1290 call <SID>SrcExpl_CloseWin()
1291 " Do the cleaning work
1292 call <SID>SrcExpl_CleanUp()
1293 " We change the flag to false
1294 let s:SrcExpl_isRunning = 0
1302 " SrcExpl_Close() {{{
1304 " The user interface function to close the Source Explorer
1306 function! <SID>SrcExpl_Close()
1309 if s:SrcExpl_isRunning == 1
1310 " Not in the exact tab page
1311 if s:SrcExpl_tabPage != tabpagenr()
1312 call <SID>SrcExpl_ReportErr("Not support multiple tab pages")
1316 call <SID>SrcExpl_CloseWin()
1317 " Do the cleaning work
1318 call <SID>SrcExpl_CleanUp()
1319 " We change the flag to false
1320 let s:SrcExpl_isRunning = 0
1322 " Tell users the reason
1323 call <SID>SrcExpl_ReportErr("Source Explorer is close")
1334 " The user interface function to open the Source Explorer
1336 function! <SID>SrcExpl()
1339 if s:SrcExpl_isRunning == 0
1340 " Initialize the properties
1341 if <SID>SrcExpl_Init()
1345 call <SID>SrcExpl_OpenWin()
1346 " We change the flag to true
1347 let s:SrcExpl_isRunning = 1
1349 " Not in the exact tab page
1350 if s:SrcExpl_tabPage != tabpagenr()
1351 call <SID>SrcExpl_ReportErr("Not support multiple tab pages")
1355 call <SID>SrcExpl_ReportErr("Source Explorer is running")
1364 " Avoid side effects {{{
1367 let &cpoptions = s:save_cpo
1372 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
1374 " vim:foldmethod=marker:tabstop=4
1376 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""