Skip to content
This repository was archived by the owner on Sep 6, 2021. It is now read-only.

Commit ef601cf

Browse files
committed
Merge pull request #7103 from adobe/nj/issue-7002
[cmv4] Simplify and update soft tab handling for multiple selections
2 parents 6a66ee4 + 5ad81c2 commit ef601cf

2 files changed

Lines changed: 431 additions & 53 deletions

File tree

src/editor/Editor.js

Lines changed: 58 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -200,24 +200,16 @@ define(function (require, exports, module) {
200200
"Shift-Tab": "indentLess",
201201

202202
"Left": function (instance) {
203-
if (!self._handleSoftTabNavigation(-1, "moveH")) {
204-
CodeMirror.commands.goCharLeft(instance);
205-
}
203+
self._handleSoftTabNavigation(-1, "moveH");
206204
},
207205
"Right": function (instance) {
208-
if (!self._handleSoftTabNavigation(1, "moveH")) {
209-
CodeMirror.commands.goCharRight(instance);
210-
}
206+
self._handleSoftTabNavigation(1, "moveH");
211207
},
212208
"Backspace": function (instance) {
213-
if (!self._handleSoftTabNavigation(-1, "deleteH")) {
214-
CodeMirror.commands.delCharBefore(instance);
215-
}
209+
self._handleSoftTabNavigation(-1, "deleteH");
216210
},
217211
"Delete": function (instance) {
218-
if (!self._handleSoftTabNavigation(1, "deleteH")) {
219-
CodeMirror.commands.delCharAfter(instance);
220-
}
212+
self._handleSoftTabNavigation(1, "deleteH");
221213
},
222214
"Esc": function (instance) {
223215
if (self.getSelections().length > 1) {
@@ -448,59 +440,73 @@ define(function (require, exports, module) {
448440
/**
449441
* @private
450442
* Handle left arrow, right arrow, backspace and delete keys when soft tabs are used.
451-
* @param {!CodeMirror} instance CodeMirror instance
452443
* @param {number} direction Direction of movement: 1 for forward, -1 for backward
453-
* @param {function} functionName name of the CodeMirror function to call
454-
* @return {boolean} true if key was handled
444+
* @param {string} functionName name of the CodeMirror function to call if we handle the key
455445
*/
456446
Editor.prototype._handleSoftTabNavigation = function (direction, functionName) {
457-
var handled = false,
458-
instance = this._codeMirror;
447+
var instance = this._codeMirror,
448+
overallJump = null;
459449

460450
if (!instance.getOption("indentWithTabs")) {
461-
var indentUnit = instance.getOption("indentUnit"),
462-
cursor = this.getCursorPos(),
463-
jump = cursor.ch % indentUnit,
464-
line = instance.getLine(cursor.line);
465-
466-
if (direction === 1) {
467-
jump = indentUnit - jump;
468-
469-
if (cursor.ch + jump > line.length) { // Jump would go beyond current line
470-
return false;
471-
}
472-
473-
if (line.substr(cursor.ch, jump).search(/\S/) === -1) {
474-
instance[functionName](jump, "char");
475-
handled = true;
476-
}
477-
} else {
478-
// Quick exit if we are at the beginning of the line
479-
if (cursor.ch === 0) {
480-
return false;
451+
var indentUnit = instance.getOption("indentUnit");
452+
453+
_.each(this.getSelections(), function (sel) {
454+
if (CodeMirror.cmpPos(sel.start, sel.end) !== 0) {
455+
// This is a range - it will just collapse/be deleted regardless of the jump we set, so
456+
// we can just ignore it and continue. (We don't want to return false in this case since
457+
// we want to keep looking at other ranges.)
458+
return;
481459
}
482460

483-
// If we are on the tab boundary, jump by the full amount,
484-
// but not beyond the start of the line.
485-
if (jump === 0) {
486-
jump = indentUnit;
487-
}
461+
var cursor = sel.start,
462+
jump = cursor.ch % indentUnit,
463+
line = instance.getLine(cursor.line);
488464

489-
// Search backwards to the first non-space character
490-
var offset = line.substr(cursor.ch - jump, jump).search(/\s*$/g);
465+
// Don't do any soft tab handling if there are non-whitespace characters before the cursor in
466+
// any of the selections.
467+
if (line.substr(0, cursor.ch).search(/\S/) !== -1) {
468+
jump = null;
469+
} else if (direction === 1) { // right
470+
jump = indentUnit - jump;
491471

492-
if (offset !== -1) { // Adjust to jump to first non-space character
493-
jump -= offset;
472+
// Don't jump if it would take us past the end of the line, or if there are
473+
// non-whitespace characters within the jump distance.
474+
if (cursor.ch + jump > line.length || line.substr(cursor.ch, jump).search(/\S/) !== -1) {
475+
jump = null;
476+
}
477+
} else { // left
478+
// If we are on the tab boundary, jump by the full amount,
479+
// but not beyond the start of the line.
480+
if (jump === 0) {
481+
jump = indentUnit;
482+
}
483+
if (cursor.ch - jump < 0) {
484+
jump = null;
485+
} else {
486+
// We're moving left, so negate the jump.
487+
jump = -jump;
488+
}
494489
}
495490

496-
if (jump > 0) {
497-
instance[functionName](-jump, "char");
498-
handled = true;
491+
// Did we calculate a jump, and is this jump value either the first one or
492+
// consistent with all the other jumps? If so, we're good. Otherwise, bail
493+
// out of the foreach, since as soon as we hit an inconsistent jump we don't
494+
// have to look any further.
495+
if (jump !== null &&
496+
(overallJump === null || overallJump === jump)) {
497+
overallJump = jump;
498+
} else {
499+
overallJump = null;
500+
return false;
499501
}
500-
}
502+
});
501503
}
502-
503-
return handled;
504+
505+
if (overallJump === null) {
506+
// Just do the default move, which is one char in the given direction.
507+
overallJump = direction;
508+
}
509+
instance[functionName](overallJump, "char");
504510
};
505511

506512
/**

0 commit comments

Comments
 (0)