diff --git a/public/scripts/autocomplete/AutoComplete.js b/public/scripts/autocomplete/AutoComplete.js
index d1205f6e8..b7ccd6ee1 100644
--- a/public/scripts/autocomplete/AutoComplete.js
+++ b/public/scripts/autocomplete/AutoComplete.js
@@ -25,6 +25,8 @@ export class AutoComplete {
/**@type {boolean}*/ isReplaceable = false;
/**@type {boolean}*/ isShowingDetails = false;
/**@type {boolean}*/ wasForced = false;
+ /**@type {boolean}*/ isForceHidden = false;
+ /**@type {boolean}*/ canBeAutoHidden = false;
/**@type {string}*/ text;
/**@type {AutoCompleteNameResult}*/ parserResult;
@@ -57,6 +59,10 @@ export class AutoComplete {
return power_user.stscript.matching ?? 'fuzzy';
}
+ get autoHide() {
+ return power_user.stscript.autocomplete.autoHide ?? false;
+ }
+
@@ -224,6 +230,16 @@ export class AutoComplete {
return a.name.localeCompare(b.name);
}
+ basicAutoHideCheck() {
+ // auto hide only if at least one char has been typed after the name + space
+ return this.textarea.selectionStart > this.parserResult.start
+ + this.parserResult.name.length
+ + (this.startQuote ? 1 : 0)
+ + (this.endQuote ? 1 : 0)
+ + 1
+ ;
+ }
+
/**
* Show the autocomplete.
* @param {boolean} isInput Whether triggered by input.
@@ -244,6 +260,9 @@ export class AutoComplete {
return this.hide();
}
+ // disable force-hide if trigger was forced
+ if (isForced) this.isForceHidden = false;
+
// request provider to get name result (potentially "incomplete", i.e. not an actual existing name) for
// cursor position
this.parserResult = await this.getNameAt(this.text, this.textarea.selectionStart);
@@ -275,12 +294,16 @@ export class AutoComplete {
this.name = this.name.slice(0, this.textarea.selectionStart - (this.parserResult.start) - (this.startQuote ? 1 : 0));
this.parserResult.name = this.name;
this.isReplaceable = true;
+ this.isForceHidden = false;
+ this.canBeAutoHidden = false;
} else {
this.isReplaceable = false;
+ this.canBeAutoHidden = this.basicAutoHideCheck();
}
} else {
// if not forced and no user input -> just show details
this.isReplaceable = false;
+ this.canBeAutoHidden = this.basicAutoHideCheck();
}
if (isForced || isInput || isSelect) {
@@ -292,8 +315,11 @@ export class AutoComplete {
this.secondaryParserResult = result;
this.name = this.secondaryParserResult.name;
this.isReplaceable = isForced || this.secondaryParserResult.isRequired;
+ this.isForceHidden = false;
+ this.canBeAutoHidden = false;
} else {
this.isReplaceable = false;
+ this.canBeAutoHidden = this.basicAutoHideCheck();
}
}
}
@@ -314,7 +340,17 @@ export class AutoComplete {
// filter the list of options by the partial name according to the matching type
.filter(it => this.isReplaceable || it.name == '' ? matchers[this.matchType](it.name) : it.name.toLowerCase() == this.name)
// remove aliases
- .filter((it,idx,list) => list.findIndex(opt=>opt.value == it.value) == idx)
+ .filter((it,idx,list) => list.findIndex(opt=>opt.value == it.value) == idx);
+
+ if (this.result.length == 0 && this.effectiveParserResult != this.parserResult && isForced) {
+ // no matching secondary results and forced trigger -> show current command details
+ this.secondaryParserResult = null;
+ this.result = [this.effectiveParserResult.optionList.find(it=>it.name == this.effectiveParserResult.name)];
+ this.name = this.effectiveParserResult.name;
+ this.fuzzyRegex = /(.*)(.*)(.*)/;
+ }
+
+ this.result
// update remaining options
.map(option => {
// build element
@@ -336,6 +372,15 @@ export class AutoComplete {
;
+
+ if (this.isForceHidden) {
+ // hidden with escape
+ return this.hide();
+ }
+ if (this.autoHide && this.canBeAutoHidden && !isForced && this.effectiveParserResult == this.parserResult && this.result.length == 1) {
+ // auto hide user setting enabled and somewhere after name part and would usually show command details
+ return this.hide();
+ }
if (this.result.length == 0) {
if (!isInput) {
// no result and no input? hide autocomplete
@@ -683,6 +728,8 @@ export class AutoComplete {
if (evt.ctrlKey || evt.altKey || evt.shiftKey) return;
evt.preventDefault();
evt.stopPropagation();
+ this.isForceHidden = true;
+ this.wasForced = false;
this.hide();
return;
}
diff --git a/public/scripts/power-user.js b/public/scripts/power-user.js
index d05160915..93186df20 100644
--- a/public/scripts/power-user.js
+++ b/public/scripts/power-user.js
@@ -259,6 +259,7 @@ let power_user = {
stscript: {
matching: 'fuzzy',
autocomplete: {
+ autoHide: false,
style: 'theme',
font: {
scale: 0.8,
@@ -1618,6 +1619,7 @@ function loadPowerUserSettings(settings, data) {
$('#token_padding').val(power_user.token_padding);
$('#aux_field').val(power_user.aux_field);
+ $('#stscript_autocomplete_autoHide').prop('checked', power_user.stscript.autocomplete.autoHide ?? false).trigger('input');
$('#stscript_matching').val(power_user.stscript.matching ?? 'fuzzy');
$('#stscript_autocomplete_style').val(power_user.stscript.autocomplete_style ?? 'theme');
document.body.setAttribute('data-stscript-style', power_user.stscript.autocomplete_style);
@@ -3646,6 +3648,11 @@ $(document).ready(() => {
saveSettingsDebounced();
});
+ $('#stscript_autocomplete_autoHide').on('input', function () {
+ power_user.stscript.autocomplete.autoHide = !!$(this).prop('checked');
+ saveSettingsDebounced();
+ });
+
$('#stscript_matching').on('change', function () {
const value = $(this).find(':selected').val();
power_user.stscript.matching = String(value);
diff --git a/public/scripts/slash-commands/SlashCommandAutoCompleteNameResult.js b/public/scripts/slash-commands/SlashCommandAutoCompleteNameResult.js
index c6bd0d1fb..80ed27a37 100644
--- a/public/scripts/slash-commands/SlashCommandAutoCompleteNameResult.js
+++ b/public/scripts/slash-commands/SlashCommandAutoCompleteNameResult.js
@@ -99,7 +99,7 @@ export class SlashCommandAutoCompleteNameResult extends AutoCompleteNameResult {
const result = new AutoCompleteSecondaryNameResult(
value,
start + name.length,
- cmdArg.enumList.map(it=>new SlashCommandEnumAutoCompleteOption(it)),
+ cmdArg.enumList.map(it=>new SlashCommandEnumAutoCompleteOption(this.executor.command, it)),
true,
);
result.isRequired = true;
@@ -154,7 +154,7 @@ export class SlashCommandAutoCompleteNameResult extends AutoCompleteNameResult {
const result = new AutoCompleteSecondaryNameResult(
value,
start,
- cmdArg.enumList.map(it=>new SlashCommandEnumAutoCompleteOption(it)),
+ cmdArg.enumList.map(it=>new SlashCommandEnumAutoCompleteOption(this.executor.command, it)),
false,
);
const isCompleteValue = cmdArg.enumList.find(it=>it.value == value);
diff --git a/public/scripts/slash-commands/SlashCommandEnumAutoCompleteOption.js b/public/scripts/slash-commands/SlashCommandEnumAutoCompleteOption.js
index 9d9a5d40d..12d9c64ad 100644
--- a/public/scripts/slash-commands/SlashCommandEnumAutoCompleteOption.js
+++ b/public/scripts/slash-commands/SlashCommandEnumAutoCompleteOption.js
@@ -1,16 +1,20 @@
import { AutoCompleteOption } from '../autocomplete/AutoCompleteOption.js';
+import { SlashCommand } from './SlashCommand.js';
import { SlashCommandEnumValue } from './SlashCommandEnumValue.js';
export class SlashCommandEnumAutoCompleteOption extends AutoCompleteOption {
+ /**@type {SlashCommand}*/ cmd;
/**@type {SlashCommandEnumValue}*/ enumValue;
/**
+ * @param {SlashCommand} cmd
* @param {SlashCommandEnumValue} enumValue
*/
- constructor(enumValue) {
+ constructor(cmd, enumValue) {
super(enumValue.value, '◊');
+ this.cmd = cmd;
this.enumValue = enumValue;
}
@@ -25,22 +29,6 @@ export class SlashCommandEnumAutoCompleteOption extends AutoCompleteOption {
renderDetails() {
- const frag = document.createDocumentFragment();
- const specs = document.createElement('div'); {
- specs.classList.add('specs');
- const name = document.createElement('div'); {
- name.classList.add('name');
- name.classList.add('monospace');
- name.textContent = this.name;
- specs.append(name);
- }
- frag.append(specs);
- }
- const help = document.createElement('span'); {
- help.classList.add('help');
- help.textContent = this.enumValue.description;
- frag.append(help);
- }
- return frag;
+ return this.cmd.renderHelpDetails();
}
}
diff --git a/public/scripts/slash-commands/SlashCommandNamedArgumentAutoCompleteOption.js b/public/scripts/slash-commands/SlashCommandNamedArgumentAutoCompleteOption.js
index f6b114a25..29f4867fd 100644
--- a/public/scripts/slash-commands/SlashCommandNamedArgumentAutoCompleteOption.js
+++ b/public/scripts/slash-commands/SlashCommandNamedArgumentAutoCompleteOption.js
@@ -27,22 +27,6 @@ export class SlashCommandNamedArgumentAutoCompleteOption extends AutoCompleteOpt
renderDetails() {
- const frag = document.createDocumentFragment();
- const specs = document.createElement('div'); {
- specs.classList.add('specs');
- const name = document.createElement('div'); {
- name.classList.add('name');
- name.classList.add('monospace');
- name.textContent = this.name;
- specs.append(name);
- }
- frag.append(specs);
- }
- const help = document.createElement('span'); {
- help.classList.add('help');
- help.innerHTML = `${this.arg.isRequired ? '' : '(optional) '}${this.arg.description ?? ''}`;
- frag.append(help);
- }
- return frag;
+ return this.cmd.renderHelpDetails();
}
}