diff options
| author | JP Appel <jeanpierre.appel01@gmail.com> | 2025-07-19 00:54:11 -0400 |
|---|---|---|
| committer | JP Appel <jeanpierre.appel01@gmail.com> | 2025-07-19 00:54:11 -0400 |
| commit | ce7bb43b8e0910c812c8ab9299969679082507b9 (patch) | |
| tree | 3128c5c5b2e426d09d2555f93a188df795511f0a | |
| parent | 493b08d185c784069f45be410eb9dc8d556dfb6d (diff) | |
Improve command documentation and query output
Add flags to change document and list separator in query output.
Simplified cutom output format handling.
| -rw-r--r-- | cmd/index.go | 2 | ||||
| -rw-r--r-- | cmd/query.go | 44 | ||||
| -rw-r--r-- | pkg/query/outputs.go | 81 |
3 files changed, 72 insertions, 55 deletions
diff --git a/cmd/index.go b/cmd/index.go index 2f18fe0..dde9550 100644 --- a/cmd/index.go +++ b/cmd/index.go @@ -36,7 +36,7 @@ func setupIndexFlags(args []string, fs *flag.FlagSet, flags *IndexFlags) { fs.Usage = func() { f := fs.Output() fmt.Fprintf(f, "Usage of %s %s\n", os.Args[0], fs.Name()) - fmt.Fprintf(f, "\t%s [global-flags] %s [index-flags] <subcommand>\n\n", os.Args[0], fs.Name()) + fmt.Fprintf(f, " %s [global-flags] %s [index-flags] <subcommand>\n\n", os.Args[0], fs.Name()) fmt.Fprintln(f, "Subcommands:") fmt.Fprintln(f, "build - create a new index") fmt.Fprintln(f, "update - update an existing index") diff --git a/cmd/query.go b/cmd/query.go index a2ac5a4..649b9ea 100644 --- a/cmd/query.go +++ b/cmd/query.go @@ -12,6 +12,8 @@ import ( type QueryFlags struct { Outputer query.Outputer + DocumentSeparator string + ListSeparator string CustomFormat string OptimizationLevel int } @@ -28,17 +30,53 @@ func setupQueryFlags(args []string, fs *flag.FlagSet, flags *QueryFlags, dateFor flags.Outputer = query.JsonOutput{} return nil case "pathonly": - flags.Outputer, _ = query.NewCustomOutput("%p", dateFormat) + flags.Outputer, _ = query.NewCustomOutput("%p", dateFormat, "\n", "") return nil case "custom": var err error - flags.Outputer, err = query.NewCustomOutput(flags.CustomFormat, dateFormat) + flags.Outputer, err = query.NewCustomOutput(flags.CustomFormat, dateFormat, flags.DocumentSeparator, flags.ListSeparator) return err } return fmt.Errorf("Unrecognized output format: %s", arg) }) - fs.StringVar(&flags.CustomFormat, "outCustomFormat", query.DefaultOutputFormat, "format string for --outFormat custom, see EXAMPLES for more details") + fs.StringVar(&flags.CustomFormat, "outCustomFormat", query.DefaultOutputFormat, "format string for --outFormat custom, see Output Format 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() { + f := fs.Output() + fmt.Fprintf(f, "Usage of %s %s\n", os.Args[0], fs.Name()) + fmt.Fprintf(f, " %s [global-flags] %s [query-flags]\n\n", + os.Args[0], fs.Name()) + fmt.Fprintln(f, "Query Flags:") + fs.PrintDefaults() + fmt.Fprintln(f, "\nOutput Format:") + help := `The output format of query results can be customized by setting -outCustomFormat. + + The output of each document has the value of -docSeparator appended to it. + Dates are formated using -dateFormat + Lists use -listSeparator to delimit elements + + Placeholder - Type - Value + %p - Str - path + %T - Str - title + %d - Date - date + %f - Date - filetime + %a - List - authors + %t - List - tags + %l - List - links + %m - Str - meta + + Examples: + "%p %T %d tags:%t" -> '/a/path/to/document A Title 2006-01-02T15:04:05Z07:00 tags:tag1, tag2\n' + "<h1><a href="%p">%T</a></h1>" -> '<h1><a href="/a/path/to/document">A Title</a></h1>\n' + +` + fmt.Fprint(f, help) + fmt.Fprintln(f, "Global Flags:") + flag.PrintDefaults() + } fs.Parse(args) } diff --git a/pkg/query/outputs.go b/pkg/query/outputs.go index af00bdf..50a6c4d 100644 --- a/pkg/query/outputs.go +++ b/pkg/query/outputs.go @@ -1,6 +1,7 @@ package query import ( + "bytes" "encoding/json" "fmt" "io" @@ -40,6 +41,8 @@ type CustomOutput struct { stringTokens []string tokens []OutputToken datetimeFormat string + docSeparator string + listSeparator string } // compile time interface check @@ -201,13 +204,22 @@ func ParseOutputFormat(formatStr string) ([]OutputToken, []string, error) { return toks, strToks, nil } -func NewCustomOutput(formatStr string, datetimeFormat string) (CustomOutput, error) { +func NewCustomOutput( + formatStr string, datetimeFormat string, + docSeparator string, listSeparator string, +) (CustomOutput, error) { outToks, strToks, err := ParseOutputFormat(formatStr) if err != nil { return CustomOutput{}, err } - return CustomOutput{strToks, outToks, datetimeFormat}, nil + return CustomOutput{ + strToks, + outToks, + datetimeFormat, + docSeparator, + listSeparator, + }, nil } func (o CustomOutput) OutputOne(doc *index.Document) (string, error) { @@ -255,70 +267,37 @@ func (o CustomOutput) OutputTo(w io.Writer, docs []*index.Document) (int, error) func (o CustomOutput) writeDoc(w io.Writer, doc *index.Document) (int, error) { curStrTok := 0 - n := 0 + var b bytes.Buffer for _, token := range o.tokens { switch token { case OUT_TOK_STR: if curStrTok >= len(o.stringTokens) { - return n, ErrExpectedMoreStringTokens - } - cnt, err := w.Write([]byte(o.stringTokens[curStrTok])) - if err != nil { - return n, err + return 0, ErrExpectedMoreStringTokens } - n += cnt + b.WriteString(o.stringTokens[curStrTok]) curStrTok++ case OUT_TOK_PATH: - cnt, err := w.Write([]byte(doc.Path)) - if err != nil { - return n, err - } - n += cnt + b.WriteString(doc.Path) case OUT_TOK_TITLE: - cnt, err := w.Write([]byte(doc.Title)) - if err != nil { - return n, err - } - n += cnt + b.WriteString(doc.Title) case OUT_TOK_DATE: - cnt, err := w.Write([]byte(doc.Date.Format(o.datetimeFormat))) - if err != nil { - return n, err - } - n += cnt + b.WriteString(doc.Date.Format(o.datetimeFormat)) case OUT_TOK_FILETIME: - cnt, err := w.Write([]byte(doc.FileTime.Format(o.datetimeFormat))) - if err != nil { - return n, err - } - n += cnt + b.WriteString(doc.FileTime.Format(o.datetimeFormat)) case OUT_TOK_AUTHORS: - cnt, err := w.Write([]byte(strings.Join(doc.Authors, ", "))) - if err != nil { - return n, err - } - n += cnt + b.WriteString(strings.Join(doc.Authors, o.listSeparator)) case OUT_TOK_TAGS: - cnt, err := w.Write([]byte(strings.Join(doc.Tags, ", "))) - if err != nil { - return n, err - } - n += cnt + b.WriteString(strings.Join(doc.Tags, o.listSeparator)) case OUT_TOK_LINKS: - cnt, err := w.Write([]byte(strings.Join(doc.Links, ", "))) - if err != nil { - return n, err - } - n += cnt + b.WriteString(strings.Join(doc.Links, o.listSeparator)) case OUT_TOK_META: - cnt, err := w.Write([]byte(doc.OtherMeta)) - if err != nil { - return n, err - } - n += cnt + b.WriteString(doc.OtherMeta) default: - return n, ErrUnrecognizedOutputToken + return 0, ErrUnrecognizedOutputToken } } - return n, nil + + b.WriteString(o.docSeparator) + n, err := io.Copy(w, &b) + return int(n), err } |
