Compare commits
107 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5781ac6bbd | |||
| a51bc4427a | |||
| 80854584bb | |||
| a27b882493 | |||
| ba6f957692 | |||
| ec0e1bf26f | |||
| e4df298bb4 | |||
| 804d21e31d | |||
| 6d33687866 | |||
| 21bb1efb46 | |||
| 9d0986f1ca | |||
| fd483f397f | |||
| 09364850ee | |||
| 4d3a8bad4c | |||
| cc39b0aa41 | |||
| 6fc3b4be75 | |||
| af6d690fc8 | |||
| eea5152444 | |||
| 1ca38b625b | |||
| f964407c47 | |||
| 3be2e76ec0 | |||
| f9a9b90ed7 | |||
| 1f2917ac22 | |||
| fe1a8569f6 | |||
| 33e8d4f328 | |||
| e183260d0a | |||
| b4023942b4 | |||
| c10c24d90d | |||
| 915f63cac4 | |||
| 5c30ff4d3e | |||
| 3269f02ba7 | |||
| e5c2e3b3eb | |||
| 77f4aee0af | |||
| 868cbdfc7b | |||
| a650c0eab8 | |||
| a7dc8d8c6f | |||
| 355db16d2c | |||
| c54ce41eb7 | |||
| afb7d4c9d1 | |||
| b55cdde9da | |||
| 93cbc6c770 | |||
| 3b1b4a0a96 | |||
| 10b45cb54d | |||
| 9d289e571b | |||
| cce871c30e | |||
| c2b605a90f | |||
| 09149592b5 | |||
| e7410e551b | |||
| 9d77bc4192 | |||
| 537fa0c423 | |||
| c78dbc8bc1 | |||
| 249eed5c2c | |||
| 55eb3b24f7 | |||
| 508c255d0f | |||
| 9f8a90c0ac | |||
| 861dc935cb | |||
| 96ef8cacea | |||
| 5f3ecc8713 | |||
| 8b8ef0eb46 | |||
| 2dbea54c84 | |||
| a776d9fb6f | |||
| 57b7bbff5a | |||
| a832b0ed54 | |||
| 3ec75b84ae | |||
| b932763080 | |||
| 374f8f2f69 | |||
| 226c253d5a | |||
| c78a9f7950 | |||
| 7264510ab2 | |||
| 3458ec6511 | |||
| 2c80db6678 | |||
| 439aa6e4f5 | |||
| adf544dca9 | |||
| 0965269ee9 | |||
| 19d370c4e9 | |||
| cee0f8b652 | |||
| 37664d3487 | |||
| 5a78015d81 | |||
| 7250962ba3 | |||
| 442120bfdb | |||
| de624d1e54 | |||
| 523029cc45 | |||
| 934affe419 | |||
| 55b9af1589 | |||
| 16dd7e46ef | |||
| 851c77d8f2 | |||
| ee55b74898 | |||
| 13fc1e5c66 | |||
| 87112c2942 | |||
| 2664fdca30 | |||
| e05f523145 | |||
| 1148d29439 | |||
| 7ba52978d1 | |||
| 138a9fee43 | |||
| 1d522eaf0d | |||
| b5c5da64c9 | |||
| 8466425836 | |||
| b774ee5cd0 | |||
| 7e2e0e926b | |||
| 30f673c63c | |||
| bb5be728e3 | |||
| 0be5d1c657 | |||
| d143e6be06 | |||
| e65a78a5f5 | |||
| 4f443a3c62 | |||
| ff82ddea97 | |||
| 08dd36e1b0 |
@@ -3,6 +3,7 @@ rvm:
|
|||||||
- 2.0.0
|
- 2.0.0
|
||||||
- 2.1.0
|
- 2.1.0
|
||||||
- 2.1.1
|
- 2.1.1
|
||||||
|
- jruby-19mode
|
||||||
before_install:
|
before_install:
|
||||||
- sudo apt-get update
|
- sudo apt-get update
|
||||||
- sudo apt-get install libicu-dev
|
- sudo apt-get install libicu-dev
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
source 'https://rubygems.org'
|
source 'https://rubygems.org'
|
||||||
|
|
||||||
gemspec
|
gemspec
|
||||||
gem 'rake', '~> 10.2.2'
|
gem 'rake', '~> 10.4'
|
||||||
|
|||||||
+18
@@ -1,3 +1,21 @@
|
|||||||
|
# 3.1.1 /2014-12-04
|
||||||
|
|
||||||
|
* Security fix for [remote code execution issue](https://github.com/gollum/gollum/issues/913). Please update!
|
||||||
|
|
||||||
|
# 3.1 / 2014-11-28
|
||||||
|
|
||||||
|
* New features
|
||||||
|
* Drag-and-drop uploading in the editor [@lucas-clemente](https://github.com/lucas-clemente)
|
||||||
|
* Latest changes view [@etienneCharignon](https://github.com/etienneCharignon) (#707)
|
||||||
|
* Option `--no-edit` to disable editing from the web interface [@bambycha](https://github.com/bambycha) (#879)
|
||||||
|
* Option `--mathjax-config` to specify custom mathjax configuration [@hardywu](https://github.com/hardywu) (#842)
|
||||||
|
* Major enhancements
|
||||||
|
* Made the Gollum theme responsive [@rtrvrtg](https://github.com/rtrvrtg) (#831)
|
||||||
|
* Depends on new [gollum-lib](https://github.com/gollum/gollum-lib) `4.0.0`
|
||||||
|
* Allows specifiying [git adapter](https://github.com/gollum/gollum/wiki/Git-adapters) with `--adapter` [@bartkamphorst](https://github.com/bartkamphorst), [@dometto](https://github.com/dometto)
|
||||||
|
* Numerous bugfixes
|
||||||
|
* **NB**: please pass `--h1-title` if you do not want page titles to default to the page's filepath. See [here](https://github.com/gollum/gollum/wiki/Page-titles).
|
||||||
|
|
||||||
# 2.4.11 / 2013-01-08
|
# 2.4.11 / 2013-01-08
|
||||||
|
|
||||||
* Numerous security issues have been fixed. Please update to `2.4.11`
|
* Numerous security issues have been fixed. Please update to `2.4.11`
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ Gollum follows the rules of [Semantic Versioning](http://semver.org/) and uses
|
|||||||
|
|
||||||
## SECURITY
|
## SECURITY
|
||||||
|
|
||||||
Don't enable `--custom-css` or `--custom-js` unless you trust every user who has the ability to edit the wiki.
|
Don't enable `--custom-css`, `--custom-js` or `--mathjax-config` unless you trust every user who has the ability to edit the wiki.
|
||||||
A better solution with more security is being tracked in [#665](https://github.com/gollum/gollum/issues/665).
|
A better solution with more security is being tracked in [#665](https://github.com/gollum/gollum/issues/665).
|
||||||
|
|
||||||
## INSTALLATION
|
## INSTALLATION
|
||||||
@@ -39,6 +39,7 @@ The best way to install Gollum is with RubyGems:
|
|||||||
```bash
|
```bash
|
||||||
$ [sudo] gem install gollum
|
$ [sudo] gem install gollum
|
||||||
```
|
```
|
||||||
|
You may first need to install some additional [development packages](https://github.com/gollum/gollum/wiki/Installation) for your OS.
|
||||||
|
|
||||||
If you're installing from source, you can use [Bundler][bundler] to pick up all the
|
If you're installing from source, you can use [Bundler][bundler] to pick up all the
|
||||||
gems:
|
gems:
|
||||||
@@ -51,15 +52,15 @@ In order to use the various formats that Gollum supports, you will need to
|
|||||||
separately install the necessary dependencies for each format. You only need
|
separately install the necessary dependencies for each format. You only need
|
||||||
to install the dependencies for the formats that you plan to use.
|
to install the dependencies for the formats that you plan to use.
|
||||||
|
|
||||||
* [ASCIIDoc](http://www.methods.co.nz/asciidoc/) -- `brew install asciidoc` on mac or `apt-get install -y asciidoc` on Ubuntu
|
* [AsciiDoc](http://asciidoctor.org) -- `gem install asciidoctor`
|
||||||
* [Creole](http://wikicreole.org/) -- `gem install creole`
|
* [Creole](http://www.wikicreole.org/) -- `gem install creole`
|
||||||
* [Markdown](http://daringfireball.net/projects/markdown/) -- `gem install redcarpet`
|
* [Markdown](http://daringfireball.net/projects/markdown/) -- `gem install redcarpet`
|
||||||
* [GitHub Flavored Markdown](https://help.github.com/articles/github-flavored-markdown) -- `gem install github-markdown`
|
* [GitHub Flavored Markdown](https://help.github.com/articles/github-flavored-markdown) -- `gem install github-markdown`
|
||||||
* [Org](http://orgmode.org/) -- `gem install org-ruby`
|
* [Org](http://orgmode.org/) -- `gem install org-ruby`
|
||||||
* [Pod](http://search.cpan.org/dist/perl/pod/perlpod.pod) -- `Pod::Simple::HTML` comes with Perl >= 5.10. Lower versions should install Pod::Simple from CPAN.
|
* [Pod](http://search.cpan.org/dist/perl/pod/perlpod.pod) -- `Pod::Simple::HTML` comes with Perl >= 5.10. Lower versions should install Pod::Simple from CPAN.
|
||||||
* [RDoc](http://rdoc.sourceforge.net/)
|
* [RDoc](http://rdoc.sourceforge.net/)
|
||||||
* [ReStructuredText](http://docutils.sourceforge.net/rst.html) -- `easy_install docutils`
|
* [ReStructuredText](http://docutils.sourceforge.net/rst.html) -- `easy_install docutils`
|
||||||
* [Textile](http://www.textism.com/tools/textile/) -- `gem install RedCloth`
|
* [Textile](http://en.wikipedia.org/wiki/Textile_(markup_language)) -- `gem install RedCloth`
|
||||||
* [MediaWiki](http://www.mediawiki.org/wiki/Help:Formatting) -- `gem install wikicloth`
|
* [MediaWiki](http://www.mediawiki.org/wiki/Help:Formatting) -- `gem install wikicloth`
|
||||||
|
|
||||||
[bundler]: http://gembundler.com/
|
[bundler]: http://gembundler.com/
|
||||||
@@ -98,32 +99,35 @@ Options:
|
|||||||
--port [PORT] Bind port (default 4567).
|
--port [PORT] Bind port (default 4567).
|
||||||
--host [HOST] Hostname or IP address to listen on (default 0.0.0.0).
|
--host [HOST] Hostname or IP address to listen on (default 0.0.0.0).
|
||||||
--version Display current version.
|
--version Display current version.
|
||||||
--config [CONFIG] Path to additional configuration file
|
--config [CONFIG] Path to additional configuration file.
|
||||||
|
--adapter [ADAPTER] Git adapter to use in the backend. Defaults to grit.
|
||||||
--irb Start an irb process with gollum loaded for the current wiki.
|
--irb Start an irb process with gollum loaded for the current wiki.
|
||||||
--css Inject custom css. Uses custom.css from root repository
|
--css Inject custom css. Uses custom.css from root repository.
|
||||||
--js Inject custom js. Uses custom.js from root repository
|
--js Inject custom js. Uses custom.js from root repository.
|
||||||
--template-dir [PATH] Specify custom template directory
|
--template-dir [PATH] Specify custom template directory.
|
||||||
--page-file-dir [PATH] Specify the sub directory for all page files (default: repository root).
|
--page-file-dir [PATH] Specify the sub directory for all page files (default: repository root).
|
||||||
--base-path [PATH] Specify the base path.
|
--base-path [PATH] Specify the base path for the served pages (default: /) Example: --base-path wiki yields the home page accessible at http://localhost:4567/wiki/.
|
||||||
--gollum-path [PATH] Specify the gollum path.
|
--gollum-path [PATH] Specify the path to the git repository to be served.
|
||||||
--ref [REF] Specify the repository ref to use (default: master).
|
--ref [REF] Specify the repository ref to use (default: master).
|
||||||
|
--bare Specify that the repository is bare (only necessary when using the grit adapter).
|
||||||
|
--no-edit Restricts editing capability through frontend.
|
||||||
--no-live-preview Disables livepreview.
|
--no-live-preview Disables livepreview.
|
||||||
--live-preview Enables livepreview.
|
--live-preview Enables livepreview.
|
||||||
--allow-uploads Allows file uploads.
|
--allow-uploads [MODE] Allows file uploads. Modes: dir (default, store all uploads in the same directory), page (store each upload at the same location as the page).
|
||||||
--mathjax Enables mathjax.
|
--mathjax Enables mathjax for rendering mathematical equations. Uses the TeX-AMS-MML_HTMLorMML config with the autoload-all extension by default.
|
||||||
|
--mathjax-config [SOURCE] Inject custom mathjax config file. Uses mathjax.config.js from root repository by default.
|
||||||
--user-icons [SOURCE] Set the history user icons. Valid values: gravatar, identicon, none. Default: none.
|
--user-icons [SOURCE] Set the history user icons. Valid values: gravatar, identicon, none. Default: none.
|
||||||
--show-all Shows all files in file view. By default only valid pages are shown.
|
--show-all Shows all files in file view. By default only valid pages are shown.
|
||||||
--collapse-tree Collapse file view tree. By default, expanded tree is shown.
|
--collapse-tree Collapse file view tree. By default, expanded tree is shown.
|
||||||
--h1-title Sets page title to value of first h1
|
--h1-title Sets page title to value of first h1.
|
||||||
```
|
```
|
||||||
|
|
||||||
Note that the gollum server will not run on Windows because of [an issue](https://github.com/rtomayko/posix-spawn/issues/9) with posix-spawn (which is used by Grit).
|
Note that the gollum server will not run on Windows because of [an issue](https://github.com/rtomayko/posix-spawn/issues/9) with posix-spawn (which is used by Grit).
|
||||||
|
|
||||||
### RACK
|
### RACK
|
||||||
|
|
||||||
You can also run gollum with any rack-compatible server by placing this config.ru
|
You can also run gollum with any rack-compatible server by placing configuring a config.ru
|
||||||
file inside your wiki repository. This allows you to utilize any Rack middleware
|
file. This allows you to utilize any Rack middleware like Rack::Auth, OmniAuth, etc. See below for an example of a `config.ru`. You can define all the [options available on the command line](#running) by configuring the app's `:wiki_options` hash. See [here](https://github.com/gollum/gollum/wiki/Using-Gollum-with-Rack) for the names of the options corresponding to the command line switches.
|
||||||
like Rack::Auth, OmniAuth, etc.
|
|
||||||
|
|
||||||
```ruby
|
```ruby
|
||||||
#!/usr/bin/env ruby
|
#!/usr/bin/env ruby
|
||||||
|
|||||||
+21
-4
@@ -22,6 +22,7 @@ options = { 'port' => 4567, 'bind' => '0.0.0.0' }
|
|||||||
wiki_options = {
|
wiki_options = {
|
||||||
:live_preview => false,
|
:live_preview => false,
|
||||||
:allow_uploads => false,
|
:allow_uploads => false,
|
||||||
|
:allow_editing => true,
|
||||||
}
|
}
|
||||||
|
|
||||||
opts = OptionParser.new do |opts|
|
opts = OptionParser.new do |opts|
|
||||||
@@ -44,6 +45,10 @@ opts = OptionParser.new do |opts|
|
|||||||
options['config'] = config
|
options['config'] = config
|
||||||
end
|
end
|
||||||
|
|
||||||
|
opts.on("--adapter [ADAPTER]", "Git adapter to use in the backend. Defaults to grit.") do |adapter|
|
||||||
|
Gollum::GIT_ADAPTER = adapter
|
||||||
|
end
|
||||||
|
|
||||||
opts.on("--irb", "Start an irb process with gollum loaded for the current wiki.") do
|
opts.on("--irb", "Start an irb process with gollum loaded for the current wiki.") do
|
||||||
options['irb'] = true
|
options['irb'] = true
|
||||||
end
|
end
|
||||||
@@ -64,11 +69,11 @@ opts = OptionParser.new do |opts|
|
|||||||
wiki_options[:page_file_dir] = path
|
wiki_options[:page_file_dir] = path
|
||||||
end
|
end
|
||||||
|
|
||||||
opts.on("--base-path [PATH]", "Specify the base path.") do |path|
|
opts.on("--base-path [PATH]", "Specify the base path for the served pages (default: /) Example: --base-path wiki yields the home page accessible at http://localhost:4567/wiki/.") do |path|
|
||||||
wiki_options[:base_path] = path
|
wiki_options[:base_path] = path
|
||||||
end
|
end
|
||||||
|
|
||||||
opts.on("--gollum-path [PATH]", "Specify the gollum path.") do |path|
|
opts.on("--gollum-path [PATH]", "Specify the path to the git repository to be served.") do |path|
|
||||||
wiki_options[:gollum_path] = path
|
wiki_options[:gollum_path] = path
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -76,6 +81,14 @@ opts = OptionParser.new do |opts|
|
|||||||
wiki_options[:ref] = ref
|
wiki_options[:ref] = ref
|
||||||
end
|
end
|
||||||
|
|
||||||
|
opts.on("--bare", "Specify that the repository is bare (only necessary when using the grit adapter).") do
|
||||||
|
wiki_options[:repo_is_bare] = true
|
||||||
|
end
|
||||||
|
|
||||||
|
opts.on("--no-edit", "Restricts editing capability through frontend.") do
|
||||||
|
wiki_options[:allow_editing] = false
|
||||||
|
end
|
||||||
|
|
||||||
opts.on("--no-live-preview", "Disables livepreview.") do
|
opts.on("--no-live-preview", "Disables livepreview.") do
|
||||||
wiki_options[:live_preview] = false
|
wiki_options[:live_preview] = false
|
||||||
end
|
end
|
||||||
@@ -89,10 +102,14 @@ opts = OptionParser.new do |opts|
|
|||||||
wiki_options[:per_page_uploads] = true if mode == :page
|
wiki_options[:per_page_uploads] = true if mode == :page
|
||||||
end
|
end
|
||||||
|
|
||||||
opts.on("--mathjax", "Enables mathjax.") do
|
opts.on("--mathjax", "Enables mathjax for rendering mathematical equations. Uses the TeX-AMS-MML_HTMLorMML config with the autoload-all extension by default.") do
|
||||||
wiki_options[:mathjax] = true
|
wiki_options[:mathjax] = true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
opts.on("--mathjax-config [SOURCE]", "Inject custom mathjax config file. Uses mathjax.config.js from root repository by default") do |source|
|
||||||
|
wiki_options[:mathjax_config] = source || 'mathjax.config.js'
|
||||||
|
end
|
||||||
|
|
||||||
opts.on("--user-icons [SOURCE]", "Set the history user icons. Valid values: gravatar, identicon, none. Default: none.") do |source|
|
opts.on("--user-icons [SOURCE]", "Set the history user icons. Valid values: gravatar, identicon, none. Default: none.") do |source|
|
||||||
wiki_options[:user_icons] = source
|
wiki_options[:user_icons] = source
|
||||||
end
|
end
|
||||||
@@ -211,4 +228,4 @@ else
|
|||||||
# Rack::Handler does not work with Ctrl + C. Use Rack::Server instead.
|
# Rack::Handler does not work with Ctrl + C. Use Rack::Server instead.
|
||||||
Rack::Server.new(:app => MapGollum.new(base_path), :Port => options['port'], :Host => options['bind']).start
|
Rack::Server.new(:app => MapGollum.new(base_path), :Port => options['port'], :Host => options['bind']).start
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Gollum wiki server
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User=%i
|
||||||
|
ExecStart=/usr/bin/gollum
|
||||||
|
Restart=on-abort
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
+567
-31
@@ -5,8 +5,8 @@ Gem::Specification.new do |s|
|
|||||||
s.required_ruby_version = '>= 1.9'
|
s.required_ruby_version = '>= 1.9'
|
||||||
|
|
||||||
s.name = 'gollum'
|
s.name = 'gollum'
|
||||||
s.version = '3.0.0'
|
s.version = '4.0.0'
|
||||||
s.date = '2014-04-05'
|
s.date = '2015-04-11'
|
||||||
s.rubyforge_project = 'gollum'
|
s.rubyforge_project = 'gollum'
|
||||||
s.license = 'MIT'
|
s.license = 'MIT'
|
||||||
|
|
||||||
@@ -24,8 +24,8 @@ Gem::Specification.new do |s|
|
|||||||
s.rdoc_options = ['--charset=UTF-8']
|
s.rdoc_options = ['--charset=UTF-8']
|
||||||
s.extra_rdoc_files = %w[README.md LICENSE]
|
s.extra_rdoc_files = %w[README.md LICENSE]
|
||||||
|
|
||||||
s.add_dependency 'gollum-lib', '~> 3.0'
|
s.add_dependency 'gollum-lib', '~> 4.0', '>= 4.0.1'
|
||||||
s.add_dependency 'github-markdown', '~> 0.6.5'
|
s.add_dependency 'kramdown', '~> 1.6.0'
|
||||||
s.add_dependency 'sinatra', '~> 1.4', '>= 1.4.4'
|
s.add_dependency 'sinatra', '~> 1.4', '>= 1.4.4'
|
||||||
s.add_dependency 'mustache', ['>= 0.99.5', '< 1.0.0']
|
s.add_dependency 'mustache', ['>= 0.99.5', '< 1.0.0']
|
||||||
s.add_dependency 'useragent', '~> 0.10.0'
|
s.add_dependency 'useragent', '~> 0.10.0'
|
||||||
@@ -45,6 +45,9 @@ Gem::Specification.new do |s|
|
|||||||
Rakefile
|
Rakefile
|
||||||
bin/gollum
|
bin/gollum
|
||||||
config.rb
|
config.rb
|
||||||
|
contrib/openrc/conf.d/gollum
|
||||||
|
contrib/openrc/init.d/gollum
|
||||||
|
contrib/systemd/gollum@.service
|
||||||
docs/sanitization.md
|
docs/sanitization.md
|
||||||
gollum.gemspec
|
gollum.gemspec
|
||||||
lib/gollum.rb
|
lib/gollum.rb
|
||||||
@@ -95,16 +98,21 @@ Gem::Specification.new do |s|
|
|||||||
lib/gollum/public/gollum/livepreview/images/lr_24.png
|
lib/gollum/public/gollum/livepreview/images/lr_24.png
|
||||||
lib/gollum/public/gollum/livepreview/images/save_24.png
|
lib/gollum/public/gollum/livepreview/images/save_24.png
|
||||||
lib/gollum/public/gollum/livepreview/images/savecomment_24.png
|
lib/gollum/public/gollum/livepreview/images/savecomment_24.png
|
||||||
lib/gollum/public/gollum/livepreview/index.html
|
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/ace.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/ace.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/anchor.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/anchor.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/anchor_test.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/anchor_test.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/autocomplete.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/autocomplete/popup.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/autocomplete/text_completer.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/autocomplete/util.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/background_tokenizer.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/background_tokenizer.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/background_tokenizer_test.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/background_tokenizer_test.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/commands/command_manager.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/commands/command_manager.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/commands/command_manager_test.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/commands/command_manager_test.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/commands/default_commands.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/commands/default_commands.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/commands/incremental_search_commands.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/commands/multi_select_commands.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/commands/multi_select_commands.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/commands/occur_commands.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/config.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/config.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/config_test.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/config_test.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/css/codefolding-fold-button-states.png
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/css/codefolding-fold-button-states.png
|
||||||
@@ -123,28 +131,57 @@ Gem::Specification.new do |s|
|
|||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/editor_highlight_selected_word_test.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/editor_highlight_selected_word_test.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/editor_navigation_test.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/editor_navigation_test.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/editor_text_edit_test.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/editor_text_edit_test.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/ext/beautify.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/ext/beautify/php_rules.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/ext/chromevox.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/ext/elastic_tabstops_lite.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/ext/emmet.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/ext/error_marker.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/ext/keybinding_menu.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/ext/language_tools.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/ext/linking.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/ext/menu_tools/add_editor_menu_options.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/ext/menu_tools/element_generator.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/ext/menu_tools/generate_settings_menu.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/ext/menu_tools/get_editor_keyboard_shortcuts.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/ext/menu_tools/get_set_functions.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/ext/menu_tools/overlay_page.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/ext/menu_tools/settings_menu.css
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/ext/modelist.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/ext/old_ie.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/ext/old_ie_test.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/ext/searchbox.css
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/ext/searchbox.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/ext/settings_menu.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/ext/spellcheck.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/ext/split.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/ext/static.css
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/ext/static.css
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/ext/static_highlight.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/ext/static_highlight.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/ext/static_highlight_test.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/ext/static_highlight_test.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/ext/statusbar.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/ext/textarea.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/ext/textarea.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/ext/themelist.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/ext/whitespace.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/ext/whitespace_test.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/incremental_search.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/incremental_search_test.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/keyboard/emacs.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/keyboard/emacs.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/keyboard/emacs_test.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/keyboard/hash_handler.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/keyboard/hash_handler.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/keyboard/keybinding.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/keyboard/keybinding.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/keyboard/keybinding_test.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/keyboard/state_handler.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/keyboard/state_handler.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/keyboard/textarea.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/keyboard/textinput.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/keyboard/textinput.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/keyboard/vim.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/keyboard/vim.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/keyboard/vim/commands.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/keyboard/vim_test.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/keyboard/vim/maps/aliases.js
|
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/keyboard/vim/maps/motions.js
|
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/keyboard/vim/maps/operators.js
|
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/keyboard/vim/maps/util.js
|
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/keyboard/vim/registers.js
|
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/layer/cursor.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/layer/cursor.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/layer/font_metrics.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/layer/gutter.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/layer/gutter.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/layer/marker.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/layer/marker.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/layer/text.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/layer/text.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/layer/text_test.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/layer/text_test.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/lib/browser_focus.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/lib/app_config.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/lib/dom.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/lib/dom.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/lib/es5-shim.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/lib/es5-shim.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/lib/event.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/lib/event.js
|
||||||
@@ -157,56 +194,158 @@ Gem::Specification.new do |s|
|
|||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/lib/oop.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/lib/oop.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/lib/regexp.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/lib/regexp.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/lib/useragent.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/lib/useragent.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/line_widgets.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/Readme.md
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/highlight_rules_test.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/package.json
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/package.json
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/test_highlight_rules.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/text_asciidoc.txt
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/text_coffee.txt
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/text_curly.txt
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/text_html.txt
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/text_javascript.txt
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/text_javascript.txt
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/text_livescript.txt
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/text_lucene.txt
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/text_markdown.txt
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/text_php.txt
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/text_ruby.txt
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/text_xml.txt
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_abap.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_abc.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_actionscript.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_ada.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_asciidoc.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_assembly_x86.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_autohotkey.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_batchfile.json
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_c9search.json
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_c9search.json
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_c_cpp.json
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_c_cpp.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_cirru.json
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_clojure.json
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_clojure.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_cobol.json
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_coffee.json
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_coffee.json
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_coldfusion.json
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_coldfusion.json
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_csharp.json
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_csharp.json
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_css.json
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_css.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_curly.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_d.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_dart.json
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_diff.json
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_diff.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_dot.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_eiffel.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_ejs.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_elixir.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_elm.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_erlang.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_forth.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_ftl.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_gcode.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_gherkin.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_gitignore.json
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_glsl.json
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_glsl.json
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_golang.json
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_golang.json
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_groovy.json
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_groovy.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_haml.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_handlebars.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_haskell.json
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_haxe.json
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_haxe.json
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_html.json
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_html.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_html_ruby.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_ini.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_io.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_jack.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_jade.json
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_java.json
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_java.json
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_javascript.json
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_javascript.json
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_json.json
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_json.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_jsoniq.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_jsp.json
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_jsx.json
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_jsx.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_julia.json
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_latex.json
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_latex.json
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_less.json
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_less.json
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_liquid.json
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_liquid.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_lisp.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_livescript.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_logiql.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_lsl.json
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_lua.json
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_lua.json
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_luapage.json
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_luapage.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_lucene.json
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_markdown.json
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_markdown.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_mask.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_matlab.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_mel.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_mushcode.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_mysql.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_nix.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_objectivec.json
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_ocaml.json
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_ocaml.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_pascal.json
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_perl.json
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_perl.json
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_pgsql.json
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_pgsql.json
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_php.json
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_php.json
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_powershell.json
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_powershell.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_prolog.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_properties.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_protobuf.json
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_python.json
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_python.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_r.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_rdoc.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_rhtml.json
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_ruby.json
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_ruby.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_rust.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_sass.json
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_scad.json
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_scad.json
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_scala.json
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_scala.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_scheme.json
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_scss.json
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_scss.json
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_sh.json
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_sh.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_sjs.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_smarty.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_snippets.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_soy_template.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_space.json
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_sql.json
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_sql.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_stylus.json
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_svg.json
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_svg.json
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_tcl.json
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_tcl.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_tex.json
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_text.json
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_text.json
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_textile.json
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_textile.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_toml.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_twig.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_typescript.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_vala.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_vbscript.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_velocity.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_verilog.json
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_vhdl.json
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_xml.json
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_xml.json
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_xquery.json
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_xquery.json
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_yaml.json
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/_test/tokens_yaml.json
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/abap.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/abap.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/abap_highlight_rules.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/abap_highlight_rules.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/abc.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/abc_highlight_rules.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/actionscript.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/actionscript_highlight_rules.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/ada.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/ada_highlight_rules.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/apache_conf.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/apache_conf_highlight_rules.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/applescript.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/applescript_highlight_rules.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/asciidoc.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/asciidoc.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/asciidoc_highlight_rules.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/asciidoc_highlight_rules.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/assembly_x86.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/assembly_x86_highlight_rules.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/autohotkey.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/autohotkey_highlight_rules.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/batchfile.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/batchfile_highlight_rules.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/behaviour.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/behaviour.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/behaviour/behaviour_test.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/behaviour/css.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/behaviour/cstyle.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/behaviour/cstyle.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/behaviour/html.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/behaviour/html.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/behaviour/xml.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/behaviour/xml.js
|
||||||
@@ -215,8 +354,12 @@ Gem::Specification.new do |s|
|
|||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/c9search_highlight_rules.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/c9search_highlight_rules.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/c_cpp.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/c_cpp.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/c_cpp_highlight_rules.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/c_cpp_highlight_rules.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/cirru.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/cirru_highlight_rules.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/clojure.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/clojure.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/clojure_highlight_rules.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/clojure_highlight_rules.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/cobol.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/cobol_highlight_rules.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/coffee.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/coffee.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/coffee/coffee-script.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/coffee/coffee-script.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/coffee/helpers.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/coffee/helpers.js
|
||||||
@@ -227,7 +370,6 @@ Gem::Specification.new do |s|
|
|||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/coffee/rewriter.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/coffee/rewriter.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/coffee/scope.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/coffee/scope.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/coffee_highlight_rules.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/coffee_highlight_rules.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/coffee_highlight_rules_test.js
|
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/coffee_worker.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/coffee_worker.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/coldfusion.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/coldfusion.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/coldfusion_highlight_rules.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/coldfusion_highlight_rules.js
|
||||||
@@ -237,33 +379,63 @@ Gem::Specification.new do |s|
|
|||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/css.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/css.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/css/csslint.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/css/csslint.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/css_highlight_rules.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/css_highlight_rules.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/css_highlight_rules_test.js
|
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/css_test.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/css_test.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/css_worker.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/css_worker.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/css_worker_test.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/css_worker_test.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/curly.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/curly_highlight_rules.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/d.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/d_highlight_rules.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/dart.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/dart.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/dart_highlight_rules.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/dart_highlight_rules.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/diff.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/diff.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/diff_highlight_rules.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/diff_highlight_rules.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/django.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/doc_comment_highlight_rules.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/doc_comment_highlight_rules.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/dockerfile.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/dockerfile_highlight_rules.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/dot.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/dot_highlight_rules.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/eiffel.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/eiffel_highlight_rules.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/ejs.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/elixir.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/elixir_highlight_rules.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/elm.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/elm_highlight_rules.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/erlang.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/erlang_highlight_rules.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/folding/asciidoc.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/folding/asciidoc.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/folding/c9search.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/folding/c9search.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/folding/coffee.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/folding/coffee.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/folding/coffee_test.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/folding/coffee_test.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/folding/csharp.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/folding/cstyle.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/folding/cstyle.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/folding/cstyle_test.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/folding/cstyle_test.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/folding/diff.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/folding/diff.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/folding/fold_mode.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/folding/fold_mode.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/folding/html.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/folding/html.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/folding/html_test.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/folding/html_test.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/folding/ini.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/folding/latex.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/folding/latex.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/folding/lua.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/folding/lua.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/folding/markdown.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/folding/markdown.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/folding/mixed.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/folding/mixed.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/folding/pythonic.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/folding/pythonic.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/folding/pythonic_test.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/folding/pythonic_test.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/folding/velocity.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/folding/xml.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/folding/xml.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/folding/xml_test.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/folding/xml_test.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/forth.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/forth_highlight_rules.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/ftl.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/ftl_highlight_rules.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/gcode.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/gcode_highlight_rules.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/gherkin.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/gherkin_highlight_rules.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/gitignore.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/gitignore_highlight_rules.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/glsl.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/glsl.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/glsl_highlight_rules.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/glsl_highlight_rules.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/golang.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/golang.js
|
||||||
@@ -272,12 +444,26 @@ Gem::Specification.new do |s|
|
|||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/groovy_highlight_rules.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/groovy_highlight_rules.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/haml.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/haml.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/haml_highlight_rules.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/haml_highlight_rules.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/handlebars.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/handlebars_highlight_rules.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/haskell.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/haskell_highlight_rules.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/haxe.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/haxe.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/haxe_highlight_rules.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/haxe_highlight_rules.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/html.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/html.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/html/saxparser.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/html_completions.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/html_highlight_rules.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/html_highlight_rules.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/html_highlight_rules_test.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/html_ruby.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/html_ruby_highlight_rules.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/html_test.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/html_test.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/html_worker.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/ini.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/ini_highlight_rules.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/io.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/io_highlight_rules.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/jack.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/jack_highlight_rules.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/jade.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/jade.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/jade_highlight_rules.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/jade_highlight_rules.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/java.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/java.js
|
||||||
@@ -285,54 +471,89 @@ Gem::Specification.new do |s|
|
|||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/javascript.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/javascript.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/javascript/jshint.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/javascript/jshint.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/javascript_highlight_rules.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/javascript_highlight_rules.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/javascript_highlight_rules_test.js
|
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/javascript_test.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/javascript_test.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/javascript_worker.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/javascript_worker.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/javascript_worker_test.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/javascript_worker_test.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/js_regex_highlight_rules.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/json.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/json.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/json/json_parse.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/json/json_parse.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/json_highlight_rules.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/json_highlight_rules.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/json_worker.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/json_worker.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/json_worker_test.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/json_worker_test.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/jsoniq.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/jsp.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/jsp.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/jsp_highlight_rules.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/jsp_highlight_rules.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/jsx.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/jsx.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/jsx_highlight_rules.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/jsx_highlight_rules.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/julia.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/julia_highlight_rules.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/latex.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/latex.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/latex_highlight_rules.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/latex_highlight_rules.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/less.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/less.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/less_highlight_rules.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/less_highlight_rules.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/liquid.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/liquid.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/liquid_highlight_rules.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/liquid_highlight_rules.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/liquid_highlight_rules_test.js
|
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/lisp.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/lisp.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/lisp_highlight_rules.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/lisp_highlight_rules.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/livescript.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/logiql.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/logiql_highlight_rules.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/logiql_test.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/lsl.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/lsl_highlight_rules.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/lua.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/lua.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/lua/luaparse.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/lua_highlight_rules.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/lua_highlight_rules.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/lua_worker.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/luapage.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/luapage.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/luapage_highlight_rules.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/luapage_highlight_rules.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/lucene.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/lucene.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/lucene_highlight_rules.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/lucene_highlight_rules.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/lucene_highlight_rules_test.js
|
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/makefile.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/makefile.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/makefile_highlight_rules.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/makefile_highlight_rules.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/markdown.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/markdown.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/markdown_highlight_rules.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/markdown_highlight_rules.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/markdown_highlight_rules_test.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/mask.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/mask_highlight_rules.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/matching_brace_outdent.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/matching_brace_outdent.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/matching_parens_outdent.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/matching_parens_outdent.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/matlab.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/matlab_highlight_rules.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/mel.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/mel_highlight_rules.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/mushcode.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/mushcode_highlight_rules.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/mysql.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/mysql_highlight_rules.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/nix.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/nix_highlight_rules.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/objectivec.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/objectivec.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/objectivec_highlight_rules.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/objectivec_highlight_rules.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/ocaml.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/ocaml.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/ocaml_highlight_rules.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/ocaml_highlight_rules.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/pascal.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/pascal_highlight_rules.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/perl.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/perl.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/perl_highlight_rules.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/perl_highlight_rules.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/pgsql.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/pgsql.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/pgsql_highlight_rules.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/pgsql_highlight_rules.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/php.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/php.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/php/php.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/php_highlight_rules.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/php_highlight_rules.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/php_test.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/php_worker.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/plain_text.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/plain_text_test.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/powershell.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/powershell.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/powershell_highlight_rules.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/powershell_highlight_rules.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/praat.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/praat_highlight_rules.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/prolog.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/prolog_highlight_rules.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/properties.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/properties_highlight_rules.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/protobuf.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/protobuf_highlight_rules.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/python.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/python.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/python_highlight_rules.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/python_highlight_rules.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/python_test.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/python_test.js
|
||||||
@@ -344,15 +565,30 @@ Gem::Specification.new do |s|
|
|||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/rhtml_highlight_rules.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/rhtml_highlight_rules.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/ruby.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/ruby.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/ruby_highlight_rules.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/ruby_highlight_rules.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/ruby_highlight_rules_test.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/ruby_test.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/rust.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/rust_highlight_rules.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/sass.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/sass_highlight_rules.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/scad.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/scad.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/scad_highlight_rules.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/scad_highlight_rules.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/scala.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/scala.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/scala_highlight_rules.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/scala_highlight_rules.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/scheme.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/scheme_highlight_rules.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/scss.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/scss.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/scss_highlight_rules.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/scss_highlight_rules.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/sh.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/sh.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/sh_highlight_rules.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/sh_highlight_rules.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/sjs.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/sjs_highlight_rules.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/smarty.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/smarty_highlight_rules.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/snippets.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/soy_template.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/soy_template_highlight_rules.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/space.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/space_highlight_rules.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/sql.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/sql.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/sql_highlight_rules.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/sql_highlight_rules.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/stylus.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/stylus.js
|
||||||
@@ -368,32 +604,50 @@ Gem::Specification.new do |s|
|
|||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/text_test.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/text_test.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/textile.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/textile.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/textile_highlight_rules.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/textile_highlight_rules.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/toml.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/toml_highlight_rules.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/twig.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/twig_highlight_rules.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/typescript.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/typescript.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/typescript_highlight_rules.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/typescript_highlight_rules.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/vala.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/vala_highlight_rules.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/vbscript.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/vbscript_highlight_rules.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/velocity.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/velocity_highlight_rules.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/verilog.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/verilog_highlight_rules.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/vhdl.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/vhdl_highlight_rules.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/xml.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/xml.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/xml/dom-parser.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/xml/dom.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/xml/sax.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/xml_highlight_rules.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/xml_highlight_rules.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/xml_highlight_rules_test.js
|
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/xml_test.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/xml_test.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/xml_util.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/xml_worker.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/xquery.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/xquery.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/xquery/JSONParseTreeHandler.js
|
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/xquery/Readme.md
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/xquery/Readme.md
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/xquery/XQueryParser.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/xquery/jsoniq_lexer.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/xquery/visitors/SyntaxHighlighter.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/xquery/xqlint.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/xquery_highlight_rules.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/xquery/xquery_lexer.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/xquery_worker.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/xquery_worker.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/yaml.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/yaml.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/yaml_highlight_rules.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mode/yaml_highlight_rules.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/model/editor.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/model/editor.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mouse/default_gutter_handler.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mouse/default_gutter_handler.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mouse/default_handlers.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mouse/default_handlers.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mouse/dragdrop.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mouse/dragdrop_handler.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mouse/fold_handler.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mouse/fold_handler.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mouse/mouse_event.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mouse/mouse_event.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mouse/mouse_handler.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mouse/mouse_handler.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mouse/mouse_handler_test.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mouse/multi_select_handler.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/mouse/multi_select_handler.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/multi_select.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/multi_select.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/multi_select_test.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/multi_select_test.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/occur.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/occur_test.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/placeholder.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/placeholder.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/placeholder_test.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/placeholder_test.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/range.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/range.js
|
||||||
@@ -402,12 +656,282 @@ Gem::Specification.new do |s|
|
|||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/range_test.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/range_test.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/renderloop.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/renderloop.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/requirejs/text.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/requirejs/text.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/requirejs/text_build.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/scrollbar.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/scrollbar.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/search.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/search.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/search_highlight.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/search_highlight.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/search_test.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/search_test.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/selection.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/selection.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/selection_test.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/selection_test.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/_.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/_all_modes.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/_all_modes.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/abap.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/abap.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/abc.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/abc.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/actionscript.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/actionscript.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/ada.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/ada.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/all_modes.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/all_modes.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/apache.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/apache_conf.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/apache_conf.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/applescript.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/applescript.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/asciidoc.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/asciidoc.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/assembly_x86.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/assembly_x86.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/autohotkey.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/autohotkey.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/autoit.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/batchfile.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/batchfile.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/c.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/c9search.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/c9search.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/c_cpp.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/c_cpp.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/chef.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/cirru.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/cirru.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/clojure.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/clojure.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/cmake.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/cobol.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/cobol.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/coffee.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/coffee.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/coldfusion.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/coldfusion.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/cs.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/csharp.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/csharp.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/css.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/css.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/curly.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/curly.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/d.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/d.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/dart.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/dart.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/diff.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/diff.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/django.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/django.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/dockerfile.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/dockerfile.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/dot.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/dot.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/dummy.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/dummy_syntax.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/eiffel.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/eiffel.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/ejs.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/ejs.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/elixir.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/elixir.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/elm.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/elm.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/erlang.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/erlang.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/eruby.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/falcon.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/forth.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/forth.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/ftl.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/ftl.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/gcode.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/gcode.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/gherkin.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/gherkin.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/gitignore.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/gitignore.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/glsl.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/glsl.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/go.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/golang.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/golang.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/groovy.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/groovy.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/haml.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/haml.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/handlebars.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/handlebars.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/haskell.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/haskell.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/haxe.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/haxe.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/html.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/html.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/html_ruby.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/html_ruby.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/htmldjango.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/htmltornado.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/ini.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/ini.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/io.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/io.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/jack.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/jack.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/jade.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/jade.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/java.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/java.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/javascript-jquery.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/javascript.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/javascript.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/json.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/json.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/jsoniq.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/jsoniq.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/jsp.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/jsp.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/jsx.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/jsx.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/julia.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/julia.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/latex.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/latex.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/ledger.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/less.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/less.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/liquid.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/liquid.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/lisp.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/lisp.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/livescript.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/livescript.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/logiql.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/logiql.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/lsl.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/lsl.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/lua.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/lua.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/luapage.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/luapage.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/lucene.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/lucene.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/makefile.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/makefile.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/mako.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/markdown.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/markdown.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/matlab.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/matlab.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/mel.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/mel.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/mushcode.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/mushcode.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/mushcode_high_rules.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/mushcode_high_rules.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/mysql.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/mysql.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/nix.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/nix.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/objc.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/objectivec.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/objectivec.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/ocaml.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/ocaml.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/pascal.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/pascal.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/perl.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/perl.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/pgsql.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/pgsql.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/php.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/php.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/plain_text.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/plain_text.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/powershell.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/powershell.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/praat.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/praat.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/prolog.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/prolog.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/properties.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/properties.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/protobuf.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/protobuf.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/python.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/python.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/r.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/r.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/rdoc.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/rdoc.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/rhtml.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/rhtml.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/rst.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/ruby.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/ruby.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/rust.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/rust.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/sass.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/sass.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/scad.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/scad.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/scala.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/scala.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/scheme.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/scheme.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/scss.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/scss.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/sh.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/sh.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/sjs.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/sjs.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/smarty.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/smarty.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/snippets.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/snippets.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/soy_template.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/soy_template.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/space.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/space.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/sql.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/sql.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/stylus.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/stylus.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/svg.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/svg.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/tcl.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/tcl.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/tex.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/tex.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/text.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/text.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/textile.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/textile.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/tmsnippet.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/toml.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/toml.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/twig.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/twig.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/typescript.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/typescript.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/vala.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/vala.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/vbscript.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/vbscript.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/velocity.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/velocity.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/verilog.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/verilog.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/vhdl.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/vhdl.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/xml.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/xml.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/xquery.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/xquery.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/xslt.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/yaml.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets/yaml.snippets
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/snippets_test.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/split.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/split.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/test/all.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/test/all.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/test/all_browser.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/test/all_browser.js
|
||||||
@@ -423,6 +947,8 @@ Gem::Specification.new do |s|
|
|||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/test/tests.html
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/test/tests.html
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/theme/ambiance.css
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/theme/ambiance.css
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/theme/ambiance.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/theme/ambiance.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/theme/chaos.css
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/theme/chaos.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/theme/chrome.css
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/theme/chrome.css
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/theme/chrome.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/theme/chrome.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/theme/clouds.css
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/theme/clouds.css
|
||||||
@@ -443,8 +969,12 @@ Gem::Specification.new do |s|
|
|||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/theme/github.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/theme/github.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/theme/idle_fingers.css
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/theme/idle_fingers.css
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/theme/idle_fingers.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/theme/idle_fingers.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/theme/katzenmilch.css
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/theme/katzenmilch.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/theme/kr_theme.css
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/theme/kr_theme.css
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/theme/kr_theme.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/theme/kr_theme.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/theme/kuroir.css
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/theme/kuroir.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/theme/merbivore.css
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/theme/merbivore.css
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/theme/merbivore.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/theme/merbivore.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/theme/merbivore_soft.css
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/theme/merbivore_soft.css
|
||||||
@@ -459,6 +989,8 @@ Gem::Specification.new do |s|
|
|||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/theme/solarized_dark.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/theme/solarized_dark.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/theme/solarized_light.css
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/theme/solarized_light.css
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/theme/solarized_light.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/theme/solarized_light.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/theme/terminal.css
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/theme/terminal.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/theme/textmate.css
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/theme/textmate.css
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/theme/textmate.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/theme/textmate.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/theme/tomorrow.css
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/theme/tomorrow.css
|
||||||
@@ -481,6 +1013,8 @@ Gem::Specification.new do |s|
|
|||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/token_iterator_test.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/token_iterator_test.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/tokenizer.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/tokenizer.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/tokenizer_dev.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/tokenizer_dev.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/tokenizer_test.js
|
||||||
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/tooltip.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/undomanager.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/undomanager.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/unicode.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/unicode.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/virtual_renderer.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/virtual_renderer.js
|
||||||
@@ -488,7 +1022,7 @@ Gem::Specification.new do |s|
|
|||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/worker/mirror.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/worker/mirror.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/worker/worker.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/worker/worker.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/worker/worker_client.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/worker/worker_client.js
|
||||||
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/worker/worker_sourcemint.js
|
lib/gollum/public/gollum/livepreview/js/ace/lib/ace/worker/worker_test.js
|
||||||
lib/gollum/public/gollum/livepreview/js/jquery.ba-throttle-debounce.min.js
|
lib/gollum/public/gollum/livepreview/js/jquery.ba-throttle-debounce.min.js
|
||||||
lib/gollum/public/gollum/livepreview/js/livepreview.js
|
lib/gollum/public/gollum/livepreview/js/livepreview.js
|
||||||
lib/gollum/public/gollum/livepreview/js/md_sundown.js
|
lib/gollum/public/gollum/livepreview/js/md_sundown.js
|
||||||
@@ -517,7 +1051,9 @@ Gem::Specification.new do |s|
|
|||||||
lib/gollum/templates/history_authors/gravatar.mustache
|
lib/gollum/templates/history_authors/gravatar.mustache
|
||||||
lib/gollum/templates/history_authors/identicon.mustache
|
lib/gollum/templates/history_authors/identicon.mustache
|
||||||
lib/gollum/templates/history_authors/none.mustache
|
lib/gollum/templates/history_authors/none.mustache
|
||||||
|
lib/gollum/templates/latest_changes.mustache
|
||||||
lib/gollum/templates/layout.mustache
|
lib/gollum/templates/layout.mustache
|
||||||
|
lib/gollum/templates/livepreview.mustache
|
||||||
lib/gollum/templates/page.mustache
|
lib/gollum/templates/page.mustache
|
||||||
lib/gollum/templates/pages.mustache
|
lib/gollum/templates/pages.mustache
|
||||||
lib/gollum/templates/search.mustache
|
lib/gollum/templates/search.mustache
|
||||||
@@ -531,15 +1067,15 @@ Gem::Specification.new do |s|
|
|||||||
lib/gollum/views/file_view.rb
|
lib/gollum/views/file_view.rb
|
||||||
lib/gollum/views/has_page.rb
|
lib/gollum/views/has_page.rb
|
||||||
lib/gollum/views/history.rb
|
lib/gollum/views/history.rb
|
||||||
|
lib/gollum/views/latest_changes.rb
|
||||||
lib/gollum/views/layout.rb
|
lib/gollum/views/layout.rb
|
||||||
|
lib/gollum/views/livepreview.rb
|
||||||
lib/gollum/views/page.rb
|
lib/gollum/views/page.rb
|
||||||
lib/gollum/views/pages.rb
|
lib/gollum/views/pages.rb
|
||||||
lib/gollum/views/search.rb
|
lib/gollum/views/search.rb
|
||||||
licenses/css_tree_menu_thecssninja/license.txt
|
licenses/css_tree_menu_thecssninja/license.txt
|
||||||
licenses/licenses.txt
|
licenses/licenses.txt
|
||||||
licenses/unity_asset_pool/COPYRIGHT
|
licenses/unity_asset_pool/COPYRIGHT
|
||||||
openrc/conf.d/gollum
|
|
||||||
openrc/init.d/gollum
|
|
||||||
]
|
]
|
||||||
# = MANIFEST =
|
# = MANIFEST =
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -16,7 +16,7 @@ require File.expand_path('../gollum/uri_encode_component', __FILE__)
|
|||||||
$KCODE = 'U' if RUBY_VERSION[0, 3] == '1.8'
|
$KCODE = 'U' if RUBY_VERSION[0, 3] == '1.8'
|
||||||
|
|
||||||
module Gollum
|
module Gollum
|
||||||
VERSION = '3.0.0'
|
VERSION = '4.0.0'
|
||||||
|
|
||||||
def self.assets_path
|
def self.assets_path
|
||||||
::File.expand_path('gollum/public', ::File.dirname(__FILE__))
|
::File.expand_path('gollum/public', ::File.dirname(__FILE__))
|
||||||
|
|||||||
+64
-17
@@ -20,6 +20,13 @@ Gollum::set_git_max_filesize(190 * 10**6)
|
|||||||
# Fix to_url
|
# Fix to_url
|
||||||
class String
|
class String
|
||||||
alias :upstream_to_url :to_url
|
alias :upstream_to_url :to_url
|
||||||
|
|
||||||
|
if defined?(Gollum::GIT_ADAPTER) && Gollum::GIT_ADAPTER != 'grit'
|
||||||
|
def to_ascii
|
||||||
|
self # Do not transliterate utf-8 url's unless using Grit
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# _Header => header which causes errors
|
# _Header => header which causes errors
|
||||||
def to_url
|
def to_url
|
||||||
return nil if self.nil?
|
return nil if self.nil?
|
||||||
@@ -42,7 +49,7 @@ module Precious
|
|||||||
class App < Sinatra::Base
|
class App < Sinatra::Base
|
||||||
register Mustache::Sinatra
|
register Mustache::Sinatra
|
||||||
include Precious::Helpers
|
include Precious::Helpers
|
||||||
|
|
||||||
dir = File.dirname(File.expand_path(__FILE__))
|
dir = File.dirname(File.expand_path(__FILE__))
|
||||||
|
|
||||||
# Detect unsupported browsers.
|
# Detect unsupported browsers.
|
||||||
@@ -86,11 +93,16 @@ module Precious
|
|||||||
end
|
end
|
||||||
|
|
||||||
before do
|
before do
|
||||||
|
settings.wiki_options[:allow_editing] = settings.wiki_options.fetch(:allow_editing, true)
|
||||||
|
@allow_editing = settings.wiki_options[:allow_editing]
|
||||||
|
forbid unless @allow_editing || request.request_method == "GET"
|
||||||
|
Precious::App.set(:mustache, {:templates => settings.wiki_options[:template_dir]}) if settings.wiki_options[:template_dir]
|
||||||
@base_url = url('/', false).chomp('/')
|
@base_url = url('/', false).chomp('/')
|
||||||
# above will detect base_path when it's used with map in a config.ru
|
# above will detect base_path when it's used with map in a config.ru
|
||||||
settings.wiki_options.merge!({ :base_path => @base_url })
|
settings.wiki_options.merge!({ :base_path => @base_url })
|
||||||
@css = settings.wiki_options[:css]
|
@css = settings.wiki_options[:css]
|
||||||
@js = settings.wiki_options[:js]
|
@js = settings.wiki_options[:js]
|
||||||
|
@mathjax_config = settings.wiki_options[:mathjax_config]
|
||||||
end
|
end
|
||||||
|
|
||||||
get '/' do
|
get '/' do
|
||||||
@@ -105,7 +117,6 @@ module Precious
|
|||||||
# name, path, version
|
# name, path, version
|
||||||
def wiki_page(name, path = nil, version = nil, exact = true)
|
def wiki_page(name, path = nil, version = nil, exact = true)
|
||||||
wiki = wiki_new
|
wiki = wiki_new
|
||||||
|
|
||||||
path = name if path.nil?
|
path = name if path.nil?
|
||||||
name = extract_name(name) || wiki.index_page
|
name = extract_name(name) || wiki.index_page
|
||||||
path = extract_path(path)
|
path = extract_path(path)
|
||||||
@@ -126,14 +137,17 @@ module Precious
|
|||||||
end
|
end
|
||||||
|
|
||||||
get '/edit/*' do
|
get '/edit/*' do
|
||||||
|
forbid unless @allow_editing
|
||||||
wikip = wiki_page(params[:splat].first)
|
wikip = wiki_page(params[:splat].first)
|
||||||
@name = wikip.name
|
@name = wikip.name
|
||||||
@path = wikip.path
|
@path = wikip.path
|
||||||
|
@upload_dest = find_upload_dest(@path)
|
||||||
|
|
||||||
wiki = wikip.wiki
|
wiki = wikip.wiki
|
||||||
|
@allow_uploads = wiki.allow_uploads
|
||||||
if page = wikip.page
|
if page = wikip.page
|
||||||
if wiki.live_preview && page.format.to_s.include?('markdown') && supported_useragent?(request.user_agent)
|
if wiki.live_preview && page.format.to_s.include?('markdown') && supported_useragent?(request.user_agent)
|
||||||
live_preview_url = '/livepreview/index.html?page=' + encodeURIComponent(@name)
|
live_preview_url = '/livepreview/?page=' + encodeURIComponent(@name)
|
||||||
if @path
|
if @path
|
||||||
live_preview_url << '&path=' + encodeURIComponent(@path)
|
live_preview_url << '&path=' + encodeURIComponent(@path)
|
||||||
end
|
end
|
||||||
@@ -163,7 +177,8 @@ module Precious
|
|||||||
tempfile = params[:file][:tempfile]
|
tempfile = params[:file][:tempfile]
|
||||||
end
|
end
|
||||||
|
|
||||||
dir = wiki.per_page_uploads ? params[:upload_dest] : 'uploads'
|
# Remove page file dir prefix from upload path if necessary -- committer handles this itself
|
||||||
|
dir = wiki.per_page_uploads ? params[:upload_dest].match(/^(#{wiki.page_file_dir}\/+)?(.*)/)[2] : 'uploads'
|
||||||
ext = ::File.extname(fullname)
|
ext = ::File.extname(fullname)
|
||||||
format = ext.split('.').last || 'txt'
|
format = ext.split('.').last || 'txt'
|
||||||
filename = ::File.basename(fullname, ext)
|
filename = ::File.basename(fullname, ext)
|
||||||
@@ -251,21 +266,27 @@ module Precious
|
|||||||
end
|
end
|
||||||
|
|
||||||
get '/delete/*' do
|
get '/delete/*' do
|
||||||
|
forbid unless @allow_editing
|
||||||
wikip = wiki_page(params[:splat].first)
|
wikip = wiki_page(params[:splat].first)
|
||||||
name = wikip.name
|
name = wikip.name
|
||||||
wiki = wikip.wiki
|
wiki = wikip.wiki
|
||||||
page = wikip.page
|
page = wikip.page
|
||||||
unless page.nil?
|
unless page.nil?
|
||||||
wiki.delete_page(page, { :message => "Destroyed #{name} (#{page.format})" })
|
commit = commit_message
|
||||||
|
commit[:message] = "Destroyed #{name} (#{page.format})"
|
||||||
|
wiki.delete_page(page, commit)
|
||||||
end
|
end
|
||||||
|
|
||||||
redirect to('/')
|
redirect to('/')
|
||||||
end
|
end
|
||||||
|
|
||||||
get '/create/*' do
|
get '/create/*' do
|
||||||
|
forbid unless @allow_editing
|
||||||
wikip = wiki_page(params[:splat].first.gsub('+', '-'))
|
wikip = wiki_page(params[:splat].first.gsub('+', '-'))
|
||||||
@name = wikip.name.to_url
|
@name = wikip.name.to_url
|
||||||
@path = wikip.path
|
@path = wikip.path
|
||||||
|
@allow_uploads = wikip.wiki.allow_uploads
|
||||||
|
@upload_dest = find_upload_dest(@path)
|
||||||
|
|
||||||
page_dir = settings.wiki_options[:page_file_dir].to_s
|
page_dir = settings.wiki_options[:page_file_dir].to_s
|
||||||
unless page_dir.empty?
|
unless page_dir.empty?
|
||||||
@@ -297,7 +318,7 @@ module Precious
|
|||||||
wiki.write_page(name, format, params[:content], commit_message, path)
|
wiki.write_page(name, format, params[:content], commit_message, path)
|
||||||
|
|
||||||
page_dir = settings.wiki_options[:page_file_dir].to_s
|
page_dir = settings.wiki_options[:page_file_dir].to_s
|
||||||
redirect to("/#{clean_url(::File.join(page_dir, path, name))}")
|
redirect to("/#{clean_url(::File.join(page_dir, path, encodeURIComponent(name)))}")
|
||||||
rescue Gollum::DuplicatePageError => e
|
rescue Gollum::DuplicatePageError => e
|
||||||
@message = "Duplicate page: #{e.message}"
|
@message = "Duplicate page: #{e.message}"
|
||||||
mustache :error
|
mustache :error
|
||||||
@@ -340,6 +361,12 @@ module Precious
|
|||||||
mustache :page
|
mustache :page
|
||||||
end
|
end
|
||||||
|
|
||||||
|
get '/livepreview/' do
|
||||||
|
wiki = wiki_new
|
||||||
|
@mathjax = wiki.mathjax
|
||||||
|
mustache :livepreview, { :layout => false }
|
||||||
|
end
|
||||||
|
|
||||||
get '/history/*' do
|
get '/history/*' do
|
||||||
@page = wiki_page(params[:splat].first).page
|
@page = wiki_page(params[:splat].first).page
|
||||||
@page_num = [params[:page].to_i, 1].max
|
@page_num = [params[:page].to_i, 1].max
|
||||||
@@ -351,8 +378,15 @@ module Precious
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
get '/latest_changes' do
|
||||||
|
@wiki = wiki_new
|
||||||
|
max_count = settings.wiki_options.fetch(:latest_changes_count, 10)
|
||||||
|
@versions = @wiki.latest_changes({:max_count => max_count})
|
||||||
|
mustache :latest_changes
|
||||||
|
end
|
||||||
|
|
||||||
post '/compare/*' do
|
post '/compare/*' do
|
||||||
@file = params[:splat].first
|
@file = encodeURIComponent(params[:splat].first)
|
||||||
@versions = params[:versions] || []
|
@versions = params[:versions] || []
|
||||||
if @versions.size < 2
|
if @versions.size < 2
|
||||||
redirect to("/history/#{@file}")
|
redirect to("/history/#{@file}")
|
||||||
@@ -396,6 +430,8 @@ module Precious
|
|||||||
@content = page.formatted_data
|
@content = page.formatted_data
|
||||||
@version = version
|
@version = version
|
||||||
mustache :page
|
mustache :page
|
||||||
|
elsif file = wikip.wiki.file("#{file_path}", version, true)
|
||||||
|
show_file(file)
|
||||||
else
|
else
|
||||||
halt 404
|
halt 404
|
||||||
end
|
end
|
||||||
@@ -421,6 +457,7 @@ module Precious
|
|||||||
wiki = Gollum::Wiki.new(settings.gollum_path, wiki_options)
|
wiki = Gollum::Wiki.new(settings.gollum_path, wiki_options)
|
||||||
@results = wiki.pages
|
@results = wiki.pages
|
||||||
@results += wiki.files if settings.wiki_options[:show_all]
|
@results += wiki.files if settings.wiki_options[:show_all]
|
||||||
|
@results = @results.sort_by { |p| p.name.downcase } # Sort Results alphabetically, fixes 922
|
||||||
@ref = wiki.ref
|
@ref = wiki.ref
|
||||||
mustache :pages
|
mustache :pages
|
||||||
end
|
end
|
||||||
@@ -453,10 +490,7 @@ module Precious
|
|||||||
@page = page
|
@page = page
|
||||||
@name = name
|
@name = name
|
||||||
@content = page.formatted_data
|
@content = page.formatted_data
|
||||||
@upload_dest = settings.wiki_options[:allow_uploads] ?
|
@upload_dest = find_upload_dest(path)
|
||||||
(settings.wiki_options[:per_page_uploads] ?
|
|
||||||
"#{path}/#{@name}".sub(/^\/\//, '') : 'uploads'
|
|
||||||
) : ''
|
|
||||||
|
|
||||||
# Extensions and layout data
|
# Extensions and layout data
|
||||||
@editable = true
|
@editable = true
|
||||||
@@ -469,18 +503,24 @@ module Precious
|
|||||||
|
|
||||||
mustache :page
|
mustache :page
|
||||||
elsif file = wiki.file(fullpath, wiki.ref, true)
|
elsif file = wiki.file(fullpath, wiki.ref, true)
|
||||||
if file.on_disk?
|
show_file(file)
|
||||||
send_file file.on_disk_path, :disposition => 'inline'
|
|
||||||
else
|
|
||||||
content_type file.mime_type
|
|
||||||
file.raw_data
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
|
not_found unless @allow_editing
|
||||||
page_path = [path, name].compact.join('/')
|
page_path = [path, name].compact.join('/')
|
||||||
redirect to("/create/#{clean_url(encodeURIComponent(page_path))}")
|
redirect to("/create/#{clean_url(encodeURIComponent(page_path))}")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def show_file(file)
|
||||||
|
return unless file
|
||||||
|
if file.on_disk?
|
||||||
|
send_file file.on_disk_path, :disposition => 'inline'
|
||||||
|
else
|
||||||
|
content_type file.mime_type
|
||||||
|
file.raw_data
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def update_wiki_page(wiki, page, content, commit, name = nil, format = nil)
|
def update_wiki_page(wiki, page, content, commit, name = nil, format = nil)
|
||||||
return if !page ||
|
return if !page ||
|
||||||
((!content || page.raw_data == content) && page.format == format)
|
((!content || page.raw_data == content) && page.format == format)
|
||||||
@@ -505,5 +545,12 @@ module Precious
|
|||||||
commit_message.merge! author_parameters unless author_parameters.nil?
|
commit_message.merge! author_parameters unless author_parameters.nil?
|
||||||
commit_message
|
commit_message
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def find_upload_dest(path)
|
||||||
|
settings.wiki_options[:allow_uploads] ?
|
||||||
|
(settings.wiki_options[:per_page_uploads] ?
|
||||||
|
"#{path}/#{@name}".sub(/^\/\//, '') : 'uploads'
|
||||||
|
) : ''
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -39,5 +39,17 @@ module Precious
|
|||||||
url.gsub('%2F', '/').gsub(/^\/+/, '').gsub('//', '/')
|
url.gsub('%2F', '/').gsub(/^\/+/, '').gsub('//', '/')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def forbid(msg = "Forbidden. This wiki is set to no-edit mode.")
|
||||||
|
@message = msg
|
||||||
|
status 403
|
||||||
|
halt mustache :error
|
||||||
|
end
|
||||||
|
|
||||||
|
def not_found(msg = nil)
|
||||||
|
@message = msg || "The requested page does not exist."
|
||||||
|
status 404
|
||||||
|
return mustache :error
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -4,8 +4,11 @@
|
|||||||
display: block;
|
display: block;
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 50%;
|
top: 0;
|
||||||
left: 50%;
|
left: 0;
|
||||||
|
z-index: 999999;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
#gollum-dialog-dialog.active {
|
#gollum-dialog-dialog.active {
|
||||||
@@ -13,24 +16,117 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
#gollum-dialog-dialog-inner {
|
#gollum-dialog-dialog-inner {
|
||||||
margin: 0 0 0 -225px;
|
margin: 0px;
|
||||||
position: relative;
|
top: 0px;
|
||||||
width: 450px;
|
right: 0px;
|
||||||
|
bottom: 0px;
|
||||||
border: 7px solid #999;
|
left: 0px;
|
||||||
border: 7px solid rgba(0, 0, 0, 0.3);
|
width: 100%;
|
||||||
border-radius: 5px;
|
height: 100%;
|
||||||
-moz-border-radius: 5px;
|
|
||||||
-webkit-border-radius: 5px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#gollum-dialog-dialog-bg {
|
#gollum-dialog-dialog-bg {
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
overflow: hidden;
|
|
||||||
padding: 1em;
|
padding: 1em;
|
||||||
|
|
||||||
background: -webkit-gradient(linear, left top, left bottom, from(#f7f7f7), to(#ffffff));
|
height: 100%;
|
||||||
background: -moz-linear-gradient(top, #f7f7f7, #ffffff);
|
box-sizing: border-box;
|
||||||
|
-moz-box-sizing: border-box;
|
||||||
|
-webkit-box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media all and (min-width: 480px) {
|
||||||
|
#gollum-dialog-dialog {
|
||||||
|
display: block;
|
||||||
|
overflow: visible;
|
||||||
|
position: absolute;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: 999999;
|
||||||
|
width: auto;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#gollum-dialog-dialog.active {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
#gollum-dialog-dialog-inner {
|
||||||
|
margin: auto;
|
||||||
|
position: fixed;
|
||||||
|
|
||||||
|
width: auto;
|
||||||
|
height: auto;
|
||||||
|
|
||||||
|
min-width: 280px;
|
||||||
|
min-height: 380px;
|
||||||
|
|
||||||
|
max-width: 450px;
|
||||||
|
max-height: 450px;
|
||||||
|
|
||||||
|
top: 10px;
|
||||||
|
right: 10px;
|
||||||
|
bottom: 10px;
|
||||||
|
left: 10px;
|
||||||
|
|
||||||
|
border: 7px solid #999;
|
||||||
|
border: 7px solid rgba(0, 0, 0, 0.3);
|
||||||
|
border-radius: 5px;
|
||||||
|
-moz-border-radius: 5px;
|
||||||
|
-webkit-border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#gollum-dialog-dialog-bg {
|
||||||
|
background-color: #fff;
|
||||||
|
overflow: hidden;
|
||||||
|
padding: 1em;
|
||||||
|
|
||||||
|
background: -webkit-gradient(linear, left top, left bottom, from(#f7f7f7), to(#ffffff));
|
||||||
|
background: -moz-linear-gradient(top, #f7f7f7, #ffffff);
|
||||||
|
|
||||||
|
height: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
-moz-box-sizing: border-box;
|
||||||
|
-webkit-box-sizing: border-box;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media all and (min-width: 940px) {
|
||||||
|
#gollum-dialog-dialog {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
width: auto;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#gollum-dialog-dialog-inner {
|
||||||
|
margin: 0 0 0 -225px;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
width: 450px;
|
||||||
|
height: auto;
|
||||||
|
|
||||||
|
top: auto;
|
||||||
|
right: auto;
|
||||||
|
bottom: auto;
|
||||||
|
left: auto;
|
||||||
|
|
||||||
|
border: 7px solid #999;
|
||||||
|
border: 7px solid rgba(0, 0, 0, 0.3);
|
||||||
|
border-radius: 5px;
|
||||||
|
-moz-border-radius: 5px;
|
||||||
|
-webkit-border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#gollum-dialog-dialog-bg {
|
||||||
|
height: auto;
|
||||||
|
|
||||||
|
box-sizing: content-box;
|
||||||
|
-moz-box-sizing: content-box;
|
||||||
|
-webkit-box-sizing: content-box;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#gollum-dialog-dialog-inner h4 {
|
#gollum-dialog-dialog-inner h4 {
|
||||||
@@ -52,10 +148,16 @@
|
|||||||
display: block;
|
display: block;
|
||||||
border: 0;
|
border: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
overflow: hidden;
|
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#gollum-dialog-dialog-body fieldset:after {
|
||||||
|
content: ".";
|
||||||
|
display: block;
|
||||||
|
clear: both;
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
#gollum-dialog-dialog-body fieldset .field {
|
#gollum-dialog-dialog-body fieldset .field {
|
||||||
margin: 0 0 1.5em 0;
|
margin: 0 0 1.5em 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
|||||||
@@ -19,15 +19,15 @@ a {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#gollum-editor {
|
#gollum-editor {
|
||||||
border: 1px solid #e4e4e4;
|
margin: 0 0 5em;
|
||||||
background: #f9f9f9;
|
padding: 0em 1em 0.4em;
|
||||||
margin: 1em 0 5em;
|
}
|
||||||
overflow: hidden;
|
|
||||||
padding: 1em 1em 0.4em;
|
|
||||||
|
|
||||||
border-radius: 1em;
|
#gollum-editor:after {
|
||||||
-moz-border-radius: 1em;
|
content: ".";
|
||||||
-webkit-border-radius: 1em;
|
display: block;
|
||||||
|
visibility: hidden;
|
||||||
|
clear: both;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ff #gollum-editor,
|
.ff #gollum-editor,
|
||||||
@@ -35,6 +35,18 @@ a {
|
|||||||
padding-bottom: 1em;
|
padding-bottom: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media all and (min-width: 940px) {
|
||||||
|
#gollum-editor {
|
||||||
|
border: 1px solid #e4e4e4;
|
||||||
|
background: #f9f9f9;
|
||||||
|
margin: 1em 0 5em;
|
||||||
|
|
||||||
|
border-radius: 1em;
|
||||||
|
-moz-border-radius: 1em;
|
||||||
|
-webkit-border-radius: 1em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#gollum-editor form fieldset {
|
#gollum-editor form fieldset {
|
||||||
border: 0;
|
border: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
@@ -45,7 +57,13 @@ a {
|
|||||||
#gollum-editor .singleline {
|
#gollum-editor .singleline {
|
||||||
display: block;
|
display: block;
|
||||||
margin: 0 0 0.7em 0;
|
margin: 0 0 0.7em 0;
|
||||||
overflow: hidden;
|
}
|
||||||
|
|
||||||
|
#gollum-editor .singleline:after {
|
||||||
|
content: ".";
|
||||||
|
display: block;
|
||||||
|
visibility: hidden;
|
||||||
|
clear: both;
|
||||||
}
|
}
|
||||||
|
|
||||||
#gollum-editor .singleline input {
|
#gollum-editor .singleline input {
|
||||||
@@ -94,7 +112,6 @@ a {
|
|||||||
/* @control function-bar */
|
/* @control function-bar */
|
||||||
#gollum-editor #gollum-editor-function-bar {
|
#gollum-editor #gollum-editor-function-bar {
|
||||||
border-bottom: 1px solid #ddd;
|
border-bottom: 1px solid #ddd;
|
||||||
overflow: hidden;
|
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,9 +126,21 @@ a {
|
|||||||
|
|
||||||
#gollum-editor #gollum-editor-function-bar.active #gollum-editor-function-buttons {
|
#gollum-editor #gollum-editor-function-bar.active #gollum-editor-function-buttons {
|
||||||
display: block;
|
display: block;
|
||||||
float: left;
|
margin: 0;
|
||||||
overflow: hidden;
|
padding: 0;
|
||||||
padding: 0 0 1.1em 0;
|
}
|
||||||
|
|
||||||
|
@media all and (min-width: 940px) {
|
||||||
|
#gollum-editor #gollum-editor-function-bar {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#gollum-editor #gollum-editor-function-bar.active #gollum-editor-function-buttons {
|
||||||
|
overflow: hidden;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0 0 1.1em 0;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#gollum-editor #gollum-editor-function-bar a.function-button {
|
#gollum-editor #gollum-editor-function-bar a.function-button {
|
||||||
@@ -120,12 +149,12 @@ a {
|
|||||||
color: #333;
|
color: #333;
|
||||||
display: block;
|
display: block;
|
||||||
float: left;
|
float: left;
|
||||||
height: 25px;
|
height: 32px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
margin: 0.2em 0.5em 0 0;
|
margin: 1px 1px 0 0;
|
||||||
/* text-indent: -5000px; */
|
/* text-indent: -5000px; */
|
||||||
text-shadow: 0 1px 0 #fff;
|
text-shadow: 0 1px 0 #fff;
|
||||||
width: 25px;
|
width: 32px;
|
||||||
|
|
||||||
border-radius: 0.3em;
|
border-radius: 0.3em;
|
||||||
-moz-border-radius: 0.3em;
|
-moz-border-radius: 0.3em;
|
||||||
@@ -150,41 +179,84 @@ a {
|
|||||||
background-image: url(../images/icon-sprite.png);
|
background-image: url(../images/icon-sprite.png);
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
display: block;
|
display: block;
|
||||||
height: 25px;
|
height: 32px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-indent: -5000px;
|
text-indent: -5000px;
|
||||||
width: 25px;
|
width: 32px;
|
||||||
}
|
}
|
||||||
|
|
||||||
a#function-bold span { background-position: 0 0; }
|
a#function-bold span { background-position: 3px 3px; }
|
||||||
a#function-italic span { background-position: -27px 0; }
|
a#function-italic span { background-position: -24px 3px; }
|
||||||
a#function-underline span { background-position: -54px 0; }
|
a#function-underline span { background-position: -51px 3px; }
|
||||||
a#function-code span { background-position: -82px 0; }
|
a#function-code span { background-position: -79px 3px; }
|
||||||
a#function-ul span { background-position: -109px 0; }
|
a#function-ul span { background-position: -106px 3px; }
|
||||||
a#function-ol span { background-position: -136px 0; }
|
a#function-ol span { background-position: -133px 3px; }
|
||||||
a#function-blockquote span { background-position: -163px 0; }
|
a#function-blockquote span { background-position: -160px 3px; }
|
||||||
a#function-hr span { background-position: -190px 0; }
|
a#function-hr span { background-position: -187px 3px; }
|
||||||
a#function-h1 span { background-position: -217px 0; }
|
a#function-h1 span { background-position: -214px 3px; }
|
||||||
a#function-h2 span { background-position: -244px 0; }
|
a#function-h2 span { background-position: -241px 3px; }
|
||||||
a#function-h3 span { background-position: -271px 0; }
|
a#function-h3 span { background-position: -268px 3px; }
|
||||||
a#function-link span { background-position: -298px 0; }
|
a#function-link span { background-position: -295px 3px; }
|
||||||
a#function-image span { background-position: -324px 0; }
|
a#function-image span { background-position: -321px 3px; }
|
||||||
a#function-help span { background-position: -405px 0; }
|
a#function-help span { background-position: -402px 3px; }
|
||||||
|
|
||||||
a#function-bold:hover span { background-position: 0 -28px; }
|
a#function-bold:hover span { background-position: 3px -25px; }
|
||||||
a#function-italic:hover span { background-position: -27px -28px; }
|
a#function-italic:hover span { background-position: -24px -25px; }
|
||||||
a#function-underline:hover span { background-position: -54px -28px; }
|
a#function-underline:hover span { background-position: -51px -25px; }
|
||||||
a#function-code:hover span { background-position: -82px -28px; }
|
a#function-code:hover span { background-position: -79px -25px; }
|
||||||
a#function-ul:hover span { background-position: -109px -28px; }
|
a#function-ul:hover span { background-position: -106px -25px; }
|
||||||
a#function-ol:hover span { background-position: -136px -28px; }
|
a#function-ol:hover span { background-position: -133px -25px; }
|
||||||
a#function-blockquote:hover span { background-position: -163px -28px; }
|
a#function-blockquote:hover span { background-position: -160px -25px; }
|
||||||
a#function-hr:hover span { background-position: -190px -28px; }
|
a#function-hr:hover span { background-position: -187px -25px; }
|
||||||
a#function-h1:hover span { background-position: -217px -28px; }
|
a#function-h1:hover span { background-position: -214px -25px; }
|
||||||
a#function-h2:hover span { background-position: -244px -28px; }
|
a#function-h2:hover span { background-position: -241px -25px; }
|
||||||
a#function-h3:hover span { background-position: -271px -28px; }
|
a#function-h3:hover span { background-position: -268px -25px; }
|
||||||
a#function-link:hover span { background-position: -298px -28px; }
|
a#function-link:hover span { background-position: -295px -25px; }
|
||||||
a#function-image:hover span { background-position: -324px -28px; }
|
a#function-image:hover span { background-position: -321px -25px; }
|
||||||
a#function-help:hover span { background-position: -405px -28px; }
|
a#function-help:hover span { background-position: -402px -25px; }
|
||||||
|
|
||||||
|
@media all and (min-width: 940px) {
|
||||||
|
#gollum-editor #gollum-editor-function-bar a.function-button {
|
||||||
|
height: 25px;
|
||||||
|
width: 25px;
|
||||||
|
margin: 0.2em 0.5em 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#gollum-editor #gollum-editor-function-bar a span {
|
||||||
|
width: 25px;
|
||||||
|
height: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
a#function-bold span { background-position: 0 0; }
|
||||||
|
a#function-italic span { background-position: -27px 0; }
|
||||||
|
a#function-underline span { background-position: -54px 0; }
|
||||||
|
a#function-code span { background-position: -82px 0; }
|
||||||
|
a#function-ul span { background-position: -109px 0; }
|
||||||
|
a#function-ol span { background-position: -136px 0; }
|
||||||
|
a#function-blockquote span { background-position: -163px 0; }
|
||||||
|
a#function-hr span { background-position: -190px 0; }
|
||||||
|
a#function-h1 span { background-position: -217px 0; }
|
||||||
|
a#function-h2 span { background-position: -244px 0; }
|
||||||
|
a#function-h3 span { background-position: -271px 0; }
|
||||||
|
a#function-link span { background-position: -298px 0; }
|
||||||
|
a#function-image span { background-position: -324px 0; }
|
||||||
|
a#function-help span { background-position: -405px 0; }
|
||||||
|
|
||||||
|
a#function-bold:hover span { background-position: 0 -28px; }
|
||||||
|
a#function-italic:hover span { background-position: -27px -28px; }
|
||||||
|
a#function-underline:hover span { background-position: -54px -28px; }
|
||||||
|
a#function-code:hover span { background-position: -82px -28px; }
|
||||||
|
a#function-ul:hover span { background-position: -109px -28px; }
|
||||||
|
a#function-ol:hover span { background-position: -136px -28px; }
|
||||||
|
a#function-blockquote:hover span { background-position: -163px -28px; }
|
||||||
|
a#function-hr:hover span { background-position: -190px -28px; }
|
||||||
|
a#function-h1:hover span { background-position: -217px -28px; }
|
||||||
|
a#function-h2:hover span { background-position: -244px -28px; }
|
||||||
|
a#function-h3:hover span { background-position: -271px -28px; }
|
||||||
|
a#function-link:hover span { background-position: -298px -28px; }
|
||||||
|
a#function-image:hover span { background-position: -324px -28px; }
|
||||||
|
a#function-help:hover span { background-position: -405px -28px; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#gollum-editor #gollum-editor-function-bar a.disabled {
|
#gollum-editor #gollum-editor-function-bar a.disabled {
|
||||||
@@ -192,14 +264,19 @@ a#function-help:hover span { background-position: -405px -28px; }
|
|||||||
}
|
}
|
||||||
|
|
||||||
#gollum-editor #gollum-editor-function-bar span.function-divider {
|
#gollum-editor #gollum-editor-function-bar span.function-divider {
|
||||||
display: block;
|
display: none;
|
||||||
float: left;
|
|
||||||
width: 0.5em;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#gollum-editor #gollum-editor-function-bar #gollum-editor-format-selector {
|
#gollum-editor #gollum-editor-function-bar #gollum-editor-format-selector {
|
||||||
overflow: hidden;
|
padding: 0.2em 0 0.5em 0;
|
||||||
padding: .2em 0 .5em 0;
|
clear: both;
|
||||||
|
}
|
||||||
|
|
||||||
|
#gollum-editor #gollum-editor-function-bar #gollum-editor-format-selector:after {
|
||||||
|
content: ".";
|
||||||
|
display: block;
|
||||||
|
clear: both;
|
||||||
|
visibility: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
#gollum-editor #gollum-editor-function-bar
|
#gollum-editor #gollum-editor-function-bar
|
||||||
@@ -208,13 +285,12 @@ a#function-help:hover span { background-position: -405px -28px; }
|
|||||||
border: 1px solid #ddd;
|
border: 1px solid #ddd;
|
||||||
color: #333;
|
color: #333;
|
||||||
|
|
||||||
float: right;
|
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
line-height: 1.6em;
|
line-height: 1.6em;
|
||||||
padding: 0.3em 0.4em;
|
padding: 0.3em 0.4em;
|
||||||
|
display: inline-block;
|
||||||
|
|
||||||
border-radius: 0.5em;
|
border-radius: 0.5em;
|
||||||
-moz-border-radius: 0.5em;
|
-moz-border-radius: 0.5em;
|
||||||
@@ -224,11 +300,11 @@ a#function-help:hover span { background-position: -405px -28px; }
|
|||||||
#gollum-editor #gollum-editor-function-bar
|
#gollum-editor #gollum-editor-function-bar
|
||||||
#gollum-editor-format-selector label {
|
#gollum-editor-format-selector label {
|
||||||
color: #999;
|
color: #999;
|
||||||
float: right;
|
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
line-height: 1.6em;
|
line-height: 1.6em;
|
||||||
padding: .3em 0.5em 0 0;
|
padding: .3em 0.5em 0 0;
|
||||||
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
#gollum-editor #gollum-editor-function-bar
|
#gollum-editor #gollum-editor-function-bar
|
||||||
@@ -236,6 +312,56 @@ a#function-help:hover span { background-position: -405px -28px; }
|
|||||||
content: ':';
|
content: ':';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media all and (min-width: 940px) {
|
||||||
|
#gollum-editor #gollum-editor-function-bar span.function-divider {
|
||||||
|
display: block;
|
||||||
|
width: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#gollum-editor #gollum-editor-function-bar span.function-divider {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
#gollum-editor #gollum-editor-function-bar
|
||||||
|
#gollum-editor-format-selector {
|
||||||
|
clear: none;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
#gollum-editor #gollum-editor-function-bar
|
||||||
|
#gollum-editor-format-selector select {
|
||||||
|
}
|
||||||
|
|
||||||
|
#gollum-editor #gollum-editor-function-bar
|
||||||
|
#gollum-editor-format-selector label {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* @section uploads */
|
||||||
|
|
||||||
|
#gollum-editor-body.dragging {
|
||||||
|
box-shadow: 0 0 10px #AAE000;
|
||||||
|
}
|
||||||
|
|
||||||
|
#gollum-editor-body.uploading {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
#gollum-editor-body + div {
|
||||||
|
display: none;
|
||||||
|
font-size: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#gollum-editor-body + div > i {
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#gollum-editor-body.uploading + div {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* @section form-fields */
|
/* @section form-fields */
|
||||||
|
|
||||||
@@ -245,12 +371,18 @@ a#function-help:hover span { background-position: -405px -28px; }
|
|||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
font-family: Consolas, "Liberation Mono", Courier, monospace;
|
font-family: Consolas, "Liberation Mono", Courier, monospace;
|
||||||
line-height: 1.4em;
|
line-height: 1.4em;
|
||||||
margin: 1em 0 0.4em;
|
margin: 0 0 0.4em;
|
||||||
padding: 0.5em;
|
padding: 0.5em;
|
||||||
width: 98%;
|
width: 98%;
|
||||||
height: 20em;
|
height: 20em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media all and (min-width: 940px) {
|
||||||
|
#gollum-editor textarea {
|
||||||
|
margin: 1em 0 0.4em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#gollum-editor input#gollum-editor-submit {
|
#gollum-editor input#gollum-editor-submit {
|
||||||
background-color: #f7f7f7;
|
background-color: #f7f7f7;
|
||||||
border: 1px solid #d4d4d4;
|
border: 1px solid #d4d4d4;
|
||||||
@@ -445,6 +577,7 @@ a#function-help:hover span { background-position: -405px -28px; }
|
|||||||
|
|
||||||
/* @section help */
|
/* @section help */
|
||||||
#gollum-editor-help {
|
#gollum-editor-help {
|
||||||
|
clear: both;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
@@ -455,13 +588,13 @@ a#function-help:hover span { background-position: -405px -28px; }
|
|||||||
#gollum-editor-help-parent,
|
#gollum-editor-help-parent,
|
||||||
#gollum-editor-help-list {
|
#gollum-editor-help-list {
|
||||||
display: block;
|
display: block;
|
||||||
float: left;
|
|
||||||
height: 17em;
|
|
||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
overflow: auto;
|
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 1em 0;
|
float: left;
|
||||||
width: 18%;
|
width: 50%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
-webkit-box-sizing: border-box;
|
||||||
|
-moz-box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
#gollum-editor-help-parent {
|
#gollum-editor-help-parent {
|
||||||
@@ -491,6 +624,7 @@ a#function-help:hover span { background-position: -405px -28px; }
|
|||||||
width: auto;
|
width: auto;
|
||||||
padding: 0.2em 1em;
|
padding: 0.2em 1em;
|
||||||
text-shadow: 0 -1px 0 #fff;
|
text-shadow: 0 -1px 0 #fff;
|
||||||
|
font-size: 0.8em;
|
||||||
}
|
}
|
||||||
|
|
||||||
#gollum-editor-help-parent li a:hover,
|
#gollum-editor-help-parent li a:hover,
|
||||||
@@ -518,6 +652,7 @@ a#function-help:hover span { background-position: -405px -28px; }
|
|||||||
overflow: auto;
|
overflow: auto;
|
||||||
height: 17em;
|
height: 17em;
|
||||||
padding: 1em;
|
padding: 1em;
|
||||||
|
clear: both;
|
||||||
}
|
}
|
||||||
|
|
||||||
#gollum-editor-help-content {
|
#gollum-editor-help-content {
|
||||||
@@ -532,6 +667,29 @@ a#function-help:hover span { background-position: -405px -28px; }
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media all and (min-width: 940px) {
|
||||||
|
#gollum-editor-help {
|
||||||
|
clear: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#gollum-editor-help-parent,
|
||||||
|
#gollum-editor-help-list {
|
||||||
|
height: 17em;
|
||||||
|
width: 18%;
|
||||||
|
overflow: auto;
|
||||||
|
padding: 1em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#gollum-editor-help-parent li a,
|
||||||
|
#gollum-editor-help-list li a {
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#gollum-editor-help-wrapper {
|
||||||
|
clear: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* IE */
|
/* IE */
|
||||||
.ie #gollum-editor .singleline input {
|
.ie #gollum-editor .singleline input {
|
||||||
padding-top: 0.25em;
|
padding-top: 0.25em;
|
||||||
|
|||||||
@@ -21,9 +21,15 @@ body, html {
|
|||||||
#wiki-wrapper {
|
#wiki-wrapper {
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
width: 920px;
|
width: 100%;
|
||||||
padding-left:20px;
|
}
|
||||||
padding-right:20px;
|
|
||||||
|
@media all and (min-width: 940px) {
|
||||||
|
#wiki-wrapper {
|
||||||
|
max-width: 920px;
|
||||||
|
padding-left:20px;
|
||||||
|
padding-right:20px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
a:link {
|
a:link {
|
||||||
@@ -39,22 +45,41 @@ a:hover, a:visited {
|
|||||||
|
|
||||||
/* @section head */
|
/* @section head */
|
||||||
#head {
|
#head {
|
||||||
border-bottom: 1px solid #ddd;
|
margin: 1em 0 0;
|
||||||
margin: 4em 0 1.5em;
|
padding: 0;
|
||||||
padding-bottom: 0.3em;
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
#head h1 {
|
#head h1 {
|
||||||
font-size: 2.5em;
|
font-size: 1.5em;
|
||||||
float: left;
|
float: left;
|
||||||
line-height: normal;
|
line-height: normal;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 2px 0 0 0;
|
padding: 0 0 0 0.667em;
|
||||||
}
|
}
|
||||||
|
|
||||||
#head ul.actions {
|
#head ul.actions {
|
||||||
float: right;
|
clear: both;
|
||||||
|
margin: 0 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media all and (min-width: 940px) {
|
||||||
|
#head {
|
||||||
|
border-bottom: 1px solid #ddd;
|
||||||
|
padding-bottom: 0.3em;
|
||||||
|
margin: 4em 0 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#head h1 {
|
||||||
|
font-size: 2.5em;
|
||||||
|
padding: 2px 0 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#head ul.actions {
|
||||||
|
clear: none;
|
||||||
|
float: right;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* @section content */
|
/* @section content */
|
||||||
@@ -89,6 +114,12 @@ a:hover, a:visited {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#wiki-body table {
|
||||||
|
display: block;
|
||||||
|
overflow: auto;
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.has-sidebar #wiki-body {
|
.has-sidebar #wiki-body {
|
||||||
width: 68%;
|
width: 68%;
|
||||||
}
|
}
|
||||||
@@ -244,6 +275,16 @@ a:hover, a:visited {
|
|||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#footer .actions {
|
||||||
|
margin-left: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media all and (min-width: 940px) {
|
||||||
|
#footer .actions {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* @section history */
|
/* @section history */
|
||||||
.history h1 {
|
.history h1 {
|
||||||
@@ -257,7 +298,7 @@ a:hover, a:visited {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#wiki-history {
|
#wiki-history {
|
||||||
margin-top: 2em;
|
margin: 2em 1em 0 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
#wiki-history fieldset {
|
#wiki-history fieldset {
|
||||||
@@ -283,7 +324,8 @@ a:hover, a:visited {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#wiki-history table tr td {
|
#wiki-history table tr td {
|
||||||
border: 1px solid #c0dce9;
|
border-top: 1px solid #c0dce9;
|
||||||
|
border-bottom: 1px solid #c0dce9;
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
line-height: 1.6em;
|
line-height: 1.6em;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
@@ -291,8 +333,8 @@ a:hover, a:visited {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#wiki-history table tr td.checkbox {
|
#wiki-history table tr td.checkbox {
|
||||||
width: 4em;
|
width: auto;
|
||||||
padding: 0.3em;
|
padding: 0 0.2em 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#wiki-history table tr td.checkbox input {
|
#wiki-history table tr td.checkbox input {
|
||||||
@@ -364,6 +406,25 @@ a:hover, a:visited {
|
|||||||
margin: 0 0.6em 0 0;
|
margin: 0 0.6em 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media all and (min-width: 940px) {
|
||||||
|
#wiki-history {
|
||||||
|
margin: 2em 0 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#wiki-history table tr td {
|
||||||
|
border: 1px solid #c0dce9;
|
||||||
|
font-size: 1em;
|
||||||
|
line-height: 1.6em;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0.3em 0.7em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#wiki-history table tr td.checkbox {
|
||||||
|
width: 4em;
|
||||||
|
padding: 0.3em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* @section edit */
|
/* @section edit */
|
||||||
.edit h1 {
|
.edit h1 {
|
||||||
@@ -378,6 +439,7 @@ a:hover, a:visited {
|
|||||||
|
|
||||||
|
|
||||||
/* @section search */
|
/* @section search */
|
||||||
|
|
||||||
.results h1 {
|
.results h1 {
|
||||||
color: #999;
|
color: #999;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
@@ -390,6 +452,8 @@ a:hover, a:visited {
|
|||||||
|
|
||||||
.results #results {
|
.results #results {
|
||||||
border-bottom: 1px solid #ccc;
|
border-bottom: 1px solid #ccc;
|
||||||
|
margin-left: 1em;
|
||||||
|
margin-right: 1em;
|
||||||
margin-bottom: 2em;
|
margin-bottom: 2em;
|
||||||
padding-bottom: 2em;
|
padding-bottom: 2em;
|
||||||
}
|
}
|
||||||
@@ -400,12 +464,33 @@ a:hover, a:visited {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.results #results ul li {
|
.results #results ul li {
|
||||||
font-size: 1.2em;
|
list-style: none;
|
||||||
line-height: 1.6em;
|
|
||||||
list-style-position: outside;
|
|
||||||
padding: 0.2em 0;
|
padding: 0.2em 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.results #results ul li a {
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media all and (min-width: 640px) {
|
||||||
|
.results #results ul li {
|
||||||
|
font-size: 1.2em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media all and (min-width: 940px) {
|
||||||
|
.results #results {
|
||||||
|
margin-left: 0;
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.results #results ul li {
|
||||||
|
list-style: disc;
|
||||||
|
list-style-position: outside;
|
||||||
|
line-height: 1.6em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.results #results ul li span.count {
|
.results #results ul li span.count {
|
||||||
color: #999;
|
color: #999;
|
||||||
}
|
}
|
||||||
@@ -522,8 +607,8 @@ ul.actions {
|
|||||||
ul.actions li {
|
ul.actions li {
|
||||||
float: left;
|
float: left;
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
margin-left: 0.6em;
|
margin-left: 1px;
|
||||||
margin-bottom: 0.6em;
|
margin-bottom: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.minibutton a {
|
.minibutton a {
|
||||||
@@ -533,7 +618,7 @@ ul.actions {
|
|||||||
display: block;
|
display: block;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0.4em 1em;
|
padding: 0.6em 1em;
|
||||||
height: 1.4em;
|
height: 1.4em;
|
||||||
|
|
||||||
text-shadow: 0 1px 0 #fff;
|
text-shadow: 0 1px 0 #fff;
|
||||||
@@ -547,6 +632,18 @@ ul.actions {
|
|||||||
-webkit-border-radius: 3px;
|
-webkit-border-radius: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media all and (min-width: 940px) {
|
||||||
|
ul.actions li {
|
||||||
|
margin-left: 0.6em;
|
||||||
|
margin-bottom: 0.6em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.minibutton a {
|
||||||
|
padding: 0.4em 1em;
|
||||||
|
height: 1.4em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#search-submit {
|
#search-submit {
|
||||||
background-color: #f7f7f7;
|
background-color: #f7f7f7;
|
||||||
border: 1px solid #d4d4d4;
|
border: 1px solid #d4d4d4;
|
||||||
@@ -627,7 +724,7 @@ ul.actions {
|
|||||||
/* @control searchbar */
|
/* @control searchbar */
|
||||||
#head #searchbar {
|
#head #searchbar {
|
||||||
float: right;
|
float: right;
|
||||||
padding: 0;
|
padding: 2px 0 0 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -684,7 +781,7 @@ ul.actions {
|
|||||||
height: inherit;
|
height: inherit;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-indent: -5000px;
|
text-indent: -5000px;
|
||||||
width: 28px;
|
width: 32px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ff #head #searchbar #searchbar-fauxtext #search-submit span,
|
.ff #head #searchbar #searchbar-fauxtext #search-submit span,
|
||||||
@@ -697,11 +794,31 @@ ul.actions {
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media all and (min-width: 940px) {
|
||||||
|
#head #searchbar {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#head #searchbar #searchbar-fauxtext #search-submit span {
|
||||||
|
width: 28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#head #searchbar #searchbar-fauxtext #search-submit:hover span {
|
||||||
|
background-position: -431px -28px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* @section pages */
|
/* @section pages */
|
||||||
|
|
||||||
#pages {
|
#pages {
|
||||||
font-size: 1.2em;
|
font-size: 1.2em;
|
||||||
margin-bottom: 20px;
|
margin: 0 1em 20px 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media all and (min-width: 940px) {
|
||||||
|
#pages {
|
||||||
|
margin: 0 0 20px 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#pages ul {
|
#pages ul {
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
/* IE7-specific styles */
|
/* IE7-specific styles */
|
||||||
|
|
||||||
|
.ie #wiki-wrapper {
|
||||||
|
width: 920px;
|
||||||
|
padding-left:20px;
|
||||||
|
padding-right:20px;
|
||||||
|
}
|
||||||
|
|
||||||
.ie #head #searchbar #searchbar-fauxtext input#search-query {
|
.ie #head #searchbar #searchbar-fauxtext input#search-query {
|
||||||
border: 0;
|
border: 0;
|
||||||
float: left;
|
float: left;
|
||||||
|
|||||||
@@ -2,6 +2,10 @@
|
|||||||
Gollum v3 Template
|
Gollum v3 Template
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Font Awesome 4.0.3 by @davegandy - http://fontawesome.io - @fontawesome
|
||||||
|
* License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
|
||||||
|
*/
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'FontAwesome';
|
font-family: 'FontAwesome';
|
||||||
src: url('../fonts/fontawesome-webfont.eot?v=4.0.3');
|
src: url('../fonts/fontawesome-webfont.eot?v=4.0.3');
|
||||||
@@ -23,6 +27,51 @@
|
|||||||
content: "\f0c1";
|
content: "\f0c1";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.fa-spinner:before {
|
||||||
|
content: "\f110";
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-spin {
|
||||||
|
-webkit-animation: spin 2s infinite linear;
|
||||||
|
-moz-animation: spin 2s infinite linear;
|
||||||
|
-o-animation: spin 2s infinite linear;
|
||||||
|
animation: spin 2s infinite linear;
|
||||||
|
}
|
||||||
|
@-moz-keyframes spin {
|
||||||
|
0% {
|
||||||
|
-moz-transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
-moz-transform: rotate(359deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@-webkit-keyframes spin {
|
||||||
|
0% {
|
||||||
|
-webkit-transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
-webkit-transform: rotate(359deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@-o-keyframes spin {
|
||||||
|
0% {
|
||||||
|
-o-transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
-o-transform: rotate(359deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@keyframes spin {
|
||||||
|
0% {
|
||||||
|
-webkit-transform: rotate(0deg);
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
-webkit-transform: rotate(359deg);
|
||||||
|
transform: rotate(359deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* margin & padding reset*/
|
/* margin & padding reset*/
|
||||||
* {
|
* {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
@@ -48,7 +97,6 @@ body {
|
|||||||
font: 13.34px Helvetica, arial, freesans, clean, sans-serif;
|
font: 13.34px Helvetica, arial, freesans, clean, sans-serif;
|
||||||
font-size: small;
|
font-size: small;
|
||||||
line-height: 1.4;
|
line-height: 1.4;
|
||||||
min-width: 980px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
img {
|
||||||
@@ -82,13 +130,19 @@ a:active, a:hover {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.markdown-body {
|
.markdown-body {
|
||||||
padding: 30px;
|
padding: 1em;
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
line-height: 1.7;
|
line-height: 1.7;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media all and (min-width: 940px) {
|
||||||
|
.markdown-body {
|
||||||
|
padding: 30px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.markdown-body > *:first-child {
|
.markdown-body > *:first-child {
|
||||||
margin-top: 0 !important;
|
margin-top: 0 !important;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,6 +98,52 @@
|
|||||||
$('#gollum-editor-help').removeClass('jaws');
|
$('#gollum-editor-help').removeClass('jaws');
|
||||||
}
|
}
|
||||||
} // EditorHas.functionBar
|
} // EditorHas.functionBar
|
||||||
|
|
||||||
|
if ( EditorHas.dragDropUpload() ) {
|
||||||
|
var $editorBody = $('#gollum-editor-body');
|
||||||
|
var editorBody = $('#gollum-editor-body')[0];
|
||||||
|
editorBody.ondragover = function(e) {
|
||||||
|
$editorBody.addClass('dragging');
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
editorBody.ondragleave = function() {
|
||||||
|
$editorBody.removeClass('dragging');
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
editorBody.ondrop = function(e) {
|
||||||
|
debug("dropped file");
|
||||||
|
e.preventDefault();
|
||||||
|
$editorBody.removeClass('dragging').addClass('uploading');
|
||||||
|
|
||||||
|
var file = e.dataTransfer.files[0],
|
||||||
|
formData = new FormData();
|
||||||
|
formData.append('upload_dest', uploadDest);
|
||||||
|
formData.append('file', file);
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: baseUrl + '/uploadFile',
|
||||||
|
data: formData,
|
||||||
|
cache: false,
|
||||||
|
contentType: false,
|
||||||
|
processData: false,
|
||||||
|
type: 'POST',
|
||||||
|
success: function(){
|
||||||
|
$editorBody.removeClass('uploading');
|
||||||
|
var text = '[[/' + uploadDest + '/' + file.name + ']]';
|
||||||
|
var pos = editorBody.selectionStart || 0;
|
||||||
|
editorBody.value = editorBody.value.substring(0, pos) + text + editorBody.value.substring(pos);
|
||||||
|
editorBody.selectionStart = pos + text.length;
|
||||||
|
editorBody.selectionEnd = pos + text.length;
|
||||||
|
},
|
||||||
|
error: function(r, textStatus) {
|
||||||
|
alert('Error uploading file: ' + textStatus);
|
||||||
|
$editorBody.removeClass('uploading');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
} // EditorHas.dragDropUpload
|
||||||
} // EditorHas.baseEditorMarkup
|
} // EditorHas.baseEditorMarkup
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -444,6 +490,17 @@
|
|||||||
*/
|
*/
|
||||||
titleDisplayed: function() {
|
titleDisplayed: function() {
|
||||||
return ( ActiveOptions.NewFile );
|
return ( ActiveOptions.NewFile );
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* EditorHas.dragDropUpload
|
||||||
|
* True if the editor is supports drag and drop file uploads, false otherwise.
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
dragDropUpload: function() {
|
||||||
|
return $('#gollum-editor.uploads-allowed').length;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
@@ -546,9 +603,12 @@
|
|||||||
typeof definitionObject.replace == 'string' ) {
|
typeof definitionObject.replace == 'string' ) {
|
||||||
debug('Running replacement - using ' + definitionObject.replace);
|
debug('Running replacement - using ' + definitionObject.replace);
|
||||||
var rt = definitionObject.replace;
|
var rt = definitionObject.replace;
|
||||||
|
|
||||||
|
repText = escape( repText );
|
||||||
repText = repText.replace( searchExp, rt );
|
repText = repText.replace( searchExp, rt );
|
||||||
// remove backreferences
|
// remove backreferences
|
||||||
repText = repText.replace( /\$[\d]/g, '' );
|
repText = repText.replace( /\$[\d]/g, '' );
|
||||||
|
repText = unescape( repText );
|
||||||
|
|
||||||
if ( repText === '' ) {
|
if ( repText === '' ) {
|
||||||
debug('Search string is empty');
|
debug('Search string is empty');
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
/**
|
/**
|
||||||
* ASCIIDoc Language Definition
|
* AsciiDoc Language Definition
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
(function($) {
|
(function($) {
|
||||||
|
|
||||||
var ASCIIDoc = {
|
var AsciiDoc = {
|
||||||
|
|
||||||
'function-bold' : {
|
'function-bold' : {
|
||||||
search: /(^[\n]+)([\n\s]*)/g,
|
search: /(^[\n]+)([\n\s]*)/g,
|
||||||
@@ -19,7 +19,7 @@ var ASCIIDoc = {
|
|||||||
|
|
||||||
'function-code' : {
|
'function-code' : {
|
||||||
search: /(^[\n]+)([\n\s]*)/g,
|
search: /(^[\n]+)([\n\s]*)/g,
|
||||||
replace: "+$1+$2"
|
replace: "`$1`$2"
|
||||||
},
|
},
|
||||||
|
|
||||||
'function-ul' : {
|
'function-ul' : {
|
||||||
@@ -37,6 +37,21 @@ var ASCIIDoc = {
|
|||||||
replace: "----\n$1$2\n----\n"
|
replace: "----\n$1$2\n----\n"
|
||||||
},
|
},
|
||||||
|
|
||||||
|
'function-h1' : {
|
||||||
|
search: /(.+)([\n]?)/g,
|
||||||
|
replace: "= $1$2"
|
||||||
|
},
|
||||||
|
|
||||||
|
'function-h2' : {
|
||||||
|
search: /(.+)([\n]?)/g,
|
||||||
|
replace: "== $1$2"
|
||||||
|
},
|
||||||
|
|
||||||
|
'function-h3' : {
|
||||||
|
search: /(.+)([\n]?)/g,
|
||||||
|
replace: "=== $1$2"
|
||||||
|
},
|
||||||
|
|
||||||
'function-link' : {
|
'function-link' : {
|
||||||
exec: function( txt, selText, $field ) {
|
exec: function( txt, selText, $field ) {
|
||||||
var results = null;
|
var results = null;
|
||||||
@@ -102,20 +117,20 @@ var ASCIIDoc = {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
$.GollumEditor.defineLanguage('asciidoc', ASCIIDoc);
|
$.GollumEditor.defineLanguage('asciidoc', AsciiDoc);
|
||||||
|
|
||||||
|
|
||||||
var ASCIIDocHelp = [
|
var AsciiDocHelp = [
|
||||||
{
|
{
|
||||||
menuName: 'Text Formatting',
|
menuName: 'Text Formatting',
|
||||||
content: [
|
content: [
|
||||||
{
|
{
|
||||||
menuName: 'Headers',
|
menuName: 'Headers',
|
||||||
data: '<p>ASCIIDoc headers can be written in two ways: with differing underlines or with different indentation using <code>=</code> (equals sign). ASCIIDoc supports headings 1-4. The editor will automatically use the <code>=</code> notation. To create a level one header, prefix your line with one <code>=</code>. Level two headers are created with <code>==</code> and so on.</p>'
|
data: '<p>AsciiDoc headers can be written in two ways: with differing underlines or with different indentation using <code>=</code> (equals sign). AsciiDoc supports headings 1-4. The editor will automatically use the <code>=</code> notation. To create a level one header, prefix your line with one <code>=</code>. Level two headers are created with <code>==</code> and so on.</p>'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
menuName: 'Bold / Italic',
|
menuName: 'Bold / Italic',
|
||||||
data: '<p>To display text as <strong>bold</strong>, wrap the text in <code>*</code> (asterisks). To display text as <em>italic</em>, wrap the text in <code>_</code> (underscores). To create <code>monospace</code> text, wrap the text in <code>+</code> (plus signs).'
|
data: '<p>To display text as <strong>bold</strong>, wrap the text in <code>*</code> (asterisks). To display text as <em>italic</em>, wrap the text in <code>_</code> (underscores). To create <code>monospace</code> text, wrap the text in <code>`</code> (backtick).'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
menuName: 'Scripts',
|
menuName: 'Scripts',
|
||||||
@@ -123,7 +138,7 @@ var ASCIIDocHelp = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
menuName: 'Special Characters',
|
menuName: 'Special Characters',
|
||||||
data: '<p>ASCIIDoc will automatically convert textual representations of commonly-used special characters. For example, <code>(R)</code> becomes ®, <code>(C)</code> becomes © and <code>(TM)</code> becomes ™.</p>'
|
data: '<p>AsciiDoc will automatically convert textual representations of commonly-used special characters. For example, <code>(R)</code> becomes ®, <code>(C)</code> becomes © and <code>(TM)</code> becomes ™.</p>'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -132,7 +147,7 @@ var ASCIIDocHelp = [
|
|||||||
content: [
|
content: [
|
||||||
{
|
{
|
||||||
menuName: 'Paragraphs',
|
menuName: 'Paragraphs',
|
||||||
data: '<p>ASCIIDoc allows paragraphs to have optional titles or icons to denote special sections. To make a normal paragraph, simply add a line between blocks and a new paragraph will start. If you want to title your paragraphs, adda line prefixed by <code>.</code> (full stop). An example paragraph with optional title is displayed below:<br><br><code>.Optional Title<br><br>This is my paragraph. It is two sentences long.</code></p>'
|
data: '<p>AsciiDoc allows paragraphs to have optional titles or icons to denote special sections. To make a normal paragraph, simply add a line between blocks and a new paragraph will start. If you want to title your paragraphs, adda line prefixed by <code>.</code> (full stop). An example paragraph with optional title is displayed below:<br><br><code>.Optional Title<br><br>This is my paragraph. It is two sentences long.</code></p>'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
menuName: 'Source Blocks',
|
menuName: 'Source Blocks',
|
||||||
@@ -157,12 +172,12 @@ var ASCIIDocHelp = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
menuName: 'Images',
|
menuName: 'Images',
|
||||||
data: '<p>Images in ASCIIDoc work much like hyperlinks, but image URLs are prefixed with <code>image:</code>. For example, to link to an image at <code>images/icons/home.png</code>, write <code>image:images/icons/home.png</code>. Alt text can be added by appending the text to the URI in <code>[</code> (brackets).</p>'
|
data: '<p>Images in AsciiDoc work much like hyperlinks, but image URLs are prefixed with <code>image:</code>. For example, to link to an image at <code>images/icons/home.png</code>, write <code>image:images/icons/home.png</code>. Alt text can be added by appending the text to the URI in <code>[</code> (brackets).</p>'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
$.GollumEditor.defineHelp('asciidoc', ASCIIDocHelp);
|
$.GollumEditor.defineHelp('asciidoc', AsciiDocHelp);
|
||||||
|
|
||||||
})(jQuery);
|
})(jQuery);
|
||||||
|
|||||||
@@ -13,6 +13,12 @@
|
|||||||
markupCreated: false,
|
markupCreated: false,
|
||||||
markup: '',
|
markup: '',
|
||||||
|
|
||||||
|
currentAspect: function(){
|
||||||
|
if (window.innerWidth < 480) return "small-mobile";
|
||||||
|
if ($('#gollum-dialog-dialog').css('position') == 'fixed') return "large-mobile";
|
||||||
|
return "desktop";
|
||||||
|
},
|
||||||
|
|
||||||
attachEvents: function( evtOK ) {
|
attachEvents: function( evtOK ) {
|
||||||
$('#gollum-dialog-action-ok').click(function( e ) {
|
$('#gollum-dialog-action-ok').click(function( e ) {
|
||||||
Dialog.eventOK( e, evtOK );
|
Dialog.eventOK( e, evtOK );
|
||||||
@@ -185,6 +191,8 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$(window).unbind('resize', Dialog.resize);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -268,14 +276,28 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$(window).bind('resize', Dialog.resize);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
resize: function(){
|
||||||
|
Dialog.position();
|
||||||
|
},
|
||||||
|
|
||||||
position: function() {
|
position: function() {
|
||||||
var dialogHeight = $('#gollum-dialog-dialog-inner').height();
|
if (Dialog.currentAspect() == "small-mobile") {
|
||||||
$('#gollum-dialog-dialog-inner')
|
$('#gollum-dialog-dialog-inner').css('height', '100%').css('margin-top', 'auto');
|
||||||
.css('height', dialogHeight + 'px')
|
}
|
||||||
.css('margin-top', -1 * parseInt( dialogHeight / 2 ));
|
else if (Dialog.currentAspect() == "large-mobile") {
|
||||||
|
$('#gollum-dialog-dialog-inner').css('height', 'auto').css('margin-top', 'auto');
|
||||||
|
}
|
||||||
|
else if (Dialog.currentAspect() == "desktop") {
|
||||||
|
var dialogHeight = $('#gollum-dialog-dialog-inner').height();
|
||||||
|
$('#gollum-dialog-dialog-inner')
|
||||||
|
.css('height', dialogHeight + 'px')
|
||||||
|
.css('margin-top', -1 * parseInt( dialogHeight / 2 ));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -46,13 +46,16 @@ var Editor = require("./editor").Editor;
|
|||||||
var EditSession = require("./edit_session").EditSession;
|
var EditSession = require("./edit_session").EditSession;
|
||||||
var UndoManager = require("./undomanager").UndoManager;
|
var UndoManager = require("./undomanager").UndoManager;
|
||||||
var Renderer = require("./virtual_renderer").VirtualRenderer;
|
var Renderer = require("./virtual_renderer").VirtualRenderer;
|
||||||
var MultiSelect = require("./multi_select").MultiSelect;
|
|
||||||
|
|
||||||
// The following require()s are for inclusion in the built ace file
|
// The following require()s are for inclusion in the built ace file
|
||||||
require("./worker/worker_client");
|
require("./worker/worker_client");
|
||||||
require("./keyboard/hash_handler");
|
require("./keyboard/hash_handler");
|
||||||
require("./placeholder");
|
require("./placeholder");
|
||||||
|
require("./multi_select");
|
||||||
require("./mode/folding/fold_mode");
|
require("./mode/folding/fold_mode");
|
||||||
|
require("./theme/textmate");
|
||||||
|
require("./ext/error_marker");
|
||||||
|
|
||||||
exports.config = require("./config");
|
exports.config = require("./config");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -71,34 +74,53 @@ exports.require = require;
|
|||||||
exports.edit = function(el) {
|
exports.edit = function(el) {
|
||||||
if (typeof(el) == "string") {
|
if (typeof(el) == "string") {
|
||||||
var _id = el;
|
var _id = el;
|
||||||
var el = document.getElementById(_id);
|
el = document.getElementById(_id);
|
||||||
if (!el)
|
if (!el)
|
||||||
throw "ace.edit can't find div #" + _id;
|
throw new Error("ace.edit can't find div #" + _id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (el.env && el.env.editor instanceof Editor)
|
if (el && el.env && el.env.editor instanceof Editor)
|
||||||
return el.env.editor;
|
return el.env.editor;
|
||||||
|
|
||||||
var doc = exports.createEditSession(dom.getInnerText(el));
|
var value = "";
|
||||||
el.innerHTML = '';
|
if (el && /input|textarea/i.test(el.tagName)) {
|
||||||
|
var oldNode = el;
|
||||||
|
value = oldNode.value;
|
||||||
|
el = dom.createElement("pre");
|
||||||
|
oldNode.parentNode.replaceChild(el, oldNode);
|
||||||
|
} else {
|
||||||
|
value = dom.getInnerText(el);
|
||||||
|
el.innerHTML = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
var doc = exports.createEditSession(value);
|
||||||
|
|
||||||
var editor = new Editor(new Renderer(el));
|
var editor = new Editor(new Renderer(el));
|
||||||
new MultiSelect(editor);
|
|
||||||
editor.setSession(doc);
|
editor.setSession(doc);
|
||||||
|
|
||||||
var env = {
|
var env = {
|
||||||
document: doc,
|
document: doc,
|
||||||
editor: editor,
|
editor: editor,
|
||||||
onResize: editor.resize.bind(editor)
|
onResize: editor.resize.bind(editor, null)
|
||||||
};
|
};
|
||||||
|
if (oldNode) env.textarea = oldNode;
|
||||||
event.addListener(window, "resize", env.onResize);
|
event.addListener(window, "resize", env.onResize);
|
||||||
el.env = editor.env = env;
|
editor.on("destroy", function() {
|
||||||
|
event.removeListener(window, "resize", env.onResize);
|
||||||
|
env.editor.container.env = null; // prevent memory leak on old ie
|
||||||
|
});
|
||||||
|
editor.container.env = editor.env = env;
|
||||||
return editor;
|
return editor;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new [[EditSession]], and returns the associated [[Document]].
|
||||||
|
* @param {Document | String} text {:textParam}
|
||||||
|
* @param {TextMode} mode {:modeParam}
|
||||||
|
*
|
||||||
|
**/
|
||||||
exports.createEditSession = function(text, mode) {
|
exports.createEditSession = function(text, mode) {
|
||||||
var doc = new EditSession(text, doc);
|
var doc = new EditSession(text, mode);
|
||||||
doc.setUndoManager(new UndoManager());
|
doc.setUndoManager(new UndoManager());
|
||||||
return doc;
|
return doc;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 2010, Ajax.org B.V.
|
* Copyright (c) 2010, Ajax.org B.V.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
* * Redistributions of source code must retain the above copyright
|
* * Redistributions of source code must retain the above copyright
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
* * Neither the name of Ajax.org B.V. nor the
|
* * Neither the name of Ajax.org B.V. nor the
|
||||||
* names of its contributors may be used to endorse or promote products
|
* names of its contributors may be used to endorse or promote products
|
||||||
* derived from this software without specific prior written permission.
|
* derived from this software without specific prior written permission.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
@@ -35,8 +35,8 @@ var oop = require("./lib/oop");
|
|||||||
var EventEmitter = require("./lib/event_emitter").EventEmitter;
|
var EventEmitter = require("./lib/event_emitter").EventEmitter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Defines the floating pointer in the document. Whenever text is inserted or deleted before the cursor, the position of the cursor is updated.
|
* Defines a floating pointer in the document. Whenever text is inserted or deleted before the cursor, the position of the anchor is updated.
|
||||||
*
|
*
|
||||||
* @class Anchor
|
* @class Anchor
|
||||||
**/
|
**/
|
||||||
@@ -52,112 +52,112 @@ var EventEmitter = require("./lib/event_emitter").EventEmitter;
|
|||||||
**/
|
**/
|
||||||
|
|
||||||
var Anchor = exports.Anchor = function(doc, row, column) {
|
var Anchor = exports.Anchor = function(doc, row, column) {
|
||||||
this.document = doc;
|
this.$onChange = this.onChange.bind(this);
|
||||||
|
this.attach(doc);
|
||||||
|
|
||||||
if (typeof column == "undefined")
|
if (typeof column == "undefined")
|
||||||
this.setPosition(row.row, row.column);
|
this.setPosition(row.row, row.column);
|
||||||
else
|
else
|
||||||
this.setPosition(row, column);
|
this.setPosition(row, column);
|
||||||
|
|
||||||
this.$onChange = this.onChange.bind(this);
|
|
||||||
doc.on("change", this.$onChange);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
oop.implement(this, EventEmitter);
|
oop.implement(this, EventEmitter);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an object identifying the `row` and `column` position of the current anchor.
|
* Returns an object identifying the `row` and `column` position of the current anchor.
|
||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
**/
|
**/
|
||||||
|
|
||||||
this.getPosition = function() {
|
this.getPosition = function() {
|
||||||
return this.$clipPositionToDocument(this.row, this.column);
|
return this.$clipPositionToDocument(this.row, this.column);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Returns the current document.
|
* Returns the current document.
|
||||||
* @returns {Document}
|
* @returns {Document}
|
||||||
**/
|
**/
|
||||||
|
|
||||||
this.getDocument = function() {
|
this.getDocument = function() {
|
||||||
return this.document;
|
return this.document;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* experimental: allows anchor to stick to the next on the left
|
||||||
|
*/
|
||||||
|
this.$insertRight = false;
|
||||||
|
/**
|
||||||
* Fires whenever the anchor position changes.
|
* Fires whenever the anchor position changes.
|
||||||
*
|
*
|
||||||
* Both of these objects have a `row` and `column` property corresponding to the position.
|
* Both of these objects have a `row` and `column` property corresponding to the position.
|
||||||
*
|
*
|
||||||
* Events that can trigger this function include [[Anchor.setPosition `setPosition()`]].
|
* Events that can trigger this function include [[Anchor.setPosition `setPosition()`]].
|
||||||
*
|
|
||||||
* @event change
|
|
||||||
* @param {Object} e An object containing information about the anchor position. It has two properties:
|
|
||||||
* - `old`: An object describing the old Anchor position
|
|
||||||
* - `value`: An object describing the new Anchor position
|
|
||||||
*
|
*
|
||||||
|
* @event change
|
||||||
|
* @param {Object} e An object containing information about the anchor position. It has two properties:
|
||||||
|
* - `old`: An object describing the old Anchor position
|
||||||
|
* - `value`: An object describing the new Anchor position
|
||||||
*
|
*
|
||||||
**/
|
**/
|
||||||
|
|
||||||
this.onChange = function(e) {
|
this.onChange = function(e) {
|
||||||
var delta = e.data;
|
var delta = e.data;
|
||||||
var range = delta.range;
|
var range = delta.range;
|
||||||
|
|
||||||
if (range.start.row == range.end.row && range.start.row != this.row)
|
if (range.start.row == range.end.row && range.start.row != this.row)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (range.start.row > this.row)
|
if (range.start.row > this.row)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (range.start.row == this.row && range.start.column > this.column)
|
if (range.start.row == this.row && range.start.column > this.column)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var row = this.row;
|
var row = this.row;
|
||||||
var column = this.column;
|
var column = this.column;
|
||||||
|
var start = range.start;
|
||||||
|
var end = range.end;
|
||||||
|
|
||||||
if (delta.action === "insertText") {
|
if (delta.action === "insertText") {
|
||||||
if (range.start.row === row && range.start.column <= column) {
|
if (start.row === row && start.column <= column) {
|
||||||
if (range.start.row === range.end.row) {
|
if (start.column === column && this.$insertRight) {
|
||||||
column += range.end.column - range.start.column;
|
// do nothing
|
||||||
|
} else if (start.row === end.row) {
|
||||||
|
column += end.column - start.column;
|
||||||
|
} else {
|
||||||
|
column -= start.column;
|
||||||
|
row += end.row - start.row;
|
||||||
}
|
}
|
||||||
else {
|
} else if (start.row !== end.row && start.row < row) {
|
||||||
column -= range.start.column;
|
row += end.row - start.row;
|
||||||
row += range.end.row - range.start.row;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (range.start.row !== range.end.row && range.start.row < row) {
|
|
||||||
row += range.end.row - range.start.row;
|
|
||||||
}
|
}
|
||||||
} else if (delta.action === "insertLines") {
|
} else if (delta.action === "insertLines") {
|
||||||
if (range.start.row <= row) {
|
if (start.row === row && column === 0 && this.$insertRight) {
|
||||||
row += range.end.row - range.start.row;
|
// do nothing
|
||||||
}
|
}
|
||||||
}
|
else if (start.row <= row) {
|
||||||
else if (delta.action == "removeText") {
|
row += end.row - start.row;
|
||||||
if (range.start.row == row && range.start.column < column) {
|
}
|
||||||
if (range.end.column >= column)
|
} else if (delta.action === "removeText") {
|
||||||
column = range.start.column;
|
if (start.row === row && start.column < column) {
|
||||||
|
if (end.column >= column)
|
||||||
|
column = start.column;
|
||||||
else
|
else
|
||||||
column = Math.max(0, column - (range.end.column - range.start.column));
|
column = Math.max(0, column - (end.column - start.column));
|
||||||
|
|
||||||
} else if (range.start.row !== range.end.row && range.start.row < row) {
|
} else if (start.row !== end.row && start.row < row) {
|
||||||
if (range.end.row == row) {
|
if (end.row === row)
|
||||||
column = Math.max(0, column - range.end.column) + range.start.column;
|
column = Math.max(0, column - end.column) + start.column;
|
||||||
}
|
row -= (end.row - start.row);
|
||||||
row -= (range.end.row - range.start.row);
|
} else if (end.row === row) {
|
||||||
}
|
row -= end.row - start.row;
|
||||||
else if (range.end.row == row) {
|
column = Math.max(0, column - end.column) + start.column;
|
||||||
row -= range.end.row - range.start.row;
|
|
||||||
column = Math.max(0, column - range.end.column) + range.start.column;
|
|
||||||
}
|
}
|
||||||
} else if (delta.action == "removeLines") {
|
} else if (delta.action == "removeLines") {
|
||||||
if (range.start.row <= row) {
|
if (start.row <= row) {
|
||||||
if (range.end.row <= row)
|
if (end.row <= row)
|
||||||
row -= range.end.row - range.start.row;
|
row -= end.row - start.row;
|
||||||
else {
|
else {
|
||||||
row = range.start.row;
|
row = start.row;
|
||||||
column = 0;
|
column = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -166,16 +166,13 @@ var Anchor = exports.Anchor = function(doc, row, column) {
|
|||||||
this.setPosition(row, column, true);
|
this.setPosition(row, column, true);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the anchor position to the specified row and column. If `noClip` is `true`, the position is not clipped.
|
* Sets the anchor position to the specified row and column. If `noClip` is `true`, the position is not clipped.
|
||||||
* @param {Number} row The row index to move the anchor to
|
* @param {Number} row The row index to move the anchor to
|
||||||
* @param {Number} column The column index to move the anchor to
|
* @param {Number} column The column index to move the anchor to
|
||||||
* @param {Boolean} noClip Identifies if you want the position to be clipped
|
* @param {Boolean} noClip Identifies if you want the position to be clipped
|
||||||
*
|
*
|
||||||
*
|
|
||||||
*
|
|
||||||
**/
|
**/
|
||||||
|
|
||||||
this.setPosition = function(row, column, noClip) {
|
this.setPosition = function(row, column, noClip) {
|
||||||
var pos;
|
var pos;
|
||||||
if (noClip) {
|
if (noClip) {
|
||||||
@@ -183,47 +180,47 @@ var Anchor = exports.Anchor = function(doc, row, column) {
|
|||||||
row: row,
|
row: row,
|
||||||
column: column
|
column: column
|
||||||
};
|
};
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
pos = this.$clipPositionToDocument(row, column);
|
pos = this.$clipPositionToDocument(row, column);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.row == pos.row && this.column == pos.column)
|
if (this.row == pos.row && this.column == pos.column)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var old = {
|
var old = {
|
||||||
row: this.row,
|
row: this.row,
|
||||||
column: this.column
|
column: this.column
|
||||||
};
|
};
|
||||||
|
|
||||||
this.row = pos.row;
|
this.row = pos.row;
|
||||||
this.column = pos.column;
|
this.column = pos.column;
|
||||||
this._emit("change", {
|
this._signal("change", {
|
||||||
old: old,
|
old: old,
|
||||||
value: pos
|
value: pos
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When called, the `'change'` event listener is removed.
|
* When called, the `"change"` event listener is removed.
|
||||||
*
|
*
|
||||||
**/
|
**/
|
||||||
|
|
||||||
this.detach = function() {
|
this.detach = function() {
|
||||||
this.document.removeEventListener("change", this.$onChange);
|
this.document.removeEventListener("change", this.$onChange);
|
||||||
};
|
};
|
||||||
|
this.attach = function(doc) {
|
||||||
/**
|
this.document = doc || this.document;
|
||||||
|
this.document.on("change", this.$onChange);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
* Clips the anchor position to the specified row and column.
|
* Clips the anchor position to the specified row and column.
|
||||||
* @param {Number} row The row index to clip the anchor to
|
* @param {Number} row The row index to clip the anchor to
|
||||||
* @param {Number} column The column index to clip the anchor to
|
* @param {Number} column The column index to clip the anchor to
|
||||||
*
|
*
|
||||||
*
|
|
||||||
*
|
|
||||||
**/
|
**/
|
||||||
this.$clipPositionToDocument = function(row, column) {
|
this.$clipPositionToDocument = function(row, column) {
|
||||||
var pos = {};
|
var pos = {};
|
||||||
|
|
||||||
if (row >= this.document.getLength()) {
|
if (row >= this.document.getLength()) {
|
||||||
pos.row = Math.max(0, this.document.getLength() - 1);
|
pos.row = Math.max(0, this.document.getLength() - 1);
|
||||||
pos.column = this.document.getLine(pos.row).length;
|
pos.column = this.document.getLine(pos.row).length;
|
||||||
@@ -236,13 +233,13 @@ var Anchor = exports.Anchor = function(doc, row, column) {
|
|||||||
pos.row = row;
|
pos.row = row;
|
||||||
pos.column = Math.min(this.document.getLine(pos.row).length, Math.max(0, column));
|
pos.column = Math.min(this.document.getLine(pos.row).length, Math.max(0, column));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (column < 0)
|
if (column < 0)
|
||||||
pos.column = 0;
|
pos.column = 0;
|
||||||
|
|
||||||
return pos;
|
return pos;
|
||||||
};
|
};
|
||||||
|
|
||||||
}).call(Anchor.prototype);
|
}).call(Anchor.prototype);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -57,6 +57,15 @@ module.exports = {
|
|||||||
doc.insert({row: 1, column: 1}, "123");
|
doc.insert({row: 1, column: 1}, "123");
|
||||||
assert.position(anchor.getPosition(), 1, 7);
|
assert.position(anchor.getPosition(), 1, 7);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"test insert text at anchor should not move anchor when insertRight is true": function() {
|
||||||
|
var doc = new Document("juhu\nkinners");
|
||||||
|
var anchor = new Anchor(doc, 1, 4);
|
||||||
|
anchor.$insertRight = true;
|
||||||
|
|
||||||
|
doc.insert({row: 1, column: 4}, "123");
|
||||||
|
assert.position(anchor.getPosition(), 1, 4);
|
||||||
|
},
|
||||||
|
|
||||||
"test insert lines before cursor should move anchor row": function() {
|
"test insert lines before cursor should move anchor row": function() {
|
||||||
var doc = new Document("juhu\nkinners");
|
var doc = new Document("juhu\nkinners");
|
||||||
@@ -65,6 +74,32 @@ module.exports = {
|
|||||||
doc.insertLines(1, ["123", "456"]);
|
doc.insertLines(1, ["123", "456"]);
|
||||||
assert.position(anchor.getPosition(), 3, 4);
|
assert.position(anchor.getPosition(), 3, 4);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"test insert lines at anchor position should move anchor down": function() {
|
||||||
|
var doc = new Document("juhu\nkinners");
|
||||||
|
var anchor = new Anchor(doc, 1, 0);
|
||||||
|
|
||||||
|
doc.insertLines(1, ["line"]);
|
||||||
|
assert.position(anchor.getPosition(), 2, 0);
|
||||||
|
},
|
||||||
|
|
||||||
|
"test insert lines at anchor position should not move anchor down when insertRight is true and column is 0": function() {
|
||||||
|
var doc = new Document("juhu\nkinners");
|
||||||
|
var anchor = new Anchor(doc, 1, 0);
|
||||||
|
anchor.$insertRight = true;
|
||||||
|
|
||||||
|
doc.insertLines(1, ["line"]);
|
||||||
|
assert.position(anchor.getPosition(), 1, 0);
|
||||||
|
},
|
||||||
|
|
||||||
|
"test insert lines at anchor row should move anchor down when column > 0": function() {
|
||||||
|
var doc = new Document("juhu\nkinners");
|
||||||
|
var anchor = new Anchor(doc, 1, 2);
|
||||||
|
anchor.$insertRight = true;
|
||||||
|
|
||||||
|
doc.insertLines(1, ["line"]);
|
||||||
|
assert.position(anchor.getPosition(), 2, 2);
|
||||||
|
},
|
||||||
|
|
||||||
"test insert new line before cursor should move anchor column": function() {
|
"test insert new line before cursor should move anchor column": function() {
|
||||||
var doc = new Document("juhu\nkinners");
|
var doc = new Document("juhu\nkinners");
|
||||||
@@ -167,6 +202,17 @@ module.exports = {
|
|||||||
});
|
});
|
||||||
|
|
||||||
doc.remove(new Range(2, 0, 2, 1));
|
doc.remove(new Range(2, 0, 2, 1));
|
||||||
|
},
|
||||||
|
|
||||||
|
"test insert/remove lines at the end of the document": function() {
|
||||||
|
var doc = new Document("juhu\nkinners\n123");
|
||||||
|
var anchor = new Anchor(doc, 2, 4);
|
||||||
|
|
||||||
|
doc.removeLines(0, 3);
|
||||||
|
assert.position(anchor.getPosition(), 0, 0);
|
||||||
|
doc.insertLines(0, ["a", "b", "c"]);
|
||||||
|
assert.position(anchor.getPosition(), 3, 0);
|
||||||
|
assert.equal(doc.getValue(), "a\nb\nc\n");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,497 @@
|
|||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Distributed under the BSD license:
|
||||||
|
*
|
||||||
|
* Copyright (c) 2012, Ajax.org B.V.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of Ajax.org B.V. nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
define(function(require, exports, module) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var HashHandler = require("./keyboard/hash_handler").HashHandler;
|
||||||
|
var AcePopup = require("./autocomplete/popup").AcePopup;
|
||||||
|
var util = require("./autocomplete/util");
|
||||||
|
var event = require("./lib/event");
|
||||||
|
var lang = require("./lib/lang");
|
||||||
|
var dom = require("./lib/dom");
|
||||||
|
var snippetManager = require("./snippets").snippetManager;
|
||||||
|
|
||||||
|
var Autocomplete = function() {
|
||||||
|
this.autoInsert = false;
|
||||||
|
this.autoSelect = true;
|
||||||
|
this.exactMatch = false;
|
||||||
|
this.gatherCompletionsId = 0;
|
||||||
|
this.keyboardHandler = new HashHandler();
|
||||||
|
this.keyboardHandler.bindKeys(this.commands);
|
||||||
|
|
||||||
|
this.blurListener = this.blurListener.bind(this);
|
||||||
|
this.changeListener = this.changeListener.bind(this);
|
||||||
|
this.mousedownListener = this.mousedownListener.bind(this);
|
||||||
|
this.mousewheelListener = this.mousewheelListener.bind(this);
|
||||||
|
|
||||||
|
this.changeTimer = lang.delayedCall(function() {
|
||||||
|
this.updateCompletions(true);
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
|
this.tooltipTimer = lang.delayedCall(this.updateDocTooltip.bind(this), 50);
|
||||||
|
};
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
|
||||||
|
this.$init = function() {
|
||||||
|
this.popup = new AcePopup(document.body || document.documentElement);
|
||||||
|
this.popup.on("click", function(e) {
|
||||||
|
this.insertMatch();
|
||||||
|
e.stop();
|
||||||
|
}.bind(this));
|
||||||
|
this.popup.focus = this.editor.focus.bind(this.editor);
|
||||||
|
this.popup.on("show", this.tooltipTimer.bind(null, null));
|
||||||
|
this.popup.on("select", this.tooltipTimer.bind(null, null));
|
||||||
|
this.popup.on("changeHoverMarker", this.tooltipTimer.bind(null, null));
|
||||||
|
return this.popup;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.getPopup = function() {
|
||||||
|
return this.popup || this.$init();
|
||||||
|
};
|
||||||
|
|
||||||
|
this.openPopup = function(editor, prefix, keepPopupPosition) {
|
||||||
|
if (!this.popup)
|
||||||
|
this.$init();
|
||||||
|
|
||||||
|
this.popup.setData(this.completions.filtered);
|
||||||
|
|
||||||
|
editor.keyBinding.addKeyboardHandler(this.keyboardHandler);
|
||||||
|
|
||||||
|
var renderer = editor.renderer;
|
||||||
|
this.popup.setRow(this.autoSelect ? 0 : -1);
|
||||||
|
if (!keepPopupPosition) {
|
||||||
|
this.popup.setTheme(editor.getTheme());
|
||||||
|
this.popup.setFontSize(editor.getFontSize());
|
||||||
|
|
||||||
|
var lineHeight = renderer.layerConfig.lineHeight;
|
||||||
|
|
||||||
|
var pos = renderer.$cursorLayer.getPixelPosition(this.base, true);
|
||||||
|
pos.left -= this.popup.getTextLeftOffset();
|
||||||
|
|
||||||
|
var rect = editor.container.getBoundingClientRect();
|
||||||
|
pos.top += rect.top - renderer.layerConfig.offset;
|
||||||
|
pos.left += rect.left - editor.renderer.scrollLeft;
|
||||||
|
pos.left += renderer.$gutterLayer.gutterWidth;
|
||||||
|
|
||||||
|
this.popup.show(pos, lineHeight);
|
||||||
|
} else if (keepPopupPosition && !prefix) {
|
||||||
|
this.detach();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.detach = function() {
|
||||||
|
this.editor.keyBinding.removeKeyboardHandler(this.keyboardHandler);
|
||||||
|
this.editor.off("changeSelection", this.changeListener);
|
||||||
|
this.editor.off("blur", this.blurListener);
|
||||||
|
this.editor.off("mousedown", this.mousedownListener);
|
||||||
|
this.editor.off("mousewheel", this.mousewheelListener);
|
||||||
|
this.changeTimer.cancel();
|
||||||
|
this.hideDocTooltip();
|
||||||
|
|
||||||
|
this.gatherCompletionsId += 1;
|
||||||
|
if (this.popup && this.popup.isOpen)
|
||||||
|
this.popup.hide();
|
||||||
|
|
||||||
|
if (this.base)
|
||||||
|
this.base.detach();
|
||||||
|
this.activated = false;
|
||||||
|
this.completions = this.base = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.changeListener = function(e) {
|
||||||
|
var cursor = this.editor.selection.lead;
|
||||||
|
if (cursor.row != this.base.row || cursor.column < this.base.column) {
|
||||||
|
this.detach();
|
||||||
|
}
|
||||||
|
if (this.activated)
|
||||||
|
this.changeTimer.schedule();
|
||||||
|
else
|
||||||
|
this.detach();
|
||||||
|
};
|
||||||
|
|
||||||
|
this.blurListener = function(e) {
|
||||||
|
// we have to check if activeElement is a child of popup because
|
||||||
|
// on IE preventDefault doesn't stop scrollbar from being focussed
|
||||||
|
var el = document.activeElement;
|
||||||
|
var text = this.editor.textInput.getElement()
|
||||||
|
if (el != text && el.parentNode != this.popup.container
|
||||||
|
&& el != this.tooltipNode && e.relatedTarget != this.tooltipNode
|
||||||
|
&& e.relatedTarget != text
|
||||||
|
) {
|
||||||
|
this.detach();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.mousedownListener = function(e) {
|
||||||
|
this.detach();
|
||||||
|
};
|
||||||
|
|
||||||
|
this.mousewheelListener = function(e) {
|
||||||
|
this.detach();
|
||||||
|
};
|
||||||
|
|
||||||
|
this.goTo = function(where) {
|
||||||
|
var row = this.popup.getRow();
|
||||||
|
var max = this.popup.session.getLength() - 1;
|
||||||
|
|
||||||
|
switch(where) {
|
||||||
|
case "up": row = row <= 0 ? max : row - 1; break;
|
||||||
|
case "down": row = row >= max ? -1 : row + 1; break;
|
||||||
|
case "start": row = 0; break;
|
||||||
|
case "end": row = max; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.popup.setRow(row);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.insertMatch = function(data) {
|
||||||
|
if (!data)
|
||||||
|
data = this.popup.getData(this.popup.getRow());
|
||||||
|
if (!data)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (data.completer && data.completer.insertMatch) {
|
||||||
|
data.completer.insertMatch(this.editor, data);
|
||||||
|
} else {
|
||||||
|
if (this.completions.filterText) {
|
||||||
|
var ranges = this.editor.selection.getAllRanges();
|
||||||
|
for (var i = 0, range; range = ranges[i]; i++) {
|
||||||
|
range.start.column -= this.completions.filterText.length;
|
||||||
|
this.editor.session.remove(range);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (data.snippet)
|
||||||
|
snippetManager.insertSnippet(this.editor, data.snippet);
|
||||||
|
else
|
||||||
|
this.editor.execCommand("insertstring", data.value || data);
|
||||||
|
}
|
||||||
|
this.detach();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
this.commands = {
|
||||||
|
"Up": function(editor) { editor.completer.goTo("up"); },
|
||||||
|
"Down": function(editor) { editor.completer.goTo("down"); },
|
||||||
|
"Ctrl-Up|Ctrl-Home": function(editor) { editor.completer.goTo("start"); },
|
||||||
|
"Ctrl-Down|Ctrl-End": function(editor) { editor.completer.goTo("end"); },
|
||||||
|
|
||||||
|
"Esc": function(editor) { editor.completer.detach(); },
|
||||||
|
"Space": function(editor) { editor.completer.detach(); editor.insert(" ");},
|
||||||
|
"Return": function(editor) { return editor.completer.insertMatch(); },
|
||||||
|
"Shift-Return": function(editor) { editor.completer.insertMatch(true); },
|
||||||
|
"Tab": function(editor) {
|
||||||
|
var result = editor.completer.insertMatch();
|
||||||
|
if (!result && !editor.tabstopManager)
|
||||||
|
editor.completer.goTo("down");
|
||||||
|
else
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
|
||||||
|
"PageUp": function(editor) { editor.completer.popup.gotoPageUp(); },
|
||||||
|
"PageDown": function(editor) { editor.completer.popup.gotoPageDown(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
this.gatherCompletions = function(editor, callback) {
|
||||||
|
var session = editor.getSession();
|
||||||
|
var pos = editor.getCursorPosition();
|
||||||
|
|
||||||
|
var line = session.getLine(pos.row);
|
||||||
|
var prefix = util.retrievePrecedingIdentifier(line, pos.column);
|
||||||
|
|
||||||
|
this.base = session.doc.createAnchor(pos.row, pos.column - prefix.length);
|
||||||
|
this.base.$insertRight = true;
|
||||||
|
|
||||||
|
var matches = [];
|
||||||
|
var total = editor.completers.length;
|
||||||
|
editor.completers.forEach(function(completer, i) {
|
||||||
|
completer.getCompletions(editor, session, pos, prefix, function(err, results) {
|
||||||
|
if (!err)
|
||||||
|
matches = matches.concat(results);
|
||||||
|
// Fetch prefix again, because they may have changed by now
|
||||||
|
var pos = editor.getCursorPosition();
|
||||||
|
var line = session.getLine(pos.row);
|
||||||
|
callback(null, {
|
||||||
|
prefix: util.retrievePrecedingIdentifier(line, pos.column, results[0] && results[0].identifierRegex),
|
||||||
|
matches: matches,
|
||||||
|
finished: (--total === 0)
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.showPopup = function(editor) {
|
||||||
|
if (this.editor)
|
||||||
|
this.detach();
|
||||||
|
|
||||||
|
this.activated = true;
|
||||||
|
|
||||||
|
this.editor = editor;
|
||||||
|
if (editor.completer != this) {
|
||||||
|
if (editor.completer)
|
||||||
|
editor.completer.detach();
|
||||||
|
editor.completer = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
editor.on("changeSelection", this.changeListener);
|
||||||
|
editor.on("blur", this.blurListener);
|
||||||
|
editor.on("mousedown", this.mousedownListener);
|
||||||
|
editor.on("mousewheel", this.mousewheelListener);
|
||||||
|
|
||||||
|
this.updateCompletions();
|
||||||
|
};
|
||||||
|
|
||||||
|
this.updateCompletions = function(keepPopupPosition) {
|
||||||
|
if (keepPopupPosition && this.base && this.completions) {
|
||||||
|
var pos = this.editor.getCursorPosition();
|
||||||
|
var prefix = this.editor.session.getTextRange({start: this.base, end: pos});
|
||||||
|
if (prefix == this.completions.filterText)
|
||||||
|
return;
|
||||||
|
this.completions.setFilter(prefix);
|
||||||
|
if (!this.completions.filtered.length)
|
||||||
|
return this.detach();
|
||||||
|
if (this.completions.filtered.length == 1
|
||||||
|
&& this.completions.filtered[0].value == prefix
|
||||||
|
&& !this.completions.filtered[0].snippet)
|
||||||
|
return this.detach();
|
||||||
|
this.openPopup(this.editor, prefix, keepPopupPosition);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save current gatherCompletions session, session is close when a match is insert
|
||||||
|
var _id = this.gatherCompletionsId;
|
||||||
|
this.gatherCompletions(this.editor, function(err, results) {
|
||||||
|
// Only detach if result gathering is finished
|
||||||
|
var detachIfFinished = function() {
|
||||||
|
if (!results.finished) return;
|
||||||
|
return this.detach();
|
||||||
|
}.bind(this);
|
||||||
|
|
||||||
|
var prefix = results.prefix;
|
||||||
|
var matches = results && results.matches;
|
||||||
|
|
||||||
|
if (!matches || !matches.length)
|
||||||
|
return detachIfFinished();
|
||||||
|
|
||||||
|
// Wrong prefix or wrong session -> ignore
|
||||||
|
if (prefix.indexOf(results.prefix) !== 0 || _id != this.gatherCompletionsId)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.completions = new FilteredList(matches);
|
||||||
|
|
||||||
|
if (this.exactMatch)
|
||||||
|
this.completions.exactMatch = true;
|
||||||
|
|
||||||
|
this.completions.setFilter(prefix);
|
||||||
|
var filtered = this.completions.filtered;
|
||||||
|
|
||||||
|
// No results
|
||||||
|
if (!filtered.length)
|
||||||
|
return detachIfFinished();
|
||||||
|
|
||||||
|
// One result equals to the prefix
|
||||||
|
if (filtered.length == 1 && filtered[0].value == prefix && !filtered[0].snippet)
|
||||||
|
return detachIfFinished();
|
||||||
|
|
||||||
|
// Autoinsert if one result
|
||||||
|
if (this.autoInsert && filtered.length == 1 && results.finished)
|
||||||
|
return this.insertMatch(filtered[0]);
|
||||||
|
|
||||||
|
this.openPopup(this.editor, prefix, keepPopupPosition);
|
||||||
|
}.bind(this));
|
||||||
|
};
|
||||||
|
|
||||||
|
this.cancelContextMenu = function() {
|
||||||
|
this.editor.$mouseHandler.cancelContextMenu();
|
||||||
|
};
|
||||||
|
|
||||||
|
this.updateDocTooltip = function() {
|
||||||
|
var popup = this.popup;
|
||||||
|
var all = popup.data;
|
||||||
|
var selected = all && (all[popup.getHoveredRow()] || all[popup.getRow()]);
|
||||||
|
var doc = null;
|
||||||
|
if (!selected || !this.editor || !this.popup.isOpen)
|
||||||
|
return this.hideDocTooltip();
|
||||||
|
this.editor.completers.some(function(completer) {
|
||||||
|
if (completer.getDocTooltip)
|
||||||
|
doc = completer.getDocTooltip(selected);
|
||||||
|
return doc;
|
||||||
|
});
|
||||||
|
if (!doc)
|
||||||
|
doc = selected;
|
||||||
|
|
||||||
|
if (typeof doc == "string")
|
||||||
|
doc = {docText: doc}
|
||||||
|
if (!doc || !(doc.docHTML || doc.docText))
|
||||||
|
return this.hideDocTooltip();
|
||||||
|
this.showDocTooltip(doc);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.showDocTooltip = function(item) {
|
||||||
|
if (!this.tooltipNode) {
|
||||||
|
this.tooltipNode = dom.createElement("div");
|
||||||
|
this.tooltipNode.className = "ace_tooltip ace_doc-tooltip";
|
||||||
|
this.tooltipNode.style.margin = 0;
|
||||||
|
this.tooltipNode.style.pointerEvents = "auto";
|
||||||
|
this.tooltipNode.tabIndex = -1;
|
||||||
|
this.tooltipNode.onblur = this.blurListener.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
var tooltipNode = this.tooltipNode;
|
||||||
|
if (item.docHTML) {
|
||||||
|
tooltipNode.innerHTML = item.docHTML;
|
||||||
|
} else if (item.docText) {
|
||||||
|
tooltipNode.textContent = item.docText;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!tooltipNode.parentNode)
|
||||||
|
document.body.appendChild(tooltipNode);
|
||||||
|
var popup = this.popup;
|
||||||
|
var rect = popup.container.getBoundingClientRect();
|
||||||
|
tooltipNode.style.top = popup.container.style.top;
|
||||||
|
tooltipNode.style.bottom = popup.container.style.bottom;
|
||||||
|
|
||||||
|
if (window.innerWidth - rect.right < 320) {
|
||||||
|
tooltipNode.style.right = window.innerWidth - rect.left + "px";
|
||||||
|
tooltipNode.style.left = "";
|
||||||
|
} else {
|
||||||
|
tooltipNode.style.left = (rect.right + 1) + "px";
|
||||||
|
tooltipNode.style.right = "";
|
||||||
|
}
|
||||||
|
tooltipNode.style.display = "block";
|
||||||
|
};
|
||||||
|
|
||||||
|
this.hideDocTooltip = function() {
|
||||||
|
this.tooltipTimer.cancel();
|
||||||
|
if (!this.tooltipNode) return;
|
||||||
|
var el = this.tooltipNode;
|
||||||
|
if (!this.editor.isFocused() && document.activeElement == el)
|
||||||
|
this.editor.focus();
|
||||||
|
this.tooltipNode = null;
|
||||||
|
if (el.parentNode)
|
||||||
|
el.parentNode.removeChild(el);
|
||||||
|
};
|
||||||
|
|
||||||
|
}).call(Autocomplete.prototype);
|
||||||
|
|
||||||
|
Autocomplete.startCommand = {
|
||||||
|
name: "startAutocomplete",
|
||||||
|
exec: function(editor) {
|
||||||
|
if (!editor.completer)
|
||||||
|
editor.completer = new Autocomplete();
|
||||||
|
editor.completer.autoInsert = false;
|
||||||
|
editor.completer.autoSelect = true;
|
||||||
|
editor.completer.showPopup(editor);
|
||||||
|
// prevent ctrl-space opening context menu on firefox on mac
|
||||||
|
editor.completer.cancelContextMenu();
|
||||||
|
},
|
||||||
|
bindKey: "Ctrl-Space|Ctrl-Shift-Space|Alt-Space"
|
||||||
|
};
|
||||||
|
|
||||||
|
var FilteredList = function(array, filterText, mutateData) {
|
||||||
|
this.all = array;
|
||||||
|
this.filtered = array;
|
||||||
|
this.filterText = filterText || "";
|
||||||
|
this.exactMatch = false;
|
||||||
|
};
|
||||||
|
(function(){
|
||||||
|
this.setFilter = function(str) {
|
||||||
|
if (str.length > this.filterText && str.lastIndexOf(this.filterText, 0) === 0)
|
||||||
|
var matches = this.filtered;
|
||||||
|
else
|
||||||
|
var matches = this.all;
|
||||||
|
|
||||||
|
this.filterText = str;
|
||||||
|
matches = this.filterCompletions(matches, this.filterText);
|
||||||
|
matches = matches.sort(function(a, b) {
|
||||||
|
return b.exactMatch - a.exactMatch || b.score - a.score;
|
||||||
|
});
|
||||||
|
|
||||||
|
// make unique
|
||||||
|
var prev = null;
|
||||||
|
matches = matches.filter(function(item){
|
||||||
|
var caption = item.snippet || item.caption || item.value;
|
||||||
|
if (caption === prev) return false;
|
||||||
|
prev = caption;
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.filtered = matches;
|
||||||
|
};
|
||||||
|
this.filterCompletions = function(items, needle) {
|
||||||
|
var results = [];
|
||||||
|
var upper = needle.toUpperCase();
|
||||||
|
var lower = needle.toLowerCase();
|
||||||
|
loop: for (var i = 0, item; item = items[i]; i++) {
|
||||||
|
var caption = item.value || item.caption || item.snippet;
|
||||||
|
if (!caption) continue;
|
||||||
|
var lastIndex = -1;
|
||||||
|
var matchMask = 0;
|
||||||
|
var penalty = 0;
|
||||||
|
var index, distance;
|
||||||
|
|
||||||
|
if (this.exactMatch) {
|
||||||
|
if (needle !== caption.substr(0, needle.length))
|
||||||
|
continue loop;
|
||||||
|
}else{
|
||||||
|
// caption char iteration is faster in Chrome but slower in Firefox, so lets use indexOf
|
||||||
|
for (var j = 0; j < needle.length; j++) {
|
||||||
|
// TODO add penalty on case mismatch
|
||||||
|
var i1 = caption.indexOf(lower[j], lastIndex + 1);
|
||||||
|
var i2 = caption.indexOf(upper[j], lastIndex + 1);
|
||||||
|
index = (i1 >= 0) ? ((i2 < 0 || i1 < i2) ? i1 : i2) : i2;
|
||||||
|
if (index < 0)
|
||||||
|
continue loop;
|
||||||
|
distance = index - lastIndex - 1;
|
||||||
|
if (distance > 0) {
|
||||||
|
// first char mismatch should be more sensitive
|
||||||
|
if (lastIndex === -1)
|
||||||
|
penalty += 10;
|
||||||
|
penalty += distance;
|
||||||
|
}
|
||||||
|
matchMask = matchMask | (1 << index);
|
||||||
|
lastIndex = index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
item.matchMask = matchMask;
|
||||||
|
item.exactMatch = penalty ? 0 : 1;
|
||||||
|
item.score = (item.score || 0) - penalty;
|
||||||
|
results.push(item);
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
};
|
||||||
|
}).call(FilteredList.prototype);
|
||||||
|
|
||||||
|
exports.Autocomplete = Autocomplete;
|
||||||
|
exports.FilteredList = FilteredList;
|
||||||
|
|
||||||
|
});
|
||||||
@@ -0,0 +1,341 @@
|
|||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Distributed under the BSD license:
|
||||||
|
*
|
||||||
|
* Copyright (c) 2012, Ajax.org B.V.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of Ajax.org B.V. nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
define(function(require, exports, module) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var EditSession = require("../edit_session").EditSession;
|
||||||
|
var Renderer = require("../virtual_renderer").VirtualRenderer;
|
||||||
|
var Editor = require("../editor").Editor;
|
||||||
|
var Range = require("../range").Range;
|
||||||
|
var event = require("../lib/event");
|
||||||
|
var lang = require("../lib/lang");
|
||||||
|
var dom = require("../lib/dom");
|
||||||
|
|
||||||
|
var $singleLineEditor = function(el) {
|
||||||
|
var renderer = new Renderer(el);
|
||||||
|
|
||||||
|
renderer.$maxLines = 4;
|
||||||
|
|
||||||
|
var editor = new Editor(renderer);
|
||||||
|
|
||||||
|
editor.setHighlightActiveLine(false);
|
||||||
|
editor.setShowPrintMargin(false);
|
||||||
|
editor.renderer.setShowGutter(false);
|
||||||
|
editor.renderer.setHighlightGutterLine(false);
|
||||||
|
|
||||||
|
editor.$mouseHandler.$focusWaitTimout = 0;
|
||||||
|
editor.$highlightTagPending = true;
|
||||||
|
|
||||||
|
return editor;
|
||||||
|
};
|
||||||
|
|
||||||
|
var AcePopup = function(parentNode) {
|
||||||
|
var el = dom.createElement("div");
|
||||||
|
var popup = new $singleLineEditor(el);
|
||||||
|
|
||||||
|
if (parentNode)
|
||||||
|
parentNode.appendChild(el);
|
||||||
|
el.style.display = "none";
|
||||||
|
popup.renderer.content.style.cursor = "default";
|
||||||
|
popup.renderer.setStyle("ace_autocomplete");
|
||||||
|
|
||||||
|
popup.setOption("displayIndentGuides", false);
|
||||||
|
popup.setOption("dragDelay", 150);
|
||||||
|
|
||||||
|
var noop = function(){};
|
||||||
|
|
||||||
|
popup.focus = noop;
|
||||||
|
popup.$isFocused = true;
|
||||||
|
|
||||||
|
popup.renderer.$cursorLayer.restartTimer = noop;
|
||||||
|
popup.renderer.$cursorLayer.element.style.opacity = 0;
|
||||||
|
|
||||||
|
popup.renderer.$maxLines = 8;
|
||||||
|
popup.renderer.$keepTextAreaAtCursor = false;
|
||||||
|
|
||||||
|
popup.setHighlightActiveLine(false);
|
||||||
|
// set default highlight color
|
||||||
|
popup.session.highlight("");
|
||||||
|
popup.session.$searchHighlight.clazz = "ace_highlight-marker";
|
||||||
|
|
||||||
|
popup.on("mousedown", function(e) {
|
||||||
|
var pos = e.getDocumentPosition();
|
||||||
|
popup.selection.moveToPosition(pos);
|
||||||
|
selectionMarker.start.row = selectionMarker.end.row = pos.row;
|
||||||
|
e.stop();
|
||||||
|
});
|
||||||
|
|
||||||
|
var lastMouseEvent;
|
||||||
|
var hoverMarker = new Range(-1,0,-1,Infinity);
|
||||||
|
var selectionMarker = new Range(-1,0,-1,Infinity);
|
||||||
|
selectionMarker.id = popup.session.addMarker(selectionMarker, "ace_active-line", "fullLine");
|
||||||
|
popup.setSelectOnHover = function(val) {
|
||||||
|
if (!val) {
|
||||||
|
hoverMarker.id = popup.session.addMarker(hoverMarker, "ace_line-hover", "fullLine");
|
||||||
|
} else if (hoverMarker.id) {
|
||||||
|
popup.session.removeMarker(hoverMarker.id);
|
||||||
|
hoverMarker.id = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
popup.setSelectOnHover(false);
|
||||||
|
popup.on("mousemove", function(e) {
|
||||||
|
if (!lastMouseEvent) {
|
||||||
|
lastMouseEvent = e;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (lastMouseEvent.x == e.x && lastMouseEvent.y == e.y) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lastMouseEvent = e;
|
||||||
|
lastMouseEvent.scrollTop = popup.renderer.scrollTop;
|
||||||
|
var row = lastMouseEvent.getDocumentPosition().row;
|
||||||
|
if (hoverMarker.start.row != row) {
|
||||||
|
if (!hoverMarker.id)
|
||||||
|
popup.setRow(row);
|
||||||
|
setHoverMarker(row);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
popup.renderer.on("beforeRender", function() {
|
||||||
|
if (lastMouseEvent && hoverMarker.start.row != -1) {
|
||||||
|
lastMouseEvent.$pos = null;
|
||||||
|
var row = lastMouseEvent.getDocumentPosition().row;
|
||||||
|
if (!hoverMarker.id)
|
||||||
|
popup.setRow(row);
|
||||||
|
setHoverMarker(row, true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
popup.renderer.on("afterRender", function() {
|
||||||
|
var row = popup.getRow();
|
||||||
|
var t = popup.renderer.$textLayer;
|
||||||
|
var selected = t.element.childNodes[row - t.config.firstRow];
|
||||||
|
if (selected == t.selectedNode)
|
||||||
|
return;
|
||||||
|
if (t.selectedNode)
|
||||||
|
dom.removeCssClass(t.selectedNode, "ace_selected");
|
||||||
|
t.selectedNode = selected;
|
||||||
|
if (selected)
|
||||||
|
dom.addCssClass(selected, "ace_selected");
|
||||||
|
});
|
||||||
|
var hideHoverMarker = function() { setHoverMarker(-1) };
|
||||||
|
var setHoverMarker = function(row, suppressRedraw) {
|
||||||
|
if (row !== hoverMarker.start.row) {
|
||||||
|
hoverMarker.start.row = hoverMarker.end.row = row;
|
||||||
|
if (!suppressRedraw)
|
||||||
|
popup.session._emit("changeBackMarker");
|
||||||
|
popup._emit("changeHoverMarker");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
popup.getHoveredRow = function() {
|
||||||
|
return hoverMarker.start.row;
|
||||||
|
};
|
||||||
|
|
||||||
|
event.addListener(popup.container, "mouseout", hideHoverMarker);
|
||||||
|
popup.on("hide", hideHoverMarker);
|
||||||
|
popup.on("changeSelection", hideHoverMarker);
|
||||||
|
|
||||||
|
popup.session.doc.getLength = function() {
|
||||||
|
return popup.data.length;
|
||||||
|
};
|
||||||
|
popup.session.doc.getLine = function(i) {
|
||||||
|
var data = popup.data[i];
|
||||||
|
if (typeof data == "string")
|
||||||
|
return data;
|
||||||
|
return (data && data.value) || "";
|
||||||
|
};
|
||||||
|
|
||||||
|
var bgTokenizer = popup.session.bgTokenizer;
|
||||||
|
bgTokenizer.$tokenizeRow = function(row) {
|
||||||
|
var data = popup.data[row];
|
||||||
|
var tokens = [];
|
||||||
|
if (!data)
|
||||||
|
return tokens;
|
||||||
|
if (typeof data == "string")
|
||||||
|
data = {value: data};
|
||||||
|
if (!data.caption)
|
||||||
|
data.caption = data.value || data.name;
|
||||||
|
|
||||||
|
var last = -1;
|
||||||
|
var flag, c;
|
||||||
|
for (var i = 0; i < data.caption.length; i++) {
|
||||||
|
c = data.caption[i];
|
||||||
|
flag = data.matchMask & (1 << i) ? 1 : 0;
|
||||||
|
if (last !== flag) {
|
||||||
|
tokens.push({type: data.className || "" + ( flag ? "completion-highlight" : ""), value: c});
|
||||||
|
last = flag;
|
||||||
|
} else {
|
||||||
|
tokens[tokens.length - 1].value += c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.meta) {
|
||||||
|
var maxW = popup.renderer.$size.scrollerWidth / popup.renderer.layerConfig.characterWidth;
|
||||||
|
if (data.meta.length + data.caption.length < maxW - 2)
|
||||||
|
tokens.push({type: "rightAlignedText", value: data.meta});
|
||||||
|
}
|
||||||
|
return tokens;
|
||||||
|
};
|
||||||
|
bgTokenizer.$updateOnChange = noop;
|
||||||
|
bgTokenizer.start = noop;
|
||||||
|
|
||||||
|
popup.session.$computeWidth = function() {
|
||||||
|
return this.screenWidth = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
popup.$blockScrolling = Infinity;
|
||||||
|
|
||||||
|
// public
|
||||||
|
popup.isOpen = false;
|
||||||
|
popup.isTopdown = false;
|
||||||
|
|
||||||
|
popup.data = [];
|
||||||
|
popup.setData = function(list) {
|
||||||
|
popup.data = list || [];
|
||||||
|
popup.setValue(lang.stringRepeat("\n", list.length), -1);
|
||||||
|
popup.setRow(0);
|
||||||
|
};
|
||||||
|
popup.getData = function(row) {
|
||||||
|
return popup.data[row];
|
||||||
|
};
|
||||||
|
|
||||||
|
popup.getRow = function() {
|
||||||
|
return selectionMarker.start.row;
|
||||||
|
};
|
||||||
|
popup.setRow = function(line) {
|
||||||
|
line = Math.max(-1, Math.min(this.data.length, line));
|
||||||
|
if (selectionMarker.start.row != line) {
|
||||||
|
popup.selection.clearSelection();
|
||||||
|
selectionMarker.start.row = selectionMarker.end.row = line || 0;
|
||||||
|
popup.session._emit("changeBackMarker");
|
||||||
|
popup.moveCursorTo(line || 0, 0);
|
||||||
|
if (popup.isOpen)
|
||||||
|
popup._signal("select");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
popup.on("changeSelection", function() {
|
||||||
|
if (popup.isOpen)
|
||||||
|
popup.setRow(popup.selection.lead.row);
|
||||||
|
popup.renderer.scrollCursorIntoView();
|
||||||
|
});
|
||||||
|
|
||||||
|
popup.hide = function() {
|
||||||
|
this.container.style.display = "none";
|
||||||
|
this._signal("hide");
|
||||||
|
popup.isOpen = false;
|
||||||
|
};
|
||||||
|
popup.show = function(pos, lineHeight, topdownOnly) {
|
||||||
|
var el = this.container;
|
||||||
|
var screenHeight = window.innerHeight;
|
||||||
|
var screenWidth = window.innerWidth;
|
||||||
|
var renderer = this.renderer;
|
||||||
|
// var maxLines = Math.min(renderer.$maxLines, this.session.getLength());
|
||||||
|
var maxH = renderer.$maxLines * lineHeight * 1.4;
|
||||||
|
var top = pos.top + this.$borderSize;
|
||||||
|
if (top + maxH > screenHeight - lineHeight && !topdownOnly) {
|
||||||
|
el.style.top = "";
|
||||||
|
el.style.bottom = screenHeight - top + "px";
|
||||||
|
popup.isTopdown = false;
|
||||||
|
} else {
|
||||||
|
top += lineHeight;
|
||||||
|
el.style.top = top + "px";
|
||||||
|
el.style.bottom = "";
|
||||||
|
popup.isTopdown = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
el.style.display = "";
|
||||||
|
this.renderer.$textLayer.checkForSizeChanges();
|
||||||
|
|
||||||
|
var left = pos.left;
|
||||||
|
if (left + el.offsetWidth > screenWidth)
|
||||||
|
left = screenWidth - el.offsetWidth;
|
||||||
|
|
||||||
|
el.style.left = left + "px";
|
||||||
|
|
||||||
|
this._signal("show");
|
||||||
|
lastMouseEvent = null;
|
||||||
|
popup.isOpen = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
popup.getTextLeftOffset = function() {
|
||||||
|
return this.$borderSize + this.renderer.$padding + this.$imageSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
popup.$imageSize = 0;
|
||||||
|
popup.$borderSize = 1;
|
||||||
|
|
||||||
|
return popup;
|
||||||
|
};
|
||||||
|
|
||||||
|
dom.importCssString("\
|
||||||
|
.ace_editor.ace_autocomplete .ace_marker-layer .ace_active-line {\
|
||||||
|
background-color: #CAD6FA;\
|
||||||
|
z-index: 1;\
|
||||||
|
}\
|
||||||
|
.ace_editor.ace_autocomplete .ace_line-hover {\
|
||||||
|
border: 1px solid #abbffe;\
|
||||||
|
margin-top: -1px;\
|
||||||
|
background: rgba(233,233,253,0.4);\
|
||||||
|
}\
|
||||||
|
.ace_editor.ace_autocomplete .ace_line-hover {\
|
||||||
|
position: absolute;\
|
||||||
|
z-index: 2;\
|
||||||
|
}\
|
||||||
|
.ace_editor.ace_autocomplete .ace_scroller {\
|
||||||
|
background: none;\
|
||||||
|
border: none;\
|
||||||
|
box-shadow: none;\
|
||||||
|
}\
|
||||||
|
.ace_rightAlignedText {\
|
||||||
|
color: gray;\
|
||||||
|
display: inline-block;\
|
||||||
|
position: absolute;\
|
||||||
|
right: 4px;\
|
||||||
|
text-align: right;\
|
||||||
|
z-index: -1;\
|
||||||
|
}\
|
||||||
|
.ace_editor.ace_autocomplete .ace_completion-highlight{\
|
||||||
|
color: #000;\
|
||||||
|
text-shadow: 0 0 0.01em;\
|
||||||
|
}\
|
||||||
|
.ace_editor.ace_autocomplete {\
|
||||||
|
width: 280px;\
|
||||||
|
z-index: 200000;\
|
||||||
|
background: #fbfbfb;\
|
||||||
|
color: #444;\
|
||||||
|
border: 1px lightgray solid;\
|
||||||
|
position: fixed;\
|
||||||
|
box-shadow: 2px 3px 5px rgba(0,0,0,.2);\
|
||||||
|
line-height: 1.4;\
|
||||||
|
}");
|
||||||
|
|
||||||
|
exports.AcePopup = AcePopup;
|
||||||
|
|
||||||
|
});
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Distributed under the BSD license:
|
||||||
|
*
|
||||||
|
* Copyright (c) 2012, Ajax.org B.V.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of Ajax.org B.V. nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
define(function(require, exports, module) {
|
||||||
|
var Range = require("../range").Range;
|
||||||
|
|
||||||
|
var splitRegex = /[^a-zA-Z_0-9\$\-\u00C0-\u1FFF\u2C00-\uD7FF\w]+/;
|
||||||
|
|
||||||
|
function getWordIndex(doc, pos) {
|
||||||
|
var textBefore = doc.getTextRange(Range.fromPoints({row: 0, column:0}, pos));
|
||||||
|
return textBefore.split(splitRegex).length - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does a distance analysis of the word `prefix` at position `pos` in `doc`.
|
||||||
|
* @return Map
|
||||||
|
*/
|
||||||
|
function wordDistance(doc, pos) {
|
||||||
|
var prefixPos = getWordIndex(doc, pos);
|
||||||
|
var words = doc.getValue().split(splitRegex);
|
||||||
|
var wordScores = Object.create(null);
|
||||||
|
|
||||||
|
var currentWord = words[prefixPos];
|
||||||
|
|
||||||
|
words.forEach(function(word, idx) {
|
||||||
|
if (!word || word === currentWord) return;
|
||||||
|
|
||||||
|
var distance = Math.abs(prefixPos - idx);
|
||||||
|
var score = words.length - distance;
|
||||||
|
if (wordScores[word]) {
|
||||||
|
wordScores[word] = Math.max(score, wordScores[word]);
|
||||||
|
} else {
|
||||||
|
wordScores[word] = score;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return wordScores;
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.getCompletions = function(editor, session, pos, prefix, callback) {
|
||||||
|
var wordScore = wordDistance(session, pos, prefix);
|
||||||
|
var wordList = Object.keys(wordScore);
|
||||||
|
callback(null, wordList.map(function(word) {
|
||||||
|
return {
|
||||||
|
caption: word,
|
||||||
|
value: word,
|
||||||
|
score: wordScore[word],
|
||||||
|
meta: "local"
|
||||||
|
};
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
});
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Distributed under the BSD license:
|
||||||
|
*
|
||||||
|
* Copyright (c) 2012, Ajax.org B.V.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of Ajax.org B.V. nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
define(function(require, exports, module) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
exports.parForEach = function(array, fn, callback) {
|
||||||
|
var completed = 0;
|
||||||
|
var arLength = array.length;
|
||||||
|
if (arLength === 0)
|
||||||
|
callback();
|
||||||
|
for (var i = 0; i < arLength; i++) {
|
||||||
|
fn(array[i], function(result, err) {
|
||||||
|
completed++;
|
||||||
|
if (completed === arLength)
|
||||||
|
callback(result, err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var ID_REGEX = /[a-zA-Z_0-9\$\-\u00A2-\uFFFF]/;
|
||||||
|
|
||||||
|
exports.retrievePrecedingIdentifier = function(text, pos, regex) {
|
||||||
|
regex = regex || ID_REGEX;
|
||||||
|
var buf = [];
|
||||||
|
for (var i = pos-1; i >= 0; i--) {
|
||||||
|
if (regex.test(text[i]))
|
||||||
|
buf.push(text[i]);
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return buf.reverse().join("");
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.retrieveFollowingIdentifier = function(text, pos, regex) {
|
||||||
|
regex = regex || ID_REGEX;
|
||||||
|
var buf = [];
|
||||||
|
for (var i = pos; i < text.length; i++) {
|
||||||
|
if (regex.test(text[i]))
|
||||||
|
buf.push(text[i]);
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
|
};
|
||||||
|
|
||||||
|
});
|
||||||
@@ -34,12 +34,8 @@ define(function(require, exports, module) {
|
|||||||
var oop = require("./lib/oop");
|
var oop = require("./lib/oop");
|
||||||
var EventEmitter = require("./lib/event_emitter").EventEmitter;
|
var EventEmitter = require("./lib/event_emitter").EventEmitter;
|
||||||
|
|
||||||
// tokenizing lines longer than this makes editor very slow
|
|
||||||
var MAX_LINE_LENGTH = 5000;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
*
|
|
||||||
* Tokenizes the current [[Document `Document`]] in the background, and caches the tokenized rows for future use.
|
* Tokenizes the current [[Document `Document`]] in the background, and caches the tokenized rows for future use.
|
||||||
*
|
*
|
||||||
* If a certain row is changed, everything below that row is re-tokenized.
|
* If a certain row is changed, everything below that row is re-tokenized.
|
||||||
@@ -52,8 +48,6 @@ var MAX_LINE_LENGTH = 5000;
|
|||||||
* @param {Tokenizer} tokenizer The tokenizer to use
|
* @param {Tokenizer} tokenizer The tokenizer to use
|
||||||
* @param {Editor} editor The editor to associate with
|
* @param {Editor} editor The editor to associate with
|
||||||
*
|
*
|
||||||
*
|
|
||||||
*
|
|
||||||
* @constructor
|
* @constructor
|
||||||
**/
|
**/
|
||||||
|
|
||||||
@@ -70,29 +64,36 @@ var BackgroundTokenizer = function(tokenizer, editor) {
|
|||||||
if (!self.running) { return; }
|
if (!self.running) { return; }
|
||||||
|
|
||||||
var workerStart = new Date();
|
var workerStart = new Date();
|
||||||
var startLine = self.currentLine;
|
var currentLine = self.currentLine;
|
||||||
|
var endLine = -1;
|
||||||
var doc = self.doc;
|
var doc = self.doc;
|
||||||
|
|
||||||
var processedLines = 0;
|
while (self.lines[currentLine])
|
||||||
|
currentLine++;
|
||||||
|
|
||||||
|
var startLine = currentLine;
|
||||||
|
|
||||||
var len = doc.getLength();
|
var len = doc.getLength();
|
||||||
while (self.currentLine < len) {
|
var processedLines = 0;
|
||||||
self.$tokenizeRow(self.currentLine);
|
self.running = false;
|
||||||
while (self.lines[self.currentLine])
|
while (currentLine < len) {
|
||||||
self.currentLine++;
|
self.$tokenizeRow(currentLine);
|
||||||
|
endLine = currentLine;
|
||||||
|
do {
|
||||||
|
currentLine++;
|
||||||
|
} while (self.lines[currentLine]);
|
||||||
|
|
||||||
// only check every 5 lines
|
// only check every 5 lines
|
||||||
processedLines ++;
|
processedLines ++;
|
||||||
if ((processedLines % 5 == 0) && (new Date() - workerStart) > 20) {
|
if ((processedLines % 5 === 0) && (new Date() - workerStart) > 20) {
|
||||||
self.fireUpdateEvent(startLine, self.currentLine-1);
|
|
||||||
self.running = setTimeout(self.$worker, 20);
|
self.running = setTimeout(self.$worker, 20);
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
self.currentLine = currentLine;
|
||||||
self.running = false;
|
|
||||||
|
if (startLine <= endLine)
|
||||||
self.fireUpdateEvent(startLine, len - 1);
|
self.fireUpdateEvent(startLine, endLine);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -144,7 +145,7 @@ var BackgroundTokenizer = function(tokenizer, editor) {
|
|||||||
first: firstRow,
|
first: firstRow,
|
||||||
last: lastRow
|
last: lastRow
|
||||||
};
|
};
|
||||||
this._emit("update", {data: data});
|
this._signal("update", {data: data});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -164,6 +165,11 @@ var BackgroundTokenizer = function(tokenizer, editor) {
|
|||||||
// pretty long delay to prevent the tokenizer from interfering with the user
|
// pretty long delay to prevent the tokenizer from interfering with the user
|
||||||
this.running = setTimeout(this.$worker, 700);
|
this.running = setTimeout(this.$worker, 700);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.scheduleStart = function() {
|
||||||
|
if (!this.running)
|
||||||
|
this.running = setTimeout(this.$worker, 700);
|
||||||
|
}
|
||||||
|
|
||||||
this.$updateOnChange = function(delta) {
|
this.$updateOnChange = function(delta) {
|
||||||
var range = delta.range;
|
var range = delta.range;
|
||||||
@@ -185,8 +191,6 @@ var BackgroundTokenizer = function(tokenizer, editor) {
|
|||||||
this.currentLine = Math.min(startRow, this.currentLine, this.doc.getLength());
|
this.currentLine = Math.min(startRow, this.currentLine, this.doc.getLength());
|
||||||
|
|
||||||
this.stop();
|
this.stop();
|
||||||
// pretty long delay to prevent the tokenizer from interfering with the user
|
|
||||||
this.running = setTimeout(this.$worker, 700);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -226,17 +230,9 @@ var BackgroundTokenizer = function(tokenizer, editor) {
|
|||||||
var line = this.doc.getLine(row);
|
var line = this.doc.getLine(row);
|
||||||
var state = this.states[row - 1];
|
var state = this.states[row - 1];
|
||||||
|
|
||||||
if (line.length > MAX_LINE_LENGTH) {
|
var data = this.tokenizer.getLineTokens(line, state, row);
|
||||||
var overflow = {value: line.substr(MAX_LINE_LENGTH), type: "text"};
|
|
||||||
line = line.slice(0, MAX_LINE_LENGTH);
|
|
||||||
}
|
|
||||||
var data = this.tokenizer.getLineTokens(line, state);
|
|
||||||
if (overflow) {
|
|
||||||
data.tokens.push(overflow);
|
|
||||||
data.state = "start";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.states[row] !== data.state) {
|
if (this.states[row] + "" !== data.state + "") {
|
||||||
this.states[row] = data.state;
|
this.states[row] = data.state;
|
||||||
this.lines[row + 1] = null;
|
this.lines[row + 1] = null;
|
||||||
if (this.currentLine > row + 1)
|
if (this.currentLine > row + 1)
|
||||||
|
|||||||
@@ -62,19 +62,19 @@ module.exports = {
|
|||||||
doc.setMode("./mode/javascript")
|
doc.setMode("./mode/javascript")
|
||||||
|
|
||||||
forceTokenize(doc)
|
forceTokenize(doc)
|
||||||
testStates(doc, ["comment", "start", "start"])
|
testStates(doc, ["comment_regex_allowed", "start", "no_regex"])
|
||||||
|
|
||||||
doc.remove(new Range(0,2,1,2))
|
doc.remove(new Range(0,2,1,2))
|
||||||
testStates(doc, [null, "start"])
|
testStates(doc, [null, "no_regex"])
|
||||||
|
|
||||||
forceTokenize(doc)
|
forceTokenize(doc)
|
||||||
testStates(doc, ["comment", "comment"])
|
testStates(doc, ["comment_regex_allowed", "comment_regex_allowed"])
|
||||||
|
|
||||||
doc.insert({row:0, column:2}, "\n*/")
|
doc.insert({row:0, column:2}, "\n*/")
|
||||||
testStates(doc, [undefined, undefined, "comment"])
|
testStates(doc, [undefined, undefined, "comment_regex_allowed"])
|
||||||
|
|
||||||
forceTokenize(doc)
|
forceTokenize(doc)
|
||||||
testStates(doc, ["comment", "start", "start"])
|
testStates(doc, ["comment_regex_allowed", "start", "no_regex"])
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -2,45 +2,44 @@ define(function(require, exports, module) {
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var oop = require("../lib/oop");
|
var oop = require("../lib/oop");
|
||||||
var HashHandler = require("../keyboard/hash_handler").HashHandler;
|
var MultiHashHandler = require("../keyboard/hash_handler").MultiHashHandler;
|
||||||
var EventEmitter = require("../lib/event_emitter").EventEmitter;
|
var EventEmitter = require("../lib/event_emitter").EventEmitter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @class CommandManager
|
* @class CommandManager
|
||||||
*
|
*
|
||||||
*
|
|
||||||
**/
|
**/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* new CommandManager(platform, commands)
|
* new CommandManager(platform, commands)
|
||||||
* @param {String} platform Identifier for the platform; must be either `'mac'` or `'win'`
|
* @param {String} platform Identifier for the platform; must be either `"mac"` or `"win"`
|
||||||
* @param {Array} commands A list of commands
|
* @param {Array} commands A list of commands
|
||||||
*
|
*
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
**/
|
**/
|
||||||
|
|
||||||
var CommandManager = function(platform, commands) {
|
var CommandManager = function(platform, commands) {
|
||||||
this.platform = platform;
|
MultiHashHandler.call(this, commands, platform);
|
||||||
this.commands = this.byName = {};
|
this.byName = this.commands;
|
||||||
this.commmandKeyBinding = {};
|
|
||||||
|
|
||||||
this.addCommands(commands);
|
|
||||||
|
|
||||||
this.setDefaultHandler("exec", function(e) {
|
this.setDefaultHandler("exec", function(e) {
|
||||||
return e.command.exec(e.editor, e.args || {});
|
return e.command.exec(e.editor, e.args || {});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
oop.inherits(CommandManager, HashHandler);
|
oop.inherits(CommandManager, MultiHashHandler);
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
oop.implement(this, EventEmitter);
|
oop.implement(this, EventEmitter);
|
||||||
|
|
||||||
this.exec = function(command, editor, args) {
|
this.exec = function(command, editor, args) {
|
||||||
if (typeof command === 'string')
|
if (Array.isArray(command)) {
|
||||||
|
for (var i = command.length; i--; ) {
|
||||||
|
if (this.exec(command[i], editor, args)) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof command === "string")
|
||||||
command = this.commands[command];
|
command = this.commands[command];
|
||||||
|
|
||||||
if (!command)
|
if (!command)
|
||||||
@@ -49,13 +48,11 @@ oop.inherits(CommandManager, HashHandler);
|
|||||||
if (editor && editor.$readOnly && !command.readOnly)
|
if (editor && editor.$readOnly && !command.readOnly)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var retvalue = this._emit("exec", {
|
var e = {editor: editor, command: command, args: args};
|
||||||
editor: editor,
|
e.returnValue = this._emit("exec", e);
|
||||||
command: command,
|
this._signal("afterExec", e);
|
||||||
args: args
|
|
||||||
});
|
|
||||||
|
|
||||||
return retvalue === false ? false : true;
|
return e.returnValue === false ? false : true;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.toggleRecording = function(editor) {
|
this.toggleRecording = function(editor) {
|
||||||
|
|||||||
+1
-1
@@ -188,7 +188,7 @@ module.exports = {
|
|||||||
assert.equal(command, "cm2");
|
assert.equal(command, "cm2");
|
||||||
|
|
||||||
var command = this.cm.findKeyCommand(0, "return");
|
var command = this.cm.findKeyCommand(0, "return");
|
||||||
assert.equal(command, "cm3");
|
assert.equal(command + "", ["cm4", "cm3"] + "");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -32,15 +32,48 @@ define(function(require, exports, module) {
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var lang = require("../lib/lang");
|
var lang = require("../lib/lang");
|
||||||
|
var config = require("../config");
|
||||||
|
var Range = require("../range").Range;
|
||||||
|
|
||||||
function bindKey(win, mac) {
|
function bindKey(win, mac) {
|
||||||
return {
|
return {win: win, mac: mac};
|
||||||
win: win,
|
|
||||||
mac: mac
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
multiSelectAction: "forEach"|"forEachLine"|function|undefined,
|
||||||
|
scrollIntoView: true|"cursor"|"center"|"selectionPart"
|
||||||
|
*/
|
||||||
exports.commands = [{
|
exports.commands = [{
|
||||||
|
name: "showSettingsMenu",
|
||||||
|
bindKey: bindKey("Ctrl-,", "Command-,"),
|
||||||
|
exec: function(editor) {
|
||||||
|
config.loadModule("ace/ext/settings_menu", function(module) {
|
||||||
|
module.init(editor);
|
||||||
|
editor.showSettingsMenu();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
readOnly: true
|
||||||
|
}, {
|
||||||
|
name: "goToNextError",
|
||||||
|
bindKey: bindKey("Alt-E", "Ctrl-E"),
|
||||||
|
exec: function(editor) {
|
||||||
|
config.loadModule("ace/ext/error_marker", function(module) {
|
||||||
|
module.showErrorMarker(editor, 1);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
scrollIntoView: "animate",
|
||||||
|
readOnly: true
|
||||||
|
}, {
|
||||||
|
name: "goToPreviousError",
|
||||||
|
bindKey: bindKey("Alt-Shift-E", "Ctrl-Shift-E"),
|
||||||
|
exec: function(editor) {
|
||||||
|
config.loadModule("ace/ext/error_marker", function(module) {
|
||||||
|
module.showErrorMarker(editor, -1);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
scrollIntoView: "animate",
|
||||||
|
readOnly: true
|
||||||
|
}, {
|
||||||
name: "selectall",
|
name: "selectall",
|
||||||
bindKey: bindKey("Ctrl-A", "Command-A"),
|
bindKey: bindKey("Ctrl-A", "Command-A"),
|
||||||
exec: function(editor) { editor.selectAll(); },
|
exec: function(editor) { editor.selectAll(); },
|
||||||
@@ -64,38 +97,86 @@ exports.commands = [{
|
|||||||
name: "fold",
|
name: "fold",
|
||||||
bindKey: bindKey("Alt-L|Ctrl-F1", "Command-Alt-L|Command-F1"),
|
bindKey: bindKey("Alt-L|Ctrl-F1", "Command-Alt-L|Command-F1"),
|
||||||
exec: function(editor) { editor.session.toggleFold(false); },
|
exec: function(editor) { editor.session.toggleFold(false); },
|
||||||
|
scrollIntoView: "center",
|
||||||
readOnly: true
|
readOnly: true
|
||||||
}, {
|
}, {
|
||||||
name: "unfold",
|
name: "unfold",
|
||||||
bindKey: bindKey("Alt-Shift-L|Ctrl-Shift-F1", "Command-Alt-Shift-L|Command-Shift-F1"),
|
bindKey: bindKey("Alt-Shift-L|Ctrl-Shift-F1", "Command-Alt-Shift-L|Command-Shift-F1"),
|
||||||
exec: function(editor) { editor.session.toggleFold(true); },
|
exec: function(editor) { editor.session.toggleFold(true); },
|
||||||
|
scrollIntoView: "center",
|
||||||
|
readOnly: true
|
||||||
|
}, {
|
||||||
|
name: "toggleFoldWidget",
|
||||||
|
bindKey: bindKey("F2", "F2"),
|
||||||
|
exec: function(editor) { editor.session.toggleFoldWidget(); },
|
||||||
|
scrollIntoView: "center",
|
||||||
|
readOnly: true
|
||||||
|
}, {
|
||||||
|
name: "toggleParentFoldWidget",
|
||||||
|
bindKey: bindKey("Alt-F2", "Alt-F2"),
|
||||||
|
exec: function(editor) { editor.session.toggleFoldWidget(true); },
|
||||||
|
scrollIntoView: "center",
|
||||||
readOnly: true
|
readOnly: true
|
||||||
}, {
|
}, {
|
||||||
name: "foldall",
|
name: "foldall",
|
||||||
bindKey: bindKey("Alt-0", "Command-Option-0"),
|
bindKey: bindKey("Ctrl-Alt-0", "Ctrl-Command-Option-0"),
|
||||||
exec: function(editor) { editor.session.foldAll(); },
|
exec: function(editor) { editor.session.foldAll(); },
|
||||||
|
scrollIntoView: "center",
|
||||||
|
readOnly: true
|
||||||
|
}, {
|
||||||
|
name: "foldOther",
|
||||||
|
bindKey: bindKey("Alt-0", "Command-Option-0"),
|
||||||
|
exec: function(editor) {
|
||||||
|
editor.session.foldAll();
|
||||||
|
editor.session.unfold(editor.selection.getAllRanges());
|
||||||
|
},
|
||||||
|
scrollIntoView: "center",
|
||||||
readOnly: true
|
readOnly: true
|
||||||
}, {
|
}, {
|
||||||
name: "unfoldall",
|
name: "unfoldall",
|
||||||
bindKey: bindKey("Alt-Shift-0", "Command-Option-Shift-0"),
|
bindKey: bindKey("Alt-Shift-0", "Command-Option-Shift-0"),
|
||||||
exec: function(editor) { editor.session.unfold(); },
|
exec: function(editor) { editor.session.unfold(); },
|
||||||
|
scrollIntoView: "center",
|
||||||
readOnly: true
|
readOnly: true
|
||||||
}, {
|
}, {
|
||||||
name: "findnext",
|
name: "findnext",
|
||||||
bindKey: bindKey("Ctrl-K", "Command-G"),
|
bindKey: bindKey("Ctrl-K", "Command-G"),
|
||||||
exec: function(editor) { editor.findNext(); },
|
exec: function(editor) { editor.findNext(); },
|
||||||
|
multiSelectAction: "forEach",
|
||||||
|
scrollIntoView: "center",
|
||||||
readOnly: true
|
readOnly: true
|
||||||
}, {
|
}, {
|
||||||
name: "findprevious",
|
name: "findprevious",
|
||||||
bindKey: bindKey("Ctrl-Shift-K", "Command-Shift-G"),
|
bindKey: bindKey("Ctrl-Shift-K", "Command-Shift-G"),
|
||||||
exec: function(editor) { editor.findPrevious(); },
|
exec: function(editor) { editor.findPrevious(); },
|
||||||
|
multiSelectAction: "forEach",
|
||||||
|
scrollIntoView: "center",
|
||||||
|
readOnly: true
|
||||||
|
}, {
|
||||||
|
name: "selectOrFindNext",
|
||||||
|
bindKey: bindKey("Alt-K", "Ctrl-G"),
|
||||||
|
exec: function(editor) {
|
||||||
|
if (editor.selection.isEmpty())
|
||||||
|
editor.selection.selectWord();
|
||||||
|
else
|
||||||
|
editor.findNext();
|
||||||
|
},
|
||||||
|
readOnly: true
|
||||||
|
}, {
|
||||||
|
name: "selectOrFindPrevious",
|
||||||
|
bindKey: bindKey("Alt-Shift-K", "Ctrl-Shift-G"),
|
||||||
|
exec: function(editor) {
|
||||||
|
if (editor.selection.isEmpty())
|
||||||
|
editor.selection.selectWord();
|
||||||
|
else
|
||||||
|
editor.findPrevious();
|
||||||
|
},
|
||||||
readOnly: true
|
readOnly: true
|
||||||
}, {
|
}, {
|
||||||
name: "find",
|
name: "find",
|
||||||
bindKey: bindKey("Ctrl-F", "Command-F"),
|
bindKey: bindKey("Ctrl-F", "Command-F"),
|
||||||
exec: function(editor) {
|
exec: function(editor) {
|
||||||
var needle = prompt("Find:", editor.getCopyText());
|
config.loadModule("ace/ext/searchbox", function(e) {e.Search(editor)});
|
||||||
editor.find(needle);
|
|
||||||
},
|
},
|
||||||
readOnly: true
|
readOnly: true
|
||||||
}, {
|
}, {
|
||||||
@@ -108,120 +189,144 @@ exports.commands = [{
|
|||||||
bindKey: bindKey("Ctrl-Shift-Home", "Command-Shift-Up"),
|
bindKey: bindKey("Ctrl-Shift-Home", "Command-Shift-Up"),
|
||||||
exec: function(editor) { editor.getSelection().selectFileStart(); },
|
exec: function(editor) { editor.getSelection().selectFileStart(); },
|
||||||
multiSelectAction: "forEach",
|
multiSelectAction: "forEach",
|
||||||
readOnly: true
|
readOnly: true,
|
||||||
|
scrollIntoView: "animate",
|
||||||
|
aceCommandGroup: "fileJump"
|
||||||
}, {
|
}, {
|
||||||
name: "gotostart",
|
name: "gotostart",
|
||||||
bindKey: bindKey("Ctrl-Home", "Command-Home|Command-Up"),
|
bindKey: bindKey("Ctrl-Home", "Command-Home|Command-Up"),
|
||||||
exec: function(editor) { editor.navigateFileStart(); },
|
exec: function(editor) { editor.navigateFileStart(); },
|
||||||
multiSelectAction: "forEach",
|
multiSelectAction: "forEach",
|
||||||
readOnly: true
|
readOnly: true,
|
||||||
|
scrollIntoView: "animate",
|
||||||
|
aceCommandGroup: "fileJump"
|
||||||
}, {
|
}, {
|
||||||
name: "selectup",
|
name: "selectup",
|
||||||
bindKey: bindKey("Shift-Up", "Shift-Up"),
|
bindKey: bindKey("Shift-Up", "Shift-Up"),
|
||||||
exec: function(editor) { editor.getSelection().selectUp(); },
|
exec: function(editor) { editor.getSelection().selectUp(); },
|
||||||
multiSelectAction: "forEach",
|
multiSelectAction: "forEach",
|
||||||
|
scrollIntoView: "cursor",
|
||||||
readOnly: true
|
readOnly: true
|
||||||
}, {
|
}, {
|
||||||
name: "golineup",
|
name: "golineup",
|
||||||
bindKey: bindKey("Up", "Up|Ctrl-P"),
|
bindKey: bindKey("Up", "Up|Ctrl-P"),
|
||||||
exec: function(editor, args) { editor.navigateUp(args.times); },
|
exec: function(editor, args) { editor.navigateUp(args.times); },
|
||||||
multiSelectAction: "forEach",
|
multiSelectAction: "forEach",
|
||||||
|
scrollIntoView: "cursor",
|
||||||
readOnly: true
|
readOnly: true
|
||||||
}, {
|
}, {
|
||||||
name: "selecttoend",
|
name: "selecttoend",
|
||||||
bindKey: bindKey("Ctrl-Shift-End", "Command-Shift-Down"),
|
bindKey: bindKey("Ctrl-Shift-End", "Command-Shift-Down"),
|
||||||
exec: function(editor) { editor.getSelection().selectFileEnd(); },
|
exec: function(editor) { editor.getSelection().selectFileEnd(); },
|
||||||
multiSelectAction: "forEach",
|
multiSelectAction: "forEach",
|
||||||
readOnly: true
|
readOnly: true,
|
||||||
|
scrollIntoView: "animate",
|
||||||
|
aceCommandGroup: "fileJump"
|
||||||
}, {
|
}, {
|
||||||
name: "gotoend",
|
name: "gotoend",
|
||||||
bindKey: bindKey("Ctrl-End", "Command-End|Command-Down"),
|
bindKey: bindKey("Ctrl-End", "Command-End|Command-Down"),
|
||||||
exec: function(editor) { editor.navigateFileEnd(); },
|
exec: function(editor) { editor.navigateFileEnd(); },
|
||||||
multiSelectAction: "forEach",
|
multiSelectAction: "forEach",
|
||||||
readOnly: true
|
readOnly: true,
|
||||||
|
scrollIntoView: "animate",
|
||||||
|
aceCommandGroup: "fileJump"
|
||||||
}, {
|
}, {
|
||||||
name: "selectdown",
|
name: "selectdown",
|
||||||
bindKey: bindKey("Shift-Down", "Shift-Down"),
|
bindKey: bindKey("Shift-Down", "Shift-Down"),
|
||||||
exec: function(editor) { editor.getSelection().selectDown(); },
|
exec: function(editor) { editor.getSelection().selectDown(); },
|
||||||
multiSelectAction: "forEach",
|
multiSelectAction: "forEach",
|
||||||
|
scrollIntoView: "cursor",
|
||||||
readOnly: true
|
readOnly: true
|
||||||
}, {
|
}, {
|
||||||
name: "golinedown",
|
name: "golinedown",
|
||||||
bindKey: bindKey("Down", "Down|Ctrl-N"),
|
bindKey: bindKey("Down", "Down|Ctrl-N"),
|
||||||
exec: function(editor, args) { editor.navigateDown(args.times); },
|
exec: function(editor, args) { editor.navigateDown(args.times); },
|
||||||
multiSelectAction: "forEach",
|
multiSelectAction: "forEach",
|
||||||
|
scrollIntoView: "cursor",
|
||||||
readOnly: true
|
readOnly: true
|
||||||
}, {
|
}, {
|
||||||
name: "selectwordleft",
|
name: "selectwordleft",
|
||||||
bindKey: bindKey("Ctrl-Shift-Left", "Option-Shift-Left"),
|
bindKey: bindKey("Ctrl-Shift-Left", "Option-Shift-Left"),
|
||||||
exec: function(editor) { editor.getSelection().selectWordLeft(); },
|
exec: function(editor) { editor.getSelection().selectWordLeft(); },
|
||||||
multiSelectAction: "forEach",
|
multiSelectAction: "forEach",
|
||||||
|
scrollIntoView: "cursor",
|
||||||
readOnly: true
|
readOnly: true
|
||||||
}, {
|
}, {
|
||||||
name: "gotowordleft",
|
name: "gotowordleft",
|
||||||
bindKey: bindKey("Ctrl-Left", "Option-Left"),
|
bindKey: bindKey("Ctrl-Left", "Option-Left"),
|
||||||
exec: function(editor) { editor.navigateWordLeft(); },
|
exec: function(editor) { editor.navigateWordLeft(); },
|
||||||
multiSelectAction: "forEach",
|
multiSelectAction: "forEach",
|
||||||
|
scrollIntoView: "cursor",
|
||||||
readOnly: true
|
readOnly: true
|
||||||
}, {
|
}, {
|
||||||
name: "selecttolinestart",
|
name: "selecttolinestart",
|
||||||
bindKey: bindKey("Alt-Shift-Left", "Command-Shift-Left"),
|
bindKey: bindKey("Alt-Shift-Left", "Command-Shift-Left"),
|
||||||
exec: function(editor) { editor.getSelection().selectLineStart(); },
|
exec: function(editor) { editor.getSelection().selectLineStart(); },
|
||||||
multiSelectAction: "forEach",
|
multiSelectAction: "forEach",
|
||||||
|
scrollIntoView: "cursor",
|
||||||
readOnly: true
|
readOnly: true
|
||||||
}, {
|
}, {
|
||||||
name: "gotolinestart",
|
name: "gotolinestart",
|
||||||
bindKey: bindKey("Alt-Left|Home", "Command-Left|Home|Ctrl-A"),
|
bindKey: bindKey("Alt-Left|Home", "Command-Left|Home|Ctrl-A"),
|
||||||
exec: function(editor) { editor.navigateLineStart(); },
|
exec: function(editor) { editor.navigateLineStart(); },
|
||||||
multiSelectAction: "forEach",
|
multiSelectAction: "forEach",
|
||||||
|
scrollIntoView: "cursor",
|
||||||
readOnly: true
|
readOnly: true
|
||||||
}, {
|
}, {
|
||||||
name: "selectleft",
|
name: "selectleft",
|
||||||
bindKey: bindKey("Shift-Left", "Shift-Left"),
|
bindKey: bindKey("Shift-Left", "Shift-Left"),
|
||||||
exec: function(editor) { editor.getSelection().selectLeft(); },
|
exec: function(editor) { editor.getSelection().selectLeft(); },
|
||||||
multiSelectAction: "forEach",
|
multiSelectAction: "forEach",
|
||||||
|
scrollIntoView: "cursor",
|
||||||
readOnly: true
|
readOnly: true
|
||||||
}, {
|
}, {
|
||||||
name: "gotoleft",
|
name: "gotoleft",
|
||||||
bindKey: bindKey("Left", "Left|Ctrl-B"),
|
bindKey: bindKey("Left", "Left|Ctrl-B"),
|
||||||
exec: function(editor, args) { editor.navigateLeft(args.times); },
|
exec: function(editor, args) { editor.navigateLeft(args.times); },
|
||||||
multiSelectAction: "forEach",
|
multiSelectAction: "forEach",
|
||||||
|
scrollIntoView: "cursor",
|
||||||
readOnly: true
|
readOnly: true
|
||||||
}, {
|
}, {
|
||||||
name: "selectwordright",
|
name: "selectwordright",
|
||||||
bindKey: bindKey("Ctrl-Shift-Right", "Option-Shift-Right"),
|
bindKey: bindKey("Ctrl-Shift-Right", "Option-Shift-Right"),
|
||||||
exec: function(editor) { editor.getSelection().selectWordRight(); },
|
exec: function(editor) { editor.getSelection().selectWordRight(); },
|
||||||
multiSelectAction: "forEach",
|
multiSelectAction: "forEach",
|
||||||
|
scrollIntoView: "cursor",
|
||||||
readOnly: true
|
readOnly: true
|
||||||
}, {
|
}, {
|
||||||
name: "gotowordright",
|
name: "gotowordright",
|
||||||
bindKey: bindKey("Ctrl-Right", "Option-Right"),
|
bindKey: bindKey("Ctrl-Right", "Option-Right"),
|
||||||
exec: function(editor) { editor.navigateWordRight(); },
|
exec: function(editor) { editor.navigateWordRight(); },
|
||||||
multiSelectAction: "forEach",
|
multiSelectAction: "forEach",
|
||||||
|
scrollIntoView: "cursor",
|
||||||
readOnly: true
|
readOnly: true
|
||||||
}, {
|
}, {
|
||||||
name: "selecttolineend",
|
name: "selecttolineend",
|
||||||
bindKey: bindKey("Alt-Shift-Right", "Command-Shift-Right"),
|
bindKey: bindKey("Alt-Shift-Right", "Command-Shift-Right"),
|
||||||
exec: function(editor) { editor.getSelection().selectLineEnd(); },
|
exec: function(editor) { editor.getSelection().selectLineEnd(); },
|
||||||
multiSelectAction: "forEach",
|
multiSelectAction: "forEach",
|
||||||
|
scrollIntoView: "cursor",
|
||||||
readOnly: true
|
readOnly: true
|
||||||
}, {
|
}, {
|
||||||
name: "gotolineend",
|
name: "gotolineend",
|
||||||
bindKey: bindKey("Alt-Right|End", "Command-Right|End|Ctrl-E"),
|
bindKey: bindKey("Alt-Right|End", "Command-Right|End|Ctrl-E"),
|
||||||
exec: function(editor) { editor.navigateLineEnd(); },
|
exec: function(editor) { editor.navigateLineEnd(); },
|
||||||
multiSelectAction: "forEach",
|
multiSelectAction: "forEach",
|
||||||
|
scrollIntoView: "cursor",
|
||||||
readOnly: true
|
readOnly: true
|
||||||
}, {
|
}, {
|
||||||
name: "selectright",
|
name: "selectright",
|
||||||
bindKey: bindKey("Shift-Right", "Shift-Right"),
|
bindKey: bindKey("Shift-Right", "Shift-Right"),
|
||||||
exec: function(editor) { editor.getSelection().selectRight(); },
|
exec: function(editor) { editor.getSelection().selectRight(); },
|
||||||
multiSelectAction: "forEach",
|
multiSelectAction: "forEach",
|
||||||
|
scrollIntoView: "cursor",
|
||||||
readOnly: true
|
readOnly: true
|
||||||
}, {
|
}, {
|
||||||
name: "gotoright",
|
name: "gotoright",
|
||||||
bindKey: bindKey("Right", "Right|Ctrl-F"),
|
bindKey: bindKey("Right", "Right|Ctrl-F"),
|
||||||
exec: function(editor, args) { editor.navigateRight(args.times); },
|
exec: function(editor, args) { editor.navigateRight(args.times); },
|
||||||
multiSelectAction: "forEach",
|
multiSelectAction: "forEach",
|
||||||
|
scrollIntoView: "cursor",
|
||||||
readOnly: true
|
readOnly: true
|
||||||
}, {
|
}, {
|
||||||
name: "selectpagedown",
|
name: "selectpagedown",
|
||||||
@@ -268,12 +373,14 @@ exports.commands = [{
|
|||||||
bindKey: "Shift-Home",
|
bindKey: "Shift-Home",
|
||||||
exec: function(editor) { editor.getSelection().selectLineStart(); },
|
exec: function(editor) { editor.getSelection().selectLineStart(); },
|
||||||
multiSelectAction: "forEach",
|
multiSelectAction: "forEach",
|
||||||
|
scrollIntoView: "cursor",
|
||||||
readOnly: true
|
readOnly: true
|
||||||
}, {
|
}, {
|
||||||
name: "selectlineend",
|
name: "selectlineend",
|
||||||
bindKey: "Shift-End",
|
bindKey: "Shift-End",
|
||||||
exec: function(editor) { editor.getSelection().selectLineEnd(); },
|
exec: function(editor) { editor.getSelection().selectLineEnd(); },
|
||||||
multiSelectAction: "forEach",
|
multiSelectAction: "forEach",
|
||||||
|
scrollIntoView: "cursor",
|
||||||
readOnly: true
|
readOnly: true
|
||||||
}, {
|
}, {
|
||||||
name: "togglerecording",
|
name: "togglerecording",
|
||||||
@@ -287,16 +394,32 @@ exports.commands = [{
|
|||||||
readOnly: true
|
readOnly: true
|
||||||
}, {
|
}, {
|
||||||
name: "jumptomatching",
|
name: "jumptomatching",
|
||||||
bindKey: bindKey("Ctrl-P", "Ctrl-Shift-P"),
|
bindKey: bindKey("Ctrl-P", "Ctrl-P"),
|
||||||
exec: function(editor) { editor.jumpToMatching(); },
|
exec: function(editor) { editor.jumpToMatching(); },
|
||||||
multiSelectAction: "forEach",
|
multiSelectAction: "forEach",
|
||||||
|
scrollIntoView: "animate",
|
||||||
readOnly: true
|
readOnly: true
|
||||||
}, {
|
}, {
|
||||||
name: "selecttomatching",
|
name: "selecttomatching",
|
||||||
bindKey: bindKey("Ctrl-Shift-P", null),
|
bindKey: bindKey("Ctrl-Shift-P", "Ctrl-Shift-P"),
|
||||||
exec: function(editor) { editor.jumpToMatching(true); },
|
exec: function(editor) { editor.jumpToMatching(true); },
|
||||||
|
multiSelectAction: "forEach",
|
||||||
|
scrollIntoView: "animate",
|
||||||
readOnly: true
|
readOnly: true
|
||||||
},
|
}, {
|
||||||
|
name: "expandToMatching",
|
||||||
|
bindKey: bindKey("Ctrl-Shift-M", "Ctrl-Shift-M"),
|
||||||
|
exec: function(editor) { editor.jumpToMatching(true, true); },
|
||||||
|
multiSelectAction: "forEach",
|
||||||
|
scrollIntoView: "animate",
|
||||||
|
readOnly: true
|
||||||
|
}, {
|
||||||
|
name: "passKeysToBrowser",
|
||||||
|
bindKey: bindKey("null", "null"),
|
||||||
|
exec: function() {},
|
||||||
|
passEvent: true,
|
||||||
|
readOnly: true
|
||||||
|
},
|
||||||
|
|
||||||
// commands disabled in readOnly mode
|
// commands disabled in readOnly mode
|
||||||
{
|
{
|
||||||
@@ -310,60 +433,55 @@ exports.commands = [{
|
|||||||
editor.clearSelection();
|
editor.clearSelection();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
scrollIntoView: "cursor",
|
||||||
multiSelectAction: "forEach"
|
multiSelectAction: "forEach"
|
||||||
}, {
|
}, {
|
||||||
name: "removeline",
|
name: "removeline",
|
||||||
bindKey: bindKey("Ctrl-D", "Command-D"),
|
bindKey: bindKey("Ctrl-D", "Command-D"),
|
||||||
exec: function(editor) { editor.removeLines(); },
|
exec: function(editor) { editor.removeLines(); },
|
||||||
multiSelectAction: "forEach"
|
scrollIntoView: "cursor",
|
||||||
|
multiSelectAction: "forEachLine"
|
||||||
}, {
|
}, {
|
||||||
name: "duplicateSelection",
|
name: "duplicateSelection",
|
||||||
bindKey: bindKey("Ctrl-Shift-D", "Command-Shift-D"),
|
bindKey: bindKey("Ctrl-Shift-D", "Command-Shift-D"),
|
||||||
exec: function(editor) { editor.duplicateSelection(); },
|
exec: function(editor) { editor.duplicateSelection(); },
|
||||||
|
scrollIntoView: "cursor",
|
||||||
multiSelectAction: "forEach"
|
multiSelectAction: "forEach"
|
||||||
}, {
|
}, {
|
||||||
name: "sortlines",
|
name: "sortlines",
|
||||||
bindKey: bindKey("Ctrl-Alt-S", "Command-Alt-S"),
|
bindKey: bindKey("Ctrl-Alt-S", "Command-Alt-S"),
|
||||||
exec: function(editor) { editor.sortLines(); },
|
exec: function(editor) { editor.sortLines(); },
|
||||||
multiSelectAction: "forEach"
|
scrollIntoView: "selection",
|
||||||
|
multiSelectAction: "forEachLine"
|
||||||
}, {
|
}, {
|
||||||
name: "togglecomment",
|
name: "togglecomment",
|
||||||
bindKey: bindKey("Ctrl-/", "Command-/"),
|
bindKey: bindKey("Ctrl-/", "Command-/"),
|
||||||
exec: function(editor) { editor.toggleCommentLines(); },
|
exec: function(editor) { editor.toggleCommentLines(); },
|
||||||
multiSelectAction: "forEach"
|
multiSelectAction: "forEachLine",
|
||||||
|
scrollIntoView: "selectionPart"
|
||||||
|
}, {
|
||||||
|
name: "toggleBlockComment",
|
||||||
|
bindKey: bindKey("Ctrl-Shift-/", "Command-Shift-/"),
|
||||||
|
exec: function(editor) { editor.toggleBlockComment(); },
|
||||||
|
multiSelectAction: "forEach",
|
||||||
|
scrollIntoView: "selectionPart"
|
||||||
}, {
|
}, {
|
||||||
name: "modifyNumberUp",
|
name: "modifyNumberUp",
|
||||||
bindKey: bindKey("Ctrl-Shift-Up", "Alt-Shift-Up"),
|
bindKey: bindKey("Ctrl-Shift-Up", "Alt-Shift-Up"),
|
||||||
exec: function(editor) { editor.modifyNumber(1); },
|
exec: function(editor) { editor.modifyNumber(1); },
|
||||||
|
scrollIntoView: "cursor",
|
||||||
multiSelectAction: "forEach"
|
multiSelectAction: "forEach"
|
||||||
}, {
|
}, {
|
||||||
name: "modifyNumberDown",
|
name: "modifyNumberDown",
|
||||||
bindKey: bindKey("Ctrl-Shift-Down", "Alt-Shift-Down"),
|
bindKey: bindKey("Ctrl-Shift-Down", "Alt-Shift-Down"),
|
||||||
exec: function(editor) { editor.modifyNumber(-1); },
|
exec: function(editor) { editor.modifyNumber(-1); },
|
||||||
|
scrollIntoView: "cursor",
|
||||||
multiSelectAction: "forEach"
|
multiSelectAction: "forEach"
|
||||||
}, {
|
}, {
|
||||||
name: "replace",
|
name: "replace",
|
||||||
bindKey: bindKey("Ctrl-R", "Command-Option-F"),
|
bindKey: bindKey("Ctrl-H", "Command-Option-F"),
|
||||||
exec: function(editor) {
|
exec: function(editor) {
|
||||||
var needle = prompt("Find:", editor.getCopyText());
|
config.loadModule("ace/ext/searchbox", function(e) {e.Search(editor, true)});
|
||||||
if (!needle)
|
|
||||||
return;
|
|
||||||
var replacement = prompt("Replacement:");
|
|
||||||
if (!replacement)
|
|
||||||
return;
|
|
||||||
editor.replace(replacement, {needle: needle});
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
name: "replaceall",
|
|
||||||
bindKey: bindKey("Ctrl-Shift-R", "Command-Shift-Option-F"),
|
|
||||||
exec: function(editor) {
|
|
||||||
var needle = prompt("Find:");
|
|
||||||
if (!needle)
|
|
||||||
return;
|
|
||||||
var replacement = prompt("Replacement:");
|
|
||||||
if (!replacement)
|
|
||||||
return;
|
|
||||||
editor.replaceAll(replacement, {needle: needle});
|
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
name: "undo",
|
name: "undo",
|
||||||
@@ -376,92 +494,228 @@ exports.commands = [{
|
|||||||
}, {
|
}, {
|
||||||
name: "copylinesup",
|
name: "copylinesup",
|
||||||
bindKey: bindKey("Alt-Shift-Up", "Command-Option-Up"),
|
bindKey: bindKey("Alt-Shift-Up", "Command-Option-Up"),
|
||||||
exec: function(editor) { editor.copyLinesUp(); }
|
exec: function(editor) { editor.copyLinesUp(); },
|
||||||
|
scrollIntoView: "cursor"
|
||||||
}, {
|
}, {
|
||||||
name: "movelinesup",
|
name: "movelinesup",
|
||||||
bindKey: bindKey("Alt-Up", "Option-Up"),
|
bindKey: bindKey("Alt-Up", "Option-Up"),
|
||||||
exec: function(editor) { editor.moveLinesUp(); }
|
exec: function(editor) { editor.moveLinesUp(); },
|
||||||
|
scrollIntoView: "cursor"
|
||||||
}, {
|
}, {
|
||||||
name: "copylinesdown",
|
name: "copylinesdown",
|
||||||
bindKey: bindKey("Alt-Shift-Down", "Command-Option-Down"),
|
bindKey: bindKey("Alt-Shift-Down", "Command-Option-Down"),
|
||||||
exec: function(editor) { editor.copyLinesDown(); }
|
exec: function(editor) { editor.copyLinesDown(); },
|
||||||
|
scrollIntoView: "cursor"
|
||||||
}, {
|
}, {
|
||||||
name: "movelinesdown",
|
name: "movelinesdown",
|
||||||
bindKey: bindKey("Alt-Down", "Option-Down"),
|
bindKey: bindKey("Alt-Down", "Option-Down"),
|
||||||
exec: function(editor) { editor.moveLinesDown(); }
|
exec: function(editor) { editor.moveLinesDown(); },
|
||||||
|
scrollIntoView: "cursor"
|
||||||
}, {
|
}, {
|
||||||
name: "del",
|
name: "del",
|
||||||
bindKey: bindKey("Delete", "Delete|Ctrl-D"),
|
bindKey: bindKey("Delete", "Delete|Ctrl-D|Shift-Delete"),
|
||||||
exec: function(editor) { editor.remove("right"); },
|
exec: function(editor) { editor.remove("right"); },
|
||||||
multiSelectAction: "forEach"
|
multiSelectAction: "forEach",
|
||||||
|
scrollIntoView: "cursor"
|
||||||
}, {
|
}, {
|
||||||
name: "backspace",
|
name: "backspace",
|
||||||
bindKey: bindKey(
|
bindKey: bindKey(
|
||||||
"Command-Backspace|Option-Backspace|Shift-Backspace|Backspace",
|
"Shift-Backspace|Backspace",
|
||||||
"Ctrl-Backspace|Command-Backspace|Shift-Backspace|Backspace|Ctrl-H"
|
"Ctrl-Backspace|Shift-Backspace|Backspace|Ctrl-H"
|
||||||
),
|
),
|
||||||
exec: function(editor) { editor.remove("left"); },
|
exec: function(editor) { editor.remove("left"); },
|
||||||
multiSelectAction: "forEach"
|
multiSelectAction: "forEach",
|
||||||
|
scrollIntoView: "cursor"
|
||||||
|
}, {
|
||||||
|
name: "cut_or_delete",
|
||||||
|
bindKey: bindKey("Shift-Delete", null),
|
||||||
|
exec: function(editor) {
|
||||||
|
if (editor.selection.isEmpty()) {
|
||||||
|
editor.remove("left");
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
multiSelectAction: "forEach",
|
||||||
|
scrollIntoView: "cursor"
|
||||||
}, {
|
}, {
|
||||||
name: "removetolinestart",
|
name: "removetolinestart",
|
||||||
bindKey: bindKey("Alt-Backspace", "Command-Backspace"),
|
bindKey: bindKey("Alt-Backspace", "Command-Backspace"),
|
||||||
exec: function(editor) { editor.removeToLineStart(); },
|
exec: function(editor) { editor.removeToLineStart(); },
|
||||||
multiSelectAction: "forEach"
|
multiSelectAction: "forEach",
|
||||||
|
scrollIntoView: "cursor"
|
||||||
}, {
|
}, {
|
||||||
name: "removetolineend",
|
name: "removetolineend",
|
||||||
bindKey: bindKey("Alt-Delete", "Ctrl-K"),
|
bindKey: bindKey("Alt-Delete", "Ctrl-K"),
|
||||||
exec: function(editor) { editor.removeToLineEnd(); },
|
exec: function(editor) { editor.removeToLineEnd(); },
|
||||||
multiSelectAction: "forEach"
|
multiSelectAction: "forEach",
|
||||||
|
scrollIntoView: "cursor"
|
||||||
}, {
|
}, {
|
||||||
name: "removewordleft",
|
name: "removewordleft",
|
||||||
bindKey: bindKey("Ctrl-Backspace", "Alt-Backspace|Ctrl-Alt-Backspace"),
|
bindKey: bindKey("Ctrl-Backspace", "Alt-Backspace|Ctrl-Alt-Backspace"),
|
||||||
exec: function(editor) { editor.removeWordLeft(); },
|
exec: function(editor) { editor.removeWordLeft(); },
|
||||||
multiSelectAction: "forEach"
|
multiSelectAction: "forEach",
|
||||||
|
scrollIntoView: "cursor"
|
||||||
}, {
|
}, {
|
||||||
name: "removewordright",
|
name: "removewordright",
|
||||||
bindKey: bindKey("Ctrl-Delete", "Alt-Delete"),
|
bindKey: bindKey("Ctrl-Delete", "Alt-Delete"),
|
||||||
exec: function(editor) { editor.removeWordRight(); },
|
exec: function(editor) { editor.removeWordRight(); },
|
||||||
multiSelectAction: "forEach"
|
multiSelectAction: "forEach",
|
||||||
|
scrollIntoView: "cursor"
|
||||||
}, {
|
}, {
|
||||||
name: "outdent",
|
name: "outdent",
|
||||||
bindKey: bindKey("Shift-Tab", "Shift-Tab"),
|
bindKey: bindKey("Shift-Tab", "Shift-Tab"),
|
||||||
exec: function(editor) { editor.blockOutdent(); },
|
exec: function(editor) { editor.blockOutdent(); },
|
||||||
multiSelectAction: "forEach"
|
multiSelectAction: "forEach",
|
||||||
|
scrollIntoView: "selectionPart"
|
||||||
}, {
|
}, {
|
||||||
name: "indent",
|
name: "indent",
|
||||||
bindKey: bindKey("Tab", "Tab"),
|
bindKey: bindKey("Tab", "Tab"),
|
||||||
exec: function(editor) { editor.indent(); },
|
exec: function(editor) { editor.indent(); },
|
||||||
multiSelectAction: "forEach"
|
multiSelectAction: "forEach",
|
||||||
|
scrollIntoView: "selectionPart"
|
||||||
|
}, {
|
||||||
|
name: "blockoutdent",
|
||||||
|
bindKey: bindKey("Ctrl-[", "Ctrl-["),
|
||||||
|
exec: function(editor) { editor.blockOutdent(); },
|
||||||
|
multiSelectAction: "forEachLine",
|
||||||
|
scrollIntoView: "selectionPart"
|
||||||
|
}, {
|
||||||
|
name: "blockindent",
|
||||||
|
bindKey: bindKey("Ctrl-]", "Ctrl-]"),
|
||||||
|
exec: function(editor) { editor.blockIndent(); },
|
||||||
|
multiSelectAction: "forEachLine",
|
||||||
|
scrollIntoView: "selectionPart"
|
||||||
}, {
|
}, {
|
||||||
name: "insertstring",
|
name: "insertstring",
|
||||||
exec: function(editor, str) { editor.insert(str); },
|
exec: function(editor, str) { editor.insert(str); },
|
||||||
multiSelectAction: "forEach"
|
multiSelectAction: "forEach",
|
||||||
|
scrollIntoView: "cursor"
|
||||||
}, {
|
}, {
|
||||||
name: "inserttext",
|
name: "inserttext",
|
||||||
exec: function(editor, args) {
|
exec: function(editor, args) {
|
||||||
editor.insert(lang.stringRepeat(args.text || "", args.times || 1));
|
editor.insert(lang.stringRepeat(args.text || "", args.times || 1));
|
||||||
},
|
},
|
||||||
multiSelectAction: "forEach"
|
multiSelectAction: "forEach",
|
||||||
|
scrollIntoView: "cursor"
|
||||||
}, {
|
}, {
|
||||||
name: "splitline",
|
name: "splitline",
|
||||||
bindKey: bindKey(null, "Ctrl-O"),
|
bindKey: bindKey(null, "Ctrl-O"),
|
||||||
exec: function(editor) { editor.splitLine(); },
|
exec: function(editor) { editor.splitLine(); },
|
||||||
multiSelectAction: "forEach"
|
multiSelectAction: "forEach",
|
||||||
|
scrollIntoView: "cursor"
|
||||||
}, {
|
}, {
|
||||||
name: "transposeletters",
|
name: "transposeletters",
|
||||||
bindKey: bindKey("Ctrl-T", "Ctrl-T"),
|
bindKey: bindKey("Ctrl-T", "Ctrl-T"),
|
||||||
exec: function(editor) { editor.transposeLetters(); },
|
exec: function(editor) { editor.transposeLetters(); },
|
||||||
multiSelectAction: function(editor) {editor.transposeSelections(1); }
|
multiSelectAction: function(editor) {editor.transposeSelections(1); },
|
||||||
|
scrollIntoView: "cursor"
|
||||||
}, {
|
}, {
|
||||||
name: "touppercase",
|
name: "touppercase",
|
||||||
bindKey: bindKey("Ctrl-U", "Ctrl-U"),
|
bindKey: bindKey("Ctrl-U", "Ctrl-U"),
|
||||||
exec: function(editor) { editor.toUpperCase(); },
|
exec: function(editor) { editor.toUpperCase(); },
|
||||||
multiSelectAction: "forEach"
|
multiSelectAction: "forEach",
|
||||||
|
scrollIntoView: "cursor"
|
||||||
}, {
|
}, {
|
||||||
name: "tolowercase",
|
name: "tolowercase",
|
||||||
bindKey: bindKey("Ctrl-Shift-U", "Ctrl-Shift-U"),
|
bindKey: bindKey("Ctrl-Shift-U", "Ctrl-Shift-U"),
|
||||||
exec: function(editor) { editor.toLowerCase(); },
|
exec: function(editor) { editor.toLowerCase(); },
|
||||||
multiSelectAction: "forEach"
|
multiSelectAction: "forEach",
|
||||||
|
scrollIntoView: "cursor"
|
||||||
|
}, {
|
||||||
|
name: "expandtoline",
|
||||||
|
bindKey: bindKey("Ctrl-Shift-L", "Command-Shift-L"),
|
||||||
|
exec: function(editor) {
|
||||||
|
var range = editor.selection.getRange();
|
||||||
|
|
||||||
|
range.start.column = range.end.column = 0;
|
||||||
|
range.end.row++;
|
||||||
|
editor.selection.setRange(range, false);
|
||||||
|
},
|
||||||
|
multiSelectAction: "forEach",
|
||||||
|
scrollIntoView: "cursor",
|
||||||
|
readOnly: true
|
||||||
|
}, {
|
||||||
|
name: "joinlines",
|
||||||
|
bindKey: bindKey(null, null),
|
||||||
|
exec: function(editor) {
|
||||||
|
var isBackwards = editor.selection.isBackwards();
|
||||||
|
var selectionStart = isBackwards ? editor.selection.getSelectionLead() : editor.selection.getSelectionAnchor();
|
||||||
|
var selectionEnd = isBackwards ? editor.selection.getSelectionAnchor() : editor.selection.getSelectionLead();
|
||||||
|
var firstLineEndCol = editor.session.doc.getLine(selectionStart.row).length;
|
||||||
|
var selectedText = editor.session.doc.getTextRange(editor.selection.getRange());
|
||||||
|
var selectedCount = selectedText.replace(/\n\s*/, " ").length;
|
||||||
|
var insertLine = editor.session.doc.getLine(selectionStart.row);
|
||||||
|
|
||||||
|
for (var i = selectionStart.row + 1; i <= selectionEnd.row + 1; i++) {
|
||||||
|
var curLine = lang.stringTrimLeft(lang.stringTrimRight(editor.session.doc.getLine(i)));
|
||||||
|
if (curLine.length !== 0) {
|
||||||
|
curLine = " " + curLine;
|
||||||
|
}
|
||||||
|
insertLine += curLine;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectionEnd.row + 1 < (editor.session.doc.getLength() - 1)) {
|
||||||
|
// Don't insert a newline at the end of the document
|
||||||
|
insertLine += editor.session.doc.getNewLineCharacter();
|
||||||
|
}
|
||||||
|
|
||||||
|
editor.clearSelection();
|
||||||
|
editor.session.doc.replace(new Range(selectionStart.row, 0, selectionEnd.row + 2, 0), insertLine);
|
||||||
|
|
||||||
|
if (selectedCount > 0) {
|
||||||
|
// Select the text that was previously selected
|
||||||
|
editor.selection.moveCursorTo(selectionStart.row, selectionStart.column);
|
||||||
|
editor.selection.selectTo(selectionStart.row, selectionStart.column + selectedCount);
|
||||||
|
} else {
|
||||||
|
// If the joined line had something in it, start the cursor at that something
|
||||||
|
firstLineEndCol = editor.session.doc.getLine(selectionStart.row).length > firstLineEndCol ? (firstLineEndCol + 1) : firstLineEndCol;
|
||||||
|
editor.selection.moveCursorTo(selectionStart.row, firstLineEndCol);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
multiSelectAction: "forEach",
|
||||||
|
readOnly: true
|
||||||
|
}, {
|
||||||
|
name: "invertSelection",
|
||||||
|
bindKey: bindKey(null, null),
|
||||||
|
exec: function(editor) {
|
||||||
|
var endRow = editor.session.doc.getLength() - 1;
|
||||||
|
var endCol = editor.session.doc.getLine(endRow).length;
|
||||||
|
var ranges = editor.selection.rangeList.ranges;
|
||||||
|
var newRanges = [];
|
||||||
|
|
||||||
|
// If multiple selections don't exist, rangeList will return 0 so replace with single range
|
||||||
|
if (ranges.length < 1) {
|
||||||
|
ranges = [editor.selection.getRange()];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < ranges.length; i++) {
|
||||||
|
if (i == (ranges.length - 1)) {
|
||||||
|
// The last selection must connect to the end of the document, unless it already does
|
||||||
|
if (!(ranges[i].end.row === endRow && ranges[i].end.column === endCol)) {
|
||||||
|
newRanges.push(new Range(ranges[i].end.row, ranges[i].end.column, endRow, endCol));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i === 0) {
|
||||||
|
// The first selection must connect to the start of the document, unless it already does
|
||||||
|
if (!(ranges[i].start.row === 0 && ranges[i].start.column === 0)) {
|
||||||
|
newRanges.push(new Range(0, 0, ranges[i].start.row, ranges[i].start.column));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
newRanges.push(new Range(ranges[i-1].end.row, ranges[i-1].end.column, ranges[i].start.row, ranges[i].start.column));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
editor.exitMultiSelectMode();
|
||||||
|
editor.clearSelection();
|
||||||
|
|
||||||
|
for(var i = 0; i < newRanges.length; i++) {
|
||||||
|
editor.selection.addRange(newRanges[i], false);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
readOnly: true,
|
||||||
|
scrollIntoView: "none"
|
||||||
}];
|
}];
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
+232
@@ -0,0 +1,232 @@
|
|||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Distributed under the BSD license:
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010, Ajax.org B.V.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of Ajax.org B.V. nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
define(function(require, exports, module) {
|
||||||
|
|
||||||
|
var config = require("../config");
|
||||||
|
var oop = require("../lib/oop");
|
||||||
|
var HashHandler = require("../keyboard/hash_handler").HashHandler;
|
||||||
|
var occurStartCommand = require("./occur_commands").occurStartCommand;
|
||||||
|
|
||||||
|
// These commands can be installed in a normal key handler to start iSearch:
|
||||||
|
exports.iSearchStartCommands = [{
|
||||||
|
name: "iSearch",
|
||||||
|
bindKey: {win: "Ctrl-F", mac: "Command-F"},
|
||||||
|
exec: function(editor, options) {
|
||||||
|
config.loadModule(["core", "ace/incremental_search"], function(e) {
|
||||||
|
var iSearch = e.iSearch = e.iSearch || new e.IncrementalSearch();
|
||||||
|
iSearch.activate(editor, options.backwards);
|
||||||
|
if (options.jumpToFirstMatch) iSearch.next(options);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
readOnly: true
|
||||||
|
}, {
|
||||||
|
name: "iSearchBackwards",
|
||||||
|
exec: function(editor, jumpToNext) { editor.execCommand('iSearch', {backwards: true}); },
|
||||||
|
readOnly: true
|
||||||
|
}, {
|
||||||
|
name: "iSearchAndGo",
|
||||||
|
bindKey: {win: "Ctrl-K", mac: "Command-G"},
|
||||||
|
exec: function(editor, jumpToNext) { editor.execCommand('iSearch', {jumpToFirstMatch: true, useCurrentOrPrevSearch: true}); },
|
||||||
|
readOnly: true
|
||||||
|
}, {
|
||||||
|
name: "iSearchBackwardsAndGo",
|
||||||
|
bindKey: {win: "Ctrl-Shift-K", mac: "Command-Shift-G"},
|
||||||
|
exec: function(editor) { editor.execCommand('iSearch', {jumpToFirstMatch: true, backwards: true, useCurrentOrPrevSearch: true}); },
|
||||||
|
readOnly: true
|
||||||
|
}];
|
||||||
|
|
||||||
|
// These commands are only available when incremental search mode is active:
|
||||||
|
exports.iSearchCommands = [{
|
||||||
|
name: "restartSearch",
|
||||||
|
bindKey: {win: "Ctrl-F", mac: "Command-F"},
|
||||||
|
exec: function(iSearch) {
|
||||||
|
iSearch.cancelSearch(true);
|
||||||
|
},
|
||||||
|
readOnly: true,
|
||||||
|
isIncrementalSearchCommand: true
|
||||||
|
}, {
|
||||||
|
name: "searchForward",
|
||||||
|
bindKey: {win: "Ctrl-S|Ctrl-K", mac: "Ctrl-S|Command-G"},
|
||||||
|
exec: function(iSearch, options) {
|
||||||
|
options.useCurrentOrPrevSearch = true;
|
||||||
|
iSearch.next(options);
|
||||||
|
},
|
||||||
|
readOnly: true,
|
||||||
|
isIncrementalSearchCommand: true
|
||||||
|
}, {
|
||||||
|
name: "searchBackward",
|
||||||
|
bindKey: {win: "Ctrl-R|Ctrl-Shift-K", mac: "Ctrl-R|Command-Shift-G"},
|
||||||
|
exec: function(iSearch, options) {
|
||||||
|
options.useCurrentOrPrevSearch = true;
|
||||||
|
options.backwards = true;
|
||||||
|
iSearch.next(options);
|
||||||
|
},
|
||||||
|
readOnly: true,
|
||||||
|
isIncrementalSearchCommand: true
|
||||||
|
}, {
|
||||||
|
name: "extendSearchTerm",
|
||||||
|
exec: function(iSearch, string) {
|
||||||
|
iSearch.addString(string);
|
||||||
|
},
|
||||||
|
readOnly: true,
|
||||||
|
isIncrementalSearchCommand: true
|
||||||
|
}, {
|
||||||
|
name: "extendSearchTermSpace",
|
||||||
|
bindKey: "space",
|
||||||
|
exec: function(iSearch) { iSearch.addString(' '); },
|
||||||
|
readOnly: true,
|
||||||
|
isIncrementalSearchCommand: true
|
||||||
|
}, {
|
||||||
|
name: "shrinkSearchTerm",
|
||||||
|
bindKey: "backspace",
|
||||||
|
exec: function(iSearch) {
|
||||||
|
iSearch.removeChar();
|
||||||
|
},
|
||||||
|
readOnly: true,
|
||||||
|
isIncrementalSearchCommand: true
|
||||||
|
}, {
|
||||||
|
name: 'confirmSearch',
|
||||||
|
bindKey: 'return',
|
||||||
|
exec: function(iSearch) { iSearch.deactivate(); },
|
||||||
|
readOnly: true,
|
||||||
|
isIncrementalSearchCommand: true
|
||||||
|
}, {
|
||||||
|
name: 'cancelSearch',
|
||||||
|
bindKey: 'esc|Ctrl-G',
|
||||||
|
exec: function(iSearch) { iSearch.deactivate(true); },
|
||||||
|
readOnly: true,
|
||||||
|
isIncrementalSearchCommand: true
|
||||||
|
}, {
|
||||||
|
name: 'occurisearch',
|
||||||
|
bindKey: 'Ctrl-O',
|
||||||
|
exec: function(iSearch) {
|
||||||
|
var options = oop.mixin({}, iSearch.$options);
|
||||||
|
iSearch.deactivate();
|
||||||
|
occurStartCommand.exec(iSearch.$editor, options);
|
||||||
|
},
|
||||||
|
readOnly: true,
|
||||||
|
isIncrementalSearchCommand: true
|
||||||
|
}, {
|
||||||
|
name: "yankNextWord",
|
||||||
|
bindKey: "Ctrl-w",
|
||||||
|
exec: function(iSearch) {
|
||||||
|
var ed = iSearch.$editor,
|
||||||
|
range = ed.selection.getRangeOfMovements(function(sel) { sel.moveCursorWordRight(); }),
|
||||||
|
string = ed.session.getTextRange(range);
|
||||||
|
iSearch.addString(string);
|
||||||
|
},
|
||||||
|
readOnly: true,
|
||||||
|
isIncrementalSearchCommand: true
|
||||||
|
}, {
|
||||||
|
name: "yankNextChar",
|
||||||
|
bindKey: "Ctrl-Alt-y",
|
||||||
|
exec: function(iSearch) {
|
||||||
|
var ed = iSearch.$editor,
|
||||||
|
range = ed.selection.getRangeOfMovements(function(sel) { sel.moveCursorRight(); }),
|
||||||
|
string = ed.session.getTextRange(range);
|
||||||
|
iSearch.addString(string);
|
||||||
|
},
|
||||||
|
readOnly: true,
|
||||||
|
isIncrementalSearchCommand: true
|
||||||
|
}, {
|
||||||
|
name: 'recenterTopBottom',
|
||||||
|
bindKey: 'Ctrl-l',
|
||||||
|
exec: function(iSearch) { iSearch.$editor.execCommand('recenterTopBottom'); },
|
||||||
|
readOnly: true,
|
||||||
|
isIncrementalSearchCommand: true
|
||||||
|
}, {
|
||||||
|
name: 'selectAllMatches',
|
||||||
|
bindKey: 'Ctrl-space',
|
||||||
|
exec: function(iSearch) {
|
||||||
|
var ed = iSearch.$editor,
|
||||||
|
hl = ed.session.$isearchHighlight,
|
||||||
|
ranges = hl && hl.cache ? hl.cache
|
||||||
|
.reduce(function(ranges, ea) {
|
||||||
|
return ranges.concat(ea ? ea : []); }, []) : [];
|
||||||
|
iSearch.deactivate(false);
|
||||||
|
ranges.forEach(ed.selection.addRange.bind(ed.selection));
|
||||||
|
},
|
||||||
|
readOnly: true,
|
||||||
|
isIncrementalSearchCommand: true
|
||||||
|
}, {
|
||||||
|
name: 'searchAsRegExp',
|
||||||
|
bindKey: 'Alt-r',
|
||||||
|
exec: function(iSearch) {
|
||||||
|
iSearch.convertNeedleToRegExp();
|
||||||
|
},
|
||||||
|
readOnly: true,
|
||||||
|
isIncrementalSearchCommand: true
|
||||||
|
}];
|
||||||
|
|
||||||
|
function IncrementalSearchKeyboardHandler(iSearch) {
|
||||||
|
this.$iSearch = iSearch;
|
||||||
|
}
|
||||||
|
|
||||||
|
oop.inherits(IncrementalSearchKeyboardHandler, HashHandler);
|
||||||
|
|
||||||
|
;(function() {
|
||||||
|
|
||||||
|
this.attach = function(editor) {
|
||||||
|
var iSearch = this.$iSearch;
|
||||||
|
HashHandler.call(this, exports.iSearchCommands, editor.commands.platform);
|
||||||
|
this.$commandExecHandler = editor.commands.addEventListener('exec', function(e) {
|
||||||
|
if (!e.command.isIncrementalSearchCommand) return undefined;
|
||||||
|
e.stopPropagation();
|
||||||
|
e.preventDefault();
|
||||||
|
return e.command.exec(iSearch, e.args || {});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.detach = function(editor) {
|
||||||
|
if (!this.$commandExecHandler) return;
|
||||||
|
editor.commands.removeEventListener('exec', this.$commandExecHandler);
|
||||||
|
delete this.$commandExecHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
var handleKeyboard$super = this.handleKeyboard;
|
||||||
|
this.handleKeyboard = function(data, hashId, key, keyCode) {
|
||||||
|
if (((hashId === 1/*ctrl*/ || hashId === 8/*command*/) && key === 'v')
|
||||||
|
|| (hashId === 1/*ctrl*/ && key === 'y')) return null;
|
||||||
|
var cmd = handleKeyboard$super.call(this, data, hashId, key, keyCode);
|
||||||
|
if (cmd.command) { return cmd; }
|
||||||
|
if (hashId == -1) {
|
||||||
|
var extendCmd = this.commands.extendSearchTerm;
|
||||||
|
if (extendCmd) { return {command: extendCmd, args: key}; }
|
||||||
|
}
|
||||||
|
return {command: "null", passEvent: hashId == 0 || hashId == 4};
|
||||||
|
}
|
||||||
|
|
||||||
|
}).call(IncrementalSearchKeyboardHandler.prototype);
|
||||||
|
|
||||||
|
|
||||||
|
exports.IncrementalSearchKeyboardHandler = IncrementalSearchKeyboardHandler;
|
||||||
|
|
||||||
|
});
|
||||||
+17
-1
@@ -35,41 +35,49 @@ exports.defaultCommands = [{
|
|||||||
name: "addCursorAbove",
|
name: "addCursorAbove",
|
||||||
exec: function(editor) { editor.selectMoreLines(-1); },
|
exec: function(editor) { editor.selectMoreLines(-1); },
|
||||||
bindKey: {win: "Ctrl-Alt-Up", mac: "Ctrl-Alt-Up"},
|
bindKey: {win: "Ctrl-Alt-Up", mac: "Ctrl-Alt-Up"},
|
||||||
|
scrollIntoView: "cursor",
|
||||||
readonly: true
|
readonly: true
|
||||||
}, {
|
}, {
|
||||||
name: "addCursorBelow",
|
name: "addCursorBelow",
|
||||||
exec: function(editor) { editor.selectMoreLines(1); },
|
exec: function(editor) { editor.selectMoreLines(1); },
|
||||||
bindKey: {win: "Ctrl-Alt-Down", mac: "Ctrl-Alt-Down"},
|
bindKey: {win: "Ctrl-Alt-Down", mac: "Ctrl-Alt-Down"},
|
||||||
|
scrollIntoView: "cursor",
|
||||||
readonly: true
|
readonly: true
|
||||||
}, {
|
}, {
|
||||||
name: "addCursorAboveSkipCurrent",
|
name: "addCursorAboveSkipCurrent",
|
||||||
exec: function(editor) { editor.selectMoreLines(-1, true); },
|
exec: function(editor) { editor.selectMoreLines(-1, true); },
|
||||||
bindKey: {win: "Ctrl-Alt-Shift-Up", mac: "Ctrl-Alt-Shift-Up"},
|
bindKey: {win: "Ctrl-Alt-Shift-Up", mac: "Ctrl-Alt-Shift-Up"},
|
||||||
|
scrollIntoView: "cursor",
|
||||||
readonly: true
|
readonly: true
|
||||||
}, {
|
}, {
|
||||||
name: "addCursorBelowSkipCurrent",
|
name: "addCursorBelowSkipCurrent",
|
||||||
exec: function(editor) { editor.selectMoreLines(1, true); },
|
exec: function(editor) { editor.selectMoreLines(1, true); },
|
||||||
bindKey: {win: "Ctrl-Alt-Shift-Down", mac: "Ctrl-Alt-Shift-Down"},
|
bindKey: {win: "Ctrl-Alt-Shift-Down", mac: "Ctrl-Alt-Shift-Down"},
|
||||||
|
scrollIntoView: "cursor",
|
||||||
readonly: true
|
readonly: true
|
||||||
}, {
|
}, {
|
||||||
name: "selectMoreBefore",
|
name: "selectMoreBefore",
|
||||||
exec: function(editor) { editor.selectMore(-1); },
|
exec: function(editor) { editor.selectMore(-1); },
|
||||||
bindKey: {win: "Ctrl-Alt-Left", mac: "Ctrl-Alt-Left"},
|
bindKey: {win: "Ctrl-Alt-Left", mac: "Ctrl-Alt-Left"},
|
||||||
|
scrollIntoView: "cursor",
|
||||||
readonly: true
|
readonly: true
|
||||||
}, {
|
}, {
|
||||||
name: "selectMoreAfter",
|
name: "selectMoreAfter",
|
||||||
exec: function(editor) { editor.selectMore(1); },
|
exec: function(editor) { editor.selectMore(1); },
|
||||||
bindKey: {win: "Ctrl-Alt-Right", mac: "Ctrl-Alt-Right"},
|
bindKey: {win: "Ctrl-Alt-Right", mac: "Ctrl-Alt-Right"},
|
||||||
|
scrollIntoView: "cursor",
|
||||||
readonly: true
|
readonly: true
|
||||||
}, {
|
}, {
|
||||||
name: "selectNextBefore",
|
name: "selectNextBefore",
|
||||||
exec: function(editor) { editor.selectMore(-1, true); },
|
exec: function(editor) { editor.selectMore(-1, true); },
|
||||||
bindKey: {win: "Ctrl-Alt-Shift-Left", mac: "Ctrl-Alt-Shift-Left"},
|
bindKey: {win: "Ctrl-Alt-Shift-Left", mac: "Ctrl-Alt-Shift-Left"},
|
||||||
|
scrollIntoView: "cursor",
|
||||||
readonly: true
|
readonly: true
|
||||||
}, {
|
}, {
|
||||||
name: "selectNextAfter",
|
name: "selectNextAfter",
|
||||||
exec: function(editor) { editor.selectMore(1, true); },
|
exec: function(editor) { editor.selectMore(1, true); },
|
||||||
bindKey: {win: "Ctrl-Alt-Shift-Right", mac: "Ctrl-Alt-Shift-Right"},
|
bindKey: {win: "Ctrl-Alt-Shift-Right", mac: "Ctrl-Alt-Shift-Right"},
|
||||||
|
scrollIntoView: "cursor",
|
||||||
readonly: true
|
readonly: true
|
||||||
}, {
|
}, {
|
||||||
name: "splitIntoLines",
|
name: "splitIntoLines",
|
||||||
@@ -79,7 +87,14 @@ exports.defaultCommands = [{
|
|||||||
}, {
|
}, {
|
||||||
name: "alignCursors",
|
name: "alignCursors",
|
||||||
exec: function(editor) { editor.alignCursors(); },
|
exec: function(editor) { editor.alignCursors(); },
|
||||||
bindKey: {win: "Ctrl-Alt-A", mac: "Ctrl-Alt-A"}
|
bindKey: {win: "Ctrl-Alt-A", mac: "Ctrl-Alt-A"},
|
||||||
|
scrollIntoView: "cursor"
|
||||||
|
}, {
|
||||||
|
name: "findAll",
|
||||||
|
exec: function(editor) { editor.findAll(); },
|
||||||
|
bindKey: {win: "Ctrl-Alt-K", mac: "Ctrl-Alt-G"},
|
||||||
|
scrollIntoView: "cursor",
|
||||||
|
readonly: true
|
||||||
}];
|
}];
|
||||||
|
|
||||||
// commands active only in multiselect mode
|
// commands active only in multiselect mode
|
||||||
@@ -87,6 +102,7 @@ exports.multiSelectCommands = [{
|
|||||||
name: "singleSelection",
|
name: "singleSelection",
|
||||||
bindKey: "esc",
|
bindKey: "esc",
|
||||||
exec: function(editor) { editor.exitMultiSelectMode(); },
|
exec: function(editor) { editor.exitMultiSelectMode(); },
|
||||||
|
scrollIntoView: "cursor",
|
||||||
readonly: true,
|
readonly: true,
|
||||||
isAvailable: function(editor) {return editor && editor.inMultiSelectMode}
|
isAvailable: function(editor) {return editor && editor.inMultiSelectMode}
|
||||||
}];
|
}];
|
||||||
|
|||||||
@@ -0,0 +1,110 @@
|
|||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Distributed under the BSD license:
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010, Ajax.org B.V.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of Ajax.org B.V. nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
define(function(require, exports, module) {
|
||||||
|
|
||||||
|
var config = require("../config"),
|
||||||
|
Occur = require("../occur").Occur;
|
||||||
|
|
||||||
|
// These commands can be installed in a normal command handler to start occur:
|
||||||
|
var occurStartCommand = {
|
||||||
|
name: "occur",
|
||||||
|
exec: function(editor, options) {
|
||||||
|
var alreadyInOccur = !!editor.session.$occur;
|
||||||
|
var occurSessionActive = new Occur().enter(editor, options);
|
||||||
|
if (occurSessionActive && !alreadyInOccur)
|
||||||
|
OccurKeyboardHandler.installIn(editor);
|
||||||
|
},
|
||||||
|
readOnly: true
|
||||||
|
};
|
||||||
|
|
||||||
|
var occurCommands = [{
|
||||||
|
name: "occurexit",
|
||||||
|
bindKey: 'esc|Ctrl-G',
|
||||||
|
exec: function(editor) {
|
||||||
|
var occur = editor.session.$occur;
|
||||||
|
if (!occur) return;
|
||||||
|
occur.exit(editor, {});
|
||||||
|
if (!editor.session.$occur) OccurKeyboardHandler.uninstallFrom(editor);
|
||||||
|
},
|
||||||
|
readOnly: true
|
||||||
|
}, {
|
||||||
|
name: "occuraccept",
|
||||||
|
bindKey: 'enter',
|
||||||
|
exec: function(editor) {
|
||||||
|
var occur = editor.session.$occur;
|
||||||
|
if (!occur) return;
|
||||||
|
occur.exit(editor, {translatePosition: true});
|
||||||
|
if (!editor.session.$occur) OccurKeyboardHandler.uninstallFrom(editor);
|
||||||
|
},
|
||||||
|
readOnly: true
|
||||||
|
}];
|
||||||
|
|
||||||
|
var HashHandler = require("../keyboard/hash_handler").HashHandler;
|
||||||
|
var oop = require("../lib/oop");
|
||||||
|
|
||||||
|
|
||||||
|
function OccurKeyboardHandler() {}
|
||||||
|
|
||||||
|
oop.inherits(OccurKeyboardHandler, HashHandler);
|
||||||
|
|
||||||
|
;(function() {
|
||||||
|
|
||||||
|
this.isOccurHandler = true;
|
||||||
|
|
||||||
|
this.attach = function(editor) {
|
||||||
|
HashHandler.call(this, occurCommands, editor.commands.platform);
|
||||||
|
this.$editor = editor;
|
||||||
|
}
|
||||||
|
|
||||||
|
var handleKeyboard$super = this.handleKeyboard;
|
||||||
|
this.handleKeyboard = function(data, hashId, key, keyCode) {
|
||||||
|
var cmd = handleKeyboard$super.call(this, data, hashId, key, keyCode);
|
||||||
|
return (cmd && cmd.command) ? cmd : undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
}).call(OccurKeyboardHandler.prototype);
|
||||||
|
|
||||||
|
OccurKeyboardHandler.installIn = function(editor) {
|
||||||
|
var handler = new this();
|
||||||
|
editor.keyBinding.addKeyboardHandler(handler);
|
||||||
|
editor.commands.addCommands(occurCommands);
|
||||||
|
}
|
||||||
|
|
||||||
|
OccurKeyboardHandler.uninstallFrom = function(editor) {
|
||||||
|
editor.commands.removeCommands(occurCommands);
|
||||||
|
var handler = editor.getKeyboardHandler();
|
||||||
|
if (handler.isOccurHandler)
|
||||||
|
editor.keyBinding.removeKeyboardHandler(handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.occurStartCommand = occurStartCommand;
|
||||||
|
|
||||||
|
});
|
||||||
@@ -32,6 +32,11 @@ define(function(require, exports, module) {
|
|||||||
"no use strict";
|
"no use strict";
|
||||||
|
|
||||||
var lang = require("./lib/lang");
|
var lang = require("./lib/lang");
|
||||||
|
var oop = require("./lib/oop");
|
||||||
|
var net = require("./lib/net");
|
||||||
|
var AppConfig = require("./lib/app_config").AppConfig;
|
||||||
|
|
||||||
|
module.exports = exports = new AppConfig();
|
||||||
|
|
||||||
var global = (function() {
|
var global = (function() {
|
||||||
return this;
|
return this;
|
||||||
@@ -65,30 +70,81 @@ exports.all = function() {
|
|||||||
return lang.copyObject(options);
|
return lang.copyObject(options);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// module loading
|
||||||
exports.moduleUrl = function(name, component) {
|
exports.moduleUrl = function(name, component) {
|
||||||
if (options.$moduleUrls[name])
|
if (options.$moduleUrls[name])
|
||||||
return options.$moduleUrls[name];
|
return options.$moduleUrls[name];
|
||||||
|
|
||||||
var parts = name.split("/");
|
var parts = name.split("/");
|
||||||
component = component || parts[parts.length - 2] || "";
|
component = component || parts[parts.length - 2] || "";
|
||||||
var base = parts[parts.length - 1].replace(component, "").replace(/(^[\-_])|([\-_]$)/, "");
|
|
||||||
|
// todo make this configurable or get rid of '-'
|
||||||
|
var sep = component == "snippets" ? "/" : "-";
|
||||||
|
var base = parts[parts.length - 1];
|
||||||
|
if (component == "worker" && sep == "-") {
|
||||||
|
var re = new RegExp("^" + component + "[\\-_]|[\\-_]" + component + "$", "g");
|
||||||
|
base = base.replace(re, "");
|
||||||
|
}
|
||||||
|
|
||||||
if (!base && parts.length > 1)
|
if ((!base || base == component) && parts.length > 1)
|
||||||
base = parts[parts.length - 2];
|
base = parts[parts.length - 2];
|
||||||
var path = options[component + "Path"];
|
var path = options[component + "Path"];
|
||||||
if (path == null)
|
if (path == null) {
|
||||||
path = options.basePath;
|
path = options.basePath;
|
||||||
|
} else if (sep == "/") {
|
||||||
|
component = sep = "";
|
||||||
|
}
|
||||||
if (path && path.slice(-1) != "/")
|
if (path && path.slice(-1) != "/")
|
||||||
path += "/";
|
path += "/";
|
||||||
return path + component + "-" + base + this.get("suffix");
|
return path + component + sep + base + this.get("suffix");
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.setModuleUrl = function(name, subst) {
|
exports.setModuleUrl = function(name, subst) {
|
||||||
return options.$moduleUrls[name] = subst;
|
return options.$moduleUrls[name] = subst;
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.init = function() {
|
exports.$loading = {};
|
||||||
options.packaged = require.packaged || module.packaged || (global.define && define.packaged);
|
exports.loadModule = function(moduleName, onLoad) {
|
||||||
|
var module, moduleType;
|
||||||
|
if (Array.isArray(moduleName)) {
|
||||||
|
moduleType = moduleName[0];
|
||||||
|
moduleName = moduleName[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
module = require(moduleName);
|
||||||
|
} catch (e) {}
|
||||||
|
// require(moduleName) can return empty object if called after require([moduleName], callback)
|
||||||
|
if (module && !exports.$loading[moduleName])
|
||||||
|
return onLoad && onLoad(module);
|
||||||
|
|
||||||
|
if (!exports.$loading[moduleName])
|
||||||
|
exports.$loading[moduleName] = [];
|
||||||
|
|
||||||
|
exports.$loading[moduleName].push(onLoad);
|
||||||
|
|
||||||
|
if (exports.$loading[moduleName].length > 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var afterLoad = function() {
|
||||||
|
require([moduleName], function(module) {
|
||||||
|
exports._emit("load.module", {name: moduleName, module: module});
|
||||||
|
var listeners = exports.$loading[moduleName];
|
||||||
|
exports.$loading[moduleName] = null;
|
||||||
|
listeners.forEach(function(onLoad) {
|
||||||
|
onLoad && onLoad(module);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!exports.get("packaged"))
|
||||||
|
return afterLoad();
|
||||||
|
net.loadScript(exports.moduleUrl(moduleName, moduleType), afterLoad);
|
||||||
|
};
|
||||||
|
|
||||||
|
// initialization
|
||||||
|
function init(packaged) {
|
||||||
|
options.packaged = packaged || require.packaged || module.packaged || (global.define && define.packaged);
|
||||||
|
|
||||||
if (!global.document)
|
if (!global.document)
|
||||||
return "";
|
return "";
|
||||||
@@ -96,7 +152,11 @@ exports.init = function() {
|
|||||||
var scriptOptions = {};
|
var scriptOptions = {};
|
||||||
var scriptUrl = "";
|
var scriptUrl = "";
|
||||||
|
|
||||||
var scripts = document.getElementsByTagName("script");
|
// Use currentScript.ownerDocument in case this file was loaded from imported document. (HTML Imports)
|
||||||
|
var currentScript = (document.currentScript || document._currentScript ); // native or polyfill
|
||||||
|
var currentDocument = currentScript && currentScript.ownerDocument || document;
|
||||||
|
|
||||||
|
var scripts = currentDocument.getElementsByTagName("script");
|
||||||
for (var i=0; i<scripts.length; i++) {
|
for (var i=0; i<scripts.length; i++) {
|
||||||
var script = scripts[i];
|
var script = scripts[i];
|
||||||
|
|
||||||
@@ -122,6 +182,7 @@ exports.init = function() {
|
|||||||
scriptOptions.packaged = true;
|
scriptOptions.packaged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scriptOptions.basePath = scriptOptions.base;
|
||||||
scriptOptions.workerPath = scriptOptions.workerPath || scriptOptions.base;
|
scriptOptions.workerPath = scriptOptions.workerPath || scriptOptions.base;
|
||||||
scriptOptions.modePath = scriptOptions.modePath || scriptOptions.base;
|
scriptOptions.modePath = scriptOptions.modePath || scriptOptions.base;
|
||||||
scriptOptions.themePath = scriptOptions.themePath || scriptOptions.base;
|
scriptOptions.themePath = scriptOptions.themePath || scriptOptions.base;
|
||||||
@@ -132,6 +193,8 @@ exports.init = function() {
|
|||||||
exports.set(key, scriptOptions[key]);
|
exports.set(key, scriptOptions[key]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports.init = init;
|
||||||
|
|
||||||
function deHyphenate(str) {
|
function deHyphenate(str) {
|
||||||
return str.replace(/-(.)/g, function(m, m1) { return m1.toUpperCase(); });
|
return str.replace(/-(.)/g, function(m, m1) { return m1.toUpperCase(); });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,10 +40,10 @@ var assert = require("./test/assertions");
|
|||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
|
||||||
"test path resolution" : function() {
|
"test: path resolution" : function() {
|
||||||
config.set("packaged", "true");
|
config.set("packaged", "true");
|
||||||
var url = config.moduleUrl("kr_theme", "theme");
|
var url = config.moduleUrl("kr_theme", "theme");
|
||||||
assert.equal(url, "theme-kr.js");
|
assert.equal(url, "theme-kr_theme.js");
|
||||||
|
|
||||||
config.set("basePath", "a/b");
|
config.set("basePath", "a/b");
|
||||||
url = config.moduleUrl("m/theme", "theme");
|
url = config.moduleUrl("m/theme", "theme");
|
||||||
@@ -60,12 +60,76 @@ module.exports = {
|
|||||||
url = config.moduleUrl("foo/1", "theme");
|
url = config.moduleUrl("foo/1", "theme");
|
||||||
assert.equal(url, "a/b1.js");
|
assert.equal(url, "a/b1.js");
|
||||||
|
|
||||||
|
url = config.moduleUrl("snippets/js");
|
||||||
|
assert.equal(url, "a/b/snippets/js.js");
|
||||||
|
|
||||||
|
config.setModuleUrl("snippets/js", "_.js");
|
||||||
|
url = config.moduleUrl("snippets/js");
|
||||||
|
assert.equal(url, "_.js");
|
||||||
|
|
||||||
|
url = config.moduleUrl("ace/ext/textarea");
|
||||||
|
assert.equal(url, "a/b/ext-textarea.js");
|
||||||
|
|
||||||
assert.equal();
|
assert.equal();
|
||||||
|
},
|
||||||
|
"test: define options" : function() {
|
||||||
|
var o = {};
|
||||||
|
config.defineOptions(o, "test_object", {
|
||||||
|
opt1: {
|
||||||
|
set: function(val) {
|
||||||
|
this.x = val;
|
||||||
|
},
|
||||||
|
value: 7,
|
||||||
|
},
|
||||||
|
initialValue: {
|
||||||
|
set: function(val) {
|
||||||
|
this.x = val;
|
||||||
|
},
|
||||||
|
initialValue: 8,
|
||||||
|
},
|
||||||
|
opt2: {
|
||||||
|
get: function(val) {
|
||||||
|
return this.x;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
forwarded: "model"
|
||||||
|
});
|
||||||
|
o.model = {};
|
||||||
|
config.defineOptions(o.model, "model", {
|
||||||
|
forwarded: {value: 1}
|
||||||
|
});
|
||||||
|
|
||||||
|
config.resetOptions(o);
|
||||||
|
config.resetOptions(o.model);
|
||||||
|
assert.equal(o.getOption("opt1"), 7);
|
||||||
|
assert.equal(o.getOption("opt2"), 7);
|
||||||
|
o.setOption("opt1", 8);
|
||||||
|
assert.equal(o.getOption("opt1"), 8);
|
||||||
|
assert.equal(o.getOption("opt2"), 8);
|
||||||
|
|
||||||
|
assert.equal(o.getOption("forwarded"), 1);
|
||||||
|
|
||||||
|
assert.equal(o.getOption("new"), undefined);
|
||||||
|
o.setOption("new", 0);
|
||||||
|
assert.equal(o.getOption("new"), undefined);
|
||||||
|
|
||||||
|
|
||||||
|
assert.equal(o.getOption("initialValue"), 8);
|
||||||
|
o.setOption("initialValue", 7);
|
||||||
|
assert.equal(o.getOption("opt2"), 7);
|
||||||
|
|
||||||
|
config.setDefaultValues("test_object", {
|
||||||
|
opt1: 1,
|
||||||
|
forwarded: 2
|
||||||
|
});
|
||||||
|
config.resetOptions(o);
|
||||||
|
assert.equal(o.getOption("opt1"), 1);
|
||||||
|
assert.equal(o.getOption("forwarded"), 2);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (typeof module !== "undefined" && module === require.main) {
|
if (typeof module !== "undefined" && module === require.main) {
|
||||||
require("asyncjs").test.testcase(module.exports).exec()
|
require("asyncjs").test.testcase(module.exports).exec();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,21 @@
|
|||||||
.ace_editor {
|
.ace_editor {
|
||||||
position: absolute;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro', monospace;
|
font: 12px/normal 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro', monospace;
|
||||||
font-size: 12px;
|
direction: ltr;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ace_scroller {
|
.ace_scroller {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background-color: inherit;
|
||||||
|
-ms-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
cursor: text;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ace_content {
|
.ace_content {
|
||||||
@@ -15,16 +23,40 @@
|
|||||||
-moz-box-sizing: border-box;
|
-moz-box-sizing: border-box;
|
||||||
-webkit-box-sizing: border-box;
|
-webkit-box-sizing: border-box;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
cursor: text;
|
min-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ace_dragging .ace_scroller:before{
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
content: '';
|
||||||
|
background: rgba(250, 250, 250, 0.01);
|
||||||
|
z-index: 1000;
|
||||||
|
}
|
||||||
|
.ace_dragging.ace_dark .ace_scroller:before{
|
||||||
|
background: rgba(0, 0, 0, 0.01);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ace_selecting, .ace_selecting * {
|
||||||
|
cursor: text !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ace_gutter {
|
.ace_gutter {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
overflow : hidden;
|
overflow : hidden;
|
||||||
height: 100%;
|
|
||||||
width: auto;
|
width: auto;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
z-index: 4;
|
z-index: 4;
|
||||||
|
-ms-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ace_gutter-active-line {
|
.ace_gutter-active-line {
|
||||||
@@ -44,34 +76,47 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.ace_gutter-cell.ace_error {
|
.ace_gutter-cell.ace_error {
|
||||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QUM2OEZDQTQ4RTU0MTFFMUEzM0VFRTM2RUY1M0RBMjYiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QUM2OEZDQTU4RTU0MTFFMUEzM0VFRTM2RUY1M0RBMjYiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpBQzY4RkNBMjhFNTQxMUUxQTMzRUVFMzZFRjUzREEyNiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpBQzY4RkNBMzhFNTQxMUUxQTMzRUVFMzZFRjUzREEyNiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PkgXxbAAAAJbSURBVHjapFNNaBNBFH4zs5vdZLP5sQmNpT82QY209heh1ioWisaDRcSKF0WKJ0GQnrzrxasHsR6EnlrwD0TagxJabaVEpFYxLWlLSS822tr87m66ccfd2GKyVhA6MMybgfe97/vmPUQphd0sZjto9XIn9OOsvlu2nkqRzVU+6vvlzPf8W6bk8dxQ0NPbxAALgCgg2JkaQuhzQau/El0zbmUA7U0Es8v2CiYmKQJHGO1QICCLoqilMhkmurDAyapKgqItezi/USRdJqEYY4D5jCy03ht2yMkkvL91jTTX10qzyyu2hruPRN7jgbH+EOsXcMLgYiThEgAMhABW85oqy1DXdRIdvP1AHJ2acQXvDIrVHcdQNrEKNYSVMSZGMjEzIIAwDXIo+6G/FxcGnzkC3T2oMhLjre49sBB+RRcHLqdafK6sYdE/GGBwU1VpFNj0aN8pJbe+BkZyevUrvLl6Xmm0W9IuTc0DxrDNAJd5oEvI/KRsNC3bQyNjPO9yQ1YHcfj2QvfQc/5TUhJTBc2iM0U7AWDQtc1nJHvD/cfO2s7jaGkiTEfa/Ep8coLu7zmNmh8+dc5lZDuUeFAGUNA/OY6JVaypQ0vjr7XYjUvJM37vt+j1vuTK5DgVfVUoTjVe+y3/LxMxY2GgU+CSLy4cpfsYorRXuXIOi0Vt40h67uZFTdIo6nLaZcwUJWAzwNS0tBnqqKzQDnjdG/iPyZxo46HaKUpbvYkj8qYRTZsBhge+JHhZyh0x9b95JqjVJkT084kZIPwu/mPWqPgfQ5jXh2+92Ay7HedfAgwA6KDWafb4w3cAAAAASUVORK5CYII=");
|
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAABOFBMVEX/////////QRswFAb/Ui4wFAYwFAYwFAaWGAfDRymzOSH/PxswFAb/SiUwFAYwFAbUPRvjQiDllog5HhHdRybsTi3/Tyv9Tir+Syj/UC3////XurebMBIwFAb/RSHbPx/gUzfdwL3kzMivKBAwFAbbvbnhPx66NhowFAYwFAaZJg8wFAaxKBDZurf/RB6mMxb/SCMwFAYwFAbxQB3+RB4wFAb/Qhy4Oh+4QifbNRcwFAYwFAYwFAb/QRzdNhgwFAYwFAbav7v/Uy7oaE68MBK5LxLewr/r2NXewLswFAaxJw4wFAbkPRy2PyYwFAaxKhLm1tMwFAazPiQwFAaUGAb/QBrfOx3bvrv/VC/maE4wFAbRPBq6MRO8Qynew8Dp2tjfwb0wFAbx6eju5+by6uns4uH9/f36+vr/GkHjAAAAYnRSTlMAGt+64rnWu/bo8eAA4InH3+DwoN7j4eLi4xP99Nfg4+b+/u9B/eDs1MD1mO7+4PHg2MXa347g7vDizMLN4eG+Pv7i5evs/v79yu7S3/DV7/498Yv24eH+4ufQ3Ozu/v7+y13sRqwAAADLSURBVHjaZc/XDsFgGIBhtDrshlitmk2IrbHFqL2pvXf/+78DPokj7+Fz9qpU/9UXJIlhmPaTaQ6QPaz0mm+5gwkgovcV6GZzd5JtCQwgsxoHOvJO15kleRLAnMgHFIESUEPmawB9ngmelTtipwwfASilxOLyiV5UVUyVAfbG0cCPHig+GBkzAENHS0AstVF6bacZIOzgLmxsHbt2OecNgJC83JERmePUYq8ARGkJx6XtFsdddBQgZE2nPR6CICZhawjA4Fb/chv+399kfR+MMMDGOQAAAABJRU5ErkJggg==");
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-position: 2px center;
|
background-position: 2px center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ace_gutter-cell.ace_warning {
|
.ace_gutter-cell.ace_warning {
|
||||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QUM2OEZDQTg4RTU0MTFFMUEzM0VFRTM2RUY1M0RBMjYiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QUM2OEZDQTk4RTU0MTFFMUEzM0VFRTM2RUY1M0RBMjYiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpBQzY4RkNBNjhFNTQxMUUxQTMzRUVFMzZFRjUzREEyNiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpBQzY4RkNBNzhFNTQxMUUxQTMzRUVFMzZFRjUzREEyNiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pgd7PfIAAAGmSURBVHjaYvr//z8DJZiJgUIANoCRkREb9gLiSVAaQx4OQM7AAkwd7XU2/v++/rOttdYGEB9dASEvOMydGKfH8Gv/p4XTkvRBfLxeQAP+1cUhXopyvzhP7P/IoSj7g7Mw09cNKO6J1QQ0L4gICPIv/veg/8W+JdFvQNLHVsW9/nmn9zk7B+cCkDwhL7gt6knSZnx9/LuCEOcvkIAMP+cvto9nfqyZmmUAksfnBUtbM60gX/3/kgyv3/xSFOL5DZT+L8vP+Yfh5cvfPvp/xUHyQHXGyAYwgpwBjZYFT3Y1OEl/OfCH4ffv3wzc4iwMvNIsDJ+f/mH4+vIPAxsb631WW0Yln6ZpQLXdMK/DXGDflh+sIv37EivD5x//Gb7+YWT4y86sl7BCCkSD+Z++/1dkvsFRl+HnD1Rvje4F8whjMXmGj58YGf5zsDMwcnAwfPvKcml62DsQDeaDxN+/Y0qwlpEHqrdB94IRNIDUgfgfKJChGK4OikEW3gTiXUB950ASLFAF54AC94A0G9QAfOnmF9DCDzABFqS08IHYDIScdijOjQABBgC+/9awBH96jwAAAABJRU5ErkJggg==");
|
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAmVBMVEX///8AAAD///8AAAAAAABPSzb/5sAAAAB/blH/73z/ulkAAAAAAAD85pkAAAAAAAACAgP/vGz/rkDerGbGrV7/pkQICAf////e0IsAAAD/oED/qTvhrnUAAAD/yHD/njcAAADuv2r/nz//oTj/p064oGf/zHAAAAA9Nir/tFIAAAD/tlTiuWf/tkIAAACynXEAAAAAAAAtIRW7zBpBAAAAM3RSTlMAABR1m7RXO8Ln31Z36zT+neXe5OzooRDfn+TZ4p3h2hTf4t3k3ucyrN1K5+Xaks52Sfs9CXgrAAAAjklEQVR42o3PbQ+CIBQFYEwboPhSYgoYunIqqLn6/z8uYdH8Vmdnu9vz4WwXgN/xTPRD2+sgOcZjsge/whXZgUaYYvT8QnuJaUrjrHUQreGczuEafQCO/SJTufTbroWsPgsllVhq3wJEk2jUSzX3CUEDJC84707djRc5MTAQxoLgupWRwW6UB5fS++NV8AbOZgnsC7BpEAAAAABJRU5ErkJggg==");
|
||||||
background-position: 2px center;
|
background-position: 2px center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ace_gutter-cell.ace_info {
|
.ace_gutter-cell.ace_info {
|
||||||
background-image: url("data:image/gif;base64,R0lGODlhEAAQAMQAAAAAAEFBQVJSUl5eXmRkZGtra39/f4WFhYmJiZGRkaampry8vMPDw8zMzNXV1dzc3OTk5Orq6vDw8P///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABQALAAAAAAQABAAAAUuICWOZGmeaBml5XGwFCQSBGyXRSAwtqQIiRuiwIM5BoYVbEFIyGCQoeJGrVptIQA7");
|
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAAAAAA6mKC9AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAJ0Uk5TAAB2k804AAAAPklEQVQY02NgIB68QuO3tiLznjAwpKTgNyDbMegwisCHZUETUZV0ZqOquBpXj2rtnpSJT1AEnnRmL2OgGgAAIKkRQap2htgAAAAASUVORK5CYII=");
|
||||||
background-position: 2px center;
|
background-position: 2px center;
|
||||||
}
|
}
|
||||||
.ace_dark .ace_gutter-cell.ace_info {
|
.ace_dark .ace_gutter-cell.ace_info {
|
||||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpGRTk5MTVGREIxNDkxMUUxOTc5Q0FFREQyMTNGMjBFQyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpGRTk5MTVGRUIxNDkxMUUxOTc5Q0FFREQyMTNGMjBFQyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkZFOTkxNUZCQjE0OTExRTE5NzlDQUVERDIxM0YyMEVDIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkZFOTkxNUZDQjE0OTExRTE5NzlDQUVERDIxM0YyMEVDIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+SIDkjAAAAJ1JREFUeNpi/P//PwMlgImBQkB7A6qrq/+DMC55FkIGKCoq4pVnpFkgTp069f/+/fv/r1u37r+tre1/kg0A+ptn9uzZYLaRkRHpLvjw4cNXWVlZhufPnzOcO3eOdAO0tbVPAjHDmzdvGA4fPsxIsgGSkpJmv379Ynj37h2DjIyMCMkG3LhxQ/T27dsMampqDHZ2dq/pH41DxwCAAAMAFdc68dUsFZgAAAAASUVORK5CYII=");
|
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAJFBMVEUAAAChoaGAgIAqKiq+vr6tra1ZWVmUlJSbm5s8PDxubm56enrdgzg3AAAAAXRSTlMAQObYZgAAAClJREFUeNpjYMAPdsMYHegyJZFQBlsUlMFVCWUYKkAZMxZAGdxlDMQBAG+TBP4B6RyJAAAAAElFTkSuQmCC");
|
||||||
}
|
}
|
||||||
|
|
||||||
.ace_scrollbar {
|
.ace_scrollbar {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
overflow-x: hidden;
|
|
||||||
overflow-y: scroll;
|
|
||||||
right: 0;
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
z-index: 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ace_scrollbar-inner {
|
.ace_scrollbar-inner {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 1px;
|
cursor: text;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ace_scrollbar-v{
|
||||||
|
overflow-x: hidden;
|
||||||
|
overflow-y: scroll;
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ace_scrollbar-h {
|
||||||
|
overflow-x: scroll;
|
||||||
|
overflow-y: hidden;
|
||||||
left: 0;
|
left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,22 +138,29 @@
|
|||||||
resize: none;
|
resize: none;
|
||||||
outline: none;
|
outline: none;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
font: inherit;
|
||||||
|
padding: 0 1px;
|
||||||
|
margin: 0 -1px;
|
||||||
|
text-indent: -1em;
|
||||||
|
-ms-user-select: text;
|
||||||
|
-moz-user-select: text;
|
||||||
|
-webkit-user-select: text;
|
||||||
|
user-select: text;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ace_text-input.ace_composition {
|
.ace_text-input.ace_composition {
|
||||||
background: #fff;
|
background: inherit;
|
||||||
color: #000;
|
color: inherit;
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
border: solid lightgray 1px;
|
text-indent: 0;
|
||||||
margin: -1px
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.ace_layer {
|
.ace_layer {
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
white-space: nowrap;
|
white-space: pre;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
-moz-box-sizing: border-box;
|
-moz-box-sizing: border-box;
|
||||||
@@ -127,7 +179,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.ace_text-layer {
|
.ace_text-layer {
|
||||||
color: black;
|
|
||||||
font: inherit !important;
|
font: inherit !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,6 +197,16 @@
|
|||||||
-moz-box-sizing: border-box;
|
-moz-box-sizing: border-box;
|
||||||
-webkit-box-sizing: border-box;
|
-webkit-box-sizing: border-box;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
border-left: 2px solid
|
||||||
|
}
|
||||||
|
|
||||||
|
.ace_slim-cursors .ace_cursor {
|
||||||
|
border-left-width: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ace_overwrite-cursors .ace_cursor {
|
||||||
|
border-left-width: 0;
|
||||||
|
border-bottom: 1px solid;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ace_hidden-cursors .ace_cursor {
|
.ace_hidden-cursors .ace_cursor {
|
||||||
@@ -153,26 +214,15 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.ace_smooth-blinking .ace_cursor {
|
.ace_smooth-blinking .ace_cursor {
|
||||||
-moz-transition: opacity 0.18s;
|
|
||||||
-webkit-transition: opacity 0.18s;
|
-webkit-transition: opacity 0.18s;
|
||||||
-o-transition: opacity 0.18s;
|
|
||||||
-ms-transition: opacity 0.18s;
|
|
||||||
transition: opacity 0.18s;
|
transition: opacity 0.18s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ace_cursor[style*="opacity: 0"]{
|
|
||||||
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
|
|
||||||
}
|
|
||||||
|
|
||||||
.ace_editor.ace_multiselect .ace_cursor {
|
.ace_editor.ace_multiselect .ace_cursor {
|
||||||
border-left-width: 1px;
|
border-left-width: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ace_line {
|
.ace_marker-layer .ace_step, .ace_marker-layer .ace_stack {
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ace_marker-layer .ace_step {
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: 3;
|
z-index: 3;
|
||||||
}
|
}
|
||||||
@@ -211,15 +261,13 @@
|
|||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
|
|
||||||
background-image:
|
background-image:
|
||||||
url("data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%11%00%00%00%09%08%06%00%00%00%D4%E8%C7%0C%00%00%03%1EiCCPICC%20Profile%00%00x%01%85T%DFk%D3P%14%FE%DAe%9D%B0%E1%8B%3Ag%11%09%3Eh%91ndStC%9C%B6kW%BA%CDZ%EA6%B7!H%9B%A6m%5C%9A%C6%24%ED~%B0%07%D9%8Bo%3A%C5w%F1%07%3E%F9%07%0C%D9%83o%7B%92%0D%C6%14a%F8%AC%88%22L%F6%22%B3%9E%9B4M'S%03%B9%F7%BB%DF%F9%EE9'%E7%E4%5E%A0%F9qZ%D3%14%2F%0F%14USO%C5%C2%FC%C4%E4%14%DF%F2%01%5E%1CC%2B%FChM%8B%86%16J%26G%40%0F%D3%B2y%EF%B3%F3%0E%1E%C6lt%EEo%DF%AB%FEc%D5%9A%95%0C%11%F0%1C%20%BE%945%C4%22%E1Y%A0i%5C%D4t%13%E0%D6%89%EF%9D15%C2%CDLsX%A7%04%09%1Fg8oc%81%E1%8C%8D%23%96f45%40%9A%09%C2%07%C5B%3AK%B8%408%98i%E0%F3%0D%D8%CE%81%14%E4'%26%A9%92.%8B%3C%ABER%2F%E5dE%B2%0C%F6%F0%1Fs%83%F2_%B0%A8%94%E9%9B%AD%E7%10%8Dm%9A%19N%D1%7C%8A%DE%1F9%7Dp%8C%E6%00%D5%C1%3F_%18%BDA%B8%9DpX6%E3%A35~B%CD%24%AE%11%26%BD%E7%EEti%98%EDe%9A%97Y)%12%25%1C%24%BCbT%AE3li%E6%0B%03%89%9A%E6%D3%ED%F4P%92%B0%9F4%BF43Y%F3%E3%EDP%95%04%EB1%C5%F5%F6KF%F4%BA%BD%D7%DB%91%93%07%E35%3E%A7)%D6%7F%40%FE%BD%F7%F5r%8A%E5y%92%F0%EB%B4%1E%8D%D5%F4%5B%92%3AV%DB%DB%E4%CD%A6%23%C3%C4wQ%3F%03HB%82%8E%1Cd(%E0%91B%0Ca%9Ac%C4%AA%F8L%16%19%22J%A4%D2itTy%B28%D6%3B(%93%96%ED%1CGx%C9_%0E%B8%5E%16%F5%5B%B2%B8%F6%E0%FB%9E%DD%25%D7%8E%BC%15%85%C5%B7%A3%D8Q%ED%B5%81%E9%BA%B2%13%9A%1B%7Fua%A5%A3n%E17%B9%E5%9B%1Bm%AB%0B%08Q%FE%8A%E5%B1H%5Ee%CAO%82Q%D7u6%E6%90S%97%FCu%0B%CF2%94%EE%25v%12X%0C%BA%AC%F0%5E%F8*l%0AO%85%17%C2%97%BF%D4%C8%CE%DE%AD%11%CB%80q%2C%3E%AB%9ES%CD%C6%EC%25%D2L%D2%EBd%B8%BF%8A%F5B%C6%18%F9%901CZ%9D%BE%24M%9C%8A9%F2%DAP%0B'%06w%82%EB%E6%E2%5C%2F%D7%07%9E%BB%CC%5D%E1%FA%B9%08%AD.r%23%8E%C2%17%F5E%7C!%F0%BE3%BE%3E_%B7o%88a%A7%DB%BE%D3d%EB%A31Z%EB%BB%D3%91%BA%A2%B1z%94%8F%DB'%F6%3D%8E%AA%13%19%B2%B1%BE%B1~V%08%2B%B4%A2cjJ%B3tO%00%03%25mN%97%F3%05%93%EF%11%84%0B%7C%88%AE-%89%8F%ABbW%90O%2B%0Ao%99%0C%5E%97%0CI%AFH%D9.%B0%3B%8F%ED%03%B6S%D6%5D%E6i_s9%F3*p%E9%1B%FD%C3%EB.7U%06%5E%19%C0%D1s.%17%A03u%E4%09%B0%7C%5E%2C%EB%15%DB%1F%3C%9E%B7%80%91%3B%DBc%AD%3Dma%BA%8B%3EV%AB%DBt.%5B%1E%01%BB%0F%AB%D5%9F%CF%AA%D5%DD%E7%E4%7F%0Bx%A3%FC%06%A9%23%0A%D6%C2%A1_2%00%00%00%09pHYs%00%00%0B%13%00%00%0B%13%01%00%9A%9C%18%00%00%00%B5IDAT(%15%A5%91%3D%0E%02!%10%85ac%E1%05%D6%CE%D6%C6%CE%D2%E8%ED%CD%DE%C0%C6%D6N.%E0V%F8%3D%9Ca%891XH%C2%BE%D9y%3F%90!%E6%9C%C3%BFk%E5%011%C6-%F5%C8N%04%DF%BD%FF%89%DFt%83DN%60%3E%F3%AB%A0%DE%1A%5Dg%BE%10Q%97%1B%40%9C%A8o%10%8F%5E%828%B4%1B%60%87%F6%02%26%85%1Ch%1E%C1%2B%5Bk%FF%86%EE%B7j%09%9A%DA%9B%ACe%A3%F9%EC%DA!9%B4%D5%A6%81%86%86%98%CC%3C%5B%40%FA%81%B3%E9%CB%23%94%C16Azo%05%D4%E1%C1%95a%3B%8A'%A0%E8%CC%17%22%85%1D%BA%00%A2%FA%DC%0A%94%D1%D1%8D%8B%3A%84%17B%C7%60%1A%25Z%FC%8D%00%00%00%00IEND%AEB%60%82"),
|
url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAJCAYAAADU6McMAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAJpJREFUeNpi/P//PwOlgAXGYGRklAVSokD8GmjwY1wasKljQpYACtpCFeADcHVQfQyMQAwzwAZI3wJKvCLkfKBaMSClBlR7BOQikCFGQEErIH0VqkabiGCAqwUadAzZJRxQr/0gwiXIal8zQQPnNVTgJ1TdawL0T5gBIP1MUJNhBv2HKoQHHjqNrA4WO4zY0glyNKLT2KIfIMAAQsdgGiXvgnYAAAAASUVORK5CYII="),
|
||||||
url("data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%05%00%00%007%08%06%00%00%00%C4%DD%80C%00%00%03%1EiCCPICC%20Profile%00%00x%01%85T%DFk%D3P%14%FE%DAe%9D%B0%E1%8B%3Ag%11%09%3Eh%91ndStC%9C%B6kW%BA%CDZ%EA6%B7!H%9B%A6m%5C%9A%C6%24%ED~%B0%07%D9%8Bo%3A%C5w%F1%07%3E%F9%07%0C%D9%83o%7B%92%0D%C6%14a%F8%AC%88%22L%F6%22%B3%9E%9B4M'S%03%B9%F7%BB%DF%F9%EE9'%E7%E4%5E%A0%F9qZ%D3%14%2F%0F%14USO%C5%C2%FC%C4%E4%14%DF%F2%01%5E%1CC%2B%FChM%8B%86%16J%26G%40%0F%D3%B2y%EF%B3%F3%0E%1E%C6lt%EEo%DF%AB%FEc%D5%9A%95%0C%11%F0%1C%20%BE%945%C4%22%E1Y%A0i%5C%D4t%13%E0%D6%89%EF%9D15%C2%CDLsX%A7%04%09%1Fg8oc%81%E1%8C%8D%23%96f45%40%9A%09%C2%07%C5B%3AK%B8%408%98i%E0%F3%0D%D8%CE%81%14%E4'%26%A9%92.%8B%3C%ABER%2F%E5dE%B2%0C%F6%F0%1Fs%83%F2_%B0%A8%94%E9%9B%AD%E7%10%8Dm%9A%19N%D1%7C%8A%DE%1F9%7Dp%8C%E6%00%D5%C1%3F_%18%BDA%B8%9DpX6%E3%A35~B%CD%24%AE%11%26%BD%E7%EEti%98%EDe%9A%97Y)%12%25%1C%24%BCbT%AE3li%E6%0B%03%89%9A%E6%D3%ED%F4P%92%B0%9F4%BF43Y%F3%E3%EDP%95%04%EB1%C5%F5%F6KF%F4%BA%BD%D7%DB%91%93%07%E35%3E%A7)%D6%7F%40%FE%BD%F7%F5r%8A%E5y%92%F0%EB%B4%1E%8D%D5%F4%5B%92%3AV%DB%DB%E4%CD%A6%23%C3%C4wQ%3F%03HB%82%8E%1Cd(%E0%91B%0Ca%9Ac%C4%AA%F8L%16%19%22J%A4%D2itTy%B28%D6%3B(%93%96%ED%1CGx%C9_%0E%B8%5E%16%F5%5B%B2%B8%F6%E0%FB%9E%DD%25%D7%8E%BC%15%85%C5%B7%A3%D8Q%ED%B5%81%E9%BA%B2%13%9A%1B%7Fua%A5%A3n%E17%B9%E5%9B%1Bm%AB%0B%08Q%FE%8A%E5%B1H%5Ee%CAO%82Q%D7u6%E6%90S%97%FCu%0B%CF2%94%EE%25v%12X%0C%BA%AC%F0%5E%F8*l%0AO%85%17%C2%97%BF%D4%C8%CE%DE%AD%11%CB%80q%2C%3E%AB%9ES%CD%C6%EC%25%D2L%D2%EBd%B8%BF%8A%F5B%C6%18%F9%901CZ%9D%BE%24M%9C%8A9%F2%DAP%0B'%06w%82%EB%E6%E2%5C%2F%D7%07%9E%BB%CC%5D%E1%FA%B9%08%AD.r%23%8E%C2%17%F5E%7C!%F0%BE3%BE%3E_%B7o%88a%A7%DB%BE%D3d%EB%A31Z%EB%BB%D3%91%BA%A2%B1z%94%8F%DB'%F6%3D%8E%AA%13%19%B2%B1%BE%B1~V%08%2B%B4%A2cjJ%B3tO%00%03%25mN%97%F3%05%93%EF%11%84%0B%7C%88%AE-%89%8F%ABbW%90O%2B%0Ao%99%0C%5E%97%0CI%AFH%D9.%B0%3B%8F%ED%03%B6S%D6%5D%E6i_s9%F3*p%E9%1B%FD%C3%EB.7U%06%5E%19%C0%D1s.%17%A03u%E4%09%B0%7C%5E%2C%EB%15%DB%1F%3C%9E%B7%80%91%3B%DBc%AD%3Dma%BA%8B%3EV%AB%DBt.%5B%1E%01%BB%0F%AB%D5%9F%CF%AA%D5%DD%E7%E4%7F%0Bx%A3%FC%06%A9%23%0A%D6%C2%A1_2%00%00%00%09pHYs%00%00%0B%13%00%00%0B%13%01%00%9A%9C%18%00%00%00%3AIDAT8%11c%FC%FF%FF%7F%18%03%1A%60%01%F2%3F%A0%891%80%04%FF%11-%F8%17%9BJ%E2%05%B1ZD%81v%26t%E7%80%F8%A3%82h%A12%1A%20%A3%01%02%0F%01%BA%25%06%00%19%C0%0D%AEF%D5%3ES%00%00%00%00IEND%AEB%60%82");
|
url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAA3CAYAAADNNiA5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACJJREFUeNpi+P//fxgTAwPDBxDxD078RSX+YeEyDFMCIMAAI3INmXiwf2YAAAAASUVORK5CYII=");
|
||||||
background-repeat: no-repeat, repeat-x;
|
background-repeat: no-repeat, repeat-x;
|
||||||
background-position: center center, top left;
|
background-position: center center, top left;
|
||||||
color: transparent;
|
color: transparent;
|
||||||
|
|
||||||
border: 1px solid black;
|
border: 1px solid black;
|
||||||
-moz-border-radius: 2px;
|
|
||||||
-webkit-border-radius: 2px;
|
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@@ -231,31 +279,33 @@
|
|||||||
|
|
||||||
.ace_fold:hover{
|
.ace_fold:hover{
|
||||||
background-image:
|
background-image:
|
||||||
url("data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%11%00%00%00%09%08%06%00%00%00%D4%E8%C7%0C%00%00%03%1EiCCPICC%20Profile%00%00x%01%85T%DFk%D3P%14%FE%DAe%9D%B0%E1%8B%3Ag%11%09%3Eh%91ndStC%9C%B6kW%BA%CDZ%EA6%B7!H%9B%A6m%5C%9A%C6%24%ED~%B0%07%D9%8Bo%3A%C5w%F1%07%3E%F9%07%0C%D9%83o%7B%92%0D%C6%14a%F8%AC%88%22L%F6%22%B3%9E%9B4M'S%03%B9%F7%BB%DF%F9%EE9'%E7%E4%5E%A0%F9qZ%D3%14%2F%0F%14USO%C5%C2%FC%C4%E4%14%DF%F2%01%5E%1CC%2B%FChM%8B%86%16J%26G%40%0F%D3%B2y%EF%B3%F3%0E%1E%C6lt%EEo%DF%AB%FEc%D5%9A%95%0C%11%F0%1C%20%BE%945%C4%22%E1Y%A0i%5C%D4t%13%E0%D6%89%EF%9D15%C2%CDLsX%A7%04%09%1Fg8oc%81%E1%8C%8D%23%96f45%40%9A%09%C2%07%C5B%3AK%B8%408%98i%E0%F3%0D%D8%CE%81%14%E4'%26%A9%92.%8B%3C%ABER%2F%E5dE%B2%0C%F6%F0%1Fs%83%F2_%B0%A8%94%E9%9B%AD%E7%10%8Dm%9A%19N%D1%7C%8A%DE%1F9%7Dp%8C%E6%00%D5%C1%3F_%18%BDA%B8%9DpX6%E3%A35~B%CD%24%AE%11%26%BD%E7%EEti%98%EDe%9A%97Y)%12%25%1C%24%BCbT%AE3li%E6%0B%03%89%9A%E6%D3%ED%F4P%92%B0%9F4%BF43Y%F3%E3%EDP%95%04%EB1%C5%F5%F6KF%F4%BA%BD%D7%DB%91%93%07%E35%3E%A7)%D6%7F%40%FE%BD%F7%F5r%8A%E5y%92%F0%EB%B4%1E%8D%D5%F4%5B%92%3AV%DB%DB%E4%CD%A6%23%C3%C4wQ%3F%03HB%82%8E%1Cd(%E0%91B%0Ca%9Ac%C4%AA%F8L%16%19%22J%A4%D2itTy%B28%D6%3B(%93%96%ED%1CGx%C9_%0E%B8%5E%16%F5%5B%B2%B8%F6%E0%FB%9E%DD%25%D7%8E%BC%15%85%C5%B7%A3%D8Q%ED%B5%81%E9%BA%B2%13%9A%1B%7Fua%A5%A3n%E17%B9%E5%9B%1Bm%AB%0B%08Q%FE%8A%E5%B1H%5Ee%CAO%82Q%D7u6%E6%90S%97%FCu%0B%CF2%94%EE%25v%12X%0C%BA%AC%F0%5E%F8*l%0AO%85%17%C2%97%BF%D4%C8%CE%DE%AD%11%CB%80q%2C%3E%AB%9ES%CD%C6%EC%25%D2L%D2%EBd%B8%BF%8A%F5B%C6%18%F9%901CZ%9D%BE%24M%9C%8A9%F2%DAP%0B'%06w%82%EB%E6%E2%5C%2F%D7%07%9E%BB%CC%5D%E1%FA%B9%08%AD.r%23%8E%C2%17%F5E%7C!%F0%BE3%BE%3E_%B7o%88a%A7%DB%BE%D3d%EB%A31Z%EB%BB%D3%91%BA%A2%B1z%94%8F%DB'%F6%3D%8E%AA%13%19%B2%B1%BE%B1~V%08%2B%B4%A2cjJ%B3tO%00%03%25mN%97%F3%05%93%EF%11%84%0B%7C%88%AE-%89%8F%ABbW%90O%2B%0Ao%99%0C%5E%97%0CI%AFH%D9.%B0%3B%8F%ED%03%B6S%D6%5D%E6i_s9%F3*p%E9%1B%FD%C3%EB.7U%06%5E%19%C0%D1s.%17%A03u%E4%09%B0%7C%5E%2C%EB%15%DB%1F%3C%9E%B7%80%91%3B%DBc%AD%3Dma%BA%8B%3EV%AB%DBt.%5B%1E%01%BB%0F%AB%D5%9F%CF%AA%D5%DD%E7%E4%7F%0Bx%A3%FC%06%A9%23%0A%D6%C2%A1_2%00%00%00%09pHYs%00%00%0B%13%00%00%0B%13%01%00%9A%9C%18%00%00%00%B5IDAT(%15%A5%91%3D%0E%02!%10%85ac%E1%05%D6%CE%D6%C6%CE%D2%E8%ED%CD%DE%C0%C6%D6N.%E0V%F8%3D%9Ca%891XH%C2%BE%D9y%3F%90!%E6%9C%C3%BFk%E5%011%C6-%F5%C8N%04%DF%BD%FF%89%DFt%83DN%60%3E%F3%AB%A0%DE%1A%5Dg%BE%10Q%97%1B%40%9C%A8o%10%8F%5E%828%B4%1B%60%87%F6%02%26%85%1Ch%1E%C1%2B%5Bk%FF%86%EE%B7j%09%9A%DA%9B%ACe%A3%F9%EC%DA!9%B4%D5%A6%81%86%86%98%CC%3C%5B%40%FA%81%B3%E9%CB%23%94%C16Azo%05%D4%E1%C1%95a%3B%8A'%A0%E8%CC%17%22%85%1D%BA%00%A2%FA%DC%0A%94%D1%D1%8D%8B%3A%84%17B%C7%60%1A%25Z%FC%8D%00%00%00%00IEND%AEB%60%82"),
|
url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAJCAYAAADU6McMAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAJpJREFUeNpi/P//PwOlgAXGYGRklAVSokD8GmjwY1wasKljQpYACtpCFeADcHVQfQyMQAwzwAZI3wJKvCLkfKBaMSClBlR7BOQikCFGQEErIH0VqkabiGCAqwUadAzZJRxQr/0gwiXIal8zQQPnNVTgJ1TdawL0T5gBIP1MUJNhBv2HKoQHHjqNrA4WO4zY0glyNKLT2KIfIMAAQsdgGiXvgnYAAAAASUVORK5CYII="),
|
||||||
url("data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%05%00%00%007%08%06%00%00%00%C4%DD%80C%00%00%03%1EiCCPICC%20Profile%00%00x%01%85T%DFk%D3P%14%FE%DAe%9D%B0%E1%8B%3Ag%11%09%3Eh%91ndStC%9C%B6kW%BA%CDZ%EA6%B7!H%9B%A6m%5C%9A%C6%24%ED~%B0%07%D9%8Bo%3A%C5w%F1%07%3E%F9%07%0C%D9%83o%7B%92%0D%C6%14a%F8%AC%88%22L%F6%22%B3%9E%9B4M'S%03%B9%F7%BB%DF%F9%EE9'%E7%E4%5E%A0%F9qZ%D3%14%2F%0F%14USO%C5%C2%FC%C4%E4%14%DF%F2%01%5E%1CC%2B%FChM%8B%86%16J%26G%40%0F%D3%B2y%EF%B3%F3%0E%1E%C6lt%EEo%DF%AB%FEc%D5%9A%95%0C%11%F0%1C%20%BE%945%C4%22%E1Y%A0i%5C%D4t%13%E0%D6%89%EF%9D15%C2%CDLsX%A7%04%09%1Fg8oc%81%E1%8C%8D%23%96f45%40%9A%09%C2%07%C5B%3AK%B8%408%98i%E0%F3%0D%D8%CE%81%14%E4'%26%A9%92.%8B%3C%ABER%2F%E5dE%B2%0C%F6%F0%1Fs%83%F2_%B0%A8%94%E9%9B%AD%E7%10%8Dm%9A%19N%D1%7C%8A%DE%1F9%7Dp%8C%E6%00%D5%C1%3F_%18%BDA%B8%9DpX6%E3%A35~B%CD%24%AE%11%26%BD%E7%EEti%98%EDe%9A%97Y)%12%25%1C%24%BCbT%AE3li%E6%0B%03%89%9A%E6%D3%ED%F4P%92%B0%9F4%BF43Y%F3%E3%EDP%95%04%EB1%C5%F5%F6KF%F4%BA%BD%D7%DB%91%93%07%E35%3E%A7)%D6%7F%40%FE%BD%F7%F5r%8A%E5y%92%F0%EB%B4%1E%8D%D5%F4%5B%92%3AV%DB%DB%E4%CD%A6%23%C3%C4wQ%3F%03HB%82%8E%1Cd(%E0%91B%0Ca%9Ac%C4%AA%F8L%16%19%22J%A4%D2itTy%B28%D6%3B(%93%96%ED%1CGx%C9_%0E%B8%5E%16%F5%5B%B2%B8%F6%E0%FB%9E%DD%25%D7%8E%BC%15%85%C5%B7%A3%D8Q%ED%B5%81%E9%BA%B2%13%9A%1B%7Fua%A5%A3n%E17%B9%E5%9B%1Bm%AB%0B%08Q%FE%8A%E5%B1H%5Ee%CAO%82Q%D7u6%E6%90S%97%FCu%0B%CF2%94%EE%25v%12X%0C%BA%AC%F0%5E%F8*l%0AO%85%17%C2%97%BF%D4%C8%CE%DE%AD%11%CB%80q%2C%3E%AB%9ES%CD%C6%EC%25%D2L%D2%EBd%B8%BF%8A%F5B%C6%18%F9%901CZ%9D%BE%24M%9C%8A9%F2%DAP%0B'%06w%82%EB%E6%E2%5C%2F%D7%07%9E%BB%CC%5D%E1%FA%B9%08%AD.r%23%8E%C2%17%F5E%7C!%F0%BE3%BE%3E_%B7o%88a%A7%DB%BE%D3d%EB%A31Z%EB%BB%D3%91%BA%A2%B1z%94%8F%DB'%F6%3D%8E%AA%13%19%B2%B1%BE%B1~V%08%2B%B4%A2cjJ%B3tO%00%03%25mN%97%F3%05%93%EF%11%84%0B%7C%88%AE-%89%8F%ABbW%90O%2B%0Ao%99%0C%5E%97%0CI%AFH%D9.%B0%3B%8F%ED%03%B6S%D6%5D%E6i_s9%F3*p%E9%1B%FD%C3%EB.7U%06%5E%19%C0%D1s.%17%A03u%E4%09%B0%7C%5E%2C%EB%15%DB%1F%3C%9E%B7%80%91%3B%DBc%AD%3Dma%BA%8B%3EV%AB%DBt.%5B%1E%01%BB%0F%AB%D5%9F%CF%AA%D5%DD%E7%E4%7F%0Bx%A3%FC%06%A9%23%0A%D6%C2%A1_2%00%00%00%09pHYs%00%00%0B%13%00%00%0B%13%01%00%9A%9C%18%00%00%003IDAT8%11c%FC%FF%FF%7F%3E%03%1A%60%01%F2%3F%A3%891%80%04%FFQ%26%F8w%C0%B43%A1%DB%0C%E2%8F%0A%A2%85%CAh%80%8C%06%08%3C%04%E8%96%18%00%A3S%0D%CD%CF%D8%C1%9D%00%00%00%00IEND%AEB%60%82");
|
url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAA3CAYAAADNNiA5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACBJREFUeNpi+P//fz4TAwPDZxDxD5X4i5fLMEwJgAADAEPVDbjNw87ZAAAAAElFTkSuQmCC");
|
||||||
background-repeat: no-repeat, repeat-x;
|
|
||||||
background-position: center center, top left;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.ace_editor.ace_dragging .ace_content {
|
.ace_tooltip {
|
||||||
cursor: move;
|
background-color: #FFF;
|
||||||
}
|
background-image: -webkit-linear-gradient(top, transparent, rgba(0, 0, 0, 0.1));
|
||||||
|
background-image: linear-gradient(to bottom, transparent, rgba(0, 0, 0, 0.1));
|
||||||
.ace_gutter-tooltip {
|
|
||||||
background-color: #FFFFD5;
|
|
||||||
border: 1px solid gray;
|
border: 1px solid gray;
|
||||||
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.4);
|
border-radius: 1px;
|
||||||
|
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
|
||||||
color: black;
|
color: black;
|
||||||
display: inline-block;
|
max-width: 100%;
|
||||||
padding: 4px;
|
padding: 3px 4px;
|
||||||
position: absolute;
|
position: fixed;
|
||||||
z-index: 300;
|
z-index: 999999;
|
||||||
-moz-box-sizing: border-box;
|
-moz-box-sizing: border-box;
|
||||||
-webkit-box-sizing: border-box;
|
-webkit-box-sizing: border-box;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
white-space: pre-line;
|
white-space: pre;
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
|
line-height: normal;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: normal;
|
||||||
|
letter-spacing: normal;
|
||||||
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ace_folding-enabled > .ace_gutter-cell {
|
.ace_folding-enabled > .ace_gutter-cell {
|
||||||
@@ -268,40 +318,41 @@
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
|
||||||
margin: 0 -12px 0 1px;
|
margin: 0 -12px 0 1px;
|
||||||
display: inline-block;
|
display: none;
|
||||||
width: 11px;
|
width: 11px;
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
|
|
||||||
background-image: url("data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%05%00%00%00%05%08%06%00%00%00%8Do%26%E5%00%00%004IDATx%DAe%8A%B1%0D%000%0C%C2%F2%2CK%96%BC%D0%8F9%81%88H%E9%D0%0E%96%C0%10%92%3E%02%80%5E%82%E4%A9*-%EEsw%C8%CC%11%EE%96w%D8%DC%E9*Eh%0C%151(%00%00%00%00IEND%AEB%60%82");
|
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAANElEQVR42mWKsQ0AMAzC8ixLlrzQjzmBiEjp0A6WwBCSPgKAXoLkqSot7nN3yMwR7pZ32NzpKkVoDBUxKAAAAABJRU5ErkJggg==");
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-position: center;
|
background-position: center;
|
||||||
|
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
|
|
||||||
border: 1px solid transparent;
|
border: 1px solid transparent;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ace_folding-enabled .ace_fold-widget {
|
||||||
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ace_fold-widget.ace_end {
|
.ace_fold-widget.ace_end {
|
||||||
background-image: url("data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%05%00%00%00%05%08%06%00%00%00%8Do%26%E5%00%00%004IDATx%DAm%C7%C1%09%000%08C%D1%8C%ECE%C8E(%8E%EC%02)%1EZJ%F1%C1'%04%07I%E1%E5%EE%CAL%F5%A2%99%99%22%E2%D6%1FU%B5%FE0%D9x%A7%26Wz5%0E%D5%00%00%00%00IEND%AEB%60%82");
|
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAANElEQVR42m3HwQkAMAhD0YzsRchFKI7sAikeWkrxwScEB0nh5e7KTPWimZki4tYfVbX+MNl4pyZXejUO1QAAAABJRU5ErkJggg==");
|
||||||
}
|
}
|
||||||
|
|
||||||
.ace_fold-widget.ace_closed {
|
.ace_fold-widget.ace_closed {
|
||||||
background-image: url("data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%03%00%00%00%06%08%06%00%00%00%06%E5%24%0C%00%00%009IDATx%DA5%CA%C1%09%000%08%03%C0%AC*(%3E%04%C1%0D%BA%B1%23%A4Uh%E0%20%81%C0%CC%F8%82%81%AA%A2%AArGfr%88%08%11%11%1C%DD%7D%E0%EE%5B%F6%F6%CB%B8%05Q%2F%E9tai%D9%00%00%00%00IEND%AEB%60%82");
|
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAGCAYAAAAG5SQMAAAAOUlEQVR42jXKwQkAMAgDwKwqKD4EwQ26sSOkVWjgIIHAzPiCgaqiqnJHZnKICBERHN194O5b9vbLuAVRL+l0YWnZAAAAAElFTkSuQmCCXA==");
|
||||||
}
|
}
|
||||||
|
|
||||||
.ace_fold-widget:hover {
|
.ace_fold-widget:hover {
|
||||||
border: 1px solid rgba(0, 0, 0, 0.3);
|
border: 1px solid rgba(0, 0, 0, 0.3);
|
||||||
background-color: rgba(255, 255, 255, 0.2);
|
background-color: rgba(255, 255, 255, 0.2);
|
||||||
-moz-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7);
|
|
||||||
-webkit-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7);
|
|
||||||
box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7);
|
box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7);
|
||||||
}
|
}
|
||||||
|
|
||||||
.ace_fold-widget:active {
|
.ace_fold-widget:active {
|
||||||
border: 1px solid rgba(0, 0, 0, 0.4);
|
border: 1px solid rgba(0, 0, 0, 0.4);
|
||||||
background-color: rgba(0, 0, 0, 0.05);
|
background-color: rgba(0, 0, 0, 0.05);
|
||||||
-moz-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8);
|
|
||||||
-webkit-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8);
|
|
||||||
box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8);
|
box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@@ -321,32 +372,22 @@
|
|||||||
background-color: rgba(255, 255, 255, 0.1);
|
background-color: rgba(255, 255, 255, 0.1);
|
||||||
}
|
}
|
||||||
.ace_dark .ace_fold-widget:active {
|
.ace_dark .ace_fold-widget:active {
|
||||||
-moz-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);
|
|
||||||
-webkit-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);
|
|
||||||
box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);
|
box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.ace_fold-widget.ace_invalid {
|
.ace_fold-widget.ace_invalid {
|
||||||
background-color: #FFB4B4;
|
background-color: #FFB4B4;
|
||||||
border-color: #DE5555;
|
border-color: #DE5555;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ace_fade-fold-widgets .ace_fold-widget {
|
.ace_fade-fold-widgets .ace_fold-widget {
|
||||||
-moz-transition: opacity 0.4s ease 0.05s;
|
|
||||||
-webkit-transition: opacity 0.4s ease 0.05s;
|
-webkit-transition: opacity 0.4s ease 0.05s;
|
||||||
-o-transition: opacity 0.4s ease 0.05s;
|
|
||||||
-ms-transition: opacity 0.4s ease 0.05s;
|
|
||||||
transition: opacity 0.4s ease 0.05s;
|
transition: opacity 0.4s ease 0.05s;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ace_fade-fold-widgets:hover .ace_fold-widget {
|
.ace_fade-fold-widgets:hover .ace_fold-widget {
|
||||||
-moz-transition: opacity 0.05s ease 0.05s;
|
|
||||||
-webkit-transition: opacity 0.05s ease 0.05s;
|
-webkit-transition: opacity 0.05s ease 0.05s;
|
||||||
-o-transition: opacity 0.05s ease 0.05s;
|
|
||||||
-ms-transition: opacity 0.05s ease 0.05s;
|
|
||||||
transition: opacity 0.05s ease 0.05s;
|
transition: opacity 0.05s ease 0.05s;
|
||||||
opacity:1;
|
opacity:1;
|
||||||
}
|
}
|
||||||
@@ -366,3 +407,16 @@
|
|||||||
.ace_italic {
|
.ace_italic {
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.ace_error-marker {
|
||||||
|
background-color: rgba(255, 0, 0,0.2);
|
||||||
|
position: absolute;
|
||||||
|
z-index: 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ace_highlight-marker {
|
||||||
|
background-color: rgba(255, 255, 0,0.2);
|
||||||
|
position: absolute;
|
||||||
|
z-index: 8;
|
||||||
|
}
|
||||||
|
|||||||
@@ -56,10 +56,10 @@ var Document = function(text) {
|
|||||||
|
|
||||||
// There has to be one line at least in the document. If you pass an empty
|
// There has to be one line at least in the document. If you pass an empty
|
||||||
// string to the insert function, nothing will happen. Workaround.
|
// string to the insert function, nothing will happen. Workaround.
|
||||||
if (text.length == 0) {
|
if (text.length === 0) {
|
||||||
this.$lines = [""];
|
this.$lines = [""];
|
||||||
} else if (Array.isArray(text)) {
|
} else if (Array.isArray(text)) {
|
||||||
this.insertLines(0, text);
|
this._insertLines(0, text);
|
||||||
} else {
|
} else {
|
||||||
this.insert({row: 0, column:0}, text);
|
this.insert({row: 0, column:0}, text);
|
||||||
}
|
}
|
||||||
@@ -81,7 +81,7 @@ var Document = function(text) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all the lines in the document as a single string, split by the new line character.
|
* Returns all the lines in the document as a single string, joined by the new line character.
|
||||||
**/
|
**/
|
||||||
this.getValue = function() {
|
this.getValue = function() {
|
||||||
return this.getAllLines().join(this.getNewLineCharacter());
|
return this.getAllLines().join(this.getNewLineCharacter());
|
||||||
@@ -92,7 +92,6 @@ var Document = function(text) {
|
|||||||
* @param {Number} row The row number to use
|
* @param {Number} row The row number to use
|
||||||
* @param {Number} column The column number to use
|
* @param {Number} column The column number to use
|
||||||
*
|
*
|
||||||
*
|
|
||||||
**/
|
**/
|
||||||
this.createAnchor = function(row, column) {
|
this.createAnchor = function(row, column) {
|
||||||
return new Anchor(this, row, column);
|
return new Anchor(this, row, column);
|
||||||
@@ -105,28 +104,23 @@ var Document = function(text) {
|
|||||||
* @param {String} text The text to work with
|
* @param {String} text The text to work with
|
||||||
* @returns {String} A String array, with each index containing a piece of the original `text` string.
|
* @returns {String} A String array, with each index containing a piece of the original `text` string.
|
||||||
*
|
*
|
||||||
*
|
|
||||||
**/
|
**/
|
||||||
|
|
||||||
// check for IE split bug
|
// check for IE split bug
|
||||||
if ("aaa".split(/a/).length == 0)
|
if ("aaa".split(/a/).length === 0)
|
||||||
this.$split = function(text) {
|
this.$split = function(text) {
|
||||||
return text.replace(/\r\n|\r/g, "\n").split("\n");
|
return text.replace(/\r\n|\r/g, "\n").split("\n");
|
||||||
}
|
};
|
||||||
else
|
else
|
||||||
this.$split = function(text) {
|
this.$split = function(text) {
|
||||||
return text.split(/\r\n|\r|\n/);
|
return text.split(/\r\n|\r|\n/);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
this.$detectNewLine = function(text) {
|
this.$detectNewLine = function(text) {
|
||||||
var match = text.match(/^.*?(\r\n|\r|\n)/m);
|
var match = text.match(/^.*?(\r\n|\r|\n)/m);
|
||||||
if (match) {
|
this.$autoNewLine = match ? match[1] : "\n";
|
||||||
this.$autoNewLine = match[1];
|
this._signal("changeNewLineMode");
|
||||||
} else {
|
|
||||||
this.$autoNewLine = "\n";
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -134,30 +128,24 @@ var Document = function(text) {
|
|||||||
* @returns {String} If `newLineMode == windows`, `\r\n` is returned.
|
* @returns {String} If `newLineMode == windows`, `\r\n` is returned.
|
||||||
* If `newLineMode == unix`, `\n` is returned.
|
* If `newLineMode == unix`, `\n` is returned.
|
||||||
* If `newLineMode == auto`, the value of `autoNewLine` is returned.
|
* If `newLineMode == auto`, the value of `autoNewLine` is returned.
|
||||||
*
|
|
||||||
*
|
*
|
||||||
*
|
|
||||||
*
|
|
||||||
**/
|
**/
|
||||||
this.getNewLineCharacter = function() {
|
this.getNewLineCharacter = function() {
|
||||||
switch (this.$newLineMode) {
|
switch (this.$newLineMode) {
|
||||||
case "windows":
|
case "windows":
|
||||||
return "\r\n";
|
return "\r\n";
|
||||||
|
|
||||||
case "unix":
|
case "unix":
|
||||||
return "\n";
|
return "\n";
|
||||||
|
default:
|
||||||
case "auto":
|
return this.$autoNewLine || "\n";
|
||||||
return this.$autoNewLine;
|
}
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.$autoNewLine = "\n";
|
this.$autoNewLine = "";
|
||||||
this.$newLineMode = "auto";
|
this.$newLineMode = "auto";
|
||||||
/**
|
/**
|
||||||
* [Sets the new line mode.]{: #Document.setNewLineMode.desc}
|
* [Sets the new line mode.]{: #Document.setNewLineMode.desc}
|
||||||
* @param {String} newLineMode [The newline mode to use; can be either `windows`, `unix`, or `auto`]{: #Document.setNewLineMode.param}
|
* @param {String} newLineMode [The newline mode to use; can be either `windows`, `unix`, or `auto`]{: #Document.setNewLineMode.param}
|
||||||
*
|
|
||||||
*
|
*
|
||||||
**/
|
**/
|
||||||
this.setNewLineMode = function(newLineMode) {
|
this.setNewLineMode = function(newLineMode) {
|
||||||
@@ -165,11 +153,12 @@ var Document = function(text) {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
this.$newLineMode = newLineMode;
|
this.$newLineMode = newLineMode;
|
||||||
|
this._signal("changeNewLineMode");
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* [Returns the type of newlines being used; either `windows`, `unix`, or `auto`]{: #Document.getNewLineMode}
|
* [Returns the type of newlines being used; either `windows`, `unix`, or `auto`]{: #Document.getNewLineMode}
|
||||||
* @returns String
|
* @returns {String}
|
||||||
**/
|
**/
|
||||||
this.getNewLineMode = function() {
|
this.getNewLineMode = function() {
|
||||||
return this.$newLineMode;
|
return this.$newLineMode;
|
||||||
@@ -179,8 +168,6 @@ var Document = function(text) {
|
|||||||
* Returns `true` if `text` is a newline character (either `\r\n`, `\r`, or `\n`).
|
* Returns `true` if `text` is a newline character (either `\r\n`, `\r`, or `\n`).
|
||||||
* @param {String} text The text to check
|
* @param {String} text The text to check
|
||||||
*
|
*
|
||||||
*
|
|
||||||
*
|
|
||||||
**/
|
**/
|
||||||
this.isNewLine = function(text) {
|
this.isNewLine = function(text) {
|
||||||
return (text == "\r\n" || text == "\r" || text == "\n");
|
return (text == "\r\n" || text == "\r" || text == "\n");
|
||||||
@@ -190,8 +177,6 @@ var Document = function(text) {
|
|||||||
* Returns a verbatim copy of the given line as it is in the document
|
* Returns a verbatim copy of the given line as it is in the document
|
||||||
* @param {Number} row The row index to retrieve
|
* @param {Number} row The row index to retrieve
|
||||||
*
|
*
|
||||||
*
|
|
||||||
*
|
|
||||||
**/
|
**/
|
||||||
this.getLine = function(row) {
|
this.getLine = function(row) {
|
||||||
return this.$lines[row] || "";
|
return this.$lines[row] || "";
|
||||||
@@ -202,15 +187,13 @@ var Document = function(text) {
|
|||||||
* @param {Number} firstRow The first row index to retrieve
|
* @param {Number} firstRow The first row index to retrieve
|
||||||
* @param {Number} lastRow The final row index to retrieve
|
* @param {Number} lastRow The final row index to retrieve
|
||||||
*
|
*
|
||||||
*
|
|
||||||
*
|
|
||||||
**/
|
**/
|
||||||
this.getLines = function(firstRow, lastRow) {
|
this.getLines = function(firstRow, lastRow) {
|
||||||
return this.$lines.slice(firstRow, lastRow + 1);
|
return this.$lines.slice(firstRow, lastRow + 1);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all lines in the document as string array. Warning: The caller should not modify this array!
|
* Returns all lines in the document as string array.
|
||||||
**/
|
**/
|
||||||
this.getAllLines = function() {
|
this.getAllLines = function() {
|
||||||
return this.getLines(0, this.getLength());
|
return this.getLines(0, this.getLength());
|
||||||
@@ -227,19 +210,19 @@ var Document = function(text) {
|
|||||||
* [Given a range within the document, this function returns all the text within that range as a single string.]{: #Document.getTextRange.desc}
|
* [Given a range within the document, this function returns all the text within that range as a single string.]{: #Document.getTextRange.desc}
|
||||||
* @param {Range} range The range to work with
|
* @param {Range} range The range to work with
|
||||||
*
|
*
|
||||||
*
|
* @returns {String}
|
||||||
**/
|
**/
|
||||||
this.getTextRange = function(range) {
|
this.getTextRange = function(range) {
|
||||||
if (range.start.row == range.end.row) {
|
if (range.start.row == range.end.row) {
|
||||||
return this.$lines[range.start.row].substring(range.start.column,
|
return this.getLine(range.start.row)
|
||||||
range.end.column);
|
.substring(range.start.column, range.end.column);
|
||||||
}
|
|
||||||
else {
|
|
||||||
var lines = this.getLines(range.start.row+1, range.end.row-1);
|
|
||||||
lines.unshift((this.$lines[range.start.row] || "").substring(range.start.column));
|
|
||||||
lines.push((this.$lines[range.end.row] || "").substring(0, range.end.column));
|
|
||||||
return lines.join(this.getNewLineCharacter());
|
|
||||||
}
|
}
|
||||||
|
var lines = this.getLines(range.start.row, range.end.row);
|
||||||
|
lines[0] = (lines[0] || "").substring(range.start.column);
|
||||||
|
var l = lines.length - 1;
|
||||||
|
if (range.end.row - range.start.row == l)
|
||||||
|
lines[l] = lines[l].substring(0, range.end.column);
|
||||||
|
return lines.join(this.getNewLineCharacter());
|
||||||
};
|
};
|
||||||
|
|
||||||
this.$clipPosition = function(position) {
|
this.$clipPosition = function(position) {
|
||||||
@@ -247,13 +230,14 @@ var Document = function(text) {
|
|||||||
if (position.row >= length) {
|
if (position.row >= length) {
|
||||||
position.row = Math.max(0, length - 1);
|
position.row = Math.max(0, length - 1);
|
||||||
position.column = this.getLine(length-1).length;
|
position.column = this.getLine(length-1).length;
|
||||||
}
|
} else if (position.row < 0)
|
||||||
|
position.row = 0;
|
||||||
return position;
|
return position;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inserts a block of `text` and the indicated `position`.
|
* Inserts a block of `text` at the indicated `position`.
|
||||||
* @param {Object} position The position to start inserting at
|
* @param {Object} position The position to start inserting at; it's an object that looks like `{ row: row, column: column}`
|
||||||
* @param {String} text A chunk of text to insert
|
* @param {String} text A chunk of text to insert
|
||||||
* @returns {Object} The position ({row, column}) of the last line of `text`. If the length of `text` is 0, this function simply returns `position`.
|
* @returns {Object} The position ({row, column}) of the last line of `text`. If the length of `text` is 0, this function simply returns `position`.
|
||||||
*
|
*
|
||||||
@@ -275,7 +259,7 @@ var Document = function(text) {
|
|||||||
position = this.insertInLine(position, firstLine);
|
position = this.insertInLine(position, firstLine);
|
||||||
if (lastLine !== null) {
|
if (lastLine !== null) {
|
||||||
position = this.insertNewLine(position); // terminate first line
|
position = this.insertNewLine(position); // terminate first line
|
||||||
position = this.insertLines(position.row, lines);
|
position = this._insertLines(position.row, lines);
|
||||||
position = this.insertInLine(position, lastLine || "");
|
position = this.insertInLine(position, lastLine || "");
|
||||||
}
|
}
|
||||||
return position;
|
return position;
|
||||||
@@ -317,19 +301,22 @@ var Document = function(text) {
|
|||||||
* {row: row, column: 0}
|
* {row: row, column: 0}
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
**/
|
**/
|
||||||
this.insertLines = function(row, lines) {
|
this.insertLines = function(row, lines) {
|
||||||
|
if (row >= this.getLength())
|
||||||
|
return this.insert({row: row, column: 0}, "\n" + lines.join("\n"));
|
||||||
|
return this._insertLines(Math.max(row, 0), lines);
|
||||||
|
};
|
||||||
|
this._insertLines = function(row, lines) {
|
||||||
if (lines.length == 0)
|
if (lines.length == 0)
|
||||||
return {row: row, column: 0};
|
return {row: row, column: 0};
|
||||||
|
|
||||||
// apply doesn't work for big arrays (smallest threshold is on safari 0xFFFF)
|
// apply doesn't work for big arrays (smallest threshold is on safari 0xFFFF)
|
||||||
// to circumvent that we have to break huge inserts into smaller chunks here
|
// to circumvent that we have to break huge inserts into smaller chunks here
|
||||||
if (lines.length > 0xFFFF) {
|
while (lines.length > 0xF000) {
|
||||||
var end = this.insertLines(row, lines.slice(0xFFFF));
|
var end = this._insertLines(row, lines.slice(0, 0xF000));
|
||||||
lines = lines.slice(0, 0xFFFF);
|
lines = lines.slice(0xF000);
|
||||||
|
row = end.row;
|
||||||
}
|
}
|
||||||
|
|
||||||
var args = [row, 0];
|
var args = [row, 0];
|
||||||
@@ -342,8 +329,8 @@ var Document = function(text) {
|
|||||||
range: range,
|
range: range,
|
||||||
lines: lines
|
lines: lines
|
||||||
};
|
};
|
||||||
this._emit("change", { data: delta });
|
this._signal("change", { data: delta });
|
||||||
return end || range.end;
|
return range.end;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -372,14 +359,14 @@ var Document = function(text) {
|
|||||||
range: Range.fromPoints(position, end),
|
range: Range.fromPoints(position, end),
|
||||||
text: this.getNewLineCharacter()
|
text: this.getNewLineCharacter()
|
||||||
};
|
};
|
||||||
this._emit("change", { data: delta });
|
this._signal("change", { data: delta });
|
||||||
|
|
||||||
return end;
|
return end;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inserts `text` into the `position` at the current row. This method also triggers the `'change'` event.
|
* Inserts `text` into the `position` at the current row. This method also triggers the `'change'` event.
|
||||||
* @param {Object} position The position to insert at
|
* @param {Object} position The position to insert at; it's an object that looks like `{ row: row, column: column}`
|
||||||
* @param {String} text A chunk of text
|
* @param {String} text A chunk of text
|
||||||
* @returns {Object} Returns an object containing the final row and column, like this:
|
* @returns {Object} Returns an object containing the final row and column, like this:
|
||||||
* ```
|
* ```
|
||||||
@@ -406,7 +393,7 @@ var Document = function(text) {
|
|||||||
range: Range.fromPoints(position, end),
|
range: Range.fromPoints(position, end),
|
||||||
text: text
|
text: text
|
||||||
};
|
};
|
||||||
this._emit("change", { data: delta });
|
this._signal("change", { data: delta });
|
||||||
|
|
||||||
return end;
|
return end;
|
||||||
};
|
};
|
||||||
@@ -416,9 +403,10 @@ var Document = function(text) {
|
|||||||
* @param {Range} range A specified Range to remove
|
* @param {Range} range A specified Range to remove
|
||||||
* @returns {Object} Returns the new `start` property of the range, which contains `startRow` and `startColumn`. If `range` is empty, this function returns the unmodified value of `range.start`.
|
* @returns {Object} Returns the new `start` property of the range, which contains `startRow` and `startColumn`. If `range` is empty, this function returns the unmodified value of `range.start`.
|
||||||
*
|
*
|
||||||
*
|
|
||||||
**/
|
**/
|
||||||
this.remove = function(range) {
|
this.remove = function(range) {
|
||||||
|
if (!(range instanceof Range))
|
||||||
|
range = Range.fromPoints(range.start, range.end);
|
||||||
// clip to document
|
// clip to document
|
||||||
range.start = this.$clipPosition(range.start);
|
range.start = this.$clipPosition(range.start);
|
||||||
range.end = this.$clipPosition(range.end);
|
range.end = this.$clipPosition(range.end);
|
||||||
@@ -437,7 +425,7 @@ var Document = function(text) {
|
|||||||
this.removeInLine(lastRow, 0, range.end.column);
|
this.removeInLine(lastRow, 0, range.end.column);
|
||||||
|
|
||||||
if (lastFullRow >= firstFullRow)
|
if (lastFullRow >= firstFullRow)
|
||||||
this.removeLines(firstFullRow, lastFullRow);
|
this._removeLines(firstFullRow, lastFullRow);
|
||||||
|
|
||||||
if (firstFullRow != firstRow) {
|
if (firstFullRow != firstRow) {
|
||||||
this.removeInLine(firstRow, range.start.column, this.getLine(firstRow).length);
|
this.removeInLine(firstRow, range.start.column, this.getLine(firstRow).length);
|
||||||
@@ -457,7 +445,6 @@ var Document = function(text) {
|
|||||||
* @param {Number} endColumn The column to stop removing at
|
* @param {Number} endColumn The column to stop removing at
|
||||||
* @returns {Object} Returns an object containing `startRow` and `startColumn`, indicating the new row and column values.<br/>If `startColumn` is equal to `endColumn`, this function returns nothing.
|
* @returns {Object} Returns an object containing `startRow` and `startColumn`, indicating the new row and column values.<br/>If `startColumn` is equal to `endColumn`, this function returns nothing.
|
||||||
*
|
*
|
||||||
*
|
|
||||||
**/
|
**/
|
||||||
this.removeInLine = function(row, startColumn, endColumn) {
|
this.removeInLine = function(row, startColumn, endColumn) {
|
||||||
if (startColumn == endColumn)
|
if (startColumn == endColumn)
|
||||||
@@ -474,7 +461,7 @@ var Document = function(text) {
|
|||||||
range: range,
|
range: range,
|
||||||
text: removed
|
text: removed
|
||||||
};
|
};
|
||||||
this._emit("change", { data: delta });
|
this._signal("change", { data: delta });
|
||||||
return range.start;
|
return range.start;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -483,10 +470,15 @@ var Document = function(text) {
|
|||||||
* @param {Number} firstRow The first row to be removed
|
* @param {Number} firstRow The first row to be removed
|
||||||
* @param {Number} lastRow The last row to be removed
|
* @param {Number} lastRow The last row to be removed
|
||||||
* @returns {[String]} Returns all the removed lines.
|
* @returns {[String]} Returns all the removed lines.
|
||||||
*
|
|
||||||
*
|
*
|
||||||
**/
|
**/
|
||||||
this.removeLines = function(firstRow, lastRow) {
|
this.removeLines = function(firstRow, lastRow) {
|
||||||
|
if (firstRow < 0 || lastRow >= this.getLength())
|
||||||
|
return this.remove(new Range(firstRow, 0, lastRow + 1, 0));
|
||||||
|
return this._removeLines(firstRow, lastRow);
|
||||||
|
};
|
||||||
|
|
||||||
|
this._removeLines = function(firstRow, lastRow) {
|
||||||
var range = new Range(firstRow, 0, lastRow + 1, 0);
|
var range = new Range(firstRow, 0, lastRow + 1, 0);
|
||||||
var removed = this.$lines.splice(firstRow, lastRow - firstRow + 1);
|
var removed = this.$lines.splice(firstRow, lastRow - firstRow + 1);
|
||||||
|
|
||||||
@@ -496,7 +488,7 @@ var Document = function(text) {
|
|||||||
nl: this.getNewLineCharacter(),
|
nl: this.getNewLineCharacter(),
|
||||||
lines: removed
|
lines: removed
|
||||||
};
|
};
|
||||||
this._emit("change", { data: delta });
|
this._signal("change", { data: delta });
|
||||||
return removed;
|
return removed;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -519,7 +511,7 @@ var Document = function(text) {
|
|||||||
range: range,
|
range: range,
|
||||||
text: this.getNewLineCharacter()
|
text: this.getNewLineCharacter()
|
||||||
};
|
};
|
||||||
this._emit("change", { data: delta });
|
this._signal("change", { data: delta });
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -531,9 +523,10 @@ var Document = function(text) {
|
|||||||
* If the text and range are empty, this function returns an object containing the current `range.start` value.
|
* If the text and range are empty, this function returns an object containing the current `range.start` value.
|
||||||
* If the text is the exact same as what currently exists, this function returns an object containing the current `range.end` value.
|
* If the text is the exact same as what currently exists, this function returns an object containing the current `range.end` value.
|
||||||
*
|
*
|
||||||
*
|
|
||||||
**/
|
**/
|
||||||
this.replace = function(range, text) {
|
this.replace = function(range, text) {
|
||||||
|
if (!(range instanceof Range))
|
||||||
|
range = Range.fromPoints(range.start, range.end);
|
||||||
if (text.length == 0 && range.isEmpty())
|
if (text.length == 0 && range.isEmpty())
|
||||||
return range.start;
|
return range.start;
|
||||||
|
|
||||||
@@ -554,7 +547,7 @@ var Document = function(text) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies all the changes previously accumulated. These can be either `'includeText'`, `'insertLines'`, `'removeText'`, and `'removeLines'`.
|
* Applies all the changes previously accumulated. These can be either `'insertText'`, `'insertLines'`, `'removeText'`, and `'removeLines'`.
|
||||||
**/
|
**/
|
||||||
this.applyDeltas = function(deltas) {
|
this.applyDeltas = function(deltas) {
|
||||||
for (var i=0; i<deltas.length; i++) {
|
for (var i=0; i<deltas.length; i++) {
|
||||||
@@ -566,14 +559,14 @@ var Document = function(text) {
|
|||||||
else if (delta.action == "insertText")
|
else if (delta.action == "insertText")
|
||||||
this.insert(range.start, delta.text);
|
this.insert(range.start, delta.text);
|
||||||
else if (delta.action == "removeLines")
|
else if (delta.action == "removeLines")
|
||||||
this.removeLines(range.start.row, range.end.row - 1);
|
this._removeLines(range.start.row, range.end.row - 1);
|
||||||
else if (delta.action == "removeText")
|
else if (delta.action == "removeText")
|
||||||
this.remove(range);
|
this.remove(range);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reverts any changes previously applied. These can be either `'includeText'`, `'insertLines'`, `'removeText'`, and `'removeLines'`.
|
* Reverts any changes previously applied. These can be either `'insertText'`, `'insertLines'`, `'removeText'`, and `'removeLines'`.
|
||||||
**/
|
**/
|
||||||
this.revertDeltas = function(deltas) {
|
this.revertDeltas = function(deltas) {
|
||||||
for (var i=deltas.length-1; i>=0; i--) {
|
for (var i=deltas.length-1; i>=0; i--) {
|
||||||
@@ -582,16 +575,70 @@ var Document = function(text) {
|
|||||||
var range = Range.fromPoints(delta.range.start, delta.range.end);
|
var range = Range.fromPoints(delta.range.start, delta.range.end);
|
||||||
|
|
||||||
if (delta.action == "insertLines")
|
if (delta.action == "insertLines")
|
||||||
this.removeLines(range.start.row, range.end.row - 1);
|
this._removeLines(range.start.row, range.end.row - 1);
|
||||||
else if (delta.action == "insertText")
|
else if (delta.action == "insertText")
|
||||||
this.remove(range);
|
this.remove(range);
|
||||||
else if (delta.action == "removeLines")
|
else if (delta.action == "removeLines")
|
||||||
this.insertLines(range.start.row, delta.lines);
|
this._insertLines(range.start.row, delta.lines);
|
||||||
else if (delta.action == "removeText")
|
else if (delta.action == "removeText")
|
||||||
this.insert(range.start, delta.text);
|
this.insert(range.start, delta.text);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts an index position in a document to a `{row, column}` object.
|
||||||
|
*
|
||||||
|
* Index refers to the "absolute position" of a character in the document. For example:
|
||||||
|
*
|
||||||
|
* ```javascript
|
||||||
|
* var x = 0; // 10 characters, plus one for newline
|
||||||
|
* var y = -1;
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Here, `y` is an index 15: 11 characters for the first row, and 5 characters until `y` in the second.
|
||||||
|
*
|
||||||
|
* @param {Number} index An index to convert
|
||||||
|
* @param {Number} startRow=0 The row from which to start the conversion
|
||||||
|
* @returns {Object} A `{row, column}` object of the `index` position
|
||||||
|
*/
|
||||||
|
this.indexToPosition = function(index, startRow) {
|
||||||
|
var lines = this.$lines || this.getAllLines();
|
||||||
|
var newlineLength = this.getNewLineCharacter().length;
|
||||||
|
for (var i = startRow || 0, l = lines.length; i < l; i++) {
|
||||||
|
index -= lines[i].length + newlineLength;
|
||||||
|
if (index < 0)
|
||||||
|
return {row: i, column: index + lines[i].length + newlineLength};
|
||||||
|
}
|
||||||
|
return {row: l-1, column: lines[l-1].length};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the `{row, column}` position in a document to the character's index.
|
||||||
|
*
|
||||||
|
* Index refers to the "absolute position" of a character in the document. For example:
|
||||||
|
*
|
||||||
|
* ```javascript
|
||||||
|
* var x = 0; // 10 characters, plus one for newline
|
||||||
|
* var y = -1;
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Here, `y` is an index 15: 11 characters for the first row, and 5 characters until `y` in the second.
|
||||||
|
*
|
||||||
|
* @param {Object} pos The `{row, column}` to convert
|
||||||
|
* @param {Number} startRow=0 The row from which to start the conversion
|
||||||
|
* @returns {Number} The index position in the document
|
||||||
|
*/
|
||||||
|
this.positionToIndex = function(pos, startRow) {
|
||||||
|
var lines = this.$lines || this.getAllLines();
|
||||||
|
var newlineLength = this.getNewLineCharacter().length;
|
||||||
|
var index = 0;
|
||||||
|
var row = Math.min(pos.row, lines.length);
|
||||||
|
for (var i = startRow || 0; i < row; ++i)
|
||||||
|
index += lines[i].length + newlineLength;
|
||||||
|
|
||||||
|
return index + pos.column;
|
||||||
|
};
|
||||||
|
|
||||||
}).call(Document.prototype);
|
}).call(Document.prototype);
|
||||||
|
|
||||||
exports.Document = Document;
|
exports.Document = Document;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -37,10 +37,10 @@ var Range = require("../range").Range;
|
|||||||
|
|
||||||
function BracketMatch() {
|
function BracketMatch() {
|
||||||
|
|
||||||
this.findMatchingBracket = function(position, char) {
|
this.findMatchingBracket = function(position, chr) {
|
||||||
if (position.column == 0) return null;
|
if (position.column == 0) return null;
|
||||||
|
|
||||||
var charBeforeCursor = char || this.getLine(position.row).charAt(position.column-1);
|
var charBeforeCursor = chr || this.getLine(position.row).charAt(position.column-1);
|
||||||
if (charBeforeCursor == "") return null;
|
if (charBeforeCursor == "") return null;
|
||||||
|
|
||||||
var match = charBeforeCursor.match(/([\(\[\{])|([\)\]\}])/);
|
var match = charBeforeCursor.match(/([\(\[\{])|([\)\]\}])/);
|
||||||
@@ -117,6 +117,7 @@ function BracketMatch() {
|
|||||||
typeRe = new RegExp(
|
typeRe = new RegExp(
|
||||||
"(\\.?" +
|
"(\\.?" +
|
||||||
token.type.replace(".", "\\.").replace("rparen", ".paren")
|
token.type.replace(".", "\\.").replace("rparen", ".paren")
|
||||||
|
.replace(/\b(?:end|start|begin)\b/, "")
|
||||||
+ ")+"
|
+ ")+"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -173,6 +174,7 @@ function BracketMatch() {
|
|||||||
typeRe = new RegExp(
|
typeRe = new RegExp(
|
||||||
"(\\.?" +
|
"(\\.?" +
|
||||||
token.type.replace(".", "\\.").replace("lparen", ".paren")
|
token.type.replace(".", "\\.").replace("lparen", ".paren")
|
||||||
|
.replace(/\b(?:end|start|begin)\b/, "")
|
||||||
+ ")+"
|
+ ")+"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,9 @@
|
|||||||
define(function(require, exports, module) {
|
define(function(require, exports, module) {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
var Range = require("../range").Range;
|
||||||
|
var RangeList = require("../range_list").RangeList;
|
||||||
|
var oop = require("../lib/oop")
|
||||||
/*
|
/*
|
||||||
* Simple fold-data struct.
|
* Simple fold-data struct.
|
||||||
**/
|
**/
|
||||||
@@ -42,9 +45,11 @@ var Fold = exports.Fold = function(range, placeholder) {
|
|||||||
this.end = range.end;
|
this.end = range.end;
|
||||||
|
|
||||||
this.sameRow = range.start.row == range.end.row;
|
this.sameRow = range.start.row == range.end.row;
|
||||||
this.subFolds = [];
|
this.subFolds = this.ranges = [];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
oop.inherits(Fold, RangeList);
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
this.toString = function() {
|
this.toString = function() {
|
||||||
@@ -64,17 +69,21 @@ var Fold = exports.Fold = function(range, placeholder) {
|
|||||||
this.subFolds.forEach(function(subFold) {
|
this.subFolds.forEach(function(subFold) {
|
||||||
fold.subFolds.push(subFold.clone());
|
fold.subFolds.push(subFold.clone());
|
||||||
});
|
});
|
||||||
|
fold.collapseChildren = this.collapseChildren;
|
||||||
return fold;
|
return fold;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.addSubFold = function(fold) {
|
this.addSubFold = function(fold) {
|
||||||
if (this.range.isEqual(fold))
|
if (this.range.isEqual(fold))
|
||||||
return this;
|
return;
|
||||||
|
|
||||||
if (!this.range.containsRange(fold))
|
if (!this.range.containsRange(fold))
|
||||||
throw "A fold can't intersect already existing fold" + fold.range + this.range;
|
throw new Error("A fold can't intersect already existing fold" + fold.range + this.range);
|
||||||
|
|
||||||
var row = fold.range.start.row, column = fold.range.start.column;
|
// transform fold to local coordinates
|
||||||
|
consumeRange(fold, this.start);
|
||||||
|
|
||||||
|
var row = fold.start.row, column = fold.start.column;
|
||||||
for (var i = 0, cmp = -1; i < this.subFolds.length; i++) {
|
for (var i = 0, cmp = -1; i < this.subFolds.length; i++) {
|
||||||
cmp = this.subFolds[i].range.compare(row, column);
|
cmp = this.subFolds[i].range.compare(row, column);
|
||||||
if (cmp != 1)
|
if (cmp != 1)
|
||||||
@@ -95,14 +104,37 @@ var Fold = exports.Fold = function(range, placeholder) {
|
|||||||
var afterEnd = this.subFolds[j];
|
var afterEnd = this.subFolds[j];
|
||||||
|
|
||||||
if (cmp == 0)
|
if (cmp == 0)
|
||||||
throw "A fold can't intersect already existing fold" + fold.range + this.range;
|
throw new Error("A fold can't intersect already existing fold" + fold.range + this.range);
|
||||||
|
|
||||||
var consumedFolds = this.subFolds.splice(i, j - i, fold);
|
var consumedFolds = this.subFolds.splice(i, j - i, fold);
|
||||||
fold.setFoldLine(this.foldLine);
|
fold.setFoldLine(this.foldLine);
|
||||||
|
|
||||||
return fold;
|
return fold;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.restoreRange = function(range) {
|
||||||
|
return restoreRange(range, this.start);
|
||||||
|
};
|
||||||
|
|
||||||
}).call(Fold.prototype);
|
}).call(Fold.prototype);
|
||||||
|
|
||||||
|
function consumePoint(point, anchor) {
|
||||||
|
point.row -= anchor.row;
|
||||||
|
if (point.row == 0)
|
||||||
|
point.column -= anchor.column;
|
||||||
|
}
|
||||||
|
function consumeRange(range, anchor) {
|
||||||
|
consumePoint(range.start, anchor);
|
||||||
|
consumePoint(range.end, anchor);
|
||||||
|
}
|
||||||
|
function restorePoint(point, anchor) {
|
||||||
|
if (point.row == 0)
|
||||||
|
point.column += anchor.column;
|
||||||
|
point.row += anchor.row;
|
||||||
|
}
|
||||||
|
function restoreRange(range, anchor) {
|
||||||
|
restorePoint(range.start, anchor);
|
||||||
|
restorePoint(range.end, anchor);
|
||||||
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ function FoldLine(foldData, folds) {
|
|||||||
folds = this.folds = [ folds ];
|
folds = this.folds = [ folds ];
|
||||||
}
|
}
|
||||||
|
|
||||||
var last = folds[folds.length - 1]
|
var last = folds[folds.length - 1];
|
||||||
this.range = new Range(folds[0].start.row, folds[0].start.column,
|
this.range = new Range(folds[0].start.row, folds[0].start.column,
|
||||||
last.end.row, last.end.column);
|
last.end.row, last.end.column);
|
||||||
this.start = this.range.start;
|
this.start = this.range.start;
|
||||||
@@ -66,12 +66,12 @@ function FoldLine(foldData, folds) {
|
|||||||
fold.start.row += shift;
|
fold.start.row += shift;
|
||||||
fold.end.row += shift;
|
fold.end.row += shift;
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
this.addFold = function(fold) {
|
this.addFold = function(fold) {
|
||||||
if (fold.sameRow) {
|
if (fold.sameRow) {
|
||||||
if (fold.start.row < this.startRow || fold.endRow > this.endRow) {
|
if (fold.start.row < this.startRow || fold.endRow > this.endRow) {
|
||||||
throw "Can't add a fold to this FoldLine as it has no connection";
|
throw new Error("Can't add a fold to this FoldLine as it has no connection");
|
||||||
}
|
}
|
||||||
this.folds.push(fold);
|
this.folds.push(fold);
|
||||||
this.folds.sort(function(a, b) {
|
this.folds.sort(function(a, b) {
|
||||||
@@ -93,20 +93,20 @@ function FoldLine(foldData, folds) {
|
|||||||
this.start.row = fold.start.row;
|
this.start.row = fold.start.row;
|
||||||
this.start.column = fold.start.column;
|
this.start.column = fold.start.column;
|
||||||
} else {
|
} else {
|
||||||
throw "Trying to add fold to FoldRow that doesn't have a matching row";
|
throw new Error("Trying to add fold to FoldRow that doesn't have a matching row");
|
||||||
}
|
}
|
||||||
fold.foldLine = this;
|
fold.foldLine = this;
|
||||||
}
|
};
|
||||||
|
|
||||||
this.containsRow = function(row) {
|
this.containsRow = function(row) {
|
||||||
return row >= this.start.row && row <= this.end.row;
|
return row >= this.start.row && row <= this.end.row;
|
||||||
}
|
};
|
||||||
|
|
||||||
this.walk = function(callback, endRow, endColumn) {
|
this.walk = function(callback, endRow, endColumn) {
|
||||||
var lastEnd = 0,
|
var lastEnd = 0,
|
||||||
folds = this.folds,
|
folds = this.folds,
|
||||||
fold,
|
fold,
|
||||||
comp, stop, isNewRow = true;
|
cmp, stop, isNewRow = true;
|
||||||
|
|
||||||
if (endRow == null) {
|
if (endRow == null) {
|
||||||
endRow = this.end.row;
|
endRow = this.end.row;
|
||||||
@@ -116,9 +116,9 @@ function FoldLine(foldData, folds) {
|
|||||||
for (var i = 0; i < folds.length; i++) {
|
for (var i = 0; i < folds.length; i++) {
|
||||||
fold = folds[i];
|
fold = folds[i];
|
||||||
|
|
||||||
comp = fold.range.compareStart(endRow, endColumn);
|
cmp = fold.range.compareStart(endRow, endColumn);
|
||||||
// This fold is after the endRow/Column.
|
// This fold is after the endRow/Column.
|
||||||
if (comp == -1) {
|
if (cmp == -1) {
|
||||||
callback(null, endRow, endColumn, lastEnd, isNewRow);
|
callback(null, endRow, endColumn, lastEnd, isNewRow);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -127,8 +127,8 @@ function FoldLine(foldData, folds) {
|
|||||||
stop = !stop && callback(fold.placeholder, fold.start.row, fold.start.column, lastEnd);
|
stop = !stop && callback(fold.placeholder, fold.start.row, fold.start.column, lastEnd);
|
||||||
|
|
||||||
// If the user requested to stop the walk or endRow/endColumn is
|
// If the user requested to stop the walk or endRow/endColumn is
|
||||||
// inside of this fold (comp == 0), then end here.
|
// inside of this fold (cmp == 0), then end here.
|
||||||
if (stop || comp == 0) {
|
if (stop || cmp === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,7 +138,7 @@ function FoldLine(foldData, folds) {
|
|||||||
lastEnd = fold.end.column;
|
lastEnd = fold.end.column;
|
||||||
}
|
}
|
||||||
callback(null, endRow, endColumn, lastEnd, isNewRow);
|
callback(null, endRow, endColumn, lastEnd, isNewRow);
|
||||||
}
|
};
|
||||||
|
|
||||||
this.getNextFoldTo = function(row, column) {
|
this.getNextFoldTo = function(row, column) {
|
||||||
var fold, cmp;
|
var fold, cmp;
|
||||||
@@ -150,15 +150,15 @@ function FoldLine(foldData, folds) {
|
|||||||
fold: fold,
|
fold: fold,
|
||||||
kind: "after"
|
kind: "after"
|
||||||
};
|
};
|
||||||
} else if (cmp == 0) {
|
} else if (cmp === 0) {
|
||||||
return {
|
return {
|
||||||
fold: fold,
|
fold: fold,
|
||||||
kind: "inside"
|
kind: "inside"
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
};
|
||||||
|
|
||||||
this.addRemoveChars = function(row, column, len) {
|
this.addRemoveChars = function(row, column, len) {
|
||||||
var ret = this.getNextFoldTo(row, column),
|
var ret = this.getNextFoldTo(row, column),
|
||||||
@@ -175,7 +175,7 @@ function FoldLine(foldData, folds) {
|
|||||||
} else if (fold.start.row == row) {
|
} else if (fold.start.row == row) {
|
||||||
folds = this.folds;
|
folds = this.folds;
|
||||||
var i = folds.indexOf(fold);
|
var i = folds.indexOf(fold);
|
||||||
if (i == 0) {
|
if (i === 0) {
|
||||||
this.start.column += len;
|
this.start.column += len;
|
||||||
}
|
}
|
||||||
for (i; i < folds.length; i++) {
|
for (i; i < folds.length; i++) {
|
||||||
@@ -189,16 +189,18 @@ function FoldLine(foldData, folds) {
|
|||||||
this.end.column += len;
|
this.end.column += len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
this.split = function(row, column) {
|
this.split = function(row, column) {
|
||||||
var fold = this.getNextFoldTo(row, column).fold,
|
var pos = this.getNextFoldTo(row, column);
|
||||||
folds = this.folds;
|
|
||||||
var foldData = this.foldData;
|
if (!pos || pos.kind == "inside")
|
||||||
|
|
||||||
if (!fold) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
|
||||||
|
var fold = pos.fold;
|
||||||
|
var folds = this.folds;
|
||||||
|
var foldData = this.foldData;
|
||||||
|
|
||||||
var i = folds.indexOf(fold);
|
var i = folds.indexOf(fold);
|
||||||
var foldBefore = folds[i - 1];
|
var foldBefore = folds[i - 1];
|
||||||
this.end.row = foldBefore.end.row;
|
this.end.row = foldBefore.end.row;
|
||||||
@@ -211,7 +213,7 @@ function FoldLine(foldData, folds) {
|
|||||||
var newFoldLine = new FoldLine(foldData, folds);
|
var newFoldLine = new FoldLine(foldData, folds);
|
||||||
foldData.splice(foldData.indexOf(this) + 1, 0, newFoldLine);
|
foldData.splice(foldData.indexOf(this) + 1, 0, newFoldLine);
|
||||||
return newFoldLine;
|
return newFoldLine;
|
||||||
}
|
};
|
||||||
|
|
||||||
this.merge = function(foldLineNext) {
|
this.merge = function(foldLineNext) {
|
||||||
var folds = foldLineNext.folds;
|
var folds = foldLineNext.folds;
|
||||||
@@ -222,7 +224,7 @@ function FoldLine(foldData, folds) {
|
|||||||
// it's merged now with foldLineNext.
|
// it's merged now with foldLineNext.
|
||||||
var foldData = this.foldData;
|
var foldData = this.foldData;
|
||||||
foldData.splice(foldData.indexOf(foldLineNext), 1);
|
foldData.splice(foldData.indexOf(foldLineNext), 1);
|
||||||
}
|
};
|
||||||
|
|
||||||
this.toString = function() {
|
this.toString = function() {
|
||||||
var ret = [this.range.toString() + ": [" ];
|
var ret = [this.range.toString() + ": [" ];
|
||||||
@@ -230,13 +232,12 @@ function FoldLine(foldData, folds) {
|
|||||||
this.folds.forEach(function(fold) {
|
this.folds.forEach(function(fold) {
|
||||||
ret.push(" " + fold.toString());
|
ret.push(" " + fold.toString());
|
||||||
});
|
});
|
||||||
ret.push("]")
|
ret.push("]");
|
||||||
return ret.join("\n");
|
return ret.join("\n");
|
||||||
}
|
};
|
||||||
|
|
||||||
this.idxToPosition = function(idx) {
|
this.idxToPosition = function(idx) {
|
||||||
var lastFoldEndColumn = 0;
|
var lastFoldEndColumn = 0;
|
||||||
var fold;
|
|
||||||
|
|
||||||
for (var i = 0; i < this.folds.length; i++) {
|
for (var i = 0; i < this.folds.length; i++) {
|
||||||
var fold = this.folds[i];
|
var fold = this.folds[i];
|
||||||
@@ -261,7 +262,7 @@ function FoldLine(foldData, folds) {
|
|||||||
row: this.end.row,
|
row: this.end.row,
|
||||||
column: this.end.column + idx
|
column: this.end.column + idx
|
||||||
};
|
};
|
||||||
}
|
};
|
||||||
}).call(FoldLine.prototype);
|
}).call(FoldLine.prototype);
|
||||||
|
|
||||||
exports.FoldLine = FoldLine;
|
exports.FoldLine = FoldLine;
|
||||||
|
|||||||
@@ -66,7 +66,6 @@ function Folding() {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
this.getFoldsInRange = function(range) {
|
this.getFoldsInRange = function(range) {
|
||||||
range = range.clone();
|
|
||||||
var start = range.start;
|
var start = range.start;
|
||||||
var end = range.end;
|
var end = range.end;
|
||||||
var foldLines = this.$foldData;
|
var foldLines = this.$foldData;
|
||||||
@@ -104,8 +103,23 @@ function Folding() {
|
|||||||
foundFolds.push(fold);
|
foundFolds.push(fold);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
start.column -= 1;
|
||||||
|
end.column += 1;
|
||||||
|
|
||||||
return foundFolds;
|
return foundFolds;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.getFoldsInRangeList = function(ranges) {
|
||||||
|
if (Array.isArray(ranges)) {
|
||||||
|
var folds = [];
|
||||||
|
ranges.forEach(function(range) {
|
||||||
|
folds = folds.concat(this.getFoldsInRange(range));
|
||||||
|
}, this);
|
||||||
|
} else {
|
||||||
|
var folds = this.getFoldsInRange(ranges);
|
||||||
|
}
|
||||||
|
return folds;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns all folds in the document
|
* Returns all folds in the document
|
||||||
@@ -114,18 +128,9 @@ function Folding() {
|
|||||||
var folds = [];
|
var folds = [];
|
||||||
var foldLines = this.$foldData;
|
var foldLines = this.$foldData;
|
||||||
|
|
||||||
function addFold(fold) {
|
|
||||||
folds.push(fold);
|
|
||||||
if (!fold.subFolds)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (var i = 0; i < fold.subFolds.length; i++)
|
|
||||||
addFold(fold.subFolds[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var i = 0; i < foldLines.length; i++)
|
for (var i = 0; i < foldLines.length; i++)
|
||||||
for (var j = 0; j < foldLines[i].folds.length; j++)
|
for (var j = 0; j < foldLines[i].folds.length; j++)
|
||||||
addFold(foldLines[i].folds[j]);
|
folds.push(foldLines[i].folds[j]);
|
||||||
|
|
||||||
return folds;
|
return folds;
|
||||||
};
|
};
|
||||||
@@ -249,7 +254,7 @@ function Folding() {
|
|||||||
return foldLine;
|
return foldLine;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Adds a new fold.
|
* Adds a new fold.
|
||||||
*
|
*
|
||||||
* @returns
|
* @returns
|
||||||
@@ -263,9 +268,10 @@ function Folding() {
|
|||||||
|
|
||||||
if (placeholder instanceof Fold)
|
if (placeholder instanceof Fold)
|
||||||
fold = placeholder;
|
fold = placeholder;
|
||||||
else
|
else {
|
||||||
fold = new Fold(range, placeholder);
|
fold = new Fold(range, placeholder);
|
||||||
|
fold.collapseChildren = range.collapseChildren;
|
||||||
|
}
|
||||||
this.$clipRangeToDocument(fold.range);
|
this.$clipRangeToDocument(fold.range);
|
||||||
|
|
||||||
var startRow = fold.start.row;
|
var startRow = fold.start.row;
|
||||||
@@ -274,28 +280,30 @@ function Folding() {
|
|||||||
var endColumn = fold.end.column;
|
var endColumn = fold.end.column;
|
||||||
|
|
||||||
// --- Some checking ---
|
// --- Some checking ---
|
||||||
if (startRow == endRow && endColumn - startColumn < 2)
|
if (!(startRow < endRow ||
|
||||||
throw "The range has to be at least 2 characters width";
|
startRow == endRow && startColumn <= endColumn - 2))
|
||||||
|
throw new Error("The range has to be at least 2 characters width");
|
||||||
|
|
||||||
var startFold = this.getFoldAt(startRow, startColumn, 1);
|
var startFold = this.getFoldAt(startRow, startColumn, 1);
|
||||||
var endFold = this.getFoldAt(endRow, endColumn, -1);
|
var endFold = this.getFoldAt(endRow, endColumn, -1);
|
||||||
if (startFold && endFold == startFold)
|
if (startFold && endFold == startFold)
|
||||||
return startFold.addSubFold(fold);
|
return startFold.addSubFold(fold);
|
||||||
|
|
||||||
if (
|
if (startFold && !startFold.range.isStart(startRow, startColumn))
|
||||||
(startFold && !startFold.range.isStart(startRow, startColumn))
|
this.removeFold(startFold);
|
||||||
|| (endFold && !endFold.range.isEnd(endRow, endColumn))
|
|
||||||
) {
|
if (endFold && !endFold.range.isEnd(endRow, endColumn))
|
||||||
throw "A fold can't intersect already existing fold" + fold.range + startFold.range;
|
this.removeFold(endFold);
|
||||||
}
|
|
||||||
|
|
||||||
// Check if there are folds in the range we create the new fold for.
|
// Check if there are folds in the range we create the new fold for.
|
||||||
var folds = this.getFoldsInRange(fold.range);
|
var folds = this.getFoldsInRange(fold.range);
|
||||||
if (folds.length > 0) {
|
if (folds.length > 0) {
|
||||||
// Remove the folds from fold data.
|
// Remove the folds from fold data.
|
||||||
this.removeFolds(folds);
|
this.removeFolds(folds);
|
||||||
// Add the removed folds as subfolds on the new fold.
|
// Add the removed folds as subfolds on the new fold.
|
||||||
fold.subFolds = folds;
|
folds.forEach(function(subFold) {
|
||||||
|
fold.addSubFold(subFold);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var i = 0; i < foldData.length; i++) {
|
for (var i = 0; i < foldData.length; i++) {
|
||||||
@@ -304,8 +312,7 @@ function Folding() {
|
|||||||
foldLine.addFold(fold);
|
foldLine.addFold(fold);
|
||||||
added = true;
|
added = true;
|
||||||
break;
|
break;
|
||||||
}
|
} else if (startRow == foldLine.end.row) {
|
||||||
else if (startRow == foldLine.end.row) {
|
|
||||||
foldLine.addFold(fold);
|
foldLine.addFold(fold);
|
||||||
added = true;
|
added = true;
|
||||||
if (!fold.sameRow) {
|
if (!fold.sameRow) {
|
||||||
@@ -318,8 +325,7 @@ function Folding() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
} else if (endRow <= foldLine.start.row) {
|
||||||
else if (endRow <= foldLine.start.row) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -334,7 +340,7 @@ function Folding() {
|
|||||||
|
|
||||||
// Notify that fold data has changed.
|
// Notify that fold data has changed.
|
||||||
this.$modified = true;
|
this.$modified = true;
|
||||||
this._emit("changeFold", { data: fold });
|
this._emit("changeFold", { data: fold, action: "add" });
|
||||||
|
|
||||||
return fold;
|
return fold;
|
||||||
};
|
};
|
||||||
@@ -386,14 +392,16 @@ function Folding() {
|
|||||||
newFoldLine.start.column = folds[0].start.column;
|
newFoldLine.start.column = folds[0].start.column;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.$useWrapMode)
|
if (!this.$updating) {
|
||||||
this.$updateWrapData(startRow, endRow);
|
if (this.$useWrapMode)
|
||||||
else
|
this.$updateWrapData(startRow, endRow);
|
||||||
this.$updateRowLengthCache(startRow, endRow);
|
else
|
||||||
|
this.$updateRowLengthCache(startRow, endRow);
|
||||||
|
}
|
||||||
|
|
||||||
// Notify that fold data has changed.
|
// Notify that fold data has changed.
|
||||||
this.$modified = true;
|
this.$modified = true;
|
||||||
this._emit("changeFold", { data: fold });
|
this._emit("changeFold", { data: fold, action: "remove" });
|
||||||
};
|
};
|
||||||
|
|
||||||
this.removeFolds = function(folds) {
|
this.removeFolds = function(folds) {
|
||||||
@@ -413,9 +421,13 @@ function Folding() {
|
|||||||
|
|
||||||
this.expandFold = function(fold) {
|
this.expandFold = function(fold) {
|
||||||
this.removeFold(fold);
|
this.removeFold(fold);
|
||||||
fold.subFolds.forEach(function(fold) {
|
fold.subFolds.forEach(function(subFold) {
|
||||||
this.addFold(fold);
|
fold.restoreRange(subFold);
|
||||||
|
this.addFold(subFold);
|
||||||
}, this);
|
}, this);
|
||||||
|
if (fold.collapseChildren > 0) {
|
||||||
|
this.foldAll(fold.start.row+1, fold.end.row, fold.collapseChildren-1);
|
||||||
|
}
|
||||||
fold.subFolds = [];
|
fold.subFolds = [];
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -427,26 +439,30 @@ function Folding() {
|
|||||||
|
|
||||||
this.unfold = function(location, expandInner) {
|
this.unfold = function(location, expandInner) {
|
||||||
var range, folds;
|
var range, folds;
|
||||||
if (location == null)
|
if (location == null) {
|
||||||
range = new Range(0, 0, this.getLength(), 0);
|
range = new Range(0, 0, this.getLength(), 0);
|
||||||
else if (typeof location == "number")
|
expandInner = true;
|
||||||
|
} else if (typeof location == "number")
|
||||||
range = new Range(location, 0, location, this.getLine(location).length);
|
range = new Range(location, 0, location, this.getLine(location).length);
|
||||||
else if ("row" in location)
|
else if ("row" in location)
|
||||||
range = Range.fromPoints(location, location);
|
range = Range.fromPoints(location, location);
|
||||||
else
|
else
|
||||||
range = location;
|
range = location;
|
||||||
|
|
||||||
folds = this.getFoldsInRange(range);
|
folds = this.getFoldsInRangeList(range);
|
||||||
if (expandInner) {
|
if (expandInner) {
|
||||||
this.removeFolds(folds);
|
this.removeFolds(folds);
|
||||||
} else {
|
} else {
|
||||||
// TODO: might need to remove and add folds in one go instead of using
|
var subFolds = folds;
|
||||||
|
// TODO: might be better to remove and add folds in one go instead of using
|
||||||
// expandFolds several times.
|
// expandFolds several times.
|
||||||
while (folds.length) {
|
while (subFolds.length) {
|
||||||
this.expandFolds(folds);
|
this.expandFolds(subFolds);
|
||||||
folds = this.getFoldsInRange(range);
|
subFolds = this.getFoldsInRangeList(range);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (folds.length)
|
||||||
|
return folds;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -462,36 +478,41 @@ function Folding() {
|
|||||||
return foldLine ? foldLine.end.row : docRow;
|
return foldLine ? foldLine.end.row : docRow;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.getFoldDisplayLine = function(foldLine, endRow, endColumn, startRow, startColumn) {
|
this.getRowFoldStart = function(docRow, startFoldRow) {
|
||||||
if (startRow == null) {
|
var foldLine = this.getFoldLine(docRow, startFoldRow);
|
||||||
startRow = foldLine.start.row;
|
return foldLine ? foldLine.start.row : docRow;
|
||||||
startColumn = 0;
|
};
|
||||||
}
|
|
||||||
|
|
||||||
if (endRow == null) {
|
this.getFoldDisplayLine = function(foldLine, endRow, endColumn, startRow, startColumn) {
|
||||||
|
if (startRow == null)
|
||||||
|
startRow = foldLine.start.row;
|
||||||
|
if (startColumn == null)
|
||||||
|
startColumn = 0;
|
||||||
|
if (endRow == null)
|
||||||
endRow = foldLine.end.row;
|
endRow = foldLine.end.row;
|
||||||
|
if (endColumn == null)
|
||||||
endColumn = this.getLine(endRow).length;
|
endColumn = this.getLine(endRow).length;
|
||||||
}
|
|
||||||
|
|
||||||
// Build the textline using the FoldLine walker.
|
// Build the textline using the FoldLine walker.
|
||||||
var doc = this.doc;
|
var doc = this.doc;
|
||||||
var textLine = "";
|
var textLine = "";
|
||||||
|
|
||||||
foldLine.walk(function(placeholder, row, column, lastColumn) {
|
foldLine.walk(function(placeholder, row, column, lastColumn) {
|
||||||
if (row < startRow) {
|
if (row < startRow)
|
||||||
return;
|
return;
|
||||||
} else if (row == startRow) {
|
if (row == startRow) {
|
||||||
if (column < startColumn) {
|
if (column < startColumn)
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
lastColumn = Math.max(startColumn, lastColumn);
|
lastColumn = Math.max(startColumn, lastColumn);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (placeholder != null) {
|
if (placeholder != null) {
|
||||||
textLine += placeholder;
|
textLine += placeholder;
|
||||||
} else {
|
} else {
|
||||||
textLine += doc.getLine(row).substring(lastColumn, column);
|
textLine += doc.getLine(row).substring(lastColumn, column);
|
||||||
}
|
}
|
||||||
}.bind(this), endRow, endColumn);
|
}, endRow, endColumn);
|
||||||
return textLine;
|
return textLine;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -533,26 +554,22 @@ function Folding() {
|
|||||||
if (fold) {
|
if (fold) {
|
||||||
this.expandFold(fold);
|
this.expandFold(fold);
|
||||||
return;
|
return;
|
||||||
}
|
} else if (bracketPos = this.findMatchingBracket(cursor)) {
|
||||||
else if (bracketPos = this.findMatchingBracket(cursor)) {
|
|
||||||
if (range.comparePoint(bracketPos) == 1) {
|
if (range.comparePoint(bracketPos) == 1) {
|
||||||
range.end = bracketPos;
|
range.end = bracketPos;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
range.start = bracketPos;
|
range.start = bracketPos;
|
||||||
range.start.column++;
|
range.start.column++;
|
||||||
range.end.column--;
|
range.end.column--;
|
||||||
}
|
}
|
||||||
}
|
} else if (bracketPos = this.findMatchingBracket({row: cursor.row, column: cursor.column + 1})) {
|
||||||
else if (bracketPos = this.findMatchingBracket({row: cursor.row, column: cursor.column + 1})) {
|
|
||||||
if (range.comparePoint(bracketPos) == 1)
|
if (range.comparePoint(bracketPos) == 1)
|
||||||
range.end = bracketPos;
|
range.end = bracketPos;
|
||||||
else
|
else
|
||||||
range.start = bracketPos;
|
range.start = bracketPos;
|
||||||
|
|
||||||
range.start.column++;
|
range.start.column++;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
range = this.getCommentFoldRange(cursor.row, cursor.column) || range;
|
range = this.getCommentFoldRange(cursor.row, cursor.column) || range;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -560,8 +577,7 @@ function Folding() {
|
|||||||
if (tryToUnfold && folds.length) {
|
if (tryToUnfold && folds.length) {
|
||||||
this.expandFolds(folds);
|
this.expandFolds(folds);
|
||||||
return;
|
return;
|
||||||
}
|
} else if (folds.length == 1 ) {
|
||||||
else if (folds.length == 1 ) {
|
|
||||||
fold = folds[0];
|
fold = folds[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -617,10 +633,15 @@ function Folding() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.foldAll = function(startRow, endRow) {
|
this.foldAll = function(startRow, endRow, depth) {
|
||||||
|
if (depth == undefined)
|
||||||
|
depth = 100000; // JSON.stringify doesn't hanle Infinity
|
||||||
var foldWidgets = this.foldWidgets;
|
var foldWidgets = this.foldWidgets;
|
||||||
|
if (!foldWidgets)
|
||||||
|
return; // mode doesn't support folding
|
||||||
endRow = endRow || this.getLength();
|
endRow = endRow || this.getLength();
|
||||||
for (var row = startRow || 0; row < endRow; row++) {
|
startRow = startRow || 0;
|
||||||
|
for (var row = startRow; row < endRow; row++) {
|
||||||
if (foldWidgets[row] == null)
|
if (foldWidgets[row] == null)
|
||||||
foldWidgets[row] = this.getFoldWidget(row);
|
foldWidgets[row] = this.getFoldWidget(row);
|
||||||
if (foldWidgets[row] != "start")
|
if (foldWidgets[row] != "start")
|
||||||
@@ -628,13 +649,23 @@ function Folding() {
|
|||||||
|
|
||||||
var range = this.getFoldWidgetRange(row);
|
var range = this.getFoldWidgetRange(row);
|
||||||
// sometimes range can be incompatible with existing fold
|
// sometimes range can be incompatible with existing fold
|
||||||
// wouldn't it be better for addFold to return null istead of throwing?
|
// TODO change addFold to return null istead of throwing
|
||||||
if (range && range.end.row <= endRow) try {
|
if (range && range.isMultiLine()
|
||||||
this.addFold("...", range);
|
&& range.end.row <= endRow
|
||||||
} catch(e) {}
|
&& range.start.row >= startRow
|
||||||
|
) {
|
||||||
|
row = range.end.row;
|
||||||
|
try {
|
||||||
|
// addFold can change the range
|
||||||
|
var fold = this.addFold("...", range);
|
||||||
|
if (fold)
|
||||||
|
fold.collapseChildren = depth;
|
||||||
|
} catch(e) {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// structured folding
|
||||||
this.$foldStyles = {
|
this.$foldStyles = {
|
||||||
"manual": 1,
|
"manual": 1,
|
||||||
"markbegin": 1,
|
"markbegin": 1,
|
||||||
@@ -659,14 +690,14 @@ function Folding() {
|
|||||||
this.$setFolding(mode);
|
this.$setFolding(mode);
|
||||||
};
|
};
|
||||||
|
|
||||||
// structured folding
|
|
||||||
this.$setFolding = function(foldMode) {
|
this.$setFolding = function(foldMode) {
|
||||||
if (this.$foldMode == foldMode)
|
if (this.$foldMode == foldMode)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.$foldMode = foldMode;
|
this.$foldMode = foldMode;
|
||||||
|
|
||||||
this.removeListener('change', this.$updateFoldWidgets);
|
this.off('change', this.$updateFoldWidgets);
|
||||||
|
this.off('tokenizerUpdate', this.$tokenizerUpdateFoldWidgets);
|
||||||
this._emit("changeAnnotation");
|
this._emit("changeAnnotation");
|
||||||
|
|
||||||
if (!foldMode || this.$foldStyle == "manual") {
|
if (!foldMode || this.$foldStyle == "manual") {
|
||||||
@@ -679,54 +710,125 @@ function Folding() {
|
|||||||
this.getFoldWidgetRange = foldMode.getFoldWidgetRange.bind(foldMode, this, this.$foldStyle);
|
this.getFoldWidgetRange = foldMode.getFoldWidgetRange.bind(foldMode, this, this.$foldStyle);
|
||||||
|
|
||||||
this.$updateFoldWidgets = this.updateFoldWidgets.bind(this);
|
this.$updateFoldWidgets = this.updateFoldWidgets.bind(this);
|
||||||
|
this.$tokenizerUpdateFoldWidgets = this.tokenizerUpdateFoldWidgets.bind(this);
|
||||||
this.on('change', this.$updateFoldWidgets);
|
this.on('change', this.$updateFoldWidgets);
|
||||||
|
this.on('tokenizerUpdate', this.$tokenizerUpdateFoldWidgets);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.getParentFoldRangeData = function (row, ignoreCurrent) {
|
||||||
|
var fw = this.foldWidgets;
|
||||||
|
if (!fw || (ignoreCurrent && fw[row]))
|
||||||
|
return {};
|
||||||
|
|
||||||
|
var i = row - 1, firstRange;
|
||||||
|
while (i >= 0) {
|
||||||
|
var c = fw[i];
|
||||||
|
if (c == null)
|
||||||
|
c = fw[i] = this.getFoldWidget(i);
|
||||||
|
|
||||||
|
if (c == "start") {
|
||||||
|
var range = this.getFoldWidgetRange(i);
|
||||||
|
if (!firstRange)
|
||||||
|
firstRange = range;
|
||||||
|
if (range && range.end.row >= row)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
range: i !== -1 && range,
|
||||||
|
firstRange: firstRange
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
this.onFoldWidgetClick = function(row, e) {
|
this.onFoldWidgetClick = function(row, e) {
|
||||||
e = e.domEvent;
|
e = e.domEvent;
|
||||||
|
var options = {
|
||||||
|
children: e.shiftKey,
|
||||||
|
all: e.ctrlKey || e.metaKey,
|
||||||
|
siblings: e.altKey
|
||||||
|
};
|
||||||
|
|
||||||
|
var range = this.$toggleFoldWidget(row, options);
|
||||||
|
if (!range) {
|
||||||
|
var el = (e.target || e.srcElement)
|
||||||
|
if (el && /ace_fold-widget/.test(el.className))
|
||||||
|
el.className += " ace_invalid";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.$toggleFoldWidget = function(row, options) {
|
||||||
|
if (!this.getFoldWidget)
|
||||||
|
return;
|
||||||
var type = this.getFoldWidget(row);
|
var type = this.getFoldWidget(row);
|
||||||
var line = this.getLine(row);
|
var line = this.getLine(row);
|
||||||
var onlySubfolds = e.shiftKey;
|
|
||||||
var addSubfolds = onlySubfolds || e.ctrlKey || e.altKey || e.metaKey;
|
|
||||||
var fold;
|
|
||||||
|
|
||||||
if (type == "end")
|
var dir = type === "end" ? -1 : 1;
|
||||||
fold = this.getFoldAt(row, 0, -1);
|
var fold = this.getFoldAt(row, dir === -1 ? 0 : line.length, dir);
|
||||||
else
|
|
||||||
fold = this.getFoldAt(row, line.length, 1);
|
|
||||||
|
|
||||||
if (fold) {
|
if (fold) {
|
||||||
if (addSubfolds)
|
if (options.children || options.all)
|
||||||
this.removeFold(fold);
|
this.removeFold(fold);
|
||||||
else
|
else
|
||||||
this.expandFold(fold);
|
this.expandFold(fold);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var range = this.getFoldWidgetRange(row);
|
var range = this.getFoldWidgetRange(row, true);
|
||||||
if (range) {
|
// sometimes singleline folds can be missed by the code above
|
||||||
// sometimes singleline folds can be missed by the code above
|
if (range && !range.isMultiLine()) {
|
||||||
if (!range.isMultiLine()) {
|
fold = this.getFoldAt(range.start.row, range.start.column, 1);
|
||||||
fold = this.getFoldAt(range.start.row, range.start.column, 1);
|
if (fold && range.isEqual(fold.range)) {
|
||||||
if (fold && range.isEqual(fold.range)) {
|
this.removeFold(fold);
|
||||||
this.removeFold(fold);
|
return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!onlySubfolds)
|
|
||||||
this.addFold("...", range);
|
|
||||||
|
|
||||||
if (addSubfolds)
|
|
||||||
this.foldAll(range.start.row + 1, range.end.row);
|
|
||||||
} else {
|
|
||||||
if (addSubfolds)
|
|
||||||
this.foldAll(row + 1, this.getLength());
|
|
||||||
(e.target || e.srcElement).className += " ace_invalid"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (options.siblings) {
|
||||||
|
var data = this.getParentFoldRangeData(row);
|
||||||
|
if (data.range) {
|
||||||
|
var startRow = data.range.start.row + 1;
|
||||||
|
var endRow = data.range.end.row;
|
||||||
|
}
|
||||||
|
this.foldAll(startRow, endRow, options.all ? 10000 : 0);
|
||||||
|
} else if (options.children) {
|
||||||
|
endRow = range ? range.end.row : this.getLength();
|
||||||
|
this.foldAll(row + 1, range.end.row, options.all ? 10000 : 0);
|
||||||
|
} else if (range) {
|
||||||
|
if (options.all)
|
||||||
|
range.collapseChildren = 10000;
|
||||||
|
this.addFold("...", range);
|
||||||
|
}
|
||||||
|
|
||||||
|
return range;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
this.toggleFoldWidget = function(toggleParent) {
|
||||||
|
var row = this.selection.getCursor().row;
|
||||||
|
row = this.getRowFoldStart(row);
|
||||||
|
var range = this.$toggleFoldWidget(row, {});
|
||||||
|
|
||||||
|
if (range)
|
||||||
|
return;
|
||||||
|
// handle toggleParent
|
||||||
|
var data = this.getParentFoldRangeData(row, true);
|
||||||
|
range = data.range || data.firstRange;
|
||||||
|
|
||||||
|
if (range) {
|
||||||
|
row = range.start.row;
|
||||||
|
var fold = this.getFoldAt(row, this.getLine(row).length, 1);
|
||||||
|
|
||||||
|
if (fold) {
|
||||||
|
this.removeFold(fold);
|
||||||
|
} else {
|
||||||
|
this.addFold("...", range);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
this.updateFoldWidgets = function(e) {
|
this.updateFoldWidgets = function(e) {
|
||||||
var delta = e.data;
|
var delta = e.data;
|
||||||
var range = delta.range;
|
var range = delta.range;
|
||||||
@@ -743,7 +845,13 @@ function Folding() {
|
|||||||
this.foldWidgets.splice.apply(this.foldWidgets, args);
|
this.foldWidgets.splice.apply(this.foldWidgets, args);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
this.tokenizerUpdateFoldWidgets = function(e) {
|
||||||
|
var rows = e.data;
|
||||||
|
if (rows.first != rows.last) {
|
||||||
|
if (this.foldWidgets.length > rows.first)
|
||||||
|
this.foldWidgets.splice(rows.first, this.foldWidgets.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.Folding = Folding;
|
exports.Folding = Folding;
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ function createFoldTestSession() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function assertArray(a, b) {
|
function assertArray(a, b) {
|
||||||
|
assert.equal(a+"", b+"");
|
||||||
assert.ok(a.length == b.length);
|
assert.ok(a.length == b.length);
|
||||||
for (var i = 0; i < a.length; i++) {
|
for (var i = 0; i < a.length; i++) {
|
||||||
assert.equal(a[i], b[i]);
|
assert.equal(a[i], b[i]);
|
||||||
@@ -385,11 +386,12 @@ module.exports = {
|
|||||||
assert.ok(splits[i] == assertEqual[i]);
|
assert.ok(splits[i] == assertEqual[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EditSession.prototype.$wrapAsCode = true;
|
||||||
// Basic splitting.
|
// Basic splitting.
|
||||||
computeAndAssert("foo bar foo bar", [ 12 ]);
|
computeAndAssert("foo bar foo bar", [ 12 ]);
|
||||||
computeAndAssert("foo bar f bar", [ 12 ]);
|
computeAndAssert("foo bar f bar", [ 12 ]);
|
||||||
computeAndAssert("foo bar f r", [ 14 ]);
|
computeAndAssert("foo bar f r", [ 12 ]); // 14 if we enable
|
||||||
computeAndAssert("foo bar foo bar foo bara foo", [12, 25]);
|
computeAndAssert("foo bar foo bar foo bara foo", [12, 25]);
|
||||||
|
|
||||||
// Don't split if there is only whitespaces/tabs at the end of the line.
|
// Don't split if there is only whitespaces/tabs at the end of the line.
|
||||||
@@ -405,7 +407,7 @@ module.exports = {
|
|||||||
computeAndAssert("foo \t \tbar", [ 7 ]);
|
computeAndAssert("foo \t \tbar", [ 7 ]);
|
||||||
|
|
||||||
// Ignore spaces/tabs at beginning of split.
|
// Ignore spaces/tabs at beginning of split.
|
||||||
computeAndAssert("foo \t \t \t \t bar", [ 14 ]);
|
computeAndAssert("foo \t \t \t \t bar", [ 7 ]); // 14
|
||||||
|
|
||||||
// Test wrapping for asian characters.
|
// Test wrapping for asian characters.
|
||||||
computeAndAssert("ぁぁ", [1], 2);
|
computeAndAssert("ぁぁ", [1], 2);
|
||||||
@@ -417,6 +419,10 @@ module.exports = {
|
|||||||
computeAndAssert(" ab.c;ef++", [1, 3, 5, 7, 8], 2);
|
computeAndAssert(" ab.c;ef++", [1, 3, 5, 7, 8], 2);
|
||||||
computeAndAssert(" a.b", [1, 2, 3], 1);
|
computeAndAssert(" a.b", [1, 2, 3], 1);
|
||||||
computeAndAssert("#>>", [1, 2], 1);
|
computeAndAssert("#>>", [1, 2], 1);
|
||||||
|
|
||||||
|
// Test wrapping for punctuation in
|
||||||
|
EditSession.prototype.$wrapAsCode = false;
|
||||||
|
computeAndAssert("ab cde, Juhu kinners", [3, 8, 13, 19], 6);
|
||||||
},
|
},
|
||||||
|
|
||||||
"test get longest line" : function() {
|
"test get longest line" : function() {
|
||||||
@@ -898,7 +904,27 @@ module.exports = {
|
|||||||
|
|
||||||
return session;
|
return session;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"test delete fold with wrap enabled": function() {
|
||||||
|
var session = new EditSession("");
|
||||||
|
session.setValue([
|
||||||
|
"This is some placeholder text that will be folded inline.",
|
||||||
|
"This is some placeholder text that will be folded inline.",
|
||||||
|
"More text.",
|
||||||
|
"<p>The cursor in this paragraph text will be offset by 1 row.<p>",
|
||||||
|
"<p>Everything after this will be offset as well due to the folds in the row before too.</p>"
|
||||||
|
].join("\n"));
|
||||||
|
session.addFold('...', new Range(0, 8, 0, 42));
|
||||||
|
session.addFold('...', new Range(1, 8, 1, 42));
|
||||||
|
session.addFold('...', new Range(3, 7, 3, 51));
|
||||||
|
session.setOption("wrap", 40);
|
||||||
|
session.remove(new Range(0,0, 2, 5));
|
||||||
|
// needed because adjustWrapLimit is called async from renderer
|
||||||
|
session.adjustWrapLimit(80);
|
||||||
|
|
||||||
|
assert.equal(session.$wrapData + "", [[], [], [40, 76]] + "");
|
||||||
|
},
|
||||||
|
|
||||||
"test add fold": function() {
|
"test add fold": function() {
|
||||||
var session = createFoldTestSession();
|
var session = createFoldTestSession();
|
||||||
var fold;
|
var fold;
|
||||||
@@ -911,7 +937,7 @@ module.exports = {
|
|||||||
fail = true;
|
fail = true;
|
||||||
}
|
}
|
||||||
if (fail != shouldFail) {
|
if (fail != shouldFail) {
|
||||||
throw "Expected to get an exception";
|
throw new Error("Expected to get an exception");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -980,7 +1006,8 @@ module.exports = {
|
|||||||
assertArray(session.$docRowCache, [1,3,4]);
|
assertArray(session.$docRowCache, [1,3,4]);
|
||||||
assertArray(session.$screenRowCache, [1,2,3]);
|
assertArray(session.$screenRowCache, [1,2,3]);
|
||||||
|
|
||||||
session.screenToDocumentPosition(0,0);
|
var pos = session.screenToDocumentPosition(0,0);
|
||||||
|
assert.equal(pos.row, 0);
|
||||||
assertArray(session.$docRowCache, [1,3,4]);
|
assertArray(session.$docRowCache, [1,3,4]);
|
||||||
assertArray(session.$screenRowCache, [1,2,3]);
|
assertArray(session.$screenRowCache, [1,2,3]);
|
||||||
|
|
||||||
@@ -991,11 +1018,58 @@ module.exports = {
|
|||||||
session.$resetRowCache();
|
session.$resetRowCache();
|
||||||
assertArray(session.$docRowCache, []);
|
assertArray(session.$docRowCache, []);
|
||||||
assertArray(session.$screenRowCache, []);
|
assertArray(session.$screenRowCache, []);
|
||||||
|
|
||||||
|
session.screenToDocumentPosition(1,3);
|
||||||
|
assertArray(session.$docRowCache, [1]);
|
||||||
|
assertArray(session.$screenRowCache, [1]);
|
||||||
|
|
||||||
|
session.screenToDocumentPosition(5,3);
|
||||||
|
assertArray(session.$docRowCache, [1,3,4]);
|
||||||
|
assertArray(session.$screenRowCache, [1,2,3]);
|
||||||
|
|
||||||
|
session = new EditSession(new Array(30).join("\n"));
|
||||||
|
session.documentToScreenPosition(2,0);
|
||||||
|
session.documentToScreenPosition(2,0);
|
||||||
|
assertArray(session.$docRowCache, [1,2]);
|
||||||
|
assertArray(session.$screenRowCache, [1,2]);
|
||||||
|
},
|
||||||
|
|
||||||
|
"test annotations": function() {
|
||||||
|
var session = new EditSession([]),
|
||||||
|
annotation = {row: 0, type: 'info', text: "This is a test."};
|
||||||
|
|
||||||
|
session.clearAnnotations();
|
||||||
|
assertArray(session.getAnnotations(), []);
|
||||||
|
session.setAnnotations([annotation]);
|
||||||
|
assertArray(session.getAnnotations(), [annotation]);
|
||||||
|
},
|
||||||
|
|
||||||
|
"test: mode loading" : function(next) {
|
||||||
|
if (!require.undef) {
|
||||||
|
console.log("Skipping test: This test only runs in the browser");
|
||||||
|
next();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var session = new EditSession([]);
|
||||||
|
session.setMode("ace/mode/javascript");
|
||||||
|
assert.equal(session.$modeid, "ace/mode/javascript");
|
||||||
|
session.on("changeMode", function() {
|
||||||
|
assert.equal(session.$modeid, "ace/mode/javascript");
|
||||||
|
});
|
||||||
|
session.setMode("ace/mode/sh", function(mode) {
|
||||||
|
assert.ok(!mode);
|
||||||
|
});
|
||||||
|
setTimeout(function() {
|
||||||
|
session.setMode("ace/mode/javascript", function(mode) {
|
||||||
|
session.setMode("ace/mode/javascript");
|
||||||
|
assert.equal(session.$modeid, "ace/mode/javascript");
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
}, 0);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (typeof module !== "undefined" && module === require.main) {
|
if (typeof module !== "undefined" && module === require.main) {
|
||||||
require("asyncjs").test.testcase(module.exports).exec()
|
require("asyncjs").test.testcase(module.exports).exec();
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
+2
-2
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 2010, Ajax.org B.V.
|
* Copyright (c) 2010, Ajax.org B.V.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
* * Redistributions of source code must retain the above copyright
|
* * Redistributions of source code must retain the above copyright
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
* * Neither the name of Ajax.org B.V. nor the
|
* * Neither the name of Ajax.org B.V. nor the
|
||||||
* names of its contributors may be used to endorse or promote products
|
* names of its contributors may be used to endorse or promote products
|
||||||
* derived from this software without specific prior written permission.
|
* derived from this software without specific prior written permission.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ var JavaScriptMode = require("./mode/javascript").Mode;
|
|||||||
var UndoManager = require("./undomanager").UndoManager;
|
var UndoManager = require("./undomanager").UndoManager;
|
||||||
var MockRenderer = require("./test/mockrenderer").MockRenderer;
|
var MockRenderer = require("./test/mockrenderer").MockRenderer;
|
||||||
var assert = require("./test/assertions");
|
var assert = require("./test/assertions");
|
||||||
|
var whitespace = require("./ext/whitespace");
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
"test: delete line from the middle" : function() {
|
"test: delete line from the middle" : function() {
|
||||||
@@ -184,21 +185,23 @@ module.exports = {
|
|||||||
"test: comment lines should perserve selection" : function() {
|
"test: comment lines should perserve selection" : function() {
|
||||||
var session = new EditSession([" abc", "cde"].join("\n"), new JavaScriptMode());
|
var session = new EditSession([" abc", "cde"].join("\n"), new JavaScriptMode());
|
||||||
var editor = new Editor(new MockRenderer(), session);
|
var editor = new Editor(new MockRenderer(), session);
|
||||||
|
whitespace.detectIndentation(session);
|
||||||
|
|
||||||
editor.moveCursorTo(0, 2);
|
editor.moveCursorTo(0, 2);
|
||||||
editor.getSelection().selectDown();
|
editor.getSelection().selectDown();
|
||||||
editor.toggleCommentLines();
|
editor.toggleCommentLines();
|
||||||
|
|
||||||
assert.equal(["// abc", "//cde"].join("\n"), session.toString());
|
assert.equal(["// abc", "// cde"].join("\n"), session.toString());
|
||||||
|
|
||||||
var selection = editor.getSelectionRange();
|
var selection = editor.getSelectionRange();
|
||||||
assert.position(selection.start, 0, 4);
|
assert.position(selection.start, 0, 5);
|
||||||
assert.position(selection.end, 1, 4);
|
assert.position(selection.end, 1, 5);
|
||||||
},
|
},
|
||||||
|
|
||||||
"test: uncomment lines should perserve selection" : function() {
|
"test: uncomment lines should perserve selection" : function() {
|
||||||
var session = new EditSession(["// abc", "//cde"].join("\n"), new JavaScriptMode());
|
var session = new EditSession(["// abc", "//cde"].join("\n"), new JavaScriptMode());
|
||||||
var editor = new Editor(new MockRenderer(), session);
|
var editor = new Editor(new MockRenderer(), session);
|
||||||
|
session.setTabSize(2);
|
||||||
|
|
||||||
editor.moveCursorTo(0, 1);
|
editor.moveCursorTo(0, 1);
|
||||||
editor.getSelection().selectDown();
|
editor.getSelection().selectDown();
|
||||||
@@ -235,7 +238,7 @@ module.exports = {
|
|||||||
editor.getSelection().selectDown();
|
editor.getSelection().selectDown();
|
||||||
|
|
||||||
editor.toggleCommentLines();
|
editor.toggleCommentLines();
|
||||||
assert.range(editor.getSelectionRange(), 0, 2, 1, 0);
|
assert.range(editor.getSelectionRange(), 0, 3, 1, 0);
|
||||||
|
|
||||||
// select up
|
// select up
|
||||||
var session = new EditSession(["abc", "cde"].join("\n"), new JavaScriptMode());
|
var session = new EditSession(["abc", "cde"].join("\n"), new JavaScriptMode());
|
||||||
@@ -245,10 +248,10 @@ module.exports = {
|
|||||||
editor.getSelection().selectUp();
|
editor.getSelection().selectUp();
|
||||||
|
|
||||||
editor.toggleCommentLines();
|
editor.toggleCommentLines();
|
||||||
assert.range(editor.getSelectionRange(), 0, 2, 1, 0);
|
assert.range(editor.getSelectionRange(), 0, 3, 1, 0);
|
||||||
},
|
},
|
||||||
|
|
||||||
"test: move lines down should select moved lines" : function() {
|
"test: move lines down should keep selection on moved lines" : function() {
|
||||||
var session = new EditSession(["11", "22", "33", "44"].join("\n"));
|
var session = new EditSession(["11", "22", "33", "44"].join("\n"));
|
||||||
var editor = new Editor(new MockRenderer(), session);
|
var editor = new Editor(new MockRenderer(), session);
|
||||||
|
|
||||||
@@ -257,25 +260,25 @@ module.exports = {
|
|||||||
|
|
||||||
editor.moveLinesDown();
|
editor.moveLinesDown();
|
||||||
assert.equal(["33", "11", "22", "44"].join("\n"), session.toString());
|
assert.equal(["33", "11", "22", "44"].join("\n"), session.toString());
|
||||||
assert.position(editor.getCursorPosition(), 1, 0);
|
assert.position(editor.getCursorPosition(), 2, 1);
|
||||||
assert.position(editor.getSelection().getSelectionAnchor(), 3, 0);
|
assert.position(editor.getSelection().getSelectionAnchor(), 1, 1);
|
||||||
assert.position(editor.getSelection().getSelectionLead(), 1, 0);
|
assert.position(editor.getSelection().getSelectionLead(), 2, 1);
|
||||||
|
|
||||||
editor.moveLinesDown();
|
editor.moveLinesDown();
|
||||||
assert.equal(["33", "44", "11", "22"].join("\n"), session.toString());
|
assert.equal(["33", "44", "11", "22"].join("\n"), session.toString());
|
||||||
assert.position(editor.getCursorPosition(), 2, 0);
|
assert.position(editor.getCursorPosition(), 3, 1);
|
||||||
assert.position(editor.getSelection().getSelectionAnchor(), 3, 2);
|
assert.position(editor.getSelection().getSelectionAnchor(), 2, 1);
|
||||||
assert.position(editor.getSelection().getSelectionLead(), 2, 0);
|
assert.position(editor.getSelection().getSelectionLead(), 3, 1);
|
||||||
|
|
||||||
// moving again should have no effect
|
// moving again should have no effect
|
||||||
editor.moveLinesDown();
|
editor.moveLinesDown();
|
||||||
assert.equal(["33", "44", "11", "22"].join("\n"), session.toString());
|
assert.equal(["33", "44", "11", "22"].join("\n"), session.toString());
|
||||||
assert.position(editor.getCursorPosition(), 2, 0);
|
assert.position(editor.getCursorPosition(), 3, 1);
|
||||||
assert.position(editor.getSelection().getSelectionAnchor(), 3, 2);
|
assert.position(editor.getSelection().getSelectionAnchor(), 2, 1);
|
||||||
assert.position(editor.getSelection().getSelectionLead(), 2, 0);
|
assert.position(editor.getSelection().getSelectionLead(), 3, 1);
|
||||||
},
|
},
|
||||||
|
|
||||||
"test: move lines up should select moved lines" : function() {
|
"test: move lines up should keep selection on moved lines" : function() {
|
||||||
var session = new EditSession(["11", "22", "33", "44"].join("\n"));
|
var session = new EditSession(["11", "22", "33", "44"].join("\n"));
|
||||||
var editor = new Editor(new MockRenderer(), session);
|
var editor = new Editor(new MockRenderer(), session);
|
||||||
|
|
||||||
@@ -284,19 +287,18 @@ module.exports = {
|
|||||||
|
|
||||||
editor.moveLinesUp();
|
editor.moveLinesUp();
|
||||||
assert.equal(session.toString(), ["11", "33", "44", "22"].join("\n"));
|
assert.equal(session.toString(), ["11", "33", "44", "22"].join("\n"));
|
||||||
assert.position(editor.getCursorPosition(), 1, 0);
|
assert.position(editor.getCursorPosition(), 2, 1);
|
||||||
assert.position(editor.getSelection().getSelectionAnchor(), 3, 0);
|
assert.position(editor.getSelection().getSelectionAnchor(), 1, 1);
|
||||||
assert.position(editor.getSelection().getSelectionLead(), 1, 0);
|
assert.position(editor.getSelection().getSelectionLead(), 2, 1);
|
||||||
|
|
||||||
editor.moveLinesUp();
|
editor.moveLinesUp();
|
||||||
assert.equal(session.toString(), ["33", "44", "11", "22"].join("\n"));
|
assert.equal(session.toString(), ["33", "44", "11", "22"].join("\n"));
|
||||||
assert.position(editor.getCursorPosition(), 0, 0);
|
assert.position(editor.getCursorPosition(), 1, 1);
|
||||||
assert.position(editor.getSelection().getSelectionAnchor(), 2, 0);
|
assert.position(editor.getSelection().getSelectionAnchor(), 0, 1);
|
||||||
assert.position(editor.getSelection().getSelectionLead(), 0, 0);
|
assert.position(editor.getSelection().getSelectionLead(), 1, 1);
|
||||||
},
|
},
|
||||||
|
|
||||||
"test: move line without active selection should not move cursor relative to the moved line" : function()
|
"test: move line without active selection should not move cursor relative to the moved line" : function() {
|
||||||
{
|
|
||||||
var session = new EditSession(["11", "22", "33", "44"].join("\n"));
|
var session = new EditSession(["11", "22", "33", "44"].join("\n"));
|
||||||
var editor = new Editor(new MockRenderer(), session);
|
var editor = new Editor(new MockRenderer(), session);
|
||||||
|
|
||||||
@@ -314,7 +316,7 @@ module.exports = {
|
|||||||
assert.position(editor.getCursorPosition(), 1, 1);
|
assert.position(editor.getCursorPosition(), 1, 1);
|
||||||
},
|
},
|
||||||
|
|
||||||
"test: copy lines down should select lines and place cursor at the selection start" : function() {
|
"test: copy lines down should keep selection" : function() {
|
||||||
var session = new EditSession(["11", "22", "33", "44"].join("\n"));
|
var session = new EditSession(["11", "22", "33", "44"].join("\n"));
|
||||||
var editor = new Editor(new MockRenderer(), session);
|
var editor = new Editor(new MockRenderer(), session);
|
||||||
|
|
||||||
@@ -324,12 +326,12 @@ module.exports = {
|
|||||||
editor.copyLinesDown();
|
editor.copyLinesDown();
|
||||||
assert.equal(["11", "22", "33", "22", "33", "44"].join("\n"), session.toString());
|
assert.equal(["11", "22", "33", "22", "33", "44"].join("\n"), session.toString());
|
||||||
|
|
||||||
assert.position(editor.getCursorPosition(), 3, 0);
|
assert.position(editor.getCursorPosition(), 4, 1);
|
||||||
assert.position(editor.getSelection().getSelectionAnchor(), 5, 0);
|
assert.position(editor.getSelection().getSelectionAnchor(), 3, 1);
|
||||||
assert.position(editor.getSelection().getSelectionLead(), 3, 0);
|
assert.position(editor.getSelection().getSelectionLead(), 4, 1);
|
||||||
},
|
},
|
||||||
|
|
||||||
"test: copy lines up should select lines and place cursor at the selection start" : function() {
|
"test: copy lines up should keep selection" : function() {
|
||||||
var session = new EditSession(["11", "22", "33", "44"].join("\n"));
|
var session = new EditSession(["11", "22", "33", "44"].join("\n"));
|
||||||
var editor = new Editor(new MockRenderer(), session);
|
var editor = new Editor(new MockRenderer(), session);
|
||||||
|
|
||||||
@@ -339,9 +341,9 @@ module.exports = {
|
|||||||
editor.copyLinesUp();
|
editor.copyLinesUp();
|
||||||
assert.equal(["11", "22", "33", "22", "33", "44"].join("\n"), session.toString());
|
assert.equal(["11", "22", "33", "22", "33", "44"].join("\n"), session.toString());
|
||||||
|
|
||||||
assert.position(editor.getCursorPosition(), 1, 0);
|
assert.position(editor.getCursorPosition(), 2, 1);
|
||||||
assert.position(editor.getSelection().getSelectionAnchor(), 3, 0);
|
assert.position(editor.getSelection().getSelectionAnchor(), 1, 1);
|
||||||
assert.position(editor.getSelection().getSelectionLead(), 1, 0);
|
assert.position(editor.getSelection().getSelectionLead(), 2, 1);
|
||||||
},
|
},
|
||||||
|
|
||||||
"test: input a tab with soft tab should convert it to spaces" : function() {
|
"test: input a tab with soft tab should convert it to spaces" : function() {
|
||||||
|
|||||||
@@ -0,0 +1,57 @@
|
|||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Distributed under the BSD license:
|
||||||
|
*
|
||||||
|
* Copyright (c) 2012, Ajax.org B.V.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of Ajax.org B.V. nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
// [WIP]
|
||||||
|
|
||||||
|
define(function(require, exports, module) {
|
||||||
|
"use strict";
|
||||||
|
var TokenIterator = require("ace/token_iterator").TokenIterator;
|
||||||
|
|
||||||
|
var phpTransform = require("./beautify/php_rules").transform;
|
||||||
|
|
||||||
|
exports.beautify = function(session) {
|
||||||
|
var iterator = new TokenIterator(session, 0, 0);
|
||||||
|
var token = iterator.getCurrentToken();
|
||||||
|
|
||||||
|
var context = session.$modeId.split("/").pop();
|
||||||
|
|
||||||
|
var code = phpTransform(iterator, context);
|
||||||
|
session.doc.setValue(code);
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.commands = [{
|
||||||
|
name: "beautify",
|
||||||
|
exec: function(editor) {
|
||||||
|
exports.beautify(editor.session);
|
||||||
|
},
|
||||||
|
bindKey: "Ctrl-Shift-B"
|
||||||
|
}]
|
||||||
|
|
||||||
|
});
|
||||||
@@ -0,0 +1,366 @@
|
|||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Distributed under the BSD license:
|
||||||
|
*
|
||||||
|
* Copyright (c) 2012, Ajax.org B.V.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of Ajax.org B.V. nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
define(function(require, exports, module) {
|
||||||
|
"use strict";
|
||||||
|
var TokenIterator = require("ace/token_iterator").TokenIterator;
|
||||||
|
exports.newLines = [{
|
||||||
|
type: 'support.php_tag',
|
||||||
|
value: '<?php'
|
||||||
|
}, {
|
||||||
|
type: 'support.php_tag',
|
||||||
|
value: '<?'
|
||||||
|
}, {
|
||||||
|
type: 'support.php_tag',
|
||||||
|
value: '?>'
|
||||||
|
}, {
|
||||||
|
type: 'paren.lparen',
|
||||||
|
value: '{',
|
||||||
|
indent: true
|
||||||
|
}, {
|
||||||
|
type: 'paren.rparen',
|
||||||
|
breakBefore: true,
|
||||||
|
value: '}',
|
||||||
|
indent: false
|
||||||
|
}, {
|
||||||
|
type: 'paren.rparen',
|
||||||
|
breakBefore: true,
|
||||||
|
value: '})',
|
||||||
|
indent: false,
|
||||||
|
dontBreak: true
|
||||||
|
}, {
|
||||||
|
type: 'comment'
|
||||||
|
}, {
|
||||||
|
type: 'text',
|
||||||
|
value: ';'
|
||||||
|
}, {
|
||||||
|
type: 'text',
|
||||||
|
value: ':',
|
||||||
|
context: 'php'
|
||||||
|
}, {
|
||||||
|
type: 'keyword',
|
||||||
|
value: 'case',
|
||||||
|
indent: true,
|
||||||
|
dontBreak: true
|
||||||
|
}, {
|
||||||
|
type: 'keyword',
|
||||||
|
value: 'default',
|
||||||
|
indent: true,
|
||||||
|
dontBreak: true
|
||||||
|
}, {
|
||||||
|
type: 'keyword',
|
||||||
|
value: 'break',
|
||||||
|
indent: false,
|
||||||
|
dontBreak: true
|
||||||
|
}, {
|
||||||
|
type: 'punctuation.doctype.end',
|
||||||
|
value: '>'
|
||||||
|
}, {
|
||||||
|
type: 'meta.tag.punctuation.end',
|
||||||
|
value: '>'
|
||||||
|
}, {
|
||||||
|
type: 'meta.tag.punctuation.begin',
|
||||||
|
value: '<',
|
||||||
|
blockTag: true,
|
||||||
|
indent: true,
|
||||||
|
dontBreak: true
|
||||||
|
}, {
|
||||||
|
type: 'meta.tag.punctuation.begin',
|
||||||
|
value: '</',
|
||||||
|
indent: false,
|
||||||
|
breakBefore: true,
|
||||||
|
dontBreak: true
|
||||||
|
}, {
|
||||||
|
type: 'punctuation.operator',
|
||||||
|
value: ';'
|
||||||
|
}];
|
||||||
|
|
||||||
|
exports.spaces = [{
|
||||||
|
type: 'xml-pe',
|
||||||
|
prepend: true
|
||||||
|
},{
|
||||||
|
type: 'entity.other.attribute-name',
|
||||||
|
prepend: true
|
||||||
|
}, {
|
||||||
|
type: 'storage.type',
|
||||||
|
value: 'var',
|
||||||
|
append: true
|
||||||
|
}, {
|
||||||
|
type: 'storage.type',
|
||||||
|
value: 'function',
|
||||||
|
append: true
|
||||||
|
}, {
|
||||||
|
type: 'keyword.operator',
|
||||||
|
value: '='
|
||||||
|
}, {
|
||||||
|
type: 'keyword',
|
||||||
|
value: 'as',
|
||||||
|
prepend: true,
|
||||||
|
append: true
|
||||||
|
}, {
|
||||||
|
type: 'keyword',
|
||||||
|
value: 'function',
|
||||||
|
append: true
|
||||||
|
}, {
|
||||||
|
type: 'support.function',
|
||||||
|
next: /[^\(]/,
|
||||||
|
append: true
|
||||||
|
}, {
|
||||||
|
type: 'keyword',
|
||||||
|
value: 'or',
|
||||||
|
append: true,
|
||||||
|
prepend: true
|
||||||
|
}, {
|
||||||
|
type: 'keyword',
|
||||||
|
value: 'and',
|
||||||
|
append: true,
|
||||||
|
prepend: true
|
||||||
|
}, {
|
||||||
|
type: 'keyword',
|
||||||
|
value: 'case',
|
||||||
|
append: true
|
||||||
|
}, {
|
||||||
|
type: 'keyword.operator',
|
||||||
|
value: '||',
|
||||||
|
append: true,
|
||||||
|
prepend: true
|
||||||
|
}, {
|
||||||
|
type: 'keyword.operator',
|
||||||
|
value: '&&',
|
||||||
|
append: true,
|
||||||
|
prepend: true
|
||||||
|
}];
|
||||||
|
exports.singleTags = ['!doctype','area','base','br','hr','input','img','link','meta'];
|
||||||
|
|
||||||
|
exports.transform = function(iterator, maxPos, context) {
|
||||||
|
var token = iterator.getCurrentToken();
|
||||||
|
|
||||||
|
var newLines = exports.newLines;
|
||||||
|
var spaces = exports.spaces;
|
||||||
|
var singleTags = exports.singleTags;
|
||||||
|
|
||||||
|
var code = '';
|
||||||
|
|
||||||
|
var indentation = 0;
|
||||||
|
var dontBreak = false;
|
||||||
|
var tag;
|
||||||
|
var lastTag;
|
||||||
|
var lastToken = {};
|
||||||
|
var nextTag;
|
||||||
|
var nextToken = {};
|
||||||
|
var breakAdded = false;
|
||||||
|
var value = '';
|
||||||
|
|
||||||
|
while (token!==null) {
|
||||||
|
console.log(token);
|
||||||
|
|
||||||
|
if( !token ){
|
||||||
|
token = iterator.stepForward();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//change syntax
|
||||||
|
//php
|
||||||
|
if( token.type == 'support.php_tag' && token.value != '?>' ){
|
||||||
|
context = 'php';
|
||||||
|
}
|
||||||
|
else if( token.type == 'support.php_tag' && token.value == '?>' ){
|
||||||
|
context = 'html';
|
||||||
|
}
|
||||||
|
//css
|
||||||
|
else if( token.type == 'meta.tag.name.style' && context != 'css' ){
|
||||||
|
context = 'css';
|
||||||
|
}
|
||||||
|
else if( token.type == 'meta.tag.name.style' && context == 'css' ){
|
||||||
|
context = 'html';
|
||||||
|
}
|
||||||
|
//js
|
||||||
|
else if( token.type == 'meta.tag.name.script' && context != 'js' ){
|
||||||
|
context = 'js';
|
||||||
|
}
|
||||||
|
else if( token.type == 'meta.tag.name.script' && context == 'js' ){
|
||||||
|
context = 'html';
|
||||||
|
}
|
||||||
|
|
||||||
|
nextToken = iterator.stepForward();
|
||||||
|
|
||||||
|
//tag name
|
||||||
|
if (nextToken && nextToken.type.indexOf('meta.tag.name') == 0) {
|
||||||
|
nextTag = nextToken.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
//don't linebreak
|
||||||
|
if ( lastToken.type == 'support.php_tag' && lastToken.value == '<?=') {
|
||||||
|
dontBreak = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//lowercase
|
||||||
|
if (token.type == 'meta.tag.name') {
|
||||||
|
token.value = token.value.toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
//trim spaces
|
||||||
|
if (token.type == 'text') {
|
||||||
|
token.value = token.value.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
//skip empty tokens
|
||||||
|
if (!token.value) {
|
||||||
|
token = nextToken;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//put spaces back in
|
||||||
|
value = token.value;
|
||||||
|
for (var i in spaces) {
|
||||||
|
if (
|
||||||
|
token.type == spaces[i].type &&
|
||||||
|
(!spaces[i].value || token.value == spaces[i].value) &&
|
||||||
|
(
|
||||||
|
nextToken &&
|
||||||
|
(!spaces[i].next || spaces[i].next.test(nextToken.value))
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
if (spaces[i].prepend) {
|
||||||
|
value = ' ' + token.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (spaces[i].append) {
|
||||||
|
value += ' ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//tag name
|
||||||
|
if (token.type.indexOf('meta.tag.name') == 0) {
|
||||||
|
tag = token.value;
|
||||||
|
//console.log(tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
//new line before
|
||||||
|
breakAdded = false;
|
||||||
|
|
||||||
|
//outdent
|
||||||
|
for (i in newLines) {
|
||||||
|
if (
|
||||||
|
token.type == newLines[i].type &&
|
||||||
|
(
|
||||||
|
!newLines[i].value ||
|
||||||
|
token.value == newLines[i].value
|
||||||
|
) &&
|
||||||
|
(
|
||||||
|
!newLines[i].blockTag ||
|
||||||
|
singleTags.indexOf(nextTag) === -1
|
||||||
|
) &&
|
||||||
|
(
|
||||||
|
!newLines[i].context ||
|
||||||
|
newLines[i].context === context
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
if (newLines[i].indent === false) {
|
||||||
|
indentation--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
newLines[i].breakBefore &&
|
||||||
|
( !newLines[i].prev || newLines[i].prev.test(lastToken.value) )
|
||||||
|
) {
|
||||||
|
code += "\n";
|
||||||
|
breakAdded = true;
|
||||||
|
|
||||||
|
//indent
|
||||||
|
for (i = 0; i < indentation; i++) {
|
||||||
|
code += "\t";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dontBreak===false) {
|
||||||
|
for (i in newLines) {
|
||||||
|
if (
|
||||||
|
lastToken.type == newLines[i].type &&
|
||||||
|
(
|
||||||
|
!newLines[i].value || lastToken.value == newLines[i].value
|
||||||
|
) &&
|
||||||
|
(
|
||||||
|
!newLines[i].blockTag ||
|
||||||
|
singleTags.indexOf(tag) === -1
|
||||||
|
) &&
|
||||||
|
(
|
||||||
|
!newLines[i].context ||
|
||||||
|
newLines[i].context === context
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
if (newLines[i].indent === true) {
|
||||||
|
indentation++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!newLines[i].dontBreak && !breakAdded) {
|
||||||
|
code += "\n";
|
||||||
|
|
||||||
|
//indent
|
||||||
|
for (i = 0; i < indentation; i++) {
|
||||||
|
code += "\t";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
code += value;
|
||||||
|
|
||||||
|
//linebreaks back on after end short php tag
|
||||||
|
if ( lastToken.type == 'support.php_tag' && lastToken.value == '?>' ) {
|
||||||
|
dontBreak = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//next token
|
||||||
|
lastTag = tag;
|
||||||
|
|
||||||
|
lastToken = token;
|
||||||
|
|
||||||
|
token = nextToken;
|
||||||
|
|
||||||
|
if (token===null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return code;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
@@ -0,0 +1,980 @@
|
|||||||
|
define(function(require, exports, module) {
|
||||||
|
|
||||||
|
/* ChromeVox Ace namespace. */
|
||||||
|
var cvoxAce = {};
|
||||||
|
|
||||||
|
/* Typedefs for Closure compiler. */
|
||||||
|
/**
|
||||||
|
* @typedef {{
|
||||||
|
rate: number,
|
||||||
|
pitch: number,
|
||||||
|
volume: number,
|
||||||
|
relativePitch: number,
|
||||||
|
punctuationEcho: string
|
||||||
|
}}
|
||||||
|
*/
|
||||||
|
/* TODO(peterxiao): Export this typedef through cvox.Api. */
|
||||||
|
cvoxAce.SpeechProperty;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {{
|
||||||
|
* row: number,
|
||||||
|
* column: number
|
||||||
|
* }}
|
||||||
|
*/
|
||||||
|
cvoxAce.Cursor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {{
|
||||||
|
type: string,
|
||||||
|
value: string
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
cvoxAce.Token;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* These are errors and information that Ace will display in the gutter.
|
||||||
|
* @typedef {{
|
||||||
|
row: number,
|
||||||
|
column: number,
|
||||||
|
value: string
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
cvoxAce.Annotation;
|
||||||
|
|
||||||
|
/* Speech Properties. */
|
||||||
|
/**
|
||||||
|
* Speech property for speaking constant tokens.
|
||||||
|
* @type {cvoxAce.SpeechProperty}
|
||||||
|
*/
|
||||||
|
var CONSTANT_PROP = {
|
||||||
|
'rate': 0.8,
|
||||||
|
'pitch': 0.4,
|
||||||
|
'volume': 0.9
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default speech property for speaking tokens.
|
||||||
|
* @type {cvoxAce.SpeechProperty}
|
||||||
|
*/
|
||||||
|
var DEFAULT_PROP = {
|
||||||
|
'rate': 1,
|
||||||
|
'pitch': 0.5,
|
||||||
|
'volume': 0.9
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Speech property for speaking entity tokens.
|
||||||
|
* @type {cvoxAce.SpeechProperty}
|
||||||
|
*/
|
||||||
|
var ENTITY_PROP = {
|
||||||
|
'rate': 0.8,
|
||||||
|
'pitch': 0.8,
|
||||||
|
'volume': 0.9
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Speech property for speaking keywords.
|
||||||
|
* @type {cvoxAce.SpeechProperty}
|
||||||
|
*/
|
||||||
|
var KEYWORD_PROP = {
|
||||||
|
'rate': 0.8,
|
||||||
|
'pitch': 0.3,
|
||||||
|
'volume': 0.9
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Speech property for speaking storage tokens.
|
||||||
|
* @type {cvoxAce.SpeechProperty}
|
||||||
|
*/
|
||||||
|
var STORAGE_PROP = {
|
||||||
|
'rate': 0.8,
|
||||||
|
'pitch': 0.7,
|
||||||
|
'volume': 0.9
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Speech property for speaking variable tokens.
|
||||||
|
* @type {cvoxAce.SpeechProperty}
|
||||||
|
*/
|
||||||
|
var VARIABLE_PROP = {
|
||||||
|
'rate': 0.8,
|
||||||
|
'pitch': 0.8,
|
||||||
|
'volume': 0.9
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Speech property for speaking deleted text.
|
||||||
|
* @type {cvoxAce.SpeechProperty}
|
||||||
|
*/
|
||||||
|
var DELETED_PROP = {
|
||||||
|
'punctuationEcho': 'none',
|
||||||
|
'relativePitch': -0.6
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Constants for Earcons. */
|
||||||
|
var ERROR_EARCON = 'ALERT_NONMODAL';
|
||||||
|
var MODE_SWITCH_EARCON = 'ALERT_MODAL';
|
||||||
|
var NO_MATCH_EARCON = 'INVALID_KEYPRESS';
|
||||||
|
|
||||||
|
/* Constants for vim state. */
|
||||||
|
var INSERT_MODE_STATE = 'insertMode';
|
||||||
|
var COMMAND_MODE_STATE = 'start';
|
||||||
|
|
||||||
|
var REPLACE_LIST = [
|
||||||
|
{
|
||||||
|
substr: ';',
|
||||||
|
newSubstr: ' semicolon '
|
||||||
|
},
|
||||||
|
{
|
||||||
|
substr: ':',
|
||||||
|
newSubstr: ' colon '
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Context menu commands.
|
||||||
|
*/
|
||||||
|
var Command = {
|
||||||
|
SPEAK_ANNOT: 'annots',
|
||||||
|
SPEAK_ALL_ANNOTS: 'all_annots',
|
||||||
|
TOGGLE_LOCATION: 'toggle_location',
|
||||||
|
SPEAK_MODE: 'mode',
|
||||||
|
SPEAK_ROW_COL: 'row_col',
|
||||||
|
TOGGLE_DISPLACEMENT: 'toggle_displacement',
|
||||||
|
FOCUS_TEXT: 'focus_text'
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key prefix for each shortcut.
|
||||||
|
*/
|
||||||
|
var KEY_PREFIX = 'CONTROL + SHIFT ';
|
||||||
|
|
||||||
|
/* Globals. */
|
||||||
|
cvoxAce.editor = null;
|
||||||
|
/**
|
||||||
|
* Last cursor position.
|
||||||
|
* @type {cvoxAce.Cursor}
|
||||||
|
*/
|
||||||
|
var lastCursor = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Table of annotations.
|
||||||
|
* @typedef {!Object.<number, Object<number, cvoxAce.Annotation>>}
|
||||||
|
*/
|
||||||
|
var annotTable = {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to speak character, word, and then line. This allows blind users
|
||||||
|
* to know the location of the cursor when they change lines.
|
||||||
|
* @typedef {boolean}
|
||||||
|
*/
|
||||||
|
var shouldSpeakRowLocation = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to speak displacement.
|
||||||
|
* @typedef {boolean}
|
||||||
|
*/
|
||||||
|
var shouldSpeakDisplacement = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether text was changed to cause a cursor change event.
|
||||||
|
* @typedef {boolean}
|
||||||
|
*/
|
||||||
|
var changed = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Current state vim is in.
|
||||||
|
*/
|
||||||
|
var vimState = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mapping from key code to shortcut.
|
||||||
|
*/
|
||||||
|
var keyCodeToShortcutMap = {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mapping from command to shortcut.
|
||||||
|
*/
|
||||||
|
var cmdToShortcutMap = {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get shortcut string from keyCode.
|
||||||
|
* @param {number} keyCode Key code of shortcut.
|
||||||
|
* @return {string} String representation of shortcut.
|
||||||
|
*/
|
||||||
|
var getKeyShortcutString = function(keyCode) {
|
||||||
|
return KEY_PREFIX + String.fromCharCode(keyCode);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return if in vim mode.
|
||||||
|
* @return {boolean} True if in Vim mode.
|
||||||
|
*/
|
||||||
|
var isVimMode = function() {
|
||||||
|
var keyboardHandler = cvoxAce.editor.keyBinding.getKeyboardHandler();
|
||||||
|
return keyboardHandler.$id === 'ace/keyboard/vim';
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the current token.
|
||||||
|
* @param {!cvoxAce.Cursor} cursor Current position of the cursor.
|
||||||
|
* @return {!cvoxAce.Token} Token at the current position.
|
||||||
|
*/
|
||||||
|
var getCurrentToken = function(cursor) {
|
||||||
|
return cvoxAce.editor.getSession().getTokenAt(cursor.row, cursor.column + 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the current line the cursor is under.
|
||||||
|
* @param {!cvoxAce.Cursor} cursor Current cursor position.
|
||||||
|
*/
|
||||||
|
var getCurrentLine = function(cursor) {
|
||||||
|
return cvoxAce.editor.getSession().getLine(cursor.row);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event handler for row changes. When the user changes rows we want to speak
|
||||||
|
* the line so the user can work on this line. If shouldSpeakRowLocation is on
|
||||||
|
* then we speak the character, then the row, then the line so the user knows
|
||||||
|
* where the cursor is.
|
||||||
|
* @param {!cvoxAce.Cursor} currCursor Current cursor position.
|
||||||
|
*/
|
||||||
|
var onRowChange = function(currCursor) {
|
||||||
|
/* Notify that this line has an annotation. */
|
||||||
|
if (annotTable[currCursor.row]) {
|
||||||
|
cvox.Api.playEarcon(ERROR_EARCON);
|
||||||
|
}
|
||||||
|
if (shouldSpeakRowLocation) {
|
||||||
|
cvox.Api.stop();
|
||||||
|
speakChar(currCursor);
|
||||||
|
speakTokenQueue(getCurrentToken(currCursor));
|
||||||
|
speakLine(currCursor.row, 1);
|
||||||
|
} else {
|
||||||
|
speakLine(currCursor.row, 0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the cursor is at the beginning of a word. A word is
|
||||||
|
* a grouping of alphanumeric characters including underscores.
|
||||||
|
* @param {!cvoxAce.Cursor} cursor Current cursor position.
|
||||||
|
* @return {boolean} Whether there is word.
|
||||||
|
*/
|
||||||
|
var isWord = function(cursor) {
|
||||||
|
var line = getCurrentLine(cursor);
|
||||||
|
var lineSuffix = line.substr(cursor.column - 1);
|
||||||
|
if (cursor.column === 0) {
|
||||||
|
lineSuffix = ' ' + line;
|
||||||
|
}
|
||||||
|
/* Use regex to tell if the suffix is at the start of a new word. */
|
||||||
|
var firstWordRegExp = /^\W(\w+)/;
|
||||||
|
var words = firstWordRegExp.exec(lineSuffix);
|
||||||
|
return words !== null;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A mapping of syntax type to speech properties / expanding rules.
|
||||||
|
*/
|
||||||
|
var rules = {
|
||||||
|
'constant': {
|
||||||
|
prop: CONSTANT_PROP
|
||||||
|
},
|
||||||
|
'entity': {
|
||||||
|
prop: ENTITY_PROP
|
||||||
|
},
|
||||||
|
'keyword': {
|
||||||
|
prop: KEYWORD_PROP
|
||||||
|
},
|
||||||
|
'storage': {
|
||||||
|
prop: STORAGE_PROP
|
||||||
|
},
|
||||||
|
'variable': {
|
||||||
|
prop: VARIABLE_PROP
|
||||||
|
},
|
||||||
|
'meta': {
|
||||||
|
prop: DEFAULT_PROP,
|
||||||
|
replace: [
|
||||||
|
{
|
||||||
|
substr: '</',
|
||||||
|
newSubstr: ' closing tag '
|
||||||
|
},
|
||||||
|
{
|
||||||
|
substr: '/>',
|
||||||
|
newSubstr: ' close tag '
|
||||||
|
},
|
||||||
|
{
|
||||||
|
substr: '<',
|
||||||
|
newSubstr: ' tag start '
|
||||||
|
},
|
||||||
|
{
|
||||||
|
substr: '>',
|
||||||
|
newSubstr: ' tag end '
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default rule to be used.
|
||||||
|
*/
|
||||||
|
var DEFAULT_RULE = {
|
||||||
|
prop: DEFAULT_RULE
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expands substrings to how they are read based on the given rules.
|
||||||
|
* @param {string} value Text to be expanded.
|
||||||
|
* @param {Array.<Object>} replaceRules Rules to determine expansion.
|
||||||
|
* @return {string} New expanded value.
|
||||||
|
*/
|
||||||
|
var expand = function(value, replaceRules) {
|
||||||
|
var newValue = value;
|
||||||
|
for (var i = 0; i < replaceRules.length; i++) {
|
||||||
|
var replaceRule = replaceRules[i];
|
||||||
|
var regexp = new RegExp(replaceRule.substr, 'g');
|
||||||
|
newValue = newValue.replace(regexp, replaceRule.newSubstr);
|
||||||
|
}
|
||||||
|
return newValue;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Merges tokens from start inclusive to end exclusive.
|
||||||
|
* @param {Array.<cvoxAce.Token>} Tokens to be merged.
|
||||||
|
* @param {number} start Start index inclusive.
|
||||||
|
* @param {number} end End index exclusive.
|
||||||
|
* @return {cvoxAce.Token} Merged token.
|
||||||
|
*/
|
||||||
|
var mergeTokens = function(tokens, start, end) {
|
||||||
|
/* Different type of token found! Merge all previous like tokens. */
|
||||||
|
var newToken = {};
|
||||||
|
newToken.value = '';
|
||||||
|
newToken.type = tokens[start].type;
|
||||||
|
for (var j = start; j < end; j++) {
|
||||||
|
newToken.value += tokens[j].value;
|
||||||
|
}
|
||||||
|
return newToken;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Merges tokens that use the same speech properties.
|
||||||
|
* @param {Array.<cvoxAce.Token>} tokens Tokens to be merged.
|
||||||
|
* @return {Array.<cvoxAce.Token>} Merged tokens.
|
||||||
|
*/
|
||||||
|
var mergeLikeTokens = function(tokens) {
|
||||||
|
if (tokens.length <= 1) {
|
||||||
|
return tokens;
|
||||||
|
}
|
||||||
|
var newTokens = [];
|
||||||
|
var lastLikeIndex = 0;
|
||||||
|
for (var i = 1; i < tokens.length; i++) {
|
||||||
|
var lastLikeToken = tokens[lastLikeIndex];
|
||||||
|
var currToken = tokens[i];
|
||||||
|
if (getTokenRule(lastLikeToken) !== getTokenRule(currToken)) {
|
||||||
|
newTokens.push(mergeTokens(tokens, lastLikeIndex, i));
|
||||||
|
lastLikeIndex = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
newTokens.push(mergeTokens(tokens, lastLikeIndex, tokens.length));
|
||||||
|
return newTokens;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns if given row is a whitespace row.
|
||||||
|
* @param {number} row Row.
|
||||||
|
* @return {boolean} True if row is whitespaces.
|
||||||
|
*/
|
||||||
|
var isRowWhiteSpace = function(row) {
|
||||||
|
var line = cvoxAce.editor.getSession().getLine(row);
|
||||||
|
var whiteSpaceRegexp = /^\s*$/;
|
||||||
|
return whiteSpaceRegexp.exec(line) !== null;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Speak the line with syntax properties.
|
||||||
|
* @param {number} row Row to speak.
|
||||||
|
* @param {number} queue Queue mode to speak.
|
||||||
|
*/
|
||||||
|
var speakLine = function(row, queue) {
|
||||||
|
var tokens = cvoxAce.editor.getSession().getTokens(row);
|
||||||
|
if (tokens.length === 0 || isRowWhiteSpace(row)) {
|
||||||
|
cvox.Api.playEarcon('EDITABLE_TEXT');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tokens = mergeLikeTokens(tokens);
|
||||||
|
var firstToken = tokens[0];
|
||||||
|
/* Filter out first token. */
|
||||||
|
tokens = tokens.filter(function(token) {
|
||||||
|
return token !== firstToken;
|
||||||
|
});
|
||||||
|
/* Speak first token separately to flush if queue. */
|
||||||
|
speakToken_(firstToken, queue);
|
||||||
|
/* Speak rest of tokens. */
|
||||||
|
tokens.forEach(speakTokenQueue);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Speak the token based on the syntax of the token, flushing.
|
||||||
|
* @param {!cvoxAce.Token} token Token to speak.
|
||||||
|
* @param {number} queue Queue mode.
|
||||||
|
*/
|
||||||
|
var speakTokenFlush = function(token) {
|
||||||
|
speakToken_(token, 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Speak the token based on the syntax of the token, queueing.
|
||||||
|
* @param {!cvoxAce.Token} token Token to speak.
|
||||||
|
* @param {number} queue Queue mode.
|
||||||
|
*/
|
||||||
|
var speakTokenQueue = function(token) {
|
||||||
|
speakToken_(token, 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {!cvoxAce.Token} token Token to speak.
|
||||||
|
* Get the token speech property.
|
||||||
|
*/
|
||||||
|
var getTokenRule = function(token) {
|
||||||
|
/* Types are period delimited. In this case, we only syntax speak the outer
|
||||||
|
* most type of token. */
|
||||||
|
if (!token || !token.type) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var split = token.type.split('.');
|
||||||
|
if (split.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var type = split[0];
|
||||||
|
var rule = rules[type];
|
||||||
|
if (!rule) {
|
||||||
|
return DEFAULT_RULE;
|
||||||
|
}
|
||||||
|
return rule;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Speak the token based on the syntax of the token.
|
||||||
|
* @private
|
||||||
|
* @param {!cvoxAce.Token} token Token to speak.
|
||||||
|
* @param {number} queue Queue mode.
|
||||||
|
*/
|
||||||
|
var speakToken_ = function(token, queue) {
|
||||||
|
var rule = getTokenRule(token);
|
||||||
|
var value = expand(token.value, REPLACE_LIST);
|
||||||
|
if (rule.replace) {
|
||||||
|
value = expand(value, rule.replace);
|
||||||
|
}
|
||||||
|
cvox.Api.speak(value, queue, rule.prop);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Speaks the character under the cursor. This is queued.
|
||||||
|
* @param {!cvoxAce.Cursor} cursor Current cursor position.
|
||||||
|
* @return {string} Character.
|
||||||
|
*/
|
||||||
|
var speakChar = function(cursor) {
|
||||||
|
var line = getCurrentLine(cursor);
|
||||||
|
cvox.Api.speak(line[cursor.column], 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Speaks the jump from lastCursor to currCursor. This function assumes the
|
||||||
|
* jump takes place on the current line.
|
||||||
|
* @param {!cvoxAce.Cursor} lastCursor Previous cursor position.
|
||||||
|
* @param {!cvoxAce.Cursor} currCursor Current cursor position.
|
||||||
|
*/
|
||||||
|
var speakDisplacement = function(lastCursor, currCursor) {
|
||||||
|
var line = getCurrentLine(currCursor);
|
||||||
|
|
||||||
|
/* Get the text that we jumped past. */
|
||||||
|
var displace = line.substring(lastCursor.column, currCursor.column);
|
||||||
|
|
||||||
|
/* Speak out loud spaces. */
|
||||||
|
displace = displace.replace(/ /g, ' space ');
|
||||||
|
cvox.Api.speak(displace);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Speaks the word if the cursor jumped to a new word or to the beginning
|
||||||
|
* of the line. Otherwise speak the charactor.
|
||||||
|
* @param {!cvoxAce.Cursor} lastCursor Previous cursor position.
|
||||||
|
* @param {!cvoxAce.Cursor} currCursor Current cursor position.
|
||||||
|
*/
|
||||||
|
var speakCharOrWordOrLine = function(lastCursor, currCursor) {
|
||||||
|
/* Say word only if jump. */
|
||||||
|
if (Math.abs(lastCursor.column - currCursor.column) !== 1) {
|
||||||
|
var currLineLength = getCurrentLine(currCursor).length;
|
||||||
|
/* Speak line if jumping to beginning or end of line. */
|
||||||
|
if (currCursor.column === 0 || currCursor.column === currLineLength) {
|
||||||
|
speakLine(currCursor.row, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (isWord(currCursor)) {
|
||||||
|
cvox.Api.stop();
|
||||||
|
speakTokenQueue(getCurrentToken(currCursor));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
speakChar(currCursor);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event handler for column changes. If shouldSpeakDisplacement is on, then
|
||||||
|
* we just speak displacements in row changes. Otherwise, we either speak
|
||||||
|
* the character for single character movements, the word when jumping to the
|
||||||
|
* next word, or the entire line if jumping to beginning or end of the line.
|
||||||
|
* @param {!cvoxAce.Cursor} lastCursor Previous cursor position.
|
||||||
|
* @param {!cvoxAce.Cursor} currCursor Current cursor position.
|
||||||
|
*/
|
||||||
|
var onColumnChange = function(lastCursor, currCursor) {
|
||||||
|
if (!cvoxAce.editor.selection.isEmpty()) {
|
||||||
|
speakDisplacement(lastCursor, currCursor);
|
||||||
|
cvox.Api.speak('selected', 1);
|
||||||
|
}
|
||||||
|
else if (shouldSpeakDisplacement) {
|
||||||
|
speakDisplacement(lastCursor, currCursor);
|
||||||
|
} else {
|
||||||
|
speakCharOrWordOrLine(lastCursor, currCursor);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event handler for cursor changes. Classify cursor changes as either row or
|
||||||
|
* column changes, then delegate accordingly.
|
||||||
|
* @param {!Event} evt The event.
|
||||||
|
*/
|
||||||
|
var onCursorChange = function(evt) {
|
||||||
|
/* Do not speak if cursor change was a result of text insertion. We want to
|
||||||
|
* speak the text that was inserted and not where the cursor lands. */
|
||||||
|
if (changed) {
|
||||||
|
changed = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var currCursor = cvoxAce.editor.selection.getCursor();
|
||||||
|
if (currCursor.row !== lastCursor.row) {
|
||||||
|
onRowChange(currCursor);
|
||||||
|
} else {
|
||||||
|
onColumnChange(lastCursor, currCursor);
|
||||||
|
}
|
||||||
|
lastCursor = currCursor;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event handler for selection changes.
|
||||||
|
* @param {!Event} evt The event.
|
||||||
|
*/
|
||||||
|
var onSelectionChange = function(evt) {
|
||||||
|
/* Assumes that when selection changes to empty, the user has unselected. */
|
||||||
|
if (cvoxAce.editor.selection.isEmpty()) {
|
||||||
|
cvox.Api.speak('unselected');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event handler for source changes. We want auditory feedback for inserting
|
||||||
|
* and deleting text.
|
||||||
|
* @param {!Event} evt The event.
|
||||||
|
*/
|
||||||
|
var onChange = function(evt) {
|
||||||
|
var data = evt.data;
|
||||||
|
switch (data.action) {
|
||||||
|
case 'removeText':
|
||||||
|
cvox.Api.speak(data.text, 0, DELETED_PROP);
|
||||||
|
/* Let the future cursor change event know it's from text change. */
|
||||||
|
changed = true;
|
||||||
|
break;
|
||||||
|
case 'insertText':
|
||||||
|
cvox.Api.speak(data.text, 0);
|
||||||
|
/* Let the future cursor change event know it's from text change. */
|
||||||
|
changed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether or not the annotation is new.
|
||||||
|
* @param {!cvoxAce.Annotation} annot Annotation in question.
|
||||||
|
* @return {boolean} Whether annot is new.
|
||||||
|
*/
|
||||||
|
var isNewAnnotation = function(annot) {
|
||||||
|
var row = annot.row;
|
||||||
|
var col = annot.column;
|
||||||
|
return !annotTable[row] || !annotTable[row][col];
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Populates the annotation table.
|
||||||
|
* @param {!Array.<cvoxAce.Annotation>} annotations Array of annotations.
|
||||||
|
*/
|
||||||
|
var populateAnnotations = function(annotations) {
|
||||||
|
annotTable = {};
|
||||||
|
for (var i = 0; i < annotations.length; i++) {
|
||||||
|
var annotation = annotations[i];
|
||||||
|
var row = annotation.row;
|
||||||
|
var col = annotation.column;
|
||||||
|
if (!annotTable[row]) {
|
||||||
|
annotTable[row] = {};
|
||||||
|
}
|
||||||
|
annotTable[row][col] = annotation;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event handler for annotation changes. We want to notify the user when an
|
||||||
|
* a new annotation appears.
|
||||||
|
* @param {!Event} evt Event.
|
||||||
|
*/
|
||||||
|
var onAnnotationChange = function(evt) {
|
||||||
|
var annotations = cvoxAce.editor.getSession().getAnnotations();
|
||||||
|
var newAnnotations = annotations.filter(isNewAnnotation);
|
||||||
|
if (newAnnotations.length > 0) {
|
||||||
|
cvox.Api.playEarcon(ERROR_EARCON);
|
||||||
|
}
|
||||||
|
populateAnnotations(annotations);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Speak annotation.
|
||||||
|
* @param {!cvoxAce.Annotation} annot Annotation to speak.
|
||||||
|
*/
|
||||||
|
var speakAnnot = function(annot) {
|
||||||
|
var annotText = annot.type + ' ' + annot.text + ' on ' +
|
||||||
|
rowColToString(annot.row, annot.column);
|
||||||
|
annotText = annotText.replace(';', 'semicolon');
|
||||||
|
cvox.Api.speak(annotText, 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Speak annotations in a row.
|
||||||
|
* @param {number} row Row of annotations to speak.
|
||||||
|
*/
|
||||||
|
var speakAnnotsByRow = function(row) {
|
||||||
|
var annots = annotTable[row];
|
||||||
|
for (var col in annots) {
|
||||||
|
speakAnnot(annots[col]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a string representation of a row and column.
|
||||||
|
* @param {boolean} row Zero indexed row.
|
||||||
|
* @param {boolean} col Zero indexed column.
|
||||||
|
* @return {string} Row and column to be spoken.
|
||||||
|
*/
|
||||||
|
var rowColToString = function(row, col) {
|
||||||
|
return 'row ' + (row + 1) + ' column ' + (col + 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Speaks the row and column.
|
||||||
|
*/
|
||||||
|
var speakCurrRowAndCol = function() {
|
||||||
|
cvox.Api.speak(rowColToString(lastCursor.row, lastCursor.column));
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Speaks all annotations.
|
||||||
|
*/
|
||||||
|
var speakAllAnnots = function() {
|
||||||
|
for (var row in annotTable) {
|
||||||
|
speakAnnotsByRow(row);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Speak the vim mode. If no vim mode, this function does nothing.
|
||||||
|
*/
|
||||||
|
var speakMode = function() {
|
||||||
|
if (!isVimMode()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch (cvoxAce.editor.keyBinding.$data.state) {
|
||||||
|
case INSERT_MODE_STATE:
|
||||||
|
cvox.Api.speak('Insert mode');
|
||||||
|
break;
|
||||||
|
case COMMAND_MODE_STATE:
|
||||||
|
cvox.Api.speak('Command mode');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggle speak location.
|
||||||
|
*/
|
||||||
|
var toggleSpeakRowLocation = function() {
|
||||||
|
shouldSpeakRowLocation = !shouldSpeakRowLocation;
|
||||||
|
/* Auditory feedback of the change. */
|
||||||
|
if (shouldSpeakRowLocation) {
|
||||||
|
cvox.Api.speak('Speak location on row change enabled.');
|
||||||
|
} else {
|
||||||
|
cvox.Api.speak('Speak location on row change disabled.');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggle speak displacement.
|
||||||
|
*/
|
||||||
|
var toggleSpeakDisplacement = function() {
|
||||||
|
shouldSpeakDisplacement = !shouldSpeakDisplacement;
|
||||||
|
/* Auditory feedback of the change. */
|
||||||
|
if (shouldSpeakDisplacement) {
|
||||||
|
cvox.Api.speak('Speak displacement on column changes.');
|
||||||
|
} else {
|
||||||
|
cvox.Api.speak('Speak current character or word on column changes.');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event handler for key down events. Gets the right shortcut from the map,
|
||||||
|
* and calls the associated function.
|
||||||
|
* @param {!Event} evt Keyboard event.
|
||||||
|
*/
|
||||||
|
var onKeyDown = function(evt) {
|
||||||
|
if (evt.ctrlKey && evt.shiftKey) {
|
||||||
|
var shortcut = keyCodeToShortcutMap[evt.keyCode];
|
||||||
|
if (shortcut) {
|
||||||
|
shortcut.func();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event handler for status change events. Auditory feedback of changing
|
||||||
|
* between vim states.
|
||||||
|
* @param {!Event} evt Change status event.
|
||||||
|
* @param {!Object} editor Editor state.
|
||||||
|
*/
|
||||||
|
var onChangeStatus = function(evt, editor) {
|
||||||
|
if (!isVimMode()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var state = editor.keyBinding.$data.state;
|
||||||
|
if (state === vimState) {
|
||||||
|
/* State hasn't changed, do nothing. */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch (state) {
|
||||||
|
case INSERT_MODE_STATE:
|
||||||
|
cvox.Api.playEarcon(MODE_SWITCH_EARCON);
|
||||||
|
/* When in insert mode, we want to speak out keys as feedback. */
|
||||||
|
cvox.Api.setKeyEcho(true);
|
||||||
|
break;
|
||||||
|
case COMMAND_MODE_STATE:
|
||||||
|
cvox.Api.playEarcon(MODE_SWITCH_EARCON);
|
||||||
|
/* When in command mode, we want don't speak out keys because those keys
|
||||||
|
* are not being inserted in the document. */
|
||||||
|
cvox.Api.setKeyEcho(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
vimState = state;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles context menu events. This is a ChromeVox feature where hitting
|
||||||
|
* the shortcut ChromeVox + comma will open up a search bar where you can
|
||||||
|
* type in various commands. All keyboard shortcuts are also commands that
|
||||||
|
* can be invoked. This handles the event that ChromeVox sends to the page.
|
||||||
|
* @param {Event} evt Event received.
|
||||||
|
*/
|
||||||
|
var contextMenuHandler = function(evt) {
|
||||||
|
var cmd = evt.detail['customCommand'];
|
||||||
|
var shortcut = cmdToShortcutMap[cmd];
|
||||||
|
if (shortcut) {
|
||||||
|
shortcut.func();
|
||||||
|
/* ChromeVox will bring focus to an element near the cursor instead of the
|
||||||
|
* text input. */
|
||||||
|
cvoxAce.editor.focus();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the ChromeVox context menu.
|
||||||
|
*/
|
||||||
|
var initContextMenu = function() {
|
||||||
|
var ACTIONS = SHORTCUTS.map(function(shortcut) {
|
||||||
|
return {
|
||||||
|
desc: shortcut.desc + getKeyShortcutString(shortcut.keyCode),
|
||||||
|
cmd: shortcut.cmd
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
/* Attach ContextMenuActions. */
|
||||||
|
var body = document.querySelector('body');
|
||||||
|
body.setAttribute('contextMenuActions', JSON.stringify(ACTIONS));
|
||||||
|
|
||||||
|
/* Listen for ContextMenu events. */
|
||||||
|
body.addEventListener('ATCustomEvent', contextMenuHandler, true);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event handler for find events. When there is a match, we want to speak the
|
||||||
|
* line we are now at. Otherwise, we want to notify the user there was no
|
||||||
|
* match
|
||||||
|
* @param {!Event} evt The event.
|
||||||
|
*/
|
||||||
|
var onFindSearchbox = function(evt) {
|
||||||
|
if (evt.match) {
|
||||||
|
/* There is still a match! Speak the line. */
|
||||||
|
speakLine(lastCursor.row, 0);
|
||||||
|
} else {
|
||||||
|
/* No match, give auditory feedback! */
|
||||||
|
cvox.Api.playEarcon(NO_MATCH_EARCON);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Focus to text input.
|
||||||
|
*/
|
||||||
|
var focus = function() {
|
||||||
|
cvoxAce.editor.focus();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shortcut definitions.
|
||||||
|
*/
|
||||||
|
var SHORTCUTS = [
|
||||||
|
{
|
||||||
|
/* 1 key. */
|
||||||
|
keyCode: 49,
|
||||||
|
func: function() {
|
||||||
|
speakAnnotsByRow(lastCursor.row);
|
||||||
|
},
|
||||||
|
cmd: Command.SPEAK_ANNOT,
|
||||||
|
desc: 'Speak annotations on line'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/* 2 key. */
|
||||||
|
keyCode: 50,
|
||||||
|
func: speakAllAnnots,
|
||||||
|
cmd: Command.SPEAK_ALL_ANNOTS,
|
||||||
|
desc: 'Speak all annotations'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/* 3 key. */
|
||||||
|
keyCode: 51,
|
||||||
|
func: speakMode,
|
||||||
|
cmd: Command.SPEAK_MODE,
|
||||||
|
desc: 'Speak Vim mode'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/* 4 key. */
|
||||||
|
keyCode: 52,
|
||||||
|
func: toggleSpeakRowLocation,
|
||||||
|
cmd: Command.TOGGLE_LOCATION,
|
||||||
|
desc: 'Toggle speak row location'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/* 5 key. */
|
||||||
|
keyCode: 53,
|
||||||
|
func: speakCurrRowAndCol,
|
||||||
|
cmd: Command.SPEAK_ROW_COL,
|
||||||
|
desc: 'Speak row and column'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/* 6 key. */
|
||||||
|
keyCode: 54,
|
||||||
|
func: toggleSpeakDisplacement,
|
||||||
|
cmd: Command.TOGGLE_DISPLACEMENT,
|
||||||
|
desc: 'Toggle speak displacement'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/* 7 key. */
|
||||||
|
keyCode: 55,
|
||||||
|
func: focus,
|
||||||
|
cmd: Command.FOCUS_TEXT,
|
||||||
|
desc: 'Focus text'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event handler for focus events.
|
||||||
|
*/
|
||||||
|
var onFocus = function() {
|
||||||
|
cvoxAce.editor = editor;
|
||||||
|
|
||||||
|
/* Set up listeners. */
|
||||||
|
editor.getSession().selection.on('changeCursor', onCursorChange);
|
||||||
|
editor.getSession().selection.on('changeSelection', onSelectionChange);
|
||||||
|
editor.getSession().on('change', onChange);
|
||||||
|
editor.getSession().on('changeAnnotation', onAnnotationChange);
|
||||||
|
editor.on('changeStatus', onChangeStatus);
|
||||||
|
editor.on('findSearchBox', onFindSearchbox);
|
||||||
|
editor.container.addEventListener('keydown', onKeyDown);
|
||||||
|
|
||||||
|
lastCursor = editor.selection.getCursor();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the theme.
|
||||||
|
* @param {Object} editor Editor to use.
|
||||||
|
*/
|
||||||
|
var init = function(editor) {
|
||||||
|
onFocus();
|
||||||
|
|
||||||
|
/* Construct maps. */
|
||||||
|
SHORTCUTS.forEach(function(shortcut) {
|
||||||
|
keyCodeToShortcutMap[shortcut.keyCode] = shortcut;
|
||||||
|
cmdToShortcutMap[shortcut.cmd] = shortcut;
|
||||||
|
});
|
||||||
|
|
||||||
|
editor.on('focus', onFocus);
|
||||||
|
|
||||||
|
/* Assume we start in command mode if vim. */
|
||||||
|
if (isVimMode()) {
|
||||||
|
cvox.Api.setKeyEcho(false);
|
||||||
|
}
|
||||||
|
initContextMenu();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns if cvox exists, and the api exists.
|
||||||
|
* @return {boolean} Whether not Cvox Api exists.
|
||||||
|
*/
|
||||||
|
function cvoxApiExists() {
|
||||||
|
return (typeof(cvox) !== 'undefined') && cvox && cvox.Api;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of tries for Cvox loading.
|
||||||
|
* @type {number}
|
||||||
|
*/
|
||||||
|
var tries = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Max number of tries to watch for Cvox loading.
|
||||||
|
* @type {number}
|
||||||
|
*/
|
||||||
|
var MAX_TRIES = 15;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check for ChromeVox load.
|
||||||
|
* @param {Object} editor Editor to use.
|
||||||
|
*/
|
||||||
|
function watchForCvoxLoad(editor) {
|
||||||
|
if (cvoxApiExists()) {
|
||||||
|
init(editor);
|
||||||
|
} else {
|
||||||
|
tries++;
|
||||||
|
if (tries >= MAX_TRIES) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
window.setTimeout(watchForCvoxLoad, 500, editor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var Editor = require('../editor').Editor;
|
||||||
|
require('../config').defineOptions(Editor.prototype, 'editor', {
|
||||||
|
enableChromevoxEnhancements: {
|
||||||
|
set: function(val) {
|
||||||
|
if (val) {
|
||||||
|
watchForCvoxLoad(this);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
value: true // turn it on by default or check for window.cvox
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
@@ -0,0 +1,319 @@
|
|||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Distributed under the BSD license:
|
||||||
|
*
|
||||||
|
* Copyright (c) 2012, Ajax.org B.V.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of Ajax.org B.V. nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
define(function(require, exports, module) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var ElasticTabstopsLite = function(editor) {
|
||||||
|
this.$editor = editor;
|
||||||
|
var self = this;
|
||||||
|
var changedRows = [];
|
||||||
|
var recordChanges = false;
|
||||||
|
this.onAfterExec = function() {
|
||||||
|
recordChanges = false;
|
||||||
|
self.processRows(changedRows);
|
||||||
|
changedRows = [];
|
||||||
|
};
|
||||||
|
this.onExec = function() {
|
||||||
|
recordChanges = true;
|
||||||
|
};
|
||||||
|
this.onChange = function(e) {
|
||||||
|
var range = e.data.range
|
||||||
|
if (recordChanges) {
|
||||||
|
if (changedRows.indexOf(range.start.row) == -1)
|
||||||
|
changedRows.push(range.start.row);
|
||||||
|
if (range.end.row != range.start.row)
|
||||||
|
changedRows.push(range.end.row);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
this.processRows = function(rows) {
|
||||||
|
this.$inChange = true;
|
||||||
|
var checkedRows = [];
|
||||||
|
|
||||||
|
for (var r = 0, rowCount = rows.length; r < rowCount; r++) {
|
||||||
|
var row = rows[r];
|
||||||
|
|
||||||
|
if (checkedRows.indexOf(row) > -1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var cellWidthObj = this.$findCellWidthsForBlock(row);
|
||||||
|
var cellWidths = this.$setBlockCellWidthsToMax(cellWidthObj.cellWidths);
|
||||||
|
var rowIndex = cellWidthObj.firstRow;
|
||||||
|
|
||||||
|
for (var w = 0, l = cellWidths.length; w < l; w++) {
|
||||||
|
var widths = cellWidths[w];
|
||||||
|
checkedRows.push(rowIndex);
|
||||||
|
this.$adjustRow(rowIndex, widths);
|
||||||
|
rowIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.$inChange = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.$findCellWidthsForBlock = function(row) {
|
||||||
|
var cellWidths = [], widths;
|
||||||
|
|
||||||
|
// starting row and backward
|
||||||
|
var rowIter = row;
|
||||||
|
while (rowIter >= 0) {
|
||||||
|
widths = this.$cellWidthsForRow(rowIter);
|
||||||
|
if (widths.length == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
cellWidths.unshift(widths);
|
||||||
|
rowIter--;
|
||||||
|
}
|
||||||
|
var firstRow = rowIter + 1;
|
||||||
|
|
||||||
|
// forward (not including starting row)
|
||||||
|
rowIter = row;
|
||||||
|
var numRows = this.$editor.session.getLength();
|
||||||
|
|
||||||
|
while (rowIter < numRows - 1) {
|
||||||
|
rowIter++;
|
||||||
|
|
||||||
|
widths = this.$cellWidthsForRow(rowIter);
|
||||||
|
if (widths.length == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
cellWidths.push(widths);
|
||||||
|
}
|
||||||
|
|
||||||
|
return { cellWidths: cellWidths, firstRow: firstRow };
|
||||||
|
};
|
||||||
|
|
||||||
|
this.$cellWidthsForRow = function(row) {
|
||||||
|
var selectionColumns = this.$selectionColumnsForRow(row);
|
||||||
|
// todo: support multicursor
|
||||||
|
|
||||||
|
var tabs = [-1].concat(this.$tabsForRow(row));
|
||||||
|
var widths = tabs.map(function(el) { return 0; } ).slice(1);
|
||||||
|
var line = this.$editor.session.getLine(row);
|
||||||
|
|
||||||
|
for (var i = 0, len = tabs.length - 1; i < len; i++) {
|
||||||
|
var leftEdge = tabs[i]+1;
|
||||||
|
var rightEdge = tabs[i+1];
|
||||||
|
|
||||||
|
var rightmostSelection = this.$rightmostSelectionInCell(selectionColumns, rightEdge);
|
||||||
|
var cell = line.substring(leftEdge, rightEdge);
|
||||||
|
widths[i] = Math.max(cell.replace(/\s+$/g,'').length, rightmostSelection - leftEdge);
|
||||||
|
}
|
||||||
|
|
||||||
|
return widths;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.$selectionColumnsForRow = function(row) {
|
||||||
|
var selections = [], cursor = this.$editor.getCursorPosition();
|
||||||
|
if (this.$editor.session.getSelection().isEmpty()) {
|
||||||
|
// todo: support multicursor
|
||||||
|
if (row == cursor.row)
|
||||||
|
selections.push(cursor.column);
|
||||||
|
}
|
||||||
|
|
||||||
|
return selections;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.$setBlockCellWidthsToMax = function(cellWidths) {
|
||||||
|
var startingNewBlock = true, blockStartRow, blockEndRow, maxWidth;
|
||||||
|
var columnInfo = this.$izip_longest(cellWidths);
|
||||||
|
|
||||||
|
for (var c = 0, l = columnInfo.length; c < l; c++) {
|
||||||
|
var column = columnInfo[c];
|
||||||
|
if (!column.push) {
|
||||||
|
console.error(column);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// add an extra None to the end so that the end of the column automatically
|
||||||
|
// finishes a block
|
||||||
|
column.push(NaN);
|
||||||
|
|
||||||
|
for (var r = 0, s = column.length; r < s; r++) {
|
||||||
|
var width = column[r];
|
||||||
|
if (startingNewBlock) {
|
||||||
|
blockStartRow = r;
|
||||||
|
maxWidth = 0;
|
||||||
|
startingNewBlock = false;
|
||||||
|
}
|
||||||
|
if (isNaN(width)) {
|
||||||
|
// block ended
|
||||||
|
blockEndRow = r;
|
||||||
|
|
||||||
|
for (var j = blockStartRow; j < blockEndRow; j++) {
|
||||||
|
cellWidths[j][c] = maxWidth;
|
||||||
|
}
|
||||||
|
startingNewBlock = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
maxWidth = Math.max(maxWidth, width);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return cellWidths;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.$rightmostSelectionInCell = function(selectionColumns, cellRightEdge) {
|
||||||
|
var rightmost = 0;
|
||||||
|
|
||||||
|
if (selectionColumns.length) {
|
||||||
|
var lengths = [];
|
||||||
|
for (var s = 0, length = selectionColumns.length; s < length; s++) {
|
||||||
|
if (selectionColumns[s] <= cellRightEdge)
|
||||||
|
lengths.push(s);
|
||||||
|
else
|
||||||
|
lengths.push(0);
|
||||||
|
}
|
||||||
|
rightmost = Math.max.apply(Math, lengths);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rightmost;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.$tabsForRow = function(row) {
|
||||||
|
var rowTabs = [], line = this.$editor.session.getLine(row),
|
||||||
|
re = /\t/g, match;
|
||||||
|
|
||||||
|
while ((match = re.exec(line)) != null) {
|
||||||
|
rowTabs.push(match.index);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rowTabs;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.$adjustRow = function(row, widths) {
|
||||||
|
var rowTabs = this.$tabsForRow(row);
|
||||||
|
|
||||||
|
if (rowTabs.length == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var bias = 0, location = -1;
|
||||||
|
|
||||||
|
// this always only contains two elements, so we're safe in the loop below
|
||||||
|
var expandedSet = this.$izip(widths, rowTabs);
|
||||||
|
|
||||||
|
for (var i = 0, l = expandedSet.length; i < l; i++) {
|
||||||
|
var w = expandedSet[i][0], it = expandedSet[i][1];
|
||||||
|
location += 1 + w;
|
||||||
|
it += bias;
|
||||||
|
var difference = location - it;
|
||||||
|
|
||||||
|
if (difference == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var partialLine = this.$editor.session.getLine(row).substr(0, it );
|
||||||
|
var strippedPartialLine = partialLine.replace(/\s*$/g, "");
|
||||||
|
var ispaces = partialLine.length - strippedPartialLine.length;
|
||||||
|
|
||||||
|
if (difference > 0) {
|
||||||
|
// put the spaces after the tab and then delete the tab, so any insertion
|
||||||
|
// points behave as expected
|
||||||
|
this.$editor.session.getDocument().insertInLine({row: row, column: it + 1}, Array(difference + 1).join(" ") + "\t");
|
||||||
|
this.$editor.session.getDocument().removeInLine(row, it, it + 1);
|
||||||
|
|
||||||
|
bias += difference;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (difference < 0 && ispaces >= -difference) {
|
||||||
|
this.$editor.session.getDocument().removeInLine(row, it + difference, it);
|
||||||
|
bias += difference;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// the is a (naive) Python port--but works for these purposes
|
||||||
|
this.$izip_longest = function(iterables) {
|
||||||
|
if (!iterables[0])
|
||||||
|
return [];
|
||||||
|
var longest = iterables[0].length;
|
||||||
|
var iterablesLength = iterables.length;
|
||||||
|
|
||||||
|
for (var i = 1; i < iterablesLength; i++) {
|
||||||
|
var iLength = iterables[i].length;
|
||||||
|
if (iLength > longest)
|
||||||
|
longest = iLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
var expandedSet = [];
|
||||||
|
|
||||||
|
for (var l = 0; l < longest; l++) {
|
||||||
|
var set = [];
|
||||||
|
for (var i = 0; i < iterablesLength; i++) {
|
||||||
|
if (iterables[i][l] === "")
|
||||||
|
set.push(NaN);
|
||||||
|
else
|
||||||
|
set.push(iterables[i][l]);
|
||||||
|
}
|
||||||
|
|
||||||
|
expandedSet.push(set);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return expandedSet;
|
||||||
|
};
|
||||||
|
|
||||||
|
// an even more (naive) Python port
|
||||||
|
this.$izip = function(widths, tabs) {
|
||||||
|
// grab the shorter size
|
||||||
|
var size = widths.length >= tabs.length ? tabs.length : widths.length;
|
||||||
|
|
||||||
|
var expandedSet = [];
|
||||||
|
for (var i = 0; i < size; i++) {
|
||||||
|
var set = [ widths[i], tabs[i] ];
|
||||||
|
expandedSet.push(set);
|
||||||
|
}
|
||||||
|
return expandedSet;
|
||||||
|
};
|
||||||
|
|
||||||
|
}).call(ElasticTabstopsLite.prototype);
|
||||||
|
|
||||||
|
exports.ElasticTabstopsLite = ElasticTabstopsLite;
|
||||||
|
|
||||||
|
var Editor = require("../editor").Editor;
|
||||||
|
require("../config").defineOptions(Editor.prototype, "editor", {
|
||||||
|
useElasticTabstops: {
|
||||||
|
set: function(val) {
|
||||||
|
if (val) {
|
||||||
|
if (!this.elasticTabstops)
|
||||||
|
this.elasticTabstops = new ElasticTabstopsLite(this);
|
||||||
|
this.commands.on("afterExec", this.elasticTabstops.onAfterExec);
|
||||||
|
this.commands.on("exec", this.elasticTabstops.onExec);
|
||||||
|
this.on("change", this.elasticTabstops.onChange);
|
||||||
|
} else if (this.elasticTabstops) {
|
||||||
|
this.commands.removeListener("afterExec", this.elasticTabstops.onAfterExec);
|
||||||
|
this.commands.removeListener("exec", this.elasticTabstops.onExec);
|
||||||
|
this.removeListener("change", this.elasticTabstops.onChange);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
@@ -0,0 +1,434 @@
|
|||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Distributed under the BSD license:
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010, Ajax.org B.V.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of Ajax.org B.V. nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
define(function(require, exports, module) {
|
||||||
|
"use strict";
|
||||||
|
var HashHandler = require("ace/keyboard/hash_handler").HashHandler;
|
||||||
|
var Editor = require("ace/editor").Editor;
|
||||||
|
var snippetManager = require("ace/snippets").snippetManager;
|
||||||
|
var Range = require("ace/range").Range;
|
||||||
|
var emmet, emmetPath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of {@link IEmmetEditor} interface for Ace
|
||||||
|
*/
|
||||||
|
function AceEmmetEditor() {}
|
||||||
|
|
||||||
|
AceEmmetEditor.prototype = {
|
||||||
|
setupContext: function(editor) {
|
||||||
|
this.ace = editor;
|
||||||
|
this.indentation = editor.session.getTabString();
|
||||||
|
if (!emmet)
|
||||||
|
emmet = window.emmet;
|
||||||
|
emmet.require("resources").setVariable("indentation", this.indentation);
|
||||||
|
this.$syntax = null;
|
||||||
|
this.$syntax = this.getSyntax();
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Returns character indexes of selected text: object with <code>start</code>
|
||||||
|
* and <code>end</code> properties. If there's no selection, should return
|
||||||
|
* object with <code>start</code> and <code>end</code> properties referring
|
||||||
|
* to current caret position
|
||||||
|
* @return {Object}
|
||||||
|
* @example
|
||||||
|
* var selection = editor.getSelectionRange();
|
||||||
|
* alert(selection.start + ', ' + selection.end);
|
||||||
|
*/
|
||||||
|
getSelectionRange: function() {
|
||||||
|
// TODO should start be caret position instead?
|
||||||
|
var range = this.ace.getSelectionRange();
|
||||||
|
var doc = this.ace.session.doc;
|
||||||
|
return {
|
||||||
|
start: doc.positionToIndex(range.start),
|
||||||
|
end: doc.positionToIndex(range.end)
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates selection from <code>start</code> to <code>end</code> character
|
||||||
|
* indexes. If <code>end</code> is ommited, this method should place caret
|
||||||
|
* and <code>start</code> index
|
||||||
|
* @param {Number} start
|
||||||
|
* @param {Number} [end]
|
||||||
|
* @example
|
||||||
|
* editor.createSelection(10, 40);
|
||||||
|
*
|
||||||
|
* //move caret to 15th character
|
||||||
|
* editor.createSelection(15);
|
||||||
|
*/
|
||||||
|
createSelection: function(start, end) {
|
||||||
|
var doc = this.ace.session.doc;
|
||||||
|
this.ace.selection.setRange({
|
||||||
|
start: doc.indexToPosition(start),
|
||||||
|
end: doc.indexToPosition(end)
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns current line's start and end indexes as object with <code>start</code>
|
||||||
|
* and <code>end</code> properties
|
||||||
|
* @return {Object}
|
||||||
|
* @example
|
||||||
|
* var range = editor.getCurrentLineRange();
|
||||||
|
* alert(range.start + ', ' + range.end);
|
||||||
|
*/
|
||||||
|
getCurrentLineRange: function() {
|
||||||
|
var ace = this.ace;
|
||||||
|
var row = ace.getCursorPosition().row;
|
||||||
|
var lineLength = ace.session.getLine(row).length;
|
||||||
|
var index = ace.session.doc.positionToIndex({row: row, column: 0});
|
||||||
|
return {
|
||||||
|
start: index,
|
||||||
|
end: index + lineLength
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns current caret position
|
||||||
|
* @return {Number|null}
|
||||||
|
*/
|
||||||
|
getCaretPos: function(){
|
||||||
|
var pos = this.ace.getCursorPosition();
|
||||||
|
return this.ace.session.doc.positionToIndex(pos);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set new caret position
|
||||||
|
* @param {Number} index Caret position
|
||||||
|
*/
|
||||||
|
setCaretPos: function(index){
|
||||||
|
var pos = this.ace.session.doc.indexToPosition(index);
|
||||||
|
this.ace.selection.moveToPosition(pos);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns content of current line
|
||||||
|
* @return {String}
|
||||||
|
*/
|
||||||
|
getCurrentLine: function() {
|
||||||
|
var row = this.ace.getCursorPosition().row;
|
||||||
|
return this.ace.session.getLine(row);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replace editor's content or it's part (from <code>start</code> to
|
||||||
|
* <code>end</code> index). If <code>value</code> contains
|
||||||
|
* <code>caret_placeholder</code>, the editor will put caret into
|
||||||
|
* this position. If you skip <code>start</code> and <code>end</code>
|
||||||
|
* arguments, the whole target's content will be replaced with
|
||||||
|
* <code>value</code>.
|
||||||
|
*
|
||||||
|
* If you pass <code>start</code> argument only,
|
||||||
|
* the <code>value</code> will be placed at <code>start</code> string
|
||||||
|
* index of current content.
|
||||||
|
*
|
||||||
|
* If you pass <code>start</code> and <code>end</code> arguments,
|
||||||
|
* the corresponding substring of current target's content will be
|
||||||
|
* replaced with <code>value</code>.
|
||||||
|
* @param {String} value Content you want to paste
|
||||||
|
* @param {Number} [start] Start index of editor's content
|
||||||
|
* @param {Number} [end] End index of editor's content
|
||||||
|
* @param {Boolean} [noIndent] Do not auto indent <code>value</code>
|
||||||
|
*/
|
||||||
|
replaceContent: function(value, start, end, noIndent) {
|
||||||
|
if (end == null)
|
||||||
|
end = start == null ? this.getContent().length : start;
|
||||||
|
if (start == null)
|
||||||
|
start = 0;
|
||||||
|
|
||||||
|
var editor = this.ace;
|
||||||
|
var doc = editor.session.doc;
|
||||||
|
var range = Range.fromPoints(doc.indexToPosition(start), doc.indexToPosition(end));
|
||||||
|
editor.session.remove(range);
|
||||||
|
|
||||||
|
range.end = range.start;
|
||||||
|
//editor.selection.setRange(range);
|
||||||
|
|
||||||
|
value = this.$updateTabstops(value);
|
||||||
|
snippetManager.insertSnippet(editor, value);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns editor's content
|
||||||
|
* @return {String}
|
||||||
|
*/
|
||||||
|
getContent: function(){
|
||||||
|
return this.ace.getValue();
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns current editor's syntax mode
|
||||||
|
* @return {String}
|
||||||
|
*/
|
||||||
|
getSyntax: function() {
|
||||||
|
if (this.$syntax)
|
||||||
|
return this.$syntax;
|
||||||
|
var syntax = this.ace.session.$modeId.split("/").pop();
|
||||||
|
if (syntax == "html" || syntax == "php") {
|
||||||
|
var cursor = this.ace.getCursorPosition();
|
||||||
|
var state = this.ace.session.getState(cursor.row);
|
||||||
|
if (typeof state != "string")
|
||||||
|
state = state[0];
|
||||||
|
if (state) {
|
||||||
|
state = state.split("-");
|
||||||
|
if (state.length > 1)
|
||||||
|
syntax = state[0];
|
||||||
|
else if (syntax == "php")
|
||||||
|
syntax = "html";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return syntax;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns current output profile name (@see emmet#setupProfile)
|
||||||
|
* @return {String}
|
||||||
|
*/
|
||||||
|
getProfileName: function() {
|
||||||
|
switch(this.getSyntax()) {
|
||||||
|
case "css": return "css";
|
||||||
|
case "xml":
|
||||||
|
case "xsl":
|
||||||
|
return "xml";
|
||||||
|
case "html":
|
||||||
|
var profile = emmet.require("resources").getVariable("profile");
|
||||||
|
// no forced profile, guess from content html or xhtml?
|
||||||
|
if (!profile)
|
||||||
|
profile = this.ace.session.getLines(0,2).join("").search(/<!DOCTYPE[^>]+XHTML/i) != -1 ? "xhtml": "html";
|
||||||
|
return profile;
|
||||||
|
}
|
||||||
|
return "xhtml";
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ask user to enter something
|
||||||
|
* @param {String} title Dialog title
|
||||||
|
* @return {String} Entered data
|
||||||
|
* @since 0.65
|
||||||
|
*/
|
||||||
|
prompt: function(title) {
|
||||||
|
return prompt(title);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns current selection
|
||||||
|
* @return {String}
|
||||||
|
* @since 0.65
|
||||||
|
*/
|
||||||
|
getSelection: function() {
|
||||||
|
return this.ace.session.getTextRange();
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns current editor's file path
|
||||||
|
* @return {String}
|
||||||
|
* @since 0.65
|
||||||
|
*/
|
||||||
|
getFilePath: function() {
|
||||||
|
return "";
|
||||||
|
},
|
||||||
|
|
||||||
|
// update tabstops: make sure all caret placeholders are unique
|
||||||
|
// by default, abbreviation parser generates all unlinked (un-mirrored)
|
||||||
|
// tabstops as ${0}, so we have upgrade all caret tabstops with unique
|
||||||
|
// positions but make sure that all other tabstops are not linked accidentally
|
||||||
|
// based on https://github.com/sergeche/emmet-sublime/blob/master/editor.js#L119-L171
|
||||||
|
$updateTabstops: function(value) {
|
||||||
|
var base = 1000;
|
||||||
|
var zeroBase = 0;
|
||||||
|
var lastZero = null;
|
||||||
|
var range = emmet.require('range');
|
||||||
|
var ts = emmet.require('tabStops');
|
||||||
|
var settings = emmet.require('resources').getVocabulary("user");
|
||||||
|
var tabstopOptions = {
|
||||||
|
tabstop: function(data) {
|
||||||
|
var group = parseInt(data.group, 10);
|
||||||
|
var isZero = group === 0;
|
||||||
|
if (isZero)
|
||||||
|
group = ++zeroBase;
|
||||||
|
else
|
||||||
|
group += base;
|
||||||
|
|
||||||
|
var placeholder = data.placeholder;
|
||||||
|
if (placeholder) {
|
||||||
|
// recursively update nested tabstops
|
||||||
|
placeholder = ts.processText(placeholder, tabstopOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = '${' + group + (placeholder ? ':' + placeholder : '') + '}';
|
||||||
|
|
||||||
|
if (isZero) {
|
||||||
|
lastZero = range.create(data.start, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
escape: function(ch) {
|
||||||
|
if (ch == '$') return '\\$';
|
||||||
|
if (ch == '\\') return '\\\\';
|
||||||
|
return ch;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
value = ts.processText(value, tabstopOptions);
|
||||||
|
|
||||||
|
if (settings.variables['insert_final_tabstop'] && !/\$\{0\}$/.test(value)) {
|
||||||
|
value += '${0}';
|
||||||
|
} else if (lastZero) {
|
||||||
|
value = emmet.require('utils').replaceSubstring(value, '${0}', lastZero);
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
var keymap = {
|
||||||
|
expand_abbreviation: {"mac": "ctrl+alt+e", "win": "alt+e"},
|
||||||
|
match_pair_outward: {"mac": "ctrl+d", "win": "ctrl+,"},
|
||||||
|
match_pair_inward: {"mac": "ctrl+j", "win": "ctrl+shift+0"},
|
||||||
|
matching_pair: {"mac": "ctrl+alt+j", "win": "alt+j"},
|
||||||
|
next_edit_point: "alt+right",
|
||||||
|
prev_edit_point: "alt+left",
|
||||||
|
toggle_comment: {"mac": "command+/", "win": "ctrl+/"},
|
||||||
|
split_join_tag: {"mac": "shift+command+'", "win": "shift+ctrl+`"},
|
||||||
|
remove_tag: {"mac": "command+'", "win": "shift+ctrl+;"},
|
||||||
|
evaluate_math_expression: {"mac": "shift+command+y", "win": "shift+ctrl+y"},
|
||||||
|
increment_number_by_1: "ctrl+up",
|
||||||
|
decrement_number_by_1: "ctrl+down",
|
||||||
|
increment_number_by_01: "alt+up",
|
||||||
|
decrement_number_by_01: "alt+down",
|
||||||
|
increment_number_by_10: {"mac": "alt+command+up", "win": "shift+alt+up"},
|
||||||
|
decrement_number_by_10: {"mac": "alt+command+down", "win": "shift+alt+down"},
|
||||||
|
select_next_item: {"mac": "shift+command+.", "win": "shift+ctrl+."},
|
||||||
|
select_previous_item: {"mac": "shift+command+,", "win": "shift+ctrl+,"},
|
||||||
|
reflect_css_value: {"mac": "shift+command+r", "win": "shift+ctrl+r"},
|
||||||
|
|
||||||
|
encode_decode_data_url: {"mac": "shift+ctrl+d", "win": "ctrl+'"},
|
||||||
|
// update_image_size: {"mac": "shift+ctrl+i", "win": "ctrl+u"},
|
||||||
|
// expand_as_you_type: "ctrl+alt+enter",
|
||||||
|
// wrap_as_you_type: {"mac": "shift+ctrl+g", "win": "shift+ctrl+g"},
|
||||||
|
expand_abbreviation_with_tab: "Tab",
|
||||||
|
wrap_with_abbreviation: {"mac": "shift+ctrl+a", "win": "shift+ctrl+a"}
|
||||||
|
};
|
||||||
|
|
||||||
|
var editorProxy = new AceEmmetEditor();
|
||||||
|
exports.commands = new HashHandler();
|
||||||
|
exports.runEmmetCommand = function(editor) {
|
||||||
|
try {
|
||||||
|
editorProxy.setupContext(editor);
|
||||||
|
if (editorProxy.getSyntax() == "php")
|
||||||
|
return false;
|
||||||
|
var actions = emmet.require("actions");
|
||||||
|
|
||||||
|
if (this.action == "expand_abbreviation_with_tab") {
|
||||||
|
if (!editor.selection.isEmpty())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.action == "wrap_with_abbreviation") {
|
||||||
|
// without setTimeout prompt doesn't work on firefox
|
||||||
|
return setTimeout(function() {
|
||||||
|
actions.run("wrap_with_abbreviation", editorProxy);
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
var pos = editor.selection.lead;
|
||||||
|
var token = editor.session.getTokenAt(pos.row, pos.column);
|
||||||
|
if (token && /\btag\b/.test(token.type))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var result = actions.run(this.action, editorProxy);
|
||||||
|
} catch(e) {
|
||||||
|
editor._signal("changeStatus", typeof e == "string" ? e : e.message);
|
||||||
|
console.log(e);
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
for (var command in keymap) {
|
||||||
|
exports.commands.addCommand({
|
||||||
|
name: "emmet:" + command,
|
||||||
|
action: command,
|
||||||
|
bindKey: keymap[command],
|
||||||
|
exec: exports.runEmmetCommand,
|
||||||
|
multiSelectAction: "forEach"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.updateCommands = function(editor, enabled) {
|
||||||
|
if (enabled) {
|
||||||
|
editor.keyBinding.addKeyboardHandler(exports.commands);
|
||||||
|
} else {
|
||||||
|
editor.keyBinding.removeKeyboardHandler(exports.commands);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.isSupportedMode = function(modeId) {
|
||||||
|
return modeId && /css|less|scss|sass|stylus|html|php|twig|ejs/.test(modeId);
|
||||||
|
};
|
||||||
|
|
||||||
|
var onChangeMode = function(e, target) {
|
||||||
|
var editor = target;
|
||||||
|
if (!editor)
|
||||||
|
return;
|
||||||
|
var enabled = exports.isSupportedMode(editor.session.$modeId);
|
||||||
|
if (e.enableEmmet === false)
|
||||||
|
enabled = false;
|
||||||
|
if (enabled) {
|
||||||
|
if (typeof emmetPath == "string") {
|
||||||
|
require("ace/config").loadModule(emmetPath, function() {
|
||||||
|
emmetPath = null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.updateCommands(editor, enabled);
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.AceEmmetEditor = AceEmmetEditor;
|
||||||
|
require("ace/config").defineOptions(Editor.prototype, "editor", {
|
||||||
|
enableEmmet: {
|
||||||
|
set: function(val) {
|
||||||
|
this[val ? "on" : "removeListener"]("changeMode", onChangeMode);
|
||||||
|
onChangeMode({enableEmmet: !!val}, this);
|
||||||
|
},
|
||||||
|
value: true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
exports.setCore = function(e) {
|
||||||
|
if (typeof e == "string")
|
||||||
|
emmetPath = e;
|
||||||
|
else
|
||||||
|
emmet = e;
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
@@ -0,0 +1,214 @@
|
|||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Distributed under the BSD license:
|
||||||
|
*
|
||||||
|
* Copyright (c) 2012, Ajax.org B.V.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of Ajax.org B.V. nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
define(function(require, exports, module) {
|
||||||
|
"use strict";
|
||||||
|
var LineWidgets = require("../line_widgets").LineWidgets;
|
||||||
|
var dom = require("../lib/dom");
|
||||||
|
var Range = require("../range").Range;
|
||||||
|
|
||||||
|
function binarySearch(array, needle, comparator) {
|
||||||
|
var first = 0;
|
||||||
|
var last = array.length - 1;
|
||||||
|
|
||||||
|
while (first <= last) {
|
||||||
|
var mid = (first + last) >> 1;
|
||||||
|
var c = comparator(needle, array[mid]);
|
||||||
|
if (c > 0)
|
||||||
|
first = mid + 1;
|
||||||
|
else if (c < 0)
|
||||||
|
last = mid - 1;
|
||||||
|
else
|
||||||
|
return mid;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the nearest lesser index, "-1" means "0, "-2" means "1", etc.
|
||||||
|
return -(first + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function findAnnotations(session, row, dir) {
|
||||||
|
var annotations = session.getAnnotations().sort(Range.comparePoints);
|
||||||
|
if (!annotations.length)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var i = binarySearch(annotations, {row: row, column: -1}, Range.comparePoints);
|
||||||
|
if (i < 0)
|
||||||
|
i = -i - 1;
|
||||||
|
|
||||||
|
if (i >= annotations.length - 1)
|
||||||
|
i = dir > 0 ? 0 : annotations.length - 1;
|
||||||
|
else if (i === 0 && dir < 0)
|
||||||
|
i = annotations.length - 1;
|
||||||
|
|
||||||
|
var annotation = annotations[i];
|
||||||
|
if (!annotation || !dir)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (annotation.row === row) {
|
||||||
|
do {
|
||||||
|
annotation = annotations[i += dir];
|
||||||
|
} while (annotation && annotation.row === row);
|
||||||
|
if (!annotation)
|
||||||
|
return annotations.slice();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var matched = [];
|
||||||
|
row = annotation.row;
|
||||||
|
do {
|
||||||
|
matched[dir < 0 ? "unshift" : "push"](annotation);
|
||||||
|
annotation = annotations[i += dir];
|
||||||
|
} while (annotation && annotation.row == row);
|
||||||
|
return matched.length && matched;
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.showErrorMarker = function(editor, dir) {
|
||||||
|
var session = editor.session;
|
||||||
|
if (!session.widgetManager) {
|
||||||
|
session.widgetManager = new LineWidgets(session);
|
||||||
|
session.widgetManager.attach(editor);
|
||||||
|
}
|
||||||
|
|
||||||
|
var pos = editor.getCursorPosition();
|
||||||
|
var row = pos.row;
|
||||||
|
var oldWidget = session.lineWidgets && session.lineWidgets[row];
|
||||||
|
if (oldWidget) {
|
||||||
|
oldWidget.destroy();
|
||||||
|
} else {
|
||||||
|
row -= dir;
|
||||||
|
}
|
||||||
|
var annotations = findAnnotations(session, row, dir);
|
||||||
|
var gutterAnno;
|
||||||
|
if (annotations) {
|
||||||
|
var annotation = annotations[0];
|
||||||
|
pos.column = (annotation.pos && typeof annotation.column != "number"
|
||||||
|
? annotation.pos.sc
|
||||||
|
: annotation.column) || 0;
|
||||||
|
pos.row = annotation.row;
|
||||||
|
gutterAnno = editor.renderer.$gutterLayer.$annotations[pos.row];
|
||||||
|
} else if (oldWidget) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
gutterAnno = {
|
||||||
|
text: ["Looks good!"],
|
||||||
|
className: "ace_ok"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
editor.session.unfold(pos.row);
|
||||||
|
editor.selection.moveToPosition(pos);
|
||||||
|
|
||||||
|
var w = {
|
||||||
|
row: pos.row,
|
||||||
|
fixedWidth: true,
|
||||||
|
coverGutter: true,
|
||||||
|
el: dom.createElement("div")
|
||||||
|
};
|
||||||
|
var el = w.el.appendChild(dom.createElement("div"));
|
||||||
|
var arrow = w.el.appendChild(dom.createElement("div"));
|
||||||
|
arrow.className = "error_widget_arrow " + gutterAnno.className;
|
||||||
|
|
||||||
|
var left = editor.renderer.$cursorLayer
|
||||||
|
.getPixelPosition(pos).left;
|
||||||
|
arrow.style.left = left + editor.renderer.gutterWidth - 5 + "px";
|
||||||
|
|
||||||
|
w.el.className = "error_widget_wrapper";
|
||||||
|
el.className = "error_widget " + gutterAnno.className;
|
||||||
|
el.innerHTML = gutterAnno.text.join("<br>");
|
||||||
|
|
||||||
|
el.appendChild(dom.createElement("div"));
|
||||||
|
|
||||||
|
var kb = function(_, hashId, keyString) {
|
||||||
|
if (hashId === 0 && (keyString === "esc" || keyString === "return")) {
|
||||||
|
w.destroy();
|
||||||
|
return {command: "null"};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
w.destroy = function() {
|
||||||
|
if (editor.$mouseHandler.isMousePressed)
|
||||||
|
return;
|
||||||
|
editor.keyBinding.removeKeyboardHandler(kb);
|
||||||
|
session.widgetManager.removeLineWidget(w);
|
||||||
|
editor.off("changeSelection", w.destroy);
|
||||||
|
editor.off("changeSession", w.destroy);
|
||||||
|
editor.off("mouseup", w.destroy);
|
||||||
|
editor.off("change", w.destroy);
|
||||||
|
};
|
||||||
|
|
||||||
|
editor.keyBinding.addKeyboardHandler(kb);
|
||||||
|
editor.on("changeSelection", w.destroy);
|
||||||
|
editor.on("changeSession", w.destroy);
|
||||||
|
editor.on("mouseup", w.destroy);
|
||||||
|
editor.on("change", w.destroy);
|
||||||
|
|
||||||
|
editor.session.widgetManager.addLineWidget(w);
|
||||||
|
|
||||||
|
w.el.onmousedown = editor.focus.bind(editor);
|
||||||
|
|
||||||
|
editor.renderer.scrollCursorIntoView(null, 0.5, {bottom: w.el.offsetHeight});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
dom.importCssString("\
|
||||||
|
.error_widget_wrapper {\
|
||||||
|
background: inherit;\
|
||||||
|
color: inherit;\
|
||||||
|
border:none\
|
||||||
|
}\
|
||||||
|
.error_widget {\
|
||||||
|
border-top: solid 2px;\
|
||||||
|
border-bottom: solid 2px;\
|
||||||
|
margin: 5px 0;\
|
||||||
|
padding: 10px 40px;\
|
||||||
|
white-space: pre-wrap;\
|
||||||
|
}\
|
||||||
|
.error_widget.ace_error, .error_widget_arrow.ace_error{\
|
||||||
|
border-color: #ff5a5a\
|
||||||
|
}\
|
||||||
|
.error_widget.ace_warning, .error_widget_arrow.ace_warning{\
|
||||||
|
border-color: #F1D817\
|
||||||
|
}\
|
||||||
|
.error_widget.ace_info, .error_widget_arrow.ace_info{\
|
||||||
|
border-color: #5a5a5a\
|
||||||
|
}\
|
||||||
|
.error_widget.ace_ok, .error_widget_arrow.ace_ok{\
|
||||||
|
border-color: #5aaa5a\
|
||||||
|
}\
|
||||||
|
.error_widget_arrow {\
|
||||||
|
position: absolute;\
|
||||||
|
border: solid 5px;\
|
||||||
|
border-top-color: transparent!important;\
|
||||||
|
border-right-color: transparent!important;\
|
||||||
|
border-left-color: transparent!important;\
|
||||||
|
top: -5px;\
|
||||||
|
}\
|
||||||
|
", "");
|
||||||
|
|
||||||
|
});
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Distributed under the BSD license:
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 Matthew Christopher Kastor-Inare III, Atropa Inc. Intl
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Contributed to Ajax.org under the BSD license.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of Ajax.org B.V. nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
/*jslint indent: 4, maxerr: 50, white: true, browser: true, vars: true*/
|
||||||
|
/*global define, require */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show Keyboard Shortcuts
|
||||||
|
* @fileOverview Show Keyboard Shortcuts <br />
|
||||||
|
* Generates a menu which displays the keyboard shortcuts.
|
||||||
|
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||||
|
* Matthew Christopher Kastor-Inare III </a><br />
|
||||||
|
* ☭ Hial Atropa!! ☭
|
||||||
|
*/
|
||||||
|
|
||||||
|
define(function(require, exports, module) {
|
||||||
|
"use strict";
|
||||||
|
var Editor = require("ace/editor").Editor;
|
||||||
|
/**
|
||||||
|
* Generates a menu which displays the keyboard shortcuts.
|
||||||
|
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||||
|
* Matthew Christopher Kastor-Inare III </a><br />
|
||||||
|
* ☭ Hial Atropa!! ☭
|
||||||
|
* @param {ace.Editor} editor An instance of the ace editor.
|
||||||
|
*/
|
||||||
|
function showKeyboardShortcuts (editor) {
|
||||||
|
// make sure the menu isn't open already.
|
||||||
|
if(!document.getElementById('kbshortcutmenu')) {
|
||||||
|
var overlayPage = require('./menu_tools/overlay_page').overlayPage;
|
||||||
|
var getEditorKeybordShortcuts = require('./menu_tools/get_editor_keyboard_shortcuts').getEditorKeybordShortcuts;
|
||||||
|
var kb = getEditorKeybordShortcuts(editor);
|
||||||
|
var el = document.createElement('div');
|
||||||
|
var commands = kb.reduce(function(previous, current) {
|
||||||
|
return previous + '<div class="ace_optionsMenuEntry"><span class="ace_optionsMenuCommand">'
|
||||||
|
+ current.command + '</span> : '
|
||||||
|
+ '<span class="ace_optionsMenuKey">' + current.key + '</span></div>';
|
||||||
|
}, '');
|
||||||
|
|
||||||
|
el.id = 'kbshortcutmenu';
|
||||||
|
el.innerHTML = '<h1>Keyboard Shortcuts</h1>' + commands + '</div>';
|
||||||
|
overlayPage(editor, el, '0', '0', '0', null);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
module.exports.init = function(editor) {
|
||||||
|
Editor.prototype.showKeyboardShortcuts = function() {
|
||||||
|
showKeyboardShortcuts(this);
|
||||||
|
};
|
||||||
|
editor.commands.addCommands([{
|
||||||
|
name: "showKeyboardShortcuts",
|
||||||
|
bindKey: {win: "Ctrl-Alt-h", mac: "Command-Alt-h"},
|
||||||
|
exec: function(editor, line) {
|
||||||
|
editor.showKeyboardShortcuts();
|
||||||
|
}
|
||||||
|
}]);
|
||||||
|
};
|
||||||
|
|
||||||
|
});
|
||||||
@@ -0,0 +1,226 @@
|
|||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Distributed under the BSD license:
|
||||||
|
*
|
||||||
|
* Copyright (c) 2012, Ajax.org B.V.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of Ajax.org B.V. nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
define(function(require, exports, module) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var snippetManager = require("../snippets").snippetManager;
|
||||||
|
var Autocomplete = require("../autocomplete").Autocomplete;
|
||||||
|
var config = require("../config");
|
||||||
|
var lang = require("../lib/lang");
|
||||||
|
var util = require("../autocomplete/util");
|
||||||
|
|
||||||
|
var textCompleter = require("../autocomplete/text_completer");
|
||||||
|
var keyWordCompleter = {
|
||||||
|
getCompletions: function(editor, session, pos, prefix, callback) {
|
||||||
|
if (session.$mode.completer) {
|
||||||
|
return session.$mode.completer.getCompletions(editor, session, pos, prefix, callback);
|
||||||
|
}
|
||||||
|
var state = editor.session.getState(pos.row);
|
||||||
|
var completions = session.$mode.getCompletions(state, session, pos, prefix);
|
||||||
|
callback(null, completions);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var snippetCompleter = {
|
||||||
|
getCompletions: function(editor, session, pos, prefix, callback) {
|
||||||
|
var snippetMap = snippetManager.snippetMap;
|
||||||
|
var completions = [];
|
||||||
|
snippetManager.getActiveScopes(editor).forEach(function(scope) {
|
||||||
|
var snippets = snippetMap[scope] || [];
|
||||||
|
for (var i = snippets.length; i--;) {
|
||||||
|
var s = snippets[i];
|
||||||
|
var caption = s.name || s.tabTrigger;
|
||||||
|
if (!caption)
|
||||||
|
continue;
|
||||||
|
completions.push({
|
||||||
|
caption: caption,
|
||||||
|
snippet: s.content,
|
||||||
|
meta: s.tabTrigger && !s.name ? s.tabTrigger + "\u21E5 " : "snippet",
|
||||||
|
type: "snippet"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, this);
|
||||||
|
callback(null, completions);
|
||||||
|
},
|
||||||
|
getDocTooltip: function(item) {
|
||||||
|
if (item.type == "snippet" && !item.docHTML) {
|
||||||
|
item.docHTML = [
|
||||||
|
"<b>", lang.escapeHTML(item.caption), "</b>", "<hr></hr>",
|
||||||
|
lang.escapeHTML(item.snippet)
|
||||||
|
].join("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var completers = [snippetCompleter, textCompleter, keyWordCompleter];
|
||||||
|
// Allows default completers to be removed or replaced with a explict set of completers
|
||||||
|
// A null argument here will result in an empty completer array, not a null attribute
|
||||||
|
exports.setCompleters = function(val) {
|
||||||
|
completers = val || [];
|
||||||
|
};
|
||||||
|
exports.addCompleter = function(completer) {
|
||||||
|
completers.push(completer);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Exports existing completer so that user can construct his own set of completers.
|
||||||
|
exports.textCompleter = textCompleter;
|
||||||
|
exports.keyWordCompleter = keyWordCompleter;
|
||||||
|
exports.snippetCompleter = snippetCompleter;
|
||||||
|
|
||||||
|
var expandSnippet = {
|
||||||
|
name: "expandSnippet",
|
||||||
|
exec: function(editor) {
|
||||||
|
return snippetManager.expandWithTab(editor);
|
||||||
|
},
|
||||||
|
bindKey: "Tab"
|
||||||
|
};
|
||||||
|
|
||||||
|
var onChangeMode = function(e, editor) {
|
||||||
|
loadSnippetsForMode(editor.session.$mode);
|
||||||
|
};
|
||||||
|
|
||||||
|
var loadSnippetsForMode = function(mode) {
|
||||||
|
var id = mode.$id;
|
||||||
|
if (!snippetManager.files)
|
||||||
|
snippetManager.files = {};
|
||||||
|
loadSnippetFile(id);
|
||||||
|
if (mode.modes)
|
||||||
|
mode.modes.forEach(loadSnippetsForMode);
|
||||||
|
};
|
||||||
|
|
||||||
|
var loadSnippetFile = function(id) {
|
||||||
|
if (!id || snippetManager.files[id])
|
||||||
|
return;
|
||||||
|
var snippetFilePath = id.replace("mode", "snippets");
|
||||||
|
snippetManager.files[id] = {};
|
||||||
|
config.loadModule(snippetFilePath, function(m) {
|
||||||
|
if (m) {
|
||||||
|
snippetManager.files[id] = m;
|
||||||
|
if (!m.snippets && m.snippetText)
|
||||||
|
m.snippets = snippetManager.parseSnippetFile(m.snippetText);
|
||||||
|
snippetManager.register(m.snippets || [], m.scope);
|
||||||
|
if (m.includeScopes) {
|
||||||
|
snippetManager.snippetMap[m.scope].includeScopes = m.includeScopes;
|
||||||
|
m.includeScopes.forEach(function(x) {
|
||||||
|
loadSnippetFile("ace/mode/" + x);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
function getCompletionPrefix(editor) {
|
||||||
|
var pos = editor.getCursorPosition();
|
||||||
|
var line = editor.session.getLine(pos.row);
|
||||||
|
var prefix;
|
||||||
|
// Try to find custom prefixes on the completers
|
||||||
|
editor.completers.forEach(function(completer) {
|
||||||
|
if (completer.identifierRegexps) {
|
||||||
|
completer.identifierRegexps.forEach(function(identifierRegex) {
|
||||||
|
if (!prefix && identifierRegex)
|
||||||
|
prefix = util.retrievePrecedingIdentifier(line, pos.column, identifierRegex);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return prefix || util.retrievePrecedingIdentifier(line, pos.column);
|
||||||
|
}
|
||||||
|
|
||||||
|
var doLiveAutocomplete = function(e) {
|
||||||
|
var editor = e.editor;
|
||||||
|
var text = e.args || "";
|
||||||
|
var hasCompleter = editor.completer && editor.completer.activated;
|
||||||
|
|
||||||
|
// We don't want to autocomplete with no prefix
|
||||||
|
if (e.command.name === "backspace") {
|
||||||
|
if (hasCompleter && !getCompletionPrefix(editor))
|
||||||
|
editor.completer.detach();
|
||||||
|
}
|
||||||
|
else if (e.command.name === "insertstring") {
|
||||||
|
var prefix = getCompletionPrefix(editor);
|
||||||
|
// Only autocomplete if there's a prefix that can be matched
|
||||||
|
if (prefix && !hasCompleter) {
|
||||||
|
if (!editor.completer) {
|
||||||
|
// Create new autocompleter
|
||||||
|
editor.completer = new Autocomplete();
|
||||||
|
}
|
||||||
|
// Disable autoInsert
|
||||||
|
editor.completer.autoInsert = false;
|
||||||
|
editor.completer.showPopup(editor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var Editor = require("../editor").Editor;
|
||||||
|
require("../config").defineOptions(Editor.prototype, "editor", {
|
||||||
|
enableBasicAutocompletion: {
|
||||||
|
set: function(val) {
|
||||||
|
if (val) {
|
||||||
|
if (!this.completers)
|
||||||
|
this.completers = Array.isArray(val)? val: completers;
|
||||||
|
this.commands.addCommand(Autocomplete.startCommand);
|
||||||
|
} else {
|
||||||
|
this.commands.removeCommand(Autocomplete.startCommand);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
value: false
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Enable live autocomplete. If the value is an array, it is assumed to be an array of completers
|
||||||
|
* and will use them instead of the default completers.
|
||||||
|
*/
|
||||||
|
enableLiveAutocompletion: {
|
||||||
|
set: function(val) {
|
||||||
|
if (val) {
|
||||||
|
if (!this.completers)
|
||||||
|
this.completers = Array.isArray(val)? val: completers;
|
||||||
|
// On each change automatically trigger the autocomplete
|
||||||
|
this.commands.on('afterExec', doLiveAutocomplete);
|
||||||
|
} else {
|
||||||
|
this.commands.removeListener('afterExec', doLiveAutocomplete);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
value: false
|
||||||
|
},
|
||||||
|
enableSnippets: {
|
||||||
|
set: function(val) {
|
||||||
|
if (val) {
|
||||||
|
this.commands.addCommand(expandSnippet);
|
||||||
|
this.on("changeMode", onChangeMode);
|
||||||
|
onChangeMode(null, this);
|
||||||
|
} else {
|
||||||
|
this.commands.removeCommand(expandSnippet);
|
||||||
|
this.off("changeMode", onChangeMode);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
value: false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Distributed under the BSD license:
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010, Ajax.org B.V.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of Ajax.org B.V. nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
define(function(require, exports, module) {
|
||||||
|
|
||||||
|
var Editor = require("ace/editor").Editor;
|
||||||
|
|
||||||
|
require("../config").defineOptions(Editor.prototype, "editor", {
|
||||||
|
enableLinking: {
|
||||||
|
set: function(val) {
|
||||||
|
if (val) {
|
||||||
|
this.on("click", onClick);
|
||||||
|
this.on("mousemove", onMouseMove);
|
||||||
|
} else {
|
||||||
|
this.off("click", onClick);
|
||||||
|
this.off("mousemove", onMouseMove);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
value: false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
function onMouseMove(e) {
|
||||||
|
var editor = e.editor;
|
||||||
|
var ctrl = e.getAccelKey();
|
||||||
|
|
||||||
|
if (ctrl) {
|
||||||
|
var editor = e.editor;
|
||||||
|
var docPos = e.getDocumentPosition();
|
||||||
|
var session = editor.session;
|
||||||
|
var token = session.getTokenAt(docPos.row, docPos.column);
|
||||||
|
|
||||||
|
editor._emit("linkHover", {position: docPos, token: token});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onClick(e) {
|
||||||
|
var ctrl = e.getAccelKey();
|
||||||
|
var button = e.getButton();
|
||||||
|
|
||||||
|
if (button == 0 && ctrl) {
|
||||||
|
var editor = e.editor;
|
||||||
|
var docPos = e.getDocumentPosition();
|
||||||
|
var session = editor.session;
|
||||||
|
var token = session.getTokenAt(docPos.row, docPos.column);
|
||||||
|
|
||||||
|
editor._emit("linkClick", {position: docPos, token: token});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
+109
@@ -0,0 +1,109 @@
|
|||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Distributed under the BSD license:
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 Matthew Christopher Kastor-Inare III, Atropa Inc. Intl
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Contributed to Ajax.org under the BSD license.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of Ajax.org B.V. nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
/*jslint indent: 4, maxerr: 50, white: true, browser: true, vars: true*/
|
||||||
|
/*global define, require */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add Editor Menu Options
|
||||||
|
* @fileOverview Add Editor Menu Options <br />
|
||||||
|
* The menu options property needs to be added to the editor
|
||||||
|
* so that the settings menu can know about options for
|
||||||
|
* selection elements and track which option is selected.
|
||||||
|
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||||
|
* Matthew Christopher Kastor-Inare III </a><br />
|
||||||
|
* ☭ Hial Atropa!! ☭
|
||||||
|
*/
|
||||||
|
|
||||||
|
define(function(require, exports, module) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The menu options property needs to be added to the editor
|
||||||
|
* so that the settings menu can know about options for
|
||||||
|
* selection elements and track which option is selected.
|
||||||
|
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||||
|
* Matthew Christopher Kastor-Inare III </a><br />
|
||||||
|
* ☭ Hial Atropa!! ☭
|
||||||
|
* @param {ace.Editor} editor An instance of the ace editor.
|
||||||
|
*/
|
||||||
|
module.exports.addEditorMenuOptions = function addEditorMenuOptions (editor) {
|
||||||
|
var modelist = require('../modelist');
|
||||||
|
var themelist = require('../themelist');
|
||||||
|
editor.menuOptions = {
|
||||||
|
setNewLineMode: [{
|
||||||
|
textContent: "unix",
|
||||||
|
value: "unix"
|
||||||
|
}, {
|
||||||
|
textContent: "windows",
|
||||||
|
value: "windows"
|
||||||
|
}, {
|
||||||
|
textContent: "auto",
|
||||||
|
value: "auto"
|
||||||
|
}],
|
||||||
|
setTheme: [],
|
||||||
|
setMode: [],
|
||||||
|
setKeyboardHandler: [{
|
||||||
|
textContent: "ace",
|
||||||
|
value: ""
|
||||||
|
}, {
|
||||||
|
textContent: "vim",
|
||||||
|
value: "ace/keyboard/vim"
|
||||||
|
}, {
|
||||||
|
textContent: "emacs",
|
||||||
|
value: "ace/keyboard/emacs"
|
||||||
|
}, {
|
||||||
|
textContent: "textarea",
|
||||||
|
value: "ace/keyboard/textarea"
|
||||||
|
}, {
|
||||||
|
textContent: "sublime",
|
||||||
|
value: "ace/keyboard/sublime"
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
|
||||||
|
editor.menuOptions.setTheme = themelist.themes.map(function(theme) {
|
||||||
|
return {
|
||||||
|
textContent: theme.caption,
|
||||||
|
value: theme.theme
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
editor.menuOptions.setMode = modelist.modes.map(function(mode) {
|
||||||
|
return {
|
||||||
|
textContent: mode.name,
|
||||||
|
value: mode.mode
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
+148
@@ -0,0 +1,148 @@
|
|||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Distributed under the BSD license:
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 Matthew Christopher Kastor-Inare III, Atropa Inc. Intl
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Contributed to Ajax.org under the BSD license.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of Ajax.org B.V. nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
/*jslint indent: 4, maxerr: 50, white: true, browser: true, vars: true*/
|
||||||
|
/*global define, require */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Element Generator
|
||||||
|
* @fileOverview Element Generator <br />
|
||||||
|
* Contains methods for generating elements.
|
||||||
|
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||||
|
* Matthew Christopher Kastor-Inare III </a><br />
|
||||||
|
* ☭ Hial Atropa!! ☭
|
||||||
|
*/
|
||||||
|
|
||||||
|
define(function(require, exports, module) {
|
||||||
|
'use strict';
|
||||||
|
/**
|
||||||
|
* Creates a DOM option element
|
||||||
|
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||||
|
* Matthew Christopher Kastor-Inare III </a><br />
|
||||||
|
* ☭ Hial Atropa!! ☭
|
||||||
|
* @param {object} obj An object containing properties to add to the dom
|
||||||
|
* element. If one of those properties is named `selected` then it will be
|
||||||
|
* added as an attribute on the element instead.
|
||||||
|
*/
|
||||||
|
module.exports.createOption = function createOption (obj) {
|
||||||
|
var attribute;
|
||||||
|
var el = document.createElement('option');
|
||||||
|
for(attribute in obj) {
|
||||||
|
if(obj.hasOwnProperty(attribute)) {
|
||||||
|
if(attribute === 'selected') {
|
||||||
|
el.setAttribute(attribute, obj[attribute]);
|
||||||
|
} else {
|
||||||
|
el[attribute] = obj[attribute];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return el;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Creates a DOM checkbox element.
|
||||||
|
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||||
|
* Matthew Christopher Kastor-Inare III </a><br />
|
||||||
|
* ☭ Hial Atropa!! ☭
|
||||||
|
* @param {string} id The id of the element.
|
||||||
|
* @param {boolean} checked Whether or not the element is checked.
|
||||||
|
* @param {string} clss The class of the element.
|
||||||
|
* @returns {DOMElement} Returns a checkbox element reference.
|
||||||
|
*/
|
||||||
|
module.exports.createCheckbox = function createCheckbox (id, checked, clss) {
|
||||||
|
var el = document.createElement('input');
|
||||||
|
el.setAttribute('type', 'checkbox');
|
||||||
|
el.setAttribute('id', id);
|
||||||
|
el.setAttribute('name', id);
|
||||||
|
el.setAttribute('value', checked);
|
||||||
|
el.setAttribute('class', clss);
|
||||||
|
if(checked) {
|
||||||
|
el.setAttribute('checked', 'checked');
|
||||||
|
}
|
||||||
|
return el;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Creates a DOM text input element.
|
||||||
|
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||||
|
* Matthew Christopher Kastor-Inare III </a><br />
|
||||||
|
* ☭ Hial Atropa!! ☭
|
||||||
|
* @param {string} id The id of the element.
|
||||||
|
* @param {string} value The default value of the input element.
|
||||||
|
* @param {string} clss The class of the element.
|
||||||
|
* @returns {DOMElement} Returns an input element reference.
|
||||||
|
*/
|
||||||
|
module.exports.createInput = function createInput (id, value, clss) {
|
||||||
|
var el = document.createElement('input');
|
||||||
|
el.setAttribute('type', 'text');
|
||||||
|
el.setAttribute('id', id);
|
||||||
|
el.setAttribute('name', id);
|
||||||
|
el.setAttribute('value', value);
|
||||||
|
el.setAttribute('class', clss);
|
||||||
|
return el;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Creates a DOM label element.
|
||||||
|
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||||
|
* Matthew Christopher Kastor-Inare III </a><br />
|
||||||
|
* ☭ Hial Atropa!! ☭
|
||||||
|
* @param {string} text The label text.
|
||||||
|
* @param {string} labelFor The id of the element being labeled.
|
||||||
|
* @returns {DOMElement} Returns a label element reference.
|
||||||
|
*/
|
||||||
|
module.exports.createLabel = function createLabel (text, labelFor) {
|
||||||
|
var el = document.createElement('label');
|
||||||
|
el.setAttribute('for', labelFor);
|
||||||
|
el.textContent = text;
|
||||||
|
return el;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Creates a DOM selection element.
|
||||||
|
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||||
|
* Matthew Christopher Kastor-Inare III </a><br />
|
||||||
|
* ☭ Hial Atropa!! ☭
|
||||||
|
* @param {string} id The id of the element.
|
||||||
|
* @param {string} values An array of objects suitable for `createOption`
|
||||||
|
* @param {string} clss The class of the element.
|
||||||
|
* @returns {DOMElement} Returns a selection element reference.
|
||||||
|
* @see ace/ext/element_generator.createOption
|
||||||
|
*/
|
||||||
|
module.exports.createSelection = function createSelection (id, values, clss) {
|
||||||
|
var el = document.createElement('select');
|
||||||
|
el.setAttribute('id', id);
|
||||||
|
el.setAttribute('name', id);
|
||||||
|
el.setAttribute('class', clss);
|
||||||
|
values.forEach(function(item) {
|
||||||
|
el.appendChild(module.exports.createOption(item));
|
||||||
|
});
|
||||||
|
return el;
|
||||||
|
};
|
||||||
|
|
||||||
|
});
|
||||||
+264
@@ -0,0 +1,264 @@
|
|||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Distributed under the BSD license:
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 Matthew Christopher Kastor-Inare III, Atropa Inc. Intl
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Contributed to Ajax.org under the BSD license.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of Ajax.org B.V. nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
/*jslint indent: 4, maxerr: 50, white: true, browser: true, vars: true*/
|
||||||
|
/*global define*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the settings menu
|
||||||
|
* @fileOverview Generates the settings menu.
|
||||||
|
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||||
|
* Matthew Christopher Kastor-Inare III </a><br />
|
||||||
|
* ☭ Hial Atropa!! ☭
|
||||||
|
*/
|
||||||
|
|
||||||
|
define(function(require, exports, module) {
|
||||||
|
'use strict';
|
||||||
|
var egen = require('./element_generator');
|
||||||
|
var addEditorMenuOptions = require('./add_editor_menu_options').addEditorMenuOptions;
|
||||||
|
var getSetFunctions = require('./get_set_functions').getSetFunctions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates an interactive menu with settings useful to end users.
|
||||||
|
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||||
|
* Matthew Christopher Kastor-Inare III </a><br />
|
||||||
|
* ☭ Hial Atropa!! ☭
|
||||||
|
* @param {ace.Editor} editor An instance of the ace editor.
|
||||||
|
*/
|
||||||
|
module.exports.generateSettingsMenu = function generateSettingsMenu (editor) {
|
||||||
|
/**
|
||||||
|
* container for dom elements that will go in the menu.
|
||||||
|
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||||
|
* Matthew Christopher Kastor-Inare III </a><br />
|
||||||
|
* ☭ Hial Atropa!! ☭
|
||||||
|
*/
|
||||||
|
var elements = [];
|
||||||
|
/**
|
||||||
|
* Sorts the menu entries (elements var) so they'll appear in alphabetical order
|
||||||
|
* the sort is performed based on the value of the contains property
|
||||||
|
* of each element. Since this is an `array.sort` the array is sorted
|
||||||
|
* in place.
|
||||||
|
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||||
|
* Matthew Christopher Kastor-Inare III </a><br />
|
||||||
|
* ☭ Hial Atropa!! ☭
|
||||||
|
*/
|
||||||
|
function cleanupElementsList() {
|
||||||
|
elements.sort(function(a, b) {
|
||||||
|
var x = a.getAttribute('contains');
|
||||||
|
var y = b.getAttribute('contains');
|
||||||
|
return x.localeCompare(y);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Wraps all dom elements contained in the elements var with a single
|
||||||
|
* div.
|
||||||
|
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||||
|
* Matthew Christopher Kastor-Inare III </a><br />
|
||||||
|
* ☭ Hial Atropa!! ☭
|
||||||
|
*/
|
||||||
|
function wrapElements() {
|
||||||
|
var topmenu = document.createElement('div');
|
||||||
|
topmenu.setAttribute('id', 'ace_settingsmenu');
|
||||||
|
elements.forEach(function(element) {
|
||||||
|
topmenu.appendChild(element);
|
||||||
|
});
|
||||||
|
|
||||||
|
var el = topmenu.appendChild(document.createElement('div'));
|
||||||
|
var version = "1.1.8";
|
||||||
|
el.style.padding = "1em";
|
||||||
|
el.textContent = "Ace version " + version;
|
||||||
|
|
||||||
|
return topmenu;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Creates a new menu entry.
|
||||||
|
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||||
|
* Matthew Christopher Kastor-Inare III </a><br />
|
||||||
|
* ☭ Hial Atropa!! ☭
|
||||||
|
* @param {object} obj This is a reference to the object containing the
|
||||||
|
* set function. It is used to set up event listeners for when the
|
||||||
|
* menu options change.
|
||||||
|
* @param {string} clss Maps to the class of the dom element. This is
|
||||||
|
* the name of the object containing the set function e.g. `editor`,
|
||||||
|
* `session`, `renderer`.
|
||||||
|
* @param {string} item This is the set function name. It maps to the
|
||||||
|
* id of the dom element (check, select, input) and to the "contains"
|
||||||
|
* attribute of the div holding both the element and its label.
|
||||||
|
* @param {mixed} val This is the value of the setting. It is mapped to
|
||||||
|
* the dom element's value, checked, or selected option accordingly.
|
||||||
|
*/
|
||||||
|
function createNewEntry(obj, clss, item, val) {
|
||||||
|
var el;
|
||||||
|
var div = document.createElement('div');
|
||||||
|
div.setAttribute('contains', item);
|
||||||
|
div.setAttribute('class', 'ace_optionsMenuEntry');
|
||||||
|
div.setAttribute('style', 'clear: both;');
|
||||||
|
|
||||||
|
div.appendChild(egen.createLabel(
|
||||||
|
item.replace(/^set/, '').replace(/([A-Z])/g, ' $1').trim(),
|
||||||
|
item
|
||||||
|
));
|
||||||
|
|
||||||
|
if (Array.isArray(val)) {
|
||||||
|
el = egen.createSelection(item, val, clss);
|
||||||
|
el.addEventListener('change', function(e) {
|
||||||
|
try{
|
||||||
|
editor.menuOptions[e.target.id].forEach(function(x) {
|
||||||
|
if(x.textContent !== e.target.textContent) {
|
||||||
|
delete x.selected;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
obj[e.target.id](e.target.value);
|
||||||
|
} catch (err) {
|
||||||
|
throw new Error(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else if(typeof val === 'boolean') {
|
||||||
|
el = egen.createCheckbox(item, val, clss);
|
||||||
|
el.addEventListener('change', function(e) {
|
||||||
|
try{
|
||||||
|
// renderer['setHighlightGutterLine'](true);
|
||||||
|
obj[e.target.id](!!e.target.checked);
|
||||||
|
} catch (err) {
|
||||||
|
throw new Error(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// this aids in giving the ability to specify settings through
|
||||||
|
// post and get requests.
|
||||||
|
// /ace_editor.html?setMode=ace/mode/html&setOverwrite=true
|
||||||
|
el = egen.createInput(item, val, clss);
|
||||||
|
el.addEventListener('change', function(e) {
|
||||||
|
try{
|
||||||
|
if(e.target.value === 'true') {
|
||||||
|
obj[e.target.id](true);
|
||||||
|
} else if(e.target.value === 'false') {
|
||||||
|
obj[e.target.id](false);
|
||||||
|
} else {
|
||||||
|
obj[e.target.id](e.target.value);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
throw new Error(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
el.style.cssText = 'float:right;';
|
||||||
|
div.appendChild(el);
|
||||||
|
return div;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Generates selection fields for the menu and populates their options
|
||||||
|
* using information from `editor.menuOptions`
|
||||||
|
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||||
|
* Matthew Christopher Kastor-Inare III </a><br />
|
||||||
|
* ☭ Hial Atropa!! ☭
|
||||||
|
* @param {string} item The set function name.
|
||||||
|
* @param {object} esr A reference to the object having the set function.
|
||||||
|
* @param {string} clss The name of the object containing the set function.
|
||||||
|
* @param {string} fn The matching get function's function name.
|
||||||
|
* @returns {DOMElement} Returns a dom element containing a selection
|
||||||
|
* element populated with options. The option whose value matches that
|
||||||
|
* returned from `esr[fn]()` will be selected.
|
||||||
|
*/
|
||||||
|
function makeDropdown(item, esr, clss, fn) {
|
||||||
|
var val = editor.menuOptions[item];
|
||||||
|
var currentVal = esr[fn]();
|
||||||
|
if (typeof currentVal == 'object')
|
||||||
|
currentVal = currentVal.$id;
|
||||||
|
val.forEach(function(valuex) {
|
||||||
|
if (valuex.value === currentVal)
|
||||||
|
valuex.selected = 'selected';
|
||||||
|
});
|
||||||
|
return createNewEntry(esr, clss, item, val);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Processes the set functions returned from `getSetFunctions`. First it
|
||||||
|
* checks for menu options defined in `editor.menuOptions`. If no
|
||||||
|
* options are specified then it checks whether there is a get function
|
||||||
|
* (replace set with get) for the setting. When either of those
|
||||||
|
* conditions are met it will attempt to create a new entry for the
|
||||||
|
* settings menu and push it into the elements array defined above.
|
||||||
|
* It can only do so for get functions which return
|
||||||
|
* strings, numbers, and booleans. A special case is written in for
|
||||||
|
* `getMode` where it looks at the returned objects `$id` property and
|
||||||
|
* forwards that through instead. Other special cases could be written
|
||||||
|
* in but that would get a bit ridiculous.
|
||||||
|
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||||
|
* Matthew Christopher Kastor-Inare III </a><br />
|
||||||
|
* ☭ Hial Atropa!! ☭
|
||||||
|
* @param {object} setObj An item from the array returned by
|
||||||
|
* `getSetFunctions`.
|
||||||
|
*/
|
||||||
|
function handleSet(setObj) {
|
||||||
|
var item = setObj.functionName;
|
||||||
|
var esr = setObj.parentObj;
|
||||||
|
var clss = setObj.parentName;
|
||||||
|
var val;
|
||||||
|
var fn = item.replace(/^set/, 'get');
|
||||||
|
if(editor.menuOptions[item] !== undefined) {
|
||||||
|
// has options for select element
|
||||||
|
elements.push(makeDropdown(item, esr, clss, fn));
|
||||||
|
} else if(typeof esr[fn] === 'function') {
|
||||||
|
// has get function
|
||||||
|
try {
|
||||||
|
val = esr[fn]();
|
||||||
|
if(typeof val === 'object') {
|
||||||
|
// setMode takes a string, getMode returns an object
|
||||||
|
// the $id property of that object is the string
|
||||||
|
// which may be given to setMode...
|
||||||
|
val = val.$id;
|
||||||
|
}
|
||||||
|
// the rest of the get functions return strings,
|
||||||
|
// booleans, or numbers.
|
||||||
|
elements.push(
|
||||||
|
createNewEntry(esr, clss, item, val)
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
// if there are errors it is because the element
|
||||||
|
// does not belong in the settings menu
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addEditorMenuOptions(editor);
|
||||||
|
// gather the set functions
|
||||||
|
getSetFunctions(editor).forEach(function(setObj) {
|
||||||
|
// populate the elements array with good stuff.
|
||||||
|
handleSet(setObj);
|
||||||
|
});
|
||||||
|
// sort the menu entries in the elements list so people can find
|
||||||
|
// the settings in alphabetical order.
|
||||||
|
cleanupElementsList();
|
||||||
|
// dump the entries from the elements list and wrap them up in a div
|
||||||
|
return wrapElements();
|
||||||
|
};
|
||||||
|
|
||||||
|
});
|
||||||
+91
@@ -0,0 +1,91 @@
|
|||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Distributed under the BSD license:
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 Matthew Christopher Kastor-Inare III, Atropa Inc. Intl
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Contributed to Ajax.org under the BSD license.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of Ajax.org B.V. nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
/*jslint indent: 4, maxerr: 50, white: true, browser: true, vars: true*/
|
||||||
|
/*global define, require */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Editor Keyboard Shortcuts
|
||||||
|
* @fileOverview Get Editor Keyboard Shortcuts <br />
|
||||||
|
* Gets a map of keyboard shortcuts to command names for the current platform.
|
||||||
|
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||||
|
* Matthew Christopher Kastor-Inare III </a><br />
|
||||||
|
* ☭ Hial Atropa!! ☭
|
||||||
|
*/
|
||||||
|
|
||||||
|
define(function(require, exports, module) {
|
||||||
|
"use strict";
|
||||||
|
var keys = require("../../lib/keys");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a map of keyboard shortcuts to command names for the current platform.
|
||||||
|
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||||
|
* Matthew Christopher Kastor-Inare III </a><br />
|
||||||
|
* ☭ Hial Atropa!! ☭
|
||||||
|
* @param {ace.Editor} editor An editor instance.
|
||||||
|
* @returns {Array} Returns an array of objects representing the keyboard
|
||||||
|
* shortcuts for the given editor.
|
||||||
|
* @example
|
||||||
|
* var getKbShortcuts = require('./get_keyboard_shortcuts');
|
||||||
|
* console.log(getKbShortcuts(editor));
|
||||||
|
* // [
|
||||||
|
* // {'command' : aCommand, 'key' : 'Control-d'},
|
||||||
|
* // {'command' : aCommand, 'key' : 'Control-d'}
|
||||||
|
* // ]
|
||||||
|
*/
|
||||||
|
module.exports.getEditorKeybordShortcuts = function(editor) {
|
||||||
|
var KEY_MODS = keys.KEY_MODS;
|
||||||
|
var keybindings = [];
|
||||||
|
var commandMap = {};
|
||||||
|
editor.keyBinding.$handlers.forEach(function(handler) {
|
||||||
|
var ckb = handler.commandKeyBinding;
|
||||||
|
for (var i in ckb) {
|
||||||
|
var key = i.replace(/(^|-)\w/g, function(x) { return x.toUpperCase(); });
|
||||||
|
var commands = ckb[i];
|
||||||
|
if (!Array.isArray(commands))
|
||||||
|
commands = [commands];
|
||||||
|
commands.forEach(function(command) {
|
||||||
|
if (typeof command != "string")
|
||||||
|
command = command.name
|
||||||
|
if (commandMap[command]) {
|
||||||
|
commandMap[command].key += "|" + key;
|
||||||
|
} else {
|
||||||
|
commandMap[command] = {key: key, command: command};
|
||||||
|
keybindings.push(commandMap[command]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return keybindings;
|
||||||
|
};
|
||||||
|
|
||||||
|
});
|
||||||
+141
@@ -0,0 +1,141 @@
|
|||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Distributed under the BSD license:
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 Matthew Christopher Kastor-Inare III, Atropa Inc. Intl
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Contributed to Ajax.org under the BSD license.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of Ajax.org B.V. nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
/*jslint indent: 4, maxerr: 50, white: true, browser: true, vars: true */
|
||||||
|
/*global define*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Set Functions
|
||||||
|
* @fileOverview Get Set Functions <br />
|
||||||
|
* Gets various functions for setting settings.
|
||||||
|
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||||
|
* Matthew Christopher Kastor-Inare III </a><br />
|
||||||
|
* ☭ Hial Atropa!! ☭
|
||||||
|
*/
|
||||||
|
|
||||||
|
define(function(require, exports, module) {
|
||||||
|
'use strict';
|
||||||
|
/**
|
||||||
|
* Generates a list of set functions for the settings menu.
|
||||||
|
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||||
|
* Matthew Christopher Kastor-Inare III </a><br />
|
||||||
|
* ☭ Hial Atropa!! ☭
|
||||||
|
* @param {object} editor The editor instance
|
||||||
|
* @return {array} Returns an array of objects. Each object contains the
|
||||||
|
* following properties: functionName, parentObj, and parentName. The
|
||||||
|
* function name will be the name of a method beginning with the string
|
||||||
|
* `set` which was found. The parent object will be a reference to the
|
||||||
|
* object having the method matching the function name. The parent name
|
||||||
|
* will be a string representing the identifier of the parent object e.g.
|
||||||
|
* `editor`, `session`, or `renderer`.
|
||||||
|
*/
|
||||||
|
module.exports.getSetFunctions = function getSetFunctions (editor) {
|
||||||
|
/**
|
||||||
|
* Output array. Will hold the objects described above.
|
||||||
|
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||||
|
* Matthew Christopher Kastor-Inare III </a><br />
|
||||||
|
* ☭ Hial Atropa!! ☭
|
||||||
|
*/
|
||||||
|
var out = [];
|
||||||
|
/**
|
||||||
|
* This object provides a map between the objects which will be
|
||||||
|
* traversed and the parent name which will appear in the output.
|
||||||
|
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||||
|
* Matthew Christopher Kastor-Inare III </a><br />
|
||||||
|
* ☭ Hial Atropa!! ☭
|
||||||
|
*/
|
||||||
|
var my = {
|
||||||
|
'editor' : editor,
|
||||||
|
'session' : editor.session,
|
||||||
|
'renderer' : editor.renderer
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* This array will hold the set function names which have already been
|
||||||
|
* found so that they are not added to the output multiple times.
|
||||||
|
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||||
|
* Matthew Christopher Kastor-Inare III </a><br />
|
||||||
|
* ☭ Hial Atropa!! ☭
|
||||||
|
*/
|
||||||
|
var opts = [];
|
||||||
|
/**
|
||||||
|
* This is a list of set functions which will not appear in the settings
|
||||||
|
* menu. I don't know what to do with setKeyboardHandler. When I tried
|
||||||
|
* to use it, it didn't appear to be working. Someone who knows better
|
||||||
|
* could remove it from this list and add it's options to
|
||||||
|
* add_editor_menu_options.js
|
||||||
|
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||||
|
* Matthew Christopher Kastor-Inare III </a><br />
|
||||||
|
* ☭ Hial Atropa!! ☭
|
||||||
|
*/
|
||||||
|
var skip = [
|
||||||
|
'setOption',
|
||||||
|
'setUndoManager',
|
||||||
|
'setDocument',
|
||||||
|
'setValue',
|
||||||
|
'setBreakpoints',
|
||||||
|
'setScrollTop',
|
||||||
|
'setScrollLeft',
|
||||||
|
'setSelectionStyle',
|
||||||
|
'setWrapLimitRange'
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This will search the objects mapped to the `my` variable above. When
|
||||||
|
* it finds a set function in the object that is not listed in the
|
||||||
|
* `skip` list or the `opts` list it will push a new object to the
|
||||||
|
* output array.
|
||||||
|
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||||
|
* Matthew Christopher Kastor-Inare III </a><br />
|
||||||
|
* ☭ Hial Atropa!! ☭
|
||||||
|
*/
|
||||||
|
['renderer', 'session', 'editor'].forEach(function(esra) {
|
||||||
|
var esr = my[esra];
|
||||||
|
var clss = esra;
|
||||||
|
for(var fn in esr) {
|
||||||
|
if(skip.indexOf(fn) === -1) {
|
||||||
|
if(/^set/.test(fn) && opts.indexOf(fn) === -1) {
|
||||||
|
// found set function
|
||||||
|
opts.push(fn);
|
||||||
|
out.push({
|
||||||
|
'functionName' : fn,
|
||||||
|
'parentObj' : esr,
|
||||||
|
'parentName' : clss
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return out;
|
||||||
|
};
|
||||||
|
|
||||||
|
});
|
||||||
@@ -0,0 +1,116 @@
|
|||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Distributed under the BSD license:
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 Matthew Christopher Kastor-Inare III, Atropa Inc. Intl
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Contributed to Ajax.org under the BSD license.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of Ajax.org B.V. nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
/*jslint indent: 4, maxerr: 50, white: true, browser: true, vars: true*/
|
||||||
|
/*global define, require */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overlay Page
|
||||||
|
* @fileOverview Overlay Page <br />
|
||||||
|
* Generates an overlay for displaying menus. The overlay is an absolutely
|
||||||
|
* positioned div.
|
||||||
|
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||||
|
* Matthew Christopher Kastor-Inare III </a><br />
|
||||||
|
* ☭ Hial Atropa!! ☭
|
||||||
|
*/
|
||||||
|
|
||||||
|
define(function(require, exports, module) {
|
||||||
|
'use strict';
|
||||||
|
var dom = require("../../lib/dom");
|
||||||
|
var cssText = require("../../requirejs/text!./settings_menu.css");
|
||||||
|
dom.importCssString(cssText);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates an overlay for displaying menus. The overlay is an absolutely
|
||||||
|
* positioned div.
|
||||||
|
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||||
|
* Matthew Christopher Kastor-Inare III </a><br />
|
||||||
|
* ☭ Hial Atropa!! ☭
|
||||||
|
* @param {DOMElement} contentElement Any element which may be presented inside
|
||||||
|
* a div.
|
||||||
|
* @param {string|number} top absolute position value.
|
||||||
|
* @param {string|number} right absolute position value.
|
||||||
|
* @param {string|number} bottom absolute position value.
|
||||||
|
* @param {string|number} left absolute position value.
|
||||||
|
*/
|
||||||
|
module.exports.overlayPage = function overlayPage(editor, contentElement, top, right, bottom, left) {
|
||||||
|
top = top ? 'top: ' + top + ';' : '';
|
||||||
|
bottom = bottom ? 'bottom: ' + bottom + ';' : '';
|
||||||
|
right = right ? 'right: ' + right + ';' : '';
|
||||||
|
left = left ? 'left: ' + left + ';' : '';
|
||||||
|
|
||||||
|
var closer = document.createElement('div');
|
||||||
|
var contentContainer = document.createElement('div');
|
||||||
|
|
||||||
|
function documentEscListener(e) {
|
||||||
|
if (e.keyCode === 27) {
|
||||||
|
closer.click();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
closer.style.cssText = 'margin: 0; padding: 0; ' +
|
||||||
|
'position: fixed; top:0; bottom:0; left:0; right:0;' +
|
||||||
|
'z-index: 9990; ' +
|
||||||
|
'background-color: rgba(0, 0, 0, 0.3);';
|
||||||
|
closer.addEventListener('click', function() {
|
||||||
|
document.removeEventListener('keydown', documentEscListener);
|
||||||
|
closer.parentNode.removeChild(closer);
|
||||||
|
editor.focus();
|
||||||
|
closer = null;
|
||||||
|
});
|
||||||
|
// click closer if esc key is pressed
|
||||||
|
document.addEventListener('keydown', documentEscListener);
|
||||||
|
|
||||||
|
contentContainer.style.cssText = top + right + bottom + left;
|
||||||
|
contentContainer.addEventListener('click', function(e) {
|
||||||
|
e.stopPropagation();
|
||||||
|
});
|
||||||
|
|
||||||
|
var wrapper = dom.createElement("div");
|
||||||
|
wrapper.style.position = "relative";
|
||||||
|
|
||||||
|
var closeButton = dom.createElement("div");
|
||||||
|
closeButton.className = "ace_closeButton";
|
||||||
|
closeButton.addEventListener('click', function() {
|
||||||
|
closer.click();
|
||||||
|
});
|
||||||
|
|
||||||
|
wrapper.appendChild(closeButton);
|
||||||
|
contentContainer.appendChild(wrapper);
|
||||||
|
|
||||||
|
contentContainer.appendChild(contentElement);
|
||||||
|
closer.appendChild(contentContainer);
|
||||||
|
document.body.appendChild(closer);
|
||||||
|
editor.blur();
|
||||||
|
};
|
||||||
|
|
||||||
|
});
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
#ace_settingsmenu, #kbshortcutmenu {
|
||||||
|
background-color: #F7F7F7;
|
||||||
|
color: black;
|
||||||
|
box-shadow: -5px 4px 5px rgba(126, 126, 126, 0.55);
|
||||||
|
padding: 1em 0.5em 2em 1em;
|
||||||
|
overflow: auto;
|
||||||
|
position: absolute;
|
||||||
|
margin: 0;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
z-index: 9991;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ace_dark #ace_settingsmenu, .ace_dark #kbshortcutmenu {
|
||||||
|
box-shadow: -20px 10px 25px rgba(126, 126, 126, 0.25);
|
||||||
|
background-color: rgba(255, 255, 255, 0.6);
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ace_optionsMenuEntry:hover {
|
||||||
|
background-color: rgba(100, 100, 100, 0.1);
|
||||||
|
-webkit-transition: all 0.5s;
|
||||||
|
transition: all 0.3s
|
||||||
|
}
|
||||||
|
|
||||||
|
.ace_closeButton {
|
||||||
|
background: rgba(245, 146, 146, 0.5);
|
||||||
|
border: 1px solid #F48A8A;
|
||||||
|
border-radius: 50%;
|
||||||
|
padding: 7px;
|
||||||
|
position: absolute;
|
||||||
|
right: -8px;
|
||||||
|
top: -8px;
|
||||||
|
z-index: 1000;
|
||||||
|
}
|
||||||
|
.ace_closeButton{
|
||||||
|
background: rgba(245, 146, 146, 0.9);
|
||||||
|
}
|
||||||
|
.ace_optionsMenuKey {
|
||||||
|
color: darkslateblue;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.ace_optionsMenuCommand {
|
||||||
|
color: darkcyan;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
@@ -0,0 +1,195 @@
|
|||||||
|
define(function(require, exports, module) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var modes = [];
|
||||||
|
/**
|
||||||
|
* Suggests a mode based on the file extension present in the given path
|
||||||
|
* @param {string} path The path to the file
|
||||||
|
* @returns {object} Returns an object containing information about the
|
||||||
|
* suggested mode.
|
||||||
|
*/
|
||||||
|
function getModeForPath(path) {
|
||||||
|
var mode = modesByName.text;
|
||||||
|
var fileName = path.split(/[\/\\]/).pop();
|
||||||
|
for (var i = 0; i < modes.length; i++) {
|
||||||
|
if (modes[i].supportsFile(fileName)) {
|
||||||
|
mode = modes[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
var Mode = function(name, caption, extensions) {
|
||||||
|
this.name = name;
|
||||||
|
this.caption = caption;
|
||||||
|
this.mode = "ace/mode/" + name;
|
||||||
|
this.extensions = extensions;
|
||||||
|
if (/\^/.test(extensions)) {
|
||||||
|
var re = extensions.replace(/\|(\^)?/g, function(a, b){
|
||||||
|
return "$|" + (b ? "^" : "^.*\\.");
|
||||||
|
}) + "$";
|
||||||
|
} else {
|
||||||
|
var re = "^.*\\.(" + extensions + ")$";
|
||||||
|
}
|
||||||
|
|
||||||
|
this.extRe = new RegExp(re, "gi");
|
||||||
|
};
|
||||||
|
|
||||||
|
Mode.prototype.supportsFile = function(filename) {
|
||||||
|
return filename.match(this.extRe);
|
||||||
|
};
|
||||||
|
|
||||||
|
// todo firstlinematch
|
||||||
|
var supportedModes = {
|
||||||
|
ABAP: ["abap"],
|
||||||
|
ABC: ["abc"],
|
||||||
|
ActionScript:["as"],
|
||||||
|
ADA: ["ada|adb"],
|
||||||
|
Apache_Conf: ["^htaccess|^htgroups|^htpasswd|^conf|htaccess|htgroups|htpasswd"],
|
||||||
|
AsciiDoc: ["asciidoc"],
|
||||||
|
Assembly_x86:["asm"],
|
||||||
|
AutoHotKey: ["ahk"],
|
||||||
|
BatchFile: ["bat|cmd"],
|
||||||
|
C9Search: ["c9search_results"],
|
||||||
|
C_Cpp: ["cpp|c|cc|cxx|h|hh|hpp"],
|
||||||
|
Cirru: ["cirru|cr"],
|
||||||
|
Clojure: ["clj|cljs"],
|
||||||
|
Cobol: ["CBL|COB"],
|
||||||
|
coffee: ["coffee|cf|cson|^Cakefile"],
|
||||||
|
ColdFusion: ["cfm"],
|
||||||
|
CSharp: ["cs"],
|
||||||
|
CSS: ["css"],
|
||||||
|
Curly: ["curly"],
|
||||||
|
D: ["d|di"],
|
||||||
|
Dart: ["dart"],
|
||||||
|
Diff: ["diff|patch"],
|
||||||
|
Dockerfile: ["^Dockerfile"],
|
||||||
|
Dot: ["dot"],
|
||||||
|
Dummy: ["dummy"],
|
||||||
|
DummySyntax: ["dummy"],
|
||||||
|
Eiffel: ["e"],
|
||||||
|
EJS: ["ejs"],
|
||||||
|
Elixir: ["ex|exs"],
|
||||||
|
Elm: ["elm"],
|
||||||
|
Erlang: ["erl|hrl"],
|
||||||
|
Forth: ["frt|fs|ldr"],
|
||||||
|
FTL: ["ftl"],
|
||||||
|
Gcode: ["gcode"],
|
||||||
|
Gherkin: ["feature"],
|
||||||
|
Gitignore: ["^.gitignore"],
|
||||||
|
Glsl: ["glsl|frag|vert"],
|
||||||
|
golang: ["go"],
|
||||||
|
Groovy: ["groovy"],
|
||||||
|
HAML: ["haml"],
|
||||||
|
Handlebars: ["hbs|handlebars|tpl|mustache"],
|
||||||
|
Haskell: ["hs"],
|
||||||
|
haXe: ["hx"],
|
||||||
|
HTML: ["html|htm|xhtml"],
|
||||||
|
HTML_Ruby: ["erb|rhtml|html.erb"],
|
||||||
|
INI: ["ini|conf|cfg|prefs"],
|
||||||
|
Io: ["io"],
|
||||||
|
Jack: ["jack"],
|
||||||
|
Jade: ["jade"],
|
||||||
|
Java: ["java"],
|
||||||
|
JavaScript: ["js|jsm"],
|
||||||
|
JSON: ["json"],
|
||||||
|
JSONiq: ["jq"],
|
||||||
|
JSP: ["jsp"],
|
||||||
|
JSX: ["jsx"],
|
||||||
|
Julia: ["jl"],
|
||||||
|
LaTeX: ["tex|latex|ltx|bib"],
|
||||||
|
LESS: ["less"],
|
||||||
|
Liquid: ["liquid"],
|
||||||
|
Lisp: ["lisp"],
|
||||||
|
LiveScript: ["ls"],
|
||||||
|
LogiQL: ["logic|lql"],
|
||||||
|
LSL: ["lsl"],
|
||||||
|
Lua: ["lua"],
|
||||||
|
LuaPage: ["lp"],
|
||||||
|
Lucene: ["lucene"],
|
||||||
|
Makefile: ["^Makefile|^GNUmakefile|^makefile|^OCamlMakefile|make"],
|
||||||
|
Markdown: ["md|markdown"],
|
||||||
|
Mask: ["mask"],
|
||||||
|
MATLAB: ["matlab"],
|
||||||
|
MEL: ["mel"],
|
||||||
|
MUSHCode: ["mc|mush"],
|
||||||
|
MySQL: ["mysql"],
|
||||||
|
Nix: ["nix"],
|
||||||
|
ObjectiveC: ["m|mm"],
|
||||||
|
OCaml: ["ml|mli"],
|
||||||
|
Pascal: ["pas|p"],
|
||||||
|
Perl: ["pl|pm"],
|
||||||
|
pgSQL: ["pgsql"],
|
||||||
|
PHP: ["php|phtml"],
|
||||||
|
Powershell: ["ps1"],
|
||||||
|
Praat: ["praat|praatscript|psc|proc"],
|
||||||
|
Prolog: ["plg|prolog"],
|
||||||
|
Properties: ["properties"],
|
||||||
|
Protobuf: ["proto"],
|
||||||
|
Python: ["py"],
|
||||||
|
R: ["r"],
|
||||||
|
RDoc: ["Rd"],
|
||||||
|
RHTML: ["Rhtml"],
|
||||||
|
Ruby: ["rb|ru|gemspec|rake|^Guardfile|^Rakefile|^Gemfile"],
|
||||||
|
Rust: ["rs"],
|
||||||
|
SASS: ["sass"],
|
||||||
|
SCAD: ["scad"],
|
||||||
|
Scala: ["scala"],
|
||||||
|
Scheme: ["scm|rkt"],
|
||||||
|
SCSS: ["scss"],
|
||||||
|
SH: ["sh|bash|^.bashrc"],
|
||||||
|
SJS: ["sjs"],
|
||||||
|
Smarty: ["smarty|tpl"],
|
||||||
|
snippets: ["snippets"],
|
||||||
|
Soy_Template:["soy"],
|
||||||
|
Space: ["space"],
|
||||||
|
SQL: ["sql"],
|
||||||
|
Stylus: ["styl|stylus"],
|
||||||
|
SVG: ["svg"],
|
||||||
|
Tcl: ["tcl"],
|
||||||
|
Tex: ["tex"],
|
||||||
|
Text: ["txt"],
|
||||||
|
Textile: ["textile"],
|
||||||
|
Toml: ["toml"],
|
||||||
|
Twig: ["twig"],
|
||||||
|
Typescript: ["ts|typescript|str"],
|
||||||
|
Vala: ["vala"],
|
||||||
|
VBScript: ["vbs|vb"],
|
||||||
|
Velocity: ["vm"],
|
||||||
|
Verilog: ["v|vh|sv|svh"],
|
||||||
|
VHDL: ["vhd|vhdl"],
|
||||||
|
XML: ["xml|rdf|rss|wsdl|xslt|atom|mathml|mml|xul|xbl"],
|
||||||
|
XQuery: ["xq"],
|
||||||
|
YAML: ["yaml|yml"],
|
||||||
|
// Add the missing mode "Django" to ext-modelist
|
||||||
|
Django: ["html"]
|
||||||
|
};
|
||||||
|
|
||||||
|
var nameOverrides = {
|
||||||
|
ObjectiveC: "Objective-C",
|
||||||
|
CSharp: "C#",
|
||||||
|
golang: "Go",
|
||||||
|
C_Cpp: "C and C++",
|
||||||
|
coffee: "CoffeeScript",
|
||||||
|
HTML_Ruby: "HTML (Ruby)",
|
||||||
|
FTL: "FreeMarker"
|
||||||
|
};
|
||||||
|
var modesByName = {};
|
||||||
|
for (var name in supportedModes) {
|
||||||
|
var data = supportedModes[name];
|
||||||
|
var displayName = (nameOverrides[name] || name).replace(/_/g, " ");
|
||||||
|
var filename = name.toLowerCase();
|
||||||
|
var mode = new Mode(filename, displayName, data[0]);
|
||||||
|
modesByName[filename] = mode;
|
||||||
|
modes.push(mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
getModeForPath: getModeForPath,
|
||||||
|
modes: modes,
|
||||||
|
modesByName: modesByName
|
||||||
|
};
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
@@ -0,0 +1,114 @@
|
|||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Distributed under the BSD license:
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010, Ajax.org B.V.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of Ajax.org B.V. nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
define(function(require, exports, module) {
|
||||||
|
"use strict";
|
||||||
|
var MAX_TOKEN_COUNT = 1000;
|
||||||
|
var useragent = require("../lib/useragent");
|
||||||
|
var TokenizerModule = require("../tokenizer");
|
||||||
|
|
||||||
|
function patch(obj, name, regexp, replacement) {
|
||||||
|
eval("obj['" + name + "']=" + obj[name].toString().replace(
|
||||||
|
regexp, replacement
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (useragent.isIE && useragent.isIE < 10 && window.top.document.compatMode === "BackCompat")
|
||||||
|
useragent.isOldIE = true;
|
||||||
|
|
||||||
|
if (typeof document != "undefined" && !document.documentElement.querySelector) {
|
||||||
|
useragent.isOldIE = true;
|
||||||
|
var qs = function(el, selector) {
|
||||||
|
if (selector.charAt(0) == ".") {
|
||||||
|
var classNeme = selector.slice(1);
|
||||||
|
} else {
|
||||||
|
var m = selector.match(/(\w+)=(\w+)/);
|
||||||
|
var attr = m && m[1];
|
||||||
|
var attrVal = m && m[2];
|
||||||
|
}
|
||||||
|
for (var i = 0; i < el.all.length; i++) {
|
||||||
|
var ch = el.all[i];
|
||||||
|
if (classNeme) {
|
||||||
|
if (ch.className.indexOf(classNeme) != -1)
|
||||||
|
return ch;
|
||||||
|
} else if (attr) {
|
||||||
|
if (ch.getAttribute(attr) == attrVal)
|
||||||
|
return ch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var sb = require("./searchbox").SearchBox.prototype;
|
||||||
|
patch(
|
||||||
|
sb, "$initElements",
|
||||||
|
/([^\s=]*).querySelector\((".*?")\)/g,
|
||||||
|
"qs($1, $2)"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
var compliantExecNpcg = /()??/.exec("")[1] === undefined;
|
||||||
|
if (compliantExecNpcg)
|
||||||
|
return;
|
||||||
|
var proto = TokenizerModule.Tokenizer.prototype;
|
||||||
|
TokenizerModule.Tokenizer_orig = TokenizerModule.Tokenizer;
|
||||||
|
proto.getLineTokens_orig = proto.getLineTokens;
|
||||||
|
|
||||||
|
patch(
|
||||||
|
TokenizerModule, "Tokenizer",
|
||||||
|
"ruleRegExps.push(adjustedregex);\n",
|
||||||
|
function(m) {
|
||||||
|
return m + '\
|
||||||
|
if (state[i].next && RegExp(adjustedregex).test(""))\n\
|
||||||
|
rule._qre = RegExp(adjustedregex, "g");\n\
|
||||||
|
';
|
||||||
|
}
|
||||||
|
);
|
||||||
|
TokenizerModule.Tokenizer.prototype = proto;
|
||||||
|
patch(
|
||||||
|
proto, "getLineTokens",
|
||||||
|
/if \(match\[i \+ 1\] === undefined\)\s*continue;/,
|
||||||
|
"if (!match[i + 1]) {\n\
|
||||||
|
if (value)continue;\n\
|
||||||
|
var qre = state[mapping[i]]._qre;\n\
|
||||||
|
if (!qre) continue;\n\
|
||||||
|
qre.lastIndex = lastIndex;\n\
|
||||||
|
if (!qre.exec(line) || qre.lastIndex != lastIndex)\n\
|
||||||
|
continue;\n\
|
||||||
|
}"
|
||||||
|
);
|
||||||
|
|
||||||
|
patch(
|
||||||
|
require("../mode/text").Mode.prototype, "getTokenizer",
|
||||||
|
/Tokenizer/,
|
||||||
|
"TokenizerModule.Tokenizer"
|
||||||
|
);
|
||||||
|
|
||||||
|
useragent.isOldIE = true;
|
||||||
|
|
||||||
|
});
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Distributed under the BSD license:
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010, Ajax.org B.V.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of Ajax.org B.V. nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
if (typeof process !== "undefined") {
|
||||||
|
require("amd-loader");
|
||||||
|
}
|
||||||
|
|
||||||
|
define(function(require, exports, module) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var assert = require("../test/assertions");
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
"test: getTokenizer() (smoke test)" : function() {
|
||||||
|
var exec = RegExp.prototype.exec
|
||||||
|
var brokenExec = function(str) {
|
||||||
|
var result = exec.call(this, str);
|
||||||
|
if (result) {
|
||||||
|
for (var i = result.length; i--;)
|
||||||
|
if (!result[i])
|
||||||
|
result[i] = "";
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// break this to emulate old ie
|
||||||
|
RegExp.prototype.exec = brokenExec;
|
||||||
|
require("./old_ie");
|
||||||
|
var Tokenizer = require("../tokenizer").Tokenizer;
|
||||||
|
var JavaScriptHighlightRules = require("../mode/javascript_highlight_rules").JavaScriptHighlightRules;
|
||||||
|
var tokenizer = new Tokenizer((new JavaScriptHighlightRules).getRules());
|
||||||
|
|
||||||
|
var tokens = tokenizer.getLineTokens("'juhu'", "start").tokens;
|
||||||
|
assert.equal("string", tokens[0].type);
|
||||||
|
} finally {
|
||||||
|
// restore modified functions
|
||||||
|
RegExp.prototype.exec = exec;
|
||||||
|
var module = require("../tokenizer");
|
||||||
|
module.Tokenizer = module.Tokenizer_orig;
|
||||||
|
module.Tokenizer.prototype.getLineTokens = module.Tokenizer.prototype.getLineTokens_orig;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
if (typeof module !== "undefined" && module === require.main) {
|
||||||
|
require("asyncjs").test.testcase(module.exports).exec()
|
||||||
|
}
|
||||||
@@ -0,0 +1,153 @@
|
|||||||
|
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------------------------
|
||||||
|
* Editor Search Form
|
||||||
|
* --------------------------------------------------------------------------------------- */
|
||||||
|
.ace_search {
|
||||||
|
background-color: #ddd;
|
||||||
|
border: 1px solid #cbcbcb;
|
||||||
|
border-top: 0 none;
|
||||||
|
max-width: 325px;
|
||||||
|
overflow: hidden;
|
||||||
|
margin: 0;
|
||||||
|
padding: 4px;
|
||||||
|
padding-right: 6px;
|
||||||
|
padding-bottom: 0;
|
||||||
|
position: absolute;
|
||||||
|
top: 0px;
|
||||||
|
z-index: 99;
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
|
.ace_search.left {
|
||||||
|
border-left: 0 none;
|
||||||
|
border-radius: 0px 0px 5px 0px;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
.ace_search.right {
|
||||||
|
border-radius: 0px 0px 0px 5px;
|
||||||
|
border-right: 0 none;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ace_search_form, .ace_replace_form {
|
||||||
|
border-radius: 3px;
|
||||||
|
border: 1px solid #cbcbcb;
|
||||||
|
float: left;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.ace_search_form.ace_nomatch {
|
||||||
|
outline: 1px solid red;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ace_search_field {
|
||||||
|
background-color: white;
|
||||||
|
border-right: 1px solid #cbcbcb;
|
||||||
|
border: 0 none;
|
||||||
|
-webkit-box-sizing: border-box;
|
||||||
|
-moz-box-sizing: border-box;
|
||||||
|
box-sizing: border-box;
|
||||||
|
float: left;
|
||||||
|
height: 22px;
|
||||||
|
outline: 0;
|
||||||
|
padding: 0 7px;
|
||||||
|
width: 214px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
.ace_searchbtn,
|
||||||
|
.ace_replacebtn {
|
||||||
|
background: #fff;
|
||||||
|
border: 0 none;
|
||||||
|
border-left: 1px solid #dcdcdc;
|
||||||
|
cursor: pointer;
|
||||||
|
float: left;
|
||||||
|
height: 22px;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.ace_searchbtn:last-child,
|
||||||
|
.ace_replacebtn:last-child {
|
||||||
|
border-top-right-radius: 3px;
|
||||||
|
border-bottom-right-radius: 3px;
|
||||||
|
}
|
||||||
|
.ace_searchbtn:disabled {
|
||||||
|
background: none;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
.ace_searchbtn {
|
||||||
|
background-position: 50% 50%;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
width: 27px;
|
||||||
|
}
|
||||||
|
.ace_searchbtn.prev {
|
||||||
|
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAFCAYAAAB4ka1VAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADFJREFUeNpiSU1NZUAC/6E0I0yACYskCpsJiySKIiY0SUZk40FyTEgCjGgKwTRAgAEAQJUIPCE+qfkAAAAASUVORK5CYII=);
|
||||||
|
}
|
||||||
|
.ace_searchbtn.next {
|
||||||
|
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAFCAYAAAB4ka1VAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADRJREFUeNpiTE1NZQCC/0DMyIAKwGJMUAYDEo3M/s+EpvM/mkKwCQxYjIeLMaELoLMBAgwAU7UJObTKsvAAAAAASUVORK5CYII=);
|
||||||
|
}
|
||||||
|
.ace_searchbtn_close {
|
||||||
|
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAcCAYAAABRVo5BAAAAZ0lEQVR42u2SUQrAMAhDvazn8OjZBilCkYVVxiis8H4CT0VrAJb4WHT3C5xU2a2IQZXJjiQIRMdkEoJ5Q2yMqpfDIo+XY4k6h+YXOyKqTIj5REaxloNAd0xiKmAtsTHqW8sR2W5f7gCu5nWFUpVjZwAAAABJRU5ErkJggg==) no-repeat 50% 0;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 0 none;
|
||||||
|
color: #656565;
|
||||||
|
cursor: pointer;
|
||||||
|
float: right;
|
||||||
|
font: 16px/16px Arial;
|
||||||
|
height: 14px;
|
||||||
|
margin: 5px 1px 9px 5px;
|
||||||
|
padding: 0;
|
||||||
|
text-align: center;
|
||||||
|
width: 14px;
|
||||||
|
}
|
||||||
|
.ace_searchbtn_close:hover {
|
||||||
|
background-color: #656565;
|
||||||
|
background-position: 50% 100%;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
.ace_replacebtn.prev {
|
||||||
|
width: 54px
|
||||||
|
}
|
||||||
|
.ace_replacebtn.next {
|
||||||
|
width: 27px
|
||||||
|
}
|
||||||
|
|
||||||
|
.ace_button {
|
||||||
|
margin-left: 2px;
|
||||||
|
cursor: pointer;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-o-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
overflow: hidden;
|
||||||
|
opacity: 0.7;
|
||||||
|
border: 1px solid rgba(100,100,100,0.23);
|
||||||
|
padding: 1px;
|
||||||
|
-moz-box-sizing: border-box;
|
||||||
|
box-sizing: border-box;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ace_button:hover {
|
||||||
|
background-color: #eee;
|
||||||
|
opacity:1;
|
||||||
|
}
|
||||||
|
.ace_button:active {
|
||||||
|
background-color: #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ace_button.checked {
|
||||||
|
border-color: #3399ff;
|
||||||
|
opacity:1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ace_search_options{
|
||||||
|
margin-bottom: 3px;
|
||||||
|
text-align: right;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-o-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
@@ -0,0 +1,308 @@
|
|||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Distributed under the BSD license:
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010, Ajax.org B.V.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of Ajax.org B.V. nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
define(function(require, exports, module) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var dom = require("../lib/dom");
|
||||||
|
var lang = require("../lib/lang");
|
||||||
|
var event = require("../lib/event");
|
||||||
|
var searchboxCss = require("../requirejs/text!./searchbox.css");
|
||||||
|
var HashHandler = require("../keyboard/hash_handler").HashHandler;
|
||||||
|
var keyUtil = require("../lib/keys");
|
||||||
|
|
||||||
|
dom.importCssString(searchboxCss, "ace_searchbox");
|
||||||
|
|
||||||
|
var html = '<div class="ace_search right">\
|
||||||
|
<button type="button" action="hide" class="ace_searchbtn_close"></button>\
|
||||||
|
<div class="ace_search_form">\
|
||||||
|
<input class="ace_search_field" placeholder="Search for" spellcheck="false"></input>\
|
||||||
|
<button type="button" action="findNext" class="ace_searchbtn next"></button>\
|
||||||
|
<button type="button" action="findPrev" class="ace_searchbtn prev"></button>\
|
||||||
|
<button type="button" action="findAll" class="ace_searchbtn" title="Alt-Enter">All</button>\
|
||||||
|
</div>\
|
||||||
|
<div class="ace_replace_form">\
|
||||||
|
<input class="ace_search_field" placeholder="Replace with" spellcheck="false"></input>\
|
||||||
|
<button type="button" action="replaceAndFindNext" class="ace_replacebtn">Replace</button>\
|
||||||
|
<button type="button" action="replaceAll" class="ace_replacebtn">All</button>\
|
||||||
|
</div>\
|
||||||
|
<div class="ace_search_options">\
|
||||||
|
<span action="toggleRegexpMode" class="ace_button" title="RegExp Search">.*</span>\
|
||||||
|
<span action="toggleCaseSensitive" class="ace_button" title="CaseSensitive Search">Aa</span>\
|
||||||
|
<span action="toggleWholeWords" class="ace_button" title="Whole Word Search">\\b</span>\
|
||||||
|
</div>\
|
||||||
|
</div>'.replace(/>\s+/g, ">");
|
||||||
|
|
||||||
|
var SearchBox = function(editor, range, showReplaceForm) {
|
||||||
|
var div = dom.createElement("div");
|
||||||
|
div.innerHTML = html;
|
||||||
|
this.element = div.firstChild;
|
||||||
|
|
||||||
|
this.$init();
|
||||||
|
this.setEditor(editor);
|
||||||
|
};
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
this.setEditor = function(editor) {
|
||||||
|
editor.searchBox = this;
|
||||||
|
editor.container.appendChild(this.element);
|
||||||
|
this.editor = editor;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.$initElements = function(sb) {
|
||||||
|
this.searchBox = sb.querySelector(".ace_search_form");
|
||||||
|
this.replaceBox = sb.querySelector(".ace_replace_form");
|
||||||
|
this.searchOptions = sb.querySelector(".ace_search_options");
|
||||||
|
this.regExpOption = sb.querySelector("[action=toggleRegexpMode]");
|
||||||
|
this.caseSensitiveOption = sb.querySelector("[action=toggleCaseSensitive]");
|
||||||
|
this.wholeWordOption = sb.querySelector("[action=toggleWholeWords]");
|
||||||
|
this.searchInput = this.searchBox.querySelector(".ace_search_field");
|
||||||
|
this.replaceInput = this.replaceBox.querySelector(".ace_search_field");
|
||||||
|
};
|
||||||
|
|
||||||
|
this.$init = function() {
|
||||||
|
var sb = this.element;
|
||||||
|
|
||||||
|
this.$initElements(sb);
|
||||||
|
|
||||||
|
var _this = this;
|
||||||
|
event.addListener(sb, "mousedown", function(e) {
|
||||||
|
setTimeout(function(){
|
||||||
|
_this.activeInput.focus();
|
||||||
|
}, 0);
|
||||||
|
event.stopPropagation(e);
|
||||||
|
});
|
||||||
|
event.addListener(sb, "click", function(e) {
|
||||||
|
var t = e.target || e.srcElement;
|
||||||
|
var action = t.getAttribute("action");
|
||||||
|
if (action && _this[action])
|
||||||
|
_this[action]();
|
||||||
|
else if (_this.$searchBarKb.commands[action])
|
||||||
|
_this.$searchBarKb.commands[action].exec(_this);
|
||||||
|
event.stopPropagation(e);
|
||||||
|
});
|
||||||
|
|
||||||
|
event.addCommandKeyListener(sb, function(e, hashId, keyCode) {
|
||||||
|
var keyString = keyUtil.keyCodeToString(keyCode);
|
||||||
|
var command = _this.$searchBarKb.findKeyCommand(hashId, keyString);
|
||||||
|
if (command && command.exec) {
|
||||||
|
command.exec(_this);
|
||||||
|
event.stopEvent(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.$onChange = lang.delayedCall(function() {
|
||||||
|
_this.find(false, false);
|
||||||
|
});
|
||||||
|
|
||||||
|
event.addListener(this.searchInput, "input", function() {
|
||||||
|
_this.$onChange.schedule(20);
|
||||||
|
});
|
||||||
|
event.addListener(this.searchInput, "focus", function() {
|
||||||
|
_this.activeInput = _this.searchInput;
|
||||||
|
_this.searchInput.value && _this.highlight();
|
||||||
|
});
|
||||||
|
event.addListener(this.replaceInput, "focus", function() {
|
||||||
|
_this.activeInput = _this.replaceInput;
|
||||||
|
_this.searchInput.value && _this.highlight();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
//keybinging outsite of the searchbox
|
||||||
|
this.$closeSearchBarKb = new HashHandler([{
|
||||||
|
bindKey: "Esc",
|
||||||
|
name: "closeSearchBar",
|
||||||
|
exec: function(editor) {
|
||||||
|
editor.searchBox.hide();
|
||||||
|
}
|
||||||
|
}]);
|
||||||
|
|
||||||
|
//keybinging outsite of the searchbox
|
||||||
|
this.$searchBarKb = new HashHandler();
|
||||||
|
this.$searchBarKb.bindKeys({
|
||||||
|
"Ctrl-f|Command-f|Ctrl-H|Command-Option-F": function(sb) {
|
||||||
|
var isReplace = sb.isReplace = !sb.isReplace;
|
||||||
|
sb.replaceBox.style.display = isReplace ? "" : "none";
|
||||||
|
sb[isReplace ? "replaceInput" : "searchInput"].focus();
|
||||||
|
},
|
||||||
|
"Ctrl-G|Command-G": function(sb) {
|
||||||
|
sb.findNext();
|
||||||
|
},
|
||||||
|
"Ctrl-Shift-G|Command-Shift-G": function(sb) {
|
||||||
|
sb.findPrev();
|
||||||
|
},
|
||||||
|
"esc": function(sb) {
|
||||||
|
setTimeout(function() { sb.hide();});
|
||||||
|
},
|
||||||
|
"Return": function(sb) {
|
||||||
|
if (sb.activeInput == sb.replaceInput)
|
||||||
|
sb.replace();
|
||||||
|
sb.findNext();
|
||||||
|
},
|
||||||
|
"Shift-Return": function(sb) {
|
||||||
|
if (sb.activeInput == sb.replaceInput)
|
||||||
|
sb.replace();
|
||||||
|
sb.findPrev();
|
||||||
|
},
|
||||||
|
"Alt-Return": function(sb) {
|
||||||
|
if (sb.activeInput == sb.replaceInput)
|
||||||
|
sb.replaceAll();
|
||||||
|
sb.findAll();
|
||||||
|
},
|
||||||
|
"Tab": function(sb) {
|
||||||
|
(sb.activeInput == sb.replaceInput ? sb.searchInput : sb.replaceInput).focus();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.$searchBarKb.addCommands([{
|
||||||
|
name: "toggleRegexpMode",
|
||||||
|
bindKey: {win: "Alt-R|Alt-/", mac: "Ctrl-Alt-R|Ctrl-Alt-/"},
|
||||||
|
exec: function(sb) {
|
||||||
|
sb.regExpOption.checked = !sb.regExpOption.checked;
|
||||||
|
sb.$syncOptions();
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
name: "toggleCaseSensitive",
|
||||||
|
bindKey: {win: "Alt-C|Alt-I", mac: "Ctrl-Alt-R|Ctrl-Alt-I"},
|
||||||
|
exec: function(sb) {
|
||||||
|
sb.caseSensitiveOption.checked = !sb.caseSensitiveOption.checked;
|
||||||
|
sb.$syncOptions();
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
name: "toggleWholeWords",
|
||||||
|
bindKey: {win: "Alt-B|Alt-W", mac: "Ctrl-Alt-B|Ctrl-Alt-W"},
|
||||||
|
exec: function(sb) {
|
||||||
|
sb.wholeWordOption.checked = !sb.wholeWordOption.checked;
|
||||||
|
sb.$syncOptions();
|
||||||
|
}
|
||||||
|
}]);
|
||||||
|
|
||||||
|
this.$syncOptions = function() {
|
||||||
|
dom.setCssClass(this.regExpOption, "checked", this.regExpOption.checked);
|
||||||
|
dom.setCssClass(this.wholeWordOption, "checked", this.wholeWordOption.checked);
|
||||||
|
dom.setCssClass(this.caseSensitiveOption, "checked", this.caseSensitiveOption.checked);
|
||||||
|
this.find(false, false);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.highlight = function(re) {
|
||||||
|
this.editor.session.highlight(re || this.editor.$search.$options.re);
|
||||||
|
this.editor.renderer.updateBackMarkers()
|
||||||
|
};
|
||||||
|
this.find = function(skipCurrent, backwards) {
|
||||||
|
var range = this.editor.find(this.searchInput.value, {
|
||||||
|
skipCurrent: skipCurrent,
|
||||||
|
backwards: backwards,
|
||||||
|
wrap: true,
|
||||||
|
regExp: this.regExpOption.checked,
|
||||||
|
caseSensitive: this.caseSensitiveOption.checked,
|
||||||
|
wholeWord: this.wholeWordOption.checked
|
||||||
|
});
|
||||||
|
var noMatch = !range && this.searchInput.value;
|
||||||
|
dom.setCssClass(this.searchBox, "ace_nomatch", noMatch);
|
||||||
|
this.editor._emit("findSearchBox", { match: !noMatch });
|
||||||
|
this.highlight();
|
||||||
|
};
|
||||||
|
this.findNext = function() {
|
||||||
|
this.find(true, false);
|
||||||
|
};
|
||||||
|
this.findPrev = function() {
|
||||||
|
this.find(true, true);
|
||||||
|
};
|
||||||
|
this.findAll = function(){
|
||||||
|
var range = this.editor.findAll(this.searchInput.value, {
|
||||||
|
regExp: this.regExpOption.checked,
|
||||||
|
caseSensitive: this.caseSensitiveOption.checked,
|
||||||
|
wholeWord: this.wholeWordOption.checked
|
||||||
|
});
|
||||||
|
var noMatch = !range && this.searchInput.value;
|
||||||
|
dom.setCssClass(this.searchBox, "ace_nomatch", noMatch);
|
||||||
|
this.editor._emit("findSearchBox", { match: !noMatch });
|
||||||
|
this.highlight();
|
||||||
|
this.hide();
|
||||||
|
};
|
||||||
|
this.replace = function() {
|
||||||
|
if (!this.editor.getReadOnly())
|
||||||
|
this.editor.replace(this.replaceInput.value);
|
||||||
|
};
|
||||||
|
this.replaceAndFindNext = function() {
|
||||||
|
if (!this.editor.getReadOnly()) {
|
||||||
|
this.editor.replace(this.replaceInput.value);
|
||||||
|
this.findNext()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.replaceAll = function() {
|
||||||
|
if (!this.editor.getReadOnly())
|
||||||
|
this.editor.replaceAll(this.replaceInput.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.hide = function() {
|
||||||
|
this.element.style.display = "none";
|
||||||
|
this.editor.keyBinding.removeKeyboardHandler(this.$closeSearchBarKb);
|
||||||
|
this.editor.focus();
|
||||||
|
};
|
||||||
|
this.show = function(value, isReplace) {
|
||||||
|
this.element.style.display = "";
|
||||||
|
this.replaceBox.style.display = isReplace ? "" : "none";
|
||||||
|
|
||||||
|
this.isReplace = isReplace;
|
||||||
|
|
||||||
|
if (value)
|
||||||
|
this.searchInput.value = value;
|
||||||
|
this.searchInput.focus();
|
||||||
|
this.searchInput.select();
|
||||||
|
|
||||||
|
this.editor.keyBinding.addKeyboardHandler(this.$closeSearchBarKb);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.isFocused = function() {
|
||||||
|
var el = document.activeElement;
|
||||||
|
return el == this.searchInput || el == this.replaceInput;
|
||||||
|
}
|
||||||
|
}).call(SearchBox.prototype);
|
||||||
|
|
||||||
|
exports.SearchBox = SearchBox;
|
||||||
|
|
||||||
|
exports.Search = function(editor, isReplace) {
|
||||||
|
var sb = editor.searchBox || new SearchBox(editor);
|
||||||
|
sb.show(editor.session.getTextRange(), isReplace);
|
||||||
|
};
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------------------------
|
||||||
|
* TODO
|
||||||
|
* --------------------------------------------------------------------------------------- */
|
||||||
|
/*
|
||||||
|
- move search form to the left if it masks current word
|
||||||
|
- includ all options that search has. ex: regex
|
||||||
|
- searchbox.searchbox is not that pretty. we should have just searchbox
|
||||||
|
- disable prev button if it makes sence
|
||||||
|
*/
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Distributed under the BSD license:
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 Matthew Christopher Kastor-Inare III, Atropa Inc. Intl
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Contributed to Ajax.org under the BSD license.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of Ajax.org B.V. nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
/*jslint indent: 4, maxerr: 50, white: true, browser: true, vars: true*/
|
||||||
|
/*global define, require */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show Settings Menu
|
||||||
|
* @fileOverview Show Settings Menu <br />
|
||||||
|
* Displays an interactive settings menu mostly generated on the fly based on
|
||||||
|
* the current state of the editor.
|
||||||
|
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||||
|
* Matthew Christopher Kastor-Inare III </a><br />
|
||||||
|
* ☭ Hial Atropa!! ☭
|
||||||
|
*/
|
||||||
|
|
||||||
|
define(function(require, exports, module) {
|
||||||
|
"use strict";
|
||||||
|
var generateSettingsMenu = require('./menu_tools/generate_settings_menu').generateSettingsMenu;
|
||||||
|
var overlayPage = require('./menu_tools/overlay_page').overlayPage;
|
||||||
|
/**
|
||||||
|
* This displays the settings menu if it is not already being shown.
|
||||||
|
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||||
|
* Matthew Christopher Kastor-Inare III </a><br />
|
||||||
|
* ☭ Hial Atropa!! ☭
|
||||||
|
* @param {ace.Editor} editor An instance of the ace editor.
|
||||||
|
*/
|
||||||
|
function showSettingsMenu(editor) {
|
||||||
|
// make sure the menu isn't open already.
|
||||||
|
var sm = document.getElementById('ace_settingsmenu');
|
||||||
|
if (!sm)
|
||||||
|
overlayPage(editor, generateSettingsMenu(editor), '0', '0', '0');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the settings menu extension. It adds the showSettingsMenu
|
||||||
|
* method to the given editor object and adds the showSettingsMenu command
|
||||||
|
* to the editor with appropriate keyboard shortcuts.
|
||||||
|
* @param {ace.Editor} editor An instance of the Editor.
|
||||||
|
*/
|
||||||
|
module.exports.init = function(editor) {
|
||||||
|
var Editor = require("ace/editor").Editor;
|
||||||
|
Editor.prototype.showSettingsMenu = function() {
|
||||||
|
showSettingsMenu(this);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
define(function(require, exports, module) {
|
||||||
|
"use strict";
|
||||||
|
var event = require("../lib/event");
|
||||||
|
|
||||||
|
exports.contextMenuHandler = function(e){
|
||||||
|
var host = e.target;
|
||||||
|
var text = host.textInput.getElement();
|
||||||
|
if (!host.selection.isEmpty())
|
||||||
|
return;
|
||||||
|
var c = host.getCursorPosition();
|
||||||
|
var r = host.session.getWordRange(c.row, c.column);
|
||||||
|
var w = host.session.getTextRange(r);
|
||||||
|
|
||||||
|
host.session.tokenRe.lastIndex = 0;
|
||||||
|
if (!host.session.tokenRe.test(w))
|
||||||
|
return;
|
||||||
|
var PLACEHOLDER = "\x01\x01";
|
||||||
|
var value = w + " " + PLACEHOLDER;
|
||||||
|
text.value = value;
|
||||||
|
text.setSelectionRange(w.length, w.length + 1);
|
||||||
|
text.setSelectionRange(0, 0);
|
||||||
|
text.setSelectionRange(0, w.length);
|
||||||
|
|
||||||
|
var afterKeydown = false;
|
||||||
|
event.addListener(text, "keydown", function onKeydown() {
|
||||||
|
event.removeListener(text, "keydown", onKeydown);
|
||||||
|
afterKeydown = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
host.textInput.setInputHandler(function(newVal) {
|
||||||
|
console.log(newVal , value, text.selectionStart, text.selectionEnd)
|
||||||
|
if (newVal == value)
|
||||||
|
return '';
|
||||||
|
if (newVal.lastIndexOf(value, 0) === 0)
|
||||||
|
return newVal.slice(value.length);
|
||||||
|
if (newVal.substr(text.selectionEnd) == value)
|
||||||
|
return newVal.slice(0, -value.length);
|
||||||
|
if (newVal.slice(-2) == PLACEHOLDER) {
|
||||||
|
var val = newVal.slice(0, -2);
|
||||||
|
if (val.slice(-1) == " ") {
|
||||||
|
if (afterKeydown)
|
||||||
|
return val.substring(0, text.selectionEnd);
|
||||||
|
val = val.slice(0, -1);
|
||||||
|
host.session.replace(r, val);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return newVal;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// todo support highlighting with typo.js
|
||||||
|
var Editor = require("../editor").Editor;
|
||||||
|
require("../config").defineOptions(Editor.prototype, "editor", {
|
||||||
|
spellcheck: {
|
||||||
|
set: function(val) {
|
||||||
|
var text = this.textInput.getElement();
|
||||||
|
text.spellcheck = !!val;
|
||||||
|
if (!val)
|
||||||
|
this.removeListener("nativecontextmenu", exports.contextMenuHandler);
|
||||||
|
else
|
||||||
|
this.on("nativecontextmenu", exports.contextMenuHandler);
|
||||||
|
},
|
||||||
|
value: true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
+8
-10
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 2010, Ajax.org B.V.
|
* Copyright (c) 2010, Ajax.org B.V.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
* * Redistributions of source code must retain the above copyright
|
* * Redistributions of source code must retain the above copyright
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
* * Neither the name of Ajax.org B.V. nor the
|
* * Neither the name of Ajax.org B.V. nor the
|
||||||
* names of its contributors may be used to endorse or promote products
|
* names of its contributors may be used to endorse or promote products
|
||||||
* derived from this software without specific prior written permission.
|
* derived from this software without specific prior written permission.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
@@ -29,14 +29,12 @@
|
|||||||
* ***** END LICENSE BLOCK ***** */
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
define(function(require, exports, module) {
|
define(function(require, exports, module) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
"never use strict";
|
/**
|
||||||
|
* this is experimental, and subject to change, use at your own risk!
|
||||||
module.exports = {
|
*/
|
||||||
_default: {
|
module.exports = require("../split");
|
||||||
text: "",
|
|
||||||
isLine: false
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1,22 +1,31 @@
|
|||||||
.ace_editor {
|
.ace_static_highlight {
|
||||||
font-family: 'Monaco', 'Menlo', 'Droid Sans Mono', 'Courier New', monospace;
|
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro', 'Droid Sans Mono', monospace;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ace_editor .ace_gutter {
|
.ace_static_highlight .ace_gutter {
|
||||||
width: 25px !important;
|
width: 25px !important;
|
||||||
display: block;
|
|
||||||
float: left;
|
float: left;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
padding: 0 3px 0 0;
|
padding: 0 3px 0 0;
|
||||||
margin-right: 3px;
|
margin-right: 3px;
|
||||||
|
position: static !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ace_line { clear: both; }
|
.ace_static_highlight .ace_line { clear: both; }
|
||||||
|
|
||||||
*.ace_gutter-cell {
|
.ace_static_highlight .ace_gutter-cell {
|
||||||
-moz-user-select: -moz-none;
|
-moz-user-select: -moz-none;
|
||||||
-khtml-user-select: none;
|
-khtml-user-select: none;
|
||||||
-webkit-user-select: none;
|
-webkit-user-select: none;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.ace_static_highlight .ace_gutter-cell:before {
|
||||||
|
content: counter(ace_line, decimal);
|
||||||
|
counter-increment: ace_line;
|
||||||
|
}
|
||||||
|
.ace_static_highlight {
|
||||||
|
counter-reset: ace_line;
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 2010, Ajax.org B.V.
|
* Copyright (c) 2010, Ajax.org B.V.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
* * Redistributions of source code must retain the above copyright
|
* * Redistributions of source code must retain the above copyright
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
* * Neither the name of Ajax.org B.V. nor the
|
* * Neither the name of Ajax.org B.V. nor the
|
||||||
* names of its contributors may be used to endorse or promote products
|
* names of its contributors may be used to endorse or promote products
|
||||||
* derived from this software without specific prior written permission.
|
* derived from this software without specific prior written permission.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
@@ -34,55 +34,157 @@ define(function(require, exports, module) {
|
|||||||
var EditSession = require("../edit_session").EditSession;
|
var EditSession = require("../edit_session").EditSession;
|
||||||
var TextLayer = require("../layer/text").Text;
|
var TextLayer = require("../layer/text").Text;
|
||||||
var baseStyles = require("../requirejs/text!./static.css");
|
var baseStyles = require("../requirejs/text!./static.css");
|
||||||
|
var config = require("../config");
|
||||||
|
var dom = require("../lib/dom");
|
||||||
|
|
||||||
/* Transforms a given input code snippet into HTML using the given mode
|
|
||||||
*
|
|
||||||
* @param {string} input Code snippet
|
|
||||||
* @param {mode} mode Mode loaded from /ace/mode (use 'ServerSideHiglighter.getMode')
|
|
||||||
* @param {string} r Code snippet
|
|
||||||
* @returns {object} An object containing: html, css
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.render = function(input, mode, theme, lineStart, disableGutter) {
|
var highlight = function(el, opts, callback) {
|
||||||
|
var m = el.className.match(/lang-(\w+)/);
|
||||||
|
var mode = opts.mode || m && ("ace/mode/" + m[1]);
|
||||||
|
if (!mode)
|
||||||
|
return false;
|
||||||
|
var theme = opts.theme || "ace/theme/textmate";
|
||||||
|
|
||||||
|
var data = "";
|
||||||
|
var nodes = [];
|
||||||
|
|
||||||
|
if (el.firstElementChild) {
|
||||||
|
var textLen = 0;
|
||||||
|
for (var i = 0; i < el.childNodes.length; i++) {
|
||||||
|
var ch = el.childNodes[i];
|
||||||
|
if (ch.nodeType == 3) {
|
||||||
|
textLen += ch.data.length;
|
||||||
|
data += ch.data;
|
||||||
|
} else {
|
||||||
|
nodes.push(textLen, ch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
data = dom.getInnerText(el);
|
||||||
|
if (opts.trim)
|
||||||
|
data = data.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
highlight.render(data, mode, theme, opts.firstLineNumber, !opts.showGutter, function (highlighted) {
|
||||||
|
dom.importCssString(highlighted.css, "ace_highlight");
|
||||||
|
el.innerHTML = highlighted.html;
|
||||||
|
var container = el.firstChild.firstChild;
|
||||||
|
for (var i = 0; i < nodes.length; i += 2) {
|
||||||
|
var pos = highlighted.session.doc.indexToPosition(nodes[i]);
|
||||||
|
var node = nodes[i + 1];
|
||||||
|
var lineEl = container.children[pos.row];
|
||||||
|
lineEl && lineEl.appendChild(node);
|
||||||
|
}
|
||||||
|
callback && callback();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transforms a given input code snippet into HTML using the given mode
|
||||||
|
*
|
||||||
|
* @param {string} input Code snippet
|
||||||
|
* @param {string|mode} mode String specifying the mode to load such as
|
||||||
|
* `ace/mode/javascript` or, a mode loaded from `/ace/mode`
|
||||||
|
* (use 'ServerSideHiglighter.getMode').
|
||||||
|
* @param {string|theme} theme String specifying the theme to load such as
|
||||||
|
* `ace/theme/twilight` or, a theme loaded from `/ace/theme`.
|
||||||
|
* @param {number} lineStart A number indicating the first line number. Defaults
|
||||||
|
* to 1.
|
||||||
|
* @param {boolean} disableGutter Specifies whether or not to disable the gutter.
|
||||||
|
* `true` disables the gutter, `false` enables the gutter. Defaults to `false`.
|
||||||
|
* @param {function} callback When specifying the mode or theme as a string,
|
||||||
|
* this method has no return value and you must specify a callback function. The
|
||||||
|
* callback will receive the rendered object containing the properties `html`
|
||||||
|
* and `css`.
|
||||||
|
* @returns {object} An object containing the properties `html` and `css`.
|
||||||
|
*/
|
||||||
|
highlight.render = function(input, mode, theme, lineStart, disableGutter, callback) {
|
||||||
|
var waiting = 1;
|
||||||
|
var modeCache = EditSession.prototype.$modes;
|
||||||
|
|
||||||
|
// if either the theme or the mode were specified as objects
|
||||||
|
// then we need to lazily load them.
|
||||||
|
if (typeof theme == "string") {
|
||||||
|
waiting++;
|
||||||
|
config.loadModule(['theme', theme], function(m) {
|
||||||
|
theme = m;
|
||||||
|
--waiting || done();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// allow setting mode options e.h {path: "ace/mode/php", inline:true}
|
||||||
|
var modeOptions;
|
||||||
|
if (mode && typeof mode === "object" && !mode.getTokenizer) {
|
||||||
|
modeOptions = mode;
|
||||||
|
mode = modeOptions.path;
|
||||||
|
}
|
||||||
|
if (typeof mode == "string") {
|
||||||
|
waiting++;
|
||||||
|
config.loadModule(['mode', mode], function(m) {
|
||||||
|
if (!modeCache[mode] || modeOptions)
|
||||||
|
modeCache[mode] = new m.Mode(modeOptions);
|
||||||
|
mode = modeCache[mode];
|
||||||
|
--waiting || done();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// loads or passes the specified mode module then calls renderer
|
||||||
|
function done() {
|
||||||
|
var result = highlight.renderSync(input, mode, theme, lineStart, disableGutter);
|
||||||
|
return callback ? callback(result) : result;
|
||||||
|
}
|
||||||
|
return --waiting || done();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transforms a given input code snippet into HTML using the given mode
|
||||||
|
* @param {string} input Code snippet
|
||||||
|
* @param {mode} mode Mode loaded from /ace/mode (use 'ServerSideHiglighter.getMode')
|
||||||
|
* @param {string} r Code snippet
|
||||||
|
* @returns {object} An object containing: html, css
|
||||||
|
*/
|
||||||
|
highlight.renderSync = function(input, mode, theme, lineStart, disableGutter) {
|
||||||
lineStart = parseInt(lineStart || 1, 10);
|
lineStart = parseInt(lineStart || 1, 10);
|
||||||
|
|
||||||
var session = new EditSession("");
|
var session = new EditSession("");
|
||||||
session.setMode(mode);
|
|
||||||
session.setUseWorker(false);
|
session.setUseWorker(false);
|
||||||
|
session.setMode(mode);
|
||||||
|
|
||||||
var textLayer = new TextLayer(document.createElement("div"));
|
var textLayer = new TextLayer(document.createElement("div"));
|
||||||
textLayer.setSession(session);
|
textLayer.setSession(session);
|
||||||
textLayer.config = {
|
textLayer.config = {
|
||||||
characterWidth: 10,
|
characterWidth: 10,
|
||||||
lineHeight: 20
|
lineHeight: 20
|
||||||
};
|
};
|
||||||
|
|
||||||
session.setValue(input);
|
session.setValue(input);
|
||||||
|
|
||||||
var stringBuilder = [];
|
var stringBuilder = [];
|
||||||
var length = session.getLength();
|
var length = session.getLength();
|
||||||
|
|
||||||
for(var ix = 0; ix < length; ix++) {
|
for(var ix = 0; ix < length; ix++) {
|
||||||
stringBuilder.push("<div class='ace_line'>");
|
stringBuilder.push("<div class='ace_line'>");
|
||||||
if (!disableGutter)
|
if (!disableGutter)
|
||||||
stringBuilder.push("<span class='ace_gutter ace_gutter-cell' unselectable='on'>" + (ix + lineStart) + "</span>");
|
stringBuilder.push("<span class='ace_gutter ace_gutter-cell' unselectable='on'>" + /*(ix + lineStart) + */ "</span>");
|
||||||
textLayer.$renderLine(stringBuilder, ix, true, false);
|
textLayer.$renderLine(stringBuilder, ix, true, false);
|
||||||
stringBuilder.push("</div>");
|
stringBuilder.push("\n</div>");
|
||||||
}
|
}
|
||||||
|
|
||||||
// let's prepare the whole html
|
// let's prepare the whole html
|
||||||
var html = "<div class=':cssClass'>\
|
var html = "<div class='" + theme.cssClass + "'>" +
|
||||||
<div class='ace_editor ace_scroller ace_text-layer'>\
|
"<div class='ace_static_highlight' style='counter-reset:ace_line " + (lineStart - 1) + "'>" +
|
||||||
:code\
|
stringBuilder.join("") +
|
||||||
</div>\
|
"</div>" +
|
||||||
</div>".replace(/:cssClass/, theme.cssClass).replace(/:code/, stringBuilder.join(""));
|
"</div>";
|
||||||
|
|
||||||
textLayer.destroy();
|
textLayer.destroy();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
css: baseStyles + theme.cssText,
|
css: baseStyles + theme.cssText,
|
||||||
html: html
|
html: html,
|
||||||
|
session: session
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
module.exports = highlight;
|
||||||
|
module.exports.highlight =highlight;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -9,62 +9,82 @@ define(function(require, exports, module) {
|
|||||||
var assert = require("assert");
|
var assert = require("assert");
|
||||||
var highlighter = require("./static_highlight");
|
var highlighter = require("./static_highlight");
|
||||||
var JavaScriptMode = require("../mode/javascript").Mode;
|
var JavaScriptMode = require("../mode/javascript").Mode;
|
||||||
|
var TextMode = require("../mode/text").Mode;
|
||||||
|
|
||||||
// Execution ORDER: test.setUpSuite, setUp, testFn, tearDown, test.tearDownSuite
|
// Execution ORDER: test.setUpSuite, setUp, testFn, tearDown, test.tearDownSuite
|
||||||
module.exports = {
|
module.exports = {
|
||||||
timeout: 10000,
|
timeout: 10000,
|
||||||
|
|
||||||
"test simple snippet": function(next) {
|
"test simple snippet": function(next) {
|
||||||
var theme = require("../theme/tomorrow");
|
var theme = require("../theme/tomorrow");
|
||||||
var snippet = "\
|
var snippet = [
|
||||||
/** this is a function\n\
|
"/** this is a function",
|
||||||
*\n\
|
"*",
|
||||||
*/\n\
|
"*/",
|
||||||
function hello (a, b, c) {\n\
|
"function hello (a, b, c) {",
|
||||||
console.log(a * b + c + 'sup?');\n\
|
" console.log(a * b + c + 'sup$');",
|
||||||
}";
|
"}"
|
||||||
|
].join("\n");
|
||||||
var mode = new JavaScriptMode();
|
var mode = new JavaScriptMode();
|
||||||
|
|
||||||
var result = highlighter.render(snippet, mode, theme);
|
var result = highlighter.render(snippet, mode, theme);
|
||||||
assert.equal(result.html, "<div class='ace-tomorrow'> <div class='ace_editor ace_scroller ace_text-layer'> <div class='ace_line'><span class='ace_gutter ace_gutter-cell' unselectable='on'>1</span><span class='ace_comment ace_doc'>/** this is a function</span></div><div class='ace_line'><span class='ace_gutter ace_gutter-cell' unselectable='on'>2</span><span class='ace_comment ace_doc'>*</span></div><div class='ace_line'><span class='ace_gutter ace_gutter-cell' unselectable='on'>3</span><span class='ace_comment ace_doc'>*/</span></div><div class='ace_line'><span class='ace_gutter ace_gutter-cell' unselectable='on'>4</span><span class='ace_storage ace_type'>function</span> <span class='ace_entity ace_name ace_function'>hello</span> <span class='ace_paren ace_lparen'>(</span><span class='ace_variable ace_parameter'>a</span><span class='ace_punctuation ace_operator'>, </span><span class='ace_variable ace_parameter'>b</span><span class='ace_punctuation ace_operator'>, </span><span class='ace_variable ace_parameter'>c</span><span class='ace_paren ace_rparen'>)</span> <span class='ace_paren ace_lparen'>{</span></div><div class='ace_line'><span class='ace_gutter ace_gutter-cell' unselectable='on'>5</span>    <span class='ace_storage ace_type'>console</span><span class='ace_punctuation ace_operator'>.</span><span class='ace_support ace_function ace_firebug'>log</span><span class='ace_paren ace_lparen'>(</span><span class='ace_identifier'>a</span> <span class='ace_keyword ace_operator'>*</span> <span class='ace_identifier'>b</span> <span class='ace_keyword ace_operator'>+</span> <span class='ace_identifier'>c</span> <span class='ace_keyword ace_operator'>+</span> <span class='ace_string'>'sup?'</span><span class='ace_paren ace_rparen'>)</span><span class='ace_punctuation ace_operator'>;</span></div><div class='ace_line'><span class='ace_gutter ace_gutter-cell' unselectable='on'>6</span><span class='ace_paren ace_rparen'>}</span></div> </div> </div>");
|
assert.equal(result.html, "<div class='ace-tomorrow'><div class='ace_static_highlight' style='counter-reset:ace_line 0'>"
|
||||||
|
+ "<div class='ace_line'><span class='ace_gutter ace_gutter-cell' unselectable='on'></span><span class='ace_comment ace_doc'>/**\xa0this\xa0is\xa0a\xa0function</span>\n</div>"
|
||||||
|
+ "<div class='ace_line'><span class='ace_gutter ace_gutter-cell' unselectable='on'></span><span class='ace_comment ace_doc'>*</span>\n</div>"
|
||||||
|
+ "<div class='ace_line'><span class='ace_gutter ace_gutter-cell' unselectable='on'></span><span class='ace_comment ace_doc'>*/</span>\n</div>"
|
||||||
|
+ "<div class='ace_line'><span class='ace_gutter ace_gutter-cell' unselectable='on'></span><span class='ace_storage ace_type'>function</span>\xa0<span class='ace_entity ace_name ace_function'>hello</span>\xa0<span class='ace_paren ace_lparen'>(</span><span class='ace_variable ace_parameter'>a</span><span class='ace_punctuation ace_operator'>,\xa0</span><span class='ace_variable ace_parameter'>b</span><span class='ace_punctuation ace_operator'>,\xa0</span><span class='ace_variable ace_parameter'>c</span><span class='ace_paren ace_rparen'>)</span>\xa0<span class='ace_paren ace_lparen'>{</span>\n</div>"
|
||||||
|
+ "<div class='ace_line'><span class='ace_gutter ace_gutter-cell' unselectable='on'></span>\xa0\xa0\xa0\xa0<span class='ace_storage ace_type'>console</span><span class='ace_punctuation ace_operator'>.</span><span class='ace_support ace_function ace_firebug'>log</span><span class='ace_paren ace_lparen'>(</span><span class='ace_identifier'>a</span>\xa0<span class='ace_keyword ace_operator'>*</span>\xa0<span class='ace_identifier'>b</span>\xa0<span class='ace_keyword ace_operator'>+</span>\xa0<span class='ace_identifier'>c</span>\xa0<span class='ace_keyword ace_operator'>+</span>\xa0<span class='ace_string'>'sup$'</span><span class='ace_paren ace_rparen'>)</span><span class='ace_punctuation ace_operator'>;</span>\n</div>"
|
||||||
|
+ "<div class='ace_line'><span class='ace_gutter ace_gutter-cell' unselectable='on'></span><span class='ace_paren ace_rparen'>}</span>\n</div>"
|
||||||
|
+ "</div></div>");
|
||||||
assert.ok(!!result.css);
|
assert.ok(!!result.css);
|
||||||
next();
|
next();
|
||||||
},
|
},
|
||||||
|
|
||||||
"test css from theme is used": function(next) {
|
"test css from theme is used": function(next) {
|
||||||
var theme = require("../theme/tomorrow");
|
var theme = require("../theme/tomorrow");
|
||||||
var snippet = "\
|
var snippet = [
|
||||||
/** this is a function\n\
|
"/** this is a function",
|
||||||
*\n\
|
"*",
|
||||||
*/\n\
|
"*/",
|
||||||
function hello (a, b, c) {\n\
|
"function hello (a, b, c) {",
|
||||||
console.log(a * b + c + 'sup?');\n\
|
" console.log(a * b + c + 'sup?');",
|
||||||
}";
|
"}"
|
||||||
|
].join("\n");
|
||||||
var mode = new JavaScriptMode();
|
var mode = new JavaScriptMode();
|
||||||
|
|
||||||
var isError = false, result;
|
var result = highlighter.render(snippet, mode, theme);
|
||||||
result = highlighter.render(snippet, mode, theme);
|
|
||||||
|
|
||||||
assert.ok(result.css.indexOf(theme.cssText) !== -1);
|
assert.ok(result.css.indexOf(theme.cssText) !== -1);
|
||||||
|
|
||||||
|
next();
|
||||||
|
},
|
||||||
|
|
||||||
|
"test theme classname should be in output html": function(next) {
|
||||||
|
var theme = require("../theme/tomorrow");
|
||||||
|
var snippet = [
|
||||||
|
"/** this is a function",
|
||||||
|
"*",
|
||||||
|
"*/",
|
||||||
|
"function hello (a, b, c) {",
|
||||||
|
" console.log(a * b + c + 'sup?');",
|
||||||
|
"}"
|
||||||
|
].join("\n");
|
||||||
|
var mode = new JavaScriptMode();
|
||||||
|
|
||||||
|
var result = highlighter.render(snippet, mode, theme);
|
||||||
|
assert.equal(!!result.html.match(/<div class='ace-tomorrow'>/), true);
|
||||||
|
|
||||||
next();
|
next();
|
||||||
},
|
},
|
||||||
|
|
||||||
"test theme classname should be in output html": function (next) {
|
"test js string replace specials": function(next) {
|
||||||
var theme = require("../theme/tomorrow");
|
var theme = require("../theme/tomorrow");
|
||||||
var snippet = "\
|
var snippet = "$'$1$2$$$&";
|
||||||
/** this is a function\n\
|
var mode = new TextMode();
|
||||||
*\n\
|
|
||||||
*/\n\
|
var result = highlighter.render(snippet, mode, theme);
|
||||||
function hello (a, b, c) {\n\
|
assert.ok(result.html.indexOf(snippet) != -1);
|
||||||
console.log(a * b + c + 'sup?');\n\
|
|
||||||
}";
|
|
||||||
var mode = new JavaScriptMode();
|
|
||||||
|
|
||||||
var isError = false, result;
|
|
||||||
result = highlighter.render(snippet, mode, theme);
|
|
||||||
assert.equal(!!result.html.match(/<div class='ace-tomorrow'>/), true);
|
|
||||||
|
|
||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
define(function(require, exports, module) {
|
||||||
|
"use strict";
|
||||||
|
/** simple statusbar **/
|
||||||
|
var dom = require("ace/lib/dom");
|
||||||
|
var lang = require("ace/lib/lang");
|
||||||
|
|
||||||
|
var StatusBar = function(editor, parentNode) {
|
||||||
|
this.element = dom.createElement("div");
|
||||||
|
this.element.className = "ace_status-indicator";
|
||||||
|
this.element.style.cssText = "display: inline-block;";
|
||||||
|
parentNode.appendChild(this.element);
|
||||||
|
|
||||||
|
var statusUpdate = lang.delayedCall(function(){
|
||||||
|
this.updateStatus(editor)
|
||||||
|
}.bind(this));
|
||||||
|
editor.on("changeStatus", function() {
|
||||||
|
statusUpdate.schedule(100);
|
||||||
|
});
|
||||||
|
editor.on("changeSelection", function() {
|
||||||
|
statusUpdate.schedule(100);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
(function(){
|
||||||
|
this.updateStatus = function(editor) {
|
||||||
|
var status = [];
|
||||||
|
function add(str, separator) {
|
||||||
|
str && status.push(str, separator || "|");
|
||||||
|
}
|
||||||
|
|
||||||
|
add(editor.keyBinding.getStatusText(editor));
|
||||||
|
if (editor.commands.recording)
|
||||||
|
add("REC");
|
||||||
|
|
||||||
|
var c = editor.selection.lead;
|
||||||
|
add(c.row + ":" + c.column, " ");
|
||||||
|
if (!editor.selection.isEmpty()) {
|
||||||
|
var r = editor.getSelectionRange();
|
||||||
|
add("(" + (r.end.row - r.start.row) + ":" +(r.end.column - r.start.column) + ")");
|
||||||
|
}
|
||||||
|
status.pop();
|
||||||
|
this.element.textContent = status.join("");
|
||||||
|
};
|
||||||
|
}).call(StatusBar.prototype);
|
||||||
|
|
||||||
|
exports.StatusBar = StatusBar;
|
||||||
|
|
||||||
|
});
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 2010, Ajax.org B.V.
|
* Copyright (c) 2010, Ajax.org B.V.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
* * Redistributions of source code must retain the above copyright
|
* * Redistributions of source code must retain the above copyright
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
* * Neither the name of Ajax.org B.V. nor the
|
* * Neither the name of Ajax.org B.V. nor the
|
||||||
* names of its contributors may be used to endorse or promote products
|
* names of its contributors may be used to endorse or promote products
|
||||||
* derived from this software without specific prior written permission.
|
* derived from this software without specific prior written permission.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
@@ -73,8 +73,8 @@ function applyStyles(elm, styles) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function setupContainer(element, getValue) {
|
function setupContainer(element, getValue) {
|
||||||
if (element.type != 'textarea') {
|
if (element.type != 'textarea') {
|
||||||
throw "Textarea required!";
|
throw new Error("Textarea required!");
|
||||||
}
|
}
|
||||||
|
|
||||||
var parentNode = element.parentNode;
|
var parentNode = element.parentNode;
|
||||||
@@ -132,11 +132,7 @@ function setupContainer(element, getValue) {
|
|||||||
resizeEvent();
|
resizeEvent();
|
||||||
|
|
||||||
// Insert the div container after the element.
|
// Insert the div container after the element.
|
||||||
if (element.nextSibling) {
|
parentNode.insertBefore(container, element.nextSibling);
|
||||||
parentNode.insertBefore(container, element.nextSibling);
|
|
||||||
} else {
|
|
||||||
parentNode.appendChild(container);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Override the forms onsubmit function. Set the innerHTML and value
|
// Override the forms onsubmit function. Set the innerHTML and value
|
||||||
// of the textarea before submitting.
|
// of the textarea before submitting.
|
||||||
@@ -145,7 +141,6 @@ function setupContainer(element, getValue) {
|
|||||||
var oldSumit = parentNode.onsubmit;
|
var oldSumit = parentNode.onsubmit;
|
||||||
// Override the onsubmit function of the form.
|
// Override the onsubmit function of the form.
|
||||||
parentNode.onsubmit = function(evt) {
|
parentNode.onsubmit = function(evt) {
|
||||||
element.innerHTML = getValue();
|
|
||||||
element.value = getValue();
|
element.value = getValue();
|
||||||
// If there is a onsubmit function already, then call
|
// If there is a onsubmit function already, then call
|
||||||
// it with the current context and pass the event.
|
// it with the current context and pass the event.
|
||||||
@@ -160,7 +155,7 @@ function setupContainer(element, getValue) {
|
|||||||
return container;
|
return container;
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.transformTextarea = function(element, loader) {
|
exports.transformTextarea = function(element, options) {
|
||||||
var session;
|
var session;
|
||||||
var container = setupContainer(element, function() {
|
var container = setupContainer(element, function() {
|
||||||
return session.getValue();
|
return session.getValue();
|
||||||
@@ -177,7 +172,8 @@ exports.transformTextarea = function(element, loader) {
|
|||||||
left: "0px",
|
left: "0px",
|
||||||
right: "0px",
|
right: "0px",
|
||||||
bottom: "0px",
|
bottom: "0px",
|
||||||
border: "1px solid gray"
|
border: "1px solid gray",
|
||||||
|
position: "absolute"
|
||||||
});
|
});
|
||||||
container.appendChild(editorDiv);
|
container.appendChild(editorDiv);
|
||||||
|
|
||||||
@@ -198,7 +194,7 @@ exports.transformTextarea = function(element, loader) {
|
|||||||
var settingDiv = document.createElement("div");
|
var settingDiv = document.createElement("div");
|
||||||
var settingDivStyles = {
|
var settingDivStyles = {
|
||||||
top: "0px",
|
top: "0px",
|
||||||
left: "0px",
|
left: "20%",
|
||||||
right: "0px",
|
right: "0px",
|
||||||
bottom: "0px",
|
bottom: "0px",
|
||||||
position: "absolute",
|
position: "absolute",
|
||||||
@@ -207,7 +203,8 @@ exports.transformTextarea = function(element, loader) {
|
|||||||
color: "white",
|
color: "white",
|
||||||
display: "none",
|
display: "none",
|
||||||
overflow: "auto",
|
overflow: "auto",
|
||||||
fontSize: "14px"
|
fontSize: "14px",
|
||||||
|
boxShadow: "-5px 2px 3px gray"
|
||||||
};
|
};
|
||||||
if (!UA.isOldIE) {
|
if (!UA.isOldIE) {
|
||||||
settingDivStyles.backgroundColor = "rgba(0, 0, 0, 0.6)";
|
settingDivStyles.backgroundColor = "rgba(0, 0, 0, 0.6)";
|
||||||
@@ -218,9 +215,8 @@ exports.transformTextarea = function(element, loader) {
|
|||||||
applyStyles(settingDiv, settingDivStyles);
|
applyStyles(settingDiv, settingDivStyles);
|
||||||
container.appendChild(settingDiv);
|
container.appendChild(settingDiv);
|
||||||
|
|
||||||
|
options = options || exports.defaultOptions;
|
||||||
// Power up ace on the textarea:
|
// Power up ace on the textarea:
|
||||||
var options = {};
|
|
||||||
|
|
||||||
var editor = ace.edit(editorDiv);
|
var editor = ace.edit(editorDiv);
|
||||||
session = editor.getSession();
|
session = editor.getSession();
|
||||||
|
|
||||||
@@ -228,14 +224,14 @@ exports.transformTextarea = function(element, loader) {
|
|||||||
editor.focus();
|
editor.focus();
|
||||||
|
|
||||||
// Add the settingPanel opener to the editor's div.
|
// Add the settingPanel opener to the editor's div.
|
||||||
editorDiv.appendChild(settingOpener);
|
container.appendChild(settingOpener);
|
||||||
|
|
||||||
// Create the API.
|
// Create the API.
|
||||||
setupApi(editor, editorDiv, settingDiv, ace, options, loader);
|
setupApi(editor, editorDiv, settingDiv, ace, options, load);
|
||||||
|
|
||||||
// Create the setting's panel.
|
// Create the setting's panel.
|
||||||
setupSettingPanel(settingDiv, settingOpener, editor, options);
|
setupSettingPanel(settingDiv, settingOpener, editor);
|
||||||
|
|
||||||
var state = "";
|
var state = "";
|
||||||
event.addListener(settingOpener, "mousemove", function(e) {
|
event.addListener(settingOpener, "mousemove", function(e) {
|
||||||
var rect = this.getBoundingClientRect();
|
var rect = this.getBoundingClientRect();
|
||||||
@@ -248,7 +244,7 @@ exports.transformTextarea = function(element, loader) {
|
|||||||
this.style.cursor = "nw-resize";
|
this.style.cursor = "nw-resize";
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
event.addListener(settingOpener, "mousedown", function(e) {
|
event.addListener(settingOpener, "mousedown", function(e) {
|
||||||
if (state == "toggle") {
|
if (state == "toggle") {
|
||||||
editor.setDisplaySettings();
|
editor.setDisplaySettings();
|
||||||
@@ -280,117 +276,98 @@ function setupApi(editor, editorDiv, settingDiv, ace, options, loader) {
|
|||||||
loader = loader || load;
|
loader = loader || load;
|
||||||
|
|
||||||
function toBool(value) {
|
function toBool(value) {
|
||||||
return value == "true";
|
return value === "true" || value == true;
|
||||||
}
|
}
|
||||||
|
|
||||||
editor.setDisplaySettings = function(display) {
|
editor.setDisplaySettings = function(display) {
|
||||||
if (display == null)
|
if (display == null)
|
||||||
display = settingDiv.style.display == "none";
|
display = settingDiv.style.display == "none";
|
||||||
settingDiv.style.display = display ? "block" : "none";
|
if (display) {
|
||||||
|
settingDiv.style.display = "block";
|
||||||
|
settingDiv.hideButton.focus();
|
||||||
|
editor.on("focus", function onFocus() {
|
||||||
|
editor.removeListener("focus", onFocus);
|
||||||
|
settingDiv.style.display = "none";
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
editor.focus();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
editor.$setOption = editor.setOption;
|
||||||
|
editor.$getOption = editor.getOption;
|
||||||
editor.setOption = function(key, value) {
|
editor.setOption = function(key, value) {
|
||||||
if (options[key] == value) return;
|
|
||||||
|
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case "gutter":
|
|
||||||
renderer.setShowGutter(toBool(value));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "mode":
|
case "mode":
|
||||||
if (value != "text") {
|
editor.$setOption("mode", "ace/mode/" + value)
|
||||||
// Load the required mode file. Files get loaded only once.
|
|
||||||
loader("mode-" + value + ".js", "ace/mode/" + value, function() {
|
|
||||||
var aceMode = require("../mode/" + value).Mode;
|
|
||||||
session.setMode(new aceMode());
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
session.setMode(new (require("../mode/text").Mode));
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "theme":
|
case "theme":
|
||||||
if (value != "textmate") {
|
editor.$setOption("theme", "ace/theme/" + value)
|
||||||
// Load the required theme file. Files get loaded only once.
|
|
||||||
loader("theme-" + value + ".js", "ace/theme/" + value, function() {
|
|
||||||
editor.setTheme("ace/theme/" + value);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
editor.setTheme("ace/theme/textmate");
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
case "keybindings":
|
||||||
case "fontSize":
|
switch (value) {
|
||||||
editorDiv.style.fontSize = value;
|
case "vim":
|
||||||
|
editor.setKeyboardHandler("ace/keyboard/vim");
|
||||||
|
break;
|
||||||
|
case "emacs":
|
||||||
|
editor.setKeyboardHandler("ace/keyboard/emacs");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
editor.setKeyboardHandler(null);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "softWrap":
|
case "softWrap":
|
||||||
switch (value) {
|
case "fontSize":
|
||||||
case "off":
|
editor.$setOption(key, value);
|
||||||
session.setUseWrapMode(false);
|
|
||||||
renderer.setPrintMarginColumn(80);
|
|
||||||
break;
|
|
||||||
case "40":
|
|
||||||
session.setUseWrapMode(true);
|
|
||||||
session.setWrapLimitRange(40, 40);
|
|
||||||
renderer.setPrintMarginColumn(40);
|
|
||||||
break;
|
|
||||||
case "80":
|
|
||||||
session.setUseWrapMode(true);
|
|
||||||
session.setWrapLimitRange(80, 80);
|
|
||||||
renderer.setPrintMarginColumn(80);
|
|
||||||
break;
|
|
||||||
case "free":
|
|
||||||
session.setUseWrapMode(true);
|
|
||||||
session.setWrapLimitRange(null, null);
|
|
||||||
renderer.setPrintMarginColumn(80);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "useSoftTabs":
|
|
||||||
session.setUseSoftTabs(toBool(value));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "showPrintMargin":
|
|
||||||
renderer.setShowPrintMargin(toBool(value));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "showInvisibles":
|
|
||||||
editor.setShowInvisibles(toBool(value));
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
editor.$setOption(key, toBool(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
options[key] = value;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
editor.getOption = function(key) {
|
editor.getOption = function(key) {
|
||||||
return options[key];
|
switch (key) {
|
||||||
|
case "mode":
|
||||||
|
return editor.$getOption("mode").substr("ace/mode/".length)
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "theme":
|
||||||
|
return editor.$getOption("theme").substr("ace/theme/".length)
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "keybindings":
|
||||||
|
var value = editor.getKeyboardHandler()
|
||||||
|
switch (value && value.$id) {
|
||||||
|
case "ace/keyboard/vim":
|
||||||
|
return "vim";
|
||||||
|
case "ace/keyboard/emacs":
|
||||||
|
return "emacs";
|
||||||
|
default:
|
||||||
|
return "ace";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return editor.$getOption(key);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
editor.getOptions = function() {
|
editor.setOptions(options);
|
||||||
return options;
|
|
||||||
};
|
|
||||||
|
|
||||||
for (var option in exports.options) {
|
|
||||||
editor.setOption(option, exports.options[option]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return editor;
|
return editor;
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupSettingPanel(settingDiv, settingOpener, editor, options) {
|
function setupSettingPanel(settingDiv, settingOpener, editor) {
|
||||||
var BOOL = {
|
var BOOL = null;
|
||||||
"true": true,
|
|
||||||
"false": false
|
|
||||||
};
|
|
||||||
|
|
||||||
var desc = {
|
var desc = {
|
||||||
mode: "Mode:",
|
mode: "Mode:",
|
||||||
gutter: "Display Gutter:",
|
wrap: "Soft Wrap:",
|
||||||
theme: "Theme:",
|
theme: "Theme:",
|
||||||
fontSize: "Font Size:",
|
fontSize: "Font Size:",
|
||||||
softWrap: "Soft Wrap:",
|
showGutter: "Display Gutter:",
|
||||||
|
keybindings: "Keyboard",
|
||||||
showPrintMargin: "Show Print Margin:",
|
showPrintMargin: "Show Print Margin:",
|
||||||
useSoftTabs: "Use Soft Tabs:",
|
useSoftTabs: "Use Soft Tabs:",
|
||||||
showInvisibles: "Show Invisibles"
|
showInvisibles: "Show Invisibles"
|
||||||
@@ -442,7 +419,7 @@ function setupSettingPanel(settingDiv, settingOpener, editor, options) {
|
|||||||
twilight: "Twilight",
|
twilight: "Twilight",
|
||||||
vibrant_ink: "Vibrant Ink"
|
vibrant_ink: "Vibrant Ink"
|
||||||
},
|
},
|
||||||
gutter: BOOL,
|
showGutter: BOOL,
|
||||||
fontSize: {
|
fontSize: {
|
||||||
"10px": "10px",
|
"10px": "10px",
|
||||||
"11px": "11px",
|
"11px": "11px",
|
||||||
@@ -450,12 +427,17 @@ function setupSettingPanel(settingDiv, settingOpener, editor, options) {
|
|||||||
"14px": "14px",
|
"14px": "14px",
|
||||||
"16px": "16px"
|
"16px": "16px"
|
||||||
},
|
},
|
||||||
softWrap: {
|
wrap: {
|
||||||
off: "Off",
|
off: "Off",
|
||||||
40: "40",
|
40: "40",
|
||||||
80: "80",
|
80: "80",
|
||||||
free: "Free"
|
free: "Free"
|
||||||
},
|
},
|
||||||
|
keybindings: {
|
||||||
|
ace: "ace",
|
||||||
|
vim: "vim",
|
||||||
|
emacs: "emacs"
|
||||||
|
},
|
||||||
showPrintMargin: BOOL,
|
showPrintMargin: BOOL,
|
||||||
useSoftTabs: BOOL,
|
useSoftTabs: BOOL,
|
||||||
showInvisibles: BOOL
|
showInvisibles: BOOL
|
||||||
@@ -465,6 +447,14 @@ function setupSettingPanel(settingDiv, settingOpener, editor, options) {
|
|||||||
table.push("<table><tr><th>Setting</th><th>Value</th></tr>");
|
table.push("<table><tr><th>Setting</th><th>Value</th></tr>");
|
||||||
|
|
||||||
function renderOption(builder, option, obj, cValue) {
|
function renderOption(builder, option, obj, cValue) {
|
||||||
|
if (!obj) {
|
||||||
|
builder.push(
|
||||||
|
"<input type='checkbox' title='", option, "' ",
|
||||||
|
cValue + "" == "true" ? "checked='true'" : "",
|
||||||
|
"'></input>"
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
builder.push("<select title='" + option + "'>");
|
builder.push("<select title='" + option + "'>");
|
||||||
for (var value in obj) {
|
for (var value in obj) {
|
||||||
builder.push("<option value='" + value + "' ");
|
builder.push("<option value='" + value + "' ");
|
||||||
@@ -480,27 +470,30 @@ function setupSettingPanel(settingDiv, settingOpener, editor, options) {
|
|||||||
builder.push("</select>");
|
builder.push("</select>");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var option in options) {
|
for (var option in exports.defaultOptions) {
|
||||||
table.push("<tr><td>", desc[option], "</td>");
|
table.push("<tr><td>", desc[option], "</td>");
|
||||||
table.push("<td>");
|
table.push("<td>");
|
||||||
renderOption(table, option, optionValues[option], options[option]);
|
renderOption(table, option, optionValues[option], editor.getOption(option));
|
||||||
table.push("</td></tr>");
|
table.push("</td></tr>");
|
||||||
}
|
}
|
||||||
table.push("</table>");
|
table.push("</table>");
|
||||||
settingDiv.innerHTML = table.join("");
|
settingDiv.innerHTML = table.join("");
|
||||||
|
|
||||||
|
var onChange = function(e) {
|
||||||
|
var select = e.currentTarget;
|
||||||
|
editor.setOption(select.title, select.value);
|
||||||
|
};
|
||||||
|
var onClick = function(e) {
|
||||||
|
var cb = e.currentTarget;
|
||||||
|
editor.setOption(cb.title, cb.checked);
|
||||||
|
};
|
||||||
var selects = settingDiv.getElementsByTagName("select");
|
var selects = settingDiv.getElementsByTagName("select");
|
||||||
for (var i = 0; i < selects.length; i++) {
|
for (var i = 0; i < selects.length; i++)
|
||||||
var onChange = (function() {
|
|
||||||
var select = selects[i];
|
|
||||||
return function() {
|
|
||||||
var option = select.title;
|
|
||||||
var value = select.value;
|
|
||||||
editor.setOption(option, value);
|
|
||||||
};
|
|
||||||
})();
|
|
||||||
selects[i].onchange = onChange;
|
selects[i].onchange = onChange;
|
||||||
}
|
var cbs = settingDiv.getElementsByTagName("input");
|
||||||
|
for (var i = 0; i < cbs.length; i++)
|
||||||
|
cbs[i].onclick = onClick;
|
||||||
|
|
||||||
|
|
||||||
var button = document.createElement("input");
|
var button = document.createElement("input");
|
||||||
button.type = "button";
|
button.type = "button";
|
||||||
@@ -509,18 +502,20 @@ function setupSettingPanel(settingDiv, settingOpener, editor, options) {
|
|||||||
editor.setDisplaySettings(false);
|
editor.setDisplaySettings(false);
|
||||||
});
|
});
|
||||||
settingDiv.appendChild(button);
|
settingDiv.appendChild(button);
|
||||||
|
settingDiv.hideButton = button;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default startup options.
|
// Default startup options.
|
||||||
exports.options = {
|
exports.defaultOptions = {
|
||||||
mode: "text",
|
mode: "javascript",
|
||||||
theme: "textmate",
|
theme: "textmate",
|
||||||
gutter: "false",
|
wrap: "off",
|
||||||
fontSize: "12px",
|
fontSize: "12px",
|
||||||
softWrap: "off",
|
showGutter: "false",
|
||||||
|
keybindings: "ace",
|
||||||
showPrintMargin: "false",
|
showPrintMargin: "false",
|
||||||
useSoftTabs: "true",
|
useSoftTabs: "true",
|
||||||
showInvisibles: "true"
|
showInvisibles: "false"
|
||||||
};
|
};
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,100 @@
|
|||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Distributed under the BSD license:
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 Matthew Christopher Kastor-Inare III, Atropa Inc. Intl
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Contributed to Ajax.org under the BSD license.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of Ajax.org B.V. nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a list of themes available when ace was built.
|
||||||
|
* @fileOverview Generates a list of themes available when ace was built.
|
||||||
|
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||||
|
* Matthew Christopher Kastor-Inare III </a><br />
|
||||||
|
* ☭ Hial Atropa!! ☭
|
||||||
|
*/
|
||||||
|
|
||||||
|
define(function(require, exports, module) {
|
||||||
|
"use strict";
|
||||||
|
require("ace/lib/fixoldbrowsers");
|
||||||
|
|
||||||
|
var themeData = [
|
||||||
|
["Chrome" ],
|
||||||
|
["Clouds" ],
|
||||||
|
["Crimson Editor" ],
|
||||||
|
["Dawn" ],
|
||||||
|
["Dreamweaver" ],
|
||||||
|
["Eclipse" ],
|
||||||
|
["GitHub" ],
|
||||||
|
["Solarized Light"],
|
||||||
|
["TextMate" ],
|
||||||
|
["Tomorrow" ],
|
||||||
|
["XCode" ],
|
||||||
|
["Kuroir"],
|
||||||
|
["KatzenMilch"],
|
||||||
|
["Ambiance" ,"ambiance" , "dark"],
|
||||||
|
["Chaos" ,"chaos" , "dark"],
|
||||||
|
["Clouds Midnight" ,"clouds_midnight" , "dark"],
|
||||||
|
["Cobalt" ,"cobalt" , "dark"],
|
||||||
|
["idle Fingers" ,"idle_fingers" , "dark"],
|
||||||
|
["krTheme" ,"kr_theme" , "dark"],
|
||||||
|
["Merbivore" ,"merbivore" , "dark"],
|
||||||
|
["Merbivore Soft" ,"merbivore_soft" , "dark"],
|
||||||
|
["Mono Industrial" ,"mono_industrial" , "dark"],
|
||||||
|
["Monokai" ,"monokai" , "dark"],
|
||||||
|
["Pastel on dark" ,"pastel_on_dark" , "dark"],
|
||||||
|
["Solarized Dark" ,"solarized_dark" , "dark"],
|
||||||
|
["Terminal" ,"terminal" , "dark"],
|
||||||
|
["Tomorrow Night" ,"tomorrow_night" , "dark"],
|
||||||
|
["Tomorrow Night Blue" ,"tomorrow_night_blue" , "dark"],
|
||||||
|
["Tomorrow Night Bright","tomorrow_night_bright" , "dark"],
|
||||||
|
["Tomorrow Night 80s" ,"tomorrow_night_eighties" , "dark"],
|
||||||
|
["Twilight" ,"twilight" , "dark"],
|
||||||
|
["Vibrant Ink" ,"vibrant_ink" , "dark"]
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
exports.themesByName = {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An array containing information about available themes.
|
||||||
|
*/
|
||||||
|
exports.themes = themeData.map(function(data) {
|
||||||
|
var name = data[1] || data[0].replace(/ /g, "_").toLowerCase();
|
||||||
|
var theme = {
|
||||||
|
caption: data[0],
|
||||||
|
theme: "ace/theme/" + name,
|
||||||
|
isDark: data[2] == "dark",
|
||||||
|
name: name
|
||||||
|
};
|
||||||
|
exports.themesByName[name] = theme;
|
||||||
|
return theme;
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
@@ -0,0 +1,213 @@
|
|||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Distributed under the BSD license:
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010, Ajax.org B.V.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of Ajax.org B.V. nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
define(function(require, exports, module) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var lang = require("../lib/lang");
|
||||||
|
|
||||||
|
// based on http://www.freehackers.org/Indent_Finder
|
||||||
|
exports.$detectIndentation = function(lines, fallback) {
|
||||||
|
var stats = [];
|
||||||
|
var changes = [];
|
||||||
|
var tabIndents = 0;
|
||||||
|
var prevSpaces = 0;
|
||||||
|
var max = Math.min(lines.length, 1000);
|
||||||
|
for (var i = 0; i < max; i++) {
|
||||||
|
var line = lines[i];
|
||||||
|
// ignore empty and comment lines
|
||||||
|
if (!/^\s*[^*+\-\s]/.test(line))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (line[0] == "\t")
|
||||||
|
tabIndents++;
|
||||||
|
|
||||||
|
var spaces = line.match(/^ */)[0].length;
|
||||||
|
if (spaces && line[spaces] != "\t") {
|
||||||
|
var diff = spaces - prevSpaces;
|
||||||
|
if (diff > 0 && !(prevSpaces%diff) && !(spaces%diff))
|
||||||
|
changes[diff] = (changes[diff] || 0) + 1;
|
||||||
|
|
||||||
|
stats[spaces] = (stats[spaces] || 0) + 1;
|
||||||
|
}
|
||||||
|
prevSpaces = spaces;
|
||||||
|
|
||||||
|
// ignore lines ending with backslash
|
||||||
|
while (i < max && line[line.length - 1] == "\\")
|
||||||
|
line = lines[i++];
|
||||||
|
}
|
||||||
|
|
||||||
|
function getScore(indent) {
|
||||||
|
var score = 0;
|
||||||
|
for (var i = indent; i < stats.length; i += indent)
|
||||||
|
score += stats[i] || 0;
|
||||||
|
return score;
|
||||||
|
}
|
||||||
|
|
||||||
|
var changesTotal = changes.reduce(function(a,b){return a+b}, 0);
|
||||||
|
|
||||||
|
var first = {score: 0, length: 0};
|
||||||
|
var spaceIndents = 0;
|
||||||
|
for (var i = 1; i < 12; i++) {
|
||||||
|
var score = getScore(i);
|
||||||
|
if (i == 1) {
|
||||||
|
spaceIndents = score;
|
||||||
|
score = stats[1] ? 0.9 : 0.8;
|
||||||
|
if (!stats.length)
|
||||||
|
score = 0
|
||||||
|
} else
|
||||||
|
score /= spaceIndents;
|
||||||
|
|
||||||
|
if (changes[i])
|
||||||
|
score += changes[i] / changesTotal;
|
||||||
|
|
||||||
|
if (score > first.score)
|
||||||
|
first = {score: score, length: i};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (first.score && first.score > 1.4)
|
||||||
|
var tabLength = first.length;
|
||||||
|
|
||||||
|
if (tabIndents > spaceIndents + 1)
|
||||||
|
return {ch: "\t", length: tabLength};
|
||||||
|
|
||||||
|
if (spaceIndents > tabIndents + 1)
|
||||||
|
return {ch: " ", length: tabLength};
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.detectIndentation = function(session) {
|
||||||
|
var lines = session.getLines(0, 1000);
|
||||||
|
var indent = exports.$detectIndentation(lines) || {};
|
||||||
|
|
||||||
|
if (indent.ch)
|
||||||
|
session.setUseSoftTabs(indent.ch == " ");
|
||||||
|
|
||||||
|
if (indent.length)
|
||||||
|
session.setTabSize(indent.length);
|
||||||
|
return indent;
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.trimTrailingSpace = function(session, trimEmpty) {
|
||||||
|
var doc = session.getDocument();
|
||||||
|
var lines = doc.getAllLines();
|
||||||
|
|
||||||
|
var min = trimEmpty ? -1 : 0;
|
||||||
|
|
||||||
|
for (var i = 0, l=lines.length; i < l; i++) {
|
||||||
|
var line = lines[i];
|
||||||
|
var index = line.search(/\s+$/);
|
||||||
|
|
||||||
|
if (index > min)
|
||||||
|
doc.removeInLine(i, index, line.length);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.convertIndentation = function(session, ch, len) {
|
||||||
|
var oldCh = session.getTabString()[0];
|
||||||
|
var oldLen = session.getTabSize();
|
||||||
|
if (!len) len = oldLen;
|
||||||
|
if (!ch) ch = oldCh;
|
||||||
|
|
||||||
|
var tab = ch == "\t" ? ch: lang.stringRepeat(ch, len);
|
||||||
|
|
||||||
|
var doc = session.doc;
|
||||||
|
var lines = doc.getAllLines();
|
||||||
|
|
||||||
|
var cache = {};
|
||||||
|
var spaceCache = {};
|
||||||
|
for (var i = 0, l=lines.length; i < l; i++) {
|
||||||
|
var line = lines[i];
|
||||||
|
var match = line.match(/^\s*/)[0];
|
||||||
|
if (match) {
|
||||||
|
var w = session.$getStringScreenWidth(match)[0];
|
||||||
|
var tabCount = Math.floor(w/oldLen);
|
||||||
|
var reminder = w%oldLen;
|
||||||
|
var toInsert = cache[tabCount] || (cache[tabCount] = lang.stringRepeat(tab, tabCount));
|
||||||
|
toInsert += spaceCache[reminder] || (spaceCache[reminder] = lang.stringRepeat(" ", reminder));
|
||||||
|
|
||||||
|
if (toInsert != match) {
|
||||||
|
doc.removeInLine(i, 0, match.length);
|
||||||
|
doc.insertInLine({row: i, column: 0}, toInsert);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
session.setTabSize(len);
|
||||||
|
session.setUseSoftTabs(ch == " ");
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.$parseStringArg = function(text) {
|
||||||
|
var indent = {};
|
||||||
|
if (/t/.test(text))
|
||||||
|
indent.ch = "\t";
|
||||||
|
else if (/s/.test(text))
|
||||||
|
indent.ch = " ";
|
||||||
|
var m = text.match(/\d+/);
|
||||||
|
if (m)
|
||||||
|
indent.length = parseInt(m[0], 10);
|
||||||
|
return indent;
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.$parseArg = function(arg) {
|
||||||
|
if (!arg)
|
||||||
|
return {};
|
||||||
|
if (typeof arg == "string")
|
||||||
|
return exports.$parseStringArg(arg);
|
||||||
|
if (typeof arg.text == "string")
|
||||||
|
return exports.$parseStringArg(arg.text);
|
||||||
|
return arg;
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.commands = [{
|
||||||
|
name: "detectIndentation",
|
||||||
|
exec: function(editor) {
|
||||||
|
exports.detectIndentation(editor.session);
|
||||||
|
// todo show message?
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
name: "trimTrailingSpace",
|
||||||
|
exec: function(editor) {
|
||||||
|
exports.trimTrailingSpace(editor.session);
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
name: "convertIndentation",
|
||||||
|
exec: function(editor, arg) {
|
||||||
|
var indent = exports.$parseArg(arg);
|
||||||
|
exports.convertIndentation(editor.session, indent.ch, indent.length);
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
name: "setIndentation",
|
||||||
|
exec: function(editor, arg) {
|
||||||
|
var indent = exports.$parseArg(arg);
|
||||||
|
indent.length && editor.session.setTabSize(indent.length);
|
||||||
|
indent.ch && editor.session.setUseSoftTabs(indent.ch == " ");
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
|
||||||
|
});
|
||||||
@@ -0,0 +1,116 @@
|
|||||||
|
if (typeof process !== "undefined") {
|
||||||
|
require("amd-loader");
|
||||||
|
require("../test/mockdom");
|
||||||
|
}
|
||||||
|
|
||||||
|
define(function(require, exports, module) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var assert = require("assert");
|
||||||
|
var EditSession = require("../edit_session").EditSession;
|
||||||
|
var whitespace = require("./whitespace");
|
||||||
|
|
||||||
|
// Execution ORDER: test.setUpSuite, setUp, testFn, tearDown, test.tearDownSuite
|
||||||
|
module.exports = {
|
||||||
|
timeout: 10000,
|
||||||
|
|
||||||
|
"test tab detection": function(next) {
|
||||||
|
var s = new EditSession([
|
||||||
|
"define({",
|
||||||
|
"\tfoo:1,",
|
||||||
|
"\tbar:2,",
|
||||||
|
"\tbaz:{,",
|
||||||
|
"\t\tx:3",
|
||||||
|
"\t}",
|
||||||
|
"})"
|
||||||
|
]);
|
||||||
|
|
||||||
|
var indent = whitespace.$detectIndentation(s.doc.$lines);
|
||||||
|
assert.equal(indent.ch, "\t");
|
||||||
|
assert.equal(indent.length, undefined);
|
||||||
|
|
||||||
|
s.insert({row: 0, column: 0}, " ");
|
||||||
|
indent = whitespace.$detectIndentation(s.doc.$lines);
|
||||||
|
assert.equal(indent.ch, "\t");
|
||||||
|
assert.equal(indent.length, 4);
|
||||||
|
|
||||||
|
s.setValue("");
|
||||||
|
indent = whitespace.$detectIndentation(s.doc.$lines);
|
||||||
|
assert.ok(!indent);
|
||||||
|
|
||||||
|
next();
|
||||||
|
},
|
||||||
|
|
||||||
|
"test empty session": function(next) {
|
||||||
|
var s = new EditSession([
|
||||||
|
"define({",
|
||||||
|
"foo:1,",
|
||||||
|
"})"
|
||||||
|
]);
|
||||||
|
var indent = whitespace.$detectIndentation(s.doc.$lines);
|
||||||
|
assert.ok(!indent);
|
||||||
|
s.insert({row: 1, column: 0}, " x\n ");
|
||||||
|
|
||||||
|
indent = whitespace.$detectIndentation(s.doc.$lines);
|
||||||
|
assert.equal(indent.ch, " ");
|
||||||
|
assert.equal(indent.length, 4);
|
||||||
|
|
||||||
|
next();
|
||||||
|
},
|
||||||
|
|
||||||
|
"!test one line": function(next) {
|
||||||
|
var s = new EditSession([
|
||||||
|
"define({",
|
||||||
|
" foo:1,",
|
||||||
|
"})"
|
||||||
|
]);
|
||||||
|
var indent = whitespace.$detectIndentation(s.doc.$lines);
|
||||||
|
assert.equal(indent.ch, " ");
|
||||||
|
assert.equal(indent.length, 4);
|
||||||
|
|
||||||
|
next();
|
||||||
|
},
|
||||||
|
|
||||||
|
"test 1 width indents": function(next) {
|
||||||
|
var s = new EditSession([
|
||||||
|
"define({",
|
||||||
|
" foo:1,",
|
||||||
|
"})",
|
||||||
|
"define({",
|
||||||
|
" bar:1,",
|
||||||
|
"})",
|
||||||
|
" t",
|
||||||
|
" t",
|
||||||
|
" t",
|
||||||
|
" t",
|
||||||
|
" t",
|
||||||
|
" t",
|
||||||
|
" t",
|
||||||
|
" t"
|
||||||
|
]);
|
||||||
|
var indent = whitespace.$detectIndentation(s.doc.$lines);
|
||||||
|
// assert.equal(indent.ch, " ");
|
||||||
|
// assert.equal(indent.length, 4);
|
||||||
|
|
||||||
|
s = new EditSession([
|
||||||
|
"{",
|
||||||
|
" foo:1,",
|
||||||
|
" bar: {",
|
||||||
|
" baz:2",
|
||||||
|
" }",
|
||||||
|
"}"
|
||||||
|
]);
|
||||||
|
indent = whitespace.$detectIndentation(s.doc.$lines);
|
||||||
|
assert.equal(indent.ch, " ");
|
||||||
|
assert.equal(indent.length, 1);
|
||||||
|
|
||||||
|
next();
|
||||||
|
},
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
if (typeof module !== "undefined" && module === require.main) {
|
||||||
|
require("asyncjs").test.testcase(module.exports).exec();
|
||||||
|
}
|
||||||
@@ -0,0 +1,317 @@
|
|||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Distributed under the BSD license:
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010, Ajax.org B.V.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of Ajax.org B.V. nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
define(function(require, exports, module) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var oop = require("./lib/oop");
|
||||||
|
var Range = require("./range").Range;
|
||||||
|
var Search = require("./search").Search;
|
||||||
|
var SearchHighlight = require("./search_highlight").SearchHighlight;
|
||||||
|
var iSearchCommandModule = require("./commands/incremental_search_commands");
|
||||||
|
var ISearchKbd = iSearchCommandModule.IncrementalSearchKeyboardHandler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class IncrementalSearch
|
||||||
|
*
|
||||||
|
* Implements immediate searching while the user is typing. When incremental
|
||||||
|
* search is activated, keystrokes into the editor will be used for composing
|
||||||
|
* a search term. Immediately after every keystroke the search is updated:
|
||||||
|
* - so-far-matching characters are highlighted
|
||||||
|
* - the cursor is moved to the next match
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Creates a new `IncrementalSearch` object.
|
||||||
|
*
|
||||||
|
* @constructor
|
||||||
|
**/
|
||||||
|
function IncrementalSearch() {
|
||||||
|
this.$options = {wrap: false, skipCurrent: false};
|
||||||
|
this.$keyboardHandler = new ISearchKbd(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
oop.inherits(IncrementalSearch, Search);
|
||||||
|
|
||||||
|
// regexp handling
|
||||||
|
|
||||||
|
function isRegExp(obj) {
|
||||||
|
return obj instanceof RegExp;
|
||||||
|
}
|
||||||
|
|
||||||
|
function regExpToObject(re) {
|
||||||
|
var string = String(re),
|
||||||
|
start = string.indexOf('/'),
|
||||||
|
flagStart = string.lastIndexOf('/');
|
||||||
|
return {
|
||||||
|
expression: string.slice(start+1, flagStart),
|
||||||
|
flags: string.slice(flagStart+1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function stringToRegExp(string, flags) {
|
||||||
|
try {
|
||||||
|
return new RegExp(string, flags);
|
||||||
|
} catch (e) { return string; }
|
||||||
|
}
|
||||||
|
|
||||||
|
function objectToRegExp(obj) {
|
||||||
|
return stringToRegExp(obj.expression, obj.flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
// iSearch class
|
||||||
|
|
||||||
|
;(function() {
|
||||||
|
|
||||||
|
this.activate = function(ed, backwards) {
|
||||||
|
this.$editor = ed;
|
||||||
|
this.$startPos = this.$currentPos = ed.getCursorPosition();
|
||||||
|
this.$options.needle = '';
|
||||||
|
this.$options.backwards = backwards;
|
||||||
|
ed.keyBinding.addKeyboardHandler(this.$keyboardHandler);
|
||||||
|
// we need to completely intercept paste, just registering an event handler does not work
|
||||||
|
this.$originalEditorOnPaste = ed.onPaste; ed.onPaste = this.onPaste.bind(this);
|
||||||
|
this.$mousedownHandler = ed.addEventListener('mousedown', this.onMouseDown.bind(this));
|
||||||
|
this.selectionFix(ed);
|
||||||
|
this.statusMessage(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.deactivate = function(reset) {
|
||||||
|
this.cancelSearch(reset);
|
||||||
|
var ed = this.$editor;
|
||||||
|
ed.keyBinding.removeKeyboardHandler(this.$keyboardHandler);
|
||||||
|
if (this.$mousedownHandler) {
|
||||||
|
ed.removeEventListener('mousedown', this.$mousedownHandler);
|
||||||
|
delete this.$mousedownHandler;
|
||||||
|
}
|
||||||
|
ed.onPaste = this.$originalEditorOnPaste;
|
||||||
|
this.message('');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.selectionFix = function(editor) {
|
||||||
|
// Fix selection bug: When clicked inside the editor
|
||||||
|
// editor.selection.$isEmpty is false even if the mouse click did not
|
||||||
|
// open a selection. This is interpreted by the move commands to
|
||||||
|
// extend the selection. To only extend the selection when there is
|
||||||
|
// one, we clear it here
|
||||||
|
if (editor.selection.isEmpty() && !editor.session.$emacsMark) {
|
||||||
|
editor.clearSelection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.highlight = function(regexp) {
|
||||||
|
var sess = this.$editor.session,
|
||||||
|
hl = sess.$isearchHighlight = sess.$isearchHighlight || sess.addDynamicMarker(
|
||||||
|
new SearchHighlight(null, "ace_isearch-result", "text"));
|
||||||
|
hl.setRegexp(regexp);
|
||||||
|
sess._emit("changeBackMarker"); // force highlight layer redraw
|
||||||
|
}
|
||||||
|
|
||||||
|
this.cancelSearch = function(reset) {
|
||||||
|
var e = this.$editor;
|
||||||
|
this.$prevNeedle = this.$options.needle;
|
||||||
|
this.$options.needle = '';
|
||||||
|
if (reset) {
|
||||||
|
e.moveCursorToPosition(this.$startPos);
|
||||||
|
this.$currentPos = this.$startPos;
|
||||||
|
} else {
|
||||||
|
e.pushEmacsMark && e.pushEmacsMark(this.$startPos, false);
|
||||||
|
}
|
||||||
|
this.highlight(null);
|
||||||
|
return Range.fromPoints(this.$currentPos, this.$currentPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.highlightAndFindWithNeedle = function(moveToNext, needleUpdateFunc) {
|
||||||
|
if (!this.$editor) return null;
|
||||||
|
var options = this.$options;
|
||||||
|
|
||||||
|
// get search term
|
||||||
|
if (needleUpdateFunc) {
|
||||||
|
options.needle = needleUpdateFunc.call(this, options.needle || '') || '';
|
||||||
|
}
|
||||||
|
if (options.needle.length === 0) {
|
||||||
|
this.statusMessage(true);
|
||||||
|
return this.cancelSearch(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
// try to find the next occurence and enable highlighting marker
|
||||||
|
options.start = this.$currentPos;
|
||||||
|
var session = this.$editor.session,
|
||||||
|
found = this.find(session),
|
||||||
|
shouldSelect = this.$editor.emacsMark ?
|
||||||
|
!!this.$editor.emacsMark() : !this.$editor.selection.isEmpty();
|
||||||
|
if (found) {
|
||||||
|
if (options.backwards) found = Range.fromPoints(found.end, found.start);
|
||||||
|
this.$editor.selection.setRange(Range.fromPoints(shouldSelect ? this.$startPos : found.end, found.end));
|
||||||
|
if (moveToNext) this.$currentPos = found.end;
|
||||||
|
// highlight after cursor move, so selection works properly
|
||||||
|
this.highlight(options.re)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.statusMessage(found);
|
||||||
|
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.addString = function(s) {
|
||||||
|
return this.highlightAndFindWithNeedle(false, function(needle) {
|
||||||
|
if (!isRegExp(needle))
|
||||||
|
return needle + s;
|
||||||
|
var reObj = regExpToObject(needle);
|
||||||
|
reObj.expression += s;
|
||||||
|
return objectToRegExp(reObj);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.removeChar = function(c) {
|
||||||
|
return this.highlightAndFindWithNeedle(false, function(needle) {
|
||||||
|
if (!isRegExp(needle))
|
||||||
|
return needle.substring(0, needle.length-1);
|
||||||
|
var reObj = regExpToObject(needle);
|
||||||
|
reObj.expression = reObj.expression.substring(0, reObj.expression.length-1);
|
||||||
|
return objectToRegExp(reObj);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.next = function(options) {
|
||||||
|
// try to find the next occurence of whatever we have searched for
|
||||||
|
// earlier.
|
||||||
|
// options = {[backwards: BOOL], [useCurrentOrPrevSearch: BOOL]}
|
||||||
|
options = options || {};
|
||||||
|
this.$options.backwards = !!options.backwards;
|
||||||
|
this.$currentPos = this.$editor.getCursorPosition();
|
||||||
|
return this.highlightAndFindWithNeedle(true, function(needle) {
|
||||||
|
return options.useCurrentOrPrevSearch && needle.length === 0 ?
|
||||||
|
this.$prevNeedle || '' : needle;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.onMouseDown = function(evt) {
|
||||||
|
// when mouse interaction happens then we quit incremental search
|
||||||
|
this.deactivate();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.onPaste = function(text) {
|
||||||
|
this.addString(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.convertNeedleToRegExp = function() {
|
||||||
|
return this.highlightAndFindWithNeedle(false, function(needle) {
|
||||||
|
return isRegExp(needle) ? needle : stringToRegExp(needle, 'ig');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.convertNeedleToString = function() {
|
||||||
|
return this.highlightAndFindWithNeedle(false, function(needle) {
|
||||||
|
return isRegExp(needle) ? regExpToObject(needle).expression : needle;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.statusMessage = function(found) {
|
||||||
|
var options = this.$options, msg = '';
|
||||||
|
msg += options.backwards ? 'reverse-' : '';
|
||||||
|
msg += 'isearch: ' + options.needle;
|
||||||
|
msg += found ? '' : ' (not found)';
|
||||||
|
this.message(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.message = function(msg) {
|
||||||
|
if (this.$editor.showCommandLine) {
|
||||||
|
this.$editor.showCommandLine(msg);
|
||||||
|
this.$editor.focus();
|
||||||
|
} else {
|
||||||
|
console.log(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}).call(IncrementalSearch.prototype);
|
||||||
|
|
||||||
|
|
||||||
|
exports.IncrementalSearch = IncrementalSearch;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Config settings for enabling/disabling [[IncrementalSearch `IncrementalSearch`]].
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
|
||||||
|
var dom = require('./lib/dom');
|
||||||
|
dom.importCssString && dom.importCssString("\
|
||||||
|
.ace_marker-layer .ace_isearch-result {\
|
||||||
|
position: absolute;\
|
||||||
|
z-index: 6;\
|
||||||
|
-moz-box-sizing: border-box;\
|
||||||
|
-webkit-box-sizing: border-box;\
|
||||||
|
box-sizing: border-box;\
|
||||||
|
}\
|
||||||
|
div.ace_isearch-result {\
|
||||||
|
border-radius: 4px;\
|
||||||
|
background-color: rgba(255, 200, 0, 0.5);\
|
||||||
|
box-shadow: 0 0 4px rgb(255, 200, 0);\
|
||||||
|
}\
|
||||||
|
.ace_dark div.ace_isearch-result {\
|
||||||
|
background-color: rgb(100, 110, 160);\
|
||||||
|
box-shadow: 0 0 4px rgb(80, 90, 140);\
|
||||||
|
}", "incremental-search-highlighting");
|
||||||
|
|
||||||
|
// support for default keyboard handler
|
||||||
|
var commands = require("./commands/command_manager");
|
||||||
|
(function() {
|
||||||
|
this.setupIncrementalSearch = function(editor, val) {
|
||||||
|
if (this.usesIncrementalSearch == val) return;
|
||||||
|
this.usesIncrementalSearch = val;
|
||||||
|
var iSearchCommands = iSearchCommandModule.iSearchStartCommands;
|
||||||
|
var method = val ? 'addCommands' : 'removeCommands';
|
||||||
|
this[method](iSearchCommands);
|
||||||
|
};
|
||||||
|
}).call(commands.CommandManager.prototype);
|
||||||
|
|
||||||
|
// incremental search config option
|
||||||
|
var Editor = require("./editor").Editor;
|
||||||
|
require("./config").defineOptions(Editor.prototype, "editor", {
|
||||||
|
useIncrementalSearch: {
|
||||||
|
set: function(val) {
|
||||||
|
this.keyBinding.$handlers.forEach(function(handler) {
|
||||||
|
if (handler.setupIncrementalSearch) {
|
||||||
|
handler.setupIncrementalSearch(this, val);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this._emit('incrementalSearchSettingChanged', {isEnabled: val});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
@@ -0,0 +1,213 @@
|
|||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Distributed under the BSD license:
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010, Ajax.org B.V.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of Ajax.org B.V. nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
if (typeof process !== "undefined") {
|
||||||
|
require("amd-loader");
|
||||||
|
}
|
||||||
|
|
||||||
|
define(function(require, exports, module) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var emacs = require('./keyboard/emacs');
|
||||||
|
var EditSession = require("./edit_session").EditSession;
|
||||||
|
var Editor = require("./editor").Editor;
|
||||||
|
var MockRenderer = require("./test/mockrenderer").MockRenderer;
|
||||||
|
var Range = require("./range").Range;
|
||||||
|
var MultiSelect = require("./multi_select").MultiSelect;
|
||||||
|
var assert = require("./test/assertions");
|
||||||
|
var IncrementalSearch = require("./incremental_search").IncrementalSearch;
|
||||||
|
|
||||||
|
require("./multi_select");
|
||||||
|
|
||||||
|
var editor, iSearch;
|
||||||
|
function testRanges(str, ranges) {
|
||||||
|
ranges = ranges || editor.selection.getAllRanges();
|
||||||
|
assert.equal(ranges + "", str + "");
|
||||||
|
}
|
||||||
|
|
||||||
|
// force "rerender"
|
||||||
|
function callHighlighterUpdate() {
|
||||||
|
var session = editor.session,
|
||||||
|
ranges = [],
|
||||||
|
mockMarkerLayer = {
|
||||||
|
drawSingleLineMarker: function(_, markerRanges) {
|
||||||
|
ranges = ranges.concat(markerRanges);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
session.$isearchHighlight.update([], mockMarkerLayer, session, {
|
||||||
|
firstRow: 0, lastRow: session.getRowLength()});
|
||||||
|
return ranges;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
|
||||||
|
name: "ACE incremental_search.js",
|
||||||
|
|
||||||
|
setUp: function() {
|
||||||
|
var session = new EditSession(["abc123", "xyz124"]);
|
||||||
|
editor = new Editor(new MockRenderer(), session);
|
||||||
|
new MultiSelect(editor);
|
||||||
|
iSearch = new IncrementalSearch();
|
||||||
|
},
|
||||||
|
|
||||||
|
"test: keyboard handler setup" : function() {
|
||||||
|
iSearch.activate(editor);
|
||||||
|
assert.equal(editor.getKeyboardHandler(), iSearch.$keyboardHandler);
|
||||||
|
iSearch.deactivate();
|
||||||
|
assert.notEqual(editor.getKeyboardHandler(), iSearch.$keyboardHandler);
|
||||||
|
},
|
||||||
|
|
||||||
|
"test: isearch highlight setup" : function() {
|
||||||
|
var sess = editor.session;
|
||||||
|
iSearch.activate(editor);
|
||||||
|
iSearch.highlight('foo');
|
||||||
|
var highl = sess.$isearchHighlight.id;
|
||||||
|
assert.ok(sess.$isearchHighlight, 'session has no isearch highlighter');
|
||||||
|
assert.equal(sess.getMarkers()[highl.id], highl.id, 'isearch highlight not in markers');
|
||||||
|
iSearch.deactivate();
|
||||||
|
iSearch.activate(editor);
|
||||||
|
iSearch.highlight('bar');
|
||||||
|
var highl2 = sess.$isearchHighlight.id;
|
||||||
|
assert.equal(highl2, highl, 'multiple isearch highlights');
|
||||||
|
},
|
||||||
|
|
||||||
|
"test: find simple text incrementally" : function() {
|
||||||
|
iSearch.activate(editor);
|
||||||
|
var range = iSearch.addString('1'), // "1"
|
||||||
|
highlightRanges = callHighlighterUpdate(editor.session);
|
||||||
|
testRanges("Range: [0/3] -> [0/4]", [range], "range");
|
||||||
|
testRanges("Range: [0/3] -> [0/4],Range: [1/3] -> [1/4]", highlightRanges, "highlight");
|
||||||
|
|
||||||
|
range = iSearch.addString('2'); // "12"
|
||||||
|
highlightRanges = callHighlighterUpdate(editor.session);
|
||||||
|
testRanges("Range: [0/3] -> [0/5]", [range], "range");
|
||||||
|
testRanges("Range: [0/3] -> [0/5],Range: [1/3] -> [1/5]", highlightRanges, "highlight");
|
||||||
|
|
||||||
|
range = iSearch.addString('3'); // "123"
|
||||||
|
highlightRanges = callHighlighterUpdate(editor.session);
|
||||||
|
testRanges("Range: [0/3] -> [0/6]", [range], "range");
|
||||||
|
testRanges("Range: [0/3] -> [0/6]", highlightRanges, "highlight");
|
||||||
|
|
||||||
|
range = iSearch.removeChar(); // "12"
|
||||||
|
highlightRanges = callHighlighterUpdate(editor.session);
|
||||||
|
testRanges("Range: [0/3] -> [0/5]", [range], "range");
|
||||||
|
testRanges("Range: [0/3] -> [0/5],Range: [1/3] -> [1/5]", highlightRanges, "highlight");
|
||||||
|
},
|
||||||
|
|
||||||
|
"test: forward / backward" : function() {
|
||||||
|
iSearch.activate(editor);
|
||||||
|
iSearch.addString('1'); iSearch.addString('2');
|
||||||
|
var range = iSearch.next();
|
||||||
|
testRanges("Range: [1/3] -> [1/5]", [range], "range");
|
||||||
|
|
||||||
|
range = iSearch.next(); // nothing to find
|
||||||
|
testRanges("", [range], "range");
|
||||||
|
|
||||||
|
range = iSearch.next({backwards: true}); // backwards
|
||||||
|
testRanges("Range: [1/5] -> [1/3]", [range], "range");
|
||||||
|
},
|
||||||
|
|
||||||
|
"test: cancelSearch" : function() {
|
||||||
|
iSearch.activate(editor);
|
||||||
|
iSearch.addString('1'); iSearch.addString('2');
|
||||||
|
var range = iSearch.cancelSearch(true);
|
||||||
|
testRanges("Range: [0/0] -> [0/0]", [range], "range");
|
||||||
|
|
||||||
|
iSearch.addString('1'); range = iSearch.addString('2');
|
||||||
|
testRanges("Range: [0/3] -> [0/5]", [range], "range");
|
||||||
|
},
|
||||||
|
|
||||||
|
"test: failing search keeps pos" : function() {
|
||||||
|
iSearch.activate(editor);
|
||||||
|
iSearch.addString('1'); iSearch.addString('2');
|
||||||
|
var range = iSearch.addString('x');
|
||||||
|
testRanges("", [range], "range");
|
||||||
|
assert.position(editor.getCursorPosition(), 0, 5);
|
||||||
|
},
|
||||||
|
|
||||||
|
"test: backwards search" : function() {
|
||||||
|
editor.moveCursorTo(1,0);
|
||||||
|
iSearch.activate(editor, true);
|
||||||
|
iSearch.addString('1'); var range = iSearch.addString('2');;
|
||||||
|
testRanges("Range: [0/5] -> [0/3]", [range], "range");
|
||||||
|
assert.position(editor.getCursorPosition(), 0, 3);
|
||||||
|
},
|
||||||
|
|
||||||
|
"test: forwards then backwards, same result, reoriented range" : function() {
|
||||||
|
iSearch.activate(editor);
|
||||||
|
iSearch.addString('1'); var range = iSearch.addString('2');;
|
||||||
|
testRanges("Range: [0/3] -> [0/5]", [range], "range");
|
||||||
|
assert.position(editor.getCursorPosition(), 0, 5);
|
||||||
|
|
||||||
|
range = iSearch.next({backwards: true});
|
||||||
|
testRanges("Range: [0/5] -> [0/3]", [range], "range");
|
||||||
|
assert.position(editor.getCursorPosition(), 0, 3);
|
||||||
|
},
|
||||||
|
|
||||||
|
"test: reuse prev search via option" : function() {
|
||||||
|
iSearch.activate(editor);
|
||||||
|
iSearch.addString('1'); iSearch.addString('2');;
|
||||||
|
assert.position(editor.getCursorPosition(), 0, 5);
|
||||||
|
iSearch.deactivate();
|
||||||
|
|
||||||
|
iSearch.activate(editor);
|
||||||
|
iSearch.next({backwards: false, useCurrentOrPrevSearch: true});
|
||||||
|
assert.position(editor.getCursorPosition(), 1, 5);
|
||||||
|
},
|
||||||
|
|
||||||
|
"test: don't extend selection range if selection is empty" : function() {
|
||||||
|
iSearch.activate(editor);
|
||||||
|
iSearch.addString('1'); iSearch.addString('2');;
|
||||||
|
testRanges("Range: [0/5] -> [0/5]", [editor.getSelectionRange()], "sel range");
|
||||||
|
},
|
||||||
|
|
||||||
|
"test: extend selection range if selection exists" : function() {
|
||||||
|
iSearch.activate(editor);
|
||||||
|
editor.selection.selectTo(0, 1);
|
||||||
|
iSearch.addString('1'); iSearch.addString('2');;
|
||||||
|
testRanges("Range: [0/0] -> [0/5]", [editor.getSelectionRange()], "sel range");
|
||||||
|
},
|
||||||
|
|
||||||
|
"test: extend selection in emacs mark mode" : function() {
|
||||||
|
var emacs = require('./keyboard/emacs');
|
||||||
|
editor.keyBinding.addKeyboardHandler(emacs.handler);
|
||||||
|
emacs.handler.commands.setMark.exec(editor);
|
||||||
|
iSearch.activate(editor);
|
||||||
|
iSearch.addString('1'); iSearch.addString('2');
|
||||||
|
testRanges("Range: [0/0] -> [0/5]", [editor.getSelectionRange()], "sel range");
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
if (typeof module !== "undefined" && module === require.main) {
|
||||||
|
require("asyncjs").test.testcase(module.exports).exec()
|
||||||
|
}
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 2010, Ajax.org B.V.
|
* Copyright (c) 2010, Ajax.org B.V.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
* * Redistributions of source code must retain the above copyright
|
* * Redistributions of source code must retain the above copyright
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
* * Neither the name of Ajax.org B.V. nor the
|
* * Neither the name of Ajax.org B.V. nor the
|
||||||
* names of its contributors may be used to endorse or promote products
|
* names of its contributors may be used to endorse or promote products
|
||||||
* derived from this software without specific prior written permission.
|
* derived from this software without specific prior written permission.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
@@ -32,15 +32,18 @@ define(function(require, exports, module) {
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var dom = require("../lib/dom");
|
var dom = require("../lib/dom");
|
||||||
|
require("../incremental_search");
|
||||||
|
var iSearchCommandModule = require("../commands/incremental_search_commands");
|
||||||
|
|
||||||
var screenToTextBlockCoordinates = function(pageX, pageY) {
|
|
||||||
|
var screenToTextBlockCoordinates = function(x, y) {
|
||||||
var canvasPos = this.scroller.getBoundingClientRect();
|
var canvasPos = this.scroller.getBoundingClientRect();
|
||||||
|
|
||||||
var col = Math.floor(
|
var col = Math.floor(
|
||||||
(pageX + this.scrollLeft - canvasPos.left - this.$padding - dom.getPageScrollLeft()) / this.characterWidth
|
(x + this.scrollLeft - canvasPos.left - this.$padding) / this.characterWidth
|
||||||
);
|
);
|
||||||
var row = Math.floor(
|
var row = Math.floor(
|
||||||
(pageY + this.scrollTop - canvasPos.top - dom.getPageScrollTop()) / this.lineHeight
|
(y + this.scrollTop - canvasPos.top) / this.lineHeight
|
||||||
);
|
);
|
||||||
|
|
||||||
return this.session.screenToDocumentPosition(row, col);
|
return this.session.screenToDocumentPosition(row, col);
|
||||||
@@ -49,20 +52,26 @@ var screenToTextBlockCoordinates = function(pageX, pageY) {
|
|||||||
var HashHandler = require("./hash_handler").HashHandler;
|
var HashHandler = require("./hash_handler").HashHandler;
|
||||||
exports.handler = new HashHandler();
|
exports.handler = new HashHandler();
|
||||||
|
|
||||||
|
exports.handler.isEmacs = true;
|
||||||
|
exports.handler.$id = "ace/keyboard/emacs";
|
||||||
|
|
||||||
var initialized = false;
|
var initialized = false;
|
||||||
|
var $formerLongWords;
|
||||||
|
var $formerLineStart;
|
||||||
|
|
||||||
exports.handler.attach = function(editor) {
|
exports.handler.attach = function(editor) {
|
||||||
if (!initialized) {
|
if (!initialized) {
|
||||||
initialized = true;
|
initialized = true;
|
||||||
dom.importCssString('\
|
dom.importCssString('\
|
||||||
.emacs-mode .ace_cursor{\
|
.emacs-mode .ace_cursor{\
|
||||||
border: 2px rgba(50,250,50,0.8) solid!important;\
|
border: 1px rgba(50,250,50,0.8) solid!important;\
|
||||||
-moz-box-sizing: border-box!important;\
|
-moz-box-sizing: border-box!important;\
|
||||||
-webkit-box-sizing: border-box!important;\
|
-webkit-box-sizing: border-box!important;\
|
||||||
box-sizing: border-box!important;\
|
box-sizing: border-box!important;\
|
||||||
background-color: rgba(0,250,0,0.9);\
|
background-color: rgba(0,250,0,0.9);\
|
||||||
opacity: 0.5;\
|
opacity: 0.5;\
|
||||||
}\
|
}\
|
||||||
.emacs-mode .ace_cursor.ace_hidden{\
|
.emacs-mode .ace_hidden-cursors .ace_cursor{\
|
||||||
opacity: 1;\
|
opacity: 1;\
|
||||||
background-color: transparent;\
|
background-color: transparent;\
|
||||||
}\
|
}\
|
||||||
@@ -79,110 +88,268 @@ exports.handler.attach = function(editor) {
|
|||||||
}', 'emacsMode'
|
}', 'emacsMode'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
// in emacs, gotowordleft/right should not count a space as a word..
|
||||||
|
$formerLongWords = editor.session.$selectLongWords;
|
||||||
|
editor.session.$selectLongWords = true;
|
||||||
|
// CTRL-A should go to actual beginning of line
|
||||||
|
$formerLineStart = editor.session.$useEmacsStyleLineStart;
|
||||||
|
editor.session.$useEmacsStyleLineStart = true;
|
||||||
|
|
||||||
|
editor.session.$emacsMark = null; // the active mark
|
||||||
|
editor.session.$emacsMarkRing = editor.session.$emacsMarkRing || [];
|
||||||
|
|
||||||
|
editor.emacsMark = function() {
|
||||||
|
return this.session.$emacsMark;
|
||||||
|
};
|
||||||
|
|
||||||
|
editor.setEmacsMark = function(p) {
|
||||||
|
// to deactivate pass in a falsy value
|
||||||
|
this.session.$emacsMark = p;
|
||||||
|
};
|
||||||
|
|
||||||
|
editor.pushEmacsMark = function(p, activate) {
|
||||||
|
var prevMark = this.session.$emacsMark;
|
||||||
|
if (prevMark)
|
||||||
|
this.session.$emacsMarkRing.push(prevMark);
|
||||||
|
if (!p || activate) this.setEmacsMark(p);
|
||||||
|
else this.session.$emacsMarkRing.push(p);
|
||||||
|
};
|
||||||
|
|
||||||
|
editor.popEmacsMark = function() {
|
||||||
|
var mark = this.emacsMark();
|
||||||
|
if (mark) { this.setEmacsMark(null); return mark; }
|
||||||
|
return this.session.$emacsMarkRing.pop();
|
||||||
|
};
|
||||||
|
|
||||||
|
editor.getLastEmacsMark = function(p) {
|
||||||
|
return this.session.$emacsMark || this.session.$emacsMarkRing.slice(-1)[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
editor.emacsMarkForSelection = function(replacement) {
|
||||||
|
// find the mark in $emacsMarkRing corresponding to the current
|
||||||
|
// selection
|
||||||
|
var sel = this.selection,
|
||||||
|
multiRangeLength = this.multiSelect ?
|
||||||
|
this.multiSelect.getAllRanges().length : 1,
|
||||||
|
selIndex = sel.index || 0,
|
||||||
|
markRing = this.session.$emacsMarkRing,
|
||||||
|
markIndex = markRing.length - (multiRangeLength - selIndex),
|
||||||
|
lastMark = markRing[markIndex] || sel.anchor;
|
||||||
|
if (replacement) {
|
||||||
|
markRing.splice(markIndex, 1,
|
||||||
|
"row" in replacement && "column" in replacement ?
|
||||||
|
replacement : undefined);
|
||||||
|
}
|
||||||
|
return lastMark;
|
||||||
|
}
|
||||||
|
|
||||||
|
editor.on("click", $resetMarkMode);
|
||||||
|
editor.on("changeSession", $kbSessionChange);
|
||||||
editor.renderer.screenToTextCoordinates = screenToTextBlockCoordinates;
|
editor.renderer.screenToTextCoordinates = screenToTextBlockCoordinates;
|
||||||
editor.setStyle("emacs-mode");
|
editor.setStyle("emacs-mode");
|
||||||
|
editor.commands.addCommands(commands);
|
||||||
|
exports.handler.platform = editor.commands.platform;
|
||||||
|
editor.$emacsModeHandler = this;
|
||||||
|
editor.addEventListener('copy', this.onCopy);
|
||||||
|
editor.addEventListener('paste', this.onPaste);
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.handler.detach = function(editor) {
|
exports.handler.detach = function(editor) {
|
||||||
delete editor.renderer.screenToTextCoordinates;
|
delete editor.renderer.screenToTextCoordinates;
|
||||||
|
editor.session.$selectLongWords = $formerLongWords;
|
||||||
|
editor.session.$useEmacsStyleLineStart = $formerLineStart;
|
||||||
|
editor.removeEventListener("click", $resetMarkMode);
|
||||||
|
editor.removeEventListener("changeSession", $kbSessionChange);
|
||||||
editor.unsetStyle("emacs-mode");
|
editor.unsetStyle("emacs-mode");
|
||||||
|
editor.commands.removeCommands(commands);
|
||||||
|
editor.removeEventListener('copy', this.onCopy);
|
||||||
|
editor.removeEventListener('paste', this.onPaste);
|
||||||
|
editor.$emacsModeHandler = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var $kbSessionChange = function(e) {
|
||||||
|
if (e.oldSession) {
|
||||||
|
e.oldSession.$selectLongWords = $formerLongWords;
|
||||||
|
e.oldSession.$useEmacsStyleLineStart = $formerLineStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
$formerLongWords = e.session.$selectLongWords;
|
||||||
|
e.session.$selectLongWords = true;
|
||||||
|
$formerLineStart = e.session.$useEmacsStyleLineStart;
|
||||||
|
e.session.$useEmacsStyleLineStart = true;
|
||||||
|
|
||||||
|
if (!e.session.hasOwnProperty('$emacsMark'))
|
||||||
|
e.session.$emacsMark = null;
|
||||||
|
if (!e.session.hasOwnProperty('$emacsMarkRing'))
|
||||||
|
e.session.$emacsMarkRing = [];
|
||||||
|
};
|
||||||
|
|
||||||
|
var $resetMarkMode = function(e) {
|
||||||
|
e.editor.session.$emacsMark = null;
|
||||||
|
};
|
||||||
|
|
||||||
var keys = require("../lib/keys").KEY_MODS;
|
var keys = require("../lib/keys").KEY_MODS;
|
||||||
var eMods = {
|
var eMods = {C: "ctrl", S: "shift", M: "alt", CMD: "command"};
|
||||||
C: "ctrl", S: "shift", M: "alt"
|
var combinations = ["C-S-M-CMD",
|
||||||
};
|
"S-M-CMD", "C-M-CMD", "C-S-CMD", "C-S-M",
|
||||||
["S-C-M", "S-C", "S-M", "C-M", "S", "C", "M"].forEach(function(c) {
|
"M-CMD", "S-CMD", "S-M", "C-CMD", "C-M", "C-S",
|
||||||
|
"CMD", "M", "S", "C"];
|
||||||
|
combinations.forEach(function(c) {
|
||||||
var hashId = 0;
|
var hashId = 0;
|
||||||
c.split("-").forEach(function(c){
|
c.split("-").forEach(function(c) {
|
||||||
hashId = hashId | keys[eMods[c]];
|
hashId = hashId | keys[eMods[c]];
|
||||||
});
|
});
|
||||||
eMods[hashId] = c.toLowerCase() + "-";
|
eMods[hashId] = c.toLowerCase() + "-";
|
||||||
});
|
});
|
||||||
|
|
||||||
|
exports.handler.onCopy = function(e, editor) {
|
||||||
|
if (editor.$handlesEmacsOnCopy) return;
|
||||||
|
editor.$handlesEmacsOnCopy = true;
|
||||||
|
exports.handler.commands.killRingSave.exec(editor);
|
||||||
|
editor.$handlesEmacsOnCopy = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.handler.onPaste = function(e, editor) {
|
||||||
|
editor.pushEmacsMark(editor.getCursorPosition());
|
||||||
|
};
|
||||||
|
|
||||||
exports.handler.bindKey = function(key, command) {
|
exports.handler.bindKey = function(key, command) {
|
||||||
|
if (typeof key == "object")
|
||||||
|
key = key[this.platform];
|
||||||
if (!key)
|
if (!key)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var ckb = this.commmandKeyBinding;
|
var ckb = this.commandKeyBinding;
|
||||||
key.split("|").forEach(function(keyPart) {
|
key.split("|").forEach(function(keyPart) {
|
||||||
keyPart = keyPart.toLowerCase();
|
keyPart = keyPart.toLowerCase();
|
||||||
ckb[keyPart] = command;
|
ckb[keyPart] = command;
|
||||||
keyPart = keyPart.split(" ")[0];
|
// register all partial key combos as null commands
|
||||||
if (!ckb[keyPart])
|
// to be able to activate key combos with arbitrary length
|
||||||
ckb[keyPart] = "null";
|
// Example: if keyPart is "C-c C-l t" then "C-c C-l t" will
|
||||||
|
// get command assigned and "C-c" and "C-c C-l" will get
|
||||||
|
// a null command assigned in this.commandKeyBinding. For
|
||||||
|
// the lookup logic see handleKeyboard()
|
||||||
|
var keyParts = keyPart.split(" ").slice(0,-1);
|
||||||
|
keyParts.reduce(function(keyMapKeys, keyPart, i) {
|
||||||
|
var prefix = keyMapKeys[i-1] ? keyMapKeys[i-1] + ' ' : '';
|
||||||
|
return keyMapKeys.concat([prefix + keyPart]);
|
||||||
|
}, []).forEach(function(keyPart) {
|
||||||
|
if (!ckb[keyPart]) ckb[keyPart] = "null";
|
||||||
|
});
|
||||||
}, this);
|
}, this);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports.handler.getStatusText = function(editor, data) {
|
||||||
|
var str = "";
|
||||||
|
if (data.count)
|
||||||
|
str += data.count;
|
||||||
|
if (data.keyChain)
|
||||||
|
str += " " + data.keyChain
|
||||||
|
return str;
|
||||||
|
};
|
||||||
|
|
||||||
exports.handler.handleKeyboard = function(data, hashId, key, keyCode) {
|
exports.handler.handleKeyboard = function(data, hashId, key, keyCode) {
|
||||||
|
// if keyCode == -1 a non-printable key was pressed, such as just
|
||||||
|
// control. Handling those is currently not supported in this handler
|
||||||
|
if (keyCode === -1) return undefined;
|
||||||
|
|
||||||
|
var editor = data.editor;
|
||||||
|
editor._signal("changeStatus");
|
||||||
|
// insertstring data.count times
|
||||||
if (hashId == -1) {
|
if (hashId == -1) {
|
||||||
|
editor.pushEmacsMark();
|
||||||
if (data.count) {
|
if (data.count) {
|
||||||
var str = Array(data.count + 1).join(key);
|
var str = new Array(data.count + 1).join(key);
|
||||||
data.count = null;
|
data.count = null;
|
||||||
return {command: "insertstring", args: str};
|
return {command: "insertstring", args: str};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key == "\x00")
|
|
||||||
return;
|
|
||||||
|
|
||||||
var modifier = eMods[hashId];
|
var modifier = eMods[hashId];
|
||||||
if (modifier == "c-" || data.universalArgument) {
|
|
||||||
|
// CTRL + number / universalArgument for setting data.count
|
||||||
|
if (modifier == "c-" || data.count) {
|
||||||
var count = parseInt(key[key.length - 1]);
|
var count = parseInt(key[key.length - 1]);
|
||||||
if (count) {
|
if (typeof count === 'number' && !isNaN(count)) {
|
||||||
data.count = count;
|
data.count = Math.max(data.count, 0) || 0;
|
||||||
|
data.count = 10 * data.count + count;
|
||||||
return {command: "null"};
|
return {command: "null"};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
data.universalArgument = false;
|
|
||||||
|
|
||||||
if (modifier)
|
// this.commandKeyBinding maps key specs like "c-p" (for CTRL + P) to
|
||||||
key = modifier + key;
|
// command objects, for lookup key needs to include the modifier
|
||||||
|
if (modifier) key = modifier + key;
|
||||||
|
|
||||||
if (data.keyChain)
|
// Key combos like CTRL+X H build up the data.keyChain
|
||||||
key = data.keyChain += " " + key;
|
if (data.keyChain) key = data.keyChain += " " + key;
|
||||||
|
|
||||||
var command = this.commmandKeyBinding[key];
|
// Key combo prefixes get stored as "null" (String!) in this
|
||||||
|
// this.commandKeyBinding. When encountered no command is invoked but we
|
||||||
|
// buld up data.keyChain
|
||||||
|
var command = this.commandKeyBinding[key];
|
||||||
data.keyChain = command == "null" ? key : "";
|
data.keyChain = command == "null" ? key : "";
|
||||||
|
|
||||||
if (!command)
|
// there really is no command
|
||||||
return;
|
if (!command) return undefined;
|
||||||
|
|
||||||
if (command == "null")
|
// we pass b/c of key combo or universalArgument
|
||||||
return {command: "null"};
|
if (command === "null") return {command: "null"};
|
||||||
|
|
||||||
if (command == "universalArgument") {
|
if (command === "universalArgument") {
|
||||||
data.universalArgument = true;
|
// if no number pressed emacs repeats action 4 times.
|
||||||
|
// minus sign is needed to allow next keypress to replace it
|
||||||
|
data.count = -4;
|
||||||
return {command: "null"};
|
return {command: "null"};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof command != "string") {
|
// lookup command
|
||||||
var args = command.args;
|
// TODO extract special handling of markmode
|
||||||
command = command.command;
|
// TODO special case command.command is really unnecessary, remove
|
||||||
|
var args;
|
||||||
|
if (typeof command !== "string") {
|
||||||
|
args = command.args;
|
||||||
|
if (command.command) command = command.command;
|
||||||
|
if (command === "goorselect") {
|
||||||
|
command = editor.emacsMark() ? args[1] : args[0];
|
||||||
|
args = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof command == "string") {
|
if (typeof command === "string") {
|
||||||
command = this.commands[command] || data.editor.commands.commands[command];
|
if (command === "insertstring" ||
|
||||||
|
command === "splitline" ||
|
||||||
|
command === "togglecomment") {
|
||||||
|
editor.pushEmacsMark();
|
||||||
|
}
|
||||||
|
command = this.commands[command] || editor.commands.commands[command];
|
||||||
|
if (!command) return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!command.readonly && !command.isYank)
|
if (!command.readOnly && !command.isYank)
|
||||||
data.lastCommand = null;
|
data.lastCommand = null;
|
||||||
|
|
||||||
|
if (!command.readOnly && editor.emacsMark())
|
||||||
|
editor.setEmacsMark(null)
|
||||||
|
|
||||||
if (data.count) {
|
if (data.count) {
|
||||||
var count = data.count;
|
var count = data.count;
|
||||||
data.count = 0;
|
data.count = 0;
|
||||||
return {
|
if (!command || !command.handlesCount) {
|
||||||
args: args,
|
return {
|
||||||
command: {
|
args: args,
|
||||||
exec: function(editor, args) {
|
command: {
|
||||||
for (var i = 0; i < count; i++)
|
exec: function(editor, args) {
|
||||||
command.exec(editor, args);
|
for (var i = 0; i < count; i++)
|
||||||
|
command.exec(editor, args);
|
||||||
|
},
|
||||||
|
multiSelectAction: command.multiSelectAction
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
};
|
} else {
|
||||||
|
if (!args) args = {};
|
||||||
|
if (typeof args === 'object') args.count = count;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {command: command, args: args};
|
return {command: command, args: args};
|
||||||
@@ -190,16 +357,16 @@ exports.handler.handleKeyboard = function(data, hashId, key, keyCode) {
|
|||||||
|
|
||||||
exports.emacsKeys = {
|
exports.emacsKeys = {
|
||||||
// movement
|
// movement
|
||||||
"Up|C-p" : "golineup",
|
"Up|C-p" : {command: "goorselect", args: ["golineup","selectup"]},
|
||||||
"Down|C-n" : "golinedown",
|
"Down|C-n" : {command: "goorselect", args: ["golinedown","selectdown"]},
|
||||||
"Left|C-b" : "gotoleft",
|
"Left|C-b" : {command: "goorselect", args: ["gotoleft","selectleft"]},
|
||||||
"Right|C-f" : "gotoright",
|
"Right|C-f" : {command: "goorselect", args: ["gotoright","selectright"]},
|
||||||
"C-Left|M-b" : "gotowordleft",
|
"C-Left|M-b" : {command: "goorselect", args: ["gotowordleft","selectwordleft"]},
|
||||||
"C-Right|M-f" : "gotowordright",
|
"C-Right|M-f" : {command: "goorselect", args: ["gotowordright","selectwordright"]},
|
||||||
"Home|C-a" : "gotolinestart",
|
"Home|C-a" : {command: "goorselect", args: ["gotolinestart","selecttolinestart"]},
|
||||||
"End|C-e" : "gotolineend",
|
"End|C-e" : {command: "goorselect", args: ["gotolineend","selecttolineend"]},
|
||||||
"C-Home|S-M-,": "gotostart",
|
"C-Home|S-M-,": {command: "goorselect", args: ["gotostart","selecttostart"]},
|
||||||
"C-End|S-M-." : "gotoend",
|
"C-End|S-M-." : {command: "goorselect", args: ["gotoend","selecttoend"]},
|
||||||
|
|
||||||
// selection
|
// selection
|
||||||
"S-Up|S-C-p" : "selectup",
|
"S-Up|S-C-p" : "selectup",
|
||||||
@@ -219,14 +386,16 @@ exports.emacsKeys = {
|
|||||||
"C-x C-p": "selectall",
|
"C-x C-p": "selectall",
|
||||||
|
|
||||||
// todo fix these
|
// todo fix these
|
||||||
"C-Down": "gotopagedown",
|
"C-Down": {command: "goorselect", args: ["gotopagedown","selectpagedown"]},
|
||||||
"C-Up": "gotopageup",
|
"C-Up": {command: "goorselect", args: ["gotopageup","selectpageup"]},
|
||||||
"PageDown|C-v": "gotopagedown",
|
"PageDown|C-v": {command: "goorselect", args: ["gotopagedown","selectpagedown"]},
|
||||||
"PageUp|M-v": "gotopageup",
|
"PageUp|M-v": {command: "goorselect", args: ["gotopageup","selectpageup"]},
|
||||||
"S-C-Down": "selectpagedown",
|
"S-C-Down": "selectpagedown",
|
||||||
"S-C-Up": "selectpageup",
|
"S-C-Up": "selectpageup",
|
||||||
"C-s": "findnext",
|
|
||||||
"C-r": "findprevious",
|
"C-s": "iSearch",
|
||||||
|
"C-r": "iSearchBackwards",
|
||||||
|
|
||||||
"M-C-s": "findnext",
|
"M-C-s": "findnext",
|
||||||
"M-C-r": "findprevious",
|
"M-C-r": "findprevious",
|
||||||
"S-M-5": "replace",
|
"S-M-5": "replace",
|
||||||
@@ -245,27 +414,26 @@ exports.emacsKeys = {
|
|||||||
"M-y": "yankRotate",
|
"M-y": "yankRotate",
|
||||||
"C-g": "keyboardQuit",
|
"C-g": "keyboardQuit",
|
||||||
|
|
||||||
"C-w": "killRegion",
|
"C-w|C-S-W": "killRegion",
|
||||||
"M-w": "killRingSave",
|
"M-w": "killRingSave",
|
||||||
|
|
||||||
"C-Space": "setMark",
|
"C-Space": "setMark",
|
||||||
"C-x C-x": "exchangePointAndMark",
|
"C-x C-x": "exchangePointAndMark",
|
||||||
|
|
||||||
"C-t": "transposeletters",
|
"C-t": "transposeletters",
|
||||||
|
"M-u": "touppercase", // Doesn't work
|
||||||
"M-u": "touppercase",
|
|
||||||
"M-l": "tolowercase",
|
"M-l": "tolowercase",
|
||||||
"M-/": "autocomplete",
|
"M-/": "autocomplete", // Doesn't work
|
||||||
"C-u": "universalArgument",
|
"C-u": "universalArgument",
|
||||||
|
|
||||||
"M-;": "togglecomment",
|
"M-;": "togglecomment",
|
||||||
|
|
||||||
"C-/|C-x u|S-C--|C-z": "undo",
|
"C-/|C-x u|S-C--|C-z": "undo",
|
||||||
"S-C-/|S-C-x u|C--|S-C-z": "redo", //infinite undo?
|
"S-C-/|S-C-x u|C--|S-C-z": "redo", //infinite undo?
|
||||||
// vertical editing
|
// vertical editing
|
||||||
"C-x r": "selectRectangularRegion"
|
"C-x r": "selectRectangularRegion",
|
||||||
|
"M-x": {command: "focusCommandLine", args: "M-x "}
|
||||||
// todo
|
// todo
|
||||||
// "M-x" "C-x C-t" "M-t" "M-c" "F11" "C-M- "M-q"
|
// "C-x C-t" "M-t" "M-c" "F11" "C-M- "M-q"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -275,7 +443,7 @@ exports.handler.addCommands({
|
|||||||
recenterTopBottom: function(editor) {
|
recenterTopBottom: function(editor) {
|
||||||
var renderer = editor.renderer;
|
var renderer = editor.renderer;
|
||||||
var pos = renderer.$cursorLayer.getPixelPosition();
|
var pos = renderer.$cursorLayer.getPixelPosition();
|
||||||
var h = renderer.$size.scrollerHeight - renderer.lineHeight;
|
var h = renderer.$size.scrollerHeight - renderer.lineHeight;
|
||||||
var scrollTop = renderer.scrollTop;
|
var scrollTop = renderer.scrollTop;
|
||||||
if (Math.abs(pos.top - scrollTop) < 2) {
|
if (Math.abs(pos.top - scrollTop) < 2) {
|
||||||
scrollTop = pos.top - h;
|
scrollTop = pos.top - h;
|
||||||
@@ -289,15 +457,74 @@ exports.handler.addCommands({
|
|||||||
selectRectangularRegion: function(editor) {
|
selectRectangularRegion: function(editor) {
|
||||||
editor.multiSelect.toggleBlockSelection();
|
editor.multiSelect.toggleBlockSelection();
|
||||||
},
|
},
|
||||||
setMark: function() {
|
setMark: {
|
||||||
|
exec: function(editor, args) {
|
||||||
|
// Sets mark-mode and clears current selection.
|
||||||
|
// When mark is set, keyboard cursor movement commands become
|
||||||
|
// selection modification commands. That is,
|
||||||
|
// "goto" commands become "select" commands.
|
||||||
|
// Any insertion or mouse click resets mark-mode.
|
||||||
|
// setMark twice in a row at the same place resets markmode.
|
||||||
|
// in multi select mode, ea selection is handled individually
|
||||||
|
|
||||||
|
if (args && args.count) {
|
||||||
|
if (editor.inMultiSelectMode) editor.forEachSelection(moveToMark);
|
||||||
|
else moveToMark();
|
||||||
|
moveToMark();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var mark = editor.emacsMark(),
|
||||||
|
ranges = editor.selection.getAllRanges(),
|
||||||
|
rangePositions = ranges.map(function(r) { return {row: r.start.row, column: r.start.column}; }),
|
||||||
|
transientMarkModeActive = true,
|
||||||
|
hasNoSelection = ranges.every(function(range) { return range.isEmpty(); });
|
||||||
|
// if transientMarkModeActive then mark behavior is a little
|
||||||
|
// different. Deactivate the mark when setMark is run with active
|
||||||
|
// mark
|
||||||
|
if (transientMarkModeActive && (mark || !hasNoSelection)) {
|
||||||
|
if (editor.inMultiSelectMode) editor.forEachSelection({exec: editor.clearSelection.bind(editor)})
|
||||||
|
else editor.clearSelection();
|
||||||
|
if (mark) editor.pushEmacsMark(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mark) {
|
||||||
|
rangePositions.forEach(function(pos) { editor.pushEmacsMark(pos); });
|
||||||
|
editor.setEmacsMark(rangePositions[rangePositions.length-1]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||||
|
|
||||||
|
function moveToMark() {
|
||||||
|
var mark = editor.popEmacsMark();
|
||||||
|
mark && editor.moveCursorToPosition(mark);
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
readOnly: true,
|
||||||
|
handlesCount: true
|
||||||
},
|
},
|
||||||
exchangePointAndMark: {
|
exchangePointAndMark: {
|
||||||
exec: function(editor) {
|
exec: function exchangePointAndMark$exec(editor, args) {
|
||||||
var range = editor.selection.getRange();
|
var sel = editor.selection;
|
||||||
editor.selection.setSelectionRange(range, !editor.selection.isBackwards());
|
if (!args.count && !sel.isEmpty()) { // just invert selection
|
||||||
|
sel.setSelectionRange(sel.getRange(), !sel.isBackwards());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.count) { // replace mark and point
|
||||||
|
var pos = {row: sel.lead.row, column: sel.lead.column};
|
||||||
|
sel.clearSelection();
|
||||||
|
sel.moveCursorToPosition(editor.emacsMarkForSelection(pos));
|
||||||
|
} else { // create selection to last mark
|
||||||
|
sel.selectToPosition(editor.emacsMarkForSelection());
|
||||||
|
}
|
||||||
},
|
},
|
||||||
readonly: true,
|
readOnly: true,
|
||||||
multiselectAction: "forEach"
|
handlesCount: true,
|
||||||
|
multiSelectAction: "forEach"
|
||||||
},
|
},
|
||||||
killWord: {
|
killWord: {
|
||||||
exec: function(editor, dir) {
|
exec: function(editor, dir) {
|
||||||
@@ -314,10 +541,23 @@ exports.handler.addCommands({
|
|||||||
editor.session.remove(range);
|
editor.session.remove(range);
|
||||||
editor.clearSelection();
|
editor.clearSelection();
|
||||||
},
|
},
|
||||||
multiselectAction: "forEach"
|
multiSelectAction: "forEach"
|
||||||
},
|
},
|
||||||
killLine: function(editor) {
|
killLine: function(editor) {
|
||||||
editor.selection.selectLine();
|
editor.pushEmacsMark(null);
|
||||||
|
var pos = editor.getCursorPosition();
|
||||||
|
if (pos.column === 0 &&
|
||||||
|
editor.session.doc.getLine(pos.row).length === 0) {
|
||||||
|
// If an already empty line is killed, remove
|
||||||
|
// the line entirely
|
||||||
|
editor.selection.selectLine();
|
||||||
|
} else {
|
||||||
|
// otherwise just remove from the current cursor position
|
||||||
|
// to the end (but don't delete the selection if it's before
|
||||||
|
// the cursor)
|
||||||
|
editor.clearSelection();
|
||||||
|
editor.selection.selectLineEnd();
|
||||||
|
}
|
||||||
var range = editor.getSelectionRange();
|
var range = editor.getSelectionRange();
|
||||||
var text = editor.session.getTextRange(range);
|
var text = editor.session.getTextRange(range);
|
||||||
exports.killRing.add(text);
|
exports.killRing.add(text);
|
||||||
@@ -326,26 +566,63 @@ exports.handler.addCommands({
|
|||||||
editor.clearSelection();
|
editor.clearSelection();
|
||||||
},
|
},
|
||||||
yank: function(editor) {
|
yank: function(editor) {
|
||||||
editor.onPaste(exports.killRing.get());
|
editor.onPaste(exports.killRing.get() || '');
|
||||||
editor.keyBinding.$data.lastCommand = "yank";
|
editor.keyBinding.$data.lastCommand = "yank";
|
||||||
},
|
},
|
||||||
yankRotate: function(editor) {
|
yankRotate: function(editor) {
|
||||||
if (editor.keyBinding.$data.lastCommand != "yank")
|
if (editor.keyBinding.$data.lastCommand != "yank")
|
||||||
return;
|
return;
|
||||||
|
|
||||||
editor.undo();
|
editor.undo();
|
||||||
|
editor.session.$emacsMarkRing.pop(); // also undo recording mark
|
||||||
editor.onPaste(exports.killRing.rotate());
|
editor.onPaste(exports.killRing.rotate());
|
||||||
editor.keyBinding.$data.lastCommand = "yank";
|
editor.keyBinding.$data.lastCommand = "yank";
|
||||||
},
|
},
|
||||||
killRegion: function(editor) {
|
killRegion: {
|
||||||
exports.killRing.add(editor.getCopyText());
|
exec: function(editor) {
|
||||||
editor.commands.byName.cut.exec(editor);
|
exports.killRing.add(editor.getCopyText());
|
||||||
|
editor.commands.byName.cut.exec(editor);
|
||||||
|
},
|
||||||
|
readOnly: true,
|
||||||
|
multiSelectAction: "forEach"
|
||||||
},
|
},
|
||||||
killRingSave: function(editor) {
|
killRingSave: {
|
||||||
exports.killRing.add(editor.getCopyText());
|
exec: function(editor) {
|
||||||
|
// copy text and deselect. will save marks for starts of the
|
||||||
|
// selection(s)
|
||||||
|
|
||||||
|
editor.$handlesEmacsOnCopy = true;
|
||||||
|
var marks = editor.session.$emacsMarkRing.slice(),
|
||||||
|
deselectedMarks = [];
|
||||||
|
exports.killRing.add(editor.getCopyText());
|
||||||
|
|
||||||
|
setTimeout(function() {
|
||||||
|
function deselect() {
|
||||||
|
var sel = editor.selection, range = sel.getRange(),
|
||||||
|
pos = sel.isBackwards() ? range.end : range.start;
|
||||||
|
deselectedMarks.push({row: pos.row, column: pos.column});
|
||||||
|
sel.clearSelection();
|
||||||
|
}
|
||||||
|
editor.$handlesEmacsOnCopy = false;
|
||||||
|
if (editor.inMultiSelectMode) editor.forEachSelection({exec: deselect});
|
||||||
|
else deselect();
|
||||||
|
editor.session.$emacsMarkRing = marks.concat(deselectedMarks.reverse());
|
||||||
|
}, 0);
|
||||||
|
},
|
||||||
|
readOnly: true
|
||||||
|
},
|
||||||
|
keyboardQuit: function(editor) {
|
||||||
|
editor.selection.clearSelection();
|
||||||
|
editor.setEmacsMark(null);
|
||||||
|
editor.keyBinding.$data.count = null;
|
||||||
|
},
|
||||||
|
focusCommandLine: function(editor, arg) {
|
||||||
|
if (editor.showCommandLine)
|
||||||
|
editor.showCommandLine(arg);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
exports.handler.addCommands(iSearchCommandModule.iSearchStartCommands);
|
||||||
|
|
||||||
var commands = exports.handler.commands;
|
var commands = exports.handler.commands;
|
||||||
commands.yank.isYank = true;
|
commands.yank.isYank = true;
|
||||||
commands.yankRotate.isYank = true;
|
commands.yankRotate.isYank = true;
|
||||||
@@ -357,8 +634,9 @@ exports.killRing = {
|
|||||||
if (this.$data.length > 30)
|
if (this.$data.length > 30)
|
||||||
this.$data.shift();
|
this.$data.shift();
|
||||||
},
|
},
|
||||||
get: function() {
|
get: function(n) {
|
||||||
return this.$data[this.$data.length - 1] || "";
|
n = n || 1;
|
||||||
|
return this.$data.slice(this.$data.length-n, this.$data.length).reverse().join('\n');
|
||||||
},
|
},
|
||||||
pop: function() {
|
pop: function() {
|
||||||
if (this.$data.length > 1)
|
if (this.$data.length > 1)
|
||||||
@@ -371,5 +649,4 @@ exports.killRing = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,151 @@
|
|||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Distributed under the BSD license:
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010, Ajax.org B.V.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of Ajax.org B.V. nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
if (typeof process !== "undefined") {
|
||||||
|
require("amd-loader");
|
||||||
|
}
|
||||||
|
|
||||||
|
define(function(require, exports, module) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
require("../multi_select");
|
||||||
|
|
||||||
|
var EditSession = require("./../edit_session").EditSession,
|
||||||
|
Editor = require("./../editor").Editor,
|
||||||
|
Range = require("./../range").Range,
|
||||||
|
MockRenderer = require("./../test/mockrenderer").MockRenderer,
|
||||||
|
emacs = require('./emacs'),
|
||||||
|
assert = require("./../test/assertions"),
|
||||||
|
editor, sel;
|
||||||
|
|
||||||
|
function initEditor(docString) {
|
||||||
|
var doc = new EditSession(docString.split("\n"));
|
||||||
|
editor = new Editor(new MockRenderer(), doc);
|
||||||
|
editor.setKeyboardHandler(emacs.handler);
|
||||||
|
sel = editor.selection;
|
||||||
|
}
|
||||||
|
|
||||||
|
function print(obj) {
|
||||||
|
return JSON.stringify(obj, null, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
function pluck(arr, what) {
|
||||||
|
return arr.map(function(ea) { return ea[what]; });
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
|
||||||
|
"test: detach removes emacs commands from command manager": function() {
|
||||||
|
initEditor('');
|
||||||
|
assert.ok(!!editor.commands.byName["keyboardQuit"], 'setup error: emacs commands not installed');
|
||||||
|
editor.keyBinding.removeKeyboardHandler(editor.getKeyboardHandler());
|
||||||
|
assert.ok(!editor.commands.byName["keyboardQuit"], 'emacs commands not removed');
|
||||||
|
},
|
||||||
|
|
||||||
|
"test: keyboardQuit clears selection": function() {
|
||||||
|
initEditor('foo');
|
||||||
|
editor.selectAll();
|
||||||
|
editor.execCommand('keyboardQuit');
|
||||||
|
assert.ok(editor.selection.isEmpty(), 'selection non-empty');
|
||||||
|
},
|
||||||
|
|
||||||
|
"test: exchangePointAndMark without mark set": function() {
|
||||||
|
initEditor('foo');
|
||||||
|
sel.setRange(Range.fromPoints({row: 0, column: 1}, {row: 0, column: 3}));
|
||||||
|
editor.execCommand('exchangePointAndMark');
|
||||||
|
assert.deepEqual({row: 0, column: 1}, editor.getCursorPosition(), print(editor.getCursorPosition()));
|
||||||
|
},
|
||||||
|
|
||||||
|
"test: exchangePointAndMark with mark set": function() {
|
||||||
|
initEditor('foo');
|
||||||
|
editor.pushEmacsMark({row: 0, column: 1});
|
||||||
|
editor.pushEmacsMark({row: 0, column: 2});
|
||||||
|
editor.execCommand('exchangePointAndMark', {count: 4});
|
||||||
|
assert.deepEqual({row: 0, column: 2}, editor.getCursorPosition(), print(editor.getCursorPosition()));
|
||||||
|
assert.deepEqual([{row: 0, column: 1}, {row: 0, column: 0}], editor.session.$emacsMarkRing, print(editor.session.$emacsMarkRing));
|
||||||
|
},
|
||||||
|
|
||||||
|
"test: exchangePointAndMark with selection": function() {
|
||||||
|
initEditor('foo');
|
||||||
|
editor.pushEmacsMark({row: 0, column: 1});
|
||||||
|
editor.pushEmacsMark({row: 0, column: 2});
|
||||||
|
sel.setRange(Range.fromPoints({row: 0, column: 0}, {row: 0, column: 1}), true);
|
||||||
|
editor.execCommand('exchangePointAndMark');
|
||||||
|
assert.deepEqual({row: 0, column: 1}, editor.getCursorPosition(), print(editor.getCursorPosition()));
|
||||||
|
assert.deepEqual([{row: 0, column: 1}, {row: 0, column: 2}], editor.session.$emacsMarkRing, print(editor.session.$emacsMarkRing));
|
||||||
|
},
|
||||||
|
|
||||||
|
"test: exchangePointAndMark with multi selection": function() {
|
||||||
|
initEditor('foo\nhello world\n123');
|
||||||
|
var ranges = [[{row: 0, column: 0}, {row: 0, column: 3}],
|
||||||
|
[{row: 1, column: 0}, {row: 1, column: 5}],
|
||||||
|
[{row: 1, column: 6}, {row: 1, column: 11}]]
|
||||||
|
ranges.forEach(function(r) {
|
||||||
|
sel.addRange(Range.fromPoints(r[0], r[1]));
|
||||||
|
});
|
||||||
|
assert.equal("foo\nhello\nworld", editor.getSelectedText());
|
||||||
|
editor.execCommand('exchangePointAndMark');
|
||||||
|
assert.equal("foo\nhello\nworld", editor.getSelectedText());
|
||||||
|
assert.deepEqual(pluck(ranges, 0), pluck(sel.getAllRanges(), 'cursor'), "selections dir not inverted");
|
||||||
|
},
|
||||||
|
|
||||||
|
"test: exchangePointAndMark with multi cursors": function() {
|
||||||
|
initEditor('foo\nhello world\n123');
|
||||||
|
var ranges = [[{row: 0, column: 0}, {row: 0, column: 3}],
|
||||||
|
[{row: 1, column: 0}, {row: 1, column: 5}],
|
||||||
|
[{row: 1, column: 6}, {row: 1, column: 11}]];
|
||||||
|
// move cursors to the start of each range and set a mark to its end
|
||||||
|
// without selecting anything
|
||||||
|
ranges.forEach(function(r) {
|
||||||
|
editor.pushEmacsMark(r[1]);
|
||||||
|
sel.addRange(Range.fromPoints(r[0], r[0]));
|
||||||
|
});
|
||||||
|
assert.deepEqual(pluck(ranges, 0), pluck(sel.getAllRanges(), 'cursor'), print(sel.getAllRanges()));
|
||||||
|
editor.execCommand('exchangePointAndMark');
|
||||||
|
assert.deepEqual(pluck(ranges, 1), pluck(sel.getAllRanges(), 'cursor'), "not inverted: " + print(sel.getAllRanges()));
|
||||||
|
},
|
||||||
|
|
||||||
|
"test: setMark with multi cursors": function() {
|
||||||
|
initEditor('foo\nhello world\n123');
|
||||||
|
var positions = [{row: 0, column: 0},
|
||||||
|
{row: 1, column: 0},
|
||||||
|
{row: 1, column: 6}];
|
||||||
|
positions.forEach(function(p) { sel.addRange(Range.fromPoints(p,p)); });
|
||||||
|
editor.execCommand('setMark');
|
||||||
|
assert.deepEqual(positions, editor.session.$emacsMarkRing, print(editor.session.$emacsMarkRing));
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
if (typeof module !== "undefined" && module === require.main) {
|
||||||
|
require("asyncjs").test.testcase(module.exports).exec()
|
||||||
|
}
|
||||||
@@ -31,17 +31,27 @@
|
|||||||
define(function(require, exports, module) {
|
define(function(require, exports, module) {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var keyUtil = require("../lib/keys");
|
var keyUtil = require("../lib/keys");
|
||||||
|
var useragent = require("../lib/useragent");
|
||||||
|
var KEY_MODS = keyUtil.KEY_MODS;
|
||||||
|
|
||||||
function HashHandler(config, platform) {
|
function HashHandler(config, platform) {
|
||||||
this.platform = platform;
|
this.platform = platform || (useragent.isMac ? "mac" : "win");
|
||||||
this.commands = {};
|
this.commands = {};
|
||||||
this.commmandKeyBinding = {};
|
this.commandKeyBinding = {};
|
||||||
|
|
||||||
this.addCommands(config);
|
this.addCommands(config);
|
||||||
};
|
this.$singleCommand = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function MultiHashHandler(config, platform) {
|
||||||
|
HashHandler.call(this, config, platform);
|
||||||
|
this.$singleCommand = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
MultiHashHandler.prototype = HashHandler.prototype;
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
|
|
||||||
this.addCommand = function(command) {
|
this.addCommand = function(command) {
|
||||||
if (this.commands[command.name])
|
if (this.commands[command.name])
|
||||||
@@ -53,47 +63,92 @@ function HashHandler(config, platform) {
|
|||||||
this._buildKeyHash(command);
|
this._buildKeyHash(command);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.removeCommand = function(command) {
|
this.removeCommand = function(command, keepCommand) {
|
||||||
var name = (typeof command === 'string' ? command : command.name);
|
var name = command && (typeof command === 'string' ? command : command.name);
|
||||||
command = this.commands[name];
|
command = this.commands[name];
|
||||||
delete this.commands[name];
|
if (!keepCommand)
|
||||||
|
delete this.commands[name];
|
||||||
|
|
||||||
// exhaustive search is brute force but since removeCommand is
|
// exhaustive search is brute force but since removeCommand is
|
||||||
// not a performance critical operation this should be OK
|
// not a performance critical operation this should be OK
|
||||||
var ckb = this.commmandKeyBinding;
|
var ckb = this.commandKeyBinding;
|
||||||
for (var hashId in ckb) {
|
for (var keyId in ckb) {
|
||||||
for (var key in ckb[hashId]) {
|
var cmdGroup = ckb[keyId];
|
||||||
if (ckb[hashId][key] == command)
|
if (cmdGroup == command) {
|
||||||
delete ckb[hashId][key];
|
delete ckb[keyId];
|
||||||
|
} else if (Array.isArray(cmdGroup)) {
|
||||||
|
var i = cmdGroup.indexOf(command);
|
||||||
|
if (i != -1) {
|
||||||
|
cmdGroup.splice(i, 1);
|
||||||
|
if (cmdGroup.length == 1)
|
||||||
|
ckb[keyId] = cmdGroup[0];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.bindKey = function(key, command) {
|
this.bindKey = function(key, command, asDefault) {
|
||||||
if(!key)
|
if (typeof key == "object")
|
||||||
|
key = key[this.platform];
|
||||||
|
if (!key)
|
||||||
return;
|
return;
|
||||||
if (typeof command == "function") {
|
if (typeof command == "function")
|
||||||
this.addCommand({exec: command, bindKey: key, name: key});
|
return this.addCommand({exec: command, bindKey: key, name: command.name || key});
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var ckb = this.commmandKeyBinding;
|
|
||||||
key.split("|").forEach(function(keyPart) {
|
key.split("|").forEach(function(keyPart) {
|
||||||
var binding = this.parseKeys(keyPart, command);
|
var chain = "";
|
||||||
var hashId = binding.hashId;
|
if (keyPart.indexOf(" ") != -1) {
|
||||||
(ckb[hashId] || (ckb[hashId] = {}))[binding.key] = command;
|
var parts = keyPart.split(/\s+/);
|
||||||
|
keyPart = parts.pop();
|
||||||
|
parts.forEach(function(keyPart) {
|
||||||
|
var binding = this.parseKeys(keyPart);
|
||||||
|
var id = KEY_MODS[binding.hashId] + binding.key;
|
||||||
|
chain += (chain ? " " : "") + id;
|
||||||
|
this._addCommandToBinding(chain, "chainKeys");
|
||||||
|
}, this);
|
||||||
|
chain += " ";
|
||||||
|
}
|
||||||
|
var binding = this.parseKeys(keyPart);
|
||||||
|
var id = KEY_MODS[binding.hashId] + binding.key;
|
||||||
|
this._addCommandToBinding(chain + id, command, asDefault);
|
||||||
}, this);
|
}, this);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this._addCommandToBinding = function(keyId, command, asDefault) {
|
||||||
|
var ckb = this.commandKeyBinding, i;
|
||||||
|
if (!command) {
|
||||||
|
delete ckb[keyId];
|
||||||
|
} else if (!ckb[keyId] || this.$singleCommand) {
|
||||||
|
ckb[keyId] = command;
|
||||||
|
} else {
|
||||||
|
if (!Array.isArray(ckb[keyId])) {
|
||||||
|
ckb[keyId] = [ckb[keyId]];
|
||||||
|
} else if ((i = ckb[keyId].indexOf(command)) != -1) {
|
||||||
|
ckb[keyId].splice(i, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (asDefault || command.isDefault)
|
||||||
|
ckb[keyId].unshift(command);
|
||||||
|
else
|
||||||
|
ckb[keyId].push(command);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
this.addCommands = function(commands) {
|
this.addCommands = function(commands) {
|
||||||
commands && Object.keys(commands).forEach(function(name) {
|
commands && Object.keys(commands).forEach(function(name) {
|
||||||
var command = commands[name];
|
var command = commands[name];
|
||||||
|
if (!command)
|
||||||
|
return;
|
||||||
|
|
||||||
if (typeof command === "string")
|
if (typeof command === "string")
|
||||||
return this.bindKey(command, name);
|
return this.bindKey(command, name);
|
||||||
|
|
||||||
if (typeof command === "function")
|
if (typeof command === "function")
|
||||||
command = { exec: command };
|
command = { exec: command };
|
||||||
|
|
||||||
|
if (typeof command !== "object")
|
||||||
|
return;
|
||||||
|
|
||||||
if (!command.name)
|
if (!command.name)
|
||||||
command.name = name;
|
command.name = name;
|
||||||
|
|
||||||
@@ -114,16 +169,11 @@ function HashHandler(config, platform) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
this._buildKeyHash = function(command) {
|
this._buildKeyHash = function(command) {
|
||||||
var binding = command.bindKey;
|
this.bindKey(command.bindKey, command);
|
||||||
if (!binding)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var key = typeof binding == "string" ? binding: binding[this.platform];
|
|
||||||
this.bindKey(key, command);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// accepts keys in the form ctrl+Enter or ctrl-Enter
|
// accepts keys in the form ctrl+Enter or ctrl-Enter
|
||||||
// keys without modifiers or shift only
|
// keys without modifiers or shift only
|
||||||
this.parseKeys = function(keys) {
|
this.parseKeys = function(keys) {
|
||||||
var parts = keys.toLowerCase().split(/[\-\+]([\-\+])?/).filter(function(x){return x});
|
var parts = keys.toLowerCase().split(/[\-\+]([\-\+])?/).filter(function(x){return x});
|
||||||
var key = parts.pop();
|
var key = parts.pop();
|
||||||
@@ -139,25 +189,43 @@ function HashHandler(config, platform) {
|
|||||||
var hashId = 0;
|
var hashId = 0;
|
||||||
for (var i = parts.length; i--;) {
|
for (var i = parts.length; i--;) {
|
||||||
var modifier = keyUtil.KEY_MODS[parts[i]];
|
var modifier = keyUtil.KEY_MODS[parts[i]];
|
||||||
if (modifier == null)
|
if (modifier == null) {
|
||||||
throw "invalid modifier " + parts[i] + " in " + keys;
|
if (typeof console != "undefined")
|
||||||
|
console.error("invalid modifier " + parts[i] + " in " + keys);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
hashId |= modifier;
|
hashId |= modifier;
|
||||||
}
|
}
|
||||||
return {key: key, hashId: hashId};
|
return {key: key, hashId: hashId};
|
||||||
};
|
};
|
||||||
|
|
||||||
this.findKeyCommand = function findKeyCommand(hashId, keyString) {
|
this.findKeyCommand = function findKeyCommand(hashId, keyString) {
|
||||||
var ckbr = this.commmandKeyBinding;
|
var key = KEY_MODS[hashId] + keyString;
|
||||||
return ckbr[hashId] && ckbr[hashId][keyString];
|
return this.commandKeyBinding[key];
|
||||||
};
|
};
|
||||||
|
|
||||||
this.handleKeyboard = function(data, hashId, keyString, keyCode) {
|
this.handleKeyboard = function(data, hashId, keyString, keyCode) {
|
||||||
return {
|
var key = KEY_MODS[hashId] + keyString;
|
||||||
command: this.findKeyCommand(hashId, keyString)
|
var command = this.commandKeyBinding[key];
|
||||||
};
|
if (data.$keyChain) {
|
||||||
|
data.$keyChain += " " + key;
|
||||||
|
command = this.commandKeyBinding[data.$keyChain] || command;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (command) {
|
||||||
|
if (command == "chainKeys" || command[command.length - 1] == "chainKeys") {
|
||||||
|
data.$keyChain = data.$keyChain || key;
|
||||||
|
return {command: "null"};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.$keyChain && keyCode > 0)
|
||||||
|
data.$keyChain = "";
|
||||||
|
return {command: command};
|
||||||
};
|
};
|
||||||
|
|
||||||
}).call(HashHandler.prototype)
|
}).call(HashHandler.prototype);
|
||||||
|
|
||||||
exports.HashHandler = HashHandler;
|
exports.HashHandler = HashHandler;
|
||||||
|
exports.MultiHashHandler = MultiHashHandler;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ var event = require("../lib/event");
|
|||||||
|
|
||||||
var KeyBinding = function(editor) {
|
var KeyBinding = function(editor) {
|
||||||
this.$editor = editor;
|
this.$editor = editor;
|
||||||
this.$data = { };
|
this.$data = {editor: editor};
|
||||||
this.$handlers = [];
|
this.$handlers = [];
|
||||||
this.setDefaultHandler(editor.commands);
|
this.setDefaultHandler(editor.commands);
|
||||||
};
|
};
|
||||||
@@ -46,15 +46,15 @@ var KeyBinding = function(editor) {
|
|||||||
this.removeKeyboardHandler(this.$defaultHandler);
|
this.removeKeyboardHandler(this.$defaultHandler);
|
||||||
this.$defaultHandler = kb;
|
this.$defaultHandler = kb;
|
||||||
this.addKeyboardHandler(kb, 0);
|
this.addKeyboardHandler(kb, 0);
|
||||||
this.$data = {editor: this.$editor};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.setKeyboardHandler = function(kb) {
|
this.setKeyboardHandler = function(kb) {
|
||||||
if (this.$handlers[this.$handlers.length - 1] == kb)
|
var h = this.$handlers;
|
||||||
|
if (h[h.length - 1] == kb)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
while (this.$handlers[1])
|
while (h[h.length - 1] && h[h.length - 1] != this.$defaultHandler)
|
||||||
this.removeKeyboardHandler(this.$handlers[1]);
|
this.removeKeyboardHandler(h[h.length - 1]);
|
||||||
|
|
||||||
this.addKeyboardHandler(kb, 1);
|
this.addKeyboardHandler(kb, 1);
|
||||||
};
|
};
|
||||||
@@ -62,6 +62,8 @@ var KeyBinding = function(editor) {
|
|||||||
this.addKeyboardHandler = function(kb, pos) {
|
this.addKeyboardHandler = function(kb, pos) {
|
||||||
if (!kb)
|
if (!kb)
|
||||||
return;
|
return;
|
||||||
|
if (typeof kb == "function" && !kb.handleKeyboard)
|
||||||
|
kb.handleKeyboard = kb;
|
||||||
var i = this.$handlers.indexOf(kb);
|
var i = this.$handlers.indexOf(kb);
|
||||||
if (i != -1)
|
if (i != -1)
|
||||||
this.$handlers.splice(i, 1);
|
this.$handlers.splice(i, 1);
|
||||||
@@ -87,33 +89,42 @@ var KeyBinding = function(editor) {
|
|||||||
this.getKeyboardHandler = function() {
|
this.getKeyboardHandler = function() {
|
||||||
return this.$handlers[this.$handlers.length - 1];
|
return this.$handlers[this.$handlers.length - 1];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.getStatusText = function() {
|
||||||
|
var data = this.$data;
|
||||||
|
var editor = data.editor;
|
||||||
|
return this.$handlers.map(function(h) {
|
||||||
|
return h.getStatusText && h.getStatusText(editor, data) || "";
|
||||||
|
}).filter(Boolean).join(" ");
|
||||||
|
};
|
||||||
|
|
||||||
this.$callKeyboardHandlers = function (hashId, keyString, keyCode, e) {
|
this.$callKeyboardHandlers = function(hashId, keyString, keyCode, e) {
|
||||||
var toExecute;
|
var toExecute;
|
||||||
|
var success = false;
|
||||||
|
var commands = this.$editor.commands;
|
||||||
|
|
||||||
for (var i = this.$handlers.length; i--;) {
|
for (var i = this.$handlers.length; i--;) {
|
||||||
toExecute = this.$handlers[i].handleKeyboard(
|
toExecute = this.$handlers[i].handleKeyboard(
|
||||||
this.$data, hashId, keyString, keyCode, e
|
this.$data, hashId, keyString, keyCode, e
|
||||||
);
|
);
|
||||||
if (toExecute && toExecute.command)
|
if (!toExecute || !toExecute.command)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// allow keyboardHandler to consume keys
|
||||||
|
if (toExecute.command == "null") {
|
||||||
|
success = true;
|
||||||
|
} else {
|
||||||
|
success = commands.exec(toExecute.command, this.$editor, toExecute.args, e);
|
||||||
|
}
|
||||||
|
// do not stop input events to not break repeating
|
||||||
|
if (success && e && hashId != -1 &&
|
||||||
|
toExecute.passEvent != true && toExecute.command.passEvent != true
|
||||||
|
) {
|
||||||
|
event.stopEvent(e);
|
||||||
|
}
|
||||||
|
if (success)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!toExecute || !toExecute.command)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
var success = false;
|
|
||||||
var commands = this.$editor.commands;
|
|
||||||
|
|
||||||
// allow keyboardHandler to consume keys
|
|
||||||
if (toExecute.command != "null")
|
|
||||||
success = commands.exec(toExecute.command, this.$editor, toExecute.args, e);
|
|
||||||
else
|
|
||||||
success = toExecute.passEvent != true;
|
|
||||||
|
|
||||||
// do not stop input events to not break repeating
|
|
||||||
if (success && e && hashId != -1)
|
|
||||||
event.stopEvent(e);
|
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,69 @@
|
|||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Distributed under the BSD license:
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010, Ajax.org B.V.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of Ajax.org B.V. nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
if (typeof process !== "undefined") {
|
||||||
|
require("amd-loader");
|
||||||
|
}
|
||||||
|
|
||||||
|
define(function(require, exports, module) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var EditSession = require("./../edit_session").EditSession,
|
||||||
|
Editor = require("./../editor").Editor,
|
||||||
|
MockRenderer = require("./../test/mockrenderer").MockRenderer,
|
||||||
|
assert = require("./../test/assertions"),
|
||||||
|
HashHandler = require('./hash_handler').HashHandler,
|
||||||
|
keys = require('../lib/keys'),
|
||||||
|
editor;
|
||||||
|
|
||||||
|
function initEditor(docString) {
|
||||||
|
var doc = new EditSession(docString.split("\n"));
|
||||||
|
editor = new Editor(new MockRenderer(), doc);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
|
||||||
|
"test: adding a new keyboard handler does not remove the default handler": function() {
|
||||||
|
initEditor('abc');
|
||||||
|
var handler = new HashHandler({'del': 'f1'});
|
||||||
|
editor.keyBinding.setKeyboardHandler(handler);
|
||||||
|
editor.onCommandKey({}, 0, keys['f1']);
|
||||||
|
assert.equal('bc', editor.getValue(), "binding of new handler");
|
||||||
|
editor.onCommandKey({}, 0, keys['delete']);
|
||||||
|
assert.equal('c', editor.getValue(), "bindings of the old handler should still work");
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
if (typeof module !== "undefined" && module === require.main) {
|
||||||
|
require("asyncjs").test.testcase(module.exports).exec()
|
||||||
|
}
|
||||||
@@ -223,8 +223,7 @@ StateHandler.prototype = {
|
|||||||
* This is a useful matching function and therefore is defined here so that
|
* This is a useful matching function and therefore is defined here so that
|
||||||
* users of KeyboardStateMapper can use it.
|
* users of KeyboardStateMapper can use it.
|
||||||
*
|
*
|
||||||
* @return boolean
|
* @return {Boolean} If no command key (Command|Option|Shift|Ctrl) is pressed, it
|
||||||
* If no command key (Command|Option|Shift|Ctrl) is pressed, it
|
|
||||||
* returns true. If the only the Shift key is pressed + a character
|
* returns true. If the only the Shift key is pressed + a character
|
||||||
* true is returned as well. Otherwise, false is returned.
|
* true is returned as well. Otherwise, false is returned.
|
||||||
* Summing up, the function returns true whenever the user typed
|
* Summing up, the function returns true whenever the user typed
|
||||||
|
|||||||
@@ -0,0 +1,82 @@
|
|||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Distributed under the BSD license:
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010, Ajax.org B.V.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of Ajax.org B.V. nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
define(function(require, exports, module) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var HashHandler = require("./hash_handler").HashHandler;
|
||||||
|
exports.handler = new HashHandler();
|
||||||
|
|
||||||
|
[{
|
||||||
|
bindKey: "Shift-Tab|Tab",
|
||||||
|
command: "passKeysToBrowser"
|
||||||
|
}, {
|
||||||
|
bindKey: {win: "Ctrl-L", mac: "Cmd-L"},
|
||||||
|
command: "passKeysToBrowser"
|
||||||
|
}, {
|
||||||
|
bindKey: {win: "Ctrl-G", mac: "Cmd-G"},
|
||||||
|
command: "gotoline"
|
||||||
|
}, {
|
||||||
|
bindKey: {win: "Ctrl-T|Ctrl-Shift-T", mac: "Cmd-T|Cmd-Shift-T"},
|
||||||
|
command: "passKeysToBrowser"
|
||||||
|
}, {
|
||||||
|
bindKey: {win: "Ctrl-G", mac: "Cmd-G"},
|
||||||
|
command: "passKeysToBrowser"
|
||||||
|
}, {
|
||||||
|
bindKey: {win: "Ctrl-G", mac: "Cmd-G"},
|
||||||
|
command: "passKeysToBrowser"
|
||||||
|
}, {
|
||||||
|
name: "golineup",
|
||||||
|
bindKey: {win: null, mac: "Ctrl-P"},
|
||||||
|
}, {
|
||||||
|
name: "golinedown",
|
||||||
|
bindKey: {win: null, mac: "Ctrl-N"},
|
||||||
|
}, {
|
||||||
|
name: "gotoleft",
|
||||||
|
bindKey: {win: null, mac: "Ctrl-B"},
|
||||||
|
}, {
|
||||||
|
name: "gotoright",
|
||||||
|
bindKey: {win: null, mac: "Ctrl-F"},
|
||||||
|
}, {
|
||||||
|
name: "gotolineend",
|
||||||
|
bindKey: {win: null, mac: "Ctrl-E"},
|
||||||
|
}, {
|
||||||
|
name: "gotolinestart",
|
||||||
|
bindKey: {win: null, mac: "Ctrl-A"},
|
||||||
|
}
|
||||||
|
].forEach(function(k) {
|
||||||
|
var bindKey = k.bindKey;
|
||||||
|
if (typeof bindKey == "object")
|
||||||
|
bindKey = bindKey[exports.handler.platform];
|
||||||
|
exports.handler.bindKey(bindKey, k.command);
|
||||||
|
});
|
||||||
|
exports.handler.$id = "ace/keyboard/textarea";
|
||||||
|
|
||||||
|
});
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 2010, Ajax.org B.V.
|
* Copyright (c) 2010, Ajax.org B.V.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
* * Redistributions of source code must retain the above copyright
|
* * Redistributions of source code must retain the above copyright
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
* * Neither the name of Ajax.org B.V. nor the
|
* * Neither the name of Ajax.org B.V. nor the
|
||||||
* names of its contributors may be used to endorse or promote products
|
* names of its contributors may be used to endorse or promote products
|
||||||
* derived from this software without specific prior written permission.
|
* derived from this software without specific prior written permission.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
@@ -34,189 +34,253 @@ define(function(require, exports, module) {
|
|||||||
var event = require("../lib/event");
|
var event = require("../lib/event");
|
||||||
var useragent = require("../lib/useragent");
|
var useragent = require("../lib/useragent");
|
||||||
var dom = require("../lib/dom");
|
var dom = require("../lib/dom");
|
||||||
|
var lang = require("../lib/lang");
|
||||||
|
var BROKEN_SETDATA = useragent.isChrome < 18;
|
||||||
|
var USE_IE_MIME_TYPE = useragent.isIE;
|
||||||
|
|
||||||
var TextInput = function(parentNode, host) {
|
var TextInput = function(parentNode, host) {
|
||||||
var text = dom.createElement("textarea");
|
var text = dom.createElement("textarea");
|
||||||
text.className = "ace_text-input";
|
text.className = "ace_text-input";
|
||||||
/*/ debug
|
|
||||||
text.style.opacity = 1
|
|
||||||
text.style.background = "rgba(0, 250, 0, 0.3)"
|
|
||||||
text.style.outline = "rgba(0, 250, 0, 0.8) solid 1px"
|
|
||||||
text.style.outlineOffset = "3px"
|
|
||||||
/**/
|
|
||||||
if (useragent.isTouchPad)
|
if (useragent.isTouchPad)
|
||||||
text.setAttribute("x-palm-disable-auto-cap", true);
|
text.setAttribute("x-palm-disable-auto-cap", true);
|
||||||
|
|
||||||
text.wrap = "off";
|
text.setAttribute("wrap", "off");
|
||||||
text.spellcheck = false;
|
text.setAttribute("autocorrect", "off");
|
||||||
|
text.setAttribute("autocapitalize", "off");
|
||||||
|
text.setAttribute("spellcheck", false);
|
||||||
|
|
||||||
text.style.top = "-2em";
|
text.style.opacity = "0";
|
||||||
|
if (useragent.isOldIE) text.style.top = "-100px";
|
||||||
parentNode.insertBefore(text, parentNode.firstChild);
|
parentNode.insertBefore(text, parentNode.firstChild);
|
||||||
|
|
||||||
var PLACEHOLDER = useragent.isIE || useragent.isOpera ? "\x01\x01" : "\x00\x00";
|
var PLACEHOLDER = "\x01\x01";
|
||||||
|
|
||||||
resetValue();
|
|
||||||
|
|
||||||
if (isFocused())
|
|
||||||
host.onFocus();
|
|
||||||
|
|
||||||
// Somehow fixes problem with firing onpropertychange on first typed char
|
|
||||||
if (useragent.isOldIE) {
|
|
||||||
resetSelection();
|
|
||||||
resetValue();
|
|
||||||
setTimeout(resetSelection);
|
|
||||||
}
|
|
||||||
|
|
||||||
var cut = false
|
|
||||||
var copied = false;
|
var copied = false;
|
||||||
var pasted = false;
|
var pasted = false;
|
||||||
|
var inComposition = false;
|
||||||
var inCompostion = false;
|
|
||||||
|
|
||||||
var resetTimeout = null;
|
|
||||||
|
|
||||||
var tempStyle = '';
|
var tempStyle = '';
|
||||||
|
var isSelectionEmpty = true;
|
||||||
|
|
||||||
function resetValue() {
|
// FOCUS
|
||||||
text.value = PLACEHOLDER;
|
// ie9 throws error if document.activeElement is accessed too soon
|
||||||
//http://code.google.com/p/chromium/issues/detail?id=76516
|
try { var isFocused = document.activeElement === text; } catch(e) {}
|
||||||
if (useragent.isWebKit && !resetTimeout)
|
|
||||||
resetTimeout = setTimeout(function(){
|
event.addListener(text, "blur", function(e) {
|
||||||
text.value = PLACEHOLDER;
|
host.onBlur(e);
|
||||||
resetSelection();
|
isFocused = false;
|
||||||
resetTimeout = null;
|
});
|
||||||
});
|
event.addListener(text, "focus", function(e) {
|
||||||
|
isFocused = true;
|
||||||
|
host.onFocus(e);
|
||||||
|
resetSelection();
|
||||||
|
});
|
||||||
|
this.focus = function() {
|
||||||
|
text.style.position = "fixed";
|
||||||
|
text.style.top = "-10000000px";
|
||||||
|
text.focus();
|
||||||
|
setTimeout(function() {
|
||||||
|
text.style.position = "";
|
||||||
|
}, 0);
|
||||||
};
|
};
|
||||||
|
this.blur = function() { text.blur(); };
|
||||||
|
this.isFocused = function() {
|
||||||
|
return isFocused;
|
||||||
|
};
|
||||||
|
|
||||||
|
// modifying selection of blured textarea can focus it (chrome mac/linux)
|
||||||
|
var syncSelection = lang.delayedCall(function() {
|
||||||
|
isFocused && resetSelection(isSelectionEmpty);
|
||||||
|
});
|
||||||
|
var syncValue = lang.delayedCall(function() {
|
||||||
|
if (!inComposition) {
|
||||||
|
text.value = PLACEHOLDER;
|
||||||
|
isFocused && resetSelection();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
function resetSelection(isEmpty) {
|
function resetSelection(isEmpty) {
|
||||||
var selectionStart = isEmpty ? 2 : 1;
|
if (inComposition)
|
||||||
var selectionEnd = 2;
|
return;
|
||||||
|
|
||||||
|
// this prevents infinite recursion on safari 8
|
||||||
|
// see https://github.com/ajaxorg/ace/issues/2114
|
||||||
|
inComposition = true;
|
||||||
|
|
||||||
|
if (inputHandler) {
|
||||||
|
selectionStart = 0;
|
||||||
|
selectionEnd = isEmpty ? 0 : text.value.length - 1;
|
||||||
|
} else {
|
||||||
|
var selectionStart = isEmpty ? 2 : 1;
|
||||||
|
var selectionEnd = 2;
|
||||||
|
}
|
||||||
// on firefox this throws if textarea is hidden
|
// on firefox this throws if textarea is hidden
|
||||||
try {
|
try {
|
||||||
if (text.setSelectionRange) {
|
text.setSelectionRange(selectionStart, selectionEnd);
|
||||||
text.setSelectionRange(selectionStart, selectionEnd);
|
|
||||||
}
|
|
||||||
// IE8 does not support setSelectionRange
|
|
||||||
else if (text.createTextRange) {
|
|
||||||
var range = text.createTextRange();
|
|
||||||
range.collapse(true);
|
|
||||||
range.moveEnd('character', selectionEnd);
|
|
||||||
range.moveStart('character', selectionStart);
|
|
||||||
range.select();
|
|
||||||
}
|
|
||||||
} catch(e){}
|
} catch(e){}
|
||||||
|
|
||||||
|
inComposition = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetValue() {
|
||||||
|
if (inComposition)
|
||||||
|
return;
|
||||||
|
text.value = PLACEHOLDER;
|
||||||
|
//http://code.google.com/p/chromium/issues/detail?id=76516
|
||||||
|
if (useragent.isWebKit)
|
||||||
|
syncValue.schedule();
|
||||||
|
}
|
||||||
|
|
||||||
|
useragent.isWebKit || host.addEventListener('changeSelection', function() {
|
||||||
|
if (host.selection.isEmpty() != isSelectionEmpty) {
|
||||||
|
isSelectionEmpty = !isSelectionEmpty;
|
||||||
|
syncSelection.schedule();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
resetValue();
|
||||||
|
if (isFocused)
|
||||||
|
host.onFocus();
|
||||||
|
|
||||||
|
|
||||||
|
var isAllSelected = function(text) {
|
||||||
|
return text.selectionStart === 0 && text.selectionEnd === text.value.length;
|
||||||
};
|
};
|
||||||
|
// IE8 does not support setSelectionRange
|
||||||
|
if (!text.setSelectionRange && text.createTextRange) {
|
||||||
|
text.setSelectionRange = function(selectionStart, selectionEnd) {
|
||||||
|
var range = this.createTextRange();
|
||||||
|
range.collapse(true);
|
||||||
|
range.moveStart('character', selectionStart);
|
||||||
|
range.moveEnd('character', selectionEnd);
|
||||||
|
range.select();
|
||||||
|
};
|
||||||
|
isAllSelected = function(text) {
|
||||||
|
try {
|
||||||
|
var range = text.ownerDocument.selection.createRange();
|
||||||
|
}catch(e) {}
|
||||||
|
if (!range || range.parentElement() != text) return false;
|
||||||
|
return range.text == text.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (useragent.isOldIE) {
|
||||||
|
var inPropertyChange = false;
|
||||||
|
var onPropertyChange = function(e){
|
||||||
|
if (inPropertyChange)
|
||||||
|
return;
|
||||||
|
var data = text.value;
|
||||||
|
if (inComposition || !data || data == PLACEHOLDER)
|
||||||
|
return;
|
||||||
|
// can happen either after delete or during insert operation
|
||||||
|
if (e && data == PLACEHOLDER[0])
|
||||||
|
return syncProperty.schedule();
|
||||||
|
|
||||||
|
sendText(data);
|
||||||
|
// ie8 calls propertychange handlers synchronously!
|
||||||
|
inPropertyChange = true;
|
||||||
|
resetValue();
|
||||||
|
inPropertyChange = false;
|
||||||
|
};
|
||||||
|
var syncProperty = lang.delayedCall(onPropertyChange);
|
||||||
|
event.addListener(text, "propertychange", onPropertyChange);
|
||||||
|
|
||||||
|
var keytable = { 13:1, 27:1 };
|
||||||
|
event.addListener(text, "keyup", function (e) {
|
||||||
|
if (inComposition && (!text.value || keytable[e.keyCode]))
|
||||||
|
setTimeout(onCompositionEnd, 0);
|
||||||
|
if ((text.value.charCodeAt(0)||0) < 129) {
|
||||||
|
return syncProperty.call();
|
||||||
|
}
|
||||||
|
inComposition ? onCompositionUpdate() : onCompositionStart();
|
||||||
|
});
|
||||||
|
// when user presses backspace after focusing the editor
|
||||||
|
// propertychange isn't called for the next character
|
||||||
|
event.addListener(text, "keydown", function (e) {
|
||||||
|
syncProperty.schedule(50);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
var onSelect = function(e) {
|
var onSelect = function(e) {
|
||||||
if (cut) {
|
|
||||||
cut = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (copied) {
|
if (copied) {
|
||||||
copied = false;
|
copied = false;
|
||||||
return;
|
} else if (isAllSelected(text)) {
|
||||||
}
|
|
||||||
if (text.selectionStart === 0 && text.selectionEnd === text.value.length) {
|
|
||||||
host.selectAll();
|
host.selectAll();
|
||||||
resetSelection();
|
resetSelection();
|
||||||
|
} else if (inputHandler) {
|
||||||
|
resetSelection(host.selection.isEmpty());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var onInput = function(e) {
|
var inputHandler = null;
|
||||||
if (inCompostion)
|
this.setInputHandler = function(cb) {inputHandler = cb};
|
||||||
return;
|
this.getInputHandler = function() {return inputHandler};
|
||||||
|
var afterContextMenu = false;
|
||||||
|
|
||||||
|
var sendText = function(data) {
|
||||||
|
if (inputHandler) {
|
||||||
|
data = inputHandler(data);
|
||||||
|
inputHandler = null;
|
||||||
|
}
|
||||||
if (pasted) {
|
if (pasted) {
|
||||||
var data = text.value;
|
resetSelection();
|
||||||
resetValue();
|
|
||||||
if (data)
|
if (data)
|
||||||
host.onPaste(data);
|
host.onPaste(data);
|
||||||
pasted = false;
|
pasted = false;
|
||||||
return;
|
} else if (data == PLACEHOLDER.charAt(0)) {
|
||||||
}
|
if (afterContextMenu)
|
||||||
|
host.execCommand("del", {source: "ace"});
|
||||||
var data = text.value;
|
else // some versions of android do not fire keydown when pressing backspace
|
||||||
if (data.substring(0, 2) == PLACEHOLDER)
|
host.execCommand("backspace", {source: "ace"});
|
||||||
data = data.substr(2);
|
} else {
|
||||||
else
|
if (data.substring(0, 2) == PLACEHOLDER)
|
||||||
data = data.substr(1);
|
data = data.substr(2);
|
||||||
|
else if (data.charAt(0) == PLACEHOLDER.charAt(0))
|
||||||
resetValue();
|
data = data.substr(1);
|
||||||
if (data) {
|
else if (data.charAt(data.length - 1) == PLACEHOLDER.charAt(0))
|
||||||
// can happen if undo in textarea isn't stopped
|
|
||||||
if (data[data.length - 1] == PLACEHOLDER[0])
|
|
||||||
data = data.slice(0, -1);
|
data = data.slice(0, -1);
|
||||||
if (data)
|
// can happen if undo in textarea isn't stopped
|
||||||
host.onTextInput(data);
|
if (data.charAt(data.length - 1) == PLACEHOLDER.charAt(0))
|
||||||
} else
|
data = data.slice(0, -1);
|
||||||
host.onDelete();
|
|
||||||
|
if (data)
|
||||||
|
host.onTextInput(data);
|
||||||
|
}
|
||||||
|
if (afterContextMenu)
|
||||||
|
afterContextMenu = false;
|
||||||
};
|
};
|
||||||
|
var onInput = function(e) {
|
||||||
var onCompositionStart = function(e) {
|
// console.log("onInput", inComposition)
|
||||||
inCompostion = true;
|
if (inComposition)
|
||||||
host.onCompositionStart();
|
|
||||||
setTimeout(onCompositionUpdate, 0);
|
|
||||||
};
|
|
||||||
|
|
||||||
var onCompositionUpdate = function() {
|
|
||||||
if (!inCompostion) return;
|
|
||||||
host.onCompositionUpdate(text.value);
|
|
||||||
};
|
|
||||||
|
|
||||||
var onCompositionEnd = function(e) {
|
|
||||||
inCompostion = false;
|
|
||||||
host.onCompositionEnd();
|
|
||||||
};
|
|
||||||
|
|
||||||
var onCut = function(e) {
|
|
||||||
var data = host.getCopyText();
|
|
||||||
if (!data) {
|
|
||||||
event.preventDefault(e);
|
|
||||||
return;
|
return;
|
||||||
}
|
var data = text.value;
|
||||||
|
sendText(data);
|
||||||
|
resetValue();
|
||||||
|
};
|
||||||
|
|
||||||
|
var handleClipboardData = function(e, data) {
|
||||||
var clipboardData = e.clipboardData || window.clipboardData;
|
var clipboardData = e.clipboardData || window.clipboardData;
|
||||||
|
if (!clipboardData || BROKEN_SETDATA)
|
||||||
if (clipboardData) {
|
return;
|
||||||
|
// using "Text" doesn't work on old webkit but ie needs it
|
||||||
|
// TODO are there other browsers that require "Text"?
|
||||||
|
var mime = USE_IE_MIME_TYPE ? "Text" : "text/plain";
|
||||||
|
if (data) {
|
||||||
// Safari 5 has clipboardData object, but does not handle setData()
|
// Safari 5 has clipboardData object, but does not handle setData()
|
||||||
var supported = clipboardData.setData("Text", data);
|
return clipboardData.setData(mime, data) !== false;
|
||||||
if (supported) {
|
} else {
|
||||||
host.onCut();
|
return clipboardData.getData(mime);
|
||||||
event.preventDefault(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!supported) {
|
|
||||||
cut = true;
|
|
||||||
text.value = data;
|
|
||||||
text.select();
|
|
||||||
setTimeout(function(){
|
|
||||||
cut = false;
|
|
||||||
resetValue();
|
|
||||||
resetSelection();
|
|
||||||
host.onCut();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var onCopy = function(e) {
|
var doCopy = function(e, isCut) {
|
||||||
var data = host.getCopyText();
|
var data = host.getCopyText();
|
||||||
if (!data) {
|
if (!data)
|
||||||
|
return event.preventDefault(e);
|
||||||
|
|
||||||
|
if (handleClipboardData(e, data)) {
|
||||||
|
isCut ? host.onCut() : host.onCopy();
|
||||||
event.preventDefault(e);
|
event.preventDefault(e);
|
||||||
return;
|
} else {
|
||||||
}
|
|
||||||
|
|
||||||
var clipboardData = e.clipboardData || window.clipboardData;
|
|
||||||
|
|
||||||
if (clipboardData) {
|
|
||||||
// Safari 5 has clipboardData object, but does not handle setData()
|
|
||||||
var supported = clipboardData.setData("Text", data);
|
|
||||||
if (supported) {
|
|
||||||
host.onCopy();
|
|
||||||
event.preventDefault(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!supported) {
|
|
||||||
copied = true;
|
copied = true;
|
||||||
text.value = data;
|
text.value = data;
|
||||||
text.select();
|
text.select();
|
||||||
@@ -224,20 +288,26 @@ var TextInput = function(parentNode, host) {
|
|||||||
copied = false;
|
copied = false;
|
||||||
resetValue();
|
resetValue();
|
||||||
resetSelection();
|
resetSelection();
|
||||||
host.onCopy();
|
isCut ? host.onCut() : host.onCopy();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var onCut = function(e) {
|
||||||
|
doCopy(e, true);
|
||||||
|
};
|
||||||
|
|
||||||
|
var onCopy = function(e) {
|
||||||
|
doCopy(e, false);
|
||||||
|
};
|
||||||
|
|
||||||
var onPaste = function(e) {
|
var onPaste = function(e) {
|
||||||
var clipboardData = e.clipboardData || window.clipboardData;
|
var data = handleClipboardData(e);
|
||||||
|
if (typeof data == "string") {
|
||||||
if (clipboardData) {
|
|
||||||
var data = clipboardData.getData("Text");
|
|
||||||
if (data)
|
if (data)
|
||||||
host.onPaste(data);
|
host.onPaste(data);
|
||||||
|
if (useragent.isIE)
|
||||||
|
setTimeout(resetSelection);
|
||||||
event.preventDefault(e);
|
event.preventDefault(e);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -261,7 +331,7 @@ var TextInput = function(parentNode, host) {
|
|||||||
if (!('oncut' in text) || !('oncopy' in text) || !('onpaste' in text)){
|
if (!('oncut' in text) || !('oncopy' in text) || !('onpaste' in text)){
|
||||||
event.addListener(parentNode, "keydown", function(e) {
|
event.addListener(parentNode, "keydown", function(e) {
|
||||||
if ((useragent.isMac && !e.metaKey) || !e.ctrlKey)
|
if ((useragent.isMac && !e.metaKey) || !e.ctrlKey)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
switch (e.keyCode) {
|
switch (e.keyCode) {
|
||||||
case 67:
|
case 67:
|
||||||
@@ -277,68 +347,128 @@ var TextInput = function(parentNode, host) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (useragent.isOldIE) {
|
|
||||||
event.addListener(text, "propertychange", function(e){
|
|
||||||
if (text.value != "" && text.value != PLACEHOLDER)
|
|
||||||
onInput(e);
|
|
||||||
});
|
|
||||||
|
|
||||||
var keytable = { 13:1, 27:1 };
|
// COMPOSITION
|
||||||
event.addListener(text, "keyup", function (e) {
|
var onCompositionStart = function(e) {
|
||||||
if (inCompostion && (!text.value || keytable[e.keyCode]))
|
if (inComposition || !host.onCompositionStart || host.$readOnly)
|
||||||
setTimeout(onCompositionEnd, 0);
|
return;
|
||||||
if ((text.value.charCodeAt(0)|0) < 129) {
|
// console.log("onCompositionStart", inComposition)
|
||||||
|
inComposition = {};
|
||||||
|
host.onCompositionStart();
|
||||||
|
setTimeout(onCompositionUpdate, 0);
|
||||||
|
host.on("mousedown", onCompositionEnd);
|
||||||
|
if (!host.selection.isEmpty()) {
|
||||||
|
host.insert("");
|
||||||
|
host.session.markUndoGroup();
|
||||||
|
host.selection.clearSelection();
|
||||||
|
}
|
||||||
|
host.session.markUndoGroup();
|
||||||
|
};
|
||||||
|
|
||||||
|
var onCompositionUpdate = function() {
|
||||||
|
// console.log("onCompositionUpdate", inComposition && JSON.stringify(text.value))
|
||||||
|
if (!inComposition || !host.onCompositionUpdate || host.$readOnly)
|
||||||
|
return;
|
||||||
|
var val = text.value.replace(/\x01/g, "");
|
||||||
|
if (inComposition.lastValue === val) return;
|
||||||
|
|
||||||
|
host.onCompositionUpdate(val);
|
||||||
|
if (inComposition.lastValue)
|
||||||
|
host.undo();
|
||||||
|
inComposition.lastValue = val;
|
||||||
|
if (inComposition.lastValue) {
|
||||||
|
var r = host.selection.getRange();
|
||||||
|
host.insert(inComposition.lastValue);
|
||||||
|
host.session.markUndoGroup();
|
||||||
|
inComposition.range = host.selection.getRange();
|
||||||
|
host.selection.setRange(r);
|
||||||
|
host.selection.clearSelection();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var onCompositionEnd = function(e) {
|
||||||
|
if (!host.onCompositionEnd || host.$readOnly) return;
|
||||||
|
// console.log("onCompositionEnd", inComposition &&inComposition.lastValue)
|
||||||
|
var c = inComposition;
|
||||||
|
inComposition = false;
|
||||||
|
var timer = setTimeout(function() {
|
||||||
|
timer = null;
|
||||||
|
var str = text.value.replace(/\x01/g, "");
|
||||||
|
// console.log(str, c.lastValue)
|
||||||
|
if (inComposition)
|
||||||
return;
|
return;
|
||||||
|
else if (str == c.lastValue)
|
||||||
|
resetValue();
|
||||||
|
else if (!c.lastValue && str) {
|
||||||
|
resetValue();
|
||||||
|
sendText(str);
|
||||||
}
|
}
|
||||||
inCompostion ? onCompositionUpdate() : onCompositionStart();
|
|
||||||
});
|
});
|
||||||
}
|
inputHandler = function compositionInputHandler(str) {
|
||||||
|
// console.log("onCompositionEnd", str, c.lastValue)
|
||||||
|
if (timer)
|
||||||
|
clearTimeout(timer);
|
||||||
|
str = str.replace(/\x01/g, "");
|
||||||
|
if (str == c.lastValue)
|
||||||
|
return "";
|
||||||
|
if (c.lastValue && timer)
|
||||||
|
host.undo();
|
||||||
|
return str;
|
||||||
|
};
|
||||||
|
host.onCompositionEnd();
|
||||||
|
host.removeListener("mousedown", onCompositionEnd);
|
||||||
|
if (e.type == "compositionend" && c.range) {
|
||||||
|
host.selection.setRange(c.range);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var syncComposition = lang.delayedCall(onCompositionUpdate, 50);
|
||||||
|
|
||||||
event.addListener(text, "compositionstart", onCompositionStart);
|
event.addListener(text, "compositionstart", onCompositionStart);
|
||||||
if (useragent.isGecko) {
|
if (useragent.isGecko) {
|
||||||
event.addListener(text, "text", onCompositionUpdate);
|
event.addListener(text, "text", function(){syncComposition.schedule()});
|
||||||
}
|
} else {
|
||||||
if (useragent.isWebKit) {
|
event.addListener(text, "keyup", function(){syncComposition.schedule()});
|
||||||
event.addListener(text, "keyup", onCompositionUpdate);
|
event.addListener(text, "keydown", function(){syncComposition.schedule()});
|
||||||
}
|
}
|
||||||
event.addListener(text, "compositionend", onCompositionEnd);
|
event.addListener(text, "compositionend", onCompositionEnd);
|
||||||
|
|
||||||
event.addListener(text, "blur", function() {
|
|
||||||
host.onBlur();
|
|
||||||
});
|
|
||||||
|
|
||||||
event.addListener(text, "focus", function() {
|
|
||||||
host.onFocus();
|
|
||||||
resetSelection();
|
|
||||||
});
|
|
||||||
|
|
||||||
this.focus = function() {
|
|
||||||
text.focus();
|
|
||||||
};
|
|
||||||
|
|
||||||
this.blur = function() {
|
|
||||||
text.blur();
|
|
||||||
};
|
|
||||||
|
|
||||||
function isFocused() {
|
|
||||||
return document.activeElement === text;
|
|
||||||
}
|
|
||||||
this.isFocused = isFocused;
|
|
||||||
|
|
||||||
this.getElement = function() {
|
this.getElement = function() {
|
||||||
return text;
|
return text;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.setReadOnly = function(readOnly) {
|
||||||
|
text.readOnly = readOnly;
|
||||||
|
};
|
||||||
|
|
||||||
this.onContextMenu = function(e) {
|
this.onContextMenu = function(e) {
|
||||||
|
afterContextMenu = true;
|
||||||
|
resetSelection(host.selection.isEmpty());
|
||||||
|
host._emit("nativecontextmenu", {target: host, domEvent: e});
|
||||||
|
this.moveToMouse(e, true);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.moveToMouse = function(e, bringToFront) {
|
||||||
|
if (!bringToFront && useragent.isOldIE)
|
||||||
|
return;
|
||||||
if (!tempStyle)
|
if (!tempStyle)
|
||||||
tempStyle = text.style.cssText;
|
tempStyle = text.style.cssText;
|
||||||
|
text.style.cssText = (bringToFront ? "z-index:100000;" : "")
|
||||||
|
+ "height:" + text.style.height + ";"
|
||||||
|
+ (useragent.isIE ? "opacity:0.1;" : "");
|
||||||
|
|
||||||
text.style.cssText =
|
var rect = host.container.getBoundingClientRect();
|
||||||
"position:fixed; z-index:100000;" +
|
var style = dom.computedStyle(host.container);
|
||||||
(useragent.isIE ? "background:rgba(0, 0, 0, 0.03); opacity:0.1;" : "") + //"background:rgba(250, 0, 0, 0.3); opacity:1;" +
|
var top = rect.top + (parseInt(style.borderTopWidth) || 0);
|
||||||
"left:" + (e.clientX - 2) + "px; top:" + (e.clientY - 2) + "px;";
|
var left = rect.left + (parseInt(rect.borderLeftWidth) || 0);
|
||||||
|
var maxTop = rect.bottom - top - text.clientHeight -2;
|
||||||
resetSelection(host.selection.isEmpty());
|
var move = function(e) {
|
||||||
|
text.style.left = e.clientX - left - 2 + "px";
|
||||||
|
text.style.top = Math.min(e.clientY - top - 2, maxTop) + "px";
|
||||||
|
};
|
||||||
|
move(e);
|
||||||
|
|
||||||
if (e.type != "mousedown")
|
if (e.type != "mousedown")
|
||||||
return;
|
return;
|
||||||
@@ -347,15 +477,15 @@ var TextInput = function(parentNode, host) {
|
|||||||
host.renderer.$keepTextAreaAtCursor = null;
|
host.renderer.$keepTextAreaAtCursor = null;
|
||||||
|
|
||||||
// on windows context menu is opened after mouseup
|
// on windows context menu is opened after mouseup
|
||||||
if (useragent.isWin)
|
if (useragent.isWin && !useragent.isOldIE)
|
||||||
event.capture(host.container, function(e) {
|
event.capture(host.container, move, onContextMenuClose);
|
||||||
text.style.left = e.clientX - 2 + "px";
|
|
||||||
text.style.top = e.clientY - 2 + "px";
|
|
||||||
}, onContextMenuClose);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.onContextMenuClose = onContextMenuClose;
|
||||||
|
var closeTimeout;
|
||||||
function onContextMenuClose() {
|
function onContextMenuClose() {
|
||||||
setTimeout(function () {
|
clearTimeout(closeTimeout)
|
||||||
|
closeTimeout = setTimeout(function () {
|
||||||
if (tempStyle) {
|
if (tempStyle) {
|
||||||
text.style.cssText = tempStyle;
|
text.style.cssText = tempStyle;
|
||||||
tempStyle = '';
|
tempStyle = '';
|
||||||
@@ -364,16 +494,15 @@ var TextInput = function(parentNode, host) {
|
|||||||
host.renderer.$keepTextAreaAtCursor = true;
|
host.renderer.$keepTextAreaAtCursor = true;
|
||||||
host.renderer.$moveTextAreaToCursor();
|
host.renderer.$moveTextAreaToCursor();
|
||||||
}
|
}
|
||||||
}, 0);
|
}, useragent.isOldIE ? 200 : 0);
|
||||||
};
|
}
|
||||||
this.onContextMenuClose = onContextMenuClose;
|
|
||||||
|
|
||||||
// firefox fires contextmenu event after opening it
|
var onContextMenu = function(e) {
|
||||||
if (!useragent.isGecko)
|
host.textInput.onContextMenu(e);
|
||||||
event.addListener(text, "contextmenu", function(e) {
|
onContextMenuClose();
|
||||||
host.textInput.onContextMenu(e);
|
};
|
||||||
onContextMenuClose();
|
event.addListener(host.renderer.scroller, "contextmenu", onContextMenu);
|
||||||
});
|
event.addListener(text, "contextmenu", onContextMenu);
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.TextInput = TextInput;
|
exports.TextInput = TextInput;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,561 +0,0 @@
|
|||||||
/* ***** BEGIN LICENSE BLOCK *****
|
|
||||||
* Distributed under the BSD license:
|
|
||||||
*
|
|
||||||
* Copyright (c) 2010, Ajax.org B.V.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
* * Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* * Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* * Neither the name of Ajax.org B.V. nor the
|
|
||||||
* names of its contributors may be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
|
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* ***** END LICENSE BLOCK ***** */
|
|
||||||
|
|
||||||
define(function(require, exports, module) {
|
|
||||||
|
|
||||||
"never use strict";
|
|
||||||
|
|
||||||
var util = require("./maps/util");
|
|
||||||
var motions = require("./maps/motions");
|
|
||||||
var operators = require("./maps/operators");
|
|
||||||
var alias = require("./maps/aliases");
|
|
||||||
var registers = require("./registers");
|
|
||||||
|
|
||||||
var NUMBER = 1;
|
|
||||||
var OPERATOR = 2;
|
|
||||||
var MOTION = 3;
|
|
||||||
var ACTION = 4;
|
|
||||||
var HMARGIN = 8; // Minimum amount of line separation between margins;
|
|
||||||
|
|
||||||
var repeat = function repeat(fn, count, args) {
|
|
||||||
while (0 < count--)
|
|
||||||
fn.apply(this, args);
|
|
||||||
};
|
|
||||||
|
|
||||||
var ensureScrollMargin = function(editor) {
|
|
||||||
var renderer = editor.renderer;
|
|
||||||
var pos = renderer.$cursorLayer.getPixelPosition();
|
|
||||||
|
|
||||||
var top = pos.top;
|
|
||||||
|
|
||||||
var margin = HMARGIN * renderer.layerConfig.lineHeight;
|
|
||||||
if (2 * margin > renderer.$size.scrollerHeight)
|
|
||||||
margin = renderer.$size.scrollerHeight / 2;
|
|
||||||
|
|
||||||
if (renderer.scrollTop > top - margin) {
|
|
||||||
renderer.session.setScrollTop(top - margin);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (renderer.scrollTop + renderer.$size.scrollerHeight < top + margin + renderer.lineHeight) {
|
|
||||||
renderer.session.setScrollTop(top + margin + renderer.lineHeight - renderer.$size.scrollerHeight);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var actions = exports.actions = {
|
|
||||||
"z": {
|
|
||||||
param: true,
|
|
||||||
fn: function(editor, range, count, param) {
|
|
||||||
switch (param) {
|
|
||||||
case "z":
|
|
||||||
editor.renderer.alignCursor(null, 0.5);
|
|
||||||
break;
|
|
||||||
case "t":
|
|
||||||
editor.renderer.alignCursor(null, 0);
|
|
||||||
break;
|
|
||||||
case "b":
|
|
||||||
editor.renderer.alignCursor(null, 1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"r": {
|
|
||||||
param: true,
|
|
||||||
fn: function(editor, range, count, param) {
|
|
||||||
if (param && param.length) {
|
|
||||||
repeat(function() { editor.insert(param); }, count || 1);
|
|
||||||
editor.navigateLeft();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"R": {
|
|
||||||
fn: function(editor, range, count, param) {
|
|
||||||
util.insertMode(editor);
|
|
||||||
editor.setOverwrite(true);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"~": {
|
|
||||||
fn: function(editor, range, count) {
|
|
||||||
repeat(function() {
|
|
||||||
var range = editor.selection.getRange();
|
|
||||||
if (range.isEmpty())
|
|
||||||
range.end.column++;
|
|
||||||
var text = editor.session.getTextRange(range);
|
|
||||||
var toggled = text.toUpperCase();
|
|
||||||
if (toggled == text)
|
|
||||||
editor.navigateRight();
|
|
||||||
else
|
|
||||||
editor.session.replace(range, toggled);
|
|
||||||
}, count || 1);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"*": {
|
|
||||||
fn: function(editor, range, count, param) {
|
|
||||||
editor.selection.selectWord();
|
|
||||||
editor.findNext();
|
|
||||||
ensureScrollMargin(editor);
|
|
||||||
var r = editor.selection.getRange();
|
|
||||||
editor.selection.setSelectionRange(r, true);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"#": {
|
|
||||||
fn: function(editor, range, count, param) {
|
|
||||||
editor.selection.selectWord();
|
|
||||||
editor.findPrevious();
|
|
||||||
ensureScrollMargin(editor);
|
|
||||||
var r = editor.selection.getRange();
|
|
||||||
editor.selection.setSelectionRange(r, true);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"n": {
|
|
||||||
fn: function(editor, range, count, param) {
|
|
||||||
var options = editor.getLastSearchOptions();
|
|
||||||
options.backwards = false;
|
|
||||||
|
|
||||||
editor.selection.moveCursorRight();
|
|
||||||
editor.selection.clearSelection();
|
|
||||||
editor.findNext(options);
|
|
||||||
|
|
||||||
ensureScrollMargin(editor);
|
|
||||||
var r = editor.selection.getRange();
|
|
||||||
r.end.row = r.start.row;
|
|
||||||
r.end.column = r.start.column;
|
|
||||||
editor.selection.setSelectionRange(r, true);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"N": {
|
|
||||||
fn: function(editor, range, count, param) {
|
|
||||||
var options = editor.getLastSearchOptions();
|
|
||||||
options.backwards = true;
|
|
||||||
|
|
||||||
editor.findPrevious(options);
|
|
||||||
ensureScrollMargin(editor);
|
|
||||||
var r = editor.selection.getRange();
|
|
||||||
r.end.row = r.start.row;
|
|
||||||
r.end.column = r.start.column;
|
|
||||||
editor.selection.setSelectionRange(r, true);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"v": {
|
|
||||||
fn: function(editor, range, count, param) {
|
|
||||||
editor.selection.selectRight();
|
|
||||||
util.visualMode(editor, false);
|
|
||||||
},
|
|
||||||
acceptsMotion: true
|
|
||||||
},
|
|
||||||
"V": {
|
|
||||||
fn: function(editor, range, count, param) {
|
|
||||||
//editor.selection.selectLine();
|
|
||||||
//editor.selection.selectLeft();
|
|
||||||
var row = editor.getCursorPosition().row;
|
|
||||||
editor.selection.clearSelection();
|
|
||||||
editor.selection.moveCursorTo(row, 0);
|
|
||||||
editor.selection.selectLineEnd();
|
|
||||||
editor.selection.visualLineStart = row;
|
|
||||||
|
|
||||||
util.visualMode(editor, true);
|
|
||||||
},
|
|
||||||
acceptsMotion: true
|
|
||||||
},
|
|
||||||
"Y": {
|
|
||||||
fn: function(editor, range, count, param) {
|
|
||||||
util.copyLine(editor);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"p": {
|
|
||||||
fn: function(editor, range, count, param) {
|
|
||||||
var defaultReg = registers._default;
|
|
||||||
|
|
||||||
editor.setOverwrite(false);
|
|
||||||
if (defaultReg.isLine) {
|
|
||||||
var pos = editor.getCursorPosition();
|
|
||||||
var lines = defaultReg.text.split("\n");
|
|
||||||
editor.session.getDocument().insertLines(pos.row + 1, lines);
|
|
||||||
editor.moveCursorTo(pos.row + 1, 0);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
editor.navigateRight();
|
|
||||||
editor.insert(defaultReg.text);
|
|
||||||
editor.navigateLeft();
|
|
||||||
}
|
|
||||||
editor.setOverwrite(true);
|
|
||||||
editor.selection.clearSelection();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"P": {
|
|
||||||
fn: function(editor, range, count, param) {
|
|
||||||
var defaultReg = registers._default;
|
|
||||||
editor.setOverwrite(false);
|
|
||||||
|
|
||||||
if (defaultReg.isLine) {
|
|
||||||
var pos = editor.getCursorPosition();
|
|
||||||
var lines = defaultReg.text.split("\n");
|
|
||||||
editor.session.getDocument().insertLines(pos.row, lines);
|
|
||||||
editor.moveCursorTo(pos.row, 0);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
editor.insert(defaultReg.text);
|
|
||||||
}
|
|
||||||
editor.setOverwrite(true);
|
|
||||||
editor.selection.clearSelection();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"J": {
|
|
||||||
fn: function(editor, range, count, param) {
|
|
||||||
var session = editor.session;
|
|
||||||
range = editor.getSelectionRange();
|
|
||||||
var pos = {row: range.start.row, column: range.start.column};
|
|
||||||
count = count || range.end.row - range.start.row;
|
|
||||||
var maxRow = Math.min(pos.row + (count || 1), session.getLength() - 1);
|
|
||||||
|
|
||||||
range.start.column = session.getLine(pos.row).length;
|
|
||||||
range.end.column = session.getLine(maxRow).length;
|
|
||||||
range.end.row = maxRow;
|
|
||||||
|
|
||||||
var text = "";
|
|
||||||
for (var i = pos.row; i < maxRow; i++) {
|
|
||||||
var nextLine = session.getLine(i + 1);
|
|
||||||
text += " " + /^\s*(.*)$/.exec(nextLine)[1] || "";
|
|
||||||
}
|
|
||||||
|
|
||||||
session.replace(range, text);
|
|
||||||
editor.moveCursorTo(pos.row, pos.column);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"u": {
|
|
||||||
fn: function(editor, range, count, param) {
|
|
||||||
count = parseInt(count || 1, 10);
|
|
||||||
for (var i = 0; i < count; i++) {
|
|
||||||
editor.undo();
|
|
||||||
}
|
|
||||||
editor.selection.clearSelection();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ctrl-r": {
|
|
||||||
fn: function(editor, range, count, param) {
|
|
||||||
count = parseInt(count || 1, 10);
|
|
||||||
for (var i = 0; i < count; i++) {
|
|
||||||
editor.redo();
|
|
||||||
}
|
|
||||||
editor.selection.clearSelection();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
":": {
|
|
||||||
fn: function(editor, range, count, param) {
|
|
||||||
// not implemented
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"/": {
|
|
||||||
fn: function(editor, range, count, param) {
|
|
||||||
// not implemented
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"?": {
|
|
||||||
fn: function(editor, range, count, param) {
|
|
||||||
// not implemented
|
|
||||||
}
|
|
||||||
},
|
|
||||||
".": {
|
|
||||||
fn: function(editor, range, count, param) {
|
|
||||||
util.onInsertReplaySequence = inputBuffer.lastInsertCommands;
|
|
||||||
var previous = inputBuffer.previous;
|
|
||||||
if (previous) // If there is a previous action
|
|
||||||
inputBuffer.exec(editor, previous.action, previous.param);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var inputBuffer = exports.inputBuffer = {
|
|
||||||
accepting: [NUMBER, OPERATOR, MOTION, ACTION],
|
|
||||||
currentCmd: null,
|
|
||||||
//currentMode: 0,
|
|
||||||
currentCount: "",
|
|
||||||
status: "",
|
|
||||||
|
|
||||||
// Types
|
|
||||||
operator: null,
|
|
||||||
motion: null,
|
|
||||||
|
|
||||||
lastInsertCommands: [],
|
|
||||||
|
|
||||||
push: function(editor, ch, keyId) {
|
|
||||||
this.idle = false;
|
|
||||||
var wObj = this.waitingForParam;
|
|
||||||
if (wObj) {
|
|
||||||
this.exec(editor, wObj, ch);
|
|
||||||
}
|
|
||||||
// If input is a number (that doesn't start with 0)
|
|
||||||
else if (!(ch === "0" && !this.currentCount.length) &&
|
|
||||||
(ch.match(/^\d+$/) && this.isAccepting(NUMBER))) {
|
|
||||||
// Assuming that ch is always of type String, and not Number
|
|
||||||
this.currentCount += ch;
|
|
||||||
this.currentCmd = NUMBER;
|
|
||||||
this.accepting = [NUMBER, OPERATOR, MOTION, ACTION];
|
|
||||||
}
|
|
||||||
else if (!this.operator && this.isAccepting(OPERATOR) && operators[ch]) {
|
|
||||||
this.operator = {
|
|
||||||
ch: ch,
|
|
||||||
count: this.getCount()
|
|
||||||
};
|
|
||||||
this.currentCmd = OPERATOR;
|
|
||||||
this.accepting = [NUMBER, MOTION, ACTION];
|
|
||||||
this.exec(editor, { operator: this.operator });
|
|
||||||
}
|
|
||||||
else if (motions[ch] && this.isAccepting(MOTION)) {
|
|
||||||
this.currentCmd = MOTION;
|
|
||||||
|
|
||||||
var ctx = {
|
|
||||||
operator: this.operator,
|
|
||||||
motion: {
|
|
||||||
ch: ch,
|
|
||||||
count: this.getCount()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (motions[ch].param)
|
|
||||||
this.waitForParam(ctx);
|
|
||||||
else
|
|
||||||
this.exec(editor, ctx);
|
|
||||||
}
|
|
||||||
else if (alias[ch] && this.isAccepting(MOTION)) {
|
|
||||||
alias[ch].operator.count = this.getCount();
|
|
||||||
this.exec(editor, alias[ch]);
|
|
||||||
}
|
|
||||||
else if (actions[ch] && this.isAccepting(ACTION)) {
|
|
||||||
var actionObj = {
|
|
||||||
action: {
|
|
||||||
fn: actions[ch].fn,
|
|
||||||
count: this.getCount()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (actions[ch].param) {
|
|
||||||
this.waitForParam(actionObj);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.exec(editor, actionObj);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (actions[ch].acceptsMotion)
|
|
||||||
this.idle = false;
|
|
||||||
}
|
|
||||||
else if (this.operator) {
|
|
||||||
this.exec(editor, { operator: this.operator }, ch);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.waitingForParam || this.motion || this.operator) {
|
|
||||||
this.status += ch;
|
|
||||||
} else if (this.currentCount) {
|
|
||||||
this.status = this.currentCount;
|
|
||||||
} else if (this.status) {
|
|
||||||
this.status = "";
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
editor._emit("changeStatus");
|
|
||||||
},
|
|
||||||
|
|
||||||
waitForParam: function(cmd) {
|
|
||||||
this.waitingForParam = cmd;
|
|
||||||
},
|
|
||||||
|
|
||||||
getCount: function() {
|
|
||||||
var count = this.currentCount;
|
|
||||||
this.currentCount = "";
|
|
||||||
return count && parseInt(count, 10);
|
|
||||||
},
|
|
||||||
|
|
||||||
exec: function(editor, action, param) {
|
|
||||||
var m = action.motion;
|
|
||||||
var o = action.operator;
|
|
||||||
var a = action.action;
|
|
||||||
|
|
||||||
if (!param)
|
|
||||||
param = action.param;
|
|
||||||
|
|
||||||
if (o) {
|
|
||||||
this.previous = {
|
|
||||||
action: action,
|
|
||||||
param: param
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (o && !editor.selection.isEmpty()) {
|
|
||||||
if (operators[o.ch].selFn) {
|
|
||||||
operators[o.ch].selFn(editor, editor.getSelectionRange(), o.count, param);
|
|
||||||
this.reset();
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// There is an operator, but no motion or action. We try to pass the
|
|
||||||
// current ch to the operator to see if it responds to it (an example
|
|
||||||
// of this is the 'dd' operator).
|
|
||||||
else if (!m && !a && o && param) {
|
|
||||||
operators[o.ch].fn(editor, null, o.count, param);
|
|
||||||
this.reset();
|
|
||||||
}
|
|
||||||
else if (m) {
|
|
||||||
var run = function(fn) {
|
|
||||||
if (fn && typeof fn === "function") { // There should always be a motion
|
|
||||||
if (m.count && !motionObj.handlesCount)
|
|
||||||
repeat(fn, m.count, [editor, null, m.count, param]);
|
|
||||||
else
|
|
||||||
fn(editor, null, m.count, param);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var motionObj = motions[m.ch];
|
|
||||||
var selectable = motionObj.sel;
|
|
||||||
|
|
||||||
if (!o) {
|
|
||||||
if ((util.onVisualMode || util.onVisualLineMode) && selectable)
|
|
||||||
run(motionObj.sel);
|
|
||||||
else
|
|
||||||
run(motionObj.nav);
|
|
||||||
}
|
|
||||||
else if (selectable) {
|
|
||||||
repeat(function() {
|
|
||||||
run(motionObj.sel);
|
|
||||||
operators[o.ch].fn(editor, editor.getSelectionRange(), o.count, param);
|
|
||||||
}, o.count || 1);
|
|
||||||
}
|
|
||||||
this.reset();
|
|
||||||
}
|
|
||||||
else if (a) {
|
|
||||||
a.fn(editor, editor.getSelectionRange(), a.count, param);
|
|
||||||
this.reset();
|
|
||||||
}
|
|
||||||
handleCursorMove(editor);
|
|
||||||
},
|
|
||||||
|
|
||||||
isAccepting: function(type) {
|
|
||||||
return this.accepting.indexOf(type) !== -1;
|
|
||||||
},
|
|
||||||
|
|
||||||
reset: function() {
|
|
||||||
this.operator = null;
|
|
||||||
this.motion = null;
|
|
||||||
this.currentCount = "";
|
|
||||||
this.status = "";
|
|
||||||
this.accepting = [NUMBER, OPERATOR, MOTION, ACTION];
|
|
||||||
this.idle = true;
|
|
||||||
this.waitingForParam = null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function setPreviousCommand(fn) {
|
|
||||||
inputBuffer.previous = { action: { action: { fn: fn } } };
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.coreCommands = {
|
|
||||||
start: {
|
|
||||||
exec: function start(editor) {
|
|
||||||
util.insertMode(editor);
|
|
||||||
setPreviousCommand(start);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
startBeginning: {
|
|
||||||
exec: function startBeginning(editor) {
|
|
||||||
editor.navigateLineStart();
|
|
||||||
util.insertMode(editor);
|
|
||||||
setPreviousCommand(startBeginning);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// Stop Insert mode as soon as possible. Works like typing <Esc> in
|
|
||||||
// insert mode.
|
|
||||||
stop: {
|
|
||||||
exec: function stop(editor) {
|
|
||||||
inputBuffer.reset();
|
|
||||||
util.onVisualMode = false;
|
|
||||||
util.onVisualLineMode = false;
|
|
||||||
inputBuffer.lastInsertCommands = util.normalMode(editor);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
append: {
|
|
||||||
exec: function append(editor) {
|
|
||||||
var pos = editor.getCursorPosition();
|
|
||||||
var lineLen = editor.session.getLine(pos.row).length;
|
|
||||||
if (lineLen)
|
|
||||||
editor.navigateRight();
|
|
||||||
util.insertMode(editor);
|
|
||||||
setPreviousCommand(append);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
appendEnd: {
|
|
||||||
exec: function appendEnd(editor) {
|
|
||||||
editor.navigateLineEnd();
|
|
||||||
util.insertMode(editor);
|
|
||||||
setPreviousCommand(appendEnd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var handleCursorMove = exports.onCursorMove = function(editor, e) {
|
|
||||||
if (util.currentMode === 'insert' || handleCursorMove.running)
|
|
||||||
return;
|
|
||||||
else if(!editor.selection.isEmpty()) {
|
|
||||||
handleCursorMove.running = true;
|
|
||||||
if (util.onVisualLineMode) {
|
|
||||||
var originRow = editor.selection.visualLineStart;
|
|
||||||
var cursorRow = editor.getCursorPosition().row;
|
|
||||||
if(originRow <= cursorRow) {
|
|
||||||
var endLine = editor.session.getLine(cursorRow);
|
|
||||||
editor.selection.clearSelection();
|
|
||||||
editor.selection.moveCursorTo(originRow, 0);
|
|
||||||
editor.selection.selectTo(cursorRow, endLine.length);
|
|
||||||
} else {
|
|
||||||
var endLine = editor.session.getLine(originRow);
|
|
||||||
editor.selection.clearSelection();
|
|
||||||
editor.selection.moveCursorTo(originRow, endLine.length);
|
|
||||||
editor.selection.selectTo(cursorRow, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
handleCursorMove.running = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (e && (util.onVisualLineMode || util.onVisualMode)) {
|
|
||||||
editor.selection.clearSelection();
|
|
||||||
util.normalMode(editor);
|
|
||||||
}
|
|
||||||
|
|
||||||
handleCursorMove.running = true;
|
|
||||||
var pos = editor.getCursorPosition();
|
|
||||||
var lineLen = editor.session.getLine(pos.row).length;
|
|
||||||
|
|
||||||
if (lineLen && pos.column === lineLen)
|
|
||||||
editor.navigateLeft();
|
|
||||||
handleCursorMove.running = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
||||||
@@ -1,593 +0,0 @@
|
|||||||
/* ***** BEGIN LICENSE BLOCK *****
|
|
||||||
* Distributed under the BSD license:
|
|
||||||
*
|
|
||||||
* Copyright (c) 2010, Ajax.org B.V.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
* * Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* * Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* * Neither the name of Ajax.org B.V. nor the
|
|
||||||
* names of its contributors may be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
|
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* ***** END LICENSE BLOCK ***** */
|
|
||||||
|
|
||||||
|
|
||||||
define(function(require, exports, module) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
var util = require("./util");
|
|
||||||
|
|
||||||
var keepScrollPosition = function(editor, fn) {
|
|
||||||
var scrollTopRow = editor.renderer.getScrollTopRow();
|
|
||||||
var initialRow = editor.getCursorPosition().row;
|
|
||||||
var diff = initialRow - scrollTopRow;
|
|
||||||
fn && fn.call(editor);
|
|
||||||
editor.renderer.scrollToRow(editor.getCursorPosition().row - diff);
|
|
||||||
};
|
|
||||||
|
|
||||||
function Motion(m) {
|
|
||||||
if (typeof m == "function") {
|
|
||||||
var getPos = m;
|
|
||||||
m = this;
|
|
||||||
} else {
|
|
||||||
var getPos = m.getPos;
|
|
||||||
}
|
|
||||||
m.nav = function(editor, range, count, param) {
|
|
||||||
var a = getPos(editor, range, count, param, false);
|
|
||||||
if (!a)
|
|
||||||
return;
|
|
||||||
editor.clearSelection();
|
|
||||||
editor.moveCursorTo(a.row, a.column);
|
|
||||||
};
|
|
||||||
m.sel = function(editor, range, count, param) {
|
|
||||||
var a = getPos(editor, range, count, param, true);
|
|
||||||
if (!a)
|
|
||||||
return;
|
|
||||||
editor.selection.selectTo(a.row, a.column);
|
|
||||||
};
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
|
|
||||||
var nonWordRe = /[\s.\/\\()\"'-:,.;<>~!@#$%^&*|+=\[\]{}`~?]/;
|
|
||||||
var wordSeparatorRe = /[.\/\\()\"'-:,.;<>~!@#$%^&*|+=\[\]{}`~?]/;
|
|
||||||
var whiteRe = /\s/;
|
|
||||||
var StringStream = function(editor, cursor) {
|
|
||||||
var sel = editor.selection;
|
|
||||||
this.range = sel.getRange();
|
|
||||||
cursor = cursor || sel.selectionLead;
|
|
||||||
this.row = cursor.row;
|
|
||||||
this.col = cursor.column;
|
|
||||||
var line = editor.session.getLine(this.row);
|
|
||||||
var maxRow = editor.session.getLength();
|
|
||||||
this.ch = line[this.col] || '\n';
|
|
||||||
this.skippedLines = 0;
|
|
||||||
|
|
||||||
this.next = function() {
|
|
||||||
this.ch = line[++this.col] || this.handleNewLine(1);
|
|
||||||
//this.debug()
|
|
||||||
return this.ch;
|
|
||||||
};
|
|
||||||
this.prev = function() {
|
|
||||||
this.ch = line[--this.col] || this.handleNewLine(-1);
|
|
||||||
//this.debug()
|
|
||||||
return this.ch;
|
|
||||||
};
|
|
||||||
this.peek = function(dir) {
|
|
||||||
var ch = line[this.col + dir];
|
|
||||||
if (ch)
|
|
||||||
return ch;
|
|
||||||
if (dir == -1)
|
|
||||||
return '\n';
|
|
||||||
if (this.col == line.length - 1)
|
|
||||||
return '\n';
|
|
||||||
return editor.session.getLine(this.row + 1)[0] || '\n';
|
|
||||||
};
|
|
||||||
|
|
||||||
this.handleNewLine = function(dir) {
|
|
||||||
if (dir == 1){
|
|
||||||
if (this.col == line.length)
|
|
||||||
return '\n';
|
|
||||||
if (this.row == maxRow - 1)
|
|
||||||
return '';
|
|
||||||
this.col = 0;
|
|
||||||
this.row ++;
|
|
||||||
line = editor.session.getLine(this.row);
|
|
||||||
this.skippedLines++;
|
|
||||||
return line[0] || '\n';
|
|
||||||
}
|
|
||||||
if (dir == -1) {
|
|
||||||
if (this.row === 0)
|
|
||||||
return '';
|
|
||||||
this.row --;
|
|
||||||
line = editor.session.getLine(this.row);
|
|
||||||
this.col = line.length;
|
|
||||||
this.skippedLines--;
|
|
||||||
return '\n';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
this.debug = function() {
|
|
||||||
console.log(line.substring(0, this.col)+'|'+this.ch+'\''+this.col+'\''+line.substr(this.col+1));
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
var Search = require("../../../search").Search;
|
|
||||||
var search = new Search();
|
|
||||||
|
|
||||||
function find(editor, needle, dir) {
|
|
||||||
search.$options.needle = needle;
|
|
||||||
search.$options.backwards = dir == -1;
|
|
||||||
return search.find(editor.session);
|
|
||||||
}
|
|
||||||
|
|
||||||
var Range = require("../../../range").Range;
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
"w": new Motion(function(editor) {
|
|
||||||
var str = new StringStream(editor);
|
|
||||||
|
|
||||||
if (str.ch && wordSeparatorRe.test(str.ch)) {
|
|
||||||
while (str.ch && wordSeparatorRe.test(str.ch))
|
|
||||||
str.next();
|
|
||||||
} else {
|
|
||||||
while (str.ch && !nonWordRe.test(str.ch))
|
|
||||||
str.next();
|
|
||||||
}
|
|
||||||
while (str.ch && whiteRe.test(str.ch) && str.skippedLines < 2)
|
|
||||||
str.next();
|
|
||||||
|
|
||||||
str.skippedLines == 2 && str.prev();
|
|
||||||
return {column: str.col, row: str.row};
|
|
||||||
}),
|
|
||||||
"W": new Motion(function(editor) {
|
|
||||||
var str = new StringStream(editor);
|
|
||||||
while(str.ch && !(whiteRe.test(str.ch) && !whiteRe.test(str.peek(1))) && str.skippedLines < 2)
|
|
||||||
str.next();
|
|
||||||
if (str.skippedLines == 2)
|
|
||||||
str.prev();
|
|
||||||
else
|
|
||||||
str.next();
|
|
||||||
|
|
||||||
return {column: str.col, row: str.row};
|
|
||||||
}),
|
|
||||||
"b": new Motion(function(editor) {
|
|
||||||
var str = new StringStream(editor);
|
|
||||||
|
|
||||||
str.prev();
|
|
||||||
while (str.ch && whiteRe.test(str.ch) && str.skippedLines > -2)
|
|
||||||
str.prev();
|
|
||||||
|
|
||||||
if (str.ch && wordSeparatorRe.test(str.ch)) {
|
|
||||||
while (str.ch && wordSeparatorRe.test(str.ch))
|
|
||||||
str.prev();
|
|
||||||
} else {
|
|
||||||
while (str.ch && !nonWordRe.test(str.ch))
|
|
||||||
str.prev();
|
|
||||||
}
|
|
||||||
str.ch && str.next();
|
|
||||||
return {column: str.col, row: str.row};
|
|
||||||
}),
|
|
||||||
"B": new Motion(function(editor) {
|
|
||||||
var str = new StringStream(editor);
|
|
||||||
str.prev();
|
|
||||||
while(str.ch && !(!whiteRe.test(str.ch) && whiteRe.test(str.peek(-1))) && str.skippedLines > -2)
|
|
||||||
str.prev();
|
|
||||||
|
|
||||||
if (str.skippedLines == -2)
|
|
||||||
str.next();
|
|
||||||
|
|
||||||
return {column: str.col, row: str.row};
|
|
||||||
}),
|
|
||||||
"e": new Motion(function(editor) {
|
|
||||||
var str = new StringStream(editor);
|
|
||||||
|
|
||||||
str.next();
|
|
||||||
while (str.ch && whiteRe.test(str.ch))
|
|
||||||
str.next();
|
|
||||||
|
|
||||||
if (str.ch && wordSeparatorRe.test(str.ch)) {
|
|
||||||
while (str.ch && wordSeparatorRe.test(str.ch))
|
|
||||||
str.next();
|
|
||||||
} else {
|
|
||||||
while (str.ch && !nonWordRe.test(str.ch))
|
|
||||||
str.next();
|
|
||||||
}
|
|
||||||
str.ch && str.prev();
|
|
||||||
return {column: str.col, row: str.row};
|
|
||||||
}),
|
|
||||||
"E": new Motion(function(editor) {
|
|
||||||
var str = new StringStream(editor);
|
|
||||||
str.next();
|
|
||||||
while(str.ch && !(!whiteRe.test(str.ch) && whiteRe.test(str.peek(1))))
|
|
||||||
str.next();
|
|
||||||
|
|
||||||
return {column: str.col, row: str.row};
|
|
||||||
}),
|
|
||||||
|
|
||||||
"l": {
|
|
||||||
nav: function(editor) {
|
|
||||||
editor.navigateRight();
|
|
||||||
},
|
|
||||||
sel: function(editor) {
|
|
||||||
var pos = editor.getCursorPosition();
|
|
||||||
var col = pos.column;
|
|
||||||
var lineLen = editor.session.getLine(pos.row).length;
|
|
||||||
|
|
||||||
// Solving the behavior at the end of the line due to the
|
|
||||||
// different 0 index-based colum positions in ACE.
|
|
||||||
if (lineLen && col !== lineLen) //In selection mode you can select the newline
|
|
||||||
editor.selection.selectRight();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"h": {
|
|
||||||
nav: function(editor) {
|
|
||||||
var pos = editor.getCursorPosition();
|
|
||||||
if (pos.column > 0)
|
|
||||||
editor.navigateLeft();
|
|
||||||
},
|
|
||||||
sel: function(editor) {
|
|
||||||
var pos = editor.getCursorPosition();
|
|
||||||
if (pos.column > 0)
|
|
||||||
editor.selection.selectLeft();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"H": {
|
|
||||||
nav: function(editor) {
|
|
||||||
var row = editor.renderer.getScrollTopRow();
|
|
||||||
editor.moveCursorTo(row);
|
|
||||||
},
|
|
||||||
sel: function(editor) {
|
|
||||||
var row = editor.renderer.getScrollTopRow();
|
|
||||||
editor.selection.selectTo(row);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"M": {
|
|
||||||
nav: function(editor) {
|
|
||||||
var topRow = editor.renderer.getScrollTopRow();
|
|
||||||
var bottomRow = editor.renderer.getScrollBottomRow();
|
|
||||||
var row = topRow + ((bottomRow - topRow) / 2);
|
|
||||||
editor.moveCursorTo(row);
|
|
||||||
},
|
|
||||||
sel: function(editor) {
|
|
||||||
var topRow = editor.renderer.getScrollTopRow();
|
|
||||||
var bottomRow = editor.renderer.getScrollBottomRow();
|
|
||||||
var row = topRow + ((bottomRow - topRow) / 2);
|
|
||||||
editor.selection.selectTo(row);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"L": {
|
|
||||||
nav: function(editor) {
|
|
||||||
var row = editor.renderer.getScrollBottomRow();
|
|
||||||
editor.moveCursorTo(row);
|
|
||||||
},
|
|
||||||
sel: function(editor) {
|
|
||||||
var row = editor.renderer.getScrollBottomRow();
|
|
||||||
editor.selection.selectTo(row);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"k": {
|
|
||||||
nav: function(editor) {
|
|
||||||
editor.navigateUp();
|
|
||||||
},
|
|
||||||
sel: function(editor) {
|
|
||||||
editor.selection.selectUp();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"j": {
|
|
||||||
nav: function(editor) {
|
|
||||||
editor.navigateDown();
|
|
||||||
},
|
|
||||||
sel: function(editor) {
|
|
||||||
editor.selection.selectDown();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
"i": {
|
|
||||||
param: true,
|
|
||||||
sel: function(editor, range, count, param) {
|
|
||||||
switch (param) {
|
|
||||||
case "w":
|
|
||||||
editor.selection.selectWord();
|
|
||||||
break;
|
|
||||||
case "W":
|
|
||||||
editor.selection.selectAWord();
|
|
||||||
break;
|
|
||||||
case "(":
|
|
||||||
case "{":
|
|
||||||
case "[":
|
|
||||||
var cursor = editor.getCursorPosition();
|
|
||||||
var end = editor.session.$findClosingBracket(param, cursor, /paren/);
|
|
||||||
if (!end)
|
|
||||||
return;
|
|
||||||
var start = editor.session.$findOpeningBracket(editor.session.$brackets[param], cursor, /paren/);
|
|
||||||
if (!start)
|
|
||||||
return;
|
|
||||||
start.column ++;
|
|
||||||
editor.selection.setSelectionRange(Range.fromPoints(start, end));
|
|
||||||
break;
|
|
||||||
case "'":
|
|
||||||
case '"':
|
|
||||||
case "/":
|
|
||||||
var end = find(editor, param, 1);
|
|
||||||
if (!end)
|
|
||||||
return;
|
|
||||||
var start = find(editor, param, -1);
|
|
||||||
if (!start)
|
|
||||||
return;
|
|
||||||
editor.selection.setSelectionRange(Range.fromPoints(start.end, end.start));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"a": {
|
|
||||||
param: true,
|
|
||||||
sel: function(editor, range, count, param) {
|
|
||||||
switch (param) {
|
|
||||||
case "w":
|
|
||||||
editor.selection.selectAWord();
|
|
||||||
break;
|
|
||||||
case "W":
|
|
||||||
editor.selection.selectAWord();
|
|
||||||
break;
|
|
||||||
case "(":
|
|
||||||
case "{":
|
|
||||||
case "[":
|
|
||||||
var cursor = editor.getCursorPosition();
|
|
||||||
var end = editor.session.$findClosingBracket(param, cursor, /paren/);
|
|
||||||
if (!end)
|
|
||||||
return;
|
|
||||||
var start = editor.session.$findOpeningBracket(editor.session.$brackets[param], cursor, /paren/);
|
|
||||||
if (!start)
|
|
||||||
return;
|
|
||||||
end.column ++;
|
|
||||||
editor.selection.setSelectionRange(Range.fromPoints(start, end));
|
|
||||||
break;
|
|
||||||
case "'":
|
|
||||||
case "\"":
|
|
||||||
case "/":
|
|
||||||
var end = find(editor, param, 1);
|
|
||||||
if (!end)
|
|
||||||
return;
|
|
||||||
var start = find(editor, param, -1);
|
|
||||||
if (!start)
|
|
||||||
return;
|
|
||||||
end.column ++;
|
|
||||||
editor.selection.setSelectionRange(Range.fromPoints(start.start, end.end));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
"f": new Motion({
|
|
||||||
param: true,
|
|
||||||
handlesCount: true,
|
|
||||||
getPos: function(editor, range, count, param, isSel) {
|
|
||||||
var cursor = editor.getCursorPosition();
|
|
||||||
var column = util.getRightNthChar(editor, cursor, param, count || 1);
|
|
||||||
|
|
||||||
if (typeof column === "number") {
|
|
||||||
cursor.column += column + (isSel ? 2 : 1);
|
|
||||||
return cursor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
"F": new Motion({
|
|
||||||
param: true,
|
|
||||||
handlesCount: true,
|
|
||||||
getPos: function(editor, range, count, param, isSel) {
|
|
||||||
var cursor = editor.getCursorPosition();
|
|
||||||
var column = util.getLeftNthChar(editor, cursor, param, count || 1);
|
|
||||||
|
|
||||||
if (typeof column === "number") {
|
|
||||||
cursor.column -= column + 1;
|
|
||||||
return cursor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
"t": new Motion({
|
|
||||||
param: true,
|
|
||||||
handlesCount: true,
|
|
||||||
getPos: function(editor, range, count, param, isSel) {
|
|
||||||
var cursor = editor.getCursorPosition();
|
|
||||||
var column = util.getRightNthChar(editor, cursor, param, count || 1);
|
|
||||||
|
|
||||||
if (typeof column === "number") {
|
|
||||||
cursor.column += column + (isSel ? 1 : 0);
|
|
||||||
return cursor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
"T": new Motion({
|
|
||||||
param: true,
|
|
||||||
handlesCount: true,
|
|
||||||
getPos: function(editor, range, count, param, isSel) {
|
|
||||||
var cursor = editor.getCursorPosition();
|
|
||||||
var column = util.getLeftNthChar(editor, cursor, param, count || 1);
|
|
||||||
|
|
||||||
if (typeof column === "number") {
|
|
||||||
cursor.column -= column;
|
|
||||||
return cursor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
|
|
||||||
"^": {
|
|
||||||
nav: function(editor) {
|
|
||||||
editor.navigateLineStart();
|
|
||||||
},
|
|
||||||
sel: function(editor) {
|
|
||||||
editor.selection.selectLineStart();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"$": {
|
|
||||||
nav: function(editor) {
|
|
||||||
editor.navigateLineEnd();
|
|
||||||
},
|
|
||||||
sel: function(editor) {
|
|
||||||
editor.selection.selectLineEnd();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"0": new Motion(function(ed) {
|
|
||||||
return {row: ed.selection.lead.row, column: 0};
|
|
||||||
}),
|
|
||||||
"G": {
|
|
||||||
nav: function(editor, range, count, param) {
|
|
||||||
if (!count && count !== 0) { // Stupid JS
|
|
||||||
count = editor.session.getLength();
|
|
||||||
}
|
|
||||||
editor.gotoLine(count);
|
|
||||||
},
|
|
||||||
sel: function(editor, range, count, param) {
|
|
||||||
if (!count && count !== 0) { // Stupid JS
|
|
||||||
count = editor.session.getLength();
|
|
||||||
}
|
|
||||||
editor.selection.selectTo(count, 0);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"g": {
|
|
||||||
param: true,
|
|
||||||
nav: function(editor, range, count, param) {
|
|
||||||
switch(param) {
|
|
||||||
case "m":
|
|
||||||
console.log("Middle line");
|
|
||||||
break;
|
|
||||||
case "e":
|
|
||||||
console.log("End of prev word");
|
|
||||||
break;
|
|
||||||
case "g":
|
|
||||||
editor.gotoLine(count || 0);
|
|
||||||
case "u":
|
|
||||||
editor.gotoLine(count || 0);
|
|
||||||
case "U":
|
|
||||||
editor.gotoLine(count || 0);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
sel: function(editor, range, count, param) {
|
|
||||||
switch(param) {
|
|
||||||
case "m":
|
|
||||||
console.log("Middle line");
|
|
||||||
break;
|
|
||||||
case "e":
|
|
||||||
console.log("End of prev word");
|
|
||||||
break;
|
|
||||||
case "g":
|
|
||||||
editor.selection.selectTo(count || 0, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"o": {
|
|
||||||
nav: function(editor, range, count, param) {
|
|
||||||
count = count || 1;
|
|
||||||
var content = "";
|
|
||||||
while (0 < count--)
|
|
||||||
content += "\n";
|
|
||||||
|
|
||||||
if (content.length) {
|
|
||||||
editor.navigateLineEnd()
|
|
||||||
editor.insert(content);
|
|
||||||
util.insertMode(editor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"O": {
|
|
||||||
nav: function(editor, range, count, param) {
|
|
||||||
var row = editor.getCursorPosition().row;
|
|
||||||
count = count || 1;
|
|
||||||
var content = "";
|
|
||||||
while (0 < count--)
|
|
||||||
content += "\n";
|
|
||||||
|
|
||||||
if (content.length) {
|
|
||||||
if(row > 0) {
|
|
||||||
editor.navigateUp();
|
|
||||||
editor.navigateLineEnd()
|
|
||||||
editor.insert(content);
|
|
||||||
} else {
|
|
||||||
editor.session.insert({row: 0, column: 0}, content);
|
|
||||||
editor.navigateUp();
|
|
||||||
}
|
|
||||||
util.insertMode(editor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"%": new Motion(function(editor){
|
|
||||||
var brRe = /[\[\]{}()]/g;
|
|
||||||
var cursor = editor.getCursorPosition();
|
|
||||||
var ch = editor.session.getLine(cursor.row)[cursor.column];
|
|
||||||
if (!brRe.test(ch)) {
|
|
||||||
var range = find(editor, brRe);
|
|
||||||
if (!range)
|
|
||||||
return;
|
|
||||||
cursor = range.start;
|
|
||||||
}
|
|
||||||
var match = editor.session.findMatchingBracket({
|
|
||||||
row: cursor.row,
|
|
||||||
column: cursor.column + 1
|
|
||||||
});
|
|
||||||
|
|
||||||
return match;
|
|
||||||
}),
|
|
||||||
"{": new Motion(function(ed) {
|
|
||||||
var session = ed.session;
|
|
||||||
var row = session.selection.lead.row;
|
|
||||||
while(row > 0 && !/\S/.test(session.getLine(row)))
|
|
||||||
row--;
|
|
||||||
while(/\S/.test(session.getLine(row)))
|
|
||||||
row--;
|
|
||||||
return {column: 0, row: row};
|
|
||||||
}),
|
|
||||||
"}": new Motion(function(ed) {
|
|
||||||
var session = ed.session;
|
|
||||||
var l = session.getLength();
|
|
||||||
var row = session.selection.lead.row;
|
|
||||||
while(row < l && !/\S/.test(session.getLine(row)))
|
|
||||||
row++;
|
|
||||||
while(/\S/.test(session.getLine(row)))
|
|
||||||
row++;
|
|
||||||
return {column: 0, row: row};
|
|
||||||
}),
|
|
||||||
"ctrl-d": {
|
|
||||||
nav: function(editor, range, count, param) {
|
|
||||||
editor.selection.clearSelection();
|
|
||||||
keepScrollPosition(editor, editor.gotoPageDown);
|
|
||||||
},
|
|
||||||
sel: function(editor, range, count, param) {
|
|
||||||
keepScrollPosition(editor, editor.selectPageDown);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ctrl-u": {
|
|
||||||
nav: function(editor, range, count, param) {
|
|
||||||
editor.selection.clearSelection();
|
|
||||||
keepScrollPosition(editor, editor.gotoPageUp);
|
|
||||||
|
|
||||||
},
|
|
||||||
sel: function(editor, range, count, param) {
|
|
||||||
keepScrollPosition(editor, editor.selectPageUp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.backspace = module.exports.left = module.exports.h;
|
|
||||||
module.exports.right = module.exports.l;
|
|
||||||
module.exports.up = module.exports.k;
|
|
||||||
module.exports.down = module.exports.j;
|
|
||||||
module.exports.pagedown = module.exports["ctrl-d"];
|
|
||||||
module.exports.pageup = module.exports["ctrl-u"];
|
|
||||||
|
|
||||||
});
|
|
||||||
@@ -1,196 +0,0 @@
|
|||||||
/* ***** BEGIN LICENSE BLOCK *****
|
|
||||||
* Distributed under the BSD license:
|
|
||||||
*
|
|
||||||
* Copyright (c) 2010, Ajax.org B.V.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
* * Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* * Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* * Neither the name of Ajax.org B.V. nor the
|
|
||||||
* names of its contributors may be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
|
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* ***** END LICENSE BLOCK ***** */
|
|
||||||
|
|
||||||
define(function(require, exports, module) {
|
|
||||||
|
|
||||||
"never use strict";
|
|
||||||
|
|
||||||
var util = require("./util");
|
|
||||||
var registers = require("../registers");
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
"d": {
|
|
||||||
selFn: function(editor, range, count, param) {
|
|
||||||
registers._default.text = editor.getCopyText();
|
|
||||||
registers._default.isLine = util.onVisualLineMode;
|
|
||||||
if(util.onVisualLineMode)
|
|
||||||
editor.removeLines();
|
|
||||||
else
|
|
||||||
editor.session.remove(range);
|
|
||||||
util.normalMode(editor);
|
|
||||||
},
|
|
||||||
fn: function(editor, range, count, param) {
|
|
||||||
count = count || 1;
|
|
||||||
switch (param) {
|
|
||||||
case "d":
|
|
||||||
registers._default.text = "";
|
|
||||||
registers._default.isLine = true;
|
|
||||||
for (var i = 0; i < count; i++) {
|
|
||||||
editor.selection.selectLine();
|
|
||||||
registers._default.text += editor.getCopyText();
|
|
||||||
var selRange = editor.getSelectionRange();
|
|
||||||
// check if end of the document was reached
|
|
||||||
if (!selRange.isMultiLine()) {
|
|
||||||
lastLineReached = true
|
|
||||||
var row = selRange.start.row - 1;
|
|
||||||
var col = editor.session.getLine(row).length
|
|
||||||
selRange.setStart(row, col);
|
|
||||||
editor.session.remove(selRange);
|
|
||||||
editor.selection.clearSelection();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
editor.session.remove(selRange);
|
|
||||||
editor.selection.clearSelection();
|
|
||||||
}
|
|
||||||
registers._default.text = registers._default.text.replace(/\n$/, "");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (range) {
|
|
||||||
editor.selection.setSelectionRange(range);
|
|
||||||
registers._default.text = editor.getCopyText();
|
|
||||||
registers._default.isLine = false;
|
|
||||||
editor.session.remove(range);
|
|
||||||
editor.selection.clearSelection();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"c": {
|
|
||||||
selFn: function(editor, range, count, param) {
|
|
||||||
editor.session.remove(range);
|
|
||||||
util.insertMode(editor);
|
|
||||||
},
|
|
||||||
fn: function(editor, range, count, param) {
|
|
||||||
count = count || 1;
|
|
||||||
switch (param) {
|
|
||||||
case "c":
|
|
||||||
for (var i = 0; i < count; i++) {
|
|
||||||
editor.removeLines();
|
|
||||||
util.insertMode(editor);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (range) {
|
|
||||||
|
|
||||||
// range.end.column ++;
|
|
||||||
editor.session.remove(range);
|
|
||||||
util.insertMode(editor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"y": {
|
|
||||||
selFn: function(editor, range, count, param) {
|
|
||||||
registers._default.text = editor.getCopyText();
|
|
||||||
registers._default.isLine = util.onVisualLineMode;
|
|
||||||
editor.selection.clearSelection();
|
|
||||||
util.normalMode(editor);
|
|
||||||
},
|
|
||||||
fn: function(editor, range, count, param) {
|
|
||||||
count = count || 1;
|
|
||||||
switch (param) {
|
|
||||||
case "y":
|
|
||||||
var pos = editor.getCursorPosition();
|
|
||||||
editor.selection.selectLine();
|
|
||||||
for (var i = 0; i < count - 1; i++) {
|
|
||||||
editor.selection.moveCursorDown();
|
|
||||||
}
|
|
||||||
registers._default.text = editor.getCopyText().replace(/\n$/, "");
|
|
||||||
editor.selection.clearSelection();
|
|
||||||
registers._default.isLine = true;
|
|
||||||
editor.moveCursorToPosition(pos);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (range) {
|
|
||||||
var pos = editor.getCursorPosition();
|
|
||||||
editor.selection.setSelectionRange(range);
|
|
||||||
registers._default.text = editor.getCopyText();
|
|
||||||
registers._default.isLine = false;
|
|
||||||
editor.selection.clearSelection();
|
|
||||||
editor.moveCursorTo(pos.row, pos.column);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
">": {
|
|
||||||
selFn: function(editor, range, count, param) {
|
|
||||||
count = count || 1;
|
|
||||||
for (var i = 0; i < count; i++) {
|
|
||||||
editor.indent();
|
|
||||||
}
|
|
||||||
util.normalMode(editor);
|
|
||||||
},
|
|
||||||
fn: function(editor, range, count, param) {
|
|
||||||
count = parseInt(count || 1, 10);
|
|
||||||
switch (param) {
|
|
||||||
case ">":
|
|
||||||
var pos = editor.getCursorPosition();
|
|
||||||
editor.selection.selectLine();
|
|
||||||
for (var i = 0; i < count - 1; i++) {
|
|
||||||
editor.selection.moveCursorDown();
|
|
||||||
}
|
|
||||||
editor.indent();
|
|
||||||
editor.selection.clearSelection();
|
|
||||||
editor.moveCursorToPosition(pos);
|
|
||||||
editor.navigateLineEnd();
|
|
||||||
editor.navigateLineStart();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"<": {
|
|
||||||
selFn: function(editor, range, count, param) {
|
|
||||||
count = count || 1;
|
|
||||||
for (var i = 0; i < count; i++) {
|
|
||||||
editor.blockOutdent();
|
|
||||||
}
|
|
||||||
util.normalMode(editor);
|
|
||||||
},
|
|
||||||
fn: function(editor, range, count, param) {
|
|
||||||
count = count || 1;
|
|
||||||
switch (param) {
|
|
||||||
case "<":
|
|
||||||
var pos = editor.getCursorPosition();
|
|
||||||
editor.selection.selectLine();
|
|
||||||
for (var i = 0; i < count - 1; i++) {
|
|
||||||
editor.selection.moveCursorDown();
|
|
||||||
}
|
|
||||||
editor.blockOutdent();
|
|
||||||
editor.selection.clearSelection();
|
|
||||||
editor.moveCursorToPosition(pos);
|
|
||||||
editor.navigateLineEnd();
|
|
||||||
editor.navigateLineStart();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
||||||
@@ -1,134 +0,0 @@
|
|||||||
define(function(require, exports, module) {
|
|
||||||
var registers = require("../registers");
|
|
||||||
|
|
||||||
var dom = require("../../../lib/dom");
|
|
||||||
dom.importCssString('.insert-mode .ace_cursor{\
|
|
||||||
border-left: 2px solid #333333;\
|
|
||||||
}\
|
|
||||||
.ace_dark.insert-mode .ace_cursor{\
|
|
||||||
border-left: 2px solid #eeeeee;\
|
|
||||||
}\
|
|
||||||
.normal-mode .ace_cursor{\
|
|
||||||
border: 0!important;\
|
|
||||||
background-color: red;\
|
|
||||||
opacity: 0.5;\
|
|
||||||
}', 'vimMode');
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
onVisualMode: false,
|
|
||||||
onVisualLineMode: false,
|
|
||||||
currentMode: 'normal',
|
|
||||||
noMode: function(editor) {
|
|
||||||
editor.unsetStyle('insert-mode');
|
|
||||||
editor.unsetStyle('normal-mode');
|
|
||||||
if (editor.commands.recording)
|
|
||||||
editor.commands.toggleRecording(editor);
|
|
||||||
editor.setOverwrite(false);
|
|
||||||
},
|
|
||||||
insertMode: function(editor) {
|
|
||||||
this.currentMode = 'insert';
|
|
||||||
// Switch editor to insert mode
|
|
||||||
editor.setStyle('insert-mode');
|
|
||||||
editor.unsetStyle('normal-mode');
|
|
||||||
|
|
||||||
editor.setOverwrite(false);
|
|
||||||
editor.keyBinding.$data.buffer = "";
|
|
||||||
editor.keyBinding.$data.state = "insertMode";
|
|
||||||
this.onVisualMode = false;
|
|
||||||
this.onVisualLineMode = false;
|
|
||||||
if(this.onInsertReplaySequence) {
|
|
||||||
// Ok, we're apparently replaying ("."), so let's do it
|
|
||||||
editor.commands.macro = this.onInsertReplaySequence;
|
|
||||||
editor.commands.replay(editor);
|
|
||||||
this.onInsertReplaySequence = null;
|
|
||||||
this.normalMode(editor);
|
|
||||||
} else {
|
|
||||||
editor._emit("changeStatus");
|
|
||||||
// Record any movements, insertions in insert mode
|
|
||||||
if(!editor.commands.recording)
|
|
||||||
editor.commands.toggleRecording(editor);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
normalMode: function(editor) {
|
|
||||||
// Switch editor to normal mode
|
|
||||||
this.currentMode = 'normal';
|
|
||||||
|
|
||||||
editor.unsetStyle('insert-mode');
|
|
||||||
editor.setStyle('normal-mode');
|
|
||||||
editor.clearSelection();
|
|
||||||
|
|
||||||
var pos;
|
|
||||||
if (!editor.getOverwrite()) {
|
|
||||||
pos = editor.getCursorPosition();
|
|
||||||
if (pos.column > 0)
|
|
||||||
editor.navigateLeft();
|
|
||||||
}
|
|
||||||
|
|
||||||
editor.setOverwrite(true);
|
|
||||||
editor.keyBinding.$data.buffer = "";
|
|
||||||
editor.keyBinding.$data.state = "start";
|
|
||||||
this.onVisualMode = false;
|
|
||||||
this.onVisualLineMode = false;
|
|
||||||
editor._emit("changeStatus");
|
|
||||||
// Save recorded keystrokes
|
|
||||||
if (editor.commands.recording) {
|
|
||||||
editor.commands.toggleRecording(editor);
|
|
||||||
return editor.commands.macro;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
},
|
|
||||||
visualMode: function(editor, lineMode) {
|
|
||||||
if (
|
|
||||||
(this.onVisualLineMode && lineMode)
|
|
||||||
|| (this.onVisualMode && !lineMode)
|
|
||||||
) {
|
|
||||||
this.normalMode(editor);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
editor.setStyle('insert-mode');
|
|
||||||
editor.unsetStyle('normal-mode');
|
|
||||||
|
|
||||||
editor._emit("changeStatus");
|
|
||||||
if (lineMode) {
|
|
||||||
this.onVisualLineMode = true;
|
|
||||||
} else {
|
|
||||||
this.onVisualMode = true;
|
|
||||||
this.onVisualLineMode = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getRightNthChar: function(editor, cursor, ch, n) {
|
|
||||||
var line = editor.getSession().getLine(cursor.row);
|
|
||||||
var matches = line.substr(cursor.column + 1).split(ch);
|
|
||||||
|
|
||||||
return n < matches.length ? matches.slice(0, n).join(ch).length : null;
|
|
||||||
},
|
|
||||||
getLeftNthChar: function(editor, cursor, ch, n) {
|
|
||||||
var line = editor.getSession().getLine(cursor.row);
|
|
||||||
var matches = line.substr(0, cursor.column).split(ch);
|
|
||||||
|
|
||||||
return n < matches.length ? matches.slice(-1 * n).join(ch).length : null;
|
|
||||||
},
|
|
||||||
toRealChar: function(ch) {
|
|
||||||
if (ch.length === 1)
|
|
||||||
return ch;
|
|
||||||
|
|
||||||
if (/^shift-./.test(ch))
|
|
||||||
return ch[ch.length - 1].toUpperCase();
|
|
||||||
else
|
|
||||||
return "";
|
|
||||||
},
|
|
||||||
copyLine: function(editor) {
|
|
||||||
var pos = editor.getCursorPosition();
|
|
||||||
editor.selection.clearSelection();
|
|
||||||
editor.moveCursorTo(pos.row, pos.column);
|
|
||||||
editor.selection.selectLine();
|
|
||||||
registers._default.isLine = true;
|
|
||||||
registers._default.text = editor.getCopyText().replace(/\n$/, "");
|
|
||||||
editor.selection.clearSelection();
|
|
||||||
editor.moveCursorTo(pos.row, pos.column);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -32,11 +32,15 @@ define(function(require, exports, module) {
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var dom = require("../lib/dom");
|
var dom = require("../lib/dom");
|
||||||
|
var IE8;
|
||||||
|
|
||||||
var Cursor = function(parentEl) {
|
var Cursor = function(parentEl) {
|
||||||
this.element = dom.createElement("div");
|
this.element = dom.createElement("div");
|
||||||
this.element.className = "ace_layer ace_cursor-layer";
|
this.element.className = "ace_layer ace_cursor-layer";
|
||||||
parentEl.appendChild(this.element);
|
parentEl.appendChild(this.element);
|
||||||
|
|
||||||
|
if (IE8 === undefined)
|
||||||
|
IE8 = "opacity" in this.element;
|
||||||
|
|
||||||
this.isVisible = false;
|
this.isVisible = false;
|
||||||
this.isBlinking = true;
|
this.isBlinking = true;
|
||||||
@@ -46,9 +50,22 @@ var Cursor = function(parentEl) {
|
|||||||
this.cursors = [];
|
this.cursors = [];
|
||||||
this.cursor = this.addCursor();
|
this.cursor = this.addCursor();
|
||||||
dom.addCssClass(this.element, "ace_hidden-cursors");
|
dom.addCssClass(this.element, "ace_hidden-cursors");
|
||||||
|
this.$updateCursors = this.$updateVisibility.bind(this);
|
||||||
};
|
};
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
|
this.$updateVisibility = function(val) {
|
||||||
|
var cursors = this.cursors;
|
||||||
|
for (var i = cursors.length; i--; )
|
||||||
|
cursors[i].style.visibility = val ? "" : "hidden";
|
||||||
|
};
|
||||||
|
this.$updateOpacity = function(val) {
|
||||||
|
var cursors = this.cursors;
|
||||||
|
for (var i = cursors.length; i--; )
|
||||||
|
cursors[i].style.opacity = val ? "" : "0";
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
this.$padding = 0;
|
this.$padding = 0;
|
||||||
this.setPadding = function(padding) {
|
this.setPadding = function(padding) {
|
||||||
@@ -74,12 +91,13 @@ var Cursor = function(parentEl) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
this.setSmoothBlinking = function(smoothBlinking) {
|
this.setSmoothBlinking = function(smoothBlinking) {
|
||||||
if (smoothBlinking != this.smoothBlinking) {
|
if (smoothBlinking != this.smoothBlinking && !IE8) {
|
||||||
this.smoothBlinking = smoothBlinking;
|
this.smoothBlinking = smoothBlinking;
|
||||||
if (smoothBlinking)
|
dom.setCssClass(this.element, "ace_smooth-blinking", smoothBlinking);
|
||||||
dom.addCssClass(this.element, "ace_smooth-blinking");
|
this.$updateCursors(true);
|
||||||
else
|
this.$updateCursors = (smoothBlinking
|
||||||
dom.removeCssClass(this.element, "ace_smooth-blinking");
|
? this.$updateOpacity
|
||||||
|
: this.$updateVisibility).bind(this);
|
||||||
this.restartTimer();
|
this.restartTimer();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -113,35 +131,34 @@ var Cursor = function(parentEl) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
this.restartTimer = function() {
|
this.restartTimer = function() {
|
||||||
|
var update = this.$updateCursors;
|
||||||
clearInterval(this.intervalId);
|
clearInterval(this.intervalId);
|
||||||
clearTimeout(this.timeoutId);
|
clearTimeout(this.timeoutId);
|
||||||
if (this.smoothBlinking)
|
if (this.smoothBlinking) {
|
||||||
dom.removeCssClass(this.element, "ace_smooth-blinking");
|
dom.removeCssClass(this.element, "ace_smooth-blinking");
|
||||||
for (var i = this.cursors.length; i--; )
|
}
|
||||||
this.cursors[i].style.opacity = "";
|
|
||||||
|
update(true);
|
||||||
|
|
||||||
if (!this.isBlinking || !this.blinkInterval || !this.isVisible)
|
if (!this.isBlinking || !this.blinkInterval || !this.isVisible)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (this.smoothBlinking)
|
if (this.smoothBlinking) {
|
||||||
setTimeout(function(){
|
setTimeout(function(){
|
||||||
dom.addCssClass(this.element, "ace_smooth-blinking");
|
dom.addCssClass(this.element, "ace_smooth-blinking");
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
var blink = function(){
|
var blink = function(){
|
||||||
this.timeoutId = setTimeout(function() {
|
this.timeoutId = setTimeout(function() {
|
||||||
for (var i = this.cursors.length; i--; ) {
|
update(false);
|
||||||
this.cursors[i].style.opacity = 0;
|
}, 0.6 * this.blinkInterval);
|
||||||
}
|
|
||||||
}.bind(this), 0.6 * this.blinkInterval);
|
|
||||||
}.bind(this);
|
}.bind(this);
|
||||||
|
|
||||||
this.intervalId = setInterval(function() {
|
this.intervalId = setInterval(function() {
|
||||||
for (var i = this.cursors.length; i--; ) {
|
update(true);
|
||||||
this.cursors[i].style.opacity = "";
|
|
||||||
}
|
|
||||||
blink();
|
blink();
|
||||||
}.bind(this), this.blinkInterval);
|
}, this.blinkInterval);
|
||||||
|
|
||||||
blink();
|
blink();
|
||||||
};
|
};
|
||||||
@@ -170,19 +187,23 @@ var Cursor = function(parentEl) {
|
|||||||
selections = [{cursor: null}];
|
selections = [{cursor: null}];
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var i = selections.length; i--; ) {
|
for (var i = 0, n = selections.length; i < n; i++) {
|
||||||
var pixelPos = this.getPixelPosition(selections[i].cursor, true);
|
var pixelPos = this.getPixelPosition(selections[i].cursor, true);
|
||||||
if ((pixelPos.top > config.height + config.offset ||
|
if ((pixelPos.top > config.height + config.offset ||
|
||||||
pixelPos.top < -config.offset) && i > 1) {
|
pixelPos.top < 0) && i > 1) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var style = (this.cursors[cursorIndex++] || this.addCursor()).style;
|
var style = (this.cursors[cursorIndex++] || this.addCursor()).style;
|
||||||
|
|
||||||
style.left = pixelPos.left + "px";
|
if (!this.drawCursor) {
|
||||||
style.top = pixelPos.top + "px";
|
style.left = pixelPos.left + "px";
|
||||||
style.width = config.characterWidth + "px";
|
style.top = pixelPos.top + "px";
|
||||||
style.height = config.lineHeight + "px";
|
style.width = config.characterWidth + "px";
|
||||||
|
style.height = config.lineHeight + "px";
|
||||||
|
} else {
|
||||||
|
this.drawCursor(style, pixelPos, config, selections[i], this.session);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
while (this.cursors.length > cursorIndex)
|
while (this.cursors.length > cursorIndex)
|
||||||
this.removeCursor();
|
this.removeCursor();
|
||||||
@@ -194,6 +215,8 @@ var Cursor = function(parentEl) {
|
|||||||
this.$pixelPos = pixelPos;
|
this.$pixelPos = pixelPos;
|
||||||
this.restartTimer();
|
this.restartTimer();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.drawCursor = null;
|
||||||
|
|
||||||
this.$setOverwrite = function(overwrite) {
|
this.$setOverwrite = function(overwrite) {
|
||||||
if (overwrite != this.overwrite) {
|
if (overwrite != this.overwrite) {
|
||||||
|
|||||||
@@ -0,0 +1,176 @@
|
|||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Distributed under the BSD license:
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010, Ajax.org B.V.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of Ajax.org B.V. nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
define(function(require, exports, module) {
|
||||||
|
|
||||||
|
var oop = require("../lib/oop");
|
||||||
|
var dom = require("../lib/dom");
|
||||||
|
var lang = require("../lib/lang");
|
||||||
|
var useragent = require("../lib/useragent");
|
||||||
|
var EventEmitter = require("../lib/event_emitter").EventEmitter;
|
||||||
|
|
||||||
|
var CHAR_COUNT = 0;
|
||||||
|
|
||||||
|
var FontMetrics = exports.FontMetrics = function(parentEl, interval) {
|
||||||
|
this.el = dom.createElement("div");
|
||||||
|
this.$setMeasureNodeStyles(this.el.style, true);
|
||||||
|
|
||||||
|
this.$main = dom.createElement("div");
|
||||||
|
this.$setMeasureNodeStyles(this.$main.style);
|
||||||
|
|
||||||
|
this.$measureNode = dom.createElement("div");
|
||||||
|
this.$setMeasureNodeStyles(this.$measureNode.style);
|
||||||
|
|
||||||
|
|
||||||
|
this.el.appendChild(this.$main);
|
||||||
|
this.el.appendChild(this.$measureNode);
|
||||||
|
parentEl.appendChild(this.el);
|
||||||
|
|
||||||
|
if (!CHAR_COUNT)
|
||||||
|
this.$testFractionalRect();
|
||||||
|
this.$measureNode.innerHTML = lang.stringRepeat("X", CHAR_COUNT);
|
||||||
|
|
||||||
|
this.$characterSize = {width: 0, height: 0};
|
||||||
|
this.checkForSizeChanges();
|
||||||
|
};
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
|
||||||
|
oop.implement(this, EventEmitter);
|
||||||
|
|
||||||
|
this.$characterSize = {width: 0, height: 0};
|
||||||
|
|
||||||
|
this.$testFractionalRect = function() {
|
||||||
|
var el = dom.createElement("div");
|
||||||
|
this.$setMeasureNodeStyles(el.style);
|
||||||
|
el.style.width = "0.2px";
|
||||||
|
document.documentElement.appendChild(el);
|
||||||
|
var w = el.getBoundingClientRect().width;
|
||||||
|
if (w > 0 && w < 1)
|
||||||
|
CHAR_COUNT = 50;
|
||||||
|
else
|
||||||
|
CHAR_COUNT = 100;
|
||||||
|
el.parentNode.removeChild(el);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.$setMeasureNodeStyles = function(style, isRoot) {
|
||||||
|
style.width = style.height = "auto";
|
||||||
|
style.left = style.top = "0px";
|
||||||
|
style.visibility = "hidden";
|
||||||
|
style.position = "absolute";
|
||||||
|
style.whiteSpace = "pre";
|
||||||
|
|
||||||
|
if (useragent.isIE < 8) {
|
||||||
|
style["font-family"] = "inherit";
|
||||||
|
} else {
|
||||||
|
style.font = "inherit";
|
||||||
|
}
|
||||||
|
style.overflow = isRoot ? "hidden" : "visible";
|
||||||
|
};
|
||||||
|
|
||||||
|
this.checkForSizeChanges = function() {
|
||||||
|
var size = this.$measureSizes();
|
||||||
|
if (size && (this.$characterSize.width !== size.width || this.$characterSize.height !== size.height)) {
|
||||||
|
this.$measureNode.style.fontWeight = "bold";
|
||||||
|
var boldSize = this.$measureSizes();
|
||||||
|
this.$measureNode.style.fontWeight = "";
|
||||||
|
this.$characterSize = size;
|
||||||
|
this.charSizes = Object.create(null);
|
||||||
|
this.allowBoldFonts = boldSize && boldSize.width === size.width && boldSize.height === size.height;
|
||||||
|
this._emit("changeCharacterSize", {data: size});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.$pollSizeChanges = function() {
|
||||||
|
if (this.$pollSizeChangesTimer)
|
||||||
|
return this.$pollSizeChangesTimer;
|
||||||
|
var self = this;
|
||||||
|
return this.$pollSizeChangesTimer = setInterval(function() {
|
||||||
|
self.checkForSizeChanges();
|
||||||
|
}, 500);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.setPolling = function(val) {
|
||||||
|
if (val) {
|
||||||
|
this.$pollSizeChanges();
|
||||||
|
} else {
|
||||||
|
if (this.$pollSizeChangesTimer)
|
||||||
|
this.$pollSizeChangesTimer;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.$measureSizes = function() {
|
||||||
|
if (CHAR_COUNT === 50) {
|
||||||
|
var rect = null;
|
||||||
|
try {
|
||||||
|
rect = this.$measureNode.getBoundingClientRect();
|
||||||
|
} catch(e) {
|
||||||
|
rect = {width: 0, height:0 };
|
||||||
|
};
|
||||||
|
var size = {
|
||||||
|
height: rect.height,
|
||||||
|
width: rect.width / CHAR_COUNT
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
var size = {
|
||||||
|
height: this.$measureNode.clientHeight,
|
||||||
|
width: this.$measureNode.clientWidth / CHAR_COUNT
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// Size and width can be null if the editor is not visible or
|
||||||
|
// detached from the document
|
||||||
|
if (size.width === 0 || size.height === 0)
|
||||||
|
return null;
|
||||||
|
return size;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.$measureCharWidth = function(ch) {
|
||||||
|
this.$main.innerHTML = lang.stringRepeat(ch, CHAR_COUNT);
|
||||||
|
var rect = this.$main.getBoundingClientRect();
|
||||||
|
return rect.width / CHAR_COUNT;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.getCharacterWidth = function(ch) {
|
||||||
|
var w = this.charSizes[ch];
|
||||||
|
if (w === undefined) {
|
||||||
|
this.charSizes[ch] = this.$measureCharWidth(ch) / this.$characterSize.width;
|
||||||
|
}
|
||||||
|
return w;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.destroy = function() {
|
||||||
|
clearInterval(this.$pollSizeChangesTimer);
|
||||||
|
if (this.el && this.el.parentNode)
|
||||||
|
this.el.parentNode.removeChild(this.el);
|
||||||
|
};
|
||||||
|
|
||||||
|
}).call(FontMetrics.prototype);
|
||||||
|
|
||||||
|
});
|
||||||
@@ -46,6 +46,8 @@ var Gutter = function(parentEl) {
|
|||||||
|
|
||||||
this.$annotations = [];
|
this.$annotations = [];
|
||||||
this.$updateAnnotations = this.$updateAnnotations.bind(this);
|
this.$updateAnnotations = this.$updateAnnotations.bind(this);
|
||||||
|
|
||||||
|
this.$cells = [];
|
||||||
};
|
};
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
@@ -56,7 +58,8 @@ var Gutter = function(parentEl) {
|
|||||||
if (this.session)
|
if (this.session)
|
||||||
this.session.removeEventListener("change", this.$updateAnnotations);
|
this.session.removeEventListener("change", this.$updateAnnotations);
|
||||||
this.session = session;
|
this.session = session;
|
||||||
session.on("change", this.$updateAnnotations);
|
if (session)
|
||||||
|
session.on("change", this.$updateAnnotations);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.addGutterDecoration = function(row, className){
|
this.addGutterDecoration = function(row, className){
|
||||||
@@ -73,8 +76,7 @@ var Gutter = function(parentEl) {
|
|||||||
|
|
||||||
this.setAnnotations = function(annotations) {
|
this.setAnnotations = function(annotations) {
|
||||||
// iterate over sparse array
|
// iterate over sparse array
|
||||||
this.$annotations = []
|
this.$annotations = [];
|
||||||
var rowInfo, row;
|
|
||||||
for (var i = 0; i < annotations.length; i++) {
|
for (var i = 0; i < annotations.length; i++) {
|
||||||
var annotation = annotations[i];
|
var annotation = annotations[i];
|
||||||
var row = annotation.row;
|
var row = annotation.row;
|
||||||
@@ -110,76 +112,140 @@ var Gutter = function(parentEl) {
|
|||||||
} else if (delta.action == "removeText" || delta.action == "removeLines") {
|
} else if (delta.action == "removeText" || delta.action == "removeLines") {
|
||||||
this.$annotations.splice(firstRow, len + 1, null);
|
this.$annotations.splice(firstRow, len + 1, null);
|
||||||
} else {
|
} else {
|
||||||
var args = Array(len + 1);
|
var args = new Array(len + 1);
|
||||||
args.unshift(firstRow, 1);
|
args.unshift(firstRow, 1);
|
||||||
this.$annotations.splice.apply(this.$annotations, args);
|
this.$annotations.splice.apply(this.$annotations, args);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.update = function(config) {
|
this.update = function(config) {
|
||||||
var emptyAnno = {className: ""};
|
var session = this.session;
|
||||||
var html = [];
|
var firstRow = config.firstRow;
|
||||||
var i = config.firstRow;
|
var lastRow = Math.min(config.lastRow + config.gutterOffset, // needed to compensate for hor scollbar
|
||||||
var lastRow = config.lastRow;
|
session.getLength() - 1);
|
||||||
var fold = this.session.getNextFoldLine(i);
|
var fold = session.getNextFoldLine(firstRow);
|
||||||
var foldStart = fold ? fold.start.row : Infinity;
|
var foldStart = fold ? fold.start.row : Infinity;
|
||||||
var foldWidgets = this.$showFoldWidgets && this.session.foldWidgets;
|
var foldWidgets = this.$showFoldWidgets && session.foldWidgets;
|
||||||
var breakpoints = this.session.$breakpoints;
|
var breakpoints = session.$breakpoints;
|
||||||
var decorations = this.session.$decorations;
|
var decorations = session.$decorations;
|
||||||
|
var firstLineNumber = session.$firstLineNumber;
|
||||||
var lastLineNumber = 0;
|
var lastLineNumber = 0;
|
||||||
|
|
||||||
|
var gutterRenderer = session.gutterRenderer || this.$renderer;
|
||||||
|
|
||||||
|
var cell = null;
|
||||||
|
var index = -1;
|
||||||
|
var row = firstRow;
|
||||||
while (true) {
|
while (true) {
|
||||||
if(i > foldStart) {
|
if (row > foldStart) {
|
||||||
i = fold.end.row + 1;
|
row = fold.end.row + 1;
|
||||||
fold = this.session.getNextFoldLine(i, fold);
|
fold = session.getNextFoldLine(row, fold);
|
||||||
foldStart = fold ?fold.start.row :Infinity;
|
foldStart = fold ? fold.start.row : Infinity;
|
||||||
}
|
}
|
||||||
if(i > lastRow)
|
if (row > lastRow) {
|
||||||
|
while (this.$cells.length > index + 1) {
|
||||||
|
cell = this.$cells.pop();
|
||||||
|
this.element.removeChild(cell.element);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
var annotation = this.$annotations[i] || emptyAnno;
|
cell = this.$cells[++index];
|
||||||
html.push(
|
if (!cell) {
|
||||||
"<div class='ace_gutter-cell ",
|
cell = {element: null, textNode: null, foldWidget: null};
|
||||||
breakpoints[i] || "", decorations[i] || "", annotation.className,
|
cell.element = dom.createElement("div");
|
||||||
"' style='height:", this.session.getRowLength(i) * config.lineHeight, "px;'>",
|
cell.textNode = document.createTextNode('');
|
||||||
lastLineNumber = i + 1
|
cell.element.appendChild(cell.textNode);
|
||||||
);
|
this.element.appendChild(cell.element);
|
||||||
|
this.$cells[index] = cell;
|
||||||
|
}
|
||||||
|
|
||||||
|
var className = "ace_gutter-cell ";
|
||||||
|
if (breakpoints[row])
|
||||||
|
className += breakpoints[row];
|
||||||
|
if (decorations[row])
|
||||||
|
className += decorations[row];
|
||||||
|
if (this.$annotations[row])
|
||||||
|
className += this.$annotations[row].className;
|
||||||
|
if (cell.element.className != className)
|
||||||
|
cell.element.className = className;
|
||||||
|
|
||||||
|
var height = session.getRowLength(row) * config.lineHeight + "px";
|
||||||
|
if (height != cell.element.style.height)
|
||||||
|
cell.element.style.height = height;
|
||||||
|
|
||||||
if (foldWidgets) {
|
if (foldWidgets) {
|
||||||
var c = foldWidgets[i];
|
var c = foldWidgets[row];
|
||||||
// check if cached value is invalidated and we need to recompute
|
// check if cached value is invalidated and we need to recompute
|
||||||
if (c == null)
|
if (c == null)
|
||||||
c = foldWidgets[i] = this.session.getFoldWidget(i);
|
c = foldWidgets[row] = session.getFoldWidget(row);
|
||||||
if (c)
|
|
||||||
html.push(
|
|
||||||
"<span class='ace_fold-widget ace_", c,
|
|
||||||
c == "start" && i == foldStart && i < fold.end.row ? " ace_closed" : " ace_open",
|
|
||||||
"' style='height:", config.lineHeight, "px",
|
|
||||||
"'></span>"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
html.push("</div>");
|
if (c) {
|
||||||
|
if (!cell.foldWidget) {
|
||||||
|
cell.foldWidget = dom.createElement("span");
|
||||||
|
cell.element.appendChild(cell.foldWidget);
|
||||||
|
}
|
||||||
|
var className = "ace_fold-widget ace_" + c;
|
||||||
|
if (c == "start" && row == foldStart && row < fold.end.row)
|
||||||
|
className += " ace_closed";
|
||||||
|
else
|
||||||
|
className += " ace_open";
|
||||||
|
if (cell.foldWidget.className != className)
|
||||||
|
cell.foldWidget.className = className;
|
||||||
|
|
||||||
i++;
|
var height = config.lineHeight + "px";
|
||||||
|
if (cell.foldWidget.style.height != height)
|
||||||
|
cell.foldWidget.style.height = height;
|
||||||
|
} else {
|
||||||
|
if (cell.foldWidget) {
|
||||||
|
cell.element.removeChild(cell.foldWidget);
|
||||||
|
cell.foldWidget = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var text = lastLineNumber = gutterRenderer
|
||||||
|
? gutterRenderer.getText(session, row)
|
||||||
|
: row + firstLineNumber;
|
||||||
|
if (text != cell.textNode.data)
|
||||||
|
cell.textNode.data = text;
|
||||||
|
|
||||||
|
row++;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.element = dom.setInnerHtml(this.element, html.join(""));
|
|
||||||
this.element.style.height = config.minHeight + "px";
|
this.element.style.height = config.minHeight + "px";
|
||||||
|
|
||||||
|
if (this.$fixedWidth || session.$useWrapMode)
|
||||||
|
lastLineNumber = session.getLength() + firstLineNumber;
|
||||||
|
|
||||||
|
var gutterWidth = gutterRenderer
|
||||||
|
? gutterRenderer.getWidth(session, lastLineNumber, config)
|
||||||
|
: lastLineNumber.toString().length * config.characterWidth;
|
||||||
|
|
||||||
if (this.session.$useWrapMode)
|
|
||||||
lastLineNumber = this.session.getLength();
|
|
||||||
|
|
||||||
var gutterWidth = ("" + lastLineNumber).length * config.characterWidth;
|
|
||||||
var padding = this.$padding || this.$computePadding();
|
var padding = this.$padding || this.$computePadding();
|
||||||
gutterWidth += padding.left + padding.right;
|
gutterWidth += padding.left + padding.right;
|
||||||
if (gutterWidth !== this.gutterWidth) {
|
if (gutterWidth !== this.gutterWidth && !isNaN(gutterWidth)) {
|
||||||
this.gutterWidth = gutterWidth;
|
this.gutterWidth = gutterWidth;
|
||||||
this.element.style.width = Math.ceil(this.gutterWidth) + "px";
|
this.element.style.width = Math.ceil(this.gutterWidth) + "px";
|
||||||
this._emit("changeGutterWidth", gutterWidth);
|
this._emit("changeGutterWidth", gutterWidth);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.$fixedWidth = false;
|
||||||
|
|
||||||
|
this.$showLineNumbers = true;
|
||||||
|
this.$renderer = "";
|
||||||
|
this.setShowLineNumbers = function(show) {
|
||||||
|
this.$renderer = !show && {
|
||||||
|
getWidth: function() {return ""},
|
||||||
|
getText: function() {return ""}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
this.getShowLineNumbers = function() {
|
||||||
|
return this.$showLineNumbers;
|
||||||
|
};
|
||||||
|
|
||||||
this.$showFoldWidgets = true;
|
this.$showFoldWidgets = true;
|
||||||
this.setShowFoldWidgets = function(show) {
|
this.setShowFoldWidgets = function(show) {
|
||||||
if (show)
|
if (show)
|
||||||
@@ -199,9 +265,9 @@ var Gutter = function(parentEl) {
|
|||||||
if (!this.element.firstChild)
|
if (!this.element.firstChild)
|
||||||
return {left: 0, right: 0};
|
return {left: 0, right: 0};
|
||||||
var style = dom.computedStyle(this.element.firstChild);
|
var style = dom.computedStyle(this.element.firstChild);
|
||||||
this.$padding = {}
|
this.$padding = {};
|
||||||
this.$padding.left = parseInt(style.paddingLeft) + 1;
|
this.$padding.left = parseInt(style.paddingLeft) + 1 || 0;
|
||||||
this.$padding.right = parseInt(style.paddingRight);
|
this.$padding.right = parseInt(style.paddingRight) || 0;
|
||||||
return this.$padding;
|
return this.$padding;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -82,6 +82,8 @@ var Marker = function(parentEl) {
|
|||||||
marker.renderer(html, range, left, top, config);
|
marker.renderer(html, range, left, top, config);
|
||||||
} else if (marker.type == "fullLine") {
|
} else if (marker.type == "fullLine") {
|
||||||
this.drawFullLineMarker(html, range, marker.clazz, config);
|
this.drawFullLineMarker(html, range, marker.clazz, config);
|
||||||
|
} else if (marker.type == "screenLine") {
|
||||||
|
this.drawScreenLineMarker(html, range, marker.clazz, config);
|
||||||
} else if (range.isMultiLine()) {
|
} else if (range.isMultiLine()) {
|
||||||
if (marker.type == "text")
|
if (marker.type == "text")
|
||||||
this.drawTextMarker(html, range, marker.clazz, config);
|
this.drawTextMarker(html, range, marker.clazz, config);
|
||||||
@@ -91,7 +93,7 @@ var Marker = function(parentEl) {
|
|||||||
this.drawSingleLineMarker(html, range, marker.clazz + " ace_start", config);
|
this.drawSingleLineMarker(html, range, marker.clazz + " ace_start", config);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.element = dom.setInnerHtml(this.element, html.join(""));
|
this.element.innerHTML = html.join("");
|
||||||
};
|
};
|
||||||
|
|
||||||
this.$getTop = function(row, layerConfig) {
|
this.$getTop = function(row, layerConfig) {
|
||||||
@@ -99,7 +101,7 @@ var Marker = function(parentEl) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Draws a marker, which spans a range of text on multiple lines
|
// Draws a marker, which spans a range of text on multiple lines
|
||||||
this.drawTextMarker = function(stringBuilder, range, clazz, layerConfig) {
|
this.drawTextMarker = function(stringBuilder, range, clazz, layerConfig, extraStyle) {
|
||||||
// selection start
|
// selection start
|
||||||
var row = range.start.row;
|
var row = range.start.row;
|
||||||
|
|
||||||
@@ -107,35 +109,36 @@ var Marker = function(parentEl) {
|
|||||||
row, range.start.column,
|
row, range.start.column,
|
||||||
row, this.session.getScreenLastRowColumn(row)
|
row, this.session.getScreenLastRowColumn(row)
|
||||||
);
|
);
|
||||||
this.drawSingleLineMarker(stringBuilder, lineRange, clazz + " ace_start", layerConfig, 1, "text");
|
this.drawSingleLineMarker(stringBuilder, lineRange, clazz + " ace_start", layerConfig, 1, extraStyle);
|
||||||
|
|
||||||
// selection end
|
// selection end
|
||||||
row = range.end.row;
|
row = range.end.row;
|
||||||
lineRange = new Range(row, 0, row, range.end.column);
|
lineRange = new Range(row, 0, row, range.end.column);
|
||||||
this.drawSingleLineMarker(stringBuilder, lineRange, clazz, layerConfig, 0, "text");
|
this.drawSingleLineMarker(stringBuilder, lineRange, clazz, layerConfig, 0, extraStyle);
|
||||||
|
|
||||||
for (row = range.start.row + 1; row < range.end.row; row++) {
|
for (row = range.start.row + 1; row < range.end.row; row++) {
|
||||||
lineRange.start.row = row;
|
lineRange.start.row = row;
|
||||||
lineRange.end.row = row;
|
lineRange.end.row = row;
|
||||||
lineRange.end.column = this.session.getScreenLastRowColumn(row);
|
lineRange.end.column = this.session.getScreenLastRowColumn(row);
|
||||||
this.drawSingleLineMarker(stringBuilder, lineRange, clazz, layerConfig, 1, "text");
|
this.drawSingleLineMarker(stringBuilder, lineRange, clazz, layerConfig, 1, extraStyle);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Draws a multi line marker, where lines span the full width
|
// Draws a multi line marker, where lines span the full width
|
||||||
this.drawMultiLineMarker = function(stringBuilder, range, clazz, config, type) {
|
this.drawMultiLineMarker = function(stringBuilder, range, clazz, config, extraStyle) {
|
||||||
// from selection start to the end of the line
|
// from selection start to the end of the line
|
||||||
var padding = this.$padding;
|
var padding = this.$padding;
|
||||||
var height = config.lineHeight;
|
var height = config.lineHeight;
|
||||||
var top = this.$getTop(range.start.row, config);
|
var top = this.$getTop(range.start.row, config);
|
||||||
var left = padding + range.start.column * config.characterWidth;
|
var left = padding + range.start.column * config.characterWidth;
|
||||||
|
extraStyle = extraStyle || "";
|
||||||
|
|
||||||
stringBuilder.push(
|
stringBuilder.push(
|
||||||
"<div class='", clazz, " ace_start' style='",
|
"<div class='", clazz, " ace_start' style='",
|
||||||
"height:", height, "px;",
|
"height:", height, "px;",
|
||||||
"right:0;",
|
"right:0;",
|
||||||
"top:", top, "px;",
|
"top:", top, "px;",
|
||||||
"left:", left, "px;'></div>"
|
"left:", left, "px;", extraStyle, "'></div>"
|
||||||
);
|
);
|
||||||
|
|
||||||
// from start of the last line to the selection end
|
// from start of the last line to the selection end
|
||||||
@@ -147,7 +150,7 @@ var Marker = function(parentEl) {
|
|||||||
"height:", height, "px;",
|
"height:", height, "px;",
|
||||||
"width:", width, "px;",
|
"width:", width, "px;",
|
||||||
"top:", top, "px;",
|
"top:", top, "px;",
|
||||||
"left:", padding, "px;'></div>"
|
"left:", padding, "px;", extraStyle, "'></div>"
|
||||||
);
|
);
|
||||||
|
|
||||||
// all the complete lines
|
// all the complete lines
|
||||||
@@ -161,12 +164,12 @@ var Marker = function(parentEl) {
|
|||||||
"height:", height, "px;",
|
"height:", height, "px;",
|
||||||
"right:0;",
|
"right:0;",
|
||||||
"top:", top, "px;",
|
"top:", top, "px;",
|
||||||
"left:", padding, "px;'></div>"
|
"left:", padding, "px;", extraStyle, "'></div>"
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Draws a marker which covers part or whole width of a single screen line
|
// Draws a marker which covers part or whole width of a single screen line
|
||||||
this.drawSingleLineMarker = function(stringBuilder, range, clazz, config, extraLength) {
|
this.drawSingleLineMarker = function(stringBuilder, range, clazz, config, extraLength, extraStyle) {
|
||||||
var height = config.lineHeight;
|
var height = config.lineHeight;
|
||||||
var width = (range.end.column + (extraLength || 0) - range.start.column) * config.characterWidth;
|
var width = (range.end.column + (extraLength || 0) - range.start.column) * config.characterWidth;
|
||||||
|
|
||||||
@@ -178,11 +181,11 @@ var Marker = function(parentEl) {
|
|||||||
"height:", height, "px;",
|
"height:", height, "px;",
|
||||||
"width:", width, "px;",
|
"width:", width, "px;",
|
||||||
"top:", top, "px;",
|
"top:", top, "px;",
|
||||||
"left:", left,"px;'></div>"
|
"left:", left, "px;", extraStyle || "", "'></div>"
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.drawFullLineMarker = function(stringBuilder, range, clazz, config) {
|
this.drawFullLineMarker = function(stringBuilder, range, clazz, config, extraStyle) {
|
||||||
var top = this.$getTop(range.start.row, config);
|
var top = this.$getTop(range.start.row, config);
|
||||||
var height = config.lineHeight;
|
var height = config.lineHeight;
|
||||||
if (range.start.row != range.end.row)
|
if (range.start.row != range.end.row)
|
||||||
@@ -192,9 +195,21 @@ var Marker = function(parentEl) {
|
|||||||
"<div class='", clazz, "' style='",
|
"<div class='", clazz, "' style='",
|
||||||
"height:", height, "px;",
|
"height:", height, "px;",
|
||||||
"top:", top, "px;",
|
"top:", top, "px;",
|
||||||
"left:0;right:0;'></div>"
|
"left:0;right:0;", extraStyle || "", "'></div>"
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
|
this.drawScreenLineMarker = function(stringBuilder, range, clazz, config, extraStyle) {
|
||||||
|
var top = this.$getTop(range.start.row, config);
|
||||||
|
var height = config.lineHeight;
|
||||||
|
|
||||||
|
stringBuilder.push(
|
||||||
|
"<div class='", clazz, "' style='",
|
||||||
|
"height:", height, "px;",
|
||||||
|
"top:", top, "px;",
|
||||||
|
"left:0;right:0;", extraStyle || "", "'></div>"
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
}).call(Marker.prototype);
|
}).call(Marker.prototype);
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user