diff --git a/cockatrice/resources/help/deck_search.md b/cockatrice/resources/help/deck_search.md
index 4e1c5c557..2ddad9e66 100644
--- a/cockatrice/resources/help/deck_search.md
+++ b/cockatrice/resources/help/deck_search.md
@@ -29,6 +29,11 @@ searches are case insensitive.
Format:
[f:standard](#f:standard) (Any deck with format set to standard)
+Comments:
+[c:good](#c:good) (Any deck with comments containing the word good)
+[c:good c:deck](#c:good c:deck) (Any deck with comments containing the words good and deck)
+[c:"good deck"](#c:%22good deck%22) (Any deck with comments containing the exact phrase "good deck")
+
Deck Contents (Uses [card search expressions](#cardSearchSyntaxHelp)):
[[plains]] (Any deck that contains at least one card with "plains" in its name)
[[t:legendary]] (Any deck that contains at least one legendary)
diff --git a/cockatrice/src/filters/deck_filter_string.cpp b/cockatrice/src/filters/deck_filter_string.cpp
index 5cce5d323..42a77fe5a 100644
--- a/cockatrice/src/filters/deck_filter_string.cpp
+++ b/cockatrice/src/filters/deck_filter_string.cpp
@@ -13,7 +13,7 @@ QueryPartList <- ComplexQueryPart ( ws ("AND" ws)? ComplexQueryPart)* ws*
ComplexQueryPart <- SomewhatComplexQueryPart ws "OR" ws ComplexQueryPart / SomewhatComplexQueryPart
SomewhatComplexQueryPart <- [(] QueryPartList [)] / QueryPart
-QueryPart <- NotQuery / DeckContentQuery / DeckNameQuery / FileNameQuery / PathQuery / FormatQuery / GenericQuery
+QueryPart <- NotQuery / DeckContentQuery / DeckNameQuery / FileNameQuery / PathQuery / FormatQuery / CommentQuery / GenericQuery
NotQuery <- ('NOT' ws/'-') SomewhatComplexQueryPart
@@ -25,6 +25,7 @@ DeckNameQuery <- ([Dd] 'eck')? [Nn] 'ame'? [:] String
FileNameQuery <- [Ff] ([Nn] / 'ile' ([Nn] 'ame')?) [:] String
PathQuery <- [Pp] 'ath'? [:] String
FormatQuery <- [Ff] 'ormat'? [:] String
+CommentQuery <- [Cc] ('omment' 's'?)? [:] String
GenericQuery <- String
@@ -166,6 +167,14 @@ static void setupParserRules()
};
};
+ search["CommentQuery"] = [](const peg::SemanticValues &sv) -> DeckFilter {
+ auto value = std::any_cast(sv[0]);
+ return [=](const DeckPreviewWidget *deck, const ExtraDeckSearchInfo &) {
+ auto comments = deck->deckLoader->getDeck().deckList.getComments();
+ return comments.contains(value, Qt::CaseInsensitive);
+ };
+ };
+
search["GenericQuery"] = [](const peg::SemanticValues &sv) -> DeckFilter {
auto name = std::any_cast(sv[0]);
return [=](const DeckPreviewWidget *deck, const ExtraDeckSearchInfo &) {