diff --git a/package.json b/package.json
index b0cb5977a..6e2ee0125 100644
--- a/package.json
+++ b/package.json
@@ -156,7 +156,7 @@
"status-bar": "file:packages/status-bar",
"styleguide": "file:./packages/styleguide",
"superstring": "^2.4.4",
- "symbols-view": "https://codeload.github.com/atom/symbols-view/legacy.tar.gz/refs/tags/v0.118.4",
+ "symbols-view": "file:./packages/symbols-view",
"tabs": "file:packages/tabs",
"temp": "0.9.4",
"text-buffer": "^13.18.6",
@@ -224,7 +224,7 @@
"spell-check": "0.77.1",
"status-bar": "file:./packages/status-bar",
"styleguide": "file:./packages/styleguide",
- "symbols-view": "0.118.4",
+ "symbols-view": "file:./packages/symbols-view",
"tabs": "file:./packages/tabs",
"timecop": "file:./packages/timecop",
"tree-view": "0.229.1",
diff --git a/packages/symbols-view/.eslintignore b/packages/symbols-view/.eslintignore
new file mode 100644
index 000000000..c9d5b1e13
--- /dev/null
+++ b/packages/symbols-view/.eslintignore
@@ -0,0 +1 @@
+**/fixtures/**/*.js
diff --git a/packages/symbols-view/.eslintrc.js b/packages/symbols-view/.eslintrc.js
new file mode 100644
index 000000000..8c11ad1d1
--- /dev/null
+++ b/packages/symbols-view/.eslintrc.js
@@ -0,0 +1,7 @@
+module.exports = {
+ parser: 'babel-eslint',
+ extends: 'fbjs',
+ globals: {
+ atom: true
+ }
+};
diff --git a/packages/symbols-view/.github/no-response.yml b/packages/symbols-view/.github/no-response.yml
new file mode 100644
index 000000000..1c8799d13
--- /dev/null
+++ b/packages/symbols-view/.github/no-response.yml
@@ -0,0 +1,15 @@
+# Configuration for probot-no-response - https://github.com/probot/no-response
+
+# Number of days of inactivity before an issue is closed for lack of response
+daysUntilClose: 28
+
+# Label requiring a response
+responseRequiredLabel: more-information-needed
+
+# Comment to post when closing an issue for lack of response. Set to `false` to disable.
+closeComment: >
+ This issue has been automatically closed because there has been no response
+ to our request for more information from the original author. With only the
+ information that is currently in the issue, we don't have enough information
+ to take action. Please reach out if you have or find the answers we need so
+ that we can investigate further.
diff --git a/packages/symbols-view/.gitignore b/packages/symbols-view/.gitignore
new file mode 100644
index 000000000..3c3629e64
--- /dev/null
+++ b/packages/symbols-view/.gitignore
@@ -0,0 +1 @@
+node_modules
diff --git a/packages/symbols-view/.pairs b/packages/symbols-view/.pairs
new file mode 100644
index 000000000..91845b111
--- /dev/null
+++ b/packages/symbols-view/.pairs
@@ -0,0 +1,16 @@
+pairs:
+ ns: Nathan Sobo; nathan
+ cj: Corey Johnson; cj
+ dg: David Graham; dgraham
+ ks: Kevin Sawicki; kevin
+ jc: Jerry Cheung; jerry
+ bl: Brian Lopez; brian
+ jp: Justin Palmer; justin
+ gt: Garen Torikian; garen
+ mc: Matt Colyer; mcolyer
+ bo: Ben Ogle; benogle
+ jr: Jason Rudolph; jasonrudolph
+ jl: Jessica Lord; jlord
+email:
+ domain: github.com
+#global: true
diff --git a/packages/symbols-view/.travis.yml b/packages/symbols-view/.travis.yml
new file mode 100644
index 000000000..20cfe5175
--- /dev/null
+++ b/packages/symbols-view/.travis.yml
@@ -0,0 +1,15 @@
+language: objective-c
+
+notifications:
+ email:
+ on_success: never
+ on_failure: change
+
+script: 'curl -s https://raw.githubusercontent.com/atom/ci/master/build-package.sh | sh'
+
+git:
+ depth: 10
+
+branches:
+ only:
+ - master
diff --git a/packages/symbols-view/CONTRIBUTING.md b/packages/symbols-view/CONTRIBUTING.md
new file mode 100644
index 000000000..9c8ac3e5b
--- /dev/null
+++ b/packages/symbols-view/CONTRIBUTING.md
@@ -0,0 +1 @@
+[See how you can contribute](https://github.com/pulsar-edit/.github/blob/main/CONTRIBUTING.md)
diff --git a/packages/symbols-view/LICENSE.md b/packages/symbols-view/LICENSE.md
new file mode 100644
index 000000000..4d231b456
--- /dev/null
+++ b/packages/symbols-view/LICENSE.md
@@ -0,0 +1,20 @@
+Copyright (c) 2014 GitHub Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/packages/symbols-view/README.md b/packages/symbols-view/README.md
new file mode 100644
index 000000000..fd20ed5b0
--- /dev/null
+++ b/packages/symbols-view/README.md
@@ -0,0 +1,16 @@
+# Symbols View package
+
+Display the list of functions/methods in the editor.
+
+If your project has a `tags`/`.tags`/`TAGS`/`.TAGS` file at the root then following are supported:
+
+|Command|Description|Keybinding (Linux)|Keybinding (macOS)|Keybinding (Windows)|
+|-------|-----------|------------------|-----------------|--------------------|
+|`symbols-view:toggle-file-symbols`|Show all symbols in current file|ctrl-r|cmd-r|ctrl-r|
+|`symbols-view:toggle-project-symbols`|Show all symbols in the project|ctrl-shift-r|cmd-shift-r|ctrl-shift-r|
+|`symbols-view:go-to-declaration`|Jump to the symbol under the cursor|ctrl-alt-down|cmd-alt-down||
+|`symbols-view:return-from-declaration`|Return from the jump|ctrl-alt-up|cmd-alt-up||
+
+This package uses [ctags](http://ctags.sourceforge.net).
+
+![](https://f.cloud.github.com/assets/671378/2241860/30ef0b2e-9ce8-11e3-86e2-2c17c0885fa4.png)
diff --git a/packages/symbols-view/appveyor.yml b/packages/symbols-view/appveyor.yml
new file mode 100644
index 000000000..3ab50c6e5
--- /dev/null
+++ b/packages/symbols-view/appveyor.yml
@@ -0,0 +1,29 @@
+image: Visual Studio 2015
+
+version: "{build}"
+
+platform: x64
+
+branches:
+ only:
+ - master
+
+clone_depth: 10
+
+skip_tags: true
+
+environment:
+ APM_TEST_PACKAGES:
+
+ matrix:
+ - ATOM_CHANNEL: stable
+ - ATOM_CHANNEL: beta
+
+install:
+ - ps: Install-Product node 4
+
+build_script:
+ - ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/atom/ci/master/build-package.ps1'))
+
+test: off
+deploy: off
diff --git a/packages/symbols-view/keymaps/symbols-view.cson b/packages/symbols-view/keymaps/symbols-view.cson
new file mode 100644
index 000000000..1014a3955
--- /dev/null
+++ b/packages/symbols-view/keymaps/symbols-view.cson
@@ -0,0 +1,18 @@
+'.platform-darwin atom-text-editor':
+ 'cmd-r': 'symbols-view:toggle-file-symbols'
+ 'cmd-alt-down': 'symbols-view:go-to-declaration'
+ 'cmd-alt-up': 'symbols-view:return-from-declaration'
+
+'.platform-win32 atom-text-editor':
+ 'ctrl-r': 'symbols-view:toggle-file-symbols'
+
+'.platform-linux atom-text-editor':
+ 'ctrl-r': 'symbols-view:toggle-file-symbols'
+ 'ctrl-alt-down': 'symbols-view:go-to-declaration'
+ 'ctrl-alt-up': 'symbols-view:return-from-declaration'
+
+'.platform-darwin':
+ 'cmd-shift-r': 'symbols-view:toggle-project-symbols'
+
+'.platform-win32, .platform-linux':
+ 'ctrl-shift-r': 'symbols-view:toggle-project-symbols'
diff --git a/packages/symbols-view/lib/ctags-config b/packages/symbols-view/lib/ctags-config
new file mode 100644
index 000000000..66d26e8eb
--- /dev/null
+++ b/packages/symbols-view/lib/ctags-config
@@ -0,0 +1,198 @@
+--langdef=CoffeeScript
+--langmap=CoffeeScript:.coffee
+--regex-CoffeeScript=/^[ \t]*(@?[a-zA-Z$_\.0-9]+)[ \t]*(=|\:)[ \t]*(\(.*\))?[ \t]*(-|=)>/\1/f,function/
+--regex-CoffeeScript=/^[ \t]*([a-zA-Z$_0-9]+\:\:[a-zA-Z$_\.0-9]+)[ \t]*(=|\:)[ \t]*(\(.*\))?[ \t]*(-|=)>/\1/f,function/
+--regex-CoffeeScript=/^[ \t]*describe[ \t]"(.+)"[ \t]*,[ \t]+[-=]>/\1/f,function/
+--regex-CoffeeScript=/^[ \t]*describe[ \t]'(.+)'[ \t]*,[ \t]+[-=]>/\1/f,function/
+--regex-CoffeeScript=/^[ \t]*it[ \t]"([^"]+)"[ \t]*,[ \t]+[-=]>/\1/f,function/
+--regex-CoffeeScript=/^[ \t]*it[ \t]'([^']+)'[ \t]*,[ \t]+[-=]>/\1/f,function/
+--regex-CoffeeScript=/^[ \t]*f+describe[ \t]"(.+)"[ \t]*,[ \t]+[-=]>/focused\: \1/f,function/
+--regex-CoffeeScript=/^[ \t]*f+describe[ \t]'(.+)'[ \t]*,[ \t]+[-=]>/focused: \1/f,function/
+--regex-CoffeeScript=/^[ \t]*f+it[ \t]"([^"]+)"[ \t]*,[ \t]+[-=]>/focused: \1/f,function/
+--regex-CoffeeScript=/^[ \t]*f+it[ \t]'([^']+)'[ \t]*,[ \t]+[-=]>/focused: \1/f,function/
+--regex-CoffeeScript=/^[ \t]*xdescribe[ \t]"(.+)"[ \t]*,[ \t]+[-=]>/disabled\: \1/f,function/
+--regex-CoffeeScript=/^[ \t]*xdescribe[ \t]'(.+)'[ \t]*,[ \t]+[-=]>/disabled: \1/f,function/
+--regex-CoffeeScript=/^[ \t]*xit[ \t]"([^"]+)"[ \t]*,[ \t]+[-=]>/disabled: \1/f,function/
+--regex-CoffeeScript=/^[ \t]*xit[ \t]'([^']+)'[ \t]*,[ \t]+[-=]>/disabled: \1/f,function/
+--regex-CoffeeScript=/^[ \t]*class[ \t]*([a-zA-Z$_\.0-9]+)[ \t]*/\1/f,function/
+
+--langdef=ColdFusion
+--langmap=ColdFusion:.cfc
+--langmap=ColdFusion:+.cfm
+--langmap=ColdFusion:+.cfml
+--regex-ColdFusion=/(,|(;|^)[ \t]*(var|([A-Za-z_$][A-Za-z0-9_$.]*\.)*))[ \t]*([A-Za-z0-9_$]+)[ \t]*=[ \t]*function[ \t]*\(/\5/,function/
+--regex-ColdFusion=/function[ \t]+([A-Za-z0-9_$]+)[ \t]*\([^)]*\)/\1/,function/
+--regex-ColdFusion=/cffunction[ \t]+([A-Za-z0-9_$]+)[ \t]*\([^)]*\)/\1/,cffunction/
+--regex-ColdFusion=/(,|^|\*\/)[ \t]*([A-Za-z_$][A-Za-z0-9_$]+)[ \t]*:[ \t]*function[ \t]*\(/\2/,function/
+--regex-ColdFusion=/(,|^|\*\/)[ \t]*(static[ \t]+)?(while|if|for|function|switch|with|([A-Za-z_$][A-Za-z0-9_$]+))[ \t]*\(.*\)[ \t]*\{/\2\4/,function/
+--regex-ColdFusion=/(,|^|\*\/)[ \t]*get[ \t]+([A-Za-z_$][A-Za-z0-9_$]+)[ \t]*\([ \t]*\)[ \t]*\{/get \2/,function/
+--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/
+--regex-ColdFusion=/(,|^|\*\/)[ \t]*async[ \t]+([A-Za-z_$][A-Za-z0-9_$]+)[ \t]*\([ \t]*([A-Za-z_$].+)?[ \t]*\)[ \t]*\{/\2/,function/
+--regex-ColdFusion=/component[ \t]+([A-Za-z0-9._$]+)[ \t]*/\1/c,component/
+--regex-ColdFusion=/^[ \t]*given[ \t]"(.+)"[ \t]*,[ \t]+[-=]>/\1/f,function/
+--regex-ColdFusion=/^[ \t]*given[ \t]'(.+)'[ \t]*,[ \t]+[-=]>/\1/f,function/
+--regex-ColdFusion=/^[ \t]*story[ \t]"(.+)"[ \t]*,[ \t]+[-=]>/\1/f,function/
+--regex-ColdFusion=/^[ \t]*story[ \t]"(.+)"[ \t]*,[ \t]+[-=]>/\1/f,function/
+--regex-ColdFusion=/^[ \t]*feature[ \t]'(.+)'[ \t]*,[ \t]+[-=]>/\1/f,function/
+--regex-ColdFusion=/^[ \t]*feature[ \t]'(.+)'[ \t]*,[ \t]+[-=]>/\1/f,function/
+--regex-ColdFusion=/^[ \t]*when[ \t]"(.+)"[ \t]*,[ \t]+[-=]>/\1/f,function/
+--regex-ColdFusion=/^[ \t]*when[ \t]'(.+)'[ \t]*,[ \t]+[-=]>/\1/f,function/
+--regex-ColdFusion=/^[ \t]*then[ \t]"(.+)"[ \t]*,[ \t]+[-=]>/\1/f,function/
+--regex-ColdFusion=/^[ \t]*then[ \t]'(.+)'[ \t]*,[ \t]+[-=]>/\1/f,function/
+--regex-ColdFusion=/^[ \t]*describe[ \t]"(.+)"[ \t]*,[ \t]+[-=]>/\1/f,function/
+--regex-ColdFusion=/^[ \t]*describe[ \t]'(.+)'[ \t]*,[ \t]+[-=]>/\1/f,function/
+--regex-ColdFusion=/^[ \t]*it[ \t]"([^"]+)"[ \t]*,[ \t]+[-=]>/\1/f,function/
+--regex-ColdFusion=/^[ \t]*it[ \t]'([^']+)'[ \t]*,[ \t]+[-=]>/\1/f,function/
+--regex-ColdFusion=/^[ \t]*xdescribe[ \t]"(.+)"[ \t]*,[ \t]+[-=]>/disabled\: \1/f,function/
+--regex-ColdFusion=/^[ \t]*xdescribe[ \t]'(.+)'[ \t]*,[ \t]+[-=]>/disabled: \1/f,function/
+--regex-ColdFusion=/^[ \t]*xit[ \t]"([^"]+)"[ \t]*,[ \t]+[-=]>/disabled: \1/f,function/
+--regex-ColdFusion=/^[ \t]*xit[ \t]'([^']+)'[ \t]*,[ \t]+[-=]>/disabled: \1/f,function/
+
+--langdef=Css
+--langmap=Css:.css
+--langmap=Css:+.less
+--langmap=Css:+.scss
+--regex-Css=/^[ \t]*(.+)[ \t]*\{/\1/f,function/
+--regex-Css=/^[ \t]*(.+)[ \t]*,[ \t]*$/\1/f,function/
+--regex-Css=/^[ \t]*[@$]([a-zA-Z$_][-a-zA-Z$_0-9]*)[ \t]*:/\1/f,function/
+
+--langdef=Sass
+--langmap=Sass:.sass
+--regex-Sass=/^[ \t]*([#.]*[a-zA-Z_0-9]+)[ \t]*$/\1/f,function/
+
+--langdef=Yaml
+--langmap=Yaml:.yaml
+--langmap=Yaml:+.yml
+--regex-Yaml=/^[ \t]*([a-zA-Z_0-9 ]+)[ \t]*\:[ \t]*/\1/f,function/
+
+--regex-Html=/^[ \t]*<([a-zA-Z]+)[ \t]*.*>/\1/f,function/
+
+--langdef=Markdown
+--langmap=Markdown:.md
+--langmap=Markdown:+.markdown
+--langmap=Markdown:+.mdown
+--langmap=Markdown:+.mkd
+--langmap=Markdown:+.mkdown
+--langmap=Markdown:+.ron
+--regex-Markdown=/^#+[ \t]*([^#]+)/\1/f,function/
+
+--langdef=Json
+--langmap=Json:.json
+--regex-Json=/^[ \t]*"([^"]+)"[ \t]*\:/\1/f,function/
+
+--langdef=Cson
+--langmap=Cson:.cson
+--langmap=Cson:+.gyp
+--regex-Cson=/^[ \t]*'([^']+)'[ \t]*\:/\1/f,function/
+--regex-Cson=/^[ \t]*"([^"]+)"[ \t]*\:/\1/f,function/
+--regex-Cson=/^[ \t]*([^'"]+)[ \t]*\:/\1/f,function/
+
+--langmap=C++:+.mm
+
+--langmap=Ruby:+(Rakefile)
+
+--langmap=Php:+.module
+
+--langdef=Go
+--langmap=Go:.go
+--regex-Go=/func([ \t]+\([^)]+\))?[ \t]+([a-zA-Z0-9_]+)/\2/f,func/
+--regex-Go=/var[ \t]+([a-zA-Z_][a-zA-Z0-9_]*)/\1/v,var/
+--regex-Go=/type[ \t]+([a-zA-Z_][a-zA-Z0-9_]*)/\1/t,type/
+
+--langdef=Capnp
+--langmap=Capnp:.capnp
+--regex-Capnp=/struct[ \t]+([A-Za-z]+)/\1/s,struct/
+--regex-Capnp=/enum[ \t]+([A-Za-z]+)/\1/e,enum/
+--regex-Capnp=/using[ \t]+([A-Za-z]+)[ \t]+=[ \t]+import/\1/u,using/
+--regex-Capnp=/const[ \t]+([A-Za-z]+)/\1/c,const/
+
+--langmap=perl:+.pod
+--regex-perl=/with[ \t]+([^;]+)[ \t]*?;/\1/w,role,roles/
+--regex-perl=/extends[ \t]+['"]([^'"]+)['"][ \t]*?;/\1/e,extends/
+--regex-perl=/use[ \t]+base[ \t]+['"]([^'"]+)['"][ \t]*?;/\1/e,extends/
+--regex-perl=/use[ \t]+parent[ \t]+['"]([^'"]+)['"][ \t]*?;/\1/e,extends/
+--regex-perl=/Mojo::Base[ \t]+['"]([^'"]+)['"][ \t]*?;/\1/e,extends/
+--regex-perl=/^[ \t]*?use[ \t]+([^;]+)[ \t]*?;/\1/u,use,uses/
+--regex-perl=/^[ \t]*?require[ \t]+((\w|\:)+)/\1/r,require,requires/
+--regex-perl=/^[ \t]*?has[ \t]+['"]?(\w+)['"]?/\1/a,attribute,attributes/
+--regex-perl=/^[ \t]*?\*(\w+)[ \t]*?=/\1/a,alias,aliases/
+--regex-perl=/->helper\([ \t]?['"]?(\w+)['"]?/\1/h,helper,helpers/
+--regex-perl=/^[ \t]*?our[ \t]*?[\$@%](\w+)/\1/o,our,ours/
+--regex-perl=/^\=head1[ \t]+(.+)/\1/p,pod,Plain Old Documentation/
+--regex-perl=/^\=head2[ \t]+(.+)/-- \1/p,pod,Plain Old Documentation/
+--regex-perl=/^\=head[3-5][ \t]+(.+)/---- \1/p,pod,Plain Old Documentation/
+
+--regex-JavaScript=/(,|(;|^)[ \t]*(var|let|([A-Za-z_$][A-Za-z0-9_$.]*\.)*))[ \t]*([A-Za-z0-9_$]+)[ \t]*=[ \t]*function[ \t]*\(/\5/,function/
+--regex-JavaScript=/function[ \t]+([A-Za-z0-9_$]+)[ \t]*\([^)]*\)/\1/,function/
+--regex-JavaScript=/(,|^|\*\/)[ \t]*([A-Za-z_$][A-Za-z0-9_$]+)[ \t]*:[ \t]*function[ \t]*\(/\2/,function/
+--regex-JavaScript=/(,|^|\*\/)[ \t]*(static[ \t]+)?(while|if|for|function|switch|with|([A-Za-z_$][A-Za-z0-9_$]+))[ \t]*\(.*\)[ \t]*\{/\2\4/,function/
+--regex-JavaScript=/(,|^|\*\/)[ \t]*get[ \t]+([A-Za-z_$][A-Za-z0-9_$]+)[ \t]*\([ \t]*\)[ \t]*\{/get \2/,function/
+--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/
+--regex-JavaScript=/(,|^|\*\/)[ \t]*async[ \t]+([A-Za-z_$][A-Za-z0-9_$]+)[ \t]*\([ \t]*([A-Za-z_$].+)?[ \t]*\)[ \t]*\{/\2/,function/
+--regex-JavaScript=/class[ \t]+([A-Za-z0-9._$]+)[ \t]*/\1/c,class/
+--regex-JavaScript=/^[ \t]*describe\("([^"]+)"[ \t]*,/\1/f,function/
+--regex-JavaScript=/^[ \t]*describe\('([^']+)'[ \t]*,/\1/f,function/
+--regex-JavaScript=/^[ \t]*it\("([^"]+)"[ \t]*,/\1/f,function/
+--regex-JavaScript=/^[ \t]*it\('([^']+)'[ \t]*,/\1/f,function/
+--regex-JavaScript=/^[ \t]*f+describe\('([^']+)'[ \t]*,/focused: \1/f,function/
+--regex-JavaScript=/^[ \t]*f+describe\("([^"]+)"[ \t]*,/focused: \1/f,function/
+--regex-JavaScript=/^[ \t]*f+it\('([^']+)'[ \t]*,/focused: \1/f,function/
+--regex-JavaScript=/^[ \t]*f+it\("([^"]+)"[ \t]*,/focused: \1/f,function/
+--regex-JavaScript=/^[ \t]*xdescribe\('([^']+)'[ \t]*,/disabled: \1/f,function/
+--regex-JavaScript=/^[ \t]*xdescribe\("([^"]+)"[ \t]*,/disabled: \1/f,function/
+--regex-JavaScript=/^[ \t]*xit\('([^']+)'[ \t]*,/disabled: \1/f,function/
+--regex-JavaScript=/^[ \t]*xit\("([^"]+)"[ \t]*,/disabled: \1/f,function/
+
+--langdef=haxe
+--langmap=haxe:.hx
+--regex-haxe=/^package[ \t]+([A-Za-z0-9_.]+)/\1/p,package/
+--regex-haxe=/^[ \t]*[(@:macro|private|public|static|override|inline|dynamic)( \t)]*function[ \t]+([A-Za-z0-9_]+)/\1/f,function/
+--regex-haxe=/^[ \t]*([private|public|static|protected|inline][ \t]*)+var[ \t]+([A-Za-z0-9_]+)/\2/v,variable/
+--regex-haxe=/^[ \t]*package[ \t]*([A-Za-z0-9_]+)/\1/p,package/
+--regex-haxe=/^[ \t]*(extern[ \t]*|@:native\([^)]*\)[ \t]*)*class[ \t]+([A-Za-z0-9_]+)[ \t]*[^\{]*/\2/c,class/
+--regex-haxe=/^[ \t]*(extern[ \t]+)?interface[ \t]+([A-Za-z0-9_]+)/\2/i,interface/
+--regex-haxe=/^[ \t]*typedef[ \t]+([A-Za-z0-9_]+)/\1/t,typedef/
+--regex-haxe=/^[ \t]*enum[ \t]+([A-Za-z0-9_]+)/\1/t,typedef/
+--regex-haxe=/^[ \t]*+([A-Za-z0-9_]+)(;|\([^)]*:[^)]*\))/\1/t,enum_field/
+
+--langdef=Elixir
+--langmap=Elixir:.ex.exs
+--regex-Elixir=/^[ \t]*def(p?)[ \t]+([a-z_][a-zA-Z0-9_?!]*)/\2/f,functions,functions (def ...)/
+--regex-Elixir=/^[ \t]*defcallback[ \t]+([a-z_][a-zA-Z0-9_?!]*)/\1/c,callbacks,callbacks (defcallback ...)/
+--regex-Elixir=/^[ \t]*defdelegate[ \t]+([a-z_][a-zA-Z0-9_?!]*)/\1/d,delegates,delegates (defdelegate ...)/
+--regex-Elixir=/^[ \t]*defexception[ \t]+([A-Z][a-zA-Z0-9_]*\.)*([A-Z][a-zA-Z0-9_?!]*)/\2/e,exceptions,exceptions (defexception ...)/
+--regex-Elixir=/^[ \t]*defimpl[ \t]+([A-Z][a-zA-Z0-9_]*\.)*([A-Z][a-zA-Z0-9_?!]*)/\2/i,implementations,implementations (defimpl ...)/
+--regex-Elixir=/^[ \t]*defmacro(p?)[ \t]+([a-z_][a-zA-Z0-9_?!]*)\(/\2/a,macros,macros (defmacro ...)/
+--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")/
+--regex-Elixir=/^[ \t]*defmodule[ \t]+([A-Z][a-zA-Z0-9_]*\.)*([A-Z][a-zA-Z0-9_?!]*)/\2/m,modules,modules (defmodule ...)/
+--regex-Elixir=/^[ \t]*defprotocol[ \t]+([A-Z][a-zA-Z0-9_]*\.)*([A-Z][a-zA-Z0-9_?!]*)/\2/p,protocols,protocols (defprotocol...)/
+--regex-Elixir=/^[ \t]*Record\.defrecord[ \t]+:([a-zA-Z0-9_]+)/\1/r,records,records (defrecord...)/
+
+--langdef=Nim
+--langmap=Nim:.nim
+--regex-Nim=/^[\t\s]*proc\s+([_A-Za-z0-9]+)\**(\[\w+(\:\s+\w+)?\])?\s*\(/\1/f,function/
+--regex-Nim=/^[\t\s]*iterator\s+([_A-Za-z0-9]+)\**(\[\w+(\:\s+\w+)?\])?\s*\(/\1/i,iterator/
+--regex-Nim=/^[\t\s]*macro\s+([_A-Za-z0-9]+)\**(\[\w+(\:\s+\w+)?\])?\s*\(/\1/m,macro/
+--regex-Nim=/^[\t\s]*method\s+([_A-Za-z0-9]+)\**(\[\w+(\:\s+\w+)?\])?\s*\(/\1/h,method/
+--regex-Nim=/^[\t\s]*template\s+([_A-Za-z0-9]+)\**(\[\w+(\:\s+\w+)?\])?\s*\(/\1/t,generics/
+--regex-Nim=/^[\t\s]*converter\s+([_A-Za-z0-9]+)\**(\[\w+(\:\s+\w+)?\])?\s*\(/\1/c,converter/
+
+--langdef=Fountain
+--langmap=Fountain:.fountain
+--langmap=Fountain:+.ftn
+--regex-Fountain=/^(([iI][nN][tT]|[eE][xX][tT]|[^\w][eE][sS][tT]|\.|[iI]\.?\/[eE]\.?)([^\n]+))/\1/f,function/
+
+--langdef=Julia
+--langmap=Julia:.jl
+--regex-Julia=/^[ \t]*(function|macro|abstract|type|typealias|immutable)[ \t]+([^ \t({[]+).*$/\2/f,function/
+--regex-Julia=/^[ \t]*(([^@#$ \t({[]+)|\(([^@#$ \t({[]+)\)|\((\$)\))[ \t]*(\{.*\})?[ \t]*\([^#]*\)[ \t]*=([^=].*$|$)/\2\3\4/f,function/
+
+--langdef=Latex
+--langmap=latex:.tex
+--regex-latex=/\\label\{([^}]*)\}/\1/l,label/
+--regex-latex=/\\section\{([^}]*)\}/\1/s,section/
+--regex-latex=/\\subsection\{([^}]*)\}/\1/t,subsection/
+--regex-latex=/\\subsubsection\{([^}]*)\}/\1/u,subsubsection/
+--regex-latex=/\\section\*\{([^}]*)\}/\1/s,section/
+--regex-latex=/\\subsection\*\{([^}]*)\}/\1/t,subsection/
+--regex-latex=/\\subsubsection\*\{([^}]*)\}/\1/u,subsubsection/
diff --git a/packages/symbols-view/lib/file-view.js b/packages/symbols-view/lib/file-view.js
new file mode 100644
index 000000000..18c190f3a
--- /dev/null
+++ b/packages/symbols-view/lib/file-view.js
@@ -0,0 +1,146 @@
+/** @babel */
+
+import { CompositeDisposable } from 'atom';
+import SymbolsView from './symbols-view';
+import TagGenerator from './tag-generator';
+import { match } from 'fuzzaldrin';
+
+export default class FileView extends SymbolsView {
+ constructor(stack) {
+ super(stack);
+ this.cachedTags = {};
+ this.watchedEditors = new WeakSet();
+
+ this.editorsSubscription = atom.workspace.observeTextEditors(editor => {
+ if (this.watchedEditors.has(editor)) return;
+
+ const removeFromCache = () => {
+ delete this.cachedTags[editor.getPath()];
+ };
+ const editorSubscriptions = new CompositeDisposable();
+ editorSubscriptions.add(editor.onDidChangeGrammar(removeFromCache));
+ editorSubscriptions.add(editor.onDidSave(removeFromCache));
+ editorSubscriptions.add(editor.onDidChangePath(removeFromCache));
+ editorSubscriptions.add(editor.getBuffer().onDidReload(removeFromCache));
+ editorSubscriptions.add(editor.getBuffer().onDidDestroy(removeFromCache));
+ editor.onDidDestroy(() => {
+ this.watchedEditors.delete(editor);
+ editorSubscriptions.dispose();
+ });
+
+ this.watchedEditors.add(editor);
+ });
+ }
+
+ destroy() {
+ this.editorsSubscription.dispose();
+ return super.destroy();
+ }
+
+ elementForItem({position, name}) {
+ // Style matched characters in search results
+ const matches = match(name, this.selectListView.getFilterQuery());
+
+ const li = document.createElement('li');
+ li.classList.add('two-lines');
+
+ const primaryLine = document.createElement('div');
+ primaryLine.classList.add('primary-line');
+ primaryLine.appendChild(SymbolsView.highlightMatches(this, name, matches));
+ li.appendChild(primaryLine);
+
+ const secondaryLine = document.createElement('div');
+ secondaryLine.classList.add('secondary-line');
+ secondaryLine.textContent = `Line ${position.row + 1}`;
+ li.appendChild(secondaryLine);
+
+ return li;
+ }
+
+ didChangeSelection(item) {
+ if (atom.config.get('symbols-view.quickJumpToFileSymbol') && item) {
+ this.openTag(item);
+ }
+ }
+
+ async didCancelSelection() {
+ await this.cancel();
+ const editor = this.getEditor();
+ if (this.initialState && editor) {
+ this.deserializeEditorState(editor, this.initialState);
+ }
+ this.initialState = null;
+ }
+
+ async toggle() {
+ if (this.panel.isVisible()) {
+ await this.cancel();
+ }
+ const filePath = this.getPath();
+ if (filePath) {
+ const editor = this.getEditor();
+ if (atom.config.get('symbols-view.quickJumpToFileSymbol') && editor) {
+ this.initialState = this.serializeEditorState(editor);
+ }
+ this.populate(filePath);
+ this.attach();
+ }
+ }
+
+ serializeEditorState(editor) {
+ const editorElement = atom.views.getView(editor);
+ const scrollTop = editorElement.getScrollTop();
+
+ return {
+ bufferRanges: editor.getSelectedBufferRanges(),
+ scrollTop,
+ };
+ }
+
+ deserializeEditorState(editor, {bufferRanges, scrollTop}) {
+ const editorElement = atom.views.getView(editor);
+
+ editor.setSelectedBufferRanges(bufferRanges);
+ editorElement.setScrollTop(scrollTop);
+ }
+
+ getEditor() {
+ return atom.workspace.getActiveTextEditor();
+ }
+
+ getPath() {
+ if (this.getEditor()) {
+ return this.getEditor().getPath();
+ }
+ return undefined;
+ }
+
+ getScopeName() {
+ if (this.getEditor() && this.getEditor().getGrammar()) {
+ return this.getEditor().getGrammar().scopeName;
+ }
+ return undefined;
+ }
+
+ async populate(filePath) {
+ const tags = this.cachedTags[filePath];
+ if (tags) {
+ await this.selectListView.update({items: tags});
+ } else {
+ await this.selectListView.update({
+ items: [],
+ loadingMessage: 'Generating symbols\u2026',
+ });
+ await this.selectListView.update({
+ items: await this.generateTags(filePath),
+ loadingMessage: null,
+ });
+ }
+ }
+
+ async generateTags(filePath) {
+ const generator = new TagGenerator(filePath, this.getScopeName());
+ this.cachedTags[filePath] = await generator.generate();
+ return this.cachedTags[filePath];
+ }
+}
diff --git a/packages/symbols-view/lib/get-tags-file.js b/packages/symbols-view/lib/get-tags-file.js
new file mode 100644
index 000000000..e7f617714
--- /dev/null
+++ b/packages/symbols-view/lib/get-tags-file.js
@@ -0,0 +1,20 @@
+/** @babel */
+
+import path from 'path';
+import fs from 'fs-plus';
+
+const files = ['tags', 'TAGS', '.tags', '.TAGS', path.join('.git', 'tags'), path.join('.git', 'TAGS')];
+export default function(directoryPath) {
+ if (!directoryPath) {
+ return undefined;
+ }
+
+ for (const file of files) {
+ const tagsFile = path.join(directoryPath, file);
+ if (fs.isFileSync(tagsFile)) {
+ return tagsFile;
+ }
+ }
+
+ return undefined;
+}
diff --git a/packages/symbols-view/lib/go-back-view.js b/packages/symbols-view/lib/go-back-view.js
new file mode 100644
index 000000000..a5e533c89
--- /dev/null
+++ b/packages/symbols-view/lib/go-back-view.js
@@ -0,0 +1,28 @@
+/** @babel */
+
+import SymbolsView from './symbols-view';
+
+export default class GoBackView extends SymbolsView {
+ toggle() {
+ const previousTag = this.stack.pop();
+ if (!previousTag) {
+ return;
+ }
+
+ const restorePosition = () => {
+ if (previousTag.position) {
+ this.moveToPosition(previousTag.position, false);
+ }
+ };
+
+ const previousEditor = atom.workspace.getTextEditors().find(e => e.id === previousTag.editorId);
+
+ if (previousEditor) {
+ const pane = atom.workspace.paneForItem(previousEditor);
+ pane.setActiveItem(previousEditor);
+ restorePosition();
+ } else if (previousTag.file) {
+ atom.workspace.open(previousTag.file).then(restorePosition);
+ }
+ }
+}
diff --git a/packages/symbols-view/lib/go-to-view.js b/packages/symbols-view/lib/go-to-view.js
new file mode 100644
index 000000000..50f2aa6c7
--- /dev/null
+++ b/packages/symbols-view/lib/go-to-view.js
@@ -0,0 +1,65 @@
+/** @babel */
+
+import path from 'path';
+import SymbolsView from './symbols-view';
+import TagReader from './tag-reader';
+
+export default class GoToView extends SymbolsView {
+ toggle() {
+ if (this.panel.isVisible()) {
+ this.cancel();
+ } else {
+ this.populate();
+ }
+ }
+
+ detached() {
+ if (this.resolveFindTagPromise) {
+ this.resolveFindTagPromise([]);
+ }
+ }
+
+ findTag(editor) {
+ if (this.resolveFindTagPromise) {
+ this.resolveFindTagPromise([]);
+ }
+
+ return new Promise((resolve, reject) => {
+ this.resolveFindTagPromise = resolve;
+ TagReader.find(editor, (error, matches) => {
+ if (!matches) {
+ matches = [];
+ }
+ if (error) {
+ return reject(error);
+ } else {
+ return resolve(matches);
+ }
+ });
+ });
+ }
+
+ async populate() {
+ let editor = atom.workspace.getActiveTextEditor();
+ if (!editor) {
+ return;
+ }
+
+ this.findTag(editor).then(async matches => {
+ let tags = [];
+ for (let match of Array.from(matches)) {
+ let position = this.getTagLine(match);
+ if (!position) { continue; }
+ match.name = path.basename(match.file);
+ tags.push(match);
+ }
+
+ if (tags.length === 1) {
+ this.openTag(tags[0]);
+ } else if (tags.length > 0) {
+ await this.selectListView.update({items: tags});
+ this.attach();
+ }
+ });
+ }
+}
diff --git a/packages/symbols-view/lib/load-tags-handler.js b/packages/symbols-view/lib/load-tags-handler.js
new file mode 100644
index 000000000..692aff39c
--- /dev/null
+++ b/packages/symbols-view/lib/load-tags-handler.js
@@ -0,0 +1,25 @@
+/** @babel */
+/* global emit*/
+
+import async from 'async';
+import ctags from 'ctags';
+import getTagsFile from './get-tags-file';
+
+export default function(directoryPaths) {
+ return async.each(
+ directoryPaths,
+ (directoryPath, done) => {
+ let tagsFilePath = getTagsFile(directoryPath);
+ if (!tagsFilePath) { return done(); }
+
+ let stream = ctags.createReadStream(tagsFilePath);
+ stream.on('data', function(tags) {
+ for (const tag of Array.from(tags)) { tag.directory = directoryPath; }
+ return emit('tags', tags);
+ });
+ stream.on('end', done);
+ return stream.on('error', done);
+ }
+ , this.async()
+ );
+}
diff --git a/packages/symbols-view/lib/main.js b/packages/symbols-view/lib/main.js
new file mode 100644
index 000000000..e18b50e5b
--- /dev/null
+++ b/packages/symbols-view/lib/main.js
@@ -0,0 +1,93 @@
+/** @babel */
+
+export default {
+ activate() {
+ this.stack = [];
+
+ this.workspaceSubscription = atom.commands.add('atom-workspace', {
+ 'symbols-view:toggle-project-symbols': () => {
+ this.createProjectView().toggle();
+ },
+ });
+
+ this.editorSubscription = atom.commands.add('atom-text-editor', {
+ 'symbols-view:toggle-file-symbols': () => {
+ this.createFileView().toggle();
+ },
+ 'symbols-view:go-to-declaration': () => {
+ this.createGoToView().toggle();
+ },
+ 'symbols-view:return-from-declaration': () => {
+ this.createGoBackView().toggle();
+ },
+ });
+ },
+
+ deactivate() {
+ if (this.fileView != null) {
+ this.fileView.destroy();
+ this.fileView = null;
+ }
+
+ if (this.projectView != null) {
+ this.projectView.destroy();
+ this.projectView = null;
+ }
+
+ if (this.goToView != null) {
+ this.goToView.destroy();
+ this.goToView = null;
+ }
+
+ if (this.goBackView != null) {
+ this.goBackView.destroy();
+ this.goBackView = null;
+ }
+
+ if (this.workspaceSubscription != null) {
+ this.workspaceSubscription.dispose();
+ this.workspaceSubscription = null;
+ }
+
+ if (this.editorSubscription != null) {
+ this.editorSubscription.dispose();
+ this.editorSubscription = null;
+ }
+ },
+
+ createFileView() {
+ if (this.fileView) {
+ return this.fileView;
+ }
+ const FileView = require('./file-view');
+ this.fileView = new FileView(this.stack);
+ return this.fileView;
+ },
+
+ createProjectView() {
+ if (this.projectView) {
+ return this.projectView;
+ }
+ const ProjectView = require('./project-view');
+ this.projectView = new ProjectView(this.stack);
+ return this.projectView;
+ },
+
+ createGoToView() {
+ if (this.goToView) {
+ return this.goToView;
+ }
+ const GoToView = require('./go-to-view');
+ this.goToView = new GoToView(this.stack);
+ return this.goToView;
+ },
+
+ createGoBackView() {
+ if (this.goBackView) {
+ return this.goBackView;
+ }
+ const GoBackView = require('./go-back-view');
+ this.goBackView = new GoBackView(this.stack);
+ return this.goBackView;
+ },
+};
diff --git a/packages/symbols-view/lib/project-view.js b/packages/symbols-view/lib/project-view.js
new file mode 100644
index 000000000..e0605cad1
--- /dev/null
+++ b/packages/symbols-view/lib/project-view.js
@@ -0,0 +1,105 @@
+/** @babel */
+
+import { CompositeDisposable, File } from 'atom';
+import humanize from 'humanize-plus';
+import SymbolsView from './symbols-view';
+import TagReader from './tag-reader';
+import getTagsFile from './get-tags-file';
+
+export default class ProjectView extends SymbolsView {
+ constructor(stack) {
+ super(stack, 'Project has no tags file or it is empty', 10);
+ this.reloadTags = true;
+ }
+
+ destroy() {
+ this.stopTask();
+ this.unwatchTagsFiles();
+ return super.destroy();
+ }
+
+ toggle() {
+ if (this.panel.isVisible()) {
+ this.cancel();
+ } else {
+ this.populate();
+ this.attach();
+ }
+ }
+
+ async populate() {
+ if (this.tags) {
+ await this.selectListView.update({items: this.tags});
+ }
+
+ if (this.reloadTags) {
+ this.reloadTags = false;
+ this.startTask();
+
+ if (this.tags) {
+ await this.selectListView.update({
+ loadingMessage: 'Reloading project symbols\u2026',
+ });
+ } else {
+ await this.selectListView.update({
+ loadingMessage: 'Loading project symbols\u2026',
+ loadingBadge: 0,
+ });
+ let tagsRead = 0;
+ this.loadTagsTask.on('tags', tags => {
+ tagsRead += tags.length;
+ this.selectListView.update({loadingBadge: humanize.intComma(tagsRead)});
+ });
+ }
+ }
+ }
+
+ stopTask() {
+ if (this.loadTagsTask) {
+ this.loadTagsTask.terminate();
+ }
+ }
+
+ startTask() {
+ this.stopTask();
+
+ this.loadTagsTask = TagReader.getAllTags(tags => {
+ this.tags = tags;
+ this.reloadTags = this.tags.length === 0;
+ this.selectListView.update({
+ loadingMessage: null,
+ loadingBadge: null,
+ items: this.tags,
+ });
+ });
+
+ this.watchTagsFiles();
+ }
+
+ watchTagsFiles() {
+ this.unwatchTagsFiles();
+
+ this.tagsFileSubscriptions = new CompositeDisposable();
+ let reloadTags = () => {
+ this.reloadTags = true;
+ this.watchTagsFiles();
+ };
+
+ for (const projectPath of Array.from(atom.project.getPaths())) {
+ const tagsFilePath = getTagsFile(projectPath);
+ if (tagsFilePath) {
+ const tagsFile = new File(tagsFilePath);
+ this.tagsFileSubscriptions.add(tagsFile.onDidChange(reloadTags));
+ this.tagsFileSubscriptions.add(tagsFile.onDidDelete(reloadTags));
+ this.tagsFileSubscriptions.add(tagsFile.onDidRename(reloadTags));
+ }
+ }
+ }
+
+ unwatchTagsFiles() {
+ if (this.tagsFileSubscriptions) {
+ this.tagsFileSubscriptions.dispose();
+ }
+ this.tagsFileSubscriptions = null;
+ }
+}
diff --git a/packages/symbols-view/lib/symbols-view.js b/packages/symbols-view/lib/symbols-view.js
new file mode 100644
index 000000000..17cf42312
--- /dev/null
+++ b/packages/symbols-view/lib/symbols-view.js
@@ -0,0 +1,224 @@
+/** @babel */
+
+import path from 'path';
+import { Point } from 'atom';
+import SelectListView from 'atom-select-list';
+import fs from 'fs-plus';
+import { match } from 'fuzzaldrin';
+
+export default class SymbolsView {
+ static highlightMatches(context, name, matches, offsetIndex) {
+ if (!offsetIndex) {
+ offsetIndex = 0;
+ }
+ let lastIndex = 0;
+ let matchedChars = []; // Build up a set of matched chars to be more semantic
+ const fragment = document.createDocumentFragment();
+
+ for (let matchIndex of Array.from(matches)) {
+ matchIndex -= offsetIndex;
+ if (matchIndex < 0) {
+ continue; // If marking up the basename, omit name matches
+ }
+ const unmatched = name.substring(lastIndex, matchIndex);
+ if (unmatched) {
+ if (matchedChars.length) {
+ const span = document.createElement('span');
+ span.classList.add('character-match');
+ span.textContent = matchedChars.join('');
+ fragment.appendChild(span);
+ }
+ matchedChars = [];
+ fragment.appendChild(document.createTextNode(unmatched));
+ }
+ matchedChars.push(name[matchIndex]);
+ lastIndex = matchIndex + 1;
+ }
+
+ if (matchedChars.length) {
+ const span = document.createElement('span');
+ span.classList.add('character-match');
+ span.textContent = matchedChars.join('');
+ fragment.appendChild(span);
+ }
+
+ // Remaining characters are plain text
+ fragment.appendChild(document.createTextNode(name.substring(lastIndex)));
+
+ return fragment;
+ }
+
+ constructor(stack, emptyMessage = 'No symbols found', maxResults = null) {
+ this.stack = stack;
+ this.selectListView = new SelectListView({
+ maxResults,
+ emptyMessage,
+ items: [],
+ filterKeyForItem: (item) => item.name,
+ elementForItem: this.elementForItem.bind(this),
+ didChangeSelection: this.didChangeSelection.bind(this),
+ didConfirmSelection: this.didConfirmSelection.bind(this),
+ didConfirmEmptySelection: this.didConfirmEmptySelection.bind(this),
+ didCancelSelection: this.didCancelSelection.bind(this),
+ });
+ this.element = this.selectListView.element;
+ this.element.classList.add('symbols-view');
+ this.panel = atom.workspace.addModalPanel({item: this, visible: false});
+ }
+
+ async destroy() {
+ await this.cancel();
+ this.panel.destroy();
+ return this.selectListView.destroy();
+ }
+
+ getFilterKey() {
+ return 'name';
+ }
+
+ elementForItem({position, name, file, directory}) {
+ // Style matched characters in search results
+ const matches = match(name, this.selectListView.getFilterQuery());
+
+ if (atom.project.getPaths().length > 1) {
+ file = path.join(path.basename(directory), file);
+ }
+
+ const li = document.createElement('li');
+ li.classList.add('two-lines');
+
+ const primaryLine = document.createElement('div');
+ primaryLine.classList.add('primary-line');
+ if (position) {
+ primaryLine.textContent = `${name}:${position.row + 1}`;
+ } else {
+ primaryLine.appendChild(SymbolsView.highlightMatches(this, name, matches));
+ }
+ li.appendChild(primaryLine);
+
+ const secondaryLine = document.createElement('div');
+ secondaryLine.classList.add('secondary-line');
+ secondaryLine.textContent = file;
+ li.appendChild(secondaryLine);
+
+ return li;
+ }
+
+ async cancel() {
+ if (!this.isCanceling) {
+ this.isCanceling = true;
+ await this.selectListView.update({items: []});
+ this.panel.hide();
+ if (this.previouslyFocusedElement) {
+ this.previouslyFocusedElement.focus();
+ this.previouslyFocusedElement = null;
+ }
+ this.isCanceling = false;
+ }
+ }
+
+ didCancelSelection() {
+ this.cancel();
+ }
+
+ didConfirmEmptySelection() {
+ this.cancel();
+ }
+
+ async didConfirmSelection(tag) {
+ if (tag.file && !fs.isFileSync(path.join(tag.directory, tag.file))) {
+ await this.selectListView.update({errorMessage: 'Selected file does not exist'});
+ setTimeout(() => {
+ this.selectListView.update({errorMessage: null});
+ }, 2000);
+ } else {
+ await this.cancel();
+ this.openTag(tag);
+ }
+ }
+
+ didChangeSelection(tag) {
+ // no-op
+ }
+
+ openTag(tag) {
+ const editor = atom.workspace.getActiveTextEditor();
+ let previous;
+ if (editor) {
+ previous = {
+ editorId: editor.id,
+ position: editor.getCursorBufferPosition(),
+ file: editor.getURI(),
+ };
+ }
+
+ let {position} = tag;
+ if (!position) { position = this.getTagLine(tag); }
+ if (tag.file) {
+ atom.workspace.open(path.join(tag.directory, tag.file)).then(() => {
+ if (position) {
+ return this.moveToPosition(position);
+ }
+ return undefined;
+ });
+ } else if (position && previous && !previous.position.isEqual(position)) {
+ this.moveToPosition(position);
+ }
+
+ this.stack.push(previous);
+ }
+
+ moveToPosition(position, beginningOfLine) {
+ const editor = atom.workspace.getActiveTextEditor();
+ if (beginningOfLine == null) {
+ beginningOfLine = true;
+ }
+ if (editor) {
+ editor.setCursorBufferPosition(position, {autoscroll: false});
+ if (beginningOfLine) {
+ editor.moveToFirstCharacterOfLine();
+ }
+ editor.scrollToCursorPosition({center: true});
+ }
+ }
+
+ attach() {
+ this.previouslyFocusedElement = document.activeElement;
+ this.panel.show();
+ this.selectListView.reset();
+ this.selectListView.focus();
+ }
+
+ getTagLine(tag) {
+ if (!tag) {
+ return undefined;
+ }
+
+ if (tag.lineNumber) {
+ return new Point(tag.lineNumber - 1, 0);
+ }
+
+ // Remove leading /^ and trailing $/
+ if (!tag.pattern) {
+ return undefined;
+ }
+ const pattern = tag.pattern.replace(/(^\/\^)|(\$\/$)/g, '').trim();
+
+ if (!pattern) {
+ return undefined;
+ }
+ const file = path.join(tag.directory, tag.file);
+ if (!fs.isFileSync(file)) {
+ return undefined;
+ }
+ const iterable = fs.readFileSync(file, 'utf8').split('\n');
+ for (let index = 0; index < iterable.length; index++) {
+ let line = iterable[index];
+ if (pattern === line.trim()) {
+ return new Point(index, 0);
+ }
+ }
+
+ return undefined;
+ }
+}
diff --git a/packages/symbols-view/lib/tag-generator.js b/packages/symbols-view/lib/tag-generator.js
new file mode 100644
index 000000000..d07534b8c
--- /dev/null
+++ b/packages/symbols-view/lib/tag-generator.js
@@ -0,0 +1,128 @@
+/** @babel */
+
+import { BufferedProcess, Point } from 'atom';
+import path from 'path';
+import fs from 'fs-plus';
+
+export default class TagGenerator {
+ constructor(path1, scopeName) {
+ this.path = path1;
+ this.scopeName = scopeName;
+ }
+
+ getPackageRoot() {
+ const {resourcePath} = atom.getLoadSettings();
+ const currentFileWasRequiredFromSnapshot = !fs.isAbsolute(__dirname);
+ const packageRoot = currentFileWasRequiredFromSnapshot
+ ? path.join(resourcePath, 'node_modules', 'symbols-view')
+ : path.resolve(__dirname, '..');
+
+ if (path.extname(resourcePath) === '.asar' && packageRoot.indexOf(resourcePath) === 0) {
+ return path.join(`${resourcePath}.unpacked`, 'node_modules', 'symbols-view');
+ } else {
+ return packageRoot;
+ }
+ }
+
+ parseTagLine(line) {
+ let sections = line.split('\t');
+ if (sections.length > 3) {
+ return {
+ position: new Point(parseInt(sections[2], 10) - 1),
+ name: sections[0],
+ };
+ }
+ return null;
+ }
+
+ getLanguage() {
+ if (['.cson', '.gyp'].includes(path.extname(this.path))) {
+ return 'Cson';
+ }
+
+ switch (this.scopeName) {
+ case 'source.c': return 'C';
+ case 'source.cpp': return 'C++';
+ case 'source.clojure': return 'Lisp';
+ case 'source.capnp': return 'Capnp';
+ case 'source.cfscript': return 'ColdFusion';
+ case 'source.cfscript.embedded': return 'ColdFusion';
+ case 'source.coffee': return 'CoffeeScript';
+ case 'source.css': return 'Css';
+ case 'source.css.less': return 'Css';
+ case 'source.css.scss': return 'Css';
+ case 'source.elixir': return 'Elixir';
+ case 'source.fountain': return 'Fountain';
+ case 'source.gfm': return 'Markdown';
+ case 'source.go': return 'Go';
+ case 'source.java': return 'Java';
+ case 'source.js': return 'JavaScript';
+ case 'source.js.jsx': return 'JavaScript';
+ case 'source.jsx': return 'JavaScript';
+ case 'source.json': return 'Json';
+ case 'source.julia': return 'Julia';
+ case 'source.makefile': return 'Make';
+ case 'source.objc': return 'C';
+ case 'source.objcpp': return 'C++';
+ case 'source.python': return 'Python';
+ case 'source.ruby': return 'Ruby';
+ case 'source.sass': return 'Sass';
+ case 'source.yaml': return 'Yaml';
+ case 'text.html': return 'Html';
+ case 'text.html.php': return 'Php';
+ case 'text.tex.latex': return 'Latex';
+ case 'text.html.cfml': return 'ColdFusion';
+ }
+ return undefined;
+ }
+
+ generate() {
+ let tags = {};
+ const packageRoot = this.getPackageRoot();
+ const command = path.join(packageRoot, 'vendor', `ctags-${process.platform}`);
+ const defaultCtagsFile = path.join(packageRoot, 'lib', 'ctags-config');
+ const args = [`--options=${defaultCtagsFile}`, '--fields=+KS'];
+
+ if (atom.config.get('symbols-view.useEditorGrammarAsCtagsLanguage')) {
+ const language = this.getLanguage();
+ if (language) {
+ args.push(`--language-force=${language}`);
+ }
+ }
+
+ args.push('-nf', '-', this.path);
+
+ return new Promise((resolve) => {
+ let result, tag;
+ return new BufferedProcess({
+ command: command,
+ args: args,
+ stdout: (lines) => {
+ return (() => {
+ result = [];
+ for (const line of Array.from(lines.split('\n'))) {
+ let item;
+ if (tag = this.parseTagLine(line)) {
+ item = tags[tag.position.row] ? tags[tag.position.row] : (tags[tag.position.row] = tag);
+ }
+ result.push(item);
+ }
+ return result;
+ })();
+ },
+ stderr() {},
+ exit() {
+ tags = ((() => {
+ result = [];
+ for (const row in tags) {
+ tag = tags[row];
+ result.push(tag);
+ }
+ return result;
+ })());
+ return resolve(tags);
+ },
+ });
+ });
+ }
+}
diff --git a/packages/symbols-view/lib/tag-reader.js b/packages/symbols-view/lib/tag-reader.js
new file mode 100644
index 000000000..07ed8ab93
--- /dev/null
+++ b/packages/symbols-view/lib/tag-reader.js
@@ -0,0 +1,124 @@
+/** @babel */
+
+import { Task } from 'atom';
+import ctags from 'ctags';
+import async from 'async';
+import getTagsFile from './get-tags-file';
+import _ from 'underscore-plus';
+
+let handlerPath = require.resolve('./load-tags-handler');
+
+let wordAtCursor = (text, cursorIndex, wordSeparator, noStripBefore) => {
+ const beforeCursor = text.slice(0, cursorIndex);
+ const afterCursor = text.slice(cursorIndex);
+ const beforeCursorWordBegins = noStripBefore ? 0 : beforeCursor.lastIndexOf(wordSeparator) + 1;
+ let afterCursorWordEnds = afterCursor.indexOf(wordSeparator);
+ if (afterCursorWordEnds === -1) {
+ afterCursorWordEnds = afterCursor.length;
+ }
+ return beforeCursor.slice(beforeCursorWordBegins) + afterCursor.slice(0, afterCursorWordEnds);
+};
+
+export default {
+ find(editor, callback) {
+ let symbol;
+ const symbols = [];
+
+ if (symbol = editor.getSelectedText()) {
+ symbols.push(symbol);
+ }
+
+ if (!symbols.length) {
+ let nonWordCharacters;
+ const cursor = editor.getLastCursor();
+ const cursorPosition = cursor.getBufferPosition();
+ const scope = cursor.getScopeDescriptor();
+ const rubyScopes = scope.getScopesArray().filter(s => /^source\.ruby($|\.)/.test(s));
+
+ const wordRegExp = rubyScopes.length ?
+ (nonWordCharacters = atom.config.get('editor.nonWordCharacters', {scope}),
+ // Allow special handling for fully-qualified ruby constants
+ nonWordCharacters = nonWordCharacters.replace(/:/g, ''),
+ new RegExp(`[^\\s${_.escapeRegExp(nonWordCharacters)}]+([!?]|\\s*=>?)?|[<=>]+`, 'g'))
+ :
+ cursor.wordRegExp();
+
+ const addSymbol = (symbol) => {
+ if (rubyScopes.length) {
+ // Normalize assignment syntax
+ if (/\s+=?$/.test(symbol)) { symbols.push(symbol.replace(/\s+=$/, '=')); }
+ // Strip away assignment & hashrocket syntax
+ symbols.push(symbol.replace(/\s+=>?$/, ''));
+ } else {
+ symbols.push(symbol);
+ }
+ };
+
+ // Can't use `getCurrentWordBufferRange` here because we want to select
+ // the last match of the potential 2 matches under cursor.
+ editor.scanInBufferRange(wordRegExp, cursor.getCurrentLineBufferRange(), ({range, match}) => {
+ if (range.containsPoint(cursorPosition)) {
+ symbol = match[0];
+ if (rubyScopes.length && symbol.indexOf(':') > -1) {
+ const cursorWithinSymbol = cursorPosition.column - range.start.column;
+ // Add fully-qualified ruby constant up until the cursor position
+ addSymbol(wordAtCursor(symbol, cursorWithinSymbol, ':', true));
+ // Additionally, also look up the bare word under cursor
+ addSymbol(wordAtCursor(symbol, cursorWithinSymbol, ':'));
+ } else {
+ addSymbol(symbol);
+ }
+ }
+ });
+ }
+
+ if (!symbols.length) {
+ process.nextTick(() => {
+ callback(null, []);
+ });
+ }
+
+ async.map(atom.project.getPaths(), (projectPath, done) => {
+ const tagsFile = getTagsFile(projectPath);
+ let foundTags = [];
+ let foundErr = null;
+ const detectCallback = () => {
+ done(foundErr, foundTags);
+ };
+ if (!tagsFile) {
+ return detectCallback();
+ }
+ // Find the first symbol in the list that matches a tag
+ return async.detectSeries(symbols, (symbol, doneDetect) => {
+ ctags.findTags(tagsFile, symbol, (err, tags) => {
+ if (!tags) {
+ tags = [];
+ }
+ if (err) {
+ foundErr = err;
+ doneDetect(false);
+ } else if (tags.length) {
+ for (const tag of Array.from(tags)) {
+ tag.directory = projectPath;
+ }
+ foundTags = tags;
+ doneDetect(true);
+ } else {
+ doneDetect(false);
+ }
+ });
+ }, detectCallback);
+ }, (err, foundTags) => {
+ callback(err, _.flatten(foundTags));
+ });
+ },
+
+ getAllTags(callback) {
+ const projectTags = [];
+ const task = Task.once(handlerPath, atom.project.getPaths(), () => callback(projectTags));
+ task.on('tags', (tags) => {
+ projectTags.push(...tags);
+ });
+ return task;
+ },
+};
diff --git a/packages/symbols-view/menus/symbols-view.cson b/packages/symbols-view/menus/symbols-view.cson
new file mode 100644
index 000000000..9e1dc85b1
--- /dev/null
+++ b/packages/symbols-view/menus/symbols-view.cson
@@ -0,0 +1,17 @@
+'menu': [
+ {
+ 'label': 'Packages'
+ 'submenu': [
+ 'label': 'Symbols'
+ 'submenu': [
+ { 'label': 'File Symbols', 'command': 'symbols-view:toggle-file-symbols' }
+ { 'label': 'Project Symbols', 'command': 'symbols-view:toggle-project-symbols' }
+ ]
+ ]
+ }
+]
+
+'context-menu':
+ 'atom-text-editor:not([mini])': [
+ { 'label': 'Go to Declaration', 'command': 'symbols-view:go-to-declaration' }
+ ]
diff --git a/packages/symbols-view/package-lock.json b/packages/symbols-view/package-lock.json
new file mode 100644
index 000000000..d72551850
--- /dev/null
+++ b/packages/symbols-view/package-lock.json
@@ -0,0 +1,1748 @@
+{
+ "name": "symbols-view",
+ "version": "0.118.4",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "symbols-view",
+ "version": "0.118.4",
+ "license": "MIT",
+ "dependencies": {
+ "async": "^0.2.6",
+ "atom-select-list": "^0.7.0",
+ "ctags": "^3.1.0",
+ "fs-plus": "^3.0.0",
+ "fuzzaldrin": "^2.1.0",
+ "humanize-plus": "^1.8.2",
+ "temp": "^0.8.3",
+ "underscore-plus": "^1.6.6"
+ },
+ "devDependencies": {
+ "babel-eslint": "^6.1.2",
+ "eslint": "^3.12.2",
+ "eslint-config-fbjs": "^1.1.1",
+ "eslint-plugin-babel": "^3.3.0",
+ "eslint-plugin-flowtype": "^2.29.1",
+ "eslint-plugin-jasmine": "^2.2.0",
+ "eslint-plugin-prefer-object-spread": "^1.1.0",
+ "eslint-plugin-react": "^5.2.2"
+ },
+ "engines": {
+ "atom": "*"
+ }
+ },
+ "node_modules/acorn": {
+ "version": "5.7.3",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz",
+ "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==",
+ "dev": true,
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-jsx": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz",
+ "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=",
+ "dev": true,
+ "dependencies": {
+ "acorn": "^3.0.4"
+ }
+ },
+ "node_modules/acorn-jsx/node_modules/acorn": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz",
+ "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=",
+ "dev": true,
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "4.11.8",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz",
+ "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=",
+ "dev": true,
+ "dependencies": {
+ "co": "^4.6.0",
+ "json-stable-stringify": "^1.0.1"
+ }
+ },
+ "node_modules/ajv-keywords": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz",
+ "integrity": "sha1-MU3QpLM2j609/NxU7eYXG4htrzw=",
+ "dev": true,
+ "peerDependencies": {
+ "ajv": ">=4.10.0"
+ }
+ },
+ "node_modules/ansi-escapes": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz",
+ "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "dev": true,
+ "dependencies": {
+ "sprintf-js": "~1.0.2"
+ }
+ },
+ "node_modules/async": {
+ "version": "0.2.10",
+ "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz",
+ "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E="
+ },
+ "node_modules/atom-select-list": {
+ "version": "0.7.2",
+ "resolved": "https://registry.npmjs.org/atom-select-list/-/atom-select-list-0.7.2.tgz",
+ "integrity": "sha512-a707OB1DhLGjzqtFrtMQKH7BBxFuCh8UBoUWxgFOrLrSwVh3g+/TlVPVDOz12+U0mDu3mIrnYLqQyhywQOTxhw==",
+ "dependencies": {
+ "etch": "^0.12.6",
+ "fuzzaldrin": "^2.1.0"
+ }
+ },
+ "node_modules/babel-code-frame": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
+ "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=",
+ "dev": true,
+ "dependencies": {
+ "chalk": "^1.1.3",
+ "esutils": "^2.0.2",
+ "js-tokens": "^3.0.2"
+ }
+ },
+ "node_modules/babel-eslint": {
+ "version": "6.1.2",
+ "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-6.1.2.tgz",
+ "integrity": "sha1-UpNBn+NnLWZZjTJ9qWlFZ7pqXy8=",
+ "deprecated": "babel-eslint is now @babel/eslint-parser. This package will no longer receive updates.",
+ "dev": true,
+ "dependencies": {
+ "babel-traverse": "^6.0.20",
+ "babel-types": "^6.0.19",
+ "babylon": "^6.0.18",
+ "lodash.assign": "^4.0.0",
+ "lodash.pickby": "^4.0.0"
+ }
+ },
+ "node_modules/babel-messages": {
+ "version": "6.23.0",
+ "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz",
+ "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=",
+ "dev": true,
+ "dependencies": {
+ "babel-runtime": "^6.22.0"
+ }
+ },
+ "node_modules/babel-runtime": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
+ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
+ "dev": true,
+ "dependencies": {
+ "core-js": "^2.4.0",
+ "regenerator-runtime": "^0.11.0"
+ }
+ },
+ "node_modules/babel-traverse": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz",
+ "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=",
+ "dev": true,
+ "dependencies": {
+ "babel-code-frame": "^6.26.0",
+ "babel-messages": "^6.23.0",
+ "babel-runtime": "^6.26.0",
+ "babel-types": "^6.26.0",
+ "babylon": "^6.18.0",
+ "debug": "^2.6.8",
+ "globals": "^9.18.0",
+ "invariant": "^2.2.2",
+ "lodash": "^4.17.4"
+ }
+ },
+ "node_modules/babel-types": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz",
+ "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=",
+ "dev": true,
+ "dependencies": {
+ "babel-runtime": "^6.26.0",
+ "esutils": "^2.0.2",
+ "lodash": "^4.17.4",
+ "to-fast-properties": "^1.0.3"
+ }
+ },
+ "node_modules/babylon": {
+ "version": "6.18.0",
+ "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz",
+ "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==",
+ "dev": true,
+ "bin": {
+ "babylon": "bin/babylon.js"
+ }
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/buffer-from": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
+ "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
+ "dev": true
+ },
+ "node_modules/caller-path": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz",
+ "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=",
+ "dev": true,
+ "dependencies": {
+ "callsites": "^0.2.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/callsites": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz",
+ "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/chalk": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^2.2.1",
+ "escape-string-regexp": "^1.0.2",
+ "has-ansi": "^2.0.0",
+ "strip-ansi": "^3.0.0",
+ "supports-color": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/circular-json": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz",
+ "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==",
+ "deprecated": "CircularJSON is in maintenance only, flatted is its successor.",
+ "dev": true
+ },
+ "node_modules/cli-cursor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz",
+ "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=",
+ "dev": true,
+ "dependencies": {
+ "restore-cursor": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/cli-width": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz",
+ "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=",
+ "dev": true
+ },
+ "node_modules/co": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
+ "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=",
+ "dev": true,
+ "engines": {
+ "iojs": ">= 1.0.0",
+ "node": ">= 0.12.0"
+ }
+ },
+ "node_modules/code-point-at": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
+ "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
+ },
+ "node_modules/concat-stream": {
+ "version": "1.6.2",
+ "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
+ "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
+ "dev": true,
+ "engines": [
+ "node >= 0.8"
+ ],
+ "dependencies": {
+ "buffer-from": "^1.0.0",
+ "inherits": "^2.0.3",
+ "readable-stream": "^2.2.2",
+ "typedarray": "^0.0.6"
+ }
+ },
+ "node_modules/core-js": {
+ "version": "2.6.10",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.10.tgz",
+ "integrity": "sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA==",
+ "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.",
+ "dev": true,
+ "hasInstallScript": true
+ },
+ "node_modules/core-util-is": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
+ "dev": true
+ },
+ "node_modules/ctags": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/ctags/-/ctags-3.1.0.tgz",
+ "integrity": "sha512-7/aiGLj8Ih7Ko3bAAg8bQUwHjOGXKQ7XC+bv+vLh84BtkVodPEOpOnr65FnWjX2oFWoKSaDuxe7jFHudD2Q0uw==",
+ "hasInstallScript": true,
+ "dependencies": {
+ "event-stream": "~3.1.0",
+ "nan": "^2.14.0"
+ }
+ },
+ "node_modules/d": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz",
+ "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==",
+ "dev": true,
+ "dependencies": {
+ "es5-ext": "^0.10.50",
+ "type": "^1.0.1"
+ }
+ },
+ "node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dev": true,
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/deep-is": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
+ "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
+ "dev": true
+ },
+ "node_modules/doctrine": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+ "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+ "dev": true,
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/duplexer": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz",
+ "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E="
+ },
+ "node_modules/es5-ext": {
+ "version": "0.10.53",
+ "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz",
+ "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==",
+ "dev": true,
+ "dependencies": {
+ "es6-iterator": "~2.0.3",
+ "es6-symbol": "~3.1.3",
+ "next-tick": "~1.0.0"
+ }
+ },
+ "node_modules/es6-iterator": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
+ "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=",
+ "dev": true,
+ "dependencies": {
+ "d": "1",
+ "es5-ext": "^0.10.35",
+ "es6-symbol": "^3.1.1"
+ }
+ },
+ "node_modules/es6-map": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz",
+ "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=",
+ "dev": true,
+ "dependencies": {
+ "d": "1",
+ "es5-ext": "~0.10.14",
+ "es6-iterator": "~2.0.1",
+ "es6-set": "~0.1.5",
+ "es6-symbol": "~3.1.1",
+ "event-emitter": "~0.3.5"
+ }
+ },
+ "node_modules/es6-set": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz",
+ "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=",
+ "dev": true,
+ "dependencies": {
+ "d": "1",
+ "es5-ext": "~0.10.14",
+ "es6-iterator": "~2.0.1",
+ "es6-symbol": "3.1.1",
+ "event-emitter": "~0.3.5"
+ }
+ },
+ "node_modules/es6-set/node_modules/es6-symbol": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz",
+ "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=",
+ "dev": true,
+ "dependencies": {
+ "d": "1",
+ "es5-ext": "~0.10.14"
+ }
+ },
+ "node_modules/es6-symbol": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz",
+ "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==",
+ "dev": true,
+ "dependencies": {
+ "d": "^1.0.1",
+ "ext": "^1.1.2"
+ }
+ },
+ "node_modules/es6-weak-map": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz",
+ "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==",
+ "dev": true,
+ "dependencies": {
+ "d": "1",
+ "es5-ext": "^0.10.46",
+ "es6-iterator": "^2.0.3",
+ "es6-symbol": "^3.1.1"
+ }
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/escope": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz",
+ "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=",
+ "dev": true,
+ "dependencies": {
+ "es6-map": "^0.1.3",
+ "es6-weak-map": "^2.0.1",
+ "esrecurse": "^4.1.0",
+ "estraverse": "^4.1.1"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/eslint": {
+ "version": "3.19.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-3.19.0.tgz",
+ "integrity": "sha1-yPxiAcf0DdCJQbh8CFdnOGpnmsw=",
+ "dev": true,
+ "dependencies": {
+ "babel-code-frame": "^6.16.0",
+ "chalk": "^1.1.3",
+ "concat-stream": "^1.5.2",
+ "debug": "^2.1.1",
+ "doctrine": "^2.0.0",
+ "escope": "^3.6.0",
+ "espree": "^3.4.0",
+ "esquery": "^1.0.0",
+ "estraverse": "^4.2.0",
+ "esutils": "^2.0.2",
+ "file-entry-cache": "^2.0.0",
+ "glob": "^7.0.3",
+ "globals": "^9.14.0",
+ "ignore": "^3.2.0",
+ "imurmurhash": "^0.1.4",
+ "inquirer": "^0.12.0",
+ "is-my-json-valid": "^2.10.0",
+ "is-resolvable": "^1.0.0",
+ "js-yaml": "^3.5.1",
+ "json-stable-stringify": "^1.0.0",
+ "levn": "^0.3.0",
+ "lodash": "^4.0.0",
+ "mkdirp": "^0.5.0",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.8.2",
+ "path-is-inside": "^1.0.1",
+ "pluralize": "^1.2.1",
+ "progress": "^1.1.8",
+ "require-uncached": "^1.0.2",
+ "shelljs": "^0.7.5",
+ "strip-bom": "^3.0.0",
+ "strip-json-comments": "~2.0.1",
+ "table": "^3.7.8",
+ "text-table": "~0.2.0",
+ "user-home": "^2.0.0"
+ },
+ "bin": {
+ "eslint": "bin/eslint.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/eslint-config-fbjs": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/eslint-config-fbjs/-/eslint-config-fbjs-1.1.1.tgz",
+ "integrity": "sha1-3Sn42RLop1Ulfp7u8AuuHM5X9zo=",
+ "dev": true,
+ "peerDependencies": {
+ "babel-eslint": "^6.1.2",
+ "eslint": "^3.0.0",
+ "eslint-plugin-babel": "^3.3.0",
+ "eslint-plugin-flowtype": "^2.15.0",
+ "eslint-plugin-react": "^5.2.2"
+ }
+ },
+ "node_modules/eslint-plugin-babel": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-babel/-/eslint-plugin-babel-3.3.0.tgz",
+ "integrity": "sha1-L0lK7c9vSqTnW5FVmAg3vB+94ZM=",
+ "dev": true,
+ "peerDependencies": {
+ "eslint": ">=1.0.0"
+ }
+ },
+ "node_modules/eslint-plugin-flowtype": {
+ "version": "2.50.3",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-flowtype/-/eslint-plugin-flowtype-2.50.3.tgz",
+ "integrity": "sha512-X+AoKVOr7Re0ko/yEXyM5SSZ0tazc6ffdIOocp2fFUlWoDt7DV0Bz99mngOkAFLOAWjqRA5jPwqUCbrx13XoxQ==",
+ "dev": true,
+ "dependencies": {
+ "lodash": "^4.17.10"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "peerDependencies": {
+ "eslint": ">=2.0.0"
+ }
+ },
+ "node_modules/eslint-plugin-jasmine": {
+ "version": "2.10.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-jasmine/-/eslint-plugin-jasmine-2.10.1.tgz",
+ "integrity": "sha1-VzO3CedR9LxA4x4cFpib0s377Jc=",
+ "dev": true,
+ "engines": {
+ "node": ">=4",
+ "npm": ">=2"
+ }
+ },
+ "node_modules/eslint-plugin-prefer-object-spread": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-prefer-object-spread/-/eslint-plugin-prefer-object-spread-1.2.1.tgz",
+ "integrity": "sha1-J/uRhTaQzOs65hAdnIrsxqZ6QCw=",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0.0"
+ },
+ "peerDependencies": {
+ "eslint": ">=0.8.0"
+ }
+ },
+ "node_modules/eslint-plugin-react": {
+ "version": "5.2.2",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-5.2.2.tgz",
+ "integrity": "sha1-fbBo4fVIf2hx5N7vNqOBwwPqwWE=",
+ "dev": true,
+ "dependencies": {
+ "doctrine": "^1.2.2",
+ "jsx-ast-utils": "^1.2.1"
+ }
+ },
+ "node_modules/eslint-plugin-react/node_modules/doctrine": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz",
+ "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=",
+ "dev": true,
+ "dependencies": {
+ "esutils": "^2.0.2",
+ "isarray": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/espree": {
+ "version": "3.5.4",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz",
+ "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==",
+ "dev": true,
+ "dependencies": {
+ "acorn": "^5.5.0",
+ "acorn-jsx": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+ "dev": true,
+ "bin": {
+ "esparse": "bin/esparse.js",
+ "esvalidate": "bin/esvalidate.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/esquery": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz",
+ "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==",
+ "dev": true,
+ "dependencies": {
+ "estraverse": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=0.6"
+ }
+ },
+ "node_modules/esrecurse": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz",
+ "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==",
+ "dev": true,
+ "dependencies": {
+ "estraverse": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estraverse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+ "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/etch": {
+ "version": "0.12.8",
+ "resolved": "https://registry.npmjs.org/etch/-/etch-0.12.8.tgz",
+ "integrity": "sha512-dFLRe4wLroVtwzyy1vGlE3BSDZHiL0kZME5XgNGzZIULcYTvVno8vbiIleAesoKJmwWaxDTzG+4eppg2zk14JQ=="
+ },
+ "node_modules/event-emitter": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz",
+ "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=",
+ "dev": true,
+ "dependencies": {
+ "d": "1",
+ "es5-ext": "~0.10.14"
+ }
+ },
+ "node_modules/event-stream": {
+ "version": "3.1.7",
+ "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.1.7.tgz",
+ "integrity": "sha1-tMVAAS0P4UmEIPPYlGAI22OTw3o=",
+ "dependencies": {
+ "duplexer": "~0.1.1",
+ "from": "~0",
+ "map-stream": "~0.1.0",
+ "pause-stream": "0.0.11",
+ "split": "0.2",
+ "stream-combiner": "~0.0.4",
+ "through": "~2.3.1"
+ }
+ },
+ "node_modules/exit-hook": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz",
+ "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/ext": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz",
+ "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==",
+ "dev": true,
+ "dependencies": {
+ "type": "^2.0.0"
+ }
+ },
+ "node_modules/ext/node_modules/type": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/type/-/type-2.0.0.tgz",
+ "integrity": "sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow==",
+ "dev": true
+ },
+ "node_modules/fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
+ "dev": true
+ },
+ "node_modules/figures": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz",
+ "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=",
+ "dev": true,
+ "dependencies": {
+ "escape-string-regexp": "^1.0.5",
+ "object-assign": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/file-entry-cache": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz",
+ "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=",
+ "dev": true,
+ "dependencies": {
+ "flat-cache": "^1.2.1",
+ "object-assign": "^4.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/flat-cache": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz",
+ "integrity": "sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg==",
+ "dev": true,
+ "dependencies": {
+ "circular-json": "^0.3.1",
+ "graceful-fs": "^4.1.2",
+ "rimraf": "~2.6.2",
+ "write": "^0.2.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/flat-cache/node_modules/rimraf": {
+ "version": "2.6.3",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
+ "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
+ "dev": true,
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ }
+ },
+ "node_modules/from": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz",
+ "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4="
+ },
+ "node_modules/fs-plus": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/fs-plus/-/fs-plus-3.1.1.tgz",
+ "integrity": "sha512-Se2PJdOWXqos1qVTkvqqjb0CSnfBnwwD+pq+z4ksT+e97mEShod/hrNg0TRCCsXPbJzcIq+NuzQhigunMWMJUA==",
+ "dependencies": {
+ "async": "^1.5.2",
+ "mkdirp": "^0.5.1",
+ "rimraf": "^2.5.2",
+ "underscore-plus": "1.x"
+ }
+ },
+ "node_modules/fs-plus/node_modules/async": {
+ "version": "1.5.2",
+ "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
+ "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo="
+ },
+ "node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
+ },
+ "node_modules/fuzzaldrin": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fuzzaldrin/-/fuzzaldrin-2.1.0.tgz",
+ "integrity": "sha1-kCBMPi/appQbso0WZF1BgGOpDps="
+ },
+ "node_modules/generate-function": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz",
+ "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==",
+ "dev": true,
+ "dependencies": {
+ "is-property": "^1.0.2"
+ }
+ },
+ "node_modules/generate-object-property": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz",
+ "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=",
+ "dev": true,
+ "dependencies": {
+ "is-property": "^1.0.0"
+ }
+ },
+ "node_modules/glob": {
+ "version": "7.1.6",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
+ "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/globals": {
+ "version": "9.18.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz",
+ "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/graceful-fs": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz",
+ "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==",
+ "dev": true
+ },
+ "node_modules/has-ansi": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
+ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/humanize-plus": {
+ "version": "1.8.2",
+ "resolved": "https://registry.npmjs.org/humanize-plus/-/humanize-plus-1.8.2.tgz",
+ "integrity": "sha1-pls0RZrWNnrbs3B6gqPJ+RYWcDA=",
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/ignore": {
+ "version": "3.3.10",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz",
+ "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==",
+ "dev": true
+ },
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+ "dependencies": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
+ },
+ "node_modules/inquirer": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz",
+ "integrity": "sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34=",
+ "dev": true,
+ "dependencies": {
+ "ansi-escapes": "^1.1.0",
+ "ansi-regex": "^2.0.0",
+ "chalk": "^1.0.0",
+ "cli-cursor": "^1.0.1",
+ "cli-width": "^2.0.0",
+ "figures": "^1.3.5",
+ "lodash": "^4.3.0",
+ "readline2": "^1.0.1",
+ "run-async": "^0.1.0",
+ "rx-lite": "^3.1.2",
+ "string-width": "^1.0.1",
+ "strip-ansi": "^3.0.0",
+ "through": "^2.3.6"
+ }
+ },
+ "node_modules/interpret": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz",
+ "integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/invariant": {
+ "version": "2.2.4",
+ "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
+ "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
+ "dev": true,
+ "dependencies": {
+ "loose-envify": "^1.0.0"
+ }
+ },
+ "node_modules/is-fullwidth-code-point": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
+ "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
+ "dev": true,
+ "dependencies": {
+ "number-is-nan": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-my-ip-valid": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz",
+ "integrity": "sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ==",
+ "dev": true
+ },
+ "node_modules/is-my-json-valid": {
+ "version": "2.20.0",
+ "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.20.0.tgz",
+ "integrity": "sha512-XTHBZSIIxNsIsZXg7XB5l8z/OBFosl1Wao4tXLpeC7eKU4Vm/kdop2azkPqULwnfGQjmeDIyey9g7afMMtdWAA==",
+ "dev": true,
+ "dependencies": {
+ "generate-function": "^2.0.0",
+ "generate-object-property": "^1.1.0",
+ "is-my-ip-valid": "^1.0.0",
+ "jsonpointer": "^4.0.0",
+ "xtend": "^4.0.0"
+ }
+ },
+ "node_modules/is-property": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz",
+ "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=",
+ "dev": true
+ },
+ "node_modules/is-resolvable": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz",
+ "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==",
+ "dev": true
+ },
+ "node_modules/isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+ "dev": true
+ },
+ "node_modules/js-tokens": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
+ "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=",
+ "dev": true
+ },
+ "node_modules/js-yaml": {
+ "version": "3.13.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
+ "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
+ "dev": true,
+ "dependencies": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/json-stable-stringify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz",
+ "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=",
+ "dev": true,
+ "dependencies": {
+ "jsonify": "~0.0.0"
+ }
+ },
+ "node_modules/jsonify": {
+ "version": "0.0.0",
+ "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz",
+ "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=",
+ "dev": true,
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/jsonpointer": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz",
+ "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/jsx-ast-utils": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-1.4.1.tgz",
+ "integrity": "sha1-OGchPo3Xm/Ho8jAMDPwe+xgsDfE=",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/levn": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
+ "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=",
+ "dev": true,
+ "dependencies": {
+ "prelude-ls": "~1.1.2",
+ "type-check": "~0.3.2"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/lodash": {
+ "version": "4.17.15",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+ "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
+ "dev": true
+ },
+ "node_modules/lodash.assign": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz",
+ "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=",
+ "dev": true
+ },
+ "node_modules/lodash.pickby": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/lodash.pickby/-/lodash.pickby-4.6.0.tgz",
+ "integrity": "sha1-feoh2MGNdwOifHBMFdO4SmfjOv8=",
+ "dev": true
+ },
+ "node_modules/loose-envify": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+ "dev": true,
+ "dependencies": {
+ "js-tokens": "^3.0.0 || ^4.0.0"
+ },
+ "bin": {
+ "loose-envify": "cli.js"
+ }
+ },
+ "node_modules/map-stream": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz",
+ "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ="
+ },
+ "node_modules/minimatch": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/minimist": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+ "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
+ },
+ "node_modules/mkdirp": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
+ "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
+ "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)",
+ "dependencies": {
+ "minimist": "0.0.8"
+ },
+ "bin": {
+ "mkdirp": "bin/cmd.js"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+ "dev": true
+ },
+ "node_modules/mute-stream": {
+ "version": "0.0.5",
+ "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz",
+ "integrity": "sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA=",
+ "dev": true
+ },
+ "node_modules/nan": {
+ "version": "2.14.0",
+ "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz",
+ "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg=="
+ },
+ "node_modules/natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
+ "dev": true
+ },
+ "node_modules/next-tick": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz",
+ "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=",
+ "dev": true
+ },
+ "node_modules/number-is-nan": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
+ "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/onetime": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz",
+ "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/optionator": {
+ "version": "0.8.3",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz",
+ "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==",
+ "dev": true,
+ "dependencies": {
+ "deep-is": "~0.1.3",
+ "fast-levenshtein": "~2.0.6",
+ "levn": "~0.3.0",
+ "prelude-ls": "~1.1.2",
+ "type-check": "~0.3.2",
+ "word-wrap": "~1.2.3"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/os-homedir": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
+ "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/path-is-inside": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz",
+ "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=",
+ "dev": true
+ },
+ "node_modules/path-parse": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
+ "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
+ "dev": true
+ },
+ "node_modules/pause-stream": {
+ "version": "0.0.11",
+ "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz",
+ "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=",
+ "dependencies": {
+ "through": "~2.3"
+ }
+ },
+ "node_modules/pluralize": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-1.2.1.tgz",
+ "integrity": "sha1-0aIUg/0iu0HlihL6NCGCMUCJfEU=",
+ "dev": true
+ },
+ "node_modules/prelude-ls": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
+ "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/process-nextick-args": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
+ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
+ "dev": true
+ },
+ "node_modules/progress": {
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz",
+ "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/readable-stream": {
+ "version": "2.3.6",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+ "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
+ "dev": true,
+ "dependencies": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "node_modules/readline2": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/readline2/-/readline2-1.0.1.tgz",
+ "integrity": "sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU=",
+ "dev": true,
+ "dependencies": {
+ "code-point-at": "^1.0.0",
+ "is-fullwidth-code-point": "^1.0.0",
+ "mute-stream": "0.0.5"
+ }
+ },
+ "node_modules/rechoir": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz",
+ "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=",
+ "dev": true,
+ "dependencies": {
+ "resolve": "^1.1.6"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/regenerator-runtime": {
+ "version": "0.11.1",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
+ "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==",
+ "dev": true
+ },
+ "node_modules/require-uncached": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz",
+ "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=",
+ "dev": true,
+ "dependencies": {
+ "caller-path": "^0.1.0",
+ "resolve-from": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/resolve": {
+ "version": "1.13.1",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.13.1.tgz",
+ "integrity": "sha512-CxqObCX8K8YtAhOBRg+lrcdn+LK+WYOS8tSjqSFbjtrI5PnS63QPhZl4+yKfrU9tdsbMu9Anr/amegT87M9Z6w==",
+ "dev": true,
+ "dependencies": {
+ "path-parse": "^1.0.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/resolve-from": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz",
+ "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/restore-cursor": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz",
+ "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=",
+ "dev": true,
+ "dependencies": {
+ "exit-hook": "^1.0.0",
+ "onetime": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/rimraf": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+ "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ }
+ },
+ "node_modules/run-async": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz",
+ "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=",
+ "dev": true,
+ "dependencies": {
+ "once": "^1.3.0"
+ }
+ },
+ "node_modules/rx-lite": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz",
+ "integrity": "sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI=",
+ "dev": true
+ },
+ "node_modules/safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+ "dev": true
+ },
+ "node_modules/shelljs": {
+ "version": "0.7.8",
+ "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.7.8.tgz",
+ "integrity": "sha1-3svPh0sNHl+3LhSxZKloMEjprLM=",
+ "dev": true,
+ "dependencies": {
+ "glob": "^7.0.0",
+ "interpret": "^1.0.0",
+ "rechoir": "^0.6.2"
+ },
+ "bin": {
+ "shjs": "bin/shjs"
+ },
+ "engines": {
+ "iojs": "*",
+ "node": ">=0.11.0"
+ }
+ },
+ "node_modules/slice-ansi": {
+ "version": "0.0.4",
+ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz",
+ "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/split": {
+ "version": "0.2.10",
+ "resolved": "https://registry.npmjs.org/split/-/split-0.2.10.tgz",
+ "integrity": "sha1-Zwl8YB1pfOE2j0GPBs0gHPBSGlc=",
+ "dependencies": {
+ "through": "2"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/sprintf-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
+ "dev": true
+ },
+ "node_modules/stream-combiner": {
+ "version": "0.0.4",
+ "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz",
+ "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=",
+ "dependencies": {
+ "duplexer": "~0.1.1"
+ }
+ },
+ "node_modules/string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "dev": true,
+ "dependencies": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "node_modules/string-width": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+ "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+ "dev": true,
+ "dependencies": {
+ "code-point-at": "^1.0.0",
+ "is-fullwidth-code-point": "^1.0.0",
+ "strip-ansi": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/strip-json-comments": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
+ "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/table": {
+ "version": "3.8.3",
+ "resolved": "https://registry.npmjs.org/table/-/table-3.8.3.tgz",
+ "integrity": "sha1-K7xULw/amGGnVdOUf+/Ys/UThV8=",
+ "dev": true,
+ "dependencies": {
+ "ajv": "^4.7.0",
+ "ajv-keywords": "^1.0.0",
+ "chalk": "^1.1.1",
+ "lodash": "^4.0.0",
+ "slice-ansi": "0.0.4",
+ "string-width": "^2.0.0"
+ }
+ },
+ "node_modules/table/node_modules/ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/table/node_modules/is-fullwidth-code-point": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/table/node_modules/string-width": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+ "dev": true,
+ "dependencies": {
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/table/node_modules/strip-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/temp": {
+ "version": "0.8.4",
+ "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.4.tgz",
+ "integrity": "sha512-s0ZZzd0BzYv5tLSptZooSjK8oj6C+c19p7Vqta9+6NPOf7r+fxq0cJe6/oN4LTC79sy5NY8ucOJNgwsKCSbfqg==",
+ "dependencies": {
+ "rimraf": "~2.6.2"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/temp/node_modules/rimraf": {
+ "version": "2.6.3",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
+ "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ }
+ },
+ "node_modules/text-table": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
+ "dev": true
+ },
+ "node_modules/through": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
+ "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU="
+ },
+ "node_modules/to-fast-properties": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz",
+ "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/type": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz",
+ "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==",
+ "dev": true
+ },
+ "node_modules/type-check": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
+ "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=",
+ "dev": true,
+ "dependencies": {
+ "prelude-ls": "~1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/typedarray": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
+ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
+ "dev": true
+ },
+ "node_modules/underscore": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz",
+ "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg=="
+ },
+ "node_modules/underscore-plus": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/underscore-plus/-/underscore-plus-1.7.0.tgz",
+ "integrity": "sha512-A3BEzkeicFLnr+U/Q3EyWwJAQPbA19mtZZ4h+lLq3ttm9kn8WC4R3YpuJZEXmWdLjYP47Zc8aLZm9kwdv+zzvA==",
+ "dependencies": {
+ "underscore": "^1.9.1"
+ }
+ },
+ "node_modules/user-home": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz",
+ "integrity": "sha1-nHC/2Babwdy/SGBODwS4tJzenp8=",
+ "dev": true,
+ "dependencies": {
+ "os-homedir": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
+ "dev": true
+ },
+ "node_modules/word-wrap": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
+ "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
+ },
+ "node_modules/write": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz",
+ "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=",
+ "dev": true,
+ "dependencies": {
+ "mkdirp": "^0.5.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/xtend": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
+ "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.4"
+ }
+ }
+ }
+}
diff --git a/packages/symbols-view/package.json b/packages/symbols-view/package.json
new file mode 100644
index 000000000..93366633f
--- /dev/null
+++ b/packages/symbols-view/package.json
@@ -0,0 +1,53 @@
+{
+ "name": "symbols-view",
+ "version": "0.118.4",
+ "main": "./lib/main",
+ "description": "Jump to a function/method in the current editor with `cmd-r`.",
+ "license": "MIT",
+ "activationCommands": {
+ "atom-workspace": [
+ "symbols-view:toggle-project-symbols"
+ ],
+ "atom-text-editor": [
+ "symbols-view:go-to-declaration",
+ "symbols-view:return-from-declaration",
+ "symbols-view:toggle-file-symbols"
+ ]
+ },
+ "dependencies": {
+ "async": "^0.2.6",
+ "atom-select-list": "^0.7.0",
+ "ctags": "^3.1.0",
+ "fs-plus": "^3.0.0",
+ "fuzzaldrin": "^2.1.0",
+ "humanize-plus": "^1.8.2",
+ "temp": "^0.8.3",
+ "underscore-plus": "^1.6.6"
+ },
+ "configSchema": {
+ "useEditorGrammarAsCtagsLanguage": {
+ "default": true,
+ "type": "boolean",
+ "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."
+ },
+ "quickJumpToFileSymbol": {
+ "default": true,
+ "type": "boolean",
+ "description": "Automatically visit selected file-symbols"
+ }
+ },
+ "repository": "https://github.com/pulsar-edit/symbols-view",
+ "engines": {
+ "atom": "*"
+ },
+ "devDependencies": {
+ "babel-eslint": "^6.1.2",
+ "eslint": "^3.12.2",
+ "eslint-config-fbjs": "^1.1.1",
+ "eslint-plugin-babel": "^3.3.0",
+ "eslint-plugin-flowtype": "^2.29.1",
+ "eslint-plugin-jasmine": "^2.2.0",
+ "eslint-plugin-prefer-object-spread": "^1.1.0",
+ "eslint-plugin-react": "^5.2.2"
+ }
+}
diff --git a/packages/symbols-view/spec/async-spec-helpers.js b/packages/symbols-view/spec/async-spec-helpers.js
new file mode 100644
index 000000000..7642fdfb9
--- /dev/null
+++ b/packages/symbols-view/spec/async-spec-helpers.js
@@ -0,0 +1,67 @@
+/** @babel */
+
+export function beforeEach(fn) {
+ global.beforeEach(function() {
+ const result = fn();
+ if (result instanceof Promise) {
+ waitsForPromise(() => result);
+ }
+ });
+}
+
+export function afterEach(fn) {
+ global.afterEach(function() {
+ const result = fn();
+ if (result instanceof Promise) {
+ waitsForPromise(() => result);
+ }
+ });
+}
+
+['it', 'fit', 'ffit', 'fffit'].forEach(function(name) {
+ module.exports[name] = function(description, fn) {
+ global[name](description, function() {
+ const result = fn();
+ if (result instanceof Promise) {
+ waitsForPromise(() => result);
+ }
+ });
+ };
+});
+
+export async function conditionPromise(condition) {
+ const startTime = Date.now();
+
+ while (true) {
+ await timeoutPromise(100);
+
+ let conditionResult = condition();
+ if (condition instanceof Promise) {
+ conditionResult = await conditionResult;
+ }
+
+ if (conditionResult) {
+ return;
+ }
+
+ if (Date.now() - startTime > 5000) {
+ throw new Error('Timed out waiting on condition');
+ }
+ }
+}
+
+export function timeoutPromise(timeout) {
+ return new Promise(function(resolve) {
+ global.setTimeout(resolve, timeout);
+ });
+}
+
+function waitsForPromise(fn) {
+ const promise = fn();
+ global.waitsFor('spec promise to resolve', function(done) {
+ promise.then(done, function(error) {
+ jasmine.getEnv().currentSpec.fail(error);
+ done();
+ });
+ });
+}
diff --git a/packages/symbols-view/spec/fixtures/c/sample.c b/packages/symbols-view/spec/fixtures/c/sample.c
new file mode 100644
index 000000000..5a98bf4c1
--- /dev/null
+++ b/packages/symbols-view/spec/fixtures/c/sample.c
@@ -0,0 +1,6 @@
+#define UNUSED(x) (void)(x)
+
+static void f(int x)
+{
+ UNUSED(x);
+}
diff --git a/packages/symbols-view/spec/fixtures/js/sample.js b/packages/symbols-view/spec/fixtures/js/sample.js
new file mode 100644
index 000000000..fb33b0b43
--- /dev/null
+++ b/packages/symbols-view/spec/fixtures/js/sample.js
@@ -0,0 +1,13 @@
+var quicksort = function () {
+ var sort = function(items) {
+ if (items.length <= 1) return items;
+ var pivot = items.shift(), current, left = [], right = [];
+ while(items.length > 0) {
+ current = items.shift();
+ current < pivot ? left.push(current) : right.push(current);
+ }
+ return sort(left).concat(pivot).concat(sort(right));
+ };
+
+ return sort(Array.apply(this, arguments));
+};
\ No newline at end of file
diff --git a/packages/symbols-view/spec/fixtures/js/tagged-duplicate.js b/packages/symbols-view/spec/fixtures/js/tagged-duplicate.js
new file mode 100644
index 000000000..a4b6fbb8a
--- /dev/null
+++ b/packages/symbols-view/spec/fixtures/js/tagged-duplicate.js
@@ -0,0 +1,3 @@
+ function duplicate() {
+ return false;
+ }
diff --git a/packages/symbols-view/spec/fixtures/js/tagged.js b/packages/symbols-view/spec/fixtures/js/tagged.js
new file mode 100644
index 000000000..4adaac609
--- /dev/null
+++ b/packages/symbols-view/spec/fixtures/js/tagged.js
@@ -0,0 +1,11 @@
+var thisIsCrazy = true;
+
+function callMeMaybe() {
+ return "here's my number";
+}
+
+var iJustMetYou = callMeMaybe();
+
+function duplicate() {
+ return true;
+}
diff --git a/packages/symbols-view/spec/fixtures/ruby/file1.rb b/packages/symbols-view/spec/fixtures/ruby/file1.rb
new file mode 100644
index 000000000..62697a7b3
--- /dev/null
+++ b/packages/symbols-view/spec/fixtures/ruby/file1.rb
@@ -0,0 +1,33 @@
+module A::Foo
+ B = 'b'
+
+ def bar!
+
+ end
+
+ def bar?
+
+ end
+
+ def baz
+ end
+
+ def baz=(*)
+ end
+end
+
+if bar?
+ baz
+ bar!
+elsif !bar!
+ baz= 1
+ baz = 2
+ Foo = 3
+ { :baz => 4 }
+ A::Foo::B
+ C::Foo::B
+ D::Foo::E
+end
+
+module D::Foo
+end
diff --git a/packages/symbols-view/spec/symbols-view-spec.js b/packages/symbols-view/spec/symbols-view-spec.js
new file mode 100644
index 000000000..97cebe8d3
--- /dev/null
+++ b/packages/symbols-view/spec/symbols-view-spec.js
@@ -0,0 +1,532 @@
+/** @babel */
+/* eslint-env jasmine */
+
+import path from 'path';
+import etch from 'etch';
+import fs from 'fs-plus';
+import temp from 'temp';
+import SymbolsView from '../lib/symbols-view';
+import TagGenerator from '../lib/tag-generator';
+
+import {it, fit, ffit, fffit, beforeEach, afterEach, conditionPromise} from './async-spec-helpers';
+
+describe('SymbolsView', () => {
+ let [symbolsView, activationPromise, editor, directory] = [];
+
+ const getWorkspaceView = () => atom.views.getView(atom.workspace);
+ const getEditorView = () => atom.views.getView(atom.workspace.getActiveTextEditor());
+
+ beforeEach(async () => {
+ jasmine.unspy(global, 'setTimeout');
+
+ atom.project.setPaths([
+ temp.mkdirSync('other-dir-'),
+ temp.mkdirSync('atom-symbols-view-'),
+ ]);
+
+ directory = atom.project.getDirectories()[1];
+ fs.copySync(path.join(__dirname, 'fixtures', 'js'), atom.project.getPaths()[1]);
+
+ activationPromise = atom.packages.activatePackage('symbols-view');
+ jasmine.attachToDOM(getWorkspaceView());
+ });
+
+ describe('when tags can be generated for a file', () => {
+ beforeEach(async () => {
+ await atom.workspace.open(directory.resolve('sample.js'));
+ });
+
+ it('initially displays all JavaScript functions with line numbers', async () => {
+ atom.commands.dispatch(getEditorView(), 'symbols-view:toggle-file-symbols');
+ await activationPromise;
+ symbolsView = atom.workspace.getModalPanels()[0].item;
+ await conditionPromise(() => symbolsView.element.querySelectorAll('li').length > 0);
+ expect(symbolsView.selectListView.refs.loadingMessage).toBeUndefined();
+ expect(document.body.contains(symbolsView.element)).toBe(true);
+ expect(symbolsView.element.querySelectorAll('li').length).toBe(2);
+ expect(symbolsView.element.querySelector('li:first-child .primary-line')).toHaveText('quicksort');
+ expect(symbolsView.element.querySelector('li:first-child .secondary-line')).toHaveText('Line 1');
+ expect(symbolsView.element.querySelector('li:last-child .primary-line')).toHaveText('quicksort.sort');
+ expect(symbolsView.element.querySelector('li:last-child .secondary-line')).toHaveText('Line 2');
+ expect(symbolsView.selectListView.refs.errorMessage).toBeUndefined();
+ });
+
+ it('caches tags until the editor changes', async () => {
+ editor = atom.workspace.getActiveTextEditor();
+ atom.commands.dispatch(getEditorView(), 'symbols-view:toggle-file-symbols');
+ await activationPromise;
+ symbolsView = atom.workspace.getModalPanels()[0].item;
+ await conditionPromise(() => symbolsView.element.querySelectorAll('li').length > 0);
+ await symbolsView.cancel();
+
+ spyOn(symbolsView, 'generateTags').andCallThrough();
+ atom.commands.dispatch(getEditorView(), 'symbols-view:toggle-file-symbols');
+ await conditionPromise(() => symbolsView.element.querySelectorAll('li').length > 0);
+ expect(symbolsView.selectListView.refs.loadingMessage).toBeUndefined();
+ expect(symbolsView.element.querySelectorAll('li').length).toBe(2);
+ expect(symbolsView.generateTags).not.toHaveBeenCalled();
+ await symbolsView.cancel();
+
+ await editor.save();
+ atom.commands.dispatch(getEditorView(), 'symbols-view:toggle-file-symbols');
+ await conditionPromise(() => symbolsView.element.querySelectorAll('li').length > 0);
+ expect(symbolsView.selectListView.refs.loadingMessage).toBeUndefined();
+ expect(symbolsView.element.querySelectorAll('li').length).toBe(2);
+ expect(symbolsView.generateTags).toHaveBeenCalled();
+ editor.destroy();
+ expect(symbolsView.cachedTags).toEqual({});
+ });
+
+ it('displays an error when no tags match text in mini-editor', async () => {
+ atom.commands.dispatch(getEditorView(), 'symbols-view:toggle-file-symbols');
+ await activationPromise;
+ symbolsView = atom.workspace.getModalPanels()[0].item;
+ await conditionPromise(() => symbolsView.element.querySelectorAll('li').length > 0);
+
+ symbolsView.selectListView.refs.queryEditor.setText('nothing will match this');
+ await conditionPromise(() => symbolsView.selectListView.refs.emptyMessage);
+ expect(document.body.contains(symbolsView.element)).toBe(true);
+ expect(symbolsView.element.querySelectorAll('li').length).toBe(0);
+ expect(symbolsView.selectListView.refs.emptyMessage.textContent.length).toBeGreaterThan(0);
+
+ // Should remove error
+ symbolsView.selectListView.refs.queryEditor.setText('');
+ await conditionPromise(() => symbolsView.element.querySelectorAll('li').length > 0);
+ expect(symbolsView.element.querySelectorAll('li').length).toBe(2);
+ expect(symbolsView.selectListView.refs.emptyMessage).toBeUndefined();
+ });
+
+ it('moves the cursor to the selected function', async () => {
+ expect(atom.workspace.getActiveTextEditor().getCursorBufferPosition()).toEqual([0, 0]);
+ atom.commands.dispatch(getEditorView(), 'symbols-view:toggle-file-symbols');
+ await activationPromise;
+ symbolsView = atom.workspace.getModalPanels()[0].item;
+ await conditionPromise(() => symbolsView.element.querySelectorAll('li').length > 0);
+
+ symbolsView.element.querySelectorAll('li')[1].click();
+ expect(atom.workspace.getActiveTextEditor().getCursorBufferPosition()).toEqual([1, 2]);
+ });
+ });
+
+ describe("when tags can't be generated for a file", () => {
+ beforeEach(async () => {
+ await atom.workspace.open('sample.txt');
+ });
+
+ it('shows an error message when no matching tags are found', async () => {
+ atom.commands.dispatch(getEditorView(), 'symbols-view:toggle-file-symbols');
+ await activationPromise;
+ symbolsView = atom.workspace.getModalPanels()[0].item;
+
+ await conditionPromise(() => symbolsView.selectListView.refs.emptyMessage);
+ expect(document.body.contains(symbolsView.element));
+ expect(symbolsView.element.querySelectorAll('li').length).toBe(0);
+ expect(symbolsView.selectListView.refs.emptyMessage).toBeVisible();
+ expect(symbolsView.selectListView.refs.emptyMessage.textContent.length).toBeGreaterThan(0);
+ expect(symbolsView.selectListView.refs.loadingMessage).not.toBeVisible();
+ });
+ });
+
+ describe('TagGenerator', () => {
+ it('generates tags for all JavaScript functions', async () => {
+ let tags = [];
+ const sampleJsPath = directory.resolve('sample.js');
+ await new TagGenerator(sampleJsPath).generate().then(o => tags = o);
+ expect(tags.length).toBe(2);
+ expect(tags[0].name).toBe('quicksort');
+ expect(tags[0].position.row).toBe(0);
+ expect(tags[1].name).toBe('quicksort.sort');
+ expect(tags[1].position.row).toBe(1);
+ });
+
+ it('generates no tags for text file', async () => {
+ let tags = [];
+ const sampleJsPath = directory.resolve('sample.txt');
+ await new TagGenerator(sampleJsPath).generate().then(o => tags = o);
+ expect(tags.length).toBe(0);
+ });
+ });
+
+ describe('go to declaration', () => {
+ it("doesn't move the cursor when no declaration is found", async () => {
+ await atom.workspace.open(directory.resolve('tagged.js'));
+ editor = atom.workspace.getActiveTextEditor();
+ editor.setCursorBufferPosition([0, 2]);
+ atom.commands.dispatch(getEditorView(), 'symbols-view:go-to-declaration');
+
+ await activationPromise;
+
+ expect(editor.getCursorBufferPosition()).toEqual([0, 2]);
+ });
+
+ it('moves the cursor to the declaration when there is a single matching declaration', async () => {
+ await atom.workspace.open(directory.resolve('tagged.js'));
+ editor = atom.workspace.getActiveTextEditor();
+ editor.setCursorBufferPosition([6, 24]);
+ spyOn(SymbolsView.prototype, 'moveToPosition').andCallThrough();
+ atom.commands.dispatch(getEditorView(), 'symbols-view:go-to-declaration');
+
+ await conditionPromise(() => SymbolsView.prototype.moveToPosition.callCount === 1);
+ expect(editor.getCursorBufferPosition()).toEqual([2, 0]);
+ });
+
+ it('correctly moves the cursor to the declaration of a C preprocessor macro', async () => {
+ atom.project.setPaths([temp.mkdirSync('atom-symbols-view-c-')]);
+ fs.copySync(path.join(__dirname, 'fixtures', 'c'), atom.project.getPaths()[0]);
+
+ await atom.packages.activatePackage('language-c');
+ await atom.workspace.open('sample.c');
+
+ editor = atom.workspace.getActiveTextEditor();
+ editor.setCursorBufferPosition([4, 4]);
+ spyOn(SymbolsView.prototype, 'moveToPosition').andCallThrough();
+ atom.commands.dispatch(getEditorView(), 'symbols-view:go-to-declaration');
+
+ await conditionPromise(() => SymbolsView.prototype.moveToPosition.callCount === 1);
+ expect(editor.getCursorBufferPosition()).toEqual([0, 0]);
+ });
+
+ it('displays matches when more than one exists and opens the selected match', async () => {
+ await atom.workspace.open(directory.resolve('tagged.js'));
+ editor = atom.workspace.getActiveTextEditor();
+ editor.setCursorBufferPosition([8, 14]);
+ atom.commands.dispatch(getEditorView(), 'symbols-view:go-to-declaration');
+ symbolsView = atom.workspace.getModalPanels()[0].item;
+
+ await conditionPromise(() => symbolsView.element.querySelectorAll('li').length > 0);
+ expect(symbolsView.element.querySelectorAll('li').length).toBe(2);
+ expect(symbolsView.element).toBeVisible();
+ spyOn(SymbolsView.prototype, 'moveToPosition').andCallThrough();
+ symbolsView.selectListView.confirmSelection();
+
+ await conditionPromise(() => SymbolsView.prototype.moveToPosition.callCount === 1);
+ expect(atom.workspace.getActiveTextEditor().getPath()).toBe(directory.resolve('tagged-duplicate.js'));
+ expect(atom.workspace.getActiveTextEditor().getCursorBufferPosition()).toEqual([0, 4]);
+ });
+
+ it('includes ? and ! characters in ruby symbols', async () => {
+ atom.project.setPaths([temp.mkdirSync('atom-symbols-view-ruby-')]);
+ fs.copySync(path.join(__dirname, 'fixtures', 'ruby'), atom.project.getPaths()[0]);
+
+ await atom.packages.activatePackage('language-ruby');
+ await atom.workspace.open('file1.rb');
+
+ spyOn(SymbolsView.prototype, 'moveToPosition').andCallThrough();
+ atom.workspace.getActiveTextEditor().setCursorBufferPosition([18, 4]);
+ atom.commands.dispatch(getEditorView(), 'symbols-view:go-to-declaration');
+
+ await activationPromise;
+ await conditionPromise(() => SymbolsView.prototype.moveToPosition.callCount === 1);
+ expect(atom.workspace.getActiveTextEditor().getCursorBufferPosition()).toEqual([7, 2]);
+ SymbolsView.prototype.moveToPosition.reset();
+ atom.workspace.getActiveTextEditor().setCursorBufferPosition([19, 2]);
+ atom.commands.dispatch(getEditorView(), 'symbols-view:go-to-declaration');
+
+ await conditionPromise(() => SymbolsView.prototype.moveToPosition.callCount === 1);
+ expect(atom.workspace.getActiveTextEditor().getCursorBufferPosition()).toEqual([11, 2]);
+ SymbolsView.prototype.moveToPosition.reset();
+ atom.workspace.getActiveTextEditor().setCursorBufferPosition([20, 5]);
+ atom.commands.dispatch(getEditorView(), 'symbols-view:go-to-declaration');
+
+ await conditionPromise(() => SymbolsView.prototype.moveToPosition.callCount === 1);
+ expect(atom.workspace.getActiveTextEditor().getCursorBufferPosition()).toEqual([3, 2]);
+ SymbolsView.prototype.moveToPosition.reset();
+ atom.workspace.getActiveTextEditor().setCursorBufferPosition([21, 7]);
+ atom.commands.dispatch(getEditorView(), 'symbols-view:go-to-declaration');
+
+ await conditionPromise(() => SymbolsView.prototype.moveToPosition.callCount === 1);
+ expect(atom.workspace.getActiveTextEditor().getCursorBufferPosition()).toEqual([3, 2]);
+ });
+
+ it('handles jumping to assignment ruby method definitions', async () => {
+ atom.project.setPaths([temp.mkdirSync('atom-symbols-view-ruby-')]);
+ fs.copySync(path.join(__dirname, 'fixtures', 'ruby'), atom.project.getPaths()[0]);
+
+ await atom.packages.activatePackage('language-ruby');
+ await atom.workspace.open('file1.rb');
+ spyOn(SymbolsView.prototype, 'moveToPosition').andCallThrough();
+ atom.workspace.getActiveTextEditor().setCursorBufferPosition([22, 5]);
+ atom.commands.dispatch(getEditorView(), 'symbols-view:go-to-declaration');
+
+ await conditionPromise(() => SymbolsView.prototype.moveToPosition.callCount === 1);
+ expect(atom.workspace.getActiveTextEditor().getCursorBufferPosition()).toEqual([14, 2]);
+ SymbolsView.prototype.moveToPosition.reset();
+ atom.workspace.getActiveTextEditor().setCursorBufferPosition([23, 5]);
+ atom.commands.dispatch(getEditorView(), 'symbols-view:go-to-declaration');
+
+ await conditionPromise(() => SymbolsView.prototype.moveToPosition.callCount === 1);
+ expect(atom.workspace.getActiveTextEditor().getCursorBufferPosition()).toEqual([14, 2]);
+ SymbolsView.prototype.moveToPosition.reset();
+ atom.workspace.getActiveTextEditor().setCursorBufferPosition([24, 5]);
+ atom.commands.dispatch(getEditorView(), 'symbols-view:go-to-declaration');
+
+ await conditionPromise(() => SymbolsView.prototype.moveToPosition.callCount === 1);
+ expect(atom.workspace.getActiveTextEditor().getCursorBufferPosition()).toEqual([0, 0]);
+ SymbolsView.prototype.moveToPosition.reset();
+ atom.workspace.getActiveTextEditor().setCursorBufferPosition([25, 5]);
+ atom.commands.dispatch(getEditorView(), 'symbols-view:go-to-declaration');
+
+ await conditionPromise(() => SymbolsView.prototype.moveToPosition.callCount === 1);
+ expect(atom.workspace.getActiveTextEditor().getCursorBufferPosition()).toEqual([11, 2]);
+ });
+
+ it('handles jumping to fully qualified ruby constant definitions', async () => {
+ atom.project.setPaths([temp.mkdirSync('atom-symbols-view-ruby-')]);
+ fs.copySync(path.join(__dirname, 'fixtures', 'ruby'), atom.project.getPaths()[0]);
+ await atom.packages.activatePackage('language-ruby');
+ await atom.workspace.open('file1.rb');
+ spyOn(SymbolsView.prototype, 'moveToPosition').andCallThrough();
+ atom.workspace.getActiveTextEditor().setCursorBufferPosition([26, 10]);
+ atom.commands.dispatch(getEditorView(), 'symbols-view:go-to-declaration');
+
+ await conditionPromise(() => SymbolsView.prototype.moveToPosition.callCount === 1);
+ expect(atom.workspace.getActiveTextEditor().getCursorBufferPosition()).toEqual([1, 2]);
+ SymbolsView.prototype.moveToPosition.reset();
+ atom.workspace.getActiveTextEditor().setCursorBufferPosition([27, 5]);
+ atom.commands.dispatch(getEditorView(), 'symbols-view:go-to-declaration');
+
+ await conditionPromise(() => SymbolsView.prototype.moveToPosition.callCount === 1);
+ expect(atom.workspace.getActiveTextEditor().getCursorBufferPosition()).toEqual([0, 0]);
+ SymbolsView.prototype.moveToPosition.reset();
+ atom.workspace.getActiveTextEditor().setCursorBufferPosition([28, 5]);
+ atom.commands.dispatch(getEditorView(), 'symbols-view:go-to-declaration');
+
+ await conditionPromise(() => SymbolsView.prototype.moveToPosition.callCount === 1);
+ expect(atom.workspace.getActiveTextEditor().getCursorBufferPosition()).toEqual([31, 0]);
+ });
+
+ describe('return from declaration', () => {
+ it("doesn't do anything when no go-to have been triggered", async () => {
+ await atom.workspace.open(directory.resolve('tagged.js'));
+ editor = atom.workspace.getActiveTextEditor();
+ editor.setCursorBufferPosition([6, 0]);
+ atom.commands.dispatch(getEditorView(), 'symbols-view:return-from-declaration');
+
+ await activationPromise;
+ expect(editor.getCursorBufferPosition()).toEqual([6, 0]);
+ });
+
+ it('returns to previous row and column', async () => {
+ await atom.workspace.open(directory.resolve('tagged.js'));
+ editor = atom.workspace.getActiveTextEditor();
+ editor.setCursorBufferPosition([6, 24]);
+ spyOn(SymbolsView.prototype, 'moveToPosition').andCallThrough();
+ atom.commands.dispatch(getEditorView(), 'symbols-view:go-to-declaration');
+
+ await activationPromise;
+ await conditionPromise(() => SymbolsView.prototype.moveToPosition.callCount === 1);
+ expect(editor.getCursorBufferPosition()).toEqual([2, 0]);
+ atom.commands.dispatch(getEditorView(), 'symbols-view:return-from-declaration');
+
+ await conditionPromise(() => SymbolsView.prototype.moveToPosition.callCount === 2);
+ expect(editor.getCursorBufferPosition()).toEqual([6, 24]);
+ });
+ });
+
+ describe("when the tag is in a file that doesn't exist", () => {
+ it("doesn't display the tag", async () => {
+ fs.removeSync(directory.resolve('tagged-duplicate.js'));
+ await atom.workspace.open(directory.resolve('tagged.js'));
+
+ editor = atom.workspace.getActiveTextEditor();
+ editor.setCursorBufferPosition([8, 14]);
+ spyOn(SymbolsView.prototype, 'moveToPosition').andCallThrough();
+ atom.commands.dispatch(getEditorView(), 'symbols-view:go-to-declaration');
+
+ await conditionPromise(() => SymbolsView.prototype.moveToPosition.callCount === 1);
+ expect(editor.getCursorBufferPosition()).toEqual([8, 0]);
+ });
+ });
+ });
+
+ describe('project symbols', () => {
+ it('displays all tags', async () => {
+ await atom.workspace.open(directory.resolve('tagged.js'));
+ expect(getWorkspaceView().querySelector('.symbols-view')).toBeNull();
+ atom.commands.dispatch(getWorkspaceView(), 'symbols-view:toggle-project-symbols');
+
+ await activationPromise;
+ symbolsView = atom.workspace.getModalPanels()[0].item;
+
+ await conditionPromise(() => symbolsView.element.querySelectorAll('li').length > 0);
+ const directoryBasename = path.basename(directory.getPath());
+ const taggedFile = path.join(directoryBasename, 'tagged.js');
+ expect(symbolsView.selectListView.refs.loadingMessage).toBeUndefined();
+ expect(document.body.contains(symbolsView.element)).toBe(true);
+ expect(symbolsView.element.querySelectorAll('li').length).toBe(4);
+ expect(symbolsView.element.querySelector('li:first-child .primary-line')).toHaveText('callMeMaybe');
+ expect(symbolsView.element.querySelector('li:first-child .secondary-line')).toHaveText(taggedFile);
+ expect(symbolsView.element.querySelector('li:last-child .primary-line')).toHaveText('thisIsCrazy');
+ expect(symbolsView.element.querySelector('li:last-child .secondary-line')).toHaveText(taggedFile);
+ atom.commands.dispatch(getWorkspaceView(), 'symbols-view:toggle-project-symbols');
+ fs.removeSync(directory.resolve('tags'));
+
+ await conditionPromise(() => symbolsView.reloadTags);
+ atom.commands.dispatch(getWorkspaceView(), 'symbols-view:toggle-project-symbols');
+
+ await conditionPromise(() => symbolsView.selectListView.refs.loadingMessage);
+ await conditionPromise(() => symbolsView.element.querySelectorAll('li').length === 0);
+ });
+
+ describe('when there is only one project', () => {
+ beforeEach(async () => atom.project.setPaths([directory.getPath()]));
+
+ it("does not include the root directory's name when displaying the tag's filename", async () => {
+ await atom.workspace.open(directory.resolve('tagged.js'));
+ expect(getWorkspaceView().querySelector('.symbols-view')).toBeNull();
+ atom.commands.dispatch(getWorkspaceView(), 'symbols-view:toggle-project-symbols');
+
+ await activationPromise;
+ symbolsView = atom.workspace.getModalPanels()[0].item;
+ await conditionPromise(() => symbolsView.element.querySelectorAll('li').length > 0);
+ expect(symbolsView.element.querySelector('li:first-child .primary-line')).toHaveText('callMeMaybe');
+ expect(symbolsView.element.querySelector('li:first-child .secondary-line')).toHaveText('tagged.js');
+ });
+ });
+
+ describe('when selecting a tag', () => {
+ describe("when the file doesn't exist", () => {
+ beforeEach(async () => fs.removeSync(directory.resolve('tagged.js')));
+
+ it("doesn't open the editor", async () => {
+ atom.commands.dispatch(getWorkspaceView(), 'symbols-view:toggle-project-symbols');
+
+ await activationPromise;
+
+ symbolsView = atom.workspace.getModalPanels()[0].item;
+
+ await conditionPromise(() => symbolsView.element.querySelectorAll('li').length > 0);
+ spyOn(atom.workspace, 'open').andCallThrough();
+ symbolsView.element.querySelector('li:first-child').click();
+ await conditionPromise(() => symbolsView.selectListView.refs.errorMessage);
+ expect(atom.workspace.open).not.toHaveBeenCalled();
+ expect(symbolsView.selectListView.refs.errorMessage.textContent.length).toBeGreaterThan(0);
+ });
+ });
+ });
+ });
+
+ describe('when useEditorGrammarAsCtagsLanguage is set to true', () => {
+ it("uses the language associated with the editor's grammar", async () => {
+ atom.config.set('symbols-view.useEditorGrammarAsCtagsLanguage', true);
+
+ await atom.packages.activatePackage('language-javascript');
+ await atom.workspace.open('sample.javascript');
+ atom.workspace.getActiveTextEditor().setText('var test = function() {}');
+ await atom.workspace.getActiveTextEditor().save();
+ atom.commands.dispatch(getEditorView(), 'symbols-view:toggle-file-symbols');
+ await activationPromise;
+
+ symbolsView = atom.workspace.getModalPanels()[0].item;
+ await conditionPromise(() => symbolsView.selectListView.refs.emptyMessage);
+ atom.commands.dispatch(getEditorView(), 'symbols-view:toggle-file-symbols');
+
+ atom.workspace.getActiveTextEditor().setGrammar(atom.grammars.grammarForScopeName('source.js'));
+ atom.commands.dispatch(getEditorView(), 'symbols-view:toggle-file-symbols');
+ await conditionPromise(() => symbolsView.element.querySelectorAll('li').length === 1);
+ expect(document.body.contains(symbolsView.element)).toBe(true);
+ expect(symbolsView.element.querySelector('li:first-child .primary-line')).toHaveText('test');
+ expect(symbolsView.element.querySelector('li:first-child .secondary-line')).toHaveText('Line 1');
+ });
+ });
+
+ describe('match highlighting', () => {
+ beforeEach(async () => {
+ await atom.workspace.open(directory.resolve('sample.js'));
+ });
+
+ it('highlights an exact match', async () => {
+ atom.commands.dispatch(getEditorView(), 'symbols-view:toggle-file-symbols');
+
+ await activationPromise;
+ symbolsView = atom.workspace.getModalPanels()[0].item;
+ await conditionPromise(() => symbolsView.element.querySelectorAll('li').length > 0);
+ symbolsView.selectListView.refs.queryEditor.setText('quicksort');
+ await getOrScheduleUpdatePromise();
+ const resultView = symbolsView.element.querySelector('.selected');
+ const matches = resultView.querySelectorAll('.character-match');
+ expect(matches.length).toBe(1);
+ expect(matches[0].textContent).toBe('quicksort');
+ });
+
+ it('highlights a partial match', async () => {
+ atom.commands.dispatch(getEditorView(), 'symbols-view:toggle-file-symbols');
+ await activationPromise;
+ symbolsView = atom.workspace.getModalPanels()[0].item;
+ await conditionPromise(() => symbolsView.element.querySelectorAll('li').length > 0);
+ symbolsView.selectListView.refs.queryEditor.setText('quick');
+ await getOrScheduleUpdatePromise();
+ const resultView = symbolsView.element.querySelector('.selected');
+ const matches = resultView.querySelectorAll('.character-match');
+ expect(matches.length).toBe(1);
+ expect(matches[0].textContent).toBe('quick');
+ });
+
+ it('highlights multiple matches in the symbol name', async () => {
+ atom.commands.dispatch(getEditorView(), 'symbols-view:toggle-file-symbols');
+ await activationPromise;
+ symbolsView = atom.workspace.getModalPanels()[0].item;
+ await conditionPromise(() => symbolsView.element.querySelectorAll('li').length > 0);
+ symbolsView.selectListView.refs.queryEditor.setText('quicort');
+ await getOrScheduleUpdatePromise();
+ const resultView = symbolsView.element.querySelector('.selected');
+ const matches = resultView.querySelectorAll('.character-match');
+ expect(matches.length).toBe(2);
+ expect(matches[0].textContent).toBe('quic');
+ expect(matches[1].textContent).toBe('ort');
+ });
+ });
+
+ describe('quickjump to symbol', () => {
+ beforeEach(async () => {
+ await atom.workspace.open(directory.resolve('sample.js'));
+ });
+
+ it('jumps to the selected function', async () => {
+ expect(atom.workspace.getActiveTextEditor().getCursorBufferPosition()).toEqual([0, 0]);
+ atom.commands.dispatch(getEditorView(), 'symbols-view:toggle-file-symbols');
+ await activationPromise;
+ symbolsView = atom.workspace.getModalPanels()[0].item;
+ await conditionPromise(() => symbolsView.element.querySelectorAll('li').length > 0);
+ symbolsView.selectListView.selectNext();
+ expect(atom.workspace.getActiveTextEditor().getCursorBufferPosition()).toEqual([1, 2]);
+ });
+
+ it('restores previous editor state on cancel', async () => {
+ const bufferRanges = [{start: {row: 0, column: 0}, end: {row: 0, column: 3}}];
+ atom.workspace.getActiveTextEditor().setSelectedBufferRanges(bufferRanges);
+ atom.commands.dispatch(getEditorView(), 'symbols-view:toggle-file-symbols');
+
+ await activationPromise;
+ symbolsView = atom.workspace.getModalPanels()[0].item;
+ await conditionPromise(() => symbolsView.element.querySelectorAll('li').length > 0);
+
+ symbolsView.selectListView.selectNext();
+ expect(atom.workspace.getActiveTextEditor().getCursorBufferPosition()).toEqual([1, 2]);
+ await symbolsView.cancel();
+ expect(atom.workspace.getActiveTextEditor().getSelectedBufferRanges()).toEqual(bufferRanges);
+ });
+ });
+
+ describe('when quickJumpToSymbol is set to false', async () => {
+ beforeEach(async () => {
+ atom.config.set('symbols-view.quickJumpToFileSymbol', false);
+ await atom.workspace.open(directory.resolve('sample.js'));
+ });
+
+ it("won't jumps to the selected function", async () => {
+ expect(atom.workspace.getActiveTextEditor().getCursorBufferPosition()).toEqual([0, 0]);
+ atom.commands.dispatch(getEditorView(), 'symbols-view:toggle-file-symbols');
+
+ await activationPromise;
+ symbolsView = atom.workspace.getModalPanels()[0].item;
+ await conditionPromise(() => symbolsView.element.querySelectorAll('li').length > 0);
+ symbolsView.selectListView.selectNext();
+ expect(atom.workspace.getActiveTextEditor().getCursorBufferPosition()).toEqual([0, 0]);
+ });
+ });
+});
+
+function getOrScheduleUpdatePromise () {
+ return new Promise((resolve) => etch.getScheduler().updateDocument(resolve))
+}
diff --git a/packages/symbols-view/styles/symbols-view.less b/packages/symbols-view/styles/symbols-view.less
new file mode 100644
index 000000000..63262cb5d
--- /dev/null
+++ b/packages/symbols-view/styles/symbols-view.less
@@ -0,0 +1,7 @@
+@import "ui-variables";
+
+// Highlight matched text
+.symbols-view .list-group .character-match {
+ color: @text-color-highlight;
+ font-weight: bold;
+}
diff --git a/packages/symbols-view/vendor/ctags-darwin b/packages/symbols-view/vendor/ctags-darwin
new file mode 100755
index 000000000..86576c957
Binary files /dev/null and b/packages/symbols-view/vendor/ctags-darwin differ
diff --git a/packages/symbols-view/vendor/ctags-linux b/packages/symbols-view/vendor/ctags-linux
new file mode 100755
index 000000000..0e229e3ef
Binary files /dev/null and b/packages/symbols-view/vendor/ctags-linux differ
diff --git a/packages/symbols-view/vendor/ctags-win32.exe b/packages/symbols-view/vendor/ctags-win32.exe
new file mode 100644
index 000000000..b688c2936
Binary files /dev/null and b/packages/symbols-view/vendor/ctags-win32.exe differ
diff --git a/yarn.lock b/yarn.lock
index baa4933c5..52a0388cf 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -9087,9 +9087,8 @@ sylvester@^0.0.12:
resolved "https://registry.yarnpkg.com/sylvester/-/sylvester-0.0.12.tgz#5a884415cd2d002c57e7a3aac99462a75ce9fdb4"
integrity sha512-SzRP5LQ6Ts2G5NyAa/jg16s8e3R7rfdFjizy1zeoecYWw+nGL+YA1xZvW/+iJmidBGSdLkuvdwTYEyJEb+EiUw==
-"symbols-view@https://codeload.github.com/atom/symbols-view/legacy.tar.gz/refs/tags/v0.118.4":
+"symbols-view@file:./packages/symbols-view":
version "0.118.4"
- resolved "https://codeload.github.com/atom/symbols-view/legacy.tar.gz/refs/tags/v0.118.4#cd1b515d4a3d720402b85301ea8e4d6c8815aaf2"
dependencies:
async "^0.2.6"
atom-select-list "^0.7.0"