aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Gopkg.lock6
-rw-r--r--Gopkg.toml2
-rw-r--r--bridge/core/auth/credential.go30
-rw-r--r--bridge/core/auth/token.go6
-rw-r--r--bridge/core/bridge.go43
-rw-r--r--bridge/github/config.go17
-rw-r--r--bridge/github/import.go4
-rw-r--r--bridge/github/import_test.go3
-rw-r--r--bridge/gitlab/config.go17
-rw-r--r--bridge/gitlab/import.go4
-rw-r--r--bridge/gitlab/import_test.go3
-rw-r--r--commands/bridge_auth.go21
-rw-r--r--commands/bridge_auth_show.go29
-rw-r--r--commands/bridge_configure.go2
-rw-r--r--commands/bridge_pull.go2
-rw-r--r--commands/user_adopt.go12
-rw-r--r--vendor/github.com/MichaelMure/go-term-text/.travis.yml2
-rw-r--r--vendor/github.com/MichaelMure/go-term-text/Readme.md9
-rw-r--r--vendor/github.com/MichaelMure/go-term-text/escape_state.go265
-rw-r--r--vendor/github.com/MichaelMure/go-term-text/go.mod4
-rw-r--r--vendor/github.com/MichaelMure/go-term-text/go.sum4
-rw-r--r--vendor/github.com/MichaelMure/go-term-text/wrap.go149
22 files changed, 549 insertions, 85 deletions
diff --git a/Gopkg.lock b/Gopkg.lock
index 8e2f5b81..94d25032 100644
--- a/Gopkg.lock
+++ b/Gopkg.lock
@@ -25,12 +25,12 @@
version = "v0.9.2"
[[projects]]
- digest = "1:b46ef47d5fcc120e6fc1f75e75106f31cbb51fe9981234b5c191d0083d8f9867"
+ digest = "1:364c89f564ef045872f82ff2f156fd3cb09274e4a3bdbf89aef2c2370c955f95"
name = "github.com/MichaelMure/go-term-text"
packages = ["."]
pruneopts = "UT"
- revision = "60f9049b9d18b9370b8ed1247fe4334af5db131a"
- version = "v0.2.1"
+ revision = "6d868251433124ef4ed19c9f8e973ac610d42ef5"
+ version = "v0.2.4"
[[projects]]
digest = "1:897d91c431ce469d35a5e6030e60e617dccd9a0e95bdffa6a80594f5c5800d29"
diff --git a/Gopkg.toml b/Gopkg.toml
index 84f156db..c7496bb0 100644
--- a/Gopkg.toml
+++ b/Gopkg.toml
@@ -82,7 +82,7 @@
[[constraint]]
name = "github.com/MichaelMure/go-term-text"
- version = "0.2.1"
+ version = "0.2.4"
[[constraint]]
branch = "master"
diff --git a/bridge/core/auth/credential.go b/bridge/core/auth/credential.go
index a462a116..fd026c5d 100644
--- a/bridge/core/auth/credential.go
+++ b/bridge/core/auth/credential.go
@@ -32,9 +32,15 @@ func NewErrMultipleMatchCredential(matching []entity.Id) *entity.ErrMultipleMatc
return entity.NewErrMultipleMatch("credential", matching)
}
+// Special Id to mark a credential as being associated to the default user, whoever it might be.
+// The intended use is for the bridge configuration, to be able to create and store a credential
+// with no identities created yet, and then select one with `git-bug user adopt`
+const DefaultUserId = entity.Id("default-user")
+
type Credential interface {
ID() entity.Id
UserId() entity.Id
+ updateUserId(id entity.Id)
Target() string
Kind() CredentialKind
CreateTime() time.Time
@@ -42,7 +48,7 @@ type Credential interface {
// Return all the specific properties of the credential that need to be saved into the configuration.
// This does not include Target, User, Kind and CreateTime.
- ToConfig() map[string]string
+ toConfig() map[string]string
}
// Load loads a credential from the repo config
@@ -90,6 +96,7 @@ func LoadWithPrefix(repo repository.RepoConfig, prefix string) (Credential, erro
return matching[0], nil
}
+// loadFromConfig is a helper to construct a Credential from the set of git configs
func loadFromConfig(rawConfigs map[string]string, id entity.Id) (Credential, error) {
keyPrefix := fmt.Sprintf("%s.%s.", configKeyPrefix, id)
@@ -168,7 +175,7 @@ func PrefixExist(repo repository.RepoConfig, prefix string) bool {
// Store stores a credential in the global git config
func Store(repo repository.RepoConfig, cred Credential) error {
- confs := cred.ToConfig()
+ confs := cred.toConfig()
prefix := fmt.Sprintf("%s.%s.", configKeyPrefix, cred.ID())
@@ -213,6 +220,25 @@ func Remove(repo repository.RepoConfig, id entity.Id) error {
return repo.GlobalConfig().RemoveAll(keyPrefix)
}
+// ReplaceDefaultUser update all the credential attributed to the temporary "default user"
+// with a real user Id
+func ReplaceDefaultUser(repo repository.RepoConfig, id entity.Id) error {
+ list, err := List(repo, WithUserId(DefaultUserId))
+ if err != nil {
+ return err
+ }
+
+ for _, cred := range list {
+ cred.updateUserId(id)
+ err = Store(repo, cred)
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
/*
* Sorting
*/
diff --git a/bridge/core/auth/token.go b/bridge/core/auth/token.go
index 12a3bfc0..8333ef12 100644
--- a/bridge/core/auth/token.go
+++ b/bridge/core/auth/token.go
@@ -59,6 +59,10 @@ func (t *Token) UserId() entity.Id {
return t.userId
}
+func (t *Token) updateUserId(id entity.Id) {
+ t.userId = id
+}
+
func (t *Token) Target() string {
return t.target
}
@@ -88,7 +92,7 @@ func (t *Token) Validate() error {
return nil
}
-func (t *Token) ToConfig() map[string]string {
+func (t *Token) toConfig() map[string]string {
return map[string]string{
tokenValueKey: t.Value,
}
diff --git a/bridge/core/bridge.go b/bridge/core/bridge.go
index c6731ff9..1d0a4681 100644
--- a/bridge/core/bridge.go
+++ b/bridge/core/bridge.go
@@ -43,13 +43,14 @@ type BridgeParams struct {
// Bridge is a wrapper around a BridgeImpl that will bind low-level
// implementation with utility code to provide high-level functions.
type Bridge struct {
- Name string
- repo *cache.RepoCache
- impl BridgeImpl
- importer Importer
- exporter Exporter
- conf Configuration
- initDone bool
+ Name string
+ repo *cache.RepoCache
+ impl BridgeImpl
+ importer Importer
+ exporter Exporter
+ conf Configuration
+ initImportDone bool
+ initExportDone bool
}
// Register will register a new BridgeImpl
@@ -273,8 +274,25 @@ func (b *Bridge) getExporter() Exporter {
return b.exporter
}
-func (b *Bridge) ensureInit() error {
- if b.initDone {
+func (b *Bridge) ensureImportInit() error {
+ if b.initImportDone {
+ return nil
+ }
+
+ importer := b.getImporter()
+ if importer != nil {
+ err := importer.Init(b.repo, b.conf)
+ if err != nil {
+ return err
+ }
+ }
+
+ b.initImportDone = true
+ return nil
+}
+
+func (b *Bridge) ensureExportInit() error {
+ if b.initExportDone {
return nil
}
@@ -294,8 +312,7 @@ func (b *Bridge) ensureInit() error {
}
}
- b.initDone = true
-
+ b.initExportDone = true
return nil
}
@@ -313,7 +330,7 @@ func (b *Bridge) ImportAllSince(ctx context.Context, since time.Time) (<-chan Im
return nil, err
}
- err = b.ensureInit()
+ err = b.ensureImportInit()
if err != nil {
return nil, err
}
@@ -367,7 +384,7 @@ func (b *Bridge) ExportAll(ctx context.Context, since time.Time) (<-chan ExportR
return nil, err
}
- err = b.ensureInit()
+ err = b.ensureExportInit()
if err != nil {
return nil, err
}
diff --git a/bridge/github/config.go b/bridge/github/config.go
index bc26a2fc..ea4b622f 100644
--- a/bridge/github/config.go
+++ b/bridge/github/config.go
@@ -25,6 +25,7 @@ import (
"github.com/MichaelMure/git-bug/bridge/core/auth"
"github.com/MichaelMure/git-bug/cache"
"github.com/MichaelMure/git-bug/entity"
+ "github.com/MichaelMure/git-bug/identity"
"github.com/MichaelMure/git-bug/repository"
"github.com/MichaelMure/git-bug/util/colors"
"github.com/MichaelMure/git-bug/util/interrupt"
@@ -89,10 +90,16 @@ func (g *Github) Configure(repo *cache.RepoCache, params core.BridgeParams) (cor
}
user, err := repo.GetUserIdentity()
- if err != nil {
+ if err != nil && err != identity.ErrNoIdentitySet {
return nil, err
}
+ // default to a "to be filled" user Id if we don't have a valid one yet
+ userId := auth.DefaultUserId
+ if user != nil {
+ userId = user.Id()
+ }
+
var cred auth.Credential
switch {
@@ -101,13 +108,13 @@ func (g *Github) Configure(repo *cache.RepoCache, params core.BridgeParams) (cor
if err != nil {
return nil, err
}
- if cred.UserId() != user.Id() {
+ if user != nil && cred.UserId() != user.Id() {
return nil, fmt.Errorf("selected credential don't match the user")
}
case params.TokenRaw != "":
- cred = auth.NewToken(user.Id(), params.TokenRaw, target)
+ cred = auth.NewToken(userId, params.TokenRaw, target)
default:
- cred, err = promptTokenOptions(repo, user.Id(), owner, project)
+ cred, err = promptTokenOptions(repo, userId, owner, project)
if err != nil {
return nil, err
}
@@ -326,7 +333,7 @@ func promptToken() (string, error) {
return token, nil
}
- fmt.Println("token is invalid")
+ fmt.Println("token has incorrect format")
}
}
diff --git a/bridge/github/import.go b/bridge/github/import.go
index 092e3e71..dfc851fd 100644
--- a/bridge/github/import.go
+++ b/bridge/github/import.go
@@ -12,6 +12,7 @@ import (
"github.com/MichaelMure/git-bug/bug"
"github.com/MichaelMure/git-bug/cache"
"github.com/MichaelMure/git-bug/entity"
+ "github.com/MichaelMure/git-bug/identity"
"github.com/MichaelMure/git-bug/util/text"
)
@@ -47,6 +48,9 @@ func (gi *githubImporter) Init(repo *cache.RepoCache, conf core.Configuration) e
if err == nil {
opts = append(opts, auth.WithUserId(user.Id()))
}
+ if err == identity.ErrNoIdentitySet {
+ opts = append(opts, auth.WithUserId(auth.DefaultUserId))
+ }
creds, err := auth.List(repo, opts...)
if err != nil {
diff --git a/bridge/github/import_test.go b/bridge/github/import_test.go
index 304229a0..57bab61e 100644
--- a/bridge/github/import_test.go
+++ b/bridge/github/import_test.go
@@ -143,6 +143,9 @@ func Test_Importer(t *testing.T) {
err = author.Commit(repo)
require.NoError(t, err)
+ err = identity.SetUserIdentity(repo, author)
+ require.NoError(t, err)
+
token := auth.NewToken(author.Id(), envToken, target)
err = auth.Store(repo, token)
require.NoError(t, err)
diff --git a/bridge/gitlab/config.go b/bridge/gitlab/config.go
index ce066766..1f542d39 100644
--- a/bridge/gitlab/config.go
+++ b/bridge/gitlab/config.go
@@ -19,6 +19,7 @@ import (
"github.com/MichaelMure/git-bug/bridge/core/auth"
"github.com/MichaelMure/git-bug/cache"
"github.com/MichaelMure/git-bug/entity"
+ "github.com/MichaelMure/git-bug/identity"
"github.com/MichaelMure/git-bug/repository"
"github.com/MichaelMure/git-bug/util/colors"
)
@@ -73,10 +74,16 @@ func (g *Gitlab) Configure(repo *cache.RepoCache, params core.BridgeParams) (cor
}
user, err := repo.GetUserIdentity()
- if err != nil {
+ if err != nil && err != identity.ErrNoIdentitySet {
return nil, err
}
+ // default to a "to be filled" user Id if we don't have a valid one yet
+ userId := auth.DefaultUserId
+ if user != nil {
+ userId = user.Id()
+ }
+
var cred auth.Credential
switch {
@@ -85,13 +92,13 @@ func (g *Gitlab) Configure(repo *cache.RepoCache, params core.BridgeParams) (cor
if err != nil {
return nil, err
}
- if cred.UserId() != user.Id() {
+ if user != nil && cred.UserId() != user.Id() {
return nil, fmt.Errorf("selected credential don't match the user")
}
case params.TokenRaw != "":
- cred = auth.NewToken(user.Id(), params.TokenRaw, target)
+ cred = auth.NewToken(userId, params.TokenRaw, target)
default:
- cred, err = promptTokenOptions(repo, user.Id())
+ cred, err = promptTokenOptions(repo, userId)
if err != nil {
return nil, err
}
@@ -289,7 +296,7 @@ func promptToken() (string, error) {
return token, nil
}
- fmt.Println("token format is invalid")
+ fmt.Println("token has incorrect format")
}
}
diff --git a/bridge/gitlab/import.go b/bridge/gitlab/import.go
index 4fa37505..fa6bbfb6 100644
--- a/bridge/gitlab/import.go
+++ b/bridge/gitlab/import.go
@@ -13,6 +13,7 @@ import (
"github.com/MichaelMure/git-bug/bug"
"github.com/MichaelMure/git-bug/cache"
"github.com/MichaelMure/git-bug/entity"
+ "github.com/MichaelMure/git-bug/identity"
"github.com/MichaelMure/git-bug/util/text"
)
@@ -42,6 +43,9 @@ func (gi *gitlabImporter) Init(repo *cache.RepoCache, conf core.Configuration) e
if err == nil {
opts = append(opts, auth.WithUserId(user.Id()))
}
+ if err == identity.ErrNoIdentitySet {
+ opts = append(opts, auth.WithUserId(auth.DefaultUserId))
+ }
creds, err := auth.List(repo, opts...)
if err != nil {
diff --git a/bridge/gitlab/import_test.go b/bridge/gitlab/import_test.go
index 6e378b07..1e2f5d50 100644
--- a/bridge/gitlab/import_test.go
+++ b/bridge/gitlab/import_test.go
@@ -97,6 +97,9 @@ func TestImport(t *testing.T) {
err = author.Commit(repo)
require.NoError(t, err)
+ err = identity.SetUserIdentity(repo, author)
+ require.NoError(t, err)
+
token := auth.NewToken(author.Id(), envToken, target)
err = auth.Store(repo, token)
require.NoError(t, err)
diff --git a/commands/bridge_auth.go b/commands/bridge_auth.go
index 4e8b50c4..bfbab33c 100644
--- a/commands/bridge_auth.go
+++ b/commands/bridge_auth.go
@@ -37,14 +37,21 @@ func runBridgeAuth(cmd *cobra.Command, args []string) error {
value = cred.Value
}
- user, err := backend.ResolveIdentity(cred.UserId())
- if err != nil {
- return err
- }
- userFmt := user.DisplayName()
+ var userFmt string
+
+ switch cred.UserId() {
+ case auth.DefaultUserId:
+ userFmt = colors.Red("default user")
+ default:
+ user, err := backend.ResolveIdentity(cred.UserId())
+ if err != nil {
+ return err
+ }
+ userFmt = user.DisplayName()
- if cred.UserId() == defaultUser.Id() {
- userFmt = colors.Red(userFmt)
+ if cred.UserId() == defaultUser.Id() {
+ userFmt = colors.Red(userFmt)
+ }
}
fmt.Printf("%s %s %s %s %s\n",
diff --git a/commands/bridge_auth_show.go b/commands/bridge_auth_show.go
index 5352957d..02c56806 100644
--- a/commands/bridge_auth_show.go
+++ b/commands/bridge_auth_show.go
@@ -7,17 +7,46 @@ import (
"github.com/spf13/cobra"
"github.com/MichaelMure/git-bug/bridge/core/auth"
+ "github.com/MichaelMure/git-bug/cache"
+ "github.com/MichaelMure/git-bug/util/colors"
+ "github.com/MichaelMure/git-bug/util/interrupt"
)
func runBridgeAuthShow(cmd *cobra.Command, args []string) error {
+ backend, err := cache.NewRepoCache(repo)
+ if err != nil {
+ return err
+ }
+ defer backend.Close()
+ interrupt.RegisterCleaner(backend.Close)
+
cred, err := auth.LoadWithPrefix(repo, args[0])
if err != nil {
return err
}
+ var userFmt string
+
+ switch cred.UserId() {
+ case auth.DefaultUserId:
+ userFmt = colors.Red("default user")
+ default:
+ user, err := backend.ResolveIdentity(cred.UserId())
+ if err != nil {
+ return err
+ }
+ userFmt = user.DisplayName()
+
+ defaultUser, _ := backend.GetUserIdentity()
+ if cred.UserId() == defaultUser.Id() {
+ userFmt = colors.Red(userFmt)
+ }
+ }
+
fmt.Printf("Id: %s\n", cred.ID())
fmt.Printf("Target: %s\n", cred.Target())
fmt.Printf("Kind: %s\n", cred.Kind())
+ fmt.Printf("User: %s\n", userFmt)
fmt.Printf("Creation: %s\n", cred.CreateTime().Format(time.RFC822))
switch cred := cred.(type) {
diff --git a/commands/bridge_configure.go b/commands/bridge_configure.go
index 26bd7bc2..0e29d06a 100644
--- a/commands/bridge_configure.go
+++ b/commands/bridge_configure.go
@@ -206,7 +206,7 @@ git bug bridge configure \
--target=github \
--url=https://github.com/michaelmure/git-bug \
--token=$(TOKEN)`,
- PreRunE: loadRepoEnsureUser,
+ PreRunE: loadRepo,
RunE: runBridgeConfigure,
}
diff --git a/commands/bridge_pull.go b/commands/bridge_pull.go
index 692ec5e9..2dd3d93e 100644
--- a/commands/bridge_pull.go
+++ b/commands/bridge_pull.go
@@ -138,7 +138,7 @@ func parseSince(since string) (time.Time, error) {
var bridgePullCmd = &cobra.Command{
Use: "pull [<name>]",
Short: "Pull updates.",
- PreRunE: loadRepoEnsureUser,
+ PreRunE: loadRepo,
RunE: runBridgePull,
Args: cobra.MaximumNArgs(1),
}
diff --git a/commands/user_adopt.go b/commands/user_adopt.go
index d84d4048..a7de54d9 100644
--- a/commands/user_adopt.go
+++ b/commands/user_adopt.go
@@ -4,7 +4,9 @@ import (
"fmt"
"os"
+ "github.com/MichaelMure/git-bug/bridge/core/auth"
"github.com/MichaelMure/git-bug/cache"
+ "github.com/MichaelMure/git-bug/identity"
"github.com/MichaelMure/git-bug/util/interrupt"
"github.com/spf13/cobra"
)
@@ -24,6 +26,16 @@ func runUserAdopt(cmd *cobra.Command, args []string) error {
return err
}
+ _, err = backend.GetUserIdentity()
+ if err == identity.ErrNoIdentitySet {
+ err = auth.ReplaceDefaultUser(repo, i.Id())
+ if err != nil {
+ return err
+ }
+ } else if err != nil {
+ return err
+ }
+
err = backend.SetUserIdentity(i)
if err != nil {
return err
diff --git a/vendor/github.com/MichaelMure/go-term-text/.travis.yml b/vendor/github.com/MichaelMure/go-term-text/.travis.yml
index 496ca056..c5db9518 100644
--- a/vendor/github.com/MichaelMure/go-term-text/.travis.yml
+++ b/vendor/github.com/MichaelMure/go-term-text/.travis.yml
@@ -1,9 +1,9 @@
language: go
go:
- - 1.10.x
- 1.11.x
- 1.12.x
+ - 1.13.x
env:
- GO111MODULE=on
diff --git a/vendor/github.com/MichaelMure/go-term-text/Readme.md b/vendor/github.com/MichaelMure/go-term-text/Readme.md
index 457b4472..25722ee9 100644
--- a/vendor/github.com/MichaelMure/go-term-text/Readme.md
+++ b/vendor/github.com/MichaelMure/go-term-text/Readme.md
@@ -20,6 +20,7 @@ Included algorithms cover:
- trimming
- alignment
- escape sequence extraction and reapplication
+- escape sequence snapshot and simplification
- truncation
## Example
@@ -31,7 +32,7 @@ import (
"fmt"
"strings"
- text "github.com/MichaelMure/go-term-text"
+ "github.com/MichaelMure/go-term-text"
)
func main() {
@@ -41,8 +42,10 @@ func main() {
"various graphic design. 一只 A Quick \x1b[31m敏捷的狐 Fox " +
"狸跳过了\x1b[0mDog一只懒狗。"
- output, n := text.WrapWithPadIndent(input, 60,
- "\x1b[34m<-indent-> \x1b[0m", "\x1b[33m<-pad-> \x1b[0m")
+ output, n := text.Wrap(input, 60,
+ text.WrapIndent("\x1b[34m<-indent-> \x1b[0m"),
+ text.WrapPad("\x1b[33m<-pad-> \x1b[0m"),
+ )
fmt.Printf("output has %d lines\n\n", n)
diff --git a/vendor/github.com/MichaelMure/go-term-text/escape_state.go b/vendor/github.com/MichaelMure/go-term-text/escape_state.go
new file mode 100644
index 00000000..cec35c26
--- /dev/null
+++ b/vendor/github.com/MichaelMure/go-term-text/escape_state.go
@@ -0,0 +1,265 @@
+package text
+
+import (
+ "fmt"
+ "strconv"
+ "strings"
+)
+
+const Escape = '\x1b'
+
+type EscapeState struct {
+ Bold bool
+ Dim bool
+ Italic bool
+ Underlined bool
+ Blink bool
+ Reverse bool
+ Hidden bool
+ CrossedOut bool
+
+ FgColor Color
+ BgColor Color
+}
+
+type Color interface {
+ Codes() []string
+}
+
+func (es *EscapeState) Witness(s string) {
+ inEscape := false
+ var start int
+
+ runes := []rune(s)
+
+ for i, r := range runes {
+ if r == Escape {
+ inEscape = true
+ start = i
+ continue
+ }
+ if inEscape {
+ if r == 'm' {
+ inEscape = false
+ es.witnessCode(string(runes[start+1 : i]))
+ }
+ continue
+ }
+ }
+}
+
+func (es *EscapeState) witnessCode(s string) {
+ if s == "" {
+ return
+ }
+ if s == "[" {
+ es.reset()
+ return
+ }
+ if len(s) < 2 {
+ return
+ }
+ if s[0] != '[' {
+ return
+ }
+
+ s = s[1:]
+ split := strings.Split(s, ";")
+
+ dequeue := func() {
+ split = split[1:]
+ }
+
+ color := func(ground int) Color {
+ if len(split) < 1 {
+ // the whole sequence is broken, ignoring the rest
+ return nil
+ }
+
+ subCode := split[0]
+ dequeue()
+
+ switch subCode {
+ case "2":
+ if len(split) < 3 {
+ return nil
+ }
+ r, err := strconv.Atoi(split[0])
+ dequeue()
+ if err != nil {
+ return nil
+ }
+ g, err := strconv.Atoi(split[0])
+ dequeue()
+ if err != nil {
+ return nil
+ }
+ b, err := strconv.Atoi(split[0])
+ dequeue()
+ if err != nil {
+ return nil
+ }
+ return &ColorRGB{ground: ground, R: r, G: g, B: b}
+
+ case "5":
+ if len(split) < 1 {
+ return nil
+ }
+ index, err := strconv.Atoi(split[0])
+ dequeue()
+ if err != nil {
+ return nil
+ }
+ return &Color256{ground: ground, Index: index}
+
+ }
+ return nil
+ }
+
+ for len(split) > 0 {
+ code, err := strconv.Atoi(split[0])
+ if err != nil {
+ return
+ }
+ dequeue()
+
+ switch {
+ case code == 0:
+ es.reset()
+
+ case code == 1:
+ es.Bold = true
+ case code == 2:
+ es.Dim = true
+ case code == 3:
+ es.Italic = true
+ case code == 4:
+ es.Underlined = true
+ case code == 5:
+ es.Blink = true
+ // case code == 6:
+ case code == 7:
+ es.Reverse = true
+ case code == 8:
+ es.Hidden = true
+ case code == 9:
+ es.CrossedOut = true
+
+ case code == 21:
+ es.Bold = false
+ case code == 22:
+ es.Dim = false
+ case code == 23:
+ es.Italic = false
+ case code == 24:
+ es.Underlined = false
+ case code == 25:
+ es.Blink = false
+ // case code == 26:
+ case code == 27:
+ es.Reverse = false
+ case code == 28:
+ es.Hidden = false
+ case code == 29:
+ es.CrossedOut = false
+
+ case (code >= 30 && code <= 37) || code == 39 || (code >= 90 && code <= 97):
+ es.FgColor = ColorIndex(code)
+
+ case (code >= 40 && code <= 47) || code == 49 || (code >= 100 && code <= 107):
+ es.BgColor = ColorIndex(code)
+
+ case code == 38:
+ es.FgColor = color(code)
+ if es.FgColor == nil {
+ return
+ }
+
+ case code == 48:
+ es.BgColor = color(code)
+ if es.BgColor == nil {
+ return
+ }
+ }
+ }
+}
+
+func (es *EscapeState) reset() {
+ *es = EscapeState{}
+}
+
+func (es *EscapeState) String() string {
+ var codes []string
+
+ if es.Bold {
+ codes = append(codes, strconv.Itoa(1))
+ }
+ if es.Dim {
+ codes = append(codes, strconv.Itoa(2))
+ }
+ if es.Italic {
+ codes = append(codes, strconv.Itoa(3))
+ }
+ if es.Underlined {
+ codes = append(codes, strconv.Itoa(4))
+ }
+ if es.Blink {
+ codes = append(codes, strconv.Itoa(5))
+ }
+ if es.Reverse {
+ codes = append(codes, strconv.Itoa(7))
+ }
+ if es.Hidden {
+ codes = append(codes, strconv.Itoa(8))
+ }
+ if es.CrossedOut {
+ codes = append(codes, strconv.Itoa(9))
+ }
+
+ if es.FgColor != nil {
+ codes = append(codes, es.FgColor.Codes()...)
+ }
+ if es.BgColor != nil {
+ codes = append(codes, es.BgColor.Codes()...)
+ }
+
+ if len(codes) == 0 {
+ return "\x1b[0m"
+ }
+
+ return fmt.Sprintf("\x1b[%sm", strings.Join(codes, ";"))
+}
+
+type ColorIndex int
+
+func (cInd ColorIndex) Codes() []string {
+ return []string{strconv.Itoa(int(cInd))}
+}
+
+type Color256 struct {
+ ground int
+ Index int
+}
+
+func (c256 Color256) Codes() []string {
+ return []string{
+ strconv.Itoa(c256.ground),
+ "5",
+ strconv.Itoa(c256.Index),
+ }
+}
+
+type ColorRGB struct {
+ ground int
+ R, G, B int
+}
+
+func (cRGB ColorRGB) Codes() []string {
+ return []string{
+ strconv.Itoa(cRGB.ground),
+ "2",
+ strconv.Itoa(cRGB.R),
+ strconv.Itoa(cRGB.G),
+ strconv.Itoa(cRGB.B),
+ }
+}
diff --git a/vendor/github.com/MichaelMure/go-term-text/go.mod b/vendor/github.com/MichaelMure/go-term-text/go.mod
index 162c5dac..a03c8606 100644
--- a/vendor/github.com/MichaelMure/go-term-text/go.mod
+++ b/vendor/github.com/MichaelMure/go-term-text/go.mod
@@ -1,8 +1,8 @@
module github.com/MichaelMure/go-term-text
-go 1.10
+go 1.11
require (
- github.com/mattn/go-runewidth v0.0.4
+ github.com/mattn/go-runewidth v0.0.6
github.com/stretchr/testify v1.3.0
)
diff --git a/vendor/github.com/MichaelMure/go-term-text/go.sum b/vendor/github.com/MichaelMure/go-term-text/go.sum
index 0aaedf16..a119b457 100644
--- a/vendor/github.com/MichaelMure/go-term-text/go.sum
+++ b/vendor/github.com/MichaelMure/go-term-text/go.sum
@@ -1,7 +1,7 @@
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y=
-github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
+github.com/mattn/go-runewidth v0.0.6 h1:V2iyH+aX9C5fsYCpK60U8BYIvmhqxuOL3JZcqc1NB7k=
+github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
diff --git a/vendor/github.com/MichaelMure/go-term-text/wrap.go b/vendor/github.com/MichaelMure/go-term-text/wrap.go
index 2fd6ed5f..eba9e0b8 100644
--- a/vendor/github.com/MichaelMure/go-term-text/wrap.go
+++ b/vendor/github.com/MichaelMure/go-term-text/wrap.go
@@ -13,52 +13,89 @@ func init() {
runewidth.DefaultCondition.EastAsianWidth = false
}
-// Wrap a text for a given line size.
-// Handle properly terminal color escape code
-func Wrap(text string, lineWidth int) (string, int) {
- return WrapLeftPadded(text, lineWidth, 0)
+type wrapOpts struct {
+ indent string
+ pad string
+ align Alignment
}
-// WrapLeftPadded wrap a text for a given line size with a left padding.
-// Handle properly terminal color escape code
-func WrapLeftPadded(text string, lineWidth int, leftPad int) (string, int) {
- pad := strings.Repeat(" ", leftPad)
- return WrapWithPad(text, lineWidth, pad)
+// WrapOption is a functional option for the Wrap() function
+type WrapOption func(opts *wrapOpts)
+
+// WrapPad configure the padding with a string for Wrap()
+func WrapPad(pad string) WrapOption {
+ return func(opts *wrapOpts) {
+ opts.pad = pad
+ }
}
-// WrapWithPad wrap a text for a given line size with a custom left padding
-// Handle properly terminal color escape code
-func WrapWithPad(text string, lineWidth int, pad string) (string, int) {
- return WrapWithPadIndent(text, lineWidth, pad, pad)
+// WrapPadded configure the padding with a number of space characters for Wrap()
+func WrapPadded(padLen int) WrapOption {
+ return func(opts *wrapOpts) {
+ opts.pad = strings.Repeat(" ", padLen)
+ }
}
-// WrapWithPad wrap a text for a given line size with a custom left padding
-// This function also align the result depending on the requested alignment.
-// Handle properly terminal color escape code
-func WrapWithPadAlign(text string, lineWidth int, pad string, align Alignment) (string, int) {
- return WrapWithPadIndentAlign(text, lineWidth, pad, pad, align)
+// WrapPad configure the indentation on the first line for Wrap()
+func WrapIndent(indent string) WrapOption {
+ return func(opts *wrapOpts) {
+ opts.indent = indent
+ }
}
-// WrapWithPadIndent wrap a text for a given line size with a custom left padding
-// and a first line indent. The padding is not effective on the first line, indent
-// is used instead, which allow to implement indents and outdents.
-// Handle properly terminal color escape code
-func WrapWithPadIndent(text string, lineWidth int, indent string, pad string) (string, int) {
- return WrapWithPadIndentAlign(text, lineWidth, indent, pad, NoAlign)
+// WrapAlign configure the text alignment for Wrap()
+func WrapAlign(align Alignment) WrapOption {
+ return func(opts *wrapOpts) {
+ opts.align = align
+ }
}
-// WrapWithPadIndentAlign wrap a text for a given line size with a custom left padding
-// and a first line indent. The padding is not effective on the first line, indent
-// is used instead, which allow to implement indents and outdents.
-// This function also align the result depending on the requested alignment.
+// allWrapOpts compile the set of WrapOption into a final wrapOpts
+// from the default values.
+func allWrapOpts(opts []WrapOption) *wrapOpts {
+ wrapOpts := &wrapOpts{
+ indent: "",
+ pad: "",
+ align: NoAlign,
+ }
+ for _, opt := range opts {
+ opt(wrapOpts)
+ }
+ if wrapOpts.indent == "" {
+ wrapOpts.indent = wrapOpts.pad
+ }
+ return wrapOpts
+}
+
+// Wrap a text for a given line size.
// Handle properly terminal color escape code
-func WrapWithPadIndentAlign(text string, lineWidth int, indent string, pad string, align Alignment) (string, int) {
+// Options are accepted to configure things like indent, padding or alignment.
+// Return the wrapped text and the number of lines
+func Wrap(text string, lineWidth int, opts ...WrapOption) (string, int) {
+ wrapOpts := allWrapOpts(opts)
+
+ if lineWidth <= 0 {
+ return "", 1
+ }
+
var lines []string
nbLine := 0
+ if len(wrapOpts.indent) >= lineWidth {
+ // fallback rendering
+ lines = append(lines, strings.Repeat("⭬", lineWidth))
+ nbLine++
+ wrapOpts.indent = wrapOpts.pad
+ }
+ if len(wrapOpts.pad) >= lineWidth {
+ // fallback rendering
+ line := strings.Repeat("⭬", lineWidth)
+ return strings.Repeat(line+"\n", 5), 5
+ }
+
// Start with the indent
- padStr := indent
- padLen := Len(indent)
+ padStr := wrapOpts.indent
+ padLen := Len(wrapOpts.indent)
// tabs are formatted as 4 spaces
text = strings.Replace(text, "\t", " ", -1)
@@ -67,8 +104,8 @@ func WrapWithPadIndentAlign(text string, lineWidth int, indent string, pad strin
for i, line := range strings.Split(text, "\n") {
// on the second line, use the padding instead
if i == 1 {
- padStr = pad
- padLen = Len(pad)
+ padStr = wrapOpts.pad
+ padLen = Len(wrapOpts.pad)
}
if line == "" || strings.TrimSpace(line) == "" {
@@ -87,14 +124,14 @@ func WrapWithPadIndentAlign(text string, lineWidth int, indent string, pad strin
// use the first wrapped line, ignore everything else and
// wrap the remaining of the line with the normal padding.
- content := LineAlign(strings.TrimRight(split[0], " "), lineWidth-padLen, align)
+ content := LineAlign(strings.TrimRight(split[0], " "), lineWidth-padLen, wrapOpts.align)
lines = append(lines, padStr+content)
nbLine++
line = strings.TrimPrefix(line, split[0])
line = strings.TrimLeft(line, " ")
- padStr = pad
- padLen = Len(pad)
+ padStr = wrapOpts.pad
+ padLen = Len(wrapOpts.pad)
wrapped = softwrapLine(line, lineWidth-padLen)
split = strings.Split(wrapped, "\n")
}
@@ -102,10 +139,10 @@ func WrapWithPadIndentAlign(text string, lineWidth int, indent string, pad strin
for j, seg := range split {
if j == 0 {
// keep the left padding of the wrapped line
- content := LineAlign(strings.TrimRight(seg, " "), lineWidth-padLen, align)
+ content := LineAlign(strings.TrimRight(seg, " "), lineWidth-padLen, wrapOpts.align)
lines = append(lines, padStr+content)
} else {
- content := LineAlign(strings.TrimSpace(seg), lineWidth-padLen, align)
+ content := LineAlign(strings.TrimSpace(seg), lineWidth-padLen, wrapOpts.align)
lines = append(lines, padStr+content)
}
nbLine++
@@ -115,6 +152,42 @@ func WrapWithPadIndentAlign(text string, lineWidth int, indent string, pad strin
return strings.Join(lines, "\n"), nbLine
}
+// WrapLeftPadded wrap a text for a given line size with a left padding.
+// Handle properly terminal color escape code
+func WrapLeftPadded(text string, lineWidth int, leftPad int) (string, int) {
+ return Wrap(text, lineWidth, WrapPadded(leftPad))
+}
+
+// WrapWithPad wrap a text for a given line size with a custom left padding
+// Handle properly terminal color escape code
+func WrapWithPad(text string, lineWidth int, pad string) (string, int) {
+ return Wrap(text, lineWidth, WrapPad(pad))
+}
+
+// WrapWithPad wrap a text for a given line size with a custom left padding
+// This function also align the result depending on the requested alignment.
+// Handle properly terminal color escape code
+func WrapWithPadAlign(text string, lineWidth int, pad string, align Alignment) (string, int) {
+ return Wrap(text, lineWidth, WrapPad(pad), WrapAlign(align))
+}
+
+// WrapWithPadIndent wrap a text for a given line size with a custom left padding
+// and a first line indent. The padding is not effective on the first line, indent
+// is used instead, which allow to implement indents and outdents.
+// Handle properly terminal color escape code
+func WrapWithPadIndent(text string, lineWidth int, indent string, pad string) (string, int) {
+ return Wrap(text, lineWidth, WrapIndent(indent), WrapPad(pad))
+}
+
+// WrapWithPadIndentAlign wrap a text for a given line size with a custom left padding
+// and a first line indent. The padding is not effective on the first line, indent
+// is used instead, which allow to implement indents and outdents.
+// This function also align the result depending on the requested alignment.
+// Handle properly terminal color escape code
+func WrapWithPadIndentAlign(text string, lineWidth int, indent string, pad string, align Alignment) (string, int) {
+ return Wrap(text, lineWidth, WrapIndent(indent), WrapPad(pad), WrapAlign(align))
+}
+
// Break a line into several lines so that each line consumes at most
// 'textWidth' cells. Lines break at groups of white spaces and multibyte
// chars. Nothing is removed from the original text so that it behaves like a