Skip to content

Instantly share code, notes, and snippets.

@d3m3vilurr
Created January 23, 2014 22:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save d3m3vilurr/8588379 to your computer and use it in GitHub Desktop.
Save d3m3vilurr/8588379 to your computer and use it in GitHub Desktop.
IRCCloud CJK Autocompletion Patch
// ==UserScript==
// @name IRCCloud CJK Autocompletion Patch
// @namespace https://gist.github.com/d3m3vilurr/8588379
// @version 0.1
// @include https://www.irccloud.com/*
// @run-at document-body
// @grant unsafeWindow
// ==/UserScript==
var init = function() {
if (!unsafeWindow.TabCompletion) {
console.log('wait irccloud modules');
return setTimeout(init, 1000);
}
unsafeWindow.TabCompletion.prototype.getCandidates = function () {
if (!this.word && !this.cycling) {
this.cacheCursorRange();
// Split the sentence either side of the word before the selection
var value = this.getValue();
this.wordsTillSelection = value.slice(0, this.cursorRange.start);
this.afterSelection = value.slice(this.cursorRange.start);
// Split on non words
// Word chars are alnum: a-z0-9
// diacritics: \u00C0-\u00D6 \u00D8-\u00F6 \u00F8-\u02AF
// specific list of chars: # [ \ ] ^ _ ` { | } -
var tokens = this.wordsTillSelection.split(/[^a-z0-9\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02AF\uAC00-\uD7FF\u1100-\u11FF\u3130-\u318F\u31C0-\u4DBF\uA960-\uA97F\uFF00-\uFFEF\u1B000-\u1B0FF\u2FF0-\u30FF\u4E00-\u9FFF\u20000-\u2A6DF\u2A700-\u2B73F\u2B740-\u2B81F\uF900-\uFAFF\u2E80-\u2EFF\u2F00-\u2FDF\uF900-\uFAFF\u2F800-\u2FA1F\uFE30-\uFE4F#[\\\]^_`{|}-]+/i);
this.word = tokens.pop();
}
var members = this.model.getMembers();
var channels = this.model.connection.buffers.channels;
var previousBuffer = this.model.session.previousBuffer;
// Build up list of matching candidates
var candidates = [];
var chanCommandMatch = this.wordsTillSelection.match(/^\/(j|join|channel|rejoin|mode)\s*$/i);
var startChanCommandMatch = this.wordsTillSelection.match(/^\/(j|join|channel|rejoin|mode)(?:\s+|$)/i);
if (startChanCommandMatch) {
if (startChanCommandMatch[1].toLowerCase() == 'mode') {
this.cyclingModeChannels = true;
} else {
this.cyclingJoin = true;
}
}
var topicCommandMatch = this.wordsTillSelection.match(/^\/topic\s*$/i);
var startBanCommandMatch = this.wordsTillSelection.match(/^\/ban(?:\s+|$)/i);
var nonJoinOnlyChans = false;
if (chanCommandMatch) {
// Channel command, only complete from channels
this.cycling = true;
this.cyclingCommand = true;
if (this.cyclingModeChannels) {
nonJoinOnlyChans = true;
}
channels.each(function (channel) {
if (!channel.isArchived()) {
candidates.push(channel);
}
});
candidates.sort(this.cmpBuffers);
} else if (this.model.isChannel() && topicCommandMatch) {
// Cycle topics
var topic = this.model.getTopic().getText();
this.cycling = true;
this.cyclingCommand = true;
this.cyclingTopic = true;
// TODO keep a history of topics server side
candidates.push(topic);
} else if (!this.word) {
// No word, only complete from last highlighted (or conversation recipient)
this.cycling = true;
this.cyclingLastHighlighted = true;
if (this.model.isConversation()) {
candidates.push(this.model.getRecipient());
} else {
members.each(function (member) {
if (!member.isIgnored() && member.lastHighlighted) {
candidates.push(member);
}
});
}
// Sort by last highlighted
candidates.sort(function (a, b) {
return (b.getLastHighlighted() || 0) - (a.getLastHighlighted() || 0);
});
} else {
// Have a word, not a channel command, add matching members and channels
var anyMembers = false;
members.each(function (member) {
if (this.inputMatches(member.getName(), this.word)) {
anyMembers = true;
candidates.push(member);
}
}, this);
if (!startBanCommandMatch) {
channels.each(function (chan) {
if (this.inputMatchesNoStrip(chan.getName(), this.word)) {
if (!anyMembers) {
nonJoinOnlyChans = true;
}
candidates.push(chan);
}
}, this);
}
candidates.sort(_.bind(this.cmpAll, this));
}
// Move previous chan to start for join commands
if (startChanCommandMatch && previousBuffer && previousBuffer.isChannel()) {
var prevChanIndex = $.inArray(previousBuffer, candidates);
if (prevChanIndex !== -1) {
var prevChan = candidates.splice(prevChanIndex, 1)[0];
candidates.unshift(prevChan);
}
}
var selfChanIndex = $.inArray(this.model, candidates);
if (selfChanIndex !== -1) {
// Move current chan to end for join commands and to start for other chan only commands
var selfChan = candidates.splice(selfChanIndex, 1)[0];
if (nonJoinOnlyChans) {
candidates.unshift(selfChan);
} else {
candidates.push(selfChan);
}
}
if (!this.cyclingTopic) {
// Move yourself to the end
var selfIndex = _.indexOf(_.map(candidates, function (item, index) {
return item.getName().toLowerCase();
}), this.model.getNick().toLowerCase());
if (selfIndex !== -1) {
candidates.push(candidates.splice(selfIndex, 1)[0]);
}
}
if (startBanCommandMatch) {
this.cyclingBan = true;
// Add a ban mask too
candidates = _.flatten(_.map(candidates, function (m) {
return [m, m.getBanMask(true)];
}));
}
return candidates;
};
};
init();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment