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. 30
      js/inputbar.js
  3. 154
      js/models.js

@ -609,28 +609,6 @@ weechat.controller('WeechatCtrl', ['$rootScope', '$scope', '$store', '$timeout',
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
$rootScope.toggleNicklist = function() {
settings.nonicklist = !settings.nonicklist;

@ -155,6 +155,7 @@ weechat.directive('inputBar', function() {
// Support different browser quirks
var code = $event.keyCode ? $event.keyCode : $event.charCode;
var keydown = $event.type === "keydown";
// reset quick keys display
$rootScope.showQuickKeys = false;
@ -214,7 +215,7 @@ weechat.directive('inputBar', function() {
// Alt+A -> switch to buffer with activity
if ($event.altKey && (code === 97 || code === 65)) {
$event.preventDefault();
$rootScope.switchToActivityBuffer();
models.switchToActivityBuffer();
return true;
}
@ -226,14 +227,23 @@ weechat.directive('inputBar', function() {
return true;
}
// Alt+< -> switch to previous buffer
// Alt+< -> go back in history
if ($event.altKey && (code === 60 || code === 226)) {
var previousBuffer = models.getPreviousBuffer();
if (previousBuffer) {
models.setActiveBuffer(previousBuffer.id);
$event.preventDefault();
return true;
}
$event.preventDefault();
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
@ -272,7 +282,7 @@ weechat.directive('inputBar', function() {
var caretPos;
// 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;
if ($scope.command.slice(0, caretPos).indexOf("\n") !== -1) {
return false;
@ -289,7 +299,7 @@ weechat.directive('inputBar', function() {
}
// 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;
if ($scope.command.slice(caretPos).indexOf("\n") !== -1) {
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 previousBuffer = null;
var history = this.History();
this.model = { 'buffers': {} };
@ -442,15 +521,6 @@ models.service('models', ['$rootScope', '$filter', function($rootScope, $filter)
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.
* 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
* @return true on success, false if buffer was not found
*/
this.setActiveBuffer = function(bufferId, key) {
if (key === undefined) {
this.setActiveBuffer = function(bufferId, key, isMoveInHistory) {
if (!key) {
key = 'id';
}
@ -467,8 +537,7 @@ models.service('models', ['$rootScope', '$filter', function($rootScope, $filter)
if (key === 'id') {
activeBuffer = this.model.buffers[bufferId];
}
else {
} else {
activeBuffer = _.find(this.model.buffers, function(buffer) {
if (buffer[key] === bufferId) {
return buffer;
@ -495,11 +564,70 @@ models.service('models', ['$rootScope', '$filter', function($rootScope, $filter)
activeBuffer.unread = 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('notificationChanged');
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
*/

Loading…
Cancel
Save