parent
7abd3c17b2
commit
a918923852
@ -0,0 +1,174 @@ |
|||||||
|
/** |
||||||
|
* Portable utilities for IRC. |
||||||
|
*/ |
||||||
|
|
||||||
|
var IrcUtils = { |
||||||
|
/** |
||||||
|
* Completes a single nick. |
||||||
|
* |
||||||
|
* @param candidate What to search for |
||||||
|
* @param nickList Array of current nicks sorted alphabetically |
||||||
|
* @return Completed nick (null if not found) |
||||||
|
*/ |
||||||
|
_completeSingleNick: function(candidate, nickList) { |
||||||
|
var foundNick = null; |
||||||
|
|
||||||
|
nickList.some(function(nick) { |
||||||
|
if (nick.search(candidate) == 0) { |
||||||
|
// found!
|
||||||
|
foundNick = nick; |
||||||
|
return true; |
||||||
|
} |
||||||
|
return false; |
||||||
|
}); |
||||||
|
|
||||||
|
return foundNick; |
||||||
|
}, |
||||||
|
|
||||||
|
/** |
||||||
|
* Get the next nick when iterating nicks. |
||||||
|
* |
||||||
|
* @param iterCandidate First characters to look at |
||||||
|
* @param currentNick Current selected nick |
||||||
|
* @param nickList Array of current nicks sorted alphabetically |
||||||
|
* @return Next nick (may be the same) |
||||||
|
*/ |
||||||
|
_nextNick: function(iterCandidate, currentNick, nickList) { |
||||||
|
var firstInGroup = null; |
||||||
|
var matchingNicks = []; |
||||||
|
var at = null; |
||||||
|
|
||||||
|
// collect matching nicks
|
||||||
|
for (var i = 0; i < nickList.length; ++i) { |
||||||
|
if (nickList[i].search(iterCandidate) == 0) { |
||||||
|
matchingNicks.push(nickList[i]); |
||||||
|
if (currentNick == nickList[i]) { |
||||||
|
at = matchingNicks.length - 1; |
||||||
|
} |
||||||
|
} else if (matchingNicks.length > 0) { |
||||||
|
// end of group, no need to check after this
|
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (at == null || matchingNicks.length == 0) { |
||||||
|
return currentNick; |
||||||
|
} else { |
||||||
|
++at; |
||||||
|
if (at == matchingNicks.length) { |
||||||
|
// cycle
|
||||||
|
at = 0; |
||||||
|
} |
||||||
|
return matchingNicks[at]; |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
/** |
||||||
|
* Nicks tab completion. |
||||||
|
* |
||||||
|
* @param text Plain text (no colors) |
||||||
|
* @param caretPos Current caret position (0 means before the first character) |
||||||
|
* @param doIterate True to iterate the nicks if possible |
||||||
|
* @param iterCandidate Current iteration candidate (null if not iterating) |
||||||
|
* @param nickList Array of current nicks sorted alphabetically |
||||||
|
* @return Object with following properties: |
||||||
|
* text: new complete replacement text |
||||||
|
* caretPos: new caret position within new text |
||||||
|
* foundNick: completed nick (or null if not possible) |
||||||
|
* iterCandidate: current iterating candidate |
||||||
|
*/ |
||||||
|
completeNick: function(text, caretPos, doIterate, iterCandidate, nickList) { |
||||||
|
// text before and after caret
|
||||||
|
var beforeCaret = text.substring(0, caretPos); |
||||||
|
var afterCaret = text.substring(caretPos); |
||||||
|
|
||||||
|
// default: don't change anything
|
||||||
|
var ret = { |
||||||
|
text: text, |
||||||
|
caretPos: caretPos, |
||||||
|
foundNick: null, |
||||||
|
iterCandidate: null |
||||||
|
}; |
||||||
|
|
||||||
|
// iterating nicks at the beginning?
|
||||||
|
var m = beforeCaret.match(/^([a-zA-Z0-9_\\\[\]{}^`|-]+): $/); |
||||||
|
if (m) { |
||||||
|
if (doIterate) { |
||||||
|
// try iterating
|
||||||
|
var newNick = IrcUtils._nextNick(iterCandidate, m[1], nickList); |
||||||
|
beforeCaret = newNick + ': '; |
||||||
|
return { |
||||||
|
text: beforeCaret + afterCaret, |
||||||
|
caretPos: beforeCaret.length, |
||||||
|
foundNick: newNick, |
||||||
|
iterCandidate: iterCandidate |
||||||
|
}; |
||||||
|
} else { |
||||||
|
// if not iterating, don't do anything
|
||||||
|
return ret; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// nick completion in the beginning?
|
||||||
|
m = beforeCaret.match(/^([a-zA-Z0-9_\\\[\]{}^`|-]+)$/); |
||||||
|
if (m) { |
||||||
|
// try completing
|
||||||
|
var newNick = IrcUtils._completeSingleNick(m[1], nickList); |
||||||
|
if (newNick === null) { |
||||||
|
// no match
|
||||||
|
return ret; |
||||||
|
} |
||||||
|
beforeCaret = newNick + ': '; |
||||||
|
if (afterCaret[0] == ' ') { |
||||||
|
// swallow first space after caret if any
|
||||||
|
afterCaret = afterCaret.substring(1); |
||||||
|
} |
||||||
|
return { |
||||||
|
text: beforeCaret + afterCaret, |
||||||
|
caretPos: beforeCaret.length, |
||||||
|
foundNick: newNick, |
||||||
|
iterCandidate: m[1] |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
// iterating nicks in the middle?
|
||||||
|
m = beforeCaret.match(/^(.* )([a-zA-Z0-9_\\\[\]{}^`|-]+) $/); |
||||||
|
if (m) { |
||||||
|
if (doIterate) { |
||||||
|
// try iterating
|
||||||
|
var newNick = IrcUtils._nextNick(iterCandidate, m[2], nickList); |
||||||
|
beforeCaret = m[1] + newNick + ' '; |
||||||
|
return { |
||||||
|
text: beforeCaret + afterCaret, |
||||||
|
caretPos: beforeCaret.length, |
||||||
|
foundNick: newNick, |
||||||
|
iterCandidate: iterCandidate |
||||||
|
}; |
||||||
|
} else { |
||||||
|
// if not iterating, don't do anything
|
||||||
|
return ret; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// nick completion elsewhere in the middle?
|
||||||
|
m = beforeCaret.match(/^(.* )([a-zA-Z0-9_\\\[\]{}^`|-]+)$/); |
||||||
|
if (m) { |
||||||
|
// try completing
|
||||||
|
var newNick = IrcUtils._completeSingleNick(m[2], nickList); |
||||||
|
if (newNick === null) { |
||||||
|
// no match
|
||||||
|
return ret; |
||||||
|
} |
||||||
|
beforeCaret = m[1] + newNick + ' '; |
||||||
|
return { |
||||||
|
text: beforeCaret + afterCaret, |
||||||
|
caretPos: beforeCaret.length, |
||||||
|
foundNick: newNick, |
||||||
|
iterCandidate: m[2] |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
// completion not possible
|
||||||
|
return ret; |
||||||
|
} |
||||||
|
}; |
Loading…
Reference in new issue