feat: parse all Go CLIs with flaggy; dump bash complete.
stdlib flag dropped --hop after the query. One wrapper in internal/cli, source <(./bin/cli/complete.go bash). Gitea #34.
This commit is contained in:
+49
-51
@@ -3,12 +3,15 @@ package rank
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/eSlider/2dph/internal/cli"
|
||||
"github.com/integrii/flaggy"
|
||||
)
|
||||
|
||||
const Usage = `usage: bin/brain/search.go "query" [--root facts|info] [--repo REPO] [-n N] [--hop N] [--json] [--no-web]
|
||||
bin/brain/search.go serve [port]
|
||||
bin/brain/search.go --list-model`
|
||||
bin/brain/search.go --list-model
|
||||
source <(./bin/cli/complete.go bash)`
|
||||
|
||||
type Options struct {
|
||||
Query string
|
||||
@@ -21,62 +24,57 @@ type Options struct {
|
||||
NoWeb bool
|
||||
}
|
||||
|
||||
// NewParser is the flaggy schema for search (also used by bin/cli/complete.go).
|
||||
func NewParser(opt *Options) *flaggy.Parser {
|
||||
if opt.Limit == 0 {
|
||||
opt.Limit = 20
|
||||
}
|
||||
p := cli.New("brain-search")
|
||||
p.Description = "deduction search: facts → info → web"
|
||||
p.String(&opt.Root, "", "root", "facts or info")
|
||||
p.String(&opt.Repo, "", "repo", "filter by repo")
|
||||
p.Int(&opt.Limit, "n", "n", "max hits")
|
||||
p.Int(&opt.Hop, "", "hop", "walk FROM_FILE depth 1-3")
|
||||
p.Bool(&opt.JSONOut, "", "json", "JSON output")
|
||||
p.Bool(&opt.NoWeb, "", "no-web", "stay local")
|
||||
p.Bool(&opt.ListModel, "", "list-model", "print embedding model")
|
||||
return p
|
||||
}
|
||||
|
||||
// ParseArgs reads flags. Unknown flags are an error: silently dropping them
|
||||
// meant `--hop 1` vanished and its argument `1` was appended to the query.
|
||||
func ParseArgs(args []string) (Options, error) {
|
||||
opt := Options{Limit: 20}
|
||||
var queryArgs []string
|
||||
|
||||
for i := 0; i < len(args); i++ {
|
||||
arg := args[i]
|
||||
wantsValue := arg == "--root" || arg == "--repo" || arg == "-n" || arg == "--hop"
|
||||
if wantsValue && i+1 >= len(args) {
|
||||
return opt, fmt.Errorf("%s needs a value", arg)
|
||||
}
|
||||
switch arg {
|
||||
case "--root":
|
||||
i++
|
||||
opt.Root = args[i]
|
||||
if opt.Root != "facts" && opt.Root != "info" {
|
||||
return opt, fmt.Errorf("--root must be facts or info, got %q", opt.Root)
|
||||
}
|
||||
case "--repo":
|
||||
i++
|
||||
opt.Repo = args[i]
|
||||
case "-n":
|
||||
i++
|
||||
n, err := strconv.Atoi(args[i])
|
||||
if err != nil || n < 1 {
|
||||
return opt, fmt.Errorf("-n must be a positive integer, got %q", args[i])
|
||||
}
|
||||
opt.Limit = n
|
||||
case "--hop":
|
||||
i++
|
||||
n, err := strconv.Atoi(args[i])
|
||||
if err != nil || n < 1 {
|
||||
return opt, fmt.Errorf("--hop must be a positive integer, got %q", args[i])
|
||||
}
|
||||
if n > 3 {
|
||||
return opt, fmt.Errorf("--hop max is 3 (File → Commit → Person)")
|
||||
}
|
||||
opt.Hop = n
|
||||
case "--json":
|
||||
opt.JSONOut = true
|
||||
case "--no-web":
|
||||
opt.NoWeb = true
|
||||
case "--list-model":
|
||||
opt.ListModel = true
|
||||
default:
|
||||
if strings.HasPrefix(arg, "-") {
|
||||
return opt, fmt.Errorf("unknown flag %q", arg)
|
||||
}
|
||||
queryArgs = append(queryArgs, arg)
|
||||
}
|
||||
p := NewParser(&opt)
|
||||
var q string
|
||||
p.AddPositionalValue(&q, "query", 1, false, "search query")
|
||||
if err := cli.Parse(p, args); err != nil {
|
||||
return opt, err
|
||||
}
|
||||
opt.Query = cli.Query(q, p.TrailingArguments)
|
||||
if opt.Root != "" && opt.Root != "facts" && opt.Root != "info" {
|
||||
return opt, fmt.Errorf("--root must be facts or info, got %q", opt.Root)
|
||||
}
|
||||
if opt.Limit < 1 {
|
||||
return opt, fmt.Errorf("-n must be a positive integer, got %q", strconv.Itoa(opt.Limit))
|
||||
}
|
||||
if opt.Hop < 0 {
|
||||
return opt, fmt.Errorf("--hop must be a positive integer, got %q", strconv.Itoa(opt.Hop))
|
||||
}
|
||||
if opt.Hop > 3 {
|
||||
return opt, fmt.Errorf("--hop max is 3 (File → Commit → Person)")
|
||||
}
|
||||
|
||||
opt.Query = strings.TrimSpace(strings.Join(queryArgs, " "))
|
||||
if opt.Query == "" && !opt.ListModel {
|
||||
return opt, fmt.Errorf("no query given")
|
||||
}
|
||||
return opt, nil
|
||||
}
|
||||
|
||||
// Parser is the search schema for bin/cli/complete.go.
|
||||
func Parser() *flaggy.Parser {
|
||||
opt := Options{Limit: 20}
|
||||
p := NewParser(&opt)
|
||||
var q string
|
||||
p.AddPositionalValue(&q, "query", 1, false, "search query")
|
||||
return p
|
||||
}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
package rank
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/eSlider/2dph/internal/cli"
|
||||
"github.com/integrii/flaggy"
|
||||
)
|
||||
|
||||
type GetOptions struct {
|
||||
ID string
|
||||
Body bool
|
||||
JSONOut bool
|
||||
}
|
||||
|
||||
func GetParser(opt *GetOptions) *flaggy.Parser {
|
||||
p := cli.New("brain-get")
|
||||
p.Description = "read one leaf"
|
||||
p.Bool(&opt.Body, "", "body", "full text instead of snippet")
|
||||
p.Bool(&opt.JSONOut, "", "json", "JSON output")
|
||||
p.AddPositionalValue(&opt.ID, "id", 1, false, "leaf id")
|
||||
return p
|
||||
}
|
||||
|
||||
func ParseGet(args []string) (GetOptions, error) {
|
||||
var opt GetOptions
|
||||
if err := cli.Parse(GetParser(&opt), args); err != nil {
|
||||
return opt, err
|
||||
}
|
||||
if opt.ID == "" {
|
||||
return opt, fmt.Errorf("id required")
|
||||
}
|
||||
return opt, nil
|
||||
}
|
||||
|
||||
type JSONFlag struct {
|
||||
JSONOut bool
|
||||
}
|
||||
|
||||
func bindJSON(name string, opt *JSONFlag) *flaggy.Parser {
|
||||
p := cli.New(name)
|
||||
p.Bool(&opt.JSONOut, "", "json", "JSON output")
|
||||
return p
|
||||
}
|
||||
|
||||
func StatsParser() *flaggy.Parser {
|
||||
opt := JSONFlag{}
|
||||
return bindJSON("brain-stats", &opt)
|
||||
}
|
||||
|
||||
func EvalParser() *flaggy.Parser {
|
||||
opt := JSONFlag{}
|
||||
return bindJSON("brain-eval", &opt)
|
||||
}
|
||||
|
||||
func ParseJSONFlag(name string, args []string) (JSONFlag, error) {
|
||||
var opt JSONFlag
|
||||
return opt, cli.Parse(bindJSON(name, &opt), args)
|
||||
}
|
||||
Reference in New Issue
Block a user