├── .gitignore ├── Support ├── dev_guru_index.gz ├── completions.json ├── JSSpec │ ├── index.html │ ├── JSSpec.css │ ├── specs.js │ └── diff_match_patch.js ├── run_js.js ├── Array.instance.completions.json ├── run_js.rb └── lib │ ├── current_word.rb │ └── tm │ └── complete.rb ├── TODO ├── Tests ├── Embedded Javascript Test.html ├── run_js.test.js ├── Embedded Javascript Test Invalid.html └── Javascript Folding & Indent.js ├── Snippets ├── this.tmSnippet ├── window_.tmSnippet ├── arguments.tmSnippet ├── document_.tmSnippet ├── prototype.tmSnippet ├── function.tmSnippet ├── console_log.tmSnippet ├── Escaped Newline 2.tmSnippet ├── Object Method.tmSnippet ├── console_assert.tmSnippet ├── if instanceof.tmSnippet ├── if !null.tmSnippet ├── if (isArray).tmSnippet ├── setTimeout function.tmSnippet ├── Prototype (proto).plist ├── Google AJAX Libs: MooTools 1_2_1.tmSnippet ├── case.tmSnippet ├── closure.tmSnippet ├── if !undefined.tmSnippet ├── if ___ else.tmSnippet ├── Anonymous Function.tmDelta ├── for (in) {…}.tmSnippet ├── if.tmSnippet ├── Get Elements.tmSnippet ├── Internet Explorer Conditional Comment.tmSnippet ├── for (…) {…} 2.tmSnippet ├── Escaped Newline.tmSnippet ├── try … catch.tmSnippet ├── Array_prototype_slice_call(arguments).tmSnippet ├── for (…) {…} (DOM).tmSnippet ├── for (…) {…}.tmSnippet ├── Array_prototype_slice_call(arguments) → arguments.tmSnippet ├── Internet Explorer Conditional Comment Escape.tmSnippet ├── for (…) {…} (PPK).tmSnippet ├── switch case.tmSnippet ├── for (…) {…} (Fastest reverse).tmSnippet ├── for (…) {…} (Fastest).tmSnippet ├── for (…) {…} (faster).tmSnippet ├── window_addEventListener_load.tmSnippet ├── Class Closure MyClass = (fn(){…})().tmSnippet ├── createNode…appendChild idiom.tmSnippet └── JSSpec Standalone.tmSnippet ├── Preferences ├── Symbol List Class.tmPreferences ├── Symbol List Instance.tmPreferences ├── Symbol List Sub 1.tmPreferences ├── Symbol List Sub 2.tmPreferences ├── Symbol List Banned.tmPreferences ├── Comments.tmPreferences ├── Misc.tmPreferences ├── Typing Pairs: String and Comment.tmPreferences └── Indent.tmPreferences ├── Commands ├── Complete.tmCommand ├── New Function.tmCommand ├── New Method.tmCommand ├── Help.tmCommand ├── Documentation for Word : Selection (tool tip).tmCommand ├── convert this to me.tmCommand ├── convert this to self.tmCommand ├── Documentation for Word : Selection Google Lucky.tmCommand ├── Documentation for Word.plist ├── Documentation for Word : Selection Google.tmCommand ├── Copy as Bookmarklet to Clipboard.tmCommand ├── console 2.tmCommand ├── console.tmCommand └── Reformat Document : Selection.tmCommand ├── DragCommands ├── relative script path string.tmDragCommand └── relative script path.tmDragCommand ├── README.md ├── info.plist └── Syntaxes └── JavaScript.plist /.gitignore: -------------------------------------------------------------------------------- 1 | *.cache 2 | -------------------------------------------------------------------------------- /Support/dev_guru_index.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/subtleGradient/javascript.tmbundle/HEAD/Support/dev_guru_index.gz -------------------------------------------------------------------------------- /Support/completions.json: -------------------------------------------------------------------------------- 1 | { 2 | "extra_chars": "_$", 3 | "images": { 4 | "String" : "String.png", 5 | "RegExp" : "RegExp.png", 6 | "Number" : "Number.png", 7 | "Array" : "Array.png", 8 | "Function": "Function.png", 9 | "Object" : "Object.png", 10 | "Node" : "Node.png", 11 | "NodeList": "NodeList.png", 12 | "mixed" : "mixed.png" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | Dumb Completion 2 | 3 | * Cross-Platform Browser Object Model API 4 | * Cross-Platform Document Object Model API 5 | * String 6 | * Number 7 | * Array 8 | 9 | Smart Completion 10 | 11 | * String 12 | * "string literal" 13 | * 'string literal' 14 | * /regex literal/ 15 | * Number 16 | 17 | Find out the return type of all the DOM, BOM & Object methods / properties 18 | Completions Format 19 | -------------------------------------------------------------------------------- /Tests/Embedded Javascript Test.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | Embedded Javascript Test.html 7 | 10 | 11 | 12 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /Snippets/this.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | this 7 | name 8 | this 9 | scope 10 | source.js 11 | tabTrigger 12 | t 13 | uuid 14 | 51EC03B2-4E2B-49B0-A843-6BEB7281BE98 15 | 16 | 17 | -------------------------------------------------------------------------------- /Snippets/window_.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | window 7 | name 8 | window 9 | scope 10 | source.js 11 | tabTrigger 12 | w 13 | uuid 14 | 5CAA9822-629C-4362-B02A-FCEF38C79BD5 15 | 16 | 17 | -------------------------------------------------------------------------------- /Snippets/arguments.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | arguments 7 | name 8 | arguments 9 | scope 10 | source.js 11 | tabTrigger 12 | a 13 | uuid 14 | C85B5F76-4CA8-47C2-B6E1-8A324D6E3B61 15 | 16 | 17 | -------------------------------------------------------------------------------- /Snippets/document_.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | document 7 | name 8 | document 9 | scope 10 | source.js 11 | tabTrigger 12 | d 13 | uuid 14 | C1197E58-D065-4EDC-9BAB-EB41622C1630 15 | 16 | 17 | -------------------------------------------------------------------------------- /Snippets/prototype.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | .prototype 7 | name 8 | prototype 9 | scope 10 | source.js 11 | tabTrigger 12 | .p 13 | uuid 14 | FB90E487-9B42-4512-9036-01CD3CD8B04B 15 | 16 | 17 | -------------------------------------------------------------------------------- /Snippets/function.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | function$1($2){$0} 7 | name 8 | Function 9 | scope 10 | source.js 11 | tabTrigger 12 | f 13 | uuid 14 | F0E4FB6A-4878-48C6-A777-62438DF1E14F 15 | 16 | 17 | -------------------------------------------------------------------------------- /Tests/run_js.test.js: -------------------------------------------------------------------------------- 1 | // Relative Paths 2 | // @require 'relative_path.js'; 3 | // @require 'relative_path.css'; 4 | 5 | // Urls 6 | // @require 'http://ajax.googleapis.com/ajax/libs/mootools/1.2.1/mootools.js'; 7 | 8 | // Libraries 9 | // @require 'mootools'; 10 | // @require 'jsspec'; 11 | 12 | window.alert('alerts') 13 | 14 | window.confirm('confirms') 15 | ? window.alert('confirmed') 16 | : window.alert('not confirmed') 17 | ; 18 | 19 | try{throw {}}catch(e){ console.log(e.line); }; FRED++ 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Snippets/console_log.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | console.log($0) 7 | name 8 | console.log 9 | scope 10 | source.js 11 | tabTrigger 12 | l 13 | uuid 14 | 78F5005B-82AE-4BF0-9E1B-407E32FF796B 15 | 16 | 17 | -------------------------------------------------------------------------------- /Snippets/Escaped Newline 2.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | \n 7 | keyEquivalent 8 | ~ 9 | name 10 | Escaped Newline 11 | scope 12 | source.js string.quoted 13 | uuid 14 | B7D324A1-E600-4014-8CDF-B73BA554921A 15 | 16 | 17 | -------------------------------------------------------------------------------- /Snippets/Object Method.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | ${1:}: function(${3:}){$0} 7 | name 8 | Object Method 9 | scope 10 | source.js 11 | tabTrigger 12 | :f 13 | uuid 14 | 77065D69-742A-4FF0-9A41-AD211DFBE72F 15 | 16 | 17 | -------------------------------------------------------------------------------- /Snippets/console_assert.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | console.assert(${0:false}) 7 | name 8 | console.assert 9 | scope 10 | source.js 11 | tabTrigger 12 | ass 13 | uuid 14 | 19479745-D001-4EB3-8A66-6679C2273C58 15 | 16 | 17 | -------------------------------------------------------------------------------- /Snippets/if instanceof.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | if ($1 instanceof ${2:Array})$0 7 | name 8 | if instanceof 9 | scope 10 | source.js 11 | tabTrigger 12 | ifi 13 | uuid 14 | 9F13050B-61FC-4A9A-9A91-F2CD8529A5FE 15 | 16 | 17 | -------------------------------------------------------------------------------- /Snippets/if !null.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | if (${1:${TM_SELECTED_TEXT:myVar}} != null) $0 7 | name 8 | if !null 9 | scope 10 | source.js 11 | tabTrigger 12 | ifn 13 | uuid 14 | 75783526-1546-4967-B37B-5CDA089593B3 15 | 16 | 17 | -------------------------------------------------------------------------------- /Snippets/if (isArray).tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | if ($1Array.isArray(${2:array}))$0 7 | name 8 | if (isArray) 9 | scope 10 | source.js 11 | tabTrigger 12 | ifa 13 | uuid 14 | D99FC647-570A-48E2-B6FB-147D432346BB 15 | 16 | 17 | -------------------------------------------------------------------------------- /Snippets/setTimeout function.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | setTimeout($0, ${10:10}); 7 | name 8 | setTimeout 9 | scope 10 | source.js 11 | tabTrigger 12 | timeout 13 | uuid 14 | 009A3E6C-FE3F-4A18-8759-2DC31F17BBE2 15 | 16 | 17 | -------------------------------------------------------------------------------- /Snippets/Prototype (proto).plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | .prototype.${2:methodName} = f$0 7 | name 8 | .prototype.method = f 9 | scope 10 | source.js 11 | tabTrigger 12 | .pf 13 | uuid 14 | 2F96136B-0193-42F5-90FC-B6F456A3AD77 15 | 16 | 17 | -------------------------------------------------------------------------------- /Snippets/Google AJAX Libs: MooTools 1_2_1.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | http://ajax.googleapis.com/ajax/libs/mootools/1.2.3/mootools.js 7 | name 8 | Google AJAX Libs: MooTools 1.2.1 9 | tabTrigger 10 | moo 11 | uuid 12 | B914AE71-B1B3-48A1-A4AE-6E5F9425C3B6 13 | 14 | 15 | -------------------------------------------------------------------------------- /Snippets/case.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | break; 7 | case ${20:/*Expression*/}: 8 | ${0:} 9 | break; 10 | name 11 | case 12 | scope 13 | source.js 14 | tabTrigger 15 | break; 16 | uuid 17 | 77750C34-3335-4766-900D-FFFF412DB7F5 18 | 19 | 20 | -------------------------------------------------------------------------------- /Snippets/closure.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | (function(){ 7 | ${0:${TM_SELECTED_TEXT: 8 | }}})(); 9 | 10 | keyEquivalent 11 | ^W 12 | name 13 | closure 14 | scope 15 | source.js 16 | uuid 17 | 9655FB2D-E7ED-4189-9050-6F5B5D305975 18 | 19 | 20 | -------------------------------------------------------------------------------- /Snippets/if !undefined.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | if (typeof ${1:${TM_SELECTED_TEXT:myVar}} != 'undefined') $0 7 | name 8 | if !undefined 9 | scope 10 | source.js 11 | tabTrigger 12 | ifu 13 | uuid 14 | 2831C11D-1907-4BC1-9A4D-BEE70EAFD0CF 15 | 16 | 17 | -------------------------------------------------------------------------------- /Snippets/if ___ else.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | if (${1:true}) { 7 | ${0:${TM_SELECTED_TEXT: 8 | }}} else {}; 9 | name 10 | if … else 11 | scope 12 | source.js 13 | tabTrigger 14 | ife 15 | uuid 16 | 31964029-9D71-4ADC-8213-DFE5C4E222B3 17 | 18 | 19 | -------------------------------------------------------------------------------- /Snippets/Anonymous Function.tmDelta: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | changed 6 | 7 | scope 8 | disabled source.js 9 | 10 | deleted 11 | 12 | content 13 | tabTrigger 14 | 15 | isDelta 16 | 17 | uuid 18 | 4C6EDB43-3E2E-411B-A016-13C135C59833 19 | 20 | 21 | -------------------------------------------------------------------------------- /Snippets/for (in) {…}.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | for (var ${1:property} in ${2:object}) { 7 | ${0:$2[$1]} 8 | } 9 | name 10 | for (in) {…} 11 | scope 12 | source.js 13 | tabTrigger 14 | forin 15 | uuid 16 | 3F4AB53B-210C-4E0C-8D04-12192DECC3D1 17 | 18 | 19 | -------------------------------------------------------------------------------- /Snippets/if.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | if (${1:true}) {${0:${TM_SELECTED_TEXT:}}} 7 | keyEquivalent 8 | ^W 9 | name 10 | if 11 | scope 12 | source.js 13 | tabTrigger 14 | if 15 | uuid 16 | F19F3732-39A7-48EC-A72B-A8F477A01795 17 | 18 | 19 | -------------------------------------------------------------------------------- /Snippets/Get Elements.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | .getElement${1/(T)|.*/(?1:s)/}By${1:I}${1/(I)|(T)|.*/(?2:agName)(?1:d)/}($2)$0 7 | name 8 | get Elements 9 | scope 10 | source.js 11 | tabTrigger 12 | .get 13 | uuid 14 | 9E0E3BCC-7F20-4D6B-891D-A44D6EC56E31 15 | 16 | 17 | -------------------------------------------------------------------------------- /Snippets/Internet Explorer Conditional Comment.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | /*@cc_on ${0:$TM_SELECTED_TEXT} @*/ 7 | name 8 | Internet Explorer Conditional Comment 9 | scope 10 | source.js 11 | tabTrigger 12 | @ 13 | uuid 14 | E1B2FC98-AF98-4392-8069-C82C2C192617 15 | 16 | 17 | -------------------------------------------------------------------------------- /Snippets/for (…) {…} 2.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | for (${1:before_all}; ${2:test_before_each}; ${3:after_each}) { 7 | ${0:// statement} 8 | } 9 | name 10 | for (…) {…} 11 | scope 12 | source.js 13 | tabTrigger 14 | for 15 | uuid 16 | 6976CD86-07BB-4419-BE5E-10F60944DB1A 17 | 18 | 19 | -------------------------------------------------------------------------------- /Snippets/Escaped Newline.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | \\ 7 | 8 | keyEquivalent 9 | 10 | name 11 | Escaped Literal Newline 12 | scope 13 | source.js string.quoted -string.quoted.other.es6 -punctuation.definition.string.begin 14 | uuid 15 | 0EC93ADD-A849-4951-9235-B51E720E31FE 16 | 17 | 18 | -------------------------------------------------------------------------------- /Snippets/try … catch.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | try { 7 | ${0:$TM_SELECTED_TEXT}} catch(e){} 8 | keyEquivalent 9 | ^W 10 | name 11 | try … catch 12 | scope 13 | source.js 14 | tabTrigger 15 | try 16 | uuid 17 | 12767C79-C781-4BFC-8BA3-D108DB14292D 18 | 19 | 20 | -------------------------------------------------------------------------------- /Snippets/Array_prototype_slice_call(arguments).tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | arguments 7 | name 8 | arguments → Array.prototype.slice.call(arguments) 9 | scope 10 | source.js 11 | tabTrigger 12 | Array.prototype.slice.call(arguments) 13 | uuid 14 | E6827B03-693B-4C9E-B288-D7EEF36D6EF1 15 | 16 | 17 | -------------------------------------------------------------------------------- /Snippets/for (…) {…} (DOM).tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | for (var ${20:i}=-1, ${2:node}; ${2:node} = ${1:Nodes}[++${20:i}];) { 7 | ${0:${2:node}} 8 | } 9 | name 10 | for (…) {…} (DOM) 11 | scope 12 | source.js 13 | tabTrigger 14 | for 15 | uuid 16 | 92D6EE80-615E-45B7-B2E2-FF5C200A8478 17 | 18 | 19 | -------------------------------------------------------------------------------- /Snippets/for (…) {…}.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | for (var ${20:i}=0; ${20:i} < ${1:${2:Things}.length}; ${20:i}++) { 7 | ${0:$2[$20]} 8 | } 9 | name 10 | for (…) {…} (Classic) 11 | scope 12 | source.js 13 | tabTrigger 14 | for 15 | uuid 16 | 011C4681-FBEC-4891-9326-3DECFCDED6D6 17 | 18 | 19 | -------------------------------------------------------------------------------- /Snippets/Array_prototype_slice_call(arguments) → arguments.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | Array.prototype.slice.call(arguments) 7 | name 8 | Array.prototype.slice.call(arguments) → arguments 9 | scope 10 | source.js 11 | tabTrigger 12 | arguments 13 | uuid 14 | BBDBA2F8-0C0D-41AC-97F2-EB3A09D9044C 15 | 16 | 17 | -------------------------------------------------------------------------------- /Snippets/Internet Explorer Conditional Comment Escape.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | @*/${0:$TM_SELECTED_TEXT}/*@ 7 | name 8 | Internet Explorer Conditional Comment Escape 9 | scope 10 | source.js comment.block.conditional 11 | tabTrigger 12 | @ 13 | uuid 14 | 603A6D98-A136-4766-828B-C39178AB8003 15 | 16 | 17 | -------------------------------------------------------------------------------- /Snippets/for (…) {…} (PPK).tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | for (var ${20:i}=0, ${2:thing}; ${2:thing} = ${1:Things}[${20:i}]; ${20:i}++){ 7 | $0${2:thing} 8 | } 9 | name 10 | for (…) {…} (PPK) 11 | scope 12 | source.js 13 | tabTrigger 14 | for 15 | uuid 16 | 9BF3315C-88FF-46A1-89E1-9A5E9EAC78D0 17 | 18 | 19 | -------------------------------------------------------------------------------- /Snippets/switch case.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | switch(${10:/*Expression*/}){ 7 | case ${20:/*Expression*/}: 8 | ${0:} 9 | break; 10 | default: 11 | 12 | } 13 | name 14 | switch … case 15 | scope 16 | source.js 17 | tabTrigger 18 | switch 19 | uuid 20 | 65AAF33F-7706-4FC0-B5E0-E9AABEF0731E 21 | 22 | 23 | -------------------------------------------------------------------------------- /Snippets/for (…) {…} (Fastest reverse).tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | for (var ${20:i} = ${1:${2:Things}.length}; --$20 >= 0;){ 7 | ${0:$2[$20]} 8 | } 9 | name 10 | for (…) {…} (Fastest reverse) 11 | scope 12 | source.js 13 | tabTrigger 14 | for 15 | uuid 16 | 814C024D-3431-48B5-8B34-4BDC29DCB277 17 | 18 | 19 | -------------------------------------------------------------------------------- /Snippets/for (…) {…} (Fastest).tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | for (var ${20:i} = -1, ${30:ln} = ${1:${2:Things}.length}; ++$20 < $30;) { 7 | ${0:$2[$20]} 8 | } 9 | name 10 | for (…) {…} (Fastest) 11 | scope 12 | source.js 13 | tabTrigger 14 | for 15 | uuid 16 | 6DC06A4E-E151-467F-9CF7-FA61DD540D6E 17 | 18 | 19 | -------------------------------------------------------------------------------- /Snippets/for (…) {…} (faster).tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | for (var ${20:i} = ${1:${2:Things}.length} - 1; ${20:i} >= 0; ${20:i}--){ 7 | ${0:$2[$20]} 8 | } 9 | name 10 | for (…) {…} (Improved Native For-Loop) 11 | scope 12 | source.js 13 | tabTrigger 14 | for 15 | uuid 16 | C207B7C3-5597-4873-8AAD-C46FB8842AF2 17 | 18 | 19 | -------------------------------------------------------------------------------- /Snippets/window_addEventListener_load.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | window.addEventListener('load',function(){ 7 | 8 | $0${TM_SELECTED_TEXT: 9 | } 10 | },false); 11 | name 12 | window.addEventListener('load') 13 | scope 14 | source.js 15 | tabTrigger 16 | load 17 | uuid 18 | 523E9E93-6E43-4E2F-9F6F-465A8A24714E 19 | 20 | 21 | -------------------------------------------------------------------------------- /Preferences/Symbol List Class.tmPreferences: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | name 6 | Symbol List Class 7 | scope 8 | source.js entity.name.type.class 9 | settings 10 | 11 | showInSymbolList 12 | 1 13 | symbolTransformation 14 | 15 | s/^/• /g; 16 | 17 | 18 | uuid 19 | 3CEA49B2-A5C5-405C-82E2-B8B668877C37 20 | 21 | 22 | -------------------------------------------------------------------------------- /Preferences/Symbol List Instance.tmPreferences: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | name 6 | Symbol List Instance 7 | scope 8 | source.js entity.name.instance 9 | settings 10 | 11 | showInSymbolList 12 | 1 13 | symbolTransformation 14 | 15 | s/^/\t/g; 16 | 17 | 18 | uuid 19 | E6EB7CC8-04E8-43A9-93B2-BC9EF5BA862B 20 | 21 | 22 | -------------------------------------------------------------------------------- /Preferences/Symbol List Sub 1.tmPreferences: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | name 6 | Symbol List Sub 1 7 | scope 8 | source.js entity.name.function 9 | settings 10 | 11 | showInSymbolList 12 | 1 13 | symbolTransformation 14 | 15 | s/^/ /g; 16 | s/$/:/g; 17 | 18 | 19 | uuid 20 | 73557394-4F0F-4DD3-8029-EEE8201AC7F5 21 | 22 | 23 | -------------------------------------------------------------------------------- /Support/JSSpec/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | JSSpec results 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Preferences/Symbol List Sub 2.tmPreferences: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | name 6 | Symbol List Sub 2 7 | scope 8 | source.js meta.group meta.group object.property.function 9 | settings 10 | 11 | showInSymbolList 12 | 1 13 | symbolTransformation 14 | 15 | s/^/  /g; 16 | s/$/:/g; 17 | 18 | 19 | uuid 20 | 51841DDB-C2A4-461C-A8AB-6C124AD50EAE 21 | 22 | 23 | -------------------------------------------------------------------------------- /Support/run_js.js: -------------------------------------------------------------------------------- 1 | (function(window){ 2 | 3 | function e_sh(s){ 4 | return String(s).replace(/'/g,'’').replace(/(?=["\n\\])/g,'\\'); 5 | }; 6 | 7 | window.alert = function(s){ 8 | console.debug($DIALOG +' -e -p \'{messageTitle="JavaScript";informativeText="'+ e_sh(s) +'";}\''); 9 | TextMate.system($DIALOG +' -e -p \'{messageTitle="JavaScript";informativeText="'+ e_sh(s) +'";}\'', null); 10 | }; 11 | 12 | var __TM_confirm_Status; 13 | window.confirm = function(s){ 14 | TextMate.system($DIALOG +' -e -p \'{messageTitle="JavaScript";informativeText="'+ e_sh(s) +'";buttonTitles=("OK","Cancel");}\'', null) 15 | .onreadoutput = function(s){ __TM_confirm_Status = s != 1; }; 16 | return __TM_confirm_Status; 17 | }; 18 | 19 | })(this); 20 | -------------------------------------------------------------------------------- /Snippets/Class Closure MyClass = (fn(){…})().tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | ${1/^(\w+)$|.+/(?1:var )/}${1:MyClass} = (function(${2:}){ 7 | function ${1/(?:.*\.)?(\w*)/$1/}(){$0}; 8 | ${1/(?:.*\.)?(\w*)/$1/}.prototype = {}; 9 | return ${1/(?:.*\.)?(\w*)/$1/}; 10 | })(${2/(.+)/(?1:{})/}); 11 | name 12 | Class Closure MyClass = (fn(){…})() 13 | scope 14 | source.js 15 | tabTrigger 16 | cla 17 | uuid 18 | ED5F2161-F404-45EA-A8CD-5A4C0CB18DFF 19 | 20 | 21 | -------------------------------------------------------------------------------- /Snippets/createNode…appendChild idiom.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | var ${1:element} = document.createElement('${10:div}'); 7 | $0${100:$1.innerHTML = ${290:'${300:lorem}'}; 8 | }${110:$1.appendChild(document.createTextNode(${355:${290:'${350:$300}'}})); 9 | }${200:document.body}.appendChild($1); 10 | name 11 | createNode…appendChild idiom 12 | scope 13 | source.js 14 | tabTrigger 15 | el= 16 | uuid 17 | E39E4E5A-32FC-4BD5-91D8-6A8B6A5AEB2F 18 | 19 | 20 | -------------------------------------------------------------------------------- /Commands/Complete.tmCommand: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | beforeRunningCommand 6 | nop 7 | command 8 | #!/usr/bin/env ruby 9 | require ENV['TM_BUNDLE_SUPPORT'] + '/lib/tm/complete' 10 | TextMate::Complete.new.complete! 11 | 12 | input 13 | none 14 | keyEquivalent 15 | ~ 16 | name 17 | Code Completion 18 | output 19 | showAsTooltip 20 | scope 21 | source.js, source.js string 22 | uuid 23 | C09ABCA9-7558-4385-8E29-10E42093D8B6 24 | 25 | 26 | -------------------------------------------------------------------------------- /DragCommands/relative script path string.tmDragCommand: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | beforeRunningCommand 6 | nop 7 | command 8 | echo "'$TM_DROPPED_FILE'" 9 | draggedFileExtensions 10 | 11 | js 12 | json 13 | 14 | input 15 | selection 16 | name 17 | relative script path string 18 | output 19 | insertAsSnippet 20 | scope 21 | source.js -string 22 | uuid 23 | 5AE2BB5C-AF4F-4529-8FAE-5E0FCEE69872 24 | 25 | 26 | -------------------------------------------------------------------------------- /Commands/New Function.tmCommand: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | beforeRunningCommand 6 | nop 7 | command 8 | cat <<SNIPPET 9 | function ${TM_SELECTED_TEXT:-$TM_CURRENT_WORD}(\$1){\$0} 10 | SNIPPET 11 | fallbackInput 12 | word 13 | input 14 | selection 15 | keyEquivalent 16 | $ 17 | name 18 | New Function 19 | output 20 | insertAsSnippet 21 | scope 22 | source.js 23 | uuid 24 | 73951799-AC15-40A6-81DB-EC051AB4A033 25 | 26 | 27 | -------------------------------------------------------------------------------- /Commands/New Method.tmCommand: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | beforeRunningCommand 6 | nop 7 | command 8 | cat <<SNIPPET 9 | ${TM_SELECTED_TEXT:-$TM_CURRENT_WORD}: function(\$1){\$0}, 10 | SNIPPET 11 | 12 | fallbackInput 13 | word 14 | input 15 | selection 16 | keyEquivalent 17 | ~$ 18 | name 19 | New Method 20 | output 21 | insertAsSnippet 22 | scope 23 | source.js 24 | uuid 25 | 1717B5AE-209B-4548-9155-9E88A7230C1C 26 | 27 | 28 | -------------------------------------------------------------------------------- /Preferences/Symbol List Banned.tmPreferences: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | name 6 | Symbol List Banned 7 | scope 8 | source.js support.function, source.js meta.property.function entity.name.function, source.js meta.function-call entity.name.function -(source.js meta.function-call meta.group entity.name.function), source.js meta.group meta.function-call entity.name.function -(source.js meta.group meta.function-call meta.group entity.name.function) 9 | settings 10 | 11 | showInSymbolList 12 | 0 13 | 14 | uuid 15 | 834BC727-6B31-4073-A161-4823227219EF 16 | 17 | 18 | -------------------------------------------------------------------------------- /DragCommands/relative script path.tmDragCommand: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | beforeRunningCommand 6 | nop 7 | command 8 | echo -n "$TM_DROPPED_FILE" 9 | draggedFileExtensions 10 | 11 | js 12 | json 13 | 14 | input 15 | selection 16 | name 17 | relative script path 18 | output 19 | insertAsSnippet 20 | scope 21 | source.js string.quoted -punctuation.definition.string.begin 22 | uuid 23 | BF6200B3-9E7A-442D-873D-73FBF34657F9 24 | 25 | 26 | -------------------------------------------------------------------------------- /Commands/Help.tmCommand: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | beforeRunningCommand 6 | nop 7 | command 8 | . "$TM_SUPPORT_PATH/lib/webpreview.sh" 9 | html_header "Javascript Bundle Help" "Javascript" 10 | 11 | "$TM_SUPPORT_PATH/lib/markdown_to_help.rb" "$TM_BUNDLE_SUPPORT/../README.md" 12 | 13 | html_footer 14 | 15 | dontFollowNewOutput 16 | 17 | input 18 | none 19 | name 20 | Help 21 | output 22 | showAsHTML 23 | scope 24 | source.js 25 | uuid 26 | EB00F356-06C8-4267-8226-AA8F3943E5B1 27 | 28 | 29 | -------------------------------------------------------------------------------- /Support/Array.instance.completions.json: -------------------------------------------------------------------------------- 1 | { 2 | "suggestions": [ 3 | { "image":"Array", "display": "constructor", "match": "constructor", "tool_tip": "Specifies the function that creates an object's prototype." }, 4 | { "image":"Array", "display": "index", "match": "index", "tool_tip": "This is pseudo-property of Array prototypes because it is not inherited by default. It is, in fact, only present in arrays created by regular expression matches. The property represents the zero-based index of the match in the string." }, 5 | { "image":"Array", "display": "input", "match": "input", "tool_tip": "This property is only present in arrays created by regular expression matches. It reflects the original string against which the regular expression was matched." }, 6 | { "image":"Array", "display": "length", "match": "length", "tool_tip": "Reflects the number of elements in an array." } 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /Commands/Documentation for Word : Selection (tool tip).tmCommand: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | beforeRunningCommand 6 | nop 7 | command 8 | #!/usr/bin/env ruby 9 | require ENV['TM_BUNDLE_SUPPORT'] + '/lib/tm/complete' 10 | TextMate::Complete.new.tip! 11 | 12 | fallbackInput 13 | word 14 | input 15 | none 16 | keyEquivalent 17 | ~ 18 | name 19 | Documentation for Word / Selection (tool tip) 20 | output 21 | showAsTooltip 22 | scope 23 | source.js 24 | uuid 25 | 44006EE0-7476-418F-B8F3-D98F21A22DF6 26 | 27 | 28 | -------------------------------------------------------------------------------- /Preferences/Comments.tmPreferences: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | name 6 | Comments 7 | scope 8 | source.js 9 | settings 10 | 11 | shellVariables 12 | 13 | 14 | name 15 | TM_COMMENT_START 16 | value 17 | // 18 | 19 | 20 | name 21 | TM_COMMENT_START_2 22 | value 23 | /* 24 | 25 | 26 | name 27 | TM_COMMENT_END_2 28 | value 29 | */ 30 | 31 | 32 | 33 | uuid 34 | A67A8BD9-A951-406F-9175-018DD4B52FD1 35 | 36 | 37 | -------------------------------------------------------------------------------- /Commands/convert this to me.tmCommand: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | beforeRunningCommand 6 | nop 7 | command 8 | #!/usr/bin/env ruby 9 | 10 | code = STDIN.read 11 | 12 | if code =~ /\bme\b/ 13 | 14 | code.gsub!(/(\s*var\s+)?me\s+=\s+this\s*;?\s*$\n?/,'') 15 | code.gsub!(/\bme\b/,'this') 16 | 17 | else 18 | code.gsub!(/\bthis\b/,'me') 19 | indent = code.split("\n")[0].match(/^\s*/)[0] 20 | code = "#{indent}var me = this;\n" << code 21 | end 22 | 23 | print code 24 | 25 | fallbackInput 26 | line 27 | input 28 | selection 29 | keyEquivalent 30 | ^@S 31 | name 32 | convert this to me 33 | output 34 | replaceSelectedText 35 | scope 36 | source.js 37 | uuid 38 | 6F3570B1-89AF-43BD-BA8B-BA3B6DF4A10D 39 | 40 | 41 | -------------------------------------------------------------------------------- /Commands/convert this to self.tmCommand: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | beforeRunningCommand 6 | nop 7 | command 8 | #!/usr/bin/env ruby 9 | 10 | code = STDIN.read 11 | 12 | if code =~ /\bself\b/ 13 | 14 | code.gsub!(/(\s*var\s+)?self\s+=\s+this\s*;?\s*$\n?/,'') 15 | code.gsub!(/\bself\b/,'this') 16 | 17 | else 18 | code.gsub!(/\bthis\b/,'self') 19 | indent = code.split("\n")[0].match(/^\s*/)[0] 20 | code = "#{indent}var self = this;\n" << code 21 | end 22 | 23 | print code 24 | 25 | fallbackInput 26 | line 27 | input 28 | selection 29 | keyEquivalent 30 | ^@S 31 | name 32 | convert this to self 33 | output 34 | replaceSelectedText 35 | scope 36 | source.js 37 | uuid 38 | F035D69A-8987-459C-8425-090752784BC4 39 | 40 | 41 | -------------------------------------------------------------------------------- /Commands/Documentation for Word : Selection Google Lucky.tmCommand: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | beforeRunningCommand 6 | nop 7 | command 8 | cat|pbcopy -pboard find 9 | 10 | . "$TM_SUPPORT_PATH/lib/html.sh" 11 | redirect "http://www.google.com/search?q="${TM_SELECTED_TEXT:-$TM_CURRENT_WORD}"%20site%3Aquirksmode.org%20OR%20site%3Adeveloper.mozilla.org%2FEn%20OR%20site%3Amsdn.microsoft.com%2Fen-us%2Flibrary%20OR%20site%3Awww.w3schools.com%20OR%20site%3Awww.devguru.com&btnI=I%27m+Feeling+Lucky" 12 | 13 | fallbackInput 14 | word 15 | input 16 | selection 17 | keyEquivalent 18 | ^~h 19 | name 20 | Documentation for Word / Selection Google Lucky 21 | output 22 | showAsHTML 23 | scope 24 | source.js 25 | uuid 26 | 092B230D-ACAB-4C38-B2E4-F7E013C7CDCB 27 | 28 | 29 | -------------------------------------------------------------------------------- /Commands/Documentation for Word.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | beforeRunningCommand 6 | nop 7 | command 8 | # index created using: curl -s 'http://devguru.com/technologies/javascript/index.asp'|grep -o '<a href="[0-9]*.asp">[a-z][a-zA-Z]*</a>'|perl -pe 's/<a href="([^"]*)">([^<]*)<\/a>/$2\t$1/'|sort|uniq|gzip >dev_guru_index.gz 9 | 10 | ref=$(zgrep -w "^${TM_SELECTED_TEXT:-$TM_CURRENT_WORD}" "$TM_BUNDLE_SUPPORT/dev_guru_index.gz"|cut -f2) 11 | 12 | [[ -n "$ref" ]] && exit_show_html "<meta http-equiv='Refresh' content='0;URL=http://devguru.com/technologies/javascript/$ref'>" 13 | 14 | echo "No documentation found." 15 | fallbackInput 16 | word 17 | input 18 | selection 19 | keyEquivalent 20 | ^h 21 | name 22 | Documentation for Word / Selection 23 | output 24 | showAsTooltip 25 | scope 26 | source.js 27 | uuid 28 | B4874A14-2491-465A-A349-61E4EBCF4700 29 | 30 | 31 | -------------------------------------------------------------------------------- /Commands/Documentation for Word : Selection Google.tmCommand: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | beforeRunningCommand 6 | nop 7 | command 8 | #!/usr/bin/env bash 9 | [[ -f "${TM_SUPPORT_PATH}/lib/bash_init.sh" ]] && . "${TM_SUPPORT_PATH}/lib/bash_init.sh" 10 | 11 | cat|pbcopy -pboard find 12 | 13 | . "$TM_SUPPORT_PATH/lib/html.sh" 14 | redirect "http://www.google.com/search?q="${TM_SELECTED_TEXT:-$TM_CURRENT_WORD}"%20site%3Aquirksmode.org%20OR%20site%3Adeveloper.mozilla.org%2FEn%20OR%20site%3Amsdn.microsoft.com%2Fen-us%2Flibrary%20OR%20site%3Awww.devguru.com&btnG=Search" 15 | 16 | fallbackInput 17 | word 18 | input 19 | selection 20 | inputFormat 21 | text 22 | keyEquivalent 23 | ^h 24 | name 25 | Documentation for Word / Selection Google 26 | outputCaret 27 | afterOutput 28 | outputFormat 29 | html 30 | outputLocation 31 | newWindow 32 | scope 33 | source.js 34 | uuid 35 | 3DAB45A8-21C8-4581-809B-2D3C1E8FF1B0 36 | version 37 | 2 38 | 39 | 40 | -------------------------------------------------------------------------------- /Tests/Embedded Javascript Test Invalid.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | Embedded Javascript Test.html 7 | 11 | 12 | 13 | 14 | 1 Link!
15 | 2 Link!
16 | 3 Link!
17 | 4 Link!
18 | 19 | 5 "
22 | 23 | 6 "
26 | 27 | 7 "
28 | 8
29 | 30 | End the string if the /script tag is followed by a newline. Don't if not. 31 | 9 33 | " 34 |
35 | 36 | 10 38 | ' 39 |
40 | 41 | 11 " 43 | 44 |
45 | 46 | 12 ' 48 | 49 |
50 | 51 | 55 | 56 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /Snippets/JSSpec Standalone.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 7 | "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 8 | <html xmlns="http://www.w3.org/1999/xhtml"> 9 | <head> 10 | <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 11 | 12 | <title>JSSpec results</title> 13 | <style type="text/css"> 14 | /*<![CDATA[*/ 15 | `cat "$TM_BUNDLE_SUPPORT/JSSpec/JSSpec.css"` 16 | /*]]>*/ 17 | </style> 18 | <script type="text/javascript"> 19 | /*<![CDATA[*/ 20 | `cat "$TM_BUNDLE_SUPPORT/JSSpec/diff_match_patch.js"` 21 | /*]]>*/ 22 | </script> 23 | <script type="text/javascript"> 24 | /*<![CDATA[*/ 25 | `cat "$TM_BUNDLE_SUPPORT/JSSpec/JSSpec.js"` 26 | /*]]>*/ 27 | </script> 28 | </head> 29 | <body> 30 | <script src="${1:something}.js" type="text/javascript" charset="utf-8"></script> 31 | <script type="text/javascript" charset="utf-8"> 32 | 33 | describe('${2:$1}', { 34 | 35 | 'should exist': function(){ 36 | value_of( ${3:$1} ).should_not_be_undefined(); 37 | } 38 | , 39 | 'should work': function(){ 40 | $0 41 | } 42 | }); 43 | 44 | </script> 45 | </body> 46 | </html> 47 | 48 | name 49 | JSSpec Standalone 50 | scope 51 | text.html 52 | tabTrigger 53 | jsspec 54 | uuid 55 | 1C062C73-8798-4794-8F4A-223012E42A07 56 | 57 | 58 | -------------------------------------------------------------------------------- /Preferences/Misc.tmPreferences: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | name 6 | Misc 7 | scope 8 | source.js 9 | settings 10 | 11 | highlightPairs 12 | 13 | 14 | ' 15 | ' 16 | 17 | 18 | " 19 | " 20 | 21 | 22 | ( 23 | ) 24 | 25 | 26 | [ 27 | ] 28 | 29 | 30 | { 31 | } 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | smartTypingPairs 43 | 44 | 45 | ' 46 | ' 47 | 48 | 49 | " 50 | " 51 | 52 | 53 | ( 54 | ) 55 | 56 | 57 | [ 58 | ] 59 | 60 | 61 | { 62 | } 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | uuid 75 | AC6FAAC0-07C4-4DB3-B493-28A64B96A258 76 | 77 | 78 | -------------------------------------------------------------------------------- /Commands/Copy as Bookmarklet to Clipboard.tmCommand: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | beforeRunningCommand 6 | nop 7 | command 8 | #!/usr/bin/env perl 9 | # 10 | # Written by John Gruber, taken with permission from: 11 | # http://daringfireball.net/2007/03/javascript_bookmarklet_builder 12 | 13 | use strict; 14 | use warnings; 15 | use URI::Escape qw(uri_escape_utf8); 16 | use open IO => ":utf8", # UTF8 by default 17 | ":std"; # Apply to STDIN/STDOUT/STDERR 18 | 19 | my $src = do { local $/; <> }; 20 | 21 | # Zap the first line if there's already a bookmarklet comment: 22 | $src =~ s{^// ?javascript:.+\n}{}; 23 | my $bookmarklet = $src; 24 | 25 | $bookmarklet =~ s{^\s*//.+\n}{}gm; # Kill comments. 26 | $bookmarklet =~ s{\t}{ }gm; # Tabs to spaces 27 | $bookmarklet =~ s{ +}{ }gm; # Space runs to one space 28 | $bookmarklet =~ s{^\s+}{}gm; # Kill line-leading whitespace 29 | $bookmarklet =~ s{\s+$}{}gm; # Kill line-ending whitespace 30 | $bookmarklet =~ s{\n}{}gm; # Kill newlines 31 | 32 | # Escape single- and double-quotes, spaces, control chars, unicode: 33 | $bookmarklet = "javascript:" . 34 | uri_escape_utf8($bookmarklet, qq('" \x00-\x1f\x7f-\xff)); 35 | 36 | print "// $bookmarklet\n" . $src; 37 | 38 | # Put bookmarklet on clipboard: 39 | `/bin/echo -n '$bookmarklet' | /usr/bin/pbcopy`; 40 | 41 | input 42 | selection 43 | keyEquivalent 44 | ^H 45 | name 46 | Copy as Bookmarklet to Clipboard 47 | output 48 | replaceSelectedText 49 | scope 50 | source.js 51 | uuid 52 | 20E61C43-B81F-4FB9-9362-BFFE668EB9C9 53 | 54 | 55 | -------------------------------------------------------------------------------- /Preferences/Typing Pairs: String and Comment.tmPreferences: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | name 6 | Typing Pairs: String and Comment 7 | scope 8 | string.quoted, comment 9 | settings 10 | 11 | highlightPairs 12 | 13 | 14 | ' 15 | ' 16 | 17 | 18 | " 19 | " 20 | 21 | 22 | ( 23 | ) 24 | 25 | 26 | < 27 | > 28 | 29 | 30 | [ 31 | ] 32 | 33 | 34 | { 35 | } 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | smartTypingPairs 47 | 48 | 49 | ' 50 | ' 51 | 52 | 53 | " 54 | " 55 | 56 | 57 | ( 58 | ) 59 | 60 | 61 | < 62 | > 63 | 64 | 65 | [ 66 | ] 67 | 68 | 69 | { 70 | } 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | uuid 83 | B8541849-2B39-440E-928F-E3C55E8D1BED 84 | 85 | 86 | -------------------------------------------------------------------------------- /Support/run_js.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | $YOURCODE = STDIN.read 3 | 4 | print <<-HTML 5 | 6 | 7 | 8 | 9 | Run Javascript #{ENV['TM_FILENAME']} 10 | 11 | 12 | HTML 13 | 14 | 15 | requirements = [] 16 | requirements << ['tm-file://'+ ENV['TM_BUNDLE_SUPPORT']+ '/run_js.js?1234'] 17 | requirements << ENV['TM_WEB_FRAMEWORK'] if ENV['TM_WEB_FRAMEWORK'] 18 | requirements += $YOURCODE.scan(/@require (?:"([^"]*)"|'([^']*)')/).map { |e| e.first || e[1] } 19 | requirements.flatten! 20 | requirements.uniq! 21 | 22 | requirements = requirements.map do |requirement| 23 | 24 | requirement = 'http://ajax.googleapis.com/ajax/libs/mootools/1.2.3/mootools.js' if requirement == 'mootools' 25 | requirement = 'http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.js' if requirement == 'jquery' 26 | 27 | if requirement == 'jsspec' 28 | requirement = [ 29 | 'tm-file://'+ ENV['TM_BUNDLE_SUPPORT']+ '/JSSpec/'+ 'JSSpec.css', 30 | 'tm-file://'+ ENV['TM_BUNDLE_SUPPORT']+ '/JSSpec/'+ 'diff_match_patch.js', 31 | 'tm-file://'+ ENV['TM_BUNDLE_SUPPORT']+ '/JSSpec/'+ 'JSSpec.js' 32 | ] 33 | end 34 | 35 | requirement 36 | end.flatten 37 | 38 | requirements.uniq.each do |requirement| 39 | requirement = 'tm-file://' + File.dirname(ENV['TM_FILEPATH']||ENV['HOME']) +'/'+ requirement if requirement =~ /^(?!\/|https?:|(tm-)?file:\/\/)/ 40 | 41 | print %{\n} unless requirement =~ /\.css$/ 42 | 43 | print <<-CSS if requirement =~ /\.css$/ 44 | 47 | CSS 48 | end 49 | 50 | print <<-HTML 51 | 78 | 79 | 80 | 81 | HTML 82 | 83 | __END__ 84 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | The Javascript Bundle 2 | ===================== 3 | 4 | How to install 5 | ---- 6 | 7 | 0. Install TextMate (um… duh?) 8 | 1. Download 9 | 2. Unzip 10 | 3. Rename the folder to `js.tmbundle` 11 | * The name of the folder doesn't really matter, just so long as it has the `tmbundle` extension 12 | 4. Double-Click 13 | 5. Install the JSON Ruby Gem from your Terminal 14 | * `sudo gem install json` 15 | 6. Enjoy! 16 | 17 | Integrated Quirksmode.org Docs 18 | ------------------------------ 19 | 20 | The DOM code completions and tooltip data were generated from 21 | the excellent [Quirksmode W3C DOM Compatibility Tables](http://www.quirksmode.org/dom/compatibility.html "W3C DOM Compatibility Tables") by [PPK](http://quirksmode.org/blogs.shtml "QuirksMode Blogs") (used with permission). 22 | Scraped, reformatted and converted for use in the bundle by [Thomas Aylott / subtlegradient](http://subtlegradient.com/ "subtleGradient"). 23 | 24 | Code Completion 25 | --------------- 26 | 27 | Code Completion as-you-type for Methods and Properties of... 28 | 29 | * Cross-Platform Browser Object Model API 30 | * Cross-Platform Document Object Model API 31 | * String, Number, Array 32 | 33 | ### Dumb Completion 34 | 35 | The code completion is mostly dumb. It doesn't understand your code and just suggests the same things in almost all contexts. 36 | 37 | ### Smart Completion 38 | 39 | For some things with known types, the list of completions is filtered to only include known methods and properties of that type. 40 | 41 | *Requires the latest cutting edge build of TextMate* 42 | 43 | Snippets 44 | -------- 45 | Cut your keystroke count in half with snippets for common javascript idioms. 46 | 47 | 48 | Learn Javascript 49 | ---------------- 50 | * [Quirksmode W3C DOM Compatibility Tables](http://www.quirksmode.org/dom/compatibility.html "W3C DOM Compatibility Tables") by [PPK](http://quirksmode.org/blogs.shtml "QuirksMode Blogs") 51 | * [Eloquent JavaScript -- interactive tutorial](http://eloquentjavascript.net/ "Eloquent JavaScript -- interactive tutorial") 52 | * [A re-introduction to JavaScript - MDC](http://developer.mozilla.org/en/A_re-introduction_to_JavaScript "A re-introduction to JavaScript - MDC") 53 | * [Mozilla Javascript](http://developer.mozilla.org/En/About_JavaScript "About JavaScript - MDC") 54 | * [Microsoft JScript](http://msdn.microsoft.com/en-us/library/72bd815a%28VS.80%29.aspx "JScript") 55 | * [Safari JavaScript Reference](http://developer.apple.com/documentation/AppleApplications/Reference/SafariJSRef/Intro/Intro.html "Safari JavaScript Reference") 56 | * [Web Kit DOM Programming Topics](http://developer.apple.com/documentation/AppleApplications/Conceptual/SafariJSProgTopics/ "Web Kit DOM Programming Topics") 57 | * [JavaScript Madness: Keyboard Events](http://unixpapa.com/js/key.html "JavaScript Madness: Keyboard Events") 58 | -------------------------------------------------------------------------------- /Preferences/Indent.tmPreferences: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | name 6 | Indent 7 | scope 8 | source.js, source.json 9 | settings 10 | 11 | decreaseIndentPattern 12 | (?x)^ 13 | # ( Blank |Comments | (No Paren | String) | String | (Nested Parens ) )*+ Close Yes *+ 14 | (?> (?<yesS> (?!.) |//.*+|/\*((?!\*/).)++(\*/|$)|(^)((?!/\*).)*(\*/)| (?<noS>[^\[\]'"/]) | (?<str> '(\\'|[^'])*+' | "(\\"|[^"])*+" | /(\\/|[^/])*+/) | (?<squar> \[ \g<yesS>*+ \] ) )*+ \] \g<yesS>*+ 15 | | (?<yesR> (?!.) |//.*+|/\*((?!\*/).)++(\*/|$)|(^)((?!/\*).)*(\*/)| (?<noR>[^\(\)'"/]) | \g<str> | (?<round> \( \g<yesR>*+ \) ) )*+ \) \g<yesR>*+ 16 | | (?<yesC> (?!.) |//.*+|/\*((?!\*/).)++(\*/|$)|(^)((?!/\*).)*(\*/)| (?<noC>[^\{\}'"/]) | \g<str> | (?<curly> \{ \g<yesC>*+ \} ) )*+ \} \g<yesC>*+ 17 | | \s* (?!//|/\*) \b(?:case|default)\b 18 | (\g<str> | \g<noC> | \g<noC>? \g<curly> \b<noC>?)++ (?!\}) 19 | $ 20 | ) 21 | increaseIndentPattern 22 | (?x)^ 23 | # Yes *+ Open ( Blank |Comments | (No Paren | String) | String | (Nested Parens ) )*+ 24 | (?> \g<yesS>*+ \[ (?<yesS> (?!.) |//.*+|/\*((?!\*/).)++(\*/|$)|(^)((?!/\*).)*(\*/)| (?<noS>[^\[\]'"/]) | (?<str> '(\\'|[^'])*+' | "(\\"|[^"])*+" | /(\\/|[^/])*+/) | (?<squar> \[ \g<yesS>*+ \] ) )*+ 25 | | \g<yesR>*+ \( (?<yesR> (?!.) |//.*+|/\*((?!\*/).)++(\*/|$)|(^)((?!/\*).)*(\*/)| (?<noR>[^\(\)'"/]) | \g<str> | (?<round> \( \g<yesR>*+ \) ) )*+ 26 | | \g<yesC>*+ \{ (?<yesC> (?!.) |//.*+|/\*((?!\*/).)++(\*/|$)|(^)((?!/\*).)*(\*/)| (?<noC>[^\{\}'"/]) | \g<str> | (?<curly> \{ \g<yesC>*+ \} ) )*+ 27 | | \s* (?!//|/\*)([^\s].*)? \b(?:case|default)\b 28 | (\g<str> | \g<noC> | \g<noC>? \g<curly> \b<noC>?)++ (?!\}) 29 | )$ 30 | indentNextLinePattern 31 | ^\s*((if|while|for|switch|else if).*[)]|else)\s*$ 32 | unIndentedLinePattern 33 | (?x)^ \s* /\* ((?!\*/).)++ $ | ^\s\* | ^\s* \*/\s* $ | ^ \s* $ 34 | 35 | uuid 36 | BC062860-3346-4D3B-8421-C5543F83D11F 37 | 38 | 39 | -------------------------------------------------------------------------------- /Commands/console 2.tmCommand: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | beforeRunningCommand 6 | nop 7 | command 8 | #!/usr/bin/env ruby 9 | require ENV['TM_BUNDLE_SUPPORT'] + '/lib/tm/complete' 10 | 11 | ENV['TM_COMPLETIONS_FILE'] = nil 12 | ENV['TM_COMPLETIONS_FILES'] = nil 13 | 14 | ENV['TM_COMPLETIONS_SPLIT'] = 'json' 15 | ENV['TM_COMPLETIONS'] = '{ 16 | "suggestions":[ 17 | { "display": "console.log(message)" ,"match": "log" ,"insert": "($0)"}, 18 | { "display": "console.debug(message)" ,"match": "debug" ,"insert": "($0)"}, 19 | { "display": "console.info(message)" ,"match": "info" ,"insert": "($0)"}, 20 | { "display": "console.warn(message)" ,"match": "warn" ,"insert": "($0)"}, 21 | { "display": "console.error(message)" ,"match": "error" ,"insert": "($0)"}, 22 | { "display": "console.dir(object)" ,"match": "dir" ,"insert": "($0)"}, 23 | { "display": "console.dirxml(node)" ,"match": "dirxml" ,"insert": "($0)"}, 24 | { "display": "console.group(message)" ,"match": "group" ,"insert": "($0)"}, 25 | { "display": "console.groupCollapsed(message)" ,"match": "groupCollapsed" ,"insert": "($0)"}, 26 | { "display": "console.groupEnd()" ,"match": "groupEnd" ,"insert": "($0)"}, 27 | { "display": "console.profile(title)" ,"match": "profile" ,"insert": "($0)"}, 28 | { "display": "console.profileEnd(title)" ,"match": "profileEnd" ,"insert": "($0)"}, 29 | { "display": "console.count(title)" ,"match": "count" ,"insert": "($0)"}, 30 | { "display": "console.markTimeline(string)" ,"match": "markTimeline" ,"insert": "($0)"}, 31 | { "display": "console.time(name)" ,"match": "time" ,"insert": "($0)"}, 32 | { "display": "console.timeEnd(name)" ,"match": "timeEnd" ,"insert": "($0)"}, 33 | { "display": "console.trace()" ,"match": "trace" ,"insert": "($0)"}, 34 | { "display": "console.assert(expression, message)" ,"match": "assert" ,"insert": "(true, ${0:message})"} 35 | ] 36 | }' 37 | 38 | print 'console.' 39 | 40 | TextMate::Complete.new.complete! 41 | 42 | input 43 | none 44 | name 45 | console 46 | output 47 | afterSelectedText 48 | scope 49 | source.js 50 | tabTrigger 51 | c 52 | uuid 53 | C8A09756-FE14-461A-A3FF-D2D3A18CCF53 54 | 55 | 56 | -------------------------------------------------------------------------------- /Commands/console.tmCommand: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | beforeRunningCommand 6 | nop 7 | command 8 | #!/usr/bin/env ruby 9 | require ENV['TM_BUNDLE_SUPPORT'] + '/lib/tm/complete' 10 | 11 | ENV['TM_COMPLETIONS_FILE'] = nil 12 | ENV['TM_COMPLETIONS_FILES'] = nil 13 | 14 | ENV['TM_COMPLETIONS_SPLIT'] = 'json' 15 | ENV['TM_COMPLETIONS'] = '{ 16 | "suggestions":[ 17 | { "display": "console.log(message)" ,"match": "log" ,"insert": "($0)"}, 18 | { "display": "console.debug(message)" ,"match": "debug" ,"insert": "($0)"}, 19 | { "display": "console.info(message)" ,"match": "info" ,"insert": "($0)"}, 20 | { "display": "console.warn(message)" ,"match": "warn" ,"insert": "($0)"}, 21 | { "display": "console.error(message)" ,"match": "error" ,"insert": "($0)"}, 22 | { "display": "console.dir(object)" ,"match": "dir" ,"insert": "($0)"}, 23 | { "display": "console.dirxml(node)" ,"match": "dirxml" ,"insert": "($0)"}, 24 | { "display": "console.group(message)" ,"match": "group" ,"insert": "($0)"}, 25 | { "display": "console.groupCollapsed(message)" ,"match": "groupCollapsed" ,"insert": "($0)"}, 26 | { "display": "console.groupEnd()" ,"match": "groupEnd" ,"insert": "($0)"}, 27 | { "display": "console.profile(title)" ,"match": "profile" ,"insert": "($0)"}, 28 | { "display": "console.profileEnd(title)" ,"match": "profileEnd" ,"insert": "($0)"}, 29 | { "display": "console.count(title)" ,"match": "count" ,"insert": "($0)"}, 30 | { "display": "console.markTimeline(string)" ,"match": "markTimeline" ,"insert": "($0)"}, 31 | { "display": "console.time(name)" ,"match": "time" ,"insert": "($0)"}, 32 | { "display": "console.timeEnd(name)" ,"match": "timeEnd" ,"insert": "($0)"}, 33 | { "display": "console.trace()" ,"match": "trace" ,"insert": "($0)"}, 34 | { "display": "console.assert(expression, message)" ,"match": "assert" ,"insert": "(true, ${0:message})"} 35 | ] 36 | }' 37 | 38 | print 'console.' 39 | 40 | TextMate::Complete.new.complete! 41 | 42 | input 43 | none 44 | name 45 | console 46 | output 47 | afterSelectedText 48 | scope 49 | source.js 50 | tabTrigger 51 | console. 52 | uuid 53 | EC7B0B43-3ABA-4074-8BFC-366469F8F07D 54 | 55 | 56 | -------------------------------------------------------------------------------- /Support/JSSpec/JSSpec.css: -------------------------------------------------------------------------------- 1 | @CHARSET "UTF-8"; 2 | 3 | /* -------------------- 4 | * @Layout 5 | */ 6 | 7 | html { 8 | overflow: hidden; 9 | } 10 | 11 | body, #jsspec_container { 12 | overflow: hidden; 13 | padding: 0; 14 | margin: 0; 15 | width: 100%; 16 | height: 100%; 17 | background-color: white; 18 | } 19 | 20 | #title { 21 | padding: 0; 22 | margin: 0; 23 | position: absolute; 24 | top: 0px; 25 | left: 0px; 26 | width: 100%; 27 | height: 40px; 28 | overflow: hidden; 29 | } 30 | 31 | #list { 32 | padding: 0; 33 | margin: 0; 34 | position: absolute; 35 | top: 40px; 36 | left: 0px; 37 | bottom: 0px; 38 | overflow: auto; 39 | width: 250px; 40 | _height:expression(document.body.clientHeight-40); 41 | } 42 | 43 | #log { 44 | padding: 0; 45 | margin: 0; 46 | position: absolute; 47 | top: 40px; 48 | left: 250px; 49 | right: 0px; 50 | bottom: 0px; 51 | overflow: auto; 52 | _height:expression(document.body.clientHeight-40); 53 | _width:expression(document.body.clientWidth-250); 54 | } 55 | 56 | 57 | 58 | /* -------------------- 59 | * @Decorations and colors 60 | */ 61 | * { 62 | padding: 0; 63 | margin: 0; 64 | font-family: "Lucida Grande", Helvetica, sans-serif; 65 | } 66 | 67 | li { 68 | list-style: none; 69 | } 70 | 71 | /* hiding subtitles */ 72 | h2 { 73 | display: none; 74 | } 75 | 76 | /* title section */ 77 | div#title { 78 | padding: 0em 0.5em; 79 | } 80 | 81 | div#title h1 { 82 | font-size: 1.5em; 83 | float: left; 84 | } 85 | 86 | div#title ul li { 87 | float: left; 88 | padding: 0.5em 0em 0.5em 0.75em; 89 | } 90 | 91 | div#title p { 92 | float:right; 93 | margin-right:1em; 94 | font-size: 0.75em; 95 | } 96 | 97 | /* spec container */ 98 | ul.specs { 99 | margin: 0.5em; 100 | } 101 | ul.specs li { 102 | margin-bottom: 0.1em; 103 | } 104 | 105 | /* spec title */ 106 | ul.specs li h3 { 107 | font-weight: bold; 108 | font-size: 0.75em; 109 | padding: 0.2em 1em; 110 | cursor: pointer; 111 | _cursor: hand; 112 | } 113 | 114 | /* example container */ 115 | ul.examples li { 116 | border-style: solid; 117 | border-width: 0px 0px 1px 5px; 118 | margin: 0.2em 0em 0.2em 1em; 119 | } 120 | 121 | /* example title */ 122 | ul.examples li h4 { 123 | font-weight: normal; 124 | font-size: 0.75em; 125 | margin-left: 1em; 126 | } 127 | 128 | pre.examples-code { 129 | margin: 0.5em 2em; 130 | padding: 0.5em; 131 | background: white; 132 | border: solid 1px #CCC; 133 | font-size: 10px; 134 | font-family: "Panic Sans", "Monaco", monospace !important; 135 | } 136 | 137 | /* example explaination */ 138 | ul.examples li div { 139 | padding: 1em 2em; 140 | font-size: 0.75em; 141 | } 142 | 143 | /* styles for ongoing, success, failure, error */ 144 | div.success, div.success a { 145 | color: #FFFFFF; 146 | background-color: #65C400; 147 | } 148 | 149 | ul.specs li.success h3, ul.specs li.success h3 a { 150 | color: #FFFFFF; 151 | background-color: #65C400; 152 | } 153 | 154 | ul.examples li.success, ul.examples li.success a { 155 | color: #3D7700; 156 | background-color: #DBFFB4; 157 | border-color: #65C400; 158 | } 159 | 160 | div.exception, div.exception a { 161 | color: #FFFFFF; 162 | background-color: #C20000; 163 | } 164 | 165 | ul.specs li.exception h3, ul.specs li.exception h3 a { 166 | color: #FFFFFF; 167 | background-color: #C20000; 168 | } 169 | 170 | ul.examples li.exception, ul.examples li.exception a { 171 | color: #C20000; 172 | background-color: #FFFBD3; 173 | border-color: #C20000; 174 | } 175 | 176 | div.ongoing, div.ongoing a { 177 | color: #000000; 178 | background-color: #FFFF80; 179 | } 180 | 181 | ul.specs li.ongoing h3, ul.specs li.ongoing h3 a { 182 | color: #000000; 183 | background-color: #FFFF80; 184 | } 185 | 186 | ul.examples li.ongoing, ul.examples li.ongoing a { 187 | color: #000000; 188 | background-color: #FFFF80; 189 | border-color: #DDDD00; 190 | } 191 | 192 | 193 | 194 | /* -------------------- 195 | * values 196 | */ 197 | .number_value, .string_value, .regexp_value, .boolean_value, .dom_value { 198 | font-family: monospace; 199 | color: blue; 200 | } 201 | .object_value, .array_value { 202 | line-height: 2em; 203 | padding: 0.1em 0.2em; 204 | margin: 0.1em 0; 205 | } 206 | .date_value { 207 | font-family: monospace; 208 | color: olive; 209 | } 210 | .undefined_value, .null_value { 211 | font-style: italic; 212 | color: blue; 213 | } 214 | .dom_attr_name { 215 | } 216 | .dom_attr_value { 217 | color: red; 218 | } 219 | .dom_path { 220 | font-size: 0.75em; 221 | color: gray; 222 | } 223 | strong { 224 | font-weight: normal; 225 | background-color: #FFC6C6; 226 | } 227 | -------------------------------------------------------------------------------- /Support/JSSpec/specs.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | var SubtleSlickParse_Specs = { 3 | 4 | 'should exist': function(){ 5 | value_of( SubtleSlickParse ).should_not_be_undefined(); 6 | }, 7 | 8 | 'should parse multiple selectors': function(){ 9 | var s = SubtleSlickParse('a, b, c'); 10 | value_of( s[0][0].tag ).should_be( 'a' ); 11 | value_of( s[1][0].tag ).should_be( 'b' ); 12 | value_of( s[2][0].tag ).should_be( 'c' ); 13 | }, 14 | 15 | 'should parse multiple selectors with class': function(){ 16 | var s = SubtleSlickParse('a.class, b.class, c.class'); 17 | value_of( s[0][0].tag ).should_be( 'a' ); 18 | value_of( s[1][0].tag ).should_be( 'b' ); 19 | value_of( s[2][0].tag ).should_be( 'c' ); 20 | value_of( s[0][0].classes[0] ).should_be( 'class' ); 21 | value_of( s[1][0].classes[0] ).should_be( 'class' ); 22 | value_of( s[2][0].classes[0] ).should_be( 'class' ); 23 | }, 24 | 25 | 'should parse tag names': function(){ 26 | for (var i=0; i < tags.length; i++) {var tag = tags[i]; 27 | value_of( SubtleSlickParse(tag)[0][0].tag ).should_be( tag ); 28 | } 29 | }, 30 | 31 | 'should parse tag names with combinators': function(){ 32 | for (var i=0; i < tags.length; i++) {var tag = tags[i]; 33 | for (var C=0; C < combinators.length; C++) {var combinator = combinators[C]; 34 | 35 | var s = SubtleSlickParse(tag +combinator+ tag); 36 | 37 | value_of( s[0][0].tag ).should_be( tag ); 38 | value_of( s[0][1].tag ).should_be( tag ); 39 | value_of( s[0][1].combinator ).should_be( combinator ); 40 | } 41 | } 42 | }, 43 | 44 | 'should transform odd to 2n+1 in pseudos nth arguments': function(){ 45 | var nths = [ 46 | {raw: ":nth-child(odd)", name: "nth-child", argument:"2n+1"}, 47 | {raw: ":nth-last-child(odd)", name: "nth-last-child", argument:"2n+1"}, 48 | {raw: ":nth-last-of-type(odd)", name:"nth-last-of-type", argument:"2n+1"}, 49 | {raw: ":nth-of-type(odd)", name: "nth-of-type", argument:"2n+1"}, 50 | 51 | {raw: ":nth-child(odd)", name:'nth-child', argument:"2n+1"}, 52 | {raw: ":nth-child(2n+1)", name:'nth-child', argument:"2n+1"}, 53 | {raw: ":nth-child(n)", name:'nth-child', argument:"n" }, 54 | ]; 55 | for (var i=0,s, N; N = nths[i]; i++){ 56 | s = SubtleSlickParse(N.raw); 57 | value_of( s[0][0].pseudos[0].name ).should_be( N.name ); 58 | value_of( s[0][0].pseudos[0].argument ).should_be( N.argument ); 59 | } 60 | }, 61 | 62 | 'should transform even to 2n in pseudo nth arguments': function(){ 63 | var nths = [ 64 | {raw: ":nth-child(even)", name: "nth-child", argument:"2n"}, 65 | {raw: ":nth-last-child(even)", name: "nth-last-child", argument:"2n"}, 66 | {raw: ":nth-last-of-type(even)", name:"nth-last-of-type", argument:"2n"}, 67 | {raw: ":nth-of-type(even)", name: "nth-of-type", argument:"2n"}, 68 | 69 | {raw:":nth-child(even)", name:'nth-child', argument:"2n" }, 70 | {raw:":nth-child(2n)" , name:'nth-child', argument:"2n" }, 71 | {raw:":nth-child(n)" , name:'nth-child', argument:"n" }, 72 | ]; 73 | for (var i=0,s, N; N = nths[i]; i++){ 74 | s = SubtleSlickParse(N.raw); 75 | value_of( s[0][0].pseudos[0].name ).should_be( N.name ); 76 | value_of( s[0][0].pseudos[0].argument ).should_be( N.argument ); 77 | } 78 | } 79 | , 80 | 'should parse :not(with quoted innards)': function(){ 81 | var s = SubtleSlickParse(":not()")[0][0]; 82 | value_of( s.pseudos.length ).should_be(1); 83 | value_of( s.pseudos[0].name ).should_be('not'); 84 | value_of( s.pseudos[0].argument ).should_be(""); 85 | 86 | s = SubtleSlickParse(':not([attr])')[0][0]; 87 | value_of( s.pseudos[0].argument ).should_be('[attr]'); 88 | 89 | s = SubtleSlickParse(':not([attr=])')[0][0]; 90 | value_of( s.pseudos[0].argument ).should_be('[attr=]'); 91 | 92 | s = SubtleSlickParse(":not([attr=''])")[0][0]; 93 | value_of( s.pseudos[0].argument ).should_be("[attr='']"); 94 | 95 | s = SubtleSlickParse(':not([attr=""])')[0][0]; 96 | value_of( s.pseudos[0].argument ).should_be('[attr=""]'); 97 | } 98 | , 99 | 'should parse :pseudo arguments as null': function(){ 100 | var s = SubtleSlickParse(":pseudo")[0][0]; 101 | value_of( s.pseudos.length ).should_be(1); 102 | value_of( s.pseudos[0].name ).should_be('pseudo'); 103 | value_of( s.pseudos[0].argument ).should_be_null(); 104 | } 105 | , 106 | 'should parse :pseudo() arguments as ""': function(){ 107 | var s = SubtleSlickParse(":pseudo()")[0][0]; 108 | value_of( s.pseudos.length ).should_be(1); 109 | value_of( s.pseudos[0].name ).should_be('pseudo'); 110 | value_of( s.pseudos[0].argument ).should_not_be_null(); 111 | value_of( s.pseudos[0].argument ).should_be(""); 112 | } 113 | , 114 | 'should parse attributes': function(){ } 115 | } 116 | 117 | var combinators = ' ,>,+,~'.split(','); 118 | var tags = 'a abbr acronym address applet area b base basefont bdo big blockquote br button caption center cite code col colgroup dd del dfn dir div dl dt em fieldset font form frame frameset h1 h2 h3 h4 h5 h6 head hr html i iframe img input ins isindex kbd label legend li link map menu meta noframes noscript object ol optgroup option p param pre q s samp script select small span strike strong style sub sup table tbody td textarea tfoot th thead title tr tt u ul var'.split(' '); 119 | var attribOperators = ' = != *= ^= $= ~= |='.split(' '); 120 | var attrs = 'attr html:lang fred-rocks'.split(' '); 121 | var vals = 'myValueOfDoom;"double";\'single\';();{};\'thing[]\';"thing[]"'.split(';'); 122 | 123 | vals: for (var vi=0; vi < vals.length; vi++) { 124 | var val = vals[vi]; 125 | attrs: for (var ai=0; ai < attrs.length; ai++) { 126 | var attr = attrs[ai]; 127 | operators: for (var i=0; i < attribOperators.length; i++) { 128 | var op = attribOperators[i]; 129 | var ATTRIBUTE = '['+ attr + op + (op&&val) +']'; 130 | 131 | SubtleSlickParse_Specs['should parse attributes: '+ ATTRIBUTE] = function(){ 132 | var s = SubtleSlickParse(ATTRIBUTE)[0][0]; 133 | 134 | value_of( s.attributes.length ).should_be( 1 ); 135 | value_of( s.attributes[0].name||'' ).should_be( attr ); 136 | value_of( s.attributes[0].operator||'' ).should_be( op ); 137 | if (!op) { 138 | value_of( s.attributes[0].operator ).should_be_undefined(); 139 | value_of( s.attributes[0].value ).should_be_undefined(); 140 | value_of( s.attributes[0].regexp ).should_be_null(); 141 | } else { 142 | value_of( s.attributes[0].value ).should_be( val.replace(/^["']|['"]$/g,'') ); 143 | value_of( s.attributes[0].regexp.toString() ).should_be( SubtleSlickParse.attribValueToRegex(op, op&&val.replace(/^["']|['"]$/g,'')).toString() ); 144 | } 145 | } 146 | } 147 | } 148 | } 149 | 150 | describe('SubtleSlickParse', SubtleSlickParse_Specs); 151 | })(); 152 | 153 | 154 | describe('MooTools-Slick', { 155 | 156 | 'should exist': function(){ 157 | value_of( slick ).should_not_be_undefined(); 158 | } 159 | , 160 | 'should match attributes': function(){ 161 | 162 | } 163 | }); 164 | -------------------------------------------------------------------------------- /Support/lib/current_word.rb: -------------------------------------------------------------------------------- 1 | # When creating a custom regex for Word.current_word, you need to keep a few things in mind: 2 | # The regex matches from your caret, so your caret position will always be the beginning of the line 3 | # Everything before your caret is reversed for the match, so the left of your caret will also match your caret position as ^ 4 | # You must use a capture group () for the text you're trying to match 5 | # You must use a capture group () for the text before/after your match 6 | # 7 | # EG: /(^[a-z]*)(.*$)/ 8 | # The first capture group in that regex will match from your caret out until it can't find anymore lowercase letters. 9 | # Then it'll match everything else in the line as the before/after match part. 10 | # You can currently only use a single regex to match before and after your caret. 11 | # 12 | # Since your regex matches what's before your caret in reverse, you'll have to reverse specific stuff in your regex, eg: 13 | # /(.*):/ wouldn't match 'color' in ` color: `, but /:(.*)/ would. 14 | # It's reversed you see 15 | # 16 | module Word 17 | def self.current_word(pat='a-zA-Z0-9', direction=:both) 18 | word = ENV['TM_SELECTED_TEXT'] 19 | 20 | if word.nil? or word.empty? 21 | line, col = ENV['TM_CURRENT_LINE'], ENV['TM_LINE_INDEX'].to_i 22 | 23 | if pat.kind_of? Regexp 24 | @reg = pat 25 | else 26 | @reg = /(^[#{pat}]*)(.*$\r?\n?)/ 27 | end 28 | 29 | left, before_match = *( line[0...col].reverse.match(@reg) ||[])[1..2] 30 | right, after_match = *( line[col..-1] .match(@reg) ||[])[1..2] 31 | 32 | (before_match||='').reverse! 33 | (left||='').reverse! 34 | 35 | # p before_match, left, right, after_match 36 | 37 | case direction 38 | when :both then word = [left, right].join('') 39 | when :left then word = left 40 | when :right then word = right 41 | when :hash then word = { 42 | :line => [before_match, left, right, after_match].join(''), 43 | :before_match => before_match, 44 | :left => left, 45 | :right => right, 46 | :after_match => after_match, 47 | } 48 | end 49 | end 50 | 51 | word 52 | end 53 | end 54 | 55 | if __FILE__ == $0 56 | require "test/unit" 57 | class TestWord < Test::Unit::TestCase 58 | # =begin 59 | def test_with_spaces 60 | ENV['TM_SELECTED_TEXT']= nil 61 | ENV['TM_CURRENT_LINE'] = <<-EOF 62 | BeforeAfter 63 | EOF 64 | ENV['TM_LINE_INDEX'] = '10' 65 | ENV['TM_TAB_SIZE'] = '2' 66 | assert_equal 'BeforeAfter', Word.current_word 67 | assert_equal 'Before', Word.current_word('a-zA-Z0-9',:left) 68 | assert_equal 'After', Word.current_word('a-zA-Z0-9',:right) 69 | 70 | assert_equal ' Before', Word.current_word(" a-zA-Z",:left) 71 | assert_equal 'After ', Word.current_word(" a-zA-Z",:right) 72 | end 73 | 74 | def test_with_tabs 75 | ENV['TM_SELECTED_TEXT']= nil 76 | ENV['TM_CURRENT_LINE'] = <<-EOF 77 | BeforeAfter 78 | EOF 79 | ENV['TM_LINE_INDEX'] = '8' 80 | ENV['TM_TAB_SIZE'] = '2' 81 | assert_equal 'BeforeAfter', Word.current_word 82 | assert_equal 'Before', Word.current_word('a-zA-Z0-9',:left) 83 | assert_equal 'After', Word.current_word('a-zA-Z0-9',:right) 84 | 85 | assert_equal "\t\tBefore", Word.current_word("\ta-zA-Z",:left) 86 | assert_equal "After\t\t", Word.current_word("\ta-zA-Z",:right) 87 | end 88 | 89 | def test_with_dash 90 | ENV['TM_SELECTED_TEXT']= nil 91 | ENV['TM_CURRENT_LINE'] = <<-EOF 92 | Before--After 93 | EOF 94 | ENV['TM_LINE_INDEX'] = '11' 95 | ENV['TM_TAB_SIZE'] = '2' 96 | assert_equal 'Before--After', Word.current_word('-a-zA-Z0-9') 97 | assert_equal 'Before-', Word.current_word('-a-zA-Z0-9',:left) 98 | assert_equal '-After', Word.current_word('-a-zA-Z0-9',:right) 99 | 100 | assert_equal 'Before-', Word.current_word("\ta-zA-Z\-",:left) 101 | end 102 | 103 | def test_hash_result 104 | ENV['TM_SELECTED_TEXT']= nil 105 | ENV['TM_CURRENT_LINE'] = <<-EOF 106 | before_match BeforeAfter after_match 107 | EOF 108 | ENV['TM_LINE_INDEX'] = '22' 109 | ENV['TM_TAB_SIZE'] = '2' 110 | 111 | word = Word.current_word("a-zA-Z",:hash) 112 | 113 | assert_equal ENV['TM_CURRENT_LINE'], "#{word[:line]}" 114 | assert_equal 'Before', word[:left] 115 | assert_equal 'After', word[:right] 116 | end 117 | =begin 118 | =end 119 | def test_both_result 120 | ENV['TM_SELECTED_TEXT']= nil 121 | ENV['TM_CURRENT_LINE'] = <<-EOF 122 | before_match BeforeAfter after_match 123 | EOF 124 | ENV['TM_LINE_INDEX'] = '22' 125 | ENV['TM_TAB_SIZE'] = '2' 126 | 127 | assert_equal 'BeforeAfter', Word.current_word("a-zA-Z",:both) 128 | end 129 | 130 | def test_should_support_custom_regex 131 | ENV['TM_SELECTED_TEXT']= nil 132 | ENV['TM_CURRENT_LINE'] = <<-EOF 133 | before_match BeforeAfter after_match 134 | EOF 135 | ENV['TM_LINE_INDEX'] = '22' 136 | ENV['TM_TAB_SIZE'] = '2' 137 | 138 | assert_equal '', Word.current_word(/[a-zA-Z]/,:both) # No match since no capture group was used! 139 | 140 | assert_equal 'ef', Word.current_word(/([a-z])/,:both) # Capture group, but only selecting a single caracter before and after the caret 141 | assert_equal 'eforefter', Word.current_word(/([a-z]+)/,:both) # Only lowercase characters 142 | assert_equal 'BeforeAfter', Word.current_word(/^([a-z]*)/i,:both) # Ignore case 143 | assert_equal 'BeforeAfter', Word.current_word(/^([a-zA-Z]*)/,:both) # Explicit case 144 | end 145 | 146 | def test_should_support_custom_regex_example1 147 | ENV['TM_SELECTED_TEXT']= nil 148 | ENV['TM_CURRENT_LINE'] = <<-EOF 149 | background-color: ; 150 | EOF 151 | ENV['TM_LINE_INDEX'] = '20' 152 | ENV['TM_TAB_SIZE'] = '2' 153 | 154 | assert_equal ' background-color: ', Word.current_word(/^(.*)/,:left) 155 | assert_equal 'background-color', Word.current_word(/:([-a-z]+)/,:left) 156 | end 157 | 158 | def test_should_support_custom_regex_example2 159 | ENV['TM_SELECTED_TEXT']= nil 160 | ENV['TM_CURRENT_LINE'] = <<-EOF 161 |

Lorem ipsum dolor sit amet

162 | EOF 163 | ENV['TM_LINE_INDEX'] = '44' 164 | ENV['TM_TAB_SIZE'] = '2' 165 | 166 | assert_equal %Q{\t

Lorem ipsum}, Word.current_word(/^(.*)/,:left) 167 | assert_equal 'Lorem ipsum dolor sit amet', Word.current_word(/^([^<>]+)/i,:both) 168 | 169 | # You have to reverse the regex since it's matching against the reverse of the text before the caret 170 | assert_equal 'p', Word.current_word(/([-:a-z]+) 2 | 3 | 4 | 5 | contactEmailRot13 6 | boyvivbhf@fhogyrTenqvrag.pbz 7 | contactName 8 | Thomas Aylott 9 | description 10 | Support for <a href="http://developer.mozilla.org/en/docs/About_JavaScript">JavaScript</a>. 11 | mainMenu 12 | 13 | items 14 | 15 | EB00F356-06C8-4267-8226-AA8F3943E5B1 16 | ------------------------------------ 17 | B4874A14-2491-465A-A349-61E4EBCF4700 18 | 44006EE0-7476-418F-B8F3-D98F21A22DF6 19 | ------------------------------------ 20 | C09ABCA9-7558-4385-8E29-10E42093D8B6 21 | ------------------------------------ 22 | EA26235D-2A24-4ED4-8BC2-5424B9E80CFF 23 | ------------------------------------ 24 | D2E6A1FE-2881-4754-B399-B65F61F29C2F 25 | 43F40EB6-5839-4BE8-99C8-4976D0534E5D 26 | 52090C49-D8B2-49A0-9597-80574354B3CD 27 | 6F601764-6A78-4857-A866-B617890F0DEC 28 | 28B33806-DCD4-4D5D-A422-B6041A6D9FAA 29 | ------------------------------------ 30 | 20E61C43-B81F-4FB9-9362-BFFE668EB9C9 31 | 36EC03E9-EFF4-479A-AB90-8DFA16800642 32 | 3DAB45A8-21C8-4581-809B-2D3C1E8FF1B0 33 | 092B230D-ACAB-4C38-B2E4-F7E013C7CDCB 34 | A1E0F62C-CE89-4F5A-93F9-B6F1A36A4784 35 | 36 | submenus 37 | 38 | 28B33806-DCD4-4D5D-A422-B6041A6D9FAA 39 | 40 | items 41 | 42 | 9655FB2D-E7ED-4189-9050-6F5B5D305975 43 | 523E9E93-6E43-4E2F-9F6F-465A8A24714E 44 | 45 | name 46 | Idioms 47 | 48 | 43F40EB6-5839-4BE8-99C8-4976D0534E5D 49 | 50 | items 51 | 52 | 5CAA9822-629C-4362-B02A-FCEF38C79BD5 53 | C1197E58-D065-4EDC-9BAB-EB41622C1630 54 | 9E0E3BCC-7F20-4D6B-891D-A44D6EC56E31 55 | 56 | name 57 | DOM 58 | 59 | 52090C49-D8B2-49A0-9597-80574354B3CD 60 | 61 | items 62 | 63 | 009A3E6C-FE3F-4A18-8759-2DC31F17BBE2 64 | 65 | name 66 | BOM 67 | 68 | 66778C58-CE08-4F21-AD36-562149AEEE80 69 | 70 | items 71 | 72 | F0E4FB6A-4878-48C6-A777-62438DF1E14F 73 | ------------------------------------ 74 | 73951799-AC15-40A6-81DB-EC051AB4A033 75 | 1717B5AE-209B-4548-9155-9E88A7230C1C 76 | ------------------------------------ 77 | 77065D69-742A-4FF0-9A41-AD211DFBE72F 78 | 79 | name 80 | Function 81 | 82 | 6F601764-6A78-4857-A866-B617890F0DEC 83 | 84 | items 85 | 86 | E1B2FC98-AF98-4392-8069-C82C2C192617 87 | 603A6D98-A136-4766-828B-C39178AB8003 88 | 89 | name 90 | Special 91 | 92 | 7699AC1A-80AC-4120-A375-9371D1591F79 93 | 94 | items 95 | 96 | 12767C79-C781-4BFC-8BA3-D108DB14292D 97 | ------------------------------------ 98 | F19F3732-39A7-48EC-A72B-A8F477A01795 99 | 31964029-9D71-4ADC-8213-DFE5C4E222B3 100 | ------------------------------------ 101 | 6976CD86-07BB-4419-BE5E-10F60944DB1A 102 | 011C4681-FBEC-4891-9326-3DECFCDED6D6 103 | C207B7C3-5597-4873-8AAD-C46FB8842AF2 104 | 9BF3315C-88FF-46A1-89E1-9A5E9EAC78D0 105 | 92D6EE80-615E-45B7-B2E2-FF5C200A8478 106 | ------------------------------------ 107 | 3F4AB53B-210C-4E0C-8D04-12192DECC3D1 108 | ------------------------------------ 109 | 65AAF33F-7706-4FC0-B5E0-E9AABEF0731E 110 | 77750C34-3335-4766-900D-FFFF412DB7F5 111 | 112 | name 113 | Control 114 | 115 | D2E6A1FE-2881-4754-B399-B65F61F29C2F 116 | 117 | items 118 | 119 | 7699AC1A-80AC-4120-A375-9371D1591F79 120 | EC690F46-1906-4F55-9089-3C2929D5BB69 121 | 66778C58-CE08-4F21-AD36-562149AEEE80 122 | 123 | name 124 | Core 125 | 126 | EC690F46-1906-4F55-9089-3C2929D5BB69 127 | 128 | items 129 | 130 | DC8B46FB-8ADA-45EA-8F36-94C807A0D302 131 | ------------------------------------ 132 | 2F96136B-0193-42F5-90FC-B6F456A3AD77 133 | 134 | name 135 | Language 136 | 137 | 138 | 139 | name 140 | JavaScript — SubtleGradient 141 | ordering 142 | 143 | EB00F356-06C8-4267-8226-AA8F3943E5B1 144 | 93E017CC-6F27-11D9-90EB-000D93589AF6 145 | 0D2D03B9-F18B-4D9D-A960-716FDEC35331 146 | BC062860-3346-4D3B-8421-C5543F83D11F 147 | CB7ACED9-DA02-4A85-A75B-D9D8527CF5C9 148 | C09ABCA9-7558-4385-8E29-10E42093D8B6 149 | EC7B0B43-3ABA-4074-8BFC-366469F8F07D 150 | C8A09756-FE14-461A-A3FF-D2D3A18CCF53 151 | 78F5005B-82AE-4BF0-9E1B-407E32FF796B 152 | 44006EE0-7476-418F-B8F3-D98F21A22DF6 153 | B4874A14-2491-465A-A349-61E4EBCF4700 154 | 3DAB45A8-21C8-4581-809B-2D3C1E8FF1B0 155 | 092B230D-ACAB-4C38-B2E4-F7E013C7CDCB 156 | EA26235D-2A24-4ED4-8BC2-5424B9E80CFF 157 | 77065D69-742A-4FF0-9A41-AD211DFBE72F 158 | F0E4FB6A-4878-48C6-A777-62438DF1E14F 159 | C1197E58-D065-4EDC-9BAB-EB41622C1630 160 | 5CAA9822-629C-4362-B02A-FCEF38C79BD5 161 | 2F96136B-0193-42F5-90FC-B6F456A3AD77 162 | 19479745-D001-4EB3-8A66-6679C2273C58 163 | 73951799-AC15-40A6-81DB-EC051AB4A033 164 | 1717B5AE-209B-4548-9155-9E88A7230C1C 165 | 20E61C43-B81F-4FB9-9362-BFFE668EB9C9 166 | 36EC03E9-EFF4-479A-AB90-8DFA16800642 167 | AC6FAAC0-07C4-4DB3-B493-28A64B96A258 168 | B8541849-2B39-440E-928F-E3C55E8D1BED 169 | A67A8BD9-A951-406F-9175-018DD4B52FD1 170 | E6EB7CC8-04E8-43A9-93B2-BC9EF5BA862B 171 | 73557394-4F0F-4DD3-8029-EEE8201AC7F5 172 | 51841DDB-C2A4-461C-A8AB-6C124AD50EAE 173 | F19F3732-39A7-48EC-A72B-A8F477A01795 174 | 31964029-9D71-4ADC-8213-DFE5C4E222B3 175 | 6976CD86-07BB-4419-BE5E-10F60944DB1A 176 | 011C4681-FBEC-4891-9326-3DECFCDED6D6 177 | 6DC06A4E-E151-467F-9CF7-FA61DD540D6E 178 | 814C024D-3431-48B5-8B34-4BDC29DCB277 179 | C207B7C3-5597-4873-8AAD-C46FB8842AF2 180 | 9BF3315C-88FF-46A1-89E1-9A5E9EAC78D0 181 | 92D6EE80-615E-45B7-B2E2-FF5C200A8478 182 | 3F4AB53B-210C-4E0C-8D04-12192DECC3D1 183 | 009A3E6C-FE3F-4A18-8759-2DC31F17BBE2 184 | 9E0E3BCC-7F20-4D6B-891D-A44D6EC56E31 185 | E1B2FC98-AF98-4392-8069-C82C2C192617 186 | 603A6D98-A136-4766-828B-C39178AB8003 187 | 12767C79-C781-4BFC-8BA3-D108DB14292D 188 | 523E9E93-6E43-4E2F-9F6F-465A8A24714E 189 | 65AAF33F-7706-4FC0-B5E0-E9AABEF0731E 190 | 77750C34-3335-4766-900D-FFFF412DB7F5 191 | 9655FB2D-E7ED-4189-9050-6F5B5D305975 192 | B914AE71-B1B3-48A1-A4AE-6E5F9425C3B6 193 | 75783526-1546-4967-B37B-5CDA089593B3 194 | 2831C11D-1907-4BC1-9A4D-BEE70EAFD0CF 195 | ED5F2161-F404-45EA-A8CD-5A4C0CB18DFF 196 | 1C062C73-8798-4794-8F4A-223012E42A07 197 | C85B5F76-4CA8-47C2-B6E1-8A324D6E3B61 198 | 51EC03B2-4E2B-49B0-A843-6BEB7281BE98 199 | E6827B03-693B-4C9E-B288-D7EEF36D6EF1 200 | BBDBA2F8-0C0D-41AC-97F2-EB3A09D9044C 201 | F035D69A-8987-459C-8425-090752784BC4 202 | 6F3570B1-89AF-43BD-BA8B-BA3B6DF4A10D 203 | E39E4E5A-32FC-4BD5-91D8-6A8B6A5AEB2F 204 | 7B9AEFCC-B450-416D-8527-430FE2A08568 205 | AD506BEC-B33C-4168-A900-0A4D386A4B05 206 | 0EC93ADD-A849-4951-9235-B51E720E31FE 207 | B7D324A1-E600-4014-8CDF-B73BA554921A 208 | 4C6EDB43-3E2E-411B-A016-13C135C59833 209 | FB90E487-9B42-4512-9036-01CD3CD8B04B 210 | DC8B46FB-8ADA-45EA-8F36-94C807A0D302 211 | 834BC727-6B31-4073-A161-4823227219EF 212 | 3CEA49B2-A5C5-405C-82E2-B8B668877C37 213 | D99FC647-570A-48E2-B6FB-147D432346BB 214 | 9F13050B-61FC-4A9A-9A91-F2CD8529A5FE 215 | BF6200B3-9E7A-442D-873D-73FBF34657F9 216 | 5AE2BB5C-AF4F-4529-8FAE-5E0FCEE69872 217 | 218 | uuid 219 | 5B49710E-9A49-4BE0-BD45-6A9CB683C191 220 | 221 | 222 | -------------------------------------------------------------------------------- /Commands/Reformat Document : Selection.tmCommand: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | beforeRunningCommand 6 | nop 7 | command 8 | #!/usr/bin/env php 9 | <?php 10 | /* 11 | 12 | JS Beautifier 13 | 14 | (c) 2007, Einars "elfz" Lielmanis 15 | 16 | http://elfz.laacz.lv/beautify/ 17 | 18 | You are free to use this in any way you want, in case you find this useful or working for you. 19 | 20 | Ported with permission to TextMate by Ale Muñoz. 21 | 22 | (Based on v35 of JS Beautifier) 23 | 24 | */ 25 | 26 | error_reporting(E_ALL); 27 | ini_set('display_errors', 'on'); 28 | 29 | 30 | $n = 1; 31 | define('IN_EXPR', ++$n); 32 | define('IN_BLOCK', ++$n); 33 | 34 | 35 | define('TK_UNKNOWN', ++$n); 36 | define('TK_WORD', ++$n); 37 | define('TK_START_EXPR', ++$n); 38 | define('TK_END_EXPR', ++$n); 39 | define('TK_START_BLOCK', ++$n); 40 | define('TK_END_BLOCK', ++$n); 41 | define('TK_END_COMMAND', ++$n); 42 | define('TK_EOF', ++$n); 43 | define('TK_STRING', ++$n); 44 | 45 | define('TK_BLOCK_COMMENT', ++$n); 46 | define('TK_COMMENT', ++$n); 47 | 48 | define('TK_OPERATOR', ++$n); 49 | 50 | // internal flags 51 | define('PRINT_NONE', ++$n); 52 | define('PRINT_SPACE', ++$n); 53 | define('PRINT_NL', ++$n); 54 | 55 | 56 | function js_beautify($js_source_text, $tab_size = 4) 57 | { 58 | global $output, $token_text, $last_type, $last_text, $in, $ins, $indent, $tab_string, $is_last_nl; 59 | 60 | global $input, $input_length; 61 | 62 | $tab_string = str_repeat(' ', $tab_size); 63 | 64 | $input = $js_source_text; 65 | $input_length = strlen($input); 66 | 67 | $last_word = ''; // last TK_WORD passed 68 | $last_type = TK_START_EXPR; // last token type 69 | $last_text = ''; // last token text 70 | $output = ''; 71 | 72 | $is_last_nl = true; // was the last character written a newline? 73 | 74 | // words which should always start on new line. 75 | // simple hack for cases when lines aren't ending with semicolon. 76 | // feel free to tell me about the ones that need to be added. 77 | $line_starters = explode(',', 'continue,try,throw,return,var,if,switch,case,default,for,while,break,function'); 78 | 79 | // states showing if we are currently in expression (i.e. "if" case) - IN_EXPR, or in usual block (like, procedure), IN_BLOCK. 80 | // some formatting depends on that. 81 | $in = IN_BLOCK; 82 | $ins = array($in); 83 | 84 | 85 | $indent = 0; 86 | $pos = 0; // parser position 87 | $in_case = false; // flag for parser that case/default has been processed, and next colon needs special attention 88 | 89 | while (true) { 90 | list($token_text, $token_type) = get_next_token($pos); 91 | if ($token_type == TK_EOF) { 92 | break; 93 | } 94 | 95 | // $output .= " [$token_type:$last_type]"; 96 | 97 | switch($token_type) { 98 | 99 | case TK_START_EXPR: 100 | 101 | in(IN_EXPR); 102 | if ($last_type == TK_END_EXPR or $last_type == TK_START_EXPR) { 103 | // do nothing on (( and )( and ][ and ]( .. 104 | } elseif ($last_type != TK_WORD and $last_type != TK_OPERATOR) { 105 | space(); 106 | } elseif (in_array($last_word, $line_starters) and $last_word != 'function') { 107 | space(); 108 | } 109 | token(); 110 | break; 111 | 112 | case TK_END_EXPR: 113 | 114 | token(); 115 | in_pop(); 116 | break; 117 | 118 | case TK_START_BLOCK: 119 | 120 | in(IN_BLOCK); 121 | if ($last_type != TK_OPERATOR and $last_type != TK_START_EXPR) { 122 | if ($last_type == TK_START_BLOCK) { 123 | nl(); 124 | } else { 125 | space(); 126 | } 127 | } 128 | token(); 129 | indent(); 130 | break; 131 | 132 | case TK_END_BLOCK: 133 | 134 | if ($last_type == TK_END_EXPR) { 135 | unindent(); 136 | nl(false); 137 | } elseif ($last_type == TK_END_BLOCK) { 138 | unindent(); 139 | nl(false); 140 | } elseif ($last_type == TK_START_BLOCK) { 141 | // nothing 142 | unindent(); 143 | } else { 144 | unindent(); 145 | nl(false); 146 | } 147 | token(); 148 | in_pop(); 149 | break; 150 | 151 | case TK_WORD: 152 | 153 | if ($token_text == 'case' or $token_text == 'default') { 154 | if ($last_text == ':') { 155 | // switch cases following one another 156 | remove_indent(); 157 | } else { 158 | $indent--; 159 | nl(); 160 | $indent++; 161 | } 162 | token(); 163 | $in_case = true; 164 | break; 165 | } 166 | 167 | $prefix = PRINT_NONE; 168 | if ($last_type == TK_END_BLOCK) { 169 | if (!in_array(strtolower($token_text), array('else', 'catch', 'finally'))) { 170 | $prefix = PRINT_NL; 171 | } else { 172 | $prefix = PRINT_SPACE; 173 | space(); 174 | } 175 | } elseif ($last_type == TK_END_COMMAND && $in == IN_BLOCK) { 176 | $prefix = PRINT_NL; 177 | } elseif ($last_type == TK_END_COMMAND && $in == IN_EXPR) { 178 | $prefix = PRINT_SPACE; 179 | } elseif ($last_type == TK_WORD) { 180 | if ($last_word == 'else') { // else if 181 | $prefix = PRINT_SPACE; 182 | } else { 183 | $prefix = PRINT_SPACE; 184 | } 185 | } elseif ($last_type == TK_START_BLOCK) { 186 | $prefix = PRINT_NL; 187 | } elseif ($last_type == TK_END_EXPR) { 188 | space(); 189 | } 190 | 191 | if (in_array($token_text, $line_starters) or $prefix == PRINT_NL) { 192 | 193 | if ($last_text == 'else') { 194 | // no need to force newline on else break 195 | // DONOTHING 196 | space(); 197 | } elseif (($last_type == TK_START_EXPR or $last_text == '=') and $token_text == 'function') { 198 | // no need to force newline on 'function': (function 199 | // DONOTHING 200 | } else 201 | if ($last_type != TK_END_EXPR) { 202 | if (($last_type != TK_START_EXPR or $token_text != 'var') and $last_text != ':') { 203 | // no need to force newline on 'var': for (var x = 0...) 204 | if ($token_text == 'if' and $last_type == TK_WORD and $last_word == 'else') { 205 | // no newline for } else if { 206 | space(); 207 | } else { 208 | nl(); 209 | } 210 | } 211 | } 212 | } elseif ($prefix == PRINT_SPACE) { 213 | space(); 214 | } 215 | token(); 216 | $last_word = strtolower($token_text); 217 | break; 218 | 219 | case TK_END_COMMAND: 220 | 221 | token(); 222 | break; 223 | 224 | case TK_STRING: 225 | 226 | if ($last_type == TK_START_BLOCK or $last_type == TK_END_BLOCK) { 227 | nl(); 228 | } elseif ($last_type == TK_WORD) { 229 | space(); 230 | } 231 | token(); 232 | break; 233 | 234 | case TK_OPERATOR: 235 | $start_delim = true; 236 | $end_delim = true; 237 | 238 | if ($token_text == ':' and $in_case) { 239 | token(); // colon really asks for separate treatment 240 | nl(); 241 | $expecting_case = false; 242 | break; 243 | } 244 | 245 | $in_case = false; 246 | 247 | 248 | 249 | if ($token_text == ',') { 250 | if ($last_type == TK_END_BLOCK) { 251 | token(); 252 | nl(); 253 | } else { 254 | if ($in == IN_BLOCK) { 255 | token(); 256 | nl(); 257 | } else { 258 | token(); 259 | space(); 260 | } 261 | } 262 | break; 263 | } elseif ($token_text == '--' or $token_text == '++') { // unary operators special case 264 | if ($last_text == ';') { 265 | // space for (;; ++i) 266 | $start_delim = true; 267 | $end_delim = false; 268 | } else { 269 | $start_delim = false; 270 | $end_delim = false; 271 | } 272 | } elseif ($token_text == '!' and $last_type == TK_START_EXPR) { 273 | // special case handling: if (!a) 274 | $start_delim = false; 275 | $end_delim = false; 276 | } elseif ($last_type == TK_OPERATOR) { 277 | $start_delim = false; 278 | $end_delim = false; 279 | } elseif ($last_type == TK_END_EXPR) { 280 | $start_delim = true; 281 | $end_delim = true; 282 | } elseif ($token_text == '.') { 283 | // decimal digits or object.property 284 | $start_delim = false; 285 | $end_delim = false; 286 | 287 | } elseif ($token_text == ':') { 288 | // zz: xx 289 | // can't differentiate ternary op, so for now it's a ? b: c; without space before colon 290 | $start_delim = false; 291 | } 292 | if ($start_delim) { 293 | space(); 294 | } 295 | 296 | token(); 297 | 298 | if ($end_delim) { 299 | space(); 300 | } 301 | break; 302 | 303 | case TK_BLOCK_COMMENT: 304 | 305 | nl(); 306 | token(); 307 | nl(); 308 | break; 309 | 310 | case TK_COMMENT: 311 | 312 | //if ($last_type != TK_COMMENT) { 313 | nl(); 314 | //} 315 | token(); 316 | nl(); 317 | break; 318 | 319 | case TK_UNKNOWN: 320 | token(); 321 | break; 322 | } 323 | 324 | if ($token_type != TK_COMMENT) { 325 | $last_type = $token_type; 326 | $last_text = $token_text; 327 | } 328 | } 329 | 330 | // clean empty lines from redundant spaces 331 | $output = preg_replace('/^ +$/m', '', $output); 332 | 333 | return $output; 334 | } 335 | 336 | 337 | 338 | 339 | function nl($ignore_repeated = true) 340 | { 341 | global $indent, $output, $tab_string, $is_last_nl; 342 | 343 | if ($output == '') return; // no newline on start of file 344 | 345 | if ($ignore_repeated and $is_last_nl) { 346 | return; 347 | } 348 | 349 | $is_last_nl = true; 350 | 351 | $output .= "\n" . str_repeat($tab_string, $indent); 352 | } 353 | 354 | 355 | // hack for correct multiple newline handling 356 | function safe_nl($newlines = 1) 357 | { 358 | global $output; 359 | if ($newlines) { 360 | $output .= str_repeat("\n", $newlines - 1); 361 | } 362 | nl(); 363 | } 364 | 365 | 366 | function space() 367 | { 368 | global $output, $is_last_nl; 369 | 370 | $is_last_nl = false; 371 | 372 | if ($output and substr($output, -1) != ' ') { // prevent occassional duplicate space 373 | $output .= ' '; 374 | } 375 | } 376 | 377 | 378 | function token() 379 | { 380 | global $token_text, $output, $is_last_nl; 381 | $output .= $token_text; 382 | $is_last_nl = false; 383 | } 384 | 385 | function indent() 386 | { 387 | global $indent; 388 | $indent ++; 389 | } 390 | 391 | 392 | function unindent() 393 | { 394 | global $indent; 395 | if ($indent) { 396 | $indent --; 397 | } 398 | } 399 | 400 | 401 | function remove_indent() 402 | { 403 | global $tab_string, $output; 404 | $tab_string_len = strlen($tab_string); 405 | if (substr($output, -$tab_string_len) == $tab_string) { 406 | $output = substr($output, 0, -$tab_string_len); 407 | } 408 | } 409 | 410 | 411 | function in($where) 412 | { 413 | global $ins, $in; 414 | array_push($ins, $in); 415 | $in = $where; 416 | } 417 | 418 | 419 | function in_pop() 420 | { 421 | global $ins, $in; 422 | $in = array_pop($ins); 423 | } 424 | 425 | 426 | 427 | function make_array($str) 428 | { 429 | $res = array(); 430 | for ($i = 0; $i < strlen($str); $i++) { 431 | $res[] = $str[$i]; 432 | } 433 | return $res; 434 | } 435 | 436 | 437 | 438 | function get_next_token(&$pos) 439 | { 440 | global $last_type, $last_text; 441 | global $whitespace, $wordchar, $punct; 442 | global $input, $input_length, $is_last_nl; 443 | 444 | 445 | if (!$whitespace) $whitespace = make_array("\n\r\t "); 446 | if (!$wordchar) $wordchar = make_array('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$'); 447 | if (!$punct) $punct = explode(' ', '+ - * / % & ++ -- = += -= *= /= %= == === != !== > < >= <= >> << >>> <<< >>= <<= && &= | || ! !! , : ? ^ ^= |='); 448 | 449 | $n_newlines = 0; 450 | do { 451 | if ($pos >= $input_length) { 452 | return array('', TK_EOF); 453 | } 454 | $c = $input[$pos]; 455 | $pos += 1; 456 | if ($c == "\n") { 457 | $n_newlines += 1; 458 | } 459 | } while (in_array($c, $whitespace)); 460 | 461 | if ($n_newlines) { 462 | safe_nl($n_newlines); 463 | } 464 | 465 | if (in_array($c, $wordchar)) { 466 | if ($pos < $input_length) { 467 | while (in_array($input[$pos], $wordchar)) { 468 | $c .= $input[$pos]; 469 | $pos += 1; 470 | if ($pos == $input_length) break; 471 | } 472 | } 473 | if ($c == 'in') { // hack for 'in' operator 474 | return array($c, TK_OPERATOR); 475 | } 476 | return array($c, TK_WORD); 477 | } 478 | 479 | if ($c == '(' || $c == '[') { 480 | return array($c, TK_START_EXPR); 481 | } 482 | 483 | if ($c == ')' || $c == ']') { 484 | return array($c, TK_END_EXPR); 485 | } 486 | 487 | if ($c == '{') { 488 | return array($c, TK_START_BLOCK); 489 | } 490 | 491 | if ($c == '}') { 492 | return array($c, TK_END_BLOCK); 493 | } 494 | 495 | if ($c == ';') { 496 | return array($c, TK_END_COMMAND); 497 | } 498 | 499 | if ($c == '/') { 500 | // peek for comment /* ... */ 501 | if ($input[$pos] == '*') { 502 | $comment = ''; 503 | $pos += 1; 504 | if ($pos < $input_length){ 505 | while (!($input[$pos] == '*' && isset($input[$pos + 1]) && $input[$pos + 1] == '/') && $pos < $input_length) { 506 | $comment .= $input[$pos]; 507 | $pos += 1; 508 | if ($pos >= $input_length) break; 509 | } 510 | } 511 | $pos +=2; 512 | return array("/*$comment*/", TK_BLOCK_COMMENT); 513 | } 514 | // peek for comment // ... 515 | if ($input[$pos] == '/') { 516 | $comment = $c; 517 | while ($input[$pos] != "\x0d" && $input[$pos] != "\x0a") { 518 | $comment .= $input[$pos]; 519 | $pos += 1; 520 | if ($pos >= $input_length) break; 521 | } 522 | $pos += 1; 523 | return array($comment, TK_COMMENT); 524 | } 525 | 526 | } 527 | 528 | if ($c == "'" || // string 529 | $c == '"' || // string 530 | ($c == '/' && 531 | (($last_type == TK_WORD and $last_text == 'return') or ($last_type == TK_START_EXPR || $last_type == TK_END_BLOCK || $last_type == TK_OPERATOR || $last_type == TK_EOF || $last_type == TK_END_COMMAND)))) { // regexp 532 | $sep = $c; 533 | $c = ''; 534 | $esc = false; 535 | 536 | if ($pos < $input_length) { 537 | 538 | while ($esc || $input[$pos] != $sep) { 539 | $c .= $input[$pos]; 540 | if (!$esc) { 541 | $esc = $input[$pos] == '\\'; 542 | } else { 543 | $esc = false; 544 | } 545 | $pos += 1; 546 | if ($pos >= $input_length) break; 547 | } 548 | 549 | } 550 | 551 | $pos += 1; 552 | if ($last_type == TK_END_COMMAND) { 553 | nl(); 554 | } 555 | return array($sep . $c . $sep, TK_STRING); 556 | } 557 | 558 | if (in_array($c, $punct)) { 559 | while (in_array($c . $input[$pos], $punct)) { 560 | $c .= $input[$pos]; 561 | $pos += 1; 562 | if ($pos >= $input_length) break; 563 | } 564 | return array($c, TK_OPERATOR); 565 | } 566 | 567 | return array($c, TK_UNKNOWN); 568 | } 569 | 570 | if (isset($_ENV['TM_SELECTED_TEXT'])) { 571 | $input = get_magic_quotes_gpc() ? stripslashes($_ENV['TM_SELECTED_TEXT']) : $_ENV['TM_SELECTED_TEXT']; 572 | } else { 573 | $input = file_get_contents('php://stdin'); 574 | } 575 | 576 | print js_beautify($input); 577 | ?> 578 | input 579 | selection 580 | keyEquivalent 581 | ^H 582 | name 583 | Reformat Document / Selection 584 | output 585 | replaceSelectedText 586 | scope 587 | source.js 588 | uuid 589 | 36EC03E9-EFF4-479A-AB90-8DFA16800642 590 | 591 | 592 | -------------------------------------------------------------------------------- /Syntaxes/JavaScript.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | foldingStartMarker 6 | //\s*<[^/]|(?x)^ 7 | # Yes *+ Open ( Blank |Comments | (No Paren | String) | String | (Nested Parens ) )*+ 8 | (?> \g<yesS>*+ \[ (?<yesS> (?!.) |//.*+|/\*((?!\*/).)++(\*/|$)|(^)((?!/\*).)*(\*/)| (?<noS>[^\[\]'"/]) | (?<str> '(\\'|[^'])*+' | "(\\"|[^"])*+" | /(\\/|[^/])*+/) | (?<squar> \[ \g<yesS>*+ \] ) )*+ 9 | | \g<yesR>*+ \( (?<yesR> (?!.) |//.*+|/\*((?!\*/).)++(\*/|$)|(^)((?!/\*).)*(\*/)| (?<noR>[^\(\)'"/]) | \g<str> | (?<round> \( \g<yesR>*+ \) ) )*+ 10 | | \g<yesC>*+ \{ (?<yesC> (?!.) |//.*+|/\*((?!\*/).)++(\*/|$)|(^)((?!/\*).)*(\*/)| (?<noC>[^\{\}'"/]) | \g<str> | (?<curly> \{ \g<yesC>*+ \} ) )*+ 11 | )$ 12 | foldingStopMarker 13 | //\s*</|(?x)^ 14 | # ( Blank |Comments | (No Paren | String) | String | (Nested Parens ) )*+ Close Yes *+ 15 | (?> (?<yesS> (?!.) |//.*+|/\*((?!\*/).)++(\*/|$)|(^)((?!/\*).)*(\*/)| (?<noS>[^\[\]'"/]) | (?<str> '(\\'|[^'])*+' | "(\\"|[^"])*+" | /(\\/|[^/])*+/) | (?<squar> \[ \g<yesS>*+ \] ) )*+ \] \g<yesS>*+ 16 | | (?<yesR> (?!.) |//.*+|/\*((?!\*/).)++(\*/|$)|(^)((?!/\*).)*(\*/)| (?<noR>[^\(\)'"/]) | \g<str> | (?<round> \( \g<yesR>*+ \) ) )*+ \) \g<yesR>*+ 17 | | (?<yesC> (?!.) |//.*+|/\*((?!\*/).)++(\*/|$)|(^)((?!/\*).)*(\*/)| (?<noC>[^\{\}'"/]) | \g<str> | (?<curly> \{ \g<yesC>*+ \} ) )*+ \} \g<yesC>*+ 18 | )$ 19 | keyEquivalent 20 | ^~J 21 | name 22 | JavaScript 23 | patterns 24 | 25 | 26 | include 27 | #brackets 28 | 29 | 30 | begin 31 | (?x) 32 | (function) 33 | (?= 34 | (?:\s+ (?:[_$a-zA-Z][_$\w]*))? \s* # The function name 35 | \([^)]*\) # The properties that the function accepts 36 | ) 37 | beginCaptures 38 | 39 | 1 40 | 41 | name 42 | storage.type.function.js 43 | 44 | 45 | comment 46 | function(one,two,...)\n?{...} 47 | end 48 | (?<=})(\s*\n)? 49 | name 50 | meta.function.js 51 | patterns 52 | 53 | 54 | include 55 | #function-params 56 | 57 | 58 | include 59 | #leading-space 60 | 61 | 62 | include 63 | #function-block 64 | 65 | 66 | 67 | 68 | include 69 | source.js 70 | 71 | 72 | captures 73 | 74 | 1 75 | 76 | name 77 | entity.name.function.js 78 | 79 | 2 80 | 81 | name 82 | meta.group.braces.round.function.arguments.js 83 | 84 | 3 85 | 86 | name 87 | punctuation.section.scope.round.js 88 | 89 | 90 | match 91 | (?x)(?<= \. ) ([_$a-zA-Z][_$\w]*) ((\( \s* \))) 92 | name 93 | meta.function-call.method.without-arguments.js 94 | 95 | 96 | captures 97 | 98 | 1 99 | 100 | name 101 | entity.name.function.js 102 | 103 | 104 | match 105 | (?x)(?<= \. ) ([_$a-zA-Z][_$\w]*) (?=\() 106 | name 107 | meta.function-call.method.with-arguments.js 108 | 109 | 110 | captures 111 | 112 | 1 113 | 114 | name 115 | entity.name.function.js 116 | 117 | 2 118 | 119 | name 120 | meta.group.braces.round.function.arguments.js 121 | 122 | 3 123 | 124 | name 125 | punctuation.section.scope.js 126 | 127 | 128 | match 129 | (?x)(?<! [_$\w] ) ([_$a-zA-Z][_$\w]*) ((\( \s* \))) 130 | name 131 | meta.function-call.static.without-arguments.js 132 | 133 | 134 | captures 135 | 136 | 1 137 | 138 | name 139 | entity.name.function.js 140 | 141 | 142 | match 143 | (?x)(?<! [_$\w] ) ([_$a-zA-Z][_$\w]*) (?=\() 144 | name 145 | meta.function-call.static.with-arguments.js 146 | 147 | 148 | match 149 | (?x)(?<= \. ) ([_$a-zA-Z][_$\w]*) 150 | name 151 | variable.other.property.js 152 | 153 | 154 | match 155 | (?x) 156 | (?<! [\._$a-zA-Z] ) [_$] [_$\w]* 157 | |(?<= var \s ) [_$a-zA-Z] [_$\w]* 158 | |(?<! [_$\w] ) [_$a-zA-Z] [_$\w]* (?=( 159 | \[ 160 | |\s*(&|\*|\-|\+|~|=|!=|<|>|!|\||/=|%=|\^=) 161 | )) 162 | name 163 | variable.other.js 164 | 165 | 166 | include 167 | #leading-space 168 | 169 | 170 | repository 171 | 172 | brackets 173 | 174 | patterns 175 | 176 | 177 | begin 178 | (\{) 179 | captures 180 | 181 | 1 182 | 183 | name 184 | punctuation.section.scope.curly.js 185 | 186 | 2 187 | 188 | name 189 | punctuation.separator.objects.js 190 | 191 | 192 | end 193 | (\})(,)?\s* 194 | name 195 | meta.group.braces.curly 196 | patterns 197 | 198 | 199 | include 200 | #object-properties 201 | 202 | 203 | include 204 | $base 205 | 206 | 207 | 208 | 209 | begin 210 | (\()(?!\)) 211 | captures 212 | 213 | 1 214 | 215 | name 216 | punctuation.section.scope.round.js 217 | 218 | 219 | disabled 220 | 1 221 | end 222 | (\)) 223 | name 224 | meta.group.braces.round 225 | patterns 226 | 227 | 228 | include 229 | $base 230 | 231 | 232 | 233 | 234 | begin 235 | (\[)(?!\]) 236 | captures 237 | 238 | 1 239 | 240 | name 241 | punctuation.section.scope.square.js 242 | 243 | 244 | end 245 | (\]) 246 | name 247 | meta.group.braces.square 248 | patterns 249 | 250 | 251 | include 252 | $base 253 | 254 | 255 | 256 | 257 | 258 | function-block 259 | 260 | begin 261 | ({) 262 | captures 263 | 264 | 1 265 | 266 | name 267 | punctuation.section.function.js 268 | 269 | 2 270 | 271 | name 272 | punctuation.terminator.statement.js 273 | 274 | 275 | end 276 | (}) 277 | patterns 278 | 279 | 280 | include 281 | $base 282 | 283 | 284 | 285 | function-params 286 | 287 | begin 288 | (?x) 289 | (?<=function) # Must come after the word "function" 290 | (?:\s+ ([_$a-zA-Z][_$\w]*))? # Mtch the name if it exists 291 | \s* (\() 292 | beginCaptures 293 | 294 | 1 295 | 296 | name 297 | entity.name.function.js 298 | 299 | 2 300 | 301 | name 302 | punctuation.definition.parameters.js 303 | 304 | 305 | end 306 | \) 307 | endCaptures 308 | 309 | 0 310 | 311 | name 312 | punctuation.definition.parameters.js 313 | 314 | 315 | name 316 | meta.group.braces.round.function.arguments.js 317 | patterns 318 | 319 | 320 | captures 321 | 322 | 1 323 | 324 | name 325 | invalid.illegal.delimiter.js 326 | 327 | 328 | match 329 | (,)\s*+(?=\)) 330 | 331 | 332 | match 333 | , 334 | name 335 | punctuation.separator.parameters.function.js 336 | 337 | 338 | captures 339 | 340 | 1 341 | 342 | name 343 | invalid.illegal.delimiter.js 344 | 345 | 346 | match 347 | (?<![_$\w])([^_$a-zA-Z),\s]+) 348 | 349 | 350 | match 351 | (?<![_$\w])([_$a-zA-Z][_$\w]*) 352 | name 353 | variable.parameter.function.js 354 | 355 | 356 | 357 | leading-space 358 | 359 | patterns 360 | 361 | 362 | begin 363 | ^(?=(\t| )) 364 | end 365 | (?=[^\t\s]) 366 | name 367 | meta.leading-tabs 368 | patterns 369 | 370 | 371 | captures 372 | 373 | 1 374 | 375 | name 376 | meta.odd-tab.group1.spaces 377 | 378 | 10 379 | 380 | name 381 | meta.even-tab.group10.spaces 382 | 383 | 11 384 | 385 | name 386 | meta.odd-tab.group11.spaces 387 | 388 | 2 389 | 390 | name 391 | meta.even-tab.group2.spaces 392 | 393 | 3 394 | 395 | name 396 | meta.odd-tab.group3.spaces 397 | 398 | 4 399 | 400 | name 401 | meta.even-tab.group4.spaces 402 | 403 | 5 404 | 405 | name 406 | meta.odd-tab.group5.spaces 407 | 408 | 6 409 | 410 | name 411 | meta.even-tab.group6.spaces 412 | 413 | 7 414 | 415 | name 416 | meta.odd-tab.group7.spaces 417 | 418 | 8 419 | 420 | name 421 | meta.even-tab.group8.spaces 422 | 423 | 9 424 | 425 | name 426 | meta.odd-tab.group9.spaces 427 | 428 | 429 | match 430 | ( )( )?( )?( )?( )?( )?( )?( )?( )?( )?( )? 431 | 432 | 433 | captures 434 | 435 | 1 436 | 437 | name 438 | meta.odd-tab.group1.tab 439 | 440 | 10 441 | 442 | name 443 | meta.even-tab.group10.tab 444 | 445 | 11 446 | 447 | name 448 | meta.odd-tab.group11.tab 449 | 450 | 2 451 | 452 | name 453 | meta.even-tab.group2.tab 454 | 455 | 3 456 | 457 | name 458 | meta.odd-tab.group3.tab 459 | 460 | 4 461 | 462 | name 463 | meta.even-tab.group4.tab 464 | 465 | 5 466 | 467 | name 468 | meta.odd-tab.group5.tab 469 | 470 | 6 471 | 472 | name 473 | meta.even-tab.group6.tab 474 | 475 | 7 476 | 477 | name 478 | meta.odd-tab.group7.tab 479 | 480 | 8 481 | 482 | name 483 | meta.even-tab.group8.tab 484 | 485 | 9 486 | 487 | name 488 | meta.odd-tab.group9.tab 489 | 490 | 491 | match 492 | (\t)(\t)?(\t)?(\t)?(\t)?(\t)?(\t)?(\t)?(\t)?(\t)?(\t)? 493 | 494 | 495 | 496 | 497 | 498 | object-properties 499 | 500 | patterns 501 | 502 | 503 | captures 504 | 505 | 1 506 | 507 | name 508 | invalid.illegal.delimiter.object.comma.js 509 | 510 | 511 | match 512 | (,)\s*+(?=\}) 513 | 514 | 515 | captures 516 | 517 | 1 518 | 519 | name 520 | string.quoted.double.js 521 | 522 | 2 523 | 524 | name 525 | punctuation.definition.string.js 526 | 527 | 3 528 | 529 | name 530 | constant.other.object.key.js 531 | 532 | 4 533 | 534 | name 535 | punctuation.definition.string.js 536 | 537 | 5 538 | 539 | name 540 | punctuation.separator.objects.js 541 | 542 | 543 | comment 544 | "something" : 545 | match 546 | ((")([^"]*)(")\s*)(:)(?!\s*+function) 547 | 548 | 549 | captures 550 | 551 | 1 552 | 553 | name 554 | string.quoted.single.js 555 | 556 | 2 557 | 558 | name 559 | punctuation.definition.string.js 560 | 561 | 3 562 | 563 | name 564 | constant.other.object.key.js 565 | 566 | 4 567 | 568 | name 569 | punctuation.definition.string.js 570 | 571 | 5 572 | 573 | name 574 | punctuation.separator.objects.js 575 | 576 | 577 | comment 578 | 'something' : 579 | match 580 | ((')([^']*)(')\s*)(:)(?!\s*+function) 581 | 582 | 583 | captures 584 | 585 | 1 586 | 587 | name 588 | constant.other.object.key.js 589 | 590 | 2 591 | 592 | name 593 | punctuation.separator.objects.js 594 | 595 | 596 | comment 597 | something : 598 | match 599 | \b(\w+\b\s*)(:)(?!\s*+function) 600 | 601 | 602 | 603 | 604 | scopeName 605 | source.js.base 606 | uuid 607 | 93E017CC-6F27-11D9-90EB-000D93589AF6 608 | 609 | 610 | -------------------------------------------------------------------------------- /Support/lib/tm/complete.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require File.dirname(__FILE__) + "/../current_word" 3 | require ENV['TM_SUPPORT_PATH'] + '/lib/ui' 4 | require ENV['TM_SUPPORT_PATH'] + '/lib/escape' 5 | require ENV['TM_SUPPORT_PATH'] + '/lib/osx/plist' 6 | require 'rubygems' 7 | require 'json' 8 | require 'shellwords' 9 | 10 | module TextMate 11 | class Complete 12 | IMAGES_FOLDER_NAME = 'icons' 13 | IMAGES = { 14 | "C" => "/Applications/TextMate.app/Contents/Resources/Bundle Item Icons/Commands.png", 15 | "D" => "/Applications/TextMate.app/Contents/Resources/Bundle Item Icons/Drag Commands.png", 16 | "L" => "/Applications/TextMate.app/Contents/Resources/Bundle Item Icons/Languages.png", 17 | "M" => "/Applications/TextMate.app/Contents/Resources/Bundle Item Icons/Macros.png", 18 | "P" => "/Applications/TextMate.app/Contents/Resources/Bundle Item Icons/Preferences.png", 19 | "S" => "/Applications/TextMate.app/Contents/Resources/Bundle Item Icons/Snippets.png", 20 | "T" => "/Applications/TextMate.app/Contents/Resources/Bundle Item Icons/Templates.png", 21 | "Doc" => "/Applications/TextMate.app/Contents/Resources/Bundle Item Icons/Template Files.png", 22 | } 23 | 24 | def initialize 25 | end 26 | 27 | # 0-config completion command using environment variables for everything 28 | def complete! 29 | return choices unless choices 30 | TextMate::UI.complete(choices, {:images => images, :extra_chars => extra_chars}) 31 | end 32 | 33 | def tip! 34 | # If there is no current_word, then check the next current_word 35 | # If there really is no current_word, then show a menu of choices 36 | 37 | chars = "a-zA-Z0-9" # Hard-coded into D2 38 | chars += Regexp.escape(extra_chars) if extra_chars 39 | current_word ||= Word.current_word chars, :both 40 | 41 | result = nil 42 | menu_choices = nil 43 | choices = nil 44 | choice = 0 45 | 46 | [current_word, current_method_name, current_collection_name].each do |initial_filter| 47 | next unless initial_filter and not initial_filter.empty? 48 | # p initial_filter 49 | 50 | choices = self.choices.select { |c| (c['match'] || c['display']) =~ /^#{Regexp.quote(initial_filter)}/ } 51 | 52 | # p choices 53 | break if choices and not choices.empty? 54 | end 55 | choices ||= self.choices 56 | 57 | menu_choices = choices.map { |c| c['display'] } 58 | choice = TextMate::UI.menu(menu_choices) if menu_choices and menu_choices.length > 1 59 | if choice 60 | result = choices[choice] 61 | end 62 | result = {'tool_tip' => 'No information'} unless result 63 | 64 | TextMate::UI.tool_tip( result['tool_tip'], {:format => result['tool_tip_format'] || :text }) 65 | end 66 | 67 | def choices 68 | @choices ||= data['suggestions'] 69 | end 70 | def choices= choice_array 71 | @choices = array_to_suggestions(choice_array) 72 | end 73 | 74 | def images 75 | @images = data['images'] || IMAGES 76 | 77 | data['images']||{}.each_pair do |name,path| 78 | @images[name] = path 79 | next if File.exists? @images[name] 80 | @images[name] = ENV['TM_BUNDLE_SUPPORT'] + "/#{IMAGES_FOLDER_NAME}/" + path 81 | next if File.exists? @images[name] 82 | @images[name] = ENV['TM_SUPPORT_PATH'] + "/#{IMAGES_FOLDER_NAME}/" + path 83 | next if File.exists? @images[name] 84 | end 85 | 86 | @images 87 | end 88 | 89 | def tool_tip_prefix 90 | @tool_tip_prefix ||= data['tool_tip_prefix'] 91 | end 92 | 93 | def extra_chars 94 | ENV['TM_COMPLETIONS_EXTRACHARS'] || data['extra_chars'] 95 | end 96 | 97 | def chars 98 | "a-zA-Z0-9" 99 | end 100 | 101 | private 102 | def data(raw_data=nil) 103 | fix_legacy 104 | 105 | raw_data ||= read_data 106 | return {} unless raw_data and not raw_data.empty? 107 | 108 | @data = parse_data raw_data 109 | return @data 110 | end 111 | 112 | def read_data 113 | raw_data = read_file 114 | raw_data ||= read_string 115 | raw_data 116 | end 117 | 118 | def read_file 119 | paths = [ENV['TM_COMPLETIONS_FILE']] if ENV['TM_COMPLETIONS_FILE'] 120 | paths ||= Shellwords.shellwords( ENV['TM_COMPLETIONS_FILES'] ) if ENV.has_key?('TM_COMPLETIONS_FILES') 121 | return nil unless paths 122 | 123 | paths.map do |path| 124 | next unless path and not path.empty? 125 | path = ENV['TM_BUNDLE_SUPPORT'] + '/' + path unless File.exists? path 126 | next unless File.exists? path 127 | 128 | { :data => File.read(path), 129 | :format => path.scan(/\.([^\.]+)$/).last.last 130 | } 131 | end 132 | end 133 | 134 | def read_string 135 | [{:data => ENV['TM_COMPLETIONS'], 136 | :format => ENV['TM_COMPLETIONS_SPLIT'] 137 | }] 138 | end 139 | 140 | attr_accessor :filepath 141 | 142 | def parse_data(raw_datas) 143 | return @parsed if @parsed 144 | parsed = {"suggestions"=>[]} 145 | 146 | raw_datas.each do |raw_data| 147 | suggestions = parsed['suggestions'] 148 | 149 | case raw_data[:format] 150 | when 'plist' 151 | par = parse_plist(raw_data) 152 | when 'json' 153 | par = parse_json(raw_data) 154 | when "txt" 155 | raw_data[:format] = "\n" 156 | par = parse_string(raw_data) 157 | when nil 158 | raw_data[:format] = "," 159 | par = parse_string(raw_data) 160 | else 161 | par = parse_string(raw_data) 162 | end 163 | 164 | if par['tool_tip_prefix'] 165 | par['suggestions'] = par['suggestions'].map do |suggestion| 166 | suggestion['tool_tip'] = par['tool_tip_prefix'] + suggestion['tool_tip'] 167 | suggestion 168 | end 169 | end 170 | 171 | parsed.merge! par 172 | parsed['suggestions'] = suggestions + parsed['suggestions'] 173 | end 174 | 175 | @parsed = parsed 176 | end 177 | def parse_string(raw_data) 178 | return {} unless raw_data and raw_data[:data] 179 | return raw_data[:data] unless raw_data[:data].respond_to? :to_str 180 | raw_data[:data] = raw_data[:data].to_str 181 | 182 | data = {} 183 | data['suggestions'] = array_to_suggestions(raw_data[:data].split(raw_data[:format])) 184 | data 185 | end 186 | def parse_plist(raw_data) 187 | OSX::PropertyList.load(raw_data[:data]) 188 | end 189 | def parse_json(raw_data) 190 | JSON.parse(raw_data[:data]) 191 | end 192 | 193 | def array_to_suggestions(suggestions) 194 | suggestions.delete('') 195 | 196 | suggestions.map! do |c| 197 | {'display' => c} 198 | end 199 | 200 | suggestions 201 | end 202 | def current_method_name 203 | # Regex for finding a method or function name that's close to your caret position using Word.current_word 204 | # TODO: Allow completion prefs to define their own Complete.tip! method_name 205 | 206 | characters = "a-zA-Z0-9" # Hard-coded into D2 207 | characters += Regexp.escape(extra_chars) if extra_chars 208 | 209 | regex = %r/ 210 | (?> [^\(\)]+ | \) (?> [^\(\)]+ | \) (?> [^\(\)]+ | \) (?> [^\(\)]+ | \) (?> [^\(\)]+ | \) (?> [^\(\)]* ) \( | )+ \( | )+ \( | )+ \( | )+ \( | )+ 211 | (?: \(([#{characters}]+) )?/ix 212 | 213 | Word.current_word(regex,:left) 214 | end 215 | def current_collection_name 216 | characters = "a-zA-Z0-9" # Hard-coded into D2 217 | characters += Regexp.escape(extra_chars) if extra_chars 218 | 219 | regex = %r/ 220 | (?> [^\[\]]+ | \] (?> [^\[\]]+ | \] (?> [^\[\]]+ | \] (?> [^\[\]]+ | \] (?> [^\[\]]+ | \] (?> [^\[\]]* ) \[ | )+ \[ | )+ \[ | )+ \[ | )+ \[ | )+ 221 | (?: \[([#{characters}]+) )?/ix 222 | 223 | Word.current_word(regex,:left) 224 | end 225 | 226 | def fix_legacy 227 | ENV['TM_COMPLETIONS_SPLIT'] ||= ENV['TM_COMPLETIONS_split'] 228 | end 229 | end 230 | end 231 | 232 | if __FILE__ == $0 233 | 234 | `open "txmt://open?url=file://$TM_FILEPATH"` #For testing purposes, make this document the topmost so that the complete popup works 235 | ENV['WEB_PREVIEW_RUBY']='NO-RUN' 236 | require "test/unit" 237 | # require "complete" 238 | 239 | class TestComplete < Test::Unit::TestCase 240 | def setup 241 | @string_raw = 'ad(),adipisicing,aliqua,aliquip,amet,anim,aute,cillum,commodo,consectetur,consequat,culpa,cupidatat,deserunt,do,dolor,dolore,Duis,ea,eiusmod,elit,enim,esse,est,et,eu,ex,Excepteur,exercitation,fugiat,id,in,incididunt,ipsum,irure,labore,laboris,laborum,Lorem,magna,minim,mollit,nisi,non,nostrud,nulla,occaecat,officia,pariatur,proident,qui,quis,reprehenderit,sed,sint,sit,sunt,tempor,ullamco,Ut,ut,velit,veniam,voluptate,' 242 | 243 | @plist_raw = <<-'PLIST' 244 | { suggestions = ( 245 | { display = moo; image = Drag; insert = "(${1:one}, ${2:one}, ${3:three}${4:, ${5:five}, ${6:six}})"; tool_tip = "moo(one, two, four[, five])\n This method does something or other maybe.\n Insert longer description of it here."; }, 246 | { display = foo; image = Macro; insert = "(${1:one}, \"${2:one}\", ${3:three}${4:, ${5:five}, ${6:six}})"; tool_tip = "foo(one, two)\n This method does something or other maybe.\n Insert longer description of it here."; }, 247 | { display = bar; image = Command; insert = "(${1:one}, ${2:one}, \"${3:three}\"${4:, \"${5:five}\", ${6:six}})"; tool_tip = "bar(one, two[, three])\n This method does something or other maybe.\n Insert longer description of it here."; } 248 | ); 249 | extra_chars = '.'; 250 | images = { 251 | Command = "Commands.png"; 252 | Drag = "Drag Commands.png"; 253 | Language = "Languages.png"; 254 | Macro = "Macros.png"; 255 | Preference = "Preferences.png"; 256 | Snippet = "Snippets.png"; 257 | Template = "Template Files.png"; 258 | Templates = "Templates.png"; 259 | }; 260 | } 261 | PLIST 262 | 263 | @json_raw = <<-'JSON' 264 | { 265 | "extra_chars": "-_$.", 266 | "suggestions": [ 267 | { "display": ".moo", "image": "", "insert": "(${1:one}, ${2:one}, ${3:three}${4:, ${5:five}, ${6:six}})", "tool_tip": "moo(one, two, four[, five])\n This method does something or other maybe.\n Insert longer description of it here." }, 268 | { "display": "foo", "image": "", "insert": "(${1:one}, \"${2:one}\", ${3:three}${4:, ${5:five}, ${6:six}})", "tool_tip": "foo(one, two)\n This method does something or other maybe.\n Insert longer description of it here." }, 269 | { "display": "bar", "image": "", "insert": "(${1:one}, ${2:one}, \"${3:three}\"${4:, \"${5:five}\", ${6:six}})", "tool_tip": "bar(one, two[, three])\n This method does something or other maybe.\n Insert longer description of it here." } 270 | ], 271 | "images": { 272 | "String" : "String.png", 273 | "RegExp" : "RegExp.png", 274 | "Number" : "Number.png", 275 | "Array" : "Array.png", 276 | "Function": "Function.png", 277 | "Object" : "Object.png", 278 | "Node" : "Node.png", 279 | "NodeList": "NodeList.png" 280 | } 281 | } 282 | JSON 283 | end 284 | 285 | def test_basic_complete 286 | ENV['TM_COMPLETIONS'] = @string_raw 287 | 288 | assert_equal ENV['TM_COMPLETIONS'].split(','), TextMate::Complete.new.choices.map{|c| c['display']} 289 | assert_equal TextMate::Complete::IMAGES, TextMate::Complete.new.images 290 | 291 | TextMate::Complete.new.complete! 292 | end 293 | # 294 | def test_should_support_plist 295 | ENV['TM_COMPLETIONS_SPLIT']='plist' 296 | ENV['TM_COMPLETIONS'] = @plist_raw 297 | TextMate::Complete.new.complete! 298 | end 299 | # 300 | def test_should_support_json 301 | ENV.delete 'TM_COMPLETIONS' 302 | assert_nil(ENV['TM_COMPLETIONS']) 303 | ENV.delete 'TM_COMPLETIONS_SPLIT' 304 | assert_nil(ENV['TM_COMPLETIONS_SPLIT']) 305 | 306 | ENV['TM_COMPLETIONS_SPLIT']='json' 307 | ENV['TM_COMPLETIONS'] = @json_raw 308 | fred = TextMate::Complete.new 309 | assert_equal(3, fred.choices.length) 310 | end 311 | # 312 | def test_should_be_able_to_modify_the_choices 313 | ENV['TM_COMPLETIONS'] = @string_raw 314 | 315 | fred = TextMate::Complete.new 316 | 317 | assert_not_nil fred.choices 318 | assert_equal ENV['TM_COMPLETIONS'].split(','), fred.choices.map{|c| c['display']} 319 | fred.choices.reject!{|choice| choice['display'] !~ /^a/ } 320 | assert_equal ENV['TM_COMPLETIONS'].split(',').grep(/^a/), fred.choices.map{|c| c['display']} 321 | 322 | fred.choices=%w[fred is not my name] 323 | assert_equal %w[fred is not my name], fred.choices.map{|c| c['display']} 324 | end 325 | # 326 | def test_should_parse_files_based_on_extension_plist 327 | ENV['TM_COMPLETIONS_FILE'] = '/tmp/completions_test.plist' 328 | 329 | File.open(ENV['TM_COMPLETIONS_FILE'],'w'){|file| file.write @plist_raw } 330 | assert File.exists?(ENV['TM_COMPLETIONS_FILE']) 331 | 332 | fred = TextMate::Complete.new 333 | assert_equal(['moo', 'foo', 'bar'], fred.choices.map{|c| c['display']}) 334 | end 335 | # 336 | def test_should_parse_files_based_on_extension_txt 337 | ENV.delete 'TM_COMPLETIONS' 338 | assert_nil(ENV['TM_COMPLETIONS']) 339 | ENV.delete 'TM_COMPLETIONS_SPLIT' 340 | assert_nil(ENV['TM_COMPLETIONS_SPLIT']) 341 | 342 | ENV['TM_COMPLETIONS_FILE'] = '/tmp/completions_test.txt' 343 | 344 | File.open(ENV['TM_COMPLETIONS_FILE'],'w'){|file| file.write @string_raw.gsub(',',"\n") } 345 | assert File.exists?(ENV['TM_COMPLETIONS_FILE']) 346 | 347 | fred = TextMate::Complete.new 348 | 349 | assert_equal(@string_raw.split(','), fred.choices.map{|c| c['display']}) 350 | end 351 | # 352 | def test_should_parse_multiple_files 353 | ENV.delete 'TM_COMPLETIONS' 354 | assert_nil(ENV['TM_COMPLETIONS']) 355 | ENV.delete 'TM_COMPLETIONS_SPLIT' 356 | assert_nil(ENV['TM_COMPLETIONS_SPLIT']) 357 | ENV.delete 'TM_COMPLETIONS_FILE' 358 | assert_nil(ENV['TM_COMPLETIONS_FILE']) 359 | 360 | ENV['TM_COMPLETIONS_FILES'] = "'/tmp/completions_test.txt' '/tmp/completions_test1.txt' '/tmp/completions_test2.txt'" 361 | 362 | require 'shellwords' 363 | Shellwords.shellwords( ENV['TM_COMPLETIONS_FILES'] ).each_with_index do |filepath,i| 364 | File.open(filepath,'w'){|file| file.write @string_raw.gsub(',',"#{i}\n") } 365 | assert File.exists?(filepath) 366 | end 367 | 368 | fred = TextMate::Complete.new 369 | 370 | assert_equal(@string_raw.split(',').uniq.length * 3, fred.choices.map{|c| c['display']}.length ) 371 | end 372 | # 373 | def test_should_override_split_with_extension 374 | ENV['TM_COMPLETIONS_SPLIT'] = ',' 375 | ENV['TM_COMPLETIONS_FILE'] = '/tmp/completions_test.plist' 376 | 377 | File.open(ENV['TM_COMPLETIONS_FILE'],'w'){|file| file.write @plist_raw } 378 | assert File.exists?(ENV['TM_COMPLETIONS_FILE']) 379 | 380 | fred = TextMate::Complete.new 381 | assert_equal(['moo', 'foo', 'bar'], fred.choices.map{|c| c['display']}) 382 | end 383 | # 384 | def test_should_get_extra_chars_from_var 385 | ENV['TM_COMPLETIONS_SPLIT']=',' 386 | ENV['TM_COMPLETIONS'] = @string_raw 387 | ENV['TM_COMPLETIONS_EXTRACHARS'] = '.' 388 | 389 | fred = TextMate::Complete.new 390 | assert_equal('.', fred.extra_chars) 391 | end 392 | # 393 | def test_should_get_extra_chars_from_plist 394 | ENV['TM_COMPLETIONS_SPLIT']='plist' 395 | ENV['TM_COMPLETIONS'] = @plist_raw 396 | 397 | assert_nil(ENV['TM_COMPLETIONS_EXTRACHARS']) 398 | 399 | fred = TextMate::Complete.new 400 | assert_equal('.', fred.extra_chars) 401 | end 402 | # TODO: should_fix_image_paths 403 | =begin 404 | def test_should_fix_image_paths 405 | ENV['TM_COMPLETIONS_SPLIT'] = 'plist' 406 | ENV['TM_COMPLETIONS'] = @plist_raw 407 | ENV['TM_BUNDLE_SUPPORT'] = '/tmp' 408 | ENV['TM_SUPPORT_PATH'] = '/tmp' 409 | 410 | images = OSX::PropertyList.load(@plist_raw)['images'] 411 | 412 | FileUtils.mkdir_p "#{ENV['TM_SUPPORT_PATH']}/#{TextMate::Complete::IMAGES_FOLDER_NAME}" 413 | images.each_pair do |name,path| 414 | File.open("#{ENV['TM_SUPPORT_PATH']}/#{TextMate::Complete::IMAGES_FOLDER_NAME}/#{path}", 'w'){ |file| file.write('') } 415 | end 416 | 417 | TextMate::Complete.new.images.each_pair do |name,path| 418 | assert File.exists?(path) 419 | end 420 | 421 | end 422 | =end 423 | def test_should_apply_prefix 424 | ENV.delete 'TM_COMPLETIONS' 425 | assert_nil(ENV['TM_COMPLETIONS']) 426 | ENV.delete 'TM_COMPLETIONS_SPLIT' 427 | assert_nil(ENV['TM_COMPLETIONS_SPLIT']) 428 | 429 | @json_raw = <<-'JSON' 430 | { 431 | "extra_chars": "-_$.", 432 | "tool_tip_prefix":"prefix", 433 | "suggestions": [ 434 | { "display": ".moo", "image": "", "insert": "(${1:one}, ${2:one}, ${3:three}${4:, ${5:five}, ${6:six}})", "tool_tip": "moo(one, two, four[, five])\n This method does something or other maybe.\n Insert longer description of it here." }, 435 | { "display": "foo", "image": "", "insert": "(${1:one}, \"${2:one}\", ${3:three}${4:, ${5:five}, ${6:six}})", "tool_tip": "foo(one, two)\n This method does something or other maybe.\n Insert longer description of it here." }, 436 | { "display": "bar", "image": "", "insert": "(${1:one}, ${2:one}, \"${3:three}\"${4:, \"${5:five}\", ${6:six}})", "tool_tip": "bar(one, two[, three])\n This method does something or other maybe.\n Insert longer description of it here." } 437 | ], 438 | "images": { 439 | "String" : "String.png", 440 | "RegExp" : "RegExp.png", 441 | "Number" : "Number.png", 442 | "Array" : "Array.png", 443 | "Function": "Function.png", 444 | "Object" : "Object.png", 445 | "Node" : "Node.png", 446 | "NodeList": "NodeList.png" 447 | } 448 | } 449 | JSON 450 | 451 | ENV['TM_COMPLETIONS_SPLIT']='json' 452 | ENV['TM_COMPLETIONS'] = @json_raw 453 | fred = TextMate::Complete.new 454 | assert_equal(3, fred.choices.length) 455 | assert fred.choices.first['tool_tip'].match(/^prefix/) 456 | end 457 | # 458 | def test_should_show_tooltip_without_inserting_anything 459 | # This method passes if it shows a tooltip when selecting a menu-item 460 | # and DOESN'T insert anything or cause the document think anything has changed 461 | ENV.delete 'TM_COMPLETIONS' 462 | assert_nil(ENV['TM_COMPLETIONS']) 463 | ENV.delete 'TM_COMPLETIONS_SPLIT' 464 | assert_nil(ENV['TM_COMPLETIONS_SPLIT']) 465 | 466 | ENV['TM_COMPLETIONS_SPLIT']='json' 467 | ENV['TM_COMPLETIONS'] = @json_raw 468 | fred = TextMate::Complete.new 469 | assert_equal(3, fred.choices.length) 470 | 471 | TextMate::Complete.new.tip! 472 | end 473 | # 474 | def test_tip_should_look_for_the_current_word_and_then_try_the_closest_function_name 475 | ENV.delete 'TM_COMPLETIONS' 476 | assert_nil(ENV['TM_COMPLETIONS']) 477 | ENV.delete 'TM_COMPLETIONS_SPLIT' 478 | assert_nil(ENV['TM_COMPLETIONS_SPLIT']) 479 | 480 | ENV['TM_COMPLETIONS_SPLIT']='json' 481 | ENV['TM_COMPLETIONS'] = @json_raw 482 | fred = TextMate::Complete.new 483 | assert_equal(3, fred.choices.length) 484 | 485 | TextMate::Complete.new.tip! 486 | # 487 | # This test passes if, when run, you see the tooltip for closest function 488 | # Be sure to more your caret around and try a few times 489 | # Showing a menu is a fail 490 | # 491 | # foo( bar( ), '.moo' ) 492 | # ^ Caret here should give the tip for 'foo' 493 | # ^ Caret here should give the tip for 'bar' 494 | # ^ Caret here should give the tip for 'bar' 495 | # ^ Caret here should give the tip for '.moo' 496 | # foo( bar(one,two,foo), '.moo' ) 497 | # foo['bar'] 498 | end 499 | # 500 | end 501 | 502 | end#if 503 | -------------------------------------------------------------------------------- /Support/JSSpec/diff_match_patch.js: -------------------------------------------------------------------------------- 1 | function diff_match_patch(){this.Diff_Timeout=1.0;this.Diff_EditCost=4;this.Diff_DualThreshold=32;this.Match_Balance=0.5;this.Match_Threshold=0.5;this.Match_MinLength=100;this.Match_MaxLength=1000;this.Patch_Margin=4;function getMaxBits(){var maxbits=0;var oldi=1;var newi=2;while(oldi!=newi){maxbits++;oldi=newi;newi=newi<<1}return maxbits}this.Match_MaxBits=getMaxBits()}var DIFF_DELETE=-1;var DIFF_INSERT=1;var DIFF_EQUAL=0;diff_match_patch.prototype.diff_main=function(text1,text2,opt_checklines){if(text1==text2){return[[DIFF_EQUAL,text1]]}if(typeof opt_checklines=='undefined'){opt_checklines=true}var checklines=opt_checklines;var commonlength=this.diff_commonPrefix(text1,text2);var commonprefix=text1.substring(0,commonlength);text1=text1.substring(commonlength);text2=text2.substring(commonlength);commonlength=this.diff_commonSuffix(text1,text2);var commonsuffix=text1.substring(text1.length-commonlength);text1=text1.substring(0,text1.length-commonlength);text2=text2.substring(0,text2.length-commonlength);var diffs=this.diff_compute(text1,text2,checklines);if(commonprefix){diffs.unshift([DIFF_EQUAL,commonprefix])}if(commonsuffix){diffs.push([DIFF_EQUAL,commonsuffix])}this.diff_cleanupMerge(diffs);return diffs};diff_match_patch.prototype.diff_compute=function(text1,text2,checklines){var diffs;if(!text1){return[[DIFF_INSERT,text2]]}if(!text2){return[[DIFF_DELETE,text1]]}var longtext=text1.length>text2.length?text1:text2;var shorttext=text1.length>text2.length?text2:text1;var i=longtext.indexOf(shorttext);if(i!=-1){diffs=[[DIFF_INSERT,longtext.substring(0,i)],[DIFF_EQUAL,shorttext],[DIFF_INSERT,longtext.substring(i+shorttext.length)]];if(text1.length>text2.length){diffs[0][0]=diffs[2][0]=DIFF_DELETE}return diffs}longtext=shorttext=null;var hm=this.diff_halfMatch(text1,text2);if(hm){var text1_a=hm[0];var text1_b=hm[1];var text2_a=hm[2];var text2_b=hm[3];var mid_common=hm[4];var diffs_a=this.diff_main(text1_a,text2_a,checklines);var diffs_b=this.diff_main(text1_b,text2_b,checklines);return diffs_a.concat([[DIFF_EQUAL,mid_common]],diffs_b)}if(checklines&&text1.length+text2.length<250){checklines=false}var linearray;if(checklines){var a=this.diff_linesToChars(text1,text2);text1=a[0];text2=a[1];linearray=a[2]}diffs=this.diff_map(text1,text2);if(!diffs){diffs=[[DIFF_DELETE,text1],[DIFF_INSERT,text2]]}if(checklines){this.diff_charsToLines(diffs,linearray);this.diff_cleanupSemantic(diffs);diffs.push([DIFF_EQUAL,'']);var pointer=0;var count_delete=0;var count_insert=0;var text_delete='';var text_insert='';while(pointer=1&&count_insert>=1){var a=this.diff_main(text_delete,text_insert,false);diffs.splice(pointer-count_delete-count_insert,count_delete+count_insert);pointer=pointer-count_delete-count_insert;for(var j=a.length-1;j>=0;j--){diffs.splice(pointer,0,a[j])}pointer=pointer+a.length}count_insert=0;count_delete=0;text_delete='';text_insert=''}pointer++}diffs.pop()}return diffs};diff_match_patch.prototype.diff_linesToChars=function(text1,text2){var linearray=[];var linehash={};linearray.push('');function diff_linesToCharsMunge(text){var chars='';while(text){var i=text.indexOf('\n');if(i==-1){i=text.length}var line=text.substring(0,i+1);text=text.substring(i+1);if(linehash.hasOwnProperty?linehash.hasOwnProperty(line):(linehash[line]!==undefined)){chars+=String.fromCharCode(linehash[line])}else{linearray.push(line);linehash[line]=linearray.length-1;chars+=String.fromCharCode(linearray.length-1)}}return chars}var chars1=diff_linesToCharsMunge(text1);var chars2=diff_linesToCharsMunge(text2);return[chars1,chars2,linearray]};diff_match_patch.prototype.diff_charsToLines=function(diffs,linearray){for(var x=0;x0&&(new Date()).getTime()>ms_end){return null}v_map1[d]={};for(var k=-d;k<=d;k+=2){if(k==-d||k!=d&&v1[k-1]=0;d--){while(1){if(v_map[d].hasOwnProperty?v_map[d].hasOwnProperty((x-1)+','+y):(v_map[d][(x-1)+','+y]!==undefined)){x--;if(last_op===DIFF_DELETE){path[0][1]=text1.charAt(x)+path[0][1]}else{path.unshift([DIFF_DELETE,text1.charAt(x)])}last_op=DIFF_DELETE;break}else if(v_map[d].hasOwnProperty?v_map[d].hasOwnProperty(x+','+(y-1)):(v_map[d][x+','+(y-1)]!==undefined)){y--;if(last_op===DIFF_INSERT){path[0][1]=text2.charAt(y)+path[0][1]}else{path.unshift([DIFF_INSERT,text2.charAt(y)])}last_op=DIFF_INSERT;break}else{x--;y--;if(last_op===DIFF_EQUAL){path[0][1]=text1.charAt(x)+path[0][1]}else{path.unshift([DIFF_EQUAL,text1.charAt(x)])}last_op=DIFF_EQUAL}}}return path};diff_match_patch.prototype.diff_path2=function(v_map,text1,text2){var path=[];var x=text1.length;var y=text2.length;var last_op=null;for(var d=v_map.length-2;d>=0;d--){while(1){if(v_map[d].hasOwnProperty?v_map[d].hasOwnProperty((x-1)+','+y):(v_map[d][(x-1)+','+y]!==undefined)){x--;if(last_op===DIFF_DELETE){path[path.length-1][1]+=text1.charAt(text1.length-x-1)}else{path.push([DIFF_DELETE,text1.charAt(text1.length-x-1)])}last_op=DIFF_DELETE;break}else if(v_map[d].hasOwnProperty?v_map[d].hasOwnProperty(x+','+(y-1)):(v_map[d][x+','+(y-1)]!==undefined)){y--;if(last_op===DIFF_INSERT){path[path.length-1][1]+=text2.charAt(text2.length-y-1)}else{path.push([DIFF_INSERT,text2.charAt(text2.length-y-1)])}last_op=DIFF_INSERT;break}else{x--;y--;if(last_op===DIFF_EQUAL){path[path.length-1][1]+=text1.charAt(text1.length-x-1)}else{path.push([DIFF_EQUAL,text1.charAt(text1.length-x-1)])}last_op=DIFF_EQUAL}}}return path};diff_match_patch.prototype.diff_commonPrefix=function(text1,text2){if(!text1||!text2||text1.charCodeAt(0)!==text2.charCodeAt(0)){return 0}var pointermin=0;var pointermax=Math.min(text1.length,text2.length);var pointermid=pointermax;var pointerstart=0;while(pointermintext2.length?text1:text2;var shorttext=text1.length>text2.length?text2:text1;if(longtext.length<10||shorttext.length<1){return null}var dmp=this;function diff_halfMatchI(longtext,shorttext,i){var seed=longtext.substring(i,i+Math.floor(longtext.length/4));var j=-1;var best_common='';var best_longtext_a,best_longtext_b,best_shorttext_a,best_shorttext_b;while((j=shorttext.indexOf(seed,j+1))!=-1){var prefixLength=dmp.diff_commonPrefix(longtext.substring(i),shorttext.substring(j));var suffixLength=dmp.diff_commonSuffix(longtext.substring(0,i),shorttext.substring(0,j));if(best_common.length=longtext.length/2){return[best_longtext_a,best_longtext_b,best_shorttext_a,best_shorttext_b,best_common]}else{return null}}var hm1=diff_halfMatchI(longtext,shorttext,Math.ceil(longtext.length/4));var hm2=diff_halfMatchI(longtext,shorttext,Math.ceil(longtext.length/2));var hm;if(!hm1&&!hm2){return null}else if(!hm2){hm=hm1}else if(!hm1){hm=hm2}else{hm=hm1[4].length>hm2[4].length?hm1:hm2}var text1_a,text1_b,text2_a,text2_b;if(text1.length>text2.length){text1_a=hm[0];text1_b=hm[1];text2_a=hm[2];text2_b=hm[3]}else{text2_a=hm[0];text2_b=hm[1];text1_a=hm[2];text1_b=hm[3]}var mid_common=hm[4];return[text1_a,text1_b,text2_a,text2_b,mid_common]};diff_match_patch.prototype.diff_cleanupSemantic=function(diffs){var changes=false;var equalities=[];var lastequality=null;var pointer=0;var length_changes1=0;var length_changes2=0;while(pointer=bestScore){bestScore=score;bestEquality1=equality1;bestEdit=edit;bestEquality2=equality2}}if(diffs[pointer-1][1]!=bestEquality1){diffs[pointer-1][1]=bestEquality1;diffs[pointer][1]=bestEdit;diffs[pointer+1][1]=bestEquality2}}pointer++}};diff_match_patch.prototype.diff_cleanupEfficiency=function(diffs){var changes=false;var equalities=[];var lastequality='';var pointer=0;var pre_ins=false;var pre_del=false;var post_ins=false;var post_del=false;while(pointer0&&diffs[pointer-count_delete-count_insert-1][0]==DIFF_EQUAL){diffs[pointer-count_delete-count_insert-1][1]+=text_insert.substring(0,commonlength)}else{diffs.splice(0,0,[DIFF_EQUAL,text_insert.substring(0,commonlength)]);pointer++}text_insert=text_insert.substring(commonlength);text_delete=text_delete.substring(commonlength)}commonlength=this.diff_commonSuffix(text_insert,text_delete);if(commonlength!==0){diffs[pointer][1]=text_insert.substring(text_insert.length-commonlength)+diffs[pointer][1];text_insert=text_insert.substring(0,text_insert.length-commonlength);text_delete=text_delete.substring(0,text_delete.length-commonlength)}}if(count_delete===0){diffs.splice(pointer-count_delete-count_insert,count_delete+count_insert,[DIFF_INSERT,text_insert])}else if(count_insert===0){diffs.splice(pointer-count_delete-count_insert,count_delete+count_insert,[DIFF_DELETE,text_delete])}else{diffs.splice(pointer-count_delete-count_insert,count_delete+count_insert,[DIFF_DELETE,text_delete],[DIFF_INSERT,text_insert])}pointer=pointer-count_delete-count_insert+(count_delete?1:0)+(count_insert?1:0)+1}else if(pointer!==0&&diffs[pointer-1][0]==DIFF_EQUAL){diffs[pointer-1][1]+=diffs[pointer][1];diffs.splice(pointer,1)}else{pointer++}count_insert=0;count_delete=0;text_delete='';text_insert=''}}if(diffs[diffs.length-1][1]===''){diffs.pop()}var changes=false;pointer=1;while(pointerloc){break}last_chars1=chars1;last_chars2=chars2}if(diffs.length!=x&&diffs[x][0]===DIFF_DELETE){return last_chars2}return last_chars2+(loc-last_chars1)};diff_match_patch.prototype.diff_prettyHtml=function(diffs){this.diff_addIndex(diffs);var html=[];for(var x=0;x/g,'>');t=t.replace(/\n/g,'¶
');if(m===DIFF_DELETE){html.push('',t,'')}else if(m===DIFF_INSERT){html.push('',t,'')}else{html.push('',t,'')}}return html.join('')};diff_match_patch.prototype.diff_text1=function(diffs){var txt=[];for(var x=0;xthis.Match_MaxBits){return alert('Pattern too long for this browser.')}var s=this.match_alphabet(pattern);var score_text_length=text.length;score_text_length=Math.max(score_text_length,this.Match_MinLength);score_text_length=Math.min(score_text_length,this.Match_MaxLength);var dmp=this;function match_bitapScore(e,x){var d=Math.abs(loc-x);return(e/pattern.length/dmp.Match_Balance)+(d/score_text_length/(1.0-dmp.Match_Balance))}var score_threshold=this.Match_Threshold;var best_loc=text.indexOf(pattern,loc);if(best_loc!=-1){score_threshold=Math.min(match_bitapScore(0,best_loc),score_threshold)}best_loc=text.lastIndexOf(pattern,loc+pattern.length);if(best_loc!=-1){score_threshold=Math.min(match_bitapScore(0,best_loc),score_threshold)}var matchmask=1<<(pattern.length-1);best_loc=null;var bin_min,bin_mid;var bin_max=Math.max(loc+loc,text.length);var last_rd;for(var d=0;d=start;j--){if(d===0){rd[j]=((rd[j+1]<<1)|1)&s[text.charAt(j)]}else{rd[j]=((rd[j+1]<<1)|1)&s[text.charAt(j)]|((last_rd[j+1]<<1)|1)|((last_rd[j]<<1)|1)|last_rd[j+1]}if(rd[j]&matchmask){var score=match_bitapScore(d,j);if(score<=score_threshold){score_threshold=score;best_loc=j;if(j>loc){start=Math.max(0,loc-(j-loc))}else{break}}}}if(match_bitapScore(d+1,loc)>score_threshold){break}last_rd=rd}return best_loc};diff_match_patch.prototype.match_alphabet=function(pattern){var s=Object();for(var i=0;i2){this.diff_cleanupSemantic(diffs);this.diff_cleanupEfficiency(diffs)}}if(diffs.length===0){return[]}var patches=[];var patch=new patch_obj();var char_count1=0;var char_count2=0;var prepatch_text=text1;var postpatch_text=text1;for(var x=0;x=2*this.Patch_Margin){if(patch.diffs.length!==0){this.patch_addContext(patch,prepatch_text);patches.push(patch);patch=new patch_obj();prepatch_text=postpatch_text}}if(diff_type!==DIFF_INSERT){char_count1+=diff_text.length}if(diff_type!==DIFF_DELETE){char_count2+=diff_text.length}}if(patch.diffs.length!==0){this.patch_addContext(patch,prepatch_text);patches.push(patch)}return patches};diff_match_patch.prototype.patch_apply=function(patches,text){this.patch_splitMax(patches);var results=[];var delta=0;for(var x=0;xthis.Match_MaxBits){var bigpatch=patches[x];patches.splice(x,1);var patch_size=this.Match_MaxBits;var start1=bigpatch.start1;var start2=bigpatch.start2;var precontext='';while(bigpatch.diffs.length!==0){var patch=new patch_obj();var empty=true;patch.start1=start1-precontext.length;patch.start2=start2-precontext.length;if(precontext!==''){patch.length1=patch.length2=precontext.length;patch.diffs.push([DIFF_EQUAL,precontext])}while(bigpatch.diffs.length!==0&&patch.length1 Indent Line 4 | // Then run a Diff > Document with Saved Copy 5 | // If there are any differences then the indent rules are broken 6 | 7 | /* 8 | Block Comment 9 | */ 10 | /* 11 | Block Comment 12 | */ // Comment 13 | 14 | /** 15 | Documentation Comment (idiom) 16 | **/ // Comment 17 | 18 | /* Documentation Comment (idiom) 19 | * 20 | * Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do 21 | * eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim 22 | * ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut 23 | * aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit 24 | * in voluptate velit esse cillum dolore eu fugiat nulla pariatur. 25 | * Excepteur sint occaecat cupidatat non proident, sunt in culpa qui 26 | * officia deserunt mollit anim id est laborum. 27 | */ 28 | 29 | 30 | // nothing 31 | 32 | [1,2,3] 33 | [ 34 | 1, 35 | 2, 36 | 3 37 | ] 38 | myArray[ 39 | 0 40 | ] 41 | (statement) 42 | ( 43 | statement 44 | ) 45 | myFunction( 46 | statement 47 | ) 48 | { 49 | label:'value' 50 | } 51 | var myObj = { 52 | label:'value' 53 | } 54 | 55 | function (){ 56 | statement; 57 | } 58 | 59 | // With ; 60 | [1,2,3]; 61 | [ 62 | 1, 63 | 2, 64 | 3 65 | ]; 66 | myArray[ 67 | 0 68 | ]; 69 | (statement) 70 | ( 71 | statement 72 | ); 73 | myFunction( 74 | statement 75 | ); 76 | { 77 | label:'value' 78 | }; 79 | function(){ 80 | statement; 81 | }; 82 | 83 | 84 | 85 | // With () 86 | [1,2,3]() 87 | [ 88 | 1, 89 | 2, 90 | 3 91 | ]() 92 | myArray[ 93 | 0 94 | ]() 95 | (statement) 96 | ( 97 | statement 98 | )() 99 | myFunction( 100 | statement 101 | )() 102 | ({ 103 | label:'value' 104 | })['label']() 105 | (function(){ 106 | statement() 107 | })() 108 | 109 | 110 | 111 | // Object 112 | var myObj = { 113 | label: [1,2,3], 114 | label: [ 115 | 1, 116 | 2, 117 | 3 118 | ], 119 | label: myArray[ 120 | 0 121 | ], 122 | label: (statement), 123 | label: ( 124 | statement 125 | ), 126 | label: myFunction( 127 | statement 128 | ), 129 | label: { 130 | label:'value' 131 | }, 132 | label: function(){ 133 | statement; 134 | }, 135 | label: 0 136 | }; 137 | 138 | 139 | // ======================== 140 | // = With inline comments = 141 | // ======================== 142 | [1,2,3] // Comment 143 | [ // Comment 144 | 1, // Comment 145 | 2, // Comment 146 | 3 // Comment 147 | ] // Comment 148 | myArray[ // Comment 149 | 0 // Comment 150 | ] // Comment 151 | (statement) // Comment 152 | ( // Comment 153 | statement // Comment 154 | ) // Comment 155 | myFunction( // Comment 156 | statement // Comment 157 | ) // Comment 158 | { // Comment 159 | label:'value' // Comment 160 | } // Comment 161 | function(){ // Comment 162 | statement; // Comment 163 | } // Comment 164 | 165 | 166 | [1,2,3]; // Comment 167 | [ // Comment 168 | 1, // Comment 169 | 2, // Comment 170 | 3 // Comment 171 | ]; // Comment 172 | myArray[ // Comment 173 | 0 // Comment 174 | ]; // Comment 175 | (statement) // Comment 176 | ( // Comment 177 | statement // Comment 178 | ); // Comment 179 | myFunction( // Comment 180 | statement // Comment 181 | ); // Comment 182 | { // Comment 183 | label:'value' // Comment 184 | }; // Comment 185 | function(){ // Comment 186 | statement; // Comment 187 | }; // Comment 188 | 189 | 190 | var myObj = { // Comment 191 | label: [1,2,3], // Comment 192 | label: [ // Comment 193 | 1, // Comment 194 | 2, // Comment 195 | 3 // Comment 196 | ], // Comment 197 | label: myArray[ // Comment 198 | 0 // Comment 199 | ], // Comment 200 | label: (statement), // Comment 201 | label: ( // Comment 202 | statement // Comment 203 | ), // Comment 204 | label: myFunction( // Comment 205 | statement // Comment 206 | ), // Comment 207 | label: { // Comment 208 | label:'value' // Comment 209 | }, // Comment 210 | label: function(){ // Comment 211 | statement; // Comment 212 | }, // Comment 213 | label: 0 // Comment 214 | }; // Comment 215 | 216 | 217 | // ======================== 218 | // = With inline comments = 219 | // ======================== 220 | [1,2,3] /* Comment 221 | */ 222 | [ /* Comment 223 | */ 224 | 1, /* Comment 225 | */ 226 | 2, /* Comment 227 | */ 228 | 3 /* Comment 229 | */ 230 | ] /* Comment 231 | */ 232 | myArray[ /* Comment 233 | */ 234 | 0 /* Comment 235 | */ 236 | ] /* Comment 237 | */ 238 | (statement) /* Comment 239 | */ 240 | ( /* Comment 241 | */ 242 | statement /* Comment 243 | */ 244 | ) /* Comment 245 | */ 246 | myFunction( /* Comment 247 | */ 248 | statement /* Comment 249 | */ 250 | ) /* Comment 251 | */ 252 | { /* Comment 253 | */ 254 | label:'value' /* Comment 255 | */ 256 | } /* Comment 257 | */ 258 | function(){ /* Comment 259 | */ 260 | statement; /* Comment 261 | */ 262 | } /* Comment 263 | */ 264 | [1,2,3]; /* Comment 265 | */ 266 | [ /* Comment 267 | */ 268 | 1, /* Comment 269 | */ 270 | 2, /* Comment 271 | */ 272 | 3 /* Comment 273 | */ 274 | ]; /* Comment 275 | */ 276 | myArray[ /* Comment 277 | */ 278 | 0 /* Comment 279 | */ 280 | ]; /* Comment 281 | */ 282 | (statement) /* Comment 283 | */ 284 | ( /* Comment 285 | */ 286 | statement /* Comment 287 | */ 288 | ); /* Comment 289 | */ 290 | myFunction( /* Comment 291 | */ 292 | statement /* Comment 293 | */ 294 | ); /* Comment 295 | */ 296 | { /* Comment 297 | */ 298 | label:'value' /* Comment 299 | */ 300 | }; /* Comment 301 | */ 302 | function(){ /* Comment 303 | */ 304 | statement; /* Comment 305 | */ 306 | }; /* Comment 307 | */ 308 | var myObj = { /* Comment 309 | */ 310 | label: [1,2,3], /* Comment 311 | */ 312 | label: [ /* Comment 313 | */ 314 | 1, /* Comment 315 | */ 316 | 2, /* Comment 317 | */ 318 | 3 /* Comment 319 | */ 320 | ], /* Comment 321 | */ 322 | label: myArray[ /* Comment 323 | */ 324 | 0 /* Comment 325 | */ 326 | ], /* Comment 327 | */ 328 | label: (statement), /* Comment 329 | */ 330 | label: ( /* Comment 331 | */ 332 | statement /* Comment 333 | */ 334 | ), /* Comment 335 | */ 336 | label: myFunction( /* Comment 337 | */ 338 | statement /* Comment 339 | */ 340 | ), /* Comment 341 | */ 342 | label: { /* Comment 343 | */ 344 | label:'value' /* Comment 345 | */ 346 | }, /* Comment 347 | */ 348 | label: function(){ /* Comment 349 | */ 350 | statement; /* Comment 351 | */ 352 | }, /* Comment 353 | */ 354 | label: 0 /* Comment 355 | */ 356 | }; /* Comment 357 | */ 358 | 359 | 360 | // ================= 361 | // = With Comments = 362 | // ================= 363 | [1,2,3] /* Comment */ 364 | [ /* Comment */ 365 | 1, /* Comment */ 366 | 2, /* Comment */ 367 | 3 /* Comment */ 368 | ] /* Comment */ 369 | myArray[ /* Comment */ 370 | 0 /* Comment */ 371 | ] /* Comment */ 372 | (statement) /* Comment */ 373 | ( /* Comment */ 374 | statement /* Comment */ 375 | ) /* Comment */ 376 | myFunction( /* Comment */ 377 | statement /* Comment */ 378 | ) /* Comment */ 379 | { /* Comment */ 380 | label:'value' /* Comment */ 381 | } /* Comment */ 382 | function(){ /* Comment */ 383 | statement; /* Comment */ 384 | } /* Comment */ 385 | 386 | // With ; /* Comment */ 387 | [1,2,3]; /* Comment */ 388 | [ /* Comment */ 389 | 1, /* Comment */ 390 | 2, /* Comment */ 391 | 3 /* Comment */ 392 | ]; /* Comment */ 393 | myArray[ /* Comment */ 394 | 1, /* Comment */ 395 | 2, /* Comment */ 396 | 3 /* Comment */ 397 | ]; /* Comment */ 398 | (statement) /* Comment */ 399 | ( /* Comment */ 400 | statement /* Comment */ 401 | ); /* Comment */ 402 | myFunction( /* Comment */ 403 | statement /* Comment */ 404 | ); /* Comment */ 405 | { /* Comment */ 406 | label:'value' /* Comment */ 407 | }; /* Comment */ 408 | function(){ /* Comment */ 409 | statement; /* Comment */ 410 | }; /* Comment */ 411 | 412 | 413 | // Object /* Comment */ 414 | var myObj = { /* Comment */ 415 | label: [1,2,3], /* Comment */ 416 | label: [ /* Comment */ 417 | 1, /* Comment */ 418 | 2, /* Comment */ 419 | 3 /* Comment */ 420 | ], /* Comment */ 421 | label: myArray[ /* Comment */ 422 | 0 /* Comment */ 423 | ], /* Comment */ 424 | label: (statement), /* Comment */ 425 | label: ( /* Comment */ 426 | statement /* Comment */ 427 | ), /* Comment */ 428 | label: myFunction( /* Comment */ 429 | statement /* Comment */ 430 | ), /* Comment */ 431 | label: { /* Comment */ 432 | label:'value' /* Comment */ 433 | }, /* Comment */ 434 | label: function(){ /* Comment */ 435 | statement; /* Comment */ 436 | }, /* Comment */ 437 | label: 0 /* Comment */ 438 | }; /* Comment */ 439 | 440 | 441 | // ================= 442 | // = With Comments = 443 | // ================= 444 | /* Comment */ [1,2,3] 445 | /* Comment */ [ 446 | /* Comment */ 1, 447 | /* Comment */ 2, 448 | /* Comment */ 3 449 | /* Comment */ ] 450 | /* Comment */ myArray[ 451 | /* Comment */ 0 452 | /* Comment */ ] 453 | /* Comment */ (statement) 454 | /* Comment */ ( 455 | /* Comment */ statement 456 | /* Comment */ ) 457 | /* Comment */ myFunction( 458 | /* Comment */ statement 459 | /* Comment */ ) 460 | /* Comment */ { 461 | /* Comment */ label:'value' 462 | /* Comment */ } 463 | /* Comment */ function(){ 464 | /* Comment */ statement; 465 | /* Comment */ } 466 | 467 | /* Comment */ // With ; 468 | /* Comment */ [1,2,3]; 469 | /* Comment */ [ 470 | /* Comment */ 1, 471 | /* Comment */ 2, 472 | /* Comment */ 3 473 | /* Comment */ ]; 474 | /* Comment */ myArray[ 475 | /* Comment */ 1, 476 | /* Comment */ 2, 477 | /* Comment */ 3 478 | /* Comment */ ]; 479 | /* Comment */ (statement) 480 | /* Comment */ ( 481 | /* Comment */ statement 482 | /* Comment */ ); 483 | /* Comment */ myFunction( 484 | /* Comment */ statement 485 | /* Comment */ ); 486 | /* Comment */ { 487 | /* Comment */ label:'value' 488 | /* Comment */ }; 489 | /* Comment */ function(){ 490 | /* Comment */ statement; 491 | /* Comment */ }; 492 | 493 | /* Comment */ // Object 494 | /* Comment */ var myObj = { 495 | /* Comment */ label: [1,2,3], 496 | /* Comment */ label: [ 497 | /* Comment */ 1, 498 | /* Comment */ 2, 499 | /* Comment */ 3 500 | /* Comment */ ], 501 | /* Comment */ label: myArray[ 502 | /* Comment */ 0 503 | /* Comment */ ], 504 | /* Comment */ label: (statement), 505 | /* Comment */ label: ( 506 | /* Comment */ statement 507 | /* Comment */ ), 508 | /* Comment */ label: myFunction( 509 | /* Comment */ statement 510 | /* Comment */ ), 511 | /* Comment */ label: { 512 | /* Comment */ label:'value' 513 | /* Comment */ }, 514 | /* Comment */ label: function(){ 515 | /* Comment */ statement; 516 | /* Comment */ }, 517 | /* Comment */ label: 0 518 | /* Comment */ }; 519 | 520 | 521 | // No Fold; No Indent 522 | function(){/* { */} 523 | myArray = [/* [ */] 524 | myFunction(/* ( */) 525 | // No Fold; No Indent 526 | function(){/* } */} 527 | myArray = [/* ] */] 528 | myFunction(/* ) */) 529 | // No Fold; No Indent 530 | 531 | 532 | /* Comment {*/ function(){/* { */} 533 | /* Comment [*/ myArray = [/* [ */] 534 | /* Comment (*/ myFunction(/* ( */) 535 | // No Fold; No Indent 536 | /* Comment }*/ function(){/* } */} 537 | /* Comment ]*/ myArray = [/* ] */] 538 | /* Comment )*/ myFunction(/* ) */) 539 | // No Fold; No Indent 540 | 541 | 542 | /* Comment {*/ function(){ 543 | // Fold; Indent 544 | } 545 | /* Comment [*/ myArray = [ 546 | // Fold; Indent 547 | ] 548 | /* Comment (*/ myFunction( 549 | // Fold; Indent 550 | ) 551 | // No Fold; No Indent 552 | /* Comment }*/ function(){ 553 | // Fold; Indent 554 | } 555 | /* Comment ]*/ myArray = [ 556 | // Fold; Indent 557 | ] 558 | /* Comment )*/ myFunction( 559 | // Fold; Indent 560 | ) 561 | // No Fold; No Indent 562 | 563 | 564 | /* Comment 565 | }*/ function(){ 566 | // Fold; Indent 567 | } 568 | /* Comment 569 | ]*/ myArray = [ 570 | // Fold; Indent 571 | ] 572 | /* Comment 573 | )*/ myFunction( 574 | // Fold; Indent 575 | ) 576 | // No Fold; No Indent 577 | 578 | 579 | /* Comment 580 | {*/ function(){} 581 | /* Comment 582 | [*/ myArray = [] 583 | /* Comment 584 | (*/ myFunction() 585 | // No Fold; No Indent 586 | /* Comment 587 | }*/ function(){} 588 | /* Comment 589 | ]*/ myArray = [] 590 | /* Comment 591 | )*/ myFunction() 592 | // No Fold; No Indent 593 | 594 | 595 | function(){/* } */ 596 | // Fold; Indent 597 | /*{*/} 598 | myArray = [/* ] */ 599 | // Fold; Indent 600 | /*[*/] 601 | myFunction(/* ) */ 602 | // Fold; Indent 603 | /*(*/) 604 | // No Fold; No Indent 605 | 606 | 607 | function(){/* } 608 | */// Fold; Indent 609 | /*{ 610 | */} 611 | myArray = [/* ] 612 | */// Fold; Indent 613 | /*[ 614 | */] 615 | myFunction(/* ) 616 | */// Fold; Indent 617 | /*( 618 | */) 619 | // No Fold; No Indent 620 | 621 | 622 | 623 | // ============== 624 | // = Mixed line = 625 | // ============== 626 | 627 | [ [1,2,3],[1,2,3], 628 | [1,2,3],[1,2,3], 629 | ][0] 630 | myArray[ myArray[0] + myArray[0] + 631 | 0 632 | ][ 0 633 | ] 634 | ( (statement) + 635 | statement 636 | ) 637 | myFunction( myFunction() + myFunction() 638 | ) 639 | var myObj = { label:{ label:'value' }, label:{ label:'value' }, 640 | label:'value' 641 | } 642 | function(){ function(){ statement }; function(){ statement }; 643 | statement; 644 | } 645 | 646 | 647 | // ======== 648 | // = Bugs = 649 | // ======== 650 | 651 | myFunction() 652 | 653 | myFunction( 654 | // Fold; Indent 655 | );myFunction 656 | 657 | myFunction((0) 658 | // Fold; Indent 659 | );myFunction 660 | 661 | myFunction(something() 662 | // Fold; Indent 663 | ) 664 | 665 | myFunction(()something 666 | // Fold; Indent 667 | ) 668 | 669 | myFunction((something) 670 | // Fold; Indent 671 | ) 672 | 673 | myFunction(something(something)something 674 | // Fold; Indent 675 | something(something)something) 676 | 677 | 678 | 679 | myFunction(something()() 680 | // Fold; Indent 681 | ) 682 | 683 | myFunction(()something() 684 | // Fold; Indent 685 | ) 686 | 687 | myFunction((something)() 688 | // Fold; Indent 689 | ) 690 | 691 | myFunction(()something()(something)()something() 692 | // Fold; Indent 693 | ) 694 | 695 | 696 | 697 | // =========== 698 | // = Special = 699 | // =========== 700 | switch (statement){ 701 | case 'label': 702 | statement; 703 | break; 704 | case 'label': 705 | statement; 706 | break; 707 | case 'label': 708 | statement; 709 | break; 710 | default: 711 | statement; 712 | } 713 | 714 | function(){ 715 | 716 | switch (statement){ 717 | case 'label': 718 | statement; 719 | break; 720 | case 'label': 721 | statement; 722 | break; 723 | case 'label': 724 | statement; 725 | break; 726 | default: 727 | statement; 728 | } 729 | 730 | switch (statement){ 731 | case 'label': statement; break; 732 | case 'label': 733 | statement; 734 | break; 735 | case 'label': statement; break; 736 | default: 737 | statement; 738 | } 739 | 740 | switch (statement){ 741 | case 'label': statement; break; 742 | case 'label': statement; break; 743 | case 'label': statement; break; 744 | default: statement; 745 | } 746 | 747 | switch(expression){case expression:statements;break;default:statements;} 748 | statements; // No More Indent 749 | 750 | switch(expression){ default:function(){" { "}; } 751 | switch(expression){ default:function(){" } "}; } 752 | switch(expression){ default:function(){"\" { "}; } 753 | switch(expression){ default:function(){"\" } "}; } 754 | switch(expression){ default:function(){' { '}; } 755 | switch(expression){ default:function(){' } '}; } 756 | switch(expression){ default:function(){'\' { '}; } 757 | switch(expression){ default:function(){'\' } '}; } 758 | switch(expression){ default:function(){/ } /}; } 759 | switch(expression){ default:function(){/ \{ /}; } 760 | switch(expression){ default:function(){/\/ } /}; } 761 | switch(expression){ default:function(){/\/\{ /}; } 762 | // No More Indent 763 | 764 | } 765 | 766 | 767 | 768 | 769 | // No fold 770 | if (statement) statement; 771 | 772 | if (statement) 773 | statement; 774 | 775 | if (statement){ 776 | statement;} 777 | 778 | // Fold 779 | if (statement){ 780 | statement; 781 | } 782 | 783 | if () 784 | statement; 785 | else if () 786 | statement; 787 | else 788 | statement; 789 | while () 790 | statement; 791 | for () 792 | statement; 793 | switch () 794 | statement; 795 | 796 | 797 | // =========== 798 | // = Strings = 799 | // =========== 800 | 801 | // No Fold; No Indent 802 | myFunction("" 803 | statement; // Fold; Indent 804 | "") 805 | // No Fold; No Indent 806 | myArray = ["", 807 | statement; // Fold; Indent 808 | ""] 809 | // No Fold; No Indent 810 | function(){"" 811 | statement; // Fold; Indent 812 | ""} 813 | // No Fold; No Indent 814 | myFunction(")" 815 | statement; // Fold; Indent 816 | "(") 817 | // No Fold; No Indent 818 | myArray = ["]", 819 | statement; // Fold; Indent 820 | "["] 821 | // No Fold; No Indent 822 | function(){"}" 823 | statement; // Fold; Indent 824 | "{"} 825 | // No Fold; No Indent 826 | myFunction("\")" 827 | statement; // Fold; Indent 828 | "\"(") 829 | // No Fold; No Indent 830 | myArray = ["\"]", 831 | statement; // Fold; Indent 832 | "\"["] 833 | // No Fold; No Indent 834 | function(){"\"}" 835 | statement; // Fold; Indent 836 | "\"{"} 837 | // No Fold; No Indent 838 | myFunction(')' 839 | statement; // Fold; Indent 840 | '(') 841 | // No Fold; No Indent 842 | myArray = [']', 843 | statement; // Fold; Indent 844 | '['] 845 | // No Fold; No Indent 846 | function(){'}' 847 | statement; // Fold; Indent 848 | '{'} 849 | // No Fold; No Indent 850 | myFunction('\')' 851 | statement; // Fold; Indent 852 | '\'(') 853 | // No Fold; No Indent 854 | myArray = ['\']', 855 | statement; // Fold; Indent 856 | '\'['] 857 | // No Fold; No Indent 858 | function(){'\'}' 859 | statement; // Fold; Indent 860 | '\'{'} 861 | // No Fold; No Indent 862 | myFunction(/)/ 863 | statement; // Fold; Indent 864 | /(/) 865 | // No Fold; No Indent 866 | myArray = [/]/, 867 | statement; // Fold; Indent 868 | /[/] 869 | // No Fold; No Indent 870 | function(){/}/ 871 | statement; // Fold; Indent 872 | /{/} 873 | // No Fold; No Indent 874 | myFunction(/\/)/ 875 | statement; // Fold; Indent 876 | /\/(/) 877 | // No Fold; No Indent 878 | myArray = [/\/]/, 879 | statement; // Fold; Indent 880 | /\/[/] 881 | // No Fold; No Indent 882 | function(){/\/}/ 883 | statement; // Fold; Indent 884 | /\/{/} 885 | 886 | // No Fold; No Indent 887 | function(){" { "} 888 | function(){"\" { "} 889 | function(){' { '} 890 | function(){'\' { '} 891 | function(){/ \{ /} 892 | function(){/\/\{ /} 893 | myArray = [" [ "] 894 | myArray = ["\" [ "] 895 | myArray = [' [ '] 896 | myArray = ['\' [ '] 897 | myArray = [/ \[ /] 898 | myArray = [/\/\[ /] 899 | myFunction(" ( ") 900 | myFunction("\" ( ") 901 | myFunction(' ( ') 902 | myFunction('\' ( ') 903 | myFunction(/ \( /) 904 | myFunction(/\/\( /) 905 | // No Fold; No Indent 906 | function(){" } "} 907 | function(){"\" } "} 908 | function(){' } '} 909 | function(){'\' } '} 910 | function(){/ } /} 911 | function(){/\/ } /} 912 | myArray = [" ] "] 913 | myArray = ["\" ] "] 914 | myArray = [' ] '] 915 | myArray = ['\' ] '] 916 | myArray = [/ ] /] 917 | myArray = [/\/ ] /] 918 | myFunction(" ) ") 919 | myFunction("\" ) ") 920 | myFunction(' ) ') 921 | myFunction('\' ) ') 922 | myFunction(/ \) /) 923 | myFunction(/\/\) /) 924 | // No Fold; No Indent 925 | function(){"[ ]"} 926 | function(){"[\"]"} 927 | function(){'[ ]'} 928 | function(){'[\']'} 929 | function(){/[ ]/} 930 | function(){/[\/]/} 931 | function(){"( )"} 932 | function(){"(\")"} 933 | function(){'( )'} 934 | function(){'(\')'} 935 | function(){/( )/} 936 | function(){/(\/)/} 937 | function(){"{ }"} 938 | function(){"{\"}"} 939 | function(){'{ }'} 940 | function(){'{\'}'} 941 | function(){/{ }/} 942 | function(){/{\/}/} 943 | // No Fold; No Indent 944 | myArray = ["[ ]"] 945 | myArray = ["[\"]"] 946 | myArray = ['[ ]'] 947 | myArray = ['[\']'] 948 | myArray = [/[ ]/] 949 | myArray = [/[\/]/] 950 | myArray = ["( )"] 951 | myArray = ["(\")"] 952 | myArray = ['( )'] 953 | myArray = ['(\')'] 954 | myArray = [/( )/] 955 | myArray = [/(\/)/] 956 | myArray = ["{ }"] 957 | myArray = ["{\"}"] 958 | myArray = ['{ }'] 959 | myArray = ['{\'}'] 960 | myArray = [/{ }/] 961 | myArray = [/{\/}/] 962 | // No Fold; No Indent 963 | myFunction("[ ]") 964 | myFunction("[\"]") 965 | myFunction('[ ]') 966 | myFunction('[\']') 967 | myFunction(/[ ]/) 968 | myFunction(/[\/]/) 969 | myFunction("( )") 970 | myFunction("(\")") 971 | myFunction('( )') 972 | myFunction('(\')') 973 | myFunction(/( )/) 974 | myFunction(/(\/)/) 975 | myFunction("{ }") 976 | myFunction("{\"}") 977 | myFunction('{ }') 978 | myFunction('{\'}') 979 | myFunction(/{ }/) 980 | myFunction(/{\/}/) 981 | // No Fold; No Indent 982 | function(){"[ "} 983 | function(){"[\""} 984 | function(){'[ '} 985 | function(){'[\''} 986 | function(){/[ /} 987 | function(){/[\//} 988 | function(){"( "} 989 | function(){"(\""} 990 | function(){'( '} 991 | function(){'(\''} 992 | function(){/( /} 993 | function(){/(\//} 994 | function(){"{ "} 995 | function(){"{\""} 996 | function(){'{ '} 997 | function(){'{\''} 998 | function(){/{ /} 999 | function(){/{\//} 1000 | // No Fold; No Indent 1001 | myArray = ["[ ]"] 1002 | myArray = ["[\"]"] 1003 | myArray = ['[ ]'] 1004 | myArray = ['[\']'] 1005 | myArray = [/[ ]/] 1006 | myArray = [/[\/]/] 1007 | myArray = ["( )"] 1008 | myArray = ["(\")"] 1009 | myArray = ['( )'] 1010 | myArray = ['(\')'] 1011 | myArray = [/( )/] 1012 | myArray = [/(\/)/] 1013 | myArray = ["{ }"] 1014 | myArray = ["{\"}"] 1015 | myArray = ['{ }'] 1016 | myArray = ['{\'}'] 1017 | myArray = [/{ }/] 1018 | myArray = [/{\/}/] 1019 | // No Fold; No Indent 1020 | myFunction("[ ]") 1021 | myFunction("[\"]") 1022 | myFunction('[ ]') 1023 | myFunction('[\']') 1024 | myFunction(/[ ]/) 1025 | myFunction(/[\/]/) 1026 | myFunction("( )") 1027 | myFunction("(\")") 1028 | myFunction('( )') 1029 | myFunction('(\')') 1030 | myFunction(/( )/) 1031 | myFunction(/(\/)/) 1032 | myFunction("{ }") 1033 | myFunction("{\"}") 1034 | myFunction('{ }') 1035 | myFunction('{\'}') 1036 | myFunction(/{ }/) 1037 | myFunction(/{\/}/) 1038 | 1039 | 1040 | {/ 1041 | // No Fold; No Indent 1042 | }/ 1043 | {' 1044 | // No Fold; No Indent 1045 | }' 1046 | {" 1047 | // No Fold; No Indent 1048 | }" 1049 | 1050 | 1051 | // ============ 1052 | // = Comments = 1053 | // ============ 1054 | 1055 | // myFunction( 1056 | // No Fold; No Indent 1057 | // ) 1058 | // myArray = [ 1059 | // No Fold; No Indent 1060 | // ] 1061 | // function(){ 1062 | // No Fold; No Indent 1063 | // } 1064 | 1065 | 0 // myFunction( 1066 | 0 // No Fold; No Indent 1067 | 0 // ) 1068 | 0 // myArray = [ 1069 | 0 // No Fold; No Indent 1070 | 0 // ] 1071 | 0 // function(){ 1072 | 0 // No Fold; No Indent 1073 | 0 // } 1074 | 1075 | 1076 | function(){ 1077 | some_function(); 1078 | 1079 | /* ignore_first(); 1080 | ignore_second(); 1081 | */ 1082 | 1083 | more_functions(); 1084 | } 1085 | 1086 | 1087 | "" 1088 | '' 1089 | () 1090 | [] 1091 | {} 1092 | 1093 | 1094 | 1095 | // More Strings 1096 | // ============ 1097 | "[\"]" 1098 | "(\")" 1099 | "{\"}" 1100 | 1101 | "]\"[" 1102 | ")\"(" 1103 | "}\"{" 1104 | 1105 | '[\']' 1106 | '(\')' 1107 | '{\'}' 1108 | 1109 | ']\'[' 1110 | ')\'(' 1111 | '}\'{' 1112 | 1113 | 1114 | --------------------------------------------------------------------------------