├── .eslintignore
├── .eslintrc.js
├── .github
└── no-response.yml
├── .gitignore
├── .pairs
├── .travis.yml
├── CONTRIBUTING.md
├── ISSUE_TEMPLATE.md
├── LICENSE.md
├── PULL_REQUEST_TEMPLATE.md
├── README.md
├── appveyor.yml
├── keymaps
└── symbols-view.cson
├── lib
├── ctags-config
├── file-view.js
├── get-tags-file.js
├── go-back-view.js
├── go-to-view.js
├── load-tags-handler.js
├── main.js
├── project-view.js
├── symbols-view.js
├── tag-generator.js
└── tag-reader.js
├── menus
└── symbols-view.cson
├── package-lock.json
├── package.json
├── spec
├── async-spec-helpers.js
├── fixtures
│ ├── c
│ │ ├── sample.c
│ │ └── tags
│ ├── js
│ │ ├── sample.js
│ │ ├── tagged-duplicate.js
│ │ ├── tagged.js
│ │ └── tags
│ └── ruby
│ │ ├── file1.rb
│ │ └── tags
└── symbols-view-spec.js
├── styles
└── symbols-view.less
└── vendor
├── ctags-darwin
├── ctags-linux
└── ctags-win32.exe
/.eslintignore:
--------------------------------------------------------------------------------
1 | **/fixtures/**/*.js
2 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | parser: 'babel-eslint',
3 | extends: 'fbjs',
4 | globals: {
5 | atom: true
6 | }
7 | };
8 |
--------------------------------------------------------------------------------
/.github/no-response.yml:
--------------------------------------------------------------------------------
1 | # Configuration for probot-no-response - https://github.com/probot/no-response
2 |
3 | # Number of days of inactivity before an issue is closed for lack of response
4 | daysUntilClose: 28
5 |
6 | # Label requiring a response
7 | responseRequiredLabel: more-information-needed
8 |
9 | # Comment to post when closing an issue for lack of response. Set to `false` to disable.
10 | closeComment: >
11 | This issue has been automatically closed because there has been no response
12 | to our request for more information from the original author. With only the
13 | information that is currently in the issue, we don't have enough information
14 | to take action. Please reach out if you have or find the answers we need so
15 | that we can investigate further.
16 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
--------------------------------------------------------------------------------
/.pairs:
--------------------------------------------------------------------------------
1 | pairs:
2 | ns: Nathan Sobo; nathan
3 | cj: Corey Johnson; cj
4 | dg: David Graham; dgraham
5 | ks: Kevin Sawicki; kevin
6 | jc: Jerry Cheung; jerry
7 | bl: Brian Lopez; brian
8 | jp: Justin Palmer; justin
9 | gt: Garen Torikian; garen
10 | mc: Matt Colyer; mcolyer
11 | bo: Ben Ogle; benogle
12 | jr: Jason Rudolph; jasonrudolph
13 | jl: Jessica Lord; jlord
14 | email:
15 | domain: github.com
16 | #global: true
17 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: objective-c
2 |
3 | notifications:
4 | email:
5 | on_success: never
6 | on_failure: change
7 |
8 | script: 'curl -s https://raw.githubusercontent.com/atom/ci/master/build-package.sh | sh'
9 |
10 | git:
11 | depth: 10
12 |
13 | branches:
14 | only:
15 | - master
16 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | See the [Atom contributing guide](https://github.com/atom/atom/blob/master/CONTRIBUTING.md)
2 |
--------------------------------------------------------------------------------
/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
8 |
9 | ### Prerequisites
10 |
11 | * [ ] Put an X between the brackets on this line if you have done all of the following:
12 | * Reproduced the problem in Safe Mode: http://flight-manual.atom.io/hacking-atom/sections/debugging/#using-safe-mode
13 | * Followed all applicable steps in the debugging guide: http://flight-manual.atom.io/hacking-atom/sections/debugging/
14 | * Checked the FAQs on the message board for common solutions: https://discuss.atom.io/c/faq
15 | * Checked that your issue isn't already filed: https://github.com/issues?utf8=✓&q=is%3Aissue+user%3Aatom
16 | * Checked that there is not already an Atom package that provides the described functionality: https://atom.io/packages
17 |
18 | ### Description
19 |
20 | [Description of the issue]
21 |
22 | ### Steps to Reproduce
23 |
24 | 1. [First Step]
25 | 2. [Second Step]
26 | 3. [and so on...]
27 |
28 | **Expected behavior:** [What you expect to happen]
29 |
30 | **Actual behavior:** [What actually happens]
31 |
32 | **Reproduces how often:** [What percentage of the time does it reproduce?]
33 |
34 | ### Versions
35 |
36 | You can get this information from copy and pasting the output of `atom --version` and `apm --version` from the command line. Also, please include the OS and what version of the OS you're running.
37 |
38 | ### Additional Information
39 |
40 | Any additional information, configuration or data that might be necessary to reproduce the issue.
41 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | Copyright (c) 2014 GitHub Inc.
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 |
--------------------------------------------------------------------------------
/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ### Requirements
2 |
3 | * Filling out the template is required. Any pull request that does not include enough information to be reviewed in a timely manner may be closed at the maintainers' discretion.
4 | * All new code requires tests to ensure against regressions
5 |
6 | ### Description of the Change
7 |
8 |
13 |
14 | ### Alternate Designs
15 |
16 |
17 |
18 | ### Benefits
19 |
20 |
21 |
22 | ### Possible Drawbacks
23 |
24 |
25 |
26 | ### Applicable Issues
27 |
28 |
29 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ##### Atom and all repositories under Atom will be archived on December 15, 2022. Learn more in our [official announcement](https://github.blog/2022-06-08-sunsetting-atom/)
2 | # Symbols View package
3 | [](https://travis-ci.org/atom/symbols-view) [](https://ci.appveyor.com/project/Atom/symbols-view/branch/master) [](https://david-dm.org/atom/symbols-view)
4 |
5 | Display the list of functions/methods in the editor.
6 |
7 | If your project has a `tags`/`.tags`/`TAGS`/`.TAGS` file at the root then following are supported:
8 |
9 | |Command|Description|Keybinding (Linux)|Keybinding (macOS)|Keybinding (Windows)|
10 | |-------|-----------|------------------|-----------------|--------------------|
11 | |`symbols-view:toggle-file-symbols`|Show all symbols in current file|ctrl-r|cmd-r|ctrl-r|
12 | |`symbols-view:toggle-project-symbols`|Show all symbols in the project|ctrl-shift-r|cmd-shift-r|ctrl-shift-r|
13 | |`symbols-view:go-to-declaration`|Jump to the symbol under the cursor|ctrl-alt-down|cmd-alt-down||
14 | |`symbols-view:return-from-declaration`|Return from the jump|ctrl-alt-up|cmd-alt-up||
15 |
16 | This package uses [ctags](http://ctags.sourceforge.net).
17 |
18 | 
19 |
--------------------------------------------------------------------------------
/appveyor.yml:
--------------------------------------------------------------------------------
1 | image: Visual Studio 2015
2 |
3 | version: "{build}"
4 |
5 | platform: x64
6 |
7 | branches:
8 | only:
9 | - master
10 |
11 | clone_depth: 10
12 |
13 | skip_tags: true
14 |
15 | environment:
16 | APM_TEST_PACKAGES:
17 |
18 | matrix:
19 | - ATOM_CHANNEL: stable
20 | - ATOM_CHANNEL: beta
21 |
22 | install:
23 | - ps: Install-Product node 4
24 |
25 | build_script:
26 | - ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/atom/ci/master/build-package.ps1'))
27 |
28 | test: off
29 | deploy: off
30 |
--------------------------------------------------------------------------------
/keymaps/symbols-view.cson:
--------------------------------------------------------------------------------
1 | '.platform-darwin atom-text-editor':
2 | 'cmd-r': 'symbols-view:toggle-file-symbols'
3 | 'cmd-alt-down': 'symbols-view:go-to-declaration'
4 | 'cmd-alt-up': 'symbols-view:return-from-declaration'
5 |
6 | '.platform-win32 atom-text-editor':
7 | 'ctrl-r': 'symbols-view:toggle-file-symbols'
8 |
9 | '.platform-linux atom-text-editor':
10 | 'ctrl-r': 'symbols-view:toggle-file-symbols'
11 | 'ctrl-alt-down': 'symbols-view:go-to-declaration'
12 | 'ctrl-alt-up': 'symbols-view:return-from-declaration'
13 |
14 | '.platform-darwin':
15 | 'cmd-shift-r': 'symbols-view:toggle-project-symbols'
16 |
17 | '.platform-win32, .platform-linux':
18 | 'ctrl-shift-r': 'symbols-view:toggle-project-symbols'
19 |
--------------------------------------------------------------------------------
/lib/ctags-config:
--------------------------------------------------------------------------------
1 | --langdef=CoffeeScript
2 | --langmap=CoffeeScript:.coffee
3 | --regex-CoffeeScript=/^[ \t]*(@?[a-zA-Z$_\.0-9]+)[ \t]*(=|\:)[ \t]*(\(.*\))?[ \t]*(-|=)>/\1/f,function/
4 | --regex-CoffeeScript=/^[ \t]*([a-zA-Z$_0-9]+\:\:[a-zA-Z$_\.0-9]+)[ \t]*(=|\:)[ \t]*(\(.*\))?[ \t]*(-|=)>/\1/f,function/
5 | --regex-CoffeeScript=/^[ \t]*describe[ \t]"(.+)"[ \t]*,[ \t]+[-=]>/\1/f,function/
6 | --regex-CoffeeScript=/^[ \t]*describe[ \t]'(.+)'[ \t]*,[ \t]+[-=]>/\1/f,function/
7 | --regex-CoffeeScript=/^[ \t]*it[ \t]"([^"]+)"[ \t]*,[ \t]+[-=]>/\1/f,function/
8 | --regex-CoffeeScript=/^[ \t]*it[ \t]'([^']+)'[ \t]*,[ \t]+[-=]>/\1/f,function/
9 | --regex-CoffeeScript=/^[ \t]*f+describe[ \t]"(.+)"[ \t]*,[ \t]+[-=]>/focused\: \1/f,function/
10 | --regex-CoffeeScript=/^[ \t]*f+describe[ \t]'(.+)'[ \t]*,[ \t]+[-=]>/focused: \1/f,function/
11 | --regex-CoffeeScript=/^[ \t]*f+it[ \t]"([^"]+)"[ \t]*,[ \t]+[-=]>/focused: \1/f,function/
12 | --regex-CoffeeScript=/^[ \t]*f+it[ \t]'([^']+)'[ \t]*,[ \t]+[-=]>/focused: \1/f,function/
13 | --regex-CoffeeScript=/^[ \t]*xdescribe[ \t]"(.+)"[ \t]*,[ \t]+[-=]>/disabled\: \1/f,function/
14 | --regex-CoffeeScript=/^[ \t]*xdescribe[ \t]'(.+)'[ \t]*,[ \t]+[-=]>/disabled: \1/f,function/
15 | --regex-CoffeeScript=/^[ \t]*xit[ \t]"([^"]+)"[ \t]*,[ \t]+[-=]>/disabled: \1/f,function/
16 | --regex-CoffeeScript=/^[ \t]*xit[ \t]'([^']+)'[ \t]*,[ \t]+[-=]>/disabled: \1/f,function/
17 | --regex-CoffeeScript=/^[ \t]*class[ \t]*([a-zA-Z$_\.0-9]+)[ \t]*/\1/f,function/
18 |
19 | --langdef=ColdFusion
20 | --langmap=ColdFusion:.cfc
21 | --langmap=ColdFusion:+.cfm
22 | --langmap=ColdFusion:+.cfml
23 | --regex-ColdFusion=/(,|(;|^)[ \t]*(var|([A-Za-z_$][A-Za-z0-9_$.]*\.)*))[ \t]*([A-Za-z0-9_$]+)[ \t]*=[ \t]*function[ \t]*\(/\5/,function/
24 | --regex-ColdFusion=/function[ \t]+([A-Za-z0-9_$]+)[ \t]*\([^)]*\)/\1/,function/
25 | --regex-ColdFusion=/cffunction[ \t]+([A-Za-z0-9_$]+)[ \t]*\([^)]*\)/\1/,cffunction/
26 | --regex-ColdFusion=/(,|^|\*\/)[ \t]*([A-Za-z_$][A-Za-z0-9_$]+)[ \t]*:[ \t]*function[ \t]*\(/\2/,function/
27 | --regex-ColdFusion=/(,|^|\*\/)[ \t]*(static[ \t]+)?(while|if|for|function|switch|with|([A-Za-z_$][A-Za-z0-9_$]+))[ \t]*\(.*\)[ \t]*\{/\2\4/,function/
28 | --regex-ColdFusion=/(,|^|\*\/)[ \t]*get[ \t]+([A-Za-z_$][A-Za-z0-9_$]+)[ \t]*\([ \t]*\)[ \t]*\{/get \2/,function/
29 | --regex-ColdFusion=/(,|^|\*\/)[ \t]*set[ \t]+([A-Za-z_$][A-Za-z0-9_$]+)[ \t]*\([ \t]*([A-Za-z_$][A-Za-z0-9_$]+)?[ \t]*\)[ \t]*\{/set \2/,function/
30 | --regex-ColdFusion=/(,|^|\*\/)[ \t]*async[ \t]+([A-Za-z_$][A-Za-z0-9_$]+)[ \t]*\([ \t]*([A-Za-z_$].+)?[ \t]*\)[ \t]*\{/\2/,function/
31 | --regex-ColdFusion=/component[ \t]+([A-Za-z0-9._$]+)[ \t]*/\1/c,component/
32 | --regex-ColdFusion=/^[ \t]*given[ \t]"(.+)"[ \t]*,[ \t]+[-=]>/\1/f,function/
33 | --regex-ColdFusion=/^[ \t]*given[ \t]'(.+)'[ \t]*,[ \t]+[-=]>/\1/f,function/
34 | --regex-ColdFusion=/^[ \t]*story[ \t]"(.+)"[ \t]*,[ \t]+[-=]>/\1/f,function/
35 | --regex-ColdFusion=/^[ \t]*story[ \t]"(.+)"[ \t]*,[ \t]+[-=]>/\1/f,function/
36 | --regex-ColdFusion=/^[ \t]*feature[ \t]'(.+)'[ \t]*,[ \t]+[-=]>/\1/f,function/
37 | --regex-ColdFusion=/^[ \t]*feature[ \t]'(.+)'[ \t]*,[ \t]+[-=]>/\1/f,function/
38 | --regex-ColdFusion=/^[ \t]*when[ \t]"(.+)"[ \t]*,[ \t]+[-=]>/\1/f,function/
39 | --regex-ColdFusion=/^[ \t]*when[ \t]'(.+)'[ \t]*,[ \t]+[-=]>/\1/f,function/
40 | --regex-ColdFusion=/^[ \t]*then[ \t]"(.+)"[ \t]*,[ \t]+[-=]>/\1/f,function/
41 | --regex-ColdFusion=/^[ \t]*then[ \t]'(.+)'[ \t]*,[ \t]+[-=]>/\1/f,function/
42 | --regex-ColdFusion=/^[ \t]*describe[ \t]"(.+)"[ \t]*,[ \t]+[-=]>/\1/f,function/
43 | --regex-ColdFusion=/^[ \t]*describe[ \t]'(.+)'[ \t]*,[ \t]+[-=]>/\1/f,function/
44 | --regex-ColdFusion=/^[ \t]*it[ \t]"([^"]+)"[ \t]*,[ \t]+[-=]>/\1/f,function/
45 | --regex-ColdFusion=/^[ \t]*it[ \t]'([^']+)'[ \t]*,[ \t]+[-=]>/\1/f,function/
46 | --regex-ColdFusion=/^[ \t]*xdescribe[ \t]"(.+)"[ \t]*,[ \t]+[-=]>/disabled\: \1/f,function/
47 | --regex-ColdFusion=/^[ \t]*xdescribe[ \t]'(.+)'[ \t]*,[ \t]+[-=]>/disabled: \1/f,function/
48 | --regex-ColdFusion=/^[ \t]*xit[ \t]"([^"]+)"[ \t]*,[ \t]+[-=]>/disabled: \1/f,function/
49 | --regex-ColdFusion=/^[ \t]*xit[ \t]'([^']+)'[ \t]*,[ \t]+[-=]>/disabled: \1/f,function/
50 |
51 | --langdef=Css
52 | --langmap=Css:.css
53 | --langmap=Css:+.less
54 | --langmap=Css:+.scss
55 | --regex-Css=/^[ \t]*(.+)[ \t]*\{/\1/f,function/
56 | --regex-Css=/^[ \t]*(.+)[ \t]*,[ \t]*$/\1/f,function/
57 | --regex-Css=/^[ \t]*[@$]([a-zA-Z$_][-a-zA-Z$_0-9]*)[ \t]*:/\1/f,function/
58 |
59 | --langdef=Sass
60 | --langmap=Sass:.sass
61 | --regex-Sass=/^[ \t]*([#.]*[a-zA-Z_0-9]+)[ \t]*$/\1/f,function/
62 |
63 | --langdef=Yaml
64 | --langmap=Yaml:.yaml
65 | --langmap=Yaml:+.yml
66 | --regex-Yaml=/^[ \t]*([a-zA-Z_0-9 ]+)[ \t]*\:[ \t]*/\1/f,function/
67 |
68 | --regex-Html=/^[ \t]*<([a-zA-Z]+)[ \t]*.*>/\1/f,function/
69 |
70 | --langdef=Markdown
71 | --langmap=Markdown:.md
72 | --langmap=Markdown:+.markdown
73 | --langmap=Markdown:+.mdown
74 | --langmap=Markdown:+.mkd
75 | --langmap=Markdown:+.mkdown
76 | --langmap=Markdown:+.ron
77 | --regex-Markdown=/^#+[ \t]*([^#]+)/\1/f,function/
78 |
79 | --langdef=Json
80 | --langmap=Json:.json
81 | --regex-Json=/^[ \t]*"([^"]+)"[ \t]*\:/\1/f,function/
82 |
83 | --langdef=Cson
84 | --langmap=Cson:.cson
85 | --langmap=Cson:+.gyp
86 | --regex-Cson=/^[ \t]*'([^']+)'[ \t]*\:/\1/f,function/
87 | --regex-Cson=/^[ \t]*"([^"]+)"[ \t]*\:/\1/f,function/
88 | --regex-Cson=/^[ \t]*([^'"]+)[ \t]*\:/\1/f,function/
89 |
90 | --langmap=C++:+.mm
91 |
92 | --langmap=Ruby:+(Rakefile)
93 |
94 | --langmap=Php:+.module
95 |
96 | --langdef=Go
97 | --langmap=Go:.go
98 | --regex-Go=/func([ \t]+\([^)]+\))?[ \t]+([a-zA-Z0-9_]+)/\2/f,func/
99 | --regex-Go=/var[ \t]+([a-zA-Z_][a-zA-Z0-9_]*)/\1/v,var/
100 | --regex-Go=/type[ \t]+([a-zA-Z_][a-zA-Z0-9_]*)/\1/t,type/
101 |
102 | --langdef=Capnp
103 | --langmap=Capnp:.capnp
104 | --regex-Capnp=/struct[ \t]+([A-Za-z]+)/\1/s,struct/
105 | --regex-Capnp=/enum[ \t]+([A-Za-z]+)/\1/e,enum/
106 | --regex-Capnp=/using[ \t]+([A-Za-z]+)[ \t]+=[ \t]+import/\1/u,using/
107 | --regex-Capnp=/const[ \t]+([A-Za-z]+)/\1/c,const/
108 |
109 | --langmap=perl:+.pod
110 | --regex-perl=/with[ \t]+([^;]+)[ \t]*?;/\1/w,role,roles/
111 | --regex-perl=/extends[ \t]+['"]([^'"]+)['"][ \t]*?;/\1/e,extends/
112 | --regex-perl=/use[ \t]+base[ \t]+['"]([^'"]+)['"][ \t]*?;/\1/e,extends/
113 | --regex-perl=/use[ \t]+parent[ \t]+['"]([^'"]+)['"][ \t]*?;/\1/e,extends/
114 | --regex-perl=/Mojo::Base[ \t]+['"]([^'"]+)['"][ \t]*?;/\1/e,extends/
115 | --regex-perl=/^[ \t]*?use[ \t]+([^;]+)[ \t]*?;/\1/u,use,uses/
116 | --regex-perl=/^[ \t]*?require[ \t]+((\w|\:)+)/\1/r,require,requires/
117 | --regex-perl=/^[ \t]*?has[ \t]+['"]?(\w+)['"]?/\1/a,attribute,attributes/
118 | --regex-perl=/^[ \t]*?\*(\w+)[ \t]*?=/\1/a,alias,aliases/
119 | --regex-perl=/->helper\([ \t]?['"]?(\w+)['"]?/\1/h,helper,helpers/
120 | --regex-perl=/^[ \t]*?our[ \t]*?[\$@%](\w+)/\1/o,our,ours/
121 | --regex-perl=/^\=head1[ \t]+(.+)/\1/p,pod,Plain Old Documentation/
122 | --regex-perl=/^\=head2[ \t]+(.+)/-- \1/p,pod,Plain Old Documentation/
123 | --regex-perl=/^\=head[3-5][ \t]+(.+)/---- \1/p,pod,Plain Old Documentation/
124 |
125 | --regex-JavaScript=/(,|(;|^)[ \t]*(var|let|([A-Za-z_$][A-Za-z0-9_$.]*\.)*))[ \t]*([A-Za-z0-9_$]+)[ \t]*=[ \t]*function[ \t]*\(/\5/,function/
126 | --regex-JavaScript=/function[ \t]+([A-Za-z0-9_$]+)[ \t]*\([^)]*\)/\1/,function/
127 | --regex-JavaScript=/(,|^|\*\/)[ \t]*([A-Za-z_$][A-Za-z0-9_$]+)[ \t]*:[ \t]*function[ \t]*\(/\2/,function/
128 | --regex-JavaScript=/(,|^|\*\/)[ \t]*(static[ \t]+)?(while|if|for|function|switch|with|([A-Za-z_$][A-Za-z0-9_$]+))[ \t]*\(.*\)[ \t]*\{/\2\4/,function/
129 | --regex-JavaScript=/(,|^|\*\/)[ \t]*get[ \t]+([A-Za-z_$][A-Za-z0-9_$]+)[ \t]*\([ \t]*\)[ \t]*\{/get \2/,function/
130 | --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/,function/
131 | --regex-JavaScript=/(,|^|\*\/)[ \t]*async[ \t]+([A-Za-z_$][A-Za-z0-9_$]+)[ \t]*\([ \t]*([A-Za-z_$].+)?[ \t]*\)[ \t]*\{/\2/,function/
132 | --regex-JavaScript=/class[ \t]+([A-Za-z0-9._$]+)[ \t]*/\1/c,class/
133 | --regex-JavaScript=/^[ \t]*describe\("([^"]+)"[ \t]*,/\1/f,function/
134 | --regex-JavaScript=/^[ \t]*describe\('([^']+)'[ \t]*,/\1/f,function/
135 | --regex-JavaScript=/^[ \t]*it\("([^"]+)"[ \t]*,/\1/f,function/
136 | --regex-JavaScript=/^[ \t]*it\('([^']+)'[ \t]*,/\1/f,function/
137 | --regex-JavaScript=/^[ \t]*f+describe\('([^']+)'[ \t]*,/focused: \1/f,function/
138 | --regex-JavaScript=/^[ \t]*f+describe\("([^"]+)"[ \t]*,/focused: \1/f,function/
139 | --regex-JavaScript=/^[ \t]*f+it\('([^']+)'[ \t]*,/focused: \1/f,function/
140 | --regex-JavaScript=/^[ \t]*f+it\("([^"]+)"[ \t]*,/focused: \1/f,function/
141 | --regex-JavaScript=/^[ \t]*xdescribe\('([^']+)'[ \t]*,/disabled: \1/f,function/
142 | --regex-JavaScript=/^[ \t]*xdescribe\("([^"]+)"[ \t]*,/disabled: \1/f,function/
143 | --regex-JavaScript=/^[ \t]*xit\('([^']+)'[ \t]*,/disabled: \1/f,function/
144 | --regex-JavaScript=/^[ \t]*xit\("([^"]+)"[ \t]*,/disabled: \1/f,function/
145 |
146 | --langdef=haxe
147 | --langmap=haxe:.hx
148 | --regex-haxe=/^package[ \t]+([A-Za-z0-9_.]+)/\1/p,package/
149 | --regex-haxe=/^[ \t]*[(@:macro|private|public|static|override|inline|dynamic)( \t)]*function[ \t]+([A-Za-z0-9_]+)/\1/f,function/
150 | --regex-haxe=/^[ \t]*([private|public|static|protected|inline][ \t]*)+var[ \t]+([A-Za-z0-9_]+)/\2/v,variable/
151 | --regex-haxe=/^[ \t]*package[ \t]*([A-Za-z0-9_]+)/\1/p,package/
152 | --regex-haxe=/^[ \t]*(extern[ \t]*|@:native\([^)]*\)[ \t]*)*class[ \t]+([A-Za-z0-9_]+)[ \t]*[^\{]*/\2/c,class/
153 | --regex-haxe=/^[ \t]*(extern[ \t]+)?interface[ \t]+([A-Za-z0-9_]+)/\2/i,interface/
154 | --regex-haxe=/^[ \t]*typedef[ \t]+([A-Za-z0-9_]+)/\1/t,typedef/
155 | --regex-haxe=/^[ \t]*enum[ \t]+([A-Za-z0-9_]+)/\1/t,typedef/
156 | --regex-haxe=/^[ \t]*+([A-Za-z0-9_]+)(;|\([^)]*:[^)]*\))/\1/t,enum_field/
157 |
158 | --langdef=Elixir
159 | --langmap=Elixir:.ex.exs
160 | --regex-Elixir=/^[ \t]*def(p?)[ \t]+([a-z_][a-zA-Z0-9_?!]*)/\2/f,functions,functions (def ...)/
161 | --regex-Elixir=/^[ \t]*defcallback[ \t]+([a-z_][a-zA-Z0-9_?!]*)/\1/c,callbacks,callbacks (defcallback ...)/
162 | --regex-Elixir=/^[ \t]*defdelegate[ \t]+([a-z_][a-zA-Z0-9_?!]*)/\1/d,delegates,delegates (defdelegate ...)/
163 | --regex-Elixir=/^[ \t]*defexception[ \t]+([A-Z][a-zA-Z0-9_]*\.)*([A-Z][a-zA-Z0-9_?!]*)/\2/e,exceptions,exceptions (defexception ...)/
164 | --regex-Elixir=/^[ \t]*defimpl[ \t]+([A-Z][a-zA-Z0-9_]*\.)*([A-Z][a-zA-Z0-9_?!]*)/\2/i,implementations,implementations (defimpl ...)/
165 | --regex-Elixir=/^[ \t]*defmacro(p?)[ \t]+([a-z_][a-zA-Z0-9_?!]*)\(/\2/a,macros,macros (defmacro ...)/
166 | --regex-Elixir=/^[ \t]*defmacro(p?)[ \t]+([a-zA-Z0-9_?!]+)?[ \t]+([^ \tA-Za-z0-9_]+)[ \t]*[a-zA-Z0-9_!?!]/\3/o,operators,operators (e.g. "defmacro a <<< b")/
167 | --regex-Elixir=/^[ \t]*defmodule[ \t]+([A-Z][a-zA-Z0-9_]*\.)*([A-Z][a-zA-Z0-9_?!]*)/\2/m,modules,modules (defmodule ...)/
168 | --regex-Elixir=/^[ \t]*defprotocol[ \t]+([A-Z][a-zA-Z0-9_]*\.)*([A-Z][a-zA-Z0-9_?!]*)/\2/p,protocols,protocols (defprotocol...)/
169 | --regex-Elixir=/^[ \t]*Record\.defrecord[ \t]+:([a-zA-Z0-9_]+)/\1/r,records,records (defrecord...)/
170 |
171 | --langdef=Nim
172 | --langmap=Nim:.nim
173 | --regex-Nim=/^[\t\s]*proc\s+([_A-Za-z0-9]+)\**(\[\w+(\:\s+\w+)?\])?\s*\(/\1/f,function/
174 | --regex-Nim=/^[\t\s]*iterator\s+([_A-Za-z0-9]+)\**(\[\w+(\:\s+\w+)?\])?\s*\(/\1/i,iterator/
175 | --regex-Nim=/^[\t\s]*macro\s+([_A-Za-z0-9]+)\**(\[\w+(\:\s+\w+)?\])?\s*\(/\1/m,macro/
176 | --regex-Nim=/^[\t\s]*method\s+([_A-Za-z0-9]+)\**(\[\w+(\:\s+\w+)?\])?\s*\(/\1/h,method/
177 | --regex-Nim=/^[\t\s]*template\s+([_A-Za-z0-9]+)\**(\[\w+(\:\s+\w+)?\])?\s*\(/\1/t,generics/
178 | --regex-Nim=/^[\t\s]*converter\s+([_A-Za-z0-9]+)\**(\[\w+(\:\s+\w+)?\])?\s*\(/\1/c,converter/
179 |
180 | --langdef=Fountain
181 | --langmap=Fountain:.fountain
182 | --langmap=Fountain:+.ftn
183 | --regex-Fountain=/^(([iI][nN][tT]|[eE][xX][tT]|[^\w][eE][sS][tT]|\.|[iI]\.?\/[eE]\.?)([^\n]+))/\1/f,function/
184 |
185 | --langdef=Julia
186 | --langmap=Julia:.jl
187 | --regex-Julia=/^[ \t]*(function|macro|abstract|type|typealias|immutable)[ \t]+([^ \t({[]+).*$/\2/f,function/
188 | --regex-Julia=/^[ \t]*(([^@#$ \t({[]+)|\(([^@#$ \t({[]+)\)|\((\$)\))[ \t]*(\{.*\})?[ \t]*\([^#]*\)[ \t]*=([^=].*$|$)/\2\3\4/f,function/
189 |
190 | --langdef=Latex
191 | --langmap=latex:.tex
192 | --regex-latex=/\\label\{([^}]*)\}/\1/l,label/
193 | --regex-latex=/\\section\{([^}]*)\}/\1/s,section/
194 | --regex-latex=/\\subsection\{([^}]*)\}/\1/t,subsection/
195 | --regex-latex=/\\subsubsection\{([^}]*)\}/\1/u,subsubsection/
196 | --regex-latex=/\\section\*\{([^}]*)\}/\1/s,section/
197 | --regex-latex=/\\subsection\*\{([^}]*)\}/\1/t,subsection/
198 | --regex-latex=/\\subsubsection\*\{([^}]*)\}/\1/u,subsubsection/
199 |
--------------------------------------------------------------------------------
/lib/file-view.js:
--------------------------------------------------------------------------------
1 | /** @babel */
2 |
3 | import { CompositeDisposable } from 'atom';
4 | import SymbolsView from './symbols-view';
5 | import TagGenerator from './tag-generator';
6 | import { match } from 'fuzzaldrin';
7 |
8 | export default class FileView extends SymbolsView {
9 | constructor(stack) {
10 | super(stack);
11 | this.cachedTags = {};
12 | this.watchedEditors = new WeakSet();
13 |
14 | this.editorsSubscription = atom.workspace.observeTextEditors(editor => {
15 | if (this.watchedEditors.has(editor)) return;
16 |
17 | const removeFromCache = () => {
18 | delete this.cachedTags[editor.getPath()];
19 | };
20 | const editorSubscriptions = new CompositeDisposable();
21 | editorSubscriptions.add(editor.onDidChangeGrammar(removeFromCache));
22 | editorSubscriptions.add(editor.onDidSave(removeFromCache));
23 | editorSubscriptions.add(editor.onDidChangePath(removeFromCache));
24 | editorSubscriptions.add(editor.getBuffer().onDidReload(removeFromCache));
25 | editorSubscriptions.add(editor.getBuffer().onDidDestroy(removeFromCache));
26 | editor.onDidDestroy(() => {
27 | this.watchedEditors.delete(editor);
28 | editorSubscriptions.dispose();
29 | });
30 |
31 | this.watchedEditors.add(editor);
32 | });
33 | }
34 |
35 | destroy() {
36 | this.editorsSubscription.dispose();
37 | return super.destroy();
38 | }
39 |
40 | elementForItem({position, name}) {
41 | // Style matched characters in search results
42 | const matches = match(name, this.selectListView.getFilterQuery());
43 |
44 | const li = document.createElement('li');
45 | li.classList.add('two-lines');
46 |
47 | const primaryLine = document.createElement('div');
48 | primaryLine.classList.add('primary-line');
49 | primaryLine.appendChild(SymbolsView.highlightMatches(this, name, matches));
50 | li.appendChild(primaryLine);
51 |
52 | const secondaryLine = document.createElement('div');
53 | secondaryLine.classList.add('secondary-line');
54 | secondaryLine.textContent = `Line ${position.row + 1}`;
55 | li.appendChild(secondaryLine);
56 |
57 | return li;
58 | }
59 |
60 | didChangeSelection(item) {
61 | if (atom.config.get('symbols-view.quickJumpToFileSymbol') && item) {
62 | this.openTag(item);
63 | }
64 | }
65 |
66 | async didCancelSelection() {
67 | await this.cancel();
68 | const editor = this.getEditor();
69 | if (this.initialState && editor) {
70 | this.deserializeEditorState(editor, this.initialState);
71 | }
72 | this.initialState = null;
73 | }
74 |
75 | async toggle() {
76 | if (this.panel.isVisible()) {
77 | await this.cancel();
78 | }
79 | const filePath = this.getPath();
80 | if (filePath) {
81 | const editor = this.getEditor();
82 | if (atom.config.get('symbols-view.quickJumpToFileSymbol') && editor) {
83 | this.initialState = this.serializeEditorState(editor);
84 | }
85 | this.populate(filePath);
86 | this.attach();
87 | }
88 | }
89 |
90 | serializeEditorState(editor) {
91 | const editorElement = atom.views.getView(editor);
92 | const scrollTop = editorElement.getScrollTop();
93 |
94 | return {
95 | bufferRanges: editor.getSelectedBufferRanges(),
96 | scrollTop,
97 | };
98 | }
99 |
100 | deserializeEditorState(editor, {bufferRanges, scrollTop}) {
101 | const editorElement = atom.views.getView(editor);
102 |
103 | editor.setSelectedBufferRanges(bufferRanges);
104 | editorElement.setScrollTop(scrollTop);
105 | }
106 |
107 | getEditor() {
108 | return atom.workspace.getActiveTextEditor();
109 | }
110 |
111 | getPath() {
112 | if (this.getEditor()) {
113 | return this.getEditor().getPath();
114 | }
115 | return undefined;
116 | }
117 |
118 | getScopeName() {
119 | if (this.getEditor() && this.getEditor().getGrammar()) {
120 | return this.getEditor().getGrammar().scopeName;
121 | }
122 | return undefined;
123 | }
124 |
125 | async populate(filePath) {
126 | const tags = this.cachedTags[filePath];
127 | if (tags) {
128 | await this.selectListView.update({items: tags});
129 | } else {
130 | await this.selectListView.update({
131 | items: [],
132 | loadingMessage: 'Generating symbols\u2026',
133 | });
134 | await this.selectListView.update({
135 | items: await this.generateTags(filePath),
136 | loadingMessage: null,
137 | });
138 | }
139 | }
140 |
141 | async generateTags(filePath) {
142 | const generator = new TagGenerator(filePath, this.getScopeName());
143 | this.cachedTags[filePath] = await generator.generate();
144 | return this.cachedTags[filePath];
145 | }
146 | }
147 |
--------------------------------------------------------------------------------
/lib/get-tags-file.js:
--------------------------------------------------------------------------------
1 | /** @babel */
2 |
3 | import path from 'path';
4 | import fs from 'fs-plus';
5 |
6 | const files = ['tags', 'TAGS', '.tags', '.TAGS', path.join('.git', 'tags'), path.join('.git', 'TAGS')];
7 | export default function(directoryPath) {
8 | if (!directoryPath) {
9 | return undefined;
10 | }
11 |
12 | for (const file of files) {
13 | const tagsFile = path.join(directoryPath, file);
14 | if (fs.isFileSync(tagsFile)) {
15 | return tagsFile;
16 | }
17 | }
18 |
19 | return undefined;
20 | }
21 |
--------------------------------------------------------------------------------
/lib/go-back-view.js:
--------------------------------------------------------------------------------
1 | /** @babel */
2 |
3 | import SymbolsView from './symbols-view';
4 |
5 | export default class GoBackView extends SymbolsView {
6 | toggle() {
7 | const previousTag = this.stack.pop();
8 | if (!previousTag) {
9 | return;
10 | }
11 |
12 | const restorePosition = () => {
13 | if (previousTag.position) {
14 | this.moveToPosition(previousTag.position, false);
15 | }
16 | };
17 |
18 | const previousEditor = atom.workspace.getTextEditors().find(e => e.id === previousTag.editorId);
19 |
20 | if (previousEditor) {
21 | const pane = atom.workspace.paneForItem(previousEditor);
22 | pane.setActiveItem(previousEditor);
23 | restorePosition();
24 | } else if (previousTag.file) {
25 | atom.workspace.open(previousTag.file).then(restorePosition);
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/lib/go-to-view.js:
--------------------------------------------------------------------------------
1 | /** @babel */
2 |
3 | import path from 'path';
4 | import SymbolsView from './symbols-view';
5 | import TagReader from './tag-reader';
6 |
7 | export default class GoToView extends SymbolsView {
8 | toggle() {
9 | if (this.panel.isVisible()) {
10 | this.cancel();
11 | } else {
12 | this.populate();
13 | }
14 | }
15 |
16 | detached() {
17 | if (this.resolveFindTagPromise) {
18 | this.resolveFindTagPromise([]);
19 | }
20 | }
21 |
22 | findTag(editor) {
23 | if (this.resolveFindTagPromise) {
24 | this.resolveFindTagPromise([]);
25 | }
26 |
27 | return new Promise((resolve, reject) => {
28 | this.resolveFindTagPromise = resolve;
29 | TagReader.find(editor, (error, matches) => {
30 | if (!matches) {
31 | matches = [];
32 | }
33 | if (error) {
34 | return reject(error);
35 | } else {
36 | return resolve(matches);
37 | }
38 | });
39 | });
40 | }
41 |
42 | async populate() {
43 | let editor = atom.workspace.getActiveTextEditor();
44 | if (!editor) {
45 | return;
46 | }
47 |
48 | this.findTag(editor).then(async matches => {
49 | let tags = [];
50 | for (let match of Array.from(matches)) {
51 | let position = this.getTagLine(match);
52 | if (!position) { continue; }
53 | match.name = path.basename(match.file);
54 | tags.push(match);
55 | }
56 |
57 | if (tags.length === 1) {
58 | this.openTag(tags[0]);
59 | } else if (tags.length > 0) {
60 | await this.selectListView.update({items: tags});
61 | this.attach();
62 | }
63 | });
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/lib/load-tags-handler.js:
--------------------------------------------------------------------------------
1 | /** @babel */
2 | /* global emit*/
3 |
4 | import async from 'async';
5 | import ctags from 'ctags';
6 | import getTagsFile from './get-tags-file';
7 |
8 | export default function(directoryPaths) {
9 | return async.each(
10 | directoryPaths,
11 | (directoryPath, done) => {
12 | let tagsFilePath = getTagsFile(directoryPath);
13 | if (!tagsFilePath) { return done(); }
14 |
15 | let stream = ctags.createReadStream(tagsFilePath);
16 | stream.on('data', function(tags) {
17 | for (const tag of Array.from(tags)) { tag.directory = directoryPath; }
18 | return emit('tags', tags);
19 | });
20 | stream.on('end', done);
21 | return stream.on('error', done);
22 | }
23 | , this.async()
24 | );
25 | }
26 |
--------------------------------------------------------------------------------
/lib/main.js:
--------------------------------------------------------------------------------
1 | /** @babel */
2 |
3 | export default {
4 | activate() {
5 | this.stack = [];
6 |
7 | this.workspaceSubscription = atom.commands.add('atom-workspace', {
8 | 'symbols-view:toggle-project-symbols': () => {
9 | this.createProjectView().toggle();
10 | },
11 | });
12 |
13 | this.editorSubscription = atom.commands.add('atom-text-editor', {
14 | 'symbols-view:toggle-file-symbols': () => {
15 | this.createFileView().toggle();
16 | },
17 | 'symbols-view:go-to-declaration': () => {
18 | this.createGoToView().toggle();
19 | },
20 | 'symbols-view:return-from-declaration': () => {
21 | this.createGoBackView().toggle();
22 | },
23 | });
24 | },
25 |
26 | deactivate() {
27 | if (this.fileView != null) {
28 | this.fileView.destroy();
29 | this.fileView = null;
30 | }
31 |
32 | if (this.projectView != null) {
33 | this.projectView.destroy();
34 | this.projectView = null;
35 | }
36 |
37 | if (this.goToView != null) {
38 | this.goToView.destroy();
39 | this.goToView = null;
40 | }
41 |
42 | if (this.goBackView != null) {
43 | this.goBackView.destroy();
44 | this.goBackView = null;
45 | }
46 |
47 | if (this.workspaceSubscription != null) {
48 | this.workspaceSubscription.dispose();
49 | this.workspaceSubscription = null;
50 | }
51 |
52 | if (this.editorSubscription != null) {
53 | this.editorSubscription.dispose();
54 | this.editorSubscription = null;
55 | }
56 | },
57 |
58 | createFileView() {
59 | if (this.fileView) {
60 | return this.fileView;
61 | }
62 | const FileView = require('./file-view');
63 | this.fileView = new FileView(this.stack);
64 | return this.fileView;
65 | },
66 |
67 | createProjectView() {
68 | if (this.projectView) {
69 | return this.projectView;
70 | }
71 | const ProjectView = require('./project-view');
72 | this.projectView = new ProjectView(this.stack);
73 | return this.projectView;
74 | },
75 |
76 | createGoToView() {
77 | if (this.goToView) {
78 | return this.goToView;
79 | }
80 | const GoToView = require('./go-to-view');
81 | this.goToView = new GoToView(this.stack);
82 | return this.goToView;
83 | },
84 |
85 | createGoBackView() {
86 | if (this.goBackView) {
87 | return this.goBackView;
88 | }
89 | const GoBackView = require('./go-back-view');
90 | this.goBackView = new GoBackView(this.stack);
91 | return this.goBackView;
92 | },
93 | };
94 |
--------------------------------------------------------------------------------
/lib/project-view.js:
--------------------------------------------------------------------------------
1 | /** @babel */
2 |
3 | import { CompositeDisposable, File } from 'atom';
4 | import humanize from 'humanize-plus';
5 | import SymbolsView from './symbols-view';
6 | import TagReader from './tag-reader';
7 | import getTagsFile from './get-tags-file';
8 |
9 | export default class ProjectView extends SymbolsView {
10 | constructor(stack) {
11 | super(stack, 'Project has no tags file or it is empty', 10);
12 | this.reloadTags = true;
13 | }
14 |
15 | destroy() {
16 | this.stopTask();
17 | this.unwatchTagsFiles();
18 | return super.destroy();
19 | }
20 |
21 | toggle() {
22 | if (this.panel.isVisible()) {
23 | this.cancel();
24 | } else {
25 | this.populate();
26 | this.attach();
27 | }
28 | }
29 |
30 | async populate() {
31 | if (this.tags) {
32 | await this.selectListView.update({items: this.tags});
33 | }
34 |
35 | if (this.reloadTags) {
36 | this.reloadTags = false;
37 | this.startTask();
38 |
39 | if (this.tags) {
40 | await this.selectListView.update({
41 | loadingMessage: 'Reloading project symbols\u2026',
42 | });
43 | } else {
44 | await this.selectListView.update({
45 | loadingMessage: 'Loading project symbols\u2026',
46 | loadingBadge: 0,
47 | });
48 | let tagsRead = 0;
49 | this.loadTagsTask.on('tags', tags => {
50 | tagsRead += tags.length;
51 | this.selectListView.update({loadingBadge: humanize.intComma(tagsRead)});
52 | });
53 | }
54 | }
55 | }
56 |
57 | stopTask() {
58 | if (this.loadTagsTask) {
59 | this.loadTagsTask.terminate();
60 | }
61 | }
62 |
63 | startTask() {
64 | this.stopTask();
65 |
66 | this.loadTagsTask = TagReader.getAllTags(tags => {
67 | this.tags = tags;
68 | this.reloadTags = this.tags.length === 0;
69 | this.selectListView.update({
70 | loadingMessage: null,
71 | loadingBadge: null,
72 | items: this.tags,
73 | });
74 | });
75 |
76 | this.watchTagsFiles();
77 | }
78 |
79 | watchTagsFiles() {
80 | this.unwatchTagsFiles();
81 |
82 | this.tagsFileSubscriptions = new CompositeDisposable();
83 | let reloadTags = () => {
84 | this.reloadTags = true;
85 | this.watchTagsFiles();
86 | };
87 |
88 | for (const projectPath of Array.from(atom.project.getPaths())) {
89 | const tagsFilePath = getTagsFile(projectPath);
90 | if (tagsFilePath) {
91 | const tagsFile = new File(tagsFilePath);
92 | this.tagsFileSubscriptions.add(tagsFile.onDidChange(reloadTags));
93 | this.tagsFileSubscriptions.add(tagsFile.onDidDelete(reloadTags));
94 | this.tagsFileSubscriptions.add(tagsFile.onDidRename(reloadTags));
95 | }
96 | }
97 | }
98 |
99 | unwatchTagsFiles() {
100 | if (this.tagsFileSubscriptions) {
101 | this.tagsFileSubscriptions.dispose();
102 | }
103 | this.tagsFileSubscriptions = null;
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/lib/symbols-view.js:
--------------------------------------------------------------------------------
1 | /** @babel */
2 |
3 | import path from 'path';
4 | import { Point } from 'atom';
5 | import SelectListView from 'atom-select-list';
6 | import fs from 'fs-plus';
7 | import { match } from 'fuzzaldrin';
8 |
9 | export default class SymbolsView {
10 | static highlightMatches(context, name, matches, offsetIndex) {
11 | if (!offsetIndex) {
12 | offsetIndex = 0;
13 | }
14 | let lastIndex = 0;
15 | let matchedChars = []; // Build up a set of matched chars to be more semantic
16 | const fragment = document.createDocumentFragment();
17 |
18 | for (let matchIndex of Array.from(matches)) {
19 | matchIndex -= offsetIndex;
20 | if (matchIndex < 0) {
21 | continue; // If marking up the basename, omit name matches
22 | }
23 | const unmatched = name.substring(lastIndex, matchIndex);
24 | if (unmatched) {
25 | if (matchedChars.length) {
26 | const span = document.createElement('span');
27 | span.classList.add('character-match');
28 | span.textContent = matchedChars.join('');
29 | fragment.appendChild(span);
30 | }
31 | matchedChars = [];
32 | fragment.appendChild(document.createTextNode(unmatched));
33 | }
34 | matchedChars.push(name[matchIndex]);
35 | lastIndex = matchIndex + 1;
36 | }
37 |
38 | if (matchedChars.length) {
39 | const span = document.createElement('span');
40 | span.classList.add('character-match');
41 | span.textContent = matchedChars.join('');
42 | fragment.appendChild(span);
43 | }
44 |
45 | // Remaining characters are plain text
46 | fragment.appendChild(document.createTextNode(name.substring(lastIndex)));
47 |
48 | return fragment;
49 | }
50 |
51 | constructor(stack, emptyMessage = 'No symbols found', maxResults = null) {
52 | this.stack = stack;
53 | this.selectListView = new SelectListView({
54 | maxResults,
55 | emptyMessage,
56 | items: [],
57 | filterKeyForItem: (item) => item.name,
58 | elementForItem: this.elementForItem.bind(this),
59 | didChangeSelection: this.didChangeSelection.bind(this),
60 | didConfirmSelection: this.didConfirmSelection.bind(this),
61 | didConfirmEmptySelection: this.didConfirmEmptySelection.bind(this),
62 | didCancelSelection: this.didCancelSelection.bind(this),
63 | });
64 | this.element = this.selectListView.element;
65 | this.element.classList.add('symbols-view');
66 | this.panel = atom.workspace.addModalPanel({item: this, visible: false});
67 | }
68 |
69 | async destroy() {
70 | await this.cancel();
71 | this.panel.destroy();
72 | return this.selectListView.destroy();
73 | }
74 |
75 | getFilterKey() {
76 | return 'name';
77 | }
78 |
79 | elementForItem({position, name, file, directory}) {
80 | // Style matched characters in search results
81 | const matches = match(name, this.selectListView.getFilterQuery());
82 |
83 | if (atom.project.getPaths().length > 1) {
84 | file = path.join(path.basename(directory), file);
85 | }
86 |
87 | const li = document.createElement('li');
88 | li.classList.add('two-lines');
89 |
90 | const primaryLine = document.createElement('div');
91 | primaryLine.classList.add('primary-line');
92 | if (position) {
93 | primaryLine.textContent = `${name}:${position.row + 1}`;
94 | } else {
95 | primaryLine.appendChild(SymbolsView.highlightMatches(this, name, matches));
96 | }
97 | li.appendChild(primaryLine);
98 |
99 | const secondaryLine = document.createElement('div');
100 | secondaryLine.classList.add('secondary-line');
101 | secondaryLine.textContent = file;
102 | li.appendChild(secondaryLine);
103 |
104 | return li;
105 | }
106 |
107 | async cancel() {
108 | if (!this.isCanceling) {
109 | this.isCanceling = true;
110 | await this.selectListView.update({items: []});
111 | this.panel.hide();
112 | if (this.previouslyFocusedElement) {
113 | this.previouslyFocusedElement.focus();
114 | this.previouslyFocusedElement = null;
115 | }
116 | this.isCanceling = false;
117 | }
118 | }
119 |
120 | didCancelSelection() {
121 | this.cancel();
122 | }
123 |
124 | didConfirmEmptySelection() {
125 | this.cancel();
126 | }
127 |
128 | async didConfirmSelection(tag) {
129 | if (tag.file && !fs.isFileSync(path.join(tag.directory, tag.file))) {
130 | await this.selectListView.update({errorMessage: 'Selected file does not exist'});
131 | setTimeout(() => {
132 | this.selectListView.update({errorMessage: null});
133 | }, 2000);
134 | } else {
135 | await this.cancel();
136 | this.openTag(tag);
137 | }
138 | }
139 |
140 | didChangeSelection(tag) {
141 | // no-op
142 | }
143 |
144 | openTag(tag) {
145 | const editor = atom.workspace.getActiveTextEditor();
146 | let previous;
147 | if (editor) {
148 | previous = {
149 | editorId: editor.id,
150 | position: editor.getCursorBufferPosition(),
151 | file: editor.getURI(),
152 | };
153 | }
154 |
155 | let {position} = tag;
156 | if (!position) { position = this.getTagLine(tag); }
157 | if (tag.file) {
158 | atom.workspace.open(path.join(tag.directory, tag.file)).then(() => {
159 | if (position) {
160 | return this.moveToPosition(position);
161 | }
162 | return undefined;
163 | });
164 | } else if (position && previous && !previous.position.isEqual(position)) {
165 | this.moveToPosition(position);
166 | }
167 |
168 | this.stack.push(previous);
169 | }
170 |
171 | moveToPosition(position, beginningOfLine) {
172 | const editor = atom.workspace.getActiveTextEditor();
173 | if (beginningOfLine == null) {
174 | beginningOfLine = true;
175 | }
176 | if (editor) {
177 | editor.setCursorBufferPosition(position, {autoscroll: false});
178 | if (beginningOfLine) {
179 | editor.moveToFirstCharacterOfLine();
180 | }
181 | editor.scrollToCursorPosition({center: true});
182 | }
183 | }
184 |
185 | attach() {
186 | this.previouslyFocusedElement = document.activeElement;
187 | this.panel.show();
188 | this.selectListView.reset();
189 | this.selectListView.focus();
190 | }
191 |
192 | getTagLine(tag) {
193 | if (!tag) {
194 | return undefined;
195 | }
196 |
197 | if (tag.lineNumber) {
198 | return new Point(tag.lineNumber - 1, 0);
199 | }
200 |
201 | // Remove leading /^ and trailing $/
202 | if (!tag.pattern) {
203 | return undefined;
204 | }
205 | const pattern = tag.pattern.replace(/(^\/\^)|(\$\/$)/g, '').trim();
206 |
207 | if (!pattern) {
208 | return undefined;
209 | }
210 | const file = path.join(tag.directory, tag.file);
211 | if (!fs.isFileSync(file)) {
212 | return undefined;
213 | }
214 | const iterable = fs.readFileSync(file, 'utf8').split('\n');
215 | for (let index = 0; index < iterable.length; index++) {
216 | let line = iterable[index];
217 | if (pattern === line.trim()) {
218 | return new Point(index, 0);
219 | }
220 | }
221 |
222 | return undefined;
223 | }
224 | }
225 |
--------------------------------------------------------------------------------
/lib/tag-generator.js:
--------------------------------------------------------------------------------
1 | /** @babel */
2 |
3 | import { BufferedProcess, Point } from 'atom';
4 | import path from 'path';
5 | import fs from 'fs-plus';
6 |
7 | export default class TagGenerator {
8 | constructor(path1, scopeName) {
9 | this.path = path1;
10 | this.scopeName = scopeName;
11 | }
12 |
13 | getPackageRoot() {
14 | const {resourcePath} = atom.getLoadSettings();
15 | const currentFileWasRequiredFromSnapshot = !fs.isAbsolute(__dirname);
16 | const packageRoot = currentFileWasRequiredFromSnapshot
17 | ? path.join(resourcePath, 'node_modules', 'symbols-view')
18 | : path.resolve(__dirname, '..');
19 |
20 | if (path.extname(resourcePath) === '.asar' && packageRoot.indexOf(resourcePath) === 0) {
21 | return path.join(`${resourcePath}.unpacked`, 'node_modules', 'symbols-view');
22 | } else {
23 | return packageRoot;
24 | }
25 | }
26 |
27 | parseTagLine(line) {
28 | let sections = line.split('\t');
29 | if (sections.length > 3) {
30 | return {
31 | position: new Point(parseInt(sections[2], 10) - 1),
32 | name: sections[0],
33 | };
34 | }
35 | return null;
36 | }
37 |
38 | getLanguage() {
39 | if (['.cson', '.gyp'].includes(path.extname(this.path))) {
40 | return 'Cson';
41 | }
42 |
43 | switch (this.scopeName) {
44 | case 'source.c': return 'C';
45 | case 'source.cpp': return 'C++';
46 | case 'source.clojure': return 'Lisp';
47 | case 'source.capnp': return 'Capnp';
48 | case 'source.cfscript': return 'ColdFusion';
49 | case 'source.cfscript.embedded': return 'ColdFusion';
50 | case 'source.coffee': return 'CoffeeScript';
51 | case 'source.css': return 'Css';
52 | case 'source.css.less': return 'Css';
53 | case 'source.css.scss': return 'Css';
54 | case 'source.elixir': return 'Elixir';
55 | case 'source.fountain': return 'Fountain';
56 | case 'source.gfm': return 'Markdown';
57 | case 'source.go': return 'Go';
58 | case 'source.java': return 'Java';
59 | case 'source.js': return 'JavaScript';
60 | case 'source.js.jsx': return 'JavaScript';
61 | case 'source.jsx': return 'JavaScript';
62 | case 'source.json': return 'Json';
63 | case 'source.julia': return 'Julia';
64 | case 'source.makefile': return 'Make';
65 | case 'source.objc': return 'C';
66 | case 'source.objcpp': return 'C++';
67 | case 'source.python': return 'Python';
68 | case 'source.ruby': return 'Ruby';
69 | case 'source.sass': return 'Sass';
70 | case 'source.yaml': return 'Yaml';
71 | case 'text.html': return 'Html';
72 | case 'text.html.php': return 'Php';
73 | case 'text.tex.latex': return 'Latex';
74 | case 'text.html.cfml': return 'ColdFusion';
75 | }
76 | return undefined;
77 | }
78 |
79 | generate() {
80 | let tags = {};
81 | const packageRoot = this.getPackageRoot();
82 | const command = path.join(packageRoot, 'vendor', `ctags-${process.platform}`);
83 | const defaultCtagsFile = path.join(packageRoot, 'lib', 'ctags-config');
84 | const args = [`--options=${defaultCtagsFile}`, '--fields=+KS'];
85 |
86 | if (atom.config.get('symbols-view.useEditorGrammarAsCtagsLanguage')) {
87 | const language = this.getLanguage();
88 | if (language) {
89 | args.push(`--language-force=${language}`);
90 | }
91 | }
92 |
93 | args.push('-nf', '-', this.path);
94 |
95 | return new Promise((resolve) => {
96 | let result, tag;
97 | return new BufferedProcess({
98 | command: command,
99 | args: args,
100 | stdout: (lines) => {
101 | return (() => {
102 | result = [];
103 | for (const line of Array.from(lines.split('\n'))) {
104 | let item;
105 | if (tag = this.parseTagLine(line)) {
106 | item = tags[tag.position.row] ? tags[tag.position.row] : (tags[tag.position.row] = tag);
107 | }
108 | result.push(item);
109 | }
110 | return result;
111 | })();
112 | },
113 | stderr() {},
114 | exit() {
115 | tags = ((() => {
116 | result = [];
117 | for (const row in tags) {
118 | tag = tags[row];
119 | result.push(tag);
120 | }
121 | return result;
122 | })());
123 | return resolve(tags);
124 | },
125 | });
126 | });
127 | }
128 | }
129 |
--------------------------------------------------------------------------------
/lib/tag-reader.js:
--------------------------------------------------------------------------------
1 | /** @babel */
2 |
3 | import { Task } from 'atom';
4 | import ctags from 'ctags';
5 | import async from 'async';
6 | import getTagsFile from './get-tags-file';
7 | import _ from 'underscore-plus';
8 |
9 | let handlerPath = require.resolve('./load-tags-handler');
10 |
11 | let wordAtCursor = (text, cursorIndex, wordSeparator, noStripBefore) => {
12 | const beforeCursor = text.slice(0, cursorIndex);
13 | const afterCursor = text.slice(cursorIndex);
14 | const beforeCursorWordBegins = noStripBefore ? 0 : beforeCursor.lastIndexOf(wordSeparator) + 1;
15 | let afterCursorWordEnds = afterCursor.indexOf(wordSeparator);
16 | if (afterCursorWordEnds === -1) {
17 | afterCursorWordEnds = afterCursor.length;
18 | }
19 | return beforeCursor.slice(beforeCursorWordBegins) + afterCursor.slice(0, afterCursorWordEnds);
20 | };
21 |
22 | export default {
23 | find(editor, callback) {
24 | let symbol;
25 | const symbols = [];
26 |
27 | if (symbol = editor.getSelectedText()) {
28 | symbols.push(symbol);
29 | }
30 |
31 | if (!symbols.length) {
32 | let nonWordCharacters;
33 | const cursor = editor.getLastCursor();
34 | const cursorPosition = cursor.getBufferPosition();
35 | const scope = cursor.getScopeDescriptor();
36 | const rubyScopes = scope.getScopesArray().filter(s => /^source\.ruby($|\.)/.test(s));
37 |
38 | const wordRegExp = rubyScopes.length ?
39 | (nonWordCharacters = atom.config.get('editor.nonWordCharacters', {scope}),
40 | // Allow special handling for fully-qualified ruby constants
41 | nonWordCharacters = nonWordCharacters.replace(/:/g, ''),
42 | new RegExp(`[^\\s${_.escapeRegExp(nonWordCharacters)}]+([!?]|\\s*=>?)?|[<=>]+`, 'g'))
43 | :
44 | cursor.wordRegExp();
45 |
46 | const addSymbol = (symbol) => {
47 | if (rubyScopes.length) {
48 | // Normalize assignment syntax
49 | if (/\s+=?$/.test(symbol)) { symbols.push(symbol.replace(/\s+=$/, '=')); }
50 | // Strip away assignment & hashrocket syntax
51 | symbols.push(symbol.replace(/\s+=>?$/, ''));
52 | } else {
53 | symbols.push(symbol);
54 | }
55 | };
56 |
57 | // Can't use `getCurrentWordBufferRange` here because we want to select
58 | // the last match of the potential 2 matches under cursor.
59 | editor.scanInBufferRange(wordRegExp, cursor.getCurrentLineBufferRange(), ({range, match}) => {
60 | if (range.containsPoint(cursorPosition)) {
61 | symbol = match[0];
62 | if (rubyScopes.length && symbol.indexOf(':') > -1) {
63 | const cursorWithinSymbol = cursorPosition.column - range.start.column;
64 | // Add fully-qualified ruby constant up until the cursor position
65 | addSymbol(wordAtCursor(symbol, cursorWithinSymbol, ':', true));
66 | // Additionally, also look up the bare word under cursor
67 | addSymbol(wordAtCursor(symbol, cursorWithinSymbol, ':'));
68 | } else {
69 | addSymbol(symbol);
70 | }
71 | }
72 | });
73 | }
74 |
75 | if (!symbols.length) {
76 | process.nextTick(() => {
77 | callback(null, []);
78 | });
79 | }
80 |
81 | async.map(atom.project.getPaths(), (projectPath, done) => {
82 | const tagsFile = getTagsFile(projectPath);
83 | let foundTags = [];
84 | let foundErr = null;
85 | const detectCallback = () => {
86 | done(foundErr, foundTags);
87 | };
88 | if (!tagsFile) {
89 | return detectCallback();
90 | }
91 | // Find the first symbol in the list that matches a tag
92 | return async.detectSeries(symbols, (symbol, doneDetect) => {
93 | ctags.findTags(tagsFile, symbol, (err, tags) => {
94 | if (!tags) {
95 | tags = [];
96 | }
97 | if (err) {
98 | foundErr = err;
99 | doneDetect(false);
100 | } else if (tags.length) {
101 | for (const tag of Array.from(tags)) {
102 | tag.directory = projectPath;
103 | }
104 | foundTags = tags;
105 | doneDetect(true);
106 | } else {
107 | doneDetect(false);
108 | }
109 | });
110 | }, detectCallback);
111 | }, (err, foundTags) => {
112 | callback(err, _.flatten(foundTags));
113 | });
114 | },
115 |
116 | getAllTags(callback) {
117 | const projectTags = [];
118 | const task = Task.once(handlerPath, atom.project.getPaths(), () => callback(projectTags));
119 | task.on('tags', (tags) => {
120 | projectTags.push(...tags);
121 | });
122 | return task;
123 | },
124 | };
125 |
--------------------------------------------------------------------------------
/menus/symbols-view.cson:
--------------------------------------------------------------------------------
1 | 'menu': [
2 | {
3 | 'label': 'Packages'
4 | 'submenu': [
5 | 'label': 'Symbols'
6 | 'submenu': [
7 | { 'label': 'File Symbols', 'command': 'symbols-view:toggle-file-symbols' }
8 | { 'label': 'Project Symbols', 'command': 'symbols-view:toggle-project-symbols' }
9 | ]
10 | ]
11 | }
12 | ]
13 |
14 | 'context-menu':
15 | 'atom-text-editor:not([mini])': [
16 | { 'label': 'Go to Declaration', 'command': 'symbols-view:go-to-declaration' }
17 | ]
18 |
--------------------------------------------------------------------------------
/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "symbols-view",
3 | "version": "0.118.4",
4 | "lockfileVersion": 1,
5 | "requires": true,
6 | "dependencies": {
7 | "acorn": {
8 | "version": "5.7.3",
9 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz",
10 | "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==",
11 | "dev": true
12 | },
13 | "acorn-jsx": {
14 | "version": "3.0.1",
15 | "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz",
16 | "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=",
17 | "dev": true,
18 | "requires": {
19 | "acorn": "^3.0.4"
20 | },
21 | "dependencies": {
22 | "acorn": {
23 | "version": "3.3.0",
24 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz",
25 | "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=",
26 | "dev": true
27 | }
28 | }
29 | },
30 | "ajv": {
31 | "version": "4.11.8",
32 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz",
33 | "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=",
34 | "dev": true,
35 | "requires": {
36 | "co": "^4.6.0",
37 | "json-stable-stringify": "^1.0.1"
38 | }
39 | },
40 | "ajv-keywords": {
41 | "version": "1.5.1",
42 | "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz",
43 | "integrity": "sha1-MU3QpLM2j609/NxU7eYXG4htrzw=",
44 | "dev": true
45 | },
46 | "ansi-escapes": {
47 | "version": "1.4.0",
48 | "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz",
49 | "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=",
50 | "dev": true
51 | },
52 | "ansi-regex": {
53 | "version": "2.1.1",
54 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
55 | "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
56 | "dev": true
57 | },
58 | "ansi-styles": {
59 | "version": "2.2.1",
60 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
61 | "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
62 | "dev": true
63 | },
64 | "argparse": {
65 | "version": "1.0.10",
66 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
67 | "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
68 | "dev": true,
69 | "requires": {
70 | "sprintf-js": "~1.0.2"
71 | }
72 | },
73 | "async": {
74 | "version": "0.2.10",
75 | "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz",
76 | "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E="
77 | },
78 | "atom-select-list": {
79 | "version": "0.7.2",
80 | "resolved": "https://registry.npmjs.org/atom-select-list/-/atom-select-list-0.7.2.tgz",
81 | "integrity": "sha512-a707OB1DhLGjzqtFrtMQKH7BBxFuCh8UBoUWxgFOrLrSwVh3g+/TlVPVDOz12+U0mDu3mIrnYLqQyhywQOTxhw==",
82 | "requires": {
83 | "etch": "^0.12.6",
84 | "fuzzaldrin": "^2.1.0"
85 | }
86 | },
87 | "babel-code-frame": {
88 | "version": "6.26.0",
89 | "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
90 | "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=",
91 | "dev": true,
92 | "requires": {
93 | "chalk": "^1.1.3",
94 | "esutils": "^2.0.2",
95 | "js-tokens": "^3.0.2"
96 | }
97 | },
98 | "babel-eslint": {
99 | "version": "6.1.2",
100 | "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-6.1.2.tgz",
101 | "integrity": "sha1-UpNBn+NnLWZZjTJ9qWlFZ7pqXy8=",
102 | "dev": true,
103 | "requires": {
104 | "babel-traverse": "^6.0.20",
105 | "babel-types": "^6.0.19",
106 | "babylon": "^6.0.18",
107 | "lodash.assign": "^4.0.0",
108 | "lodash.pickby": "^4.0.0"
109 | }
110 | },
111 | "babel-messages": {
112 | "version": "6.23.0",
113 | "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz",
114 | "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=",
115 | "dev": true,
116 | "requires": {
117 | "babel-runtime": "^6.22.0"
118 | }
119 | },
120 | "babel-runtime": {
121 | "version": "6.26.0",
122 | "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
123 | "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
124 | "dev": true,
125 | "requires": {
126 | "core-js": "^2.4.0",
127 | "regenerator-runtime": "^0.11.0"
128 | }
129 | },
130 | "babel-traverse": {
131 | "version": "6.26.0",
132 | "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz",
133 | "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=",
134 | "dev": true,
135 | "requires": {
136 | "babel-code-frame": "^6.26.0",
137 | "babel-messages": "^6.23.0",
138 | "babel-runtime": "^6.26.0",
139 | "babel-types": "^6.26.0",
140 | "babylon": "^6.18.0",
141 | "debug": "^2.6.8",
142 | "globals": "^9.18.0",
143 | "invariant": "^2.2.2",
144 | "lodash": "^4.17.4"
145 | }
146 | },
147 | "babel-types": {
148 | "version": "6.26.0",
149 | "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz",
150 | "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=",
151 | "dev": true,
152 | "requires": {
153 | "babel-runtime": "^6.26.0",
154 | "esutils": "^2.0.2",
155 | "lodash": "^4.17.4",
156 | "to-fast-properties": "^1.0.3"
157 | }
158 | },
159 | "babylon": {
160 | "version": "6.18.0",
161 | "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz",
162 | "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==",
163 | "dev": true
164 | },
165 | "balanced-match": {
166 | "version": "1.0.0",
167 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
168 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
169 | },
170 | "brace-expansion": {
171 | "version": "1.1.11",
172 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
173 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
174 | "requires": {
175 | "balanced-match": "^1.0.0",
176 | "concat-map": "0.0.1"
177 | }
178 | },
179 | "buffer-from": {
180 | "version": "1.1.1",
181 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
182 | "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
183 | "dev": true
184 | },
185 | "caller-path": {
186 | "version": "0.1.0",
187 | "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz",
188 | "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=",
189 | "dev": true,
190 | "requires": {
191 | "callsites": "^0.2.0"
192 | }
193 | },
194 | "callsites": {
195 | "version": "0.2.0",
196 | "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz",
197 | "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=",
198 | "dev": true
199 | },
200 | "chalk": {
201 | "version": "1.1.3",
202 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
203 | "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
204 | "dev": true,
205 | "requires": {
206 | "ansi-styles": "^2.2.1",
207 | "escape-string-regexp": "^1.0.2",
208 | "has-ansi": "^2.0.0",
209 | "strip-ansi": "^3.0.0",
210 | "supports-color": "^2.0.0"
211 | }
212 | },
213 | "circular-json": {
214 | "version": "0.3.3",
215 | "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz",
216 | "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==",
217 | "dev": true
218 | },
219 | "cli-cursor": {
220 | "version": "1.0.2",
221 | "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz",
222 | "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=",
223 | "dev": true,
224 | "requires": {
225 | "restore-cursor": "^1.0.1"
226 | }
227 | },
228 | "cli-width": {
229 | "version": "2.2.0",
230 | "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz",
231 | "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=",
232 | "dev": true
233 | },
234 | "co": {
235 | "version": "4.6.0",
236 | "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
237 | "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=",
238 | "dev": true
239 | },
240 | "code-point-at": {
241 | "version": "1.1.0",
242 | "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
243 | "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
244 | "dev": true
245 | },
246 | "concat-map": {
247 | "version": "0.0.1",
248 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
249 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
250 | },
251 | "concat-stream": {
252 | "version": "1.6.2",
253 | "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
254 | "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
255 | "dev": true,
256 | "requires": {
257 | "buffer-from": "^1.0.0",
258 | "inherits": "^2.0.3",
259 | "readable-stream": "^2.2.2",
260 | "typedarray": "^0.0.6"
261 | }
262 | },
263 | "core-js": {
264 | "version": "2.6.10",
265 | "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.10.tgz",
266 | "integrity": "sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA==",
267 | "dev": true
268 | },
269 | "core-util-is": {
270 | "version": "1.0.2",
271 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
272 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
273 | "dev": true
274 | },
275 | "ctags": {
276 | "version": "3.1.0",
277 | "resolved": "https://registry.npmjs.org/ctags/-/ctags-3.1.0.tgz",
278 | "integrity": "sha512-7/aiGLj8Ih7Ko3bAAg8bQUwHjOGXKQ7XC+bv+vLh84BtkVodPEOpOnr65FnWjX2oFWoKSaDuxe7jFHudD2Q0uw==",
279 | "requires": {
280 | "event-stream": "~3.1.0",
281 | "nan": "^2.14.0"
282 | }
283 | },
284 | "d": {
285 | "version": "1.0.1",
286 | "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz",
287 | "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==",
288 | "dev": true,
289 | "requires": {
290 | "es5-ext": "^0.10.50",
291 | "type": "^1.0.1"
292 | }
293 | },
294 | "debug": {
295 | "version": "2.6.9",
296 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
297 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
298 | "dev": true,
299 | "requires": {
300 | "ms": "2.0.0"
301 | }
302 | },
303 | "deep-is": {
304 | "version": "0.1.3",
305 | "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
306 | "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
307 | "dev": true
308 | },
309 | "doctrine": {
310 | "version": "2.1.0",
311 | "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
312 | "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
313 | "dev": true,
314 | "requires": {
315 | "esutils": "^2.0.2"
316 | }
317 | },
318 | "duplexer": {
319 | "version": "0.1.1",
320 | "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz",
321 | "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E="
322 | },
323 | "es5-ext": {
324 | "version": "0.10.53",
325 | "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz",
326 | "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==",
327 | "dev": true,
328 | "requires": {
329 | "es6-iterator": "~2.0.3",
330 | "es6-symbol": "~3.1.3",
331 | "next-tick": "~1.0.0"
332 | }
333 | },
334 | "es6-iterator": {
335 | "version": "2.0.3",
336 | "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
337 | "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=",
338 | "dev": true,
339 | "requires": {
340 | "d": "1",
341 | "es5-ext": "^0.10.35",
342 | "es6-symbol": "^3.1.1"
343 | }
344 | },
345 | "es6-map": {
346 | "version": "0.1.5",
347 | "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz",
348 | "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=",
349 | "dev": true,
350 | "requires": {
351 | "d": "1",
352 | "es5-ext": "~0.10.14",
353 | "es6-iterator": "~2.0.1",
354 | "es6-set": "~0.1.5",
355 | "es6-symbol": "~3.1.1",
356 | "event-emitter": "~0.3.5"
357 | }
358 | },
359 | "es6-set": {
360 | "version": "0.1.5",
361 | "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz",
362 | "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=",
363 | "dev": true,
364 | "requires": {
365 | "d": "1",
366 | "es5-ext": "~0.10.14",
367 | "es6-iterator": "~2.0.1",
368 | "es6-symbol": "3.1.1",
369 | "event-emitter": "~0.3.5"
370 | },
371 | "dependencies": {
372 | "es6-symbol": {
373 | "version": "3.1.1",
374 | "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz",
375 | "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=",
376 | "dev": true,
377 | "requires": {
378 | "d": "1",
379 | "es5-ext": "~0.10.14"
380 | }
381 | }
382 | }
383 | },
384 | "es6-symbol": {
385 | "version": "3.1.3",
386 | "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz",
387 | "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==",
388 | "dev": true,
389 | "requires": {
390 | "d": "^1.0.1",
391 | "ext": "^1.1.2"
392 | }
393 | },
394 | "es6-weak-map": {
395 | "version": "2.0.3",
396 | "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz",
397 | "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==",
398 | "dev": true,
399 | "requires": {
400 | "d": "1",
401 | "es5-ext": "^0.10.46",
402 | "es6-iterator": "^2.0.3",
403 | "es6-symbol": "^3.1.1"
404 | }
405 | },
406 | "escape-string-regexp": {
407 | "version": "1.0.5",
408 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
409 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
410 | "dev": true
411 | },
412 | "escope": {
413 | "version": "3.6.0",
414 | "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz",
415 | "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=",
416 | "dev": true,
417 | "requires": {
418 | "es6-map": "^0.1.3",
419 | "es6-weak-map": "^2.0.1",
420 | "esrecurse": "^4.1.0",
421 | "estraverse": "^4.1.1"
422 | }
423 | },
424 | "eslint": {
425 | "version": "3.19.0",
426 | "resolved": "https://registry.npmjs.org/eslint/-/eslint-3.19.0.tgz",
427 | "integrity": "sha1-yPxiAcf0DdCJQbh8CFdnOGpnmsw=",
428 | "dev": true,
429 | "requires": {
430 | "babel-code-frame": "^6.16.0",
431 | "chalk": "^1.1.3",
432 | "concat-stream": "^1.5.2",
433 | "debug": "^2.1.1",
434 | "doctrine": "^2.0.0",
435 | "escope": "^3.6.0",
436 | "espree": "^3.4.0",
437 | "esquery": "^1.0.0",
438 | "estraverse": "^4.2.0",
439 | "esutils": "^2.0.2",
440 | "file-entry-cache": "^2.0.0",
441 | "glob": "^7.0.3",
442 | "globals": "^9.14.0",
443 | "ignore": "^3.2.0",
444 | "imurmurhash": "^0.1.4",
445 | "inquirer": "^0.12.0",
446 | "is-my-json-valid": "^2.10.0",
447 | "is-resolvable": "^1.0.0",
448 | "js-yaml": "^3.5.1",
449 | "json-stable-stringify": "^1.0.0",
450 | "levn": "^0.3.0",
451 | "lodash": "^4.0.0",
452 | "mkdirp": "^0.5.0",
453 | "natural-compare": "^1.4.0",
454 | "optionator": "^0.8.2",
455 | "path-is-inside": "^1.0.1",
456 | "pluralize": "^1.2.1",
457 | "progress": "^1.1.8",
458 | "require-uncached": "^1.0.2",
459 | "shelljs": "^0.7.5",
460 | "strip-bom": "^3.0.0",
461 | "strip-json-comments": "~2.0.1",
462 | "table": "^3.7.8",
463 | "text-table": "~0.2.0",
464 | "user-home": "^2.0.0"
465 | }
466 | },
467 | "eslint-config-fbjs": {
468 | "version": "1.1.1",
469 | "resolved": "https://registry.npmjs.org/eslint-config-fbjs/-/eslint-config-fbjs-1.1.1.tgz",
470 | "integrity": "sha1-3Sn42RLop1Ulfp7u8AuuHM5X9zo=",
471 | "dev": true
472 | },
473 | "eslint-plugin-babel": {
474 | "version": "3.3.0",
475 | "resolved": "https://registry.npmjs.org/eslint-plugin-babel/-/eslint-plugin-babel-3.3.0.tgz",
476 | "integrity": "sha1-L0lK7c9vSqTnW5FVmAg3vB+94ZM=",
477 | "dev": true
478 | },
479 | "eslint-plugin-flowtype": {
480 | "version": "2.50.3",
481 | "resolved": "https://registry.npmjs.org/eslint-plugin-flowtype/-/eslint-plugin-flowtype-2.50.3.tgz",
482 | "integrity": "sha512-X+AoKVOr7Re0ko/yEXyM5SSZ0tazc6ffdIOocp2fFUlWoDt7DV0Bz99mngOkAFLOAWjqRA5jPwqUCbrx13XoxQ==",
483 | "dev": true,
484 | "requires": {
485 | "lodash": "^4.17.10"
486 | }
487 | },
488 | "eslint-plugin-jasmine": {
489 | "version": "2.10.1",
490 | "resolved": "https://registry.npmjs.org/eslint-plugin-jasmine/-/eslint-plugin-jasmine-2.10.1.tgz",
491 | "integrity": "sha1-VzO3CedR9LxA4x4cFpib0s377Jc=",
492 | "dev": true
493 | },
494 | "eslint-plugin-prefer-object-spread": {
495 | "version": "1.2.1",
496 | "resolved": "https://registry.npmjs.org/eslint-plugin-prefer-object-spread/-/eslint-plugin-prefer-object-spread-1.2.1.tgz",
497 | "integrity": "sha1-J/uRhTaQzOs65hAdnIrsxqZ6QCw=",
498 | "dev": true
499 | },
500 | "eslint-plugin-react": {
501 | "version": "5.2.2",
502 | "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-5.2.2.tgz",
503 | "integrity": "sha1-fbBo4fVIf2hx5N7vNqOBwwPqwWE=",
504 | "dev": true,
505 | "requires": {
506 | "doctrine": "^1.2.2",
507 | "jsx-ast-utils": "^1.2.1"
508 | },
509 | "dependencies": {
510 | "doctrine": {
511 | "version": "1.5.0",
512 | "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz",
513 | "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=",
514 | "dev": true,
515 | "requires": {
516 | "esutils": "^2.0.2",
517 | "isarray": "^1.0.0"
518 | }
519 | }
520 | }
521 | },
522 | "espree": {
523 | "version": "3.5.4",
524 | "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz",
525 | "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==",
526 | "dev": true,
527 | "requires": {
528 | "acorn": "^5.5.0",
529 | "acorn-jsx": "^3.0.0"
530 | }
531 | },
532 | "esprima": {
533 | "version": "4.0.1",
534 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
535 | "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
536 | "dev": true
537 | },
538 | "esquery": {
539 | "version": "1.0.1",
540 | "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz",
541 | "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==",
542 | "dev": true,
543 | "requires": {
544 | "estraverse": "^4.0.0"
545 | }
546 | },
547 | "esrecurse": {
548 | "version": "4.2.1",
549 | "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz",
550 | "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==",
551 | "dev": true,
552 | "requires": {
553 | "estraverse": "^4.1.0"
554 | }
555 | },
556 | "estraverse": {
557 | "version": "4.3.0",
558 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
559 | "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
560 | "dev": true
561 | },
562 | "esutils": {
563 | "version": "2.0.3",
564 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
565 | "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
566 | "dev": true
567 | },
568 | "etch": {
569 | "version": "0.12.8",
570 | "resolved": "https://registry.npmjs.org/etch/-/etch-0.12.8.tgz",
571 | "integrity": "sha512-dFLRe4wLroVtwzyy1vGlE3BSDZHiL0kZME5XgNGzZIULcYTvVno8vbiIleAesoKJmwWaxDTzG+4eppg2zk14JQ=="
572 | },
573 | "event-emitter": {
574 | "version": "0.3.5",
575 | "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz",
576 | "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=",
577 | "dev": true,
578 | "requires": {
579 | "d": "1",
580 | "es5-ext": "~0.10.14"
581 | }
582 | },
583 | "event-stream": {
584 | "version": "3.1.7",
585 | "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.1.7.tgz",
586 | "integrity": "sha1-tMVAAS0P4UmEIPPYlGAI22OTw3o=",
587 | "requires": {
588 | "duplexer": "~0.1.1",
589 | "from": "~0",
590 | "map-stream": "~0.1.0",
591 | "pause-stream": "0.0.11",
592 | "split": "0.2",
593 | "stream-combiner": "~0.0.4",
594 | "through": "~2.3.1"
595 | }
596 | },
597 | "exit-hook": {
598 | "version": "1.1.1",
599 | "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz",
600 | "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=",
601 | "dev": true
602 | },
603 | "ext": {
604 | "version": "1.4.0",
605 | "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz",
606 | "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==",
607 | "dev": true,
608 | "requires": {
609 | "type": "^2.0.0"
610 | },
611 | "dependencies": {
612 | "type": {
613 | "version": "2.0.0",
614 | "resolved": "https://registry.npmjs.org/type/-/type-2.0.0.tgz",
615 | "integrity": "sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow==",
616 | "dev": true
617 | }
618 | }
619 | },
620 | "fast-levenshtein": {
621 | "version": "2.0.6",
622 | "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
623 | "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
624 | "dev": true
625 | },
626 | "figures": {
627 | "version": "1.7.0",
628 | "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz",
629 | "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=",
630 | "dev": true,
631 | "requires": {
632 | "escape-string-regexp": "^1.0.5",
633 | "object-assign": "^4.1.0"
634 | }
635 | },
636 | "file-entry-cache": {
637 | "version": "2.0.0",
638 | "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz",
639 | "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=",
640 | "dev": true,
641 | "requires": {
642 | "flat-cache": "^1.2.1",
643 | "object-assign": "^4.0.1"
644 | }
645 | },
646 | "flat-cache": {
647 | "version": "1.3.4",
648 | "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz",
649 | "integrity": "sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg==",
650 | "dev": true,
651 | "requires": {
652 | "circular-json": "^0.3.1",
653 | "graceful-fs": "^4.1.2",
654 | "rimraf": "~2.6.2",
655 | "write": "^0.2.1"
656 | },
657 | "dependencies": {
658 | "rimraf": {
659 | "version": "2.6.3",
660 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
661 | "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
662 | "dev": true,
663 | "requires": {
664 | "glob": "^7.1.3"
665 | }
666 | }
667 | }
668 | },
669 | "from": {
670 | "version": "0.1.7",
671 | "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz",
672 | "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4="
673 | },
674 | "fs-plus": {
675 | "version": "3.1.1",
676 | "resolved": "https://registry.npmjs.org/fs-plus/-/fs-plus-3.1.1.tgz",
677 | "integrity": "sha512-Se2PJdOWXqos1qVTkvqqjb0CSnfBnwwD+pq+z4ksT+e97mEShod/hrNg0TRCCsXPbJzcIq+NuzQhigunMWMJUA==",
678 | "requires": {
679 | "async": "^1.5.2",
680 | "mkdirp": "^0.5.1",
681 | "rimraf": "^2.5.2",
682 | "underscore-plus": "1.x"
683 | },
684 | "dependencies": {
685 | "async": {
686 | "version": "1.5.2",
687 | "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
688 | "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo="
689 | }
690 | }
691 | },
692 | "fs.realpath": {
693 | "version": "1.0.0",
694 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
695 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
696 | },
697 | "fuzzaldrin": {
698 | "version": "2.1.0",
699 | "resolved": "https://registry.npmjs.org/fuzzaldrin/-/fuzzaldrin-2.1.0.tgz",
700 | "integrity": "sha1-kCBMPi/appQbso0WZF1BgGOpDps="
701 | },
702 | "generate-function": {
703 | "version": "2.3.1",
704 | "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz",
705 | "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==",
706 | "dev": true,
707 | "requires": {
708 | "is-property": "^1.0.2"
709 | }
710 | },
711 | "generate-object-property": {
712 | "version": "1.2.0",
713 | "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz",
714 | "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=",
715 | "dev": true,
716 | "requires": {
717 | "is-property": "^1.0.0"
718 | }
719 | },
720 | "glob": {
721 | "version": "7.1.6",
722 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
723 | "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
724 | "requires": {
725 | "fs.realpath": "^1.0.0",
726 | "inflight": "^1.0.4",
727 | "inherits": "2",
728 | "minimatch": "^3.0.4",
729 | "once": "^1.3.0",
730 | "path-is-absolute": "^1.0.0"
731 | }
732 | },
733 | "globals": {
734 | "version": "9.18.0",
735 | "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz",
736 | "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==",
737 | "dev": true
738 | },
739 | "graceful-fs": {
740 | "version": "4.2.3",
741 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz",
742 | "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==",
743 | "dev": true
744 | },
745 | "has-ansi": {
746 | "version": "2.0.0",
747 | "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
748 | "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
749 | "dev": true,
750 | "requires": {
751 | "ansi-regex": "^2.0.0"
752 | }
753 | },
754 | "humanize-plus": {
755 | "version": "1.8.2",
756 | "resolved": "https://registry.npmjs.org/humanize-plus/-/humanize-plus-1.8.2.tgz",
757 | "integrity": "sha1-pls0RZrWNnrbs3B6gqPJ+RYWcDA="
758 | },
759 | "ignore": {
760 | "version": "3.3.10",
761 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz",
762 | "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==",
763 | "dev": true
764 | },
765 | "imurmurhash": {
766 | "version": "0.1.4",
767 | "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
768 | "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
769 | "dev": true
770 | },
771 | "inflight": {
772 | "version": "1.0.6",
773 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
774 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
775 | "requires": {
776 | "once": "^1.3.0",
777 | "wrappy": "1"
778 | }
779 | },
780 | "inherits": {
781 | "version": "2.0.4",
782 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
783 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
784 | },
785 | "inquirer": {
786 | "version": "0.12.0",
787 | "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz",
788 | "integrity": "sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34=",
789 | "dev": true,
790 | "requires": {
791 | "ansi-escapes": "^1.1.0",
792 | "ansi-regex": "^2.0.0",
793 | "chalk": "^1.0.0",
794 | "cli-cursor": "^1.0.1",
795 | "cli-width": "^2.0.0",
796 | "figures": "^1.3.5",
797 | "lodash": "^4.3.0",
798 | "readline2": "^1.0.1",
799 | "run-async": "^0.1.0",
800 | "rx-lite": "^3.1.2",
801 | "string-width": "^1.0.1",
802 | "strip-ansi": "^3.0.0",
803 | "through": "^2.3.6"
804 | }
805 | },
806 | "interpret": {
807 | "version": "1.2.0",
808 | "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz",
809 | "integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==",
810 | "dev": true
811 | },
812 | "invariant": {
813 | "version": "2.2.4",
814 | "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
815 | "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
816 | "dev": true,
817 | "requires": {
818 | "loose-envify": "^1.0.0"
819 | }
820 | },
821 | "is-fullwidth-code-point": {
822 | "version": "1.0.0",
823 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
824 | "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
825 | "dev": true,
826 | "requires": {
827 | "number-is-nan": "^1.0.0"
828 | }
829 | },
830 | "is-my-ip-valid": {
831 | "version": "1.0.0",
832 | "resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz",
833 | "integrity": "sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ==",
834 | "dev": true
835 | },
836 | "is-my-json-valid": {
837 | "version": "2.20.0",
838 | "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.20.0.tgz",
839 | "integrity": "sha512-XTHBZSIIxNsIsZXg7XB5l8z/OBFosl1Wao4tXLpeC7eKU4Vm/kdop2azkPqULwnfGQjmeDIyey9g7afMMtdWAA==",
840 | "dev": true,
841 | "requires": {
842 | "generate-function": "^2.0.0",
843 | "generate-object-property": "^1.1.0",
844 | "is-my-ip-valid": "^1.0.0",
845 | "jsonpointer": "^4.0.0",
846 | "xtend": "^4.0.0"
847 | }
848 | },
849 | "is-property": {
850 | "version": "1.0.2",
851 | "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz",
852 | "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=",
853 | "dev": true
854 | },
855 | "is-resolvable": {
856 | "version": "1.1.0",
857 | "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz",
858 | "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==",
859 | "dev": true
860 | },
861 | "isarray": {
862 | "version": "1.0.0",
863 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
864 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
865 | "dev": true
866 | },
867 | "js-tokens": {
868 | "version": "3.0.2",
869 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
870 | "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=",
871 | "dev": true
872 | },
873 | "js-yaml": {
874 | "version": "3.13.1",
875 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
876 | "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
877 | "dev": true,
878 | "requires": {
879 | "argparse": "^1.0.7",
880 | "esprima": "^4.0.0"
881 | }
882 | },
883 | "json-stable-stringify": {
884 | "version": "1.0.1",
885 | "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz",
886 | "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=",
887 | "dev": true,
888 | "requires": {
889 | "jsonify": "~0.0.0"
890 | }
891 | },
892 | "jsonify": {
893 | "version": "0.0.0",
894 | "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz",
895 | "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=",
896 | "dev": true
897 | },
898 | "jsonpointer": {
899 | "version": "4.0.1",
900 | "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz",
901 | "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=",
902 | "dev": true
903 | },
904 | "jsx-ast-utils": {
905 | "version": "1.4.1",
906 | "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-1.4.1.tgz",
907 | "integrity": "sha1-OGchPo3Xm/Ho8jAMDPwe+xgsDfE=",
908 | "dev": true
909 | },
910 | "levn": {
911 | "version": "0.3.0",
912 | "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
913 | "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=",
914 | "dev": true,
915 | "requires": {
916 | "prelude-ls": "~1.1.2",
917 | "type-check": "~0.3.2"
918 | }
919 | },
920 | "lodash": {
921 | "version": "4.17.15",
922 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
923 | "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
924 | "dev": true
925 | },
926 | "lodash.assign": {
927 | "version": "4.2.0",
928 | "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz",
929 | "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=",
930 | "dev": true
931 | },
932 | "lodash.pickby": {
933 | "version": "4.6.0",
934 | "resolved": "https://registry.npmjs.org/lodash.pickby/-/lodash.pickby-4.6.0.tgz",
935 | "integrity": "sha1-feoh2MGNdwOifHBMFdO4SmfjOv8=",
936 | "dev": true
937 | },
938 | "loose-envify": {
939 | "version": "1.4.0",
940 | "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
941 | "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
942 | "dev": true,
943 | "requires": {
944 | "js-tokens": "^3.0.0 || ^4.0.0"
945 | }
946 | },
947 | "map-stream": {
948 | "version": "0.1.0",
949 | "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz",
950 | "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ="
951 | },
952 | "minimatch": {
953 | "version": "3.0.4",
954 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
955 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
956 | "requires": {
957 | "brace-expansion": "^1.1.7"
958 | }
959 | },
960 | "minimist": {
961 | "version": "0.0.8",
962 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
963 | "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
964 | },
965 | "mkdirp": {
966 | "version": "0.5.1",
967 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
968 | "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
969 | "requires": {
970 | "minimist": "0.0.8"
971 | }
972 | },
973 | "ms": {
974 | "version": "2.0.0",
975 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
976 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
977 | "dev": true
978 | },
979 | "mute-stream": {
980 | "version": "0.0.5",
981 | "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz",
982 | "integrity": "sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA=",
983 | "dev": true
984 | },
985 | "nan": {
986 | "version": "2.14.0",
987 | "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz",
988 | "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg=="
989 | },
990 | "natural-compare": {
991 | "version": "1.4.0",
992 | "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
993 | "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
994 | "dev": true
995 | },
996 | "next-tick": {
997 | "version": "1.0.0",
998 | "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz",
999 | "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=",
1000 | "dev": true
1001 | },
1002 | "number-is-nan": {
1003 | "version": "1.0.1",
1004 | "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
1005 | "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
1006 | "dev": true
1007 | },
1008 | "object-assign": {
1009 | "version": "4.1.1",
1010 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
1011 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
1012 | "dev": true
1013 | },
1014 | "once": {
1015 | "version": "1.4.0",
1016 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
1017 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
1018 | "requires": {
1019 | "wrappy": "1"
1020 | }
1021 | },
1022 | "onetime": {
1023 | "version": "1.1.0",
1024 | "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz",
1025 | "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=",
1026 | "dev": true
1027 | },
1028 | "optionator": {
1029 | "version": "0.8.3",
1030 | "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz",
1031 | "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==",
1032 | "dev": true,
1033 | "requires": {
1034 | "deep-is": "~0.1.3",
1035 | "fast-levenshtein": "~2.0.6",
1036 | "levn": "~0.3.0",
1037 | "prelude-ls": "~1.1.2",
1038 | "type-check": "~0.3.2",
1039 | "word-wrap": "~1.2.3"
1040 | }
1041 | },
1042 | "os-homedir": {
1043 | "version": "1.0.2",
1044 | "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
1045 | "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=",
1046 | "dev": true
1047 | },
1048 | "path-is-absolute": {
1049 | "version": "1.0.1",
1050 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
1051 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
1052 | },
1053 | "path-is-inside": {
1054 | "version": "1.0.2",
1055 | "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz",
1056 | "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=",
1057 | "dev": true
1058 | },
1059 | "path-parse": {
1060 | "version": "1.0.6",
1061 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
1062 | "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
1063 | "dev": true
1064 | },
1065 | "pause-stream": {
1066 | "version": "0.0.11",
1067 | "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz",
1068 | "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=",
1069 | "requires": {
1070 | "through": "~2.3"
1071 | }
1072 | },
1073 | "pluralize": {
1074 | "version": "1.2.1",
1075 | "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-1.2.1.tgz",
1076 | "integrity": "sha1-0aIUg/0iu0HlihL6NCGCMUCJfEU=",
1077 | "dev": true
1078 | },
1079 | "prelude-ls": {
1080 | "version": "1.1.2",
1081 | "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
1082 | "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=",
1083 | "dev": true
1084 | },
1085 | "process-nextick-args": {
1086 | "version": "2.0.1",
1087 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
1088 | "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
1089 | "dev": true
1090 | },
1091 | "progress": {
1092 | "version": "1.1.8",
1093 | "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz",
1094 | "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=",
1095 | "dev": true
1096 | },
1097 | "readable-stream": {
1098 | "version": "2.3.6",
1099 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
1100 | "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
1101 | "dev": true,
1102 | "requires": {
1103 | "core-util-is": "~1.0.0",
1104 | "inherits": "~2.0.3",
1105 | "isarray": "~1.0.0",
1106 | "process-nextick-args": "~2.0.0",
1107 | "safe-buffer": "~5.1.1",
1108 | "string_decoder": "~1.1.1",
1109 | "util-deprecate": "~1.0.1"
1110 | }
1111 | },
1112 | "readline2": {
1113 | "version": "1.0.1",
1114 | "resolved": "https://registry.npmjs.org/readline2/-/readline2-1.0.1.tgz",
1115 | "integrity": "sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU=",
1116 | "dev": true,
1117 | "requires": {
1118 | "code-point-at": "^1.0.0",
1119 | "is-fullwidth-code-point": "^1.0.0",
1120 | "mute-stream": "0.0.5"
1121 | }
1122 | },
1123 | "rechoir": {
1124 | "version": "0.6.2",
1125 | "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz",
1126 | "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=",
1127 | "dev": true,
1128 | "requires": {
1129 | "resolve": "^1.1.6"
1130 | }
1131 | },
1132 | "regenerator-runtime": {
1133 | "version": "0.11.1",
1134 | "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
1135 | "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==",
1136 | "dev": true
1137 | },
1138 | "require-uncached": {
1139 | "version": "1.0.3",
1140 | "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz",
1141 | "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=",
1142 | "dev": true,
1143 | "requires": {
1144 | "caller-path": "^0.1.0",
1145 | "resolve-from": "^1.0.0"
1146 | }
1147 | },
1148 | "resolve": {
1149 | "version": "1.13.1",
1150 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.13.1.tgz",
1151 | "integrity": "sha512-CxqObCX8K8YtAhOBRg+lrcdn+LK+WYOS8tSjqSFbjtrI5PnS63QPhZl4+yKfrU9tdsbMu9Anr/amegT87M9Z6w==",
1152 | "dev": true,
1153 | "requires": {
1154 | "path-parse": "^1.0.6"
1155 | }
1156 | },
1157 | "resolve-from": {
1158 | "version": "1.0.1",
1159 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz",
1160 | "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=",
1161 | "dev": true
1162 | },
1163 | "restore-cursor": {
1164 | "version": "1.0.1",
1165 | "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz",
1166 | "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=",
1167 | "dev": true,
1168 | "requires": {
1169 | "exit-hook": "^1.0.0",
1170 | "onetime": "^1.0.0"
1171 | }
1172 | },
1173 | "rimraf": {
1174 | "version": "2.7.1",
1175 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
1176 | "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
1177 | "requires": {
1178 | "glob": "^7.1.3"
1179 | }
1180 | },
1181 | "run-async": {
1182 | "version": "0.1.0",
1183 | "resolved": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz",
1184 | "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=",
1185 | "dev": true,
1186 | "requires": {
1187 | "once": "^1.3.0"
1188 | }
1189 | },
1190 | "rx-lite": {
1191 | "version": "3.1.2",
1192 | "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz",
1193 | "integrity": "sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI=",
1194 | "dev": true
1195 | },
1196 | "safe-buffer": {
1197 | "version": "5.1.2",
1198 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
1199 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
1200 | "dev": true
1201 | },
1202 | "shelljs": {
1203 | "version": "0.7.8",
1204 | "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.7.8.tgz",
1205 | "integrity": "sha1-3svPh0sNHl+3LhSxZKloMEjprLM=",
1206 | "dev": true,
1207 | "requires": {
1208 | "glob": "^7.0.0",
1209 | "interpret": "^1.0.0",
1210 | "rechoir": "^0.6.2"
1211 | }
1212 | },
1213 | "slice-ansi": {
1214 | "version": "0.0.4",
1215 | "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz",
1216 | "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=",
1217 | "dev": true
1218 | },
1219 | "split": {
1220 | "version": "0.2.10",
1221 | "resolved": "https://registry.npmjs.org/split/-/split-0.2.10.tgz",
1222 | "integrity": "sha1-Zwl8YB1pfOE2j0GPBs0gHPBSGlc=",
1223 | "requires": {
1224 | "through": "2"
1225 | }
1226 | },
1227 | "sprintf-js": {
1228 | "version": "1.0.3",
1229 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
1230 | "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
1231 | "dev": true
1232 | },
1233 | "stream-combiner": {
1234 | "version": "0.0.4",
1235 | "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz",
1236 | "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=",
1237 | "requires": {
1238 | "duplexer": "~0.1.1"
1239 | }
1240 | },
1241 | "string-width": {
1242 | "version": "1.0.2",
1243 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
1244 | "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
1245 | "dev": true,
1246 | "requires": {
1247 | "code-point-at": "^1.0.0",
1248 | "is-fullwidth-code-point": "^1.0.0",
1249 | "strip-ansi": "^3.0.0"
1250 | }
1251 | },
1252 | "string_decoder": {
1253 | "version": "1.1.1",
1254 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
1255 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
1256 | "dev": true,
1257 | "requires": {
1258 | "safe-buffer": "~5.1.0"
1259 | }
1260 | },
1261 | "strip-ansi": {
1262 | "version": "3.0.1",
1263 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
1264 | "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
1265 | "dev": true,
1266 | "requires": {
1267 | "ansi-regex": "^2.0.0"
1268 | }
1269 | },
1270 | "strip-bom": {
1271 | "version": "3.0.0",
1272 | "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
1273 | "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
1274 | "dev": true
1275 | },
1276 | "strip-json-comments": {
1277 | "version": "2.0.1",
1278 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
1279 | "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
1280 | "dev": true
1281 | },
1282 | "supports-color": {
1283 | "version": "2.0.0",
1284 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
1285 | "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
1286 | "dev": true
1287 | },
1288 | "table": {
1289 | "version": "3.8.3",
1290 | "resolved": "https://registry.npmjs.org/table/-/table-3.8.3.tgz",
1291 | "integrity": "sha1-K7xULw/amGGnVdOUf+/Ys/UThV8=",
1292 | "dev": true,
1293 | "requires": {
1294 | "ajv": "^4.7.0",
1295 | "ajv-keywords": "^1.0.0",
1296 | "chalk": "^1.1.1",
1297 | "lodash": "^4.0.0",
1298 | "slice-ansi": "0.0.4",
1299 | "string-width": "^2.0.0"
1300 | },
1301 | "dependencies": {
1302 | "ansi-regex": {
1303 | "version": "3.0.0",
1304 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
1305 | "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
1306 | "dev": true
1307 | },
1308 | "is-fullwidth-code-point": {
1309 | "version": "2.0.0",
1310 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
1311 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
1312 | "dev": true
1313 | },
1314 | "string-width": {
1315 | "version": "2.1.1",
1316 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
1317 | "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
1318 | "dev": true,
1319 | "requires": {
1320 | "is-fullwidth-code-point": "^2.0.0",
1321 | "strip-ansi": "^4.0.0"
1322 | }
1323 | },
1324 | "strip-ansi": {
1325 | "version": "4.0.0",
1326 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
1327 | "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
1328 | "dev": true,
1329 | "requires": {
1330 | "ansi-regex": "^3.0.0"
1331 | }
1332 | }
1333 | }
1334 | },
1335 | "temp": {
1336 | "version": "0.8.4",
1337 | "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.4.tgz",
1338 | "integrity": "sha512-s0ZZzd0BzYv5tLSptZooSjK8oj6C+c19p7Vqta9+6NPOf7r+fxq0cJe6/oN4LTC79sy5NY8ucOJNgwsKCSbfqg==",
1339 | "requires": {
1340 | "rimraf": "~2.6.2"
1341 | },
1342 | "dependencies": {
1343 | "rimraf": {
1344 | "version": "2.6.3",
1345 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
1346 | "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
1347 | "requires": {
1348 | "glob": "^7.1.3"
1349 | }
1350 | }
1351 | }
1352 | },
1353 | "text-table": {
1354 | "version": "0.2.0",
1355 | "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
1356 | "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
1357 | "dev": true
1358 | },
1359 | "through": {
1360 | "version": "2.3.8",
1361 | "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
1362 | "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU="
1363 | },
1364 | "to-fast-properties": {
1365 | "version": "1.0.3",
1366 | "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz",
1367 | "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=",
1368 | "dev": true
1369 | },
1370 | "type": {
1371 | "version": "1.2.0",
1372 | "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz",
1373 | "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==",
1374 | "dev": true
1375 | },
1376 | "type-check": {
1377 | "version": "0.3.2",
1378 | "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
1379 | "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=",
1380 | "dev": true,
1381 | "requires": {
1382 | "prelude-ls": "~1.1.2"
1383 | }
1384 | },
1385 | "typedarray": {
1386 | "version": "0.0.6",
1387 | "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
1388 | "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
1389 | "dev": true
1390 | },
1391 | "underscore": {
1392 | "version": "1.9.1",
1393 | "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz",
1394 | "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg=="
1395 | },
1396 | "underscore-plus": {
1397 | "version": "1.7.0",
1398 | "resolved": "https://registry.npmjs.org/underscore-plus/-/underscore-plus-1.7.0.tgz",
1399 | "integrity": "sha512-A3BEzkeicFLnr+U/Q3EyWwJAQPbA19mtZZ4h+lLq3ttm9kn8WC4R3YpuJZEXmWdLjYP47Zc8aLZm9kwdv+zzvA==",
1400 | "requires": {
1401 | "underscore": "^1.9.1"
1402 | }
1403 | },
1404 | "user-home": {
1405 | "version": "2.0.0",
1406 | "resolved": "https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz",
1407 | "integrity": "sha1-nHC/2Babwdy/SGBODwS4tJzenp8=",
1408 | "dev": true,
1409 | "requires": {
1410 | "os-homedir": "^1.0.0"
1411 | }
1412 | },
1413 | "util-deprecate": {
1414 | "version": "1.0.2",
1415 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
1416 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
1417 | "dev": true
1418 | },
1419 | "word-wrap": {
1420 | "version": "1.2.3",
1421 | "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
1422 | "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
1423 | "dev": true
1424 | },
1425 | "wrappy": {
1426 | "version": "1.0.2",
1427 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
1428 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
1429 | },
1430 | "write": {
1431 | "version": "0.2.1",
1432 | "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz",
1433 | "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=",
1434 | "dev": true,
1435 | "requires": {
1436 | "mkdirp": "^0.5.1"
1437 | }
1438 | },
1439 | "xtend": {
1440 | "version": "4.0.2",
1441 | "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
1442 | "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
1443 | "dev": true
1444 | }
1445 | }
1446 | }
1447 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "symbols-view",
3 | "version": "0.118.4",
4 | "main": "./lib/main",
5 | "description": "Jump to a function/method in the current editor with `cmd-r`.",
6 | "license": "MIT",
7 | "activationCommands": {
8 | "atom-workspace": [
9 | "symbols-view:toggle-project-symbols"
10 | ],
11 | "atom-text-editor": [
12 | "symbols-view:go-to-declaration",
13 | "symbols-view:return-from-declaration",
14 | "symbols-view:toggle-file-symbols"
15 | ]
16 | },
17 | "dependencies": {
18 | "async": "^0.2.6",
19 | "atom-select-list": "^0.7.0",
20 | "ctags": "^3.1.0",
21 | "fs-plus": "^3.0.0",
22 | "fuzzaldrin": "^2.1.0",
23 | "humanize-plus": "^1.8.2",
24 | "temp": "^0.8.3",
25 | "underscore-plus": "^1.6.6"
26 | },
27 | "configSchema": {
28 | "useEditorGrammarAsCtagsLanguage": {
29 | "default": true,
30 | "type": "boolean",
31 | "description": "Force ctags to use the name of the current file's language in Atom when generating tags. By default, ctags automatically selects the language of a source file, ignoring those files whose language cannot be determined. This option forces the specified language to be used instead of automatically selecting the language based upon its extension."
32 | },
33 | "quickJumpToFileSymbol": {
34 | "default": true,
35 | "type": "boolean",
36 | "description": "Automatically visit selected file-symbols"
37 | }
38 | },
39 | "repository": "https://github.com/atom/symbols-view",
40 | "engines": {
41 | "atom": "*"
42 | },
43 | "devDependencies": {
44 | "babel-eslint": "^6.1.2",
45 | "eslint": "^3.12.2",
46 | "eslint-config-fbjs": "^1.1.1",
47 | "eslint-plugin-babel": "^3.3.0",
48 | "eslint-plugin-flowtype": "^2.29.1",
49 | "eslint-plugin-jasmine": "^2.2.0",
50 | "eslint-plugin-prefer-object-spread": "^1.1.0",
51 | "eslint-plugin-react": "^5.2.2"
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/spec/async-spec-helpers.js:
--------------------------------------------------------------------------------
1 | /** @babel */
2 |
3 | export function beforeEach(fn) {
4 | global.beforeEach(function() {
5 | const result = fn();
6 | if (result instanceof Promise) {
7 | waitsForPromise(() => result);
8 | }
9 | });
10 | }
11 |
12 | export function afterEach(fn) {
13 | global.afterEach(function() {
14 | const result = fn();
15 | if (result instanceof Promise) {
16 | waitsForPromise(() => result);
17 | }
18 | });
19 | }
20 |
21 | ['it', 'fit', 'ffit', 'fffit'].forEach(function(name) {
22 | module.exports[name] = function(description, fn) {
23 | global[name](description, function() {
24 | const result = fn();
25 | if (result instanceof Promise) {
26 | waitsForPromise(() => result);
27 | }
28 | });
29 | };
30 | });
31 |
32 | export async function conditionPromise(condition) {
33 | const startTime = Date.now();
34 |
35 | while (true) {
36 | await timeoutPromise(100);
37 |
38 | let conditionResult = condition();
39 | if (condition instanceof Promise) {
40 | conditionResult = await conditionResult;
41 | }
42 |
43 | if (conditionResult) {
44 | return;
45 | }
46 |
47 | if (Date.now() - startTime > 5000) {
48 | throw new Error('Timed out waiting on condition');
49 | }
50 | }
51 | }
52 |
53 | export function timeoutPromise(timeout) {
54 | return new Promise(function(resolve) {
55 | global.setTimeout(resolve, timeout);
56 | });
57 | }
58 |
59 | function waitsForPromise(fn) {
60 | const promise = fn();
61 | global.waitsFor('spec promise to resolve', function(done) {
62 | promise.then(done, function(error) {
63 | jasmine.getEnv().currentSpec.fail(error);
64 | done();
65 | });
66 | });
67 | }
68 |
--------------------------------------------------------------------------------
/spec/fixtures/c/sample.c:
--------------------------------------------------------------------------------
1 | #define UNUSED(x) (void)(x)
2 |
3 | static void f(int x)
4 | {
5 | UNUSED(x);
6 | }
7 |
--------------------------------------------------------------------------------
/spec/fixtures/c/tags:
--------------------------------------------------------------------------------
1 | !_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/
2 | !_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/
3 | !_TAG_PROGRAM_AUTHOR Darren Hiebert /dhiebert@users.sourceforge.net/
4 | !_TAG_PROGRAM_NAME Exuberant Ctags //
5 | !_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/
6 | !_TAG_PROGRAM_VERSION 5.9~svn20110310 //
7 | UNUSED sample.c 1;" d file:
8 | f sample.c /^static void f(int x)$/;" f file:
9 |
--------------------------------------------------------------------------------
/spec/fixtures/js/sample.js:
--------------------------------------------------------------------------------
1 | var quicksort = function () {
2 | var sort = function(items) {
3 | if (items.length <= 1) return items;
4 | var pivot = items.shift(), current, left = [], right = [];
5 | while(items.length > 0) {
6 | current = items.shift();
7 | current < pivot ? left.push(current) : right.push(current);
8 | }
9 | return sort(left).concat(pivot).concat(sort(right));
10 | };
11 |
12 | return sort(Array.apply(this, arguments));
13 | };
--------------------------------------------------------------------------------
/spec/fixtures/js/tagged-duplicate.js:
--------------------------------------------------------------------------------
1 | function duplicate() {
2 | return false;
3 | }
4 |
--------------------------------------------------------------------------------
/spec/fixtures/js/tagged.js:
--------------------------------------------------------------------------------
1 | var thisIsCrazy = true;
2 |
3 | function callMeMaybe() {
4 | return "here's my number";
5 | }
6 |
7 | var iJustMetYou = callMeMaybe();
8 |
9 | function duplicate() {
10 | return true;
11 | }
12 |
--------------------------------------------------------------------------------
/spec/fixtures/js/tags:
--------------------------------------------------------------------------------
1 | !_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/
2 | !_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/
3 | !_TAG_PROGRAM_AUTHOR Darren Hiebert /dhiebert@users.sourceforge.net/
4 | !_TAG_PROGRAM_NAME Exuberant Ctags //
5 | !_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/
6 | !_TAG_PROGRAM_VERSION 5.8 //
7 | callMeMaybe tagged.js /^function callMeMaybe() {$/;" f
8 | duplicate tagged-duplicate.js /^function duplicate() {$/;" f
9 | duplicate tagged.js /^function duplicate() {$/;" f
10 | thisIsCrazy tagged.js /^var thisIsCrazy = true;$/;" v
11 |
--------------------------------------------------------------------------------
/spec/fixtures/ruby/file1.rb:
--------------------------------------------------------------------------------
1 | module A::Foo
2 | B = 'b'
3 |
4 | def bar!
5 |
6 | end
7 |
8 | def bar?
9 |
10 | end
11 |
12 | def baz
13 | end
14 |
15 | def baz=(*)
16 | end
17 | end
18 |
19 | if bar?
20 | baz
21 | bar!
22 | elsif !bar!
23 | baz= 1
24 | baz = 2
25 | Foo = 3
26 | { :baz => 4 }
27 | A::Foo::B
28 | C::Foo::B
29 | D::Foo::E
30 | end
31 |
32 | module D::Foo
33 | end
34 |
--------------------------------------------------------------------------------
/spec/fixtures/ruby/tags:
--------------------------------------------------------------------------------
1 | !_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/
2 | !_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/
3 | !_TAG_PROGRAM_AUTHOR Darren Hiebert /dhiebert@users.sourceforge.net/
4 | !_TAG_PROGRAM_NAME Exuberant Ctags //
5 | !_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/
6 | !_TAG_PROGRAM_VERSION 5.8 //
7 | A::Foo file1.rb /^module A::Foo$/;" m
8 | A::Foo::B file1.rb /^ B = 'b'$/;" C
9 | B file1.rb /^ B = 'b'$/;" C
10 | D::Foo file1.rb /^module D::Foo$/;" m
11 | Foo file1.rb /^module A::Foo$/;" m
12 | bar! file1.rb /^ def bar!$/;" f class:Foo
13 | bar? file1.rb /^ def bar?$/;" f class:Foo
14 | baz file1.rb /^ def baz$/;" f class:Foo
15 | baz= file1.rb /^ def baz=(*)$/;" f class:Foo
16 |
--------------------------------------------------------------------------------
/spec/symbols-view-spec.js:
--------------------------------------------------------------------------------
1 | /** @babel */
2 | /* eslint-env jasmine */
3 |
4 | import path from 'path';
5 | import etch from 'etch';
6 | import fs from 'fs-plus';
7 | import temp from 'temp';
8 | import SymbolsView from '../lib/symbols-view';
9 | import TagGenerator from '../lib/tag-generator';
10 |
11 | import {it, fit, ffit, fffit, beforeEach, afterEach, conditionPromise} from './async-spec-helpers';
12 |
13 | describe('SymbolsView', () => {
14 | let [symbolsView, activationPromise, editor, directory] = [];
15 |
16 | const getWorkspaceView = () => atom.views.getView(atom.workspace);
17 | const getEditorView = () => atom.views.getView(atom.workspace.getActiveTextEditor());
18 |
19 | beforeEach(async () => {
20 | jasmine.unspy(global, 'setTimeout');
21 |
22 | atom.project.setPaths([
23 | temp.mkdirSync('other-dir-'),
24 | temp.mkdirSync('atom-symbols-view-'),
25 | ]);
26 |
27 | directory = atom.project.getDirectories()[1];
28 | fs.copySync(path.join(__dirname, 'fixtures', 'js'), atom.project.getPaths()[1]);
29 |
30 | activationPromise = atom.packages.activatePackage('symbols-view');
31 | jasmine.attachToDOM(getWorkspaceView());
32 | });
33 |
34 | describe('when tags can be generated for a file', () => {
35 | beforeEach(async () => {
36 | await atom.workspace.open(directory.resolve('sample.js'));
37 | });
38 |
39 | it('initially displays all JavaScript functions with line numbers', async () => {
40 | atom.commands.dispatch(getEditorView(), 'symbols-view:toggle-file-symbols');
41 | await activationPromise;
42 | symbolsView = atom.workspace.getModalPanels()[0].item;
43 | await conditionPromise(() => symbolsView.element.querySelectorAll('li').length > 0);
44 | expect(symbolsView.selectListView.refs.loadingMessage).toBeUndefined();
45 | expect(document.body.contains(symbolsView.element)).toBe(true);
46 | expect(symbolsView.element.querySelectorAll('li').length).toBe(2);
47 | expect(symbolsView.element.querySelector('li:first-child .primary-line')).toHaveText('quicksort');
48 | expect(symbolsView.element.querySelector('li:first-child .secondary-line')).toHaveText('Line 1');
49 | expect(symbolsView.element.querySelector('li:last-child .primary-line')).toHaveText('quicksort.sort');
50 | expect(symbolsView.element.querySelector('li:last-child .secondary-line')).toHaveText('Line 2');
51 | expect(symbolsView.selectListView.refs.errorMessage).toBeUndefined();
52 | });
53 |
54 | it('caches tags until the editor changes', async () => {
55 | editor = atom.workspace.getActiveTextEditor();
56 | atom.commands.dispatch(getEditorView(), 'symbols-view:toggle-file-symbols');
57 | await activationPromise;
58 | symbolsView = atom.workspace.getModalPanels()[0].item;
59 | await conditionPromise(() => symbolsView.element.querySelectorAll('li').length > 0);
60 | await symbolsView.cancel();
61 |
62 | spyOn(symbolsView, 'generateTags').andCallThrough();
63 | atom.commands.dispatch(getEditorView(), 'symbols-view:toggle-file-symbols');
64 | await conditionPromise(() => symbolsView.element.querySelectorAll('li').length > 0);
65 | expect(symbolsView.selectListView.refs.loadingMessage).toBeUndefined();
66 | expect(symbolsView.element.querySelectorAll('li').length).toBe(2);
67 | expect(symbolsView.generateTags).not.toHaveBeenCalled();
68 | await symbolsView.cancel();
69 |
70 | await editor.save();
71 | atom.commands.dispatch(getEditorView(), 'symbols-view:toggle-file-symbols');
72 | await conditionPromise(() => symbolsView.element.querySelectorAll('li').length > 0);
73 | expect(symbolsView.selectListView.refs.loadingMessage).toBeUndefined();
74 | expect(symbolsView.element.querySelectorAll('li').length).toBe(2);
75 | expect(symbolsView.generateTags).toHaveBeenCalled();
76 | editor.destroy();
77 | expect(symbolsView.cachedTags).toEqual({});
78 | });
79 |
80 | it('displays an error when no tags match text in mini-editor', async () => {
81 | atom.commands.dispatch(getEditorView(), 'symbols-view:toggle-file-symbols');
82 | await activationPromise;
83 | symbolsView = atom.workspace.getModalPanels()[0].item;
84 | await conditionPromise(() => symbolsView.element.querySelectorAll('li').length > 0);
85 |
86 | symbolsView.selectListView.refs.queryEditor.setText('nothing will match this');
87 | await conditionPromise(() => symbolsView.selectListView.refs.emptyMessage);
88 | expect(document.body.contains(symbolsView.element)).toBe(true);
89 | expect(symbolsView.element.querySelectorAll('li').length).toBe(0);
90 | expect(symbolsView.selectListView.refs.emptyMessage.textContent.length).toBeGreaterThan(0);
91 |
92 | // Should remove error
93 | symbolsView.selectListView.refs.queryEditor.setText('');
94 | await conditionPromise(() => symbolsView.element.querySelectorAll('li').length > 0);
95 | expect(symbolsView.element.querySelectorAll('li').length).toBe(2);
96 | expect(symbolsView.selectListView.refs.emptyMessage).toBeUndefined();
97 | });
98 |
99 | it('moves the cursor to the selected function', async () => {
100 | expect(atom.workspace.getActiveTextEditor().getCursorBufferPosition()).toEqual([0, 0]);
101 | atom.commands.dispatch(getEditorView(), 'symbols-view:toggle-file-symbols');
102 | await activationPromise;
103 | symbolsView = atom.workspace.getModalPanels()[0].item;
104 | await conditionPromise(() => symbolsView.element.querySelectorAll('li').length > 0);
105 |
106 | symbolsView.element.querySelectorAll('li')[1].click();
107 | expect(atom.workspace.getActiveTextEditor().getCursorBufferPosition()).toEqual([1, 2]);
108 | });
109 | });
110 |
111 | describe("when tags can't be generated for a file", () => {
112 | beforeEach(async () => {
113 | await atom.workspace.open('sample.txt');
114 | });
115 |
116 | it('shows an error message when no matching tags are found', async () => {
117 | atom.commands.dispatch(getEditorView(), 'symbols-view:toggle-file-symbols');
118 | await activationPromise;
119 | symbolsView = atom.workspace.getModalPanels()[0].item;
120 |
121 | await conditionPromise(() => symbolsView.selectListView.refs.emptyMessage);
122 | expect(document.body.contains(symbolsView.element));
123 | expect(symbolsView.element.querySelectorAll('li').length).toBe(0);
124 | expect(symbolsView.selectListView.refs.emptyMessage).toBeVisible();
125 | expect(symbolsView.selectListView.refs.emptyMessage.textContent.length).toBeGreaterThan(0);
126 | expect(symbolsView.selectListView.refs.loadingMessage).not.toBeVisible();
127 | });
128 | });
129 |
130 | describe('TagGenerator', () => {
131 | it('generates tags for all JavaScript functions', async () => {
132 | let tags = [];
133 | const sampleJsPath = directory.resolve('sample.js');
134 | await new TagGenerator(sampleJsPath).generate().then(o => tags = o);
135 | expect(tags.length).toBe(2);
136 | expect(tags[0].name).toBe('quicksort');
137 | expect(tags[0].position.row).toBe(0);
138 | expect(tags[1].name).toBe('quicksort.sort');
139 | expect(tags[1].position.row).toBe(1);
140 | });
141 |
142 | it('generates no tags for text file', async () => {
143 | let tags = [];
144 | const sampleJsPath = directory.resolve('sample.txt');
145 | await new TagGenerator(sampleJsPath).generate().then(o => tags = o);
146 | expect(tags.length).toBe(0);
147 | });
148 | });
149 |
150 | describe('go to declaration', () => {
151 | it("doesn't move the cursor when no declaration is found", async () => {
152 | await atom.workspace.open(directory.resolve('tagged.js'));
153 | editor = atom.workspace.getActiveTextEditor();
154 | editor.setCursorBufferPosition([0, 2]);
155 | atom.commands.dispatch(getEditorView(), 'symbols-view:go-to-declaration');
156 |
157 | await activationPromise;
158 |
159 | expect(editor.getCursorBufferPosition()).toEqual([0, 2]);
160 | });
161 |
162 | it('moves the cursor to the declaration when there is a single matching declaration', async () => {
163 | await atom.workspace.open(directory.resolve('tagged.js'));
164 | editor = atom.workspace.getActiveTextEditor();
165 | editor.setCursorBufferPosition([6, 24]);
166 | spyOn(SymbolsView.prototype, 'moveToPosition').andCallThrough();
167 | atom.commands.dispatch(getEditorView(), 'symbols-view:go-to-declaration');
168 |
169 | await conditionPromise(() => SymbolsView.prototype.moveToPosition.callCount === 1);
170 | expect(editor.getCursorBufferPosition()).toEqual([2, 0]);
171 | });
172 |
173 | it('correctly moves the cursor to the declaration of a C preprocessor macro', async () => {
174 | atom.project.setPaths([temp.mkdirSync('atom-symbols-view-c-')]);
175 | fs.copySync(path.join(__dirname, 'fixtures', 'c'), atom.project.getPaths()[0]);
176 |
177 | await atom.packages.activatePackage('language-c');
178 | await atom.workspace.open('sample.c');
179 |
180 | editor = atom.workspace.getActiveTextEditor();
181 | editor.setCursorBufferPosition([4, 4]);
182 | spyOn(SymbolsView.prototype, 'moveToPosition').andCallThrough();
183 | atom.commands.dispatch(getEditorView(), 'symbols-view:go-to-declaration');
184 |
185 | await conditionPromise(() => SymbolsView.prototype.moveToPosition.callCount === 1);
186 | expect(editor.getCursorBufferPosition()).toEqual([0, 0]);
187 | });
188 |
189 | it('displays matches when more than one exists and opens the selected match', async () => {
190 | await atom.workspace.open(directory.resolve('tagged.js'));
191 | editor = atom.workspace.getActiveTextEditor();
192 | editor.setCursorBufferPosition([8, 14]);
193 | atom.commands.dispatch(getEditorView(), 'symbols-view:go-to-declaration');
194 | symbolsView = atom.workspace.getModalPanels()[0].item;
195 |
196 | await conditionPromise(() => symbolsView.element.querySelectorAll('li').length > 0);
197 | expect(symbolsView.element.querySelectorAll('li').length).toBe(2);
198 | expect(symbolsView.element).toBeVisible();
199 | spyOn(SymbolsView.prototype, 'moveToPosition').andCallThrough();
200 | symbolsView.selectListView.confirmSelection();
201 |
202 | await conditionPromise(() => SymbolsView.prototype.moveToPosition.callCount === 1);
203 | expect(atom.workspace.getActiveTextEditor().getPath()).toBe(directory.resolve('tagged-duplicate.js'));
204 | expect(atom.workspace.getActiveTextEditor().getCursorBufferPosition()).toEqual([0, 4]);
205 | });
206 |
207 | it('includes ? and ! characters in ruby symbols', async () => {
208 | atom.project.setPaths([temp.mkdirSync('atom-symbols-view-ruby-')]);
209 | fs.copySync(path.join(__dirname, 'fixtures', 'ruby'), atom.project.getPaths()[0]);
210 |
211 | await atom.packages.activatePackage('language-ruby');
212 | await atom.workspace.open('file1.rb');
213 |
214 | spyOn(SymbolsView.prototype, 'moveToPosition').andCallThrough();
215 | atom.workspace.getActiveTextEditor().setCursorBufferPosition([18, 4]);
216 | atom.commands.dispatch(getEditorView(), 'symbols-view:go-to-declaration');
217 |
218 | await activationPromise;
219 | await conditionPromise(() => SymbolsView.prototype.moveToPosition.callCount === 1);
220 | expect(atom.workspace.getActiveTextEditor().getCursorBufferPosition()).toEqual([7, 2]);
221 | SymbolsView.prototype.moveToPosition.reset();
222 | atom.workspace.getActiveTextEditor().setCursorBufferPosition([19, 2]);
223 | atom.commands.dispatch(getEditorView(), 'symbols-view:go-to-declaration');
224 |
225 | await conditionPromise(() => SymbolsView.prototype.moveToPosition.callCount === 1);
226 | expect(atom.workspace.getActiveTextEditor().getCursorBufferPosition()).toEqual([11, 2]);
227 | SymbolsView.prototype.moveToPosition.reset();
228 | atom.workspace.getActiveTextEditor().setCursorBufferPosition([20, 5]);
229 | atom.commands.dispatch(getEditorView(), 'symbols-view:go-to-declaration');
230 |
231 | await conditionPromise(() => SymbolsView.prototype.moveToPosition.callCount === 1);
232 | expect(atom.workspace.getActiveTextEditor().getCursorBufferPosition()).toEqual([3, 2]);
233 | SymbolsView.prototype.moveToPosition.reset();
234 | atom.workspace.getActiveTextEditor().setCursorBufferPosition([21, 7]);
235 | atom.commands.dispatch(getEditorView(), 'symbols-view:go-to-declaration');
236 |
237 | await conditionPromise(() => SymbolsView.prototype.moveToPosition.callCount === 1);
238 | expect(atom.workspace.getActiveTextEditor().getCursorBufferPosition()).toEqual([3, 2]);
239 | });
240 |
241 | it('handles jumping to assignment ruby method definitions', async () => {
242 | atom.project.setPaths([temp.mkdirSync('atom-symbols-view-ruby-')]);
243 | fs.copySync(path.join(__dirname, 'fixtures', 'ruby'), atom.project.getPaths()[0]);
244 |
245 | await atom.packages.activatePackage('language-ruby');
246 | await atom.workspace.open('file1.rb');
247 | spyOn(SymbolsView.prototype, 'moveToPosition').andCallThrough();
248 | atom.workspace.getActiveTextEditor().setCursorBufferPosition([22, 5]);
249 | atom.commands.dispatch(getEditorView(), 'symbols-view:go-to-declaration');
250 |
251 | await conditionPromise(() => SymbolsView.prototype.moveToPosition.callCount === 1);
252 | expect(atom.workspace.getActiveTextEditor().getCursorBufferPosition()).toEqual([14, 2]);
253 | SymbolsView.prototype.moveToPosition.reset();
254 | atom.workspace.getActiveTextEditor().setCursorBufferPosition([23, 5]);
255 | atom.commands.dispatch(getEditorView(), 'symbols-view:go-to-declaration');
256 |
257 | await conditionPromise(() => SymbolsView.prototype.moveToPosition.callCount === 1);
258 | expect(atom.workspace.getActiveTextEditor().getCursorBufferPosition()).toEqual([14, 2]);
259 | SymbolsView.prototype.moveToPosition.reset();
260 | atom.workspace.getActiveTextEditor().setCursorBufferPosition([24, 5]);
261 | atom.commands.dispatch(getEditorView(), 'symbols-view:go-to-declaration');
262 |
263 | await conditionPromise(() => SymbolsView.prototype.moveToPosition.callCount === 1);
264 | expect(atom.workspace.getActiveTextEditor().getCursorBufferPosition()).toEqual([0, 0]);
265 | SymbolsView.prototype.moveToPosition.reset();
266 | atom.workspace.getActiveTextEditor().setCursorBufferPosition([25, 5]);
267 | atom.commands.dispatch(getEditorView(), 'symbols-view:go-to-declaration');
268 |
269 | await conditionPromise(() => SymbolsView.prototype.moveToPosition.callCount === 1);
270 | expect(atom.workspace.getActiveTextEditor().getCursorBufferPosition()).toEqual([11, 2]);
271 | });
272 |
273 | it('handles jumping to fully qualified ruby constant definitions', async () => {
274 | atom.project.setPaths([temp.mkdirSync('atom-symbols-view-ruby-')]);
275 | fs.copySync(path.join(__dirname, 'fixtures', 'ruby'), atom.project.getPaths()[0]);
276 | await atom.packages.activatePackage('language-ruby');
277 | await atom.workspace.open('file1.rb');
278 | spyOn(SymbolsView.prototype, 'moveToPosition').andCallThrough();
279 | atom.workspace.getActiveTextEditor().setCursorBufferPosition([26, 10]);
280 | atom.commands.dispatch(getEditorView(), 'symbols-view:go-to-declaration');
281 |
282 | await conditionPromise(() => SymbolsView.prototype.moveToPosition.callCount === 1);
283 | expect(atom.workspace.getActiveTextEditor().getCursorBufferPosition()).toEqual([1, 2]);
284 | SymbolsView.prototype.moveToPosition.reset();
285 | atom.workspace.getActiveTextEditor().setCursorBufferPosition([27, 5]);
286 | atom.commands.dispatch(getEditorView(), 'symbols-view:go-to-declaration');
287 |
288 | await conditionPromise(() => SymbolsView.prototype.moveToPosition.callCount === 1);
289 | expect(atom.workspace.getActiveTextEditor().getCursorBufferPosition()).toEqual([0, 0]);
290 | SymbolsView.prototype.moveToPosition.reset();
291 | atom.workspace.getActiveTextEditor().setCursorBufferPosition([28, 5]);
292 | atom.commands.dispatch(getEditorView(), 'symbols-view:go-to-declaration');
293 |
294 | await conditionPromise(() => SymbolsView.prototype.moveToPosition.callCount === 1);
295 | expect(atom.workspace.getActiveTextEditor().getCursorBufferPosition()).toEqual([31, 0]);
296 | });
297 |
298 | describe('return from declaration', () => {
299 | it("doesn't do anything when no go-to have been triggered", async () => {
300 | await atom.workspace.open(directory.resolve('tagged.js'));
301 | editor = atom.workspace.getActiveTextEditor();
302 | editor.setCursorBufferPosition([6, 0]);
303 | atom.commands.dispatch(getEditorView(), 'symbols-view:return-from-declaration');
304 |
305 | await activationPromise;
306 | expect(editor.getCursorBufferPosition()).toEqual([6, 0]);
307 | });
308 |
309 | it('returns to previous row and column', async () => {
310 | await atom.workspace.open(directory.resolve('tagged.js'));
311 | editor = atom.workspace.getActiveTextEditor();
312 | editor.setCursorBufferPosition([6, 24]);
313 | spyOn(SymbolsView.prototype, 'moveToPosition').andCallThrough();
314 | atom.commands.dispatch(getEditorView(), 'symbols-view:go-to-declaration');
315 |
316 | await activationPromise;
317 | await conditionPromise(() => SymbolsView.prototype.moveToPosition.callCount === 1);
318 | expect(editor.getCursorBufferPosition()).toEqual([2, 0]);
319 | atom.commands.dispatch(getEditorView(), 'symbols-view:return-from-declaration');
320 |
321 | await conditionPromise(() => SymbolsView.prototype.moveToPosition.callCount === 2);
322 | expect(editor.getCursorBufferPosition()).toEqual([6, 24]);
323 | });
324 | });
325 |
326 | describe("when the tag is in a file that doesn't exist", () => {
327 | it("doesn't display the tag", async () => {
328 | fs.removeSync(directory.resolve('tagged-duplicate.js'));
329 | await atom.workspace.open(directory.resolve('tagged.js'));
330 |
331 | editor = atom.workspace.getActiveTextEditor();
332 | editor.setCursorBufferPosition([8, 14]);
333 | spyOn(SymbolsView.prototype, 'moveToPosition').andCallThrough();
334 | atom.commands.dispatch(getEditorView(), 'symbols-view:go-to-declaration');
335 |
336 | await conditionPromise(() => SymbolsView.prototype.moveToPosition.callCount === 1);
337 | expect(editor.getCursorBufferPosition()).toEqual([8, 0]);
338 | });
339 | });
340 | });
341 |
342 | describe('project symbols', () => {
343 | it('displays all tags', async () => {
344 | await atom.workspace.open(directory.resolve('tagged.js'));
345 | expect(getWorkspaceView().querySelector('.symbols-view')).toBeNull();
346 | atom.commands.dispatch(getWorkspaceView(), 'symbols-view:toggle-project-symbols');
347 |
348 | await activationPromise;
349 | symbolsView = atom.workspace.getModalPanels()[0].item;
350 |
351 | await conditionPromise(() => symbolsView.element.querySelectorAll('li').length > 0);
352 | const directoryBasename = path.basename(directory.getPath());
353 | const taggedFile = path.join(directoryBasename, 'tagged.js');
354 | expect(symbolsView.selectListView.refs.loadingMessage).toBeUndefined();
355 | expect(document.body.contains(symbolsView.element)).toBe(true);
356 | expect(symbolsView.element.querySelectorAll('li').length).toBe(4);
357 | expect(symbolsView.element.querySelector('li:first-child .primary-line')).toHaveText('callMeMaybe');
358 | expect(symbolsView.element.querySelector('li:first-child .secondary-line')).toHaveText(taggedFile);
359 | expect(symbolsView.element.querySelector('li:last-child .primary-line')).toHaveText('thisIsCrazy');
360 | expect(symbolsView.element.querySelector('li:last-child .secondary-line')).toHaveText(taggedFile);
361 | atom.commands.dispatch(getWorkspaceView(), 'symbols-view:toggle-project-symbols');
362 | fs.removeSync(directory.resolve('tags'));
363 |
364 | await conditionPromise(() => symbolsView.reloadTags);
365 | atom.commands.dispatch(getWorkspaceView(), 'symbols-view:toggle-project-symbols');
366 |
367 | await conditionPromise(() => symbolsView.selectListView.refs.loadingMessage);
368 | await conditionPromise(() => symbolsView.element.querySelectorAll('li').length === 0);
369 | });
370 |
371 | describe('when there is only one project', () => {
372 | beforeEach(async () => atom.project.setPaths([directory.getPath()]));
373 |
374 | it("does not include the root directory's name when displaying the tag's filename", async () => {
375 | await atom.workspace.open(directory.resolve('tagged.js'));
376 | expect(getWorkspaceView().querySelector('.symbols-view')).toBeNull();
377 | atom.commands.dispatch(getWorkspaceView(), 'symbols-view:toggle-project-symbols');
378 |
379 | await activationPromise;
380 | symbolsView = atom.workspace.getModalPanels()[0].item;
381 | await conditionPromise(() => symbolsView.element.querySelectorAll('li').length > 0);
382 | expect(symbolsView.element.querySelector('li:first-child .primary-line')).toHaveText('callMeMaybe');
383 | expect(symbolsView.element.querySelector('li:first-child .secondary-line')).toHaveText('tagged.js');
384 | });
385 | });
386 |
387 | describe('when selecting a tag', () => {
388 | describe("when the file doesn't exist", () => {
389 | beforeEach(async () => fs.removeSync(directory.resolve('tagged.js')));
390 |
391 | it("doesn't open the editor", async () => {
392 | atom.commands.dispatch(getWorkspaceView(), 'symbols-view:toggle-project-symbols');
393 |
394 | await activationPromise;
395 |
396 | symbolsView = atom.workspace.getModalPanels()[0].item;
397 |
398 | await conditionPromise(() => symbolsView.element.querySelectorAll('li').length > 0);
399 | spyOn(atom.workspace, 'open').andCallThrough();
400 | symbolsView.element.querySelector('li:first-child').click();
401 | await conditionPromise(() => symbolsView.selectListView.refs.errorMessage);
402 | expect(atom.workspace.open).not.toHaveBeenCalled();
403 | expect(symbolsView.selectListView.refs.errorMessage.textContent.length).toBeGreaterThan(0);
404 | });
405 | });
406 | });
407 | });
408 |
409 | describe('when useEditorGrammarAsCtagsLanguage is set to true', () => {
410 | it("uses the language associated with the editor's grammar", async () => {
411 | atom.config.set('symbols-view.useEditorGrammarAsCtagsLanguage', true);
412 |
413 | await atom.packages.activatePackage('language-javascript');
414 | await atom.workspace.open('sample.javascript');
415 | atom.workspace.getActiveTextEditor().setText('var test = function() {}');
416 | await atom.workspace.getActiveTextEditor().save();
417 | atom.commands.dispatch(getEditorView(), 'symbols-view:toggle-file-symbols');
418 | await activationPromise;
419 |
420 | symbolsView = atom.workspace.getModalPanels()[0].item;
421 | await conditionPromise(() => symbolsView.selectListView.refs.emptyMessage);
422 | atom.commands.dispatch(getEditorView(), 'symbols-view:toggle-file-symbols');
423 |
424 | atom.workspace.getActiveTextEditor().setGrammar(atom.grammars.grammarForScopeName('source.js'));
425 | atom.commands.dispatch(getEditorView(), 'symbols-view:toggle-file-symbols');
426 | await conditionPromise(() => symbolsView.element.querySelectorAll('li').length === 1);
427 | expect(document.body.contains(symbolsView.element)).toBe(true);
428 | expect(symbolsView.element.querySelector('li:first-child .primary-line')).toHaveText('test');
429 | expect(symbolsView.element.querySelector('li:first-child .secondary-line')).toHaveText('Line 1');
430 | });
431 | });
432 |
433 | describe('match highlighting', () => {
434 | beforeEach(async () => {
435 | await atom.workspace.open(directory.resolve('sample.js'));
436 | });
437 |
438 | it('highlights an exact match', async () => {
439 | atom.commands.dispatch(getEditorView(), 'symbols-view:toggle-file-symbols');
440 |
441 | await activationPromise;
442 | symbolsView = atom.workspace.getModalPanels()[0].item;
443 | await conditionPromise(() => symbolsView.element.querySelectorAll('li').length > 0);
444 | symbolsView.selectListView.refs.queryEditor.setText('quicksort');
445 | await getOrScheduleUpdatePromise();
446 | const resultView = symbolsView.element.querySelector('.selected');
447 | const matches = resultView.querySelectorAll('.character-match');
448 | expect(matches.length).toBe(1);
449 | expect(matches[0].textContent).toBe('quicksort');
450 | });
451 |
452 | it('highlights a partial match', async () => {
453 | atom.commands.dispatch(getEditorView(), 'symbols-view:toggle-file-symbols');
454 | await activationPromise;
455 | symbolsView = atom.workspace.getModalPanels()[0].item;
456 | await conditionPromise(() => symbolsView.element.querySelectorAll('li').length > 0);
457 | symbolsView.selectListView.refs.queryEditor.setText('quick');
458 | await getOrScheduleUpdatePromise();
459 | const resultView = symbolsView.element.querySelector('.selected');
460 | const matches = resultView.querySelectorAll('.character-match');
461 | expect(matches.length).toBe(1);
462 | expect(matches[0].textContent).toBe('quick');
463 | });
464 |
465 | it('highlights multiple matches in the symbol name', async () => {
466 | atom.commands.dispatch(getEditorView(), 'symbols-view:toggle-file-symbols');
467 | await activationPromise;
468 | symbolsView = atom.workspace.getModalPanels()[0].item;
469 | await conditionPromise(() => symbolsView.element.querySelectorAll('li').length > 0);
470 | symbolsView.selectListView.refs.queryEditor.setText('quicort');
471 | await getOrScheduleUpdatePromise();
472 | const resultView = symbolsView.element.querySelector('.selected');
473 | const matches = resultView.querySelectorAll('.character-match');
474 | expect(matches.length).toBe(2);
475 | expect(matches[0].textContent).toBe('quic');
476 | expect(matches[1].textContent).toBe('ort');
477 | });
478 | });
479 |
480 | describe('quickjump to symbol', () => {
481 | beforeEach(async () => {
482 | await atom.workspace.open(directory.resolve('sample.js'));
483 | });
484 |
485 | it('jumps to the selected function', async () => {
486 | expect(atom.workspace.getActiveTextEditor().getCursorBufferPosition()).toEqual([0, 0]);
487 | atom.commands.dispatch(getEditorView(), 'symbols-view:toggle-file-symbols');
488 | await activationPromise;
489 | symbolsView = atom.workspace.getModalPanels()[0].item;
490 | await conditionPromise(() => symbolsView.element.querySelectorAll('li').length > 0);
491 | symbolsView.selectListView.selectNext();
492 | expect(atom.workspace.getActiveTextEditor().getCursorBufferPosition()).toEqual([1, 2]);
493 | });
494 |
495 | it('restores previous editor state on cancel', async () => {
496 | const bufferRanges = [{start: {row: 0, column: 0}, end: {row: 0, column: 3}}];
497 | atom.workspace.getActiveTextEditor().setSelectedBufferRanges(bufferRanges);
498 | atom.commands.dispatch(getEditorView(), 'symbols-view:toggle-file-symbols');
499 |
500 | await activationPromise;
501 | symbolsView = atom.workspace.getModalPanels()[0].item;
502 | await conditionPromise(() => symbolsView.element.querySelectorAll('li').length > 0);
503 |
504 | symbolsView.selectListView.selectNext();
505 | expect(atom.workspace.getActiveTextEditor().getCursorBufferPosition()).toEqual([1, 2]);
506 | await symbolsView.cancel();
507 | expect(atom.workspace.getActiveTextEditor().getSelectedBufferRanges()).toEqual(bufferRanges);
508 | });
509 | });
510 |
511 | describe('when quickJumpToSymbol is set to false', async () => {
512 | beforeEach(async () => {
513 | atom.config.set('symbols-view.quickJumpToFileSymbol', false);
514 | await atom.workspace.open(directory.resolve('sample.js'));
515 | });
516 |
517 | it("won't jumps to the selected function", async () => {
518 | expect(atom.workspace.getActiveTextEditor().getCursorBufferPosition()).toEqual([0, 0]);
519 | atom.commands.dispatch(getEditorView(), 'symbols-view:toggle-file-symbols');
520 |
521 | await activationPromise;
522 | symbolsView = atom.workspace.getModalPanels()[0].item;
523 | await conditionPromise(() => symbolsView.element.querySelectorAll('li').length > 0);
524 | symbolsView.selectListView.selectNext();
525 | expect(atom.workspace.getActiveTextEditor().getCursorBufferPosition()).toEqual([0, 0]);
526 | });
527 | });
528 | });
529 |
530 | function getOrScheduleUpdatePromise () {
531 | return new Promise((resolve) => etch.getScheduler().updateDocument(resolve))
532 | }
533 |
--------------------------------------------------------------------------------
/styles/symbols-view.less:
--------------------------------------------------------------------------------
1 | @import "ui-variables";
2 |
3 | // Highlight matched text
4 | .symbols-view .list-group .character-match {
5 | color: @text-color-highlight;
6 | font-weight: bold;
7 | }
8 |
--------------------------------------------------------------------------------
/vendor/ctags-darwin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/atom/symbols-view/b39fb1d3e141b57f54f6d31c81dfec4513fb2e2f/vendor/ctags-darwin
--------------------------------------------------------------------------------
/vendor/ctags-linux:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/atom/symbols-view/b39fb1d3e141b57f54f6d31c81dfec4513fb2e2f/vendor/ctags-linux
--------------------------------------------------------------------------------
/vendor/ctags-win32.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/atom/symbols-view/b39fb1d3e141b57f54f6d31c81dfec4513fb2e2f/vendor/ctags-win32.exe
--------------------------------------------------------------------------------