Fix the help example, read padding past the shape gate, catch a stray closing brace, and stop the fieldless hint naming a spelling that fails
This commit is contained in:
@@ -30,8 +30,8 @@ const usage = `Usage: fejkdata [flags] <path|template>
|
|||||||
An argument containing a { token, or a JSON object, array or string, is a
|
An argument containing a { token, or a JSON object, array or string, is a
|
||||||
template; any other argument is a path (a path never contains a brace, a bracket
|
template; any other argument is a path (a path never contains a brace, a bracket
|
||||||
or a quote). Templates reach the data by reference from the root —
|
or a quote). Templates reach the data by reference from the root —
|
||||||
{/sv_SE.person.first} — whether the data is shipped or layered with --data-path. A
|
{/sv_SE.person.last} — whether the data is shipped or layered with --data-path. An
|
||||||
bracket that is not valid JSON names no template and no path.
|
argument carrying one of those characters but no valid JSON names neither.
|
||||||
|
|
||||||
-d, --data-path D a data directory to layer over the shipped data (repeatable; last wins on a clash)
|
-d, --data-path D a data directory to layer over the shipped data (repeatable; last wins on a clash)
|
||||||
-h, --help print this help, then exit
|
-h, --help print this help, then exit
|
||||||
@@ -208,7 +208,7 @@ func (in invocation) check() (argKind, error) {
|
|||||||
return argPath, nil
|
return argPath, nil
|
||||||
}
|
}
|
||||||
if len(in.paths) != 1 {
|
if len(in.paths) != 1 {
|
||||||
return argPath, fmt.Errorf("expected one path, got %d", len(in.paths))
|
return argPath, fmt.Errorf("expected one path or template, got %d", len(in.paths))
|
||||||
}
|
}
|
||||||
return classify(in.paths[0])
|
return classify(in.paths[0])
|
||||||
}
|
}
|
||||||
@@ -276,10 +276,10 @@ const (
|
|||||||
// quote, so no path collides with any of those spellings, and the JSON gate is
|
// quote, so no path collides with any of those spellings, and the JSON gate is
|
||||||
// valid-JSON so a copied bracket names nothing rather than swallowing an argument.
|
// valid-JSON so a copied bracket names nothing rather than swallowing an argument.
|
||||||
func classify(arg string) (argKind, error) {
|
func classify(arg string) (argKind, error) {
|
||||||
if strings.ContainsRune(arg, '{') || (isJSONStart(arg) && json.Valid([]byte(arg))) {
|
if strings.ContainsRune(arg, '{') || (isJSONStart(strings.TrimSpace(arg)) && json.Valid([]byte(arg))) {
|
||||||
return argTemplate, nil
|
return argTemplate, nil
|
||||||
}
|
}
|
||||||
if i := strings.IndexAny(arg, `[]"`); i >= 0 {
|
if i := strings.IndexAny(arg, `[]}"`); i >= 0 {
|
||||||
return argPath, fmt.Errorf("%q holds a %q, which no path may, and it is not valid JSON, so it names no template either", arg, arg[i:i+1])
|
return argPath, fmt.Errorf("%q holds a %q, which no path may, and it is not valid JSON, so it names no template either", arg, arg[i:i+1])
|
||||||
}
|
}
|
||||||
return argPath, nil
|
return argPath, nil
|
||||||
|
|||||||
+16
-1
@@ -165,7 +165,11 @@ func checkArm(name string, fields map[string]node) error {
|
|||||||
return fmt.Errorf("%q is an option and can never be a field", a.key)
|
return fmt.Errorf("%q is an option and can never be a field", a.key)
|
||||||
}
|
}
|
||||||
if len(fields) == 0 {
|
if len(fields) == 0 {
|
||||||
return fmt.Errorf("no field %q; a token names a sibling field, and a bare string has none — write {/%s} to reference the data", a.key, name)
|
hint := ""
|
||||||
|
if hintableRef(name) {
|
||||||
|
hint = fmt.Sprintf(" — write {/%s} to reference the data", name)
|
||||||
|
}
|
||||||
|
return fmt.Errorf("no field %q; a token names a sibling field, and this template has none%s", a.key, hint)
|
||||||
}
|
}
|
||||||
return fmt.Errorf("no field %q", a.key)
|
return fmt.Errorf("no field %q", a.key)
|
||||||
}
|
}
|
||||||
@@ -175,6 +179,17 @@ func checkArm(name string, fields map[string]node) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// hintableRef reports whether {/name} is a reference the grammar accepts, so the
|
||||||
|
// hint never names a spelling that fails too.
|
||||||
|
func hintableRef(name string) bool {
|
||||||
|
for _, seg := range strings.Split(name, ".") {
|
||||||
|
if checkName(seg) != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// tokenOperands lists the fields one {token} body reads as operands, empty for a
|
// tokenOperands lists the fields one {token} body reads as operands, empty for a
|
||||||
// field token or a builtin that reads none.
|
// field token or a builtin that reads none.
|
||||||
func tokenOperands(body string) []string {
|
func tokenOperands(body string) []string {
|
||||||
|
|||||||
Reference in New Issue
Block a user