Refined the grammar for filtering workouts (#4531)

* Added support to filter for numbers in the description / title / tags,
  similar to #4529
* Added quoted strings when filtering in description / title / tags:
  * Words can be grouped by putting them in quotes to search for exact
    matches
  * Keywords can be put in quotes to strip their special meaning
  * Examples: "Power Builder 60", "Power" 60
  * Added this also to TrainerDay, keeping the syntax similar
* Adjusted the autocompletion to not propose keywords when within open
  quotes
This commit is contained in:
Joachim Kohlhammer
2024-08-08 23:42:38 +02:00
committed by GitHub
parent e783586ec3
commit e7e8ef3055
5 changed files with 31 additions and 5 deletions

View File

@@ -131,13 +131,12 @@ FilterEditor::keyPressEvent
if ( e->text().endsWith(" ")
|| e->text().endsWith(",")
|| e->text().endsWith(".")) {
|| e->text().endsWith(".")
|| ! isSelectorPosition()
|| isQuoted()) {
_completer->popup()->hide();
return;
}
if (! isSelectorPosition()) {
return;
}
QString completionPrefix = wordLeftOfCursor();
if (completionPrefix != _completer->completionPrefix()) {
@@ -232,6 +231,14 @@ FilterEditor::isSelectorPosition
}
bool
FilterEditor::isQuoted
() const
{
return feh.isQuoted(text(), cursorPosition());
}
/// FilterEditorHelper
FilterEditorHelper::FilterEditorHelper
@@ -366,6 +373,20 @@ FilterEditorHelper::isSelectorPosition
}
bool
FilterEditorHelper::isQuoted
(const QString &t, int cp) const
{
int count = 0;
for (int pos = 0; pos < cp; ++pos) {
if (t[pos] == '"') {
++count;
}
}
return count % 2 == 1;
}
bool
FilterEditorHelper::isWordChar
(QChar ch) const

View File

@@ -41,6 +41,7 @@ public:
QString wordLeftOfCursor(const QString &t, int cp) const;
QString wordRightOfCursor(const QString &t, int cp) const;
bool isSelectorPosition(const QString &t, int cp) const;
bool isQuoted(const QString &t, int cp) const;
bool isWordChar(QChar ch) const;
std::pair<QString, int> evaluateCompletion(const QString &originalText, const QString &completion, int cursorPosition, int selectionStart, int selectionLength) const;
@@ -76,6 +77,7 @@ private:
QString wordLeftOfCursor() const;
QString wordRightOfCursor() const;
bool isSelectorPosition() const;
bool isQuoted() const;
};
#endif

View File

@@ -51,6 +51,7 @@ extern YYSTYPE yylval;
[Vv][Oo][2][Mm][Aa][Xx] { return ZONE_VO2MAX; }
[Aa][Nn][Aa][Ee][Rr][Oo][Bb][Ii][Cc] { return ZONE_ANAEROBIC; }
[Tt][Ee][Ss][Tt] { return ZONE_TEST; }
\"[^\"]+\" { yytext[strlen(yytext) - 1] = '\0'; TrainerDayAPIQuerylval.word = yytext + 1; return WORD; }
[^ ,.]+ { TrainerDayAPIQuerylval.word = yytext; return WORD; }
. { return yytext[0]; }

View File

@@ -68,6 +68,7 @@ extern YYSTYPE yylval;
[Ee][Ll][Ee][Vv][Aa][Tt][Ii][Oo][Nn] { return ELEVATION; }
[Gg][Rr][Aa][Dd][Ee] { return GRADE; }
[zZ]([1-9]|10) { yytext += 1; WorkoutFilterlval.numValue = atoi(yytext); return ZONE; }
\"[^\"]+\" { yytext[strlen(yytext) - 1] = '\0'; WorkoutFilterlval.word = yytext + 1; return WORD; }
[^ ,.]+ { WorkoutFilterlval.word = yytext; return WORD; }
. { return yytext[0]; }

View File

@@ -240,7 +240,8 @@ words: word words { *$1 << *$2; delete $2; $$ = $1; }
| word { $$ = $1; }
;
word: WORD { $$ = new QStringList($1); }
word: WORD { $$ = new QStringList($1); }
| NUMBER { $$ = new QStringList(QString::number($1)); }
;
mixedNumValue: FLOAT { $$ = $1; }