├── .gitignore
├── CHANGELOG.md
├── LICENSE.md
├── README.md
├── icons
├── icon-class.svg
├── icon-constant.svg
├── icon-converter.svg
├── icon-enum.svg
├── icon-function.svg
├── icon-generics.svg
├── icon-interface.svg
├── icon-iterator.svg
├── icon-macro.svg
├── icon-method.svg
├── icon-namespace.svg
├── icon-struct.svg
├── icon-typedef.svg
├── icon-union.svg
├── icon-variable.svg
└── symbol-icons.woff
├── keymaps
└── symbols-tree-view.cson
├── lib
├── .ctags
├── main.coffee
├── symbols-context-menu.coffee
├── symbols-tree-view.coffee
├── tag-generator.coffee
├── tag-parser.coffee
└── tree-view.coffee
├── menus
└── symbols-tree-view.cson
├── package.json
├── screencast.gif
├── screenshot.png
├── styles
└── symbols-tree-view.less
└── vendor
├── universal-ctags-darwin
├── universal-ctags-linux
└── universal-ctags-win32.exe
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | npm-debug.log
3 | node_modules
4 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## 0.1.0 - First Release
2 | * Every feature added
3 | * Every bug fixed
4 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | Copyright (c) 2014 xndcn
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining
4 | a copy of this software and associated documentation files (the
5 | "Software"), to deal in the Software without restriction, including
6 | without limitation the rights to use, copy, modify, merge, publish,
7 | distribute, sublicense, and/or sell copies of the Software, and to
8 | permit persons to whom the Software is furnished to do so, subject to
9 | the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be
12 | included in all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # symbols-tree-view package
2 |
3 | Symbols Tree View for Atom.io, just like taglist or tagbar for VIM.
4 |
5 | tag-generator.coffee comes from http://github.com/atom/symbols-view
6 |
7 | 
8 |
9 | ## Settings
10 |
11 | * `Auto Hide` If checked then symbols-tree-view is always hidden unless mouse hover over it. (default=false)
12 |
13 | * `Auto Toggle` If checked the symbols-tree-view is auto toggled on when you open files. (default=false)
14 |
15 | * `Scroll Animation` If checked it will scroll to the destination gradually when you click the item in symbols-tree. (default=true)
16 |
17 | ## TO DO
18 |
19 | * Add specs for test
20 |
21 | * Improve icons
22 |
--------------------------------------------------------------------------------
/icons/icon-class.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
85 |
--------------------------------------------------------------------------------
/icons/icon-constant.svg:
--------------------------------------------------------------------------------
1 |
2 |
39 |
--------------------------------------------------------------------------------
/icons/icon-converter.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
73 |
--------------------------------------------------------------------------------
/icons/icon-enum.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
82 |
--------------------------------------------------------------------------------
/icons/icon-function.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
77 |
--------------------------------------------------------------------------------
/icons/icon-generics.svg:
--------------------------------------------------------------------------------
1 |
2 |
47 |
--------------------------------------------------------------------------------
/icons/icon-interface.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
87 |
--------------------------------------------------------------------------------
/icons/icon-iterator.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
77 |
--------------------------------------------------------------------------------
/icons/icon-macro.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
75 |
--------------------------------------------------------------------------------
/icons/icon-method.svg:
--------------------------------------------------------------------------------
1 |
2 |
43 |
--------------------------------------------------------------------------------
/icons/icon-namespace.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
72 |
--------------------------------------------------------------------------------
/icons/icon-struct.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
85 |
--------------------------------------------------------------------------------
/icons/icon-typedef.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
82 |
--------------------------------------------------------------------------------
/icons/icon-union.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
82 |
--------------------------------------------------------------------------------
/icons/icon-variable.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
82 |
--------------------------------------------------------------------------------
/icons/symbol-icons.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xndcn/symbols-tree-view/9ae8d173351554450077dcabd5f32c0766f8b9e6/icons/symbol-icons.woff
--------------------------------------------------------------------------------
/keymaps/symbols-tree-view.cson:
--------------------------------------------------------------------------------
1 | # Keybindings require three things to be fully defined: A selector that is
2 | # matched against the focused element, the keystroke and the command to
3 | # execute.
4 | #
5 | # Below is a basic keybinding which registers on all platforms by applying to
6 | # the root workspace element.
7 |
8 | # For more detailed documentation see
9 | # https://atom.io/docs/latest/advanced/keymaps
10 | 'atom-workspace':
11 | 'ctrl-alt-o': 'symbols-tree-view:toggle'
12 |
--------------------------------------------------------------------------------
/lib/.ctags:
--------------------------------------------------------------------------------
1 | --langdef=CoffeeScript
2 | --langmap=CoffeeScript:.coffee
3 | --regex-CoffeeScript=/^[ \t]*(@?[a-zA-Z$_\.0-9]+)[ \t]*=[ \t]*.*/\1/v,variable/
4 | --regex-CoffeeScript=/(^|=[ \t])*class ([A-Za-z_][A-Za-z0-9_]+\.)*([A-Za-z_][A-Za-z0-9_]+)( extends ([A-Za-z][A-Za-z0-9_.]*)+)?$/\3/c,class/
5 | --regex-CoffeeScript=/^[ \t]*(module\.)?(exports\.)?@?(([A-Za-z][A-Za-z0-9_.]*)+):.*[-=]>.*$/\3/m,method/
6 | --regex-CoffeeScript=/^[ \t]*(module\.)?(exports\.)?(([A-Za-z][A-Za-z0-9_.]*)+)[ \t]*=.*[-=]>.*$/\3/f,function/
7 | --regex-CoffeeScript=/^[ \t]*@(([A-Za-z][A-Za-z0-9_.]*)+)[ \t]*=[^->\n]*$/\1/f,field/
8 | --regex-CoffeeScript=/^[ \t]*@(([A-Za-z][A-Za-z0-9_.]*)+):[^->\n]*$/\1/f,static field/
9 | --regex-CoffeeScript=/^[ \t]*(([A-Za-z][A-Za-z0-9_.]*)+):[^->\n]*$/\1/f,field/
10 |
11 | --langdef=Css
12 | --langmap=Css:.css
13 | --langmap=Css:+.less
14 | --langmap=Css:+.scss
15 | --regex-Css=/^[ \t]*(.+)[ \t]*\{/\1/f,function/
16 | --regex-Css=/^[ \t]*(.+)[ \t]*,[ \t]*$/\1/f,function/
17 |
18 | --langdef=Sass
19 | --langmap=Sass:.sass
20 | --regex-Sass=/^[ \t]*([#.]*[a-zA-Z_0-9]+)[ \t]*$/\1/f,function/
21 |
22 | --langdef=Yaml
23 | --langmap=Yaml:.yaml
24 | --langmap=Yaml:+.yml
25 | --regex-Yaml=/^[ \t]*([a-zA-Z_0-9 ]+)[ \t]*\:[ \t]*/\1/f,function/
26 |
27 | --regex-Html=/^[ \t]*<([a-zA-Z]+)[ \t]*.*id="([^"]+)".*>/\1#\2/m,member\tclass:id/
28 | --regex-Html=/^[ \t]*<([a-zA-Z]+)[ \t]*.*class="([^"]+)".*>/\1.\2/m,member\tclass:class/
29 | --regex-Html=/^[ \t]*<([a-zA-Z]+)[ \t]*>/\1/m,member\tclass:no-attr/
30 |
31 | --langdef=Markdown
32 | --langmap=Markdown:.md
33 | --langmap=Markdown:+.markdown
34 | --langmap=Markdown:+.mdown
35 | --langmap=Markdown:+.mkd
36 | --langmap=Markdown:+.mkdown
37 | --langmap=Markdown:+.ron
38 | --regex-Markdown=/^#+[ \t]*([^#]+)/\1/f,function/
39 |
40 | --langdef=Json
41 | --langmap=Json:.json
42 | --regex-Json=/^[ \t]*"([^"]+)"[ \t]*\:/\1/f,function/
43 |
44 | --langdef=Cson
45 | --langmap=Cson:.cson
46 | --langmap=Cson:+.gyp
47 | --regex-Cson=/^[ \t]*'([^']+)'[ \t]*\:/\1/f,function/
48 | --regex-Cson=/^[ \t]*"([^"]+)"[ \t]*\:/\1/f,function/
49 | --regex-Cson=/^[ \t]*([^'"]+)[ \t]*\:/\1/f,function/
50 |
51 | --langmap=C++:+.mm
52 |
53 | --langmap=Ruby:+(Rakefile)
54 |
55 | --langmap=Php:+.module
56 |
57 | --langdef=Go
58 | --langmap=Go:.go
59 | --regex-Go=/func([ \t]+\([^)]+\))?[ \t]+([a-zA-Z0-9_]+)/\2/f,func/
60 | --regex-Go=/var[ \t]+([a-zA-Z_][a-zA-Z0-9_]*)/\1/v,var/
61 | --regex-Go=/type[ \t]+([a-zA-Z_][a-zA-Z0-9_]*)/\1/t,type/
62 |
63 | --langmap=perl:+.pod
64 | --regex-perl=/with[ \t]+([^;]+)[ \t]*?;/\1/w,role,roles/
65 | --regex-perl=/extends[ \t]+['"]([^'"]+)['"][ \t]*?;/\1/e,extends/
66 | --regex-perl=/use[ \t]+base[ \t]+['"]([^'"]+)['"][ \t]*?;/\1/e,extends/
67 | --regex-perl=/use[ \t]+parent[ \t]+['"]([^'"]+)['"][ \t]*?;/\1/e,extends/
68 | --regex-perl=/Mojo::Base[ \t]+['"]([^'"]+)['"][ \t]*?;/\1/e,extends/
69 | --regex-perl=/^[ \t]*?use[ \t]+([^;]+)[ \t]*?;/\1/u,use,uses/
70 | --regex-perl=/^[ \t]*?require[ \t]+((\w|\:)+)/\1/r,require,requires/
71 | --regex-perl=/^[ \t]*?has[ \t]+['"]?(\w+)['"]?/\1/a,attribute,attributes/
72 | --regex-perl=/^[ \t]*?\*(\w+)[ \t]*?=/\1/a,alias,aliases/
73 | --regex-perl=/->helper\([ \t]?['"]?(\w+)['"]?/\1/h,helper,helpers/
74 | --regex-perl=/^[ \t]*?our[ \t]*?[\$@%](\w+)/\1/o,our,ours/
75 | --regex-perl=/^\=head1[ \t]+(.+)/\1/p,pod,Plain Old Documentation/
76 | --regex-perl=/^\=head2[ \t]+(.+)/-- \1/p,pod,Plain Old Documentation/
77 | --regex-perl=/^\=head[3-5][ \t]+(.+)/---- \1/p,pod,Plain Old Documentation/
78 |
79 |
80 | --regex-JavaScript=/(,|(;|^)[ \t]*(var|let|const|([A-Za-z_$][A-Za-z0-9_$.]*\.)+))[ \t]*([A-Za-z_$][A-Za-z0-9_$.]*)[ \t]*=[ \t]*\{/\5/,object/
81 | --regex-JavaScript=/(,|(;|^)[ \t]*(var|let|const|([A-Za-z_$][A-Za-z0-9_$.]*\.)+))[ \t]*([A-Za-z_$][A-Za-z0-9_$.]*)[ \t]*=[ \t]*(\[|(new[ \t]+)?Array\()/\5/,array/
82 | --regex-JavaScript=/(,|(;|^)[ \t]*(var|let|const|([A-Za-z_$][A-Za-z0-9_$.]*\.)+))[ \t]*([A-Za-z_$][A-Za-z0-9_$.]*)[ \t]*=[ \t]*[^"]'[^']*/\5/,string/
83 | --regex-JavaScript=/(,|(;|^)[ \t]*(var|let|const|([A-Za-z_$][A-Za-z0-9_$.]*\.)+))[ \t]*([A-Za-z_$][A-Za-z0-9_$.]*)[ \t]*=[ \t]*(true|false)/\5/,boolean/
84 | --regex-JavaScript=/(,|(;|^)[ \t]*(var|let|const|([A-Za-z_$][A-Za-z0-9_$.]*\.)+))[ \t]*([A-Za-z_$][A-Za-z0-9_$.]*)[ \t]*=[ \t]*[0-9]+/\5/,number/
85 | --regex-JavaScript=/(,|(;|^)[ \t]*(var|let|const|([A-Za-z_$][A-Za-z0-9_$.]*\.)+))[ \t]*([A-Za-z_$][A-Za-z0-9_$.]*)[ \t]*=[ \t]*null/\5/,null/
86 | --regex-JavaScript=/(,|(;|^)[ \t]*(var|let|const|([A-Za-z_$][A-Za-z0-9_$.]*\.)+))[ \t]*([A-Za-z_$][A-Za-z0-9_$.]*)[ \t]*=[ \t]*undefined/\5/,undefined/
87 |
88 | --regex-JavaScript=/(,|(;|^)[ \t]*(var|let|([A-Za-z_$][A-Za-z0-9_$.]*\.)+))[ \t]*([A-Za-z_$][A-Za-z0-9_$.]*)[ \t]*=[ \t]*[^tfn0-9"'{\[]+([,;=]|$)/\5/,unknown/
89 |
90 | --regex-JavaScript=/(,|(;|^)[ \t]*(var|let|([A-Za-z_$][A-Za-z0-9_$.]*\.)+))[ \t]*([A-Za-z_$][A-Za-z0-9_$.]*)[ \t]*=[ \t]*.+([,;=]|$)/\5/,variable/
91 | --regex-JavaScript=/(,|(;|^)[ \t]*(var|let|([A-Za-z_$][A-Za-z0-9_$.]*\.)+))[ \t]*([A-Za-z_$][A-Za-z0-9_$.]*)[ \t]*[ \t]*([,;]|$)/\5/,undefined/
92 | --regex-JavaScript=/(,|(;|^)[ \t]*)const[ \t]*([A-Za-z_$][A-Za-z0-9_$]*)[ \t]*=[ \t]*.+([,;=]|$)/\3/,constant/
93 |
94 |
95 | --regex-JavaScript=/(,|(;|^)[ \t]*(var|let|([A-Za-z_$][A-Za-z0-9_$.]*\.)*))[ \t]*([A-Za-z_$][A-Za-z0-9_$]*)[ \t]*=[ \t]*function[ \t]*\(/\5/,function-expression/
96 | --regex-JavaScript=/(,|(;|^))[ \t]*(([A-Za-z_$][A-Za-z0-9_$.]*\.)+prototype\.)[ \t]*([A-Za-z_$][A-Za-z0-9_$]*)[ \t]*=[ \t]*function[ \t]*\(/\4\5/,prototype-method/
97 | --regex-JavaScript=/(,|^|\*\/)[ \t]*([A-Za-z_$][A-Za-z0-9_$]*)[ \t]*:[ \t]*function[ \t]*\(/\2/,object-method/
98 |
99 |
100 | --regex-JavaScript=/function[ \t]+([A-Za-z_$][A-Za-z0-9_$]*)[ \t]*\([^)]*\)/\1/,function-declaration/
101 |
102 | --regex-JavaScript=/(,|^|\*\/)[ \t]*(while|if|for|switch|function|([A-Za-z_$][A-Za-z0-9_$]*))[ \t]*\([^)]*\)[ \t]*\{/\3/,function/
103 |
104 | --regex-JavaScript=/(,|^|\*\/|\{)[ \t]*get[ \t]+([A-Za-z_$][A-Za-z0-9_$]*)[ \t]*\([ \t]*\)[ \t]*\{/get \2/,getter/
105 | --regex-JavaScript=/(,|^|\*\/|\{)[ \t]*set[ \t]+([A-Za-z_$][A-Za-z0-9_$]*)[ \t]*\([ \t]*([A-Za-z_$][A-Za-z0-9_$]*)?[ \t]*\)[ \t]*\{/set \2/,setter/
106 |
107 | --regex-JavaScript=/(,|^|\*\/)[ \t]*([A-Za-z_$][A-Za-z0-9_$]*)[ \t]*:[ \t]*\{/\2/,object/
108 | --regex-JavaScript=/(,|^|\*\/)[ \t]*([A-Za-z_$][A-Za-z0-9_$]*)[ \t]*:[ \t]*\[/\2/,array/
109 | --regex-JavaScript=/(,|^|\*\/)[ \t]*([A-Za-z_$][A-Za-z0-9_$]*)[ \t]*:[ \t]*[^"]'[^']*/\2/,string/
110 | --regex-JavaScript=/(,|^|\*\/)[ \t]*([A-Za-z_$][A-Za-z0-9_$]*)[ \t]*:[ \t]*(true|false)/\2/,boolean/
111 | --regex-JavaScript=/(,|^|\*\/)[ \t]*([A-Za-z_$][A-Za-z0-9_$]*)[ \t]*:[ \t]*[0-9]+/\2/,number/
112 | --regex-JavaScript=/(,|^|\*\/)[ \t]*([A-Za-z_$][A-Za-z0-9_$]*)[ \t]*:[ \t]*[^=]+([,;]|$)/\2/,variable/
113 |
114 |
115 | --langdef=haxe
116 | --langmap=haxe:.hx
117 | --regex-haxe=/^package[ \t]+([A-Za-z0-9_.]+)/\1/p,package/
118 | --regex-haxe=/^[ \t]*[(@:macro|private|public|static|override|inline|dynamic)( \t)]*function[ \t]+([A-Za-z0-9_]+)/\1/f,function/
119 | --regex-haxe=/^[ \t]*([private|public|static|protected|inline][ \t]*)+var[ \t]+([A-Za-z0-9_]+)/\2/v,variable/
120 | --regex-haxe=/^[ \t]*package[ \t]*([A-Za-z0-9_]+)/\1/p,package/
121 | --regex-haxe=/^[ \t]*(extern[ \t]*|@:native\([^)]*\)[ \t]*)*class[ \t]+([A-Za-z0-9_]+)[ \t]*[^\{]*/\2/c,class/
122 | --regex-haxe=/^[ \t]*(extern[ \t]+)?interface[ \t]+([A-Za-z0-9_]+)/\2/i,interface/
123 | --regex-haxe=/^[ \t]*typedef[ \t]+([A-Za-z0-9_]+)/\1/t,typedef/
124 | --regex-haxe=/^[ \t]*enum[ \t]+([A-Za-z0-9_]+)/\1/t,typedef/
125 | --regex-haxe=/^[ \t]*+([A-Za-z0-9_]+)(;|\([^)]*:[^)]*\))/\1/t,enum_field/
126 |
127 | --langdef=Nim
128 | --langmap=Nim:.nim
129 | --regex-Nim=/^[\t\s]*proc\s+([_A-Za-z0-9]+)\**(\[\w+(\:\s+\w+)?\])?\s*\(/\1/f,function/
130 | --regex-Nim=/^[\t\s]*iterator\s+([_A-Za-z0-9]+)\**(\[\w+(\:\s+\w+)?\])?\s*\(/\1/i,iterator/
131 | --regex-Nim=/^[\t\s]*macro\s+([_A-Za-z0-9]+)\**(\[\w+(\:\s+\w+)?\])?\s*\(/\1/m,macro/
132 | --regex-Nim=/^[\t\s]*method\s+([_A-Za-z0-9]+)\**(\[\w+(\:\s+\w+)?\])?\s*\(/\1/h,method/
133 | --regex-Nim=/^[\t\s]*template\s+([_A-Za-z0-9]+)\**(\[\w+(\:\s+\w+)?\])?\s*\(/\1/t,generics/
134 | --regex-Nim=/^[\t\s]*converter\s+([_A-Za-z0-9]+)\**(\[\w+(\:\s+\w+)?\])?\s*\(/\1/c,converter/
135 |
136 | --langdef=Rust
137 | --langmap=Rust:.rs
138 | --regex-Rust=/^[ \t]*(#\[[^\]]\][ \t]*)*(pub[ \t]+)?(extern[ \t]+)?("[^"]+"[ \t]+)?(unsafe[ \t]+)?fn[ \t]+([a-zA-Z0-9_]+)/\6/f,function/
139 | --regex-Rust=/^[ \t]*(pub[ \t]+)?type[ \t]+([a-zA-Z0-9_]+)/\2/T,typedef/
140 | --regex-Rust=/^[ \t]*(pub[ \t]+)?enum[ \t]+([a-zA-Z0-9_]+)/\2/g,enum/
141 | --regex-Rust=/^[ \t]*(pub[ \t]+)?struct[ \t]+([a-zA-Z0-9_]+)/\2/s,struct/
142 | --regex-Rust=/^[ \t]*(pub[ \t]+)?mod[ \t]+([a-zA-Z0-9_]+)/\2/m,namespace/
143 | --regex-Rust=/^[ \t]*(pub[ \t]+)?static[ \t]+([a-zA-Z0-9_]+)/\2/c,constant/
144 | --regex-Rust=/^[ \t]*(pub[ \t]+)?trait[ \t]+([a-zA-Z0-9_]+)/\2/t,method/
145 | --regex-Rust=/^[ \t]*(pub[ \t]+)?impl([ \t\n]*<[^>]*>)?[ \t]+(([a-zA-Z0-9_:]+)[ \t]*(<[^>]*>)?[ \t]+(for)[ \t]+)?([a-zA-Z0-9_]+)/\4 \6 \7/i,generic/
146 | --regex-Rust=/^[ \t]*macro_rules![ \t]+([a-zA-Z0-9_]+)/\1/d,macro/
147 |
148 | --langdef=LiveCode
149 | --langmap=LiveCode:.livecodescript
150 | --langmap=LiveCode:+.lc
151 | --langmap=LiveCode:+.irev
152 | --regex-LiveCode=/^[ \t]*(private[ \t]+)*(on|command)[ \t]*([A-Za-z0-9_]+)/\3/h,method/
153 | --regex-LiveCode=/^[ \t]*(private[ \t]+)*function[ \t]+([A-Za-z0-9_]+)/\2/f,function/
154 | --regex-LiveCode=/^[ \t]*constant[ \t]+([A-Za-z0-9_]+)/\1/c,constant/
155 | --regex-LiveCode=/^[ \t]*(global|local)[ \t]+([A-Za-z0-9_]+)/\2/v,variable/
156 |
157 | --langdef=sql
158 | --langmap=sql:.sql
159 | --langmap=sql:+.bdy
160 | --langmap=sql:+.spc
161 | --langmap=sql:+.pls
162 | --langmap=sql:+.plb
163 | --langmap=sql:+.ddl
164 | --langmap=sql:+.pks
165 | --langmap=sql:+.pkb
166 | --regex-sql=/^[ \t]*create[ \t]+([a-zA-Z0-9 \t]*)?(table)[\t]+([^.]+\.)?([a-zA-Z0-9_@.]+)/\4/t,table/i
167 | --regex-sql=/^[ \t]*create[ \t]+([a-zA-Z0-9 \t]*)?(procedure|package)[\t]+([^.]+\.)?"?([a-zA-Z0-9_@.]+)/\4/p,procedure/i
168 | --regex-sql=/^[ \t]*create[ \t]+([a-zA-Z0-9 \t]*)?(function)[\t]+([^.]+\.)?"?([a-zA-Z0-9_@.]+)/\4/f,function/i
169 | --regex-sql=/^[ \t]*create[ \t]+([a-zA-Z0-9 \t]*)?(trigger)[\t]+([^.]+\.)?"?([a-zA-Z0-9_@.]+)/\4/r,trigger/i
170 | --regex-sql=/^[ \t]*create[ \t]+([a-zA-Z0-9 \t]*)?(event)[\t]+([^.]+\.)?"?([a-zA-Z0-9_@.]+)/\4/e,event/i
171 | --regex-sql=/^[ \t]*create[ \t]+([a-zA-Z0-9 \t]*)?(index)[\t]+([^.]+\.)?"?([a-zA-Z0-9_@.]+)/\4/i,index/i
172 | --regex-sql=/^[ \t]*create[ \t]+([a-zA-Z0-9\t]*)?(publication|subscription to|synchronization user)[\t]+([^.]+\.)?"?([a-zA-Z0-9_@.]+)/\4/m,mobilink/i
173 | --regex-sql=/^[ \t]*create[ \t]+([a-zA-Z0-9 \t]*)?(variable)[\t]+([^.]+\.)?"?([a-zA-Z0-9_@.]+)/\4/v,variable/i
174 | --regex-sql=/^[ \t]*create[ \t]+([a-zA-Z0-9\t]*)?(rule|schema|server|datatype|database|message)[\t]+([^.]+\.)?"?([a-zA-Z0-9_@.]+)/\4/o,other/I
175 |
176 | --langdef=Scilab
177 | --langmap=Scilab:.sce
178 | --langmap=Scilab:+.sci
179 | --langmap=Scilab:+.m
180 | --langmap=Scilab:+.kla
181 | --regex-Scilab=#(^///[ \t]*\$begin[ \t])+ScriptHeader#Script-Header#s,package#i
182 | --regex-Scilab=#^[ \t]*function.*[ \t]]*([a-zA-Z_][a-zA-Z0-9_]*)\(#\1#q,function#
183 |
184 | --langdef=ini
185 | --langmap=ini:.ini
186 | --regex-ini=/^[ \t]*(\[.+\])[ \t]*$/\1/t,generics/
187 |
--------------------------------------------------------------------------------
/lib/main.coffee:
--------------------------------------------------------------------------------
1 | SymbolsTreeView = require './symbols-tree-view'
2 |
3 | module.exports =
4 | config:
5 | autoToggle:
6 | type: 'boolean'
7 | default: false
8 | description: 'If this option is enabled then symbols-tree-view will auto open when you open files.'
9 | scrollAnimation:
10 | type: 'boolean'
11 | default: true
12 | description: 'If this option is enabled then when you click the item in symbols-tree it will scroll to the destination gradually.'
13 | autoHide:
14 | type: 'boolean'
15 | default: false
16 | description: 'If this option is enabled then symbols-tree-view is always hidden unless mouse hover over it.'
17 | zAutoHideTypes:
18 | title: 'AutoHideTypes'
19 | type: 'string'
20 | description: 'Here you can specify a list of types that will be hidden by default (ex: "variable class")'
21 | default: ''
22 | sortByNameScopes:
23 | type: 'string'
24 | description: 'Here you can specify a list of scopes that will be sorted by name (ex: "text.html.php")'
25 | default: ''
26 | defaultWidth:
27 | type: 'number'
28 | description: 'Width of the panel (needs Atom restart)'
29 | default: 200
30 |
31 |
32 | symbolsTreeView: null
33 |
34 | activate: (state) ->
35 | @symbolsTreeView = new SymbolsTreeView(state.symbolsTreeViewState)
36 | atom.commands.add 'atom-workspace', 'symbols-tree-view:toggle': => @symbolsTreeView.toggle()
37 | atom.commands.add 'atom-workspace', 'symbols-tree-view:show': => @symbolsTreeView.showView()
38 | atom.commands.add 'atom-workspace', 'symbols-tree-view:hide': => @symbolsTreeView.hideView()
39 |
40 | atom.config.observe 'tree-view.showOnRightSide', (value) =>
41 | if @symbolsTreeView.hasParent()
42 | @symbolsTreeView.remove()
43 | @symbolsTreeView.populate()
44 | @symbolsTreeView.attach()
45 |
46 | atom.config.observe "symbols-tree-view.autoToggle", (enabled) =>
47 | if enabled
48 | @symbolsTreeView.toggle() unless @symbolsTreeView.hasParent()
49 | else
50 | @symbolsTreeView.toggle() if @symbolsTreeView.hasParent()
51 |
52 | deactivate: ->
53 | @symbolsTreeView.destroy()
54 |
55 | serialize: ->
56 | symbolsTreeViewState: @symbolsTreeView.serialize()
57 |
58 | getProvider: ->
59 | view = @symbolsTreeView
60 |
61 | providerName: 'symbols-tree-view'
62 | getSuggestionForWord: (textEditor, text, range) =>
63 | range: range
64 | callback: ()=>
65 | view.focusClickedTag.bind(view)(textEditor, text)
66 |
--------------------------------------------------------------------------------
/lib/symbols-context-menu.coffee:
--------------------------------------------------------------------------------
1 | {$, $$, View} = require 'atom-space-pen-views'
2 |
3 | module.exports =
4 | class SymbolsContextMenu extends View
5 | @content: ->
6 | @div class: 'symbols-context-menu', =>
7 | @div class: 'select-list popover-list', =>
8 | @input type: 'text', class: 'hidden-input', outlet: 'hiddenInput'
9 | @ol class: 'list-group mark-active', outlet: 'menus'
10 |
11 | initialize: ->
12 | @hiddenInput.on 'focusout', =>
13 | @hide()
14 |
15 | clear: ->
16 | @menus.empty()
17 |
18 | addMenu: (name, active, callback) ->
19 | menu = $$ ->
20 | @li class: (if active then 'active' else ''), name
21 |
22 | menu.on 'mousedown', =>
23 | menu.toggleClass('active')
24 | @hiddenInput.blur()
25 | callback(name)
26 |
27 | @menus.append(menu)
28 |
29 | toggle: (type) ->
30 | for menu in @menus.find('li')
31 | if $(menu).text() == type
32 | $(menu).toggleClass('active')
33 |
34 | addSeparator: ->
35 | @menus.append $$ ->
36 | @li class: 'separator'
37 |
38 | show: ->
39 | if @menus.children().length > 0
40 | super
41 | @hiddenInput.focus()
42 |
43 | attach: ->
44 | atom.views.getView(atom.workspace).appendChild(@element)
45 |
--------------------------------------------------------------------------------
/lib/symbols-tree-view.coffee:
--------------------------------------------------------------------------------
1 | {Point, Range} = require 'atom'
2 | {$, jQuery, View} = require 'atom-space-pen-views'
3 | {TreeView} = require './tree-view'
4 | TagGenerator = require './tag-generator'
5 | TagParser = require './tag-parser'
6 | SymbolsContextMenu = require './symbols-context-menu'
7 |
8 | module.exports =
9 | class SymbolsTreeView extends View
10 | @content: ->
11 | @div class: 'symbols-tree-view tool-panel focusable-panel'
12 |
13 | initialize: ->
14 | @treeView = new TreeView
15 | @append(@treeView)
16 |
17 | @cachedStatus = {}
18 | @contextMenu = new SymbolsContextMenu
19 | @autoHideTypes = atom.config.get('symbols-tree-view.zAutoHideTypes')
20 |
21 | @treeView.onSelect ({node, item}) =>
22 | if item.position.row >= 0 and editor = atom.workspace.getActiveTextEditor()
23 | screenPosition = editor.screenPositionForBufferPosition(item.position)
24 | screenRange = new Range(screenPosition, screenPosition)
25 | {top, left, height, width} = editor.element.pixelRectForScreenRange(screenRange)
26 | bottom = top + height
27 | desiredScrollCenter = top + height / 2
28 | unless editor.element.getScrollTop() < desiredScrollCenter < editor.element.getScrollBottom()
29 | desiredScrollTop = desiredScrollCenter - editor.element.getHeight() / 2
30 |
31 | from = {top: editor.element.getScrollTop()}
32 | to = {top: desiredScrollTop}
33 |
34 | step = (now) ->
35 | editor.element.setScrollTop(now)
36 |
37 | done = ->
38 | editor.scrollToBufferPosition(item.position, center: true)
39 | editor.setCursorBufferPosition(item.position)
40 | editor.moveToFirstCharacterOfLine()
41 |
42 | jQuery(from).animate(to, duration: @animationDuration, step: step, done: done)
43 |
44 | atom.config.observe 'symbols-tree-view.scrollAnimation', (enabled) =>
45 | @animationDuration = if enabled then 300 else 0
46 |
47 | @minimalWidth = 5
48 | @originalWidth = atom.config.get('symbols-tree-view.defaultWidth')
49 | atom.config.observe 'symbols-tree-view.autoHide', (autoHide) =>
50 | unless autoHide
51 | @width(@originalWidth)
52 | else
53 | @width(@minimalWidth)
54 |
55 | getEditor: -> atom.workspace.getActiveTextEditor()
56 | getScopeName: -> atom.workspace.getActiveTextEditor()?.getGrammar()?.scopeName
57 |
58 | populate: ->
59 | unless editor = @getEditor()
60 | @hide()
61 | else
62 | filePath = editor.getPath()
63 | @generateTags(filePath)
64 | @show()
65 |
66 | @onEditorSave = editor.onDidSave (state) =>
67 | filePath = editor.getPath()
68 | @generateTags(filePath)
69 |
70 | @onChangeRow = editor.onDidChangeCursorPosition ({oldBufferPosition, newBufferPosition}) =>
71 | if oldBufferPosition.row != newBufferPosition.row
72 | @focusCurrentCursorTag()
73 |
74 | focusCurrentCursorTag: ->
75 | if (editor = @getEditor()) and @parser?
76 | row = editor.getCursorBufferPosition().row
77 | tag = @parser.getNearestTag(row)
78 | @treeView.select(tag)
79 |
80 | focusClickedTag: (editor, text) ->
81 | console.log "clicked: #{text}"
82 | if editor = @getEditor()
83 | tag = (t for t in @parser.tags when t.name is text)[0]
84 | @treeView.select(tag)
85 | # imho, its a bad idea =(
86 | jQuery('.list-item.list-selectable-item.selected').click()
87 |
88 | updateContextMenu: (types) ->
89 | @contextMenu.clear()
90 | editor = @getEditor()?.id
91 |
92 | toggleTypeVisible = (type) =>
93 | @treeView.toggleTypeVisible(type)
94 | @nowTypeStatus[type] = !@nowTypeStatus[type]
95 |
96 | toggleSortByName = =>
97 | @nowSortStatus[0] = !@nowSortStatus[0]
98 | if @nowSortStatus[0]
99 | @treeView.sortByName()
100 | else
101 | @treeView.sortByRow()
102 | for type, visible of @nowTypeStatus
103 | @treeView.toggleTypeVisible(type) unless visible
104 | @focusCurrentCursorTag()
105 |
106 | if @cachedStatus[editor]
107 | {@nowTypeStatus, @nowSortStatus} = @cachedStatus[editor]
108 | for type, visible of @nowTypeStatus
109 | @treeView.toggleTypeVisible(type) unless visible
110 | @treeView.sortByName() if @nowSortStatus[0]
111 | else
112 | @cachedStatus[editor] = {nowTypeStatus: {}, nowSortStatus: [false]}
113 | @cachedStatus[editor].nowTypeStatus[type] = true for type in types
114 | @sortByNameScopes = atom.config.get('symbols-tree-view.sortByNameScopes')
115 | if @sortByNameScopes.indexOf(@getScopeName()) != -1
116 | @cachedStatus[editor].nowSortStatus[0] = true
117 | @treeView.sortByName()
118 | {@nowTypeStatus, @nowSortStatus} = @cachedStatus[editor]
119 |
120 | @contextMenu.addMenu(type, @nowTypeStatus[type], toggleTypeVisible) for type in types
121 | @contextMenu.addSeparator()
122 | @contextMenu.addMenu('sort by name', @nowSortStatus[0], toggleSortByName)
123 |
124 | generateTags: (filePath) ->
125 | new TagGenerator(filePath, @getScopeName()).generate().done (tags) =>
126 | @parser = new TagParser(tags, @getScopeName())
127 | {root, types} = @parser.parse()
128 | @treeView.setRoot(root)
129 | @updateContextMenu(types)
130 | @focusCurrentCursorTag()
131 |
132 | if (@autoHideTypes)
133 | for type in types
134 | if(@autoHideTypes.indexOf(type) != -1)
135 | @treeView.toggleTypeVisible(type)
136 | @contextMenu.toggle(type)
137 |
138 |
139 | # Returns an object that can be retrieved when package is activated
140 | serialize: ->
141 |
142 | # Tear down any state and detach
143 | destroy: ->
144 | @element.remove()
145 |
146 | attach: ->
147 | if atom.config.get('tree-view.showOnRightSide')
148 | @panel = atom.workspace.addLeftPanel(item: this)
149 | else
150 | @panel = atom.workspace.addRightPanel(item: this)
151 | @contextMenu.attach()
152 | @contextMenu.hide()
153 |
154 | attached: ->
155 | @onChangeEditor = atom.workspace.onDidChangeActivePaneItem (editor) =>
156 | @removeEventForEditor()
157 | @populate()
158 |
159 | @onChangeAutoHide = atom.config.observe 'symbols-tree-view.autoHide', (autoHide) =>
160 | unless autoHide
161 | @off('mouseenter mouseleave')
162 | else
163 | @mouseenter (event) =>
164 | @stop()
165 | @animate({width: @originalWidth}, duration: @animationDuration)
166 |
167 | @mouseleave (event) =>
168 | @stop()
169 | if atom.config.get('tree-view.showOnRightSide')
170 | @animate({width: @minimalWidth}, duration: @animationDuration) if event.offsetX > 0
171 | else
172 | @animate({width: @minimalWidth}, duration: @animationDuration) if event.offsetX <= 0
173 |
174 | @on "contextmenu", (event) =>
175 | left = event.pageX
176 | if left + @contextMenu.width() > atom.getSize().width
177 | left = left - @contextMenu.width()
178 | @contextMenu.css({left: left, top: event.pageY})
179 | @contextMenu.show()
180 | return false #disable original atom context menu
181 |
182 | removeEventForEditor: ->
183 | @onEditorSave?.dispose()
184 | @onChangeRow?.dispose()
185 |
186 | detached: ->
187 | @onChangeEditor?.dispose()
188 | @onChangeAutoHide?.dispose()
189 | @removeEventForEditor()
190 | @off "contextmenu"
191 |
192 | remove: ->
193 | super
194 | @panel.destroy()
195 |
196 | # Toggle the visibility of this view
197 | toggle: ->
198 | if @hasParent()
199 | @remove()
200 | else
201 | @populate()
202 | @attach()
203 |
204 | # Show view if hidden
205 | showView: ->
206 | if not @hasParent()
207 | @populate()
208 | @attach()
209 |
210 | # Hide view if visisble
211 | hideView: ->
212 | if @hasParent()
213 | @remove()
214 |
--------------------------------------------------------------------------------
/lib/tag-generator.coffee:
--------------------------------------------------------------------------------
1 | {BufferedProcess, Point} = require 'atom'
2 | Q = require 'q'
3 | path = require 'path'
4 |
5 | module.exports =
6 | class TagGenerator
7 | constructor: (@path, @scopeName) ->
8 |
9 | parseTagLine: (line) ->
10 | sections = line.split('\t')
11 | if sections.length > 3
12 | tag = {
13 | position: new Point(parseInt(sections[2]) - 1)
14 | name: sections[0]
15 | type: sections[3]
16 | parent: null
17 | }
18 | if sections.length > 4 and sections[4].search('signature:') == -1
19 | tag.parent = sections[4]
20 | if @getLanguage() == 'Python' and tag.type == 'member'
21 | tag.type = 'function'
22 | return tag
23 | else
24 | return null
25 |
26 | getLanguage: ->
27 | return 'Cson' if path.extname(@path) in ['.cson', '.gyp']
28 |
29 | {
30 | 'source.c' : 'C'
31 | 'source.cpp' : 'C++'
32 | 'source.clojure' : 'Lisp'
33 | 'source.coffee' : 'CoffeeScript'
34 | 'source.css' : 'Css'
35 | 'source.css.less' : 'Css'
36 | 'source.css.scss' : 'Css'
37 | 'source.gfm' : 'Markdown'
38 | 'source.go' : 'Go'
39 | 'source.java' : 'Java'
40 | 'source.js' : 'JavaScript'
41 | 'source.js.jsx' : 'JavaScript'
42 | 'source.jsx' : 'JavaScript'
43 | 'source.json' : 'Json'
44 | 'source.makefile' : 'Make'
45 | 'source.objc' : 'C'
46 | 'source.objcpp' : 'C++'
47 | 'source.python' : 'Python'
48 | 'source.ruby' : 'Ruby'
49 | 'source.sass' : 'Sass'
50 | 'source.yaml' : 'Yaml'
51 | 'text.html' : 'Html'
52 | 'text.html.php' : 'Php'
53 | 'source.livecodescript' : 'LiveCode'
54 | 'source.scilab' : 'Scilab' # Scilab
55 | 'source.matlab' : 'Scilab' # Matlab
56 | 'source.octave' : 'Scilab' # GNU Octave
57 |
58 | # For backward-compatibility with Atom versions < 0.166
59 | 'source.c++' : 'C++'
60 | 'source.objc++' : 'C++'
61 | }[@scopeName]
62 |
63 | generate: ->
64 | deferred = Q.defer()
65 | tags = []
66 | command = path.resolve(__dirname, '..', 'vendor', "universal-ctags-#{process.platform}")
67 | defaultCtagsFile = require.resolve('./.ctags')
68 | args = ["--options=#{defaultCtagsFile}", '--fields=KsS']
69 |
70 | if atom.config.get('symbols-view.useEditorGrammarAsCtagsLanguage')
71 | if language = @getLanguage()
72 | args.push("--language-force=#{language}")
73 |
74 | args.push('-nf', '-', @path)
75 |
76 | stdout = (lines) =>
77 | for line in lines.split('\n')
78 | if tag = @parseTagLine(line.trim())
79 | tags.push(tag)
80 | stderr = (lines) ->
81 | exit = ->
82 | deferred.resolve(tags)
83 |
84 | new BufferedProcess({command, args, stdout, stderr, exit})
85 |
86 | deferred.promise
87 |
--------------------------------------------------------------------------------
/lib/tag-parser.coffee:
--------------------------------------------------------------------------------
1 | {Point} = require 'atom'
2 |
3 | module.exports =
4 | class TagParser
5 | constructor: (tags, grammar) ->
6 | @tags = tags
7 | @grammar = grammar
8 |
9 | #splitSymbol = '::' for c/c++, and '.' for others.
10 | if @grammar == 'source.c++' or @grammar == 'source.c' or
11 | @grammar == 'source.cpp'
12 | @splitSymbol = '::'
13 | else
14 | @splitSymbol = '.'
15 |
16 | splitParentTag: (parentTag) ->
17 | index = parentTag.indexOf(':')
18 |
19 | type: parentTag.substr(0, index)
20 | parent: parentTag.substr(index+1)
21 |
22 | splitNameTag: (nameTag) ->
23 | index = nameTag.lastIndexOf(@splitSymbol)
24 | if index >= 0
25 | return nameTag.substr(index+@splitSymbol.length)
26 | else
27 | return nameTag
28 |
29 | buildMissedParent: (parents) ->
30 | parentTags = Object.keys(parents)
31 | parentTags.sort (a, b) =>
32 | {typeA, parent: nameA} = @splitParentTag(a)
33 | {typeB, parent: nameB} = @splitParentTag(b)
34 |
35 | if nameA < nameB
36 | return -1
37 | else if nameA > nameB
38 | return 1
39 | else
40 | return 0
41 |
42 | for now, i in parentTags
43 | {type, parent: name} = @splitParentTag(now)
44 |
45 | if parents[now] is null
46 | parents[now] = {
47 | name: name,
48 | type: type,
49 | position: null,
50 | parent: null
51 | }
52 |
53 | @tags.push(parents[now])
54 |
55 | if i >= 1
56 | pre = parentTags[i-1]
57 | {type, parent: name} = @splitParentTag(pre)
58 | if now.indexOf(name) >= 0
59 | parents[now].parent = pre
60 | parents[now].name = @splitNameTag(parents[now].name)
61 |
62 | parse: ->
63 | roots = []
64 | parents = {}
65 | types = {}
66 |
67 | # sort tags by row number
68 | @tags.sort (a, b) =>
69 | return a.position.row - b.position.row
70 |
71 | # try to find out all tags with parent information
72 | for tag in @tags
73 | parents[tag.parent] = null if tag.parent
74 |
75 | # try to build up relationships between parent information and the real tag
76 | for tag in @tags
77 | if tag.parent
78 | {type, parent} = @splitParentTag(tag.parent)
79 | key = tag.type + ':' + parent + @splitSymbol + tag.name
80 | else
81 | key = tag.type + ':' + tag.name
82 | parents[key] = tag
83 |
84 | # try to build up the missed parent
85 | @buildMissedParent(parents)
86 |
87 | for tag in @tags
88 | if tag.parent
89 | parent = parents[tag.parent]
90 | unless parent.position
91 | parent.position = new Point(tag.position.row-1)
92 |
93 | @tags.sort (a, b) =>
94 | return a.position.row - b.position.row
95 |
96 | for tag in @tags
97 | tag.label = tag.name
98 | tag.icon = "icon-#{tag.type}"
99 | if tag.parent
100 | parent = parents[tag.parent]
101 | parent.children ?= []
102 | parent.children.push(tag)
103 | else
104 | roots.push(tag)
105 | types[tag.type] = null
106 |
107 | return {root: {label: 'root', icon: null, children: roots}, types: Object.keys(types)}
108 |
109 | getNearestTag: (row) ->
110 | left = 0
111 | right = @tags.length-1
112 | while left <= right
113 | mid = (left + right) // 2
114 | midRow = @tags[mid].position.row
115 |
116 | if row < midRow
117 | right = mid - 1
118 | else
119 | left = mid + 1
120 |
121 | nearest = left - 1
122 | return @tags[nearest]
123 |
--------------------------------------------------------------------------------
/lib/tree-view.coffee:
--------------------------------------------------------------------------------
1 | {$, $$, View, ScrollView} = require 'atom-space-pen-views'
2 | {Emitter} = require 'event-kit'
3 |
4 | module.exports =
5 | TreeNode: class TreeNode extends View
6 | @content: ({label, icon, children}) ->
7 | if children
8 | @li class: 'list-nested-item list-selectable-item', =>
9 | @div class: 'list-item', =>
10 | @span class: "icon #{icon}", label
11 | @ul class: 'list-tree', =>
12 | for child in children
13 | @subview 'child', new TreeNode(child)
14 | else
15 | @li class: 'list-item list-selectable-item', =>
16 | @span class: "icon #{icon}", label
17 |
18 | initialize: (item) ->
19 | @emitter = new Emitter
20 | @item = item
21 | @item.view = this
22 |
23 | @on 'dblclick', @dblClickItem
24 | @on 'click', @clickItem
25 |
26 | setCollapsed: ->
27 | @toggleClass('collapsed') if @item.children
28 |
29 | setSelected: ->
30 | @addClass('selected')
31 |
32 | onDblClick: (callback) ->
33 | @emitter.on 'on-dbl-click', callback
34 | if @item.children
35 | for child in @item.children
36 | child.view.onDblClick callback
37 |
38 | onSelect: (callback) ->
39 | @emitter.on 'on-select', callback
40 | if @item.children
41 | for child in @item.children
42 | child.view.onSelect callback
43 |
44 | clickItem: (event) =>
45 | if @item.children
46 | selected = @hasClass('selected')
47 | @removeClass('selected')
48 | $target = @find('.list-item:first')
49 | left = $target.position().left
50 | right = $target.children('span').position().left
51 | width = right - left
52 | @toggleClass('collapsed') if event.offsetX <= width
53 | @addClass('selected') if selected
54 | return false if event.offsetX <= width
55 |
56 | @emitter.emit 'on-select', {node: this, item: @item}
57 | return false
58 |
59 | dblClickItem: (event) =>
60 | @emitter.emit 'on-dbl-click', {node: this, item: @item}
61 | return false
62 |
63 |
64 | TreeView: class TreeView extends ScrollView
65 | @content: ->
66 | @div class: '-tree-view-', =>
67 | @ul class: 'list-tree has-collapsable-children', outlet: 'root'
68 |
69 | initialize: ->
70 | super
71 | @emitter = new Emitter
72 |
73 | deactivate: ->
74 | @remove()
75 |
76 | onSelect: (callback) =>
77 | @emitter.on 'on-select', callback
78 |
79 | setRoot: (root, ignoreRoot=true) ->
80 | @rootNode = new TreeNode(root)
81 |
82 | @rootNode.onDblClick ({node, item}) =>
83 | node.setCollapsed()
84 | @rootNode.onSelect ({node, item}) =>
85 | @clearSelect()
86 | node.setSelected()
87 | @emitter.emit 'on-select', {node, item}
88 |
89 | @root.empty()
90 | @root.append $$ ->
91 | @div =>
92 | if ignoreRoot
93 | for child in root.children
94 | @subview 'child', child.view
95 | else
96 | @subview 'root', root.view
97 |
98 | traversal: (root, doing) =>
99 | doing(root.item)
100 | if root.item.children
101 | for child in root.item.children
102 | @traversal(child.view, doing)
103 |
104 | toggleTypeVisible: (type) =>
105 | @traversal @rootNode, (item) =>
106 | if item.type == type
107 | item.view.toggle()
108 |
109 | sortByName: (ascending=true) =>
110 | @traversal @rootNode, (item) =>
111 | item.children?.sort (a, b) =>
112 | if ascending
113 | return a.name.localeCompare(b.name)
114 | else
115 | return b.name.localeCompare(a.name)
116 | @setRoot(@rootNode.item)
117 |
118 | sortByRow: (ascending=true) =>
119 | @traversal @rootNode, (item) =>
120 | item.children?.sort (a, b) =>
121 | if ascending
122 | return a.position.row - b.position.row
123 | else
124 | return b.position.row - a.position.row
125 | @setRoot(@rootNode.item)
126 |
127 | clearSelect: ->
128 | $('.list-selectable-item').removeClass('selected')
129 |
130 | select: (item) ->
131 | @clearSelect()
132 | item?.view.setSelected()
133 |
--------------------------------------------------------------------------------
/menus/symbols-tree-view.cson:
--------------------------------------------------------------------------------
1 | # See https://atom.io/docs/latest/creating-a-package#menus for more details
2 | 'context-menu':
3 | 'atom-text-editor': [
4 | {
5 | 'label': 'Toggle Symbols-Tree-View'
6 | 'command': 'symbols-tree-view:toggle'
7 | }
8 | ]
9 | 'menu': [
10 | {
11 | 'label': 'View'
12 | 'submenu': [
13 | {'label': 'Toggle Symbols-Tree-View', 'command': 'symbols-tree-view:toggle'}
14 | ]
15 | }
16 | ]
17 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "symbols-tree-view",
3 | "main": "./lib/main",
4 | "version": "0.14.0",
5 | "description": "A symbols view like taglist",
6 | "repository": "https://github.com/xndcn/symbols-tree-view",
7 | "providedServices": {
8 | "hyperclick.provider": {
9 | "versions": {
10 | "0.0.0": "getProvider"
11 | }
12 | }
13 | },
14 | "license": "MIT",
15 | "engines": {
16 | "atom": ">0.50.0"
17 | },
18 | "dependencies": {
19 | "atom-space-pen-views": "^2.0.0",
20 | "event-kit": "latest",
21 | "q": "~1.0.1"
22 | },
23 | "keywords": [
24 | "taglist",
25 | "tagbar",
26 | "symbols"
27 | ]
28 | }
29 |
--------------------------------------------------------------------------------
/screencast.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xndcn/symbols-tree-view/9ae8d173351554450077dcabd5f32c0766f8b9e6/screencast.gif
--------------------------------------------------------------------------------
/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xndcn/symbols-tree-view/9ae8d173351554450077dcabd5f32c0766f8b9e6/screenshot.png
--------------------------------------------------------------------------------
/styles/symbols-tree-view.less:
--------------------------------------------------------------------------------
1 | // The ui-variables file is provided by base themes provided by Atom.
2 | //
3 | // See https://github.com/atom/atom-dark-ui/blob/master/stylesheets/ui-variables.less
4 | // for a full listing of what's available.
5 | @import "ui-variables";
6 |
7 | @font-face {
8 | font-family: 'symbol-icons';
9 | src: url('atom://symbols-tree-view/icons/symbol-icons.woff') format('woff');
10 | font-weight: normal;
11 | font-style: normal;
12 | }
13 |
14 | .symbols-tree-view {
15 | width: 200px;
16 | height: 100%;
17 | padding: 4px;
18 | position: relative;
19 | overflow-y: auto;
20 | overflow-x: hidden;
21 | }
22 |
23 | .symbols-context-menu {
24 | position: absolute;
25 | z-index: 1;
26 | width: 120px;
27 | .hidden-input {
28 | position: absolute;
29 | width: 0;
30 | height: 0;
31 | border: none;
32 | }
33 | .select-list.popover-list {
34 | width: 100%;
35 | min-width: 100%;
36 | ol {
37 | margin-top: 0;
38 | .separator {
39 | background: @background-color-highlight;
40 | height: 1px;
41 | }
42 | li:hover {
43 | background: @background-color-highlight;
44 | }
45 | }
46 | }
47 | }
48 |
49 | @symbol-class: '\e600';
50 | @symbol-struct: '\e601';
51 | @symbol-macro: '\e602';
52 | @symbol-typedef: '\e603';
53 | @symbol-union: '\e604';
54 | @symbol-interface:'\e605';
55 | @symbol-enum: '\e606';
56 | @symbol-variable: '\e607';
57 | @symbol-function: '\e608';
58 | @symbol-namespace:'\e609';
59 |
60 | .symbol-icon(@name) {
61 | font-family: 'symbol-icons';
62 | content: @@name;
63 | }
64 |
65 | .symbols-tree-view .icon-function::before {
66 | .symbol-icon(symbol-function);
67 | }
68 |
69 | .symbols-tree-view .icon-class::before {
70 | .symbol-icon(symbol-class);
71 | }
72 |
73 | .symbols-tree-view .icon-namespace::before {
74 | .symbol-icon(symbol-namespace);
75 | }
76 |
77 | .symbols-tree-view .icon-struct::before {
78 | .symbol-icon(symbol-struct);
79 | }
80 |
81 | .symbols-tree-view .icon-variable::before {
82 | .symbol-icon(symbol-variable);
83 | }
84 |
85 | .symbols-tree-view .icon-method::before {
86 | .symbol-icon(symbol-function);
87 | }
88 |
89 | .symbols-tree-view .icon-field::before {
90 | .symbol-icon(symbol-variable);
91 | }
92 |
93 | .symbols-tree-view .icon-member::before {
94 | .symbol-icon(symbol-variable);
95 | }
96 |
97 | .symbols-tree-view .icon-interface::before {
98 | .symbol-icon(symbol-interface);
99 | }
100 |
101 | .symbols-tree-view .icon-enum::before {
102 | .symbol-icon(symbol-enum);
103 | }
104 |
105 | .symbols-tree-view .icon-typedef::before {
106 | .symbol-icon(symbol-typedef);
107 | }
108 |
109 | .symbols-tree-view .icon-macro::before {
110 | .symbol-icon(symbol-macro);
111 | }
112 |
113 | .symbols-tree-view .icon-union::before {
114 | .symbol-icon(symbol-union);
115 | }
116 |
--------------------------------------------------------------------------------
/vendor/universal-ctags-darwin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xndcn/symbols-tree-view/9ae8d173351554450077dcabd5f32c0766f8b9e6/vendor/universal-ctags-darwin
--------------------------------------------------------------------------------
/vendor/universal-ctags-linux:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xndcn/symbols-tree-view/9ae8d173351554450077dcabd5f32c0766f8b9e6/vendor/universal-ctags-linux
--------------------------------------------------------------------------------
/vendor/universal-ctags-win32.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xndcn/symbols-tree-view/9ae8d173351554450077dcabd5f32c0766f8b9e6/vendor/universal-ctags-win32.exe
--------------------------------------------------------------------------------