fix: Commands now completable when not starting with / (#4846)

* Add commands to completable inputs when no prefix
This commit is contained in:
Daniel Sage
2023-09-30 07:06:16 -04:00
committed by GitHub
parent bdd7d95092
commit 4d8b62364d
8 changed files with 123 additions and 84 deletions
@@ -14,11 +14,17 @@ namespace {
{
if (command.startsWith('/') || command.startsWith('.'))
{
out.push_back({command.mid(1), command.at(0)});
out.push_back({
.name = command.mid(1),
.prefix = command.at(0),
});
}
else
{
out.push_back({command, '/'});
out.push_back({
.name = command,
.prefix = "",
});
}
}
@@ -13,7 +13,7 @@ namespace chatterino::completion {
struct CommandItem {
QString name{};
QChar prefix{};
QString prefix{};
};
class CommandSource : public Source
@@ -2,21 +2,18 @@
namespace chatterino::completion {
UnifiedSource::UnifiedSource(
const Channel *channel,
std::unique_ptr<EmoteSource::EmoteStrategy> emoteStrategy,
std::unique_ptr<UserSource::UserStrategy> userStrategy,
ActionCallback callback)
: emoteSource_(channel, std::move(emoteStrategy), callback)
, usersSource_(channel, std::move(userStrategy), callback,
false) // disable adding @ to front
UnifiedSource::UnifiedSource(std::vector<std::unique_ptr<Source>> sources)
: sources_(std::move(sources))
{
}
void UnifiedSource::update(const QString &query)
{
this->emoteSource_.update(query);
this->usersSource_.update(query);
// Update all sources
for (const auto &source : this->sources_)
{
source->update(query);
}
}
void UnifiedSource::addToListModel(GenericListModel &model,
@@ -24,28 +21,28 @@ void UnifiedSource::addToListModel(GenericListModel &model,
{
if (maxCount == 0)
{
this->emoteSource_.addToListModel(model, 0);
this->usersSource_.addToListModel(model, 0);
for (const auto &source : this->sources_)
{
source->addToListModel(model, 0);
}
return;
}
// Otherwise, make sure to only add maxCount elements in total. We prioritize
// accepting results from the emote source before the users source (arbitrarily).
// Make sure to only add maxCount elements in total.
int startingSize = model.rowCount();
int used = 0;
// Add up to maxCount elements
this->emoteSource_.addToListModel(model, maxCount);
int used = model.rowCount() - startingSize;
if (used >= maxCount)
for (const auto &source : this->sources_)
{
// Used up our limit on emotes
return;
source->addToListModel(model, maxCount - used);
// Calculate how many items have been added so far
used = model.rowCount() - startingSize;
if (used >= maxCount)
{
// Used up all of limit
break;
}
}
// Only add maxCount - used to ensure the total added doesn't exceed maxCount
this->usersSource_.addToListModel(model, maxCount - used);
}
void UnifiedSource::addToStringList(QStringList &list, size_t maxCount,
@@ -53,28 +50,28 @@ void UnifiedSource::addToStringList(QStringList &list, size_t maxCount,
{
if (maxCount == 0)
{
this->emoteSource_.addToStringList(list, 0, isFirstWord);
this->usersSource_.addToStringList(list, 0, isFirstWord);
for (const auto &source : this->sources_)
{
source->addToStringList(list, 0, isFirstWord);
}
return;
}
// Otherwise, make sure to only add maxCount elements in total. We prioritize
// accepting results from the emote source before the users source (arbitrarily).
// Make sure to only add maxCount elements in total.
int startingSize = list.size();
int used = 0;
// Add up to maxCount elements
this->emoteSource_.addToStringList(list, maxCount, isFirstWord);
int used = list.size() - startingSize;
if (used >= maxCount)
for (const auto &source : this->sources_)
{
// Used up our limit on emotes
return;
source->addToStringList(list, maxCount - used, isFirstWord);
// Calculate how many items have been added so far
used = list.size() - startingSize;
if (used >= maxCount)
{
// Used up all of limit
break;
}
}
// Only add maxCount - used to ensure the total added doesn't exceed maxCount
this->usersSource_.addToStringList(list, maxCount - used, isFirstWord);
}
} // namespace chatterino::completion
@@ -1,6 +1,7 @@
#pragma once
#include "common/Channel.hpp"
#include "controllers/completion/sources/CommandSource.hpp"
#include "controllers/completion/sources/EmoteSource.hpp"
#include "controllers/completion/sources/Source.hpp"
#include "controllers/completion/sources/UserSource.hpp"
@@ -13,20 +14,9 @@ namespace chatterino::completion {
class UnifiedSource : public Source
{
public:
using ActionCallback = std::function<void(const QString &)>;
/// @brief Initializes a unified completion source for the given channel.
/// Resolves both emotes and usernames for autocompletion.
/// @param channel Channel to initialize emotes and users from. Must be a
/// TwitchChannel or completion is a no-op.
/// @param emoteStrategy Strategy for selecting emotes
/// @param userStrategy Strategy for selecting users
/// @param callback ActionCallback to invoke upon InputCompletionItem selection.
/// See InputCompletionItem::action(). Can be nullptr.
UnifiedSource(const Channel *channel,
std::unique_ptr<EmoteSource::EmoteStrategy> emoteStrategy,
std::unique_ptr<UserSource::UserStrategy> userStrategy,
ActionCallback callback = nullptr);
/// @brief Initializes a unified completion source.
/// @param sources Vector of sources to unify
UnifiedSource(std::vector<std::unique_ptr<Source>> sources);
void update(const QString &query) override;
void addToListModel(GenericListModel &model,
@@ -35,8 +25,7 @@ public:
bool isFirstWord = false) const override;
private:
EmoteSource emoteSource_;
UserSource usersSource_;
std::vector<std::unique_ptr<Source>> sources_;
};
} // namespace chatterino::completion