Skip to content

Commit

Permalink
Support environments.
Browse files Browse the repository at this point in the history
  • Loading branch information
magicdrive committed Nov 2, 2024
1 parent 94556c8 commit 80f229e
Show file tree
Hide file tree
Showing 6 changed files with 137 additions and 40 deletions.
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,16 @@ Option | Description
* `<json-string>`: Direct JSON string input.
* `<null-type-name>`: The type name used to replace `null` type from json.

### Environments

Environment | Description | Default
-------------------------------- | -------------------------------------------------------------------------------- | ---------------
`KIRKE_DEFAULT_ROOT_NAME` | Specified default used <root-name> | `AutoGenerated`
`KIRKE_DEFAULT_NULL_AS` | Specified default used <null-type-name>. | `interface{}`
`KIRKE_DEFAULT_OUTPUT_MODE` | Specified the default used output mode. Only `outline` and `inline` are valid. | `outline`
`KIRKE_DEFAULT_NO_PAGER` | When value "1", output doesn't use the pager. | `0`
`KIRKE_DEFAULT_WITH_POINTER` | When value "1", defines struct and array fields as pointers. | `0`

Examples
--------

Expand Down
19 changes: 15 additions & 4 deletions internal/commandline/help.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,21 @@ Options:
--no-pager Does not use a pager even if the output size is larger than the terminal. (default: false)

Arguments:
<root-name> Used as the name of the root struct in the output. Automatically converted to camel case.
<json-file> A file containing a JSON string. It will be read even if the extension is not .json.
<json-string> Direct JSON string input.
<null-type-name> The type name used to replace `null` type from json.
<root-name> Used as the name of the root struct in the output. Automatically converted to camel case.
<json-file> A file containing a JSON string. It will be read even if the extension is not .json.
<json-string> Direct JSON string input.
<null-type-name> The type name used to replace `null` type from json.

Environments:
KIRKE_DEFAULT_ROOT_NAME Specified default used <root-name>. (default: AutoGenerated)
KIRKE_DEFAULT_NULL_AS Specified default used <null-type-name>. (default: interface{})
KIRKE_DEFAULT_OUTPUT_MODE Specified the default used output mode. Only `outline` and `inline` are valid. (default: outline)
used if the `--inline` or `--outline` option is not specified. (invalid value will ignored)
KIRKE_DEFAULT_NO_PAGER When value "1", output doesn't use the pager. (default: 0)
used if the --with-pager option is not specified.
KIRKE_DEFAULT_WITH_POINTER When value "1", defines struct and array fields as pointers. (default: 0)
used if the `--with-pointer` option is not specified. valid in outline mode.


Examples:
ex1)
Expand Down
68 changes: 48 additions & 20 deletions internal/commandline/mod.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package commandline
import (
_ "embed"
"flag"
"fmt"
"os"
)

//go:embed help.txt
Expand All @@ -14,51 +16,77 @@ func OptParse(args []string) (int, *Option, error) {

fs := flag.NewFlagSet("kirke", flag.ExitOnError)

nameOpt := fs.String("name", "AutoGenerated", "Specified root struct name.")
fs.StringVar(nameOpt, "n", "AutoGenerated", "Specified root struct name.")
// --name
var defaultName = os.Getenv("KIRKE_DEFAULT_ROOT_NAME")
if defaultName == "" {
defaultName = "AutoGenerated"
}
nameOpt := fs.String("name", defaultName, "Specified root struct name.")
fs.StringVar(nameOpt, "n", defaultName, "Specified root struct name.")

// --json
jsonOpt := fs.String("json", "", "Specified json string.")
fs.StringVar(jsonOpt, "j", "", "Specified json string.")

// --file
filePathOpt := fs.String("file", "", "Specified json string source file.")
fs.StringVar(filePathOpt, "f", "", "Specified json string source file.")

nullAsOpt := fs.String("null-as", "interface{}", "Specified type name used to replace nulls from json.")
fs.StringVar(nullAsOpt, "a", "interface{}", "Specified type name used to replace nulls from json.")
// --null-as
var defaultNullAs = os.Getenv("KIRKE_DEFAULT_NULL_AS")
if defaultNullAs == "" {
defaultNullAs = "interface{}"
}
nullAsOpt := fs.String("null-as", defaultNullAs, "Specified type name used to replace nulls from json.")
fs.StringVar(nullAsOpt, "a", defaultNullAs, "Specified type name used to replace nulls from json.")

helpFlagOpt := fs.Bool("help", false, "Show this message.")
fs.BoolVar(helpFlagOpt, "h", false, "Show this message.")
// --help
helpFlagOpt := fs.Bool("help", false, "Show help message.")
fs.BoolVar(helpFlagOpt, "h", false, "Show help message.")

// --version
versionFlagOpt := fs.Bool("version", false, "Show version.")
fs.BoolVar(versionFlagOpt, "v", false, "Show version.")

// --pipe
forcePpipeFlagOpt := fs.Bool("pipe", false, "Receive a JSON string from a pipe.")
fs.BoolVar(forcePpipeFlagOpt, "p", false, "Receive a JSON string from a pipe.")

noPagerFlagOpt := fs.Bool("no-pager", false, "Do not use a pager for output.")
// --no-pager
var defaultNoPager = os.Getenv("KIRKE_DEFAULT_NO_PAGER") == "1"
noPagerFlagOpt := fs.Bool("no-pager", defaultNoPager, "Do not use a pager for output.")

// ouputmode --inline --outline
var defaultOutputMode = os.Getenv("KIRKE_DEFAULT_OUTPUT_MODE")
inlineFlagOpt := fs.Bool("inline", false, "Create inline struct definition output.")
outlineFlagOpt := fs.Bool("outline", false, "Create outline struct definition output.")

withPointerOpt := fs.Bool("with-pointer", false, "Make nested struct fields of pointer type.")
// with-pointer
var defaultWithPointer = os.Getenv("KIRKE_DEFAULT_WITH_POINTER") == "1"
withPointerOpt := fs.Bool("with-pointer", defaultWithPointer, "Make nested struct fields of pointer type.")

fs.Usage = func() {
fmt.Fprintln(os.Stderr, "\n\n"+helpMessage)
}
err := fs.Parse(args)
if err != nil {
return optLength, nil, err
}

result := &Option{
RootObjName: *nameOpt,
Json: *jsonOpt,
FilePath: *filePathOpt,
NullAs: *nullAsOpt,
WithPointerFlag: *withPointerOpt,
HelpFlag: *helpFlagOpt,
VersionFlag: *versionFlagOpt,
ForcePipeFlag: *forcePpipeFlagOpt,
NoPagerFlag: *noPagerFlagOpt,
InlineFlag: *inlineFlagOpt,
OutlineFlag: *outlineFlagOpt,
FlagSet: fs,
RootObjName: *nameOpt,
Json: *jsonOpt,
FilePath: *filePathOpt,
NullAs: *nullAsOpt,
WithPointerFlag: *withPointerOpt,
HelpFlag: *helpFlagOpt,
VersionFlag: *versionFlagOpt,
ForcePipeFlag: *forcePpipeFlagOpt,
NoPagerFlag: *noPagerFlagOpt,
InlineFlag: *inlineFlagOpt,
OutlineFlag: *outlineFlagOpt,
DefaultOutputMode: defaultOutputMode,
FlagSet: fs,
}
OverRideHelp(fs, result.NoPagerFlag)

Expand Down
43 changes: 42 additions & 1 deletion internal/commandline/mod_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package commandline_test

import (
"os"
"testing"

"github.com/magicdrive/kirke/internal/commandline"
Expand Down Expand Up @@ -51,7 +52,7 @@ func TestOptParse_NoArgs(t *testing.T) {
ForcePipeFlag: false,
NoPagerFlag: false,
InlineFlag: false,
OutlineFlag: false,
OutlineFlag: true,
}

_, result, err := commandline.OptParse(args)
Expand Down Expand Up @@ -97,3 +98,43 @@ func TestOptParse_WithFlags(t *testing.T) {
// Compare only the relevant fields
compareOptions(t, expected, result)
}

func TestOptParse_WithEnviroments(t *testing.T) {

os.Setenv("KIRKE_DEFAULT_NULL_AS", "any")
os.Setenv("KIRKE_DEFAULT_WITH_POINTER", "1")
os.Setenv("KIRKE_DEFAULT_ROOT_NAME", "MyJsonStruct")
os.Setenv("KIRKE_DEFAULT_OUTPUT_MODE", "inline")
os.Setenv("KIRKE_DEFAULT_NO_PAGER", "1")
defer func() {
os.Unsetenv("KIRKE_DEFAULT_NULL_AS")
os.Unsetenv("KIRKE_DEFAULT_WITH_POINTER")
os.Unsetenv("KIRKE_DEFAULT_ROOT_NAME")
os.Unsetenv("KIRKE_DEFAULT_OUTPUT_MODE")
os.Unsetenv("KIRKE_DEFAULT_NO_PAGER")
}()

args := []string{}
expected := &commandline.Option{
RootObjName: "MyJsonStruct",
Json: "",
FilePath: "",
NullAs: "any",
WithPointerFlag: true,
HelpFlag: false,
VersionFlag: false,
ForcePipeFlag: false,
NoPagerFlag: true,
InlineFlag: false,
OutlineFlag: false,
DefaultOutputMode: "inline",
}

_, result, err := commandline.OptParse(args)
if err != nil {
t.Fatalf("Expected no error, got %v", err)
}

// Compare only the relevant fields
compareOptions(t, expected, result)
}
35 changes: 21 additions & 14 deletions internal/commandline/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,20 @@ const (
)

type Option struct {
RootObjName string
Json string
FilePath string
NullAs string
WithPointerFlag bool
HelpFlag bool
VersionFlag bool
ForcePipeFlag bool
NoPagerFlag bool
InlineFlag bool
OutlineFlag bool
FlagSet *flag.FlagSet
PipeReader PipeReader
RootObjName string
Json string
FilePath string
NullAs string
WithPointerFlag bool
HelpFlag bool
VersionFlag bool
ForcePipeFlag bool
NoPagerFlag bool
InlineFlag bool
OutlineFlag bool
DefaultOutputMode string
FlagSet *flag.FlagSet
PipeReader PipeReader
}

func (cr *Option) DecideJSONStr() (string, error) {
Expand Down Expand Up @@ -91,11 +92,17 @@ func (cr *Option) DecideOutputMode() (int, error) {
} else if cr.InlineFlag == false && cr.OutlineFlag == true {
return OutputModeOutline, nil
} else if cr.InlineFlag == false && cr.OutlineFlag == false {
if cr.DefaultOutputMode == "inline" {
return OutputModeInline, nil
} else if cr.DefaultOutputMode == "outline" {
return OutputModeOutline, nil
}
return OutputModeOutline, nil
} else if cr.InlineFlag == true && cr.OutlineFlag == true {
return -1, fmt.Errorf("cannot enable --inline and --outline at the same time.")
} else {
return OutputModeOutline, nil
}
return OutputModeOutline, nil
}

func isValidJSON(jsonStr string) bool {
Expand Down
2 changes: 1 addition & 1 deletion misc/sample.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"id": 12345,
"name": "Sample Data",
"description": "This is a sample JSON data with a complex structure.",
"active": null,
"nullValue": null,
"tags": [
"example",
"json",
Expand Down

0 comments on commit 80f229e

Please sign in to comment.