Implement IRC nick completion uility
This commit is contained in:
parent
7abd3c17b2
commit
a918923852
2 changed files with 175 additions and 0 deletions
|
@ -15,6 +15,7 @@
|
|||
<script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.5.2/underscore-min.js"></script>
|
||||
<script type="text/javascript" src="js/localstorage.js"></script>
|
||||
<script type="text/javascript" src="js/weechat.js"></script>
|
||||
<script type="text/javascript" src="js/irc-utils.js"></script>
|
||||
<script type="text/javascript" src="js/websockets.js"></script>
|
||||
<script type="text/javascript" src="js/models.js"></script>
|
||||
<script type="text/javascript" src="js/plugins.js"></script>
|
||||
|
|
174
js/irc-utils.js
Normal file
174
js/irc-utils.js
Normal file
|
@ -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 a new issue