|
|
|
@ -31,6 +31,9 @@ weechat.directive('inputBar', function() { |
|
|
|
|
// Emojify input. E.g. Turn :smile: into the unicode equivalent, but
|
|
|
|
|
// don't do replacements in the middle of a word (e.g. std::io::foo)
|
|
|
|
|
$scope.inputChanged = function() { |
|
|
|
|
// Cancel any command completion that was still ongoing
|
|
|
|
|
commandCompletionInputChanged = true; |
|
|
|
|
|
|
|
|
|
var emojiRegex = /^(?:[\uD800-\uDBFF][\uDC00-\uDFFF])+$/, // *only* emoji
|
|
|
|
|
changed = false, // whether a segment was modified
|
|
|
|
|
inputNode = $scope.getInputNode(), |
|
|
|
@ -76,6 +79,13 @@ weechat.directive('inputBar', function() { |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
$scope.completeNick = function() { |
|
|
|
|
if ((models.version[0] == 2 && models.version[1] >= 9 || models.version[0] > 2) && |
|
|
|
|
$scope.command.startsWith('/') ) { |
|
|
|
|
// We are completing a command, another function will do
|
|
|
|
|
// this on WeeChat 2.9 and later
|
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// input DOM node
|
|
|
|
|
var inputNode = $scope.getInputNode(); |
|
|
|
|
|
|
|
|
@ -108,6 +118,124 @@ weechat.directive('inputBar', function() { |
|
|
|
|
}, 0); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
var previousInput; |
|
|
|
|
var commandCompletionList; |
|
|
|
|
var commandCompletionAddSpace; |
|
|
|
|
var commandCompletionBaseWord; |
|
|
|
|
var commandCompletionPosition; |
|
|
|
|
var commandCompletionPositionInList; |
|
|
|
|
var commandCompletionInputChanged; |
|
|
|
|
$scope.completeCommand = function(direction) { |
|
|
|
|
if (models.version[0] < 2 || (models.version[0] == 2 && models.version[1] < 9)) { |
|
|
|
|
// Command completion is only supported on WeeChat 2.9+
|
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if ( !$scope.command.startsWith('/') ) { |
|
|
|
|
// We are not completing a command, maybe a nick?
|
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Cancel if input changes
|
|
|
|
|
commandCompletionInputChanged = false; |
|
|
|
|
|
|
|
|
|
// input DOM node
|
|
|
|
|
var inputNode = $scope.getInputNode(); |
|
|
|
|
|
|
|
|
|
// get current caret position
|
|
|
|
|
var caretPos = inputNode.selectionStart; |
|
|
|
|
|
|
|
|
|
// get current active buffer
|
|
|
|
|
var activeBuffer = models.getActiveBuffer(); |
|
|
|
|
|
|
|
|
|
// Empty input makes $scope.command undefined -- use empty string instead
|
|
|
|
|
var input = $scope.command || ''; |
|
|
|
|
|
|
|
|
|
// This function is for later cycling the list after we got it
|
|
|
|
|
var cycleCompletionList = function (direction) { |
|
|
|
|
// Don't do anything, the input has changed before we were able to complete the command
|
|
|
|
|
if ( commandCompletionInputChanged ) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Check if the list has elements and we have not cycled to the end yet
|
|
|
|
|
if ( !commandCompletionList || !commandCompletionList[0] ) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// If we are cycling in the other direction, go back two placed in the list
|
|
|
|
|
if ( direction === 'backward' ) { |
|
|
|
|
commandCompletionPositionInList -= 2; |
|
|
|
|
|
|
|
|
|
if ( commandCompletionPositionInList < 0 ) { |
|
|
|
|
// We have reached the beginning of list and are going backward, so go to the end;
|
|
|
|
|
commandCompletionPositionInList = commandCompletionList.length - 1; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Check we have not reached the end of the cycle list
|
|
|
|
|
if ( commandCompletionList.length <= commandCompletionPositionInList ) { |
|
|
|
|
// We have reached the end of the list, start at the beginning
|
|
|
|
|
commandCompletionPositionInList = 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Cycle the list
|
|
|
|
|
// First remove the word that's to be completed
|
|
|
|
|
var commandBeforeReplace = $scope.command.substring(0, commandCompletionPosition - commandCompletionBaseWord.length); |
|
|
|
|
var commandAfterReplace = $scope.command.substring(commandCompletionPosition, $scope.command.length); |
|
|
|
|
var replacedWord = commandCompletionList[commandCompletionPositionInList]; |
|
|
|
|
var suffix = commandCompletionAddSpace ? ' ' : ''; |
|
|
|
|
|
|
|
|
|
// Fill in the new command
|
|
|
|
|
$scope.command = commandBeforeReplace + replacedWord + suffix + commandAfterReplace; |
|
|
|
|
|
|
|
|
|
// Set the cursor position
|
|
|
|
|
var newCursorPos = commandBeforeReplace.length + replacedWord.length + suffix.length; |
|
|
|
|
setTimeout(function() { |
|
|
|
|
inputNode.focus(); |
|
|
|
|
inputNode.setSelectionRange(newCursorPos, newCursorPos); |
|
|
|
|
}, 0); |
|
|
|
|
|
|
|
|
|
// If there is only one item in the list, we are done, no next cycle
|
|
|
|
|
if ( commandCompletionList.length === 1) { |
|
|
|
|
previousInput = ''; |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
// Setup for the next cycle
|
|
|
|
|
commandCompletionPositionInList++; |
|
|
|
|
commandCompletionBaseWord = replacedWord + suffix; |
|
|
|
|
previousInput = $scope.command + activeBuffer.id; |
|
|
|
|
commandCompletionPosition = newCursorPos; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Check if we have requested this completion info before
|
|
|
|
|
if (input + activeBuffer.id !== previousInput) { |
|
|
|
|
// Remeber we requested this input for next time
|
|
|
|
|
previousInput = input + activeBuffer.id; |
|
|
|
|
|
|
|
|
|
// Ask weechat for the completion list
|
|
|
|
|
connection.requestCompletion(activeBuffer.id, caretPos, input).then( function(completionObject) { |
|
|
|
|
// Save the list of completion object, we will only request is once
|
|
|
|
|
// and cycle through it as long as the input doesn't change
|
|
|
|
|
commandCompletionList = completionObject.list; |
|
|
|
|
commandCompletionAddSpace = completionObject.add_space |
|
|
|
|
commandCompletionBaseWord = completionObject.base_word; |
|
|
|
|
commandCompletionPosition = caretPos; |
|
|
|
|
commandCompletionPositionInList = 0; |
|
|
|
|
}).then( function () { |
|
|
|
|
//after we get the list we can continue with our first cycle
|
|
|
|
|
cycleCompletionList(direction); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
// Input hasn't changed so we should already have our completion list
|
|
|
|
|
cycleCompletionList(direction); |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$rootScope.insertAtCaret = function(toInsert) { |
|
|
|
|
// caret position in the input bar
|
|
|
|
|
var inputNode = $scope.getInputNode(), |
|
|
|
@ -367,10 +495,18 @@ weechat.directive('inputBar', function() { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Tab -> nick completion
|
|
|
|
|
if (code === 9 && !$event.altKey && !$event.ctrlKey) { |
|
|
|
|
if (code === 9 && !$event.altKey && !$event.ctrlKey && !$event.shiftKey) { |
|
|
|
|
$event.preventDefault(); |
|
|
|
|
$scope.iterCandidate = tmpIterCandidate; |
|
|
|
|
$scope.completeNick(); |
|
|
|
|
$scope.completeCommand('forward'); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Shitft-Tab -> nick completion backward (only commands)
|
|
|
|
|
if (code === 9 && !$event.altKey && !$event.ctrlKey && $event.shiftKey) { |
|
|
|
|
$event.preventDefault(); |
|
|
|
|
$scope.completeCommand('backward'); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -606,6 +742,7 @@ weechat.directive('inputBar', function() { |
|
|
|
|
$scope.handleCompleteNickButton = function($event) { |
|
|
|
|
$event.preventDefault(); |
|
|
|
|
$scope.completeNick(); |
|
|
|
|
$scope.completeCommand('forward'); |
|
|
|
|
|
|
|
|
|
setTimeout(function() { |
|
|
|
|
$scope.getInputNode().focus(); |
|
|
|
|