fix: don't autocomplete commands mid-sentence (#6273)

This commit is contained in:
pajlada
2025-06-28 21:16:44 +02:00
committed by GitHub
parent b6623cff88
commit 89483e4c05
3 changed files with 41 additions and 12 deletions
+1
View File
@@ -17,6 +17,7 @@
- Minor: Made nicknames searchable in the Settings dialog search bar. (#5886)
- Minor: Added hotkey Action for opening account selector. (#6192)
- Minor: Add a setting to change the emote and badge thumbnail size. (#6126)
- Bugfix: Commands are no longer tab-completable in the middle of messages. (#6273)
- Bugfix: Automatic streamer mode detection now works from Flatpak. (#6250)
- Bugfix: Don't create native messaging manifest file if browser directory doesn't exist. (#6116)
- Bugfix: Fixed scrolling now working on inputs in the settings. (#6128)
@@ -27,7 +27,7 @@ void TabCompletionModel::updateResults(const QString &query,
const QString &fullTextContent,
int cursorPosition, bool isFirstWord)
{
this->updateSourceFromQuery(query);
this->updateSourceFromQuery(query, isFirstWord);
if (this->source_)
{
@@ -56,9 +56,10 @@ void TabCompletionModel::updateResults(const QString &query,
}
}
void TabCompletionModel::updateSourceFromQuery(const QString &query)
void TabCompletionModel::updateSourceFromQuery(const QString &query,
bool isFirstWord)
{
auto deducedKind = this->deduceSourceKind(query);
auto deducedKind = this->deduceSourceKind(query, isFirstWord);
if (!deducedKind)
{
// unable to determine what kind of completion is occurring
@@ -71,7 +72,8 @@ void TabCompletionModel::updateSourceFromQuery(const QString &query)
}
std::optional<TabCompletionModel::SourceKind>
TabCompletionModel::deduceSourceKind(const QString &query) const
TabCompletionModel::deduceSourceKind(const QString &query,
bool isFirstWord) const
{
if (query.length() < 2 || !this->channel_.isTwitchChannel())
{
@@ -88,7 +90,7 @@ std::optional<TabCompletionModel::SourceKind>
{
return SourceKind::Emote;
}
else if (query.startsWith('/') || query.startsWith('.'))
else if (isFirstWord && (query.startsWith('/') || query.startsWith('.')))
{
return SourceKind::Command;
}
@@ -97,14 +99,27 @@ std::optional<TabCompletionModel::SourceKind>
// Therefore, we must also consider that the user could be completing an emote
// OR a mention depending on their completion settings.
if (getSettings()->userCompletionOnlyWithAt)
if (isFirstWord)
{
// All kinds but user are possible
return SourceKind::EmoteCommand;
if (getSettings()->userCompletionOnlyWithAt)
{
// All kinds but user are possible
return SourceKind::EmoteCommand;
}
// Any kind is possible
return SourceKind::EmoteUserCommand;
}
// Any kind is possible
return SourceKind::EmoteUserCommand;
// We don't allow for mid-message command completions,
// which means only emote or user tab completions are possible.
if (getSettings()->userCompletionOnlyWithAt)
{
return SourceKind::Emote;
}
return SourceKind::EmoteUser;
}
std::unique_ptr<completion::Source> TabCompletionModel::buildSource(
@@ -121,6 +136,14 @@ std::unique_ptr<completion::Source> TabCompletionModel::buildSource(
case SourceKind::Command: {
return this->buildCommandSource();
}
case SourceKind::EmoteUser: {
std::vector<std::unique_ptr<completion::Source>> sources;
sources.push_back(this->buildEmoteSource());
sources.push_back(this->buildUserSource(false));
return std::make_unique<completion::UnifiedSource>(
std::move(sources));
}
case SourceKind::EmoteCommand: {
std::vector<std::unique_ptr<completion::Source>> sources;
sources.push_back(this->buildEmoteSource());
@@ -41,6 +41,8 @@ private:
User,
// Known to be a command, i.e. started with / or .
Command,
// Emote or user without : or @ .
EmoteUser,
// Emote or command without : or / .
EmoteCommand,
// Emote, user, or command without :, @, / .
@@ -51,14 +53,17 @@ private:
/// The completion source will only change if the deduced completion kind
/// changes (see deduceSourceKind).
/// @param query Completion query
void updateSourceFromQuery(const QString &query);
/// @param isFirstWord Whether the completion is the first word in the input
void updateSourceFromQuery(const QString &query, bool isFirstWord);
/// @brief Attempts to deduce the source kind from the current query. If the
/// bound Channel is not a TwitchChannel or if the query is too short, no
/// query type will be deduced to prevent completions.
/// @param query Completion query
/// @param isFirstWord Whether the completion is the first word in the input
/// @return An optional SourceKind deduced from the query
std::optional<SourceKind> deduceSourceKind(const QString &query) const;
std::optional<SourceKind> deduceSourceKind(const QString &query,
bool isFirstWord) const;
std::unique_ptr<completion::Source> buildSource(SourceKind kind) const;