27e168ba8b
There is now an option to choose which tab completion method to use. Also, emotes can be tab completed.
140 lines
4.3 KiB
JavaScript
140 lines
4.3 KiB
JavaScript
CyTube.tabCompleteMethods = {};
|
|
|
|
// Bash-style completion
|
|
// Only completes as far as it is possible to maintain uniqueness of the completion.
|
|
CyTube.tabCompleteMethods['Longest unique match'] = function (input, position, options, context) {
|
|
var lower = input.toLowerCase();
|
|
// First, backtrack to the nearest whitespace to find the
|
|
// incomplete string that should be completed.
|
|
var start;
|
|
var incomplete = '';
|
|
for (start = position - 1; start >= 0; start--) {
|
|
if (/\s/.test(lower[start])) {
|
|
break;
|
|
}
|
|
|
|
incomplete = lower[start] + incomplete;
|
|
}
|
|
start++;
|
|
|
|
// Nothing to complete
|
|
if (!incomplete.length) {
|
|
return {
|
|
text: input,
|
|
newPosition: position
|
|
};
|
|
}
|
|
|
|
var matches = options.filter(function (option) {
|
|
return option.toLowerCase().indexOf(incomplete) === 0;
|
|
});
|
|
|
|
var completed;
|
|
var isFullMatch = false;
|
|
if (matches.length === 0) {
|
|
return {
|
|
text: input,
|
|
newPosition: position
|
|
};
|
|
} else if (matches.length === 1) {
|
|
// Unique match
|
|
completed = matches[0];
|
|
isFullMatch = true;
|
|
} else {
|
|
// There is not a unique match, find the longest possible prefix
|
|
// that results in a unique completion
|
|
// Do this by comparing each match to the next and trimming to the
|
|
// first index where they differ.
|
|
var currentPrefix = null;
|
|
for (var i = 0; i < matches.length - 1; i++) {
|
|
var first = matches[i];
|
|
var second = matches[i+1];
|
|
var nextPrefix = '';
|
|
for (var j = 0; (currentPrefix === null || j < currentPrefix.length)
|
|
&& j < first.length
|
|
&& j < second.length; j++) {
|
|
if (first[j].toLowerCase() === second[j].toLowerCase()) {
|
|
nextPrefix += first[j];
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (currentPrefix === null || nextPrefix.length < currentPrefix.length) {
|
|
currentPrefix = nextPrefix;
|
|
}
|
|
}
|
|
|
|
completed = currentPrefix;
|
|
}
|
|
|
|
var space = isFullMatch ? ' ' : '';
|
|
return {
|
|
text: input.substring(0, start) + completed + space + input.substring(position),
|
|
newPosition: start + completed.length + space.length
|
|
};
|
|
};
|
|
|
|
// Zsh-style completion.
|
|
// Always complete a full option, and cycle through available options on successive tabs
|
|
CyTube.tabCompleteMethods['Cycle options'] = function (input, position, options, context) {
|
|
if (typeof context.start !== 'undefined') {
|
|
var currentCompletion = input.substring(context.start, position - 1);
|
|
if (currentCompletion === context.matches[context.tabIndex]) {
|
|
context.tabIndex = (context.tabIndex + 1) % context.matches.length;
|
|
var completed = context.matches[context.tabIndex];
|
|
return {
|
|
text: input.substring(0, context.start) + completed + ' ' + input.substring(position),
|
|
newPosition: context.start + completed.length + 1
|
|
};
|
|
} else {
|
|
delete context.matches;
|
|
delete context.tabIndex;
|
|
delete context.start;
|
|
}
|
|
}
|
|
|
|
var lower = input.toLowerCase();
|
|
// First, backtrack to the nearest whitespace to find the
|
|
// incomplete string that should be completed.
|
|
var start;
|
|
var incomplete = '';
|
|
for (start = position - 1; start >= 0; start--) {
|
|
if (/\s/.test(lower[start])) {
|
|
break;
|
|
}
|
|
|
|
incomplete = lower[start] + incomplete;
|
|
}
|
|
start++;
|
|
|
|
// Nothing to complete
|
|
if (!incomplete.length) {
|
|
return {
|
|
text: input,
|
|
newPosition: position
|
|
};
|
|
}
|
|
|
|
var matches = options.filter(function (option) {
|
|
return option.toLowerCase().indexOf(incomplete) === 0;
|
|
}).sort(function (a, b) {
|
|
return a.toLowerCase() > b.toLowerCase();
|
|
});
|
|
|
|
if (matches.length === 0) {
|
|
return {
|
|
text: input,
|
|
newPosition: position
|
|
};
|
|
}
|
|
|
|
context.start = start;
|
|
context.matches = matches;
|
|
context.tabIndex = 0;
|
|
return {
|
|
text: input.substring(0, start) + matches[0] + ' ' + input.substring(position),
|
|
newPosition: start + matches[0].length + 1
|
|
};
|
|
};
|