Implement buffer history for alt+a and alt+<, alt+>, and alt+/

buffer-history
Lorenz Hübschle-Schneider 11 years ago committed by Lorenz Hübschle-Schneider
parent c4bddc993d
commit 7eb45f7fcb
  1. 22
      js/glowingbear.js
  2. 26
      js/inputbar.js
  3. 154
      js/models.js

@ -609,28 +609,6 @@ weechat.controller('WeechatCtrl', ['$rootScope', '$scope', '$store', '$timeout',
return true; return true;
}; };
//XXX not sure whether this belongs here
$rootScope.switchToActivityBuffer = function() {
// Find next buffer with activity and switch to it
var sortedBuffers = _.sortBy($scope.getBuffers(), 'number');
var i, buffer;
// Try to find buffer with notification
for (i in sortedBuffers) {
buffer = sortedBuffers[i];
if (buffer.notification > 0) {
$scope.setActiveBuffer(buffer.id);
return; // return instead of break so that the second for loop isn't executed
}
}
// No notifications, find first buffer with unread lines instead
for (i in sortedBuffers) {
buffer = sortedBuffers[i];
if (buffer.unread > 0) {
$scope.setActiveBuffer(buffer.id);
return;
}
}
};
// Helper function since the keypress handler is in a different scope // Helper function since the keypress handler is in a different scope
$rootScope.toggleNicklist = function() { $rootScope.toggleNicklist = function() {
settings.nonicklist = !settings.nonicklist; settings.nonicklist = !settings.nonicklist;

@ -155,6 +155,7 @@ weechat.directive('inputBar', function() {
// Support different browser quirks // Support different browser quirks
var code = $event.keyCode ? $event.keyCode : $event.charCode; var code = $event.keyCode ? $event.keyCode : $event.charCode;
var keydown = $event.type === "keydown";
// reset quick keys display // reset quick keys display
$rootScope.showQuickKeys = false; $rootScope.showQuickKeys = false;
@ -214,7 +215,7 @@ weechat.directive('inputBar', function() {
// Alt+A -> switch to buffer with activity // Alt+A -> switch to buffer with activity
if ($event.altKey && (code === 97 || code === 65)) { if ($event.altKey && (code === 97 || code === 65)) {
$event.preventDefault(); $event.preventDefault();
$rootScope.switchToActivityBuffer(); models.switchToActivityBuffer();
return true; return true;
} }
@ -226,14 +227,23 @@ weechat.directive('inputBar', function() {
return true; return true;
} }
// Alt+< -> switch to previous buffer // Alt+< -> go back in history
if ($event.altKey && (code === 60 || code === 226)) { if ($event.altKey && (code === 60 || code === 226)) {
var previousBuffer = models.getPreviousBuffer();
if (previousBuffer) {
models.setActiveBuffer(previousBuffer.id);
$event.preventDefault(); $event.preventDefault();
return true; return models.switchToPrevNextBuffer(false);
}
// Alt+> -> go forward in history
// TODO alternative codes for cross-browser stuff
if ($event.altKey && code === 62) {
$event.preventDefault();
return models.switchToPrevNextBuffer(true);
} }
// Alt+/ -> switch to previous buffer
if ($event.altKey && code === 47) {
$event.preventDefault();
return models.switchToLastBuffer();
} }
// Double-tap Escape -> disconnect // Double-tap Escape -> disconnect
@ -272,7 +282,7 @@ weechat.directive('inputBar', function() {
var caretPos; var caretPos;
// Arrow up -> go up in history // Arrow up -> go up in history
if ($event.type === "keydown" && code === 38 && document.activeElement === inputNode) { if (keydown && code === 38 && document.activeElement === inputNode) {
caretPos = inputNode.selectionStart; caretPos = inputNode.selectionStart;
if ($scope.command.slice(0, caretPos).indexOf("\n") !== -1) { if ($scope.command.slice(0, caretPos).indexOf("\n") !== -1) {
return false; return false;
@ -289,7 +299,7 @@ weechat.directive('inputBar', function() {
} }
// Arrow down -> go down in history // Arrow down -> go down in history
if ($event.type === "keydown" && code === 40 && document.activeElement === inputNode) { if (keydown && code === 40 && document.activeElement === inputNode) {
caretPos = inputNode.selectionStart; caretPos = inputNode.selectionStart;
if ($scope.command.slice(caretPos).indexOf("\n") !== -1) { if ($scope.command.slice(caretPos).indexOf("\n") !== -1) {
return false; return false;

@ -417,9 +417,88 @@ models.service('models', ['$rootScope', '$filter', function($rootScope, $filter)
}; };
}; };
/*
* Buffer switch history
*/
this.History = function() {
// The buffer history. Pointers are converted to ints to save space.
// This means that we can definitely save the entire history and not
// consume absurd amounts of memory, unlike UTF-16 strings of len ≥ 7
var history = [];
var position = -1;
var firstSmartJump = -1;
var lastActionOffset = +1; // last is initially forward
var _return = function(bufferId) {
return bufferId.toString(16);
};
var getFirstSmartJump = function() {
return _return(history[firstSmartJump]);
};
var resetSmartJump = function() {
firstSmartJump = history.length - 1;
};
var smartJump = function() {
firstSmartJump--;
};
var getPrevNextBuffer = function(next) {
if (next && position < history.length - 1) {
return _return(history[position + 1]);
} else if (!next && position > 0) {
return _return(history[position - 1]);
}
};
var getLastDisplayedBuffer = function() {
var newPosition = position - lastActionOffset;
if (newPosition >= 0 && newPosition < history.length) {
return _return(newPosition);
}
};
var switchToLastBuffer = function() {
lastActionOffset = -lastActionOffset;
position += lastActionOffset;
};
var moveInHistory = function(forward) {
lastActionOffset = forward ? +1 : -1;
position += lastActionOffset;
};
var recordBufferSwitch = function(buffer) {
// save buffer pointer as int
history.push(parseInt("0x" + buffer.id));
firstSmartJump++;
position++;
lastActionOffset = +1;
};
var get = function() {
return {position: position, firstSmartJump: firstSmartJump, history: history};
};
return {
getFirstSmartJump: getFirstSmartJump,
resetSmartJump: resetSmartJump,
smartJump: smartJump,
getPrevNextBuffer: getPrevNextBuffer,
moveInHistory: moveInHistory,
getLastDisplayedBuffer: getLastDisplayedBuffer,
switchToLastBuffer: switchToLastBuffer,
recordBufferSwitch: recordBufferSwitch,
get: get
};
};
var activeBuffer = null; var activeBuffer = null;
var previousBuffer = null; var previousBuffer = null;
var history = this.History();
this.model = { 'buffers': {} }; this.model = { 'buffers': {} };
@ -442,15 +521,6 @@ models.service('models', ['$rootScope', '$filter', function($rootScope, $filter)
return activeBuffer; return activeBuffer;
}; };
/*
* Returns the previous current active buffer
*
* @return previous buffer object
*/
this.getPreviousBuffer = function() {
return previousBuffer;
};
/* /*
* Sets the buffer specifiee by bufferId as active. * Sets the buffer specifiee by bufferId as active.
* Deactivates the previous current buffer. * Deactivates the previous current buffer.
@ -458,8 +528,8 @@ models.service('models', ['$rootScope', '$filter', function($rootScope, $filter)
* @param bufferId id of the new active buffer * @param bufferId id of the new active buffer
* @return true on success, false if buffer was not found * @return true on success, false if buffer was not found
*/ */
this.setActiveBuffer = function(bufferId, key) { this.setActiveBuffer = function(bufferId, key, isMoveInHistory) {
if (key === undefined) { if (!key) {
key = 'id'; key = 'id';
} }
@ -467,8 +537,7 @@ models.service('models', ['$rootScope', '$filter', function($rootScope, $filter)
if (key === 'id') { if (key === 'id') {
activeBuffer = this.model.buffers[bufferId]; activeBuffer = this.model.buffers[bufferId];
} } else {
else {
activeBuffer = _.find(this.model.buffers, function(buffer) { activeBuffer = _.find(this.model.buffers, function(buffer) {
if (buffer[key] === bufferId) { if (buffer[key] === bufferId) {
return buffer; return buffer;
@ -495,11 +564,70 @@ models.service('models', ['$rootScope', '$filter', function($rootScope, $filter)
activeBuffer.unread = 0; activeBuffer.unread = 0;
activeBuffer.notification = 0; activeBuffer.notification = 0;
if (!isMoveInHistory) {
history.recordBufferSwitch(activeBuffer);
}
console.log('buffer switched to', activeBuffer.fullName, 'history:', history.get());
$rootScope.$emit('activeBufferChanged', unreadSum); $rootScope.$emit('activeBufferChanged', unreadSum);
$rootScope.$emit('notificationChanged'); $rootScope.$emit('notificationChanged');
return true; return true;
}; };
this.switchToActivityBuffer = function() {
var that = this;
var jumpTo = function(bufferId) {
that.setActiveBuffer(bufferId);
history.smartJump();
};
// Find next buffer with activity and switch to it
var sortedBuffers = _.sortBy(this.getBuffers(), 'number');
var i, buffer;
// Try to find buffer with notification
for (i in sortedBuffers) {
buffer = sortedBuffers[i];
if (buffer.notification > 0) {
jumpTo(buffer.id);
return; // return instead of break so that the second for loop isn't executed
}
}
// No notifications, find first buffer with unread lines instead
for (i in sortedBuffers) {
buffer = sortedBuffers[i];
if (buffer.unread > 0) {
jumpTo(buffer.id);
return;
}
}
// Jump back to first buffer in the series
this.setActiveBuffer(history.getFirstSmartJump());
history.resetSmartJump();
};
this.switchToPrevNextBuffer = function(forward) {
var newBufferId = history.getPrevNextBuffer(forward);
console.log('switching to buffer:', newBufferId);
if (newBufferId) {
this.setActiveBuffer(newBufferId, null, true);
history.moveInHistory(forward);
return true;
}
return false;
};
this.switchToLastBuffer = function() {
var lastBufferId = history.getLastDisplayedBuffer();
if (lastBufferId) {
this.setActiveBuffer(lastBufferId, null, true);
history.switchToLastBuffer();
return true;
}
return false;
};
/* /*
* Returns the buffer list * Returns the buffer list
*/ */

Loading…
Cancel
Save