Update vendored dependencies.

This commit is contained in:
Martin Dosch 2021-02-17 11:27:04 +01:00
parent 41c09e70c1
commit 57eac03993
10 changed files with 314 additions and 76 deletions

6
go.mod
View file

@ -7,16 +7,16 @@ require (
github.com/andybalholm/cascadia v1.2.0 // indirect github.com/andybalholm/cascadia v1.2.0 // indirect
github.com/chilts/sid v0.0.0-20190607042430-660e94789ec9 github.com/chilts/sid v0.0.0-20190607042430-660e94789ec9
github.com/mattn/go-runewidth v0.0.10 // indirect github.com/mattn/go-runewidth v0.0.10 // indirect
github.com/mattn/go-xmpp v0.0.0-20200309091041-899ef71e80d2 github.com/mattn/go-xmpp v0.0.0-20210121082723-b40e1294994d
github.com/mmcdole/gofeed v1.1.0 github.com/mmcdole/gofeed v1.1.0
github.com/mmcdole/goxpp v0.0.0-20200921145534-2f3784f67354 // indirect github.com/mmcdole/goxpp v0.0.0-20200921145534-2f3784f67354 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.1 // indirect github.com/modern-go/reflect2 v1.0.1 // indirect
github.com/olekukonko/tablewriter v0.0.4 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/rivo/uniseg v0.2.0 // indirect github.com/rivo/uniseg v0.2.0 // indirect
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect
github.com/stretchr/testify v1.5.1 // indirect github.com/stretchr/testify v1.5.1 // indirect
golang.org/x/net v0.0.0-20201224014010-6772e930b67b // indirect golang.org/x/net v0.0.0-20210119194325-5f4716e94777 // indirect
golang.org/x/text v0.3.5 // indirect golang.org/x/text v0.3.5 // indirect
jaytaylor.com/html2text v0.0.0-20200412013138-3577fbdbcff7 jaytaylor.com/html2text v0.0.0-20200412013138-3577fbdbcff7
) )

15
go.sum
View file

@ -17,12 +17,11 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68= github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.10 h1:CoZ3S2P7pvtP45xOtBw+/mDL2z0RKI576gSkzRRpdGg= github.com/mattn/go-runewidth v0.0.10 h1:CoZ3S2P7pvtP45xOtBw+/mDL2z0RKI576gSkzRRpdGg=
github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
github.com/mattn/go-xmpp v0.0.0-20200309091041-899ef71e80d2 h1:F544zRtDc/pMpFNHN46oeXV2jIAG4DoMH+6zlVSn0Q8= github.com/mattn/go-xmpp v0.0.0-20210121082723-b40e1294994d h1:LrXbX6iVhQ3Z50hnhTdyP4K60jevMzk/x2TpMYtOJqg=
github.com/mattn/go-xmpp v0.0.0-20200309091041-899ef71e80d2/go.mod h1:Cs5mF0OsrRRmhkyOod//ldNPOwJsrBvJ+1WRspv0xoc= github.com/mattn/go-xmpp v0.0.0-20210121082723-b40e1294994d/go.mod h1:Cs5mF0OsrRRmhkyOod//ldNPOwJsrBvJ+1WRspv0xoc=
github.com/mmcdole/gofeed v1.1.0 h1:T2WrGLVJRV04PY2qwhEJLHCt9JiCtBhb6SmC8ZvJH08= github.com/mmcdole/gofeed v1.1.0 h1:T2WrGLVJRV04PY2qwhEJLHCt9JiCtBhb6SmC8ZvJH08=
github.com/mmcdole/gofeed v1.1.0/go.mod h1:PPiVwgDXLlz2N83KB4TrIim2lyYM5Zn7ZWH9Pi4oHUk= github.com/mmcdole/gofeed v1.1.0/go.mod h1:PPiVwgDXLlz2N83KB4TrIim2lyYM5Zn7ZWH9Pi4oHUk=
github.com/mmcdole/goxpp v0.0.0-20181012175147-0068e33feabf h1:sWGE2v+hO0Nd4yFU/S/mDBM5plIU8v/Qhfz41hkDIAI= github.com/mmcdole/goxpp v0.0.0-20181012175147-0068e33feabf h1:sWGE2v+hO0Nd4yFU/S/mDBM5plIU8v/Qhfz41hkDIAI=
@ -37,8 +36,8 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLD
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/olekukonko/tablewriter v0.0.4 h1:vHD/YYe1Wolo78koG299f7V/VAS08c6IpCLn+Ejf/w8= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 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/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rivo/uniseg v0.1.0 h1:+2KBaVoUmb9XzDsrx/Ct0W/EYOSFf/nWTauy++DprtY= github.com/rivo/uniseg v0.1.0 h1:+2KBaVoUmb9XzDsrx/Ct0W/EYOSFf/nWTauy++DprtY=
@ -58,8 +57,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201224014010-6772e930b67b h1:iFwSg7t5GZmB/Q5TjiEAsdoLDrdJRC1RiF2WhuV29Qw= golang.org/x/net v0.0.0-20210119194325-5f4716e94777 h1:003p0dJM77cxMSyCPFphvZf/Y5/NXf5fzg6ufd1/Oew=
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=

View file

@ -43,7 +43,7 @@ const (
) )
// Default TLS configuration options // Default TLS configuration options
var DefaultConfig tls.Config var DefaultConfig = &tls.Config{}
// DebugWriter is the writer used to write debugging output to. // DebugWriter is the writer used to write debugging output to.
var DebugWriter io.Writer = os.Stderr var DebugWriter io.Writer = os.Stderr
@ -76,7 +76,7 @@ func containsIgnoreCase(s, substr string) bool {
return strings.Contains(s, substr) return strings.Contains(s, substr)
} }
func connect(host, user, passwd string) (net.Conn, error) { func connect(host, user, passwd string, timeout time.Duration) (net.Conn, error) {
addr := host addr := host
if strings.TrimSpace(host) == "" { if strings.TrimSpace(host) == "" {
@ -117,7 +117,7 @@ func connect(host, user, passwd string) (net.Conn, error) {
} }
} }
c, err := net.Dial("tcp", addr) c, err := net.DialTimeout("tcp", addr, timeout)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -153,6 +153,10 @@ type Options struct {
// Password supplies the password to use for authentication with the remote server. // Password supplies the password to use for authentication with the remote server.
Password string Password string
// DialTimeout is the time limit for establishing a connection. A
// DialTimeout of zero means no timeout.
DialTimeout time.Duration
// Resource specifies an XMPP client resource, like "bot", instead of accepting one // Resource specifies an XMPP client resource, like "bot", instead of accepting one
// from the server. Use "" to let the server generate one for your client. // from the server. Use "" to let the server generate one for your client.
Resource string Resource string
@ -221,7 +225,7 @@ func (o Options) NewClient() (*Client, error) {
} }
} }
} }
c, err := connect(host, o.User, o.Password) c, err := connect(host, o.User, o.Password, o.DialTimeout)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -237,11 +241,11 @@ func (o Options) NewClient() (*Client, error) {
var tlsconn *tls.Conn var tlsconn *tls.Conn
if o.TLSConfig != nil { if o.TLSConfig != nil {
tlsconn = tls.Client(c, o.TLSConfig) tlsconn = tls.Client(c, o.TLSConfig)
host = o.TLSConfig.ServerName
} else { } else {
DefaultConfig.ServerName = host newconfig := DefaultConfig.Clone()
newconfig := DefaultConfig
newconfig.ServerName = host newconfig.ServerName = host
tlsconn = tls.Client(c, &newconfig) tlsconn = tls.Client(c, newconfig)
} }
if err = tlsconn.Handshake(); err != nil { if err = tlsconn.Handshake(); err != nil {
return nil, err return nil, err
@ -526,8 +530,7 @@ func (c *Client) startTLSIfRequired(f *streamFeatures, o *Options, domain string
tc := o.TLSConfig tc := o.TLSConfig
if tc == nil { if tc == nil {
tc = new(tls.Config) tc = DefaultConfig.Clone()
*tc = DefaultConfig
//TODO(scott): we should consider using the server's address or reverse lookup //TODO(scott): we should consider using the server's address or reverse lookup
tc.ServerName = domain tc.ServerName = domain
} }
@ -642,7 +645,20 @@ func (c *Client) Recv() (stanza interface{}, err error) {
case *clientMessage: case *clientMessage:
if v.Event.XMLNS == XMPPNS_PUBSUB_EVENT { if v.Event.XMLNS == XMPPNS_PUBSUB_EVENT {
// Handle Pubsub notifications // Handle Pubsub notifications
return pubsubClientToReturn(v.Event), nil switch v.Event.Items.Node {
case XMPPNS_AVATAR_PEP_METADATA:
return handleAvatarMetadata(v.Event.Items.Items[0].Body,
v.From)
// I am not sure whether this can even happen.
// XEP-0084 only specifies a subscription to
// the metadata node.
/*case XMPPNS_AVATAR_PEP_DATA:
return handleAvatarData(v.Event.Items.Items[0].Body,
v.From,
v.Event.Items.Items[0].ID)*/
default:
return pubsubClientToReturn(v.Event), nil
}
} }
stamp, _ := time.Parse( stamp, _ := time.Parse(
@ -741,10 +757,41 @@ func (c *Client) Recv() (stanza interface{}, err error) {
return PubsubItems{}, err return PubsubItems{}, err
} }
return PubsubItems{ switch p.Node {
p.Node, case XMPPNS_AVATAR_PEP_DATA:
pubsubItemsToReturn(p.Items), return handleAvatarData(p.Items[0].Body,
}, nil v.From,
p.Items[0].ID)
case XMPPNS_AVATAR_PEP_METADATA:
return handleAvatarMetadata(p.Items[0].Body,
v.From)
default:
return PubsubItems{
p.Node,
pubsubItemsToReturn(p.Items),
}, nil
}
// Note: XEP-0084 states that metadata and data
// should be fetched with an id of retrieve1.
// Since we already have PubSub implemented, we
// can just use items1 and items3 to do the same
// as an Avatar node is just a PEP (PubSub) node.
/*case "retrieve1":
var p clientPubsubItems
err := xml.Unmarshal([]byte(v.Query.InnerXML), &p)
if err != nil {
return PubsubItems{}, err
}
switch p.Node {
case XMPPNS_AVATAR_PEP_DATA:
return handleAvatarData(p.Items[0].Body,
v.From,
p.Items[0].ID)
case XMPPNS_AVATAR_PEP_METADATA:
return handleAvatarMetadata(p.Items[0].Body,
v
}*/
} }
case v.Query.XMLName.Local == "": case v.Query.XMLName.Local == "":
return IQ{ID: v.ID, From: v.From, To: v.To, Type: v.Type}, nil return IQ{ID: v.ID, From: v.From, To: v.To, Type: v.Type}, nil

125
vendor/github.com/mattn/go-xmpp/xmpp_avatar.go generated vendored Normal file
View file

@ -0,0 +1,125 @@
package xmpp
import (
"crypto/sha1"
"encoding/base64"
"encoding/hex"
"encoding/xml"
"errors"
"strconv"
)
const (
XMPPNS_AVATAR_PEP_DATA = "urn:xmpp:avatar:data"
XMPPNS_AVATAR_PEP_METADATA = "urn:xmpp:avatar:metadata"
)
type clientAvatarData struct {
XMLName xml.Name `xml:"data"`
Data []byte `xml:",innerxml"`
}
type clientAvatarInfo struct {
XMLName xml.Name `xml:"info"`
Bytes string `xml:"bytes,attr"`
Width string `xml:"width,attr"`
Height string `xml:"height,attr"`
ID string `xml:"id,attr"`
Type string `xml:"type,attr"`
URL string `xml:"url,attr"`
}
type clientAvatarMetadata struct {
XMLName xml.Name `xml:"metadata"`
XMLNS string `xml:"xmlns,attr"`
Info clientAvatarInfo `xml:"info"`
}
type AvatarData struct {
Data []byte
From string
}
type AvatarMetadata struct {
From string
Bytes int
Width int
Height int
ID string
Type string
URL string
}
func handleAvatarData(itemsBody []byte, from, id string) (AvatarData, error) {
var data clientAvatarData
err := xml.Unmarshal(itemsBody, &data)
if err != nil {
return AvatarData{}, err
}
// Base64-decode the avatar data to check its SHA1 hash
dataRaw, err := base64.StdEncoding.DecodeString(
string(data.Data))
if err != nil {
return AvatarData{}, err
}
hash := sha1.Sum(dataRaw)
hashStr := hex.EncodeToString(hash[:])
if hashStr != id {
return AvatarData{}, errors.New("SHA1 hashes do not match")
}
return AvatarData{
Data: dataRaw,
From: from,
}, nil
}
func handleAvatarMetadata(body []byte, from string) (AvatarMetadata, error) {
var meta clientAvatarMetadata
err := xml.Unmarshal(body, &meta)
if err != nil {
return AvatarMetadata{}, err
}
return AvatarMetadata{
From: from,
Bytes: atoiw(meta.Info.Bytes),
Width: atoiw(meta.Info.Width),
Height: atoiw(meta.Info.Height),
ID: meta.Info.ID,
Type: meta.Info.Type,
URL: meta.Info.URL,
}, nil
}
// A wrapper for atoi which just returns -1 if an error occurs
func atoiw(str string) int {
i, err := strconv.Atoi(str)
if err != nil {
return -1
}
return i
}
func (c *Client) AvatarSubscribeMetadata(jid string) {
c.PubsubSubscribeNode(XMPPNS_AVATAR_PEP_METADATA, jid)
}
func (c *Client) AvatarUnsubscribeMetadata(jid string) {
c.PubsubUnsubscribeNode(XMPPNS_AVATAR_PEP_METADATA, jid)
}
func (c *Client) AvatarRequestData(jid string) {
c.PubsubRequestLastItems(XMPPNS_AVATAR_PEP_DATA, jid)
}
func (c *Client) AvatarRequestDataByID(jid, id string) {
c.PubsubRequestItem(XMPPNS_AVATAR_PEP_DATA, jid, id)
}
func (c *Client) AvatarRequestMetadata(jid string) {
c.PubsubRequestLastItems(XMPPNS_AVATAR_PEP_METADATA, jid)
}

View file

@ -1,8 +1,8 @@
language: go language: go
arch:
- ppc64le
- amd64
go: go:
- 1.1
- 1.2
- 1.3 - 1.3
- 1.4 - 1.4
- 1.5 - 1.5
@ -12,3 +12,11 @@ go:
- 1.9 - 1.9
- "1.10" - "1.10"
- tip - tip
jobs:
exclude :
- arch : ppc64le
go :
- 1.3
- arch : ppc64le
go :
- 1.4

View file

@ -25,7 +25,7 @@ Generate ASCII table on the fly ... Installation is simple as
- Set custom footer support - Set custom footer support
- Optional identical cells merging - Optional identical cells merging
- Set custom caption - Set custom caption
- Optional reflowing of paragrpahs in multi-line cells. - Optional reflowing of paragraphs in multi-line cells.
#### Example 1 - Basic #### Example 1 - Basic
```go ```go
@ -197,6 +197,41 @@ table.Render()
+----------+--------------------------+-------+---------+ +----------+--------------------------+-------+---------+
``` ```
#### Example 7 - Identical cells merging (specify the column index to merge)
```go
data := [][]string{
[]string{"1/1/2014", "Domain name", "1234", "$10.98"},
[]string{"1/1/2014", "January Hosting", "1234", "$10.98"},
[]string{"1/4/2014", "February Hosting", "3456", "$51.00"},
[]string{"1/4/2014", "February Extra Bandwidth", "4567", "$30.00"},
}
table := tablewriter.NewWriter(os.Stdout)
table.SetHeader([]string{"Date", "Description", "CV2", "Amount"})
table.SetFooter([]string{"", "", "Total", "$146.93"})
table.SetAutoMergeCellsByColumnIndex([]int{2, 3})
table.SetRowLine(true)
table.AppendBulk(data)
table.Render()
```
##### Output 7
```
+----------+--------------------------+-------+---------+
| DATE | DESCRIPTION | CV2 | AMOUNT |
+----------+--------------------------+-------+---------+
| 1/1/2014 | Domain name | 1234 | $10.98 |
+----------+--------------------------+ + +
| 1/1/2014 | January Hosting | | |
+----------+--------------------------+-------+---------+
| 1/4/2014 | February Hosting | 3456 | $51.00 |
+----------+--------------------------+-------+---------+
| 1/4/2014 | February Extra Bandwidth | 4567 | $30.00 |
+----------+--------------------------+-------+---------+
| TOTAL | $146.93 |
+----------+--------------------------+-------+---------+
```
#### Table with color #### Table with color
```go ```go
@ -233,7 +268,7 @@ table.Render()
#### Table with color Output #### Table with color Output
![Table with Color](https://cloud.githubusercontent.com/assets/6460392/21101956/bbc7b356-c0a1-11e6-9f36-dba694746efc.png) ![Table with Color](https://cloud.githubusercontent.com/assets/6460392/21101956/bbc7b356-c0a1-11e6-9f36-dba694746efc.png)
#### Example - 7 Table Cells with Color #### Example - 8 Table Cells with Color
Individual Cell Colors from `func Rich` take precedence over Column Colors Individual Cell Colors from `func Rich` take precedence over Column Colors
@ -289,7 +324,7 @@ table.Render()
##### Table cells with color Output ##### Table cells with color Output
![Table cells with Color](https://user-images.githubusercontent.com/9064687/63969376-bcd88d80-ca6f-11e9-9466-c3d954700b25.png) ![Table cells with Color](https://user-images.githubusercontent.com/9064687/63969376-bcd88d80-ca6f-11e9-9466-c3d954700b25.png)
#### Example 8 - Set table caption #### Example 9 - Set table caption
```go ```go
data := [][]string{ data := [][]string{
[]string{"A", "The Good", "500"}, []string{"A", "The Good", "500"},
@ -310,7 +345,7 @@ table.Render() // Send output
Note: Caption text will wrap with total width of rendered table. Note: Caption text will wrap with total width of rendered table.
##### Output 7 ##### Output 9
``` ```
+------+-----------------------+--------+ +------+-----------------------+--------+
| NAME | SIGN | RATING | | NAME | SIGN | RATING |
@ -323,7 +358,7 @@ Note: Caption text will wrap with total width of rendered table.
Movie ratings. Movie ratings.
``` ```
#### Example 8 - Set NoWhiteSpace and TablePadding option #### Example 10 - Set NoWhiteSpace and TablePadding option
```go ```go
data := [][]string{ data := [][]string{
{"node1.example.com", "Ready", "compute", "1.11"}, {"node1.example.com", "Ready", "compute", "1.11"},
@ -349,7 +384,7 @@ table.AppendBulk(data) // Add Bulk Data
table.Render() table.Render()
``` ```
##### Output 8 ##### Output 10
``` ```
NAME STATUS ROLE VERSION NAME STATUS ROLE VERSION
node1.example.com Ready compute 1.11 node1.example.com Ready compute 1.11

View file

@ -2,4 +2,4 @@ module github.com/olekukonko/tablewriter
go 1.12 go 1.12
require github.com/mattn/go-runewidth v0.0.7 require github.com/mattn/go-runewidth v0.0.9

View file

@ -1,2 +1,2 @@
github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54= github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=

View file

@ -48,39 +48,40 @@ type Border struct {
} }
type Table struct { type Table struct {
out io.Writer out io.Writer
rows [][]string rows [][]string
lines [][][]string lines [][][]string
cs map[int]int cs map[int]int
rs map[int]int rs map[int]int
headers [][]string headers [][]string
footers [][]string footers [][]string
caption bool caption bool
captionText string captionText string
autoFmt bool autoFmt bool
autoWrap bool autoWrap bool
reflowText bool reflowText bool
mW int mW int
pCenter string pCenter string
pRow string pRow string
pColumn string pColumn string
tColumn int tColumn int
tRow int tRow int
hAlign int hAlign int
fAlign int fAlign int
align int align int
newLine string newLine string
rowLine bool rowLine bool
autoMergeCells bool autoMergeCells bool
noWhiteSpace bool columnsToAutoMergeCells map[int]bool
tablePadding string noWhiteSpace bool
hdrLine bool tablePadding string
borders Border hdrLine bool
colSize int borders Border
headerParams []string colSize int
columnsParams []string headerParams []string
footerParams []string columnsParams []string
columnsAlign []int footerParams []string
columnsAlign []int
} }
// Start New Table // Start New Table
@ -276,6 +277,21 @@ func (t *Table) SetAutoMergeCells(auto bool) {
t.autoMergeCells = auto t.autoMergeCells = auto
} }
// Set Auto Merge Cells By Column Index
// This would enable / disable the merge of cells with identical values for specific columns
// If cols is empty, it is the same as `SetAutoMergeCells(true)`.
func (t *Table) SetAutoMergeCellsByColumnIndex(cols []int) {
t.autoMergeCells = true
if len(cols) > 0 {
m := make(map[int]bool)
for _, col := range cols {
m[col] = true
}
t.columnsToAutoMergeCells = m
}
}
// Set Table Border // Set Table Border
// This would enable / disable line around the table // This would enable / disable line around the table
func (t *Table) SetBorder(border bool) { func (t *Table) SetBorder(border bool) {
@ -830,9 +846,19 @@ func (t *Table) printRowMergeCells(writer io.Writer, columns [][]string, rowIdx
} }
if t.autoMergeCells { if t.autoMergeCells {
var mergeCell bool
if t.columnsToAutoMergeCells != nil {
// Check to see if the column index is in columnsToAutoMergeCells.
if t.columnsToAutoMergeCells[y] {
mergeCell = true
}
} else {
// columnsToAutoMergeCells was not set.
mergeCell = true
}
//Store the full line to merge mutli-lines cells //Store the full line to merge mutli-lines cells
fullLine := strings.TrimRight(strings.Join(columns[y], " "), " ") fullLine := strings.TrimRight(strings.Join(columns[y], " "), " ")
if len(previousLine) > y && fullLine == previousLine[y] && fullLine != "" { if len(previousLine) > y && fullLine == previousLine[y] && fullLine != "" && mergeCell {
// If this cell is identical to the one above but not empty, we don't display the border and keep the cell empty. // If this cell is identical to the one above but not empty, we don't display the border and keep the cell empty.
displayCellBorder = append(displayCellBorder, false) displayCellBorder = append(displayCellBorder, false)
str = "" str = ""

8
vendor/modules.txt vendored
View file

@ -12,7 +12,7 @@ github.com/json-iterator/go
# github.com/mattn/go-runewidth v0.0.10 # github.com/mattn/go-runewidth v0.0.10
## explicit ## explicit
github.com/mattn/go-runewidth github.com/mattn/go-runewidth
# github.com/mattn/go-xmpp v0.0.0-20200309091041-899ef71e80d2 # github.com/mattn/go-xmpp v0.0.0-20210121082723-b40e1294994d
## explicit ## explicit
github.com/mattn/go-xmpp github.com/mattn/go-xmpp
# github.com/mmcdole/gofeed v1.1.0 # github.com/mmcdole/gofeed v1.1.0
@ -32,7 +32,7 @@ github.com/modern-go/concurrent
# github.com/modern-go/reflect2 v1.0.1 # github.com/modern-go/reflect2 v1.0.1
## explicit ## explicit
github.com/modern-go/reflect2 github.com/modern-go/reflect2
# github.com/olekukonko/tablewriter v0.0.4 # github.com/olekukonko/tablewriter v0.0.5
## explicit ## explicit
github.com/olekukonko/tablewriter github.com/olekukonko/tablewriter
# github.com/rivo/uniseg v0.2.0 # github.com/rivo/uniseg v0.2.0
@ -43,9 +43,7 @@ github.com/rivo/uniseg
github.com/ssor/bom github.com/ssor/bom
# github.com/stretchr/testify v1.5.1 # github.com/stretchr/testify v1.5.1
## explicit ## explicit
# golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 # golang.org/x/net v0.0.0-20210119194325-5f4716e94777
## explicit
# golang.org/x/net v0.0.0-20201224014010-6772e930b67b
## explicit ## explicit
golang.org/x/net/html golang.org/x/net/html
golang.org/x/net/html/atom golang.org/x/net/html/atom