Insert user-configurable string when autocompleting nicks

Fixes #1176
This commit is contained in:
Pavel Djundik 2017-12-05 18:05:14 +02:00
parent 7dd4603d3c
commit b5ad495c6d
3 changed files with 39 additions and 12 deletions

View File

@ -4,6 +4,7 @@ const $ = require("jquery");
const fuzzy = require("fuzzy"); const fuzzy = require("fuzzy");
const Mousetrap = require("mousetrap"); const Mousetrap = require("mousetrap");
const emojiMap = require("./libs/simplemap.json"); const emojiMap = require("./libs/simplemap.json");
const options = require("./options");
const constants = require("./constants"); const constants = require("./constants");
const input = $("#input"); const input = $("#input");
@ -56,8 +57,19 @@ const nicksStrategy = {
template([string]) { template([string]) {
return string; return string;
}, },
replace([, original]) { replace([, original], position = 1) {
// If no postfix specified, return autocompleted nick as-is
if (!options.nickPostfix) {
return original; return original;
}
// If there is whitespace in the input already, append space to nick
if (position > 0 && /\s/.test(input.val())) {
return original + " ";
}
// If nick is first in the input, append specified postfix
return original + options.nickPostfix;
}, },
index: 1, index: 1,
}; };
@ -152,11 +164,13 @@ const backgroundColorStrategy = {
function enableAutocomplete() { function enableAutocomplete() {
let tabCount = 0; let tabCount = 0;
let lastMatch = "";
let currentMatches = []; let currentMatches = [];
input.on("input.tabcomplete", () => { input.on("input.tabcomplete", () => {
tabCount = 0; tabCount = 0;
currentMatches = []; currentMatches = [];
lastMatch = "";
}); });
Mousetrap(input.get(0)).bind("tab", (e) => { Mousetrap(input.get(0)).bind("tab", (e) => {
@ -172,27 +186,26 @@ function enableAutocomplete() {
return; return;
} }
let lastWord;
if (tabCount === 0) { if (tabCount === 0) {
lastWord = text.split(/\s/).pop(); lastMatch = text.split(/\s/).pop();
if (lastWord.length === 0) { if (lastMatch.length === 0) {
return; return;
} }
currentMatches = completeNicks(lastWord, false); currentMatches = completeNicks(lastMatch, false);
if (currentMatches.length === 0) { if (currentMatches.length === 0) {
return; return;
} }
} else {
lastWord = nicksStrategy.replace([0, currentMatches[(tabCount - 1) % currentMatches.length]]);
} }
const matchedNick = currentMatches[tabCount % currentMatches.length]; const position = input.get(0).selectionStart - lastMatch.length;
input.val(text.substr(0, input.get(0).selectionStart - lastWord.length) + nicksStrategy.replace([0, matchedNick])); const newMatch = nicksStrategy.replace([0, currentMatches[tabCount % currentMatches.length]], position);
input.val(text.substr(0, position) + newMatch);
lastMatch = newMatch;
tabCount++; tabCount++;
}, "keydown"); }, "keydown");

View File

@ -5,7 +5,6 @@ const escapeRegExp = require("lodash/escapeRegExp");
const userStyles = $("#user-specified-css"); const userStyles = $("#user-specified-css");
const storage = require("./localStorage"); const storage = require("./localStorage");
const tz = require("./libs/handlebars/tz"); const tz = require("./libs/handlebars/tz");
const autocompletion = require("./autocompletion");
const windows = $("#windows"); const windows = $("#windows");
const chat = $("#chat"); const chat = $("#chat");
@ -13,6 +12,7 @@ const chat = $("#chat");
// Default options // Default options
const options = { const options = {
autocomplete: true, autocomplete: true,
nickPostfix: "",
coloredNicks: true, coloredNicks: true,
desktopNotifications: false, desktopNotifications: false,
highlights: [], highlights: [],
@ -43,6 +43,9 @@ userOptions = null;
module.exports = options; module.exports = options;
// Due to cyclical dependency, have to require it after exports
const autocompletion = require("./autocompletion");
module.exports.shouldOpenMessagePreview = function(type) { module.exports.shouldOpenMessagePreview = function(type) {
return type === "link" ? options.links : options.media; return type === "link" ? options.links : options.media;
}; };
@ -57,6 +60,8 @@ module.exports.initialize = () => {
settings.find("#user-specified-css-input").val(options[i]); settings.find("#user-specified-css-input").val(options[i]);
} else if (i === "highlights") { } else if (i === "highlights") {
settings.find("input[name=" + i + "]").val(options[i]); settings.find("input[name=" + i + "]").val(options[i]);
} else if (i === "nickPostfix") {
settings.find("input[name=" + i + "]").val(options[i]);
} else if (i === "statusMessages") { } else if (i === "statusMessages") {
settings.find(`input[name=${i}][value=${options[i]}]`) settings.find(`input[name=${i}][value=${options[i]}]`)
.prop("checked", true); .prop("checked", true);
@ -149,6 +154,8 @@ module.exports.initialize = () => {
} else { } else {
module.exports.highlightsRE = null; module.exports.highlightsRE = null;
} }
} else if (name === "nickPostfix") {
options.nickPostfix = options[name];
} else if (name === "showSeconds") { } else if (name === "showSeconds") {
chat.find(".msg > .time").each(function() { chat.find(".msg > .time").each(function() {
$(this).text(tz($(this).parent().data("time"))); $(this).text(tz($(this).parent().data("time")));

View File

@ -55,6 +55,13 @@
Enable autocomplete Enable autocomplete
</label> </label>
</div> </div>
<div class="col-sm-12">
<label class="opt">
<label for="nickPostfix" class="sr-only">Nick autocomplete postfix (e.g. <code>, </code>)</label>
<input type="text" id="nickPostfix" name="nickPostfix" class="input" placeholder="Nick autocomplete postfix (e.g. ', ')">
</label>
</div>
<div class="col-sm-12"> <div class="col-sm-12">
<h2>Theme</h2> <h2>Theme</h2>
</div> </div>