emacs: use mark ring instead of single mark

This commit is contained in:
Robert Krahn 2013-05-26 21:01:33 -07:00
commit 6b01dde666

View file

@ -95,17 +95,15 @@ exports.handler.attach = function(editor) {
$formerLineStart = editor.session.$useEmacsStyleLineStart; $formerLineStart = editor.session.$useEmacsStyleLineStart;
editor.session.$useEmacsStyleLineStart = true; editor.session.$useEmacsStyleLineStart = true;
editor.session.$emacsMark = null; editor.session.$emacsMark = null; // the active mark
editor.session.$emacsMarkRing = editor.session.$emacsMarkRing || []; editor.session.$emacsMarkRing = editor.session.$emacsMarkRing || [];
editor.emacsMarkMode = function() { editor.emacsMark = function() {
return this.session.$emacsMark; return this.session.$emacsMark;
} }
editor.setEmacsMarkMode = function(p) { editor.setEmacsMark = function(p) {
var prevMark = this.session.$emacsMark; // to deactivate pass in a falsy value
if (prevMark)
this.session.$emacsMarkRing.push(prevMark);
this.session.$emacsMark = p; this.session.$emacsMark = p;
} }
@ -113,12 +111,18 @@ exports.handler.attach = function(editor) {
var prevMark = this.session.$emacsMark; var prevMark = this.session.$emacsMark;
if (prevMark) if (prevMark)
this.session.$emacsMarkRing.push(prevMark); this.session.$emacsMarkRing.push(prevMark);
if (activate) this.session.$emacsMark = p; if (!p || activate) this.setEmacsMark(p)
else this.session.$emacsMarkRing.push(p); else this.session.$emacsMarkRing.push(p);
} }
editor.popEmacsMark = function() {
var mark = this.emacsMark();
if (mark) { this.setEmacsMark(null); return mark; }
return this.session.$emacsMarkRing.pop();
}
editor.getLastEmacsMark = function(p) { editor.getLastEmacsMark = function(p) {
return this.session.$emacsMark || this.session.$emacsMarkRing.reverse()[0]; return this.session.$emacsMark || this.session.$emacsMarkRing.slice(-1)[0];
} }
editor.on("click", $resetMarkMode); editor.on("click", $resetMarkMode);
@ -209,7 +213,7 @@ exports.handler.handleKeyboard = function(data, hashId, key, keyCode) {
var editor = data.editor; var editor = data.editor;
// insertstring data.count times // insertstring data.count times
if (hashId == -1) { if (hashId == -1) {
editor.setEmacsMarkMode(null); editor.pushEmacsMark();
if (data.count) { if (data.count) {
var str = Array(data.count + 1).join(key); var str = Array(data.count + 1).join(key);
data.count = null; data.count = null;
@ -263,7 +267,7 @@ exports.handler.handleKeyboard = function(data, hashId, key, keyCode) {
args = command.args; args = command.args;
if (command.command) command = command.command; if (command.command) command = command.command;
if (command === "goorselect") { if (command === "goorselect") {
command = editor.emacsMarkMode() ? args[1] : args[0]; command = editor.emacsMark() ? args[1] : args[0];
args = null; args = null;
} }
} }
@ -272,7 +276,7 @@ exports.handler.handleKeyboard = function(data, hashId, key, keyCode) {
if (command === "insertstring" || if (command === "insertstring" ||
command === "splitline" || command === "splitline" ||
command === "togglecomment") { command === "togglecomment") {
editor.setEmacsMarkMode(null); editor.pushEmacsMark();
} }
command = this.commands[command] || editor.commands.commands[command]; command = this.commands[command] || editor.commands.commands[command];
if (!command) return undefined; if (!command) return undefined;
@ -401,28 +405,38 @@ exports.handler.addCommands({
editor.multiSelect.toggleBlockSelection(); editor.multiSelect.toggleBlockSelection();
}, },
setMark: { setMark: {
exec: function(editor) { exec: function(editor, args) {
// Emulate emacs highlighting behaviour in transient-mark-mode.
// Sets mark-mode and clears current selection. // Sets mark-mode and clears current selection.
// When mark is set, keyboard cursor movement commands become // When mark is set, keyboard cursor movement commands become
// selection modification commands. That is, // selection modification commands. That is,
// "goto" commands become "select" commands. // "goto" commands become "select" commands.
// Any insertion or mouse click resets mark-mode. // Any insertion or mouse click resets mark-mode.
// setMark twice in a row at the same place resets markmode // setMark twice in a row at the same place resets markmode
var markMode = editor.emacsMarkMode(); var mark = editor.emacsMark(),
if (markMode) { transientMarkModeActive = true;
// if transientMarkModeActive then mark behavior is a little
// different. Deactivate the mark when setMark is run with active
// mark
if (transientMarkModeActive && (mark || !editor.selection.isEmpty())) {
editor.pushEmacsMark(editor.getCursorPosition());
editor.pushEmacsMark();
editor.clearSelection();
return;
}
if (mark) {
var cp = editor.getCursorPosition(); var cp = editor.getCursorPosition();
if (editor.selection.isEmpty() && if (editor.selection.isEmpty() &&
markMode.row == cp.row && markMode.column == cp.column) { mark.row == cp.row && mark.column == cp.column) {
editor.setEmacsMarkMode(null); editor.pushEmacsMark();
// console.log("Mark mode off");
return; return;
} }
} }
// turn on mark mode // turn on mark mode
markMode = editor.getCursorPosition(); mark = editor.getCursorPosition();
editor.setEmacsMarkMode(markMode); editor.setEmacsMark(mark);
editor.selection.setSelectionAnchor(markMode.row, markMode.column); editor.selection.setSelectionAnchor(mark.row, mark.column);
}, },
readonly: true, readonly: true,
multiSelectAction: "forEach" multiSelectAction: "forEach"
@ -459,7 +473,7 @@ exports.handler.addCommands({
multiSelectAction: "forEach" multiSelectAction: "forEach"
}, },
killLine: function(editor) { killLine: function(editor) {
editor.setEmacsMarkMode(null); editor.pushEmacsMark(null);
var pos = editor.getCursorPosition(); var pos = editor.getCursorPosition();
if (pos.column == 0 && if (pos.column == 0 &&
editor.session.doc.getLine(pos.row).length == 0) { editor.session.doc.getLine(pos.row).length == 0) {
@ -513,7 +527,7 @@ exports.handler.addCommands({
}, },
keyboardQuit: function(editor) { keyboardQuit: function(editor) {
editor.selection.clearSelection(); editor.selection.clearSelection();
editor.setEmacsMarkMode(null); editor.setEmacsMark(null);
}, },
focusCommandLine: function(editor, arg) { focusCommandLine: function(editor, arg) {
if (editor.showCommandLine) if (editor.showCommandLine)