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,8 +645,21 @@ 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
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 return pubsubClientToReturn(v.Event), nil
} }
}
stamp, _ := time.Parse( stamp, _ := time.Parse(
"2006-01-02T15:04:05Z", "2006-01-02T15:04:05Z",
@ -741,11 +757,42 @@ func (c *Client) Recv() (stanza interface{}, err error) {
return PubsubItems{}, err 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.From)
default:
return PubsubItems{ return PubsubItems{
p.Node, p.Node,
pubsubItemsToReturn(p.Items), pubsubItemsToReturn(p.Items),
}, nil }, 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
default: default:

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

@ -72,6 +72,7 @@ type Table struct {
newLine string newLine string
rowLine bool rowLine bool
autoMergeCells bool autoMergeCells bool
columnsToAutoMergeCells map[int]bool
noWhiteSpace bool noWhiteSpace bool
tablePadding string tablePadding string
hdrLine bool hdrLine bool
@ -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