From bb1e21654729c2e337ab53bb1c7345d716fc572e Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Fri, 19 Apr 2013 16:59:35 +0200 Subject: [PATCH 01/91] Bump version number post-3.12 --- lib/codemirror.js | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index a1f9277223..e8cc55e156 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -5577,7 +5577,7 @@ window.CodeMirror = (function() { // THE END - CodeMirror.version = "3.12"; + CodeMirror.version = "3.12 +"; return CodeMirror; })(); diff --git a/package.json b/package.json index 1d11264f51..021531c672 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "codemirror", - "version":"3.12.00", + "version":"3.12.01", "main": "lib/codemirror.js", "description": "In-browser code editing made bearable", "licenses": [{"type": "MIT", From fe3bc05580d822369d78f7571523d1504fee9506 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 22 Apr 2013 09:27:09 +0200 Subject: [PATCH 02/91] Add Navigate CMS to real-world uses --- doc/realworld.html | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/realworld.html b/doc/realworld.html index 576a003de0..441d136a79 100644 --- a/doc/realworld.html +++ b/doc/realworld.html @@ -69,6 +69,7 @@
  • MIHTool (iOS web-app debugging tool)
  • Mongo MapReduce WebBrowser
  • My2ndGeneration (social coding)
  • +
  • Navigate CMS
  • NoTex (rST authoring)
  • ORG (z80 assembly IDE)
  • Orion-CodeMirror integration (running CodeMirror modes in Orion)
  • From 3b6f12e5106b08deea8f48f74387c6129a04a0c6 Mon Sep 17 00:00:00 2001 From: lynschinzer Date: Sun, 21 Apr 2013 13:13:05 +0200 Subject: [PATCH 03/91] [vim keymap] Fix HML test broken on Firefox and Opera --- test/vim_test.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/test/vim_test.js b/test/vim_test.js index 7d4dde8585..f958c5fd1a 100644 --- a/test/vim_test.js +++ b/test/vim_test.js @@ -1402,14 +1402,16 @@ testVim('Ty,;', function(cm, vim, helpers) { eq('01230123456789', cm.getValue()); }, { value: '0123456789'}); testVim('HML', function(cm, vim, helpers) { - cm.setSize(600, 400); + var lines = 35; + var textHeight = cm.defaultTextHeight(); + cm.setSize(600, lines*textHeight); cm.setCursor(120, 0); helpers.doKeys('H'); - helpers.assertCursorAt(90, 2); + helpers.assertCursorAt(86, 2); helpers.doKeys('L'); - helpers.assertCursorAt(119, 4); + helpers.assertCursorAt(120, 4); helpers.doKeys('M'); - helpers.assertCursorAt(104,4); + helpers.assertCursorAt(103,4); }, { value: (function(){ var upperLines = new Array(100); var lowerLines = new Array(100); From f7642e5405cca42d538db04e1d8777da7d892c6d Mon Sep 17 00:00:00 2001 From: Gautam Mehta Date: Sun, 21 Apr 2013 16:41:46 +0800 Subject: [PATCH 04/91] Cobol Mode include cobol mode --- mode/cobol/cobol.js | 241 ++++++++++++++++++++++++++++++++++++++++++++++++++ mode/cobol/index.html | 195 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 436 insertions(+) create mode 100644 mode/cobol/cobol.js create mode 100644 mode/cobol/index.html diff --git a/mode/cobol/cobol.js b/mode/cobol/cobol.js new file mode 100644 index 0000000000..8f45e3bbd8 --- /dev/null +++ b/mode/cobol/cobol.js @@ -0,0 +1,241 @@ +/** + * Author: Gautam Mehta + * Branched from CodeMirror's Scheme mode + */ +CodeMirror.defineMode("cobol", function () { + var BUILTIN = "builtin", COMMENT = "comment", STRING = "string", CHARACTER = "string-2", + ATOM = "atom", NUMBER = "number", BRACKET = "bracket", KEYWORD = "keyword", MODTAG = "header", + COBOLLINENUM = "def", PERIOD = "link"; + function makeKeywords(str) { + var obj = {}, words = str.split(" "); + for (var i = 0; i < words.length; ++i) obj[words[i]] = true; + return obj; + } + var atoms = makeKeywords("TRUE FALSE ZEROES ZEROS ZERO SPACES SPACE LOW-VALUE LOW-VALUES "); + var keywords = makeKeywords( + "ACCEPT ACCESS ACQUIRE ADD ADDRESS " + + "ADVANCING AFTER ALIAS ALL ALPHABET " + + "ALPHABETIC ALPHABETIC-LOWER ALPHABETIC-UPPER ALPHANUMERIC ALPHANUMERIC-EDITED " + + "ALSO ALTER ALTERNATE AND ANY " + + "ARE AREA AREAS ARITHMETIC ASCENDING " + + "ASSIGN AT ATTRIBUTE AUTHOR AUTO " + + "AUTO-SKIP AUTOMATIC B-AND B-EXOR B-LESS " + + "B-NOT B-OR BACKGROUND-COLOR BACKGROUND-COLOUR BEEP " + + "BEFORE BELL BINARY BIT BITS " + + "BLANK BLINK BLOCK BOOLEAN BOTTOM " + + "BY CALL CANCEL CD CF " + + "CH CHARACTER CHARACTERS CLASS CLOCK-UNITS " + + "CLOSE COBOL CODE CODE-SET COL " + + "COLLATING COLUMN COMMA COMMIT COMMITMENT " + + "COMMON COMMUNICATION COMP COMP-0 COMP-1 " + + "COMP-2 COMP-3 COMP-4 COMP-5 COMP-6 " + + "COMP-7 COMP-8 COMP-9 COMPUTATIONAL COMPUTATIONAL-0 " + + "COMPUTATIONAL-1 COMPUTATIONAL-2 COMPUTATIONAL-3 COMPUTATIONAL-4 COMPUTATIONAL-5 " + + "COMPUTATIONAL-6 COMPUTATIONAL-7 COMPUTATIONAL-8 COMPUTATIONAL-9 COMPUTE " + + "CONFIGURATION CONNECT CONSOLE CONTAINED CONTAINS " + + "CONTENT CONTINUE CONTROL CONTROL-AREA CONTROLS " + + "CONVERTING COPY CORR CORRESPONDING COUNT " + + "CRT CRT-UNDER CURRENCY CURRENT CURSOR " + + "DATA DATE DATE-COMPILED DATE-WRITTEN DAY " + + "DAY-OF-WEEK DB DB-ACCESS-CONTROL-KEY DB-DATA-NAME DB-EXCEPTION " + + "DB-FORMAT-NAME DB-RECORD-NAME DB-SET-NAME DB-STATUS DBCS " + + "DBCS-EDITED DE DEBUG-CONTENTS DEBUG-ITEM DEBUG-LINE " + + "DEBUG-NAME DEBUG-SUB-1 DEBUG-SUB-2 DEBUG-SUB-3 DEBUGGING " + + "DECIMAL-POINT DECLARATIVES DEFAULT DELETE DELIMITED " + + "DELIMITER DEPENDING DESCENDING DESCRIBED DESTINATION " + + "DETAIL DISABLE DISCONNECT DISPLAY DISPLAY-1 " + + "DISPLAY-2 DISPLAY-3 DISPLAY-4 DISPLAY-5 DISPLAY-6 " + + "DISPLAY-7 DISPLAY-8 DISPLAY-9 DIVIDE DIVISION " + + "DOWN DROP DUPLICATE DUPLICATES DYNAMIC " + + "EBCDIC EGI EJECT ELSE EMI " + + "EMPTY EMPTY-CHECK ENABLE END END. END-ACCEPT END-ACCEPT. " + + "END-ADD END-CALL END-COMPUTE END-DELETE END-DISPLAY " + + "END-DIVIDE END-EVALUATE END-IF END-INVOKE END-MULTIPLY " + + "END-OF-PAGE END-PERFORM END-READ END-RECEIVE END-RETURN " + + "END-REWRITE END-SEARCH END-START END-STRING END-SUBTRACT " + + "END-UNSTRING END-WRITE END-XML ENTER ENTRY " + + "ENVIRONMENT EOP EQUAL EQUALS ERASE " + + "ERROR ESI EVALUATE EVERY EXCEEDS " + + "EXCEPTION EXCLUSIVE EXIT EXTEND EXTERNAL " + + "EXTERNALLY-DESCRIBED-KEY FD FETCH FILE FILE-CONTROL " + + "FILE-STREAM FILES FILLER FINAL FIND " + + "FINISH FIRST FOOTING FOR FOREGROUND-COLOR " + + "FOREGROUND-COLOUR FORMAT FREE FROM FULL " + + "FUNCTION GENERATE GET GIVING GLOBAL " + + "GO GOBACK GREATER GROUP HEADING " + + "HIGH-VALUE HIGH-VALUES HIGHLIGHT I-O I-O-CONTROL " + + "ID IDENTIFICATION IF IN INDEX " + + "INDEX-1 INDEX-2 INDEX-3 INDEX-4 INDEX-5 " + + "INDEX-6 INDEX-7 INDEX-8 INDEX-9 INDEXED " + + "INDIC INDICATE INDICATOR INDICATORS INITIAL " + + "INITIALIZE INITIATE INPUT INPUT-OUTPUT INSPECT " + + "INSTALLATION INTO INVALID INVOKE IS " + + "JUST JUSTIFIED KANJI KEEP KEY " + + "LABEL LAST LD LEADING LEFT " + + "LEFT-JUSTIFY LENGTH LENGTH-CHECK LESS LIBRARY " + + "LIKE LIMIT LIMITS LINAGE LINAGE-COUNTER " + + "LINE LINE-COUNTER LINES LINKAGE LOCAL-STORAGE " + + "LOCALE LOCALLY LOCK " + + "MEMBER MEMORY MERGE MESSAGE METACLASS " + + "MODE MODIFIED MODIFY MODULES MOVE " + + "MULTIPLE MULTIPLY NATIONAL NATIVE NEGATIVE " + + "NEXT NO NO-ECHO NONE NOT " + + "NULL NULL-KEY-MAP NULL-MAP NULLS NUMBER " + + "NUMERIC NUMERIC-EDITED OBJECT OBJECT-COMPUTER OCCURS " + + "OF OFF OMITTED ON ONLY " + + "OPEN OPTIONAL OR ORDER ORGANIZATION " + + "OTHER OUTPUT OVERFLOW OWNER PACKED-DECIMAL " + + "PADDING PAGE PAGE-COUNTER PARSE PERFORM " + + "PF PH PIC PICTURE PLUS " + + "POINTER POSITION POSITIVE PREFIX PRESENT " + + "PRINTING PRIOR PROCEDURE PROCEDURE-POINTER PROCEDURES " + + "PROCEED PROCESS PROCESSING PROGRAM PROGRAM-ID " + + "PROMPT PROTECTED PURGE QUEUE QUOTE " + + "QUOTES RANDOM RD READ READY " + + "REALM RECEIVE RECONNECT RECORD RECORD-NAME " + + "RECORDS RECURSIVE REDEFINES REEL REFERENCE " + + "REFERENCE-MONITOR REFERENCES RELATION RELATIVE RELEASE " + + "REMAINDER REMOVAL RENAMES REPEATED REPLACE " + + "REPLACING REPORT REPORTING REPORTS REPOSITORY " + + "REQUIRED RERUN RESERVE RESET RETAINING " + + "RETRIEVAL RETURN RETURN-CODE RETURNING REVERSE-VIDEO " + + "REVERSED REWIND REWRITE RF RH " + + "RIGHT RIGHT-JUSTIFY ROLLBACK ROLLING ROUNDED " + + "RUN SAME SCREEN SD SEARCH " + + "SECTION SECURE SECURITY SEGMENT SEGMENT-LIMIT " + + "SELECT SEND SENTENCE SEPARATE SEQUENCE " + + "SEQUENTIAL SET SHARED SIGN SIZE " + + "SKIP1 SKIP2 SKIP3 SORT SORT-MERGE " + + "SORT-RETURN SOURCE SOURCE-COMPUTER SPACE-FILL " + + "SPECIAL-NAMES STANDARD STANDARD-1 STANDARD-2 " + + "START STARTING STATUS STOP STORE " + + "STRING SUB-QUEUE-1 SUB-QUEUE-2 SUB-QUEUE-3 SUB-SCHEMA " + + "SUBFILE SUBSTITUTE SUBTRACT SUM SUPPRESS " + + "SYMBOLIC SYNC SYNCHRONIZED SYSIN SYSOUT " + + "TABLE TALLYING TAPE TENANT TERMINAL " + + "TERMINATE TEST TEXT THAN THEN " + + "THROUGH THRU TIME TIMES TITLE " + + "TO TOP TRAILING TRAILING-SIGN TRANSACTION " + + "TYPE TYPEDEF UNDERLINE UNEQUAL UNIT " + + "UNSTRING UNTIL UP UPDATE UPON " + + "USAGE USAGE-MODE USE USING VALID " + + "VALIDATE VALUE VALUES VARYING VLR " + + "WAIT WHEN WHEN-COMPILED WITH WITHIN " + + "WORDS WORKING-STORAGE WRITE XML XML-CODE " + + "XML-EVENT XML-NTEXT XML-TEXT ZERO ZERO-FILL " ); + + var builtins = makeKeywords("- * ** / + < <= = > >= "); + var indentKeys = makeKeywords(""); + var tests = { + digit: /\d/, + digit_or_colon: /[\d:]/, + hex: /[0-9a-f]/i, + sign: /[+-]/, + exponent: /e/i, + keyword_char: /[^\s\(\[\;\)\]]/, + symbol: /[\w*+\-]/ + }; + function isNumber(ch, stream){ + // hex + if ( ch === '0' && stream.eat(/x/i) ) { + stream.eatWhile(tests.hex); + return true; + } + // leading sign + if ( ( ch == '+' || ch == '-' ) && ( tests.digit.test(stream.peek()) ) ) { + stream.eat(tests.sign); + ch = stream.next(); + } + if ( tests.digit.test(ch) ) { + stream.eat(ch); + stream.eatWhile(tests.digit); + if ( '.' == stream.peek()) { + stream.eat('.'); + stream.eatWhile(tests.digit); + } + if ( stream.eat(tests.exponent) ) { + stream.eat(tests.sign); + stream.eatWhile(tests.digit); + } + return true; + } + return false; + } + return { + startState: function () { + return { + indentStack: null, + indentation: 0, + mode: false + }; + }, + token: function (stream, state) { + if (state.indentStack == null && stream.sol()) { + // update indentation, but only if indentStack is empty + state.indentation = 6 ; //stream.indentation(); + } + // skip spaces + if (stream.eatSpace()) { + return null; + } + var returnType = null; + switch(state.mode){ + case "string": // multi-line string parsing mode + var next = false; + while ((next = stream.next()) != null) { + if (next == "\"" || next == "\'") { + state.mode = false; + break; + } + } + returnType = STRING; // continue on in string mode + break; + default: // default parsing mode + var ch = stream.next(); + var col = stream.column(); + if (col >= 0 && col <= 5) { + returnType = COBOLLINENUM; + } else if (col >= 72 && col <= 79) { + stream.skipToEnd(); + returnType = MODTAG; + } else if (ch == "*" && col == 6) { // comment + stream.skipToEnd(); // rest of the line is a comment + returnType = COMMENT; + } else if (ch == "\"" || ch == "\'") { + state.mode = "string"; + returnType = STRING; + } else if (ch == "'" && !( tests.digit_or_colon.test(stream.peek()) )) { + returnType = ATOM; + } else if (ch == ".") { + returnType = PERIOD; + } else if (isNumber(ch,stream)){ + returnType = NUMBER; + } else { + if (stream.current().match(tests.symbol)) { + while (col < 71) { + if (stream.eat(tests.symbol) === undefined) { + break; + } else { + col++; + } + } + } + if (keywords && keywords.propertyIsEnumerable(stream.current().toUpperCase())) { + returnType = KEYWORD; + } else if (builtins && builtins.propertyIsEnumerable(stream.current().toUpperCase())) { + returnType = BUILTIN; + } else if (atoms && atoms.propertyIsEnumerable(stream.current().toUpperCase())) { + returnType = ATOM; + } else returnType = null; + } + } + return returnType; + }, + indent: function (state) { + if (state.indentStack == null) return state.indentation; + return state.indentStack.indent; + } + }; +}); + +CodeMirror.defineMIME("text/cbl", "cobol"); diff --git a/mode/cobol/index.html b/mode/cobol/index.html new file mode 100644 index 0000000000..c66a0e8619 --- /dev/null +++ b/mode/cobol/index.html @@ -0,0 +1,195 @@ + + + + + CodeMirror: COBOL mode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    Select Theme Select Font Size + + + + +

    + + + + From 1ecf154e62ff931f77894e966995bd19b3db0105 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 22 Apr 2013 12:58:00 +0200 Subject: [PATCH 05/91] [cobol mode] Integrate Issue #1465 --- doc/compress.html | 1 + doc/modes.html | 1 + mode/cobol/cobol.js | 459 +++++++++++++++++++++++++------------------------- mode/cobol/index.html | 118 ++++++------- mode/meta.js | 1 + 5 files changed, 291 insertions(+), 289 deletions(-) diff --git a/doc/compress.html b/doc/compress.html index f1fa218def..c51b2833e0 100644 --- a/doc/compress.html +++ b/doc/compress.html @@ -73,6 +73,7 @@ + diff --git a/doc/modes.html b/doc/modes.html index d016aca8ee..ac476bef78 100644 --- a/doc/modes.html +++ b/doc/modes.html @@ -27,6 +27,7 @@
  • Asterisk dialplan
  • C, C++, C#
  • Clojure
  • +
  • COBOL
  • CoffeeScript
  • Common Lisp
  • CSS
  • diff --git a/mode/cobol/cobol.js b/mode/cobol/cobol.js index 8f45e3bbd8..d92491dde8 100644 --- a/mode/cobol/cobol.js +++ b/mode/cobol/cobol.js @@ -1,241 +1,240 @@ /** * Author: Gautam Mehta - * Branched from CodeMirror's Scheme mode + * Branched from CodeMirror's Scheme mode */ CodeMirror.defineMode("cobol", function () { - var BUILTIN = "builtin", COMMENT = "comment", STRING = "string", CHARACTER = "string-2", - ATOM = "atom", NUMBER = "number", BRACKET = "bracket", KEYWORD = "keyword", MODTAG = "header", - COBOLLINENUM = "def", PERIOD = "link"; - function makeKeywords(str) { - var obj = {}, words = str.split(" "); - for (var i = 0; i < words.length; ++i) obj[words[i]] = true; - return obj; + var BUILTIN = "builtin", COMMENT = "comment", STRING = "string", + ATOM = "atom", NUMBER = "number", KEYWORD = "keyword", MODTAG = "header", + COBOLLINENUM = "def", PERIOD = "link"; + function makeKeywords(str) { + var obj = {}, words = str.split(" "); + for (var i = 0; i < words.length; ++i) obj[words[i]] = true; + return obj; + } + var atoms = makeKeywords("TRUE FALSE ZEROES ZEROS ZERO SPACES SPACE LOW-VALUE LOW-VALUES "); + var keywords = makeKeywords( + "ACCEPT ACCESS ACQUIRE ADD ADDRESS " + + "ADVANCING AFTER ALIAS ALL ALPHABET " + + "ALPHABETIC ALPHABETIC-LOWER ALPHABETIC-UPPER ALPHANUMERIC ALPHANUMERIC-EDITED " + + "ALSO ALTER ALTERNATE AND ANY " + + "ARE AREA AREAS ARITHMETIC ASCENDING " + + "ASSIGN AT ATTRIBUTE AUTHOR AUTO " + + "AUTO-SKIP AUTOMATIC B-AND B-EXOR B-LESS " + + "B-NOT B-OR BACKGROUND-COLOR BACKGROUND-COLOUR BEEP " + + "BEFORE BELL BINARY BIT BITS " + + "BLANK BLINK BLOCK BOOLEAN BOTTOM " + + "BY CALL CANCEL CD CF " + + "CH CHARACTER CHARACTERS CLASS CLOCK-UNITS " + + "CLOSE COBOL CODE CODE-SET COL " + + "COLLATING COLUMN COMMA COMMIT COMMITMENT " + + "COMMON COMMUNICATION COMP COMP-0 COMP-1 " + + "COMP-2 COMP-3 COMP-4 COMP-5 COMP-6 " + + "COMP-7 COMP-8 COMP-9 COMPUTATIONAL COMPUTATIONAL-0 " + + "COMPUTATIONAL-1 COMPUTATIONAL-2 COMPUTATIONAL-3 COMPUTATIONAL-4 COMPUTATIONAL-5 " + + "COMPUTATIONAL-6 COMPUTATIONAL-7 COMPUTATIONAL-8 COMPUTATIONAL-9 COMPUTE " + + "CONFIGURATION CONNECT CONSOLE CONTAINED CONTAINS " + + "CONTENT CONTINUE CONTROL CONTROL-AREA CONTROLS " + + "CONVERTING COPY CORR CORRESPONDING COUNT " + + "CRT CRT-UNDER CURRENCY CURRENT CURSOR " + + "DATA DATE DATE-COMPILED DATE-WRITTEN DAY " + + "DAY-OF-WEEK DB DB-ACCESS-CONTROL-KEY DB-DATA-NAME DB-EXCEPTION " + + "DB-FORMAT-NAME DB-RECORD-NAME DB-SET-NAME DB-STATUS DBCS " + + "DBCS-EDITED DE DEBUG-CONTENTS DEBUG-ITEM DEBUG-LINE " + + "DEBUG-NAME DEBUG-SUB-1 DEBUG-SUB-2 DEBUG-SUB-3 DEBUGGING " + + "DECIMAL-POINT DECLARATIVES DEFAULT DELETE DELIMITED " + + "DELIMITER DEPENDING DESCENDING DESCRIBED DESTINATION " + + "DETAIL DISABLE DISCONNECT DISPLAY DISPLAY-1 " + + "DISPLAY-2 DISPLAY-3 DISPLAY-4 DISPLAY-5 DISPLAY-6 " + + "DISPLAY-7 DISPLAY-8 DISPLAY-9 DIVIDE DIVISION " + + "DOWN DROP DUPLICATE DUPLICATES DYNAMIC " + + "EBCDIC EGI EJECT ELSE EMI " + + "EMPTY EMPTY-CHECK ENABLE END END. END-ACCEPT END-ACCEPT. " + + "END-ADD END-CALL END-COMPUTE END-DELETE END-DISPLAY " + + "END-DIVIDE END-EVALUATE END-IF END-INVOKE END-MULTIPLY " + + "END-OF-PAGE END-PERFORM END-READ END-RECEIVE END-RETURN " + + "END-REWRITE END-SEARCH END-START END-STRING END-SUBTRACT " + + "END-UNSTRING END-WRITE END-XML ENTER ENTRY " + + "ENVIRONMENT EOP EQUAL EQUALS ERASE " + + "ERROR ESI EVALUATE EVERY EXCEEDS " + + "EXCEPTION EXCLUSIVE EXIT EXTEND EXTERNAL " + + "EXTERNALLY-DESCRIBED-KEY FD FETCH FILE FILE-CONTROL " + + "FILE-STREAM FILES FILLER FINAL FIND " + + "FINISH FIRST FOOTING FOR FOREGROUND-COLOR " + + "FOREGROUND-COLOUR FORMAT FREE FROM FULL " + + "FUNCTION GENERATE GET GIVING GLOBAL " + + "GO GOBACK GREATER GROUP HEADING " + + "HIGH-VALUE HIGH-VALUES HIGHLIGHT I-O I-O-CONTROL " + + "ID IDENTIFICATION IF IN INDEX " + + "INDEX-1 INDEX-2 INDEX-3 INDEX-4 INDEX-5 " + + "INDEX-6 INDEX-7 INDEX-8 INDEX-9 INDEXED " + + "INDIC INDICATE INDICATOR INDICATORS INITIAL " + + "INITIALIZE INITIATE INPUT INPUT-OUTPUT INSPECT " + + "INSTALLATION INTO INVALID INVOKE IS " + + "JUST JUSTIFIED KANJI KEEP KEY " + + "LABEL LAST LD LEADING LEFT " + + "LEFT-JUSTIFY LENGTH LENGTH-CHECK LESS LIBRARY " + + "LIKE LIMIT LIMITS LINAGE LINAGE-COUNTER " + + "LINE LINE-COUNTER LINES LINKAGE LOCAL-STORAGE " + + "LOCALE LOCALLY LOCK " + + "MEMBER MEMORY MERGE MESSAGE METACLASS " + + "MODE MODIFIED MODIFY MODULES MOVE " + + "MULTIPLE MULTIPLY NATIONAL NATIVE NEGATIVE " + + "NEXT NO NO-ECHO NONE NOT " + + "NULL NULL-KEY-MAP NULL-MAP NULLS NUMBER " + + "NUMERIC NUMERIC-EDITED OBJECT OBJECT-COMPUTER OCCURS " + + "OF OFF OMITTED ON ONLY " + + "OPEN OPTIONAL OR ORDER ORGANIZATION " + + "OTHER OUTPUT OVERFLOW OWNER PACKED-DECIMAL " + + "PADDING PAGE PAGE-COUNTER PARSE PERFORM " + + "PF PH PIC PICTURE PLUS " + + "POINTER POSITION POSITIVE PREFIX PRESENT " + + "PRINTING PRIOR PROCEDURE PROCEDURE-POINTER PROCEDURES " + + "PROCEED PROCESS PROCESSING PROGRAM PROGRAM-ID " + + "PROMPT PROTECTED PURGE QUEUE QUOTE " + + "QUOTES RANDOM RD READ READY " + + "REALM RECEIVE RECONNECT RECORD RECORD-NAME " + + "RECORDS RECURSIVE REDEFINES REEL REFERENCE " + + "REFERENCE-MONITOR REFERENCES RELATION RELATIVE RELEASE " + + "REMAINDER REMOVAL RENAMES REPEATED REPLACE " + + "REPLACING REPORT REPORTING REPORTS REPOSITORY " + + "REQUIRED RERUN RESERVE RESET RETAINING " + + "RETRIEVAL RETURN RETURN-CODE RETURNING REVERSE-VIDEO " + + "REVERSED REWIND REWRITE RF RH " + + "RIGHT RIGHT-JUSTIFY ROLLBACK ROLLING ROUNDED " + + "RUN SAME SCREEN SD SEARCH " + + "SECTION SECURE SECURITY SEGMENT SEGMENT-LIMIT " + + "SELECT SEND SENTENCE SEPARATE SEQUENCE " + + "SEQUENTIAL SET SHARED SIGN SIZE " + + "SKIP1 SKIP2 SKIP3 SORT SORT-MERGE " + + "SORT-RETURN SOURCE SOURCE-COMPUTER SPACE-FILL " + + "SPECIAL-NAMES STANDARD STANDARD-1 STANDARD-2 " + + "START STARTING STATUS STOP STORE " + + "STRING SUB-QUEUE-1 SUB-QUEUE-2 SUB-QUEUE-3 SUB-SCHEMA " + + "SUBFILE SUBSTITUTE SUBTRACT SUM SUPPRESS " + + "SYMBOLIC SYNC SYNCHRONIZED SYSIN SYSOUT " + + "TABLE TALLYING TAPE TENANT TERMINAL " + + "TERMINATE TEST TEXT THAN THEN " + + "THROUGH THRU TIME TIMES TITLE " + + "TO TOP TRAILING TRAILING-SIGN TRANSACTION " + + "TYPE TYPEDEF UNDERLINE UNEQUAL UNIT " + + "UNSTRING UNTIL UP UPDATE UPON " + + "USAGE USAGE-MODE USE USING VALID " + + "VALIDATE VALUE VALUES VARYING VLR " + + "WAIT WHEN WHEN-COMPILED WITH WITHIN " + + "WORDS WORKING-STORAGE WRITE XML XML-CODE " + + "XML-EVENT XML-NTEXT XML-TEXT ZERO ZERO-FILL " ); + + var builtins = makeKeywords("- * ** / + < <= = > >= "); + var tests = { + digit: /\d/, + digit_or_colon: /[\d:]/, + hex: /[0-9a-f]/i, + sign: /[+-]/, + exponent: /e/i, + keyword_char: /[^\s\(\[\;\)\]]/, + symbol: /[\w*+\-]/ + }; + function isNumber(ch, stream){ + // hex + if ( ch === '0' && stream.eat(/x/i) ) { + stream.eatWhile(tests.hex); + return true; } - var atoms = makeKeywords("TRUE FALSE ZEROES ZEROS ZERO SPACES SPACE LOW-VALUE LOW-VALUES "); - var keywords = makeKeywords( - "ACCEPT ACCESS ACQUIRE ADD ADDRESS " + - "ADVANCING AFTER ALIAS ALL ALPHABET " + - "ALPHABETIC ALPHABETIC-LOWER ALPHABETIC-UPPER ALPHANUMERIC ALPHANUMERIC-EDITED " + - "ALSO ALTER ALTERNATE AND ANY " + - "ARE AREA AREAS ARITHMETIC ASCENDING " + - "ASSIGN AT ATTRIBUTE AUTHOR AUTO " + - "AUTO-SKIP AUTOMATIC B-AND B-EXOR B-LESS " + - "B-NOT B-OR BACKGROUND-COLOR BACKGROUND-COLOUR BEEP " + - "BEFORE BELL BINARY BIT BITS " + - "BLANK BLINK BLOCK BOOLEAN BOTTOM " + - "BY CALL CANCEL CD CF " + - "CH CHARACTER CHARACTERS CLASS CLOCK-UNITS " + - "CLOSE COBOL CODE CODE-SET COL " + - "COLLATING COLUMN COMMA COMMIT COMMITMENT " + - "COMMON COMMUNICATION COMP COMP-0 COMP-1 " + - "COMP-2 COMP-3 COMP-4 COMP-5 COMP-6 " + - "COMP-7 COMP-8 COMP-9 COMPUTATIONAL COMPUTATIONAL-0 " + - "COMPUTATIONAL-1 COMPUTATIONAL-2 COMPUTATIONAL-3 COMPUTATIONAL-4 COMPUTATIONAL-5 " + - "COMPUTATIONAL-6 COMPUTATIONAL-7 COMPUTATIONAL-8 COMPUTATIONAL-9 COMPUTE " + - "CONFIGURATION CONNECT CONSOLE CONTAINED CONTAINS " + - "CONTENT CONTINUE CONTROL CONTROL-AREA CONTROLS " + - "CONVERTING COPY CORR CORRESPONDING COUNT " + - "CRT CRT-UNDER CURRENCY CURRENT CURSOR " + - "DATA DATE DATE-COMPILED DATE-WRITTEN DAY " + - "DAY-OF-WEEK DB DB-ACCESS-CONTROL-KEY DB-DATA-NAME DB-EXCEPTION " + - "DB-FORMAT-NAME DB-RECORD-NAME DB-SET-NAME DB-STATUS DBCS " + - "DBCS-EDITED DE DEBUG-CONTENTS DEBUG-ITEM DEBUG-LINE " + - "DEBUG-NAME DEBUG-SUB-1 DEBUG-SUB-2 DEBUG-SUB-3 DEBUGGING " + - "DECIMAL-POINT DECLARATIVES DEFAULT DELETE DELIMITED " + - "DELIMITER DEPENDING DESCENDING DESCRIBED DESTINATION " + - "DETAIL DISABLE DISCONNECT DISPLAY DISPLAY-1 " + - "DISPLAY-2 DISPLAY-3 DISPLAY-4 DISPLAY-5 DISPLAY-6 " + - "DISPLAY-7 DISPLAY-8 DISPLAY-9 DIVIDE DIVISION " + - "DOWN DROP DUPLICATE DUPLICATES DYNAMIC " + - "EBCDIC EGI EJECT ELSE EMI " + - "EMPTY EMPTY-CHECK ENABLE END END. END-ACCEPT END-ACCEPT. " + - "END-ADD END-CALL END-COMPUTE END-DELETE END-DISPLAY " + - "END-DIVIDE END-EVALUATE END-IF END-INVOKE END-MULTIPLY " + - "END-OF-PAGE END-PERFORM END-READ END-RECEIVE END-RETURN " + - "END-REWRITE END-SEARCH END-START END-STRING END-SUBTRACT " + - "END-UNSTRING END-WRITE END-XML ENTER ENTRY " + - "ENVIRONMENT EOP EQUAL EQUALS ERASE " + - "ERROR ESI EVALUATE EVERY EXCEEDS " + - "EXCEPTION EXCLUSIVE EXIT EXTEND EXTERNAL " + - "EXTERNALLY-DESCRIBED-KEY FD FETCH FILE FILE-CONTROL " + - "FILE-STREAM FILES FILLER FINAL FIND " + - "FINISH FIRST FOOTING FOR FOREGROUND-COLOR " + - "FOREGROUND-COLOUR FORMAT FREE FROM FULL " + - "FUNCTION GENERATE GET GIVING GLOBAL " + - "GO GOBACK GREATER GROUP HEADING " + - "HIGH-VALUE HIGH-VALUES HIGHLIGHT I-O I-O-CONTROL " + - "ID IDENTIFICATION IF IN INDEX " + - "INDEX-1 INDEX-2 INDEX-3 INDEX-4 INDEX-5 " + - "INDEX-6 INDEX-7 INDEX-8 INDEX-9 INDEXED " + - "INDIC INDICATE INDICATOR INDICATORS INITIAL " + - "INITIALIZE INITIATE INPUT INPUT-OUTPUT INSPECT " + - "INSTALLATION INTO INVALID INVOKE IS " + - "JUST JUSTIFIED KANJI KEEP KEY " + - "LABEL LAST LD LEADING LEFT " + - "LEFT-JUSTIFY LENGTH LENGTH-CHECK LESS LIBRARY " + - "LIKE LIMIT LIMITS LINAGE LINAGE-COUNTER " + - "LINE LINE-COUNTER LINES LINKAGE LOCAL-STORAGE " + - "LOCALE LOCALLY LOCK " + - "MEMBER MEMORY MERGE MESSAGE METACLASS " + - "MODE MODIFIED MODIFY MODULES MOVE " + - "MULTIPLE MULTIPLY NATIONAL NATIVE NEGATIVE " + - "NEXT NO NO-ECHO NONE NOT " + - "NULL NULL-KEY-MAP NULL-MAP NULLS NUMBER " + - "NUMERIC NUMERIC-EDITED OBJECT OBJECT-COMPUTER OCCURS " + - "OF OFF OMITTED ON ONLY " + - "OPEN OPTIONAL OR ORDER ORGANIZATION " + - "OTHER OUTPUT OVERFLOW OWNER PACKED-DECIMAL " + - "PADDING PAGE PAGE-COUNTER PARSE PERFORM " + - "PF PH PIC PICTURE PLUS " + - "POINTER POSITION POSITIVE PREFIX PRESENT " + - "PRINTING PRIOR PROCEDURE PROCEDURE-POINTER PROCEDURES " + - "PROCEED PROCESS PROCESSING PROGRAM PROGRAM-ID " + - "PROMPT PROTECTED PURGE QUEUE QUOTE " + - "QUOTES RANDOM RD READ READY " + - "REALM RECEIVE RECONNECT RECORD RECORD-NAME " + - "RECORDS RECURSIVE REDEFINES REEL REFERENCE " + - "REFERENCE-MONITOR REFERENCES RELATION RELATIVE RELEASE " + - "REMAINDER REMOVAL RENAMES REPEATED REPLACE " + - "REPLACING REPORT REPORTING REPORTS REPOSITORY " + - "REQUIRED RERUN RESERVE RESET RETAINING " + - "RETRIEVAL RETURN RETURN-CODE RETURNING REVERSE-VIDEO " + - "REVERSED REWIND REWRITE RF RH " + - "RIGHT RIGHT-JUSTIFY ROLLBACK ROLLING ROUNDED " + - "RUN SAME SCREEN SD SEARCH " + - "SECTION SECURE SECURITY SEGMENT SEGMENT-LIMIT " + - "SELECT SEND SENTENCE SEPARATE SEQUENCE " + - "SEQUENTIAL SET SHARED SIGN SIZE " + - "SKIP1 SKIP2 SKIP3 SORT SORT-MERGE " + - "SORT-RETURN SOURCE SOURCE-COMPUTER SPACE-FILL " + - "SPECIAL-NAMES STANDARD STANDARD-1 STANDARD-2 " + - "START STARTING STATUS STOP STORE " + - "STRING SUB-QUEUE-1 SUB-QUEUE-2 SUB-QUEUE-3 SUB-SCHEMA " + - "SUBFILE SUBSTITUTE SUBTRACT SUM SUPPRESS " + - "SYMBOLIC SYNC SYNCHRONIZED SYSIN SYSOUT " + - "TABLE TALLYING TAPE TENANT TERMINAL " + - "TERMINATE TEST TEXT THAN THEN " + - "THROUGH THRU TIME TIMES TITLE " + - "TO TOP TRAILING TRAILING-SIGN TRANSACTION " + - "TYPE TYPEDEF UNDERLINE UNEQUAL UNIT " + - "UNSTRING UNTIL UP UPDATE UPON " + - "USAGE USAGE-MODE USE USING VALID " + - "VALIDATE VALUE VALUES VARYING VLR " + - "WAIT WHEN WHEN-COMPILED WITH WITHIN " + - "WORDS WORKING-STORAGE WRITE XML XML-CODE " + - "XML-EVENT XML-NTEXT XML-TEXT ZERO ZERO-FILL " ); - - var builtins = makeKeywords("- * ** / + < <= = > >= "); - var indentKeys = makeKeywords(""); - var tests = { - digit: /\d/, - digit_or_colon: /[\d:]/, - hex: /[0-9a-f]/i, - sign: /[+-]/, - exponent: /e/i, - keyword_char: /[^\s\(\[\;\)\]]/, - symbol: /[\w*+\-]/ - }; - function isNumber(ch, stream){ - // hex - if ( ch === '0' && stream.eat(/x/i) ) { - stream.eatWhile(tests.hex); - return true; - } - // leading sign - if ( ( ch == '+' || ch == '-' ) && ( tests.digit.test(stream.peek()) ) ) { - stream.eat(tests.sign); - ch = stream.next(); + // leading sign + if ( ( ch == '+' || ch == '-' ) && ( tests.digit.test(stream.peek()) ) ) { + stream.eat(tests.sign); + ch = stream.next(); + } + if ( tests.digit.test(ch) ) { + stream.eat(ch); + stream.eatWhile(tests.digit); + if ( '.' == stream.peek()) { + stream.eat('.'); + stream.eatWhile(tests.digit); + } + if ( stream.eat(tests.exponent) ) { + stream.eat(tests.sign); + stream.eatWhile(tests.digit); + } + return true; + } + return false; + } + return { + startState: function () { + return { + indentStack: null, + indentation: 0, + mode: false + }; + }, + token: function (stream, state) { + if (state.indentStack == null && stream.sol()) { + // update indentation, but only if indentStack is empty + state.indentation = 6 ; //stream.indentation(); + } + // skip spaces + if (stream.eatSpace()) { + return null; + } + var returnType = null; + switch(state.mode){ + case "string": // multi-line string parsing mode + var next = false; + while ((next = stream.next()) != null) { + if (next == "\"" || next == "\'") { + state.mode = false; + break; + } } - if ( tests.digit.test(ch) ) { - stream.eat(ch); - stream.eatWhile(tests.digit); - if ( '.' == stream.peek()) { - stream.eat('.'); - stream.eatWhile(tests.digit); + returnType = STRING; // continue on in string mode + break; + default: // default parsing mode + var ch = stream.next(); + var col = stream.column(); + if (col >= 0 && col <= 5) { + returnType = COBOLLINENUM; + } else if (col >= 72 && col <= 79) { + stream.skipToEnd(); + returnType = MODTAG; + } else if (ch == "*" && col == 6) { // comment + stream.skipToEnd(); // rest of the line is a comment + returnType = COMMENT; + } else if (ch == "\"" || ch == "\'") { + state.mode = "string"; + returnType = STRING; + } else if (ch == "'" && !( tests.digit_or_colon.test(stream.peek()) )) { + returnType = ATOM; + } else if (ch == ".") { + returnType = PERIOD; + } else if (isNumber(ch,stream)){ + returnType = NUMBER; + } else { + if (stream.current().match(tests.symbol)) { + while (col < 71) { + if (stream.eat(tests.symbol) === undefined) { + break; + } else { + col++; + } } - if ( stream.eat(tests.exponent) ) { - stream.eat(tests.sign); - stream.eatWhile(tests.digit); - } - return true; + } + if (keywords && keywords.propertyIsEnumerable(stream.current().toUpperCase())) { + returnType = KEYWORD; + } else if (builtins && builtins.propertyIsEnumerable(stream.current().toUpperCase())) { + returnType = BUILTIN; + } else if (atoms && atoms.propertyIsEnumerable(stream.current().toUpperCase())) { + returnType = ATOM; + } else returnType = null; } - return false; + } + return returnType; + }, + indent: function (state) { + if (state.indentStack == null) return state.indentation; + return state.indentStack.indent; } - return { - startState: function () { - return { - indentStack: null, - indentation: 0, - mode: false - }; - }, - token: function (stream, state) { - if (state.indentStack == null && stream.sol()) { - // update indentation, but only if indentStack is empty - state.indentation = 6 ; //stream.indentation(); - } - // skip spaces - if (stream.eatSpace()) { - return null; - } - var returnType = null; - switch(state.mode){ - case "string": // multi-line string parsing mode - var next = false; - while ((next = stream.next()) != null) { - if (next == "\"" || next == "\'") { - state.mode = false; - break; - } - } - returnType = STRING; // continue on in string mode - break; - default: // default parsing mode - var ch = stream.next(); - var col = stream.column(); - if (col >= 0 && col <= 5) { - returnType = COBOLLINENUM; - } else if (col >= 72 && col <= 79) { - stream.skipToEnd(); - returnType = MODTAG; - } else if (ch == "*" && col == 6) { // comment - stream.skipToEnd(); // rest of the line is a comment - returnType = COMMENT; - } else if (ch == "\"" || ch == "\'") { - state.mode = "string"; - returnType = STRING; - } else if (ch == "'" && !( tests.digit_or_colon.test(stream.peek()) )) { - returnType = ATOM; - } else if (ch == ".") { - returnType = PERIOD; - } else if (isNumber(ch,stream)){ - returnType = NUMBER; - } else { - if (stream.current().match(tests.symbol)) { - while (col < 71) { - if (stream.eat(tests.symbol) === undefined) { - break; - } else { - col++; - } - } - } - if (keywords && keywords.propertyIsEnumerable(stream.current().toUpperCase())) { - returnType = KEYWORD; - } else if (builtins && builtins.propertyIsEnumerable(stream.current().toUpperCase())) { - returnType = BUILTIN; - } else if (atoms && atoms.propertyIsEnumerable(stream.current().toUpperCase())) { - returnType = ATOM; - } else returnType = null; - } - } - return returnType; - }, - indent: function (state) { - if (state.indentStack == null) return state.indentation; - return state.indentStack.indent; - } - }; + }; }); -CodeMirror.defineMIME("text/cbl", "cobol"); +CodeMirror.defineMIME("text/x-cobol", "cobol"); diff --git a/mode/cobol/index.html b/mode/cobol/index.html index c66a0e8619..71cc2fa151 100644 --- a/mode/cobol/index.html +++ b/mode/cobol/index.html @@ -7,7 +7,7 @@ - + @@ -24,42 +24,42 @@ - - - - - + + + + + + .CodeMirror { + border: 1px solid #eee; + font-size : 20px; + height : auto !important; + } + .CodeMirror-activeline-background {background: #555555 !important;} + -

    Select Theme Select Font Size + + + + + + + + + + + + + + + + + + + + Select Font Size + + +

    MIME types defined: text/x-haml.

    + +

    Parsing/Highlighting Tests: normal, verbose.

    + + + diff --git a/mode/haml/test.js b/mode/haml/test.js new file mode 100644 index 0000000000..b7178d40fb --- /dev/null +++ b/mode/haml/test.js @@ -0,0 +1,94 @@ +(function() { + var mode = CodeMirror.getMode({tabSize: 4}, "haml"); + function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } + + // Requires at least one media query + MT("elementName", + "[tag %h1] Hey There"); + + MT("oneElementPerLine", + "[tag %h1] Hey There %h2"); + + MT("idSelector", + "[tag %h1][attribute #test] Hey There"); + + MT("classSelector", + "[tag %h1][attribute .hello] Hey There"); + + MT("docType", + "[tag !!! XML]"); + + MT("comment", + "[comment / Hello WORLD]"); + + MT("notComment", + "[tag %h1] This is not a / comment "); + + MT("attributes", + "[tag %a]([variable title][operator =][string \"test\"]){[atom :title] [operator =>] [string \"test\"]}"); + + MT("htmlCode", + "[tag

    ]Title[tag

    ]"); + + MT("rubyBlock", + "[operator =][variable-2 @item]"); + + MT("selectorRubyBlock", + "[tag %a.selector=] [variable-2 @item]"); + + MT("nestedRubyBlock", + "[tag %a]", + " [operator =][variable puts] [string \"test\"]"); + + MT("multilinePlaintext", + "[tag %p]", + " Hello,", + " World"); + + MT("multilineRuby", + "[tag %p]", + " [comment -# this is a comment]", + " [comment and this is a comment too]", + " Date/Time", + " [operator -] [variable now] [operator =] [tag DateTime][operator .][variable now]", + " [tag %strong=] [variable now]", + " [operator -] [keyword if] [variable now] [operator >] [tag DateTime][operator .][variable parse]([string \"December 31, 2006\"])", + " [operator =][string \"Happy\"]", + " [operator =][string \"Belated\"]", + " [operator =][string \"Birthday\"]"); + + MT("multilineComment", + "[comment /]", + " [comment Multiline]", + " [comment Comment]"); + + MT("hamlComment", + "[comment -# this is a comment]"); + + MT("multilineHamlComment", + "[comment -# this is a comment]", + " [comment and this is a comment too]"); + + MT("multilineHTMLComment", + "[comment ]"); + + MT("hamlAfterRubyTag", + "[attribute .block]", + " [tag %strong=] [variable now]", + " [attribute .test]", + " [operator =][variable now]", + " [attribute .right]"); + + MT("stretchedRuby", + "[operator =] [variable puts] [string \"Hello\"],", + " [string \"World\"]"); + + MT("interpolationInHashAttribute", + //"[tag %div]{[atom :id] [operator =>] [string \"#{][variable test][string }_#{][variable ting][string }\"]} test"); + "[tag %div]{[atom :id] [operator =>] [string \"#{][variable test][string }_#{][variable ting][string }\"]} test"); + + MT("interpolationInHTMLAttribute", + "[tag %div]([variable title][operator =][string \"#{][variable test][string }_#{][variable ting]()[string }\"]) Test"); +})(); diff --git a/test/index.html b/test/index.html index 0a0da5bd87..d397e8f7a2 100644 --- a/test/index.html +++ b/test/index.html @@ -57,6 +57,11 @@ + + + + + @@ -84,7 +89,7 @@ running = false, // Flag that states tests are running quit = false, // Flag to quit tests ASAP verbose = false; // Adds message for *every* test to output - + function runHarness(){ if (running) { quit = true; @@ -115,7 +120,7 @@ ""; runTests(displayTest); } - + function setStatus(message, className, force){ if (quit && !force) return; if (!message) throw("must provide message"); From ea302c4a0a8fd8a784cfb21464ee5c0b3e0b45c1 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 29 Apr 2013 10:18:09 +0200 Subject: [PATCH 15/91] [haml mode] Integrate --- doc/compress.html | 1 + doc/modes.html | 1 + 2 files changed, 2 insertions(+) diff --git a/doc/compress.html b/doc/compress.html index c51b2833e0..9ed4773e8e 100644 --- a/doc/compress.html +++ b/doc/compress.html @@ -85,6 +85,7 @@ + diff --git a/doc/modes.html b/doc/modes.html index ac476bef78..af798aa774 100644 --- a/doc/modes.html +++ b/doc/modes.html @@ -38,6 +38,7 @@
  • Gas (AT&T-style assembly)
  • Go
  • Groovy
  • +
  • HAML
  • Haskell
  • Haxe
  • HTML embedded scripts
  • From de9092bc99669da084fa99a16ad6ee010594dd92 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 29 Apr 2013 10:22:42 +0200 Subject: [PATCH 16/91] Remove TextMarker.getOptions It's hardly useful, error-prone, and too clunky. --- doc/manual.html | 12 +++--------- lib/codemirror.js | 16 ---------------- 2 files changed, 3 insertions(+), 25 deletions(-) diff --git a/doc/manual.html b/doc/manual.html index d098421442..a92a6bc92a 100644 --- a/doc/manual.html +++ b/doc/manual.html @@ -1104,18 +1104,12 @@

    Text-marking methods

    The method will return an object that represents the marker (with constuctor CodeMirror.TextMarker), which - exposes three methods: - clear(), to remove the mark, + exposes two methods: + clear(), to remove the mark, and find(), which returns a {from, to} object (both holding document positions), indicating the current position of the marked range, or undefined if the - marker is no longer in the document, and - finally getOptions(copyWidget), which returns an - object representing the options for the marker. - If copyWidget is given true, it will clone the - value of - the replacedWith - option, if any. + marker is no longer in the document.
    doc.setBookmark(pos: {line, ch}, ?options: object) → TextMarker
    Inserts a bookmark, a handle that follows the text around it diff --git a/lib/codemirror.js b/lib/codemirror.js index b2acbe0736..11817d7c6e 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -3597,17 +3597,6 @@ window.CodeMirror = (function() { return from && {from: from, to: to}; }; - TextMarker.prototype.getOptions = function(copyWidget) { - var repl = this.replacedWith; - return {className: this.className, - inclusiveLeft: this.inclusiveLeft, inclusiveRight: this.inclusiveRight, - atomic: this.atomic, - collapsed: this.collapsed, - replacedWith: copyWidget ? repl && repl.cloneNode(true) : repl, - readOnly: this.readOnly, - startStyle: this.startStyle, endStyle: this.endStyle}; - }; - TextMarker.prototype.attachLine = function(line) { if (!this.lines.length && this.doc.cm) { var op = this.doc.cm.curOp; @@ -3705,11 +3694,6 @@ window.CodeMirror = (function() { SharedTextMarker.prototype.find = function() { return this.primary.find(); }; - SharedTextMarker.prototype.getOptions = function(copyWidget) { - var inner = this.primary.getOptions(copyWidget); - inner.shared = true; - return inner; - }; function markTextShared(doc, from, to, options, type) { options = copyObj(options); From ca3707b67ed60d866452c31cd1310cace4bb822c Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 29 Apr 2013 10:47:05 +0200 Subject: [PATCH 17/91] Add TextMarker.changed method --- doc/manual.html | 17 +++++++++++------ lib/codemirror.js | 45 ++++++++++++++++++++++++++++++++------------- 2 files changed, 43 insertions(+), 19 deletions(-) diff --git a/doc/manual.html b/doc/manual.html index a92a6bc92a..6f47472050 100644 --- a/doc/manual.html +++ b/doc/manual.html @@ -1104,12 +1104,17 @@

    Text-marking methods

    The method will return an object that represents the marker (with constuctor CodeMirror.TextMarker), which - exposes two methods: - clear(), to remove the mark, and - find(), which returns a {from, to} - object (both holding document positions), indicating the current - position of the marked range, or undefined if the - marker is no longer in the document.
    + exposes three methods: + clear(), to remove the mark, + find(), which returns + a {from, to} object (both holding document + positions), indicating the current position of the marked range, + or undefined if the marker is no longer in the + document, and finally changed(), + which you can call if you've done something that might change + the size of the marker (for example changing the content of + a replacedWith + node), and want to cheaply update the display.
    doc.setBookmark(pos: {line, ch}, ?options: object) → TextMarker
    Inserts a bookmark, a handle that follows the text around it diff --git a/lib/codemirror.js b/lib/codemirror.js index 11817d7c6e..7563e8804e 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -976,23 +976,28 @@ window.CodeMirror = (function() { if (memo.text == line.text && memo.markedSpans == line.markedSpans && cm.display.scroller.clientWidth == memo.width && memo.classes == line.textClass + "|" + line.bgClass + "|" + line.wrapClass) - return memo.measure; + return memo; } } + function clearCachedMeasurement(cm, line) { + var exists = findCachedMeasurement(cm, line); + if (exists) exists.text = exists.measure = exists.markedSpans = null; + } + function measureLine(cm, line) { // First look in the cache - var measure = findCachedMeasurement(cm, line); - if (!measure) { - // Failing that, recompute and store result in cache - measure = measureLineInner(cm, line); - var cache = cm.display.measureLineCache; - var memo = {text: line.text, width: cm.display.scroller.clientWidth, - markedSpans: line.markedSpans, measure: measure, - classes: line.textClass + "|" + line.bgClass + "|" + line.wrapClass}; - if (cache.length == 16) cache[++cm.display.measureLineCachePos % 16] = memo; - else cache.push(memo); - } + var cached = findCachedMeasurement(cm, line); + if (cached) return cached.measure; + + // Failing that, recompute and store result in cache + var measure = measureLineInner(cm, line); + var cache = cm.display.measureLineCache; + var memo = {text: line.text, width: cm.display.scroller.clientWidth, + markedSpans: line.markedSpans, measure: measure, + classes: line.textClass + "|" + line.bgClass + "|" + line.wrapClass}; + if (cache.length == 16) cache[++cm.display.measureLineCachePos % 16] = memo; + else cache.push(memo); return measure; } @@ -1068,7 +1073,7 @@ window.CodeMirror = (function() { if (sp.collapsed && (sp.to == null || sp.to == line.text.length)) hasBadSpan = true; } var cached = !hasBadSpan && findCachedMeasurement(cm, line); - if (cached) return measureChar(cm, line, line.text.length, cached).right; + if (cached) return measureChar(cm, line, line.text.length, cached.measure).right; var pre = lineContent(cm, line); var end = pre.appendChild(zeroWidthElement(cm.display.measure)); @@ -3597,6 +3602,20 @@ window.CodeMirror = (function() { return from && {from: from, to: to}; }; + TextMarker.prototype.changed = function() { + var pos = this.find(), cm = this.doc.cm; + if (!pos || !cm) return; + var line = getLine(this.doc, pos.from.line); + clearCachedMeasurement(cm, line); + if (pos.from.line >= cm.display.showingFrom && pos.from.line < cm.display.showingTo) { + for (var node = cm.display.lineDiv.firstChild; node; node = node.nextSibling) if (node.lineObj == line) { + if (node.offsetHeight != line.height) updateLineHeight(line, node.offsetHeight); + break; + } + runInOp(cm, function() { cm.curOp.selectionChanged = true; }); + } + }; + TextMarker.prototype.attachLine = function(line) { if (!this.lines.length && this.doc.cm) { var op = this.doc.cm.curOp; From c690083563f86739dc3d271516916d88b04370ed Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 29 Apr 2013 14:21:38 +0200 Subject: [PATCH 18/91] [sass mode] Remove hard-coded lists of html tags and pseudo-elements Issue #1466 --- mode/sass/sass.js | 33 ++++++++------------------------- 1 file changed, 8 insertions(+), 25 deletions(-) diff --git a/mode/sass/sass.js b/mode/sass/sass.js index e5c82e4e1b..1c13e9b415 100644 --- a/mode/sass/sass.js +++ b/mode/sass/sass.js @@ -3,24 +3,13 @@ CodeMirror.defineMode("sass", function(config) { return new RegExp("^" + words.join("|")); }; - var tags = ["&", "a","abbr","acronym","address","applet","area","article","aside","audio","b","base","basefont","bdi","bdo","big","blockquote","body","br","button","canvas","caption","cite","code","col","colgroup","command","datalist","dd","del","details","dfn","dir","div","dl","dt","em","embed","fieldset","figcaption","figure","font","footer","form","frame","frameset","h1","h2","h3","h4","h5","h6","head","header","hgroup","hr","html","i","iframe","img","input","ins","keygen","kbd","label","legend","li","link","map","mark","menu","meta","meter","nav","noframes","noscript","object","ol","optgroup","option","output","p","param","pre","progress","q","rp","rt","ruby","s","samp","script","section","select","small","source","span","strike","strong","style","sub","summary","sup","table","tbody","td","textarea","tfoot","th","thead","time","title","tr","track","tt","u","ul","var","video","wbr"]; var keywords = ["true", "false", "null", "auto"]; var keywordsRegexp = new RegExp("^" + keywords.join("|")); var operators = ["\\(", "\\)", "=", ">", "<", "==", ">=", "<=", "\\+", "-", "\\!=", "/", "\\*", "%", "and", "or", "not"]; var opRegexp = tokenRegexp(operators); - function htmlTag(val){ - for(var i=0; i Date: Mon, 29 Apr 2013 14:23:28 +0200 Subject: [PATCH 19/91] [sass mode] Remove unused variable --- mode/sass/sass.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/mode/sass/sass.js b/mode/sass/sass.js index 1c13e9b415..8758b25189 100644 --- a/mode/sass/sass.js +++ b/mode/sass/sass.js @@ -251,8 +251,6 @@ CodeMirror.defineMode("sass", function(config) { // atoms if (stream.eatWhile(/[\w-&]/)){ - - var current = stream.current(); // matches a property definition if (stream.peek() === ":" && !stream.match(pseudoElementsRegexp, false)) return "property"; From a9654a5f9add00d5ba74dd5a04b0e9d989daf8b3 Mon Sep 17 00:00:00 2001 From: Ivan Kurnosov Date: Tue, 30 Apr 2013 15:23:28 +1200 Subject: [PATCH 20/91] Updated sql's hookIdentifier to properly match escaped ` --- mode/sql/sql.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/mode/sql/sql.js b/mode/sql/sql.js index 4ff847f32c..0ce2176da6 100644 --- a/mode/sql/sql.js +++ b/mode/sql/sql.js @@ -166,10 +166,9 @@ CodeMirror.defineMode("sql", function(config, parserConfig) { // `identifier` function hookIdentifier(stream) { - var escaped = false, ch; + var ch; while ((ch = stream.next()) != null) { - if (ch == "`" && !escaped) return "variable-2"; - escaped = !escaped && ch == "`"; + if (ch == "`" && !stream.eat("`")) return "variable-2"; } return null; } From 9069b222ce48e8d5155ef10700f41e2c40cc5668 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 1 May 2013 12:05:32 +0200 Subject: [PATCH 21/91] Preserve Doc.prototype.constructor property --- lib/codemirror.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/codemirror.js b/lib/codemirror.js index 7563e8804e..af89a0e755 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -4520,6 +4520,7 @@ window.CodeMirror = (function() { }; Doc.prototype = createObj(BranchChunk.prototype, { + constructor: Doc, iter: function(from, to, op) { if (op) this.iterN(from - this.first, to - from, op); else this.iterN(this.first, this.first + this.size, from); From f57ab844957d50ebff3652b9dd7f629f1d56e97e Mon Sep 17 00:00:00 2001 From: Irakli Gozalishvili Date: Tue, 30 Apr 2013 13:36:03 +0400 Subject: [PATCH 22/91] Preserve constructor property on the editor instance. In some cases it's more convenient to access `CodeMirror` from the instance itself, but the way prototype was defined made it impossible. --- lib/codemirror.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/codemirror.js b/lib/codemirror.js index af89a0e755..4f0823b73a 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -2733,6 +2733,7 @@ window.CodeMirror = (function() { // 'wrap f in an operation, performed on its `this` parameter' CodeMirror.prototype = { + constructor: CodeMirror, focus: function(){window.focus(); focusInput(this); onFocus(this); fastPoll(this);}, setOption: function(option, value) { From 0d8a43a05e331c1cb1881e8f11b970141fde23dd Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Fri, 3 May 2013 08:58:25 +0200 Subject: [PATCH 23/91] [markdown mode] Directly use xml mode, rather than relying on text/html binding Since the mode uses the internals of the xml mode state object, it will break if another mode defines text/html (i.e. htmlmixed). Closes #1468 --- mode/markdown/markdown.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mode/markdown/markdown.js b/mode/markdown/markdown.js index c0be49460b..d93d55590e 100644 --- a/mode/markdown/markdown.js +++ b/mode/markdown/markdown.js @@ -1,7 +1,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) { - var htmlFound = CodeMirror.mimeModes.hasOwnProperty("text/html"); - var htmlMode = CodeMirror.getMode(cmCfg, htmlFound ? "text/html" : "text/plain"); + var htmlFound = CodeMirror.modes.hasOwnProperty("xml"); + var htmlMode = CodeMirror.getMode(cmCfg, htmlFound ? {name: "xml", htmlMode: true} : "text/plain"); var aliases = { html: "htmlmixed", js: "javascript", From de983c613392d5f886e0142fc0a6c8ab9a81832e Mon Sep 17 00:00:00 2001 From: Randy Edmunds Date: Tue, 30 Apr 2013 19:43:42 -0700 Subject: [PATCH 24/91] [css mode] Add @import context --- mode/css/css.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mode/css/css.js b/mode/css/css.js index 1ef72b517d..8b1aca280e 100644 --- a/mode/css/css.js +++ b/mode/css/css.js @@ -230,6 +230,8 @@ CodeMirror.defineMode("css-base", function(config, parserConfig) { } else { style += " error"; } + } else if (context == "@import") { + style = "tag"; } else { style = "error"; } @@ -266,6 +268,7 @@ CodeMirror.defineMode("css-base", function(config, parserConfig) { } else if (type == "interpolation") state.stack.push("interpolation"); else if (type == "@media") state.stack.push("@media"); + else if (type == "@import") state.stack.push("@import"); else if (context == "@media" && /\b(keyword|attribute)\b/.test(style)) state.stack.push("@mediaType"); else if (context == "@mediaType" && stream.current() == ",") state.stack.pop(); @@ -273,6 +276,7 @@ CodeMirror.defineMode("css-base", function(config, parserConfig) { else if (context == "@mediaType(" && type == ")") state.stack.pop(); else if ((context == "rule" || context == "block") && type == ":") state.stack.push("propertyValue"); else if (context == "propertyValue" && type == ";") state.stack.pop(); + else if (context == "@import" && type == ";") state.stack.pop(); return style; }, From 85fb7c309f6b8329d2b317b6123084d2dd801a1a Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Fri, 3 May 2013 09:10:30 +0200 Subject: [PATCH 25/91] [sql mode] Don't consider '.e' a number Closes #1489 --- mode/sql/index.html | 1 - mode/sql/sql.js | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/mode/sql/index.html b/mode/sql/index.html index 7ec938a121..8a2495ca24 100644 --- a/mode/sql/index.html +++ b/mode/sql/index.html @@ -6,7 +6,6 @@ - @@ -68,7 +69,8 @@ var editor = CodeMirror.fromTextArea(document.getElementById("code"), { lineNumbers: true, matchBrackets: true, - continueComments: "Enter" + continueComments: "Enter", + extraKeys: {"Ctrl-Q": "toggleComment"} }); diff --git a/mode/javascript/javascript.js b/mode/javascript/javascript.js index 87856a89f3..fabe1c42b9 100644 --- a/mode/javascript/javascript.js +++ b/mode/javascript/javascript.js @@ -453,6 +453,9 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { }, electricChars: ":{}", + blockCommentStart: jsonMode ? null : "/*", + blockCommentEnd: jsonMode ? null : "*/", + lineComment: jsonMode ? null : "//", jsonMode: jsonMode }; diff --git a/mode/lua/lua.js b/mode/lua/lua.js index 90761e2941..b8deaa2575 100644 --- a/mode/lua/lua.js +++ b/mode/lua/lua.js @@ -133,7 +133,11 @@ CodeMirror.defineMode("lua", function(config, parserConfig) { indent: function(state, textAfter) { var closing = dedentPartial.test(textAfter); return state.basecol + indentUnit * (state.indentDepth - (closing ? 1 : 0)); - } + }, + + lineComment: "--", + blockCommentStart: "--[[", + blockCommentEnd: "]]" }; }); diff --git a/mode/ocaml/ocaml.js b/mode/ocaml/ocaml.js index 7dc3d283b2..32cbc0b7ba 100644 --- a/mode/ocaml/ocaml.js +++ b/mode/ocaml/ocaml.js @@ -106,7 +106,10 @@ CodeMirror.defineMode('ocaml', function() { token: function(stream, state) { if (stream.eatSpace()) return null; return state.tokenize(stream, state); - } + }, + + blockCommentStart: "(*", + blockCommentEnd: "*)" }; }); diff --git a/mode/php/php.js b/mode/php/php.js index 56497ed436..fa0db5b1fe 100644 --- a/mode/php/php.js +++ b/mode/php/php.js @@ -118,6 +118,9 @@ }, electricChars: "/{}:", + blockCommentStart: "/*", + blockCommentEnd: "*/", + lineComment: "//", innerMode: function(state) { return {state: state.curState, mode: state.curMode}; } }; diff --git a/mode/python/python.js b/mode/python/python.js index d69ef8389b..b623972b88 100644 --- a/mode/python/python.js +++ b/mode/python/python.js @@ -331,8 +331,9 @@ CodeMirror.defineMode("python", function(conf, parserConf) { } return state.scopes[0].offset; - } + }, + lineComment: "#" }; return external; }); diff --git a/mode/ruby/ruby.js b/mode/ruby/ruby.js index d106a542db..883244b1c7 100644 --- a/mode/ruby/ruby.js +++ b/mode/ruby/ruby.js @@ -186,8 +186,9 @@ CodeMirror.defineMode("ruby", function(config) { return ct.indented + (closing ? 0 : config.indentUnit) + (state.continuedLine ? config.indentUnit : 0); }, - electricChars: "}de" // enD and rescuE + electricChars: "}de", // enD and rescuE + lineComment: "#" }; }); diff --git a/mode/rust/rust.js b/mode/rust/rust.js index ea3005c360..7bee489b47 100644 --- a/mode/rust/rust.js +++ b/mode/rust/rust.js @@ -425,7 +425,10 @@ CodeMirror.defineMode("rust", function() { return lexical.indented + (closing ? 0 : (lexical.info == "alt" ? altIndentUnit : indentUnit)); }, - electricChars: "{}" + electricChars: "{}", + blockCommentStart: "/*", + blockCommentEnd: "*/", + lineComment: "//" }; }); diff --git a/mode/scheme/scheme.js b/mode/scheme/scheme.js index 2ed0a24cd8..c5990ae92c 100644 --- a/mode/scheme/scheme.js +++ b/mode/scheme/scheme.js @@ -223,7 +223,9 @@ CodeMirror.defineMode("scheme", function () { indent: function (state) { if (state.indentStack == null) return state.indentation; return state.indentStack.indent; - } + }, + + lineComment: ";;" }; }); diff --git a/mode/xml/xml.js b/mode/xml/xml.js index 440343bbe7..b04248c6c6 100644 --- a/mode/xml/xml.js +++ b/mode/xml/xml.js @@ -317,6 +317,8 @@ CodeMirror.defineMode("xml", function(config, parserConfig) { }, electricChars: "/", + blockCommentStart: "", configuration: parserConfig.htmlMode ? "html" : "xml" }; diff --git a/test/comment_test.js b/test/comment_test.js new file mode 100644 index 0000000000..311bdb5f49 --- /dev/null +++ b/test/comment_test.js @@ -0,0 +1,46 @@ +namespace = "comment_"; + +(function() { + function test(name, mode, run, before, after) { + return testCM(name, function(cm) { + run(cm); + eq(cm.getValue(), after); + }, {value: before, mode: mode}); + } + + var simpleProg = "function foo() {\n return bar;\n}"; + + test("block", "javascript", function(cm) { + cm.blockComment(Pos(0, 3), Pos(3, 0), {blockCommentLead: " *"}); + }, simpleProg + "\n", "/* function foo() {\n * return bar;\n * }\n */"); + + test("blockToggle", "javascript", function(cm) { + cm.blockComment(Pos(0, 3), Pos(2, 0), {blockCommentLead: " *"}); + cm.uncomment(Pos(0, 3), Pos(2, 0), {blockCommentLead: " *"}); + }, simpleProg, simpleProg); + + test("line", "javascript", function(cm) { + cm.lineComment(Pos(1, 1), Pos(1, 1)); + }, simpleProg, "function foo() {\n// return bar;\n}"); + + test("lineToggle", "javascript", function(cm) { + cm.lineComment(Pos(0, 0), Pos(2, 1)); + cm.uncomment(Pos(0, 0), Pos(2, 1)); + }, simpleProg, simpleProg); + + test("fallbackToBlock", "css", function(cm) { + cm.lineComment(Pos(0, 0), Pos(2, 1)); + }, "html {\n border: none;\n}", "/* html {\n border: none;\n} */"); + + test("fallbackToLine", "ruby", function(cm) { + cm.blockComment(Pos(0, 0), Pos(1)); + }, "def blah()\n return hah\n", "# def blah()\n# return hah\n"); + + test("commentRange", "javascript", function(cm) { + cm.blockComment(Pos(1, 2), Pos(1, 13), {fullLines: false}); + }, simpleProg, "function foo() {\n /*return bar;*/\n}"); + + test("indented", "javascript", function(cm) { + cm.lineComment(Pos(1, 0), Pos(2), {indent: true}); + }, simpleProg, "function foo() {\n // return bar;\n // }"); +})(); diff --git a/test/driver.js b/test/driver.js index aba427702e..ae79c328fe 100644 --- a/test/driver.js +++ b/test/driver.js @@ -23,8 +23,9 @@ function test(name, run, expectedFail) { tests.push({name: name, func: run, expectedFail: expectedFail}); return name; } +var namespace = ""; function testCM(name, run, opts, expectedFail) { - return test("core_" + name, function() { + return test(namespace + name, function() { var place = document.getElementById("testground"), cm = CodeMirror(place, opts); var successful = false; try { diff --git a/test/index.html b/test/index.html index d397e8f7a2..816cef5948 100644 --- a/test/index.html +++ b/test/index.html @@ -9,6 +9,7 @@ + @@ -53,6 +54,7 @@ + diff --git a/test/test.js b/test/test.js index 93d899a66e..637f6e79ca 100644 --- a/test/test.js +++ b/test/test.js @@ -32,6 +32,8 @@ var opera_version = opera && navigator.userAgent.match(/Version\/(\d+\.\d+)/); if (opera_version) opera_version = Number(opera_version); var opera_lt10 = opera && (!opera_version || opera_version < 10); +namespace = "core_"; + test("core_fromTextArea", function() { var te = document.getElementById("code"); te.value = "CONTENT"; From 3095862234bed78cb2dda2581ffe17cad5878a63 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 13 May 2013 13:53:18 +0200 Subject: [PATCH 65/91] [comment addon] Fix lint errors --- addon/comment/comment.js | 5 ++--- addon/lint/lint.js | 10 +++++----- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/addon/comment/comment.js b/addon/comment/comment.js index 2963268a72..ae42b6bcd5 100644 --- a/addon/comment/comment.js +++ b/addon/comment/comment.js @@ -1,6 +1,6 @@ (function() { "use strict"; - + var noOptions = {}; var nonWS = /[^\s\u00a0]/; var Pos = CodeMirror.Pos; @@ -34,7 +34,6 @@ self.operation(function() { if (options.indent) { - var baseCol = CodeMirror.countColumn(firstLine, null, tabSize); var baseString = firstLine.slice(0, firstNonWS(firstLine)); for (var i = from.line; i < end; ++i) { var line = self.getLine(i), cut = baseString.length; @@ -112,7 +111,7 @@ }); return true; } - + // Try block comments var startString = options.blockCommentStart || mode.blockCommentStart; var endString = options.blockCommentEnd || mode.blockCommentEnd; diff --git a/addon/lint/lint.js b/addon/lint/lint.js index ca05da76ef..29fd8d9c3c 100644 --- a/addon/lint/lint.js +++ b/addon/lint/lint.js @@ -105,11 +105,11 @@ CodeMirror.validate = (function() { } function startLinting(cm) { - var state = cm._lintState, options = state.options; - if (options.async) - options.getAnnotations(cm, updateLinting, options); - else - updateLinting(cm, options.getAnnotations(cm.getValue())); + var state = cm._lintState, options = state.options; + if (options.async) + options.getAnnotations(cm, updateLinting, options); + else + updateLinting(cm, options.getAnnotations(cm.getValue())); } function updateLinting(cm, annotationsNotSorted) { From 669c8dd45baff0193e3ac78c325c5d903af74c15 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 13 May 2013 14:05:30 +0200 Subject: [PATCH 66/91] [comment addon] Another lint fix --- addon/comment/comment.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addon/comment/comment.js b/addon/comment/comment.js index ae42b6bcd5..4f590f2870 100644 --- a/addon/comment/comment.js +++ b/addon/comment/comment.js @@ -26,7 +26,7 @@ } return; } - var tabSize = self.getOption("tabSize"), firstLine = self.getLine(from.line); + var firstLine = self.getLine(from.line); if (firstLine == null) return; var end = Math.min(to.ch != 0 || to.line == from.line ? to.line + 1 : to.line, self.lastLine() + 1); var pad = options.padding == null ? " " : options.padding; From 373cb16763574e3d1d31847f2fb911472d06114d Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 13 May 2013 14:11:59 +0200 Subject: [PATCH 67/91] Fix context menu select-all in IE9+ Closes #1522 --- lib/codemirror.js | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index 699f55a4c5..fec1d582d9 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -2097,6 +2097,13 @@ window.CodeMirror = (function() { // Adds "Select all" to context menu in FF if (posEq(sel.from, sel.to)) display.input.value = display.prevInput = " "; + function prepareSelectAllHack() { + if (display.input.selectionStart != null) { + var extval = display.input.value = " " + (posEq(sel.from, sel.to) ? "" : display.input.value); + display.prevInput = " "; + display.input.selectionStart = 1; display.input.selectionEnd = extval.length; + } + } function rehide() { display.inputDiv.style.position = "relative"; display.input.style.cssText = oldCSS; @@ -2104,12 +2111,10 @@ window.CodeMirror = (function() { slowPoll(cm); // Try to detect the user choosing select-all - if (display.input.selectionStart != null && (!ie || ie_lt9)) { + if (display.input.selectionStart != null) { + if (!ie || ie_lt9) prepareSelectAllHack(); clearTimeout(detectingSelectAll); - var extval = display.input.value = " " + (posEq(sel.from, sel.to) ? "" : display.input.value), i = 0; - display.prevInput = " "; - display.input.selectionStart = 1; display.input.selectionEnd = extval.length; - var poll = function(){ + var i = 0, poll = function(){ if (display.prevInput == " " && display.input.selectionStart == 0) operation(cm, commands.selectAll)(cm); else if (i++ < 10) detectingSelectAll = setTimeout(poll, 500); @@ -2119,6 +2124,7 @@ window.CodeMirror = (function() { } } + if (ie && !ie_lt9) prepareSelectAllHack(); if (captureMiddleClick) { e_stop(e); var mouseup = function() { From fb6df35b2e9c79d6fe4b834d92b8f7ed0407f385 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 13 May 2013 16:27:06 +0200 Subject: [PATCH 68/91] [less mode] Remove fixed list of tags It makes no sense. Issue #1466 --- mode/less/less.js | 8 -------- 1 file changed, 8 deletions(-) diff --git a/mode/less/less.js b/mode/less/less.js index 6df4790995..09f510e032 100644 --- a/mode/less/less.js +++ b/mode/less/less.js @@ -7,12 +7,6 @@ CodeMirror.defineMode("less", function(config) { var indentUnit = config.indentUnit, type; function ret(style, tp) {type = tp; return style;} - //html tags - var tags = "a abbr acronym address applet area article aside audio b base basefont bdi bdo big blockquote body br button canvas caption cite code col colgroup command datalist dd del details dfn dir div dl dt em embed fieldset figcaption figure font footer form frame frameset h1 h2 h3 h4 h5 h6 head header hgroup hr html i iframe img input ins keygen kbd label legend li link map mark menu meta meter nav noframes noscript object ol optgroup option output p param pre progress q rp rt ruby s samp script section select small source span strike strong style sub summary sup table tbody td textarea tfoot th thead time title tr track tt u ul var video wbr".split(' '); - - function inTagsArray(val){ - for(var i=0; i Date: Mon, 13 May 2013 22:43:29 +0200 Subject: [PATCH 69/91] [vim keymap] Add actionArgs for command 'i' 'I' --- keymap/vim.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/keymap/vim.js b/keymap/vim.js index 48276836ca..4d7833f14e 100644 --- a/keymap/vim.js +++ b/keymap/vim.js @@ -245,9 +245,10 @@ actionArgs: { insertAt: 'charAfter' }}, { keys: ['A'], type: 'action', action: 'enterInsertMode', actionArgs: { insertAt: 'eol' }}, - { keys: ['i'], type: 'action', action: 'enterInsertMode' }, + { keys: ['i'], type: 'action', action: 'enterInsertMode', + actionArgs: { insertAt: 'inplace' }}, { keys: ['I'], type: 'action', action: 'enterInsertMode', - motion: 'moveToFirstNonWhiteSpaceCharacter' }, + actionArgs: { insertAt: 'firstNonBlank' }}, { keys: ['o'], type: 'action', action: 'newLineAndEnterInsertMode', actionArgs: { after: true }}, { keys: ['O'], type: 'action', action: 'newLineAndEnterInsertMode', @@ -368,7 +369,7 @@ return false; } - var circularJumpList = function() { + var createCircularJumpList = function() { var size = 100; var pointer = -1; var head = 0; @@ -442,7 +443,7 @@ searchQuery: null, // Whether we are searching backwards. searchIsReversed: false, - jumpList: circularJumpList(), + jumpList: createCircularJumpList(), // Recording latest f, t, F or T motion command. lastChararacterSearch: {increment:0, forward:true, selectedCharacter:''}, registerController: new RegisterController({}) @@ -1528,6 +1529,8 @@ cm.setCursor(cursor); } else if (insertAt == 'charAfter') { cm.setCursor(offsetCursor(cm.getCursor(), 0, 1)); + } else if (insertAt == 'firstNonBlank') { ++ cm.setCursor(motions.moveToFirstNonWhiteSpaceCharacter(cm)); } cm.setOption('keyMap', 'vim-insert'); }, From 1f3e26ab6869f0a3de97f5cf01e37c93e54f4a7f Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 14 May 2013 10:51:09 +0200 Subject: [PATCH 70/91] [vim keymap] Remove stray plus character Issue #1525 --- keymap/vim.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/keymap/vim.js b/keymap/vim.js index 4d7833f14e..3640e65be8 100644 --- a/keymap/vim.js +++ b/keymap/vim.js @@ -1530,7 +1530,7 @@ } else if (insertAt == 'charAfter') { cm.setCursor(offsetCursor(cm.getCursor(), 0, 1)); } else if (insertAt == 'firstNonBlank') { -+ cm.setCursor(motions.moveToFirstNonWhiteSpaceCharacter(cm)); + cm.setCursor(motions.moveToFirstNonWhiteSpaceCharacter(cm)); } cm.setOption('keyMap', 'vim-insert'); }, From b5e0401e4424084e39cd3762feb284c01cc9caf6 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 14 May 2013 11:13:46 +0200 Subject: [PATCH 71/91] Allow mode spec objects to have mime types as name Other properties will be added/overridden in the config object for the mime type. --- lib/codemirror.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index fec1d582d9..15a092f9c4 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -3180,10 +3180,15 @@ window.CodeMirror = (function() { }; CodeMirror.resolveMode = function(spec) { - if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) + if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) { spec = mimeModes[spec]; - else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec)) + } else if (typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) { + var found = mimeModes[spec.name]; + spec = createObj(found, spec); + spec.name = found.name; + } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec)) { return CodeMirror.resolveMode("application/xml"); + } if (typeof spec == "string") return {name: spec}; else return spec || {name: "null"}; }; From c3cb802df2e001bc0b2d1b78766a603a48ec2d1b Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 14 May 2013 11:18:16 +0200 Subject: [PATCH 72/91] [clike mode] Fix interaction of dontAlignCalls and statementIndentUnit Closes #1518 --- mode/clike/clike.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mode/clike/clike.js b/mode/clike/clike.js index 83bf8019f2..09621bc08d 100644 --- a/mode/clike/clike.js +++ b/mode/clike/clike.js @@ -150,8 +150,8 @@ CodeMirror.defineMode("clike", function(config, parserConfig) { if (ctx.type == "statement" && firstChar == "}") ctx = ctx.prev; var closing = firstChar == ctx.type; if (ctx.type == "statement") return ctx.indented + (firstChar == "{" ? 0 : statementIndentUnit); - else if (dontAlignCalls && ctx.type == ")" && !closing) return ctx.indented + statementIndentUnit; - else if (ctx.align) return ctx.column + (closing ? 0 : 1); + else if (ctx.align && (!dontAlignCalls || ctx.type != ")")) return ctx.column + (closing ? 0 : 1); + else if (ctx.type == ")" && !closing) return ctx.indented + statementIndentUnit; else return ctx.indented + (closing ? 0 : indentUnit); }, From 00504d8a36c1cd4cb5699601bc49ca1012c2fe78 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 14 May 2013 11:25:48 +0200 Subject: [PATCH 73/91] Don't crash when getMode is passed null --- lib/codemirror.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index 15a092f9c4..7f5f672adb 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -3182,7 +3182,7 @@ window.CodeMirror = (function() { CodeMirror.resolveMode = function(spec) { if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) { spec = mimeModes[spec]; - } else if (typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) { + } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) { var found = mimeModes[spec.name]; spec = createObj(found, spec); spec.name = found.name; From ea523decb8bd3562bfaae4891903c46e9c190f87 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 15 May 2013 13:03:59 +0200 Subject: [PATCH 74/91] Shuffle real-world uses on front page, add Bitbucket and JSFiddle --- doc/realworld.html | 2 ++ index.html | 39 ++++++++++++++++++++------------------- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/doc/realworld.html b/doc/realworld.html index c3f2c814fc..941d926dbe 100644 --- a/doc/realworld.html +++ b/doc/realworld.html @@ -25,6 +25,7 @@
  • Adobe Brackets (code editor)
  • Amber (JavaScript-based Smalltalk system)
  • APEye (tool for testing & documenting APIs)
  • +
  • Bitbucket (code hosting)
  • Blogger's template editor
  • BlueGriffon (HTML editor)
  • Cargo Collective (creative publishing platform)
  • @@ -66,6 +67,7 @@
  • Joomla plugin
  • jQuery fundamentals (interactive tutorial)
  • jsbin.com (JS playground)
  • +
  • jsfiddle.com (another JS playground)
  • JSHint (JS linter)
  • Jumpseller (online store builder)
  • kl1p (paste service)
  • diff --git a/index.html b/index.html index 1dba41984b..a0d3d5b48f 100644 --- a/index.html +++ b/index.html @@ -120,28 +120,29 @@

    Usage demos:

    Real-world uses:

    From 36fe7d5b4a3ffdd804933a323a45f23ae0885e20 Mon Sep 17 00:00:00 2001 From: lynschinzer Date: Tue, 14 May 2013 23:16:39 +0200 Subject: [PATCH 75/91] [vim keymap] Change defaultKeymap notation format --- keymap/vim.js | 108 ++++++++++++++++++++++--------------------------------- test/vim_test.js | 62 ++++++++++++++++---------------- 2 files changed, 73 insertions(+), 97 deletions(-) diff --git a/keymap/vim.js b/keymap/vim.js index 3640e65be8..9c0197faaa 100644 --- a/keymap/vim.js +++ b/keymap/vim.js @@ -58,26 +58,26 @@ var defaultKeymap = [ // Key to key mapping. This goes first to make it possible to override // existing mappings. - { keys: ['Left'], type: 'keyToKey', toKeys: ['h'] }, - { keys: ['Right'], type: 'keyToKey', toKeys: ['l'] }, - { keys: ['Up'], type: 'keyToKey', toKeys: ['k'] }, - { keys: ['Down'], type: 'keyToKey', toKeys: ['j'] }, - { keys: ['Space'], type: 'keyToKey', toKeys: ['l'] }, - { keys: ['Backspace'], type: 'keyToKey', toKeys: ['h'] }, - { keys: ['Ctrl-Space'], type: 'keyToKey', toKeys: ['W'] }, - { keys: ['Ctrl-Backspace'], type: 'keyToKey', toKeys: ['B'] }, - { keys: ['Shift-Space'], type: 'keyToKey', toKeys: ['w'] }, - { keys: ['Shift-Backspace'], type: 'keyToKey', toKeys: ['b'] }, - { keys: ['Ctrl-n'], type: 'keyToKey', toKeys: ['j'] }, - { keys: ['Ctrl-p'], type: 'keyToKey', toKeys: ['k'] }, - { keys: ['Ctrl-['], type: 'keyToKey', toKeys: ['Esc'] }, - { keys: ['Ctrl-c'], type: 'keyToKey', toKeys: ['Esc'] }, + { keys: [''], type: 'keyToKey', toKeys: ['h'] }, + { keys: [''], type: 'keyToKey', toKeys: ['l'] }, + { keys: [''], type: 'keyToKey', toKeys: ['k'] }, + { keys: [''], type: 'keyToKey', toKeys: ['j'] }, + { keys: [''], type: 'keyToKey', toKeys: ['l'] }, + { keys: [''], type: 'keyToKey', toKeys: ['h'] }, + { keys: [''], type: 'keyToKey', toKeys: ['W'] }, + { keys: [''], type: 'keyToKey', toKeys: ['B'] }, + { keys: [''], type: 'keyToKey', toKeys: ['w'] }, + { keys: [''], type: 'keyToKey', toKeys: ['b'] }, + { keys: [''], type: 'keyToKey', toKeys: ['j'] }, + { keys: [''], type: 'keyToKey', toKeys: ['k'] }, + { keys: ['C-['], type: 'keyToKey', toKeys: [''] }, + { keys: [''], type: 'keyToKey', toKeys: [''] }, { keys: ['s'], type: 'keyToKey', toKeys: ['c', 'l'] }, { keys: ['S'], type: 'keyToKey', toKeys: ['c', 'c'] }, - { keys: ['Home'], type: 'keyToKey', toKeys: ['0'] }, - { keys: ['End'], type: 'keyToKey', toKeys: ['$'] }, - { keys: ['PageUp'], type: 'keyToKey', toKeys: ['Ctrl-b'] }, - { keys: ['PageDown'], type: 'keyToKey', toKeys: ['Ctrl-f'] }, + { keys: [''], type: 'keyToKey', toKeys: ['0'] }, + { keys: [''], type: 'keyToKey', toKeys: ['$'] }, + { keys: [''], type: 'keyToKey', toKeys: [''] }, + { keys: [''], type: 'keyToKey', toKeys: [''] }, // Motions { keys: ['H'], type: 'motion', motion: 'moveToTopLine', @@ -136,14 +136,14 @@ motionArgs: { forward: false, toJumplist: true }}, { keys: ['}'], type: 'motion', motion: 'moveByParagraph', motionArgs: { forward: true, toJumplist: true }}, - { keys: ['Ctrl-f'], type: 'motion', + { keys: [''], type: 'motion', motion: 'moveByPage', motionArgs: { forward: true }}, - { keys: ['Ctrl-b'], type: 'motion', + { keys: [''], type: 'motion', motion: 'moveByPage', motionArgs: { forward: false }}, - { keys: ['Ctrl-d'], type: 'motion', + { keys: [''], type: 'motion', motion: 'moveByScroll', motionArgs: { forward: true, explicitRepeat: true }}, - { keys: ['Ctrl-u'], type: 'motion', + { keys: [''], type: 'motion', motion: 'moveByScroll', motionArgs: { forward: false, explicitRepeat: true }}, { keys: ['g', 'g'], type: 'motion', @@ -237,9 +237,9 @@ { keys: ['~'], type: 'operatorMotion', operator: 'swapcase', motion: 'moveByCharacters', motionArgs: { forward: true }}, // Actions - { keys: ['Ctrl-i'], type: 'action', action: 'jumpListWalk', + { keys: [''], type: 'action', action: 'jumpListWalk', actionArgs: { forward: true }}, - { keys: ['Ctrl-o'], type: 'action', action: 'jumpListWalk', + { keys: [''], type: 'action', action: 'jumpListWalk', actionArgs: { forward: false }}, { keys: ['a'], type: 'action', action: 'enterInsertMode', actionArgs: { insertAt: 'charAfter' }}, @@ -264,7 +264,7 @@ { keys: ['r', 'character'], type: 'action', action: 'replace' }, { keys: ['R'], type: 'action', action: 'enterReplaceMode' }, { keys: ['u'], type: 'action', action: 'undo' }, - { keys: ['Ctrl-r'], type: 'action', action: 'redo' }, + { keys: [''], type: 'action', action: 'redo' }, { keys: ['m', 'character'], type: 'action', action: 'setMark' }, { keys: ['\"', 'character'], type: 'action', action: 'setRegister' }, { keys: ['z', 'z'], type: 'action', action: 'scrollToCursor', @@ -274,7 +274,7 @@ motion: 'moveToFirstNonWhiteSpaceCharacter' }, { keys: ['z', 't'], type: 'action', action: 'scrollToCursor', actionArgs: { position: 'top' }}, - { keys: ['z', 'Enter'], type: 'action', action: 'scrollToCursor', + { keys: ['z', ''], type: 'action', action: 'scrollToCursor', actionArgs: { position: 'top' }, motion: 'moveToFirstNonWhiteSpaceCharacter' }, { keys: ['z', '-'], type: 'action', action: 'scrollToCursor', @@ -283,9 +283,9 @@ actionArgs: { position: 'bottom' }, motion: 'moveToFirstNonWhiteSpaceCharacter' }, { keys: ['.'], type: 'action', action: 'repeatLastEdit' }, - { keys: ['Ctrl-a'], type: 'action', action: 'incrementNumberToken', + { keys: [''], type: 'action', action: 'incrementNumberToken', actionArgs: {increase: true, backtrack: false}}, - { keys: ['Ctrl-x'], type: 'action', action: 'incrementNumberToken', + { keys: [''], type: 'action', action: 'incrementNumberToken', actionArgs: {increase: false, backtrack: false}}, // Text object motions { keys: ['a', 'character'], type: 'motion', @@ -509,7 +509,7 @@ handleKey: function(cm, key) { var command; var vim = getVimState(cm); - if (key == 'Esc') { + if (key == '') { // Clear input state and get back to normal mode. vim.inputState = new InputState(); if (vim.visualMode) { @@ -717,10 +717,10 @@ inputState.selectedCharacter = keys[keys.length - 1]; if(inputState.selectedCharacter.length>1){ switch(inputState.selectedCharacter){ - case "Enter": + case "": inputState.selectedCharacter='\n'; break; - case "Space": + case "": inputState.selectedCharacter=' '; break; default: @@ -2930,41 +2930,14 @@ // Converts a key string sequence of the form abd into Vim's // keymap representation. function parseKeyString(str) { - var idx = 0; + var key, match; var keys = []; - while (idx < str.length) { - if (str.charAt(idx) != '<') { - keys.push(str.charAt(idx)); - idx++; - continue; - } - // Vim key notation here means desktop Vim key-notation. - // See :help key-notation in desktop Vim. - var vimKeyNotationStart = ++idx; - while (str.charAt(idx++) != '>') {} - var vimKeyNotation = str.substring(vimKeyNotationStart, idx - 1); - var mod=''; - var match = (/^C-(.+)$/).exec(vimKeyNotation); - if (match) { - mod='Ctrl-'; - vimKeyNotation=match[1]; - } - var key; - switch (vimKeyNotation) { - case 'BS': - key = 'Backspace'; - break; - case 'CR': - key = 'Enter'; - break; - case 'Del': - key = 'Delete'; - break; - default: - key = vimKeyNotation; - break; - } - keys.push(mod + key); + while (str) { + match = (/<\w+-.+?>|<\w+>|./).exec(str); + if(match === null)break; + key = match[0]; + str = str.substring(match.index + key.length); + keys.push(key); } return keys; } @@ -3148,8 +3121,11 @@ } if (modifier) { // Vim will parse modifier+key combination as a single key. - key = modifier + '-' + key; + key = modifier.charAt(0) + '-' + key; } + var specialKey = ({Enter:'CR',Backspace:'BS',Delete:'Del'})[key]; + key = specialKey ? specialKey : key; + key = key.length > 1 ? '<'+ key + '>' : key; vim.handleKey(cm, key); } diff --git a/test/vim_test.js b/test/vim_test.js index f2304b99cf..83bbec9ac6 100644 --- a/test/vim_test.js +++ b/test/vim_test.js @@ -190,32 +190,32 @@ function testJumplist(name, keys, endPos, startPos, dialog) { helpers.assertCursorAt(endPos); }, {value: jumplistScene}); }; -testJumplist('jumplist_H', ['H', 'Ctrl-o'], [5,2], [5,2]); -testJumplist('jumplist_M', ['M', 'Ctrl-o'], [2,2], [2,2]); -testJumplist('jumplist_L', ['L', 'Ctrl-o'], [2,2], [2,2]); -testJumplist('jumplist_[[', ['[', '[', 'Ctrl-o'], [5,2], [5,2]); -testJumplist('jumplist_]]', [']', ']', 'Ctrl-o'], [2,2], [2,2]); -testJumplist('jumplist_G', ['G', 'Ctrl-o'], [5,2], [5,2]); -testJumplist('jumplist_gg', ['g', 'g', 'Ctrl-o'], [5,2], [5,2]); -testJumplist('jumplist_%', ['%', 'Ctrl-o'], [1,5], [1,5]); -testJumplist('jumplist_{', ['{', 'Ctrl-o'], [1,5], [1,5]); -testJumplist('jumplist_}', ['}', 'Ctrl-o'], [1,5], [1,5]); -testJumplist('jumplist_\'', ['m', 'a', 'h', '\'', 'a', 'h', 'Ctrl-i'], [1,5], [1,5]); -testJumplist('jumplist_`', ['m', 'a', 'h', '`', 'a', 'h', 'Ctrl-i'], [1,5], [1,5]); -testJumplist('jumplist_*_cachedCursor', ['*', 'Ctrl-o'], [1,3], [1,3]); -testJumplist('jumplist_#_cachedCursor', ['#', 'Ctrl-o'], [1,3], [1,3]); -testJumplist('jumplist_n', ['#', 'n', 'Ctrl-o'], [1,1], [2,3]); -testJumplist('jumplist_N', ['#', 'N', 'Ctrl-o'], [1,1], [2,3]); -testJumplist('jumplist_repeat_', ['*', '*', '*', '3', 'Ctrl-o'], [2,3], [2,3]); -testJumplist('jumplist_repeat_', ['*', '*', '*', '3', 'Ctrl-o', '2', 'Ctrl-i'], [5,0], [2,3]); -testJumplist('jumplist_repeated_motion', ['3', '*', 'Ctrl-o'], [2,3], [2,3]); -testJumplist('jumplist_/', ['/', 'Ctrl-o'], [2,3], [2,3], 'dialog'); -testJumplist('jumplist_?', ['?', 'Ctrl-o'], [2,3], [2,3], 'dialog'); +testJumplist('jumplist_H', ['H', ''], [5,2], [5,2]); +testJumplist('jumplist_M', ['M', ''], [2,2], [2,2]); +testJumplist('jumplist_L', ['L', ''], [2,2], [2,2]); +testJumplist('jumplist_[[', ['[', '[', ''], [5,2], [5,2]); +testJumplist('jumplist_]]', [']', ']', ''], [2,2], [2,2]); +testJumplist('jumplist_G', ['G', ''], [5,2], [5,2]); +testJumplist('jumplist_gg', ['g', 'g', ''], [5,2], [5,2]); +testJumplist('jumplist_%', ['%', ''], [1,5], [1,5]); +testJumplist('jumplist_{', ['{', ''], [1,5], [1,5]); +testJumplist('jumplist_}', ['}', ''], [1,5], [1,5]); +testJumplist('jumplist_\'', ['m', 'a', 'h', '\'', 'a', 'h', ''], [1,5], [1,5]); +testJumplist('jumplist_`', ['m', 'a', 'h', '`', 'a', 'h', ''], [1,5], [1,5]); +testJumplist('jumplist_*_cachedCursor', ['*', ''], [1,3], [1,3]); +testJumplist('jumplist_#_cachedCursor', ['#', ''], [1,3], [1,3]); +testJumplist('jumplist_n', ['#', 'n', ''], [1,1], [2,3]); +testJumplist('jumplist_N', ['#', 'N', ''], [1,1], [2,3]); +testJumplist('jumplist_repeat_', ['*', '*', '*', '3', ''], [2,3], [2,3]); +testJumplist('jumplist_repeat_', ['*', '*', '*', '3', '', '2', ''], [5,0], [2,3]); +testJumplist('jumplist_repeated_motion', ['3', '*', ''], [2,3], [2,3]); +testJumplist('jumplist_/', ['/', ''], [2,3], [2,3], 'dialog'); +testJumplist('jumplist_?', ['?', ''], [2,3], [2,3], 'dialog'); testJumplist('jumplist_skip_delted_mark', - ['*', 'n', 'n', 'k', 'd', 'k', 'Ctrl-o', 'Ctrl-o', 'Ctrl-o'], + ['*', 'n', 'n', 'k', 'd', 'k', '', '', ''], [0,2], [0,2]); testJumplist('jumplist_skip_delted_mark', - ['*', 'n', 'n', 'k', 'd', 'k', 'Ctrl-o', 'Ctrl-i', 'Ctrl-i'], + ['*', 'n', 'n', 'k', 'd', 'k', '', '', ''], [1,0], [0,2]); /** * @param name Name of the test @@ -970,22 +970,22 @@ testVim('Y', function(cm, vim, helpers) { // Action tests testVim('ctrl-a', function(cm, vim, helpers) { cm.setCursor(0, 0); - helpers.doKeys('Ctrl-a'); + helpers.doKeys(''); eq('-9', cm.getValue()); helpers.assertCursorAt(0, 1); - helpers.doKeys('2','Ctrl-a'); + helpers.doKeys('2',''); eq('-7', cm.getValue()); }, {value: '-10'}); testVim('ctrl-x', function(cm, vim, helpers) { cm.setCursor(0, 0); - helpers.doKeys('Ctrl-x'); + helpers.doKeys(''); eq('-1', cm.getValue()); helpers.assertCursorAt(0, 1); - helpers.doKeys('2','Ctrl-x'); + helpers.doKeys('2',''); eq('-3', cm.getValue()); }, {value: '0'}); -testVim('Ctrl-x/Ctrl-a search forward', function(cm, vim, helpers) { - ['Ctrl-x', 'Ctrl-a'].forEach(function(key) { +testVim('/ search forward', function(cm, vim, helpers) { + ['', ''].forEach(function(key) { cm.setCursor(0, 0); helpers.doKeys(key); helpers.assertCursorAt(0, 5); @@ -1103,7 +1103,7 @@ testVim('r', function(cm, vim, helpers) { eq('wuuuet\nanother', cm.getValue(),'3r failed'); helpers.assertCursorAt(0, 3); cm.setCursor(0, 4); - helpers.doKeys('v', 'j', 'h', 'r', 'Space'); + helpers.doKeys('v', 'j', 'h', 'r', ''); eq('wuuu \n her', cm.getValue(),'Replacing selection by space-characters failed'); }, { value: 'wordet\nanother' }); testVim('R', function(cm, vim, helpers) { @@ -2001,7 +2001,7 @@ testVim('ex_api_test', function(cm, vim, helpers) { helpers.doEx(':ext to'); eq(val,'to','Defining ex-command failed'); CodeMirror.Vim.map('',':ext'); - helpers.doKeys('Ctrl-Enter','Space'); + helpers.doKeys('',''); is(res,'Mapping to key failed'); }); // For now, this test needs to be last because it messes up : for future tests. From 9a8282fd1d310b3bf61d101b230b4766a933688c Mon Sep 17 00:00:00 2001 From: Alex Piggott Date: Wed, 15 May 2013 13:14:57 +0200 Subject: [PATCH 76/91] [brace-fold addon] Also handle square brackets --- addon/fold/brace-fold.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/addon/fold/brace-fold.js b/addon/fold/brace-fold.js index dc78883f35..efdffb877c 100644 --- a/addon/fold/brace-fold.js +++ b/addon/fold/brace-fold.js @@ -3,17 +3,23 @@ CodeMirror.braceRangeFinder = function(cm, start) { var at = lineText.length, startChar, tokenType; for (; at > 0;) { var found = lineText.lastIndexOf("{", at); - if (found < start.ch) break; + var startToken = '{', endToken = '}'; + if (found < start.ch) { + found = lineText.lastIndexOf("[", at); + if (found < start.ch) break; + startToken = '['; endToken = ']'; + } + tokenType = cm.getTokenAt(CodeMirror.Pos(line, found + 1)).type; if (!/^(comment|string)/.test(tokenType)) { startChar = found; break; } at = found - 1; } - if (startChar == null || lineText.lastIndexOf("}") > startChar) return; + if (startChar == null || lineText.lastIndexOf(startToken) > startChar) return; var count = 1, lastLine = cm.lineCount(), end, endCh; outer: for (var i = line + 1; i < lastLine; ++i) { var text = cm.getLine(i), pos = 0; for (;;) { - var nextOpen = text.indexOf("{", pos), nextClose = text.indexOf("}", pos); + var nextOpen = text.indexOf(startToken, pos), nextClose = text.indexOf(endToken, pos); if (nextOpen < 0) nextOpen = text.length; if (nextClose < 0) nextClose = text.length; pos = Math.min(nextOpen, nextClose); From 6b7e2953febaba158e6128b7a3d07b7b02c88636 Mon Sep 17 00:00:00 2001 From: Andrey Lushnikov Date: Mon, 13 May 2013 19:12:09 +0400 Subject: [PATCH 77/91] mark-selection addon improvement Addresses issue #1484 and speeds up mark-selection add-on by maintaining text selection coverage with small chunks of text marks. --- addon/selection/mark-selection.js | 135 +++++++++++++++++++++++++++++++++++--- 1 file changed, 125 insertions(+), 10 deletions(-) diff --git a/addon/selection/mark-selection.js b/addon/selection/mark-selection.js index d7ff30c9a9..80eb9def0f 100644 --- a/addon/selection/mark-selection.js +++ b/addon/selection/mark-selection.js @@ -13,22 +13,137 @@ cm.on("cursorActivity", updateSelectedText); } else if (!val && prev) { cm.off("cursorActivity", updateSelectedText); - clearSelectedText(cm); - delete cm._selectionMark; + removeTextMarks(cm); } }); - function clearSelectedText(cm) { - if (cm._selectionMark) cm._selectionMark.clear(); + function cmp(pos1, pos2) { + return pos1.line !== pos2.line ? pos1.line - pos2.line : pos1.ch - pos2.ch; + } + + function removeTextMarks(cm) { + if (cm._selectionMarks) { + for(var i = 0; i < cm._selectionMarks.length; ++i) { + cm._selectionMarks[i].clear(); + } + } + cm._selectionMarks = null; + } + + function markText(cm, start, end) { + if (cmp(start, end) === 0) + return; + var opt = {className: "CodeMirror-selectedtext"}; + cm._selectionMarks.push(cmp(start, end) <= 0 ? cm.markText(start, end, opt) : cm.markText(end, start, opt)); + } + + var CHUNK_SIZE = 8; + var Pos = CodeMirror.Pos; + + function coverRange(cm, anchor, head) { + if (Math.abs(anchor.line - head.line) < CHUNK_SIZE) { + markText(cm, anchor, head); + return; + } + if (head.line > anchor.line) { + markText(cm, anchor, Pos(anchor.line + CHUNK_SIZE, 0)); + for(var line = anchor.line + CHUNK_SIZE; line + CHUNK_SIZE < head.line; line += CHUNK_SIZE) + markText(cm, Pos(line, 0), Pos(line + CHUNK_SIZE, 0)); + markText(cm, Pos(line, 0), head); + } else { + markText(cm, anchor, Pos(anchor.line - CHUNK_SIZE + 1, 0)); + for(var line = anchor.line - CHUNK_SIZE + 1; line - CHUNK_SIZE > head.line; line -= CHUNK_SIZE) + markText(cm, Pos(line, 0), Pos(line - CHUNK_SIZE, 0)); + markText(cm, Pos(line, 0), head); + } + } + + function createInitialCoverage(cm) { + var anchor = cm.getCursor("anchor"); + var head = cm.getCursor("head"); + cm._selectionMarks = []; + coverRange(cm, anchor, head); + } + + function getCoveredRange(cm) { + var first = cm._selectionMarks[0].find(); + var last = cm._selectionMarks[cm._selectionMarks.length - 1].find(); + if (!first || !last) + return null; + var reversed = cmp(first.from, last.to) >= 0; + return reversed ? {anchor: first.to, head: last.from, reversed: reversed} : {anchor: first.from, head: last.to, reversed: reversed}; + } + + function incrementalCoverageUpdate(cm) { + var anchor = cm.getCursor("anchor"); + var head = cm.getCursor("head"); + var reversed = cmp(head, anchor) < 0; + var lastSelection = getCoveredRange(cm); + // if the anchor of selection moved or selection changed direction - remove everything and construct from scratch. + if (!lastSelection || cmp(anchor, lastSelection.anchor) !== 0 || (reversed ^ lastSelection.reversed)) { + removeTextMarks(cm); + createInitialCoverage(cm); + return; + } + // fast return if nothing changed + if (cmp(head, lastSelection.head) === 0) + return; + + // if only column changed then update last text mark + if (head.line === lastSelection.head.line) { + var lastMark = cm._selectionMarks.pop(); + var position = lastMark.find(); + lastMark.clear(); + markText(cm, reversed ? position.to : position.from, head); + return; + } + + if (!reversed) { + // if selection shrinks + if (head.line < lastSelection.head.line) { + var textMark, + position; + do { + textMark = cm._selectionMarks.pop(); + position = textMark.find(); + textMark.clear(); + } while (cm._selectionMarks.length && position.from.line >= head.line); + markText(cm, position.from, head); + } else { + var textMark = cm._selectionMarks.pop(); + var position = textMark.find(); + textMark.clear(); + coverRange(cm, position.from, head); + } + } else { + // selection getting smaller + if (head.line > lastSelection.head.line) { + var textMark, + position; + do { + textMark = cm._selectionMarks.pop(); + position = textMark.find(); + textMark.clear(); + } while (cm._selectionMarks.length && position.to.line <= head.line); + markText(cm, position.to, head); + } else { + var textMark = cm._selectionMarks.pop(); + var position = textMark.find(); + coverRange(cm, position.to, head); + textMark.clear(); + } + } } function updateSelectedText(cm) { - clearSelectedText(cm); + cm.operation(function() { + if (!cm.somethingSelected()) + return removeTextMarks(cm); + + if (!cm._selectionMarks || !cm._selectionMarks.length) + return createInitialCoverage(cm); - if (cm.somethingSelected()) - cm._selectionMark = cm.markText(cm.getCursor("start"), cm.getCursor("end"), - {className: "CodeMirror-selectedtext"}); - else - cm._selectionMark = null; + incrementalCoverageUpdate(cm); + }); } })(); From 5a5f9f4e25b1a88de413fbca295881beacd5b82a Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 16 May 2013 11:32:46 +0200 Subject: [PATCH 78/91] [mark-selection addon] Simplify Issue #1523 --- addon/selection/mark-selection.js | 183 +++++++++++++++----------------------- 1 file changed, 71 insertions(+), 112 deletions(-) diff --git a/addon/selection/mark-selection.js b/addon/selection/mark-selection.js index 80eb9def0f..c97776e492 100644 --- a/addon/selection/mark-selection.js +++ b/addon/selection/mark-selection.js @@ -1,7 +1,8 @@ // Because sometimes you need to mark the selected *text*. // // Adds an option 'styleSelectedText' which, when enabled, gives -// selected text the CSS class "CodeMirror-selectedtext". +// selected text the CSS class given as option value, or +// "CodeMirror-selectedtext" when the value is not a string. (function() { "use strict"; @@ -9,141 +10,99 @@ CodeMirror.defineOption("styleSelectedText", false, function(cm, val, old) { var prev = old && old != CodeMirror.Init; if (val && !prev) { - updateSelectedText(cm); - cm.on("cursorActivity", updateSelectedText); + cm.state.markedSelection = []; + cm.state.markedSelectionStyle = typeof val == "string" ? val : "CodeMirror-selectedtext"; + reset(cm); + cm.on("cursorActivity", onCursorActivity); + cm.on("change", onChange); } else if (!val && prev) { - cm.off("cursorActivity", updateSelectedText); - removeTextMarks(cm); + cm.off("cursorActivity", onCursorActivity); + cm.off("change", onChange); + clear(cm); + cm.state.markedSelection = cm.state.markedSelectionStyle = null; } }); - function cmp(pos1, pos2) { - return pos1.line !== pos2.line ? pos1.line - pos2.line : pos1.ch - pos2.ch; - } - - function removeTextMarks(cm) { - if (cm._selectionMarks) { - for(var i = 0; i < cm._selectionMarks.length; ++i) { - cm._selectionMarks[i].clear(); - } - } - cm._selectionMarks = null; + function onCursorActivity(cm) { + cm.operation(function() { update(cm); }); } - function markText(cm, start, end) { - if (cmp(start, end) === 0) - return; - var opt = {className: "CodeMirror-selectedtext"}; - cm._selectionMarks.push(cmp(start, end) <= 0 ? cm.markText(start, end, opt) : cm.markText(end, start, opt)); + function onChange(cm) { + if (cm.state.markedSelection.length) + cm.operation(function() { clear(cm); }); } var CHUNK_SIZE = 8; var Pos = CodeMirror.Pos; - function coverRange(cm, anchor, head) { - if (Math.abs(anchor.line - head.line) < CHUNK_SIZE) { - markText(cm, anchor, head); - return; - } - if (head.line > anchor.line) { - markText(cm, anchor, Pos(anchor.line + CHUNK_SIZE, 0)); - for(var line = anchor.line + CHUNK_SIZE; line + CHUNK_SIZE < head.line; line += CHUNK_SIZE) - markText(cm, Pos(line, 0), Pos(line + CHUNK_SIZE, 0)); - markText(cm, Pos(line, 0), head); - } else { - markText(cm, anchor, Pos(anchor.line - CHUNK_SIZE + 1, 0)); - for(var line = anchor.line - CHUNK_SIZE + 1; line - CHUNK_SIZE > head.line; line -= CHUNK_SIZE) - markText(cm, Pos(line, 0), Pos(line - CHUNK_SIZE, 0)); - markText(cm, Pos(line, 0), head); + function cmp(pos1, pos2) { + return pos1.line - pos2.line || pos1.ch - pos2.ch; + } + + function coverRange(cm, from, to, addAt) { + if (cmp(from, to) == 0) return; + var array = cm.state.markedSelection; + var cls = cm.state.markedSelectionStyle; + for (var line = from.line;;) { + var start = line == from.line ? from : Pos(line, 0); + var endLine = line + CHUNK_SIZE, atEnd = endLine >= to.line; + var end = atEnd ? to : Pos(endLine, 0); + var mark = cm.markText(start, end, {className: cls}); + if (addAt == null) array.push(mark); + else array.splice(addAt++, 0, mark); + if (atEnd) break; + line = endLine; } } - function createInitialCoverage(cm) { - var anchor = cm.getCursor("anchor"); - var head = cm.getCursor("head"); - cm._selectionMarks = []; - coverRange(cm, anchor, head); + function clear(cm) { + var array = cm.state.markedSelection; + for (var i = 0; i < array.length; ++i) array[i].clear(); + array.length = 0; } - function getCoveredRange(cm) { - var first = cm._selectionMarks[0].find(); - var last = cm._selectionMarks[cm._selectionMarks.length - 1].find(); - if (!first || !last) - return null; - var reversed = cmp(first.from, last.to) >= 0; - return reversed ? {anchor: first.to, head: last.from, reversed: reversed} : {anchor: first.from, head: last.to, reversed: reversed}; + function reset(cm) { + clear(cm); + var from = cm.getCursor("start"), to = cm.getCursor("end"); + coverRange(cm, from, to); } - function incrementalCoverageUpdate(cm) { - var anchor = cm.getCursor("anchor"); - var head = cm.getCursor("head"); - var reversed = cmp(head, anchor) < 0; - var lastSelection = getCoveredRange(cm); - // if the anchor of selection moved or selection changed direction - remove everything and construct from scratch. - if (!lastSelection || cmp(anchor, lastSelection.anchor) !== 0 || (reversed ^ lastSelection.reversed)) { - removeTextMarks(cm); - createInitialCoverage(cm); - return; - } - // fast return if nothing changed - if (cmp(head, lastSelection.head) === 0) - return; + function update(cm) { + var from = cm.getCursor("start"), to = cm.getCursor("end"); + if (cmp(from, to) == 0) return clear(cm); - // if only column changed then update last text mark - if (head.line === lastSelection.head.line) { - var lastMark = cm._selectionMarks.pop(); - var position = lastMark.find(); - lastMark.clear(); - markText(cm, reversed ? position.to : position.from, head); - return; - } + var array = cm.state.markedSelection; + if (!array.length) return coverRange(cm, from, to); + + var coverStart = array[0].find(), coverEnd = array[array.length - 1].find(); + if (!coverStart || !coverEnd || to.line - from.line < CHUNK_SIZE || + cmp(from, coverEnd.to) >= 0 || cmp(to, coverStart.from) <= 0) + return reset(cm); - if (!reversed) { - // if selection shrinks - if (head.line < lastSelection.head.line) { - var textMark, - position; - do { - textMark = cm._selectionMarks.pop(); - position = textMark.find(); - textMark.clear(); - } while (cm._selectionMarks.length && position.from.line >= head.line); - markText(cm, position.from, head); + while (cmp(from, coverStart.from) > 0) { + array.shift().clear(); + coverStart = array[0].find(); + } + if (cmp(from, coverStart.from) < 0) { + if (coverStart.to.line - from.line < CHUNK_SIZE) { + array.shift().clear(); + coverRange(cm, from, coverStart.to, 0); } else { - var textMark = cm._selectionMarks.pop(); - var position = textMark.find(); - textMark.clear(); - coverRange(cm, position.from, head); + coverRange(cm, from, coverStart.from, 0); } - } else { - // selection getting smaller - if (head.line > lastSelection.head.line) { - var textMark, - position; - do { - textMark = cm._selectionMarks.pop(); - position = textMark.find(); - textMark.clear(); - } while (cm._selectionMarks.length && position.to.line <= head.line); - markText(cm, position.to, head); + } + + while (cmp(to, coverEnd.to) < 0) { + array.pop().clear(); + coverEnd = array[array.length - 1].find(); + } + if (cmp(to, coverEnd.to) > 0) { + if (to.line - coverEnd.from.line < CHUNK_SIZE) { + array.pop().clear(); + coverRange(cm, coverEnd.from, to); } else { - var textMark = cm._selectionMarks.pop(); - var position = textMark.find(); - coverRange(cm, position.to, head); - textMark.clear(); + coverRange(cm, coverEnd.to, to); } } } - - function updateSelectedText(cm) { - cm.operation(function() { - if (!cm.somethingSelected()) - return removeTextMarks(cm); - - if (!cm._selectionMarks || !cm._selectionMarks.length) - return createInitialCoverage(cm); - - incrementalCoverageUpdate(cm); - }); - } })(); From eccea9beaad51a34006430b446892d9a5333e543 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 16 May 2013 11:39:14 +0200 Subject: [PATCH 79/91] Move addon state objects into cm.state Rather than polluting the top-level of the editor object --- addon/display/placeholder.js | 8 ++++---- addon/lint/lint.js | 14 +++++++------- addon/search/match-highlighter.js | 8 ++++---- addon/search/search.js | 2 +- addon/selection/active-line.js | 12 ++++++------ 5 files changed, 22 insertions(+), 22 deletions(-) diff --git a/addon/display/placeholder.js b/addon/display/placeholder.js index f85f2df127..18f9dff3ab 100644 --- a/addon/display/placeholder.js +++ b/addon/display/placeholder.js @@ -19,14 +19,14 @@ }); function clearPlaceholder(cm) { - if (cm._placeholder) { - cm._placeholder.parentNode.removeChild(cm._placeholder); - cm._placeholder = null; + if (cm.state.placeholder) { + cm.state.placeholder.parentNode.removeChild(cm.state.placeholder); + cm.state.placeholder = null; } } function setPlaceholder(cm) { clearPlaceholder(cm); - var elt = cm._placeholder = document.createElement("pre"); + var elt = cm.state.placeholder = document.createElement("pre"); elt.style.cssText = "height: 0; overflow: visible"; elt.className = "CodeMirror-placeholder"; elt.appendChild(document.createTextNode(cm.getOption("placeholder"))); diff --git a/addon/lint/lint.js b/addon/lint/lint.js index 29fd8d9c3c..2e7cea1925 100644 --- a/addon/lint/lint.js +++ b/addon/lint/lint.js @@ -59,7 +59,7 @@ CodeMirror.validate = (function() { } function clearMarks(cm) { - var state = cm._lintState; + var state = cm.state.lint; if (state.hasGutter) cm.clearGutter(GUTTER_ID); for (var i = 0; i < state.marked.length; ++i) state.marked[i].clear(); @@ -105,7 +105,7 @@ CodeMirror.validate = (function() { } function startLinting(cm) { - var state = cm._lintState, options = state.options; + var state = cm.state.lint, options = state.options; if (options.async) options.getAnnotations(cm, updateLinting, options); else @@ -114,7 +114,7 @@ CodeMirror.validate = (function() { function updateLinting(cm, annotationsNotSorted) { clearMarks(cm); - var state = cm._lintState, options = state.options; + var state = cm.state.lint, options = state.options; var annotations = groupByLine(annotationsNotSorted); @@ -148,7 +148,7 @@ CodeMirror.validate = (function() { } function onChange(cm) { - var state = cm._lintState; + var state = cm.state.lint; clearTimeout(state.timeout); state.timeout = setTimeout(function(){startLinting(cm);}, state.options.delay || 500); } @@ -179,14 +179,14 @@ CodeMirror.validate = (function() { if (old && old != CodeMirror.Init) { clearMarks(cm); cm.off("change", onChange); - CodeMirror.off(cm.getWrapperElement(), "mouseover", cm._lintState.onMouseOver); - delete cm._lintState; + CodeMirror.off(cm.getWrapperElement(), "mouseover", cm.state.lint.onMouseOver); + delete cm.state.lint; } if (val) { var gutters = cm.getOption("gutters"), hasLintGutter = false; for (var i = 0; i < gutters.length; ++i) if (gutters[i] == GUTTER_ID) hasLintGutter = true; - var state = cm._lintState = new LintState(cm, parseOptions(val), hasLintGutter); + var state = cm.state.lint = new LintState(cm, parseOptions(val), hasLintGutter); cm.on("change", onChange); if (state.options.tooltips != false) CodeMirror.on(cm.getWrapperElement(), "mouseover", state.onMouseOver); diff --git a/addon/search/match-highlighter.js b/addon/search/match-highlighter.js index 14c1dab5b6..0800f4c638 100644 --- a/addon/search/match-highlighter.js +++ b/addon/search/match-highlighter.js @@ -24,19 +24,19 @@ CodeMirror.defineOption("highlightSelectionMatches", false, function(cm, val, old) { var prev = old && old != CodeMirror.Init; if (val && !prev) { - cm._matchHighlightState = new State(val); + cm.state.matchHighlighter = new State(val); cm.on("cursorActivity", highlightMatches); } else if (!val && prev) { - var over = cm._matchHighlightState.overlay; + var over = cm.state.matchHighlighter.overlay; if (over) cm.removeOverlay(over); - cm._matchHighlightState = null; + cm.state.matchHighlighter = null; cm.off("cursorActivity", highlightMatches); } }); function highlightMatches(cm) { cm.operation(function() { - var state = cm._matchHighlightState; + var state = cm.state.matchHighlighter; if (state.overlay) { cm.removeOverlay(state.overlay); state.overlay = null; diff --git a/addon/search/search.js b/addon/search/search.js index 6331b86555..eb9ab8bede 100644 --- a/addon/search/search.js +++ b/addon/search/search.js @@ -27,7 +27,7 @@ this.overlay = null; } function getSearchState(cm) { - return cm._searchState || (cm._searchState = new SearchState()); + return cm.state.search || (cm.state.search = new SearchState()); } function getSearchCursor(cm, query, pos) { // Heuristic: if the query string is all lowercase, do a case insensitive search. diff --git a/addon/selection/active-line.js b/addon/selection/active-line.js index 211de0fefd..65fab6f162 100644 --- a/addon/selection/active-line.js +++ b/addon/selection/active-line.js @@ -17,23 +17,23 @@ } else if (!val && prev) { cm.off("cursorActivity", updateActiveLine); clearActiveLine(cm); - delete cm._activeLine; + delete cm.state.activeLine; } }); function clearActiveLine(cm) { - if ("_activeLine" in cm) { - cm.removeLineClass(cm._activeLine, "wrap", WRAP_CLASS); - cm.removeLineClass(cm._activeLine, "background", BACK_CLASS); + if ("activeLine" in cm.state) { + cm.removeLineClass(cm.state.activeLine, "wrap", WRAP_CLASS); + cm.removeLineClass(cm.state.activeLine, "background", BACK_CLASS); } } function updateActiveLine(cm) { var line = cm.getLineHandle(cm.getCursor().line); - if (cm._activeLine == line) return; + if (cm.state.activeLine == line) return; clearActiveLine(cm); cm.addLineClass(line, "wrap", WRAP_CLASS); cm.addLineClass(line, "background", BACK_CLASS); - cm._activeLine = line; + cm.state.activeLine = line; } })(); From 6286d9db04d604a12f660c9b3fc0ce66929abb6b Mon Sep 17 00:00:00 2001 From: lynschinzer Date: Tue, 14 May 2013 00:41:49 +0200 Subject: [PATCH 80/91] [vim keymap] Add macro support for normal mode [vim keymap] Remove duplicated @ logic [vim keymap] Remove q swapping [vim keymap] Recover mis-deleted line from 3-way merge conflict [vim keymap] "q" repeatable by count [vim keymap] Remove deprecated lookup tables [vim keymap] Robustify if condition [vim keymap] Revise logKey logic [vim keymap] IE8 compatible forEach [vim keymap] Transparentize hidden states [vim keymap] Minor fixup [vim keymap] Eliminate globals/Remove unused function/Add tests --- keymap/vim.js | 101 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- test/index.html | 1 + test/vim_test.js | 16 +++++++++ 3 files changed, 117 insertions(+), 1 deletion(-) diff --git a/keymap/vim.js b/keymap/vim.js index 9c0197faaa..fd8167e098 100644 --- a/keymap/vim.js +++ b/keymap/vim.js @@ -262,6 +262,8 @@ { keys: ['P'], type: 'action', action: 'paste', actionArgs: { after: false }}, { keys: ['r', 'character'], type: 'action', action: 'replace' }, + { keys: ['@', 'character'], type: 'action', action: 'replayMacro' }, + { keys: ['q', 'character'], type: 'action', action: 'enterMacroRecordMode' }, { keys: ['R'], type: 'action', action: 'enterReplaceMode' }, { keys: ['u'], type: 'action', action: 'undo' }, { keys: [''], type: 'action', action: 'redo' }, @@ -411,7 +413,7 @@ } var mark = buffer[(size + pointer) % size]; // skip marks that are temporarily removed from text buffer - if (!mark.find()) { + if (mark && !mark.find()) { var inc = offset > 0 ? 1 : -1; var newCur; var oldCur = cm.getCursor(); @@ -434,6 +436,26 @@ move: move }; }; + + var createMacroState = function() { + return { + macroKeyBuffer: [], + latestRegister: undefined, + enteredMacroMode: undefined, + isMacroPlaying: false, + toggle: function(cm, registerName) { + if (this.enteredMacroMode) { //onExit + this.enteredMacroMode(); // close dialog + this.enteredMacroMode = undefined; + } else { //onEnter + this.latestRegister = registerName; + this.enteredMacroMode = cm.openDialog( + '(recording)['+registerName+']', null, {bottom:true}); + } + } + } + } + // Global Vim state. Call getVimGlobalState to get and initialize. var vimGlobalState; function getVimGlobalState() { @@ -444,6 +466,7 @@ // Whether we are searching backwards. searchIsReversed: false, jumpList: createCircularJumpList(), + macroModeState: createMacroState(), // Recording latest f, t, F or T motion command. lastChararacterSearch: {increment:0, forward:true, selectedCharacter:''}, registerController: new RegisterController({}) @@ -509,6 +532,14 @@ handleKey: function(cm, key) { var command; var vim = getVimState(cm); + var macroModeState = getVimGlobalState().macroModeState; + if (macroModeState.enteredMacroMode) { + if (key == 'q') { + actions.exitMacroRecordMode(); + return; + } + logKey(macroModeState, key); + } if (key == '') { // Clear input state and get back to normal mode. vim.inputState = new InputState(); @@ -671,6 +702,9 @@ this.unamedRegister.set(text, linewise); } }, + setRegisterText: function(name, text, linewise) { + this.getRegister(name).set(text, linewise); + }, // Gets the register named @name. If one of @name doesn't already exist, // create it. If @name is invalid, return the unamedRegister. getRegister: function(name) { @@ -1521,6 +1555,30 @@ // view into the right place. cm.scrollIntoView(); }, + replayMacro: function(cm, actionArgs) { + var registerName = actionArgs.selectedCharacter; + var repeat = actionArgs.repeat; + var macroModeState = getVimGlobalState().macroModeState; + if (registerName == '@') { + registerName = macroModeState.latestRegister; + } + var keyBuffer = parseRegisterToKeyBuffer(macroModeState, registerName); + while(repeat--){ + executeMacroKeyBuffer(cm, macroModeState, keyBuffer); + } + }, + exitMacroRecordMode: function(cm, actionArgs) { + var macroModeState = getVimGlobalState().macroModeState; + macroModeState.toggle(); + parseKeyBufferToRegister(macroModeState.latestRegister, + macroModeState.macroKeyBuffer); + }, + enterMacroRecordMode: function(cm, actionArgs) { + var macroModeState = getVimGlobalState().macroModeState; + var registerName = actionArgs.selectedCharacter; + macroModeState.toggle(cm, registerName); + emptyMacroKeyBuffer(macroModeState); + }, enterInsertMode: function(cm, actionArgs) { var insertAt = (actionArgs) ? actionArgs.insertAt : null; if (insertAt == 'eol') { @@ -3190,6 +3248,47 @@ fallthrough: ['default'] }; + function parseRegisterToKeyBuffer(macroModeState, registerName) { + var match, key; + var register = getVimGlobalState().registerController.getRegister(registerName); + var text = register.toString(); + var macroKeyBuffer = macroModeState.macroKeyBuffer; + emptyMacroKeyBuffer(macroModeState); + do { + match = text.match(/<\w+-.+>|<\w+>|.|\n/); + if(match === null)break; + key = match[0]; + text = text.substring(match.index + key.length); + macroKeyBuffer.push(key); + } while (text); + return macroKeyBuffer; + } + + function parseKeyBufferToRegister(registerName, keyBuffer) { + var text = keyBuffer.join(''); + getVimGlobalState().registerController.setRegisterText(registerName, text); + } + + function emptyMacroKeyBuffer(macroModeState) { + if(macroModeState.isMacroPlaying)return; + var macroKeyBuffer = macroModeState.macroKeyBuffer; + macroKeyBuffer.length = 0; + } + + function executeMacroKeyBuffer(cm, macroModeState, keyBuffer) { + macroModeState.isMacroPlaying = true; + for (var i = 0, len = keyBuffer.length; i < len; i++) { + CodeMirror.Vim.handleKey(cm, keyBuffer[i]); + }; + macroModeState.isMacroPlaying = false; + } + + function logKey(macroModeState, key) { + if(macroModeState.isMacroPlaying)return; + var macroKeyBuffer = macroModeState.macroKeyBuffer; + macroKeyBuffer.push(key); + } + function exitReplaceMode(cm) { cm.toggleOverwrite(); cm.setCursor(cm.getCursor().line, cm.getCursor().ch-1, true); diff --git a/test/index.html b/test/index.html index 816cef5948..3eb691576a 100644 --- a/test/index.html +++ b/test/index.html @@ -9,6 +9,7 @@ + diff --git a/test/vim_test.js b/test/vim_test.js index 83bbec9ac6..ff376c6dc2 100644 --- a/test/vim_test.js +++ b/test/vim_test.js @@ -169,6 +169,22 @@ function testVim(name, run, opts, expectedFail) { } }, expectedFail); }; +testVim('qq@q', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('q', 'q', 'l', 'l', 'q'); + helpers.assertCursorAt(0,2); + helpers.doKeys('@', 'q'); + helpers.assertCursorAt(0,4); +}, { value: ' '}); +testVim('@@', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('q', 'q', 'l', 'l', 'q'); + helpers.assertCursorAt(0,2); + helpers.doKeys('@', 'q'); + helpers.assertCursorAt(0,4); + helpers.doKeys('@', '@'); + helpers.assertCursorAt(0,6); +}, { value: ' '}); var jumplistScene = ''+ 'word\n'+ '(word)\n'+ From 4206fd03bb0c6c7a4f0eea002d777e3839ca420e Mon Sep 17 00:00:00 2001 From: lynschinzer Date: Thu, 16 May 2013 11:00:25 +0200 Subject: [PATCH 81/91] [vim keymap] Fix zz/zt/zb --- keymap/vim.js | 23 ++++++++++------------- test/vim_test.js | 39 +++++++++++++++++++++++++++++++++++---- 2 files changed, 45 insertions(+), 17 deletions(-) diff --git a/keymap/vim.js b/keymap/vim.js index fd8167e098..ac6d29c465 100644 --- a/keymap/vim.js +++ b/keymap/vim.js @@ -1538,22 +1538,19 @@ }, scrollToCursor: function(cm, actionArgs) { var lineNum = cm.getCursor().line; - var heightProp = window.getComputedStyle(cm.getScrollerElement()). - getPropertyValue('height'); - var height = parseInt(heightProp); - var y = cm.charCoords({line: lineNum, ch: 0}, "local").top; - var halfHeight = parseInt(height) / 2; + var charCoords = cm.charCoords({line: lineNum, ch: 0}, "local"); + var height = cm.getScrollInfo().clientHeight; + var y = charCoords.top; + var lineHeight = charCoords.bottom - y; switch (actionArgs.position) { - case 'center': y = y - (height / 2) + 10; - break; - case 'bottom': y = y - height; - break; - case 'top': break; + case 'center': y = y - (height / 2) + lineHeight; + break; + case 'bottom': y = y - height + lineHeight*1.4; + break; + case 'top': y = y + lineHeight*0.4; + break; } cm.scrollTo(null, y); - // The calculations are slightly off, use scrollIntoView to nudge the - // view into the right place. - cm.scrollIntoView(); }, replayMacro: function(cm, actionArgs) { var registerName = actionArgs.selectedCharacter; diff --git a/test/vim_test.js b/test/vim_test.js index ff376c6dc2..69714079de 100644 --- a/test/vim_test.js +++ b/test/vim_test.js @@ -1752,14 +1752,45 @@ testVim('HML', function(cm, vim, helpers) { helpers.doKeys('M'); helpers.assertCursorAt(103,4); }, { value: (function(){ - var upperLines = new Array(100); - var lowerLines = new Array(100); + var lines = new Array(100); var upper = ' xx\n'; var lower = ' xx\n'; - upper = upperLines.join(upper); - lower = upperLines.join(lower); + upper = lines.join(upper); + lower = lines.join(lower); return upper + lower; })()}); + +var zVals = ['zb','zz','zt','z-','z.','z'].map(function(e, idx){ + var lineNum = 250; + var lines = 35; + testVim(e, function(cm, vim, helpers) { + var k1 = e[0]; + var k2 = e.substring(1); + var textHeight = cm.defaultTextHeight(); + cm.setSize(600, lines*textHeight); + cm.setCursor(lineNum, 0); + helpers.doKeys(k1, k2); + zVals[idx] = cm.getScrollInfo().top; + }, { value: (function(){ + return new Array(500).join('\n'); + })()}); +}); +testVim('zb', function(cm, vim, helpers){ + eq(zVals[2], zVals[5]); +}); + var squareBracketMotionSandbox = ''+ '({\n'+//0 ' ({\n'+//11 From 3788103b7b94f5960c3d3380097f7bb332daabad Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 16 May 2013 14:29:53 +0200 Subject: [PATCH 82/91] [real-world uses] Add Upsource --- doc/realworld.html | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/realworld.html b/doc/realworld.html index 941d926dbe..0c51cc79cd 100644 --- a/doc/realworld.html +++ b/doc/realworld.html @@ -98,6 +98,7 @@
  • Tumblr code highlighting shim
  • TurboPY (web publishing framework)
  • UmpleOnline (model-oriented programming tool)
  • +
  • Upsource (code viewer)
  • WebGL playground
  • WeScheme (learning tool)
  • WordPress plugin
  • From 7b8ed766a8a545a6bedc594a34f466ebe260baf7 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 16 May 2013 15:40:25 +0200 Subject: [PATCH 83/91] [css mode] Recognize SVG properties Closes #1529 --- mode/css/css.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/mode/css/css.js b/mode/css/css.js index f4ee021ed4..b9953c1767 100644 --- a/mode/css/css.js +++ b/mode/css/css.js @@ -392,7 +392,17 @@ CodeMirror.defineMode("css-base", function(config, parserConfig) { "vertical-align", "visibility", "voice-balance", "voice-duration", "voice-family", "voice-pitch", "voice-range", "voice-rate", "voice-stress", "voice-volume", "volume", "white-space", "widows", "width", "word-break", - "word-spacing", "word-wrap", "z-index" + "word-spacing", "word-wrap", "z-index", + // SVG-specific + "clip-path", "clip-rule", "mask", "enable-background", "filter", "flood-color", + "flood-opacity", "lighting-color", "stop-color", "stop-opacity", "pointer-events", + "color-interpolation", "color-interpolation-filters", "color-profile", + "color-rendering", "fill", "fill-opacity", "fill-rule", "image-rendering", + "marker", "marker-end", "marker-mid", "marker-start", "shape-rendering", "stroke", + "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", + "stroke-miterlimit", "stroke-opacity", "stroke-width", "text-rendering", + "baseline-shift", "dominant-baseline", "glyph-orientation-horizontal", + "glyph-orientation-vertical", "kerning", "text-anchor", "writing-mode" ]); var colorKeywords = keySet([ From 18c08f6efcc3dd646e2f1d7e32575cbe2940d39a Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 16 May 2013 15:50:22 +0200 Subject: [PATCH 84/91] [real-world uses] Better link for Upsource --- doc/realworld.html | 2 +- index.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/realworld.html b/doc/realworld.html index 0c51cc79cd..75507842dd 100644 --- a/doc/realworld.html +++ b/doc/realworld.html @@ -98,7 +98,7 @@
  • Tumblr code highlighting shim
  • TurboPY (web publishing framework)
  • UmpleOnline (model-oriented programming tool)
  • -
  • Upsource (code viewer)
  • +
  • Upsource (code viewer)
  • WebGL playground
  • WeScheme (learning tool)
  • WordPress plugin
  • diff --git a/index.html b/index.html index a0d3d5b48f..f5244742ea 100644 --- a/index.html +++ b/index.html @@ -129,6 +129,7 @@

    Usage demos:

  • Eloquent JavaScript
  • Emmet
  • Prose.io
  • +
  • Upsource
  • Paper.js
  • Codev
  • Tributary
  • @@ -138,7 +139,6 @@

    Usage demos:

  • The File Tree
  • JSHint
  • SQLFiddle
  • -
  • Try Haxe
  • CSSDeck
  • sketchPatch Livecodelab
  • NoTex
  • From fc38d5f9aaa946b2bce6458d07fb48a279021bd0 Mon Sep 17 00:00:00 2001 From: lynschinzer Date: Thu, 16 May 2013 14:55:05 +0200 Subject: [PATCH 85/91] [vim keymap] Improve code structure for later usage --- keymap/vim.js | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/keymap/vim.js b/keymap/vim.js index ac6d29c465..42e6ecaac0 100644 --- a/keymap/vim.js +++ b/keymap/vim.js @@ -3163,36 +3163,37 @@ * modifers. */ // TODO: Figure out a way to catch capslock. - function handleKeyEvent_(cm, key, modifier) { - if (isUpperCase(key)) { + function cmKeyToVimKey(key, modifier) { + var vimKey = key; + if (isUpperCase(vimKey)) { // Convert to lower case if shift is not the modifier since the key // we get from CodeMirror is always upper case. if (modifier == 'Shift') { modifier = null; } else { - key = key.toLowerCase(); + vimKey = vimKey.toLowerCase(); } } if (modifier) { // Vim will parse modifier+key combination as a single key. - key = modifier.charAt(0) + '-' + key; + vimKey = modifier.charAt(0) + '-' + vimKey; } - var specialKey = ({Enter:'CR',Backspace:'BS',Delete:'Del'})[key]; - key = specialKey ? specialKey : key; - key = key.length > 1 ? '<'+ key + '>' : key; - vim.handleKey(cm, key); + var specialKey = ({Enter:'CR',Backspace:'BS',Delete:'Del'})[vimKey]; + vimKey = specialKey ? specialKey : vimKey; + vimKey = vimKey.length > 1 ? '<'+ vimKey + '>' : vimKey; + return vimKey; } // Closure to bind CodeMirror, key, modifier. - function keyMapper(key, modifier) { + function keyMapper(vimKey) { return function(cm) { - handleKeyEvent_(cm, key, modifier); + vim.handleKey(cm, vimKey); }; } var modifiers = ['Shift', 'Ctrl']; - var keyMap = { + var cmToVimKeymap = { 'nofallthrough': true, 'style': 'fat-cursor' }; @@ -3204,11 +3205,9 @@ // them. key = "'" + key + "'"; } - if (modifier) { - keyMap[modifier + '-' + key] = keyMapper(keys[i], modifier); - } else { - keyMap[key] = keyMapper(keys[i]); - } + var vimKey = cmKeyToVimKey(keys[i], modifier); + var cmKey = modifier ? modifier + '-' + key : key; + cmToVimKeymap[cmKey] = keyMapper(vimKey); } } bindKeys(upperCaseAlphabet); @@ -3220,7 +3219,7 @@ bindKeys(numbers, 'Ctrl'); bindKeys(specialKeys); bindKeys(specialKeys, 'Ctrl'); - return keyMap; + return cmToVimKeymap; } CodeMirror.keyMap.vim = buildVimKeyMap(); From 20f7dc8c6f62fdcce602ec00c63d48d319c6a79a Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 20 May 2013 00:02:15 +0200 Subject: [PATCH 86/91] [real-world uses] Add snippets.pro --- doc/realworld.html | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/realworld.html b/doc/realworld.html index 75507842dd..f90b0f5a13 100644 --- a/doc/realworld.html +++ b/doc/realworld.html @@ -90,6 +90,7 @@
  • RealTime.io (Internet-of-Things infrastructure)
  • sketchPatch Livecodelab
  • Skulpt (in-browser Python environment)
  • +
  • Snippets.pro (code snippet sharing)
  • SolidShops (hosted e-commerce platform)
  • SQLFiddle (SQL playground)
  • The File Tree (collab editor)
  • From 14f3188c42f5c368a5a760cbd46510e00d8e337f Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 20 May 2013 14:48:45 +0200 Subject: [PATCH 87/91] More involved span-affects-wrapping test on Webkit A dash is only handled specially when preceded by a word character. Issue #1531 --- demo/spanaffectswrapping_shim.html | 11 ++++++----- lib/codemirror.js | 24 +++++++++++++++++------- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/demo/spanaffectswrapping_shim.html b/demo/spanaffectswrapping_shim.html index 733db067ff..14b6c8d82a 100644 --- a/demo/spanaffectswrapping_shim.html +++ b/demo/spanaffectswrapping_shim.html @@ -14,23 +14,24 @@ in lib/codemirror.js for some more details.

    -
    +
    foooo,-10br