[cscope] Adding cctree.vim vi plugin
Neil Horman
nhorman at fedoraproject.org
Thu May 26 20:01:45 UTC 2011
commit 07eae65deefd0e839c735274b7e7c318f205ea79
Author: Neil Horman <nhorman at tuxdriver.com>
Date: Thu May 26 16:01:23 2011 -0400
Adding cctree.vim vi plugin
cscope-15.7a-add-cctree.patch | 3943 +++++++++++++++++++++++++++++++++++++++++
cscope.spec | 20 +-
2 files changed, 3960 insertions(+), 3 deletions(-)
---
diff --git a/cscope-15.7a-add-cctree.patch b/cscope-15.7a-add-cctree.patch
new file mode 100644
index 0000000..2ca6542
--- /dev/null
+++ b/cscope-15.7a-add-cctree.patch
@@ -0,0 +1,3943 @@
+diff -up /dev/null cscope-15.7a/contrib/cctree.txt
+--- /dev/null 2011-05-25 12:40:15.391845002 -0400
++++ cscope-15.7a/contrib/cctree.txt 2011-05-26 14:45:02.905838546 -0400
+@@ -0,0 +1,537 @@
++*CCTree.txt* Plugin for C Call-Tree Explorer *CCTree*
++
++Author: Hari Rangarajan (First.Last AT gmail DOT com)
++Last Change: 20 May 2011
++
++CCTree version 1.51
++
++For Vim version 7.0 and above
++
++==============================================================================
++
++1. Overview |CCTree-overview|
++2. Downloads |CCTree-download|
++3. Installation |CCTree-installation|
++4. Configuration |CCTree-configuration|
++5. Features |CCTree-features|
++6. Limitations |CCTree-limitations|
++7. FAQ & TIPS |CCTree-faq|
++8. History |CCTree-history|
++9. Thanks |CCTree-thanks|
++
++==============================================================================
++1. Overview~
++ *CCTree-overview*
++
++Plugin generates dependency-trees for symbols using a cscope database in Vim.
++Basic cross-referencing includes functions and macros. Enhanced symbol
++processing covers macros, typedefs, enums, and global variables.
++
++Requires Cscope and works best with C code.
++
++==============================================================================
++2. Downloads~
++ *CCTree-download*
++
++You can download the latest release of the script from this url :
++ http://www.vim.org/scripts/script.php?script_id=2368
++
++
++Cscope packages can be found here:
++ http://cscope.sourceforge.net/
++ http://code.google.com/p/cscope-win32/
++
++
++==============================================================================
++3. Installation~
++ *CCTree-installation*
++
++Copy this file to ~/.vim/plugins/ or to /vimfiles/plugins/ (on Win32
++platforms)
++
++It should also be possible to load it as a filetype plugin ~/.vim/ftplugin/c/
++Need to set :filetype plugin on
++
++
++==============================================================================
++CONFIGURATION *CCTree-configuration*
++4. Options~
++
++You can customize behavior by changing the following variable settings
++
++4.1.1 Cscope Symbol Database~
++ *CCTreeCscopeDb*
++
++Cscope database file, g:CCTreeCscopeDb = "cscope.out"
++
++4.1.2 Call-tree Depth~
++ *CCTreeRecursiveDepth*
++Maximum call levels, g:CCTreeRecursiveDepth = 3
++
++4.1.3 Call-tree Minimum Visible Depth~
++ *CCTreeMinVisibleDepth*
++Maximum visible(unfolded) level, g:CCTreeMinVisibleDepth = 3
++
++4.1.4 Call-tree window display~
++
++4.4.1 Orientation~
++ *CCTreeOrientation*
++Orientation of window, g:CCTreeOrientation = "leftabove"
++ (standard vim options for split: [right|left][above|below])
++
++4.5 Direction~
++ *CCTreeWindowVertical*
++Use Vertical window, g:CCTreeWindowVertical = 1
++
++4.5.1 Dimensions~
++
++These settings determine the layout of the CCTree preview window.
++
++4.5.2 Horizontal Window Settings~
++ *CCTreeWindowHeight*
++ Horizontal window, g:CCTreeWindowHeight, default is -1.
++
++4.5.2 Vertical Window Settings~
++ *CCTreeWindowMinWidth*
++ *CCTreeWindowWidth*
++ Minimum width for window, g:CCTreeWindowMinWidth = 40.
++ g:CCTreeWindowWidth = -1, auto-select best width to fit.
++
++
++4.6 Call-tree display format~
++ *CCTreeDisplayMode*
++Display format, g:CCTreeDisplayMode, default: 1
++
++Values: 1 -- Ultra-compact (takes minimum screen width)
++ 2 -- Compact (Takes little more space)
++ 3 -- Wide (Takes copious amounts of space)
++
++For vertical splits, 1 and 2 are good, while 3 is good for horizontal
++displays.
++
++4.7. Dynamic Call-tree highlighting~
++ *CCTreeHilightCallTree*
++
++Enable/disable dynamic call-tree highlighting, default: 1
++
++
++4.7.1 Syntax items~
++ *CCTreeSymbol* *CCTreeHiSymbol*
++CCTreeSymbol is the symbol name.
++CCTreeHiSymbol is the highlighted call tree functions.
++
++ *CCTreeMarkers* *CCTreeHiMarkers*
++CCTreeMarkers include "|","+--->".
++CCTreeHiMarkers is the same as CCTreeMarkers except these denote the
++highlighted call-tree.
++
++
++
++==============================================================================
++COMMAND LIST *CCTree-commands-list*
++
++Database Management~
++ CCTreeLoadDB <dbname>
++ CCTreeAppendDB <dbname>
++ CCTreeUnLoadDB
++ CCTreeShowLoadedDBs
++ Refer to |CCTree-usage|
++
++Native Xref Database~
++ CCTreeLoadXRefDB <dbname>
++ CCTreeSaveXRefDB <dbname>
++
++ Refer to |CCTree-fast-loading|
++
++Symbol tracing~
++ CCTreeTraceForward <symbolname>
++ CCTreeTraceReverse <symbolname>
++ CCTreeRecurseDepthPlus
++ CCTreeRecurseDepthMinus
++ Refer to |CCTree-explore-source|
++Trace Management~
++ CCTreeWindowSaveCopy
++ CCTreeWindowHiCallTree
++ Refer to |CCTree-preview-window|
++
++Dynamic configuration~
++ CCTreeOptsEnable <option> (<tab> for auto-complete)
++ CCTreeOptsDisable <option> (<tab> for auto-complete)
++ CCTreeOptsToggle <option> (<tab> for auto-complete)
++ Options~
++ DynamicTreeHiLights: Control dynamic tree highlighting
++ UseUnicodeSymbols: Use of UTF-8 special characters for tree
++ UseConceal: Use (+Conceal) feature instead of 'ignore'
++ syntax highlighting. Allows CCTree window
++ to be exported in HTML without syntax markup
++ characters. (Vim 7.3+ only)
++ *CCTree-Enhanced-Symbol-Processing*
++ EnhancedSymbolProcessing: Cross-reference enums, macros,
++ global variables, typedefs (WARNING: Database
++ processing speeds will be slow).
++
++SHORTCUT KEYS *CCTree-Key-Map*
++Default Mappings~
++ *CCTree-Default-Key-Map*
++ Get reverse call tree for symbol <C-\><
++ Get forward call tree for symbol <C-\>>
++ Increase depth of tree and update <C-\>=
++ Decrease depth of tree and update <C-\>-
++
++ Open symbol in other window <CR>
++ Preview symbol in other window <Ctrl-P>
++
++ Save copy of preview window <C-\>y
++ Highlight current call-tree flow <C-l>
++ Compress(Fold) call tree view zs
++ (This is useful for viewing long
++ call trees which span across
++ multiple pages)
++
++Custom user-mappings
++ *CCTree-Custom-Key-Map*
++ Users can custom-map the short-cut keys by
++ overriding the following variables in their
++ Vim start-up configuration
++>
++ let g:CCTreeKeyTraceForwardTree = '<C-\>>'
++ let g:CCTreeKeyTraceReverseTree = '<C-\><'
++ let g:CCTreeKeyHilightTree = '<C-l>' " Static highlighting
++ let g:CCTreeKeySaveWindow = '<C-\>y'
++ let g:CCTreeKeyToggleWindow = '<C-\>w'
++ let g:CCTreeKeyCompressTree = 'zs' " Compress call-tree
++ let g:CCTreeKeyDepthPlus = '<C-\>='
++ let g:CCTreeKeyDepthMinus = '<C-\>-'
++<
++
++==============================================================================
++FEATURES *CCTree-features*
++
++5.1. Symbol database~
++ *CCTree-usage*
++Build cscope database, for example:
++> cscope -b -i cscope.files
++ [Tip: add -c option to build uncompressed databases for faster
++ load speeds]
++
++Load database~
++>
++ :CCTreeLoadDB
++<
++ (Please note that it might take a while depending on the
++ database size)
++
++A database name, i.e., my_cscope.out, can be specified with the command. If
++not provided, a prompt will ask for the filename; default is cscope.out.
++
++Unload database ~
++ >
++ :CCTreeUnLoadDB
++<
++Append database~
++ >
++ :CCTreeAppendDB
++<
++ Allows multiple cscope files to be loaded and cross-referenced
++ Illustration: >
++ :CCTreeAppendDB ./cscope.out
++ :CCTreeAppendDB ./dir1/cscope.out
++ :CCTreeAppendDB ./dir2/cscope.out
++<
++ A database name, i.e., my_cscope.out, can be specified with
++ the command. If not provided, a prompt will ask for the
++ filename; default is cscope.out.
++
++FASTER DATABASE LOADING *CCTree-fast-loading*
++
++Save native Xref Db~
++>
++ :CCTreeSaveXRefDb cctree.out
++<
++This command will save the cross-referenced symbols currently loaded into
++memory into a serialized format for faster loading.
++
++Load native XRef Db~
++>
++ :CCTreeLoadXRefDb cctree.out
++<
++This command will load cross-referenced symbols from the previously saved
++native format database.
++
++ccglue~
++ *CCTree-ccglue*
++
++Check out the ccglue project at http://ccglue.sourceforge.net for an external
++tool that can build cctree-compatible xref databases.
++
++
++5.2. Exploring source-code~
++ *CCTree-explore-source*
++
++Get reverse call tree for symbol <C-\><
++>
++ :CCTreeTraceReverse <symbolname>
++<
++
++Get forward call tree for symbol <C-\>>
++>
++ :CCTreeTraceForward <symbolname>
++<
++Increase depth of tree and update <C-\>=
++>
++ :CCTreeRecurseDepthPlus
++<
++Decrease depth of tree and update <C-\>-
++>
++ :CCTreeRecurseDepthMinus
++<
++5.3. Preview Window~
++ *CCTree-preview-window*
++Open symbol in other window <CR>
++Preview symbol in other window <Ctrl-P>
++
++5.4. Syntax Coloring~
++ *CCTree-Syntax*
++CCTreeHiXXXX allows dynamic highlighting of the call-tree. To observe the
++effect, move the cursor to the function to highlight the current call-tree.
++This option can be turned off using the setting, *CCTreeHilightCallTree* .
++
++For faster highlighting, the value of 'updatetime' can be changed.
++
++5.5 Support for large database files~
++ *CCTree-LargeDatabase* *CCTree-LargeFile*
++Vimscript does not have an API for reading files line-by-line. This
++becomes a problem when parsing large databases. CCTree can overcome
++the limitation using an external utility (i.e., GNU coreutils: split)
++or VimScript's perl interpreter interface (:version must indicate +perl)
++
++5.5.1 Using GNU Coreutils (split/cat)~
++ *CCTree-Tools-split* *CCTree-Tools-cat*
++ The following settings are tailored to suit GNU coreutils split; the
++default settings should work with no changes on typical linux/unix distros.
++Monopoly OSes will require installation of unixutils or equivalent.
++
++External command is setup with the following parameters~
++>
++ let g:CCTreeSplitProgCmd =
++ 'PROG_SPLIT SPLIT_OPT SPLIT_SIZE IN_FILE OUT_FILE_PREFIX'
++<
++
++Break-down of individual parameters~
++The split utility is assumed to be on the path; otherwise, specify full path
++ g:CCTreeSplitProg = 'split'
++
++Option for splitting files (-C or -l)~
++>
++ let g:CCTreeSplitProgOption = '-C'
++<
++If split program does not support -C, then this parameter must be set to
++the number of lines in the split files
++>
++ let g:CCTreeDbFileSplitLines = -1
++<
++Largest filesize Vimscript can handle; file sizes greater than this will
++be temporarily split
++>
++ let g:CCTreeDbFileMaxSize = 40000000 (40 Mbytes)
++<
++Sample system command~
++Typical:
++>
++ split -C 40000000 inputFile outputFilePrefix
++<
++ When g:CCTreeDbFileSplitLines is set to 10000 (-C options will be ignored)
++>
++ split -l 10000 inputFile outputFilePrefix
++<
++ *CCTree-Tools-Perl*
++ *CCTree-Tools-Perl-LargeFile*
++Enabling perl interface~
++
++ By default, perl usage is disabled. Set
++>
++ let g:CCTreeUsePerl = 1
++< to enable the perl interface.
++
++ Perl interface is typically faster than native Vimscript.
++ This option can be used independent of the file size
++
++ For more info on setting up perl interface
++ :help |perl-using| or :help |perl-dynamic|
++
++5.6. Miscellaneous *CCTree-Miscellaneous*
++
++ UTF-8 usage *CCTree-UTF8-Symbols*
++ UTF-8 symbols should work fine on the majority of
++ X11 systems; however, some terminals might cause problems.
++
++ To use symbols for drawing the tree, this option can be enabled.
++>
++ let g:CCTreeUseUTF8Symbols = 1
++<
++ The options interface (CCTreeOptsxxx) can be used to
++ modify options on-the-fly.
++
++==============================================================================
++6. Limitations~
++ *CCTree-limitations*
++
++The following are known limitations:
++
++Basic Symbol Processing:
++ (1) The accuracy of the call-tree will only be as good as the cscope database
++generation. (NOTE: Different flavors of Cscope have some known limitations
++due to the lexical analysis engine. This results in incorrectly identified
++function blocks, etc.)
++
++Enhanced Symbol Processing:
++ (1) Cscope does not mark-up nameless enums correctly; hence,
++CCTree cannot recognize nameless enum symbols.
++
++
++==============================================================================
++7. FAQ~
++ *CCTree-faq*
++
+++ I see strange characters "!#@" on my screen when dynamic highlighting is
++enabled. Why do I see them?
++
++Check :hi ignore. You will see something like
++hi ignore ctermfg=white guifg=bg
++
++ For console, white must be your background color; for GUI, guifg must be set
++to bg.
++
++==============================================================================
++8. History~
++ *CCTree-history*
++Version 1.51: May 18, 2011
++ 1. Robust error reporting when external (split/cat) utils fail
++
++Version 1.50: May 6, 2011
++ 1. Support cross-referencing of global variables, macros,
++ enums, and typedefs.
++
++Version 1.40: April 22, 2011
++ 1. Maintain order of functions called during forward tracing
++
++Version 1.39: April 18, 2011
++ 1. Use +Conceal feature for highlighting (only Vim 7.3)
++
++Version 1.33: April 5, 2011
++ 1. Load and trace CCTree native XRefDb directly from disk
++ 2. Fix AppendDB command when 'ignorecase' is set
++
++Version 1.26: March 28, 2011
++ 1. Fix macro cross-referencing limitation
++ 2. Correct native xref file format
++
++Version 1.21: March 21, 2011
++ 1. Support serialization of loaded
++ cscope databases (for faster loading)
++
++Version 1.07: March 09, 2011
++ 1. Fix new keymaps incorrectly applied to buffer
++ 2. CCTreeOptsToggle command for toggling options
++
++Version 1.04: March 06, 2011
++ 1. Customization for key mappings
++ 2. Dynamic configuration of UI variables
++ 3. Folding long call-trees to show current path dynamically
++
++Version 1.01: March 04, 2011
++ 1. Make UTF-8 symbols for tree optional
++
++Version 1.00: March 02, 2011
++ 1. Staging release for upcoming features
++ - Complete refactoring of code to take
++ advantage of VimScript's OO features
++ 2. Faster decompression of symbols
++ 3. Display related changes
++ - Use of unicode symbols for tree
++ 4. Bugfixes related to multi-database loading
++
++Version 0.90: February 18, 2011
++ 1. Support for large databases using external split utility or perl
++ interface
++
++Version 0.85: February 9, 2011
++ 1. Significant increase in database loading and decompression speeds
++
++Version 0.80: February 4, 2011
++ 1. Reduce memory usage by removing unused xref symbols
++
++Version 0.75: June 23, 2010
++ 1. Support for saving CCTree preview window; multiple
++ CCTree windows can now be open
++
++ersion 0.71: May 11, 2010
++ 1. Fix script bug
++
++Version 0.70: May 8, 2010
++ 1. Functionality to load multiple cscope databases
++
++Version 0.65: July 12, 2009
++ 1. Toggle preview window
++
++Version 0.61: December 24, 2008
++ 1. Fixed bug when processing include files
++ 2. Remove 'set ruler' option
++
++Version 0.60: November 26, 2008
++ 1. Added support for source-file dependency tree
++
++Version 0.50: October 17, 2008
++ 1. Optimizations for compact memory foot-print and
++ improved compressed-database load speeds
++
++Version 0.41: October 6, 2008
++ 1. Minor fix: Compressed cscope databases will load
++ incorrectly if encoding is not 8-bit
++
++Version 0.4: September 28, 2008
++ 1. Rewrite of display-related code
++ 2. New syntax hightlighting
++ 3. Dynamic highlighting for call-trees
++ 4. Support for new window modes (vertical, horizontal)
++ 5. New display format option for compact or wide call-trees
++ 6. Preview window fix
++
++Version 0.3: September 21, 2008
++ 1. Support compressed cscope databases
++ 2. Display window related bugs fixed
++ 3. More intuitive display and folding capabilities
++
++Version 0.2: September 12, 2008
++ (Patches from Yegappan Lakshmanan, thanks!)
++ 1. Support for using the plugin in Vi-compatible mode
++ 2. Filtering out unwanted lines before processing the db
++ 3. Command-line completion for the commands
++ 4. Using the cscope db from any directory
++
++Version 0.1: August 31,2008
++ 1. Cross-referencing support for only functions and macros
++ (Note: Functions inside macro definitions will be incorrectly
++ attributed to the top level calling function)
++
++
++==============================================================================
++9. Thanks~
++ *CCTree-thanks*
++
++
++ Qaiser Durrani (ver 1.51 -- Reporting issues with SunOS)
++ Ben Fritz (ver 1.39 -- Suggestion/Testing for
++ conceal feature)
++ Ben Fritz (ver 1.26 -- Bug report)
++ Frank Chang (ver 1.0x -- testing/UI enhancement
++ ideas/bug fixes)
++ Arun Chaganty/Timo Tiefel (Ver 0.60 -- bug report)
++ Michael Wookey (Ver 0.40 -- Testing/bug report/patches)
++ Yegappan Lakshmanan (Ver 0.20 -- Patches)
++
++ The Vim Community, ofcourse :)
++
++
++vim:tw=78:fo=tcq2:isk=!-~,^*,^\|,^\":ts=8:ft=help:norl:
++
+diff -up /dev/null cscope-15.7a/contrib/cctree.vim
+--- /dev/null 2011-05-25 12:40:15.391845002 -0400
++++ cscope-15.7a/contrib/cctree.vim 2011-05-26 14:45:02.906838571 -0400
+@@ -0,0 +1,3398 @@
++" C Call-Tree Explorer (CCTree) <CCTree.vim>
++"
++"
++" Script Info and Documentation
++"=============================================================================
++" Copyright: Copyright (C) August 2008 - 2011, Hari Rangarajan
++" Permission is hereby granted to use and distribute this code,
++" with or without modifications, provided that this copyright
++" notice is copied with it. Like anything else that's free,
++" cctree.vim is provided *as is* and comes with no
++" warranty of any kind, either expressed or implied. In no
++" event will the copyright holder be liable for any damamges
++" resulting from the use of this software.
++"
++" Name Of File: CCTree.vim
++" Description: C Call-Tree Explorer Vim Plugin
++" Maintainer: Hari Rangarajan <hari.rangarajan at gmail.com>
++" URL: http://vim.sourceforge.net/scripts/script.php?script_id=2368
++" Last Change: May 18, 2011
++" Version: 1.51
++"
++"=============================================================================
++"
++" {{{ Description:
++" Plugin generates dependency-trees for symbols using a cscope database
++" in Vim.
++" }}}
++" {{{ Requirements: 1) Vim 7.xx , 2) Cscope
++"
++" Tested on Unix and the following Win32 versions:
++" + Cscope, mlcscope (WIN32)
++" http://code.google.com/p/cscope-win32/
++" http://www.bell-labs.com/project/wwexptools/packages.html
++" }}}
++" {{{ Installation:
++" Copy this file to ~/.vim/plugins/
++" or to /vimfiles/plugins/ (on Win32 platforms)
++"
++" It might also be possible to load it as a filetype plugin
++" ~/.vim/ftplugin/c/
++"
++" Need to set :filetype plugin on
++"
++" }}}
++" {{{ Usage:
++" Build cscope database, for example:
++" > cscope -b -i cscope.files
++" [Tip: add -c option to build uncompressed databases for faster
++" load speeds]
++"
++" Load database with command ":CCTreeLoadDB"
++" (Please note that it might take a while depending on the
++" database size)
++"
++" Append database with command ":CCTreeAppendDB"
++" Allows multiple cscope files to be loaded and cross-referenced
++" Illustration:
++" :CCTreeAppendDB ./cscope.out
++" :CCTreeAppendDB ./dir1/cscope.out
++" :CCTreeAppendDB ./dir2/cscope.out
++"
++" A database name, i.e., my_cscope.out, can be specified with
++" the command. If not provided, a prompt will ask for the
++" filename; default is cscope.out.
++"
++" To show loaded databases, use command ":CCTreeShowLoadedDBs"
++"
++" To unload all databases, use command ":CCTreeUnLoadDB"
++" Note: There is no provision to unload databases individually
++"
++" To save the current set of databases loaded in to memory onto disk
++" in native CCTree XRef format, use command ":CCTreeSaveXRefDB"
++"
++" To load a saved native CCTree XRef format file, use
++" command ":CCTreeLoadXRefDB"
++"
++" To load a saved native CCTree XRef format file, use
++" command ":CCTreeLoadXRefDBFromDisk"
++"
++" Notes: No merging database support for CCTree native DB's [at present].
++"
++"
++" To have multiple CCTree preview windows, use ":CCTreeWindowSaveCopy"
++" Note: Once saved, only the depth of the preview window can be changed
++"
++" Default Mappings:
++" Get reverse call tree for symbol <C-\><
++" Get forward call tree for symbol <C-\>>
++" Increase depth of tree and update <C-\>=
++" Decrease depth of tree and update <C-\>-
++"
++" Open symbol in other window <CR>
++" Preview symbol in other window <Ctrl-P>
++"
++" Save copy of preview window <C-\>y
++" Highlight current call-tree flow <C-l>
++" Compress(Fold) call tree view zs
++" (This is useful for viewing long
++" call trees which span across
++" multiple pages)
++"
++" Custom user-mappings:
++" Users can custom-map the short-cut keys by
++" overriding the following variables in their
++" Vim start-up configuration
++"
++" g:CCTreeKeyTraceForwardTree = '<C-\>>'
++" g:CCTreeKeyTraceReverseTree = '<C-\><'
++" g:CCTreeKeyHilightTree = '<C-l>' " Static highlighting
++" g:CCTreeKeySaveWindow = '<C-\>y'
++" g:CCTreeKeyToggleWindow = '<C-\>w'
++" g:CCTreeKeyCompressTree = 'zs' " Compress call-tree
++" g:CCTreeKeyDepthPlus = '<C-\>='
++" g:CCTreeKeyDepthMinus = '<C-\>-'
++"
++" Command List:
++" CCTreeLoadDB <dbname>
++" CCTreeAppendDB <dbname>
++" CCTreeLoadXRefDB <dbname>
++" CCTreeSaveXRefDB <dbname>
++" CCTreeLoadXRefDBFromDisk <dbname>
++"
++" CCTreeUnLoadDB
++" CCTreeShowLoadedDBs
++"
++" CCTreeTraceForward <symbolname>
++" CCTreeTraceReverse <symbolname>
++" CCTreeRecurseDepthPlus
++" CCTreeRecurseDepthMinus
++" CCTreeWindowSaveCopy
++"
++" Only in preview window:
++" CCTreeWindowHiCallTree (same as <C-l> shorcut)
++" Highlight calling tree for keyword at cursor
++"
++" Dynamic configuration:
++" CCTreeOptsEnable <option> (<tab> for auto-complete)
++" CCTreeOptsDisable <option> (<tab> for auto-complete)
++" CCTreeOptsToggle <option> (<tab> for auto-complete)
++" Options:
++" DynamicTreeHiLights: Control dynamic tree highlighting
++" UseUnicodeSymbols: Use of UTF-8 special characters for
++" tree
++" UseConceal: Use (+Conceal) feature instead of 'ignore'
++" syntax highlighting. Allows CCTree window
++" to be exported in HTML without syntax markup
++" characters. (Vim 7.3+ only)
++" EnhancedSymbolProcessing: Cross-reference enums, macros,
++" global variables, typedefs (Warning: Database
++" processing speeds will be slow).
++"
++"
++"
++" Settings:
++" Customize behavior by changing the variable settings
++"
++" UTF-8 usage:
++" UTF-8 symbols should work fine on the majority of
++" X11 systems; however, some terminals might cause problems.
++"
++" To use symbols for drawing the tree, this option can be enabled.
++" g:CCTreeUseUTF8Symbols = 1
++" The options interface (CCTreeOptsxxx) can be used to
++" modify options on-the-fly.
++"
++" Cscope database file, g:CCTreeCscopeDb = "cscope.out"
++" Maximum call levels, g:CCTreeRecursiveDepth = 3
++" Maximum visible(unfolded) level, g:CCTreeMinVisibleDepth = 3
++" Orientation of window, g:CCTreeOrientation = "topleft"
++" (standard vim options for split: [right|left][above|below])
++"
++" Use Vertical window, g:CCTreeWindowVertical = 1
++" Min width for window, g:CCTreeWindowMinWidth = 40
++" g:CCTreeWindowWidth = -1, auto-select best width to fit
++"
++" Horizontal window, g:CCTreeWindowHeight, default is -1
++"
++"
++" Display format, g:CCTreeDisplayMode, default 1
++"
++" Values: 1 -- Ultra-compact (takes minimum screen width)
++" 2 -- Compact (Takes little more space)
++" 3 -- Wide (Takes copious amounts of space)
++"
++" For vertical splits, 1 and 2 are good, while 3 is good for
++" horizontal displays
++"
++" NOTE: To get older behavior, add the following to your vimrc
++" let g:CCTreeDisplayMode = 3
++" let g:CCTreeWindowVertical = 0
++"
++" Syntax Coloring:
++" CCTreeSymbol is the symbol name
++" CCTreeMarkers include "|","+--->"
++"
++" CCTreeHiSymbol is the highlighted call tree functions
++" CCTreeHiMarkers is the same as CCTreeMarkers except
++" these denote the highlighted call-tree
++"
++"
++" CCTreeHiXXXX allows dynamic highlighting of the call-tree.
++" To observe the effect, move the cursor to the function to
++" highlight the current call-tree. This option can be
++" turned off using the setting, g:CCTreeHilightCallTree.
++" For faster highlighting, the value of 'updatetime' can be
++" changed.
++"
++" Support for large database files:
++" Vimscript does not have an API for reading files line-by-line. This
++" becomes a problem when parsing large databases. CCTree can overcome
++" the limitation using an external utility (i.e., GNU coreutils: split)
++" or VimScript's perl interpreter interface (:version must indicate +perl)
++"
++" The following settings are tailored to suit GNU coreutils split; the default
++" settings should work with no changes on typical linux/unix distros
++" (Monopoly OSes will require installation of unixutils or equivalent)
++"
++" External command is setup with the following parameters:
++" g:CCTreeSplitProgCmd = 'PROG_SPLIT SPLIT_OPT SPLIT_SIZE IN_FILE OUT_FILE_PREFIX'
++"
++" Break-down of individual parameters:
++" The split utility is assumed to be on the path; otherwise, specify full path
++" g:CCTreeSplitProg = 'split'
++"
++" Option for splitting files (-C or -l)
++" g:CCTreeSplitProgOption = '-C'
++" If split program does not support -C, then this parameter must be set to
++" the number of lines in the split files
++" g:CCTreeDbFileSplitLines = -1
++" Largest filesize Vimscript can handle; file sizes greater than this will
++" be temporarily split
++" g:CCTreeDbFileMaxSize = 40000000 (40 Mbytes)
++"
++" Sample system command:
++" Typical:
++" split -C 40000000 inputFile outputFilePrefix
++"
++" When g:CCTreeDbFileSplitLines is set to 10000 (-C options will be ignored)
++" split -l 10000 inputFile outputFilePrefix
++"
++"
++" Using perl interface:
++" By default, perl usage is disabled. Set
++" g:CCTreeUsePerl = 1 to enable the perl interface.
++"
++" Perl interface is typically faster than native Vimscript.
++" This option can be used independent of the file size
++"
++" For more info on setting up perl interface
++" :help perl-using or :help perl-dynamic
++"
++" Writing large Xref Databases:
++" CCTree can use external utilities to write extremely large files beyond
++" VimScripts capabilities. It requires the use of an external tool that can
++" join text files (i.e., 'cat' in unix). This utility is triggered if the size
++" of the file being written exceeds g:CCTreeDbFileMaxSize (40 Mb or as configured)
++"
++" The join utility command is configured by default as follows:
++" let CCTreeJoinProgCmd = 'PROG_JOIN JOIN_OPT IN_FILES > OUT_FILE'
++"
++" let g:CCTreeJoinProg = 'cat' " PROG_JOIN
++" let g:CCTreeJoinProgOpts = "" " JOIN_OPT
++"
++"
++" }}}
++" {{{ Limitations:
++" Basic Symbol Processing:
++" The accuracy of the call-tree will only be as good as the cscope
++" database generation.
++" NOTE: Different flavors of Cscope have some known
++" limitations due to the lexical analysis engine. This results
++" in incorrectly identified function blocks, etc.
++" Enhanced Symbol Processing:
++" (1) Cscope does not mark-up nameless enums correctly; hence,
++" CCTree cannot recognize nameless enum symbols.
++" }}}
++" {{{ History:
++" Version 1.51: May 18, 2011
++" 1. Robust error reporting when external (split/cat) utils fail
++" Version 1.50: May 6, 2011
++" 1. Support cross-referencing of global variables, macros,
++" enums, and typedefs.
++" Version 1.40: April 22, 2011
++" 1. Maintain order of functions called during forward tracing
++" Version 1.39: April 18, 2011
++" 1. Use +Conceal feature for highlighting (only Vim 7.3)
++" Version 1.33: April 5, 2011
++" 1. Load and trace CCTree native XRefDb directly from disk
++" 2. Fix AppendDB command when 'ignorecase' is set
++" Version 1.26: March 28, 2011
++" 1. Fix macro cross-referencing limitation
++" 2. Correct native xref file format
++" Version 1.21: March 21, 2011
++" 1. Support serialization of loaded
++" cscope databases (for faster loading)
++" Version 1.07: March 09, 2011
++" 1. Fix new keymaps incorrectly applied to buffer
++" 2. CCTreeOptsToggle command for toggling options
++"
++" Version 1.04: March 06, 2011
++" 1. Customization for key mappings
++" 2. Dynamic configuration of UI variables
++" 3. Folding long call-trees to show current path dynamically
++"
++" Version 1.01: March 04, 2011
++" 1. Make UTF-8 symbols for tree optional
++"
++" Version 1.00: March 02, 2011
++" 1. Staging release for upcoming features
++" - Complete refactoring of code to take
++" advantage of VimScript's OO features
++" 2. Faster decompression of symbols
++" 3. Display related changes
++" - Use of unicode symbols for tree
++" 4. Bugfixes related to multi-database loading
++"
++" Version 0.90: February 18, 2011
++" 1. Support for large databases using external split utility or perl
++" interface
++"
++" Version 0.85: February 9, 2011
++" 1. Significant increase in database loading and decompression speeds
++"
++" Version 0.80: February 4, 2011
++" 1. Reduce memory usage by removing unused xref symbols
++"
++" Version 0.75: June 23, 2010
++" 1. Support for saving CCTree preview window; multiple
++" CCTree windows can now be open
++"
++" Version 0.71: May 11, 2010
++" 1. Fix script bug
++
++" Version 0.70: May 8, 2010
++" 1. Functionality to load multiple cscope databases
++"
++" Version 0.65: July 12, 2009
++" 1. Toggle preview window
++"
++" Version 0.61: December 24, 2008
++" 1. Fixed bug when processing include files
++" 2. Remove 'set ruler' option
++"
++" Version 0.60: November 26, 2008
++" 1. Added support for source-file dependency tree
++"
++" Version 0.50: October 17, 2008
++" 1. Optimizations for compact memory foot-print and
++" improved compressed-database load speeds
++"
++" Version 0.41: October 6, 2008
++" 1. Minor fix: Compressed cscope databases will load
++" incorrectly if encoding is not 8-bit
++"
++" Version 0.4: September 28, 2008
++" 1. Rewrite of "tree-display" code
++" 2. New syntax hightlighting
++" 3. Dynamic highlighting for call-trees
++" 4. Support for new window modes (vertical, horizontal)
++" 5. New display format option for compact or wide call-trees
++" NOTE: defaults for tree-orientation set to vertical
++"
++" Version 0.3:
++" September 21, 2008
++" 1. Support compressed cscope databases
++" 2. Display window related bugs fixed
++" 3. More intuitive display and folding capabilities
++"
++" Version 0.2:
++" September 12, 2008
++" (Patches from Yegappan Lakshmanan, thanks!)
++" 1. Support for using the plugin in Vi-compatible mode.
++" 2. Filtering out unwanted lines before processing the db.
++" 3. Command-line completion for the commands.
++" 4. Using the cscope db from any directory.
++"
++" Version 0.1:
++" August 31,2008
++" 1. Cross-referencing support for only functions and macros
++" Functions inside macro definitions will be incorrectly
++" attributed to the top level calling function
++"
++" }}}
++" {{{ Thanks:
++"
++" Qaiser Durrani (ver 1.51 -- Reporting issues with SunOS)
++" Ben Fritz (ver 1.39 -- Suggestion/Testing for conceal feature)
++" Ben Fritz (ver 1.26 -- Bug report)
++" Frank Chang (ver 1.0x -- testing/UI enhancement ideas/bug fixes)
++" Arun Chaganty/Timo Tiefel (Ver 0.60 -- bug report)
++" Michael Wookey (Ver 0.4 -- Testing/bug report/patches)
++" Yegappan Lakshmanan (Ver 0.2 -- Patches)
++"
++" The Vim Community, ofcourse :)
++"=============================================================================
++" }}}
++
++" {{{ Init
++if !exists('loaded_cctree') && v:version >= 700
++ " First time loading the cctree plugin
++ let loaded_cctree = 1
++else
++ "finish
++endif
++
++" Line continuation used here
++let s:cpo_save = &cpoptions
++set cpoptions&vim
++
++" Trick to get the current script ID
++map <SID>xx <SID>xx
++let s:sid = substitute(maparg('<SID>xx'), '<SNR>\(\d\+_\)xx$', '\1', '')
++unmap <SID>xx
++"}}}
++" {{{ Global variables; Modify in .vimrc to modify default behavior
++" {{{General
++if !exists('CCTreeCscopeDb')
++ let CCTreeCscopeDb = "cscope.out"
++endif
++" revisit
++if !exists('CCTreeDb')
++ let CCTreeDb = "cctree.out"
++endif
++if !exists('CCTreeRecursiveDepth')
++ let CCTreeRecursiveDepth = 3
++endif
++if !exists('CCTreeMinVisibleDepth')
++ let CCTreeMinVisibleDepth = 3
++endif
++if !exists('CCTreeEnhancedSymbolProcessing')
++ let CCTreeEnhancedSymbolProcessing = 0
++endif
++" }}}
++" {{{ Custom user-key mappings
++if !exists('CCTreeKeyTraceForwardTree')
++ let g:CCTreeKeyTraceForwardTree = '<C-\>>'
++endif
++if !exists('CCTreeKeyTraceReverseTree')
++ let g:CCTreeKeyTraceReverseTree = '<C-\><'
++endif
++if !exists('CCTreeKeyHilightTree')
++ let g:CCTreeKeyHilightTree = '<C-l>' " Static highlighting
++endif
++if !exists('CCTreeKeySaveWindow ')
++ let g:CCTreeKeySaveWindow = '<C-\>y'
++endif
++if !exists('CCTreeKeyToggleWindow ')
++ let g:CCTreeKeyToggleWindow = '<C-\>w'
++endif
++if !exists('CCTreeKeyCompressTree ')
++ let g:CCTreeKeyCompressTree = 'zs' " Compress call-tree
++endif
++if !exists('CCTreeKeyDepthPlus')
++ let g:CCTreeKeyDepthPlus = '<C-\>='
++endif
++if !exists('CCTreeKeyDepthMinus')
++ let g:CCTreeKeyDepthMinus = '<C-\>-'
++endif
++" }}}
++" {{{ CCTree UI settings
++if !exists('CCTreeOrientation')
++ let CCTreeOrientation = "topleft"
++endif
++if !exists('CCTreeWindowVertical')
++ let CCTreeWindowVertical = 1
++endif
++if !exists('CCTreeWindowWidth')
++ " -1 is auto select best width
++ let CCTreeWindowWidth = -1
++endif
++if !exists('CCTreeWindowMinWidth')
++ let CCTreeWindowMinWidth = 25
++endif
++if !exists('CCTreeWindowHeight')
++ let CCTreeWindowHeight = -1
++endif
++if !exists('CCTreeDisplayMode')
++ let CCTreeDisplayMode = 1
++endif
++if !exists('CCTreeHilightCallTree')
++ let CCTreeHilightCallTree = 1
++endif
++" }}}
++" {{{ Split prog
++if !exists('CCTreeSplitProgCmd')
++ let CCTreeSplitProgCmd = 'PROG_SPLIT SPLIT_OPT SPLIT_SIZE IN_FILE OUT_FILE_PREFIX'
++endif
++
++if !exists('CCTreeSplitProg')
++ "PROG_SPLIT
++ let CCTreeSplitProg = 'split'
++endif
++
++if !exists('CCTreeSplitProgOption')
++ "SPLIT_OPT
++ let CCTreeSplitProgOption = '-C'
++endif
++
++if !exists('CCTreeDbFileSplitLines')
++ " if SPLIT_OPT is -l
++ " If split program does not support -C, then this parameter must be set to
++ " the number of lines in the split files
++ let CCTreeDbFileSplitLines = -1
++endif
++
++if !exists('CCTreeSplitProgCmd')
++ let CCTreeSplitProgCmd = 'PROG_SPLIT SPLIT_OPT SPLIT_SIZE IN_FILE OUT_FILE_PREFIX'
++endif
++
++if !exists('CCTreeDbFileMaxSize')
++ " if SPLIT_OPT is -C
++ let CCTreeDbFileMaxSize = 40000000 "40 Mbytes
++endif
++
++" }}}
++" {{{ Join/Cat prog
++if !exists('CCTreeJoinProgCmd')
++ let CCTreeJoinProgCmd = 'PROG_JOIN JOIN_OPT IN_FILES > OUT_FILE'
++endif
++
++if !exists('CCTreeJoinProg')
++ "PROG_JOIN
++ let CCTreeJoinProg = 'cat'
++endif
++
++if !exists('CCTreeJoinProgOpts')
++ let CCTreeJoinProgOpts = ""
++endif
++" }}}
++" {{{ Misc (perl)
++if !exists('CCTreeUsePerl')
++ " Disabled by default
++ let CCTreeUsePerl = 0
++if 0 " Auto-detect perl interface (Experimental code)
++ if has('perl)
++perl << PERL_EOF
++ VIM::DoCommand("let CCTreeUsePerl = 1");
++PERL_EOF
++ endif
++endif
++endif
++
++if has('conceal')
++ let s:CCTreeUseConceal = 1
++else
++ let s:CCTreeUseConceal = 0
++endif
++
++if !exists('CCTreeUseUTF8Symbols')
++ let CCTreeUseUTF8Symbols = 0
++endif
++" }}}
++" }}}
++" {{{ Plugin related local variables
++let s:pluginname = 'CCTree'
++let s:windowtitle = 'CCTree-View'
++let s:windowsavetitle = 'CCTree-View-Copy'
++
++let s:DBClasses = { 'cscopeid': 'Cscope', 'cctreexref' : 'CCTree XRef'}
++let s:DBStorage = { 'memory': 'Memory', 'disk' : 'Disk'}
++
++" }}}
++" {{{ Turn on/off debugs
++let s:tag_debug=0
++
++" Use the Decho plugin for debugging
++function! DBGecho(...)
++ if s:tag_debug
++ Decho(a:000)
++ endif
++endfunction
++
++function! DBGredir(...)
++ if s:tag_debug
++ Decho(a:000)
++ endif
++endfunction
++
++function! Pause()
++ call input("sasasD", "asdads")
++endfunction
++" }}}
++" {{{ Progress bar (generic, numeric, rolling)
++let s:GenericProgressBar= {
++ \ 'depth': 0,
++ \ 'depthChar': '',
++ \ 'currentChar': 0,
++ \ 'updateTime': 0,
++ \ 'rangeChars': [],
++ \ 'formatStr' : '',
++ \ 'units' : ''
++ \ }
++
++function! s:GenericProgressBar.mCreate(rangechars, depthchar, fmtStr)
++ let pbr = deepcopy(s:GenericProgressBar)
++ unlet pbr.mCreate
++
++ let pbr.rangeChars = a:rangechars
++ let pbr.depthChar = a:depthchar
++ let pbr.formatStr = a:fmtStr
++
++ return pbr
++endfunction
++
++function! s:GenericProgressBar.mSetDepth(val) dict
++ let self.depth = a:val
++endfunction
++
++function! s:GenericProgressBar.mUpdate() dict
++ let staticchars = repeat(self.depthChar, self.depth)
++ let displayStr = substitute(self.formatStr, "\@PROGRESS\@",
++ \ staticchars . self.rangeChars[self.currentChar], "")
++ call s:StatusLine.mSetExtraInfo(displayStr)
++endfunction
++
++function! s:GenericProgressBar.mDone()
++ call s:StatusLine.mSetExtraInfo("")
++endfunction
++
++let s:ProgressBarRoll = {
++ \ 'updateTime' : 0,
++ \ 'curTime' : 0
++ \}
++
++function! s:ProgressBarRoll.mCreate(rollchars, depthChar) dict
++ let gpbr = s:GenericProgressBar.mCreate(a:rollchars, a:depthChar, "\@PROGRESS\@")
++ let pbr = extend(gpbr, deepcopy(s:ProgressBarRoll))
++ unlet pbr.mCreate
++
++ let pbr.curTime = localtime()
++
++ return pbr
++endfunction
++
++function! s:ProgressBarRoll.mTick(count) dict
++ if (localtime() - self.curTime) > self.updateTime
++ let self.currentChar += 1
++ if self.currentChar == len(self.rangeChars)
++ let self.currentChar = 0
++ endif
++ let self.curTime = localtime()
++ call self.mUpdate()
++ endif
++endfunction
++
++let s:ProgressBarNumeric = {
++ \ 'progress1current' : 0,
++ \ 'progressmax' : 0,
++ \ 'progress1percent' : 0,
++ \ 'progresspercent' : 0,
++ \}
++
++function! s:ProgressBarNumeric.mCreate(maxcount, unit) dict
++ let gpbr = s:GenericProgressBar.mCreate(range(0,200), '',
++ \ "Processing \@PROGRESS\@\%, total ". a:maxcount . " " . a:unit)
++ let progressbar = extend(gpbr, deepcopy(s:ProgressBarNumeric))
++ unlet progressbar.mCreate
++
++ let progressbar.progressmax = a:maxcount
++ let progressbar.progress1percent = a:maxcount/100
++
++ let progressbar.units = a:unit
++
++ return progressbar
++endfunction
++
++
++function! s:ProgressBarNumeric.mTick(count) dict
++ let self.progress1current += a:count
++ if self.progress1percent <= self.progress1current
++ let tmp = (self.progress1current/self.progress1percent)
++ let self.progresspercent += tmp
++ let self.progress1current -= tmp * self.progress1percent
++ let self.currentChar += 1
++ call self.mUpdate()
++ endif
++endfunction
++
++" }}}
++" {{{ Status line
++let s:StatusLine = {
++ \ 'symlastprogress' : 0,
++ \ 'symprogress' : 0,
++ \ 'cursym' : 0,
++ \ 'savedStatusLine' : '',
++ \ 'statusextra' : '',
++ \ 'local':0
++ \}
++
++function! s:StatusLine.mInit() dict
++ let self.savedStatusLine = &l:statusline
++ setlocal statusline=%{CCTreeStatusLine()}
++endfunction
++
++function! s:StatusLine.mRestore() dict
++ let self.currentstatus = ''
++ let self.statusextra = ''
++
++ let &l:statusline = s:StatusLine.savedStatusLine
++ redrawstatus
++endfunction
++
++function! s:StatusLine.mSetInfo(msg) dict
++ let s:StatusLine.currentstatus = a:msg
++ redrawstatus
++endfunction
++
++function! s:StatusLine.mSetExtraInfo(msg) dict
++ let s:StatusLine.statusextra = a:msg
++ redrawstatus
++endfunction
++
++function! CCTreeStatusLine()
++ return s:pluginname. " ".
++ \ s:StatusLine.currentstatus . " -- ".
++ \ s:StatusLine.statusextra
++endfunction
++"}}}
++" {{{ Shell command interface
++
++let s:ShellCmds = {'shellOutput': ''}
++
++function! s:ShellCmds.mSplit(inFile, outFile)
++ let cmdEx = substitute(g:CCTreeSplitProgCmd, "PROG_SPLIT", g:CCTreeSplitProg,"")
++ let cmdEx = substitute(cmdEx, "SPLIT_OPT", g:CCTreeSplitProgOption,"")
++ if g:CCTreeDbFileSplitLines != -1
++ let cmdEx = substitute(cmdEx, "SPLIT_SIZE", g:CCTreeDbFileSplitLines,"")
++ else
++ let cmdEx = substitute(cmdEx, "SPLIT_SIZE", g:CCTreeDbFileMaxSize,"")
++ endif
++ let cmdEx = substitute(cmdEx, "IN_FILE", a:inFile,"")
++ let cmdEx = substitute(cmdEx, "OUT_FILE_PREFIX", a:outFile,"")
++
++ return cmdEx
++endfunction
++
++function! s:ShellCmds.mJoin(inFileList, outFile)
++ let cmdEx = substitute(g:CCTreeJoinProgCmd, "PROG_JOIN", g:CCTreeJoinProg,"")
++ let cmdEx = substitute(cmdEx, "JOIN_OPT", g:CCTreeJoinProgOpts,"")
++ let cmdEx = substitute(cmdEx, "IN_FILES", a:inFileList,"")
++ let cmdEx = substitute(cmdEx, "OUT_FILE", a:outFile,"")
++
++ return cmdEx
++endfunction
++
++function! s:ShellCmds.mExec(cmd)
++ let s:shellOutput= system(a:cmd)
++ if s:shellOutput != ''
++ " Failed
++ return s:CCTreeRC.Error
++ endif
++ return s:CCTreeRC.Success
++endfunction
++
++" }}}
++
++" {{{ Virtual file interface
++let s:vFile = {}
++
++function! s:vFile.mCreate(fname, mode)
++ if a:mode == 'r'
++ return s:vFileR.mCreate(a:fname)
++ elseif a:mode == 'w'
++ return s:vFileW.mCreate(a:fname)
++ endif
++ return -1
++endfunction
++
++let s:vFileW = {
++ \ 'splitfiles' : [],
++ \ 'totSplits' : 0,
++ \ 'lines' : [],
++ \ 'fileSize' : 0
++ \}
++
++function! s:vFileW.mCreate(fname) dict
++ let vfile = deepcopy(s:vFileW)
++ unlet vfile.mCreate
++ let vfile.link = a:fname
++
++ return vfile
++endfunction
++
++function! s:vFileW.mCreateSplit() dict
++ " first split, create name
++ if self.totSplits == 0
++ let self.tlink = tempname()
++ endif
++ let fname = self.tlink .'_'. self.totSplits
++ call writefile(self.lines, fname)
++ call add(self.splitfiles, fname)
++ let self.lines = []
++ let self.totSplits += 1
++endfunction
++
++function! s:vFileW.mTestForSplit() dict
++ if self.fileSize > g:CCTreeDbFileMaxSize
++ call self.mCreateSplit()
++ endif
++endfunction
++
++function! s:vFileW.mAddFileSize(size) dict
++ let self.fileSize += a:size
++endfunction
++
++function! s:vFileW.mWriteList(linelist) dict
++ call extend(self.lines, a:linelist)
++ call self.mTestForSplit()
++endfunction
++
++function! s:vFileW.mWriteLine(line) dict
++ call add(self.lines, a:line)
++ call self.mAddFileSize(len(a:line))
++ call self.mTestForSplit()
++endfunction
++
++function! s:vFileW.mClose() dict
++ if self.totSplits == 0
++ call writefile(self.lines, self.link)
++ else
++ " force remaining lines into a new split
++ call self.mCreateSplit()
++ " now join all of them
++ let filelist = join(self.splitfiles, " ")
++ let cmdEx = s:ShellCmds.mJoin(filelist, self.link)
++ if s:ShellCmds.mExec(cmdEx) != s:CCTreeRC.Success
++ let msg = s:shellOutput ."Shell command: ".cmdEx. " failed!".
++ \ " Refer help to setup split/join utils."
++ call s:CCTreeUtils.mWarningPrompt(msg)
++ endif
++ endif
++ for afile in self.splitfiles
++ call delete(afile)
++ endfor
++ return 0
++endfunction
++
++let s:vFileR = {
++ \ 'splitfiles' : [],
++ \ 'currentSplitIdx' : 0,
++ \ 'totSplits' : 0,
++ \ 'lines' : [],
++ \ 'valid' : 0,
++ \ 'mode' : ""
++ \}
++
++
++function! s:vFileR.mIsLargeFile() dict
++ if (getfsize(self.link) > g:CCTreeDbFileMaxSize)
++ return 1
++ endif
++ return 0
++endfunction
++
++function! s:vFileR.mCreate(fname) dict
++ let vfile = deepcopy(s:vFileR)
++ unlet vfile.mCreate
++ let vfile.link = a:fname
++ let vfile.valid = filereadable(a:fname)
++ let vfile.size = getfsize(a:fname)
++
++ return vfile
++endfunction
++
++function! s:vFileR.mOpen() dict
++ if self.mode == 'w'
++ " no need to do anything
++ return 0
++ endif
++
++ if self.mIsLargeFile() == 0
++ "little trick to keep interface uniform when we don't split
++ call add(self.splitfiles, self.link)
++ let self.totSplits = 1
++ else
++ let tmpDb = tempname()
++ let cmdEx = s:ShellCmds.mSplit(self.link, tmpDb)
++
++ if s:ShellCmds.mExec(cmdEx) != s:CCTreeRC.Success
++ let msg = s:shellOutput ."Shell command: ".cmdEx. " failed!".
++ \ " Refer help to setup split/join utils."
++ call s:CCTreeUtils.mWarningPrompt(msg)
++ return -1
++ else
++ let self.splitfiles = split(expand(tmpDb."*"), "\n")
++ endif
++ if empty(self.splitfiles)
++ return -1
++ endif
++ endif
++ let self.totSplits = len(self.splitfiles)
++ return 0
++endfunction
++
++function! s:vFileR.mRead() dict
++ if (self.currentSplitIdx >= len(self.splitfiles))
++ " out of bounds
++ return -1
++ endif
++ let self.lines = readfile(self.splitfiles[self.currentSplitIdx])
++ let self.currentSplitIdx += 1
++ return 0
++endfunction
++
++function! s:vFileR.mRewind() dict
++ let self.currentSplitIdx = 0
++ let self.lines = []
++endfunction
++
++
++function! s:vFileR.mClose() dict
++ if self.totSplits == 1
++ return
++ endif
++ for afile in self.splitfiles
++ call delete(afile)
++ endfor
++endfunction
++"}}}
++" {{{Stop watch
++let s:StopWatch = {
++ \ 'text' : "(no reltime feature)",
++ \}
++
++function! s:StopWatch.mCreate() dict
++ let stopWatch = deepcopy(s:StopWatch)
++ unlet stopWatch.mCreate
++
++ call stopWatch.mReset()
++ return stopWatch
++endfunction
++
++function! s:StopWatch.mReset() dict
++ if has('reltime')
++ let self.startRTime = reltime()
++ else
++ let self.startRTime = localtime()
++ endif
++endfunction
++
++function! s:StopWatch.mSnapElapsed() dict
++ if has('reltime')
++ let self.text = reltimestr(reltime(self.startRTime))
++ else
++ let self.text = localtime() - self.startRTime
++ endif
++endfunction
++
++function! s:StopWatch.mGetText() dict
++ return self.text
++endfunction
++"}}}
++" {{{ Digraph character compression/decompression routines
++
++let s:CharMaps = {
++ \'savedEncoding' : '',
++ \'mapkind' : ''
++ \}
++
++" The encoding needs to be changed to 8-bit, otherwise we can't swap special
++" 8-bit characters; restore after done
++function! s:CharMaps.mInitTranslator() dict
++ if self.mapkind == 'Alpha'
++ let self.savedEncoding = &encoding
++ let &encoding="latin1"
++ endif
++endfunction
++
++function! s:CharMaps.mDoneTranslator() dict
++ if self.mapkind == 'Alpha'
++ let &encoding=self.savedEncoding
++ endif
++endfunction
++
++function! s:CharMaps.CrossProduct(seq1, seq2) dict
++ let cpSeq = []
++ for dc1 in range(strlen(a:seq1))
++ for dc2 in range(strlen(a:seq2))
++ call add(cpSeq, a:seq1[dc1].a:seq2[dc2])
++ endfor
++ endfor
++ return cpSeq
++endfunction
++
++let s:TranslateMap = {}
++
++function! s:TranslateMap.mCreate (srcsym, destsym, mapkind, regex) dict
++ let dicttable = extend(deepcopy(s:CharMaps), deepcopy(s:TranslateMap))
++ unlet dicttable.CrossProduct
++
++ let dicttable.mappings = {}
++
++ " map lower
++ let maxsym = min([len(a:srcsym),len (a:destsym)])
++
++ let index = 0
++ while (index < maxsym)
++ let dicttable.mappings[a:srcsym[index]] = a:destsym[index]
++ let index += 1
++ endwhile
++ " Need mapping lens, we assume it's constant across the board
++ let dicttable.mapsrclen = len(a:srcsym[0])
++ let dicttable.regex = a:regex
++
++
++ if a:mapkind == 'Alpha'
++ let dicttable.mTranslate = dicttable.mTranslateAlpha
++ elseif a:mapkind == 'Numeric'
++ let dicttable.mTranslate = dicttable.mTranslateNumeric
++ endif
++
++ let dicttable.mapkind = a:mapkind
++
++ unlet dicttable.mTranslateNumeric
++ unlet dicttable.mTranslateAlpha
++
++ return dicttable
++endfunction
++
++
++function! s:TranslateMap.mTranslateNumeric(value) dict
++ let index = 0
++ let retval = ""
++
++ " remember to deal with multi-byte characters
++ while index < len(a:value)
++ let char1 = char2nr(a:value[index])
++ if has_key(self.mappings, char1)
++ let newmap = self.mappings[char1]
++ else
++ " take only the first character
++ let newmap = a:value[index]
++ endif
++ let retval .= newmap
++ let index += 1
++ endwhile
++ return retval
++endfunction
++
++function! s:TranslateMap.mTranslateAlpha(value) dict
++ let retval = substitute(a:value, self.regex, '\=self.mappings[submatch(1)]', "g")
++ return retval
++endfunction
++
++function! s:CCTreeGetXRefDbMaps(maptype, mapkind)
++ let dichar1 = ",0123456789"
++ let dichar2 = ",0123456789"
++
++ return s:CCTreeCreateGenericMaps(a:maptype, a:mapkind, dichar1, dichar2)
++endfunction
++
++function! s:CCTreeGetCscopeMaps(maptype, mapkind)
++ let dichar1 = " teisaprnl(of)=c"
++ let dichar2 = " tnerpla"
++
++ return s:CCTreeCreateGenericMaps(a:maptype, a:mapkind, dichar1, dichar2)
++endfunction
++
++
++function! s:CCTreeCreateGenericMaps(maptype, mapkind, dichar1, dichar2)
++ let s:CharMaps.mapkind = a:mapkind
++ call s:CharMaps.mInitTranslator()
++ if a:mapkind == 'Numeric'
++ let ab = map(range(128,255), 'v:val')
++ elseif a:mapkind == 'Alpha'
++ let ab = map(range(128,255), 'nr2char(v:val)')
++ else
++ return {}
++ endif
++ let ac = s:CharMaps.CrossProduct(a:dichar1, a:dichar2)
++ if a:maptype == 'Compress'
++ let maps = s:TranslateMap.mCreate(ac, ab, a:mapkind,
++ \'\(['.a:dichar1.']['.a:dichar2.']\)\C')
++ elseif a:maptype == 'Uncompress'
++ let maps = s:TranslateMap.mCreate(ab, ac, a:mapkind,
++ \'\([\d128-\d255]\)')
++ endif
++ call s:CharMaps.mDoneTranslator()
++ return maps
++endfunction
++" }}}
++" {{{ Unique list filter object
++
++let s:UniqList = {}
++
++function! s:UniqList.mFilterEntries(lstval) dict
++ let valdict = {}
++ let reslist = ''
++ for aval in a:lstval
++ if !has_key(valdict, aval)
++ let valdict[aval] = ''
++ let reslist .= (aval . ",")
++ endif
++ endfor
++ return reslist
++endfunction
++
++let s:CCTreeUniqListFilter = deepcopy(s:UniqList)
++function! s:CCTreeMakeCommaListUnique(clist)
++ let entries = split(a:clist, ",")
++ if len(entries) > 0
++ return s:CCTreeUniqListFilter.mFilterEntries(entries)
++ endif
++ return ""
++endfunction
++" }}}
++" {{{ Buffer/Window
++func! s:FindOpenBuffer(filename)
++ let bnrHigh = bufnr("$")
++ "tabpagebuflist(tabpagenr())
++
++ for bufnrs in range(1, bnrHigh)
++ if (bufexists(bufnrs) == 1 && bufname(bufnrs) == a:filename && bufloaded(bufnrs) != 0 )
++ return bufnrs
++ endif
++ endfor
++ " Could not find the buffer
++ return 0
++endfunction
++
++func! s:FindOpenWindow(filename)
++ let bufnr = s:FindOpenBuffer(a:filename)
++ if (bufnr > 0)
++ let newWinnr = bufwinnr(bufnr)
++ if newWinnr != -1
++ exec newWinnr.'wincmd w'
++ return 1
++ endif
++ endif
++ " Could not find the buffer
++ return 0
++endfunction
++" }}}
++" {{{ Utils library
++
++let s:Utils = {}
++
++" Use this function to determine the correct "g" flag
++" for substitution
++function! s:Utils.mGetSearchFlag(gvalue)
++ let ret = (!a:gvalue)* (&gdefault) + (!&gdefault)*(a:gvalue)
++ if ret == 1
++ return 'g'
++ endif
++ return ''
++endfunc
++
++" Strlen works for multibyte characters
++function! s:Utils.mStrlenEx(val)
++ return strlen(substitute(a:val, ".", "x", "g"))
++endfunc
++" }}}
++" {{{ Generic db loader interface
++let s:GenericDbLdr = {
++ \ 'fDBName' : '',
++ \ 'class' : 'Generic',
++ \ }
++
++function! s:GenericDbLdr.mCreate(fname) dict
++ let gdb = deepcopy(s:GenericDbLdr)
++ unlet gdb.mCreate
++ let gdb.fDBName = a:fname
++
++ if !filereadable(a:fname)
++ return s:CCTreeRC.Error
++ endif
++
++ return gdb
++endfunction
++
++function! s:GenericDbLdr.mParseDbHeader(gRdr)
++ let header = readfile(self.fDBName, "", a:gRdr.headerLines)
++ return a:gRdr.mParseDbHeader(header)
++endfunction
++
++let s:XRefMemDbLdr = {
++ \ 'class' : s:DBStorage.memory
++ \}
++
++function! s:XRefMemDbLdr.mCreate(fname) dict
++ let gdb = s:GenericDbLdr.mCreate(a:fname)
++ if type(gdb) != type({})
++ return gdb
++ endif
++ let mdb = extend(gdb, deepcopy(s:XRefMemDbLdr))
++ unlet mdb.mCreate
++
++ return mdb
++endfunction
++
++if has('perl') && g:CCTreeUsePerl == 1
++" Perl function
++function! s:XRefMemDbLdr.mLoadFileIntoXRefDb(xRefDb, gRdr) dict
++ let stage = 1
++ for afltr in a:gRdr.opts
++ let stageidxstr = 'Stage ('.stage.'/'.len(a:gRdr.opts).') '
++ call s:StatusLine.mSetInfo(stageidxstr. ': (PERL) Loading database ')
++ call a:gRdr.mProcessingStateInit()
++ let pBar = s:ProgressBarNumeric.mCreate(getfsize(self.fDBName), "bytes")
++ echomsg 'filtering '. afltr
++perl << PERL_EOF
++ #use strict;
++ #use warnings FATAL => 'all';
++ #use warnings NONFATAL => 'redefine';
++
++ my $filebytes = 0;
++ my $filterpat = VIM::Eval("afltr");
++
++ open (CSCOPEDB, VIM::Eval("self.fDBName")) or die "File trouble!";
++ #VIM::DoCommand("echomsg '".$filterpat."'");
++
++ while (<CSCOPEDB>) {
++ $filebytes += length($_);
++ chomp($_);
++
++ if ($_ !~ $filterpat) {
++ next;
++ }
++ VIM::DoCommand("call pBar.mTick(".$filebytes.")");
++ $filebytes = 0;
++ VIM::DoCommand("call a:gRdr.mProcessSymbol(a:xRefDb, '".$_."')");
++ }
++ VIM::DoCommand("call pBar.mDone()");
++ close(CSCOPEDB);
++PERL_EOF
++ call a:gRdr.mProcessingStateDone()
++ let stage += 1
++ endfor
++endfunction
++else
++" Native Vim function
++function! s:XRefMemDbLdr.mLoadFileIntoXRefDb(xRefDb, gRdr) dict
++ let vDbFile = s:vFile.mCreate(self.fDBName, "r")
++ if vDbFile.valid == 0
++ return -1
++ endif
++ if vDbFile.mIsLargeFile() == 1
++ call s:StatusLine.mSetExtraInfo('Database '
++ \.' >'.g:CCTreeDbFileMaxSize .' bytes. Splitting '.
++ \'into smaller chunks... (this may take some time)')
++ endif
++ try
++ if vDbFile.mOpen() == 0
++ call self.mReadFileIntoXRefDb(vDbFile,
++ \ a:xRefDb,
++ \ a:gRdr)
++ endif
++ finally
++ call vDbFile.mClose()
++ endtry
++endfunction
++endif
++
++function! s:XRefMemDbLdr.mReadFileIntoXRefDb(vDbFile, xrefdb, gRdr)
++ let stage = 0
++ for afltr in a:gRdr.opts
++ call a:vDbFile.mRewind()
++ let stage += 1
++ call a:gRdr.mProcessingStateInit()
++ while 1 == 1
++ if a:vDbFile.mRead() == -1
++ break
++ endif
++ let stageidxstr = 'Stage ('.stage.'/'.len(a:gRdr.opts).') '
++ let fileidxstr = '('.a:vDbFile.currentSplitIdx.'/'.a:vDbFile.totSplits.') '
++ call s:StatusLine.mSetInfo(stageidxstr. ': Reading database chunk '.fileidxstr)
++ " Filter-out lines that doesn't have relevant information
++ let plist = a:gRdr.mReadLinesFromFile(a:vDbFile, afltr)
++ let pBar = s:ProgressBarNumeric.mCreate(len(plist), "items")
++ call s:StatusLine.mSetInfo(stageidxstr.': Analyzing database chunk '.fileidxstr)
++ call self.mProcessListIntoXrefDb(plist, a:gRdr, a:xrefdb, pBar)
++ call pBar.mDone()
++ " clean-up memory
++ call garbagecollect()
++ endwhile
++ call a:gRdr.mProcessingStateDone()
++ endfor
++endfunction
++
++function! s:XRefMemDbLdr.mProcessListIntoXrefDb(symbols, rdr, xrefdb, pbar)
++ for a in a:symbols
++ call a:pbar.mTick(1)
++ call a:rdr.mProcessSymbol(a:xrefdb, a)
++ endfor
++endfunction
++
++function! s:GenericDbLdr.mParseDbHeader(gRdr)
++ let header = readfile(self.fDBName, "", a:gRdr.headerLines)
++ return a:gRdr.mParseDbHeader(header)
++endfunction
++
++" }}}
++" {{{ Generic Disk DB Ldr
++let s:XRefDiskDbLdr = {
++ \ 'class' : s:DBStorage.disk
++ \ }
++
++function! s:XRefDiskDbLdr.mCreate(fname) dict
++ let gdb = s:GenericDbLdr.mCreate(a:fname)
++ if type(gdb) != type({})
++ return gdb
++ endif
++ let mdb = extend(gdb, deepcopy(s:XRefDiskDbLdr))
++ unlet mdb.mCreate
++
++ return mdb
++endfunction
++
++function! s:XRefDiskDbLdr.mLoadFileIntoXRefDb(xRefDb, gRdr) dict
++ call a:xRefDb.mSetLink(self.fDBName)
++endfunction
++
++"}}}
++" {{{ Xref disk DB
++let s:XRefDiskDb = {
++ \ 'link':'',
++ \ 'savedTags': '',
++ \ 'class' : s:DBStorage.disk
++ \ }
++
++function! s:XRefDiskDb.mCreate() dict
++ let fdb = deepcopy(s:XRefDiskDb)
++ unlet fdb.mCreate
++ let fdb.maps = s:CCTreeGetXRefDbMaps('Uncompress', 'Numeric')
++
++ return fdb
++endfunction
++
++function! s:XRefDiskDb.mSetLink(filedb) dict
++ let self.link = a:filedb
++ " revisit, do parse header here
++endfunction
++
++function! s:XRefDiskDb.mClear() dict
++ " do nothing
++endfunction
++
++function! s:XRefDiskDb.mInitState() dict
++ let self.savedTags = &tags
++ let &tags = self.link
++endfunction
++
++function! s:XRefDiskDb.mRestoreState() dict
++ let &tags = self.savedTags
++endfunction
++
++function! s:XRefDiskDb.mDecodeTagEntry(tagentry) dict
++ let itms = split(a:tagentry.name, "#")
++ let a:tagentry.n = itms[1]
++ let a:tagentry.idx = itms[0]
++
++ " Vim taglist() drops empty fields, so need to protect
++ if has_key(a:tagentry, 'c')
++ let a:tagentry.c = self.maps.mTranslate(a:tagentry.c)
++ else
++ let a:tagentry.c = ''
++ endif
++ if has_key(a:tagentry, 'p')
++ let a:tagentry.p = self.maps.mTranslate(a:tagentry.p)
++ else
++ let a:tagentry.p = ''
++ endif
++
++ return a:tagentry
++endfunction
++
++function! s:XRefDiskDb.mGetSymbolIdFromName(symname) dict
++ let symtagline = taglist('\#'.a:symname.'$')
++ let g:xyz = symtagline
++ let asym = self.mDecodeTagEntry(symtagline[0])
++ return asym.idx
++endfunction
++
++function! s:XRefDiskDb.mGetSymbolFromId(symid) dict
++ let symtagline = taglist('^'.a:symid.'\#')
++ if empty(symtagline)
++ echomsg "Failed to locate ".a:symid
++ else
++ return self.mDecodeTagEntry(symtagline[0])
++ endif
++ return {}
++endfunction
++
++function! s:XRefDiskDb.mGetSymbolIds() dict
++ " illegal
++ let symtaglines = taglist('^.')
++ return keys(self.symidhash)
++endfunction
++
++function! s:XRefDiskDb.mGetSymbolNames(lead) dict
++ if empty(a:lead)
++ let symtaglines = taglist('^.')
++ else
++ let symtaglines = taglist('#'.a:lead)
++ endif
++ let alist = []
++ for atag in symtaglines
++ let acctreesym = self.mDecodeTagEntry(atag)
++ call add(alist, acctreesym.n)
++ endfor
++ return alist
++endfunction
++" }}}
++" {{{ TagFile utils
++let s:CCTreeTagDbRdr = {'class': 'CCTreeXrefDb',
++ \ 'headerLines' : 4,
++ \ 'compressed' : 0,
++ \ 'opts': ['v:val !~ "^[\!]"'],
++ \ 'perl_opts': "^[^\!]",
++ \ 'mapPreKeys': {'c':'','p':''},
++ \ 'mapPostKeys': {'c':'','p':''}
++ \ }
++
++function! s:CCTreeTagDbRdr.mCreate(fname) dict
++ let cctxdbrdr = deepcopy(s:CCTreeTagDbRdr)
++ unlet cctxdbrdr.mCreate
++
++ return cctxdbrdr
++endfunction
++
++function! s:CCTreeTagDbRdr.mRequirePreProcessing() dict
++ return s:CCTreeRC.False
++endfunction
++
++function! s:CCTreeTagDbRdr.mRequirePostProcessing() dict
++ return s:CCTreeRC.True
++endfunction
++
++function! s:CCTreeTagDbRdr.mRequireCleanup() dict
++ " Clean-up all symbols [never]
++ return s:CCTreeRC.False
++endfunction
++
++function! s:CCTreeTagDbRdr.mGetPreProcessingMaps() dict
++ return s:CCTreeGetXRefDbMaps('Compress', 'Alpha')
++endfunction
++
++function! s:CCTreeTagDbRdr.mGetPostProcessingMaps() dict
++ return s:CCTreeGetXRefDbMaps('Uncompress', 'Alpha')
++endfunction
++
++
++function! s:CCTreeTagDbRdr.mParseDbHeader(hdr) dict
++ " just check line 3 for sanity
++ if a:hdr[2] =~ "CCTree"
++ return s:CCTreeRC.Success
++ endif
++ return s:CCTreeRC.Error
++endfunction
++
++function! s:CCTreeTagDbRdr.mProcessingStateInit() dict
++endfunction
++
++function! s:CCTreeTagDbRdr.mProcessingStateDone() dict
++endfunction
++
++function! s:CCTreeTagDbRdr.mReadLinesFromFile(vdbFile, filtercmds) dict
++ " Hard-coded assumptions here about format for performance
++ if empty(get(a:vdbFile.lines, 0)) != 1 && a:vdbFile.lines[0][0] == "!"
++ " filter out the first few lines starting with "!"
++ call remove(a:vdbFile.lines, 0, self.headerLines-1)
++ endif
++ return a:vdbFile.lines
++endfunction
++
++function! s:CCTreeTagDbRdr.mProcessSymbol(xrefdb, aline) dict
++ let cctreesym = self.mDecodeTagLine(a:aline)
++ call a:xrefdb.mInsertSym(cctreesym.idx, cctreesym)
++ " we really don't need idx any longer
++ unlet cctreesym.idx
++endfunction
++
++function! s:CCTreeTagDbRdr.mDecodeTagLine(tagline) dict
++
++ let items = split(a:tagline, "\t")
++ let newsym = s:CCTreeSym.mCreate("")
++ try
++ let [newsym.idx, newsym.n] = split(items[0], '#')
++ catch
++ echomsg "problem decoding ". a:tagline
++ endtry
++
++ "let newsym.idx = strpart(items[0], 0, idxBr)
++ "let newsym.n = items[0][ idxBr+1 : -2] "strpart(items[0], idxBr+1, strlen(items[0])-1)
++ if empty(get(items, 3)) != 1
++ let newsym.c = items[3][2:]
++ endif
++ if empty(get(items, 4)) != 1
++ let newsym.p = items[4][2:]
++ endif
++ return newsym
++endfunction
++
++" }}}
++" {{{ Generic Db Serializer
++let s:GenericDbSerializer = {}
++
++function! s:GenericDbSerializer.mCreate(xrefdb) dict
++ let gDbSerializer = deepcopy(s:GenericDbSerializer)
++ let gDbSerializer.xrefdb = a:xrefdb
++ return gDbSerializer
++endfunction
++
++function! s:GenericDbSerializer.mWriteXRefDbToFile(fname,
++ \ gWriter) dict
++ call s:StatusLine.mInit()
++ try
++ call s:StatusLine.mSetInfo('Writing XRefDb')
++ let vDbFile = s:vFile.mCreate(a:fname, "w")
++ call vDbFile.mWriteList(a:gWriter.mBuildHeader())
++ call self.mWriteSymsToFile(vDbFile, a:gWriter)
++ finally
++ call vDbFile.mClose()
++ call s:StatusLine.mRestore()
++ endtry
++endfunction
++
++function! s:GenericDbSerializer.mWriteSymsToFile(dstVFile,
++ \ gWriter) dict
++ let pBar = s:ProgressBarNumeric.mCreate(self.xrefdb.mGetSymbolCount(),
++ \ "items")
++ call a:gWriter.mInitWriting()
++ " write syms
++ for asymid in sort(self.xrefdb.mGetSymbolIds())
++ let acctreesym = self.xrefdb.mGetSymbolFromId(asymid)
++ call a:dstVFile.mWriteLine(a:gWriter.mBuildTagLine(acctreesym,
++ \ asymid))
++ call pBar.mTick(1)
++ endfor
++ call pBar.mDone()
++ call a:gWriter.mDoneWriting()
++endfunction
++" }}}
++" {{{ CCTreeTagDb Writer
++let s:CCTreeTagDbWriter = {}
++
++function! s:CCTreeTagDbWriter.mCreate(tmaps) dict
++ let dbwriter = deepcopy(s:CCTreeTagDbWriter)
++ unlet dbwriter.mCreate
++
++
++ let dbwriter.tmaps = a:tmaps
++ return dbwriter
++endfunction
++
++function! s:CCTreeTagDbWriter.mInitWriting() dict
++ call self.tmaps.mInitTranslator()
++endfunction
++
++function! s:CCTreeTagDbWriter.mDoneWriting() dict
++ call self.tmaps.mDoneTranslator()
++endfunction
++
++function! s:CCTreeTagDbWriter.mBuildHeader() dict
++ let hdr = []
++ call add(hdr, "!_TAG_FILE_FORMAT\t2\t/extended format; --format=1 will not append ;\" to lines/")
++ call add(hdr, "!_TAG_FILE_SORTED\t1\t/0=unsorted, 1=sorted, 2=foldcase/")
++ call add(hdr, "!_TAG_PROGRAM_NAME\t\tCCTree (Vim plugin)//")
++ call add(hdr, "!_TAG_PROGRAM_URL\thttp://vim.sourceforge.net/scripts/script.php?script_id=2368\t/site/")
++ return hdr
++endfunction
++
++
++function! s:CCTreeTagDbWriter.mBuildTagLine(sym, symid) dict
++ let basetag = a:symid .'#'. a:sym.n."\t"."\t"."/^\$/".";\""
++ let cm = self.tmaps.mTranslate(a:sym.c)
++ let pm = self.tmaps.mTranslate(a:sym.p)
++
++ let basetag .= "\tc:". self.tmaps.mTranslate(a:sym.c)
++ let basetag .= "\tp:". self.tmaps.mTranslate(a:sym.p)
++
++ return basetag
++endfunction
++" }}}
++" {{{ CCTree constants
++let s:CCTreeRC = {
++ \ 'Error' : -1,
++ \ 'True' : 1,
++ \ 'False' : 0,
++ \ 'Success' : 2
++ \ }
++"}}}
++" {{{ CCTree DB Obj
++" Symbol definition
++
++let s:CCTreeSym = {
++ \'k': "",
++ \'n': "",
++ \'c': "",
++ \'p': ""
++ \}
++
++function! s:CCTreeSym.mCreate(name, kind)
++ let sym = deepcopy(s:CCTreeSym)
++ unlet sym.mCreate
++ let sym.n = a:name
++ let sym.k = a:kind
++ return sym
++endfunction
++
++
++" }}}
++" {{{ GenericXref, XrefDb
++let s:GenericXRef = {}
++
++function! s:GenericXRef.mCreate(filedb) dict
++ let gxref = deepcopy(s:GenericXRef)
++ return gxref
++endfunction
++
++function! s:GenericXRef.mInitState() dict
++endfunction
++
++function! s:GenericXRef.mRestoreState() dict
++endfunction
++" {{{ XRef Database object
++let s:xRefMemDb = {
++ \ 'symuniqid': 0,
++ \ 'symidhash' : {},
++ \ 'symnamehash' : {},
++ \ 'class' : s:DBStorage.memory
++ \}
++
++
++function s:xRefMemDb.mCreate() dict
++ let dbObj = deepcopy(s:xRefMemDb)
++ unlet dbObj.mCreate
++
++ return dbObj
++endfunction
++
++function s:xRefMemDb.mInitState() dict
++endfunction
++
++function s:xRefMemDb.mRestoreState() dict
++endfunction
++
++function s:xRefMemDb.mClear() dict
++ let self.symidhash = {}
++ let self.symnamehash = {}
++ let self.symuniqid = 0
++endfunction
++
++function! s:xRefMemDb.mInsertSym(idx, cctreesym) dict
++ let self.symuniqid = max([self.symuniqid, a:idx])
++ let self.symidhash[a:idx] = a:cctreesym
++ let self.symnamehash[a:cctreesym.n] = a:idx
++endfunction
++
++function! s:xRefMemDb.mRemoveSymById(symidx) dict
++ call self.mRemoveSymByName(acctreesym.n)
++ call remove(self.symidhash, a:symidx)
++endfunction
++
++function! s:xRefMemDb.mRemoveSymByName(symname) dict
++ call remove(self.symnamehash, a:symname)
++endfunction
++
++function! s:xRefMemDb.mAddSym(name, kind) dict
++ if !has_key(self.symnamehash, a:name)
++ let self.symnamehash[a:name] = self.symuniqid
++ let self.symidhash[self.symuniqid] =
++ \s:CCTreeSym.mCreate(a:name, a:kind)
++ let self.symuniqid += 1
++ endif
++ let asymid = self.symnamehash[a:name]
++ if a:kind != ""
++ let asym = self.symidhash[asymid]
++ let asym.k = a:kind
++ endif
++ return asymid
++endfunction
++
++function! s:xRefMemDb.mMarkXRefSyms(funcentryidx, newfuncidx) dict
++ let self.symidhash[a:funcentryidx]['c'] .= (",". a:newfuncidx)
++ let self.symidhash[a:newfuncidx]['p'] .= (",". a:funcentryidx)
++endfunction
++
++function! s:xRefMemDb.mGetSymbolFromName(symname) dict
++ return self.symidhash[self.symnamehash[a:symname]]
++endfunction
++
++function! s:xRefMemDb.mGetSymbolIdFromName(symname) dict
++ if has_key(self.symnamehash, a:symname)
++ return self.symnamehash[a:symname]
++ else
++ return s:CCTreeRC.Error
++ endif
++endfunction
++
++function! s:xRefMemDb.mGetSymbolFromId(symid) dict
++ return self.symidhash[a:symid]
++endfunction
++
++function! s:xRefMemDb.mGetSymbolIds() dict
++ return keys(self.symidhash)
++endfunction
++
++function! s:xRefMemDb.mGetSymbolNames(lead) dict
++ let syms = keys(self.symnamehash)
++ if empty(a:lead) != 1
++ return filter(syms, 'v:val =~? a:lead')
++ endif
++ return syms
++endfunction
++
++function! s:xRefMemDb.mGetSymbolCount() dict
++ return len(self.symnamehash)
++endfunction
++
++function! s:xRefMemDb.mTranslateSymbols(map, tkeys) dict
++ call a:map.mInitTranslator()
++ let pBar = s:ProgressBarNumeric.mCreate(len(self.symnamehash), "items")
++
++ for asym in keys(self.symnamehash)
++ let idx = self.symnamehash[asym]
++ let val = self.symidhash[idx]
++ if has_key(a:tkeys, 'n')
++ let uncmpname = a:map.mTranslate(asym)
++ if (asym != uncmpname)
++ "Set up new entry
++ let self.symnamehash[uncmpname] = idx
++ " free the old entry
++ call remove(self.symnamehash, asym)
++ " Set uncompressed name
++ let val.n = uncmpname
++ endif
++ endif
++ if has_key(a:tkeys, 'p')
++ let val.p = a:map.mTranslate(val.p)
++ endif
++ if has_key(a:tkeys, 'c')
++ let val.c = a:map.mTranslate(val.c)
++ endif
++ call pBar.mTick(1)
++ endfor
++ call pBar.mDone()
++ call a:map.mDoneTranslator()
++endfunction
++
++function! s:xRefMemDb.mCleanSymbols () dict
++ let pBar = s:ProgressBarNumeric.mCreate(len(self.symnamehash), "items")
++ for asym in keys(self.symnamehash)
++ let idx = self.symnamehash[asym]
++ let val = self.symidhash[idx]
++ if empty(val.p) && empty(val.c)
++ call remove(self.symnamehash, asym)
++ call remove(self.symidhash, idx)
++ else
++ let val.p = s:CCTreeMakeCommaListUnique(val.p)
++ let val.c = s:CCTreeMakeCommaListUnique(val.c)
++ endif
++ call pBar.mTick(1)
++ endfor
++ call pBar.mDone()
++endfunction
++"}}}
++"}}} End of Xref
++" {{{ Tracer
++let s:CallTree = {
++ \ 'symbol' : ""
++ \ }
++function! s:CallTree.mCreate(name) dict
++ let ct = deepcopy(s:CallTree)
++ unlet ct.mCreate
++
++ let ct.symbol = a:name
++
++ return ct
++endfunction
++
++function! s:CallTree.mAddChildLink(childTree) dict
++ if !has_key(self, 'childlinks')
++ let self.childlinks = []
++ endif
++ call add(self.childlinks, a:childTree)
++endfunction
++
++let s:XRefTracer = {
++ \}
++
++function! s:XRefTracer.mCreate(xrefdb) dict
++ let xreftracer = deepcopy(s:XRefTracer)
++ let xreftracer.xrefdb = a:xrefdb
++
++ return xreftracer
++endfunction
++
++function! s:XRefTracer.mInitTracing() dict
++ call self.xrefdb.mInitState()
++endfunction
++
++function! s:XRefTracer.mDoneTracing() dict
++ call self.xrefdb.mRestoreState()
++endfunction
++
++function! s:XRefTracer.mGetSymbolIdXRef(symid, direction) dict
++ let acctreesym = self.xrefdb.mGetSymbolFromId(a:symid)
++ let symidslist = split(
++ \s:CCTreeMakeCommaListUnique(acctreesym[a:direction]), ",")
++ return symidslist
++endfunction
++
++function! s:XRefTracer.mBuildForSymbol(symid, curdepth, maxdepth,
++ \ direction, pbar) dict
++ if (a:curdepth > a:maxdepth)
++ return {}
++ endif
++
++ call a:pbar.mSetDepth(a:curdepth)
++ let asym = self.xrefdb.mGetSymbolFromId(a:symid)
++ " revisit
++ if empty(asym)
++ return {}
++ endif
++
++ let rtree = s:CallTree.mCreate(asym['n'])
++
++ for entry in self.mGetSymbolIdXRef(a:symid, a:direction)
++ call a:pbar.mTick(1)
++ let ctree =
++ \self.mBuildForSymbol(entry, a:curdepth+1, a:maxdepth,
++ \a:direction, a:pbar)
++ call rtree.mAddChildLink(ctree)
++ endfor
++ return rtree
++endfunction
++" }}}
++
++" {{{ Cscope Reader
++
++
++let s:CscopeDbRdrState = {
++ \'curfuncidx': -1,
++ \'curfileidx': -1,
++ \'curmacroidx': -1,
++ \'curenumidx': -1,
++ \ }
++
++function! s:CscopeDbRdrState.mCreate() dict
++ return deepcopy(s:CscopeDbRdrState)
++endfunction
++
++let s:CscopeDbRdrSymTags = {
++ \'func' : '$}',
++ \'macro' : '#\)',
++ \'file' : '@\~',
++ \'enum' : 'em',
++ \'global' : 'g',
++ \'typedef' : 't',
++ \}
++
++let s:CscopeDbSymFilter = ['v:val =~ "^\t[#`$}@\~\)]"']
++let s:CscopeDbSymEnhFilter = ['v:val =~ "^\t[emgt#`$}@~)]"',
++ \ 'v:val =~ "^\\a\\|^\t[)$}#]"']
++
++let s:CscopeDbSymFilterPerl = ['^\t[\`\#\$\}\@\~\)]']
++let s:CscopeDbSymEnhFilterPerl = ['^\t[\`\#\$\}\@\~\)emgt]',
++ \ '^[A-Za-z]|^\t[\#\$\}\)]']
++
++let s:CscopeDbRdr = {
++ \ 'class': 'Cscope',
++ \ 'headerLines' : 1,
++ \ 'compressed' : 0,
++ \ 'opts': [],
++ \ 'perl_opts': '',
++ \ 'mapPreKeys': {'n':''},
++ \ 'mapPostKeys': {'n':''}
++ \}
++
++function! s:CscopeDbRdr.mCreate(fname, enhanced) dict
++ let csdbrdr = deepcopy(s:CscopeDbRdr)
++ unlet csdbrdr.mCreate
++
++ if a:enhanced == 1
++ if g:CCTreeUsePerl == 1
++ let csdbrdr.opts = s:CscopeDbSymEnhFilterPerl
++ else
++ let csdbrdr.opts = s:CscopeDbSymEnhFilter
++ endif
++ else
++ if g:CCTreeUsePerl == 1
++ let csdbrdr.opts = s:CscopeDbSymFilterPerl
++ else
++ let csdbrdr.opts = s:CscopeDbSymFilter
++ endif
++ endif
++ return csdbrdr
++endfunction
++
++function! s:CscopeDbRdr.mProcessingStateInit() dict
++ let self.iState = s:CscopeDbRdrState.mCreate()
++endfunction
++
++function! s:CscopeDbRdr.mProcessingStateDone() dict
++ " discard state
++ unlet self.iState
++endfunction
++
++function! s:CscopeDbRdr.mReadLinesFromFile(vDbFile, filtercmds) dict
++ return s:CCTreeUtils.mFilter(a:vDbFile.lines, a:filtercmds)
++endfunction
++
++function! s:CscopeDbRdr.mParseDbHeader(dbHeader) dict
++ if a:dbHeader[0] =~ "cscope"
++ if (a:dbHeader[0] !~ "cscope.*\-c")
++ let self.compressed = s:CCTreeRC.True
++ else
++ let self.compressed = s:CCTreeRC.False
++ endif
++ return s:CCTreeRC.Success
++ endif
++ return s:CCTreeRC.Error
++endfunction
++
++function! s:CscopeDbRdr.mRequirePreProcessing() dict
++ return (self.compressed == 1)? s:CCTreeRC.True : s:CCTreeRC.False
++endfunction
++
++function! s:CscopeDbRdr.mRequirePostProcessing() dict
++ return (self.compressed == 1)? s:CCTreeRC.True : s:CCTreeRC.False
++endfunction
++
++function! s:CscopeDbRdr.mRequireCleanup() dict
++ " Clean-up all symbols [always]
++ return s:CCTreeRC.True
++endfunction
++
++function! s:CscopeDbRdr.mGetPreProcessingMaps() dict
++ return s:CCTreeGetCscopeMaps('Compress', 'Alpha')
++endfunction
++
++function! s:CscopeDbRdr.mGetPostProcessingMaps() dict
++ return s:CCTreeGetCscopeMaps('Uncompress', 'Alpha')
++endfunction
++
++function! s:CscopeDbRdr.mProcessSymbol(xrefdb, symbol) dict
++ try
++ if a:symbol[0] == "\t"
++ return self.mProcessTaggedSymbol(a:xrefdb, a:symbol)
++ else
++ return self.mProcessUnTaggedSymbol(a:xrefdb, a:symbol)
++ endif
++ catch
++ echomsg 'Problem with '. a:symbol
++ endtry
++endfunction
++
++function! s:CscopeDbRdr.mProcessUnTaggedSymbol(xrefdb, symbol) dict
++ let cursymidx = a:xrefdb.mGetSymbolIdFromName(a:symbol)
++ if cursymidx != s:CCTreeRC.Error
++ if self.iState.curfuncidx != -1
++ call a:xrefdb.mMarkXRefSyms(self.iState.curfuncidx, cursymidx)
++ elseif self.iState.curmacroidx != -1
++ call a:xrefdb.mMarkXRefSyms(self.iState.curmacroidx, cursymidx)
++ endif
++ endif
++endfunction
++
++function! s:CscopeDbRdr.mProcessTaggedSymbol(xrefdb, symbol) dict
++ if self.iState.curmacroidx != -1
++ if a:symbol[1] == "`"
++ call a:xrefdb.mMarkXRefSyms(self.iState.curmacroidx,
++ \ a:xrefdb.mAddSym(a:symbol[2:], ""))
++ elseif a:symbol[1] == ')'
++ let self.iState.curmacroidx = -1
++ endif
++ elseif self.iState.curfuncidx != -1
++ " inside function
++ if a:symbol[1] == "`"
++ call a:xrefdb.mMarkXRefSyms(self.iState.curfuncidx,
++ \ a:xrefdb.mAddSym(a:symbol[2:], ""))
++ elseif a:symbol[1] == "}"
++ let self.iState.curfuncidx = -1
++ elseif a:symbol[1] == "#"
++ let self.iState.curmacroidx = a:xrefdb.mAddSym(a:symbol[2:], 'm')
++ endif
++ elseif self.iState.curenumidx != -1
++ if a:symbol[1] == "m"
++ call a:xrefdb.mMarkXRefSyms(self.iState.curenumidx,
++ \ a:xrefdb.mAddSym(a:symbol[2:], "em"))
++ else
++ " just reprocess the symbol after changing state
++ let self.iState.curenumidx = -1
++ call self.mProcessTaggedSymbol(a:xrefdb, a:symbol)
++ endif
++ elseif a:symbol[1] == "$"
++ let self.iState.curfuncidx = a:xrefdb.mAddSym(a:symbol[2:], "f")
++ elseif a:symbol[1] == "#"
++ let self.iState.curmacroidx = a:xrefdb.mAddSym(a:symbol[2:], "d")
++ elseif a:symbol[1] == "~"
++ call a:xrefdb.mMarkXRefSyms(self.iState.curfileidx,
++ \a:xrefdb.mAddSym(a:symbol[3:], "i"))
++ elseif a:symbol[1] == "e"
++ let self.iState.curenumidx = a:xrefdb.mAddSym(a:symbol[2:], "e")
++ elseif a:symbol[1] == "g"
++ call a:xrefdb.mAddSym(a:symbol[2:], "g")
++ elseif a:symbol[1] == "@"
++ if a:symbol[2] != ""
++ let self.iState.curfileidx =
++ \a:xrefdb.mAddSym(a:symbol[2:], "F")
++ endif
++ endif
++endfunction
++
++" }}}
++" {{{ CCTree helper library
++let s:CCTreeUtils = {}
++
++function! s:CCTreeUtils.mDetectDB(class)
++ if a:class == s:DBClasses.cctreexref
++ if filereadable(g:CCTreeDb)
++ return g:CCTreeDb
++ endif
++ elseif a:class == s:DBClasses.cscopeid
++ if filereadable(g:CCTreeCscopeDb)
++ return g:CCTreeCscopeDb
++ endif
++ endif
++ return ''
++endfunction
++
++function! s:CCTreeUtils.mFilter(lines, filtercmd) dict
++ let retlst = []
++ let progr = len(a:lines)/100
++ let pBar = s:ProgressBarNumeric.mCreate(len(a:lines), "items")
++ while len(a:lines) > 0
++ if progr <= len(a:lines)
++ let tmplist = remove(a:lines, 0, progr)
++ else
++ let tmplist = remove(a:lines, 0, len(a:lines)-1)
++ endif
++ call filter(tmplist, a:filtercmd)
++ call pBar.mTick(progr)
++ call extend(retlst, tmplist)
++ endwhile
++ call pBar.mDone()
++ return retlst
++endfunction
++
++function! s:CCTreeUtils.mWarningPrompt(msg) dict
++ echohl WarningMsg
++ let a = input(s:pluginname. ": ". a:msg)
++ echohl None
++endfunction
++
++function! s:CCTreeUtils.mWarningMsg(msg) dict
++ echohl WarningMsg
++ echomsg s:pluginname. ": ". a:msg
++ echohl None
++endfunction
++
++function! s:CCTreeUtils.mInfoMsg(msg) dict
++ echohl Title
++ echomsg s:pluginname. ": ". a:msg
++ echohl None
++endfunction
++
++function! s:CCTreeUtils.mWrite(msg) dict
++ echo s:pluginname. ": ". a:msg
++endfunction
++
++" }}}
++" {{{ CCTree DB management
++let s:CCTreeXrefDbEntry = {
++ \ 'type': '',
++ \ 'fname' : '',
++ \ 'fsize' : 0,
++ \ 'fdate' : 0
++ \}
++
++function! s:CCTreeXrefDbEntry.mCreate(fname, type) dict
++ let xrefdbent = deepcopy(s:CCTreeXrefDbEntry)
++ unlet xrefdbent.mCreate
++
++ let xrefdbent.type = a:type
++ let xrefdbent.fname = simplify(getcwd().'/'.a:fname)
++ let xrefdbent.fsize = getfsize(a:fname)
++ let xrefdbent.fdate = strftime("%c", getftime(a:fname))
++ return xrefdbent
++endfunction
++
++let s:CCTreeDBList = {
++ \'loadedDBs' : []
++ \ }
++
++function! s:CCTreeDBList.mCreate() dict
++ let dbList = deepcopy(s:CCTreeDBList)
++ unlet dbList.mCreate
++
++ return dbList
++endfunction
++
++function! s:CCTreeDBList.mShowLoaded() dict
++ let i = 1
++ call s:CCTreeUtils.mWrite(s:pluginname.": List of loaded cscope databases")
++ call s:CCTreeUtils.mWrite("---------------------------------------")
++ for aDBEnt in self.loadedDBs
++ call s:CCTreeUtils.mWrite(i." ".aDBEnt.fname. " ".
++ \ " (".aDBEnt.type.") ".
++ \ aDBEnt.fsize. " bytes ".
++ \ aDBEnt.fdate)
++ let i = i + 1
++ endfor
++endfunction
++
++function! s:CCTreeDBList.mClearAll() dict
++ let self.loadedDBs = []
++endfunction
++
++function! s:CCTreeDBList.mIsEmpty() dict
++ if empty(self.loadedDBs)
++ return s:CCTreeRC.True
++ endif
++ return s:CCTreeRC.False
++endfunction
++
++" Load the cscope db into the global cctree xref db
++function! s:CCTreeDBList.mCreateDbLoaderAndReader(dbName, dbclass, storageclass) dict
++ let dbUser = s:CCTreeCmdLine.mInputDBName('Load', a:dbName, a:dbclass)
++ if dbUser == ''
++ call s:CCTreeUtils.mWarningMsg('Filename required')
++ "User cancel, do nothing
++ return
++ endif
++
++ " Create generic Db loader object
++ if a:storageclass == s:DBStorage.disk
++ let gDbLdr = s:XRefDiskDbLdr.mCreate(dbUser)
++ elseif a:storageclass == s:DBStorage.memory
++ let gDbLdr = s:XRefMemDbLdr.mCreate(dbUser)
++ endif
++
++ if type(gDbLdr) != type({})
++ call s:CCTreeUtils.mWarningMsg(a:dbclass.' database ' . a:dbName .
++ \ ' not found.')
++ return s:CCTreeRC.Error
++ endif
++
++ " Create new DB reader object
++ if a:storageclass == s:DBStorage.memory
++ if a:dbclass == s:DBClasses.cscopeid
++ let gDbRdr = s:CscopeDbRdr.mCreate(dbUser, g:CCTreeEnhancedSymbolProcessing)
++ elseif a:dbclass == s:DBClasses.cctreexref
++ let gDbRdr = s:CCTreeTagDbRdr.mCreate(dbUser)
++ else
++ return s:CCTreeRC.Error
++ endif
++ if gDbLdr.mParseDbHeader(gDbRdr) == s:CCTreeRC.Error
++ call s:CCTreeUtils.mWarningMsg(gDbRdr.class.' database ' . a:dbName .
++ \ ' format is not parseable.')
++ return s:CCTreeRC.Error
++ endif
++ else
++ let gDbRdr = {}
++ endif
++
++ return {'loader': gDbLdr, 'reader': gDbRdr}
++endfunction
++
++function! s:CCTreeDBList.mAddDbToList(dbName, type)
++ let aDBEnt = s:CCTreeXrefDbEntry.mCreate(a:dbName, a:type)
++ call add(self.loadedDBs, aDBEnt)
++endfunction
++
++" Merge the cscope db into the global cctree xref db
++function! s:CCTreeDBList.mMerge(dbName, xRefDb, class)
++ " Check if merge can be supported
++ if self.loadedDBs[0].type == s:DBStorage.disk
++ call s:CCTreeUtils.mInfoMsg("Cannot merge with DBs traced from disk")
++ return
++ endif
++ " Create db loader, reader
++ let gObjs = self.mCreateDbLoaderAndReader(a:dbName, a:class, s:DBStorage.memory)
++
++ if type(gObjs) == type({})
++ " if Db is compressed, then we need to compress our symbols first
++ let swatch = s:StopWatch.mCreate()
++ if self.mLoadDB(gObjs.loader, a:xRefDb,
++ \ gObjs.reader) != s:CCTreeRC.Error
++ call self.mAddDbToList(gObjs.loader.fDBName, gObjs.loader.class)
++ let msg = "Done merging databases. xRef Symbol Count: "
++ \.a:xRefDb.mGetSymbolCount()
++ \.". Time taken: ".swatch.mGetText()." secs"
++ call s:CCTreeUtils.mInfoMsg(msg)
++ endif
++ " Load will auto decompress the symbols
++ endif
++endfunction
++
++" Load the cscope db into the global cctree xref db
++function! s:CCTreeDBList.mAddNew(dbName, xRefDb, dbclass, storageclass)
++ " Create db loader, reader
++ let gObjs = self.mCreateDbLoaderAndReader(a:dbName, a:dbclass, a:storageclass)
++
++ if type(gObjs) == type({})
++ let swatch = s:StopWatch.mCreate()
++ if self.mLoadDB(gObjs.loader, a:xRefDb,
++ \ gObjs.reader) != s:CCTreeRC.Error
++ call self.mAddDbToList(gObjs.loader.fDBName, gObjs.loader.class)
++ call swatch.mSnapElapsed()
++ if a:storageclass == s:DBStorage.memory
++ let msg = "Done loading database. xRef Symbol Count: "
++ \.a:xRefDb.mGetSymbolCount()
++ \.". Time taken: ".swatch.mGetText()." secs"
++ else
++ let msg = "Disk Xref database loaded for tracing"
++ endif
++ call s:CCTreeUtils.mInfoMsg(msg)
++ endif
++ endif
++endfunction
++
++function! s:CCTreeDBList.mLoadDB(gDbLdr, xRefDb, gRdr)
++ let rc = s:CCTreeRC.Success
++ try
++ let swatch = s:StopWatch.mCreate()
++ call s:StatusLine.mInit()
++ " if compression, then we need to compress our symbols first
++ if !empty(a:gRdr) && a:gRdr.mRequirePreProcessing() == s:CCTreeRC.True
++ call s:StatusLine.mSetInfo('Pre-processing existing symbols')
++ call a:xRefDb.mTranslateSymbols(a:gRdr.mGetPreProcessingMaps(),
++ \ a:gRdr.mapPreKeys)
++ endif
++ call garbagecollect()
++ call s:StatusLine.mSetInfo('Loading database')
++ call a:gDbLdr.mLoadFileIntoXRefDb(a:xRefDb, a:gRdr)
++ if !empty(a:gRdr) && a:gRdr.mRequireCleanup() == s:CCTreeRC.True
++ call s:StatusLine.mSetInfo('Symbol clean-up')
++ call a:xRefDb.mCleanSymbols()
++ endif
++ call garbagecollect()
++ if !empty(a:gRdr) && a:gRdr.mRequirePostProcessing() == s:CCTreeRC.True
++ call s:StatusLine.mSetInfo('Post-processing loaded symbols')
++ call a:xRefDb.mTranslateSymbols(a:gRdr.mGetPostProcessingMaps(),
++ \ a:gRdr.mapPostKeys)
++ endif
++ call swatch.mSnapElapsed()
++ " restore normalcy
++ call garbagecollect()
++ redraw
++
++ catch /^Vim:Interrupt$/ " catch interrupts (CTRL-C)
++ call s:CCTreeUtils.mWarningMsg('Loading aborted.')
++ let rc = s:CCTreeRC.Error
++ finally
++ call s:StatusLine.mRestore()
++ endtry
++ return rc
++endfunction
++"}}}
++" {{{ UI Input related
++let s:CCTreeUI = {}
++
++
++function! s:CCTreeUI.mInputDBName(dbName, class, action)
++ let dbUser = a:dbName
++ let dbUser = input(a:action. ' database ('. a:class. '): ', a:dbName, 'file')
++ return dbUser
++endfunction
++" }}}
++" {{{ CCTree Markers
++let s:TreeMarkers_UTF8 = {
++ \ 'splitT' : nr2char(0x251c),
++ \ 'arrowR' : nr2char(0x25c0),
++ \ 'arrowF' : nr2char(0x25B6),
++ \ 'extV' : nr2char(0x2502),
++ \ 'extH': nr2char(0x2500),
++ \ 'depth': nr2char(0x25BC)
++ \}
++
++let s:TreeMarkers_Text = {
++ \ 'splitT' : '+',
++ \ 'arrowF' : '>',
++ \ 'arrowR' : '<',
++ \ 'extV' : '|',
++ \ 'extH': '-',
++ \ 'depth': 'depth:'
++ \}
++
++let s:CCTreeMarkers = {
++ \ 'icons':{}
++ \ }
++function! s:CCTreeMarkers.mCreate() dict
++ let treeMarkers = deepcopy(s:CCTreeMarkers)
++
++ if &encoding == 'utf-8' && g:CCTreeUseUTF8Symbols == 1
++ let treeMarkers.icons = deepcopy(s:TreeMarkers_UTF8)
++ else
++ " default choice
++ let treeMarkers.icons = deepcopy(s:TreeMarkers_Text)
++ endif
++
++ let treeMarkers.icons.arrowSyms = treeMarkers.icons.arrowF . treeMarkers.icons.arrowR
++ let treeMarkers.icons.vertSyms = treeMarkers.icons.splitT . treeMarkers.icons.extV
++
++ return treeMarkers
++endfunction
++
++function! s:CCTreeMarkers.mGetArrow(direction) dict
++ if a:direction == 'p'
++ return self.icons.arrowR
++ elseif a:direction == 'c'
++ return self.icons.arrowF
++ endif
++ return '?'
++endfunction
++" }}}
++" {{{ User key mappings
++let s:CCTreeKeyMappings = {
++ \ 'CTreeF': g:CCTreeKeyTraceForwardTree,
++ \ 'CTreeR': g:CCTreeKeyTraceReverseTree,
++ \ 'CTreeHilight': g:CCTreeKeyHilightTree,
++ \ 'CTreeWSave': g:CCTreeKeySaveWindow,
++ \ 'CTreeWToggle': g:CCTreeKeyToggleWindow,
++ \ 'CTreeCompress': g:CCTreeKeyCompressTree,
++ \ 'CTreeDepthMinus': g:CCTreeKeyDepthMinus,
++ \ 'CTreeDepthPlus': g:CCTreeKeyDepthPlus
++ \}
++" }}}
++" {{{ CCTreeWindow
++let s:CCTreeWindow = {
++ \ 'hiKeyword': '',
++ \ 'hiKeywordLine':'',
++ \ 'lastbufname':'',
++ \ 'treeMarkers': s:CCTreeMarkers.mCreate()}
++
++function! s:CCTreeWindow.mCreate() dict
++ let win = deepcopy(s:CCTreeWindow)
++ unlet win.mCreate
++
++ return win
++endfunction
++
++function! s:CCTreeWindow.mLeave()
++ call s:FindOpenWindow(self.lastbufname)
++endfunction
++
++
++" Definition of a keyword...
++let s:CCTreeKeywordRegEx = '[A-Za-z0-9_\\\.\/]\+'
++
++function! s:CCTreeWindow.mGetKeywordAtCursor() dict
++ let curline = line(".")
++ let self.hiKeyword = ''
++ if foldclosed(curline) == -1
++ let curkeyword = matchstr(getline("."), s:CCTreeKeywordRegEx)
++ if curkeyword != ''
++ if curkeyword != self.hiKeyword || curline != self.hiKeywordLine
++ let self.hiKeyword = curkeyword
++ let self.hiKeywordLine = line(".")
++ return s:CCTreeRC.Success
++ endif
++ else
++ return s:CCTreeRC.Error
++ endif
++ endif
++ if self.hiKeyword == ''
++ return s:CCTreeRC.Error
++ endif
++ return s:CCTreeRC.Success
++endfunction
++
++function! s:CCTreeWindow.mBuildStatusLine(pState, title, items)
++ let needcomma = 0
++ let rtitle = a:title. ' ('. a:pState.keyword
++ let rtitle .= '['
++ if has_key(a:items, "depth")
++ let rtitle .= self.treeMarkers.icons.depth
++ let rtitle .= a:pState.depth
++ let needcomma = 1
++ endif
++ if has_key(a:items, "direction")
++ if needcomma == 1
++ let rtitle .= ','
++ endif
++
++ let rtitle .= self.treeMarkers.mGetArrow(a:pState.direction)
++ endif
++ let rtitle .= '])'
++
++ return rtitle
++endfunction
++
++function! CCTreeWindowPreviewStatusLine()
++ " get global
++ " this is a hack
++ let pState = s:CCTreeGlobals.PreviewState
++ let tMarkers = s:CCTreeGlobals.Window.treeMarkers
++
++ return s:CCTreeGlobals.Window.mBuildStatusLine(
++ \ s:CCTreeGlobals.PreviewState,
++ \ s:windowtitle,
++ \ {'depth':''}
++ \)
++endfunction
++
++function! s:CCTreeWindow.mPreviewSave(savetitle) dict
++ if s:FindOpenWindow(s:windowtitle) == 1
++ setlocal modifiable
++ call self.mClearMarks(b:displayTree)
++ setlocal nomodifiable
++ setlocal statusline=%-F
++ silent! exec ":f ". a:savetitle
++ return s:CCTreeRC.Success
++ endif
++ return s:CCTreeRC.Error
++endfunction
++
++function! s:CCTreeWindow.mIsOpen() dict
++ if s:FindOpenBuffer(s:windowtitle) > 0
++ return s:CCTreeRC.True
++ endif
++ return s:CCTreeRC.False
++endfunction
++
++function! s:CCTreeWindow.mClose() dict
++ if s:FindOpenWindow(s:windowtitle) == 1
++ silent! q!
++ endif
++endfunction
++
++function! s:CCTreeWindow.mDisplayToggle() dict
++ if s:FindOpenWindow(s:windowtitle) == 1
++ silent! hide
++ else
++ let winbufnr = s:FindOpenBuffer(s:windowtitle)
++ if winbufnr > 0
++ call self.mEnter()
++ silent! exec "buf ".winbufnr
++ call self.mResize()
++ silent! wincmd p
++ else
++ call s:CCTreeUtils.mWarningMsg(" No active window found.")
++ endif
++ endif
++endfunction
++
++function! s:CCTreeWindow.mResize() dict
++ if g:CCTreeWindowVertical == 1
++ if g:CCTreeWindowWidth == -1
++ exec "vertical resize ". b:maxwindowlen
++ else
++ exec "vertical resize ". g:CCTreeWindowWidth
++ endif
++ else
++ if g:CCTreeWindowHeight != -1
++ let &winminheight = g:CCTreeWindowHeight
++ exec "resize".g:CCTreeWindowHeight
++ endif
++ endif
++endfunction
++
++function! s:CCTreeWindow.mDisplayTree(atree, direction) dict
++ let incctreewin = 1
++ if (bufname('%') != s:windowtitle)
++ let incctreewin = self.mEnter()
++ endif
++
++ setlocal modifiable
++ silent 1,$d
++ let b:maxwindowlen = g:CCTreeWindowMinWidth
++ let b:displayTree = s:DisplayTree.mCreate(a:atree,
++ \ a:direction, self.treeMarkers)
++ call s:CCTreeDisplay.mPopulateTreeInCurrentBuffer(b:displayTree)
++ exec "normal gg"
++
++ " Need to force this again
++ let &l:foldlevel=g:CCTreeMinVisibleDepth
++ setlocal nomodifiable
++ call self.mResize()
++ if (incctreewin == 0)
++ call s:CCTreeWindow.mLeave()
++ endif
++endfunction
++
++function! s:CCTreeWindow.mExtractTreeSymbols(dtree)
++ let symlist = {}
++ for aentry in a:dtree.entries
++ let symlist[aentry.symbol] = 0
++ endfor
++ return symlist
++endfunction
++
++function! s:CCTreeWindow.mEnter() dict
++ let self.lastbufname = bufname("%")
++ let foundWindow = s:FindOpenWindow(s:windowtitle)
++ if foundWindow == 0
++ if g:CCTreeWindowVertical == 1
++ exec g:CCTreeOrientation." vsplit ". s:windowtitle
++ set winfixwidth
++ else
++ exec g:CCTreeOrientation." split ". s:windowtitle
++ set winfixheight
++ endif
++
++ setlocal buftype=nofile
++ setlocal bufhidden=hide
++ setlocal noswapfile
++ setlocal nonumber
++ setlocal nowrap
++ setlocal nobuflisted
++
++ if s:CCTreeUseConceal == 1
++ setlocal cole=3
++ setlocal cocu=nv
++ endif
++
++ setlocal statusline=%=%{CCTreeWindowPreviewStatusLine()}
++
++ call self.mInitSyntax(self.treeMarkers.icons)
++ let cpo_save = &cpoptions
++ set cpoptions&vim
++
++ call s:CCTreeBufferKeyMappingsCreate(s:CCTreeKeyMappings)
++
++ command! -buffer -nargs=0 CCTreeWindowHiCallTree
++ \ call s:CCTreeGlobals.mCursorHoldHandleEvent()
++
++ exec 'nnoremap <buffer> <silent> '.s:CCTreeKeyMappings.CTreeHilight.
++ \' :CCTreeWindowHiCallTree<CR>'
++ exec 'nnoremap <buffer> <silent> '.s:CCTreeKeyMappings.CTreeCompress.
++ \ ' :2,.foldclose!<CR>zv'
++
++ nnoremap <buffer> <silent> <C-p> :CCTreePreviewBufferUsingTag<CR>
++ nnoremap <buffer> <silent> <CR> :CCTreeLoadBufferUsingTag<CR>
++ nnoremap <buffer> <silent> <2-LeftMouse> :CCTreeLoadBufferUsingTag<CR>
++
++ let &cpoptions = cpo_save
++ endif
++ setlocal foldmethod=expr
++ setlocal foldexpr=CCTreeFoldExpr(getline(v:lnum))
++ setlocal foldtext=CCTreeFoldText()
++ let &l:foldlevel=g:CCTreeMinVisibleDepth
++
++ return foundWindow
++endfunction
++" }}}
++" {{{ Dynamic call-tree highlighting using
++" syntax highlight tricks
++"
++" There are 3 types of lines, marked with the start character [\s, !, #]
++" Also @ is used to mark the path that is going up
++
++function! s:CCTreeWindow.mMarkCallTree(dtree, keyword) dict
++ let declevel = -1
++ let treelst = a:dtree.entries
++ let curLine = line(".")
++
++ let declevel = treelst[curLine-1].level
++
++ let targetlevel = declevel
++ for idx in range(curLine, 1, -1)
++ let aentry = treelst[idx-1]
++
++
++ " Find our keyword
++ let linemarker = 0
++ " Skip folds
++ if declevel != -1 && foldclosed(idx) == -1
++ if targetlevel == aentry.level
++ let linemarker = 1
++ let targetlevel -= 1
++ endif
++ let aline = a:dtree.mGetNotationalTxt(aentry.level, targetlevel+1, linemarker, 1)
++ \ . aentry.symbol
++ call setline(idx, aline)
++ endif
++ endfor
++endfunction
++
++function! s:CCTreeWindow.mClearMarks(dtree) dict
++ for idx in range(line(".")+1, line("$"))
++ let breakout = (getline(idx)[0] !~ "[!#]")
++ if breakout == 1
++ break
++ endif
++ let aentry = a:dtree.entries[idx-1]
++ let aline = a:dtree.mGetNotationalTxt(aentry.level, -1, 0, 0)
++ \ . aentry.symbol
++ call setline(idx, aline)
++ endfor
++endfunction
++
++function! s:CCTreeWindow.mInitSyntax(markers) dict
++ "syntax match CCTreePathMark /\s[|+]/ contained
++ exec 'syntax match CCTreePathMark /\s['. a:markers.vertSyms . ']/ contained'
++ "syntax match CCTreeArrow /-*[<>]/ contained
++ exec 'syntax match CCTreeArrow /'.a:markers.extH.'*['. a:markers.arrowSyms .']/ contained'
++
++ syntax match CCTreeSymbol / [A-Za-z0-9_\.\\\/]\+/ contained
++ syntax region CCTreeSymbolLine start="^\s" end="$" contains=CCTreeArrow,CCTreePathMark,CCTreeSymbol oneline
++
++ "syntax match CCTreeHiArrow /-*[<>]/ contained
++ exec 'syntax match CCTreeHiArrow /'. a:markers.extH .'*['. a:markers.arrowSyms .']/ contained'
++ syntax match CCTreeHiSymbol / [A-Za-z0-9_\.\\\/]\+/ contained
++
++ "syntax match CCTreeHiPathMark /\s[|+]/ contained
++ exec 'syntax match CCTreeHiPathMark /\s[' . a:markers.vertSyms . ']/ contained'
++
++ if s:CCTreeUseConceal == 1
++ syntax match CCTreeMarkExcl /^[!#]/ contained conceal
++ syntax match CCTreeMarkTilde /@/ contained conceal
++ else
++ syntax match CCTreeMarkExcl /^[!#]/ contained
++ syntax match CCTreeMarkTilde /@/ contained
++ endif
++ "syntax region CCTreeUpArrowBlock start="@" end=/[|+]/ contains=CCTreeMarkTilde contained oneline
++ exec 'syntax region CCTreeUpArrowBlock start="@" end=/['. a:markers.vertSyms .']/ contains=CCTreeMarkTilde contained oneline'
++
++ syntax region CCTreeHiSymbolLine start="!" end="$" contains=CCTreeMarkExcl,
++ \ CCTreeUpArrowBlock,
++ \ CCTreeHiSymbol,CCTreeHiArrow,CCTreeHiPathMark oneline
++
++ syntax region CCTreeMarkedSymbolLine start="#" end="$" contains=CCTreeMarkExcl,
++ \ CCTreeMarkTilde,CCTreePathMark,
++ \ CCTreeArrow,CCTreeSymbol,CCTreeUpArrowBlock oneline
++endfunction
++
++
++" }}}
++" {{{ CCTreeDisplay
++
++let s:CCTreeDisplay = {}
++
++function! s:CCTreeDisplay.mPopulateTreeInCurrentBuffer(dtree)
++ let linelist = []
++ for aentry in a:dtree.entries
++ let aline = a:dtree.mGetNotationalTxt(aentry.level, -1, 0, 0)
++ \ . aentry.symbol
++ let len = s:Utils.mStrlenEx(aline)
++ let b:maxwindowlen = max([len+1, b:maxwindowlen])
++ call add(linelist, aline)
++ endfor
++ call setline(".", linelist)
++endfunction
++
++
++
++" }}}
++" {{{ CCTree command line interface
++let s:CCTreeCmdLine = {}
++
++
++function! s:CCTreeCmdLine.mLoadDBFromDisk(dbName) dict
++ call s:CCTreeGlobals.mUnLoadDBs()
++ let s:CCTreeGlobals.XRefDb = s:XRefDiskDb.mCreate()
++ call s:CCTreeGlobals.DbList.mAddNew(a:dbName,
++ \ s:CCTreeGlobals.XRefDb, s:DBClasses.cctreexref, "Disk")
++endfunction
++
++" Unload current db's and load new one
++" There is no selective unloading
++function! s:CCTreeCmdLine.mLoadDB(db_name, class) dict
++ call s:CCTreeGlobals.mSetupEncodingChangeAutoCmd(0)
++ call s:CCTreeGlobals.mUnLoadDBs()
++ let s:CCTreeGlobals.XRefDb = s:xRefMemDb.mCreate()
++ call s:CCTreeGlobals.DbList.mAddNew(a:db_name,
++ \ s:CCTreeGlobals.XRefDb, a:class, s:DBStorage.memory)
++ call s:CCTreeGlobals.mSetupAutoCmds()
++endfunction
++
++function! s:CCTreeCmdLine.mInputDBName(action, dbName, class) dict
++ if a:dbName == ''
++ let dbUser = s:CCTreeUI.mInputDBName(
++ \ s:CCTreeUtils.mDetectDB(a:class),
++ \ a:class, a:action)
++ else
++ let dbUser = a:dbName
++ endif
++ return dbUser
++endfunction
++
++function! s:CCTreeCmdLine.mSaveDB(dbName, class) dict
++ let dbUser = self.mInputDBName('Save', a:dbName, a:class)
++ if dbUser == ''
++ call s:CCTreeUtils.mWarningMsg('Filename required')
++ return
++ endif
++ call s:CCTreeGlobals.Window.mClose()
++ call s:CCTreeGlobals.mSetupEncodingChangeAutoCmd(0)
++ call s:CCTreeGlobals.mWriteXRefDbToFile(dbUser)
++ call s:CCTreeGlobals.mSetupAutoCmds()
++ call s:CCTreeGlobals.mUpdateForCurrentSymbol()
++endfunction
++
++" Merge current db with new one
++function! s:CCTreeCmdLine.mMergeDB(db_name, class) dict
++ "call s:CCTreeGlobals.Window.mClose()
++ call s:CCTreeGlobals.DbList.mMerge(a:db_name, s:CCTreeGlobals.XRefDb, a:class)
++endfunction
++
++
++" }}}
++" {{{ CCTree Buffer mappings
++function! s:CCTreeWindowGetHiKeyword()
++ let keyw = expand("<cword>")
++ let keyf = expand("<cfile>")
++
++ let syms = s:CCTreeGlobals.mGetPreviewTreeSymbols()
++
++ if keyw != keyf
++ if has_key(syms, keyf)
++ return keyf
++ elseif has_key(syms, keyw)
++ return keyw
++ endif
++ else
++ return keyw
++ endif
++ return ''
++endfunction
++
++
++" Keymappings used common to source files and CCTree window
++function! s:CCTreeBufferKeyMappingsCreate(kmaps)
++ let func_expr = '<SNR>'.s:sid.'CCTreeWindowGetHiKeyword()'
++ exec 'nnoremap <buffer> <silent> '.a:kmaps.CTreeR.' :CCTreeTraceReverse <C-R>='.
++ \ func_expr.'<CR><CR>'
++ exec 'nnoremap <buffer> <silent> '.a:kmaps.CTreeF.' :CCTreeTraceForward <C-R>='
++ \ .func_expr.'<CR><CR>'
++
++ exec 'nnoremap <silent> '.a:kmaps.CTreeWSave. ' :CCTreeWindowSaveCopy<CR>'
++ exec 'nnoremap <silent> '.a:kmaps.CTreeWToggle. ' :CCTreeWindowToggle<CR>'
++
++ exec 'nnoremap <buffer> <silent> '.a:kmaps.CTreeDepthPlus.
++ \ ' :CCTreeRecurseDepthPlus<CR>'
++ exec 'nnoremap <buffer> <silent> '.a:kmaps.CTreeDepthMinus.
++ \ ' :CCTreeRecurseDepthMinus<CR>'
++endfunction
++
++augroup CCTreeMaps
++au!
++" Header files get detected as cpp?
++" This is a bug in Vim 7.2, a patch needs to be applied to the runtime c
++" syntax files
++" For now, use this hack to make *.h files work
++autocmd FileType * if &ft == 'c'|| &ft == 'cpp' |
++ \ call s:CCTreeBufferKeyMappingsCreate(s:CCTreeKeyMappings)|
++ \ endif
++augroup END
++
++
++" }}}
++" {{{ Tree building
++
++let s:DisplayTreeEntry = {
++ \ 'symbol': "",
++ \ 'level': -1
++ \ }
++
++function! s:DisplayTreeEntry.mCreate(sym, level) dict
++ let te = deepcopy(s:DisplayTreeEntry)
++ let te.symbol = a:sym
++ let te.level = a:level
++ unlet te.mCreate
++
++ return te
++endfunction
++
++let s:calltreemaxdepth = 10
++let s:DisplayTree = {
++ \ 'entries': [],
++ \ 'levelMaxLen': repeat([255], s:calltreemaxdepth),
++ \ 'notTxt': {}
++ \ }
++
++function! s:DisplayTree.mCreate(calltree, direction, markers) dict
++ let dt = deepcopy(s:DisplayTree)
++ call dt.mBuildTreeForLevel(a:calltree, 0)
++ call dt.mBuildNotationalTxtMarkers(a:direction, a:markers.icons)
++
++ unlet dt.mBuildTreeForLevel
++ unlet dt.mCreate
++
++ return dt
++endfunction
++
++function! s:DisplayTree.mBuildTreeForLevel(ctree, level)
++ if !has_key(a:ctree, 'symbol')
++ return
++ endif
++
++ if g:CCTreeDisplayMode == 3
++ let curlevellen = strlen(a:ctree.symbol) + a:level + 2
++ let self.levelMaxLen[a:level] = min([self.levelMaxLen[a:level],
++ \ curlevellen])
++ endif
++
++
++ let aentry = s:DisplayTreeEntry.mCreate(a:ctree.symbol, a:level)
++ call add(self.entries, aentry)
++
++ if has_key(a:ctree, 'childlinks')
++ for alink in a:ctree['childlinks']
++ call self.mBuildTreeForLevel(alink, a:level+1)
++ endfor
++ endif
++endfunction
++
++
++function! s:DisplayTree.mBuildNotationalTxtMarkers(direction, markerSyms) dict
++ " REVISIT
++ if a:direction == 'p'
++ let directiontxt = a:markerSyms.arrowR . " "
++ elseif a:direction == 'c'
++ let directiontxt = a:markerSyms.arrowF . " "
++ endif
++
++
++ let self.notTxt.arrowHead = a:markerSyms.splitT
++ let self.notTxt.arrow = directiontxt
++ let self.notTxt.arrowLead = a:markerSyms.extH
++ let self.notTxt.sep = a:markerSyms.extV
++ if s:CCTreeUseConceal == 1
++ let concealspace = " "
++ else
++ let concealspace = ""
++ endif
++
++ let self.notTxt.symHighlighter= concealspace . "@"
++
++ let self.notTxt.hiSymbolMarker = "!".concealspace
++ let self.notTxt.hiBranchMarker = "#".concealspace
++
++ let self.notTxt.cache = {}
++
++endfunction
++
++function! s:DisplayTree.mGetNotationalTxt(depth, hiDepth, hiSym, hiPath) dict
++ let notkey = join(a:000, ":")
++ if has_key(self.notTxt.cache,notkey) == 1
++ return self.notTxt.cache[notkey]
++ else
++ return self.mBuildNotationalTxt(a:depth, a:hiDepth, a:hiSym, a:hiPath)
++ endif
++endfunction
++
++function! s:DisplayTree.mBuildNotationalTxt(depth, hiDepth, hiSym, hiPath) dict
++ let hiBranch = 0
++ let curDepth = a:depth
++ if 0
++ let Aspace = "A"
++ let Bspace = "B"
++ let Cspace = "C"
++ let Sspace = "S"
++ let Xspace = "X"
++ let Zspace = "Z"
++ let Fspace = "1"
++ else
++ let Aspace = " "
++ let Bspace = " "
++ let Cspace = " "
++ let Sspace = " "
++ let Xspace = " "
++ let Zspace = " "
++ let Fspace = " "
++ endif
++
++ if g:CCTreeDisplayMode == 1
++ let arrowLeads = self.notTxt.arrowLead
++ elseif g:CCTreeDisplayMode >= 2
++ let arrowLeads = repeat(self.notTxt.arrowLead, a:depth)
++ endif
++
++ let indentSpace = ""
++ if g:CCTreeDisplayMode == 2
++ if curDepth > 0
++ let indentSpace = repeat(Aspace, curDepth)
++ endif
++ elseif g:CCTreeDisplayMode == 3
++ if curDepth > 0
++ let indentSpace = repeat(Aspace, self.levelMaxLen[curDepth-1])
++ endif
++ endif
++ let notTxt = self.notTxt.arrowHead. arrowLeads . self.notTxt.arrow
++ if a:hiDepth == a:depth
++ let notTxt = indentSpace . self.notTxt.symHighlighter . notTxt
++ let hiBranch = 1
++ else
++ let notTxt = indentSpace. Cspace. notTxt
++ endif
++ let curDepth -= 1
++
++ let indentSpace = ""
++ while (curDepth > 0)
++ if g:CCTreeDisplayMode == 2
++ let indentSpace = repeat(Bspace, curDepth)
++ elseif g:CCTreeDisplayMode == 3
++ let indentSpace = repeat(Bspace, self.levelMaxLen[curDepth-1])
++ endif
++ let notTxt = self.notTxt.sep . notTxt
++ if a:hiDepth == curDepth && a:hiPath == 1
++ let notTxt = indentSpace . self.notTxt.symHighlighter . notTxt
++ let hiBranch = 1
++ else
++ let notTxt = indentSpace. Cspace. notTxt
++ endif
++ let curDepth -= 1
++ endwhile
++ if curDepth == 0
++ " curdepth is 0
++ if a:hiDepth == curDepth && a:hiPath == 1
++ let notTxt = self.notTxt.symHighlighter . notTxt
++ let hiBranch = 1
++ else
++ let notTxt = Fspace . notTxt
++ endif
++ let curDepth -= 1
++ endif
++ " adjust space
++ if a:depth > 0
++ let notTxt = Xspace . notTxt
++ endif
++ if hiBranch == 1
++ if a:hiSym == 1
++ let notTxt = self.notTxt.hiSymbolMarker . notTxt
++ else
++ let notTxt = self.notTxt.hiBranchMarker . notTxt
++ endif
++ else
++ let notTxt = Sspace . notTxt
++ endif
++ return notTxt
++endfunction
++
++"}}}
++" {{{ Preview window Folding
++function! CCTreeFoldExpr(line)
++ if !exists('b:displayTree') || v:lnum > len(b:displayTree.entries)
++ return 0
++ endif
++
++ let lvl = b:displayTree.entries[v:lnum-1].level
++ if lvl == 0
++ let lvl = 1
++ endif
++ return '>'.lvl
++endfunction
++
++
++function! CCTreeFoldText()
++ if s:CCTreeUseConceal == 1
++ let line = substitute(getline(v:foldstart), '[!@#]', '' , 'g')
++ else
++ let line = substitute(getline(v:foldstart), '[!@#]', ' ' , 'g')
++ endif
++ return line. " (+". (v:foldend - v:foldstart).
++ \ ')'. repeat(" ", winwidth(0))
++endfunction
++" }}}
++" {{{ Syntax coloring definitions
++"Standard display
++highlight default link CCTreeSymbol Function
++highlight default link CCTreeMarkers LineNr
++highlight default link CCTreeArrow CCTreeMarkers
++highlight default link CCTreePathMark CCTreeArrow
++highlight default link CCTreeHiPathMark CCTreePathMark
++
++" highlighted display
++highlight default link CCTreeHiKeyword Macro
++highlight default link CCTreeHiSymbol TODO
++highlight default link CCTreeHiMarkers NonText
++highlight default link CCTreeHiArrow CCTreeHiMarkers
++highlight default link CCTreeUpArrowBlock CCTreeHiArrow
++
++highlight default link CCTreeMarkExcl Ignore
++highlight default link CCTreeMarkTilde Ignore
++"}}}
++" {{{ CCTree global state
++
++let s:CCTreePreviewState = {
++ \ 'keyword':'',
++ \ 'direction': '',
++ \ 'depth' : ''
++ \}
++
++function! s:CCTreePreviewState.mCreate()
++ let state = deepcopy(s:CCTreePreviewState)
++ unlet state.mCreate
++
++ return state
++endfunction
++
++function! s:CCTreePreviewState.mStore(symbol, direction)
++ let self.keyword = a:symbol
++ let self.direction = a:direction
++endfunction
++" }}}
++" {{{ CCTree global objects
++
++let s:CCTreeGlobals = {
++ \ 'XRefDb': {},
++ \ 'DbList': s:CCTreeDBList.mCreate(),
++ \ 'PreviewState': s:CCTreePreviewState.mCreate(),
++ \ 'Window': s:CCTreeWindow.mCreate()
++ \}
++
++let g:CCTreeGlobals = s:CCTreeGlobals
++
++function! s:CCTreeGlobals.mEnable(opt) dict
++ if (has_key(s:CCTreeOptions, a:opt))
++ call s:CCTreeOptions[a:opt](1)
++ else
++ call s:CCTreeUtils.mWarningMsg('Invalid option')
++ endif
++endfunction
++
++function! s:CCTreeGlobals.mDisable(opt) dict
++ if (has_key(s:CCTreeOptions, a:opt))
++ call s:CCTreeOptions[a:opt](0)
++ else
++ call s:CCTreeUtils.mWarningMsg('Invalid option')
++ endif
++endfunction
++
++function! s:CCTreeGlobals.mToggle(opt) dict
++ if (has_key(s:CCTreeOptions, a:opt))
++ call s:CCTreeOptions[a:opt](-1)
++ else
++ call s:CCTreeUtils.mWarningMsg('Invalid option')
++ endif
++endfunction
++
++function! s:CCTreeGlobals.mGetSymNames(lead) dict
++ call self.XRefDb.mInitState()
++ let syms = self.XRefDb.mGetSymbolNames(a:lead)
++ call self.XRefDb.mRestoreState()
++ return syms
++endfunction
++
++
++function! s:CCTreeGlobals.mGetCallsForSymbol(name, depth, direction) dict
++ let pbar = s:ProgressBarRoll.mCreate(['-','\','|','/'], '*')
++ call s:StatusLine.mSetInfo('Building ')
++ redrawstatus!
++ " Create tracer
++ let xtracer = s:XRefTracer.mCreate(self.XRefDb)
++ call xtracer.mInitTracing()
++ let symid = self.XRefDb.mGetSymbolIdFromName(a:name)
++ let xrefs = xtracer.mBuildForSymbol(symid,
++ \ a:depth, self.PreviewState.depth, a:direction, pbar)
++ call xtracer.mDoneTracing()
++ return xrefs
++endfunction
++
++function! s:CCTreeGlobals.mShowLoadedDBs() dict
++ call self.DbList.mShowLoaded()
++endfunction
++
++function! s:CCTreeGlobals.mUnLoadDBs() dict
++ call s:CCTreeGlobals.Window.mClose()
++ if !empty(s:CCTreeGlobals.XRefDb)
++ call s:CCTreeGlobals.XRefDb.mClear()
++ endif
++ call s:CCTreeGlobals.DbList.mClearAll()
++endfunction
++
++function! s:CCTreeGlobals.mSetPreviewState(name, depth, direction) dict
++ let self.PreviewState.keyword = a:name
++ let self.PreviewState.direction = a:direction
++ let self.PreviewState.depth = a:depth
++endfunction
++
++function! s:CCTreeGlobals.mUpdateForCurrentSymbol() dict
++ if self.DbList.mIsEmpty() == s:CCTreeRC.True
++ return s:CCTreeRC.Error
++ endif
++ if self.PreviewState.keyword != ''
++ let swatch = s:StopWatch.mCreate()
++ " Move this function to globals?
++ call s:StatusLine.mInit()
++ let atree = self.mGetCallsForSymbol(self.PreviewState.keyword,
++ \ 0,
++ \ self.PreviewState.direction)
++ call s:StatusLine.mRestore()
++ call self.Window.mDisplayTree(atree, self.PreviewState.direction)
++
++ call swatch.mSnapElapsed()
++ endif
++endfunction
++
++
++function! s:CCTreeGlobals.mGetPreviewTreeSymbols()
++ " REVIST
++ if exists('b:displayTree')
++ return self.Window.mExtractTreeSymbols(b:displayTree)
++ end
++ return {}
++endfunction
++
++function! s:CCTreeGlobals.mSanitizeCallDepth() dict
++ let error = 0
++ if self.PreviewState.depth >= s:calltreemaxdepth
++ self.PreviewState.depth = s:calltreemaxdepth
++ let error = 1
++ elseif self.PreviewState.depth < 1
++ let self.PreviewState.depth = 1
++ let error = 1
++ endif
++
++ if error == 1
++ call s:CCTreeUtils.mWarningMsg('Depth out of bounds')
++ endif
++ return error
++endfunction
++
++function! s:CCTreeGlobals.mRecursiveDepthIncrease() dict
++ let self.PreviewState.depth += 1
++ if self.mSanitizeCallDepth() == 0
++ call self.mUpdateForCurrentSymbol()
++ endif
++endfunction
++
++function! s:CCTreeGlobals.mRecursiveDepthDecrease() dict
++ let self.PreviewState.depth -= 1
++ if self.mSanitizeCallDepth() == 0
++ call self.mUpdateForCurrentSymbol()
++ endif
++endfunction
++
++function! s:CCTreeGlobals.mDisplayToggle() dict
++ call self.Window.mDisplayToggle()
++endfunction
++
++function! s:CCTreeGlobals.mSetupAutoCmds() dict
++ augroup CCTreeGeneral
++ au!
++ augroup END
++ call s:CCTreeGlobals.mSetupCursorMoveAutoCmd(g:CCTreeHilightCallTree)
++ call s:CCTreeGlobals.mSetupEncodingChangeAutoCmd(g:CCTreeUseUTF8Symbols)
++endfunction
++
++function! s:CCTreeGlobals.mSetupCursorMoveAutoCmd(enable) dict
++ if a:enable == 1
++ exec 'autocmd CCTreeGeneral CursorMoved '.s:windowtitle.' call s:CCTreeGlobals.mCursorHoldHandleEvent()'
++ else
++ exec 'autocmd! CCTreeGeneral CursorMoved '.s:windowtitle
++ endif
++endfunction
++
++function! s:CCTreeGlobals.mSetupEncodingChangeAutoCmd(enable) dict
++ return
++ if a:enable == 1
++ autocmd CCTreeGeneral EncodingChanged * call s:CCTreeGlobals.mEncodingChangedHandleEvent()
++ else
++ autocmd! CCTreeGeneral EncodingChanged *
++ endif
++endfunction
++
++function! s:CCTreeGlobals.mPreviewSave() dict
++ let rtitle = s:CCTreeGlobals.Window.mBuildStatusLine(
++ \ s:CCTreeGlobals.PreviewState,
++ \ s:windowsavetitle,
++ \ {'depth':'', 'direction':''}
++ \)
++
++ if self.Window.mPreviewSave(rtitle) == s:CCTreeRC.Success
++ call s:CCTreeUtils.mInfoMsg('Window saved as '. rtitle .
++ \ '. New window will be opened on next usage.')
++ else
++ call s:CCTreeUtils.mWarningMsg('No active window found to be saved.')
++ endif
++endfunction
++
++function! s:CCTreeGlobals.mWriteXRefDbToFile(fname) dict
++ " create db serializer and writer
++ let gDbSz = s:GenericDbSerializer.mCreate(self.XRefDb)
++ let gDbWriter = s:CCTreeTagDbWriter.mCreate(
++ \ s:CCTreeGetXRefDbMaps('Compress', 'Alpha'))
++ call gDbSz.mWriteXRefDbToFile(a:fname, gDbWriter)
++endfunction
++
++function! s:CCTreeGlobals.mReadToXRefDb(fname) dict
++ call s:StatusLine.mInit()
++ call s:StatusLine.mSetInfo('Reading XRefDb')
++ let vDbFile = s:vFile.mCreate(a:fname, "r")
++ if vDbFile.mIsLargeFile() == 1
++ call s:StatusLine.mSetExtraInfo('Xref DB '
++ \.' >'.g:CCTreeDbFileMaxSize .' bytes. Splitting '.
++ \'into smaller chunks... (this may take some time)')
++ endif
++ try
++ if vDbFile.mOpen() == 0
++ call s:TagFile.mReadToXRefDb(self.XRefDb, vDbFile)
++ endif
++ finally
++ call vDbFile.mClose()
++ call s:StatusLine.mRestore()
++ call self.DbList.mAddDbToList(a:fname, s:DBStorage.memory)
++ endtry
++endfunction
++
++function! s:CCTreeGlobals.mCursorHoldHandleEvent() dict
++ if self.Window.mGetKeywordAtCursor() != s:CCTreeRC.Error
++ setlocal modifiable
++ call self.Window.mClearMarks(b:displayTree)
++ call self.Window.mMarkCallTree(b:displayTree,
++ \ self.Window.hiKeyword)
++ setlocal nomodifiable
++ endif
++endfunction
++
++function! s:CCTreeGlobals.mEncodingChangedHandleEvent() dict
++ let self.Window.treeMarkers = s:CCTreeMarkers.mCreate()
++ if self.Window.mIsOpen() == s:CCTreeRC.True
++ call self.Window.mClose()
++ call self.mUpdateForCurrentSymbol()
++ endif
++endfunction
++
++
++function! s:CCTreeGlobals.mInit() dict
++ call self.mSetupAutoCmds()
++endfunction
++
++" }}}
++" {{{ CCTree options
++function! s:CCTreeSetUseCallTreeHiLights(val)
++ if a:val == -1
++ let g:CCTreeHilightCallTree = !g:CCTreeHilightCallTree
++ else
++ let g:CCTreeHilightCallTree = a:val
++ endif
++ call s:CCTreeGlobals.mSetupAutoCmds()
++endfunction
++
++function! s:CCTreeSetUseUtf8Symbols(val)
++ if a:val == -1
++ let g:CCTreeUseUTF8Symbols = !g:CCTreeUseUTF8Symbols
++ else
++ let g:CCTreeUseUTF8Symbols = a:val
++ endif
++ call s:CCTreeGlobals.mEncodingChangedHandleEvent()
++endfunction
++
++function! s:CCTreeSetUseConceal(val)
++ if a:val == -1
++ let s:CCTreeUseConceal = !s:CCTreeUseConceal
++ else
++ let s:CCTreeUseConceal = a:val
++ endif
++ if !has('conceal')
++ call s:CCTreeUtils.mWarningMsg('+conceal feature not available')
++ let s:CCTreeUseConceal = 0
++ endif
++endfunction
++
++function! s:CCTreeSetEnhancedSymbolProcessing(val)
++ if a:val == -1
++ let g:CCTreeEnhancedSymbolProcessing = !g:CCTreeEnhancedSymbolProcessing
++ else
++ let g:CCTreeEnhancedSymbolProcessing = a:val
++ endif
++endfunction
++
++function! s:CCTreeOptionsList(arglead, cmdline, cursorpos)
++ let opts = keys(s:CCTreeOptions)
++ if a:arglead == ''
++ return opts
++ else
++ return filter(opts, 'v:val =~? a:arglead')
++ endif
++endfunction
++
++let s:CCTreeOptions = {'UseUnicodeSymbols': function('s:CCTreeSetUseUtf8Symbols'),
++ \ 'DynamicTreeHiLights': function('s:CCTreeSetUseCallTreeHiLights'),
++ \ 'UseConceal': function('s:CCTreeSetUseConceal'),
++ \ 'EnhancedSymbolProcessing': function('s:CCTreeSetEnhancedSymbolProcessing')
++ \}
++
++" }}}
++" {{{ Vim tags interface
++
++" CCTreeCompleteKwd
++" Command line completion function to return names from the db
++function! s:CCTreeCompleteKwd(arglead, cmdline, cursorpos)
++ let syms = s:CCTreeGlobals.mGetSymNames(a:arglead)
++ if a:arglead == ''
++ return syms
++ else
++ return filter(syms, 'v:val =~? a:arglead')
++ endif
++endfunction
++
++function! s:CCTreeTraceTreeForSymbol(sym_arg, direction)
++ if s:CCTreeGlobals.DbList.mIsEmpty() == s:CCTreeRC.True
++ call s:CCTreeUtils.mWarningMsg('No database loaded')
++ return
++ endif
++
++ let symbol = a:sym_arg
++ if symbol == ''
++ let symbol = input('Trace symbol: ', expand('<cword>'),
++ \ 'customlist,<SNR>' . s:sid . 'CCTreeCompleteKwd')
++ if symbol == ''
++ return
++ endif
++ endif
++ let symmatch = s:CCTreeGlobals.mGetSymNames(symbol)
++ if len(symmatch) > 0 && index(symmatch, symbol) >= 0
++ call s:CCTreeGlobals.mSetPreviewState(symbol,
++ \ g:CCTreeRecursiveDepth,
++ \ a:direction)
++ call s:CCTreeGlobals.mUpdateForCurrentSymbol()
++ else
++ call s:CCTreeUtils.mWarningMsg('Symbol not found')
++ endif
++endfunction
++
++
++
++
++function! s:CCTreeGlobals.mLoadBufferFromKeyword()
++ " REVISIT
++ if s:CCTreeGlobals.Window.mGetKeywordAtCursor() == s:CCTreeRC.Error
++ call s:CCTreeUtils.mWarningMsg('No keyword at cursor')
++ return
++ endif
++
++ let hiKeyword = s:CCTreeGlobals.Window.hiKeyword
++ try
++ wincmd p
++ catch
++ call s:CCTreeUtils.mWarningMsg('No buffer to load file')
++ finally
++ if (cscope_connection() > 0)
++ try
++ exec "cs find g ". hiKeyword
++ catch
++ " cheap hack
++ exec "cs find f ". hiKeyword
++ endtry
++ else
++ try
++ " Ctags is smart enough to figure the path
++ exec "tag ".fnamemodify(hiKeyword, ":t")
++ catch /^Vim\%((\a\+)\)\=:E433/
++ call s:CCTreeUtils.mWarningMsg('Tag file not found')
++ catch /^Vim\%((\a\+)\)\=:E426/
++ call s:CCTreeUtils.mWarningMsg('Tag '. hiKeyword .' not found')
++ wincmd p
++ endtry
++ endif
++ endtry
++endfunction
++
++function! s:CCTreeGlobals.mPreviewBufferFromKeyword()
++ if self.Window.mGetKeywordAtCursor() == s:CCTreeRC.Error
++ call s:CCTreeUtils.mWarningMsg('No keyword found')
++ return
++ endif
++
++ let hiKeyword = s:CCTreeGlobals.Window.hiKeyword
++ silent! wincmd P
++ if !&previewwindow
++ wincmd p
++ endif
++ try
++ exec "ptag ". hiKeyword
++ catch
++ call s:CCTreeUtils.mWarningMsg('Tag '.hiKeyword. ' not found')
++ endtry
++endfunction
++
++" }}}
++" {{{ Define commands
++command! -nargs=? -complete=file CCTreeLoadXRefDBFromDisk
++ \ call s:CCTreeCmdLine.mLoadDBFromDisk(<q-args>)
++command! -nargs=? -complete=file CCTreeLoadDB call s:CCTreeCmdLine.mLoadDB(<q-args>, s:DBClasses.cscopeid)
++command! -nargs=? -complete=file CCTreeLoadXRefDB call s:CCTreeCmdLine.mLoadDB(<q-args>, s:DBClasses.cctreexref)
++command! -nargs=? -complete=file CCTreeSaveXRefDB call s:CCTreeCmdLine.mSaveDB(<q-args>, s:DBClasses.cctreexref)
++command! -nargs=? -complete=file CCTreeAppendDB call s:CCTreeCmdLine.mMergeDB(<q-args>, s:DBClasses.cscopeid)
++command! -nargs=0 CCTreeUnLoadDB call s:CCTreeGlobals.mUnLoadDBs()
++command! -nargs=0 CCTreeShowLoadedDBs call s:CCTreeGlobals.mShowLoadedDBs()
++command! -nargs=? -complete=customlist,s:CCTreeCompleteKwd
++ \ CCTreeTraceForward call s:CCTreeTraceTreeForSymbol(<q-args>, 'c')
++command! -nargs=? -complete=customlist,s:CCTreeCompleteKwd CCTreeTraceReverse
++ \ call s:CCTreeTraceTreeForSymbol(<q-args>, 'p')
++command! -nargs=0 CCTreeLoadBufferUsingTag call s:CCTreeGlobals.mLoadBufferFromKeyword()
++command! -nargs=0 CCTreePreviewBufferUsingTag call s:CCTreeGlobals.mPreviewBufferFromKeyword()
++command! -nargs=0 CCTreeRecurseDepthPlus call s:CCTreeGlobals.mRecursiveDepthIncrease()
++command! -nargs=0 CCTreeRecurseDepthMinus call s:CCTreeGlobals.mRecursiveDepthDecrease()
++" Preview Window
++command! -nargs=0 CCTreeWindowToggle call s:CCTreeGlobals.mDisplayToggle()
++command! -nargs=0 CCTreeWindowSaveCopy call s:CCTreeGlobals.mPreviewSave()
++" Run-time dynamic options
++command! -nargs=1 -complete=customlist,s:CCTreeOptionsList CCTreeOptsEnable call s:CCTreeGlobals.mEnable(<q-args>)
++command! -nargs=1 -complete=customlist,s:CCTreeOptionsList CCTreeOptsDisable call s:CCTreeGlobals.mDisable(<q-args>)
++command! -nargs=1 -complete=customlist,s:CCTreeOptionsList CCTreeOptsToggle call s:CCTreeGlobals.mToggle(<q-args>)
++"}}}
++" {{{ finish (and init)
++call s:CCTreeGlobals.mInit()
++" restore 'cpo'
++let &cpoptions = s:cpo_save
++unlet s:cpo_save
++" vim: ts=8 sw=4 sts=4 et foldenable foldmethod=marker foldcolumn=1
++" }}}
diff --git a/cscope.spec b/cscope.spec
index 17569a1..e7653b5 100644
--- a/cscope.spec
+++ b/cscope.spec
@@ -1,7 +1,7 @@
Summary: C source code tree search and browse tool
Name: cscope
Version: 15.7a
-Release: 3%{?dist}
+Release: 4%{?dist}
Source0: http://unc.dl.sourceforge.net/sourceforge/cscope/cscope-15.7a.tar.bz2
URL: http://cscope.sourceforge.net
License: BSD
@@ -12,11 +12,13 @@ BuildRequires: pkgconfig ncurses-devel flex bison m4
%define cscope_share_path %{_datadir}/cscope
%define xemacs_lisp_path %{_datadir}/xemacs/site-packages/lisp
%define emacs_lisp_path %{_datadir}/emacs/site-lisp
+%define vim_plugin_path %{datadir}/vim/vimfiles/plugin
Patch0:cscope-15.6-findassign.patch
Patch1:cscope-15.6-ocs.patch
Patch2:cscope-15.6-xcscope-man.patch
Patch3:cscope-15.7-sig_pipe.patch
+Patch4:cscope-15.7a-add-cctree.patch
%description
cscope is a mature, ncurses based, C source code tree browsing tool. It
@@ -31,6 +33,7 @@ matches for use in file editing.
%patch1 -p1
%patch2 -p1
%patch3 -p1
+%patch4 -p1
%build
%configure
@@ -43,6 +46,7 @@ mkdir -p $RPM_BUILD_ROOT/var/lib/cs
mkdir -p $RPM_BUILD_ROOT%{cscope_share_path}
cp -a contrib/xcscope/xcscope.el $RPM_BUILD_ROOT%{cscope_share_path}
cp -a contrib/xcscope/cscope-indexer $RPM_BUILD_ROOT%{_bindir}
+cp -a contrib/cctree.vim $RPM_BUILD_ROOT%{cscope_share_path}
for dir in %{xemacs_lisp_path} %{emacs_lisp_path} ; do
mkdir -p $RPM_BUILD_ROOT$dir
ln -s %{cscope_share_path}/xcscope.el $RPM_BUILD_ROOT$dir
@@ -59,10 +63,10 @@ rm -rf $RPM_BUILD_ROOT
%defattr(-,root,root,-)
%{_bindir}/*
%dir %{cscope_share_path}
-%{cscope_share_path}/xcscope.el
+%{cscope_share_path}/
%{_mandir}/man1/*
%dir /var/lib/cs
-%doc AUTHORS COPYING ChangeLog README TODO
+%doc AUTHORS COPYING ChangeLog README TODO contrib/cctree.txt
%triggerin -- xemacs
ln -sf %{cscope_share_path}/xcscope.el %{xemacs_lisp_path}/xcscope.el
@@ -70,6 +74,9 @@ ln -sf %{cscope_share_path}/xcscope.el %{xemacs_lisp_path}/xcscope.el
%triggerin -- emacs
ln -sf %{cscope_share_path}/xcscope.el %{emacs_lisp_path}/xcscope.el
+%triggerin -- vim-filesystem
+ln -sf %{cscope_share_path}/cctree.vim %{vim_plugin_path}/cctree.vim
+
%triggerun -- xemacs
[ $2 -gt 0 ] && exit 0
rm -f %{xemacs_lisp_path}/xcscope.el
@@ -78,7 +85,14 @@ rm -f %{xemacs_lisp_path}/xcscope.el
[ $2 -gt 0 ] && exit 0
rm -f %{emacs_lisp_path}/xcscope.el
+%triggerun -- vim-filesystem
+[ $2 -gt 0 ] && exit 0
+rm -f %{vim_plugin_path}/cctree.vim
+
%changelog
+* Thu May 26 2011 Neil Horman <nhorman at redhat.com> - 15.7a-4
+- Added cctree.vim vi plugin
+
* Tue Feb 08 2011 Fedora Release Engineering <rel-eng at lists.fedoraproject.org> - 15.7a-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild
More information about the scm-commits
mailing list