diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ab88c5..d469aec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +# Unreleased + +### 🚀 New Feature + +- When autocompleting a username argument of a command, only usernames will now be suggested ([#32](https://github.com/HiDeoo/YaTA/pull/32) - [nD00rn](https://github.com/nD00rn)). + # 1.11.0 ### 🚀 New Feature diff --git a/package.json b/package.json index 5686765..129487a 100644 --- a/package.json +++ b/package.json @@ -118,6 +118,8 @@ "bugs": { "url": "https://github.com/HiDeoo/YaTA/issues" }, - "contributors": [], + "contributors": [ + "nDoorn " + ], "homepage": "https://yata.now.sh" } diff --git a/src/components/Input.tsx b/src/components/Input.tsx index ea54590..1b2627b 100644 --- a/src/components/Input.tsx +++ b/src/components/Input.tsx @@ -352,7 +352,7 @@ export default class Input extends React.Component { this.completions = this.props.getCompletions( word, - previousCharacter === '@', + previousCharacter === '@' || Command.isUsernameCompletableCommandArgument(text, cursor), start === 1 && Command.isCommand(previousCharacter) ) } diff --git a/src/constants/command.ts b/src/constants/command.ts index ab0e7a0..e21bbb5 100644 --- a/src/constants/command.ts +++ b/src/constants/command.ts @@ -161,7 +161,7 @@ export type CommandDescriptor = { /** * A command argument. */ -type CommandArgument = { +export type CommandArgument = { name: string optional?: boolean } diff --git a/src/libs/Command.ts b/src/libs/Command.ts index 538ca0f..542c189 100644 --- a/src/libs/Command.ts +++ b/src/libs/Command.ts @@ -1,6 +1,6 @@ import * as _ from 'lodash' -import { CommandDescriptor, CommandName, Commands } from 'Constants/command' +import { CommandArgument, CommandDescriptor, CommandName, Commands } from 'Constants/command' import Notice from 'Libs/Notice' import { SerializedRoomState } from 'Libs/RoomState' import Twitch from 'Libs/Twitch' @@ -44,6 +44,57 @@ export default class Command { return /^[\/|.]help(?:$|\s)/i.test(message) } + /** + * Checks if the cursor in a message is associated to a command username auto-completable argument. + * Note: at the moment, it is assumed that all commands having a username completable argument have that argument at + * the first position. + * @param message - The message. + * @param cursor - The cursor position. + * @return `true` when the cursor is matching a username completable argument. + */ + public static isUsernameCompletableCommandArgument(message: string, cursor: number) { + // Bail out if the message is not even a command. + if (!Command.isCommand(message)) { + return false + } + + // Grab the command name and the first argument. + const words = message.split(' ') + const commandName = words[0].substr(1) + const firstArgument = words[1] + + // If we don't have a first argument yet, bail out. + if (_.isNil(firstArgument)) { + return false + } + + const firstArgumentStart = commandName.length + 2 + const firstArgumentEnd = firstArgumentStart + firstArgument.length + + // If we're not auto-completing the first agument, bail out. + if (cursor < firstArgumentStart || cursor > firstArgumentEnd) { + return false + } + + // Get the descriptor for this command. + const descriptor = Command.getDescriptor(commandName) + + // If we can't get a valid descriptor, this means the command is unknown. + if (_.isNil(descriptor.name)) { + return false + } + + const firstArgumentDescriptor = _.get(descriptor, 'arguments[0]') as Optional + + // If the command doesn't accept any argument or the first argument is not a + // username, bail out. + if (_.isNil(firstArgumentDescriptor) || firstArgumentDescriptor.name !== 'username') { + return false + } + + return true + } + /** * Parses a message as a whisper command (/w user message). * @return The whisper details.