CodeMirror 5.24

Notable change for css mode: Expose lineComment property for LESS and SCSS dialects. Recognize vendor prefixes on pseudo-elements.
This commit is contained in:
tophf 2017-03-18 03:24:59 +03:00
parent df570dab9e
commit b2e8bf02a9
10 changed files with 113 additions and 53 deletions

View File

@ -1,3 +1,5 @@
MIT License
Copyright (C) 2017 by Marijn Haverbeke <marijnh@gmail.com> and others
Permission is hereby granted, free of charge, to any person obtaining a copy

View File

@ -46,12 +46,17 @@
// Rough heuristic to try and detect lines that are part of multi-line string
function probablyInsideString(cm, pos, line) {
return /\bstring\b/.test(cm.getTokenTypeAt(Pos(pos.line, 0))) && !/^[\'\"`]/.test(line)
return /\bstring\b/.test(cm.getTokenTypeAt(Pos(pos.line, 0))) && !/^[\'\"\`]/.test(line)
}
function getMode(cm, pos) {
var mode = cm.getMode()
return mode.useInnerComments === false || !mode.innerMode ? mode : cm.getModeAt(pos)
}
CodeMirror.defineExtension("lineComment", function(from, to, options) {
if (!options) options = noOptions;
var self = this, mode = self.getModeAt(from);
var self = this, mode = getMode(self, from);
var firstLine = self.getLine(from.line);
if (firstLine == null || probablyInsideString(self, from, firstLine)) return;
@ -95,7 +100,7 @@
CodeMirror.defineExtension("blockComment", function(from, to, options) {
if (!options) options = noOptions;
var self = this, mode = self.getModeAt(from);
var self = this, mode = getMode(self, from);
var startString = options.blockCommentStart || mode.blockCommentStart;
var endString = options.blockCommentEnd || mode.blockCommentEnd;
if (!startString || !endString) {
@ -129,7 +134,7 @@
CodeMirror.defineExtension("uncomment", function(from, to, options) {
if (!options) options = noOptions;
var self = this, mode = self.getModeAt(from);
var self = this, mode = getMode(self, from);
var end = Math.min(to.ch != 0 || to.line == from.line ? to.line : to.line - 1, self.lastLine()), start = Math.min(from.line, end);
// Try finding line comments
@ -171,9 +176,11 @@
endLine = self.getLine(--end);
close = endLine.indexOf(endString);
}
var insideStart = Pos(start, open + 1), insideEnd = Pos(end, close + 1)
if (close == -1 ||
!/comment/.test(self.getTokenTypeAt(Pos(start, open + 1))) ||
!/comment/.test(self.getTokenTypeAt(Pos(end, close + 1))))
!/comment/.test(self.getTokenTypeAt(insideStart)) ||
!/comment/.test(self.getTokenTypeAt(insideEnd)) ||
self.getRange(insideStart, insideEnd, "\n").indexOf(endString) > -1)
return false;
// Avoid killing block comments completely outside the selection.

View File

@ -140,7 +140,11 @@
if (options.async || getAnnotations.async) {
lintAsync(cm, getAnnotations, passOptions)
} else {
updateLinting(cm, getAnnotations(cm.getValue(), passOptions, cm));
var annotations = getAnnotations(cm.getValue(), passOptions, cm);
if (annotations.then) annotations.then(function(issues) {
updateLinting(cm, issues);
});
else updateLinting(cm, annotations);
}
}

View File

@ -77,17 +77,21 @@
curLine = pos.line;
curLineObj = cm.getLineHandle(curLine);
}
if (wrapping && curLineObj.height > singleLineH)
if ((curLineObj.widgets && curLineObj.widgets.length) ||
(wrapping && curLineObj.height > singleLineH))
return cm.charCoords(pos, "local")[top ? "top" : "bottom"];
var topY = cm.heightAtLine(curLineObj, "local");
return topY + (top ? 0 : curLineObj.height);
}
var lastLine = cm.lastLine()
if (cm.display.barWidth) for (var i = 0, nextTop; i < anns.length; i++) {
var ann = anns[i];
if (ann.to.line > lastLine) continue;
var top = nextTop || getY(ann.from, true) * hScale;
var bottom = getY(ann.to, false) * hScale;
while (i < anns.length - 1) {
if (anns[i + 1].to.line > lastLine) break;
nextTop = getY(anns[i + 1].from, true) * hScale;
if (nextTop > bottom + .9) break;
ann = anns[++i];

View File

@ -371,7 +371,9 @@
"Shift-Alt-,": "goDocStart", "Shift-Alt-.": "goDocEnd",
"Ctrl-S": "findNext", "Ctrl-R": "findPrev", "Ctrl-G": quit, "Shift-Alt-5": "replace",
"Alt-/": "autocomplete",
"Ctrl-J": "newlineAndIndent", "Enter": false, "Tab": "indentAuto",
"Enter": "newlineAndIndent",
"Ctrl-J": repeated(function(cm) { cm.replaceSelection("\n", "end"); }),
"Tab": "indentAuto",
"Alt-G G": function(cm) {
var prefix = getPrefix(cm, true);

View File

@ -152,18 +152,25 @@
var text = cm.getRange(from, to);
var query = fullWord ? new RegExp("\\b" + text + "\\b") : text;
var cur = cm.getSearchCursor(query, to);
if (cur.findNext()) {
cm.addSelection(cur.from(), cur.to());
} else {
var found = cur.findNext();
if (!found) {
cur = cm.getSearchCursor(query, Pos(cm.firstLine(), 0));
if (cur.findNext())
cm.addSelection(cur.from(), cur.to());
found = cur.findNext();
}
if (!found || isSelectedRange(cm.listSelections(), cur.from(), cur.to()))
return CodeMirror.Pass
cm.addSelection(cur.from(), cur.to());
}
if (fullWord)
cm.state.sublimeFindFullWord = cm.doc.sel;
};
function isSelectedRange(ranges, from, to) {
for (var i = 0; i < ranges.length; i++)
if (ranges[i].from() == from && ranges[i].to() == to) return true
return false
}
var mirror = "(){}[]";
function selectBetweenBrackets(cm) {
var ranges = cm.listSelections(), newRanges = []

View File

@ -142,7 +142,7 @@
{ keys: 'X', type: 'operatorMotion', operator: 'delete', motion: 'moveByCharacters', motionArgs: { forward: false }, operatorMotionArgs: { visualLine: true }},
{ keys: 'D', type: 'operatorMotion', operator: 'delete', motion: 'moveToEol', motionArgs: { inclusive: true }, context: 'normal'},
{ keys: 'D', type: 'operator', operator: 'delete', operatorArgs: { linewise: true }, context: 'visual'},
{ keys: 'Y', type: 'operatorMotion', operator: 'yank', motion: 'moveToEol', motionArgs: { inclusive: true }, context: 'normal'},
{ keys: 'Y', type: 'operatorMotion', operator: 'yank', motion: 'expandToLine', motionArgs: { linewise: true }, context: 'normal'},
{ keys: 'Y', type: 'operator', operator: 'yank', operatorArgs: { linewise: true }, context: 'visual'},
{ keys: 'C', type: 'operatorMotion', operator: 'change', motion: 'moveToEol', motionArgs: { inclusive: true }, context: 'normal'},
{ keys: 'C', type: 'operator', operator: 'change', operatorArgs: { linewise: true }, context: 'visual'},
@ -1245,11 +1245,13 @@
}
}
function onPromptKeyUp(e, query, close) {
var keyName = CodeMirror.keyName(e), up;
var keyName = CodeMirror.keyName(e), up, offset;
if (keyName == 'Up' || keyName == 'Down') {
up = keyName == 'Up' ? true : false;
offset = e.target ? e.target.selectionEnd : 0;
query = vimGlobalState.searchHistoryController.nextMatch(query, up) || '';
close(query);
if (offset && e.target) e.target.selectionEnd = e.target.selectionStart = Math.min(offset, e.target.value.length);
} else {
if ( keyName != 'Left' && keyName != 'Right' && keyName != 'Ctrl' && keyName != 'Alt' && keyName != 'Shift')
vimGlobalState.searchHistoryController.reset();
@ -1281,6 +1283,8 @@
clearInputState(cm);
close();
cm.focus();
} else if (keyName == 'Up' || keyName == 'Down') {
CodeMirror.e_stop(e);
} else if (keyName == 'Ctrl-U') {
// Ctrl-U clears input.
CodeMirror.e_stop(e);
@ -1344,7 +1348,7 @@
exCommandDispatcher.processCommand(cm, input);
}
function onPromptKeyDown(e, input, close) {
var keyName = CodeMirror.keyName(e), up;
var keyName = CodeMirror.keyName(e), up, offset;
if (keyName == 'Esc' || keyName == 'Ctrl-C' || keyName == 'Ctrl-[' ||
(keyName == 'Backspace' && input == '')) {
vimGlobalState.exCommandHistoryController.pushInput(input);
@ -1355,9 +1359,12 @@
cm.focus();
}
if (keyName == 'Up' || keyName == 'Down') {
CodeMirror.e_stop(e);
up = keyName == 'Up' ? true : false;
offset = e.target ? e.target.selectionEnd : 0;
input = vimGlobalState.exCommandHistoryController.nextMatch(input, up) || '';
close(input);
if (offset && e.target) e.target.selectionEnd = e.target.selectionStart = Math.min(offset, e.target.value.length);
} else if (keyName == 'Ctrl-U') {
// Ctrl-U clears input.
CodeMirror.e_stop(e);
@ -1620,9 +1627,8 @@
return findNext(cm, prev/** prev */, query, motionArgs.repeat);
},
goToMark: function(cm, _head, motionArgs, vim) {
var mark = vim.marks[motionArgs.selectedCharacter];
if (mark) {
var pos = mark.find();
var pos = getMarkPos(cm, vim, motionArgs.selectedCharacter);
if (pos) {
return motionArgs.linewise ? { line: pos.line, ch: findFirstNonWhiteSpaceCharacter(cm.getLine(pos.line)) } : pos;
}
return null;
@ -3966,6 +3972,17 @@
return {top: from.line, bottom: to.line};
}
function getMarkPos(cm, vim, markName) {
if (markName == '\'') {
var history = cm.doc.history.done;
var event = history[history.length - 2];
return event && event.ranges && event.ranges[0].head;
}
var mark = vim.marks[markName];
return mark && mark.find();
}
var ExCommandDispatcher = function() {
this.buildCommandMap_();
};
@ -4074,11 +4091,10 @@
case '$':
return cm.lastLine();
case '\'':
var mark = cm.state.vim.marks[inputStream.next()];
if (mark && mark.find()) {
return mark.find().line;
}
throw new Error('Mark not set');
var markName = inputStream.next();
var markPos = getMarkPos(cm, cm.state.vim, markName);
if (!markPos) throw new Error('Mark not set');
return markPos.line;
default:
inputStream.backUp(1);
return undefined;
@ -4147,8 +4163,8 @@
var mapping = {
keys: lhs,
type: 'keyToEx',
exArgs: { input: rhs.substring(1) },
user: true};
exArgs: { input: rhs.substring(1) }
};
if (ctx) { mapping.context = ctx; }
defaultKeymap.unshift(mapping);
} else {
@ -4156,8 +4172,7 @@
var mapping = {
keys: lhs,
type: 'keyToKey',
toKeys: rhs,
user: true
toKeys: rhs
};
if (ctx) { mapping.context = ctx; }
defaultKeymap.unshift(mapping);
@ -4178,8 +4193,7 @@
var keys = lhs;
for (var i = 0; i < defaultKeymap.length; i++) {
if (keys == defaultKeymap[i].keys
&& defaultKeymap[i].context === ctx
&& defaultKeymap[i].user) {
&& defaultKeymap[i].context === ctx) {
defaultKeymap.splice(i, 1);
return;
}
@ -4310,25 +4324,27 @@
showConfirm(cm, regInfo);
},
sort: function(cm, params) {
var reverse, ignoreCase, unique, number;
var reverse, ignoreCase, unique, number, pattern;
function parseArgs() {
if (params.argString) {
var args = new CodeMirror.StringStream(params.argString);
if (args.eat('!')) { reverse = true; }
if (args.eol()) { return; }
if (!args.eatSpace()) { return 'Invalid arguments'; }
var opts = args.match(/[a-z]+/);
if (opts) {
opts = opts[0];
ignoreCase = opts.indexOf('i') != -1;
unique = opts.indexOf('u') != -1;
var decimal = opts.indexOf('d') != -1 && 1;
var hex = opts.indexOf('x') != -1 && 1;
var octal = opts.indexOf('o') != -1 && 1;
var opts = args.match(/([dinuox]+)?\s*(\/.+\/)?\s*/);
if (!opts && !args.eol()) { return 'Invalid arguments'; }
if (opts[1]) {
ignoreCase = opts[1].indexOf('i') != -1;
unique = opts[1].indexOf('u') != -1;
var decimal = opts[1].indexOf('d') != -1 || opts[1].indexOf('n') != -1 && 1;
var hex = opts[1].indexOf('x') != -1 && 1;
var octal = opts[1].indexOf('o') != -1 && 1;
if (decimal + hex + octal > 1) { return 'Invalid arguments'; }
number = decimal && 'decimal' || hex && 'hex' || octal && 'octal';
}
if (args.match(/\/.*\//)) { return 'patterns not supported'; }
if (opts[2]) {
pattern = new RegExp(opts[2].substr(1, opts[2].length - 2), ignoreCase ? 'i' : '');
}
}
}
var err = parseArgs();
@ -4342,14 +4358,18 @@
var curStart = Pos(lineStart, 0);
var curEnd = Pos(lineEnd, lineLength(cm, lineEnd));
var text = cm.getRange(curStart, curEnd).split('\n');
var numberRegex = (number == 'decimal') ? /(-?)([\d]+)/ :
var numberRegex = pattern ? pattern :
(number == 'decimal') ? /(-?)([\d]+)/ :
(number == 'hex') ? /(-?)(?:0x)?([0-9a-f]+)/i :
(number == 'octal') ? /([0-7]+)/ : null;
var radix = (number == 'decimal') ? 10 : (number == 'hex') ? 16 : (number == 'octal') ? 8 : null;
var numPart = [], textPart = [];
if (number) {
if (number || pattern) {
for (var i = 0; i < text.length; i++) {
if (numberRegex.exec(text[i])) {
var matchPart = pattern ? text[i].match(pattern) : null;
if (matchPart && matchPart[0] != '') {
numPart.push(matchPart);
} else if (!pattern && numberRegex.exec(text[i])) {
numPart.push(text[i]);
} else {
textPart.push(text[i]);
@ -4368,8 +4388,17 @@
bnum = parseInt((bnum[1] + bnum[2]).toLowerCase(), radix);
return anum - bnum;
}
numPart.sort(compareFn);
textPart.sort(compareFn);
function comparePatternFn(a, b) {
if (reverse) { var tmp; tmp = a; a = b; b = tmp; }
if (ignoreCase) { a[0] = a[0].toLowerCase(); b[0] = b[0].toLowerCase(); }
return (a[0] < b[0]) ? -1 : 1;
}
numPart.sort(pattern ? comparePatternFn : compareFn);
if (pattern) {
for (var i = 0; i < numPart.length; i++) {
numPart[i] = numPart[i].input;
}
} else if (!number) { textPart.sort(compareFn); }
text = (!reverse) ? textPart.concat(numPart) : numPart.concat(textPart);
if (unique) { // Remove duplicate lines
var textOld = text;

View File

@ -223,11 +223,8 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
cursor: default;
z-index: 4;
}
.CodeMirror-gutter-wrapper {
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
}
.CodeMirror-gutter-wrapper ::selection { background-color: transparent }
.CodeMirror-gutter-wrapper ::-moz-selection { background-color: transparent }
.CodeMirror-lines {
cursor: text;
@ -272,6 +269,8 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
.CodeMirror-widget {}
.CodeMirror-rtl pre { direction: rtl; }
.CodeMirror-code {
outline: none;
}

View File

@ -28,6 +28,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
colorKeywords = parserConfig.colorKeywords || {},
valueKeywords = parserConfig.valueKeywords || {},
allowNested = parserConfig.allowNested,
lineComment = parserConfig.lineComment,
supportsAtComponent = parserConfig.supportsAtComponent === true;
var type, override;
@ -253,6 +254,8 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
};
states.pseudo = function(type, stream, state) {
if (type == "meta") return "pseudo";
if (type == "word") {
override = "variable-3";
return state.context.type;
@ -407,6 +410,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
electricChars: "}",
blockCommentStart: "/*",
blockCommentEnd: "*/",
lineComment: lineComment,
fold: "brace"
};
});
@ -663,7 +667,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
"small", "small-caps", "small-caption", "smaller", "soft-light", "solid", "somali",
"source-atop", "source-in", "source-out", "source-over", "space", "space-around", "space-between", "spell-out", "square",
"square-button", "start", "static", "status-bar", "stretch", "stroke", "sub",
"subpixel-antialiased", "super", "sw-resize", "symbolic", "symbols", "table",
"subpixel-antialiased", "super", "sw-resize", "symbolic", "symbols", "system-ui", "table",
"table-caption", "table-cell", "table-column", "table-column-group",
"table-footer-group", "table-header-group", "table-row", "table-row-group",
"tamil",
@ -730,6 +734,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
valueKeywords: valueKeywords,
fontProperties: fontProperties,
allowNested: true,
lineComment: "//",
tokenHooks: {
"/": function(stream, state) {
if (stream.eat("/")) {
@ -772,6 +777,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
valueKeywords: valueKeywords,
fontProperties: fontProperties,
allowNested: true,
lineComment: "//",
tokenHooks: {
"/": function(stream, state) {
if (stream.eat("/")) {

View File

@ -64,7 +64,7 @@ code {
</textarea></form>
<script>
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
extraKeys: {"Ctrl-Space": "autocomplete"},
extraKeys: {"Ctrl-Space": "autocomplete"}
});
</script>