From 2e79d1ece2737848234adec61cca77f9f604fce2 Mon Sep 17 00:00:00 2001 From: JP Appel Date: Tue, 5 Aug 2025 13:38:06 -0400 Subject: Add headings category to query lang --- pkg/query/compiler.go | 2 ++ pkg/query/lexer.go | 16 +++++++++++----- pkg/query/lexer_test.go | 1 + pkg/query/outputs.go | 3 +++ pkg/query/parser.go | 7 ++++++- pkg/query/parser_test.go | 1 + 6 files changed, 24 insertions(+), 6 deletions(-) (limited to 'pkg/query') diff --git a/pkg/query/compiler.go b/pkg/query/compiler.go index 8b71124..efdc3b4 100644 --- a/pkg/query/compiler.go +++ b/pkg/query/compiler.go @@ -53,6 +53,8 @@ func (s Statements) buildCompile(b *strings.Builder, delim string) ([]any, error catStr = "meta " case CAT_TAGS: catStr = "tag " + case CAT_HEADINGS: + catStr = "headings " case CAT_TITLE: catStr = "title " default: diff --git a/pkg/query/lexer.go b/pkg/query/lexer.go index aa877cf..8a70c47 100644 --- a/pkg/query/lexer.go +++ b/pkg/query/lexer.go @@ -38,9 +38,9 @@ const ( TOK_CAT_DATE TOK_CAT_FILETIME TOK_CAT_TAGS + TOK_CAT_HEADINGS TOK_CAT_LINKS TOK_CAT_META - // TODO: add headings // values TOK_VAL_STR TOK_VAL_DATETIME @@ -93,6 +93,8 @@ func (tokType queryTokenType) String() string { return "Filetime Category" case TOK_CAT_TAGS: return "Tags Category" + case TOK_CAT_HEADINGS: + return "Headings Category" case TOK_CAT_LINKS: return "Links Category" case TOK_CAT_META: @@ -123,7 +125,9 @@ func (tokType queryTokenType) Any(expected ...queryTokenType) bool { } func (t queryTokenType) isCategory() bool { - return t.Any(TOK_CAT_PATH, TOK_CAT_TITLE, TOK_CAT_AUTHOR, TOK_CAT_DATE, TOK_CAT_FILETIME, TOK_CAT_TAGS, TOK_CAT_LINKS, TOK_CAT_META) + return t.Any(TOK_CAT_PATH, TOK_CAT_TITLE, TOK_CAT_AUTHOR, + TOK_CAT_DATE, TOK_CAT_FILETIME, TOK_CAT_TAGS, TOK_CAT_HEADINGS, TOK_CAT_LINKS, + TOK_CAT_META) } func (t queryTokenType) isDateOperation() bool { @@ -261,6 +265,8 @@ func tokenizeCategory(s string) Token { t.Type = TOK_CAT_FILETIME case "t", "tags": t.Type = TOK_CAT_TAGS + case "h", "headings": + t.Type = TOK_CAT_HEADINGS case "l", "links": t.Type = TOK_CAT_LINKS case "m", "meta": @@ -279,7 +285,7 @@ func tokenizeValue(s string, catType queryTokenType) Token { switch catType { case TOK_CAT_DATE, TOK_CAT_FILETIME: t.Type = TOK_VAL_DATETIME - case TOK_CAT_PATH, TOK_CAT_TITLE, TOK_CAT_AUTHOR, TOK_CAT_TAGS, TOK_CAT_LINKS, TOK_CAT_META: + case TOK_CAT_PATH, TOK_CAT_TITLE, TOK_CAT_AUTHOR, TOK_CAT_TAGS, TOK_CAT_HEADINGS, TOK_CAT_LINKS, TOK_CAT_META: t.Type = TOK_VAL_STR } return t @@ -310,7 +316,7 @@ func TokensStringify(tokens []Token) string { case TOK_CLAUSE_AND: b.WriteString("and\n") indentLvl += 1 - case TOK_CAT_PATH, TOK_CAT_TITLE, TOK_CAT_AUTHOR, TOK_CAT_DATE, TOK_CAT_FILETIME, TOK_CAT_TAGS, TOK_CAT_LINKS, TOK_CAT_META, TOK_OP_NEG: + case TOK_CAT_PATH, TOK_CAT_TITLE, TOK_CAT_AUTHOR, TOK_CAT_DATE, TOK_CAT_FILETIME, TOK_CAT_HEADINGS, TOK_CAT_TAGS, TOK_CAT_LINKS, TOK_CAT_META, TOK_OP_NEG: if i == 0 || tokens[i-1].Type != TOK_OP_NEG { writeIndent(&b, indentLvl) } @@ -328,7 +334,7 @@ func TokensStringify(tokens []Token) string { func init() { negPattern := `(?-?)` - categoryPattern := `(?T|p(?:ath)?|a(?:uthor)?|d(?:ate)?|f(?:iletime)?|t(?:ags|itle)?|l(?:inks)?|m(?:eta)?)` + categoryPattern := `(?T|p(?:ath)?|a(?:uthor)?|d(?:ate)?|f(?:iletime)?|t(?:ags|itle)?|h(?:eadings)?|l(?:inks)?|m(?:eta)?)` opPattern := `(?!re!|!=|<=|>=|=|:|~|<|>)` valPattern := `(?".*?"|\S*[^\s\)])` statementPattern := `(?` + negPattern + categoryPattern + opPattern + valPattern + `)` diff --git a/pkg/query/lexer_test.go b/pkg/query/lexer_test.go index 35bdc4f..92f9017 100644 --- a/pkg/query/lexer_test.go +++ b/pkg/query/lexer_test.go @@ -28,6 +28,7 @@ const ( TOK_CAT_DATE = query.TOK_CAT_DATE TOK_CAT_FILETIME = query.TOK_CAT_FILETIME TOK_CAT_TAGS = query.TOK_CAT_TAGS + TOK_CAT_HEADINGS = query.TOK_CAT_HEADINGS TOK_CAT_LINKS = query.TOK_CAT_LINKS TOK_CAT_META = query.TOK_CAT_META TOK_VAL_STR = query.TOK_VAL_STR diff --git a/pkg/query/outputs.go b/pkg/query/outputs.go index e3555c1..21c3f4e 100644 --- a/pkg/query/outputs.go +++ b/pkg/query/outputs.go @@ -23,6 +23,7 @@ const ( OUT_TOK_FILETIME // %f %filetime OUT_TOK_AUTHORS // %a %authors OUT_TOK_TAGS // %t %tags + OUT_TOK_HEADINGS // %h %headings OUT_TOK_LINKS // %l %links OUT_TOK_META // %m %meta ) @@ -217,6 +218,8 @@ func ParseOutputFormat(formatStr string) ([]OutputToken, []string, error) { toks = append(toks, OUT_TOK_AUTHORS) case "%t": toks = append(toks, OUT_TOK_TAGS) + case "%h": + toks = append(toks, OUT_TOK_HEADINGS) case "%l": toks = append(toks, OUT_TOK_LINKS) case "%m": diff --git a/pkg/query/parser.go b/pkg/query/parser.go index 5ff8175..3406bc6 100644 --- a/pkg/query/parser.go +++ b/pkg/query/parser.go @@ -21,6 +21,7 @@ const ( CAT_DATE CAT_FILETIME CAT_TAGS + CAT_HEADINGS CAT_LINKS CAT_META ) @@ -155,6 +156,8 @@ func (t catType) String() string { return "fileTime" case CAT_TAGS: return "tag" + case CAT_HEADINGS: + return "headings" case CAT_LINKS: return "links" case CAT_META: @@ -210,6 +213,8 @@ func tokToCat(t queryTokenType) catType { return CAT_FILETIME case TOK_CAT_TAGS: return CAT_TAGS + case TOK_CAT_HEADINGS: + return CAT_HEADINGS case TOK_CAT_LINKS: return CAT_LINKS case TOK_CAT_META: @@ -488,7 +493,7 @@ func Parse(tokens []Token) (*Clause, error) { stmt := Statement{Negated: true} clause.Statements = append(clause.Statements, stmt) - case TOK_CAT_PATH, TOK_CAT_TITLE, TOK_CAT_AUTHOR, TOK_CAT_DATE, TOK_CAT_FILETIME, TOK_CAT_TAGS, TOK_CAT_LINKS, TOK_CAT_META: + case TOK_CAT_PATH, TOK_CAT_TITLE, TOK_CAT_AUTHOR, TOK_CAT_DATE, TOK_CAT_FILETIME, TOK_CAT_TAGS, TOK_CAT_HEADINGS, TOK_CAT_LINKS, TOK_CAT_META: if !prevToken.Type.Any(TOK_CLAUSE_OR, TOK_CLAUSE_AND, TOK_VAL_STR, TOK_VAL_DATETIME, TOK_OP_NEG, TOK_CLAUSE_END) { return nil, &TokenError{ got: token, diff --git a/pkg/query/parser_test.go b/pkg/query/parser_test.go index 2e85123..5c837c0 100644 --- a/pkg/query/parser_test.go +++ b/pkg/query/parser_test.go @@ -15,6 +15,7 @@ const ( CAT_DATE = query.CAT_DATE CAT_FILETIME = query.CAT_FILETIME CAT_TAGS = query.CAT_TAGS + CAT_HEADINGS = query.CAT_HEADINGS CAT_LINKS = query.CAT_LINKS CAT_META = query.CAT_META -- cgit v1.2.3