Path: blob/master/javascript/edit-attention.js
3055 views
function keyupEditAttention(event) {1let target = event.originalTarget || event.composedPath()[0];2if (!target.matches("*:is([id*='_toprow'] [id*='_prompt'], .prompt) textarea")) return;3if (!(event.metaKey || event.ctrlKey)) return;45let isPlus = event.key == "ArrowUp";6let isMinus = event.key == "ArrowDown";7if (!isPlus && !isMinus) return;89let selectionStart = target.selectionStart;10let selectionEnd = target.selectionEnd;11let text = target.value;1213function selectCurrentParenthesisBlock(OPEN, CLOSE) {14if (selectionStart !== selectionEnd) return false;1516// Find opening parenthesis around current cursor17const before = text.substring(0, selectionStart);18let beforeParen = before.lastIndexOf(OPEN);19if (beforeParen == -1) return false;2021let beforeClosingParen = before.lastIndexOf(CLOSE);22if (beforeClosingParen != -1 && beforeClosingParen > beforeParen) return false;2324// Find closing parenthesis around current cursor25const after = text.substring(selectionStart);26let afterParen = after.indexOf(CLOSE);27if (afterParen == -1) return false;2829let afterOpeningParen = after.indexOf(OPEN);30if (afterOpeningParen != -1 && afterOpeningParen < afterParen) return false;3132// Set the selection to the text between the parenthesis33const parenContent = text.substring(beforeParen + 1, selectionStart + afterParen);34if (/.*:-?[\d.]+/s.test(parenContent)) {35const lastColon = parenContent.lastIndexOf(":");36selectionStart = beforeParen + 1;37selectionEnd = selectionStart + lastColon;38} else {39selectionStart = beforeParen + 1;40selectionEnd = selectionStart + parenContent.length;41}4243target.setSelectionRange(selectionStart, selectionEnd);44return true;45}4647function selectCurrentWord() {48if (selectionStart !== selectionEnd) return false;49const whitespace_delimiters = {"Tab": "\t", "Carriage Return": "\r", "Line Feed": "\n"};50let delimiters = opts.keyedit_delimiters;5152for (let i of opts.keyedit_delimiters_whitespace) {53delimiters += whitespace_delimiters[i];54}5556// seek backward to find beginning57while (!delimiters.includes(text[selectionStart - 1]) && selectionStart > 0) {58selectionStart--;59}6061// seek forward to find end62while (!delimiters.includes(text[selectionEnd]) && selectionEnd < text.length) {63selectionEnd++;64}6566// deselect surrounding whitespace67while (text[selectionStart] == " " && selectionStart < selectionEnd) {68selectionStart++;69}70while (text[selectionEnd - 1] == " " && selectionEnd > selectionStart) {71selectionEnd--;72}7374target.setSelectionRange(selectionStart, selectionEnd);75return true;76}7778// If the user hasn't selected anything, let's select their current parenthesis block or word79if (!selectCurrentParenthesisBlock('<', '>') && !selectCurrentParenthesisBlock('(', ')') && !selectCurrentParenthesisBlock('[', ']')) {80selectCurrentWord();81}8283event.preventDefault();8485var closeCharacter = ')';86var delta = opts.keyedit_precision_attention;87var start = selectionStart > 0 ? text[selectionStart - 1] : "";88var end = text[selectionEnd];8990if (start == '<') {91closeCharacter = '>';92delta = opts.keyedit_precision_extra;93} else if (start == '(' && end == ')' || start == '[' && end == ']') { // convert old-style (((emphasis)))94let numParen = 0;9596while (text[selectionStart - numParen - 1] == start && text[selectionEnd + numParen] == end) {97numParen++;98}99100if (start == "[") {101weight = (1 / 1.1) ** numParen;102} else {103weight = 1.1 ** numParen;104}105106weight = Math.round(weight / opts.keyedit_precision_attention) * opts.keyedit_precision_attention;107108text = text.slice(0, selectionStart - numParen) + "(" + text.slice(selectionStart, selectionEnd) + ":" + weight + ")" + text.slice(selectionEnd + numParen);109selectionStart -= numParen - 1;110selectionEnd -= numParen - 1;111} else if (start != '(') {112// do not include spaces at the end113while (selectionEnd > selectionStart && text[selectionEnd - 1] == ' ') {114selectionEnd--;115}116117if (selectionStart == selectionEnd) {118return;119}120121text = text.slice(0, selectionStart) + "(" + text.slice(selectionStart, selectionEnd) + ":1.0)" + text.slice(selectionEnd);122123selectionStart++;124selectionEnd++;125}126127if (text[selectionEnd] != ':') return;128var weightLength = text.slice(selectionEnd + 1).indexOf(closeCharacter) + 1;129var weight = parseFloat(text.slice(selectionEnd + 1, selectionEnd + weightLength));130if (isNaN(weight)) return;131132weight += isPlus ? delta : -delta;133weight = parseFloat(weight.toPrecision(12));134if (Number.isInteger(weight)) weight += ".0";135136if (closeCharacter == ')' && weight == 1) {137var endParenPos = text.substring(selectionEnd).indexOf(')');138text = text.slice(0, selectionStart - 1) + text.slice(selectionStart, selectionEnd) + text.slice(selectionEnd + endParenPos + 1);139selectionStart--;140selectionEnd--;141} else {142text = text.slice(0, selectionEnd + 1) + weight + text.slice(selectionEnd + weightLength);143}144145target.focus();146target.value = text;147target.selectionStart = selectionStart;148target.selectionEnd = selectionEnd;149150updateInput(target);151}152153addEventListener('keydown', (event) => {154keyupEditAttention(event);155});156157158