1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
|
package cmd
import (
"context"
"flag"
"fmt"
"os"
"slices"
"github.com/jpappel/atlas/pkg/data"
"github.com/jpappel/atlas/pkg/index"
"github.com/jpappel/atlas/pkg/query"
)
type QueryFlags struct {
Outputer query.Outputer
DocumentSeparator string
ListSeparator string
CustomFormat string
OptimizationLevel int
SortBy string
SortDesc bool
}
func SetupQueryFlags(args []string, fs *flag.FlagSet, flags *QueryFlags, dateFormat string) {
// NOTE: providing `-outFormat` before `-outCustomFormat` might ignore user specified format
fs.Func("outFormat", "output `format` for queries (default, json, yaml, pathonly, custom)",
func(arg string) error {
switch arg {
case "default":
flags.Outputer = query.DefaultOutput{}
return nil
case "json":
flags.Outputer = query.JsonOutput{}
return nil
case "yaml":
flags.Outputer = query.YamlOutput{}
return nil
case "pathonly":
flags.Outputer, _ = query.NewCustomOutput("%p", dateFormat, "\n", "")
return nil
case "custom":
var err error
flags.Outputer, err = query.NewCustomOutput(flags.CustomFormat, dateFormat, flags.DocumentSeparator, flags.ListSeparator)
return err
default:
return fmt.Errorf("Unrecognized output format: %s", arg)
}
})
fs.StringVar(&flags.SortBy, "sortBy", "", "category to sort by (path,title,date,filetime,meta)")
fs.BoolVar(&flags.SortDesc, "sortDesc", false, "sort in descending order")
fs.StringVar(&flags.CustomFormat, "outCustomFormat", query.DefaultOutputFormat, "`format` string for --outFormat custom, see `atlas help query` for more details")
fs.IntVar(&flags.OptimizationLevel, "optLevel", 0, "optimization `level` for queries, 0 is automatic, <0 to disable")
fs.StringVar(&flags.DocumentSeparator, "docSeparator", "\n", "separator for custom output format")
fs.StringVar(&flags.ListSeparator, "listSeparator", ", ", "separator for list fields")
fs.Usage = func() {
w := fs.Output()
fmt.Fprintf(w, "%s [global-flags] query [query-flags] <query>...\n\n", os.Args[0])
fmt.Fprintln(w, "Query Flags:")
PrintFlagSet(w, fs)
PrintGlobalFlags(w)
}
fs.Parse(args)
}
func RunQuery(gFlags GlobalFlags, qFlags QueryFlags, db *data.Query, searchQuery string) byte {
tokens := query.Lex(searchQuery)
clause, err := query.Parse(tokens)
if err != nil {
fmt.Fprintln(os.Stderr, "Failed to parse query: ", err)
return 1
}
o := query.NewOptimizer(clause, gFlags.NumWorkers)
o.Optimize(qFlags.OptimizationLevel)
artifact, err := clause.Compile()
if err != nil {
fmt.Fprintln(os.Stderr, "Failed to compile query: ", err)
return 1
}
results, err := db.Execute(context.Background(), artifact)
if err != nil {
fmt.Fprintln(os.Stderr, "Failed to execute query: ", err)
return 1
}
if len(results) == 0 {
fmt.Println("No results.")
return 0
}
outputableResults := make([]*index.Document, 0, len(results))
for _, v := range results {
outputableResults = append(outputableResults, v)
}
if qFlags.SortBy != "" {
docCmp, ok := index.NewDocCmp(qFlags.SortBy, qFlags.SortDesc)
if ok {
slices.SortFunc(outputableResults, docCmp)
}
}
_, err = qFlags.Outputer.OutputTo(os.Stdout, outputableResults)
if err != nil {
fmt.Fprintln(os.Stderr, "Error while outputting results: ", err)
return 1
}
return 0
}
|