|
import { AutoCompleteNameResult } from '../autocomplete/AutoCompleteNameResult.js'; |
|
import { AutoCompleteSecondaryNameResult } from '../autocomplete/AutoCompleteSecondaryNameResult.js'; |
|
import { SlashCommand } from './SlashCommand.js'; |
|
import { SlashCommandCommandAutoCompleteOption } from './SlashCommandCommandAutoCompleteOption.js'; |
|
import { SlashCommandEnumAutoCompleteOption } from './SlashCommandEnumAutoCompleteOption.js'; |
|
import { SlashCommandExecutor } from './SlashCommandExecutor.js'; |
|
import { SlashCommandNamedArgumentAutoCompleteOption } from './SlashCommandNamedArgumentAutoCompleteOption.js'; |
|
import { SlashCommandScope } from './SlashCommandScope.js'; |
|
|
|
export class SlashCommandAutoCompleteNameResult extends AutoCompleteNameResult { |
|
executor; |
|
scope; |
|
|
|
|
|
|
|
|
|
|
|
|
|
constructor(executor, scope, commands) { |
|
super( |
|
executor.name, |
|
executor.start, |
|
Object |
|
.keys(commands) |
|
.map(key=>new SlashCommandCommandAutoCompleteOption(commands[key], key)) |
|
, |
|
false, |
|
()=>`No matching slash commands for "/${this.name}"`, |
|
()=>'No slash commands found!', |
|
); |
|
this.executor = executor; |
|
this.scope = scope; |
|
} |
|
|
|
getSecondaryNameAt(text, index, isSelect) { |
|
const namedResult = this.getNamedArgumentAt(text, index, isSelect); |
|
if (!namedResult || namedResult.optionList.length == 0 || !namedResult.isRequired) { |
|
const unnamedResult = this.getUnnamedArgumentAt(text, index, isSelect); |
|
if (!namedResult) return unnamedResult; |
|
if (namedResult && unnamedResult) { |
|
const combinedResult = new AutoCompleteSecondaryNameResult( |
|
namedResult.name, |
|
namedResult.start, |
|
[...namedResult.optionList, ...unnamedResult.optionList], |
|
); |
|
combinedResult.isRequired = namedResult.isRequired || unnamedResult.isRequired; |
|
combinedResult.forceMatch = namedResult.forceMatch && unnamedResult.forceMatch; |
|
return combinedResult; |
|
} |
|
} |
|
return namedResult; |
|
} |
|
|
|
getNamedArgumentAt(text, index, isSelect) { |
|
function getSplitRegex() { |
|
try { |
|
return new RegExp('(?<==)'); |
|
} catch { |
|
|
|
return new RegExp('=(.*)'); |
|
} |
|
} |
|
if (!Array.isArray(this.executor.command?.namedArgumentList)) { |
|
return null; |
|
} |
|
const notProvidedNamedArguments = this.executor.command.namedArgumentList.filter(arg=>!this.executor.namedArgumentList.find(it=>it.name == arg.name)); |
|
let name; |
|
let value; |
|
let start; |
|
let cmdArg; |
|
let argAssign; |
|
const unamedArgLength = this.executor.endUnnamedArgs - this.executor.startUnnamedArgs; |
|
const namedArgsFollowedBySpace = text[this.executor.endNamedArgs] == ' '; |
|
if (this.executor.startNamedArgs <= index && this.executor.endNamedArgs + (namedArgsFollowedBySpace ? 1 : 0) >= index) { |
|
|
|
argAssign = this.executor.namedArgumentList.find(it=>it.start <= index && it.end >= index); |
|
if (argAssign) { |
|
const [argName, ...v] = text.slice(argAssign.start, index).split(getSplitRegex()); |
|
name = argName; |
|
value = v.join(''); |
|
start = argAssign.start; |
|
cmdArg = this.executor.command.namedArgumentList.find(it=>[it.name, `${it.name}=`].includes(argAssign.name)); |
|
if (cmdArg) notProvidedNamedArguments.push(cmdArg); |
|
} else { |
|
name = ''; |
|
start = index; |
|
} |
|
} else if (unamedArgLength > 0 && index >= this.executor.startUnnamedArgs && index <= this.executor.endUnnamedArgs) { |
|
|
|
|
|
if (typeof this.executor.unnamedArgumentList[0]?.value == 'string') { |
|
if (index <= this.executor.startUnnamedArgs + this.executor.unnamedArgumentList[0].value.length) { |
|
name = this.executor.unnamedArgumentList[0].value.slice(0, index - this.executor.startUnnamedArgs); |
|
start = this.executor.startUnnamedArgs; |
|
} else { |
|
return null; |
|
} |
|
} else { |
|
return null; |
|
} |
|
} else { |
|
return null; |
|
} |
|
|
|
if (name.includes('=') && cmdArg) { |
|
|
|
const enumList = cmdArg?.enumProvider?.(this.executor, this.scope) ?? cmdArg?.enumList; |
|
if (cmdArg && enumList?.length) { |
|
if (isSelect && enumList.find(it=>it.value == value) && argAssign && argAssign.end == index) { |
|
return null; |
|
} |
|
const result = new AutoCompleteSecondaryNameResult( |
|
value, |
|
start + name.length, |
|
enumList.map(it=>SlashCommandEnumAutoCompleteOption.from(this.executor.command, it)), |
|
true, |
|
); |
|
result.isRequired = true; |
|
result.forceMatch = cmdArg.forceEnum; |
|
return result; |
|
} |
|
} |
|
|
|
if (notProvidedNamedArguments.length > 0) { |
|
const result = new AutoCompleteSecondaryNameResult( |
|
name, |
|
start, |
|
notProvidedNamedArguments.map(it=>new SlashCommandNamedArgumentAutoCompleteOption(it, this.executor.command)), |
|
false, |
|
); |
|
result.isRequired = notProvidedNamedArguments.find(it=>it.isRequired) != null; |
|
return result; |
|
} |
|
|
|
return null; |
|
} |
|
|
|
getUnnamedArgumentAt(text, index, isSelect) { |
|
if (!Array.isArray(this.executor.command?.unnamedArgumentList)) { |
|
return null; |
|
} |
|
const lastArgIsBlank = this.executor.unnamedArgumentList.slice(-1)[0]?.value == ''; |
|
const notProvidedArguments = this.executor.command.unnamedArgumentList.slice(this.executor.unnamedArgumentList.length - (lastArgIsBlank ? 1 : 0)); |
|
let value; |
|
let start; |
|
let cmdArg; |
|
let argAssign; |
|
if (this.executor.startUnnamedArgs <= index && this.executor.endUnnamedArgs + 1 >= index) { |
|
|
|
const idx = this.executor.unnamedArgumentList.findIndex(it=>it.start <= index && it.end >= index); |
|
if (idx > -1) { |
|
argAssign = this.executor.unnamedArgumentList[idx]; |
|
cmdArg = this.executor.command.unnamedArgumentList[idx]; |
|
if (cmdArg === undefined && this.executor.command.unnamedArgumentList.slice(-1)[0]?.acceptsMultiple) { |
|
cmdArg = this.executor.command.unnamedArgumentList.slice(-1)[0]; |
|
} |
|
const enumList = cmdArg?.enumProvider?.(this.executor, this.scope) ?? cmdArg?.enumList; |
|
if (cmdArg && enumList.length > 0) { |
|
value = argAssign.value.toString().slice(0, index - argAssign.start); |
|
start = argAssign.start; |
|
} else { |
|
return null; |
|
} |
|
} else { |
|
value = ''; |
|
start = index; |
|
cmdArg = notProvidedArguments[0]; |
|
if (cmdArg === undefined && this.executor.command.unnamedArgumentList.slice(-1)[0]?.acceptsMultiple) { |
|
cmdArg = this.executor.command.unnamedArgumentList.slice(-1)[0]; |
|
} |
|
} |
|
} else { |
|
return null; |
|
} |
|
|
|
const enumList = cmdArg?.enumProvider?.(this.executor, this.scope) ?? cmdArg?.enumList; |
|
if (cmdArg == null || enumList.length == 0) return null; |
|
|
|
const result = new AutoCompleteSecondaryNameResult( |
|
value, |
|
start, |
|
enumList.map(it=>SlashCommandEnumAutoCompleteOption.from(this.executor.command, it)), |
|
false, |
|
); |
|
const isCompleteValue = enumList.find(it=>it.value == value); |
|
const isSelectedValue = isSelect && isCompleteValue; |
|
result.isRequired = cmdArg.isRequired && !isSelectedValue; |
|
result.forceMatch = cmdArg.forceEnum; |
|
return result; |
|
} |
|
} |
|
|