- Refactor autocomplete and similar tags logic to use new normalization functions

- Minor improved autocomplete behavior
This commit is contained in:
newtextdoc1111
2025-05-03 15:11:11 +09:00
parent 0193ba592b
commit daf56eb2ce
3 changed files with 43 additions and 36 deletions
+20 -11
View File
@@ -1,10 +1,10 @@
import { autoCompleteData } from './data.js';
import {
escapeParentheses,
formatCountHumanReadable,
hiraToKata,
kataToHira,
swapUnderscoresAndSpaces
normalizeTagToInsert,
normalizeTagToSearch,
} from './utils.js';
import { settingValues } from './settings.js';
@@ -119,7 +119,6 @@ class AutocompleteUI {
// Get ComfyUI canvas scale if available, otherwise default to 1
const scale = window.app?.canvas?.ds?.scale ?? 1.0;
console.debug(`Canvas scale: ${scale}`);
// Initial desired position: below the current text line where the caret is.
let topPosition = elOffset.top - (elScroll.top * scale) + ((caretTop - elOffset.top) + caretLineHeight) * scale;
@@ -542,7 +541,7 @@ function findCompletionCandidates(query) {
const addedTags = new Set(); // Keep track of added tags to avoid duplicates
// Generate Hiragana/Katakana variations if applicable
const queryVariations = new Set([lowerQuery, swapUnderscoresAndSpaces(lowerQuery)]);
const queryVariations = new Set([lowerQuery, normalizeTagToSearch(lowerQuery)]);
const kataQuery = hiraToKata(lowerQuery);
if (kataQuery !== lowerQuery) {
queryVariations.add(kataQuery);
@@ -617,9 +616,13 @@ function getCurrentPartialTag(inputElement) {
const text = inputElement.value;
const cursorPos = inputElement.selectionStart;
// Find the last comma before the cursor
// Find the last newline or comma before the cursor
const lastNewLine = text.lastIndexOf('\n', cursorPos - 1);
const lastComma = text.lastIndexOf(',', cursorPos - 1);
const start = lastComma === -1 ? 0 : lastComma + 1;
// Get the position of the last separator (newline or comma) before cursor
const lastSeparator = Math.max(lastNewLine, lastComma);
const start = lastSeparator === -1 ? 0 : lastSeparator + 1;
// Extract the text between the last comma (or start) and the cursor
const partial = text.substring(start, cursorPos).trimStart();
@@ -645,17 +648,22 @@ function insertTag(inputElement, tagToInsert) {
const start = lastSeparator === -1 ? 0 : lastSeparator + 1;
// Process the tag: swap underscores/spaces and escape parentheses
const processedTag = swapUnderscoresAndSpaces(tagToInsert);
const normalizedTag = escapeParentheses(processedTag);
const normalizedTag = normalizeTagToInsert(tagToInsert);
// Find the start of the word/tag being typed (skip leading whitespace after separator)
const currentWordStart = text.substring(start, cursorPos).search(/\S|$/) + start;
// Find the end of the word/tag at the cursor position, stopping at comma, newline, or end of string.
// Match non-whitespace, non-comma, non-newline characters.
const currentWordEndMatch = text.substring(cursorPos).match(/^([^\s,\n]*)/); // Changed regex to exclude \n
const currentWordEndMatch = text.substring(cursorPos).match(/^([^\s,\n]*)/);
// currentWordEnd is the position *after* the matched word part.
const currentWordEnd = currentWordEndMatch ? cursorPos + currentWordEndMatch[1].length : cursorPos; // Use group 1
// const currentWordEnd = currentWordEndMatch ? cursorPos + currentWordEndMatch[1].length : cursorPos;
let currentWordEnd = cursorPos;
// If the match was found and the cursor is within the matched word, extend currentWordEnd to include it.
if(currentWordEndMatch && normalizedTag.lastIndexOf(currentWordEndMatch[1]) !== -1){
currentWordEnd = cursorPos + currentWordEndMatch[1].length;
}
// The range to replace is from the start of the current partial tag
// up to the end of the word segment at the cursor.
@@ -668,7 +676,8 @@ function insertTag(inputElement, tagToInsert) {
const prefix = needsSpaceBefore ? ' ' : '';
// Standard separator (comma + space)
const suffix = ', ';
const needsSuffixAfter = text[replaceEnd] !== ','
const suffix = needsSuffixAfter ? ', ' : '';
// Text to insert (including prefix and suffix)
const textToInsertWithAffixes = prefix + normalizedTag + suffix;
+4 -9
View File
@@ -2,12 +2,8 @@
import { settingValues } from './settings.js';
import { autoCompleteData } from './data.js';
import {
hiraToKata,
kataToHira,
formatCountHumanReadable,
swapUnderscoresAndSpaces,
escapeParentheses,
unescapeParentheses
normalizeTagToSearch,
normalizeTagToInsert
} from './utils.js';
// --- SimilarTags UI Class ---
@@ -396,7 +392,7 @@ function getCurrentTag(inputElement) {
if (!tag) return null;
// Process the tag: swap underscores/spaces and unescape parentheses
const normalizedTag = unescapeParentheses(swapUnderscoresAndSpaces(tag)); // Use helper functions
const normalizedTag = normalizeTagToSearch(tag);
return normalizedTag;
}
@@ -448,8 +444,7 @@ function insertTag(inputElement, tagToInsert) {
effectiveEndPos--;
}
// Prepare the tag to be inserted (escape parentheses, replace underscores)
const normalizedTag = escapeParentheses(swapUnderscoresAndSpaces(tagToInsert));
const normalizedTag = normalizeTagToInsert(tagToInsert);
// Text before the insertion point (end of the current tag)
const textBefore = text.substring(0, effectiveEndPos);
+19 -16
View File
@@ -54,22 +54,6 @@ export function formatCountHumanReadable(num) {
return (num / si[i].value).toFixed(1).replace(rx, "$1") + si[i].symbol;
}
/**
* Swaps underscores and spaces in a given string.
* Example: "hello_world example" becomes "hello world_example"
* @param {string} str The input string.
* @returns {string} The string with underscores and spaces swapped.
*/
export function swapUnderscoresAndSpaces(str) {
if (!str) return str;
// Use a temporary placeholder to avoid conflicts during replacement
const tempPlaceholder = "__TEMP_SWAP__";
return str
.replace(/_/g, tempPlaceholder) // Replace underscores with placeholder
.replace(/ /g, "_") // Replace spaces with underscores
.replace(new RegExp(tempPlaceholder, 'g'), " "); // Replace placeholder with spaces
}
/**
* Escapes parentheses in a string for use in prompts.
* Replaces '(' with '\(' and ')' with '\)'.
@@ -94,6 +78,25 @@ export function unescapeParentheses(str) {
return str.replace(/\\\(/g, '(').replace(/\\\)/g, ')');
}
/**
* Normalizes a tag string for input.
* @param {string} str
* @returns
*/
export function normalizeTagToSearch(str) {
if(!str) return str;
return unescapeParentheses(str.replace(/ /g, "_"));
}
/**
* Normalizes a tag string for input.
* @param {string} str
* @returns
*/
export function normalizeTagToInsert(str) {
return escapeParentheses(str.replace(/_/g, " "));
}
// --- End String Helper Functions ---
// Function to load a CSS file