Compare commits

...
Sign in to create a new pull request.

421 commits

Author SHA1 Message Date
Joey Payne
ca8da0a3f3 Merge remote-tracking branch 'upstream/master' 2015-06-04 14:23:14 -06:00
Lennart Kats
f10da4cdb0 Merge pull request #2523 from ajaxorg/fix/various
Fix several small issues
2015-06-01 17:59:08 +02:00
Lennart Kats
d953740339 Merge pull request #2507 from ajaxorg/c9
Sync with cloud9
2015-06-01 17:39:25 +02:00
nightwing
6cec0b28b2 improve tmlanguage importer 2015-06-01 13:50:32 +04:00
nightwing
3f31ca57ed fix typo 2015-06-01 01:06:39 +04:00
Joey Payne
fb7144b622 Merge remote-tracking branch 'upstream/master' 2015-05-31 11:49:42 -06:00
nightwing
2249d06337 fix #2484 Hard-coded characterWidth in static_highlight.js
and remove dependence on mockdom
2015-05-31 17:42:00 +04:00
nightwing
1514d5f374 fix #2483 Exception on ctrl-alt-shift-click when $enableJumpToDef is true 2015-05-31 17:42:00 +04:00
nightwing
446e3e1bf9 fix #2522 Popup position is off when gutter isn't shown 2015-05-31 17:42:00 +04:00
Harutyun Amirjanyan
652dd7009c Merge pull request #2516 from ajaxorg/fix/highlighter
fix highlighting of tables in Gherkin  mode
2015-05-31 16:45:58 +04:00
Harutyun Amirjanyan
3d23e1e98f Merge pull request #2518 from ajaxorg/autocompleter
fix autocomplete blur handler
2015-05-31 16:45:36 +04:00
Harutyun Amirjanyan
cafc7e7ce1 Merge pull request #2521 from puffnfresh/patch-1
Fix invalid syntax in autoresize.html
2015-05-31 16:45:13 +04:00
Brian McKenna
abdc4c7510 Fix invalid syntax in autoresize.html
The options literal had a duplicate key.
2015-05-29 09:55:02 -06:00
nightwing
8c1d0ab7cf fix autocomplete blur handler 2015-05-28 13:56:33 +04:00
nightwing
9f57989043 fix highlighting of tables in Gherkin mode 2015-05-28 13:40:56 +04:00
nightwing
2a089863e2 fix highlighting of line-height:1.5 in less mode 2015-05-22 22:14:29 +04:00
nightwing
386c508042 convert paste into command 2015-05-22 22:14:15 +04:00
nightwing
dc7643db8d better invisible tabs (fixes #2109) 2015-05-22 21:57:13 +04:00
nightwing
5705a7c2c1 fix toggle comments in handlebars mode 2015-05-22 02:34:43 +04:00
nightwing
2e2d9bcdc9 add more php extensions 2015-05-22 02:34:43 +04:00
nightwing
a799a4086f fix quote pairing for "\n" 2015-05-22 02:34:43 +04:00
nightwing
af5c7a9c3b improve require support in worker 2015-05-22 02:34:30 +04:00
nightwing
fe96eef206 fix require for paths ending with .js in the worker 2015-05-21 23:01:27 +04:00
Lennart Kats
0a3b002e28 Merge pull request #1819 from ajaxorg/v-1.2
Refactor document delta handling for v1.2
2015-05-21 11:15:29 +02:00
nightwing
60439d927f update changelog 2015-05-21 13:01:17 +04:00
Lennart Kats
95bb17d04b Merge pull request #2496 from ajaxorg/fix/renderer
fix renderer issues with autosize
2015-05-21 10:57:04 +02:00
Lennart Kats
2c1b565591 Merge pull request #2500 from ajaxorg/fix/tokenizer
fix highlighting stopping randomly in the middle of the file
2015-05-21 10:53:05 +02:00
Harutyun Amirjanyan
53ea1a8665 Merge pull request #2502 from Pike/patch-1
Add array-of-tables to keygroup markup for toml files.
2015-05-20 22:30:19 +04:00
Axel Hecht
9534e4ea92 Add array-of-tables to keygroup markup
The markup for array-of-tables at https://github.com/toml-lang/toml#array-of-tables is
[[ foo ]]

Right now, the last ] isn't part of the markup. Figured making this an explicit token is the most apparent way to fix this.
2015-05-20 14:53:02 +02:00
nightwing
fa86327b3d fix highlighting stopping randomly in the middle of the file 2015-05-19 17:43:10 +04:00
Joey Payne
a68e8bea01 Merging latest commits.
Merge remote-tracking branch 'upstream/master'
2015-05-16 16:02:51 -06:00
nightwing
88d8cf3447 fix renderer test 2015-05-15 02:48:12 +04:00
nightwing
9e9aa8f328 use scroller as mousetarget to not miss mouse events on scrollmargin 2015-05-15 02:44:24 +04:00
nightwing
93c39ca5b0 handle hscrollbar change during autoresize 2015-05-15 02:43:41 +04:00
nightwing
0db985a3d7 fix #2495 editor freezes when setting scrollmargin and maxLines together 2015-05-15 01:53:19 +04:00
Ruben Daniels
ad5802be06 Merge pull request #2488 from ajaxorg/rounded-corners
Add rounded corners for selections
2015-05-10 19:07:21 -07:00
nightwing
0abd9ec30e rounded corners for selections 2015-05-10 14:01:28 +04:00
Harutyun Amirjanyan
6d205a8f7e Merge pull request #2470 from ajaxorg/fix/leak
Fix memory leak
2015-05-07 01:28:22 +04:00
Harutyun Amirjanyan
d2dc26f5a5 Merge pull request #2479 from bcjordan/patch-4
Update comment, add missing semicolon [ci skip]
2015-05-07 01:27:42 +04:00
Brian Jordan
ef4537a099 Update edit_session.js
Fix extra `the`
2015-05-05 09:07:46 -07:00
Harutyun Amirjanyan
46f76b4b06 Merge pull request #2473 from Leushenko/master
Add indentation for Scheme
2015-05-05 16:31:02 +04:00
Harutyun Amirjanyan
71d1ca9d20 Merge pull request #2476 from bcjordan/patch-2
Remove unused variable `EditSession`
2015-05-05 16:26:41 +04:00
Harutyun Amirjanyan
263a45db02 Merge pull request #2477 from bcjordan/patch-3
Remove unused parameter `mutateData` & add ;s
2015-05-05 16:26:28 +04:00
Joey Payne
9323a2616b Added support for nim programming language. 2015-05-04 22:54:09 -06:00
Brian Jordan
ad22b71cfe Update comment, add missing semicolon [ci skip] 2015-05-01 10:56:08 -07:00
Brian Jordan
cd8099b0ad Remove unused parameter mutateData & add ;s 2015-04-30 17:38:19 -07:00
Brian Jordan
a61d304cbb Remove unused variable EditSession 2015-04-30 17:14:16 -07:00
Alex Gilding
e72f1d8337 Add indentation for Scheme
Just copied over the Clojure indentation rules to Scheme and changed
the keywords to suit the language, so that Scheme programs can be
automatically indented too
2015-04-28 20:24:13 +01:00
nightwing
d080fe51d4 fix #2468 error in strict mode 2015-04-28 19:01:24 +04:00
Harutyun Amirjanyan
32cb8c6b0e Merge pull request #2472 from ph1ll/master
Expose ClipboardEvent in editor paste event
2015-04-28 00:51:58 +04:00
Phill Campbell
3ce8d76c89 Expose ClipboardEvent in editor paste event 2015-04-27 18:49:12 +01:00
nightwing
a842dcdee3 do not retain ref to the first editor (fixes #2469) 2015-04-26 14:44:47 +04:00
Ruben Daniels
0dcb1281cd Merge pull request #2459 from ajaxorg/c9
Sync with c9
2015-04-25 12:30:37 -07:00
Harutyun Amirjanyan
65ad04082f Merge pull request #2460 from sevin7676/master
SQL Server typos and keyword completion modifier
2015-04-23 18:11:41 +04:00
Lennart Kats
b6f7e5d6a1 Merge pull request #2461 from ajaxorg/highlighter
Fix highlighter issues
2015-04-23 07:38:28 +02:00
sevin7676
5a3bf2570f no keyword if in brackets 2015-04-22 06:06:52 -04:00
sevin7676
2d7ebc34b6 no keyword if in brackets 2015-04-22 06:05:54 -04:00
sevin7676
87044e8816 forgot keyword completions 2015-04-22 05:38:01 -04:00
sevin7676
82453d884b better completions, no unneeded string rule 2015-04-22 05:28:31 -04:00
nightwing
636ace5178 fix typo 2015-04-22 13:20:39 +04:00
Harutyun Amirjanyan
3673aabe2a Merge pull request #2465 from bcjordan/patch-1
Remove unused variable `text`
2015-04-22 11:25:22 +04:00
Brian Jordan
694d7431b7 Remove unused variable text 2015-04-21 14:58:29 -07:00
nightwing
89b9a8ac72 address review comments 2015-04-20 18:25:32 +04:00
sevin7676
67c7da75b6 fix escape character
was using wrong escape char for string, sqlserver uses double single
quote to escape a single quote
2015-04-20 08:52:03 -04:00
sevin7676
662cd11975 no cache as its storing reference in filtered list 2015-04-20 05:08:54 -04:00
sevin7676
68d531ecb2 cleanup 2015-04-20 04:52:18 -04:00
sevin7676
e58fa3e6d7 remove completionModifer, one off for SQL Server Mode 2015-04-20 04:50:25 -04:00
nightwing
e610365e67 fix #2432 setPolling(false) doesn't turn off polling 2015-04-20 01:11:10 +04:00
nightwing
65b2cf2855 update test for rust mode 2015-04-19 20:35:57 +04:00
nightwing
2008ab813f fix bracket matching in modes imported from textmate 2015-04-19 20:29:28 +04:00
nightwing
ecb699aa11 support converting from cson 2015-04-19 20:28:12 +04:00
nightwing
63687f693b fix #2441 function highlighting in rust mode 2015-04-19 20:27:07 +04:00
nightwing
685ba18451 fix #2452 . is a valid XML tagname character 2015-04-19 20:05:25 +04:00
sevin7676
1ec6eb7b5d shorter names 2015-04-19 11:59:31 -04:00
sevin7676
1027dcea7c cache modifier 2015-04-19 11:52:54 -04:00
sevin7676
961f8c4893 completion modifier for SQL and JavaScript 2015-04-19 11:24:30 -04:00
sevin7676
27284cd29f added completionModifier
allows a highlight rule modify keyword completions
2015-04-19 11:23:10 -04:00
nightwing
04f4292fbc enable Emmet for handlebars mode 2015-04-19 17:34:22 +04:00
nightwing
4e6d48bf2e make sure operationEnd events are not emitted to wrong session 2015-04-19 17:34:22 +04:00
nightwing
80f43beb73 fix typo 2015-04-19 17:34:04 +04:00
sevin7676
cf0c81a25f more snippets 2015-04-19 08:37:22 -04:00
sevin7676
ee90854917 bug fix & typo fix 2015-04-19 08:18:04 -04:00
nightwing
ff4429dd5a fixes for emacs mode 2015-04-19 15:50:22 +04:00
nightwing
487408e84d fix +6291 Hard to tell what pane has focus in Vim mode 2015-04-19 15:50:06 +04:00
nightwing
2713d0a8db center cursor after vim jumplist motions
Conflicts:
	lib/ace/editor.js
2015-04-19 15:49:41 +04:00
nightwing
b0ce5630c9 add support for bindkey.position 2015-04-19 15:48:58 +04:00
Harutyun Amirjanyan
d89311e596 Merge pull request #2456 from kevinushey/bugfix/vim-normal-mode-yank
[vim] define 'Y' as 'keyToKey' mapping (fixes #2455)
2015-04-19 02:26:47 +04:00
Kevin Ushey
5482db1c4d [vim] fix 'Y' behaviour in visual mode 2015-04-18 15:19:28 -07:00
nightwing
eb70d5a6c8 Merge remote-tracking branch 'remotes/origin/master'
Conflicts:
	lib/ace/document.js
2015-04-19 01:04:25 +04:00
Harutyun Amirjanyan
abe0286420 Merge pull request #2458 from ajaxorg/vim
update vim mode
2015-04-18 22:00:47 +04:00
nightwing
094b8a147a update vim mode 2015-04-18 21:01:11 +04:00
Harutyun Amirjanyan
f0d01b93d4 Merge pull request #2457 from sevin7676/master
Add SQL Server (Microsoft SQL) Mode
2015-04-18 19:56:27 +04:00
nightwing
ef9cc542e7 fixes for indentedSoftWrap option 2015-04-18 19:53:49 +04:00
sevin7676
73808101cd cleanup 2015-04-18 10:06:55 -04:00
nightwing
0753f9aa12 Merge remote-tracking branch 'remotes/pull/2187' 2015-04-18 18:00:14 +04:00
Harutyun Amirjanyan
f270b4ae69 Merge pull request #2421 from mortalis13/master
Added new Sublime theme
2015-04-18 17:53:16 +04:00
sevin7676
121e0e51f4 add integer 2015-04-18 09:43:13 -04:00
sevin7676
846c2fb3d3 fix space 2015-04-18 09:35:39 -04:00
sevin7676
cd1c5a42c9 cleanup 2015-04-18 09:21:09 -04:00
sevin7676
282331b133 use pound as its the typical method 2015-04-18 09:12:11 -04:00
sevin7676
db0313f2ad fix case 2015-04-18 09:09:05 -04:00
sevin7676
37a80b35da missing execute in demo doc 2015-04-18 09:05:36 -04:00
sevin7676
75f66697f6 more cleanup 2015-04-18 08:55:29 -04:00
sevin7676
32847a6761 clean up 2015-04-18 08:53:11 -04:00
sevin7676
0d0b0b4356 updated demo doc and snippets 2015-04-18 08:45:13 -04:00
sevin7676
a0a31e16a2 cleanup 2015-04-18 08:27:22 -04:00
sevin7676
295ae4dc81 make pound optional for region 2015-04-18 08:25:47 -04:00
sevin7676
d38849ef9f added doc comment highlight to fix folding 2015-04-18 08:24:59 -04:00
sevin7676
184df6d18e inherit cstyle... trying to figure out best end marker 2015-04-18 07:29:10 -04:00
sevin7676
ff0cc12efc folding partially working.. 2015-04-18 06:37:29 -04:00
Morgan Yarbrough
1b9c8bfc88 FOLDING 2015-04-17 14:24:38 -04:00
Morgan Yarbrough
e42bc9a265 progress, and about to work on folding 2015-04-17 14:09:38 -04:00
Morgan Yarbrough
12be220297 even more keywords! 2015-04-17 12:53:42 -04:00
Morgan Yarbrough
7ae5c862c2 progress but not working yet 2015-04-17 11:17:31 -04:00
sevin7676
d8f7003fb8 add null back 2015-04-17 10:03:56 -04:00
sevin7676
76ac79f116 more progress 2015-04-17 10:00:13 -04:00
sevin7676
1a6e2f83f2 small fixes 2015-04-17 09:35:58 -04:00
sevin7676
6b62974118 good progress 2015-04-17 09:28:56 -04:00
sevin7676
461faa9184 more progress 2015-04-17 08:37:54 -04:00
sevin7676
ede82e7137 progress- save comments for reuse here 2015-04-17 08:11:21 -04:00
sevin7676
f0b3aa0a6f PARTIAL 2015-04-17 07:37:17 -04:00
mortalis13
fb5f272f81 Rename Sublime theme to iPlastic 2015-04-15 21:49:38 +03:00
mortalis13
c458f96d3a Edited lib/ace/sublime.css 2015-04-10 22:19:14 +03:00
Harutyun Amirjanyan
6070fe96f7 Merge pull request #2407 from xixixao/configure-block-select
Add configuration option for block select
2015-04-09 14:56:55 +04:00
Harutyun Amirjanyan
6a2d3fcb09 Merge pull request #2408 from bostikforever/vb-case-insensitive
VBScript is case insensitive
2015-04-09 14:52:56 +04:00
Harutyun Amirjanyan
8b29f7f3c9 Merge pull request #2411 from saxbophone/master
Wider SQL Command and Data Types Coverage
2015-04-09 14:51:33 +04:00
Harutyun Amirjanyan
48de4711eb Merge pull request #2418 from xixixao/selection-zero-height
Remove 0 height selection highlight
2015-04-09 14:50:26 +04:00
nightwing
bb3fa62824 Merge commit '510d060cb2' 2015-04-09 14:20:50 +04:00
Harutyun Amirjanyan
6bdc0d6cbb Merge pull request #2440 from grit96/patch-1
Make print margin in cobalt more visible
2015-04-09 14:20:07 +04:00
nightwing
510d060cb2 cleanup 2015-04-09 14:09:03 +04:00
Geraint White
da8d545985 Make print margin in cobalt more visible 2015-04-09 09:14:21 +01:00
César Izurieta
4f655e71d9 Make deepCopy work correctly with arrays 2015-04-05 04:39:36 -03:00
nightwing
8f686eb795 release v1.1.9 2015-04-03 13:43:18 +04:00
nightwing
6fad60f546 tweaks for the new release 2015-04-03 13:30:00 +04:00
nightwing
1ae86f896a update vim mode 2015-04-03 13:29:10 +04:00
nightwing
4e4df645cc add adoc extension for asciidoc files 2015-04-03 13:29:10 +04:00
Joshua Saxby
0bf729d88f added important keywords and data types missed out 2015-03-27 22:21:42 +00:00
Joshua Saxby
cc40177114 Revert "add some new types and change the type of existing keywords"
This reverts commit fcb4023e52.
2015-03-27 22:11:41 +00:00
Joshua Saxby
fcb4023e52 add some new types and change the type of existing keywords 2015-03-27 22:10:02 +00:00
mortalis
22f802a9ff new sublime theme 2015-03-27 12:37:59 +02:00
xixixao
14a8e1f5d9 Remove 0 height selection highlight 2015-03-25 18:07:38 +00:00
Harutyun Amirjanyan
a2e05ac438 Merge pull request #2410 from kevinushey/bugfix/r-sapply-snippet
correct snippet for 'sapply'
2015-03-21 18:06:48 +04:00
Kevin Ushey
f17c67cd01 correct snippet for 'sapply' 2015-03-19 15:30:41 -07:00
Bolutife Ogunsola
9c6720edca Update tokens test file for vbscript 2015-03-19 19:11:49 +01:00
Bolutife Ogunsola
4dd8eda928 VBScript is case insensitive 2015-03-19 18:03:01 +01:00
xixixao
cb83a974b4 Add configuration option for block select 2015-03-18 21:09:45 +00:00
Ruben Daniels
75556854b9 Merge pull request #2397 from ajaxorg/fix/various
Several small fixes
2015-03-17 15:12:49 -07:00
nightwing
7e9e5aea17 remove old code 2015-03-18 01:57:03 +04:00
nightwing
bb16d65cbb update jshint 2015-03-18 01:55:07 +04:00
Harutyun Amirjanyan
c39134411d Merge pull request #2387 from jmcphers/master
Prevent vim ex commandline from obscuring search results
2015-03-17 10:00:34 +04:00
Harutyun Amirjanyan
cb0816b183 Merge pull request #2399 from kevinushey/patch/vim-colon-selection
[vim] don't select range specifier on `:` insertion
2015-03-17 09:58:58 +04:00
Kevin Ushey
e551b090b7 don't select initial text on ':' 2015-03-16 15:50:31 -07:00
nightwing
c5602489f4 add styling for ace_invisble to all themes 2015-03-15 15:27:48 +04:00
nightwing
1c1d56b3ea make blurred state clearer in github theme 2015-03-15 15:18:10 +04:00
nightwing
a78bf8e5ef update links to emmet.js 2015-03-15 15:00:00 +04:00
nightwing
d9db903190 update rust mode 2015-03-15 15:00:00 +04:00
nightwing
4af37cd722 fix #2395 context menu regression in Firefox on mac 2015-03-15 15:00:00 +04:00
Harutyun Amirjanyan
dd69f5939c Merge pull request #2380 from trystanclarke/master
Fix typeerror "Cannot read property 'container' of undefined" in autocomplete
2015-03-15 00:09:42 +04:00
Harutyun Amirjanyan
cac9e261e3 Merge pull request #2386 from timdp/behaviours-keep-selection
CstyleBehaviour: keeping selections after insertion
2015-03-15 00:01:02 +04:00
Joshua Saxby
0216e8bbfd formatting 2015-03-11 21:27:36 +00:00
Joshua Saxby
38e3452313 added SQL data types 2015-03-11 21:05:54 +00:00
Joshua Saxby
fb7b23e627 started adding missing sql keywords and types 2015-03-11 18:42:21 +00:00
Jonathan McPherson
1b1006ac1d prevent vim ex commandline from obscuring search results (fixes #2384) 2015-03-10 14:17:17 -07:00
Harutyun Amirjanyan
101656ea5c Merge pull request #2385 from mikermcneil/patch-1
makes example work out of the box
2015-03-10 23:41:57 +04:00
Ruben Daniels
6a07619ad2 Merge pull request #2370 from ajaxorg/misc
Misc issues
2015-03-10 12:33:01 -07:00
Tim De Pauw
a5c619bda8 CstyleBehaviour: keeping selections after insertion 2015-03-09 17:44:03 +01:00
Mike McNeil
3adde642dc makes example work out of the box 2015-03-07 18:40:04 -08:00
trystanclarke
967177bbc5 Update autocomplete.js 2015-03-02 09:35:46 +00:00
nightwing
60c639a34b Merge branch 'pull/2375' 2015-02-28 22:17:25 +04:00
nightwing
de9e5226bf add tests from v1.2 branch and increase split size to improve performance 2015-02-28 22:16:19 +04:00
nightwing
76e05b7fd5 fix #2381: keycode for ; is missing 2015-02-28 21:51:18 +04:00
nightwing
2506bb0921 Merge branch pull/2376 2015-02-28 21:43:09 +04:00
nightwing
481bca1b09 use ellipsis character instead of dots 2015-02-28 21:41:30 +04:00
nightwing
01f5846ee3 static highlight can be used without editor.css 2015-02-28 20:40:54 +04:00
trystanclarke
cca4ab8b45 Merge pull request #1 from trystanclarke/trystanclarke-fix-autocomp-type-error
Update autocomplete.js
2015-02-27 16:18:03 +00:00
trystanclarke
ae4989eea1 Update autocomplete.js
Fix typeerror "Cannot read property 'container' of undefined" when using live autocomplete. Error can occur when editor loses focus and the autocomplete popup has never been shown.
2015-02-27 16:15:24 +00:00
Daniel Marcotte
6df244d429 Fit what metadata we can into autocompletes
The whole meta string currently gets dropped from the autocompletes
popup if it doesn't fit.  This leads to confusing autocompletes where
the meta for some entries are missing for no apparent reason.

So, instead of dropping the entire meta string when it doesn't fit,
insert what we can and append "..." to communicate that we clipped it.
2015-02-25 16:43:39 -08:00
Scott Glajch
b5064a4bb3 Fix for issue #2374, maximum call stack exceeded in 64 bit chrome when pasting large chunks. 2015-02-25 13:00:39 -05:00
nightwing
9905267e4d fix gutter in static highlight when wrapping is enabled 2015-02-25 00:14:14 +04:00
Harutyun Amirjanyan
bed3a18d49 Merge pull request #2366 from leanprover/add-lean-mode
add 'lean' mode for Lean Theorem Prover files
2015-02-24 23:25:57 +04:00
Soonho Kong
49ff504639 fix qqstring rule in lean-mode 2015-02-24 14:10:41 -05:00
Harutyun Amirjanyan
a035cd2558 Merge pull request #2373 from pamelafox/patch-2
Add ClassName to highlighting
2015-02-24 23:03:48 +04:00
Harutyun Amirjanyan
9a275f304d Merge pull request #2371 from pamelafox/patch-1
Adding cursive and fantasy to keywords list
2015-02-24 23:02:07 +04:00
Pamela Fox
b6910a3094 Add ClassName to highlighting
So that document.getElementsByClassName gets highlighted.
2015-02-24 10:59:36 -08:00
Soonho Kong
27ad846641 highlight names followed nameProviders in lean-mode 2015-02-24 13:21:40 -05:00
Soonho Kong
34d80e81ca clean up string rule for lean-mode 2015-02-24 13:21:22 -05:00
Soonho Kong
3c34a9852f add and sort keywords/storage-modifiers for lean-mode 2015-02-24 13:20:28 -05:00
Soonho Kong
a0fe09f3be clean up unused rules for lean-mode 2015-02-24 13:19:56 -05:00
Pamela Fox
906b6c9d8d Adding cursive and fantasy to keywords list 2015-02-24 09:30:43 -08:00
Soonho Kong
74800e84ee remove single quoted string (qstring) from lean-mode 2015-02-24 12:09:11 -05:00
Soonho Kong
8f49d3d897 add a small demo for lean mode 2015-02-24 11:11:34 -05:00
Soonho Kong
9654382294 use 'defaultToken' for comment/qqstring/qstring in lean-mode
Suggested by @nightwing
2015-02-24 11:02:06 -05:00
nightwing
5ce334e930 update CONTRIBUTING.md 2015-02-24 18:49:59 +04:00
nightwing
7572a9543e update syntax docs 2015-02-24 18:42:15 +04:00
Soonho Kong
b3da9336ee add 'lean' mode for Lean Theorem Prover files 2015-02-23 07:03:52 -05:00
nightwing
4bc34f4eae fix #2341 do not use ace_editor id for the default style 2015-02-18 23:26:22 +04:00
nightwing
16b542aea4 reduce crazy large negative top value on hidden textarea (fixes #2362) 2015-02-18 23:19:27 +04:00
Ruben Daniels
60a1281708 Merge pull request #2355 from ajaxorg/build-issues
Fix build issues
2015-02-16 11:28:20 -08:00
Ruben Daniels
2ff39c2192 Merge pull request #2322 from ajaxorg/altgr
Fix altgr handling
2015-02-16 11:27:45 -08:00
Ruben Daniels
34f57e7499 Merge pull request #2316 from ajaxorg/misc
Fix xml autodindent and several small issues
2015-02-16 11:27:16 -08:00
Harutyun Amirjanyan
04e75ea0db Merge pull request #2359 from invokr/master
Added new C++11 tokens to highlighting rules
2015-02-16 19:13:07 +03:00
Robin
b0475ce3e4 Added C++11 tokens to highlighting rules 2015-02-16 14:27:22 +00:00
Harutyun Amirjanyan
d86b2fd7ee Merge pull request #2332 from kevinushey/bugfix/xml-tag-highlighting
[xml] ensure tag name starts with letter
2015-02-16 15:27:42 +03:00
nightwing
0b20e4dc1d fix #2351 Minification fails on Windows 2015-02-12 19:46:21 +04:00
nightwing
388f0235b7 fix #2348 packaged require breaks node-webkit 2015-02-12 19:45:43 +04:00
nightwing
d9e4b52ee1 fix alt-e at the last error 2015-02-10 19:09:27 +04:00
nightwing
703a5394e3 toggle fold commands must work for all selections 2015-02-10 19:09:11 +04:00
nightwing
42b43b1fbe fix highlighting of indented bash heredocs 2015-02-10 19:08:56 +04:00
nightwing
3e32d5bf7e workaround for vim cursor getting stuck on folded lines 2015-02-10 19:07:55 +04:00
Harutyun Amirjanyan
385a285c58 Merge pull request #2334 from tylerlong/master
XAML is XML
2015-02-02 19:58:44 +04:00
Tyler Long
c840471248 XAML is XML
https://msdn.microsoft.com/en-us/library/cc295302.aspx
2015-01-29 14:47:57 +08:00
Kevin Ushey
3fe1383cdc [xml] ensure tag name starts with letter 2015-01-28 10:53:42 -08:00
Harutyun Amirjanyan
6b88b939c2 Merge pull request #2325 from mdinger/add_usize_isize_highlighting
Add Rust highlight support for isize, usize, us and is
2015-01-27 23:57:24 +04:00
mdinger
1621c1519c Add highlight support for isize, usize, us and is 2015-01-24 14:18:11 -05:00
nightwing
0da0566bac fix pagedown in vim mode 2015-01-24 18:53:41 +04:00
nightwing
b93d772720 do not overwrite ctrl-alt-0 on windows since that is used on German keyboard 2015-01-23 17:21:12 +04:00
nightwing
845a6d4e98 make detection of altGr more robust 2015-01-23 17:21:12 +04:00
nightwing
8df1eb70c5 fix typo 2015-01-23 17:07:20 +04:00
Harutyun Amirjanyan
63178a0511 Merge pull request #2318 from shiroyuki/patch-1
Add the missing mode "Django" to ext-modelist
2015-01-23 16:38:49 +04:00
nightwing
9f8cb78f37 fix require path for tests 2015-01-23 16:35:45 +04:00
nightwing
acd41efcb6 do not include all whitespace lines in vim paragraphs 2015-01-23 13:36:06 +04:00
nightwing
64eaf47c4d do not throw when running vim ':write' command 2015-01-23 13:32:20 +04:00
nightwing
c769031e78 [vim] fix w for non ascii chars 2015-01-22 22:38:32 +04:00
Juti Noppornpitak
8a8bc206db Add the missing mode "Django" to ext-modelist
This is to add Django as an alternative mode for HTML files. The placement of the entry is to ensure that Django syntax highlighter does not override HTML syntax highlighter.
2015-01-19 16:30:38 -05:00
nightwing
7db217dfe0 avoid emitting spurious changeWrapMode event 2015-01-19 01:15:24 +04:00
nightwing
847bfa4bfe cleanup 2015-01-19 01:13:05 +04:00
nightwing
135b9e5baf do not autoindent after self-closing tag 2015-01-19 01:10:03 +04:00
nightwing
c356c14940 fix weird pairing of quotes in cstyle behavior 2015-01-19 00:33:14 +04:00
nightwing
2d06dc6316 workaround for word-wrap bug on chrome 2015-01-19 00:28:51 +04:00
nightwing
8c4173ba11 Merge remote-tracking branch 'remotes/origin/master' 2015-01-18 23:44:18 +04:00
Harutyun Amirjanyan
fe57baaae1 Merge pull request #2289 from iDeBugger/master
Added XMLDOM and worker for XML syntax analysis
2015-01-18 22:37:58 +03:00
Harutyun Amirjanyan
0c3246e0df Merge pull request #2315 from xixixao/patch-1
Fix doc on editor.remove
2015-01-18 22:33:43 +03:00
Michal Srb
d21be42c8a Fix doc on editor.remove 2015-01-18 14:40:51 +00:00
Smirnov O. A
ccd5d689cc Updated xmldom dependency 2015-01-16 10:06:38 +03:00
Smirnov O. A
fb41c6ce4e Update update_deps.js for xmldom 2015-01-16 09:57:52 +03:00
Smirnov O. A
3b703dad56 Merge branch 'master' of github.com:iDeBugger/ace 2015-01-14 11:07:40 +03:00
Smirnov O. A
0a7d192b3d Merge remote-tracking branch 'upstream/master' 2015-01-14 11:06:22 +03:00
Harutyun Amirjanyan
c0b300a8e8 Merge pull request #2311 from yihangho/docs/spacing
Fix spacing in index.html
2015-01-13 17:03:16 +04:00
Yihang Ho
68abe8507a Fix spacing in index.html 2015-01-13 20:45:01 +08:00
Lennart Kats
d62315a740 Merge pull request #2309 from ajaxorg/misc
Fix several small issues
2015-01-13 09:54:25 +01:00
nightwing
eddc5563d8 update json worker tests 2015-01-12 02:23:50 +04:00
nightwing
57f6fbd768 tweak completer 2015-01-12 02:12:00 +04:00
nightwing
100022564c cancel gatherCompletions if cursor position changes 2015-01-12 01:13:27 +04:00
nightwing
b57f2e2ae3 fix inline editor demo 2015-01-11 23:23:53 +04:00
nightwing
264923e4df make worker events more consistent 2015-01-11 22:48:39 +04:00
nightwing
e1a5492a7f do not throw error when trying to match tag at the end of the document 2015-01-11 22:27:12 +04:00
nightwing
5e4facea44 fix livescript highlighting 2015-01-11 22:23:25 +04:00
Harutyun Amirjanyan
37ab8daabe Merge pull request #2300 from kevinushey/patch/vim-visual-block-move-to-eol
Conform with upstream change for Vim Visual Block + move to EOL behaviour
2015-01-07 22:49:58 +04:00
nightwing
55bf8e56d3 fix highlighting of ?" in ruby mode 2015-01-07 01:18:28 +04:00
nightwing
ced37c0c19 update jshint 2015-01-06 15:45:55 +04:00
Kevin Ushey
a50833cfea conform with upstream change
Ref:
1e5ae06ba4
2015-01-05 17:11:14 -08:00
iDeBugger
b2b0e73e0f Fixed some troubles with language and codestyle 2015-01-05 00:27:11 +03:00
nightwing
72edcd332d tweak mode_creator 2015-01-05 00:34:25 +04:00
nightwing
bcc2cd9b68 Merge remote-tracking branch 'remotes/origin/master' 2015-01-05 00:20:02 +04:00
nightwing
f4ea1ccb6a always call the callback form setMode 2015-01-05 00:17:16 +04:00
nightwing
a06739af9a Merge remote-tracking branch 'remotes/origin/fix/webkit-focus-bug' 2015-01-04 23:54:53 +04:00
nightwing
aceddd9f8f Merge branch 'pull/2273' 2015-01-04 23:54:00 +04:00
nightwing
ad9aa35ffe Revert "Reduced size of sample document" 2015-01-04 23:52:40 +04:00
nightwing
b66fb6def8 Merge branch 'pull/2269' 2015-01-04 23:50:57 +04:00
nightwing
0054bb8794 cleanup 2015-01-04 23:48:28 +04:00
nightwing
4603c34b10 workaround for webkit focus bug 2015-01-01 02:00:02 +04:00
Bernhard Weichel
07d01fda44 fixed a few typos and added more snippets 2014-12-29 22:10:03 +01:00
Smirnov O. A
4aff48a837 Added XMLDOM and worker for XML syntax analysis 2014-12-24 14:44:31 +03:00
Harutyun Amirjanyan
4b8a9a475b Merge pull request #2284 from darabos/patch-1
Fix getVScrollBarAlwaysVisible
2014-12-23 23:30:26 +04:00
Matthias S. Benkmann
eccc98b83b net.put => net.request('PUT'; improved usability for "Save" buttons 2014-12-23 16:33:56 +01:00
Matthias S. Benkmann
e7afb4f19e support glob patterns for --puttable; reformat for ancient terminals 2014-12-23 15:51:23 +01:00
Matthias S. Benkmann
8919b113d1 add server upload buttons and Ctrl-S bindings to mode_editor
in combination with PUT support in ./static.py (or whatever other web server)
this allows people to save both the highlighting rules and the demo documents right
from the mode editor for a better workflow.
2014-12-23 13:03:09 +01:00
Matthias S. Benkmann
ded43d9d69 HTTP PUT support for static.py
change host default to 127.0.0.1 for better security
improved option parsing
2014-12-23 13:03:09 +01:00
Bernhard Weichel
14850f5b9e Reduced size of sample document 2014-12-22 16:55:40 +01:00
Lennart Kats
7ff1f1dd0d Merge pull request #2283 from ajaxorg/misc
Sync with cloud9
2014-12-22 13:29:17 +01:00
nightwing
8ff856186d update tests for c mode 2014-12-22 02:47:38 +04:00
nightwing
b46a0fb4f9 do not include xml tag attributes in the fold range 2014-12-22 02:47:31 +04:00
Daniel Darabos
b9a4f293ed Fix getVScrollBarAlwaysVisible.
By accident it was returning `$hScrollBarAlwaysVisible`.
2014-12-21 22:52:21 +01:00
nightwing
724b66857d Merge remote-tracking branch 'remotes/pull/2281' 2014-12-21 13:47:50 +04:00
nightwing
56cb246c78 max stack size on chrome is smaller now 2014-12-21 13:46:41 +04:00
nightwing
fed215d046 do not discard modifier info of modifier keys 2014-12-21 13:39:25 +04:00
nightwing
7a3257ab58 fix incorrect highlighting in c and haskell modes 2014-12-21 13:39:25 +04:00
nightwing
2d12ebb1df improve global access warning in the demo 2014-12-21 13:39:13 +04:00
Kevin Ushey
15b83aca5f fix move to EOL behaviour for visual block mode 2014-12-20 13:31:23 -08:00
nightwing
60dd224d96 remove old delta shim from vim mode 2014-12-20 19:53:51 +04:00
nightwing
067a1ee68b Merge remote-tracking branch 'remotes/origin/master' 2014-12-20 19:51:39 +04:00
Harutyun Amirjanyan
5ea0a9b802 Merge pull request #2280 from ajaxorg/vim2
Update vim mode to the latest version
2014-12-20 19:45:50 +04:00
nightwing
66ede32c42 update build submodule 2014-12-20 16:19:58 +04:00
nightwing
ed5c38b7c8 update list of users 2014-12-19 18:50:55 +04:00
nightwing
b5c9b7f395 fix typo in IE mouse handler 2014-12-19 18:45:25 +04:00
Lennart Kats
7b037f35ba Merge pull request #2267 from ajaxorg/fix/various
Fix various small issues
2014-12-16 16:06:41 +01:00
Harutyun Amirjanyan
52de738e8a Merge pull request #2275 from mehtaphysical/char_reserved_in_js
change variable char to character
2014-12-16 01:01:45 +04:00
Ryan Mehta
dafa24d5e1 change variable char to character 2014-12-15 12:33:49 -08:00
Bernhard Weichel
95eed25439 small fix in the snippets 2014-12-14 23:53:52 +01:00
Bernhard Weichel
7da354d5f3 fixed Uncaught TypeError: undefined is not a functionapp_config.js:147
(anonymous function)app_config.js:146 setDefaultValuesmode_creator.js:6
2014-12-14 23:40:47 +01:00
Bernhard Weichel
18b3c57de9 Merge branch 'master' of https://github.com/ajaxorg/ace into feature/ace_language_definition
# By nightwing (7) and others
# Via Harutyun Amirjanyan (4) and others
* 'master' of https://github.com/ajaxorg/ace:
  do not pair quotes inside strings
  fix toggleComment command in php mode
  fix copyLines* for multiple selections
  fix pairing of quotes in cstyle behavior
  add helper for creating tests
  Autocomplete exactMatch option
  add *~ (backup files created by various editors) to .gitignore
  Remove unneeded regex groups for Eiffel
  Update Eiffel programming language definition.
  add config.warn and refactor config to allow sharing with ace_tree
  do not use automatic scroll into view
  Teach tmlanguage.js to process multiple .tmLanguage files at once
2014-12-14 23:11:35 +01:00
Bernhard Weichel
8019a21475 added abc mode 2014-12-14 20:34:41 +01:00
nightwing
c5edaa3608 allow filtering tests in browser runner 2014-12-13 16:45:56 +04:00
nightwing
5a03993f65 update vim.js 2014-12-13 00:50:13 +04:00
Lennart Kats
5fc3bbbe09 Merge pull request #2249 from ajaxorg/misc
Several small fixes
2014-12-12 20:48:16 +01:00
nightwing
6b13aedf5f do not pair quotes inside strings 2014-12-12 17:38:39 +04:00
nightwing
ec18d9493d fix toggleComment command in php mode 2014-12-12 17:38:39 +04:00
nightwing
3fa54ce97e fix copyLines* for multiple selections 2014-12-12 17:38:39 +04:00
nightwing
852e0673ca fix pairing of quotes in cstyle behavior 2014-12-12 17:38:38 +04:00
nightwing
278f1d1674 add helper for creating tests 2014-12-12 17:38:38 +04:00
Harutyun Amirjanyan
232b3c0f8c Merge pull request #2272 from adamjimenez/autocomplete-exact
Autocomplete exactMatch option
2014-12-12 17:21:39 +04:00
nightwing
d8f0ab2a16 fix regression in setDefaultValues 2014-12-12 16:56:02 +04:00
Adam Jimenez
cfdb223e7a Autocomplete exactMatch option
Option to show only exact matches in autocomplete
2014-12-12 10:27:45 +00:00
Harutyun Amirjanyan
d68050c62b Merge pull request #2268 from mbenkmann/gitignore_backup_files
add *~ (backup files created by various editors) to .gitignore
2014-12-10 11:11:00 -08:00
Matthias S. Benkmann
119259b702 add *~ (backup files created by various editors) to .gitignore 2014-12-07 18:21:03 +01:00
nightwing
c49e5bfef9 disable warning 2014-12-07 01:26:44 +04:00
nightwing
2fc497477d highlight tags when cursor is before tagname 2014-12-07 01:26:24 +04:00
nightwing
e54882db64 use setAttribute instead of autocorrect setter, since the setter doesn't work on ipad 2014-12-07 01:08:06 +04:00
Harutyun Amirjanyan
e217418d39 Merge pull request #2266 from Conaclos/master
Update Eiffel definition
2014-12-06 13:03:03 -08:00
Victorien ELVINGER
354dc37ea6 Remove unneeded regex groups for Eiffel 2014-12-06 20:04:27 +01:00
Victorien ELVINGER
29597325d9 Update Eiffel programming language definition.
- Disable comments into strings
- Enable concise form for real numbers
- Enable juxtaposed digit separators
- Check char and string content.
2014-12-06 19:50:52 +01:00
Harutyun Amirjanyan
0d4566b42b Merge pull request #2264 from aroben/convert-many-tmlanguages
Teach tmlanguage.js to process multiple .tmLanguage files at once
2014-12-04 03:44:16 -08:00
Lennart Kats
e1933043dc Merge pull request #2254 from ajaxorg/do-not-scroll
Disable automatic scroll into view
2014-12-04 11:10:29 +01:00
nightwing
a71c17b46f add config.warn and refactor config to allow sharing with ace_tree 2014-12-04 14:02:49 +04:00
nightwing
8c1aa5c772 do not use automatic scroll into view
prepares for deprecating the feature in the next version of ace
2014-12-04 14:02:19 +04:00
Lennart Kats
35155075e0 Merge pull request #2219 from ajaxorg/vim2
better vim mode
2014-12-04 10:55:29 +01:00
Adam Roben
23a3ba85f0 Teach tmlanguage.js to process multiple .tmLanguage files at once
You can now pass more than one .tmLanguage file to tmlanguage.js and it will
process each one in turn. This can vastly speed up the processing of multiple
files as you don't have to pay the node/V8 startup cost for each file.

Note that the script's "dev mode" is now controlled by a --dev flag rather than
an unnamed second argument.
2014-12-03 13:56:22 -05:00
Lennart Kats
57a07f54b3 Merge pull request #2261 from ajaxorg/build
fix broken paths in kitchen-sink demo
2014-12-01 16:10:08 +01:00
Harutyun Amirjanyan
93bd34e1cf Merge pull request #2238 from sevin7676/master
cstyle Comment Folding (region and triple star single line block comment)
2014-11-29 23:59:14 -08:00
Harutyun Amirjanyan
16cdd9ddb3 Merge pull request #2259 from jpallen/patch-2
Highlight \ref, \vref, \cite and \citep as labels
2014-11-28 06:33:29 -08:00
James Allen
fc322711ca Highlight \ref, \vref, \cite and \citep as labels
The `\ref`, and `\cite` commands in LaTeX are similar to `\label`s in that they refer to user defined labels elsewhere in the text, and it makes sense to highlight them with the same color scheme. Particularly the coloring of arguments to `\ref` commands should match the color of `\label` commands because `\label` defines the strings that `\ref` then references.
2014-11-28 13:34:16 +00:00
sevin7676
c1a8e77760 Add comment to explain unusual naming and remove ending whitespace 2014-11-28 08:18:33 -05:00
Harutyun Amirjanyan
097d19e943 Merge pull request #2256 from devoncarew/devoncarew_dart_keywords
more dart keywords
2014-11-26 07:31:07 -08:00
Devon Carew
f7144da4ec more dart keywords 2014-11-25 13:37:36 -08:00
sevin7676
41df1f265f Fix fold widget range for region
End range should be at end of line as we don't want to display the
'#endregion' text after the fold widget (this is consistent with cstyle
region comment folding).

Added missing semi-colons.
2014-11-25 07:01:09 -05:00
sevin7676
1869024de6 changes per nightwing recommendations
Rename this.getFoldWidgetBase to avoid conflict with C# mode.

Use regex instead of substring and trim to determine single line block
comment.

Fixed formatting.

Renamed this.getRegionBlock to this.getCommentRegionBlock to prevent C#
mode conflict.

Updated this.getCommentRegionBlock regex to make nested regions work
properly.

Cleaned up this.startRegionRe (had unneeded parenthesis).
2014-11-25 06:58:45 -05:00
sevin7676
602a7efd5f removed unused line
the end of the range should be the end of the line as we don't want to
see [//#endreigon] in our fold widget.
2014-11-24 10:18:00 -05:00
sevin7676
03730ce381 extra comment to help explain code 2014-11-24 09:52:57 -05:00
sevin7676
f26841da41 tested and cleaned up 2014-11-24 09:48:41 -05:00
sevin7676
fb32897b85 progress
appears to be working, need to clean up still
2014-11-24 09:29:37 -05:00
nightwing
49b50ff347 fix broken paths in kitchen-sink demo 2014-11-23 20:06:41 +04:00
Harutyun Amirjanyan
a50fe34925 Merge pull request #2253 from wcandillon/patch-1
Remove references to built-in modules
2014-11-23 14:27:33 +04:00
William Candillon
332472ecc6 Remove references to built-in modules 2014-11-22 19:27:52 -08:00
nightwing
2f32304c2e update vim.js 2014-11-22 00:52:50 +04:00
nightwing
a40060c1ae increase timeout for intermittently failing placeholder_test.js 2014-11-21 23:15:39 +04:00
nightwing
b4d2cf810d fix failing test 2014-11-21 23:15:37 +04:00
nightwing
a185414f64 remove old vim mode 2014-11-21 23:15:34 +04:00
nightwing
f9de0a5661 use ctrl-c and mac repeat handling from old vim mode 2014-11-21 23:14:28 +04:00
nightwing
068c950517 add support for multiple selections 2014-11-21 23:14:27 +04:00
nightwing
bd7de6b43b fix find next for regexps matching empty range 2014-11-21 23:14:26 +04:00
nightwing
aa472742cc allow to customize cursor appearance 2014-11-21 23:14:24 +04:00
nightwing
8daf190b2e add CodeMirror api proxy for vim mode 2014-11-21 23:14:21 +04:00
nightwing
f47c3ea8bd add cm vim mode 2014-11-21 23:04:16 +04:00
Harutyun Amirjanyan
38ed6de508 Merge pull request #2246 from wcandillon/patch-1
Disable module resolver
2014-11-21 16:51:49 +04:00
Harutyun Amirjanyan
d8d1e08a86 Merge pull request #2236 from tenbits/master
Add Mask Highlighter
2014-11-21 16:50:44 +04:00
Harutyun Amirjanyan
2c796133e0 Merge pull request #2247 from aroben/custom-tmtheme
Teach tmtheme.js how to convert a non-built-in theme
2014-11-21 16:49:45 +04:00
Alex Kit
1587b96b3c Add Mask Highlighter 2014-11-21 05:08:12 +01:00
Adam Roben
11d15b2f28 Pretty-print CSS even when creating a new file 2014-11-20 15:19:27 -05:00
nightwing
eec012b24e fix ignoring empty delta 2014-11-20 23:28:09 +04:00
nightwing
004a19855a do not throw for broken anchors since that can break editor 2014-11-20 23:23:46 +04:00
nightwing
d619e4e746 allow passing newLineCharacter ot getValue 2014-11-20 23:02:34 +04:00
nightwing
27264bb9d9 fix infinite loop when inserting more than 0xF000 lines at once 2014-11-20 23:01:53 +04:00
Adam Roben
89702bf606 Make tmtheme.js handle elements with no settings
We just ignore them now rather than throwing an exception.
2014-11-20 10:56:57 -05:00
Adam Roben
f471e54ef0 Teach tmtheme.js how to convert a non-built-in theme
You can now pass a .tmTheme file on the command line to have it converted.
2014-11-20 10:56:32 -05:00
William Candillon
e0bd006ffc Update xqlint dependency 2014-11-18 13:55:32 -08:00
William Candillon
9f2473bce2 Disable module resolver 2014-11-18 13:48:02 -08:00
Lennart Kats
d097d41144 Merge pull request #2237 from ajaxorg/focus
fix focus related issues
2014-11-17 10:34:12 +01:00
Harutyun Amirjanyan
a0f7864b78 Merge pull request #2241 from jmeas/fix-position
Sets offset of fontMetrics div to be 0.
2014-11-16 19:14:29 +04:00
Jmeas
a45385be98 Sets offset of fontMetrics div to be 0.
Offsetting the fontMetrics div causes the 'ghost image' created when
drag and dropping an Ace Editor to be offset by that same amount. By
removing the offset we fix the problem. Closes #2240.
2014-11-15 19:59:07 +01:00
sevin7676
ef856d0f61 Javascript fixes
added forceMultiline parameter and removed line copied from C# folding
2014-11-15 09:15:25 -05:00
sevin7676
a70a9a88a9 new javascript folding in html mode 2014-11-15 09:03:31 -05:00
sevin7676
11bbc03e1d Javascript region folding 2014-11-15 08:48:20 -05:00
sevin7676
1bed3ec951 Javscript region folding 2014-11-15 08:38:21 -05:00
nightwing
bf7eba2253 fix focusing window with click on ie 2014-11-14 23:57:06 +04:00
nightwing
7326de2a48 reset cached scroll values when resizing
this is needed since scrollTop of scrollbar element can be reset to 0
when ace is moved in the document.
2014-11-14 23:57:06 +04:00
nightwing
1721ca8a0c fix unwanted scrolling into view of hidden textarea 2014-11-14 23:56:55 +04:00
Lennart Kats
c5c1bb2b13 Merge pull request #2235 from ajaxorg/hotfix/php_folding
Hotfix for regression in php folding
2014-11-12 17:08:35 +01:00
nightwing
3a8b279e43 update fold widgets in mixed modes when tokenizer state changes 2014-11-12 18:40:22 +04:00
nightwing
742e8c01a8 fix folding of li tags containing unclosed p tags 2014-11-12 18:38:50 +04:00
nightwing
5801b75b5d fix php folding 2014-11-12 18:37:59 +04:00
nightwing
a4532dd8b9 Merge remote-tracking branch 'remotes/origin/master' into v-1.2
Conflicts:
	build
	lib/ace/multi_select_test.js
2014-11-11 11:47:04 +04:00
nightwing
64f2fc4015 add newLineCharacter argument to getValue 2014-11-11 11:45:20 +04:00
nightwing
ffaf44ec0b copy insert start position before storing it in undoStack 2014-11-11 11:44:17 +04:00
nightwing
bacaeb07d8 cleanup 2014-11-11 11:40:18 +04:00
nightwing
271cefb44a fix typo 2014-11-08 23:52:05 +04:00
nightwing
b8e3198ba8 version 1.1.8 2014-11-08 23:45:22 +04:00
nightwing
a4d831f474 add more users 2014-11-08 20:56:18 +04:00
nightwing
c4e937939a Merge remote-tracking branch 'remotes/origin/mode_issues' 2014-11-08 16:25:19 +04:00
nightwing
5562566b37 Merge remote-tracking branch 'remotes/origin/emacs'
Conflicts:
	lib/ace/incremental_search_test.js
2014-11-08 16:02:02 +04:00
nightwing
072dcb1c11 fix tripple brace highlighting in handlebars mode 2014-11-06 20:43:08 +04:00
Harutyun Amirjanyan
989d0ac3fb Merge pull request #2226 from LivelyKernel/isearch-regexp-support
isearch regexp support
2014-11-06 10:15:53 +04:00
Robert Krahn
775cdedefb isearch test fix 2014-11-05 15:30:05 -08:00
Robert Krahn
a93646d2f7 isearch: commands searchAsRegExp and selectAllMatches 2014-11-05 15:30:03 -08:00
Robert Krahn
7bb5b305be isearch: add regexp support 2014-11-05 15:30:01 -08:00
nightwing
9ccf68dbb2 make sure missing emmet can't break tab key 2014-11-05 23:17:59 +04:00
nightwing
22de936727 fix bracket pairing for multiple selections 2014-11-05 23:15:45 +04:00
nightwing
525fe1ffe3 do not wrap change events in additional e.data 2014-10-18 00:56:13 +04:00
nightwing
bb827051a6 Merge branch 'master' into v-1.2
Conflicts:
	lib/ace/commands/command_manager.js
2014-10-17 19:25:02 +04:00
DanyaPostfactum
6502a3d2cb Update tests for wrap indent 2014-10-12 18:37:52 +10:00
DanyaPostfactum
f625dfeea3 Add indentSubsequentLines to options 2014-10-12 18:37:20 +10:00
DanyaPostfactum
60367772a9 Add wrap indent 2014-10-12 01:56:19 +10:00
nightwing
29023787e5 Merge remote-tracking branch 'remotes/origin/master' into v-1.2
Conflicts:
	build
	lib/ace/document.js
	lib/ace/editor.js
2014-10-05 23:04:57 +04:00
nightwing
ad54d2c46c disabled validateDelta since it breaks autocompletion popup 2014-07-02 22:04:32 +04:00
nightwing
1f7582b5a6 Merge remote-tracking branch 'remotes/origin/master' into v-1.2
Conflicts:
	lib/ace/anchor.js
	lib/ace/keyboard/vim/maps/operators.js
2014-07-02 21:58:13 +04:00
nightwing
ec97ad7904 Merge remote-tracking branch 'remotes/origin/master' into v-1.2
Conflicts:
	build
	lib/ace/document.js
2014-03-31 00:49:41 +04:00
nightwing
27b6d6dcd3 apply arguments max length also includes actual call stack 2014-02-15 00:20:10 +04:00
nightwing
6b60bcbbd6 continue refactoring 2014-02-14 23:52:59 +04:00
nightwing
46f3d77068 simplify apply_delta.js 2014-02-14 22:33:30 +04:00
nightwing
c8d1df203e restore single line delta optimization in anchor.js 2014-02-14 22:32:51 +04:00
nightwing
4299db01bd remove delta.range 2014-02-14 22:32:31 +04:00
nightwing
b5af2c898c Merge remote-tracking branch 'remotes/origin/master'
Conflicts:
	lib/ace/document.js
	lib/ace/editor.js
	lib/ace/undomanager.js
2014-02-14 18:23:03 +04:00
nightwing
c8fca3053c Merge remote-tracking branch 'remotes/origin/master'
Conflicts:
	lib/ace/line_widgets.js
2014-01-16 00:14:34 +04:00
nightwing
8d57d8765f Merge pull request #1745 aldendaniels:master into v-1.2
Refactor document delta handling
2014-01-16 00:11:00 +04:00
aldendaniels
7f1bc7af2f Break out Anchor.onChange helper functions
This should be faster since we don't have to re-initialize the helper
functions each time Anchor.onChange is fired.
2014-01-11 15:48:38 -06:00
aldendaniels
6b280bf6bb Code review fixes (mostly formatting)
- Fix unconventional '{' formatting
- Reformat `UndoManager` changes
- Revert change from `insertInLine` to `insert` in text.js
2014-01-11 15:23:20 -06:00
aldendaniels
35a27fd1ba Treat deltas with empty ranges as NOOPs 2014-01-11 14:45:08 -06:00
aldendaniels
ddd695ee3f Store single-line deltas as .text instead of .lines in undo history
Stores single-line delta content as .text instead of .lines in undo
history. This is done without modifying the original delta object in
case the caller still retains a handle to the original.
2014-01-11 14:43:47 -06:00
aldendaniels
f59708a5ba Add a doNotValidate param to applyDelta
Set it to true in insertInLine/removeInLine.

Also sped up indent/dedent by using insertInLine and removeInLine.
2014-01-11 12:00:10 -06:00
aldendaniels
ef0e8da522 Fix / complete validateDelta
This uncovered the fact that until now delta.range had not always been a
Range object. This inconsistency has been resolved by my changes in
mirror.js.
2014-01-11 11:20:34 -06:00
aldendaniels
08edcdfc98 Stop doing a line-by-line splicing in applyDelta
Also brings back the functionality where large deltas are split into
smaller deltas so that .splice.apply() calls will work.
2014-01-10 22:49:17 -06:00
aldendaniels
3a048cdf61 Bring back insertInLine
Avoids an extra $split call.
2014-01-08 22:51:39 -06:00
aldendaniels
f2a2e4e1a8 Rename the 'delete' delta action to 'remove'
Matches previous naming convention.
2014-01-08 22:18:05 -06:00
aldendaniels
6fe381f633 Rename insertText back to insert 2014-01-08 22:00:11 -06:00
aldendaniels
91df7cd663 Revert "Stop using splice.appy() in ace"
This reverts commit 8624ab8dcb.
2014-01-08 21:39:30 -06:00
aldendaniels
8624ab8dcb Stop using splice.appy() in ace
Since .apply() can't handle more than 65535 parameters, splice.apply()
is brittle. It's also hard to read. This replaces splice.apply() calls
throughout ace code with lang.spliceIntoArray().
2014-01-04 01:59:30 -06:00
aldendaniels
b503e65e03 Break on applyDelta into its own module
This makes it possible to break out helper functions without exposing
them to the rest of the document class. Also, long term, we may want to
have a stand-alone test suite for applyDelta, so it makes sense in its
own file.

All other changes involve syntax corrections (some syntax issues were
mine, others pre-existed) to make the documentation compilation work.
2014-01-03 14:59:22 -06:00
aldendaniels
612478e39f Speed up single-line deltas
2e6f12725b slowed down the application of
deltas that only affect a single line. The slow-down, though trivial for
a single line, is significant for operations than separately modify
thousands of rows (such as indenting a large document).

This commit speeds up single-line deltas by avoiding unnecessary calls
to splitLine() and joinLineWithNext().
2014-01-01 14:45:54 -06:00
aldendaniels
810e196cc6 Use console.warn for deprecated methods
console.warn makes better sense than console.log and matches similar
warnings in ace (see gutter.js for example).
2014-01-01 12:06:19 -06:00
aldendaniels
026af74016 Fix render bugs
Both were introduced in 2e6f12725b.
2014-01-01 12:04:12 -06:00
aldendaniels
27768230c8 Maintain public API and update coding convention
This seeks to keep the public API in-tact while improving method names
within ace by keeping the old methods as wrappers around the new
better-named methods.

For example, document.insert() now simply calls document.insertText()
and warns the caller via a console.log() that they are using a
deprecated method.

I've also updated the coding style of my changes (where I noticed
discrepancies) to match the rest of Ace.
2014-01-01 11:05:27 -06:00
aldendaniels
2e6f12725b #1744: Refactor document delta handling
Refactor delta handling code to:

- Combine the "insertText" and "insertLines" delta types into a single
"insert" delta type

- Combine the "removeText" and "removeLines" delta types into a single
"remove" delta type

- Make all document mutations in a single applyDelta function.

- Add basic delta validation (more needed . . . see TODOs)

- Rework anchor logic to handle new delta types (also simplified)

- Rename "insert()" to "insertText()" and "remove()" to "removeText()"

- Rename "insertLines()" to "insertFullLines()" and "removeLines()" to
"removeFullLines()"

See related issue for more information. All tests are passing and the
changes appear functional under preliminary testing, but careful review
and testing will be necessary.
2014-01-01 00:41:45 -06:00
233 changed files with 25227 additions and 5753 deletions

1
.gitignore vendored
View file

@ -2,6 +2,7 @@
.DS_Store
*.swp
*.tmp
*~
# Project files that should not be in the repo
.*

View file

@ -7,16 +7,9 @@ Feel free to fork and improve/enhance Ace any way you want. If you feel that the
There are two versions of the agreement:
1. [The Individual CLA](https://github.com/ajaxorg/ace/raw/master/doc/Contributor_License_Agreement-v2.pdf): use this version if you're working on an ajax.org in your spare time, or can clearly claim ownership of copyright in what you'll be submitting.
2. [The Corporate CLA](https://github.com/ajaxorg/ace/raw/master/doc/Corporate_Contributor_License_Agreement-v2.pdf): have your corporate lawyer review and submit this if your company is going to be contributing to ajax.org projects
1. [The Individual CLA](https://docs.google.com/a/c9.io/forms/d/1MfmfrxqD_PNlNsuK0lC2KSelRLxGLGfh_wEcG0ijVvo/viewform): use this version if you're working on the Cloud9 SDK or open source projects in your spare time, or can clearly claim ownership of copyright in what you'll be submitting.
2. [The Corporate CLA](https://docs.google.com/a/c9.io/forms/d/1vFejn4111GdnCNuQ6BfnJDaxdsUEMD4KCo1ayovAfu0/viewform): have your corporate lawyer review and submit this if your company is going to be contributing to the Cloud9 SDK and/or open source projects.
If you want to contribute to an ajax.org project please print the CLA and fill it out and sign it. Then either send it by snail mail or fax to us or send it back scanned (or as a photo) by email.
If you want to contribute to the Cloud9 SDK and/or open source projects please go to the online form, fill it out and submit it.
Email: ace+cla@c9.io
Fax: +31 (0) 206388953
Address: Ajax.org B.V.
Keizersgracht 241
1016 EA, Amsterdam
the Netherlands
Happy coding, Cloud9

View file

@ -1,4 +1,17 @@
Version 1.2.0-pre
* New Features
- Indented soft wrap (danyaPostfactum)
* API Changes
- unified delta types `{start, end, action, lines}` (Alden Daniels https://github.com/ajaxorg/ace/pull/1745)
- "change" event listeners on session and editor get delta objects directly
2015.04.03 Version 1.1.9
- Small Enhancements and Bugfixes
2014.11.08 Version 1.1.8
* API Changes
- `editor.commands.commandKeyBinding` now contains direct map from keys to commands instead of grouping them by hashid

View file

@ -120,6 +120,7 @@ function demo() {
function changeComments(data) {
return (data
.replace("doc/site/images/ace-logo.png", "demo/kitchen-sink/ace-logo.png")
.replace(/<!\-\-DEVEL[\d\D]*?DEVEL\-\->/g, "")
.replace(/PACKAGE\-\->|<!\-\-PACKAGE/g, "")
.replace(/\/\*DEVEL[\d\D]*?DEVEL\*\//g, "")
@ -306,6 +307,7 @@ function buildAceModuleInternal(opts, callback) {
ignore: opts.ignore || [],
withRequire: false,
basepath: ACE_HOME,
transforms: [normalizeLineEndings],
afterRead: [optimizeTextModules]
}, write);
}
@ -406,6 +408,10 @@ function getLoadedFileList(options, callback, result) {
callback(Object.keys(deps));
}
function normalizeLineEndings(module) {
module.source = module.source.replace(/\r\n/g, "\n");
}
function optimizeTextModules(sources) {
var textModules = {};
return sources.filter(function(pkg) {
@ -451,10 +457,10 @@ function optimizeTextModules(sources) {
if (/\.css$/.test(pkg.id)) {
// remove unnecessary whitespace from css
input = input.replace(/\n\s+/g, "\n");
input = '"' + input.replace(/\r?\n/g, '\\\n') + '"';
input = '"' + input.replace(/\n/g, '\\\n') + '"';
} else {
// but don't break other files!
input = '"' + input.replace(/\r?\n/g, '\\n\\\n') + '"';
input = '"' + input.replace(/\n/g, '\\n\\\n') + '"';
}
textModules[pkg.id] = input;
}

View file

@ -79,7 +79,7 @@ By default the editor only supports plain text mode; many other languages are av
The mode can then be used like this:
```javascript
var JavaScriptMode = require("ace/mode/javascript").Mode;
var JavaScriptMode = ace.require("ace/mode/javascript").Mode;
editor.getSession().setMode(new JavaScriptMode());
```

2
build

@ -1 +1 @@
Subproject commit fc9d2cae9fe8e6e95e74c86a31d21caadd8f9f39
Subproject commit a4e495d8901876c6bafe3870a35cb8e32c827e97

View file

@ -38,69 +38,62 @@
var ACE_NAMESPACE = "";
var global = (function() {
return this;
})();
var global = (function() { return this; })();
if (!global && typeof window != "undefined") global = window; // strict mode
if (!ACE_NAMESPACE && typeof requirejs !== "undefined")
return;
var _define = function(module, deps, payload) {
if (typeof module !== 'string') {
if (_define.original)
_define.original.apply(window, arguments);
var define = function(module, deps, payload) {
if (typeof module !== "string") {
if (define.original)
define.original.apply(this, arguments);
else {
console.error('dropping module because define wasn\'t a string.');
console.error("dropping module because define wasn\'t a string.");
console.trace();
}
return;
}
if (arguments.length == 2)
payload = deps;
if (!_define.modules) {
_define.modules = {};
_define.payloads = {};
if (!define.modules[module]) {
define.payloads[module] = payload;
define.modules[module] = null;
}
_define.payloads[module] = payload;
_define.modules[module] = null;
};
define.modules = {};
define.payloads = {};
/**
* Get at functionality define()ed using the function above
*/
var _require = function(parentId, module, callback) {
if (Object.prototype.toString.call(module) === "[object Array]") {
if (typeof module === "string") {
var payload = lookup(parentId, module);
if (payload != undefined) {
callback && callback();
return payload;
}
} else if (Object.prototype.toString.call(module) === "[object Array]") {
var params = [];
for (var i = 0, l = module.length; i < l; ++i) {
var dep = lookup(parentId, module[i]);
if (!dep && _require.original)
return _require.original.apply(window, arguments);
if (dep == undefined && require.original)
return;
params.push(dep);
}
if (callback) {
callback.apply(null, params);
}
return callback && callback.apply(null, params) || true;
}
else if (typeof module === 'string') {
var payload = lookup(parentId, module);
if (!payload && _require.original)
return _require.original.apply(window, arguments);
};
if (callback) {
callback();
}
return payload;
}
else {
if (_require.original)
return _require.original.apply(window, arguments);
}
var require = function(module, callback) {
var packagedModule = _require("", module, callback);
if (packagedModule == undefined && require.original)
return require.original.apply(this, arguments);
return packagedModule;
};
var normalizeModule = function(parentId, moduleName) {
@ -119,7 +112,6 @@ var normalizeModule = function(parentId, moduleName) {
moduleName = moduleName.replace(/\/\.\//, "/").replace(/[^\/]+\/\.\.\//, "");
}
}
return moduleName;
};
@ -128,12 +120,11 @@ var normalizeModule = function(parentId, moduleName) {
* definition function if needed.
*/
var lookup = function(parentId, moduleName) {
moduleName = normalizeModule(parentId, moduleName);
var module = _define.modules[moduleName];
var module = define.modules[moduleName];
if (!module) {
module = _define.payloads[moduleName];
module = define.payloads[moduleName];
if (typeof module === 'function') {
var exports = {};
var mod = {
@ -149,19 +140,15 @@ var lookup = function(parentId, moduleName) {
var returnValue = module(req, exports, mod);
exports = returnValue || mod.exports;
_define.modules[moduleName] = exports;
delete _define.payloads[moduleName];
define.modules[moduleName] = exports;
delete define.payloads[moduleName];
}
module = _define.modules[moduleName] = exports || module;
module = define.modules[moduleName] = exports || module;
}
return module;
};
function exportAce(ns) {
var require = function(module, callback) {
return _require("", module, callback);
};
var root = global;
if (ns) {
if (!global[ns])
@ -170,13 +157,13 @@ function exportAce(ns) {
}
if (!root.define || !root.define.packaged) {
_define.original = root.define;
root.define = _define;
define.original = root.define;
root.define = define;
root.define.packaged = true;
}
if (!root.require || !root.require.packaged) {
_require.original = root.require;
require.original = root.require;
root.require = require;
root.require.packaged = true;
}

View file

@ -7,14 +7,13 @@
<style type="text/css" media="screen">
.ace_editor {
position: relative !important;
border: 1px solid lightgray;
margin: auto;
height: 200px;
width: 80%;
}
.scrollmargin {
height: 100px;
height: 80px;
text-align: center;
}
</style>
@ -24,6 +23,8 @@
<div class="scrollmargin"></div>
<pre id="editor2">minHeight = 2 lines</pre>
<div class="scrollmargin"></div>
<pre id="editor3" style="width: 40%;"></pre>
<div class="scrollmargin"></div>
<pre id="editor"></pre>
<script src="kitchen-sink/require.js"></script>
@ -46,6 +47,13 @@ require(["ace/ace"], function(ace) {
editor2.setOption("maxLines", 30);
editor2.setOption("minLines", 2);
var editor = ace.edit("editor3");
editor.setOptions({
autoScrollEditorIntoView: true,
maxLines: 8
});
editor.renderer.setScrollMargin(10, 10, 10, 10);
var editor = ace.edit("editor");
editor.setTheme("ace/theme/tomorrow");
editor.session.setMode("ace/mode/html");

View file

@ -23,7 +23,7 @@
<pre id="editor"></pre>
<!-- load emmet code and snippets compiled for browser -->
<script src="https://nightwing.github.io/emmet-core/emmet.js"></script>
<script src="https://cloud9ide.github.io/emmet-core/emmet.js"></script>
<script src="kitchen-sink/require.js"></script>
<script>

View file

@ -531,7 +531,7 @@ new StatusBar(env.editor, cmdLine.container);
var Emmet = require("ace/ext/emmet");
net.loadScript("https://nightwing.github.io/emmet-core/emmet.js", function() {
net.loadScript("https://cloud9ide.github.io/emmet-core/emmet.js", function() {
Emmet.setCore(window.emmet);
env.editor.setOption("enableEmmet", true);
});

View file

@ -29,13 +29,17 @@
* ***** END LICENSE BLOCK ***** */
define(function(require, exports, module) {
// allow easy access to ace in console, but not in ace code which uses strict
function isStrict() {
try { return !arguments.callee.caller.caller.caller}
catch(e){ return true }
}
var dom = require("ace/lib/dom");
var Range = require("ace/range").Range;
function warn() {
if (isStrict()) {
var s = (new Error()).stack || "";
s = s.split("\n");
if (s[1] == "Error") s.shift(); // remove error description on chrome
s.shift(); // remove warn
s.shift(); // remove the getter
s = s.join("\n");
// allow easy access to ace in console, but not in ace code
if (!/at Object.InjectedScript.|@debugger eval|snippets:\/{3}|\(<anonymous>:\d+:\d+\)/.test(s)) {
console.error("trying to access to global variable");
}
}
@ -59,21 +63,155 @@ def(window, "session", function(){ warn(); return window.env.editor.session });
def(window, "split", function(){ warn(); return window.env.split });
/* for textinput debuggging
dom.importCssString("\
.ace_text-input {\
position: absolute;\
z-index: 10!important;\
width: 6em!important;\
height: 1em;\
opacity: 1!important;\
background: rgba(0, 92, 255, 0.11);\
border: none;\
font: inherit;\
padding: 0 1px;\
margin: 0 -1px;\
text-indent: 0em;\
}\
")*/
def(window, "devUtil", function(){ warn(); return exports });
exports.showTextArea = function(argument) {
dom.importCssString("\
.ace_text-input {\
position: absolute;\
z-index: 10!important;\
width: 6em!important;\
height: 1em;\
opacity: 1!important;\
background: rgba(0, 92, 255, 0.11);\
border: none;\
font: inherit;\
padding: 0 1px;\
margin: 0 -1px;\
text-indent: 0em;\
}\
");
};
exports.addGlobals = function() {
window.oop = require("ace/lib/oop");
window.dom = require("ace/lib/dom");
window.Range = require("ace/range").Range;
window.Editor = require("ace/editor").Editor;
window.assert = require("ace/test/asyncjs/assert");
window.asyncjs = require("ace/test/asyncjs/async");
window.UndoManager = require("ace/undomanager").UndoManager;
window.EditSession = require("ace/edit_session").EditSession;
window.MockRenderer = require("ace/test/mockrenderer").MockRenderer;
window.EventEmitter = require("ace/lib/event_emitter").EventEmitter;
window.getSelection = getSelection;
window.setSelection = setSelection;
window.testSelection = testSelection;
};
function getSelection(editor) {
var data = editor.multiSelect.toJSON();
if (!data.length) data = [data];
data = data.map(function(x) {
var a, c;
if (x.isBackwards) {
a = x.end;
c = x.start;
} else {
c = x.end;
a = x.start;
}
return Range.comparePoints(a, c)
? [a.row, a.column, c.row, c.column]
: [a.row, a.column];
});
return data.length > 1 ? data : data[0];
}
function setSelection(editor, data) {
if (typeof data[0] == "number")
data = [data];
editor.selection.fromJSON(data.map(function(x) {
var start = {row: x[0], column: x[1]};
var end = x.length == 2 ? start : {row: x[2], column: x[3]};
var isBackwards = Range.comparePoints(start, end) > 0;
return isBackwards ? {
start: end,
end: start,
isBackwards: true
} : {
start: start,
end: end,
isBackwards: true
};
}));
}
function testSelection(editor, data) {
assert.equal(getSelection(editor) + "", data + "");
}
exports.recordTestCase = function() {
exports.addGlobals();
var editor = window.editor;
var testcase = window.testcase = [];
var assert;
testcase.push({
type: "setValue",
data: editor.getValue()
}, {
type: "setSelection",
data: getSelection(editor)
});
editor.commands.on("afterExec", function(e) {
testcase.push({
type: "exec",
data: e
});
testcase.push({
type: "value",
data: editor.getValue()
});
testcase.push({
type: "selection",
data: getSelection(editor)
});
});
editor.on("mouseup", function() {
testcase.push({
type: "setSelection",
data: getSelection(editor)
});
});
testcase.toString = function() {
var lastValue = "";
// var lastSelection = ""
var str = this.map(function(x) {
var data = x.data;
switch (x.type) {
case "exec":
return 'editor.execCommand("'
+ data.command.name
+ (data.args ? '", ' + JSON.stringify(data.args) : '"')
+ ')';
case "setSelection":
return 'setSelection(editor, ' + JSON.stringify(data) + ')';
case "setValue":
if (lastValue != data) {
lastValue = data;
return 'editor.setValue(' + JSON.stringify(data) + ', -1)';
}
return;
case "selection":
return 'testSelection(editor, ' + JSON.stringify(data) + ')';
case "value":
if (lastValue != data) {
lastValue = data;
return 'assert.equal('
+ 'editor.getValue(),'
+ JSON.stringify(data)
+ ')';
}
return;
}
}).filter(Boolean).join("\n");
return getSelection + "\n"
+ testSelection + "\n"
+ setSelection + "\n"
+ "\n" + str + "\n";
};
};
});

View file

@ -86,9 +86,12 @@ var ownSource = {
/* filled from require*/
};
var hugeDocs = {
var hugeDocs = require.toUrl ? {
"build/src/ace.js": "",
"build/src-min/ace.js": ""
} : {
"src/ace.js": "",
"src-min/ace.js": ""
};
modelist.modes.forEach(function(m) {
@ -166,13 +169,44 @@ function loadDoc(name, callback) {
});
}
function saveDoc(name, callback) {
var doc = fileCache[name] || name;
if (!doc || !doc.session)
return callback("Unknown document: " + name);
var path = doc.path;
var parts = path.split("/");
if (parts[0] == "docs")
path = "demo/kitchen-sink/" + path;
else if (parts[0] == "ace")
path = "lib/" + path;
upload(path, doc.session.getValue(), callback);
}
function upload(url, data, callback) {
url = net.qualifyURL(url);
if (!/https?:/.test(url))
return callback(new Error("Unsupported url scheme"));
var xhr = new XMLHttpRequest();
xhr.open("PUT", url, true);
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
callback(!/^2../.test(xhr.status));
}
};
xhr.send(data);
};
module.exports = {
fileCache: fileCache,
docs: sort(prepareDocList(docs)),
ownSource: prepareDocList(ownSource),
hugeDocs: prepareDocList(hugeDocs),
initDoc: initDoc,
loadDoc: loadDoc
loadDoc: loadDoc,
saveDoc: saveDoc,
};
module.exports.all = {
"Mode Examples": module.exports.docs,

View file

@ -0,0 +1,171 @@
%abc-2.1
H:This file contains some example English tunes
% note that the comments (like this one) are to highlight usages
% and would not normally be included in such detail
O:England % the origin of all tunes is England
X:1 % tune no 1
T:Dusty Miller, The % title
T:Binny's Jig % an alternative title
C:Trad. % traditional
R:DH % double hornpipe
M:3/4 % meter
K:G % key
B>cd BAG|FA Ac BA|B>cd BAG|DG GB AG:|
Bdd gfg|aA Ac BA|Bdd gfa|gG GB AG:|
BG G/2G/2G BG|FA Ac BA|BG G/2G/2G BG|DG GB AG:|
W:Hey, the dusty miller, and his dusty coat;
W:He will win a shilling, or he spend a groat.
W:Dusty was the coat, dusty was the colour;
W:Dusty was the kiss, that I got frae the miller.
X:2
T:Old Sir Simon the King
C:Trad.
S:Offord MSS % from Offord manuscript
N:see also Playford % reference note
M:9/8
R:SJ % slip jig
N:originally in C % transcription note
K:G
D|GFG GAG G2D|GFG GAG F2D|EFE EFE EFG|A2G F2E D2:|
D|GAG GAB d2D|GAG GAB c2D|[1 EFE EFE EFG|[A2G] F2E D2:|\ % no line-break in score
M:12/8 % change of meter
[2 E2E EFE E2E EFG|\ % no line-break in score
M:9/8 % change of meter
A2G F2E D2|]
X:3
T:William and Nancy
T:New Mown Hay
T:Legacy, The
C:Trad.
O:England; Gloucs; Bledington % place of origin
B:Sussex Tune Book % can be found in these books
B:Mally's Cotswold Morris vol.1 2
D:Morris On % can be heard on this record
P:(AB)2(AC)2A % play the parts in this order
M:6/8
K:G
[P:A] D|"G"G2G GBd|"C"e2e "G"dBG|"D7"A2d "G"BAG|"C"E2"D7"F "G"G2:|
[P:B] d|"G"e2d B2d|"C"gfe "G"d2d| "G"e2d B2d|"C"gfe "D7"d2c|
"G"B2B Bcd|"C"e2e "G"dBG|"D7"A2d "G"BAG|"C"E2"D7"F "G"G2:|
% changes of meter, using inline fields
[T:Slows][M:4/4][L:1/4][P:C]"G"d2|"C"e2 "G"d2|B2 d2|"Em"gf "A7"e2|"D7"d2 "G"d2|\
"C"e2 "G"d2|[M:3/8][L:1/8] "G"B2 d |[M:6/8] "C"gfe "D7"d2c|
"G"B2B Bcd|"C"e2e "G"dBG|"D7"A2d "G"BAG|"C"E2"D7"F "G"G2:|
X:4
T:South Downs Jig
R:jig
S:Robert Harbron
M:6/8
L:1/8
K:G
|: d | dcA G3 | EFG AFE | DEF GAB | cde d2d |
dcA G3 | EFG AFE | DEF GAB | cAF G2 :|
B | Bcd e2c | d2B c2A | Bcd e2c | [M:9/8]d2B c2B A3 |
[M:6/8]DGF E3 | cBA FED | DEF GAB |1 cAF G2 :|2 cAF G3 |]
X:5
T:Atholl Brose
% in this example, which reproduces Highland Bagpipe gracing,
% the large number of grace notes mean that it is more convenient to be specific about
% score line-breaks (using the $ symbol), rather than using code line breaks to indicate them
I:linebreak $
K:D
{gcd}c<{e}A {gAGAG}A2 {gef}e>A {gAGAG}Ad|
{gcd}c<{e}A {gAGAG}A>e {ag}a>f {gef}e>d|
{gcd}c<{e}A {gAGAG}A2 {gef}e>A {gAGAG}Ad|
{g}c/d/e {g}G>{d}B {gf}gG {dc}d>B:|$
{g}c<e {gf}g>e {ag}a>e {gf}g>e|
{g}c<e {gf}g>e {ag}a2 {GdG}a>d|
{g}c<e {gf}g>e {ag}a>e {gf}g>f|
{gef}e>d {gf}g>d {gBd}B<{e}G {dc}d>B|
{g}c<e {gf}g>e {ag}a>e {gf}g>e|
{g}c<e {gf}g>e {ag}a2 {GdG}ad|
{g}c<{GdG}e {gf}ga {f}g>e {g}f>d|
{g}e/f/g {Gdc}d>c {gBd}B<{e}G {dc}d2|]
X:6
T:Untitled Reel
C:Trad.
K:D
eg|a2ab ageg|agbg agef|g2g2 fgag|f2d2 d2:|\
ed|cecA B2ed|cAcA E2ed|cecA B2ed|c2A2 A2:|
K:G
AB|cdec BcdB|ABAF GFE2|cdec BcdB|c2A2 A2:|
X:7
T:Kitchen Girl
C:Trad.
K:D
[c4a4] [B4g4]|efed c2cd|e2f2 gaba|g2e2 e2fg|
a4 g4|efed cdef|g2d2 efed|c2A2 A4:|
K:G
ABcA BAGB|ABAG EDEG|A2AB c2d2|e3f edcB|ABcA BAGB|
ABAG EGAB|cBAc BAG2|A4 A4:|
%abc-2.1
%%pagewidth 21cm
%%pageheight 29.7cm
%%topspace 0.5cm
%%topmargin 1cm
%%botmargin 0cm
%%leftmargin 1cm
%%rightmargin 1cm
%%titlespace 0cm
%%titlefont Times-Bold 32
%%subtitlefont Times-Bold 24
%%composerfont Times 16
%%vocalfont Times-Roman 14
%%staffsep 60pt
%%sysstaffsep 20pt
%%musicspace 1cm
%%vocalspace 5pt
%%measurenb 0
%%barsperstaff 5
%%scale 0.7
X: 1
T: Canzonetta a tre voci
C: Claudio Monteverdi (1567-1643)
M: C
L: 1/4
Q: "Andante mosso" 1/4 = 110
%%score [1 2 3]
V: 1 clef=treble name="Soprano"sname="A"
V: 2 clef=treble name="Alto" sname="T"
V: 3 clef=bass middle=d name="Tenor" sname="B"
%%MIDI program 1 75 % recorder
%%MIDI program 2 75
%%MIDI program 3 75
K: Eb
% 1 - 4
[V: 1] |:z4 |z4 |f2ec |_ddcc |
w: Son que-sti~i cre-spi cri-ni~e
w: Que-sti son gli~oc-chi che mi-
[V: 2] |:c2BG|AAGc|(F/G/A/B/)c=A|B2AA |
w: Son que-sti~i cre-spi cri-ni~e que - - - - sto~il vi-so e
w: Que-sti son~gli oc-chi che mi-ran - - - - do fi-so mi-
[V: 3] |:z4 |f2ec|_ddcf |(B/c/_d/e/)ff|
w: Son que-sti~i cre-spi cri-ni~e que - - - - sto~il
w: Que-sti son~gli oc-chi che mi-ran - - - - do
% 5 - 9
[V: 1] cAB2 |cAAA |c3B|G2!fermata!Gz ::e4|
w: que-sto~il vi-so ond' io ri-man-go~uc-ci-so. Deh,
w: ran-do fi-so, tut-to re-stai con-qui-so.
[V: 2] AAG2 |AFFF |A3F|=E2!fermata!Ez::c4|
w: que-sto~il vi-so ond' io ri-man-go~uc-ci-so. Deh,
w: ran-do fi-so tut-to re-stai con-qui-so.
[V: 3] (ag/f/e2)|A_ddd|A3B|c2!fermata!cz ::A4|
w: vi - - - so ond' io ti-man-go~uc-ci-so. Deh,
w: fi - - - so tut-to re-stai con-qui-so.
% 10 - 15
[V: 1] f_dec |B2c2|zAGF |\
w: dim-me-lo ben mi-o, che que-sto\
=EFG2 |1F2z2:|2F8|] % more notes
w: sol de-si-o_. % more lyrics
[V: 2] ABGA |G2AA|GF=EF |(GF3/2=E//D//E)|1F2z2:|2F8|]
w: dim-me-lo ben mi-o, che que-sto sol de-si - - - - o_.
[V: 3] _dBc>d|e2AF|=EFc_d|c4 |1F2z2:|2F8|]
w: dim-me-lo ben mi-o, che que-sto sol de-si-o_.

View file

@ -3,6 +3,6 @@
<div id="comments">
{{#each comments}}
<h2><a href="/posts/{{../permalink}}#{{id}}">{{title}}</a></h2>
<div>{{body}}</div>
<div>{{{body}}}</div>
{{/each}}
</div>

View file

@ -0,0 +1,9 @@
import logic
section
variables (A : Type) (p q : A Prop)
example : (x : A, p x q x) y : A, p y :=
assume H : x : A, p x q x,
take y : A,
show p y, from and.elim_left (H y)
end

View file

@ -0,0 +1,52 @@
/* Mask Syntax Demo */
div > ' Test ~[name]';
define :userProfile {
header {
h4 > @title;
button.close;
}
}
:userProfile {
@title > ' Hello ~[: username.toUpperCase()]'
}
style {
html, body {
background: url('name.png') 0 0 no-repeat;
}
}
button {
event click (e) {
this.textContent = `name ${e.clientX} !`;
}
}
md > """
- div
- span
Hello
[one](http://google.com)
""";
header .foo > 'Heading'
button .baz x-signal='click: test' disabled > "
Hello,
world
\"Buddy\"
"
var a = {
name: `name ${window.innerWidth}`
};
span .foo > "~[bind: a.name]"

View file

@ -20,7 +20,7 @@ class Range
end
end
{:id => 34, :key => "value"}
{:id => ?", :key => "value"}
herDocs = [<<'FOO', <<BAR, <<-BAZ, <<-`EXEC`] #comment

View file

@ -0,0 +1,72 @@
-- =============================================
-- Author: Morgan Yarbrough
-- Create date: 4/27/2015
-- Description: Test procedure that shows off language features.
-- Includes non-standard folding with region comments using either
-- line comments or block comments (both are demonstrated below).
-- This mode imitates SSMS and it designed to be used with SQL Server theme.
-- =============================================
CREATE PROCEDURE dbo.TestProcedure
--#region parameters
@vint INT = 1
,@vdate DATE = NULL
,@vdatetime DATETIME = DATEADD(dd, 1, GETDATE())
,@vvarchar VARCHAR(MAX) = ''
--#endregion
AS
BEGIN
/*#region set statements */
SET NOCOUNT ON;
SET XACT_ABORT ON;
SET QUOTED_IDENTIFIER ON;
/*#endregion*/
/**
* These comments will produce a fold widget
*/
-- folding demonstration
SET @vint = CASE
WHEN @vdate IS NULL
THEN 1
ELSE 2
END
-- another folding demonstration
IF @vint = 1
BEGIN
SET @vvarchar = 'one'
SET @vint = DATEDIFF(dd, @vdate, @vdatetime)
END
-- this mode handles strings properly
DECLARE @sql NVARCHAR(4000) = N'SELECT TOP(1) OrderID
FROM Orders
WHERE @OrderDate > GETDATE()'
-- this mode is aware of built in stored procedures
EXECUTE sp_executesql @sql
-- demonstrating some syntax highlighting
SELECT Orders.OrderID
,Customers.CompanyName
,DATEFROMPARTS(YEAR(GETDATE()), 1, 1) AS FirstDayOfYear
FROM Orders
INNER JOIN Customers
ON Orders.CustomerID = Customers.CustomerID
WHERE CompanyName NOT LIKE '%something'
OR CompanyName IS NULL
OR CompanyName IN ('bla', 'nothing')
-- this mode includes snippets
-- place your cusor at the end of the line below and trigger auto complete (Ctrl+Space)
createpr
-- SQL Server allows using keywords as object names (not recommended) as long as they are wrapped in brackets
DATABASE -- keyword
[DATABASE] -- not a keyword
END

View file

@ -53,16 +53,16 @@ require("ace/commands/default_commands").commands.push({
return;
}
var rowCount = 10;
var rowCount = 10;
var w = {
row: row,
// rowCount: rowCount,
fixedWidth: true,
el: dom.createElement("div"),
editor: editor
editor: inlineEditor
};
var el = w.el;
el.appendChild(inlineEditor.container);
el.appendChild(inlineEditor.container);
if (!editor.session.widgetManager) {
editor.session.widgetManager = new LineWidgets(editor.session);

View file

@ -2,13 +2,13 @@
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Static Code highlighter using Ace</title>
<meta name="author" content="Matthew Kastor">
<title>Static Code highlighter using Ace</title>
<meta name="author" content="Matthew Kastor">
<style type="text/css">
.code {
width: 50%;
position: relative;
white-space: pre-wrap;
border: solid lightgrey 1px
}
</style>
</head>
@ -21,9 +21,8 @@
<div class="code" ace-mode="ace/mode/css" ace-theme="ace/theme/chrome" ace-gutter="true">
.code {
width: 50%;
position: relative;
white-space: pre-wrap;
border: solid lightgrey 1px
}
</div>
@ -35,6 +34,26 @@ function wobble (flam) {
</pre>
<div class="code" ace-mode="ace/mode/lua" ace-theme="ace/theme/chrome" ace-gutter="true" style="width: 30em;">
--[[--
num_args takes in 5.1 byte code and extracts the number of arguments from its function header.
--]]--
function int(t)
return t:byte(1) + t:byte(2) * 0x100 + t:byte(3) * 0x10000 + t:byte(4) * 0x1000000
end
function num_args(func)
local dump = string.dump(func)
local offset, cursor = int(dump:sub(13)), offset + 26
--Get the params and var flag (whether there's a ... in the param)
return dump:sub(cursor):byte(), dump:sub(cursor+1):byte()
end
</div>
<script src="kitchen-sink/require.js"></script>
<script>
require.config({paths: { "ace" : "../lib/ace"}});

View file

@ -2,15 +2,13 @@
* Simple node.js server, which generates the synax highlighted version of itself
* using the Ace modes and themes on the server and serving a static web page.
*/
// $'
// include ace search path and modules
require("amd-loader");
// load jsdom, which is required by Ace
require("../../lib/ace/test/mockdom");
var http = require("http");
var fs = require("fs");
var resolve = require("path").resolve;
// load the highlighter and the desired mode and theme
var highlighter = require("../../lib/ace/ext/static_highlight");
@ -20,15 +18,22 @@ var theme = require("../../lib/ace/theme/twilight");
var port = process.env.PORT || 2222;
http.createServer(function(req, res) {
var url = req.url;
var path = /[^#?\x00]*/.exec(url)[0];
var root = resolve(__dirname + "/../../").replace(/\\/g, "/");
path = resolve(root + "/" + path).replace(/\\/g, "/");
if (path.indexOf(root + "/") != 0)
path = __filename;
res.writeHead(200, {"Content-Type": "text/html; charset=utf-8"});
fs.readFile(__filename, "utf8", function(err, data) {
fs.readFile(path, "utf8", function(err, data) {
if (err) data = err.message;
var highlighted = highlighter.render(data, new JavaScriptMode(), theme);
res.end(
'<html><body>\n' +
'<style type="text/css" media="screen">\n' +
highlighted.css +
'</style>\n' +
highlighted.html +
highlighted.html +
'</body></html>'
);
});

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

View file

@ -18,7 +18,7 @@ $(function() {
});
ace.config.loadModule("ace/ext/emmet", function() {
ace.require("ace/lib/net").loadScript("http://nightwing.github.io/emmet-core/emmet.js", function() {
ace.require("ace/lib/net").loadScript("http://cloud9ide.github.io/emmet-core/emmet.js", function() {
embedded_editor.setOption("enableEmmet", true);
editor.setOption("enableEmmet", true);
});

View file

@ -0,0 +1,59 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<script src="../demo/kitchen-sink/require.js"></script>
<script type="text/javascript">
require.config({
paths: { ace: "../lib/ace" },
waitSeconds: 0
});
</script>
</head>
<body>
<p><button onclick="toggleEditor()">Toggle editor</button></p>
<div id="container"></div>
<script>
var editor;
var counter = 0
function toggleEditor() {
if (!editor) {
var root = document.createElement("div");
root.style.height = "100px";
root.setAttribute("id", "editor");
root.textContent = "function foo(items) {\nvar x = 'All this is syntax highlighted';\nreturn x;\n}";
document.getElementById("container").appendChild(root);
editor = ace.edit(root);
if (counter++ % 2)
editor.setTheme("ace/theme/monokai");
else
editor.setTheme("ace/theme/clouds");
editor.session.setMode("ace/mode/javascript");
} else {
editor.destroy();
var el = editor.container;
el.parentNode.removeChild(el);
editor.container = null
editor.renderer = null
editor = null;
var root = document.getElementById("editor")
if (root)
root.parentNode.removeChild(root);
}
}
require(["ace/ace"], function(ace) {
window.ace = ace;
toggleEditor();
})
</script>
</body>
</html>

File diff suppressed because one or more lines are too long

View file

@ -257,7 +257,9 @@
<a href="http://ace.c9.io">
<img id="ace-logo" src="doc/site/images/ace-logo.png" style="width: 134px;margin: 46px 0px 4px 66px;">
</a>
<div><a target="_test" href="./lib/ace/test/tests.html"
style="color: whitesmoke; text-align: left; padding: 1em;">tests</a>
</div>
</div>
</div>
</div>

View file

@ -99,72 +99,54 @@ var Anchor = exports.Anchor = function(doc, row, column) {
* - `value`: An object describing the new Anchor position
*
**/
this.onChange = function(e) {
var delta = e.data;
var range = delta.range;
if (range.start.row == range.end.row && range.start.row != this.row)
this.onChange = function(delta) {
if (delta.start.row == delta.end.row && delta.start.row != this.row)
return;
if (range.start.row > this.row)
if (delta.start.row > this.row)
return;
if (range.start.row == this.row && range.start.column > this.column)
return;
var row = this.row;
var column = this.column;
var start = range.start;
var end = range.end;
if (delta.action === "insertText") {
if (start.row === row && start.column <= column) {
if (start.column === column && this.$insertRight) {
// do nothing
} else if (start.row === end.row) {
column += end.column - start.column;
} else {
column -= start.column;
row += end.row - start.row;
}
} else if (start.row !== end.row && start.row < row) {
row += end.row - start.row;
}
} else if (delta.action === "insertLines") {
if (start.row === row && column === 0 && this.$insertRight) {
// do nothing
}
else if (start.row <= row) {
row += end.row - start.row;
}
} else if (delta.action === "removeText") {
if (start.row === row && start.column < column) {
if (end.column >= column)
column = start.column;
else
column = Math.max(0, column - (end.column - start.column));
} else if (start.row !== end.row && start.row < row) {
if (end.row === row)
column = Math.max(0, column - end.column) + start.column;
row -= (end.row - start.row);
} else if (end.row === row) {
row -= end.row - start.row;
column = Math.max(0, column - end.column) + start.column;
}
} else if (delta.action == "removeLines") {
if (start.row <= row) {
if (end.row <= row)
row -= end.row - start.row;
else {
row = start.row;
column = 0;
}
}
}
this.setPosition(row, column, true);
var point = $getTransformedPoint(delta, {row: this.row, column: this.column}, this.$insertRight);
this.setPosition(point.row, point.column, true);
};
function $pointsInOrder(point1, point2, equalPointsInOrder) {
var bColIsAfter = equalPointsInOrder ? point1.column <= point2.column : point1.column < point2.column;
return (point1.row < point2.row) || (point1.row == point2.row && bColIsAfter);
}
function $getTransformedPoint(delta, point, moveIfEqual) {
// Get delta info.
var deltaIsInsert = delta.action == "insert";
var deltaRowShift = (deltaIsInsert ? 1 : -1) * (delta.end.row - delta.start.row);
var deltaColShift = (deltaIsInsert ? 1 : -1) * (delta.end.column - delta.start.column);
var deltaStart = delta.start;
var deltaEnd = deltaIsInsert ? deltaStart : delta.end; // Collapse insert range.
// DELTA AFTER POINT: No change needed.
if ($pointsInOrder(point, deltaStart, moveIfEqual)) {
return {
row: point.row,
column: point.column
};
}
// DELTA BEFORE POINT: Move point by delta shift.
if ($pointsInOrder(deltaEnd, point, !moveIfEqual)) {
return {
row: point.row + deltaRowShift,
column: point.column + (point.row == deltaEnd.row ? deltaColShift : 0)
};
}
// DELTA ENVELOPS POINT (delete only): Move point to delta start.
// TODO warn if delta.action != "remove" ?
return {
row: deltaStart.row,
column: deltaStart.column
};
}
/**
* Sets the anchor position to the specified row and column. If `noClip` is `true`, the position is not clipped.

View file

@ -71,7 +71,7 @@ module.exports = {
var doc = new Document("juhu\nkinners");
var anchor = new Anchor(doc, 1, 4);
doc.insertLines(1, ["123", "456"]);
doc.insertFullLines(1, ["123", "456"]);
assert.position(anchor.getPosition(), 3, 4);
},
@ -105,7 +105,7 @@ module.exports = {
var doc = new Document("juhu\nkinners");
var anchor = new Anchor(doc, 1, 4);
doc.insertNewLine({row: 0, column: 0});
doc.insertMergedLines({row: 0, column: 0}, ['', '']);
assert.position(anchor.getPosition(), 2, 4);
},
@ -113,7 +113,7 @@ module.exports = {
var doc = new Document("juhu\nkinners");
var anchor = new Anchor(doc, 1, 4);
doc.insertNewLine({row: 1, column: 2});
doc.insertMergedLines({row: 1, column: 2}, ['', '']);
assert.position(anchor.getPosition(), 2, 2);
},
@ -145,7 +145,7 @@ module.exports = {
var doc = new Document("juhu\n1\n2\nkinners");
var anchor = new Anchor(doc, 3, 4);
doc.removeLines(1, 2);
doc.removeFullLines(1, 2);
assert.position(anchor.getPosition(), 1, 4);
},
@ -169,7 +169,7 @@ module.exports = {
var doc = new Document("juhu\nkinners\n123");
var anchor = new Anchor(doc, 1, 5);
doc.removeLines(1, 1);
doc.removeFullLines(1, 1);
assert.position(anchor.getPosition(), 1, 0);
},
@ -208,9 +208,9 @@ module.exports = {
var doc = new Document("juhu\nkinners\n123");
var anchor = new Anchor(doc, 2, 4);
doc.removeLines(0, 3);
doc.removeFullLines(0, 3);
assert.position(anchor.getPosition(), 0, 0);
doc.insertLines(0, ["a", "b", "c"]);
doc.insertFullLines(0, ["a", "b", "c"]);
assert.position(anchor.getPosition(), 3, 0);
assert.equal(doc.getValue(), "a\nb\nc\n");
}

108
lib/ace/apply_delta.js Normal file
View file

@ -0,0 +1,108 @@
/* ***** 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";
function throwDeltaError(delta, errorText){
console.log("Invalid Delta:", delta);
throw "Invalid Delta: " + errorText;
}
function positionInDocument(docLines, position) {
return position.row >= 0 && position.row < docLines.length &&
position.column >= 0 && position.column <= docLines[position.row].length;
}
function validateDelta(docLines, delta) {
// Validate action string.
if (delta.action != "insert" && delta.action != "remove")
throwDeltaError(delta, "delta.action must be 'insert' or 'remove'");
// Validate lines type.
if (!(delta.lines instanceof Array))
throwDeltaError(delta, "delta.lines must be an Array");
// Validate range type.
if (!delta.start || !delta.end)
throwDeltaError(delta, "delta.start/end must be an present");
// Validate that the start point is contained in the document.
var start = delta.start;
if (!positionInDocument(docLines, delta.start))
throwDeltaError(delta, "delta.start must be contained in document");
// Validate that the end point is contained in the document (remove deltas only).
var end = delta.end;
if (delta.action == "remove" && !positionInDocument(docLines, end))
throwDeltaError(delta, "delta.end must contained in document for 'remove' actions");
// Validate that the .range size matches the .lines size.
var numRangeRows = end.row - start.row;
var numRangeLastLineChars = (end.column - (numRangeRows == 0 ? start.column : 0));
if (numRangeRows != delta.lines.length - 1 || delta.lines[numRangeRows].length != numRangeLastLineChars)
throwDeltaError(delta, "delta.range must match delta lines");
}
exports.applyDelta = function(docLines, delta, doNotValidate) {
// disabled validation since it breaks autocompletion popup
// if (!doNotValidate)
// validateDelta(docLines, delta);
var row = delta.start.row;
var startColumn = delta.start.column;
var line = docLines[row] || "";
switch (delta.action) {
case "insert":
var lines = delta.lines;
if (lines.length === 1) {
docLines[row] = line.substring(0, startColumn) + delta.lines[0] + line.substring(startColumn);
} else {
var args = [row, 1].concat(delta.lines);
docLines.splice.apply(docLines, args);
docLines[row] = line.substring(0, startColumn) + docLines[row];
docLines[row + delta.lines.length - 1] += line.substring(startColumn);
}
break;
case "remove":
var endColumn = delta.end.column;
var endRow = delta.end.row;
if (row === endRow) {
docLines[row] = line.substring(0, startColumn) + line.substring(endColumn);
} else {
docLines.splice(
row, endRow - row + 1,
line.substring(0, startColumn) + docLines[endRow].substring(endColumn)
);
}
break;
}
}
});

View file

@ -40,8 +40,10 @@ var dom = require("./lib/dom");
var snippetManager = require("./snippets").snippetManager;
var Autocomplete = function() {
this.autoInsert = true;
this.autoInsert = false;
this.autoSelect = true;
this.exactMatch = false;
this.gatherCompletionsId = 0;
this.keyboardHandler = new HashHandler();
this.keyboardHandler.bindKeys(this.commands);
@ -53,12 +55,11 @@ var Autocomplete = function() {
this.changeTimer = lang.delayedCall(function() {
this.updateCompletions(true);
}.bind(this));
this.tooltipTimer = lang.delayedCall(this.updateDocTooltip.bind(this), 50);
};
(function() {
this.gatherCompletionsId = 0;
this.$init = function() {
this.popup = new AcePopup(document.body || document.documentElement);
@ -72,7 +73,7 @@ var Autocomplete = function() {
this.popup.on("changeHoverMarker", this.tooltipTimer.bind(null, null));
return this.popup;
};
this.getPopup = function() {
return this.popup || this.$init();
};
@ -83,6 +84,8 @@ var Autocomplete = function() {
this.popup.setData(this.completions.filtered);
editor.keyBinding.addKeyboardHandler(this.keyboardHandler);
var renderer = editor.renderer;
this.popup.setRow(this.autoSelect ? 0 : -1);
if (!keepPopupPosition) {
@ -97,7 +100,7 @@ var Autocomplete = function() {
var rect = editor.container.getBoundingClientRect();
pos.top += rect.top - renderer.layerConfig.offset;
pos.left += rect.left - editor.renderer.scrollLeft;
pos.left += renderer.$gutterLayer.gutterWidth;
pos.left += renderer.gutterWidth;
this.popup.show(pos, lineHeight);
} else if (keepPopupPosition && !prefix) {
@ -114,11 +117,10 @@ var Autocomplete = function() {
this.changeTimer.cancel();
this.hideDocTooltip();
if (this.popup && this.popup.isOpen) {
this.gatherCompletionsId += 1;
this.gatherCompletionsId += 1;
if (this.popup && this.popup.isOpen)
this.popup.hide();
}
if (this.base)
this.base.detach();
this.activated = false;
@ -140,10 +142,11 @@ var Autocomplete = function() {
// 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
var text = this.editor.textInput.getElement();
var fromTooltip = e.relatedTarget && e.relatedTarget == this.tooltipNode;
var container = this.popup && this.popup.container;
if (el != text && el.parentNode != container && !fromTooltip
&& el != this.tooltipNode && e.relatedTarget != text
) {
this.detach();
}
@ -203,7 +206,6 @@ var Autocomplete = function() {
"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) {
@ -227,7 +229,7 @@ var Autocomplete = function() {
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) {
@ -260,7 +262,6 @@ var Autocomplete = function() {
editor.completer = this;
}
editor.keyBinding.addKeyboardHandler(this.keyboardHandler);
editor.on("changeSelection", this.changeListener);
editor.on("blur", this.blurListener);
editor.on("mousedown", this.mousedownListener);
@ -297,7 +298,7 @@ var Autocomplete = function() {
var prefix = results.prefix;
var matches = results && results.matches;
if (!matches || !matches.length)
return detachIfFinished();
@ -306,6 +307,10 @@ var Autocomplete = function() {
return;
this.completions = new FilteredList(matches);
if (this.exactMatch)
this.completions.exactMatch = true;
this.completions.setFilter(prefix);
var filtered = this.completions.filtered;
@ -328,7 +333,7 @@ var Autocomplete = function() {
this.cancelContextMenu = function() {
this.editor.$mouseHandler.cancelContextMenu();
};
this.updateDocTooltip = function() {
var popup = this.popup;
var all = popup.data;
@ -343,14 +348,14 @@ var Autocomplete = function() {
});
if (!doc)
doc = selected;
if (typeof doc == "string")
doc = {docText: doc}
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");
@ -360,21 +365,21 @@ var Autocomplete = function() {
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);
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 = "";
@ -384,7 +389,7 @@ var Autocomplete = function() {
}
tooltipNode.style.display = "block";
};
this.hideDocTooltip = function() {
this.tooltipTimer.cancel();
if (!this.tooltipNode) return;
@ -392,7 +397,7 @@ var Autocomplete = function() {
if (!this.editor.isFocused() && document.activeElement == el)
this.editor.focus();
this.tooltipNode = null;
if (el.parentNode)
if (el.parentNode)
el.parentNode.removeChild(el);
};
@ -403,19 +408,20 @@ Autocomplete.startCommand = {
exec: function(editor) {
if (!editor.completer)
editor.completer = new Autocomplete();
editor.completer.autoInsert =
editor.completer.autoInsert = false;
editor.completer.autoSelect = true;
editor.completer.showPopup(editor);
// needed for firefox on mac
// 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) {
var FilteredList = function(array, filterText) {
this.all = array;
this.filtered = array;
this.filterText = filterText || "";
this.exactMatch = false;
};
(function(){
this.setFilter = function(str) {
@ -452,23 +458,29 @@ var FilteredList = function(array, filterText, mutateData) {
var matchMask = 0;
var penalty = 0;
var index, distance;
// 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)
if (this.exactMatch) {
if (needle !== caption.substr(0, needle.length))
continue loop;
distance = index - lastIndex - 1;
if (distance > 0) {
// first char mismatch should be more sensitive
if (lastIndex === -1)
penalty += 10;
penalty += distance;
}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;
}
matchMask = matchMask | (1 << index);
lastIndex = index;
}
item.matchMask = matchMask;
item.exactMatch = penalty ? 0 : 1;

View file

@ -31,7 +31,6 @@
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;
@ -197,8 +196,12 @@ var AcePopup = function(parentNode) {
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});
var metaData = data.meta;
if (metaData.length + data.caption.length > maxW - 2) {
// trim meta to fit this popup and add ellipsis
metaData = metaData.substr(0, maxW - data.caption.length - 3) + "\u2026"
}
tokens.push({type: "rightAlignedText", value: metaData});
}
return tokens;
};
@ -209,14 +212,16 @@ var AcePopup = function(parentNode) {
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.data = list || [];
popup.setRow(0);
};
popup.getData = function(row) {
@ -241,6 +246,7 @@ var AcePopup = function(parentNode) {
popup.on("changeSelection", function() {
if (popup.isOpen)
popup.setRow(popup.selection.lead.row);
popup.renderer.scrollCursorIntoView();
});
popup.hide = function() {
@ -335,4 +341,4 @@ dom.importCssString("\
exports.AcePopup = AcePopup;
});
});

View file

@ -68,11 +68,10 @@ var BackgroundTokenizer = function(tokenizer, editor) {
var endLine = -1;
var doc = self.doc;
var startLine = currentLine;
while (self.lines[currentLine])
currentLine++;
var startLine = currentLine;
var len = doc.getLength();
var processedLines = 0;
self.running = false;
@ -172,13 +171,12 @@ var BackgroundTokenizer = function(tokenizer, editor) {
}
this.$updateOnChange = function(delta) {
var range = delta.range;
var startRow = range.start.row;
var len = range.end.row - startRow;
var startRow = delta.start.row;
var len = delta.end.row - startRow;
if (len === 0) {
this.lines[startRow] = null;
} else if (delta.action == "removeText" || delta.action == "removeLines") {
} else if (delta.action == "remove") {
this.lines.splice(startRow, len + 1, null);
this.states.splice(startRow, len + 1, null);
} else {

View file

@ -75,6 +75,49 @@ module.exports = {
forceTokenize(doc)
testStates(doc, ["comment_regex_allowed", "start", "no_regex"])
},
"test background tokenizer sends update event" : function() {
var doc = new EditSession([
"/*",
"var",
"juhu",
"*/"
]);
doc.setMode("./mode/javascript");
var updateEvent = null;
doc.bgTokenizer.on("update", function(e) {
updateEvent = e.data;
});
function checkEvent(first, last) {
assert.ok(!updateEvent, "unneccessary update event");
doc.bgTokenizer.running = 1;
doc.bgTokenizer.$worker();
assert.ok(updateEvent);
assert.equal([first, last] + "",
[updateEvent.first, updateEvent.last] + "")
updateEvent = null;
}
forceTokenize(doc);
var comment = "comment_regex_allowed";
testStates(doc, [comment, comment, comment, "start"]);
doc.remove(new Range(0,0,0,2));
testStates(doc, [comment, comment, comment, "start"]);
checkEvent(0, 3);
testStates(doc, ["start", "no_regex", "no_regex", "regex"]);
// insert /* and and press down several times quickly
doc.insert({row:0, column:0}, "/*");
doc.getTokens(0);
doc.getTokens(1);
doc.getTokens(2);
checkEvent(0, 3);
forceTokenize(doc);
testStates(doc, [comment, comment, comment, "start"]);
}
};

View file

@ -97,29 +97,33 @@ exports.commands = [{
name: "fold",
bindKey: bindKey("Alt-L|Ctrl-F1", "Command-Alt-L|Command-F1"),
exec: function(editor) { editor.session.toggleFold(false); },
multiSelectAction: "forEach",
scrollIntoView: "center",
readOnly: true
}, {
name: "unfold",
bindKey: bindKey("Alt-Shift-L|Ctrl-Shift-F1", "Command-Alt-Shift-L|Command-Shift-F1"),
exec: function(editor) { editor.session.toggleFold(true); },
multiSelectAction: "forEach",
scrollIntoView: "center",
readOnly: true
}, {
name: "toggleFoldWidget",
bindKey: bindKey("F2", "F2"),
exec: function(editor) { editor.session.toggleFoldWidget(); },
multiSelectAction: "forEach",
scrollIntoView: "center",
readOnly: true
}, {
name: "toggleParentFoldWidget",
bindKey: bindKey("Alt-F2", "Alt-F2"),
exec: function(editor) { editor.session.toggleFoldWidget(true); },
multiSelectAction: "forEach",
scrollIntoView: "center",
readOnly: true
}, {
name: "foldall",
bindKey: bindKey("Ctrl-Alt-0", "Ctrl-Command-Option-0"),
bindKey: bindKey(null, "Ctrl-Command-Option-0"),
exec: function(editor) { editor.session.foldAll(); },
scrollIntoView: "center",
readOnly: true
@ -205,12 +209,14 @@ exports.commands = [{
bindKey: bindKey("Shift-Up", "Shift-Up"),
exec: function(editor) { editor.getSelection().selectUp(); },
multiSelectAction: "forEach",
scrollIntoView: "cursor",
readOnly: true
}, {
name: "golineup",
bindKey: bindKey("Up", "Up|Ctrl-P"),
exec: function(editor, args) { editor.navigateUp(args.times); },
multiSelectAction: "forEach",
scrollIntoView: "cursor",
readOnly: true
}, {
name: "selecttoend",
@ -395,19 +401,34 @@ exports.commands = [{
bindKey: bindKey("Ctrl-P", "Ctrl-P"),
exec: function(editor) { editor.jumpToMatching(); },
multiSelectAction: "forEach",
scrollIntoView: "animate",
readOnly: true
}, {
name: "selecttomatching",
bindKey: bindKey("Ctrl-Shift-P", "Ctrl-Shift-P"),
exec: function(editor) { editor.jumpToMatching(true); },
multiSelectAction: "forEach",
scrollIntoView: "animate",
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"),
bindKey: bindKey(null, null),
exec: function() {},
passEvent: true,
readOnly: true
}, {
name: "copy",
exec: function(editor) {
// placeholder for replay macro
},
readOnly: true
},
// commands disabled in readOnly mode
@ -424,6 +445,12 @@ exports.commands = [{
},
scrollIntoView: "cursor",
multiSelectAction: "forEach"
}, {
name: "paste",
exec: function(editor, args) {
editor.$handlePaste(args);
},
scrollIntoView: "cursor"
}, {
name: "removeline",
bindKey: bindKey("Ctrl-D", "Command-D"),
@ -458,11 +485,13 @@ exports.commands = [{
name: "modifyNumberUp",
bindKey: bindKey("Ctrl-Shift-Up", "Alt-Shift-Up"),
exec: function(editor) { editor.modifyNumber(1); },
scrollIntoView: "cursor",
multiSelectAction: "forEach"
}, {
name: "modifyNumberDown",
bindKey: bindKey("Ctrl-Shift-Down", "Alt-Shift-Down"),
exec: function(editor) { editor.modifyNumber(-1); },
scrollIntoView: "cursor",
multiSelectAction: "forEach"
}, {
name: "replace",
@ -629,7 +658,7 @@ exports.commands = [{
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 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);
@ -640,7 +669,7 @@ exports.commands = [{
curLine = " " + curLine;
}
insertLine += curLine;
};
}
if (selectionEnd.row + 1 < (editor.session.doc.getLength() - 1)) {
// Don't insert a newline at the end of the document

View file

@ -69,18 +69,14 @@ exports.iSearchCommands = [{
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"},
@ -88,42 +84,30 @@ exports.iSearchCommands = [{
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
exec: function(iSearch) { iSearch.addString(' '); }
}, {
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
exec: function(iSearch) { iSearch.deactivate(); }
}, {
name: 'cancelSearch',
bindKey: 'esc|Ctrl-G',
exec: function(iSearch) { iSearch.deactivate(true); },
readOnly: true,
isIncrementalSearchCommand: true
exec: function(iSearch) { iSearch.deactivate(true); }
}, {
name: 'occurisearch',
bindKey: 'Ctrl-O',
@ -131,9 +115,7 @@ exports.iSearchCommands = [{
var options = oop.mixin({}, iSearch.$options);
iSearch.deactivate();
occurStartCommand.exec(iSearch.$editor, options);
},
readOnly: true,
isIncrementalSearchCommand: true
}
}, {
name: "yankNextWord",
bindKey: "Ctrl-w",
@ -142,9 +124,7 @@ exports.iSearchCommands = [{
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",
@ -153,16 +133,35 @@ exports.iSearchCommands = [{
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
}];
exec: function(iSearch) { iSearch.$editor.execCommand('recenterTopBottom'); }
}, {
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));
}
}, {
name: 'searchAsRegExp',
bindKey: 'Alt-r',
exec: function(iSearch) {
iSearch.convertNeedleToRegExp();
}
}].map(function(cmd) {
cmd.readOnly = true;
cmd.isIncrementalSearchCommand = true;
cmd.scrollIntoView = "animate-cursor";
return cmd;
});
function IncrementalSearchKeyboardHandler(iSearch) {
this.$iSearch = iSearch;
@ -170,7 +169,7 @@ function IncrementalSearchKeyboardHandler(iSearch) {
oop.inherits(IncrementalSearchKeyboardHandler, HashHandler);
;(function() {
(function() {
this.attach = function(editor) {
var iSearch = this.$iSearch;
@ -179,15 +178,19 @@ oop.inherits(IncrementalSearchKeyboardHandler, HashHandler);
if (!e.command.isIncrementalSearchCommand) return undefined;
e.stopPropagation();
e.preventDefault();
return e.command.exec(iSearch, e.args || {});
var scrollTop = editor.session.getScrollTop();
var result = e.command.exec(iSearch, e.args || {});
editor.renderer.scrollCursorIntoView(null, 0.5);
editor.renderer.animateScrolling(scrollTop);
return result;
});
}
};
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) {
@ -200,7 +203,7 @@ oop.inherits(IncrementalSearchKeyboardHandler, HashHandler);
if (extendCmd) { return {command: extendCmd, args: key}; }
}
return {command: "null", passEvent: hashId == 0 || hashId == 4};
}
};
}).call(IncrementalSearchKeyboardHandler.prototype);

View file

@ -35,41 +35,49 @@ exports.defaultCommands = [{
name: "addCursorAbove",
exec: function(editor) { editor.selectMoreLines(-1); },
bindKey: {win: "Ctrl-Alt-Up", mac: "Ctrl-Alt-Up"},
scrollIntoView: "cursor",
readonly: true
}, {
name: "addCursorBelow",
exec: function(editor) { editor.selectMoreLines(1); },
bindKey: {win: "Ctrl-Alt-Down", mac: "Ctrl-Alt-Down"},
scrollIntoView: "cursor",
readonly: true
}, {
name: "addCursorAboveSkipCurrent",
exec: function(editor) { editor.selectMoreLines(-1, true); },
bindKey: {win: "Ctrl-Alt-Shift-Up", mac: "Ctrl-Alt-Shift-Up"},
scrollIntoView: "cursor",
readonly: true
}, {
name: "addCursorBelowSkipCurrent",
exec: function(editor) { editor.selectMoreLines(1, true); },
bindKey: {win: "Ctrl-Alt-Shift-Down", mac: "Ctrl-Alt-Shift-Down"},
scrollIntoView: "cursor",
readonly: true
}, {
name: "selectMoreBefore",
exec: function(editor) { editor.selectMore(-1); },
bindKey: {win: "Ctrl-Alt-Left", mac: "Ctrl-Alt-Left"},
scrollIntoView: "cursor",
readonly: true
}, {
name: "selectMoreAfter",
exec: function(editor) { editor.selectMore(1); },
bindKey: {win: "Ctrl-Alt-Right", mac: "Ctrl-Alt-Right"},
scrollIntoView: "cursor",
readonly: true
}, {
name: "selectNextBefore",
exec: function(editor) { editor.selectMore(-1, true); },
bindKey: {win: "Ctrl-Alt-Shift-Left", mac: "Ctrl-Alt-Shift-Left"},
scrollIntoView: "cursor",
readonly: true
}, {
name: "selectNextAfter",
exec: function(editor) { editor.selectMore(1, true); },
bindKey: {win: "Ctrl-Alt-Shift-Right", mac: "Ctrl-Alt-Shift-Right"},
scrollIntoView: "cursor",
readonly: true
}, {
name: "splitIntoLines",
@ -79,11 +87,13 @@ exports.defaultCommands = [{
}, {
name: "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
}];
@ -92,6 +102,7 @@ exports.multiSelectCommands = [{
name: "singleSelection",
bindKey: "esc",
exec: function(editor) { editor.exitMultiSelectMode(); },
scrollIntoView: "cursor",
readonly: true,
isAvailable: function(editor) {return editor && editor.inMultiSelectMode}
}];

View file

@ -34,10 +34,12 @@ define(function(require, exports, module) {
var lang = require("./lib/lang");
var oop = require("./lib/oop");
var net = require("./lib/net");
var EventEmitter = require("./lib/event_emitter").EventEmitter;
var AppConfig = require("./lib/app_config").AppConfig;
module.exports = exports = new AppConfig();
var global = (function() {
return this;
return this || typeof window != "undefined" && window;
})();
var options = {
@ -69,8 +71,6 @@ exports.all = function() {
};
// module loading
oop.implement(exports, EventEmitter);
exports.moduleUrl = function(name, component) {
if (options.$moduleUrls[name])
return options.$moduleUrls[name];
@ -142,7 +142,6 @@ exports.loadModule = function(moduleName, onLoad) {
net.loadScript(exports.moduleUrl(moduleName, moduleType), afterLoad);
};
// initialization
function init(packaged) {
options.packaged = packaged || require.packaged || module.packaged || (global.define && define.packaged);
@ -200,102 +199,4 @@ function deHyphenate(str) {
return str.replace(/-(.)/g, function(m, m1) { return m1.toUpperCase(); });
}
var optionsProvider = {
setOptions: function(optList) {
Object.keys(optList).forEach(function(key) {
this.setOption(key, optList[key]);
}, this);
},
getOptions: function(optionNames) {
var result = {};
if (!optionNames) {
optionNames = Object.keys(this.$options);
} else if (!Array.isArray(optionNames)) {
result = optionNames;
optionNames = Object.keys(result);
}
optionNames.forEach(function(key) {
result[key] = this.getOption(key);
}, this);
return result;
},
setOption: function(name, value) {
if (this["$" + name] === value)
return;
var opt = this.$options[name];
if (!opt) {
if (typeof console != "undefined" && console.warn)
console.warn('misspelled option "' + name + '"');
return undefined;
}
if (opt.forwardTo)
return this[opt.forwardTo] && this[opt.forwardTo].setOption(name, value);
if (!opt.handlesSet)
this["$" + name] = value;
if (opt && opt.set)
opt.set.call(this, value);
},
getOption: function(name) {
var opt = this.$options[name];
if (!opt) {
if (typeof console != "undefined" && console.warn)
console.warn('misspelled option "' + name + '"');
return undefined;
}
if (opt.forwardTo)
return this[opt.forwardTo] && this[opt.forwardTo].getOption(name);
return opt && opt.get ? opt.get.call(this) : this["$" + name];
}
};
var defaultOptions = {};
/*
* option {name, value, initialValue, setterName, set, get }
*/
exports.defineOptions = function(obj, path, options) {
if (!obj.$options)
defaultOptions[path] = obj.$options = {};
Object.keys(options).forEach(function(key) {
var opt = options[key];
if (typeof opt == "string")
opt = {forwardTo: opt};
opt.name || (opt.name = key);
obj.$options[opt.name] = opt;
if ("initialValue" in opt)
obj["$" + opt.name] = opt.initialValue;
});
// implement option provider interface
oop.implement(obj, optionsProvider);
return this;
};
exports.resetOptions = function(obj) {
Object.keys(obj.$options).forEach(function(key) {
var opt = obj.$options[key];
if ("value" in opt)
obj.setOption(key, opt.value);
});
};
exports.setDefaultValue = function(path, name, value) {
var opts = defaultOptions[path] || (defaultOptions[path] = {});
if (opts[name]) {
if (opts.forwardTo)
exports.setDefaultValue(opts.forwardTo, name, value);
else
opts[name].value = value;
}
};
exports.setDefaultValues = function(path, optionHash) {
Object.keys(optionHash).forEach(function(key) {
exports.setDefaultValue(path, key, optionHash[key]);
});
};
});

View file

@ -117,12 +117,19 @@ module.exports = {
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) {
require("asyncjs").test.testcase(module.exports).exec()
require("asyncjs").test.testcase(module.exports).exec();
}

View file

@ -160,6 +160,8 @@
z-index: 1;
position: absolute;
overflow: hidden;
/* workaround for chrome bug https://github.com/ajaxorg/ace/issues/2312*/
word-wrap: normal;
white-space: pre;
height: 100%;
width: 100%;
@ -420,3 +422,30 @@
position: absolute;
z-index: 8;
}
/*
styles = []
for (var i = 1; i < 16; i++) {
styles.push(".ace_br" + i + "{" + (
["top-left", "top-right", "bottom-right", "bottom-left"]
).map(function(x, j) {
return i & (1<<j) ? "border-" + x + "-radius: 3px;" : ""
}).filter(Boolean).join(" ") + "}")
}
styles.join("\n")
*/
.ace_br1 {border-top-left-radius : 3px;}
.ace_br2 {border-top-right-radius : 3px;}
.ace_br3 {border-top-left-radius : 3px; border-top-right-radius: 3px;}
.ace_br4 {border-bottom-right-radius: 3px;}
.ace_br5 {border-top-left-radius : 3px; border-bottom-right-radius: 3px;}
.ace_br6 {border-top-right-radius : 3px; border-bottom-right-radius: 3px;}
.ace_br7 {border-top-left-radius : 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px;}
.ace_br8 {border-bottom-left-radius : 3px;}
.ace_br9 {border-top-left-radius : 3px; border-bottom-left-radius: 3px;}
.ace_br10{border-top-right-radius : 3px; border-bottom-left-radius: 3px;}
.ace_br11{border-top-left-radius : 3px; border-top-right-radius: 3px; border-bottom-left-radius: 3px;}
.ace_br12{border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;}
.ace_br13{border-top-left-radius : 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;}
.ace_br14{border-top-right-radius : 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;}
.ace_br15{border-top-left-radius : 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;}

View file

@ -32,36 +32,36 @@ define(function(require, exports, module) {
"use strict";
var oop = require("./lib/oop");
var applyDelta = require("./apply_delta").applyDelta;
var EventEmitter = require("./lib/event_emitter").EventEmitter;
var Range = require("./range").Range;
var Anchor = require("./anchor").Anchor;
/**
* Contains the text of the document. Document can be attached to several [[EditSession `EditSession`]]s.
*
* At its core, `Document`s are just an array of strings, with each row in the document matching up to the array index.
*
* @class Document
**/
/**
/**
*
* Creates a new `Document`. If `text` is included, the `Document` contains those strings; otherwise, it's empty.
* @param {String | Array} text The starting text
* @constructor
**/
var Document = function(text) {
this.$lines = [];
var Document = function(textOrLines) {
this.$lines = [""];
// 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.
if (text.length === 0) {
if (textOrLines.length === 0) {
this.$lines = [""];
} else if (Array.isArray(text)) {
this._insertLines(0, text);
} else if (Array.isArray(textOrLines)) {
this.insertMergedLines({row: 0, column: 0}, textOrLines);
} else {
this.insert({row: 0, column:0}, text);
this.insert({row: 0, column:0}, textOrLines);
}
};
@ -75,9 +75,9 @@ var Document = function(text) {
* @param {String} text The text to use
**/
this.setValue = function(text) {
var len = this.getLength();
this.remove(new Range(0, 0, len, this.getLine(len-1).length));
this.insert({row: 0, column:0}, text);
var len = this.getLength() - 1;
this.remove(new Range(0, 0, len, this.getLine(len).length));
this.insert({row: 0, column: 0}, text);
};
/**
@ -98,7 +98,7 @@ var Document = function(text) {
};
/**
* Splits a string of text on any newline (`\n`) or carriage-return ('\r') characters.
* Splits a string of text on any newline (`\n`) or carriage-return (`\r`) characters.
*
* @method $split
* @param {String} text The text to work with
@ -107,14 +107,15 @@ var Document = function(text) {
**/
// check for IE split bug
if ("aaa".split(/a/).length === 0)
if ("aaa".split(/a/).length === 0) {
this.$split = function(text) {
return text.replace(/\r\n|\r/g, "\n").split("\n");
};
else
} else {
this.$split = function(text) {
return text.split(/\r\n|\r|\n/);
};
}
this.$detectNewLine = function(text) {
@ -207,32 +208,49 @@ 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}
* @param {Range} range The range to work with
* Returns all the text within `range` as a single string.
* @param {Range} range The range to work with.
*
* @returns {String}
**/
this.getTextRange = function(range) {
if (range.start.row == range.end.row) {
return this.getLine(range.start.row)
.substring(range.start.column, range.end.column);
return this.getLinesForRange(range).join(this.getNewLineCharacter());
};
/**
* Returns all the text within `range` as an array of lines.
* @param {Range} range The range to work with.
*
* @returns {Array}
**/
this.getLinesForRange = function(range) {
var lines;
if (range.start.row === range.end.row) {
// Handle a single-line range.
lines = [this.getLine(range.start.row).substring(range.start.column, range.end.column)];
} else {
// Handle a multi-line range.
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);
}
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());
return lines;
};
this.$clipPosition = function(position) {
var length = this.getLength();
if (position.row >= length) {
position.row = Math.max(0, length - 1);
position.column = this.getLine(length-1).length;
} else if (position.row < 0)
position.row = 0;
return position;
// Deprecated methods retained for backwards compatibility.
this.insertLines = function(row, lines) {
console.warn("Use of document.insertLines is deprecated. Use the insertFullLines method instead.");
return this.insertFullLines(row, lines);
};
this.removeLines = function(firstRow, lastRow) {
console.warn("Use of document.removeLines is deprecated. Use the removeFullLines method instead.");
return this.removeFullLines(firstRow, lastRow);
};
this.insertNewLine = function(position) {
console.warn("Use of document.insertNewLine is deprecated. Use insertMergedLines(position, [\'\', \'\']) instead.");
return this.insertMergedLines(position, ["", ""]);
};
/**
@ -243,53 +261,97 @@ var Document = function(text) {
*
**/
this.insert = function(position, text) {
if (!text || text.length === 0)
return position;
position = this.$clipPosition(position);
// only detect new lines if the document has no line break yet
// Only detect new lines if the document has no line break yet.
if (this.getLength() <= 1)
this.$detectNewLine(text);
var lines = this.$split(text);
var firstLine = lines.splice(0, 1)[0];
var lastLine = lines.length == 0 ? null : lines.splice(lines.length - 1, 1)[0];
position = this.insertInLine(position, firstLine);
if (lastLine !== null) {
position = this.insertNewLine(position); // terminate first line
position = this._insertLines(position.row, lines);
position = this.insertInLine(position, lastLine || "");
return this.insertMergedLines(position, this.$split(text));
};
/**
* Inserts `text` into the `position` at the current row. This method also triggers the `"change"` event.
*
* This differs from the `insert` method in two ways:
* 1. This does NOT handle newline characters (single-line text only).
* 2. This is faster than the `insert` method for single-line text insertions.
*
* @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
* @returns {Object} Returns an object containing the final row and column, like this:
* ```
* {row: endRow, column: 0}
* ```
**/
this.insertInLine = function(position, text) {
var start = this.clippedPos(position.row, position.column);
var end = this.pos(position.row, position.column + text.length);
this.applyDelta({
start: start,
end: end,
action: "insert",
lines: [text]
}, true);
return this.clonePos(end);
};
this.clippedPos = function(row, column) {
var length = this.getLength();
if (row === undefined) {
row = length;
} else if (row < 0) {
row = 0;
} else if (row >= length) {
row = length - 1;
column = undefined;
}
var line = this.getLine(row);
if (column == undefined)
column = line.length;
column = Math.min(Math.max(column, 0), line.length);
return {row: row, column: column};
};
this.clonePos = function(pos) {
return {row: pos.row, column: pos.column};
};
this.pos = function(row, column) {
return {row: row, column: column};
};
this.$clipPosition = function(position) {
var length = this.getLength();
if (position.row >= length) {
position.row = Math.max(0, length - 1);
position.column = this.getLine(length - 1).length;
} else {
position.row = Math.max(0, position.row);
position.column = Math.min(Math.max(position.column, 0), this.getLine(position.row).length);
}
return position;
};
/**
* Fires whenever the document changes.
*
* Several methods trigger different `"change"` events. Below is a list of each action type, followed by each property that's also available:
*
* * `"insertLines"` (emitted by [[Document.insertLines]])
* * `range`: the [[Range]] of the change within the document
* * `lines`: the lines in the document that are changing
* * `"insertText"` (emitted by [[Document.insertNewLine]])
* * `range`: the [[Range]] of the change within the document
* * `text`: the text that's being added
* * `"removeLines"` (emitted by [[Document.insertLines]])
* * `range`: the [[Range]] of the change within the document
* * `lines`: the lines in the document that were removed
* * `nl`: the new line character (as defined by [[Document.getNewLineCharacter]])
* * `"removeText"` (emitted by [[Document.removeInLine]] and [[Document.removeNewLine]])
* * `range`: the [[Range]] of the change within the document
* * `text`: the text that's being removed
*
* @event change
* @param {Object} e Contains at least one property called `"action"`. `"action"` indicates the action that triggered the change. Each action also has a set of additional properties.
*
**/
* Fires whenever the document changes.
*
* Several methods trigger different `"change"` events. Below is a list of each action type, followed by each property that's also available:
*
* * `"insert"`
* * `range`: the [[Range]] of the change within the document
* * `lines`: the lines being added
* * `"remove"`
* * `range`: the [[Range]] of the change within the document
* * `lines`: the lines being removed
*
* @event change
* @param {Object} e Contains at least one property called `"action"`. `"action"` indicates the action that triggered the change. Each action also has a set of additional properties.
*
**/
/**
* Inserts the elements in `lines` into the document, starting at the row index given by `row`. This method also triggers the `'change'` event.
* Inserts the elements in `lines` into the document as full lines (does not merge with existing line), starting at the row index given by `row`. This method also triggers the `"change"` event.
* @param {Number} row The index of the row to insert at
* @param {Array} lines An array of strings
* @returns {Object} Contains the final row and column, like this:
@ -302,100 +364,57 @@ var Document = function(text) {
* ```
*
**/
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)
return {row: row, column: 0};
// 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
while (lines.length > 0xF000) {
var end = this._insertLines(row, lines.slice(0, 0xF000));
lines = lines.slice(0xF000);
row = end.row;
this.insertFullLines = function(row, lines) {
// Clip to document.
// Allow one past the document end.
row = Math.min(Math.max(row, 0), this.getLength());
// Calculate insertion point.
var column = 0;
if (row < this.getLength()) {
// Insert before the specified row.
lines = lines.concat([""]);
column = 0;
} else {
// Insert after the last row in the document.
lines = [""].concat(lines);
row--;
column = this.$lines[row].length;
}
// Insert.
this.insertMergedLines({row: row, column: column}, lines);
};
var args = [row, 0];
args.push.apply(args, lines);
this.$lines.splice.apply(this.$lines, args);
var range = new Range(row, 0, row + lines.length, 0);
var delta = {
action: "insertLines",
range: range,
/**
* Inserts the elements in `lines` into the document, starting at the position index given by `row`. This method also triggers the `"change"` event.
* @param {Number} row The index of the row to insert at
* @param {Array} lines An array of strings
* @returns {Object} Contains the final row and column, like this:
* ```
* {row: endRow, column: 0}
* ```
* If `lines` is empty, this function returns an object containing the current row, and column, like this:
* ```
* {row: row, column: 0}
* ```
*
**/
this.insertMergedLines = function(position, lines) {
var start = this.clippedPos(position.row, position.column);
var end = {
row: start.row + lines.length - 1,
column: (lines.length == 1 ? start.column : 0) + lines[lines.length - 1].length
};
this.applyDelta({
start: start,
end: end,
action: "insert",
lines: lines
};
this._signal("change", { data: delta });
return range.end;
};
/**
* Inserts a new line into the document at the current row's `position`. This method also triggers the `'change'` event.
* @param {Object} position The position to insert at
* @returns {Object} Returns an object containing the final row and column, like this:<br/>
* ```
* {row: endRow, column: 0}
* ```
*
**/
this.insertNewLine = function(position) {
position = this.$clipPosition(position);
var line = this.$lines[position.row] || "";
this.$lines[position.row] = line.substring(0, position.column);
this.$lines.splice(position.row + 1, 0, line.substring(position.column, line.length));
var end = {
row : position.row + 1,
column : 0
};
var delta = {
action: "insertText",
range: Range.fromPoints(position, end),
text: this.getNewLineCharacter()
};
this._signal("change", { data: delta });
return end;
};
/**
* Inserts `text` into the `position` at the current row. This method also triggers the `'change'` event.
* @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
* @returns {Object} Returns an object containing the final row and column, like this:
* ```
* {row: endRow, column: 0}
* ```
*
**/
this.insertInLine = function(position, text) {
if (text.length == 0)
return position;
var line = this.$lines[position.row] || "";
this.$lines[position.row] = line.substring(0, position.column) + text
+ line.substring(position.column);
var end = {
row : position.row,
column : position.column + text.length
};
var delta = {
action: "insertText",
range: Range.fromPoints(position, end),
text: text
};
this._signal("change", { data: delta });
return end;
});
return this.clonePos(end);
};
/**
@ -405,113 +424,90 @@ var Document = function(text) {
*
**/
this.remove = function(range) {
if (!(range instanceof Range))
range = Range.fromPoints(range.start, range.end);
// clip to document
range.start = this.$clipPosition(range.start);
range.end = this.$clipPosition(range.end);
if (range.isEmpty())
return range.start;
var firstRow = range.start.row;
var lastRow = range.end.row;
if (range.isMultiLine()) {
var firstFullRow = range.start.column == 0 ? firstRow : firstRow + 1;
var lastFullRow = lastRow - 1;
if (range.end.column > 0)
this.removeInLine(lastRow, 0, range.end.column);
if (lastFullRow >= firstFullRow)
this._removeLines(firstFullRow, lastFullRow);
if (firstFullRow != firstRow) {
this.removeInLine(firstRow, range.start.column, this.getLine(firstRow).length);
this.removeNewLine(range.start.row);
}
}
else {
this.removeInLine(firstRow, range.start.column, range.end.column);
}
return range.start;
var start = this.clippedPos(range.start.row, range.start.column);
var end = this.clippedPos(range.end.row, range.end.column);
this.applyDelta({
start: start,
end: end,
action: "remove",
lines: this.getLinesForRange({start: start, end: end})
});
return this.clonePos(start);
};
/**
* Removes the specified columns from the `row`. This method also triggers the `'change'` event.
* @param {Number} row The row to remove from
* @param {Number} startColumn The column to start 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.
*
**/
* Removes the specified columns from the `row`. This method also triggers a `"change"` event.
* @param {Number} row The row to remove from
* @param {Number} startColumn The column to start 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.
*
**/
this.removeInLine = function(row, startColumn, endColumn) {
if (startColumn == endColumn)
return;
var range = new Range(row, startColumn, row, endColumn);
var line = this.getLine(row);
var removed = line.substring(startColumn, endColumn);
var newLine = line.substring(0, startColumn) + line.substring(endColumn, line.length);
this.$lines.splice(row, 1, newLine);
var delta = {
action: "removeText",
range: range,
text: removed
};
this._signal("change", { data: delta });
return range.start;
var start = this.clippedPos(row, startColumn);
var end = this.clippedPos(row, endColumn);
this.applyDelta({
start: start,
end: end,
action: "remove",
lines: this.getLinesForRange({start: start, end: end})
}, true);
return this.clonePos(start);
};
/**
* Removes a range of full lines. This method also triggers the `'change'` event.
* Removes a range of full lines. This method also triggers the `"change"` event.
* @param {Number} firstRow The first row to be removed
* @param {Number} lastRow The last row to be removed
* @returns {[String]} Returns all the removed lines.
*
**/
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 removed = this.$lines.splice(firstRow, lastRow - firstRow + 1);
var delta = {
action: "removeLines",
range: range,
nl: this.getNewLineCharacter(),
lines: removed
};
this._signal("change", { data: delta });
return removed;
this.removeFullLines = function(firstRow, lastRow) {
// Clip to document.
firstRow = Math.min(Math.max(0, firstRow), this.getLength() - 1);
lastRow = Math.min(Math.max(0, lastRow ), this.getLength() - 1);
// Calculate deletion range.
// Delete the ending new line unless we're at the end of the document.
// If we're at the end of the document, delete the starting new line.
var deleteFirstNewLine = lastRow == this.getLength() - 1 && firstRow > 0;
var deleteLastNewLine = lastRow < this.getLength() - 1;
var startRow = ( deleteFirstNewLine ? firstRow - 1 : firstRow );
var startCol = ( deleteFirstNewLine ? this.getLine(startRow).length : 0 );
var endRow = ( deleteLastNewLine ? lastRow + 1 : lastRow );
var endCol = ( deleteLastNewLine ? 0 : this.getLine(endRow).length );
var range = new Range(startRow, startCol, endRow, endCol);
// Store delelted lines with bounding newlines ommitted (maintains previous behavior).
var deletedLines = this.$lines.slice(firstRow, lastRow + 1);
this.applyDelta({
start: range.start,
end: range.end,
action: "remove",
lines: this.getLinesForRange(range)
});
// Return the deleted lines.
return deletedLines;
};
/**
* Removes the new line between `row` and the row immediately following it. This method also triggers the `'change'` event.
* Removes the new line between `row` and the row immediately following it. This method also triggers the `"change"` event.
* @param {Number} row The row to check
*
**/
this.removeNewLine = function(row) {
var firstLine = this.getLine(row);
var secondLine = this.getLine(row+1);
var range = new Range(row, firstLine.length, row+1, 0);
var line = firstLine + secondLine;
this.$lines.splice(row, 2, line);
var delta = {
action: "removeText",
range: range,
text: this.getNewLineCharacter()
};
this._signal("change", { data: delta });
if (row < this.getLength() - 1 && row >= 0) {
this.applyDelta({
start: this.pos(row, this.getLine(row).length),
end: this.pos(row + 1, 0),
action: "remove",
lines: ["", ""]
});
}
};
/**
@ -525,9 +521,9 @@ var Document = function(text) {
*
**/
this.replace = function(range, text) {
if (!(range instanceof Range))
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;
// Shortcut: If the text we want to insert is the same as it is already
@ -536,55 +532,106 @@ var Document = function(text) {
return range.end;
this.remove(range);
var end;
if (text) {
var end = this.insert(range.start, text);
end = this.insert(range.start, text);
}
else {
end = range.start;
}
return end;
};
/**
* Applies all the changes previously accumulated. These can be either `'insertText'`, `'insertLines'`, `'removeText'`, and `'removeLines'`.
* Applies all changes in `deltas` to the document.
* @param {Array} deltas An array of delta objects (can include "insert" and "remove" actions)
**/
this.applyDeltas = function(deltas) {
for (var i=0; i<deltas.length; i++) {
var delta = deltas[i];
var range = Range.fromPoints(delta.range.start, delta.range.end);
if (delta.action == "insertLines")
this.insertLines(range.start.row, delta.lines);
else if (delta.action == "insertText")
this.insert(range.start, delta.text);
else if (delta.action == "removeLines")
this._removeLines(range.start.row, range.end.row - 1);
else if (delta.action == "removeText")
this.remove(range);
this.applyDelta(deltas[i]);
}
};
/**
* Reverts any changes previously applied. These can be either `'insertText'`, `'insertLines'`, `'removeText'`, and `'removeLines'`.
* Reverts all changes in `deltas` from the document.
* @param {Array} deltas An array of delta objects (can include "insert" and "remove" actions)
**/
this.revertDeltas = function(deltas) {
for (var i=deltas.length-1; i>=0; i--) {
var delta = deltas[i];
var range = Range.fromPoints(delta.range.start, delta.range.end);
if (delta.action == "insertLines")
this._removeLines(range.start.row, range.end.row - 1);
else if (delta.action == "insertText")
this.remove(range);
else if (delta.action == "removeLines")
this._insertLines(range.start.row, delta.lines);
else if (delta.action == "removeText")
this.insert(range.start, delta.text);
this.revertDelta(deltas[i]);
}
};
/**
* Applies `delta` to the document.
* @param {Object} delta A delta object (can include "insert" and "remove" actions)
**/
this.applyDelta = function(delta, doNotValidate) {
var isInsert = delta.action == "insert";
// An empty range is a NOOP.
if (isInsert ? delta.lines.length <= 1 && !delta.lines[0]
: !Range.comparePoints(delta.start, delta.end)) {
return;
}
if (isInsert && delta.lines.length > 20000)
this.$splitAndapplyLargeDelta(delta, 20000);
// Apply.
applyDelta(this.$lines, delta, doNotValidate);
this._signal("change", delta);
};
this.$splitAndapplyLargeDelta = function(delta, MAX) {
// Split large insert deltas. This is necessary because:
// 1. We need to support splicing delta lines into the document via $lines.splice.apply(...)
// 2. fn.apply() doesn't work for a large number of params. The smallest threshold is on chrome 40 ~42000.
// we use 20000 to leave some space for actual stack
//
// To Do: Ideally we'd be consistent and also split 'delete' deltas. We don't do this now, because delete
// delta handling is too slow. If we make delete delta handling faster we can split all large deltas
// as shown in https://gist.github.com/aldendaniels/8367109#file-document-snippet-js
// If we do this, update validateDelta() to limit the number of lines in a delete delta.
var lines = delta.lines;
var l = lines.length;
var row = delta.start.row;
var column = delta.start.column;
var from = 0, to = 0;
do {
from = to;
to += MAX - 1;
var chunk = lines.slice(from, to);
if (to > l) {
// Update remaining delta.
delta.lines = chunk;
delta.start.row = row + from;
delta.start.column = column;
break;
}
chunk.push("");
this.applyDelta({
start: this.pos(row + from, column),
end: this.pos(row + to, column = 0),
action: delta.action,
lines: chunk
}, true);
} while(true);
};
/**
* Reverts `delta` from the document.
* @param {Object} delta A delta object (can include "insert" and "remove" actions)
**/
this.revertDelta = function(delta) {
this.applyDelta({
start: this.clonePos(delta.start),
end: this.clonePos(delta.end),
action: (delta.action == "insert" ? "remove" : "insert"),
lines: delta.lines.slice()
});
};
/**
* Converts an index position in a document to a `{row, column}` object.
*

View file

@ -46,7 +46,7 @@ module.exports = {
var doc = new Document(["12", "34"]);
var deltas = [];
doc.on("change", function(e) { deltas.push(e.data); });
doc.on("change", function(e) { deltas.push(e); });
doc.insert({row: 0, column: 1}, "juhu");
assert.equal(doc.getValue(), ["1juhu2", "34"].join("\n"));
@ -63,9 +63,9 @@ module.exports = {
var doc = new Document(["12", "34"]);
var deltas = [];
doc.on("change", function(e) { deltas.push(e.data); });
doc.on("change", function(e) { deltas.push(e); });
doc.insertNewLine({row: 0, column: 1});
doc.insertMergedLines({row: 0, column: 1}, ['', '']);
assert.equal(doc.getValue(), ["1", "2", "34"].join("\n"));
var d = deltas.concat();
@ -80,9 +80,9 @@ module.exports = {
var doc = new Document(["12", "34"]);
var deltas = [];
doc.on("change", function(e) { deltas.push(e.data); });
doc.on("change", function(e) { deltas.push(e); });
doc.insertLines(0, ["aa", "bb"]);
doc.insertFullLines(0, ["aa", "bb"]);
assert.equal(doc.getValue(), ["aa", "bb", "12", "34"].join("\n"));
var d = deltas.concat();
@ -97,9 +97,9 @@ module.exports = {
var doc = new Document(["12", "34"]);
var deltas = [];
doc.on("change", function(e) { deltas.push(e.data); });
doc.on("change", function(e) { deltas.push(e); });
doc.insertLines(2, ["aa", "bb"]);
doc.insertFullLines(2, ["aa", "bb"]);
assert.equal(doc.getValue(), ["12", "34", "aa", "bb"].join("\n"));
},
@ -107,9 +107,9 @@ module.exports = {
var doc = new Document(["12", "34"]);
var deltas = [];
doc.on("change", function(e) { deltas.push(e.data); });
doc.on("change", function(e) { deltas.push(e); });
doc.insertLines(1, ["aa", "bb"]);
doc.insertFullLines(1, ["aa", "bb"]);
assert.equal(doc.getValue(), ["12", "aa", "bb", "34"].join("\n"));
var d = deltas.concat();
@ -124,7 +124,7 @@ module.exports = {
var doc = new Document(["12", "34"]);
var deltas = [];
doc.on("change", function(e) { deltas.push(e.data); });
doc.on("change", function(e) { deltas.push(e); });
doc.insert({row: 0, column: 0}, "aa\nbb\ncc");
assert.equal(doc.getValue(), ["aa", "bb", "cc12", "34"].join("\n"));
@ -141,9 +141,9 @@ module.exports = {
var doc = new Document(["12", "34"]);
var deltas = [];
doc.on("change", function(e) { deltas.push(e.data); });
doc.on("change", function(e) { deltas.push(e); });
doc.insert({row: 2, column: 0}, "aa\nbb\ncc");
doc.insert({row: 1, column: 2}, "aa\nbb\ncc");
assert.equal(doc.getValue(), ["12", "34aa", "bb", "cc"].join("\n"));
var d = deltas.concat();
@ -158,7 +158,7 @@ module.exports = {
var doc = new Document(["12", "34"]);
var deltas = [];
doc.on("change", function(e) { deltas.push(e.data); });
doc.on("change", function(e) { deltas.push(e); });
doc.insert({row: 0, column: 1}, "aa\nbb\ncc");
assert.equal(doc.getValue(), ["1aa", "bb", "cc2", "34"].join("\n"));
@ -175,7 +175,7 @@ module.exports = {
var doc = new Document(["1234", "5678"]);
var deltas = [];
doc.on("change", function(e) { deltas.push(e.data); });
doc.on("change", function(e) { deltas.push(e); });
doc.remove(new Range(0, 1, 0, 3));
assert.equal(doc.getValue(), ["14", "5678"].join("\n"));
@ -192,7 +192,7 @@ module.exports = {
var doc = new Document(["1234", "5678"]);
var deltas = [];
doc.on("change", function(e) { deltas.push(e.data); });
doc.on("change", function(e) { deltas.push(e); });
doc.remove(new Range(0, 4, 1, 0));
assert.equal(doc.getValue(), ["12345678"].join("\n"));
@ -209,7 +209,7 @@ module.exports = {
var doc = new Document(["1234", "5678", "abcd"]);
var deltas = [];
doc.on("change", function(e) { deltas.push(e.data); });
doc.on("change", function(e) { deltas.push(e); });
doc.remove(new Range(0, 2, 2, 2));
assert.equal(doc.getValue(), ["12cd"].join("\n"));
@ -226,7 +226,7 @@ module.exports = {
var doc = new Document(["1234", "5678", "abcd"]);
var deltas = [];
doc.on("change", function(e) { deltas.push(e.data); });
doc.on("change", function(e) { deltas.push(e); });
doc.remove(new Range(1, 0, 3, 0));
assert.equal(doc.getValue(), ["1234", ""].join("\n"));
@ -235,7 +235,7 @@ module.exports = {
"test: remove lines should return the removed lines" : function() {
var doc = new Document(["1234", "5678", "abcd"]);
var removed = doc.removeLines(1, 2);
var removed = doc.removeFullLines(1, 2);
assert.equal(removed.join("\n"), ["5678", "abcd"].join("\n"));
},
@ -296,6 +296,35 @@ module.exports = {
"test: empty document has to contain one line": function() {
var doc = new Document("");
assert.equal(doc.$lines.length, 1);
},
"test: ignore empty delta": function() {
var doc = new Document("");
doc.on("change", function() {
throw "should ignore empty delta";
})
doc.insert({row: 0, column: 0}, "");
doc.insert({row: 1, column: 1}, "");
doc.remove({start: {row: 1, column: 1}, end: {row: 1, column: 1}});
},
"test: inserting huge delta": function() {
var doc = new Document("");
var val = "";
var MAX = 0xF000;
for (var i = 0; i < 10 * MAX; i++) {
val += i + "\n"
}
doc.setValue(val);
assert.equal(doc.getValue(), val);
for (var i = 3 * MAX + 2; i >= 3 * MAX - 2; i--) {
val = doc.getLines(0, i).join("\n");
doc.setValue("\nab");
assert.equal(doc.getValue(), "\nab");
doc.insert({row: 1, column: 1}, val);
assert.equal(doc.getValue(), "\na" + val + "b");
}
}
};

View file

@ -151,7 +151,7 @@ var EditSession = function(text, mode) {
this.$foldData = [];
this.$foldData.toString = function() {
return this.join("\n");
}
};
this.on("changeFold", this.onChangeFold.bind(this));
this.$onChange = this.onChange.bind(this);
@ -249,13 +249,12 @@ var EditSession = function(text, mode) {
this.$resetRowCache(fold.start.row);
};
this.onChange = function(e) {
var delta = e.data;
this.onChange = function(delta) {
this.$modified = true;
this.$resetRowCache(delta.range.start.row);
this.$resetRowCache(delta.start.row);
var removedFolds = this.$updateInternalDataOnChange(e);
var removedFolds = this.$updateInternalDataOnChange(delta);
if (!this.$fromUndo && this.$undoManager && !delta.ignore) {
this.$deltasDoc.push(delta);
if (removedFolds && removedFolds.length != 0) {
@ -269,7 +268,7 @@ var EditSession = function(text, mode) {
}
this.bgTokenizer && this.bgTokenizer.$updateOnChange(delta);
this._signal("change", e);
this._signal("change", delta);
};
/**
@ -679,10 +678,10 @@ var EditSession = function(text, mode) {
};
/**
* Returns an array containing the IDs of all the markers, either front or back.
* Returns an object containing all of the markers, either front or back.
* @param {Boolean} inFront If `true`, indicates you only want front markers; `false` indicates only back markers
*
* @returns {Array}
* @returns {Object}
**/
this.getMarkers = function(inFront) {
return inFront ? this.$frontMarkers : this.$backMarkers;
@ -893,17 +892,17 @@ var EditSession = function(text, mode) {
config.loadModule(["mode", path], function(m) {
if (this.$modeId !== path)
return cb && cb();
if (this.$modes[path] && !options)
return this.$onChangeMode(this.$modes[path]);
if (m && m.Mode) {
if (this.$modes[path] && !options) {
this.$onChangeMode(this.$modes[path]);
} else if (m && m.Mode) {
m = new m.Mode(options);
if (!options) {
this.$modes[path] = m;
m.$id = path;
}
this.$onChangeMode(m);
cb && cb();
}
cb && cb();
}.bind(this));
// set mode to text until loading is finished
@ -969,10 +968,7 @@ var EditSession = function(text, mode) {
try {
this.$worker = this.$mode.createWorker(this);
} catch (e) {
if (typeof console == "object") {
console.log("Could not load worker");
console.log(e);
}
config.warn("Could not load worker", e);
this.$worker = null;
}
};
@ -1149,6 +1145,19 @@ var EditSession = function(text, mode) {
this.remove = function(range) {
return this.doc.remove(range);
};
/**
* Removes a range of full lines. This method also triggers the `'change'` event.
* @param {Number} firstRow The first row to be removed
* @param {Number} lastRow The last row to be removed
* @returns {[String]} Returns all the removed lines.
*
* @related Document.removeFullLines
*
**/
this.removeFullLines = function(firstRow, lastRow){
return this.doc.removeFullLines(firstRow, lastRow);
};
/**
* Reverts previous changes to your document.
@ -1225,39 +1234,36 @@ var EditSession = function(text, mode) {
this.$getUndoSelection = function(deltas, isUndo, lastUndoRange) {
function isInsert(delta) {
var insert =
delta.action === "insertText" || delta.action === "insertLines";
return isUndo ? !insert : insert;
return isUndo ? delta.action !== "insert" : delta.action === "insert";
}
var delta = deltas[0];
var range, point;
var lastDeltaIsInsert = false;
if (isInsert(delta)) {
range = Range.fromPoints(delta.range.start, delta.range.end);
range = Range.fromPoints(delta.start, delta.end);
lastDeltaIsInsert = true;
} else {
range = Range.fromPoints(delta.range.start, delta.range.start);
range = Range.fromPoints(delta.start, delta.start);
lastDeltaIsInsert = false;
}
for (var i = 1; i < deltas.length; i++) {
delta = deltas[i];
if (isInsert(delta)) {
point = delta.range.start;
point = delta.start;
if (range.compare(point.row, point.column) == -1) {
range.setStart(delta.range.start);
range.setStart(point);
}
point = delta.range.end;
point = delta.end;
if (range.compare(point.row, point.column) == 1) {
range.setEnd(delta.range.end);
range.setEnd(point);
}
lastDeltaIsInsert = true;
} else {
point = delta.range.start;
point = delta.start;
if (range.compare(point.row, point.column) == -1) {
range =
Range.fromPoints(delta.range.start, delta.range.start);
range = Range.fromPoints(delta.start, delta.start);
}
lastDeltaIsInsert = false;
}
@ -1371,7 +1377,7 @@ var EditSession = function(text, mode) {
this.indentRows = function(startRow, endRow, indentString) {
indentString = indentString.replace(/\t/g, this.getTabString());
for (var row=startRow; row<=endRow; row++)
this.insert({row: row, column:0}, indentString);
this.doc.insertInLine({row: row, column: 0}, indentString);
};
/**
@ -1428,11 +1434,11 @@ var EditSession = function(text, mode) {
x.end.row += diff;
return x;
});
var lines = dir == 0
? this.doc.getLines(firstRow, lastRow)
: this.doc.removeLines(firstRow, lastRow);
this.doc.insertLines(firstRow+diff, lines);
: this.doc.removeFullLines(firstRow, lastRow);
this.doc.insertFullLines(firstRow+diff, lines);
folds.length && this.addFolds(folds);
return diff;
};
@ -1442,8 +1448,6 @@ var EditSession = function(text, mode) {
* @param {Number} lastRow The final row to move up
* @returns {Number} If `firstRow` is less-than or equal to 0, this function returns 0. Otherwise, on success, it returns -1.
*
* @related Document.insertLines
*
**/
this.moveLinesUp = function(firstRow, lastRow) {
return this.$moveLines(firstRow, lastRow, -1);
@ -1454,8 +1458,6 @@ var EditSession = function(text, mode) {
* @param {Number} firstRow The starting row to move down
* @param {Number} lastRow The final row to move down
* @returns {Number} If `firstRow` is less-than or equal to 0, this function returns 0. Otherwise, on success, it returns -1.
*
* @related Document.insertLines
**/
this.moveLinesDown = function(firstRow, lastRow) {
return this.$moveLines(firstRow, lastRow, 1);
@ -1583,13 +1585,11 @@ var EditSession = function(text, mode) {
**/
this.setWrapLimitRange = function(min, max) {
if (this.$wrapLimitRange.min !== min || this.$wrapLimitRange.max !== max) {
this.$wrapLimitRange = {
min: min,
max: max
};
this.$wrapLimitRange = { min: min, max: max };
this.$modified = true;
// This will force a recalculation of the wrap limit
this._signal("changeWrapMode");
if (this.$useWrapMode)
this._signal("changeWrapMode");
}
};
@ -1661,34 +1661,23 @@ var EditSession = function(text, mode) {
};
};
this.$updateInternalDataOnChange = function(e) {
this.$updateInternalDataOnChange = function(delta) {
var useWrapMode = this.$useWrapMode;
var len;
var action = e.data.action;
var firstRow = e.data.range.start.row;
var lastRow = e.data.range.end.row;
var start = e.data.range.start;
var end = e.data.range.end;
var action = delta.action;
var start = delta.start;
var end = delta.end;
var firstRow = start.row;
var lastRow = end.row;
var len = lastRow - firstRow;
var removedFolds = null;
if (action.indexOf("Lines") != -1) {
if (action == "insertLines") {
lastRow = firstRow + (e.data.lines.length);
} else {
lastRow = firstRow;
}
len = e.data.lines ? e.data.lines.length : lastRow - firstRow;
} else {
len = lastRow - firstRow;
}
this.$updating = true;
if (len != 0) {
if (action.indexOf("remove") != -1) {
if (action === "remove") {
this[useWrapMode ? "$wrapData" : "$rowLengthCache"].splice(firstRow, len);
var foldLines = this.$foldData;
removedFolds = this.getFoldsInRange(e.data.range);
removedFolds = this.getFoldsInRange(delta);
this.removeFolds(removedFolds);
var foldLine = this.getFoldLine(end.row);
@ -1753,10 +1742,10 @@ var EditSession = function(text, mode) {
} else {
// Realign folds. E.g. if you add some new chars before a fold, the
// fold should "move" to the right.
len = Math.abs(e.data.range.start.column - e.data.range.end.column);
if (action.indexOf("remove") != -1) {
len = Math.abs(delta.start.column - delta.end.column);
if (action === "remove") {
// Get all the folds in the change range and remove them.
removedFolds = this.getFoldsInRange(e.data.range);
removedFolds = this.getFoldsInRange(delta);
this.removeFolds(removedFolds);
len = -len;
@ -1840,7 +1829,7 @@ var EditSession = function(text, mode) {
TAB_SPACE = 12;
this.$computeWrapSplits = function(tokens, wrapLimit) {
this.$computeWrapSplits = function(tokens, wrapLimit, tabSize) {
if (tokens.length == 0) {
return [];
}
@ -1851,6 +1840,31 @@ var EditSession = function(text, mode) {
var isCode = this.$wrapAsCode;
var indentedSoftWrap = this.$indentedSoftWrap;
var maxIndent = wrapLimit <= Math.max(2 * tabSize, 8)
|| indentedSoftWrap === false ? 0 : Math.floor(wrapLimit / 2);
function getWrapIndent() {
var indentation = 0;
if (maxIndent === 0)
return indentation;
if (indentedSoftWrap) {
for (var i = 0; i < tokens.length; i++) {
var token = tokens[i];
if (token == SPACE)
indentation += 1;
else if (token == TAB)
indentation += tabSize;
else if (token == TAB_SPACE)
continue;
else
break;
}
}
if (isCode && indentedSoftWrap !== false)
indentation += tabSize;
return Math.min(indentation, maxIndent);
}
function addSplit(screenPos) {
var displayed = tokens.slice(lastSplit, screenPos);
@ -1867,14 +1881,18 @@ var EditSession = function(text, mode) {
len -= 1;
});
if (!splits.length) {
indent = getWrapIndent();
splits.indent = indent;
}
lastDocSplit += len;
splits.push(lastDocSplit);
lastSplit = screenPos;
}
while (displayLength - lastSplit > wrapLimit) {
var indent = 0;
while (displayLength - lastSplit > wrapLimit - indent) {
// This is, where the split should be.
var split = lastSplit + wrapLimit;
var split = lastSplit + wrapLimit - indent;
// If there is a space or tab at this split position, then making
// a split is simple.
@ -1934,7 +1952,7 @@ var EditSession = function(text, mode) {
// === ELSE ===
// Search for the first non space/tab/placeholder/punctuation token backwards.
var minSplit = Math.max(split - (isCode ? 10 : wrapLimit-(wrapLimit>>2)), lastSplit - 1);
var minSplit = Math.max(split - (wrapLimit -(wrapLimit>>2)), lastSplit - 1);
while (split > minSplit && tokens[split] < PLACEHOLDER_START) {
split --;
}
@ -1962,7 +1980,7 @@ var EditSession = function(text, mode) {
// around -> force a split.
if (tokens[split] == CHAR_EXT)
split--;
addSplit(split);
addSplit(split - indent);
}
return splits;
};
@ -2069,6 +2087,16 @@ var EditSession = function(text, mode) {
}
};
this.getRowWrapIndent = function(screenRow) {
if (this.$useWrapMode) {
var pos = this.screenToDocumentPosition(screenRow, Number.MAX_VALUE);
var splits = this.$wrapData[pos.row];
return splits.length && splits[0] < pos.column ? splits.indent : 0;
} else {
return 0;
}
}
/**
* Returns the position (on screen) for the last character in the provided screen row.
* @param {Number} screenRow The screen row to check
@ -2206,20 +2234,21 @@ var EditSession = function(text, mode) {
line = this.getLine(docRow);
foldLine = null;
}
var wrapIndent = 0;
if (this.$useWrapMode) {
var splits = this.$wrapData[docRow];
if (splits) {
var splitIndex = Math.floor(screenRow - row);
column = splits[splitIndex];
if(splitIndex > 0 && splits.length) {
wrapIndent = splits.indent;
docColumn = splits[splitIndex - 1] || splits[splits.length - 1];
line = line.substring(docColumn);
}
}
}
docColumn += this.$getStringScreenWidth(line, screenColumn)[1];
docColumn += this.$getStringScreenWidth(line, screenColumn - wrapIndent)[1];
// We remove one character at the end so that the docColumn
// position returned is not associated to the next row on the screen.
@ -2311,6 +2340,7 @@ var EditSession = function(text, mode) {
textLine = this.getLine(docRow).substring(0, docColumn);
foldStartRow = docRow;
}
var wrapIndent = 0;
// Clamp textLine if in wrapMode.
if (this.$useWrapMode) {
var wrapRow = this.$wrapData[foldStartRow];
@ -2323,12 +2353,13 @@ var EditSession = function(text, mode) {
textLine = textLine.substring(
wrapRow[screenRowOffset - 1] || 0, textLine.length
);
wrapIndent = screenRowOffset > 0 ? wrapRow.indent : 0;
}
}
return {
row: screenRow,
column: this.$getStringScreenWidth(textLine)[0]
column: wrapIndent + this.$getStringScreenWidth(textLine)[0]
};
};
@ -2470,6 +2501,7 @@ config.defineOptions(EditSession.prototype, "session", {
if (this.$wrap == value)
return;
this.$wrap = value;
if (!value) {
this.setUseWrapMode(false);
} else {
@ -2477,7 +2509,6 @@ config.defineOptions(EditSession.prototype, "session", {
this.setWrapLimitRange(col, col);
this.setUseWrapMode(true);
}
this.$wrap = value;
},
get: function() {
if (this.getUseWrapMode()) {
@ -2508,6 +2539,7 @@ config.defineOptions(EditSession.prototype, "session", {
},
initialValue: "auto"
},
indentedSoftWrap: { initialValue: true },
firstLineNumber: {
set: function() {this._signal("changeBreakpoint");},
initialValue: 1

View file

@ -117,7 +117,7 @@ function BracketMatch() {
typeRe = new RegExp(
"(\\.?" +
token.type.replace(".", "\\.").replace("rparen", ".paren")
.replace(/\b(?:end|start|begin)\b/, "")
.replace(/\b(?:end)\b/, "(?:start|begin|end)")
+ ")+"
);
}
@ -174,7 +174,7 @@ function BracketMatch() {
typeRe = new RegExp(
"(\\.?" +
token.type.replace(".", "\\.").replace("lparen", ".paren")
.replace(/\b(?:end|start|begin)\b/, "")
.replace(/\b(?:start|begin)\b/, "(?:start|begin|end)")
+ ")+"
);
}

View file

@ -696,7 +696,8 @@ function Folding() {
this.$foldMode = foldMode;
this.removeListener('change', this.$updateFoldWidgets);
this.off('change', this.$updateFoldWidgets);
this.off('tokenizerUpdate', this.$tokenizerUpdateFoldWidgets);
this._emit("changeAnnotation");
if (!foldMode || this.$foldStyle == "manual") {
@ -709,8 +710,9 @@ function Folding() {
this.getFoldWidgetRange = foldMode.getFoldWidgetRange.bind(foldMode, this, this.$foldStyle);
this.$updateFoldWidgets = this.updateFoldWidgets.bind(this);
this.$tokenizerUpdateFoldWidgets = this.tokenizerUpdateFoldWidgets.bind(this);
this.on('change', this.$updateFoldWidgets);
this.on('tokenizerUpdate', this.$tokenizerUpdateFoldWidgets);
};
this.getParentFoldRangeData = function (row, ignoreCurrent) {
@ -792,7 +794,7 @@ function Folding() {
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);
this.foldAll(row + 1, endRow, options.all ? 10000 : 0);
} else if (range) {
if (options.all)
range.collapseChildren = 10000;
@ -827,15 +829,13 @@ function Folding() {
}
};
this.updateFoldWidgets = function(e) {
var delta = e.data;
var range = delta.range;
var firstRow = range.start.row;
var len = range.end.row - firstRow;
this.updateFoldWidgets = function(delta) {
var firstRow = delta.start.row;
var len = delta.end.row - firstRow;
if (len === 0) {
this.foldWidgets[firstRow] = null;
} else if (delta.action == "removeText" || delta.action == "removeLines") {
} else if (delta.action == 'remove') {
this.foldWidgets.splice(firstRow, len + 1, null);
} else {
var args = Array(len + 1);
@ -843,7 +843,13 @@ function Folding() {
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;

View file

@ -280,7 +280,7 @@ module.exports = {
session.setUseWrapMode(true);
session.setWrapLimitRange(12, 12);
session.adjustWrapLimit(80);
session.setOption("wrapMethod", "text");
assert.position(session.documentToScreenPosition(0, 11), 0, 11);
assert.position(session.documentToScreenPosition(0, 12), 1, 0);
},
@ -380,7 +380,8 @@ module.exports = {
line = lang.stringTrimRight(line);
var tokens = EditSession.prototype.$getDisplayTokens(line);
var splits = EditSession.prototype.$computeWrapSplits(tokens, wrapLimit, tabSize);
// console.log("String:", line, "Result:", splits, "Expected:", assertEqual);
console.log("String:", line, "Result:", splits, "Expected:", assertEqual);
assert.ok(splits.length == assertEqual.length);
for (var i = 0; i < splits.length; i++) {
assert.ok(splits[i] == assertEqual[i]);
@ -388,6 +389,7 @@ module.exports = {
}
EditSession.prototype.$wrapAsCode = true;
EditSession.prototype.$indentedSoftWrap = false;
// Basic splitting.
computeAndAssert("foo bar foo bar", [ 12 ]);
computeAndAssert("foo bar f bar", [ 12 ]);
@ -413,16 +415,26 @@ module.exports = {
computeAndAssert("ぁぁ", [1], 2);
computeAndAssert(" ぁぁ", [1, 2], 2);
computeAndAssert(" ぁ\tぁ", [1, 3], 2);
computeAndAssert(" ぁぁ\tぁ", [1, 4], 4);
computeAndAssert(" ぁぁ\tぁ", [2, 4], 4);
computeAndAssert("ぁぁ ぁぁ\tぁ", [3, 6], 6);
// Test wrapping for punctuation.
computeAndAssert(" ab.c;ef++", [1, 3, 5, 7, 8], 2);
computeAndAssert(" ab.c;ef++", [2, 4, 6, 8], 2);
computeAndAssert(" ab.c;ef++", [3, 5, 8], 3);
computeAndAssert(" a.b", [1, 2, 3], 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 indented wrapping
EditSession.prototype.$indentedSoftWrap = true;
computeAndAssert("foo bar foo bar foo bara foo", [12, 25]);
computeAndAssert("fooooooooooooooooooooooooooo", [12, 24]);
computeAndAssert("\t\tfoo bar fooooooooooobooooooo", [6, 10, 16, 22, 28]);
computeAndAssert("\t\t\tfoo bar fooooooooooobooooooo", [3, 7, 11, 17, 23, 29]);
computeAndAssert("\tfoo \t \t \t \t bar", [6, 12]); // 14
},
"test get longest line" : function() {
@ -430,12 +442,12 @@ module.exports = {
session.setTabSize(4);
assert.equal(session.getScreenWidth(), 2);
session.doc.insertNewLine({row: 0, column: Infinity});
session.doc.insertLines(1, ["123"]);
session.doc.insertMergedLines({row: 0, column: Infinity}, ['', '']);
session.doc.insertFullLines(1, ["123"]);
assert.equal(session.getScreenWidth(), 3);
session.doc.insertNewLine({row: 0, column: Infinity});
session.doc.insertLines(1, ["\t\t"]);
session.doc.insertMergedLines({row: 0, column: Infinity}, ['', '']);
session.doc.insertFullLines(1, ["\t\t"]);
assert.equal(session.getScreenWidth(), 8);
@ -459,9 +471,9 @@ module.exports = {
session.setUseWrapMode(true);
document.insertLines(0, ["a", "b"]);
document.insertLines(2, ["c", "d"]);
document.removeLines(1, 2);
document.insertFullLines(0, ["a", "b"]);
document.insertFullLines(2, ["c", "d"]);
document.removeFullLines(1, 2);
},
"test wrapMode init has to create wrapData array": function() {

View file

@ -150,18 +150,24 @@ var Editor = function(renderer, session) {
args: commadEvent.args,
scrollTop: this.renderer.scrollTop
};
// this.selections.push(this.selection.toJSON());
if (this.curOp.command.name && this.curOp.command.scrollIntoView !== undefined)
this.$blockScrolling++;
};
this.endOperation = function(e) {
if (this.curOp) {
if (e && e.returnValue === false)
return this.curOp = null;
this._signal("beforeEndOperation");
var command = this.curOp.command;
if (command && command.scrollIntoView) {
switch (command.scrollIntoView) {
if (command.name && this.$blockScrolling > 0)
this.$blockScrolling--;
var scrollIntoView = command && command.scrollIntoView;
if (scrollIntoView) {
switch (scrollIntoView) {
case "center-animate":
scrollIntoView = "animate";
/* fall through */
case "center":
this.renderer.scrollCursorIntoView(null, 0.5);
break;
@ -179,7 +185,7 @@ var Editor = function(renderer, session) {
default:
break;
}
if (command.scrollIntoView == "animate")
if (scrollIntoView == "animate")
this.renderer.animateScrolling(this.curOp.scrollTop);
}
@ -272,6 +278,10 @@ var Editor = function(renderer, session) {
this.setSession = function(session) {
if (this.session == session)
return;
// make sure operationEnd events are not emitted to wrong session
if (this.curOp) this.endOperation();
this.curOp = {};
var oldSession = this.session;
if (oldSession) {
@ -371,6 +381,8 @@ var Editor = function(renderer, session) {
oldSession: oldSession
});
this.curOp = null;
oldSession && oldSession._signal("changeEditor", {oldEditor: this});
session && session._signal("changeEditor", {editor: this});
};
@ -536,12 +548,18 @@ var Editor = function(renderer, session) {
var iterator = new TokenIterator(self.session, pos.row, pos.column);
var token = iterator.getCurrentToken();
if (!token || token.type.indexOf('tag-name') === -1) {
if (!token || !/\b(?:tag-open|tag-name)/.test(token.type)) {
session.removeMarker(session.$tagHighlight);
session.$tagHighlight = null;
return;
}
if (token.type.indexOf("tag-open") != -1) {
token = iterator.stepForward();
if (!token)
return;
}
var tag = token.value;
var depth = 0;
var prevToken = iterator.stepBackward();
@ -674,20 +692,15 @@ var Editor = function(renderer, session) {
*
*
**/
this.onDocumentChange = function(e) {
var delta = e.data;
var range = delta.range;
var lastRow;
this.onDocumentChange = function(delta) {
// Rerender and emit "change" event.
var wrap = this.session.$useWrapMode;
var lastRow = (delta.start.row == delta.end.row ? delta.end.row : Infinity);
this.renderer.updateLines(delta.start.row, lastRow, wrap);
if (range.start.row == range.end.row && delta.action != "insertLines" && delta.action != "removeLines")
lastRow = range.end.row;
else
lastRow = Infinity;
this.renderer.updateLines(range.start.row, lastRow, this.session.$useWrapMode);
this._signal("change", e);
// update cursor because tab characters can influence the cursor position
this._signal("change", delta);
// Update cursor because tab characters can influence the cursor position.
this.$cursorChange();
this.$updateHighlightActiveLine();
};
@ -714,6 +727,10 @@ var Editor = function(renderer, session) {
this.$cursorChange();
if (!this.$blockScrolling) {
config.warn("Automatically scrolling cursor into view after selection change",
"this will be disabled in the next version",
"set editor.$blockScrolling = Infinity to disable this message"
);
this.renderer.scrollCursorIntoView();
}
@ -898,13 +915,33 @@ var Editor = function(renderer, session) {
*
*
**/
this.onPaste = function(text) {
// todo this should change when paste becomes a command
if (this.$readOnly)
return;
var e = {text: text};
this.onPaste = function(text, event) {
var e = {text: text, event: event};
this.commands.exec("paste", this, e);
};
this.$handlePaste = function(e) {
if (typeof e == "string")
e = {text: e};
this._signal("paste", e);
this.insert(e.text, true);
var text = e.text;
if (!this.inMultiSelectMode || this.inVirtualSelectionMode) {
this.insert(text);
} else {
var lines = text.split(/\r\n|\r|\n/);
var ranges = this.selection.rangeList.ranges;
if (lines.length > ranges.length || lines.length < 2 || !lines[1])
return this.commands.exec("insertstring", this, text);
for (var i = ranges.length; i--;) {
var range = ranges[i];
if (!range.isEmpty())
this.session.remove(range);
this.session.insert(range.start, lines[i]);
}
}
};
this.execCommand = function(command, args) {
@ -1260,7 +1297,7 @@ var Editor = function(renderer, session) {
};
/**
* Removes words of text from the editor. A "word" is defined as a string of characters bookended by whitespace.
* Removes the current selection or one character.
* @param {String} dir The direction of the deletion to occur, either "left" or "right"
*
**/
@ -1592,15 +1629,7 @@ var Editor = function(renderer, session) {
**/
this.removeLines = function() {
var rows = this.$getSelectedRows();
var range;
if (rows.first === 0 || rows.last+1 < this.session.getLength())
range = new Range(rows.first, 0, rows.last+1, 0);
else
range = new Range(
rows.first-1, this.session.getLine(rows.first-1).length,
rows.last, this.session.getLine(rows.last).length
);
this.session.remove(range);
this.session.removeFullLines(rows.first, rows.last);
this.clearSelection();
};
@ -1629,9 +1658,7 @@ var Editor = function(renderer, session) {
* @related EditSession.moveLinesUp
**/
this.moveLinesDown = function() {
this.$moveLines(function(firstRow, lastRow) {
return this.session.moveLinesDown(firstRow, lastRow);
});
this.$moveLines(1, false);
};
/**
@ -1640,9 +1667,7 @@ var Editor = function(renderer, session) {
* @related EditSession.moveLinesDown
**/
this.moveLinesUp = function() {
this.$moveLines(function(firstRow, lastRow) {
return this.session.moveLinesUp(firstRow, lastRow);
});
this.$moveLines(-1, false);
};
/**
@ -1666,10 +1691,7 @@ var Editor = function(renderer, session) {
*
**/
this.copyLinesUp = function() {
this.$moveLines(function(firstRow, lastRow) {
this.session.duplicateLines(firstRow, lastRow);
return 0;
});
this.$moveLines(-1, true);
};
/**
@ -1679,51 +1701,61 @@ var Editor = function(renderer, session) {
*
**/
this.copyLinesDown = function() {
this.$moveLines(function(firstRow, lastRow) {
return this.session.duplicateLines(firstRow, lastRow);
});
this.$moveLines(1, true);
};
/**
* Executes a specific function, which can be anything that manipulates selected lines, such as copying them, duplicating them, or shifting them.
* @param {Function} mover A method to call on each selected row
*
* for internal use
* @ignore
*
**/
this.$moveLines = function(mover) {
this.$moveLines = function(dir, copy) {
var rows, moved;
var selection = this.selection;
if (!selection.inMultiSelectMode || this.inVirtualSelectionMode) {
var range = selection.toOrientedRange();
var rows = this.$getSelectedRows(range);
var linesMoved = mover.call(this, rows.first, rows.last);
range.moveBy(linesMoved, 0);
rows = this.$getSelectedRows(range);
moved = this.session.$moveLines(rows.first, rows.last, copy ? 0 : dir);
if (copy && dir == -1) moved = 0;
range.moveBy(moved, 0);
selection.fromOrientedRange(range);
} else {
var ranges = selection.rangeList.ranges;
selection.rangeList.detach(this.session);
for (var i = ranges.length; i--; ) {
this.inVirtualSelectionMode = true;
var diff = 0;
var totalDiff = 0;
var l = ranges.length;
for (var i = 0; i < l; i++) {
var rangeIndex = i;
var rows = ranges[i].collapseRows();
var last = rows.end.row;
var first = rows.start.row;
while (i--) {
rows = ranges[i].collapseRows();
if (first - rows.end.row <= 1)
first = rows.end.row;
else
ranges[i].moveBy(diff, 0);
rows = this.$getSelectedRows(ranges[i]);
var first = rows.first;
var last = rows.last;
while (++i < l) {
if (totalDiff) ranges[i].moveBy(totalDiff, 0);
var subRows = this.$getSelectedRows(ranges[i]);
if (copy && subRows.first != last)
break;
else if (!copy && subRows.first > last + 1)
break;
last = subRows.last;
}
i++;
var linesMoved = mover.call(this, first, last);
while (rangeIndex >= i) {
ranges[rangeIndex].moveBy(linesMoved, 0);
rangeIndex--;
i--;
diff = this.session.$moveLines(first, last, copy ? 0 : dir);
if (copy && dir == -1) rangeIndex = i + 1;
while (rangeIndex <= i) {
ranges[rangeIndex].moveBy(diff, 0);
rangeIndex++;
}
if (!copy) diff = 0;
totalDiff += diff;
}
selection.fromOrientedRange(selection.ranges[0]);
selection.rangeList.attach(this.session);
this.inVirtualSelectionMode = false;
}
};
@ -1736,8 +1768,8 @@ var Editor = function(renderer, session) {
*
* @returns {Object}
**/
this.$getSelectedRows = function() {
var range = this.getSelectionRange().collapseRows();
this.$getSelectedRows = function(range) {
range = (range || this.getSelectionRange()).collapseRows();
return {
first: this.session.getRowFoldStart(range.start.row),
@ -2650,6 +2682,7 @@ config.defineOptions(Editor.prototype, "editor", {
useSoftTabs: "session",
tabSize: "session",
wrap: "session",
indentedSoftWrap: "session",
foldStyle: "session",
mode: "session"
});

View file

@ -578,15 +578,14 @@ var onSelectionChange = function(evt) {
* and deleting text.
* @param {!Event} evt The event.
*/
var onChange = function(evt) {
var data = evt.data;
var onChange = function(delta) {
switch (data.action) {
case 'removeText':
case 'remove':
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':
case 'insert':
cvox.Api.speak(data.text, 0);
/* Let the future cursor change event know it's from text change. */
changed = true;

View file

@ -44,13 +44,12 @@ var ElasticTabstopsLite = function(editor) {
this.onExec = function() {
recordChanges = true;
};
this.onChange = function(e) {
var range = e.data.range
this.onChange = function(delta) {
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);
if (changedRows.indexOf(delta.start.row) == -1)
changedRows.push(delta.start.row);
if (delta.end.row != delta.start.row)
changedRows.push(delta.end.row);
}
};
};

View file

@ -342,29 +342,29 @@ var keymap = {
var editorProxy = new AceEmmetEditor();
exports.commands = new HashHandler();
exports.runEmmetCommand = function(editor) {
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;
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);
@ -393,7 +393,7 @@ exports.updateCommands = function(editor, enabled) {
};
exports.isSupportedMode = function(modeId) {
return modeId && /css|less|scss|sass|stylus|html|php|twig/.test(modeId);
return modeId && /css|less|scss|sass|stylus|html|php|twig|ejs|handlebars/.test(modeId);
};
var onChangeMode = function(e, target) {
@ -406,9 +406,8 @@ var onChangeMode = function(e, target) {
if (enabled) {
if (typeof emmetPath == "string") {
require("ace/config").loadModule(emmetPath, function() {
emmetPath = null;
});
emmetPath = null;
}
}
exports.updateCommands(editor, enabled);

View file

@ -62,7 +62,7 @@ function findAnnotations(session, row, dir) {
if (i < 0)
i = -i - 1;
if (i >= annotations.length - 1)
if (i >= annotations.length)
i = dir > 0 ? 0 : annotations.length - 1;
else if (i === 0 && dir < 0)
i = annotations.length - 1;

View file

@ -140,7 +140,7 @@ var loadSnippetFile = function(id) {
function getCompletionPrefix(editor) {
var pos = editor.getCursorPosition();
var line = editor.session.getLine(pos.row);
var prefix = util.retrievePrecedingIdentifier(line, pos.column);
var prefix;
// Try to find custom prefixes on the completers
editor.completers.forEach(function(completer) {
if (completer.identifierRegexps) {
@ -150,16 +150,13 @@ function getCompletionPrefix(editor) {
});
}
});
return prefix;
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))
@ -174,7 +171,6 @@ var doLiveAutocomplete = function(e) {
editor.completer = new Autocomplete();
}
// Disable autoInsert
editor.completer.autoSelect = false;
editor.completer.autoInsert = false;
editor.completer.showPopup(editor);
}

View file

@ -91,6 +91,12 @@ module.exports.generateSettingsMenu = function generateSettingsMenu (editor) {
elements.forEach(function(element) {
topmenu.appendChild(element);
});
var el = topmenu.appendChild(document.createElement('div'));
var version = "1.1.9";
el.style.padding = "1em";
el.textContent = "Ace version " + version;
return topmenu;
}
/**

View file

@ -43,10 +43,11 @@ Mode.prototype.supportsFile = function(filename) {
// todo firstlinematch
var supportedModes = {
ABAP: ["abap"],
ABC: ["abc"],
ActionScript:["as"],
ADA: ["ada|adb"],
Apache_Conf: ["^htaccess|^htgroups|^htpasswd|^conf|htaccess|htgroups|htpasswd"],
AsciiDoc: ["asciidoc"],
AsciiDoc: ["asciidoc|adoc"],
Assembly_x86:["asm"],
AutoHotKey: ["ahk"],
BatchFile: ["bat|cmd"],
@ -98,6 +99,7 @@ var supportedModes = {
JSX: ["jsx"],
Julia: ["jl"],
LaTeX: ["tex|latex|ltx|bib"],
Lean: ["lean|hlean"],
LESS: ["less"],
Liquid: ["liquid"],
Lisp: ["lisp"],
@ -109,17 +111,19 @@ var supportedModes = {
Lucene: ["lucene"],
Makefile: ["^Makefile|^GNUmakefile|^makefile|^OCamlMakefile|make"],
Markdown: ["md|markdown"],
Mask: ["mask"],
MATLAB: ["matlab"],
MEL: ["mel"],
MUSHCode: ["mc|mush"],
MySQL: ["mysql"],
Nix: ["nix"],
Nim: ["nim"],
ObjectiveC: ["m|mm"],
OCaml: ["ml|mli"],
Pascal: ["pas|p"],
Perl: ["pl|pm"],
pgSQL: ["pgsql"],
PHP: ["php|phtml"],
PHP: ["php|phtml|shtml|php3|php4|php5|phps|phpt|aw|ctp"],
Powershell: ["ps1"],
Praat: ["praat|praatscript|psc|proc"],
Prolog: ["plg|prolog"],
@ -143,6 +147,7 @@ var supportedModes = {
Soy_Template:["soy"],
Space: ["space"],
SQL: ["sql"],
SQLServer: ["sqlserver"],
Stylus: ["styl|stylus"],
SVG: ["svg"],
Tcl: ["tcl"],
@ -157,9 +162,11 @@ var supportedModes = {
Velocity: ["vm"],
Verilog: ["v|vh|sv|svh"],
VHDL: ["vhd|vhdl"],
XML: ["xml|rdf|rss|wsdl|xslt|atom|mathml|mml|xul|xbl"],
XML: ["xml|rdf|rss|wsdl|xslt|atom|mathml|mml|xul|xbl|xaml"],
XQuery: ["xq"],
YAML: ["yaml|yml"]
YAML: ["yaml|yml"],
// Add the missing mode "Django" to ext-modelist
Django: ["html"]
};
var nameOverrides = {
@ -188,4 +195,3 @@ module.exports = {
};
});

View file

@ -1,24 +1,31 @@
.ace_static_highlight {
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro', 'Droid Sans Mono', monospace;
font-size: 12px;
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro', 'Droid Sans Mono', monospace;
font-size: 12px;
white-space: pre-wrap
}
.ace_static_highlight .ace_gutter {
width: 25px !important;
float: left;
width: 2em;
text-align: right;
padding: 0 3px 0 0;
margin-right: 3px;
position: static !important;
}
.ace_static_highlight .ace_line { clear: both; }
.ace_static_highlight.ace_show_gutter .ace_line {
padding-left: 2.6em;
}
.ace_static_highlight .ace_line { position: relative; }
.ace_static_highlight .ace_gutter-cell {
-moz-user-select: -moz-none;
-khtml-user-select: none;
-webkit-user-select: none;
user-select: none;
-moz-user-select: -moz-none;
-khtml-user-select: none;
-webkit-user-select: none;
user-select: none;
top: 0;
bottom: 0;
left: 0;
position: absolute;
}

View file

@ -37,6 +37,10 @@ var baseStyles = require("../requirejs/text!./static.css");
var config = require("../config");
var dom = require("../lib/dom");
var SimpleTextLayer = function() {
this.config = {};
};
SimpleTextLayer.prototype = TextLayer.prototype;
var highlight = function(el, opts, callback) {
var m = el.className.match(/lang-(\w+)/);
@ -149,12 +153,8 @@ highlight.renderSync = function(input, mode, theme, lineStart, disableGutter) {
session.setUseWorker(false);
session.setMode(mode);
var textLayer = new TextLayer(document.createElement("div"));
var textLayer = new SimpleTextLayer();
textLayer.setSession(session);
textLayer.config = {
characterWidth: 10,
lineHeight: 20
};
session.setValue(input);
@ -171,7 +171,8 @@ highlight.renderSync = function(input, mode, theme, lineStart, disableGutter) {
// let's prepare the whole html
var html = "<div class='" + theme.cssClass + "'>" +
"<div class='ace_static_highlight' style='counter-reset:ace_line " + (lineStart - 1) + "'>" +
"<div class='ace_static_highlight" + (disableGutter ? "" : " ace_show_gutter") +
"' style='counter-reset:ace_line " + (lineStart - 1) + "'>" +
stringBuilder.join("") +
"</div>" +
"</div>";

View file

@ -28,12 +28,12 @@ module.exports = {
var mode = new JavaScriptMode();
var result = highlighter.render(snippet, mode, theme);
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>"
assert.equal(result.html, "<div class='ace-tomorrow'><div class='ace_static_highlight ace_show_gutter' 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'>/** this is a function</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_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>\n</div>"
+ "<div class='ace_line'><span class='ace_gutter ace_gutter-cell' unselectable='on'></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>\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);

View file

@ -51,12 +51,14 @@ var themeData = [
["Dreamweaver" ],
["Eclipse" ],
["GitHub" ],
["IPlastic" ],
["Solarized Light"],
["TextMate" ],
["Tomorrow" ],
["XCode" ],
["Kuroir"],
["KatzenMilch"],
["SQL Server" ,"sqlserver" , "light"],
["Ambiance" ,"ambiance" , "dark"],
["Chaos" ,"chaos" , "dark"],
["Clouds Midnight" ,"clouds_midnight" , "dark"],
@ -71,6 +73,7 @@ var themeData = [
["Solarized Dark" ,"solarized_dark" , "dark"],
["Terminal" ,"terminal" , "dark"],
["Tomorrow Night" ,"tomorrow_night" , "dark"],
["The Night After Tomorrow" ,"the_night_after_tomorrow" , "dark"],
["Tomorrow Night Blue" ,"tomorrow_night_blue" , "dark"],
["Tomorrow Night Bright","tomorrow_night_bright" , "dark"],
["Tomorrow Night 80s" ,"tomorrow_night_eighties" , "dark"],

View file

@ -64,6 +64,34 @@ function IncrementalSearch() {
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) {
@ -77,7 +105,7 @@ oop.inherits(IncrementalSearch, Search);
this.$mousedownHandler = ed.addEventListener('mousedown', this.onMouseDown.bind(this));
this.selectionFix(ed);
this.statusMessage(true);
}
};
this.deactivate = function(reset) {
this.cancelSearch(reset);
@ -89,7 +117,7 @@ oop.inherits(IncrementalSearch, Search);
}
ed.onPaste = this.$originalEditorOnPaste;
this.message('');
}
};
this.selectionFix = function(editor) {
// Fix selection bug: When clicked inside the editor
@ -100,7 +128,7 @@ oop.inherits(IncrementalSearch, Search);
if (editor.selection.isEmpty() && !editor.session.$emacsMark) {
editor.clearSelection();
}
}
};
this.highlight = function(regexp) {
var sess = this.$editor.session,
@ -108,7 +136,7 @@ oop.inherits(IncrementalSearch, Search);
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;
@ -122,7 +150,7 @@ oop.inherits(IncrementalSearch, Search);
}
this.highlight(null);
return Range.fromPoints(this.$currentPos, this.$currentPos);
}
};
this.highlightAndFindWithNeedle = function(moveToNext, needleUpdateFunc) {
if (!this.$editor) return null;
@ -135,7 +163,7 @@ oop.inherits(IncrementalSearch, Search);
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;
@ -148,25 +176,33 @@ oop.inherits(IncrementalSearch, Search);
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.highlight(options.re);
}
this.statusMessage(found);
return found;
}
};
this.addString = function(s) {
return this.highlightAndFindWithNeedle(false, function(needle) {
return needle + s;
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) {
return needle.length > 0 ? needle.substring(0, needle.length-1) : 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
@ -179,17 +215,29 @@ oop.inherits(IncrementalSearch, Search);
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 = '';
@ -197,7 +245,7 @@ oop.inherits(IncrementalSearch, Search);
msg += 'isearch: ' + options.needle;
msg += found ? '' : ' (not found)';
this.message(msg);
}
};
this.message = function(msg) {
if (this.$editor.showCommandLine) {
@ -206,7 +254,7 @@ oop.inherits(IncrementalSearch, Search);
} else {
console.log(msg);
}
}
};
}).call(IncrementalSearch.prototype);

View file

@ -40,6 +40,7 @@ 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;
@ -72,6 +73,7 @@ module.exports = {
setUp: function() {
var session = new EditSession(["abc123", "xyz124"]);
editor = new Editor(new MockRenderer(), session);
new MultiSelect(editor);
iSearch = new IncrementalSearch();
},

View file

@ -428,7 +428,7 @@ exports.emacsKeys = {
"M-;": "togglecomment",
"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
"C-x r": "selectRectangularRegion",
"M-x": {command: "focusCommandLine", args: "M-x "}
@ -483,7 +483,7 @@ exports.handler.addCommands({
// 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)})
if (editor.inMultiSelectMode) editor.forEachSelection({exec: editor.clearSelection.bind(editor)});
else editor.clearSelection();
if (mark) editor.pushEmacsMark(null);
return;

View file

@ -87,9 +87,12 @@ MultiHashHandler.prototype = HashHandler.prototype;
}
};
this.bindKey = function(key, command, asDefault) {
if (typeof key == "object")
this.bindKey = function(key, command, position) {
if (typeof key == "object") {
if (position == undefined)
position = key.position;
key = key[this.platform];
}
if (!key)
return;
if (typeof command == "function")
@ -110,11 +113,15 @@ MultiHashHandler.prototype = HashHandler.prototype;
}
var binding = this.parseKeys(keyPart);
var id = KEY_MODS[binding.hashId] + binding.key;
this._addCommandToBinding(chain + id, command, asDefault);
this._addCommandToBinding(chain + id, command, position);
}, this);
};
this._addCommandToBinding = function(keyId, command, asDefault) {
function getPosition(command) {
return typeof command == "object" && command.bindKey
&& command.bindKey.position || 0;
}
this._addCommandToBinding = function(keyId, command, position) {
var ckb = this.commandKeyBinding, i;
if (!command) {
delete ckb[keyId];
@ -126,11 +133,21 @@ MultiHashHandler.prototype = HashHandler.prototype;
} 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);
if (typeof position != "number") {
if (position || command.isDefault)
position = -100;
else
position = getPosition(command);
}
var commands = ckb[keyId];
for (i = 0; i < commands.length; i++) {
var other = commands[i];
var otherPos = getPosition(other);
if (otherPos > position)
break;
}
commands.splice(i, 0, command);
}
};
@ -219,10 +236,18 @@ MultiHashHandler.prototype = HashHandler.prototype;
}
}
if (data.$keyChain && keyCode > 0)
data.$keyChain = "";
if (data.$keyChain) {
if ((!hashId || hashId == 4) && keyString.length == 1)
data.$keyChain = data.$keyChain.slice(0, -key.length - 1); // wait for input
else if (hashId == -1 || keyCode > 0)
data.$keyChain = ""; // reset keyChain
}
return {command: command};
};
this.getStatusText = function(editor, data) {
return data.$keyChain || "";
};
}).call(HashHandler.prototype);

View file

@ -45,13 +45,13 @@ var TextInput = function(parentNode, host) {
if (useragent.isTouchPad)
text.setAttribute("x-palm-disable-auto-cap", true);
text.wrap = "off";
text.autocorrect = "off";
text.autocapitalize = "off";
text.spellcheck = false;
text.setAttribute("wrap", "off");
text.setAttribute("autocorrect", "off");
text.setAttribute("autocapitalize", "off");
text.setAttribute("spellcheck", false);
text.style.opacity = "0";
if (useragent.isOldIE) text.style.top = "-100px";
if (useragent.isOldIE) text.style.top = "-1000px";
parentNode.insertBefore(text, parentNode.firstChild);
var PLACEHOLDER = "\x01\x01";
@ -75,7 +75,15 @@ var TextInput = function(parentNode, host) {
host.onFocus(e);
resetSelection();
});
this.focus = function() { text.focus(); };
this.focus = function() {
if (tempStyle) return text.focus();
text.style.position = "fixed";
text.style.top = "-1000px";
text.focus();
setTimeout(function() {
text.style.position = "";
}, 0);
};
this.blur = function() { text.blur(); };
this.isFocused = function() {
return isFocused;
@ -95,6 +103,11 @@ var TextInput = function(parentNode, host) {
function resetSelection(isEmpty) {
if (inComposition)
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;
@ -106,6 +119,8 @@ var TextInput = function(parentNode, host) {
try {
text.setSelectionRange(selectionStart, selectionEnd);
} catch(e){}
inComposition = false;
}
function resetValue() {
@ -291,7 +306,7 @@ var TextInput = function(parentNode, host) {
var data = handleClipboardData(e);
if (typeof data == "string") {
if (data)
host.onPaste(data);
host.onPaste(data, e);
if (useragent.isIE)
setTimeout(resetSelection);
event.preventDefault(e);

File diff suppressed because it is too large Load diff

View file

@ -1,618 +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 lang = require("../../lib/lang");
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;
case "c":
editor.session.onFoldWidgetClick(range.start.row, {domEvent:{target :{}}});
break;
case "o":
editor.session.onFoldWidgetClick(range.start.row, {domEvent:{target :{}}});
break;
case "C":
editor.session.foldAll();
break;
case "O":
editor.session.unfold();
break;
}
}
},
"r": {
param: true,
fn: function(editor, range, count, param) {
if (param && param.length) {
if (param.length > 1)
param = param == "return" ? "\n" : param == "tab" ? "\t" : param;
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.session.replace(range, toggled);
else if (text.toLowerCase() != text)
editor.session.replace(range, text.toLowerCase())
else
editor.navigateRight();
}, 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);
}
},
"m": {
param: true,
fn: function(editor, range, count, param) {
var s = editor.session;
var markers = s.vimMarkers || (s.vimMarkers = {});
var c = editor.getCursorPosition();
if (!markers[param]) {
markers[param] = editor.session.doc.createAnchor(c);
}
markers[param].setPosition(c.row, c.column, true);
}
},
"n": {
fn: function(editor, range, count, param) {
var options = editor.getLastSearchOptions();
options.backwards = false;
options.start = null;
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;
options.start = null;
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.moveTo(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();
pos.column = editor.session.getLine(pos.row).length;
var text = lang.stringRepeat("\n" + defaultReg.text, count || 1);
editor.session.insert(pos, text);
editor.moveCursorTo(pos.row + 1, 0);
}
else {
editor.navigateRight();
editor.insert(lang.stringRepeat(defaultReg.text, count || 1));
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();
pos.column = 0;
var text = lang.stringRepeat(defaultReg.text + "\n", count || 1);
editor.session.insert(pos, text);
editor.moveCursorToPosition(pos);
}
else {
editor.insert(lang.stringRepeat(defaultReg.text, count || 1));
}
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) {
var val = ":";
if (count > 1)
val = ".,.+" + count + val;
if (editor.showCommandLine)
editor.showCommandLine(val);
}
},
"/": {
fn: function(editor, range, count, param) {
if (editor.showCommandLine)
editor.showCommandLine("/");
}
},
"?": {
fn: function(editor, range, count, param) {
if (editor.showCommandLine)
editor.showCommandLine("?");
}
},
".": {
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);
}
},
"ctrl-x": {
fn: function(editor, range, count, param) {
editor.modifyNumber(-(count || 1));
}
},
"ctrl-a": {
fn: function(editor, range, count, param) {
editor.modifyNumber(count || 1);
}
}
};
var inputBuffer = exports.inputBuffer = {
accepting: [NUMBER, OPERATOR, MOTION, ACTION],
currentCmd: null,
//currentMode: 0,
currentCount: "",
pendingCount: "",
status: "",
// Types
operator: null,
motion: null,
lastInsertCommands: [],
push: function(editor, ch, keyId) {
var status = this.status;
var isKeyHandled = true;
this.idle = false;
var wObj = this.waitingForParam;
if (/^numpad\d+$/i.test(ch))
ch = ch.substr(6);
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) &&
(/^\d+$/.test(ch) && 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.operator.count = this.getCount();
this.exec(editor, { operator: this.operator }, ch);
}
else {
isKeyHandled = ch.length == 1;
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 = "";
}
if (this.status != status)
editor._emit("changeStatus");
return isKeyHandled;
},
waitForParam: function(cmd) {
this.waitingForParam = cmd;
},
getCount: function() {
var count = this.currentCount || this.pendingCount;
this.currentCount = "";
this.pendingCount = count;
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, motionObj.param ? motionObj : 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.pendingCount = "";
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.moveTo(originRow, 0);
editor.selection.selectTo(cursorRow, endLine.length);
} else {
var endLine = editor.session.getLine(originRow);
editor.selection.moveTo(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;
}
};
});

View file

@ -1,681 +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.selection.moveTo(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;
var LAST_SEARCH_MOTION = {};
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) {
var pos = editor.getCursorPosition();
var col = pos.column;
var lineLen = editor.session.getLine(pos.row).length;
if (lineLen && col !== lineLen)
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 "]":
param = editor.session.$brackets[param];
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, isRepeat) {
if (param == "space") param = " ";
if (!isRepeat)
LAST_SEARCH_MOTION = {ch: "f", param: param};
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, isRepeat) {
if (param == "space") param = " ";
if (!isRepeat)
LAST_SEARCH_MOTION = {ch: "F", param: param};
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, isRepeat) {
if (param == "space") param = " ";
if (!isRepeat)
LAST_SEARCH_MOTION = {ch: "t", param: param};
var cursor = editor.getCursorPosition();
var column = util.getRightNthChar(editor, cursor, param, count || 1);
if (isRepeat && column == 0 && !(count > 1))
column = util.getRightNthChar(editor, cursor, param, 2);
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, isRepeat) {
if (param == "space") param = " ";
if (!isRepeat)
LAST_SEARCH_MOTION = {ch: "T", param: param};
var cursor = editor.getCursorPosition();
var column = util.getLeftNthChar(editor, cursor, param, count || 1);
if (isRepeat && column === 0 && !(count > 1))
column = util.getLeftNthChar(editor, cursor, param, 2);
if (typeof column === "number") {
cursor.column -= column;
return cursor;
}
}
}),
";": new Motion({
handlesCount: true,
getPos: function(editor, range, count, param, isSel) {
var ch = LAST_SEARCH_MOTION.ch;
if (!ch)
return;
return module.exports[ch].getPos(
editor, range, count, LAST_SEARCH_MOTION.param, isSel, true
);
}
}),
",": new Motion({
handlesCount: true,
getPos: function(editor, range, count, param, isSel) {
var ch = LAST_SEARCH_MOTION.ch;
if (!ch)
return;
var up = ch.toUpperCase();
ch = ch === up ? ch.toLowerCase() : up;
return module.exports[ch].getPos(
editor, range, count, LAST_SEARCH_MOTION.param, isSel, true
);
}
}),
"^": {
nav: function(editor) {
editor.navigateLineStart();
},
sel: function(editor) {
editor.selection.selectLineStart();
}
},
"$": {
handlesCount: true,
nav: function(editor, range, count, param) {
if (count > 1) {
editor.navigateDown(count-1);
}
editor.navigateLineEnd();
},
sel: function(editor, range, count, param) {
if (count > 1) {
editor.selection.moveCursorBy(count-1, 0);
}
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);
}
},
"`": new Motion({
param: true,
handlesCount: true,
getPos: function(editor, range, count, param, isSel) {
var s = editor.session;
var marker = s.vimMarkers && s.vimMarkers[param];
if (marker) {
return marker.getPosition();
}
}
}),
"'": new Motion({
param: true,
handlesCount: true,
getPos: function(editor, range, count, param, isSel) {
var s = editor.session;
var marker = s.vimMarkers && s.vimMarkers[param];
if (marker) {
var pos = marker.getPosition();
var line = editor.session.getLine(pos.row);
pos.column = line.search(/\S/);
if (pos.column == -1)
pos.column = line.length;
return pos;
}
},
isLine: true
})
};
module.exports.backspace = module.exports.left = module.exports.h;
module.exports.space = module.exports['return'] = 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"];
module.exports.home = module.exports["0"];
module.exports.end = module.exports["$"];
});

View file

@ -1,201 +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 registers = require("../registers");
var Range = require("../../../range").Range;
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()) {
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":
editor.$blockScrolling++;
editor.selection.$moveSelection(function() {
editor.selection.moveCursorBy(count - 1, 0);
});
var rows = editor.$getSelectedRows();
range = new Range(rows.first, 0, rows.last, Infinity);
editor.session.remove(range);
editor.$blockScrolling--;
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;
if (param && param.isLine)
param = "y";
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;
}
}
}
};
});

View file

@ -1,132 +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.vimState = "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.vimState = "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.moveTo(pos.row, pos.column);
editor.selection.selectLine();
registers._default.isLine = true;
registers._default.text = editor.getCopyText().replace(/\n$/, "");
editor.selection.moveTo(pos.row, pos.column);
}
};
});

File diff suppressed because it is too large Load diff

View file

@ -195,11 +195,15 @@ var Cursor = function(parentEl) {
}
var style = (this.cursors[cursorIndex++] || this.addCursor()).style;
style.left = pixelPos.left + "px";
style.top = pixelPos.top + "px";
style.width = config.characterWidth + "px";
style.height = config.lineHeight + "px";
if (!this.drawCursor) {
style.left = pixelPos.left + "px";
style.top = pixelPos.top + "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)
this.removeCursor();
@ -211,6 +215,8 @@ var Cursor = function(parentEl) {
this.$pixelPos = pixelPos;
this.restartTimer();
};
this.drawCursor = null;
this.$setOverwrite = function(overwrite) {
if (overwrite != this.overwrite) {

View file

@ -82,9 +82,9 @@ var FontMetrics = exports.FontMetrics = function(parentEl, interval) {
this.$setMeasureNodeStyles = function(style, isRoot) {
style.width = style.height = "auto";
style.left = style.top = "-100px";
style.left = style.top = "0px";
style.visibility = "hidden";
style.position = "fixed";
style.position = "absolute";
style.whiteSpace = "pre";
if (useragent.isIE < 8) {
@ -120,9 +120,9 @@ var FontMetrics = exports.FontMetrics = function(parentEl, interval) {
this.setPolling = function(val) {
if (val) {
this.$pollSizeChanges();
} else {
if (this.$pollSizeChangesTimer)
this.$pollSizeChangesTimer;
} else if (this.$pollSizeChangesTimer) {
clearInterval(this.$pollSizeChangesTimer);
this.$pollSizeChangesTimer = 0;
}
};

View file

@ -100,16 +100,14 @@ var Gutter = function(parentEl) {
}
};
this.$updateAnnotations = function (e) {
this.$updateAnnotations = function (delta) {
if (!this.$annotations.length)
return;
var delta = e.data;
var range = delta.range;
var firstRow = range.start.row;
var len = range.end.row - firstRow;
var firstRow = delta.start.row;
var len = delta.end.row - firstRow;
if (len === 0) {
// do nothing
} else if (delta.action == "removeText" || delta.action == "removeLines") {
} else if (delta.action == 'remove') {
this.$annotations.splice(firstRow, len + 1, null);
} else {
var args = new Array(len + 1);

View file

@ -90,7 +90,7 @@ var Marker = function(parentEl) {
else
this.drawMultiLineMarker(html, range, marker.clazz, config);
} else {
this.drawSingleLineMarker(html, range, marker.clazz + " ace_start", config);
this.drawSingleLineMarker(html, range, marker.clazz + " ace_start" + " ace_br15", config);
}
}
this.element.innerHTML = html.join("");
@ -100,27 +100,30 @@ var Marker = function(parentEl) {
return (row - layerConfig.firstRowScreen) * layerConfig.lineHeight;
};
function getBorderClass(tl, tr, br, bl) {
return (tl ? 1 : 0) | (tr ? 2 : 0) | (br ? 4 : 0) | (bl ? 8 : 0);
}
// Draws a marker, which spans a range of text on multiple lines
this.drawTextMarker = function(stringBuilder, range, clazz, layerConfig, extraStyle) {
// selection start
var row = range.start.row;
var lineRange = new Range(
row, range.start.column,
row, this.session.getScreenLastRowColumn(row)
);
this.drawSingleLineMarker(stringBuilder, lineRange, clazz + " ace_start", layerConfig, 1, extraStyle);
// selection end
row = range.end.row;
lineRange = new Range(row, 0, row, range.end.column);
this.drawSingleLineMarker(stringBuilder, lineRange, clazz, layerConfig, 0, extraStyle);
for (row = range.start.row + 1; row < range.end.row; row++) {
lineRange.start.row = row;
lineRange.end.row = row;
lineRange.end.column = this.session.getScreenLastRowColumn(row);
this.drawSingleLineMarker(stringBuilder, lineRange, clazz, layerConfig, 1, extraStyle);
var session = this.session;
var start = range.start.row;
var end = range.end.row;
var row = start;
var prev = 0;
var curr = 0;
var next = session.getScreenLastRowColumn(row);
var lineRange = new Range(row, range.start.column, row, curr);
for (; row <= end; row++) {
lineRange.start.row = lineRange.end.row = row;
lineRange.start.column = row == start ? range.start.column : session.getRowWrapIndent(row);
lineRange.end.column = next;
prev = curr;
curr = next;
next = row + 1 < end ? session.getScreenLastRowColumn(row + 1) : row == end ? 0 : range.end.column;
this.drawSingleLineMarker(stringBuilder, lineRange,
clazz + (row == start ? " ace_start" : "") + " ace_br"
+ getBorderClass(row == start || row == start + 1 && range.start.column, prev < curr, curr > next, row == end),
layerConfig, row == end ? 0 : 1, extraStyle);
}
};
@ -134,7 +137,7 @@ var Marker = function(parentEl) {
extraStyle = extraStyle || "";
stringBuilder.push(
"<div class='", clazz, " ace_start' style='",
"<div class='", clazz, " ace_br1 ace_start' style='",
"height:", height, "px;",
"right:0;",
"top:", top, "px;",
@ -146,7 +149,7 @@ var Marker = function(parentEl) {
var width = range.end.column * config.characterWidth;
stringBuilder.push(
"<div class='", clazz, "' style='",
"<div class='", clazz, " ace_br12' style='",
"height:", height, "px;",
"width:", width, "px;",
"top:", top, "px;",
@ -155,12 +158,14 @@ var Marker = function(parentEl) {
// all the complete lines
height = (range.end.row - range.start.row - 1) * config.lineHeight;
if (height < 0)
if (height <= 0)
return;
top = this.$getTop(range.start.row + 1, config);
var radiusClass = (range.start.column ? 1 : 0) | (range.end.column ? 0 : 8);
stringBuilder.push(
"<div class='", clazz, "' style='",
"<div class='", clazz, (radiusClass ? " ace_br" + radiusClass : ""), "' style='",
"height:", height, "px;",
"right:0;",
"top:", top, "px;",

View file

@ -52,7 +52,7 @@ var Text = function(parentEl) {
this.EOL_CHAR_LF = "\xAC";
this.EOL_CHAR_CRLF = "\xa4";
this.EOL_CHAR = this.EOL_CHAR_LF;
this.TAB_CHAR = "\u2192"; //"\u21E5";
this.TAB_CHAR = "\u2014"; //"\u21E5";
this.SPACE_CHAR = "\xB7";
this.$padding = 0;
@ -128,11 +128,10 @@ var Text = function(parentEl) {
for (var i = 1; i < tabSize + 1; i++) {
if (this.showInvisibles) {
tabStr.push("<span class='ace_invisible ace_invisible_tab'>"
+ this.TAB_CHAR
+ lang.stringRepeat("\xa0", i - 1)
+ lang.stringRepeat(this.TAB_CHAR, i)
+ "</span>");
} else {
tabStr.push(lang.stringRepeat("\xa0", i));
tabStr.push(lang.stringRepeat(" ", i));
}
}
if (this.displayIndentGuides) {
@ -145,9 +144,9 @@ var Text = function(parentEl) {
spaceClass = " ace_invisible_space";
tabClass = " ace_invisible_tab";
var spaceContent = lang.stringRepeat(this.SPACE_CHAR, this.tabSize);
var tabContent = this.TAB_CHAR + lang.stringRepeat("\xa0", this.tabSize - 1);
var tabContent = lang.stringRepeat(this.TAB_CHAR, this.tabSize);
} else{
var spaceContent = lang.stringRepeat("\xa0", this.tabSize);
var spaceContent = lang.stringRepeat(" ", this.tabSize);
var tabContent = spaceContent;
}
@ -325,9 +324,9 @@ var Text = function(parentEl) {
var replaceReg = /\t|&|<|( +)|([\x00-\x1f\x80-\xa0\xad\u1680\u180E\u2000-\u200f\u2028\u2029\u202F\u205F\u3000\uFEFF])|[\u1100-\u115F\u11A3-\u11A7\u11FA-\u11FF\u2329-\u232A\u2E80-\u2E99\u2E9B-\u2EF3\u2F00-\u2FD5\u2FF0-\u2FFB\u3000-\u303E\u3041-\u3096\u3099-\u30FF\u3105-\u312D\u3131-\u318E\u3190-\u31BA\u31C0-\u31E3\u31F0-\u321E\u3220-\u3247\u3250-\u32FE\u3300-\u4DBF\u4E00-\uA48C\uA490-\uA4C6\uA960-\uA97C\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFAFF\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE66\uFE68-\uFE6B\uFF01-\uFF60\uFFE0-\uFFE6]/g;
var replaceFunc = function(c, a, b, tabIdx, idx4) {
if (a) {
return self.showInvisibles ?
"<span class='ace_invisible ace_invisible_space'>" + lang.stringRepeat(self.SPACE_CHAR, c.length) + "</span>" :
lang.stringRepeat("\xa0", c.length);
return self.showInvisibles
? "<span class='ace_invisible ace_invisible_space'>" + lang.stringRepeat(self.SPACE_CHAR, c.length) + "</span>"
: c;
} else if (c == "&") {
return "&#38;";
} else if (c == "<") {
@ -420,6 +419,8 @@ var Text = function(parentEl) {
);
}
stringBuilder.push(lang.stringRepeat("\xa0", splits.indent));
split ++;
screenColumn = 0;
splitChars = splits[split] || Number.MAX_VALUE;

View file

@ -89,9 +89,9 @@ module.exports = {
"test rendering of indent guides" : function() {
var textLayer = this.textLayer
var EOL = "<span class='ace_invisible ace_invisible_eol'>" + textLayer.EOL_CHAR + "</span>";
var SPACE = function(i) {return Array(i+1).join("\xa0")}
var SPACE = function(i) {return Array(i+1).join(" ")}
var DOT = function(i) {return Array(i+1).join(textLayer.SPACE_CHAR)}
var TAB = function(i) {return textLayer.TAB_CHAR + SPACE(i-1)}
var TAB = function(i) {return Array(i+1).join(textLayer.TAB_CHAR)}
function testRender(results) {
for (var i = results.length; i--; ) {
var stringBuilder = [];

157
lib/ace/lib/app_config.js Normal file
View file

@ -0,0 +1,157 @@
/* ***** 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) {
"no use strict";
var oop = require("./oop");
var EventEmitter = require("./event_emitter").EventEmitter;
var optionsProvider = {
setOptions: function(optList) {
Object.keys(optList).forEach(function(key) {
this.setOption(key, optList[key]);
}, this);
},
getOptions: function(optionNames) {
var result = {};
if (!optionNames) {
optionNames = Object.keys(this.$options);
} else if (!Array.isArray(optionNames)) {
result = optionNames;
optionNames = Object.keys(result);
}
optionNames.forEach(function(key) {
result[key] = this.getOption(key);
}, this);
return result;
},
setOption: function(name, value) {
if (this["$" + name] === value)
return;
var opt = this.$options[name];
if (!opt) {
return warn('misspelled option "' + name + '"');
}
if (opt.forwardTo)
return this[opt.forwardTo] && this[opt.forwardTo].setOption(name, value);
if (!opt.handlesSet)
this["$" + name] = value;
if (opt && opt.set)
opt.set.call(this, value);
},
getOption: function(name) {
var opt = this.$options[name];
if (!opt) {
return warn('misspelled option "' + name + '"');
}
if (opt.forwardTo)
return this[opt.forwardTo] && this[opt.forwardTo].getOption(name);
return opt && opt.get ? opt.get.call(this) : this["$" + name];
}
};
function warn(message) {
if (typeof console != "undefined" && console.warn)
console.warn.apply(console, arguments);
}
function reportError(msg, data) {
var e = new Error(msg);
e.data = data;
if (typeof console == "object" && console.error)
console.error(e);
setTimeout(function() { throw e; });
}
var AppConfig = function() {
this.$defaultOptions = {};
};
(function() {
// module loading
oop.implement(this, EventEmitter);
/*
* option {name, value, initialValue, setterName, set, get }
*/
this.defineOptions = function(obj, path, options) {
if (!obj.$options)
this.$defaultOptions[path] = obj.$options = {};
Object.keys(options).forEach(function(key) {
var opt = options[key];
if (typeof opt == "string")
opt = {forwardTo: opt};
opt.name || (opt.name = key);
obj.$options[opt.name] = opt;
if ("initialValue" in opt)
obj["$" + opt.name] = opt.initialValue;
});
// implement option provider interface
oop.implement(obj, optionsProvider);
return this;
};
this.resetOptions = function(obj) {
Object.keys(obj.$options).forEach(function(key) {
var opt = obj.$options[key];
if ("value" in opt)
obj.setOption(key, opt.value);
});
};
this.setDefaultValue = function(path, name, value) {
var opts = this.$defaultOptions[path] || (this.$defaultOptions[path] = {});
if (opts[name]) {
if (opts.forwardTo)
this.setDefaultValue(opts.forwardTo, name, value);
else
opts[name].value = value;
}
};
this.setDefaultValues = function(path, optionHash) {
Object.keys(optionHash).forEach(function(key) {
this.setDefaultValue(path, key, optionHash[key]);
}, this);
};
this.warn = warn;
this.reportError = reportError;
}).call(AppConfig.prototype);
exports.AppConfig = AppConfig;
});

View file

@ -31,9 +31,6 @@
define(function(require, exports, module) {
"use strict";
if (typeof document == "undefined")
return;
var XHTML_NS = "http://www.w3.org/1999/xhtml";
exports.getDocumentHead = function(doc) {
@ -94,6 +91,11 @@ exports.toggleCssClass = function(el, name) {
return add;
};
if (typeof document == "undefined") {
exports.importCssString = function() {};
return;
}
/*
* Add or remove a CSS class from the list of classes on the given node
* depending on the value of <tt>include</tt>
@ -175,6 +177,7 @@ exports.getInnerHeight = function(element) {
);
};
if (window.pageYOffset !== undefined) {
exports.getPageScrollTop = function() {
return window.pageYOffset;

View file

@ -241,32 +241,17 @@ function normalizeCommandKeys(callback, e, keyCode) {
if (keyCode === 18 || keyCode === 17) {
var location = "location" in e ? e.location : e.keyLocation;
if (keyCode === 17 && location === 1) {
ts = e.timeStamp;
if (pressedKeys[keyCode] == 1)
ts = e.timeStamp;
} else if (keyCode === 18 && hashId === 3 && location === 2) {
var dt = -ts;
ts = e.timeStamp;
dt += ts;
if (dt < 3)
var dt = e.timeStamp - ts;
if (dt < 50)
pressedKeys.altGr = true;
}
}
}
if (keyCode in keys.MODIFIER_KEYS) {
switch (keys.MODIFIER_KEYS[keyCode]) {
case "Alt":
hashId = 2;
break;
case "Shift":
hashId = 4;
break;
case "Ctrl":
hashId = 1;
break;
default:
hashId = 8;
break;
}
keyCode = -1;
}
@ -323,7 +308,7 @@ exports.addCommandKeyListener = function(el, callback) {
var lastDefaultPrevented = null;
addListener(el, "keydown", function(e) {
pressedKeys[e.keyCode] = true;
pressedKeys[e.keyCode] = (pressedKeys[e.keyCode] || 0) + 1;
var result = normalizeCommandKeys(callback, e, e.keyCode);
lastDefaultPrevented = e.defaultPrevented;
return result;
@ -341,13 +326,14 @@ exports.addCommandKeyListener = function(el, callback) {
});
if (!pressedKeys) {
pressedKeys = Object.create(null);
addListener(window, "focus", function(e) {
pressedKeys = Object.create(null);
});
resetPressedKeys();
addListener(window, "focus", resetPressedKeys);
}
}
};
function resetPressedKeys(e) {
pressedKeys = Object.create(null);
}
if (window.postMessage && !useragent.isOldIE) {
var postMessageId = 1;

View file

@ -104,8 +104,8 @@ var Keys = (function() {
73: 'i', 74: 'j', 75: 'k', 76: 'l', 77: 'm', 78: 'n', 79: 'o',
80: 'p', 81: 'q', 82: 'r', 83: 's', 84: 't', 85: 'u', 86: 'v',
87: 'w', 88: 'x', 89: 'y', 90: 'z', 107: '+', 109: '-', 110: '.',
187: '=', 188: ',', 189: '-', 190: '.', 191: '/', 192: '`', 219: '[',
220: '\\',221: ']', 222: '\''
186: ';', 187: '=', 188: ',', 189: '-', 190: '.', 191: '/', 192: '`',
219: '[', 220: '\\',221: ']', 222: '\''
}
};
@ -146,7 +146,7 @@ var Keys = (function() {
})();
ret.KEY_MODS[0] = "";
ret.KEY_MODS[-1] = "input";
ret.KEY_MODS[-1] = "input-";
return ret;
})();

View file

@ -81,20 +81,24 @@ exports.copyArray = function(array){
return copy;
};
exports.deepCopy = function (obj) {
exports.deepCopy = function deepCopy(obj) {
if (typeof obj !== "object" || !obj)
return obj;
var copy;
if (Array.isArray(obj)) {
copy = [];
for (var key = 0; key < obj.length; key++) {
copy[key] = deepCopy(obj[key]);
}
return copy;
}
var cons = obj.constructor;
if (cons === RegExp)
return obj;
var copy = cons();
copy = cons();
for (var key in obj) {
if (typeof obj[key] === "object") {
copy[key] = exports.deepCopy(obj[key]);
} else {
copy[key] = obj[key];
}
copy[key] = deepCopy(obj[key]);
}
return copy;
};

View file

@ -113,18 +113,16 @@ function LineWidgets(session) {
});
};
this.updateOnChange = function(e) {
this.updateOnChange = function(delta) {
var lineWidgets = this.session.lineWidgets;
if (!lineWidgets) return;
var delta = e.data;
var range = delta.range;
var startRow = range.start.row;
var len = range.end.row - startRow;
var startRow = delta.start.row;
var len = delta.end.row - startRow;
if (len === 0) {
// return
} else if (delta.action == "removeText" || delta.action == "removeLines") {
} else if (delta.action == 'remove') {
var removed = lineWidgets.splice(startRow + 1, len);
removed.forEach(function(w) {
w && this.removeLineWidget(w);

View file

@ -13,7 +13,7 @@
[1, +1, -1, 12_345, 0.000_1,
_, 3_1, 1_2, 1_.0, 0._1];
{:id => 34, :key => "value"}
{:id => ?", :key => "value", anotherKey: [x, y?]}
=begin
=end

File diff suppressed because it is too large Load diff

View file

@ -137,7 +137,12 @@
"start",
["text"," "],
["keyword","#if"],
["constant.other"," VERBOSE >= 2"]
["text"," "],
["identifier","VERBOSE"],
["text"," "],
["keyword.operator",">="],
["text"," "],
["constant.numeric","2"]
],[
"start",
["text"," "],

View file

@ -0,0 +1,267 @@
[[
"start",
["comment.line.double-dash","-- https://github.com/Cirru/cirru-gopher/blob/master/code/scope.cr,"]
],[
"start"
],[
"line",
["support.function","set"],
["text"," "],
["variable.parameter","a"],
["text"," "],
["storage.modifier","("],
["support.function","int"],
["text"," "],
["constant.numeric","2"],
["storage.modifier",")"]
],[
"start"
],[
"line",
["support.function","print"],
["text"," "],
["storage.modifier","("],
["support.function","self"],
["storage.modifier",")"]
],[
"start"
],[
"line",
["support.function","set"],
["text"," "],
["variable.parameter","c"],
["text"," "],
["storage.modifier","("],
["support.function","child"],
["storage.modifier",")"]
],[
"start"
],[
"line",
["support.function","under"],
["text"," "],
["variable.parameter","c"]
],[
"line",
["markup.raw"," "],
["support.function","under"],
["text"," "],
["variable.parameter","parent"]
],[
"line",
["markup.raw"," "],
["support.function","print"],
["text"," "],
["variable.parameter","a"]
],[
"start"
],[
"line",
["support.function","print"],
["text"," "],
["storage.modifier","$"],
["text"," "],
["support.function","get"],
["text"," "],
["variable.parameter","c"],
["text"," "],
["variable.parameter","a"]
],[
"start"
],[
"line",
["support.function","set"],
["text"," "],
["variable.parameter","c"],
["text"," "],
["variable.parameter","x"],
["text"," "],
["storage.modifier","("],
["support.function","int"],
["text"," "],
["constant.numeric","3"],
["storage.modifier",")"]
],[
"line",
["support.function","print"],
["text"," "],
["storage.modifier","$"],
["text"," "],
["support.function","get"],
["text"," "],
["variable.parameter","c"],
["text"," "],
["variable.parameter","x"]
],[
"start"
],[
"line",
["support.function","set"],
["text"," "],
["variable.parameter","just-print"],
["text"," "],
["storage.modifier","$"],
["text"," "],
["support.function","code"]
],[
"line",
["markup.raw"," "],
["support.function","print"],
["text"," "],
["variable.parameter","a"]
],[
"start"
],[
"line",
["support.function","print"],
["text"," "],
["variable.parameter","just-print"]
],[
"start"
],[
"line",
["support.function","eval"],
["text"," "],
["storage.modifier","("],
["support.function","self"],
["storage.modifier",")"],
["text"," "],
["variable.parameter","just-print"]
],[
"line",
["support.function","eval"],
["text"," "],
["variable.parameter","just-print"]
],[
"start"
],[
"line",
["support.function","print"],
["text"," "],
["storage.modifier","("],
["support.function","string"],
["text"," "],
["string.quoted.double","\"string with space\""],
["storage.modifier",")"]
],[
"line",
["support.function","print"],
["text"," "],
["storage.modifier","("],
["support.function","string"],
["text"," "],
["string.quoted.double","\"escapes "],
["constant.character.escape","\\n"],
["string.quoted.double"," "],
["constant.character.escape","\\\"\\\\"],
["string.quoted.double","\""],
["storage.modifier",")"]
],[
"start"
],[
"start",
["support.function","brackets"],
["text"," "],
["storage.modifier","((((()))))"]
],[
"start"
],[
"line",
["string.quoted.double","\"eval\""],
["text"," "],
["storage.modifier","$"],
["text"," "],
["support.function","string"],
["text"," "],
["string.quoted.double","\"eval\""]
],[
"start"
],[
"line",
["support.function","print"],
["text"," "],
["storage.modifier","("],
["support.function","add"],
["text"," "],
["storage.modifier","$"],
["text"," "],
["storage.modifier","("],
["support.function","int"],
["text"," "],
["constant.numeric","1"],
["storage.modifier",")"],
["text"," "],
["storage.modifier","("],
["support.function","int"],
["text"," "],
["constant.numeric","2"],
["storage.modifier","))"]
],[
"start"
],[
"start",
["support.function","print"],
["text"," "],
["storage.modifier","$"],
["text"," "],
["support.function","unwrap"],
["text"," "],
["storage.modifier","$"]
],[
"line",
["text"," "],
["support.function","map"],
["text"," "],
["storage.modifier","("],
["support.function","a"],
["text"," "],
["storage.modifier","$"],
["text"," "],
["support.function","int"],
["text"," "],
["constant.numeric","1"],
["storage.modifier",")"],
["text"," "],
["storage.modifier","("],
["support.function","b"],
["text"," "],
["storage.modifier","$"],
["text"," "],
["support.function","int"],
["text"," "],
["constant.numeric","2"],
["storage.modifier",")"]
],[
"start"
],[
"line",
["support.function","print"],
["text"," "],
["variable.parameter","a"]
],[
"line",
["markup.raw"," "],
["support.function","int"],
["text"," "],
["constant.numeric","1"]
],[
"line",
["markup.raw"," "],
["storage.modifier",","],
["text"," "],
["variable.parameter","b"],
["text"," "],
["variable.parameter","c"]
],[
"line",
["markup.raw"," "],
["support.function","int"],
["text"," "],
["constant.numeric","2"]
],[
"line",
["markup.raw"," "],
["storage.modifier",","],
["text"," "],
["variable.parameter","d"]
]]

View file

@ -0,0 +1,196 @@
[[
"start",
["keyword.control.module.elixir","defmodule"],
["meta.module.elixir"," "],
["entity.name.type.module.elixir","HelloModule"],
["text"," "],
["keyword.control.elixir","do"]
],[
"comment.documentation.heredoc",
["text"," "],
["comment.documentation.heredoc","@moduledoc \"\"\""]
],[
"comment.documentation.heredoc",
["comment.documentation.heredoc"," This is supposed to be `markdown`."]
],[
"comment.documentation.heredoc",
["comment.documentation.heredoc"," __Yes__ this is [mark](http://down.format)"]
],[
"comment.documentation.heredoc"
],[
"comment.documentation.heredoc",
["comment.documentation.heredoc"," # Truly"]
],[
"comment.documentation.heredoc"
],[
"comment.documentation.heredoc",
["comment.documentation.heredoc"," ## marked"]
],[
"comment.documentation.heredoc"
],[
"comment.documentation.heredoc",
["comment.documentation.heredoc"," * with lists"]
],[
"comment.documentation.heredoc",
["comment.documentation.heredoc"," * more"]
],[
"comment.documentation.heredoc",
["comment.documentation.heredoc"," * and more"]
],[
"comment.documentation.heredoc"
],[
"comment.documentation.heredoc",
["comment.documentation.heredoc"," Even.with(code)"]
],[
"comment.documentation.heredoc",
["comment.documentation.heredoc"," blocks |> with |> samples"]
],[
"comment.documentation.heredoc"
],[
"comment.documentation.heredoc",
["comment.documentation.heredoc"," _Docs are first class citizens in Elixir_ (Jose Valim)"]
],[
"start",
["comment.documentation.heredoc"," \"\"\""]
],[
"start",
["text"," "]
],[
"start",
["text"," "],
["punctuation.definition.comment.elixir","#"],
["comment.line.number-sign.elixir"," A \"Hello world\" function"]
],[
"start",
["text"," "],
["keyword.control.elixir","def"],
["text"," some_fun "],
["keyword.control.elixir","do"]
],[
"start",
["text"," "],
["variable.other.constant.elixir","IO"],
["punctuation.separator.method.elixir","."],
["text","puts "],
["punctuation.definition.string.begin.elixir","\""],
["string.quoted.double.elixir","Juhu Kinners!"],
["punctuation.definition.string.end.elixir","\""]
],[
"start",
["text"," "],
["keyword.control.elixir","end"]
],[
"start",
["text"," "],
["punctuation.definition.comment.elixir","#"],
["comment.line.number-sign.elixir"," A private function"]
],[
"start",
["text"," "],
["keyword.control.elixir","defp"],
["text"," priv "],
["keyword.control.elixir","do"]
],[
"punctuation.definition.string.begin.elixir7",
["text"," is_regex "],
["punctuation.definition.string.begin.elixir","~r\"\"\""]
],[
"punctuation.definition.string.begin.elixir7",
["string.quoted.double.heredoc.elixir"," This is a regex"]
],[
"punctuation.definition.string.begin.elixir7",
["string.quoted.double.heredoc.elixir"," spanning several"]
],[
"punctuation.definition.string.begin.elixir7",
["string.quoted.double.heredoc.elixir"," lines."]
],[
"start",
["punctuation.definition.string.end.elixir"," \"\"\""]
],[
"start",
["text"," x "],
["keyword.operator.assignment.elixir","="],
["text"," elem"],
["punctuation.section.function.elixir","("],
["punctuation.section.scope.elixir","{"],
["text"," "],
["punctuation.definition.constant.elixir",":"],
["constant.other.symbol.elixir","a"],
["punctuation.separator.object.elixir",","],
["text"," "],
["punctuation.definition.constant.elixir",":"],
["constant.other.symbol.elixir","b"],
["punctuation.separator.object.elixir",","],
["text"," "],
["punctuation.definition.constant.elixir",":"],
["constant.other.symbol.elixir","c"],
["text"," "],
["punctuation.section.scope.elixir","}"],
["punctuation.separator.object.elixir",","],
["text"," "],
["constant.numeric.elixir","0"],
["punctuation.section.function.elixir",")"],
["text"," "],
["punctuation.definition.comment.elixir","#"],
["comment.line.number-sign.elixir","=> :a"]
],[
"start",
["text"," "],
["keyword.control.elixir","end"]
],[
"start",
["keyword.control.elixir","end"]
],[
"start"
],[
"start",
["text","test_fun "],
["keyword.operator.assignment.elixir","="],
["text"," "],
["keyword.control.elixir","fn"],
["punctuation.section.function.elixir","("],
["text","x"],
["punctuation.section.function.elixir",")"],
["text"," "],
["keyword.operator.arithmetic.elixir","-"],
["keyword.operator.comparison.elixir",">"]
],[
"start",
["text"," "],
["keyword.control.elixir","cond"],
["text"," "],
["keyword.control.elixir","do"]
],[
"start",
["text"," x "],
["keyword.operator.comparison.elixir",">"],
["text"," "],
["constant.numeric.elixir","10"],
["text"," "],
["keyword.operator.arithmetic.elixir","-"],
["keyword.operator.comparison.elixir",">"]
],[
"start",
["text"," "],
["punctuation.definition.constant.elixir",":"],
["constant.other.symbol.elixir","greater_than_ten"]
],[
"start",
["text"," "],
["constant.language.elixir","true"],
["text"," "],
["keyword.operator.arithmetic.elixir","-"],
["keyword.operator.comparison.elixir",">"]
],[
"start",
["text"," "],
["punctuation.definition.constant.elixir",":"],
["constant.other.symbol.elixir","maybe_ten"]
],[
"start",
["text"," "],
["keyword.control.elixir","end"]
],[
"start",
["keyword.control.elixir","end"]
]]

View file

@ -56,34 +56,34 @@
],[
"start",
["text"," "],
["comment","| "],
["string","start "],
["comment","| "],
["string","eat "],
["comment","| "],
["string","left "],
["comment","|"],
["string"," start "],
["comment","|"],
["string"," eat "],
["comment","|"],
["string"," left "],
["comment","|"]
],[
"start",
["text"," "],
["comment","| "],
["string"," 12 "],
["comment","| "],
["string"," 5 "],
["comment","| "],
["string"," 7 "],
["comment","|"],
["string"," 12 "],
["comment","|"],
["string"," 5 "],
["comment","|"],
["string"," 7 "],
["comment","|"]
],[
"start",
["text"," "],
["comment","| "],
["string"," 20 "],
["comment","| "],
["string"," 5 "],
["comment","| "],
["string"," 15 "],
["comment","| "],
["string"," "]
["comment","|"],
["string"," 20 "],
["comment","|"],
["string"," 5 "],
["comment","|"],
["string"," 15 "],
["comment","|"],
["string"," "]
],[
"start"
],[

View file

@ -59,9 +59,9 @@
["meta.tag.punctuation.tag-open.xml","<"],
["meta.tag.tag-name.xml","div"],
["meta.tag.punctuation.tag-close.xml",">"],
["storage.type.start","{{"],
["support.function","{{{"],
["variable.parameter","body"],
["storage.type.end","}}"],
["support.function","}}}"],
["meta.tag.punctuation.end-tag-open.xml","</"],
["meta.tag.tag-name.xml","div"],
["meta.tag.punctuation.tag-close.xml",">"]

View file

@ -0,0 +1,302 @@
[[
"start",
["comment","/* Mask Syntax Demo */"]
],[
"start"
],[
"start",
["keyword.support.constant.language","div"],
["text"," "],
["paren.lparen",">"],
["text"," "],
["string.start","'"],
["string"," Test "],
["paren.lparen.markup.italic","~["],
["identifier","name"],
["paren.rparen.markup.italic","]"],
["string.end","'"],
["paren.rparen",";"]
],[
"start"
],[
"start",
["keyword","define"],
["text"," :"],
["support.variable.class","userProfile"],
["text"," "],
["paren.lparen","{"]
],[
"start",
["text","\t"],
["keyword.support.constant.language","header"],
["text"," "],
["paren.lparen","{"]
],[
"start",
["text","\t\t"],
["keyword.support.constant.language","h4"],
["text"," "],
["paren.lparen",">"],
["text"," "],
["support.function.markup.bold","@title"],
["paren.lparen",";"]
],[
"start",
["text","\t\t"],
["keyword.support.constant.language","button"],
["support.variable.class",".close"],
["paren.lparen",";"]
],[
"start",
["text","\t"],
["paren.rparen","}"]
],[
"start",
["paren.rparen","}"]
],[
"start"
],[
"start",
["support.function.markup.bold",":userProfile"],
["text"," "],
["paren.lparen","{"]
],[
"start",
["text","\t"],
["support.function.markup.bold","@title"],
["text"," "],
["paren.lparen",">"],
["text"," "],
["string.start","'"],
["string"," Hello "],
["paren.lparen.markup.italic","~["],
["keyword.control.markup.italic",":"],
["text"," "],
["identifier","username"],
["punctuation.operator","."],
["support.function","toUpperCase"],
["paren.lparen","("],
["paren.rparen",")"],
["paren.rparen.markup.italic","]"],
["string.end","'"]
],[
"start",
["paren.rparen","}"]
],[
"start"
],[
["paren.lparen52","constant.language40"],
["constant.language","style"],
["text"," "],
["paren.lparen","{"]
],[
["css-block-ruleset","paren.lparen52","paren.lparen52","constant.language40"],
["text"," "],
["constant","html"],
["text",", "],
["constant","body"],
["text"," "],
["paren.lparen","{"]
],[
["css-block-ruleset","paren.lparen52","paren.lparen52","constant.language40"],
["text"," "],
["support.type","background"],
["text",": "],
["support.function","url("],
["string","'name.png'"],
["support.function",")"],
["text"," "],
["constant.numeric","0"],
["text"," "],
["constant.numeric","0"],
["text"," "],
["support.constant","no-repeat"],
["text",";"]
],[
["paren.lparen52","constant.language40"],
["text"," "],
["paren.rparen","}"]
],[
["#tmp","css-block-end","paren.lparen52","constant.language40"],
["paren.rparen","}"]
],[
["#tmp","start","paren.lparen52","constant.language40"]
],[
["#tmp","start","paren.lparen52","constant.language40"],
["keyword.support.constant.language","button"],
["text"," "],
["paren.lparen","{"]
],[
["paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"],
["text","\t"],
["constant.language","event"],
["text"," "],
["support.variable.class","click"],
["text"," "],
["paren.lparen","("],
["identifier","e"],
["paren.rparen",")"],
["text"," "],
["paren.lparen","{"]
],[
["#tmp","js-block-start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"],
["text","\t "],
["variable.language","this"],
["punctuation.operator","."],
["identifier","textContent"],
["text"," "],
["keyword.operator","="],
["text"," "],
["string.quasi.start","`"],
["string.quasi","name "],
["paren.quasi.start","${"],
["identifier","e"],
["punctuation.operator","."],
["identifier","clientX"],
["paren.quasi.end","}"],
["string.quasi"," !"],
["string.quasi.end","`"],
["punctuation.operator",";"]
],[
["#tmp","js-block-end","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"],
["text","\t"],
["paren.rparen","}"]
],[
["#tmp","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"],
["paren.rparen","}"]
],[
["#tmp","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"]
],[
["paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"],
["constant.language","md"],
["text"," "],
["paren.lparen",">"],
["text"," "],
["paren.lparen","\"\"\""]
],[
["#tmp","md-multiline-allowBlock","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"]
],[
["#tmp","md-multiline-listblock","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"],
["markup.list","- "],
["list","div"]
],[
["#tmp","md-multiline-listblock","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"],
["markup.list","- "],
["list","span"]
],[
["#tmp","md-multiline-listblock","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"],
["list"," "]
],[
["#tmp","md-multiline-listblock","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"],
["list","Hello"]
],[
["#tmp","md-multiline-start","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"]
],[
["#tmp","md-multiline-start","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"],
["text","["],
["string","one"],
["text","]("],
["markup.underline","http://google.com"],
["text",")"]
],[
["#tmp","md-multiline-allowBlock","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"]
],[
["#tmp","start","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"],
["paren.rparen","\"\"\";"]
],[
["#tmp","start","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"]
],[
["#tmp","start","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"]
],[
["#tmp","start","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"],
["keyword.support.constant.language","header"],
["text"," "],
["support.variable.class",".foo"],
["text"," "],
["paren.lparen",">"],
["text"," "],
["string.start","'"],
["string","Heading"],
["string.end","'"]
],[
["#tmp","start","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"]
],[
["string.start2","start","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"],
["keyword.support.constant.language","button"],
["text"," "],
["support.variable.class",".baz"],
["text"," "],
["support.variable.class.markup.bold","x-signal"],
["keyword.operator","="],
["string.start","'"],
["string","click: test"],
["string.end","'"],
["text"," "],
["support.variable.class","disabled"],
["text"," "],
["paren.lparen",">"],
["text"," "],
["string.start","\""]
],[
["string.start2","start","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"],
["string","\tHello,"]
],[
["string.start2","start","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"],
["string","\tworld "]
],[
["string.start2","start","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"],
["string","\t"],
["string.escape","\\\""],
["string","Buddy"],
["string.escape","\\\""]
],[
["#tmp","start","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"],
["string.end","\""]
],[
["#tmp","start","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"]
],[
["#tmp","js-statement-start","start","js-statement-no_regex","constant.language53","start","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"],
["constant.language","var"],
["text"," "],
["identifier","a"],
["text"," "],
["keyword.operator","="],
["text"," "],
["paren","{"]
],[
["#tmp","js-statement-no_regex","start","js-statement-no_regex","constant.language53","start","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"],
["text"," "],
["identifier","name"],
["punctuation.operator",":"],
["text"," "],
["string.quasi.start","`"],
["string.quasi","name "],
["paren.quasi.start","${"],
["variable.language","window"],
["punctuation.operator","."],
["support.constant","innerWidth"],
["paren.rparen","}"],
["string.quasi.end","`"]
],[
["#tmp","start","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"],
["paren.rparen","};"]
],[
["#tmp","start","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"]
],[
["#tmp","start","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"],
["keyword.support.constant.language","span"],
["text"," "],
["support.variable.class",".foo"],
["text"," "],
["paren.lparen",">"],
["text"," "],
["string.start","\""],
["paren.lparen.markup.italic","~["],
["keyword.control.markup.italic","bind:"],
["text"," "],
["identifier","a"],
["punctuation.operator","."],
["identifier","name"],
["paren.rparen.markup.italic","]"],
["string.end","\""]
]]

View file

@ -727,7 +727,8 @@
],[
"start",
["keyword","#ifndef"],
["constant.other"," Nil"]
["text"," "],
["constant.language.objc","Nil"]
],[
"start",
["keyword","#define"],

View file

@ -139,7 +139,7 @@
["text"," "],
["punctuation.separator.key-value","=>"],
["text"," "],
["constant.numeric","34"],
["string.character","?\""],
["text",", "],
["constant.other.symbol.ruby",":key"],
["text"," "],
@ -148,7 +148,15 @@
["string.start","\""],
["string","value"],
["string.end","\""],
["paren.rparen","}"]
["text",", "],
["identifier","anotherKey"],
["text",": "],
["paren.lparen","["],
["identifier","x"],
["text",", "],
["identifier","y"],
["text","?"],
["paren.rparen","]}"]
],[
"start"
],[

View file

@ -10,10 +10,9 @@
],[
"start",
["keyword.source.rust","fn"],
["meta.function.source.rust"," "],
["text"," "],
["entity.name.function.source.rust","main"],
["meta.function.source.rust","("],
["text",") {"]
["text","() {"]
],[
"start",
["text"," "],
@ -88,10 +87,14 @@
],[
"start",
["keyword.source.rust","fn"],
["meta.function.source.rust"," "],
["entity.name.function.source.rust","map<T, U>"],
["meta.function.source.rust","("],
["text","vector: &[T]"],
["text"," "],
["entity.name.function.source.rust","map"],
["keyword.operator","<"],
["text","T"],
["keyword.operator",","],
["text"," U"],
["keyword.operator",">"],
["text","(vector: &[T]"],
["keyword.operator",","],
["text"," function: &fn(v: &T) "],
["keyword.operator","->"],

View file

@ -199,7 +199,5 @@
["string.quoted.double.asp"," ... updated.\""]
],[
"start",
["support.function.asp","End"],
["text"," "],
["storage.type.asp","Sub"]
["storage.type.asp","End Sub"]
]]

View file

@ -126,7 +126,7 @@ var AbapHighlightRules = function() {
{token : "string", regex : "`", next : "start"},
{defaultToken : "string"}
]
}
};
};
oop.inherits(AbapHighlightRules, TextHighlightRules);

58
lib/ace/mode/abc.js Normal file
View file

@ -0,0 +1,58 @@
/* ***** 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 ***** */
/*
THIS FILE WAS AUTOGENERATED BY mode.tmpl.js
*/
define(function (require, exports, module) {
"use strict";
var oop = require("../lib/oop");
var TextMode = require("./text").Mode;
var ABCHighlightRules = require("./abc_highlight_rules").ABCHighlightRules;
// TODO: pick appropriate fold mode
var FoldMode = require("./folding/cstyle").FoldMode;
var Mode = function () {
this.HighlightRules = ABCHighlightRules;
this.foldingRules = new FoldMode();
};
oop.inherits(Mode, TextMode);
(function () {
// this.lineCommentStart = ""%.*"";
// this.blockComment = {start: ""/*"", end: ""*/""};
// Extra logic goes here.
this.$id = "ace/mode/abc"
}).call(Mode.prototype);
exports.Mode = Mode;
});

View file

@ -0,0 +1,114 @@
/* This file was partially autogenerated from https://github.com/jimhawkridge/SublimeABC
Modifications
- more classes to express the abc semantic
- added syntax highlighting for Zupfnoter conventions (https://github.com/bwl21/zupfnoter)
- separate note pitch and note duration - even if it looks the same
***********************************************************************************************/
define(function (require, exports, module) {
"use strict";
var oop = require("../lib/oop");
var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
var ABCHighlightRules = function () {
// regexp must not have capturing parentheses. Use (?:) instead.
// regexps are ordered -> the first match is used
this.$rules = {
start: [
{
token: ['zupfnoter.information.comment.line.percentage', 'information.keyword', 'in formation.keyword.embedded'],
regex: '(%%%%)(hn\\.[a-z]*)(.*)',
comment: 'Instruction Comment'
},
{
token: ['information.comment.line.percentage', 'information.keyword.embedded'],
regex: '(%%)(.*)',
comment: 'Instruction Comment'
},
{
token: 'comment.line.percentage',
regex: '%.*',
comment: 'Comments'
},
{
token: 'barline.keyword.operator',
regex: '[\\[:]*[|:][|\\]:]*(?:\\[?[0-9]+)?|\\[[0-9]+',
comment: 'Bar lines'
},
{
token: ['information.keyword.embedded', 'information.argument.string.unquoted'],
regex: '(\\[[A-Za-z]:)([^\\]]*\\])',
comment: 'embedded Header lines'
},
{
token: ['information.keyword', 'information.argument.string.unquoted'],
regex: '^([A-Za-z]:)([^%\\\\]*)',
comment: 'Header lines'
},
{
token: ['text', 'entity.name.function', 'string.unquoted', 'text'],
regex: '(\\[)([A-Z]:)(.*?)(\\])',
comment: 'Inline fields'
},
{
token: ['accent.constant.language', 'pitch.constant.numeric', 'duration.constant.numeric'],
regex: '([\\^=_]*)([A-Ga-gz][,\']*)([0-9]*/*[><0-9]*)',
comment: 'Notes'
},
{
token: 'zupfnoter.jumptarget.string.quoted',
regex: '[\\"!]\\^\\:.*?[\\"!]',
comment: 'Zupfnoter jumptarget'
}, {
token: 'zupfnoter.goto.string.quoted',
regex: '[\\"!]\\^\\@.*?[\\"!]',
comment: 'Zupfnoter goto'
},
{
token: 'zupfnoter.annotation.string.quoted',
regex: '[\\"!]\\^\\!.*?[\\"!]',
comment: 'Zupfnoter annoation'
},
{
token: 'zupfnoter.annotationref.string.quoted',
regex: '[\\"!]\\^\\#.*?[\\"!]',
comment: 'Zupfnoter annotation reference'
},
{
token: 'chordname.string.quoted',
regex: '[\\"!]\\^.*?[\\"!]',
comment: 'abc chord'
},
{
token: 'string.quoted',
regex: '[\\"!].*?[\\"!]',
comment: 'abc annotation'
}
]
};
// this.embedRules(JsonHighlightRules, "json-")
this.normalizeRules();
};
ABCHighlightRules.metaData = {
fileTypes: ['abc'],
name: 'ABC',
scopeName: 'text.abcnotation'
};
oop.inherits(ABCHighlightRules, TextHighlightRules);
exports.ABCHighlightRules = ABCHighlightRules;
});

View file

@ -0,0 +1,179 @@
/* ***** 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");
require("../../test/mockdom");
}
define(function(require, exports, module) {
"use strict";
require("../../multi_select");
var assert = require("../../test/assertions");
var Range = require("../../range").Range;
var Editor = require("../../editor").Editor;
var EditSession = require("../../edit_session").EditSession;
var MockRenderer = require("../../test/mockrenderer").MockRenderer;
var JavaScriptMode = require("../javascript").Mode;
var XMLMode = require("../xml").Mode;
var editor;
var exec = function(name, times, args) {
do {
editor.commands.exec(name, editor, args);
} while(times --> 1);
};
var testRanges = function(str) {
assert.equal(editor.selection.getAllRanges() + "", str + "");
};
module.exports = {
"test: cstyle": function() {
function testValue(line) {
assert.equal(editor.getValue(), Array(4).join(line + "\n"));
}
function testSelection(line, col, inc) {
editor.selection.rangeList.ranges.forEach(function(r) {
assert.range(r, line, col, line, col);
line += (inc || 1);
});
}
var doc = new EditSession([
"",
"",
"",
""
], new JavaScriptMode());
editor = new Editor(new MockRenderer(), doc);
editor.setOption("behavioursEnabled", true);
editor.navigateFileStart();
exec("addCursorBelow", 2);
exec("insertstring", 1, "if ");
// pairing (
exec("insertstring", 1, "(");
testValue("if ()");
testSelection(0, 4);
exec("insertstring", 1, ")");
testValue("if ()");
testSelection(0, 5);
// pairing [
exec("gotoleft", 1);
exec("insertstring", 1, "[");
testValue("if ([])");
testSelection(0, 5);
exec("insertstring", 1, "]");
testValue("if ([])");
testSelection(0, 6);
// test deletion
exec("gotoleft", 1);
exec("backspace", 1);
testValue("if ()");
testSelection(0, 4);
exec("gotolineend", 1);
exec("insertstring", 1, "{");
testValue("if (){}");
testSelection(0, 6);
exec("insertstring", 1, "}");
testValue("if (){}");
testSelection(0, 7);
exec("gotolinestart", 1);
exec("insertstring", 1, "(");
testValue("(if (){}");
exec("backspace", 1);
editor.setValue("");
exec("insertstring", 1, "{");
assert.equal(editor.getValue(), "{");
exec("insertstring", 1, "\n");
assert.equal(editor.getValue(), "{\n \n}");
editor.setValue("");
exec("insertstring", 1, "(");
exec("insertstring", 1, '"');
exec("insertstring", 1, '"');
assert.equal(editor.getValue(), '("")');
exec("backspace", 1);
exec("insertstring", 1, '"');
assert.equal(editor.getValue(), '("")');
editor.setValue("('foo')", 1);
exec("gotoleft", 1);
exec("selectleft", 1);
exec("selectMoreBefore", 1);
exec("insertstring", 1, "'");
assert.equal(editor.getValue(), "('foo')");
exec("selectleft", 1);
exec("insertstring", 1, '"');
assert.equal(editor.getValue(), '("foo")');
exec("selectleft", 1);
exec("insertstring", 1, '"');
assert.equal(editor.getValue(), '("foo")');
editor.setValue("", 1);
exec("selectleft", 1);
exec("insertstring", 1, '"');
assert.equal(editor.getValue(), '""');
exec("insertstring", 1, '\\');
exec("insertstring", 1, 'n');
exec("insertstring", 1, '"');
assert.equal(editor.getValue(), '"\\n"');
},
"test: xml": function() {
editor = new Editor(new MockRenderer());
editor.setValue(["<OuterTag>",
" <SelfClosingTag />"
].join("\n"));
editor.session.setMode(new XMLMode);
exec("gotolinedown", 1);
exec("gotolineend", 1);
exec("insertstring", 1, '\n');
assert.equal(editor.session.getLine(2), " ");
exec("gotolineup", 1);
exec("gotolineend", 1);
exec("insertstring", 1, '\n');
assert.equal(editor.session.getLine(2), " ");
}
};
});
if (typeof module !== "undefined" && module === require.main) {
require("asyncjs").test.testcase(module.exports).exec();
}

View file

@ -42,11 +42,11 @@ var SAFE_INSERT_BEFORE_TOKENS =
["text", "paren.rparen", "punctuation.operator", "comment"];
var context;
var contextCache = {}
var contextCache = {};
var initContext = function(editor) {
var id = -1;
if (editor.multiSelect) {
id = editor.selection.id;
id = editor.selection.index;
if (contextCache.rangeCount != editor.multiSelect.rangeCount)
contextCache = {rangeCount: editor.multiSelect.rangeCount};
}
@ -63,6 +63,19 @@ var initContext = function(editor) {
};
};
var getWrapped = function(selection, selected, opening, closing) {
var rowDiff = selection.end.row - selection.start.row;
return {
text: opening + selected + closing,
selection: [
0,
selection.start.column + 1,
rowDiff,
selection.end.column + (rowDiff ? 0 : 1)
]
};
};
var CstyleBehaviour = function() {
this.add("braces", "insertion", function(state, action, editor, session, text) {
var cursor = editor.getCursorPosition();
@ -72,10 +85,7 @@ var CstyleBehaviour = function() {
var selection = editor.getSelectionRange();
var selected = session.doc.getTextRange(selection);
if (selected !== "" && selected !== "{" && editor.getWrapBehavioursEnabled()) {
return {
text: '{' + selected + '}',
selection: false
};
return getWrapped(selection, selected, '{', '}');
} else if (CstyleBehaviour.isSaneInsertion(editor, session)) {
if (/[\]\}\)]/.test(line[cursor.column]) || editor.inMultiSelectMode) {
CstyleBehaviour.recordAutoInsert(editor, session, "}");
@ -155,10 +165,7 @@ var CstyleBehaviour = function() {
var selection = editor.getSelectionRange();
var selected = session.doc.getTextRange(selection);
if (selected !== "" && editor.getWrapBehavioursEnabled()) {
return {
text: '(' + selected + ')',
selection: false
};
return getWrapped(selection, selected, '(', ')');
} else if (CstyleBehaviour.isSaneInsertion(editor, session)) {
CstyleBehaviour.recordAutoInsert(editor, session, ")");
return {
@ -203,10 +210,7 @@ var CstyleBehaviour = function() {
var selection = editor.getSelectionRange();
var selected = session.doc.getTextRange(selection);
if (selected !== "" && editor.getWrapBehavioursEnabled()) {
return {
text: '[' + selected + ']',
selection: false
};
return getWrapped(selection, selected, '[', ']');
} else if (CstyleBehaviour.isSaneInsertion(editor, session)) {
CstyleBehaviour.recordAutoInsert(editor, session, "]");
return {
@ -252,56 +256,45 @@ var CstyleBehaviour = function() {
var selection = editor.getSelectionRange();
var selected = session.doc.getTextRange(selection);
if (selected !== "" && selected !== "'" && selected != '"' && editor.getWrapBehavioursEnabled()) {
return {
text: quote + selected + quote,
selection: false
};
} else {
return getWrapped(selection, selected, quote, quote);
} else if (!selected) {
var cursor = editor.getCursorPosition();
var line = session.doc.getLine(cursor.row);
var leftChar = line.substring(cursor.column-1, cursor.column);
var rightChar = line.substring(cursor.column, cursor.column + 1);
var token = session.getTokenAt(cursor.row, cursor.column);
var rightToken = session.getTokenAt(cursor.row, cursor.column + 1);
// We're escaped.
if (leftChar == '\\') {
if (leftChar == "\\" && token && /escape/.test(token.type))
return null;
var stringBefore = token && /string|escape/.test(token.type);
var stringAfter = !rightToken || /string|escape/.test(rightToken.type);
var pair;
if (rightChar == quote) {
pair = stringBefore !== stringAfter;
} else {
if (stringBefore && !stringAfter)
return null; // wrap string with different quote
if (stringBefore && stringAfter)
return null; // do not pair quotes inside strings
var wordRe = session.$mode.tokenRe;
wordRe.lastIndex = 0;
var isWordBefore = wordRe.test(leftChar);
wordRe.lastIndex = 0;
var isWordAfter = wordRe.test(leftChar);
if (isWordBefore || isWordAfter)
return null; // before or after alphanumeric
if (rightChar && !/[\s;,.})\]\\]/.test(rightChar))
return null; // there is rightChar and it isn't closing
pair = true;
}
// Find what token we're inside.
var tokens = session.getTokens(selection.start.row);
var col = 0, token;
var quotepos = -1; // Track whether we're inside an open quote.
for (var x = 0; x < tokens.length; x++) {
token = tokens[x];
if (token.type == "string") {
quotepos = -1;
} else if (quotepos < 0) {
quotepos = token.value.indexOf(quote);
}
if ((token.value.length + col) > selection.start.column) {
break;
}
col += tokens[x].value.length;
}
// Try and be smart about when we auto insert.
if (!token || (quotepos < 0 && token.type !== "comment" && (token.type !== "string" || ((selection.start.column !== token.value.length+col-1) && token.value.lastIndexOf(quote) === token.value.length-1)))) {
if (!CstyleBehaviour.isSaneInsertion(editor, session))
return;
return {
text: quote + quote,
selection: [1,1]
};
} else if (token && token.type === "string") {
// Ignore input and move right one if we're typing over the closing quote.
var rightChar = line.substring(cursor.column, cursor.column + 1);
if (rightChar == quote) {
return {
text: '',
selection: [1, 1]
};
}
}
return {
text: pair ? quote + quote : "",
selection: [1,1]
};
}
}
});

View file

@ -155,6 +155,8 @@ var XmlBehaviour = function () {
var token = iterator.getCurrentToken();
if (token && token.type.indexOf("tag-close") !== -1) {
if (token.value == "/>")
return;
//get tag name
while (token && token.type.indexOf("tag-name") === -1) {
token = iterator.stepBackward();

Some files were not shown because too many files have changed in this diff Show more