-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add cli and make go-phrase a cli app
- Loading branch information
Showing
45 changed files
with
2,870 additions
and
130 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,4 @@ | ||
/examples/*.yml | ||
|
||
.phrase | ||
.ruby-version | ||
/cli/test/*.yml |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package cli | ||
|
||
import ( | ||
"github.com/weynsee/go-phrase/phrase" | ||
"net/http" | ||
"net/http/httptest" | ||
"net/url" | ||
"os" | ||
) | ||
|
||
var ( | ||
mux *http.ServeMux | ||
client *phrase.Client | ||
server *httptest.Server | ||
|
||
testFolder = "test" | ||
) | ||
|
||
func setupAPI() { | ||
mux = http.NewServeMux() | ||
server = httptest.NewServer(mux) | ||
client = phrase.New("faketoken") | ||
client.BaseURL, _ = url.Parse(server.URL) | ||
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { | ||
}) | ||
} | ||
|
||
func tearDown() { | ||
shutdownAPI() | ||
os.RemoveAll(testFolder) | ||
} | ||
|
||
func shutdownAPI() { | ||
server.Close() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package cli | ||
|
||
import ( | ||
mcli "github.com/mitchellh/cli" | ||
) | ||
|
||
type cli struct { | ||
cli *mcli.CLI | ||
} | ||
|
||
// NewCLI returns a CLI instance. | ||
func NewCLI(version string, args []string) *cli { | ||
c := mcli.NewCLI("go-phrase", version) | ||
c.Args = args | ||
c.Commands = commands | ||
|
||
return &cli{c} | ||
} | ||
|
||
// Run runs the actual program based on the arguments given. | ||
func (c *cli) Run() (int, error) { | ||
return c.cli.Run() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package cli | ||
|
||
import ( | ||
mcli "github.com/mitchellh/cli" | ||
"reflect" | ||
"testing" | ||
) | ||
|
||
func TestNewCLI(t *testing.T) { | ||
args := []string{"a", "b"} | ||
cli := NewCLI("0.0.1", args) | ||
if got := cli.cli.Name; got != "go-phrase" { | ||
t.Error("cli Name should be go-phrase, not %+v", got) | ||
} | ||
if got := cli.cli.Args; !reflect.DeepEqual(got, args) { | ||
t.Errorf("cli.Args returned %+v, want %+v", got, args) | ||
} | ||
} | ||
|
||
func TestNewCLI_Run(t *testing.T) { | ||
args := []string{"foo", "-bar", "-baz"} | ||
cli := NewCLI("0.0.1", args) | ||
command := new(mcli.MockCommand) | ||
cli.cli.Commands = map[string]mcli.CommandFactory{ | ||
"foo": func() (mcli.Command, error) { | ||
return command, nil | ||
}, | ||
} | ||
res, err := cli.Run() | ||
if err != nil { | ||
t.Fatalf("NewCLI Run returned error %s", err.Error()) | ||
} | ||
if res != 0 { | ||
t.Fatal("NewCLI Run exit code should be 0") | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
package cli | ||
|
||
import ( | ||
mcli "github.com/mitchellh/cli" | ||
"github.com/weynsee/go-phrase/phrase" | ||
"os" | ||
) | ||
|
||
var commands map[string]mcli.CommandFactory | ||
|
||
func init() { | ||
ui := &mcli.ConcurrentUi{ | ||
Ui: &mcli.ColoredUi{ | ||
Ui: &mcli.BasicUi{ | ||
Reader: os.Stdin, | ||
Writer: os.Stdout, | ||
ErrorWriter: os.Stderr, | ||
}, | ||
WarnColor: mcli.UiColorYellow, | ||
ErrorColor: mcli.UiColorRed, | ||
OutputColor: mcli.UiColorGreen, | ||
}, | ||
} | ||
|
||
config, _ := NewConfig(".phrase") | ||
api := phrase.New(config.Secret) | ||
|
||
commands = map[string]mcli.CommandFactory{ | ||
"init": func() (mcli.Command, error) { | ||
return &InitCommand{ | ||
Ui: ui, | ||
Config: config, | ||
API: api, | ||
}, nil | ||
}, | ||
"push": func() (mcli.Command, error) { | ||
return &PushCommand{ | ||
Ui: ui, | ||
Config: config, | ||
API: api, | ||
}, nil | ||
}, | ||
"pull": func() (mcli.Command, error) { | ||
return &PullCommand{ | ||
Ui: ui, | ||
Config: config, | ||
API: api, | ||
}, nil | ||
}, | ||
"tags": func() (mcli.Command, error) { | ||
return &TagsCommand{ | ||
Ui: ui, | ||
Config: config, | ||
API: api, | ||
}, nil | ||
}, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package cli | ||
|
||
import ( | ||
"testing" | ||
) | ||
|
||
func TestCommands(t *testing.T) { | ||
keys := []string{"push", "pull", "tags", "init"} | ||
for _, command := range keys { | ||
_, err := commands[command]() | ||
if err != nil { | ||
t.Errorf("%s command returned error %s", command, err.Error()) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
package cli | ||
|
||
import ( | ||
"encoding/json" | ||
"errors" | ||
"github.com/weynsee/go-phrase/phrase" | ||
"os" | ||
) | ||
|
||
// Config stores the default values for some of the properties of the PhraseApp API client | ||
type Config struct { | ||
path string | ||
|
||
// Project auth token. You can find the auth token in your project overview or project settings form. | ||
Secret string `json:"secret"` | ||
// Default locale your PhraseApp project (default is en). | ||
DefaultLocale string `json:"default_locale"` | ||
// Set a domain for use with Gettext translation files (default is phrase). | ||
Domain string `json:"domain,omitempty"` | ||
// Specify a format that should be used as the default format when downloading files (default is yml). | ||
Format string `json:"format,omitempty"` | ||
// Set the target directly to store your localization files retrieved by phrase pull. Allows placeholders: https://github.com/phrase/phrase#allowed-placeholders-for-advanced-configuration | ||
TargetDirectory string `json:"target_directory,omitempty"` | ||
// Set the directory that contains your source locales (used by the go-phrase push command). Allows placeholders: https://github.com/phrase/phrase#allowed-placeholders-for-advanced-configuration | ||
LocaleDirectory string `json:"locale_directory,omitempty"` | ||
// Set the filename for files you download from PhraseApp via phrase pull. Allows placeholders: https://github.com/phrase/phrase#allowed-placeholders-for-advanced-configuration | ||
LocaleFilename string `json:"locale_filename,omitempty"` | ||
// Set the encoding for your localization files to UTF-8, UTF-16 or Latin-1. Please note that the encodings only work for a handful of formats like IOS .strings or Java .properties. The default will be UTF-8. If none is provided the default encoding of the formats is used. | ||
Encoding string `json:"encoding,omitempty"` | ||
} | ||
|
||
// Config stores locale specific configuration options | ||
type LocaleConfig struct { | ||
Config | ||
format | ||
} | ||
|
||
// NewConfig returns a Config instance. Its properties will be | ||
// populated from the file found in the path argument | ||
// (assumed to be in a certain JSON format), and some properties | ||
// will have default values assigned. | ||
func NewConfig(path string) (*Config, error) { | ||
config := new(Config) | ||
config.path = path | ||
if _, err := os.Stat(path); err == nil { | ||
// if file exists, initialize the object with its contents | ||
f, err := os.Open(path) | ||
if err != nil { | ||
return nil, err | ||
} | ||
if err = json.NewDecoder(f).Decode(config); err != nil { | ||
return nil, err | ||
} | ||
} | ||
|
||
// defaults | ||
if config.Domain == "" { | ||
config.Domain = "phrase" | ||
} | ||
if config.DefaultLocale == "" { | ||
config.DefaultLocale = "en" | ||
} | ||
|
||
return config, nil | ||
} | ||
|
||
// ForLocale returns a LocaleConfig for the given Locale. | ||
func (c *Config) ForLocale(l *phrase.Locale) *LocaleConfig { | ||
return newLocaleConfig(c, l) | ||
} | ||
|
||
// Valid validates the current config to check whether all values are valid. | ||
func (c *Config) Valid() error { | ||
_, found := formats[c.Format] | ||
if !found { | ||
return errors.New("Unrecognized format: " + c.Format) | ||
} | ||
return nil | ||
} | ||
|
||
func newLocaleConfig(c *Config, l *phrase.Locale) *LocaleConfig { | ||
format := formats[c.Format] | ||
lc := &LocaleConfig{*c, format} | ||
if lc.LocaleDirectory = replacePlaceholders(c.LocaleDirectory, c, l); lc.LocaleDirectory == "" { | ||
lc.LocaleDirectory = format.directoryForLocale(c, l) | ||
} | ||
if lc.LocaleFilename = replacePlaceholders(c.LocaleFilename, c, l); lc.LocaleFilename == "" { | ||
lc.LocaleFilename = format.filenameForLocale(c, l) | ||
} | ||
if lc.TargetDirectory = c.TargetDirectory; lc.TargetDirectory == "" { | ||
lc.TargetDirectory = format.properties().targetDirectory | ||
if lc.TargetDirectory == "" { | ||
lc.TargetDirectory = "phrase/locales/" | ||
} | ||
} | ||
return lc | ||
} | ||
|
||
// Save saves current values of the properties of the Config | ||
// instance to disk. | ||
func (c *Config) Save() error { | ||
f, err := os.OpenFile(c.path, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0660) | ||
if err != nil { | ||
return err | ||
} | ||
bytes, err := json.MarshalIndent(c, "", " ") | ||
if err != nil { | ||
return err | ||
} | ||
|
||
_, err = f.Write(bytes) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return f.Close() | ||
} |
Oops, something went wrong.