| Index: Source/devtools/front_end/source_frame/CodeMirrorTextEditor.js
|
| diff --git a/Source/devtools/front_end/source_frame/CodeMirrorTextEditor.js b/Source/devtools/front_end/source_frame/CodeMirrorTextEditor.js
|
| index 35e9ed2f95c8b8ea7fcc679d07d88be4f929bf27..66e153be766b458af52dcf5e7797154d62e198e5 100644
|
| --- a/Source/devtools/front_end/source_frame/CodeMirrorTextEditor.js
|
| +++ b/Source/devtools/front_end/source_frame/CodeMirrorTextEditor.js
|
| @@ -83,8 +83,10 @@ WebInspector.CodeMirrorTextEditor = function(url, delegate)
|
| "Ctrl-Down": "goDocEnd",
|
| "Ctrl-Left": "goGroupLeft",
|
| "Ctrl-Right": "goGroupRight",
|
| - "Alt-Left": "goLineStart",
|
| - "Alt-Right": "goLineEnd",
|
| + "Alt-Left": "moveCamelLeft",
|
| + "Alt-Right": "moveCamelRight",
|
| + "Shift-Alt-Left": "selectCamelLeft",
|
| + "Shift-Alt-Right": "selectCamelRight",
|
| "Ctrl-Backspace": "delGroupBefore",
|
| "Ctrl-Delete": "delGroupAfter",
|
| "Ctrl-/": "toggleComment",
|
| @@ -101,6 +103,10 @@ WebInspector.CodeMirrorTextEditor = function(url, delegate)
|
| "Cmd-Down": "goDocEnd",
|
| "Alt-Left": "goGroupLeft",
|
| "Alt-Right": "goGroupRight",
|
| + "Ctrl-Left": "moveCamelLeft",
|
| + "Ctrl-Right": "moveCamelRight",
|
| + "Shift-Ctrl-Left": "selectCamelLeft",
|
| + "Shift-Ctrl-Right": "selectCamelRight",
|
| "Cmd-Left": "goLineStartSmart",
|
| "Cmd-Right": "goLineEnd",
|
| "Alt-Backspace": "delGroupBefore",
|
| @@ -200,6 +206,28 @@ WebInspector.CodeMirrorTextEditor.selectNextOccurrenceCommand = function(codeMir
|
| CodeMirror.commands.selectNextOccurrence = WebInspector.CodeMirrorTextEditor.selectNextOccurrenceCommand;
|
|
|
| /**
|
| + * @param {boolean} shift
|
| + * @param {!CodeMirror} codeMirror
|
| + */
|
| +WebInspector.CodeMirrorTextEditor.moveCamelLeftCommand = function(shift, codeMirror)
|
| +{
|
| + codeMirror._codeMirrorTextEditor._doCamelCaseMovement(-1, shift);
|
| +}
|
| +CodeMirror.commands.moveCamelLeft = WebInspector.CodeMirrorTextEditor.moveCamelLeftCommand.bind(null, false);
|
| +CodeMirror.commands.selectCamelLeft = WebInspector.CodeMirrorTextEditor.moveCamelLeftCommand.bind(null, true);
|
| +
|
| +/**
|
| + * @param {boolean} shift
|
| + * @param {!CodeMirror} codeMirror
|
| + */
|
| +WebInspector.CodeMirrorTextEditor.moveCamelRightCommand = function(shift, codeMirror)
|
| +{
|
| + codeMirror._codeMirrorTextEditor._doCamelCaseMovement(1, shift);
|
| +}
|
| +CodeMirror.commands.moveCamelRight = WebInspector.CodeMirrorTextEditor.moveCamelRightCommand.bind(null, false);
|
| +CodeMirror.commands.selectCamelRight = WebInspector.CodeMirrorTextEditor.moveCamelRightCommand.bind(null, true);
|
| +
|
| +/**
|
| * @param {!CodeMirror} codeMirror
|
| */
|
| CodeMirror.commands.smartNewlineAndIndent = function(codeMirror)
|
| @@ -272,6 +300,154 @@ WebInspector.CodeMirrorTextEditor.MaximumNumberOfWhitespacesPerSingleSpan = 16;
|
| WebInspector.CodeMirrorTextEditor.MaxEditableTextSize = 1024 * 1024 * 10;
|
|
|
| WebInspector.CodeMirrorTextEditor.prototype = {
|
| + /**
|
| + * @param {number} lineNumber
|
| + * @param {number} lineLength
|
| + * @param {number} charNumber
|
| + * @return {{lineNumber: number, columnNumber: number}}
|
| + */
|
| + _normalizePositionForOverlappingColumn: function(lineNumber, lineLength, charNumber)
|
| + {
|
| + var linesCount = this._codeMirror.lineCount();
|
| + var columnNumber = charNumber;
|
| + if (charNumber < 0 && lineNumber > 0) {
|
| + --lineNumber;
|
| + columnNumber = this.line(lineNumber).length;
|
| + } else if (charNumber >= lineLength && lineNumber < linesCount - 1) {
|
| + ++lineNumber;
|
| + columnNumber = 0;
|
| + } else {
|
| + columnNumber = Number.constrain(charNumber, 0, lineLength);
|
| + }
|
| + return {
|
| + lineNumber: lineNumber,
|
| + columnNumber: columnNumber
|
| + };
|
| + },
|
| +
|
| + /**
|
| + * @param {number} lineNumber
|
| + * @param {number} columnNumber
|
| + * @param {number} direction
|
| + * @return {{lineNumber: number, columnNumber: number}}
|
| + */
|
| + _camelCaseMoveFromPosition: function(lineNumber, columnNumber, direction)
|
| + {
|
| + /**
|
| + * @param {number} charNumber
|
| + * @param {number} length
|
| + * @return {boolean}
|
| + */
|
| + function valid(charNumber, length)
|
| + {
|
| + return charNumber >= 0 && charNumber < length;
|
| + }
|
| +
|
| + /**
|
| + * @param {string} text
|
| + * @param {number} charNumber
|
| + * @return {boolean}
|
| + */
|
| + function isWordStart(text, charNumber)
|
| + {
|
| + var position = charNumber;
|
| + var nextPosition = charNumber + 1;
|
| + return valid(position, text.length) && valid(nextPosition, text.length)
|
| + && WebInspector.TextUtils.isWordChar(text[position]) && WebInspector.TextUtils.isWordChar(text[nextPosition])
|
| + && WebInspector.TextUtils.isUpperCase(text[position]) && WebInspector.TextUtils.isLowerCase(text[nextPosition]);
|
| + }
|
| +
|
| + /**
|
| + * @param {string} text
|
| + * @param {number} charNumber
|
| + * @return {boolean}
|
| + */
|
| + function isWordEnd(text, charNumber)
|
| + {
|
| + var position = charNumber;
|
| + var prevPosition = charNumber - 1;
|
| + return valid(position, text.length) && valid(prevPosition, text.length)
|
| + && WebInspector.TextUtils.isWordChar(text[position]) && WebInspector.TextUtils.isWordChar(text[prevPosition])
|
| + && WebInspector.TextUtils.isUpperCase(text[position]) && WebInspector.TextUtils.isLowerCase(text[prevPosition]);
|
| + }
|
| +
|
| + /**
|
| + * @param {number} lineNumber
|
| + * @param {number} lineLength
|
| + * @param {number} columnNumber
|
| + * @return {{lineNumber: number, columnNumber: number}}
|
| + */
|
| + function constrainPosition(lineNumber, lineLength, columnNumber)
|
| + {
|
| + return {
|
| + lineNumber: lineNumber,
|
| + columnNumber: Number.constrain(columnNumber, 0, lineLength)
|
| + };
|
| + }
|
| +
|
| + var text = this.line(lineNumber);
|
| + var length = text.length;
|
| +
|
| + if ((columnNumber === length && direction === 1)
|
| + || (columnNumber === 0 && direction === -1))
|
| + return this._normalizePositionForOverlappingColumn(lineNumber, length, columnNumber + direction);
|
| +
|
| + var charNumber = direction === 1 ? columnNumber : columnNumber - 1;
|
| +
|
| + // Move through initial spaces if any.
|
| + while (valid(charNumber, length) && WebInspector.TextUtils.isSpaceChar(text[charNumber]))
|
| + charNumber += direction;
|
| + if (!valid(charNumber, length))
|
| + return constrainPosition(lineNumber, length, charNumber);
|
| +
|
| + if (WebInspector.TextUtils.isStopChar(text[charNumber])) {
|
| + while (valid(charNumber, length) && WebInspector.TextUtils.isStopChar(text[charNumber]))
|
| + charNumber += direction;
|
| + if (!valid(charNumber, length))
|
| + return constrainPosition(lineNumber, length, charNumber);
|
| + return {
|
| + lineNumber: lineNumber,
|
| + columnNumber: direction === -1 ? charNumber + 1 : charNumber
|
| + };
|
| + }
|
| +
|
| + charNumber += direction;
|
| + while (valid(charNumber, length) && !isWordStart(text, charNumber) && !isWordEnd(text, charNumber) && WebInspector.TextUtils.isWordChar(text[charNumber]))
|
| + charNumber += direction;
|
| +
|
| + if (!valid(charNumber, length))
|
| + return constrainPosition(lineNumber, length, charNumber);
|
| + if (isWordStart(text, charNumber) || isWordEnd(text, charNumber)) {
|
| + return {
|
| + lineNumber: lineNumber,
|
| + columnNumber: charNumber
|
| + };
|
| + }
|
| +
|
| + return {
|
| + lineNumber: lineNumber,
|
| + columnNumber: direction === -1 ? charNumber + 1 : charNumber
|
| + };
|
| + },
|
| +
|
| + /**
|
| + * @param {number} direction
|
| + * @param {boolean} shift
|
| + */
|
| + _doCamelCaseMovement: function(direction, shift)
|
| + {
|
| + var selections = this.selections();
|
| + for (var i = 0; i < selections.length; ++i) {
|
| + var selection = selections[i];
|
| + var move = this._camelCaseMoveFromPosition(selection.endLine, selection.endColumn, direction);
|
| + selection.endLine = move.lineNumber;
|
| + selection.endColumn = move.columnNumber;
|
| + if (!shift)
|
| + selections[i] = selection.collapseToEnd();
|
| + }
|
| + this.setSelections(selections);
|
| + },
|
| +
|
| dispose: function()
|
| {
|
| WebInspector.settings.textEditorIndent.removeChangeListener(this._updateEditorIndentation, this);
|
|
|