mirror of
https://github.com/araddon/dateparse.git
synced 2024-11-10 11:51:54 +08:00
Removed vendor folder
This commit is contained in:
parent
9d3559c486
commit
539e9f19d1
9
vendor/github.com/apcera/termtables/.travis.yml
generated
vendored
9
vendor/github.com/apcera/termtables/.travis.yml
generated
vendored
@ -1,9 +0,0 @@
|
|||||||
language: go
|
|
||||||
go:
|
|
||||||
- 1.6
|
|
||||||
- 1.7
|
|
||||||
- tip
|
|
||||||
|
|
||||||
script:
|
|
||||||
- go vet $(go list ./...|grep -v "/vendor/")
|
|
||||||
- go test -v -race ./...
|
|
202
vendor/github.com/apcera/termtables/LICENSE
generated
vendored
202
vendor/github.com/apcera/termtables/LICENSE
generated
vendored
@ -1,202 +0,0 @@
|
|||||||
Apache License
|
|
||||||
Version 2.0, January 2004
|
|
||||||
http://www.apache.org/licenses/
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
||||||
|
|
||||||
1. Definitions.
|
|
||||||
|
|
||||||
"License" shall mean the terms and conditions for use, reproduction,
|
|
||||||
and distribution as defined by Sections 1 through 9 of this document.
|
|
||||||
|
|
||||||
"Licensor" shall mean the copyright owner or entity authorized by
|
|
||||||
the copyright owner that is granting the License.
|
|
||||||
|
|
||||||
"Legal Entity" shall mean the union of the acting entity and all
|
|
||||||
other entities that control, are controlled by, or are under common
|
|
||||||
control with that entity. For the purposes of this definition,
|
|
||||||
"control" means (i) the power, direct or indirect, to cause the
|
|
||||||
direction or management of such entity, whether by contract or
|
|
||||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
||||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
||||||
|
|
||||||
"You" (or "Your") shall mean an individual or Legal Entity
|
|
||||||
exercising permissions granted by this License.
|
|
||||||
|
|
||||||
"Source" form shall mean the preferred form for making modifications,
|
|
||||||
including but not limited to software source code, documentation
|
|
||||||
source, and configuration files.
|
|
||||||
|
|
||||||
"Object" form shall mean any form resulting from mechanical
|
|
||||||
transformation or translation of a Source form, including but
|
|
||||||
not limited to compiled object code, generated documentation,
|
|
||||||
and conversions to other media types.
|
|
||||||
|
|
||||||
"Work" shall mean the work of authorship, whether in Source or
|
|
||||||
Object form, made available under the License, as indicated by a
|
|
||||||
copyright notice that is included in or attached to the work
|
|
||||||
(an example is provided in the Appendix below).
|
|
||||||
|
|
||||||
"Derivative Works" shall mean any work, whether in Source or Object
|
|
||||||
form, that is based on (or derived from) the Work and for which the
|
|
||||||
editorial revisions, annotations, elaborations, or other modifications
|
|
||||||
represent, as a whole, an original work of authorship. For the purposes
|
|
||||||
of this License, Derivative Works shall not include works that remain
|
|
||||||
separable from, or merely link (or bind by name) to the interfaces of,
|
|
||||||
the Work and Derivative Works thereof.
|
|
||||||
|
|
||||||
"Contribution" shall mean any work of authorship, including
|
|
||||||
the original version of the Work and any modifications or additions
|
|
||||||
to that Work or Derivative Works thereof, that is intentionally
|
|
||||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
||||||
or by an individual or Legal Entity authorized to submit on behalf of
|
|
||||||
the copyright owner. For the purposes of this definition, "submitted"
|
|
||||||
means any form of electronic, verbal, or written communication sent
|
|
||||||
to the Licensor or its representatives, including but not limited to
|
|
||||||
communication on electronic mailing lists, source code control systems,
|
|
||||||
and issue tracking systems that are managed by, or on behalf of, the
|
|
||||||
Licensor for the purpose of discussing and improving the Work, but
|
|
||||||
excluding communication that is conspicuously marked or otherwise
|
|
||||||
designated in writing by the copyright owner as "Not a Contribution."
|
|
||||||
|
|
||||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
||||||
on behalf of whom a Contribution has been received by Licensor and
|
|
||||||
subsequently incorporated within the Work.
|
|
||||||
|
|
||||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
copyright license to reproduce, prepare Derivative Works of,
|
|
||||||
publicly display, publicly perform, sublicense, and distribute the
|
|
||||||
Work and such Derivative Works in Source or Object form.
|
|
||||||
|
|
||||||
3. Grant of Patent License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
(except as stated in this section) patent license to make, have made,
|
|
||||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
||||||
where such license applies only to those patent claims licensable
|
|
||||||
by such Contributor that are necessarily infringed by their
|
|
||||||
Contribution(s) alone or by combination of their Contribution(s)
|
|
||||||
with the Work to which such Contribution(s) was submitted. If You
|
|
||||||
institute patent litigation against any entity (including a
|
|
||||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
||||||
or a Contribution incorporated within the Work constitutes direct
|
|
||||||
or contributory patent infringement, then any patent licenses
|
|
||||||
granted to You under this License for that Work shall terminate
|
|
||||||
as of the date such litigation is filed.
|
|
||||||
|
|
||||||
4. Redistribution. You may reproduce and distribute copies of the
|
|
||||||
Work or Derivative Works thereof in any medium, with or without
|
|
||||||
modifications, and in Source or Object form, provided that You
|
|
||||||
meet the following conditions:
|
|
||||||
|
|
||||||
(a) You must give any other recipients of the Work or
|
|
||||||
Derivative Works a copy of this License; and
|
|
||||||
|
|
||||||
(b) You must cause any modified files to carry prominent notices
|
|
||||||
stating that You changed the files; and
|
|
||||||
|
|
||||||
(c) You must retain, in the Source form of any Derivative Works
|
|
||||||
that You distribute, all copyright, patent, trademark, and
|
|
||||||
attribution notices from the Source form of the Work,
|
|
||||||
excluding those notices that do not pertain to any part of
|
|
||||||
the Derivative Works; and
|
|
||||||
|
|
||||||
(d) If the Work includes a "NOTICE" text file as part of its
|
|
||||||
distribution, then any Derivative Works that You distribute must
|
|
||||||
include a readable copy of the attribution notices contained
|
|
||||||
within such NOTICE file, excluding those notices that do not
|
|
||||||
pertain to any part of the Derivative Works, in at least one
|
|
||||||
of the following places: within a NOTICE text file distributed
|
|
||||||
as part of the Derivative Works; within the Source form or
|
|
||||||
documentation, if provided along with the Derivative Works; or,
|
|
||||||
within a display generated by the Derivative Works, if and
|
|
||||||
wherever such third-party notices normally appear. The contents
|
|
||||||
of the NOTICE file are for informational purposes only and
|
|
||||||
do not modify the License. You may add Your own attribution
|
|
||||||
notices within Derivative Works that You distribute, alongside
|
|
||||||
or as an addendum to the NOTICE text from the Work, provided
|
|
||||||
that such additional attribution notices cannot be construed
|
|
||||||
as modifying the License.
|
|
||||||
|
|
||||||
You may add Your own copyright statement to Your modifications and
|
|
||||||
may provide additional or different license terms and conditions
|
|
||||||
for use, reproduction, or distribution of Your modifications, or
|
|
||||||
for any such Derivative Works as a whole, provided Your use,
|
|
||||||
reproduction, and distribution of the Work otherwise complies with
|
|
||||||
the conditions stated in this License.
|
|
||||||
|
|
||||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
||||||
any Contribution intentionally submitted for inclusion in the Work
|
|
||||||
by You to the Licensor shall be under the terms and conditions of
|
|
||||||
this License, without any additional terms or conditions.
|
|
||||||
Notwithstanding the above, nothing herein shall supersede or modify
|
|
||||||
the terms of any separate license agreement you may have executed
|
|
||||||
with Licensor regarding such Contributions.
|
|
||||||
|
|
||||||
6. Trademarks. This License does not grant permission to use the trade
|
|
||||||
names, trademarks, service marks, or product names of the Licensor,
|
|
||||||
except as required for reasonable and customary use in describing the
|
|
||||||
origin of the Work and reproducing the content of the NOTICE file.
|
|
||||||
|
|
||||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
||||||
agreed to in writing, Licensor provides the Work (and each
|
|
||||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
implied, including, without limitation, any warranties or conditions
|
|
||||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
||||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
||||||
appropriateness of using or redistributing the Work and assume any
|
|
||||||
risks associated with Your exercise of permissions under this License.
|
|
||||||
|
|
||||||
8. Limitation of Liability. In no event and under no legal theory,
|
|
||||||
whether in tort (including negligence), contract, or otherwise,
|
|
||||||
unless required by applicable law (such as deliberate and grossly
|
|
||||||
negligent acts) or agreed to in writing, shall any Contributor be
|
|
||||||
liable to You for damages, including any direct, indirect, special,
|
|
||||||
incidental, or consequential damages of any character arising as a
|
|
||||||
result of this License or out of the use or inability to use the
|
|
||||||
Work (including but not limited to damages for loss of goodwill,
|
|
||||||
work stoppage, computer failure or malfunction, or any and all
|
|
||||||
other commercial damages or losses), even if such Contributor
|
|
||||||
has been advised of the possibility of such damages.
|
|
||||||
|
|
||||||
9. Accepting Warranty or Additional Liability. While redistributing
|
|
||||||
the Work or Derivative Works thereof, You may choose to offer,
|
|
||||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
||||||
or other liability obligations and/or rights consistent with this
|
|
||||||
License. However, in accepting such obligations, You may act only
|
|
||||||
on Your own behalf and on Your sole responsibility, not on behalf
|
|
||||||
of any other Contributor, and only if You agree to indemnify,
|
|
||||||
defend, and hold each Contributor harmless for any liability
|
|
||||||
incurred by, or claims asserted against, such Contributor by reason
|
|
||||||
of your accepting any such warranty or additional liability.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
APPENDIX: How to apply the Apache License to your work.
|
|
||||||
|
|
||||||
To apply the Apache License to your work, attach the following
|
|
||||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
|
||||||
replaced with your own identifying information. (Don't include
|
|
||||||
the brackets!) The text should be enclosed in the appropriate
|
|
||||||
comment syntax for the file format. We also recommend that a
|
|
||||||
file or class name and description of purpose be included on the
|
|
||||||
same "printed page" as the copyright notice for easier
|
|
||||||
identification within third-party archives.
|
|
||||||
|
|
||||||
Copyright {yyyy} {name of copyright owner}
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
|
|
103
vendor/github.com/apcera/termtables/README.md
generated
vendored
103
vendor/github.com/apcera/termtables/README.md
generated
vendored
@ -1,103 +0,0 @@
|
|||||||
# Termtables
|
|
||||||
|
|
||||||
[![Build Status](https://travis-ci.org/apcera/termtables.svg?branch=master)](https://travis-ci.org/apcera/termtables)
|
|
||||||
|
|
||||||
A [Go](http://golang.org) port of the Ruby library [terminal-tables](https://github.com/visionmedia/terminal-table) for
|
|
||||||
fast and simple ASCII table generation.
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
```bash
|
|
||||||
go get github.com/apcera/termtables
|
|
||||||
```
|
|
||||||
|
|
||||||
## Go Style Documentation
|
|
||||||
|
|
||||||
[http://godoc.org/github.com/apcera/termtables](http://godoc.org/github.com/apcera/termtables)
|
|
||||||
|
|
||||||
## APC Command Line usage
|
|
||||||
|
|
||||||
`--markdown` — output a markdown table, e.g. `apc app list --markdown`
|
|
||||||
|
|
||||||
`--html` — output an html table, e.g. `apc app list --html`
|
|
||||||
|
|
||||||
`--ascii` — output an ascii table, e.g. `apc app list --ascii`
|
|
||||||
|
|
||||||
## Basic Usage
|
|
||||||
|
|
||||||
```go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/apcera/termtables"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
table := termtables.CreateTable()
|
|
||||||
|
|
||||||
table.AddHeaders("Name", "Age")
|
|
||||||
table.AddRow("John", "30")
|
|
||||||
table.AddRow("Sam", 18)
|
|
||||||
table.AddRow("Julie", 20.14)
|
|
||||||
|
|
||||||
fmt.Println(table.Render())
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Result:
|
|
||||||
|
|
||||||
```
|
|
||||||
+-------+-------+
|
|
||||||
| Name | Age |
|
|
||||||
+-------+-------+
|
|
||||||
| John | 30 |
|
|
||||||
| Sam | 18 |
|
|
||||||
| Julie | 20.14 |
|
|
||||||
+-------+-------+
|
|
||||||
```
|
|
||||||
|
|
||||||
## Advanced Usage
|
|
||||||
|
|
||||||
The package function-call `EnableUTF8()` will cause any tables created after
|
|
||||||
that point to use Unicode box-drawing characters for the table lines.
|
|
||||||
|
|
||||||
Calling `EnableUTF8PerLocale()` uses the C library's locale functionality to
|
|
||||||
determine if the current locale environment variables say that the current
|
|
||||||
character map is UTF-8. If, and only if, so, then `EnableUTF8()` will be
|
|
||||||
called.
|
|
||||||
|
|
||||||
Calling `SetModeHTML(true)` will cause any tables created after that point
|
|
||||||
to be emitted in HTML, while `SetModeMarkdown(true)` will trigger Markdown.
|
|
||||||
Neither should result in changes to later API to get the different results;
|
|
||||||
the primary intended use-case is extracting the same table, but for
|
|
||||||
documentation.
|
|
||||||
|
|
||||||
The table method `.AddSeparator()` inserts a rule line in the output. This
|
|
||||||
only applies in normal terminal output mode.
|
|
||||||
|
|
||||||
The table method `.AddTitle()` adds a title to the table; in terminal output,
|
|
||||||
this is an initial row; in HTML, it's a caption. In Markdown, it's a line of
|
|
||||||
text before the table, prefixed by `Table: `.
|
|
||||||
|
|
||||||
The table method `.SetAlign()` takes an alignment and a column number
|
|
||||||
(indexing starts at 1) and changes all _current_ cells in that column to have
|
|
||||||
the given alignment. It does not change the alignment of cells added to the
|
|
||||||
table after this call. Alignment is only stored on a per-cell basis.
|
|
||||||
|
|
||||||
## Known Issues
|
|
||||||
|
|
||||||
Normal output:
|
|
||||||
|
|
||||||
* `.SetAlign()` does not affect headers.
|
|
||||||
|
|
||||||
Markdown output mode:
|
|
||||||
|
|
||||||
* When emitting Markdown, the column markers are not re-flowed if a vertical
|
|
||||||
bar is an element of a cell, causing an escape to take place; since Markdown
|
|
||||||
is often converted to HTML, this only affects text viewing.
|
|
||||||
* A title in Markdown is not escaped against all possible forms of Markdown
|
|
||||||
markup (to avoid adding a dependency upon a Markdown library, as supported
|
|
||||||
syntax can vary).
|
|
||||||
* Markdown requires headers, so a dummy header will be inserted if needed.
|
|
||||||
* Table alignment is not reflected in Markdown output.
|
|
168
vendor/github.com/apcera/termtables/cell.go
generated
vendored
168
vendor/github.com/apcera/termtables/cell.go
generated
vendored
@ -1,168 +0,0 @@
|
|||||||
// Copyright 2012 Apcera Inc. All rights reserved.
|
|
||||||
|
|
||||||
package termtables
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"math"
|
|
||||||
"regexp"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"unicode/utf8"
|
|
||||||
|
|
||||||
runewidth "github.com/mattn/go-runewidth"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// Must match SGR escape sequence, which is "CSI Pm m", where the Control
|
|
||||||
// Sequence Introducer (CSI) is "ESC ["; where Pm is "A multiple numeric
|
|
||||||
// parameter composed of any number of single numeric parameters, separated
|
|
||||||
// by ; character(s). Individual values for the parameters are listed with
|
|
||||||
// Ps" and where Ps is A single (usually optional) numeric parameter,
|
|
||||||
// composed of one of [sic] more digits."
|
|
||||||
//
|
|
||||||
// In practice, the end sequence is usually given as \e[0m but reading that
|
|
||||||
// definition, it's clear that the 0 is optional and some testing confirms
|
|
||||||
// that it is certainly optional with MacOS Terminal 2.3, so we need to
|
|
||||||
// support the string \e[m as a terminator too.
|
|
||||||
colorFilter = regexp.MustCompile(`\033\[(?:\d+(?:;\d+)*)?m`)
|
|
||||||
)
|
|
||||||
|
|
||||||
// A Cell denotes one cell of a table; it spans one row and a variable number
|
|
||||||
// of columns. A given Cell can only be used at one place in a table; the act
|
|
||||||
// of adding the Cell to the table mutates it with position information, so
|
|
||||||
// do not create one "const" Cell to add it multiple times.
|
|
||||||
type Cell struct {
|
|
||||||
column int
|
|
||||||
formattedValue string
|
|
||||||
alignment *tableAlignment
|
|
||||||
colSpan int
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateCell returns a Cell where the content is the supplied value, with the
|
|
||||||
// optional supplied style (which may be given as nil). The style can include
|
|
||||||
// a non-zero ColSpan to cause the cell to become column-spanning. Changing
|
|
||||||
// the style afterwards will not adjust the column-spanning state of the cell
|
|
||||||
// itself.
|
|
||||||
func CreateCell(v interface{}, style *CellStyle) *Cell {
|
|
||||||
return createCell(0, v, style)
|
|
||||||
}
|
|
||||||
|
|
||||||
func createCell(column int, v interface{}, style *CellStyle) *Cell {
|
|
||||||
cell := &Cell{column: column, formattedValue: renderValue(v), colSpan: 1}
|
|
||||||
if style != nil {
|
|
||||||
cell.alignment = &style.Alignment
|
|
||||||
if style.ColSpan != 0 {
|
|
||||||
cell.colSpan = style.ColSpan
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return cell
|
|
||||||
}
|
|
||||||
|
|
||||||
// Width returns the width of the content of the cell, measured in runes as best
|
|
||||||
// as possible considering sophisticated Unicode.
|
|
||||||
func (c *Cell) Width() int {
|
|
||||||
return runewidth.StringWidth(filterColorCodes(c.formattedValue))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Filter out terminal bold/color sequences in a string.
|
|
||||||
// This supports only basic bold/color escape sequences.
|
|
||||||
func filterColorCodes(s string) string {
|
|
||||||
return colorFilter.ReplaceAllString(s, "")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Render returns a string representing the content of the cell, together with
|
|
||||||
// padding (to the widths specified) and handling any alignment.
|
|
||||||
func (c *Cell) Render(style *renderStyle) (buffer string) {
|
|
||||||
// if no alignment is set, import the table's default
|
|
||||||
if c.alignment == nil {
|
|
||||||
c.alignment = &style.Alignment
|
|
||||||
}
|
|
||||||
|
|
||||||
// left padding
|
|
||||||
buffer += strings.Repeat(" ", style.PaddingLeft)
|
|
||||||
|
|
||||||
// append the main value and handle alignment
|
|
||||||
buffer += c.alignCell(style)
|
|
||||||
|
|
||||||
// right padding
|
|
||||||
buffer += strings.Repeat(" ", style.PaddingRight)
|
|
||||||
|
|
||||||
// this handles escaping for, eg, Markdown, where we don't care about the
|
|
||||||
// alignment quite as much
|
|
||||||
if style.replaceContent != nil {
|
|
||||||
buffer = style.replaceContent(buffer)
|
|
||||||
}
|
|
||||||
|
|
||||||
return buffer
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Cell) alignCell(style *renderStyle) string {
|
|
||||||
buffer := ""
|
|
||||||
width := style.CellWidth(c.column)
|
|
||||||
|
|
||||||
if c.colSpan > 1 {
|
|
||||||
for i := 1; i < c.colSpan; i++ {
|
|
||||||
w := style.CellWidth(c.column + i)
|
|
||||||
if w == 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
width += style.PaddingLeft + w + style.PaddingRight + utf8.RuneCountInString(style.BorderY)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch *c.alignment {
|
|
||||||
|
|
||||||
default:
|
|
||||||
buffer += c.formattedValue
|
|
||||||
if l := width - c.Width(); l > 0 {
|
|
||||||
buffer += strings.Repeat(" ", l)
|
|
||||||
}
|
|
||||||
|
|
||||||
case AlignLeft:
|
|
||||||
buffer += c.formattedValue
|
|
||||||
if l := width - c.Width(); l > 0 {
|
|
||||||
buffer += strings.Repeat(" ", l)
|
|
||||||
}
|
|
||||||
|
|
||||||
case AlignRight:
|
|
||||||
if l := width - c.Width(); l > 0 {
|
|
||||||
buffer += strings.Repeat(" ", l)
|
|
||||||
}
|
|
||||||
buffer += c.formattedValue
|
|
||||||
|
|
||||||
case AlignCenter:
|
|
||||||
left, right := 0, 0
|
|
||||||
if l := width - c.Width(); l > 0 {
|
|
||||||
lf := float64(l)
|
|
||||||
left = int(math.Floor(lf / 2))
|
|
||||||
right = int(math.Ceil(lf / 2))
|
|
||||||
}
|
|
||||||
buffer += strings.Repeat(" ", left)
|
|
||||||
buffer += c.formattedValue
|
|
||||||
buffer += strings.Repeat(" ", right)
|
|
||||||
}
|
|
||||||
|
|
||||||
return buffer
|
|
||||||
}
|
|
||||||
|
|
||||||
// Format the raw value as a string depending on the type
|
|
||||||
func renderValue(v interface{}) string {
|
|
||||||
switch vv := v.(type) {
|
|
||||||
case string:
|
|
||||||
return vv
|
|
||||||
case bool:
|
|
||||||
return strconv.FormatBool(vv)
|
|
||||||
case int:
|
|
||||||
return strconv.Itoa(vv)
|
|
||||||
case int64:
|
|
||||||
return strconv.FormatInt(vv, 10)
|
|
||||||
case uint64:
|
|
||||||
return strconv.FormatUint(vv, 10)
|
|
||||||
case float64:
|
|
||||||
return strconv.FormatFloat(vv, 'f', 2, 64)
|
|
||||||
case fmt.Stringer:
|
|
||||||
return vv.String()
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("%v", v)
|
|
||||||
}
|
|
113
vendor/github.com/apcera/termtables/cell_test.go
generated
vendored
113
vendor/github.com/apcera/termtables/cell_test.go
generated
vendored
@ -1,113 +0,0 @@
|
|||||||
// Copyright 2012-2015 Apcera Inc. All rights reserved.
|
|
||||||
|
|
||||||
package termtables
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestCellRenderString(t *testing.T) {
|
|
||||||
style := &renderStyle{TableStyle: TableStyle{}, cellWidths: map[int]int{}}
|
|
||||||
cell := createCell(0, "foobar", nil)
|
|
||||||
|
|
||||||
output := cell.Render(style)
|
|
||||||
if output != "foobar" {
|
|
||||||
t.Fatal("Unexpected output:", output)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCellRenderBool(t *testing.T) {
|
|
||||||
style := &renderStyle{TableStyle: TableStyle{}, cellWidths: map[int]int{}}
|
|
||||||
cell := createCell(0, true, nil)
|
|
||||||
|
|
||||||
output := cell.Render(style)
|
|
||||||
if output != "true" {
|
|
||||||
t.Fatal("Unexpected output:", output)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCellRenderInteger(t *testing.T) {
|
|
||||||
style := &renderStyle{TableStyle: TableStyle{}, cellWidths: map[int]int{}}
|
|
||||||
cell := createCell(0, 12345, nil)
|
|
||||||
|
|
||||||
output := cell.Render(style)
|
|
||||||
if output != "12345" {
|
|
||||||
t.Fatal("Unexpected output:", output)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCellRenderFloat(t *testing.T) {
|
|
||||||
style := &renderStyle{TableStyle: TableStyle{}, cellWidths: map[int]int{}}
|
|
||||||
cell := createCell(0, 12.345, nil)
|
|
||||||
|
|
||||||
output := cell.Render(style)
|
|
||||||
if output != "12.35" {
|
|
||||||
t.Fatal("Unexpected output:", output)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCellRenderPadding(t *testing.T) {
|
|
||||||
style := &renderStyle{TableStyle: TableStyle{PaddingLeft: 3, PaddingRight: 4}, cellWidths: map[int]int{}}
|
|
||||||
|
|
||||||
cell := createCell(0, "foobar", nil)
|
|
||||||
|
|
||||||
output := cell.Render(style)
|
|
||||||
if output != " foobar " {
|
|
||||||
t.Fatal("Unexpected output:", output)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type foo struct {
|
|
||||||
v string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *foo) String() string {
|
|
||||||
return f.v
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCellRenderStringerStruct(t *testing.T) {
|
|
||||||
style := &renderStyle{TableStyle: TableStyle{}, cellWidths: map[int]int{}}
|
|
||||||
cell := createCell(0, &foo{v: "bar"}, nil)
|
|
||||||
|
|
||||||
output := cell.Render(style)
|
|
||||||
if output != "bar" {
|
|
||||||
t.Fatal("Unexpected output:", output)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type fooString string
|
|
||||||
|
|
||||||
func TestCellRenderGeneric(t *testing.T) {
|
|
||||||
style := &renderStyle{TableStyle: TableStyle{}, cellWidths: map[int]int{}}
|
|
||||||
cell := createCell(0, fooString("baz"), nil)
|
|
||||||
|
|
||||||
output := cell.Render(style)
|
|
||||||
if output != "baz" {
|
|
||||||
t.Fatal("Unexpected output:", output)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFilterColorCodes(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
in string
|
|
||||||
out string
|
|
||||||
}{
|
|
||||||
{"abc", "abc"},
|
|
||||||
{"", ""},
|
|
||||||
{"\033[31m\033[0m", ""},
|
|
||||||
{"a\033[31mb\033[0mc", "abc"},
|
|
||||||
{"\033[31mabc\033[0m", "abc"},
|
|
||||||
{"\033[31mfoo\033[0mbar", "foobar"},
|
|
||||||
{"\033[31mfoo\033[mbar", "foobar"},
|
|
||||||
{"\033[31mfoo\033[0;0mbar", "foobar"},
|
|
||||||
{"\033[31;4mfoo\033[0mbar", "foobar"},
|
|
||||||
{"\033[31;4;43mfoo\033[0mbar", "foobar"},
|
|
||||||
}
|
|
||||||
for _, test := range tests {
|
|
||||||
got := filterColorCodes(test.in)
|
|
||||||
if got != test.out {
|
|
||||||
t.Errorf("Invalid color-code filter result; expected %q but got %q from input %q",
|
|
||||||
test.out, got, test.in)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
107
vendor/github.com/apcera/termtables/html.go
generated
vendored
107
vendor/github.com/apcera/termtables/html.go
generated
vendored
@ -1,107 +0,0 @@
|
|||||||
// Copyright 2013 Apcera Inc. All rights reserved.
|
|
||||||
|
|
||||||
package termtables
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"html"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
type titleStyle int
|
|
||||||
|
|
||||||
const (
|
|
||||||
TitleAsCaption titleStyle = iota
|
|
||||||
TitleAsThSpan
|
|
||||||
)
|
|
||||||
|
|
||||||
// htmlStyleRules defines attributes which we can use, and might be set on a
|
|
||||||
// table by accessors, to influence the type of HTML which is output.
|
|
||||||
type htmlStyleRules struct {
|
|
||||||
title titleStyle
|
|
||||||
}
|
|
||||||
|
|
||||||
// HTML returns an HTML representations of the contents of one row of a table.
|
|
||||||
func (r *Row) HTML(tag string, style *renderStyle) string {
|
|
||||||
attrs := make([]string, len(r.cells))
|
|
||||||
elems := make([]string, len(r.cells))
|
|
||||||
for i := range r.cells {
|
|
||||||
if r.cells[i].alignment != nil {
|
|
||||||
switch *r.cells[i].alignment {
|
|
||||||
case AlignLeft:
|
|
||||||
attrs[i] = " align='left'"
|
|
||||||
case AlignCenter:
|
|
||||||
attrs[i] = " align='center'"
|
|
||||||
case AlignRight:
|
|
||||||
attrs[i] = " align='right'"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
elems[i] = html.EscapeString(strings.TrimSpace(r.cells[i].Render(style)))
|
|
||||||
}
|
|
||||||
// WAG as to max capacity, plus a bit
|
|
||||||
buf := bytes.NewBuffer(make([]byte, 0, 8192))
|
|
||||||
buf.WriteString("<tr>")
|
|
||||||
for i := range elems {
|
|
||||||
fmt.Fprintf(buf, "<%s%s>%s</%s>", tag, attrs[i], elems[i], tag)
|
|
||||||
}
|
|
||||||
buf.WriteString("</tr>\n")
|
|
||||||
return buf.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
func generateHtmlTitleRow(title interface{}, t *Table, style *renderStyle) string {
|
|
||||||
elContent := html.EscapeString(
|
|
||||||
strings.TrimSpace(CreateCell(t.title, &CellStyle{}).Render(style)),
|
|
||||||
)
|
|
||||||
|
|
||||||
switch style.htmlRules.title {
|
|
||||||
case TitleAsCaption:
|
|
||||||
return "<caption>" + elContent + "</caption>\n"
|
|
||||||
case TitleAsThSpan:
|
|
||||||
return fmt.Sprintf("<tr><th style=\"text-align: center\" colspan=\"%d\">%s</th></tr>\n",
|
|
||||||
style.columns, elContent)
|
|
||||||
default:
|
|
||||||
return "<!-- " + elContent + " -->"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// RenderHTML returns a string representation of a the table, suitable for
|
|
||||||
// inclusion as HTML elsewhere. Primary use-case controlling layout style
|
|
||||||
// is for inclusion into Markdown documents, documenting normal table use.
|
|
||||||
// Thus we leave the padding in place to have columns align when viewed as
|
|
||||||
// plain text and rely upon HTML ignoring extra whitespace.
|
|
||||||
func (t *Table) RenderHTML() (buffer string) {
|
|
||||||
// elements is already populated with row data
|
|
||||||
|
|
||||||
// generate the runtime style
|
|
||||||
style := createRenderStyle(t)
|
|
||||||
style.PaddingLeft = 0
|
|
||||||
style.PaddingRight = 0
|
|
||||||
|
|
||||||
// TODO: control CSS styles to suppress border based upon t.Style.SkipBorder
|
|
||||||
rowsText := make([]string, 0, len(t.elements)+6)
|
|
||||||
|
|
||||||
if t.title != nil || t.headers != nil {
|
|
||||||
rowsText = append(rowsText, "<thead>\n")
|
|
||||||
if t.title != nil {
|
|
||||||
rowsText = append(rowsText, generateHtmlTitleRow(t.title, t, style))
|
|
||||||
}
|
|
||||||
if t.headers != nil {
|
|
||||||
rowsText = append(rowsText, CreateRow(t.headers).HTML("th", style))
|
|
||||||
}
|
|
||||||
rowsText = append(rowsText, "</thead>\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
rowsText = append(rowsText, "<tbody>\n")
|
|
||||||
// loop over the elements and render them
|
|
||||||
for i := range t.elements {
|
|
||||||
if row, ok := t.elements[i].(*Row); ok {
|
|
||||||
rowsText = append(rowsText, row.HTML("td", style))
|
|
||||||
} else {
|
|
||||||
rowsText = append(rowsText, fmt.Sprintf("<!-- unable to render line %d, unhandled type -->\n", i))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rowsText = append(rowsText, "</tbody>\n")
|
|
||||||
|
|
||||||
return "<table class=\"termtable\">\n" + strings.Join(rowsText, "") + "</table>\n"
|
|
||||||
}
|
|
222
vendor/github.com/apcera/termtables/html_test.go
generated
vendored
222
vendor/github.com/apcera/termtables/html_test.go
generated
vendored
@ -1,222 +0,0 @@
|
|||||||
// Copyright 2013 Apcera Inc. All rights reserved.
|
|
||||||
|
|
||||||
package termtables
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestCreateTableHTML(t *testing.T) {
|
|
||||||
expected := "<table class=\"termtable\">\n" +
|
|
||||||
"<thead>\n" +
|
|
||||||
"<tr><th>Name</th><th>Value</th></tr>\n" +
|
|
||||||
"</thead>\n" +
|
|
||||||
"<tbody>\n" +
|
|
||||||
"<tr><td>hey</td><td>you</td></tr>\n" +
|
|
||||||
"<tr><td>ken</td><td>1234</td></tr>\n" +
|
|
||||||
"<tr><td>derek</td><td>3.14</td></tr>\n" +
|
|
||||||
"<tr><td>derek too</td><td>3.15</td></tr>\n" +
|
|
||||||
"</tbody>\n" +
|
|
||||||
"</table>\n"
|
|
||||||
|
|
||||||
table := CreateTable()
|
|
||||||
table.SetModeHTML()
|
|
||||||
|
|
||||||
table.AddHeaders("Name", "Value")
|
|
||||||
table.AddRow("hey", "you")
|
|
||||||
table.AddRow("ken", 1234)
|
|
||||||
table.AddRow("derek", 3.14)
|
|
||||||
table.AddRow("derek too", 3.1456788)
|
|
||||||
|
|
||||||
output := table.Render()
|
|
||||||
if output != expected {
|
|
||||||
t.Fatal(DisplayFailedOutput(output, expected))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTableWithHeaderHTML(t *testing.T) {
|
|
||||||
expected := "<table class=\"termtable\">\n" +
|
|
||||||
"<thead>\n" +
|
|
||||||
"<caption>Example</caption>\n" +
|
|
||||||
"<tr><th>Name</th><th>Value</th></tr>\n" +
|
|
||||||
"</thead>\n" +
|
|
||||||
"<tbody>\n" +
|
|
||||||
"<tr><td>hey</td><td>you</td></tr>\n" +
|
|
||||||
"<tr><td>ken</td><td>1234</td></tr>\n" +
|
|
||||||
"<tr><td>derek</td><td>3.14</td></tr>\n" +
|
|
||||||
"<tr><td>derek too</td><td>3.15</td></tr>\n" +
|
|
||||||
"</tbody>\n" +
|
|
||||||
"</table>\n"
|
|
||||||
|
|
||||||
table := CreateTable()
|
|
||||||
table.SetModeHTML()
|
|
||||||
|
|
||||||
table.AddTitle("Example")
|
|
||||||
table.AddHeaders("Name", "Value")
|
|
||||||
table.AddRow("hey", "you")
|
|
||||||
table.AddRow("ken", 1234)
|
|
||||||
table.AddRow("derek", 3.14)
|
|
||||||
table.AddRow("derek too", 3.1456788)
|
|
||||||
|
|
||||||
output := table.Render()
|
|
||||||
if output != expected {
|
|
||||||
t.Fatal(DisplayFailedOutput(output, expected))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTableTitleWidthAdjustsHTML(t *testing.T) {
|
|
||||||
expected := "<table class=\"termtable\">\n" +
|
|
||||||
"<thead>\n" +
|
|
||||||
"<caption>Example My Foo Bar'd Test</caption>\n" +
|
|
||||||
"<tr><th>Name</th><th>Value</th></tr>\n" +
|
|
||||||
"</thead>\n" +
|
|
||||||
"<tbody>\n" +
|
|
||||||
"<tr><td>hey</td><td>you</td></tr>\n" +
|
|
||||||
"<tr><td>ken</td><td>1234</td></tr>\n" +
|
|
||||||
"<tr><td>derek</td><td>3.14</td></tr>\n" +
|
|
||||||
"<tr><td>derek too</td><td>3.15</td></tr>\n" +
|
|
||||||
"</tbody>\n" +
|
|
||||||
"</table>\n"
|
|
||||||
|
|
||||||
table := CreateTable()
|
|
||||||
table.SetModeHTML()
|
|
||||||
|
|
||||||
table.AddTitle("Example My Foo Bar'd Test")
|
|
||||||
table.AddHeaders("Name", "Value")
|
|
||||||
table.AddRow("hey", "you")
|
|
||||||
table.AddRow("ken", 1234)
|
|
||||||
table.AddRow("derek", 3.14)
|
|
||||||
table.AddRow("derek too", 3.1456788)
|
|
||||||
|
|
||||||
output := table.Render()
|
|
||||||
if output != expected {
|
|
||||||
t.Fatal(DisplayFailedOutput(output, expected))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTableWithNoHeadersHTML(t *testing.T) {
|
|
||||||
expected := "<table class=\"termtable\">\n" +
|
|
||||||
"<tbody>\n" +
|
|
||||||
"<tr><td>hey</td><td>you</td></tr>\n" +
|
|
||||||
"<tr><td>ken</td><td>1234</td></tr>\n" +
|
|
||||||
"<tr><td>derek</td><td>3.14</td></tr>\n" +
|
|
||||||
"<tr><td>derek too</td><td>3.15</td></tr>\n" +
|
|
||||||
"</tbody>\n" +
|
|
||||||
"</table>\n"
|
|
||||||
|
|
||||||
table := CreateTable()
|
|
||||||
table.SetModeHTML()
|
|
||||||
|
|
||||||
table.AddRow("hey", "you")
|
|
||||||
table.AddRow("ken", 1234)
|
|
||||||
table.AddRow("derek", 3.14)
|
|
||||||
table.AddRow("derek too", 3.1456788)
|
|
||||||
|
|
||||||
output := table.Render()
|
|
||||||
if output != expected {
|
|
||||||
t.Fatal(DisplayFailedOutput(output, expected))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTableUnicodeWidthsHTML(t *testing.T) {
|
|
||||||
expected := "<table class=\"termtable\">\n" +
|
|
||||||
"<thead>\n" +
|
|
||||||
"<tr><th>Name</th><th>Cost</th></tr>\n" +
|
|
||||||
"</thead>\n" +
|
|
||||||
"<tbody>\n" +
|
|
||||||
"<tr><td>Currency</td><td>¤10</td></tr>\n" +
|
|
||||||
"<tr><td>US Dollar</td><td>$30</td></tr>\n" +
|
|
||||||
"<tr><td>Euro</td><td>€27</td></tr>\n" +
|
|
||||||
"<tr><td>Thai</td><td>฿70</td></tr>\n" +
|
|
||||||
"</tbody>\n" +
|
|
||||||
"</table>\n"
|
|
||||||
|
|
||||||
table := CreateTable()
|
|
||||||
table.SetModeHTML()
|
|
||||||
table.AddHeaders("Name", "Cost")
|
|
||||||
table.AddRow("Currency", "¤10")
|
|
||||||
table.AddRow("US Dollar", "$30")
|
|
||||||
table.AddRow("Euro", "€27")
|
|
||||||
table.AddRow("Thai", "฿70")
|
|
||||||
|
|
||||||
output := table.Render()
|
|
||||||
if output != expected {
|
|
||||||
t.Fatal(DisplayFailedOutput(output, expected))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTableWithAlignment(t *testing.T) {
|
|
||||||
expected := "<table class=\"termtable\">\n" +
|
|
||||||
"<thead>\n" +
|
|
||||||
"<tr><th>Foo</th><th>Bar</th></tr>\n" +
|
|
||||||
"</thead>\n" +
|
|
||||||
"<tbody>\n" +
|
|
||||||
"<tr><td>humpty</td><td>dumpty</td></tr>\n" +
|
|
||||||
"<tr><td align='right'>r</td><td><- on right</td></tr>\n" +
|
|
||||||
"</tbody>\n" +
|
|
||||||
"</table>\n"
|
|
||||||
|
|
||||||
table := CreateTable()
|
|
||||||
table.SetModeHTML()
|
|
||||||
table.AddHeaders("Foo", "Bar")
|
|
||||||
table.AddRow("humpty", "dumpty")
|
|
||||||
table.AddRow(CreateCell("r", &CellStyle{Alignment: AlignRight}), "<- on right")
|
|
||||||
|
|
||||||
output := table.Render()
|
|
||||||
if output != expected {
|
|
||||||
t.Fatal(DisplayFailedOutput(output, expected))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTableAfterSetAlign(t *testing.T) {
|
|
||||||
expected := "<table class=\"termtable\">\n" +
|
|
||||||
"<thead>\n" +
|
|
||||||
"<tr><th>Alphabetical</th><th>Num</th></tr>\n" +
|
|
||||||
"</thead>\n" +
|
|
||||||
"<tbody>\n" +
|
|
||||||
"<tr><td align='right'>alfa</td><td>1</td></tr>\n" +
|
|
||||||
"<tr><td align='right'>bravo</td><td>2</td></tr>\n" +
|
|
||||||
"<tr><td align='right'>charlie</td><td>3</td></tr>\n" +
|
|
||||||
"</tbody>\n" +
|
|
||||||
"</table>\n"
|
|
||||||
|
|
||||||
table := CreateTable()
|
|
||||||
table.SetModeHTML()
|
|
||||||
table.AddHeaders("Alphabetical", "Num")
|
|
||||||
table.AddRow("alfa", 1)
|
|
||||||
table.AddRow("bravo", 2)
|
|
||||||
table.AddRow("charlie", 3)
|
|
||||||
table.SetAlign(AlignRight, 1)
|
|
||||||
|
|
||||||
output := table.Render()
|
|
||||||
if output != expected {
|
|
||||||
t.Fatal(DisplayFailedOutput(output, expected))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTableWithAltTitleStyle(t *testing.T) {
|
|
||||||
expected := "" +
|
|
||||||
"<table class=\"termtable\">\n" +
|
|
||||||
"<thead>\n" +
|
|
||||||
"<tr><th style=\"text-align: center\" colspan=\"3\">Metasyntactic</th></tr>\n" +
|
|
||||||
"<tr><th>Foo</th><th>Bar</th><th>Baz</th></tr>\n" +
|
|
||||||
"</thead>\n" +
|
|
||||||
"<tbody>\n" +
|
|
||||||
"<tr><td>a</td><td>b</td><td>c</td></tr>\n" +
|
|
||||||
"<tr><td>α</td><td>β</td><td>γ</td></tr>\n" +
|
|
||||||
"</tbody>\n" +
|
|
||||||
"</table>\n"
|
|
||||||
|
|
||||||
table := CreateTable()
|
|
||||||
table.SetModeHTML()
|
|
||||||
table.SetHTMLStyleTitle(TitleAsThSpan)
|
|
||||||
table.AddTitle("Metasyntactic")
|
|
||||||
table.AddHeaders("Foo", "Bar", "Baz")
|
|
||||||
table.AddRow("a", "b", "c")
|
|
||||||
table.AddRow("α", "β", "γ")
|
|
||||||
|
|
||||||
output := table.Render()
|
|
||||||
if output != expected {
|
|
||||||
t.Fatal(DisplayFailedOutput(output, expected))
|
|
||||||
}
|
|
||||||
}
|
|
47
vendor/github.com/apcera/termtables/row.go
generated
vendored
47
vendor/github.com/apcera/termtables/row.go
generated
vendored
@ -1,47 +0,0 @@
|
|||||||
// Copyright 2012 Apcera Inc. All rights reserved.
|
|
||||||
|
|
||||||
package termtables
|
|
||||||
|
|
||||||
import "strings"
|
|
||||||
|
|
||||||
// A Row represents one row of a Table, consisting of some number of Cell
|
|
||||||
// items.
|
|
||||||
type Row struct {
|
|
||||||
cells []*Cell
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateRow returns a Row where the cells are created as needed to hold each
|
|
||||||
// item given; each item can be a Cell or content to go into a Cell created
|
|
||||||
// to hold it.
|
|
||||||
func CreateRow(items []interface{}) *Row {
|
|
||||||
row := &Row{cells: []*Cell{}}
|
|
||||||
for _, item := range items {
|
|
||||||
row.AddCell(item)
|
|
||||||
}
|
|
||||||
return row
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddCell adds one item to a row as a new cell, where the item is either a
|
|
||||||
// Cell or content to be put into a cell.
|
|
||||||
func (r *Row) AddCell(item interface{}) {
|
|
||||||
if c, ok := item.(*Cell); ok {
|
|
||||||
c.column = len(r.cells)
|
|
||||||
r.cells = append(r.cells, c)
|
|
||||||
} else {
|
|
||||||
r.cells = append(r.cells, createCell(len(r.cells), item, nil))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Render returns a string representing the content of one row of a table, where
|
|
||||||
// the Row contains Cells (not Separators) and the representation includes any
|
|
||||||
// vertical borders needed.
|
|
||||||
func (r *Row) Render(style *renderStyle) string {
|
|
||||||
// pre-render and shove into an array... helps with cleanly adding borders
|
|
||||||
renderedCells := []string{}
|
|
||||||
for _, c := range r.cells {
|
|
||||||
renderedCells = append(renderedCells, c.Render(style))
|
|
||||||
}
|
|
||||||
|
|
||||||
// format final output
|
|
||||||
return style.BorderY + strings.Join(renderedCells, style.BorderY) + style.BorderY
|
|
||||||
}
|
|
29
vendor/github.com/apcera/termtables/row_test.go
generated
vendored
29
vendor/github.com/apcera/termtables/row_test.go
generated
vendored
@ -1,29 +0,0 @@
|
|||||||
// Copyright 2012-2015 Apcera Inc. All rights reserved.
|
|
||||||
|
|
||||||
package termtables
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestBasicRowRender(t *testing.T) {
|
|
||||||
row := CreateRow([]interface{}{"foo", "bar"})
|
|
||||||
style := &renderStyle{TableStyle: TableStyle{BorderX: "-", BorderY: "|", BorderI: "+",
|
|
||||||
PaddingLeft: 1, PaddingRight: 1}, cellWidths: map[int]int{0: 3, 1: 3}}
|
|
||||||
|
|
||||||
output := row.Render(style)
|
|
||||||
if output != "| foo | bar |" {
|
|
||||||
t.Fatal("Unexpected output:", output)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRowRenderWidthBasedPadding(t *testing.T) {
|
|
||||||
row := CreateRow([]interface{}{"foo", "bar"})
|
|
||||||
style := &renderStyle{TableStyle: TableStyle{BorderX: "-", BorderY: "|", BorderI: "+",
|
|
||||||
PaddingLeft: 1, PaddingRight: 1}, cellWidths: map[int]int{0: 3, 1: 5}}
|
|
||||||
|
|
||||||
output := row.Render(style)
|
|
||||||
if output != "| foo | bar |" {
|
|
||||||
t.Fatal("Unexpected output:", output)
|
|
||||||
}
|
|
||||||
}
|
|
60
vendor/github.com/apcera/termtables/separator.go
generated
vendored
60
vendor/github.com/apcera/termtables/separator.go
generated
vendored
@ -1,60 +0,0 @@
|
|||||||
// Copyright 2012 Apcera Inc. All rights reserved.
|
|
||||||
|
|
||||||
package termtables
|
|
||||||
|
|
||||||
import "strings"
|
|
||||||
|
|
||||||
type lineType int
|
|
||||||
|
|
||||||
// These lines are for horizontal rules; these indicate desired styling,
|
|
||||||
// but simplistic (pure ASCII) markup characters may end up leaving the
|
|
||||||
// variant lines indistinguishable from LINE_INNER.
|
|
||||||
const (
|
|
||||||
// LINE_INNER *must* be the default; where there are vertical lines drawn
|
|
||||||
// across an inner line, the character at that position should indicate
|
|
||||||
// that the vertical line goes both up and down from this horizontal line.
|
|
||||||
LINE_INNER lineType = iota
|
|
||||||
|
|
||||||
// LINE_TOP has only descenders
|
|
||||||
LINE_TOP
|
|
||||||
|
|
||||||
// LINE_SUBTOP has only descenders in the middle, but goes both up and
|
|
||||||
// down at the far left & right edges.
|
|
||||||
LINE_SUBTOP
|
|
||||||
|
|
||||||
// LINE_BOTTOM has only ascenders.
|
|
||||||
LINE_BOTTOM
|
|
||||||
)
|
|
||||||
|
|
||||||
// A Separator is a horizontal rule line, with associated information which
|
|
||||||
// indicates where in a table it is, sufficient for simple cases to let
|
|
||||||
// clean tables be drawn. If a row-spanning cell is created, then this will
|
|
||||||
// be insufficient: we can get away with hand-waving of "well, it's showing
|
|
||||||
// where the border would be" but a more capable handling will require
|
|
||||||
// structure reworking. Patches welcome.
|
|
||||||
type Separator struct {
|
|
||||||
where lineType
|
|
||||||
}
|
|
||||||
|
|
||||||
// Render returns the string representation of a horizontal rule line in the
|
|
||||||
// table.
|
|
||||||
func (s *Separator) Render(style *renderStyle) string {
|
|
||||||
// loop over getting dashes
|
|
||||||
parts := []string{}
|
|
||||||
for i := 0; i < style.columns; i++ {
|
|
||||||
w := style.PaddingLeft + style.CellWidth(i) + style.PaddingRight
|
|
||||||
parts = append(parts, strings.Repeat(style.BorderX, w))
|
|
||||||
}
|
|
||||||
|
|
||||||
switch s.where {
|
|
||||||
case LINE_TOP:
|
|
||||||
return style.BorderTopLeft + strings.Join(parts, style.BorderTop) + style.BorderTopRight
|
|
||||||
case LINE_SUBTOP:
|
|
||||||
return style.BorderLeft + strings.Join(parts, style.BorderTop) + style.BorderRight
|
|
||||||
case LINE_BOTTOM:
|
|
||||||
return style.BorderBottomLeft + strings.Join(parts, style.BorderBottom) + style.BorderBottomRight
|
|
||||||
case LINE_INNER:
|
|
||||||
return style.BorderLeft + strings.Join(parts, style.BorderI) + style.BorderRight
|
|
||||||
}
|
|
||||||
panic("not reached")
|
|
||||||
}
|
|
36
vendor/github.com/apcera/termtables/straight_separator.go
generated
vendored
36
vendor/github.com/apcera/termtables/straight_separator.go
generated
vendored
@ -1,36 +0,0 @@
|
|||||||
// Copyright 2012 Apcera Inc. All rights reserved.
|
|
||||||
|
|
||||||
package termtables
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
"unicode/utf8"
|
|
||||||
)
|
|
||||||
|
|
||||||
// A StraightSeparator is a horizontal line with associated information about
|
|
||||||
// what sort of position it takes in the table, so as to control which shapes
|
|
||||||
// will be used where vertical lines are expected to touch this horizontal
|
|
||||||
// line.
|
|
||||||
type StraightSeparator struct {
|
|
||||||
where lineType
|
|
||||||
}
|
|
||||||
|
|
||||||
// Render returns a string representing this separator, with all border
|
|
||||||
// crossings appropriately chosen.
|
|
||||||
func (s *StraightSeparator) Render(style *renderStyle) string {
|
|
||||||
// loop over getting dashes
|
|
||||||
width := 0
|
|
||||||
for i := 0; i < style.columns; i++ {
|
|
||||||
width += style.PaddingLeft + style.CellWidth(i) + style.PaddingRight + utf8.RuneCountInString(style.BorderI)
|
|
||||||
}
|
|
||||||
|
|
||||||
switch s.where {
|
|
||||||
case LINE_TOP:
|
|
||||||
return style.BorderTopLeft + strings.Repeat(style.BorderX, width-1) + style.BorderTopRight
|
|
||||||
case LINE_INNER, LINE_SUBTOP:
|
|
||||||
return style.BorderLeft + strings.Repeat(style.BorderX, width-1) + style.BorderRight
|
|
||||||
case LINE_BOTTOM:
|
|
||||||
return style.BorderBottomLeft + strings.Repeat(style.BorderX, width-1) + style.BorderBottomRight
|
|
||||||
}
|
|
||||||
panic("not reached")
|
|
||||||
}
|
|
214
vendor/github.com/apcera/termtables/style.go
generated
vendored
214
vendor/github.com/apcera/termtables/style.go
generated
vendored
@ -1,214 +0,0 @@
|
|||||||
// Copyright 2012-2013 Apcera Inc. All rights reserved.
|
|
||||||
|
|
||||||
package termtables
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
"unicode/utf8"
|
|
||||||
)
|
|
||||||
|
|
||||||
type tableAlignment int
|
|
||||||
|
|
||||||
// These constants control the alignment which should be used when rendering
|
|
||||||
// the content of a cell.
|
|
||||||
const (
|
|
||||||
AlignLeft = tableAlignment(1)
|
|
||||||
AlignCenter = tableAlignment(2)
|
|
||||||
AlignRight = tableAlignment(3)
|
|
||||||
)
|
|
||||||
|
|
||||||
// TableStyle controls styling information for a Table as a whole.
|
|
||||||
//
|
|
||||||
// For the Border rules, only X, Y and I are needed, and all have defaults.
|
|
||||||
// The others will all default to the same as BorderI.
|
|
||||||
type TableStyle struct {
|
|
||||||
SkipBorder bool
|
|
||||||
BorderX string
|
|
||||||
BorderY string
|
|
||||||
BorderI string
|
|
||||||
BorderTop string
|
|
||||||
BorderBottom string
|
|
||||||
BorderRight string
|
|
||||||
BorderLeft string
|
|
||||||
BorderTopLeft string
|
|
||||||
BorderTopRight string
|
|
||||||
BorderBottomLeft string
|
|
||||||
BorderBottomRight string
|
|
||||||
PaddingLeft int
|
|
||||||
PaddingRight int
|
|
||||||
Width int
|
|
||||||
Alignment tableAlignment
|
|
||||||
htmlRules htmlStyleRules
|
|
||||||
}
|
|
||||||
|
|
||||||
// A CellStyle controls all style applicable to one Cell.
|
|
||||||
type CellStyle struct {
|
|
||||||
// Alignment indicates the alignment to be used in rendering the content
|
|
||||||
Alignment tableAlignment
|
|
||||||
|
|
||||||
// ColSpan indicates how many columns this Cell is expected to consume.
|
|
||||||
ColSpan int
|
|
||||||
}
|
|
||||||
|
|
||||||
// DefaultStyle is a TableStyle which can be used to get some simple
|
|
||||||
// default styling for a table, using ASCII characters for drawing borders.
|
|
||||||
var DefaultStyle = &TableStyle{
|
|
||||||
SkipBorder: false,
|
|
||||||
BorderX: "-", BorderY: "|", BorderI: "+",
|
|
||||||
PaddingLeft: 1, PaddingRight: 1,
|
|
||||||
Width: 80,
|
|
||||||
Alignment: AlignLeft,
|
|
||||||
|
|
||||||
// FIXME: the use of a Width here may interact poorly with a changing
|
|
||||||
// MaxColumns value; we don't set MaxColumns here because the evaluation
|
|
||||||
// order of a var and an init value adds undesired subtlety.
|
|
||||||
}
|
|
||||||
|
|
||||||
type renderStyle struct {
|
|
||||||
cellWidths map[int]int
|
|
||||||
columns int
|
|
||||||
|
|
||||||
// used for markdown rendering
|
|
||||||
replaceContent func(string) string
|
|
||||||
|
|
||||||
TableStyle
|
|
||||||
}
|
|
||||||
|
|
||||||
// setUtfBoxStyle changes the border characters to be suitable for use when
|
|
||||||
// the output stream can render UTF-8 characters.
|
|
||||||
func (s *TableStyle) setUtfBoxStyle() {
|
|
||||||
s.BorderX = "─"
|
|
||||||
s.BorderY = "│"
|
|
||||||
s.BorderI = "┼"
|
|
||||||
s.BorderTop = "┬"
|
|
||||||
s.BorderBottom = "┴"
|
|
||||||
s.BorderLeft = "├"
|
|
||||||
s.BorderRight = "┤"
|
|
||||||
s.BorderTopLeft = "╭"
|
|
||||||
s.BorderTopRight = "╮"
|
|
||||||
s.BorderBottomLeft = "╰"
|
|
||||||
s.BorderBottomRight = "╯"
|
|
||||||
}
|
|
||||||
|
|
||||||
// setAsciiBoxStyle changes the border characters back to their defaults
|
|
||||||
func (s *TableStyle) setAsciiBoxStyle() {
|
|
||||||
s.BorderX = "-"
|
|
||||||
s.BorderY = "|"
|
|
||||||
s.BorderI = "+"
|
|
||||||
s.BorderTop, s.BorderBottom, s.BorderLeft, s.BorderRight = "", "", "", ""
|
|
||||||
s.BorderTopLeft, s.BorderTopRight, s.BorderBottomLeft, s.BorderBottomRight = "", "", "", ""
|
|
||||||
s.fillStyleRules()
|
|
||||||
}
|
|
||||||
|
|
||||||
// fillStyleRules populates members of the TableStyle box-drawing specification
|
|
||||||
// with BorderI as the default.
|
|
||||||
func (s *TableStyle) fillStyleRules() {
|
|
||||||
if s.BorderTop == "" {
|
|
||||||
s.BorderTop = s.BorderI
|
|
||||||
}
|
|
||||||
if s.BorderBottom == "" {
|
|
||||||
s.BorderBottom = s.BorderI
|
|
||||||
}
|
|
||||||
if s.BorderLeft == "" {
|
|
||||||
s.BorderLeft = s.BorderI
|
|
||||||
}
|
|
||||||
if s.BorderRight == "" {
|
|
||||||
s.BorderRight = s.BorderI
|
|
||||||
}
|
|
||||||
if s.BorderTopLeft == "" {
|
|
||||||
s.BorderTopLeft = s.BorderI
|
|
||||||
}
|
|
||||||
if s.BorderTopRight == "" {
|
|
||||||
s.BorderTopRight = s.BorderI
|
|
||||||
}
|
|
||||||
if s.BorderBottomLeft == "" {
|
|
||||||
s.BorderBottomLeft = s.BorderI
|
|
||||||
}
|
|
||||||
if s.BorderBottomRight == "" {
|
|
||||||
s.BorderBottomRight = s.BorderI
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func createRenderStyle(table *Table) *renderStyle {
|
|
||||||
style := &renderStyle{TableStyle: *table.Style, cellWidths: map[int]int{}}
|
|
||||||
style.TableStyle.fillStyleRules()
|
|
||||||
|
|
||||||
if table.outputMode == outputMarkdown {
|
|
||||||
style.buildReplaceContent(table.Style.BorderY)
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: handle actually defined width condition
|
|
||||||
|
|
||||||
// loop over the rows and cells to calculate widths
|
|
||||||
for _, element := range table.elements {
|
|
||||||
// skip separators
|
|
||||||
if _, ok := element.(*Separator); ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// iterate over cells
|
|
||||||
if row, ok := element.(*Row); ok {
|
|
||||||
for i, cell := range row.cells {
|
|
||||||
// FIXME: need to support sizing with colspan handling
|
|
||||||
if cell.colSpan > 1 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if style.cellWidths[i] < cell.Width() {
|
|
||||||
style.cellWidths[i] = cell.Width()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
style.columns = len(style.cellWidths)
|
|
||||||
|
|
||||||
// calculate actual width
|
|
||||||
width := utf8.RuneCountInString(style.BorderLeft) // start at '1' for left border
|
|
||||||
internalBorderWidth := utf8.RuneCountInString(style.BorderI)
|
|
||||||
|
|
||||||
lastIndex := 0
|
|
||||||
for i, v := range style.cellWidths {
|
|
||||||
width += v + style.PaddingLeft + style.PaddingRight + internalBorderWidth
|
|
||||||
if i > lastIndex {
|
|
||||||
lastIndex = i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if internalBorderWidth != utf8.RuneCountInString(style.BorderRight) {
|
|
||||||
width += utf8.RuneCountInString(style.BorderRight) - internalBorderWidth
|
|
||||||
}
|
|
||||||
|
|
||||||
if table.titleCell != nil {
|
|
||||||
titleMinWidth := 0 +
|
|
||||||
table.titleCell.Width() +
|
|
||||||
utf8.RuneCountInString(style.BorderLeft) +
|
|
||||||
utf8.RuneCountInString(style.BorderRight) +
|
|
||||||
style.PaddingLeft +
|
|
||||||
style.PaddingRight
|
|
||||||
|
|
||||||
if width < titleMinWidth {
|
|
||||||
// minWidth must be set to include padding of the title, as required
|
|
||||||
style.cellWidths[lastIndex] += (titleMinWidth - width)
|
|
||||||
width = titleMinWidth
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// right border is covered in loop
|
|
||||||
style.Width = width
|
|
||||||
|
|
||||||
return style
|
|
||||||
}
|
|
||||||
|
|
||||||
// CellWidth returns the width of the cell at the supplied index, where the
|
|
||||||
// width is the number of tty character-cells required to draw the glyphs.
|
|
||||||
func (s *renderStyle) CellWidth(i int) int {
|
|
||||||
return s.cellWidths[i]
|
|
||||||
}
|
|
||||||
|
|
||||||
// buildReplaceContent creates a function closure, with minimal bound lexical
|
|
||||||
// state, which replaces content
|
|
||||||
func (s *renderStyle) buildReplaceContent(bad string) {
|
|
||||||
replacement := fmt.Sprintf("&#x%02x;", bad)
|
|
||||||
s.replaceContent = func(old string) string {
|
|
||||||
return strings.Replace(old, bad, replacement, -1)
|
|
||||||
}
|
|
||||||
}
|
|
371
vendor/github.com/apcera/termtables/table.go
generated
vendored
371
vendor/github.com/apcera/termtables/table.go
generated
vendored
@ -1,371 +0,0 @@
|
|||||||
// Copyright 2012-2013 Apcera Inc. All rights reserved.
|
|
||||||
|
|
||||||
package termtables
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"os"
|
|
||||||
"runtime"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/apcera/termtables/term"
|
|
||||||
)
|
|
||||||
|
|
||||||
// MaxColumns represents the maximum number of columns that are available for
|
|
||||||
// display without wrapping around the right-hand side of the terminal window.
|
|
||||||
// At program initialization, the value will be automatically set according
|
|
||||||
// to available sources of information, including the $COLUMNS environment
|
|
||||||
// variable and, on Unix, tty information.
|
|
||||||
var MaxColumns = 80
|
|
||||||
|
|
||||||
// Element the interface that can draw a representation of the contents of a
|
|
||||||
// table cell.
|
|
||||||
type Element interface {
|
|
||||||
Render(*renderStyle) string
|
|
||||||
}
|
|
||||||
|
|
||||||
type outputMode int
|
|
||||||
|
|
||||||
const (
|
|
||||||
outputTerminal outputMode = iota
|
|
||||||
outputMarkdown
|
|
||||||
outputHTML
|
|
||||||
)
|
|
||||||
|
|
||||||
// Open question: should UTF-8 become an output mode? It does require more
|
|
||||||
// tracking when resetting, if the locale-enabling had been used.
|
|
||||||
|
|
||||||
var outputsEnabled struct {
|
|
||||||
UTF8 bool
|
|
||||||
HTML bool
|
|
||||||
Markdown bool
|
|
||||||
titleStyle titleStyle
|
|
||||||
}
|
|
||||||
|
|
||||||
var defaultOutputMode outputMode = outputTerminal
|
|
||||||
|
|
||||||
// Table represents a terminal table. The Style can be directly accessed
|
|
||||||
// and manipulated; all other access is via methods.
|
|
||||||
type Table struct {
|
|
||||||
Style *TableStyle
|
|
||||||
|
|
||||||
elements []Element
|
|
||||||
headers []interface{}
|
|
||||||
title interface{}
|
|
||||||
titleCell *Cell
|
|
||||||
outputMode outputMode
|
|
||||||
}
|
|
||||||
|
|
||||||
// EnableUTF8 will unconditionally enable using UTF-8 box-drawing characters
|
|
||||||
// for any tables created after this call, as the default style.
|
|
||||||
func EnableUTF8() {
|
|
||||||
outputsEnabled.UTF8 = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetModeHTML will control whether or not new tables generated will be in HTML
|
|
||||||
// mode by default; HTML-or-not takes precedence over options which control how
|
|
||||||
// a terminal output will be rendered, such as whether or not to use UTF8.
|
|
||||||
// This affects any tables created after this call.
|
|
||||||
func SetModeHTML(onoff bool) {
|
|
||||||
outputsEnabled.HTML = onoff
|
|
||||||
chooseDefaultOutput()
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetModeMarkdown will control whether or not new tables generated will be
|
|
||||||
// in Markdown mode by default. HTML-mode takes precedence.
|
|
||||||
func SetModeMarkdown(onoff bool) {
|
|
||||||
outputsEnabled.Markdown = onoff
|
|
||||||
chooseDefaultOutput()
|
|
||||||
}
|
|
||||||
|
|
||||||
// EnableUTF8PerLocale will use current locale character map information to
|
|
||||||
// determine if UTF-8 is expected and, if so, is equivalent to EnableUTF8.
|
|
||||||
func EnableUTF8PerLocale() {
|
|
||||||
locale := getLocale()
|
|
||||||
if strings.Contains(locale, "UTF-8") {
|
|
||||||
EnableUTF8()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// getLocale returns the current locale name.
|
|
||||||
func getLocale() string {
|
|
||||||
if runtime.GOOS == "windows" {
|
|
||||||
// TODO: detect windows locale
|
|
||||||
return "US-ASCII"
|
|
||||||
}
|
|
||||||
return unixLocale()
|
|
||||||
}
|
|
||||||
|
|
||||||
// unixLocale returns the locale by checking the $LC_ALL, $LC_CTYPE, and $LANG
|
|
||||||
// environment variables. If none of those are set, it returns "US-ASCII".
|
|
||||||
func unixLocale() string {
|
|
||||||
for _, env := range []string{"LC_ALL", "LC_CTYPE", "LANG"} {
|
|
||||||
if locale := os.Getenv(env); locale != "" {
|
|
||||||
return locale
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "US-ASCII"
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetHTMLStyleTitle lets an HTML title output mode be chosen.
|
|
||||||
func SetHTMLStyleTitle(want titleStyle) {
|
|
||||||
outputsEnabled.titleStyle = want
|
|
||||||
}
|
|
||||||
|
|
||||||
// chooseDefaultOutput sets defaultOutputMode based on priority
|
|
||||||
// choosing amongst the options which are enabled. Pros: simpler
|
|
||||||
// encapsulation; cons: setting markdown doesn't disable HTML if
|
|
||||||
// HTML was previously enabled and was later disabled.
|
|
||||||
// This seems fairly reasonable.
|
|
||||||
func chooseDefaultOutput() {
|
|
||||||
if outputsEnabled.HTML {
|
|
||||||
defaultOutputMode = outputHTML
|
|
||||||
} else if outputsEnabled.Markdown {
|
|
||||||
defaultOutputMode = outputMarkdown
|
|
||||||
} else {
|
|
||||||
defaultOutputMode = outputTerminal
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
// Do not enable UTF-8 per locale by default, breaks tests.
|
|
||||||
sz, err := term.GetSize()
|
|
||||||
if err == nil && sz.Columns != 0 {
|
|
||||||
MaxColumns = sz.Columns
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateTable creates an empty Table using defaults for style.
|
|
||||||
func CreateTable() *Table {
|
|
||||||
t := &Table{elements: []Element{}, Style: DefaultStyle}
|
|
||||||
if outputsEnabled.UTF8 {
|
|
||||||
t.Style.setUtfBoxStyle()
|
|
||||||
}
|
|
||||||
if outputsEnabled.titleStyle != titleStyle(0) {
|
|
||||||
t.Style.htmlRules.title = outputsEnabled.titleStyle
|
|
||||||
}
|
|
||||||
t.outputMode = defaultOutputMode
|
|
||||||
return t
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddSeparator adds a line to the table content, where the line
|
|
||||||
// consists of separator characters.
|
|
||||||
func (t *Table) AddSeparator() {
|
|
||||||
t.elements = append(t.elements, &Separator{})
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddRow adds the supplied items as cells in one row of the table.
|
|
||||||
func (t *Table) AddRow(items ...interface{}) *Row {
|
|
||||||
row := CreateRow(items)
|
|
||||||
t.elements = append(t.elements, row)
|
|
||||||
return row
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddTitle supplies a table title, which if present will be rendered as
|
|
||||||
// one cell across the width of the table, as the first row.
|
|
||||||
func (t *Table) AddTitle(title interface{}) {
|
|
||||||
t.title = title
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddHeaders supplies column headers for the table.
|
|
||||||
func (t *Table) AddHeaders(headers ...interface{}) {
|
|
||||||
t.headers = append(t.headers, headers...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetAlign changes the alignment for elements in a column of the table;
|
|
||||||
// alignments are stored with each cell, so cells added after a call to
|
|
||||||
// SetAlign will not pick up the change. Columns are numbered from 1.
|
|
||||||
func (t *Table) SetAlign(align tableAlignment, column int) {
|
|
||||||
if column < 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for i := range t.elements {
|
|
||||||
row, ok := t.elements[i].(*Row)
|
|
||||||
if !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if column >= len(row.cells) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
row.cells[column-1].alignment = &align
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// UTF8Box sets the table style to use UTF-8 box-drawing characters,
|
|
||||||
// overriding all relevant style elements at the time of the call.
|
|
||||||
func (t *Table) UTF8Box() {
|
|
||||||
t.Style.setUtfBoxStyle()
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetModeHTML switches this table to be in HTML when rendered; the
|
|
||||||
// default depends upon whether the package function SetModeHTML() has been
|
|
||||||
// called, and with what value. This method forces the feature on for this
|
|
||||||
// table. Turning off involves choosing a different mode, per-table.
|
|
||||||
func (t *Table) SetModeHTML() {
|
|
||||||
t.outputMode = outputHTML
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetModeMarkdown switches this table to be in Markdown mode
|
|
||||||
func (t *Table) SetModeMarkdown() {
|
|
||||||
t.outputMode = outputMarkdown
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetModeTerminal switches this table to be in terminal mode.
|
|
||||||
func (t *Table) SetModeTerminal() {
|
|
||||||
t.outputMode = outputTerminal
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetHTMLStyleTitle lets an HTML output mode be chosen; we should rework this
|
|
||||||
// into a more generic and extensible API as we clean up termtables.
|
|
||||||
func (t *Table) SetHTMLStyleTitle(want titleStyle) {
|
|
||||||
t.Style.htmlRules.title = want
|
|
||||||
}
|
|
||||||
|
|
||||||
// Render returns a string representation of a fully rendered table, drawn
|
|
||||||
// out for display, with embedded newlines. If this table is in HTML mode,
|
|
||||||
// then this is equivalent to RenderHTML().
|
|
||||||
func (t *Table) Render() string {
|
|
||||||
// Elements is already populated with row data.
|
|
||||||
switch t.outputMode {
|
|
||||||
case outputTerminal:
|
|
||||||
return t.renderTerminal()
|
|
||||||
case outputMarkdown:
|
|
||||||
return t.renderMarkdown()
|
|
||||||
case outputHTML:
|
|
||||||
return t.RenderHTML()
|
|
||||||
default:
|
|
||||||
panic("unknown output mode set")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// renderTerminal returns a string representation of a fully rendered table,
|
|
||||||
// drawn out for display, with embedded newlines.
|
|
||||||
func (t *Table) renderTerminal() string {
|
|
||||||
// Use a placeholder rather than adding titles/headers to the tables
|
|
||||||
// elements or else successive calls will compound them.
|
|
||||||
tt := t.clone()
|
|
||||||
|
|
||||||
// Initial top line.
|
|
||||||
if !tt.Style.SkipBorder {
|
|
||||||
if tt.title != nil && tt.headers == nil {
|
|
||||||
tt.elements = append([]Element{&Separator{where: LINE_SUBTOP}}, tt.elements...)
|
|
||||||
} else if tt.title == nil && tt.headers == nil {
|
|
||||||
tt.elements = append([]Element{&Separator{where: LINE_TOP}}, tt.elements...)
|
|
||||||
} else {
|
|
||||||
tt.elements = append([]Element{&Separator{where: LINE_INNER}}, tt.elements...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we have headers, include them.
|
|
||||||
if tt.headers != nil {
|
|
||||||
ne := make([]Element, 2)
|
|
||||||
ne[1] = CreateRow(tt.headers)
|
|
||||||
if tt.title != nil {
|
|
||||||
ne[0] = &Separator{where: LINE_SUBTOP}
|
|
||||||
} else {
|
|
||||||
ne[0] = &Separator{where: LINE_TOP}
|
|
||||||
}
|
|
||||||
tt.elements = append(ne, tt.elements...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we have a title, write it.
|
|
||||||
if tt.title != nil {
|
|
||||||
// Match changes to this into renderMarkdown too.
|
|
||||||
tt.titleCell = CreateCell(tt.title, &CellStyle{Alignment: AlignCenter, ColSpan: 999})
|
|
||||||
ne := []Element{
|
|
||||||
&StraightSeparator{where: LINE_TOP},
|
|
||||||
CreateRow([]interface{}{tt.titleCell}),
|
|
||||||
}
|
|
||||||
tt.elements = append(ne, tt.elements...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a new table from the
|
|
||||||
// generate the runtime style. Must include all cells being printed.
|
|
||||||
style := createRenderStyle(tt)
|
|
||||||
|
|
||||||
// Loop over the elements and render them.
|
|
||||||
b := bytes.NewBuffer(nil)
|
|
||||||
for _, e := range tt.elements {
|
|
||||||
b.WriteString(e.Render(style))
|
|
||||||
b.WriteString("\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add bottom line.
|
|
||||||
if !style.SkipBorder {
|
|
||||||
b.WriteString((&Separator{where: LINE_BOTTOM}).Render(style) + "\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
return b.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
// renderMarkdown returns a string representation of a table in Markdown
|
|
||||||
// markup format using GitHub Flavored Markdown's notation (since tables
|
|
||||||
// are not in the core Markdown spec).
|
|
||||||
func (t *Table) renderMarkdown() string {
|
|
||||||
// We need ASCII drawing characters; we need a line after the header;
|
|
||||||
// *do* need a header! Do not need to markdown-escape contents of
|
|
||||||
// tables as markdown is ignored in there. Do need to do _something_
|
|
||||||
// with a '|' character shown as a member of a table.
|
|
||||||
|
|
||||||
t.Style.setAsciiBoxStyle()
|
|
||||||
|
|
||||||
firstLines := make([]Element, 0, 2)
|
|
||||||
|
|
||||||
if t.headers == nil {
|
|
||||||
initial := createRenderStyle(t)
|
|
||||||
if initial.columns > 1 {
|
|
||||||
row := CreateRow([]interface{}{})
|
|
||||||
for i := 0; i < initial.columns; i++ {
|
|
||||||
row.AddCell(CreateCell(i+1, &CellStyle{}))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
firstLines = append(firstLines, CreateRow(t.headers))
|
|
||||||
// This is a dummy line, swapped out below.
|
|
||||||
firstLines = append(firstLines, firstLines[0])
|
|
||||||
t.elements = append(firstLines, t.elements...)
|
|
||||||
// Generate the runtime style.
|
|
||||||
style := createRenderStyle(t)
|
|
||||||
// We know that the second line is a dummy, we can replace it.
|
|
||||||
mdRow := CreateRow([]interface{}{})
|
|
||||||
for i := 0; i < style.columns; i++ {
|
|
||||||
mdRow.AddCell(CreateCell(strings.Repeat("-", style.cellWidths[i]), &CellStyle{}))
|
|
||||||
}
|
|
||||||
t.elements[1] = mdRow
|
|
||||||
|
|
||||||
b := bytes.NewBuffer(nil)
|
|
||||||
// Comes after style is generated, which must come after all width-affecting
|
|
||||||
// changes are in.
|
|
||||||
if t.title != nil {
|
|
||||||
// Markdown doesn't support titles or column spanning; we _should_
|
|
||||||
// escape the title, but doing that to handle all possible forms of
|
|
||||||
// markup would require a heavy dependency, so we punt.
|
|
||||||
b.WriteString("Table: ")
|
|
||||||
b.WriteString(strings.TrimSpace(CreateCell(t.title, &CellStyle{}).Render(style)))
|
|
||||||
b.WriteString("\n\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Loop over the elements and render them.
|
|
||||||
for _, e := range t.elements {
|
|
||||||
b.WriteString(e.Render(style))
|
|
||||||
b.WriteString("\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
return b.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
// clone returns a copy of the table with the underlying slices being copied;
|
|
||||||
// the references to the Elements/cells are left as shallow copies.
|
|
||||||
func (t *Table) clone() *Table {
|
|
||||||
tt := &Table{outputMode: t.outputMode, Style: t.Style, title: t.title}
|
|
||||||
if t.headers != nil {
|
|
||||||
tt.headers = make([]interface{}, len(t.headers))
|
|
||||||
copy(tt.headers, t.headers)
|
|
||||||
}
|
|
||||||
if t.elements != nil {
|
|
||||||
tt.elements = make([]Element, len(t.elements))
|
|
||||||
copy(tt.elements, t.elements)
|
|
||||||
}
|
|
||||||
return tt
|
|
||||||
}
|
|
562
vendor/github.com/apcera/termtables/table_test.go
generated
vendored
562
vendor/github.com/apcera/termtables/table_test.go
generated
vendored
@ -1,562 +0,0 @@
|
|||||||
// Copyright 2012-2013 Apcera Inc. All rights reserved.
|
|
||||||
package termtables
|
|
||||||
|
|
||||||
import "testing"
|
|
||||||
|
|
||||||
func DisplayFailedOutput(actual, expected string) string {
|
|
||||||
return "Output didn't match expected\n\n" +
|
|
||||||
"Actual:\n\n" +
|
|
||||||
actual + "\n" +
|
|
||||||
"Expected:\n\n" +
|
|
||||||
expected
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkRendersTo(t *testing.T, table *Table, expected string) {
|
|
||||||
output := table.Render()
|
|
||||||
if output != expected {
|
|
||||||
t.Fatal(DisplayFailedOutput(output, expected))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCreateTable(t *testing.T) {
|
|
||||||
expected := "" +
|
|
||||||
"+-----------+-------+\n" +
|
|
||||||
"| Name | Value |\n" +
|
|
||||||
"+-----------+-------+\n" +
|
|
||||||
"| hey | you |\n" +
|
|
||||||
"| ken | 1234 |\n" +
|
|
||||||
"| derek | 3.14 |\n" +
|
|
||||||
"| derek too | 3.15 |\n" +
|
|
||||||
"| escaping | rox%% |\n" +
|
|
||||||
"+-----------+-------+\n"
|
|
||||||
|
|
||||||
table := CreateTable()
|
|
||||||
|
|
||||||
table.AddHeaders("Name", "Value")
|
|
||||||
table.AddRow("hey", "you")
|
|
||||||
table.AddRow("ken", 1234)
|
|
||||||
table.AddRow("derek", 3.14)
|
|
||||||
table.AddRow("derek too", 3.1456788)
|
|
||||||
table.AddRow("escaping", "rox%%")
|
|
||||||
|
|
||||||
checkRendersTo(t, table, expected)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestStyleResets(t *testing.T) {
|
|
||||||
expected := "" +
|
|
||||||
"+-----------+-------+\n" +
|
|
||||||
"| Name | Value |\n" +
|
|
||||||
"+-----------+-------+\n" +
|
|
||||||
"| hey | you |\n" +
|
|
||||||
"| ken | 1234 |\n" +
|
|
||||||
"| derek | 3.14 |\n" +
|
|
||||||
"| derek too | 3.15 |\n" +
|
|
||||||
"+-----------+-------+\n"
|
|
||||||
|
|
||||||
table := CreateTable()
|
|
||||||
table.UTF8Box()
|
|
||||||
table.Style.setAsciiBoxStyle()
|
|
||||||
|
|
||||||
table.AddHeaders("Name", "Value")
|
|
||||||
table.AddRow("hey", "you")
|
|
||||||
table.AddRow("ken", 1234)
|
|
||||||
table.AddRow("derek", 3.14)
|
|
||||||
table.AddRow("derek too", 3.1456788)
|
|
||||||
|
|
||||||
checkRendersTo(t, table, expected)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTableWithHeader(t *testing.T) {
|
|
||||||
expected := "" +
|
|
||||||
"+-------------------+\n" +
|
|
||||||
"| Example |\n" +
|
|
||||||
"+-----------+-------+\n" +
|
|
||||||
"| Name | Value |\n" +
|
|
||||||
"+-----------+-------+\n" +
|
|
||||||
"| hey | you |\n" +
|
|
||||||
"| ken | 1234 |\n" +
|
|
||||||
"| derek | 3.14 |\n" +
|
|
||||||
"| derek too | 3.15 |\n" +
|
|
||||||
"+-----------+-------+\n"
|
|
||||||
|
|
||||||
table := CreateTable()
|
|
||||||
|
|
||||||
table.AddTitle("Example")
|
|
||||||
table.AddHeaders("Name", "Value")
|
|
||||||
table.AddRow("hey", "you")
|
|
||||||
table.AddRow("ken", 1234)
|
|
||||||
table.AddRow("derek", 3.14)
|
|
||||||
table.AddRow("derek too", 3.1456788)
|
|
||||||
|
|
||||||
checkRendersTo(t, table, expected)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestTableWithHeaderMultipleTimes ensures that printing a table with headers
|
|
||||||
// multiple times continues to render correctly.
|
|
||||||
func TestTableWithHeaderMultipleTimes(t *testing.T) {
|
|
||||||
expected := "" +
|
|
||||||
"+-------------------+\n" +
|
|
||||||
"| Example |\n" +
|
|
||||||
"+-----------+-------+\n" +
|
|
||||||
"| Name | Value |\n" +
|
|
||||||
"+-----------+-------+\n" +
|
|
||||||
"| hey | you |\n" +
|
|
||||||
"| ken | 1234 |\n" +
|
|
||||||
"| derek | 3.14 |\n" +
|
|
||||||
"| derek too | 3.15 |\n" +
|
|
||||||
"+-----------+-------+\n"
|
|
||||||
|
|
||||||
table := CreateTable()
|
|
||||||
|
|
||||||
table.AddTitle("Example")
|
|
||||||
table.AddHeaders("Name", "Value")
|
|
||||||
table.AddRow("hey", "you")
|
|
||||||
table.AddRow("ken", 1234)
|
|
||||||
table.AddRow("derek", 3.14)
|
|
||||||
table.AddRow("derek too", 3.1456788)
|
|
||||||
|
|
||||||
checkRendersTo(t, table, expected)
|
|
||||||
checkRendersTo(t, table, expected)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTableTitleWidthAdjusts(t *testing.T) {
|
|
||||||
expected := "" +
|
|
||||||
"+---------------------------+\n" +
|
|
||||||
"| Example My Foo Bar'd Test |\n" +
|
|
||||||
"+-----------+---------------+\n" +
|
|
||||||
"| Name | Value |\n" +
|
|
||||||
"+-----------+---------------+\n" +
|
|
||||||
"| hey | you |\n" +
|
|
||||||
"| ken | 1234 |\n" +
|
|
||||||
"| derek | 3.14 |\n" +
|
|
||||||
"| derek too | 3.15 |\n" +
|
|
||||||
"+-----------+---------------+\n"
|
|
||||||
|
|
||||||
table := CreateTable()
|
|
||||||
|
|
||||||
table.AddTitle("Example My Foo Bar'd Test")
|
|
||||||
table.AddHeaders("Name", "Value")
|
|
||||||
table.AddRow("hey", "you")
|
|
||||||
table.AddRow("ken", 1234)
|
|
||||||
table.AddRow("derek", 3.14)
|
|
||||||
table.AddRow("derek too", 3.1456788)
|
|
||||||
|
|
||||||
checkRendersTo(t, table, expected)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTableHeaderWidthAdjusts(t *testing.T) {
|
|
||||||
expected := "" +
|
|
||||||
"+---------------+---------------------+\n" +
|
|
||||||
"| Slightly Long | More than 2 columns |\n" +
|
|
||||||
"+---------------+---------------------+\n" +
|
|
||||||
"| a | b |\n" +
|
|
||||||
"+---------------+---------------------+\n"
|
|
||||||
|
|
||||||
table := CreateTable()
|
|
||||||
|
|
||||||
table.AddHeaders("Slightly Long", "More than 2 columns")
|
|
||||||
table.AddRow("a", "b")
|
|
||||||
|
|
||||||
checkRendersTo(t, table, expected)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTableWithNoHeaders(t *testing.T) {
|
|
||||||
expected := "" +
|
|
||||||
"+-----------+------+\n" +
|
|
||||||
"| hey | you |\n" +
|
|
||||||
"| ken | 1234 |\n" +
|
|
||||||
"| derek | 3.14 |\n" +
|
|
||||||
"| derek too | 3.15 |\n" +
|
|
||||||
"+-----------+------+\n"
|
|
||||||
|
|
||||||
table := CreateTable()
|
|
||||||
|
|
||||||
table.AddRow("hey", "you")
|
|
||||||
table.AddRow("ken", 1234)
|
|
||||||
table.AddRow("derek", 3.14)
|
|
||||||
table.AddRow("derek too", 3.1456788)
|
|
||||||
|
|
||||||
checkRendersTo(t, table, expected)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTableUnicodeWidths(t *testing.T) {
|
|
||||||
expected := "" +
|
|
||||||
"+-----------+------+\n" +
|
|
||||||
"| Name | Cost |\n" +
|
|
||||||
"+-----------+------+\n" +
|
|
||||||
"| Currency | ¤10 |\n" +
|
|
||||||
"| US Dollar | $30 |\n" +
|
|
||||||
"| Euro | €27 |\n" +
|
|
||||||
"| Thai | ฿70 |\n" +
|
|
||||||
"+-----------+------+\n"
|
|
||||||
|
|
||||||
table := CreateTable()
|
|
||||||
table.AddHeaders("Name", "Cost")
|
|
||||||
table.AddRow("Currency", "¤10")
|
|
||||||
table.AddRow("US Dollar", "$30")
|
|
||||||
table.AddRow("Euro", "€27")
|
|
||||||
table.AddRow("Thai", "฿70")
|
|
||||||
|
|
||||||
checkRendersTo(t, table, expected)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTableInUTF8(t *testing.T) {
|
|
||||||
expected := "" +
|
|
||||||
"╭───────────────────╮\n" +
|
|
||||||
"│ Example │\n" +
|
|
||||||
"├───────────┬───────┤\n" +
|
|
||||||
"│ Name │ Value │\n" +
|
|
||||||
"├───────────┼───────┤\n" +
|
|
||||||
"│ hey │ you │\n" +
|
|
||||||
"│ ken │ 1234 │\n" +
|
|
||||||
"│ derek │ 3.14 │\n" +
|
|
||||||
"│ derek too │ 3.15 │\n" +
|
|
||||||
"│ escaping │ rox%% │\n" +
|
|
||||||
"╰───────────┴───────╯\n"
|
|
||||||
|
|
||||||
table := CreateTable()
|
|
||||||
table.UTF8Box()
|
|
||||||
|
|
||||||
table.AddTitle("Example")
|
|
||||||
table.AddHeaders("Name", "Value")
|
|
||||||
table.AddRow("hey", "you")
|
|
||||||
table.AddRow("ken", 1234)
|
|
||||||
table.AddRow("derek", 3.14)
|
|
||||||
table.AddRow("derek too", 3.1456788)
|
|
||||||
table.AddRow("escaping", "rox%%")
|
|
||||||
|
|
||||||
checkRendersTo(t, table, expected)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTableUnicodeUTF8AndSGR(t *testing.T) {
|
|
||||||
// at present, this mostly just tests that alignment still works
|
|
||||||
expected := "" +
|
|
||||||
"╭───────────────────────╮\n" +
|
|
||||||
"│ \033[1mFanciness\033[0m │\n" +
|
|
||||||
"├──────────┬────────────┤\n" +
|
|
||||||
"│ \033[31mred\033[0m │ \033[32mgreen\033[0m │\n" +
|
|
||||||
"├──────────┼────────────┤\n" +
|
|
||||||
"│ plain │ text │\n" +
|
|
||||||
"│ Καλημέρα │ κόσμε │\n" +
|
|
||||||
"│ \033[1mvery\033[0m │ \033[4munderlined\033[0m │\n" +
|
|
||||||
"│ a\033[1mb\033[0mc │ \033[45mmagenta\033[0m │\n" +
|
|
||||||
"│ \033[31m→\033[0m │ \033[32m←\033[0m │\n" +
|
|
||||||
"╰──────────┴────────────╯\n"
|
|
||||||
|
|
||||||
sgred := func(in string, sgrPm string) string {
|
|
||||||
return "\033[" + sgrPm + "m" + in + "\033[0m"
|
|
||||||
}
|
|
||||||
bold := func(in string) string { return sgred(in, "1") }
|
|
||||||
|
|
||||||
table := CreateTable()
|
|
||||||
table.UTF8Box()
|
|
||||||
|
|
||||||
table.AddTitle(bold("Fanciness"))
|
|
||||||
table.AddHeaders(sgred("red", "31"), sgred("green", "32"))
|
|
||||||
table.AddRow("plain", "text")
|
|
||||||
table.AddRow("Καλημέρα", "κόσμε") // from http://plan9.bell-labs.com/sys/doc/utf.html
|
|
||||||
table.AddRow(bold("very"), sgred("underlined", "4"))
|
|
||||||
table.AddRow("a"+bold("b")+"c", sgred("magenta", "45"))
|
|
||||||
table.AddRow(sgred("→", "31"), sgred("←", "32"))
|
|
||||||
// TODO: in future, if we start detecting presence of SGR sequences, we
|
|
||||||
// should ensure that the SGR reset is done at the end of the cell content,
|
|
||||||
// so that SGR doesn't "bleed across" (cells or rows). We would then add
|
|
||||||
// tests for that here.
|
|
||||||
//
|
|
||||||
// Of course, at that point, we'd also want to support automatic HTML
|
|
||||||
// styling conversion too, so would need a test for that also.
|
|
||||||
|
|
||||||
checkRendersTo(t, table, expected)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTableInMarkdown(t *testing.T) {
|
|
||||||
expected := "" +
|
|
||||||
"Table: Example\n\n" +
|
|
||||||
"| Name | Value |\n" +
|
|
||||||
"| ----- | ----- |\n" +
|
|
||||||
"| hey | you |\n" +
|
|
||||||
"| a | b | esc |\n" +
|
|
||||||
"| esc | rox%% |\n"
|
|
||||||
|
|
||||||
table := CreateTable()
|
|
||||||
table.SetModeMarkdown()
|
|
||||||
|
|
||||||
table.AddTitle("Example")
|
|
||||||
table.AddHeaders("Name", "Value")
|
|
||||||
table.AddRow("hey", "you")
|
|
||||||
table.AddRow("a | b", "esc")
|
|
||||||
table.AddRow("esc", "rox%%")
|
|
||||||
|
|
||||||
checkRendersTo(t, table, expected)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTitleUnicodeWidths(t *testing.T) {
|
|
||||||
expected := "" +
|
|
||||||
"+-------+\n" +
|
|
||||||
"| ← 5 → |\n" +
|
|
||||||
"+---+---+\n" +
|
|
||||||
"| a | b |\n" +
|
|
||||||
"| c | d |\n" +
|
|
||||||
"| e | 3 |\n" +
|
|
||||||
"+---+---+\n"
|
|
||||||
|
|
||||||
// minimum width for a table of two columns is 9 characters, given
|
|
||||||
// one space of padding, and non-empty tables.
|
|
||||||
|
|
||||||
table := CreateTable()
|
|
||||||
|
|
||||||
// We have 4 characters down for left and right columns and padding, so
|
|
||||||
// a width of 5 for us should match the minimum per the columns
|
|
||||||
|
|
||||||
// 5 characters; each arrow is three octets in UTF-8, giving 9 bytes
|
|
||||||
// so, same in character-count-width, longer in bytes
|
|
||||||
table.AddTitle("← 5 →")
|
|
||||||
|
|
||||||
// a single character per cell, here; use ASCII characters
|
|
||||||
table.AddRow("a", "b")
|
|
||||||
table.AddRow("c", "d")
|
|
||||||
table.AddRow("e", 3)
|
|
||||||
|
|
||||||
checkRendersTo(t, table, expected)
|
|
||||||
}
|
|
||||||
|
|
||||||
// We identified two error conditions wherein length wrapping would not correctly
|
|
||||||
// wrap width when, for instance, in a two-column table, the longest row in the
|
|
||||||
// right-hand column was not the same as the longest row in the left-hand column.
|
|
||||||
// This tests that we correctly accumulate the maximum width across all rows of
|
|
||||||
// the termtable and adjust width accordingly.
|
|
||||||
func TestTableWidthHandling(t *testing.T) {
|
|
||||||
expected := "" +
|
|
||||||
"+-----------------------------------------+\n" +
|
|
||||||
"| Example... to Fix My Test |\n" +
|
|
||||||
"+-----------------+-----------------------+\n" +
|
|
||||||
"| hey foo bar baz | you |\n" +
|
|
||||||
"| ken | you should write code |\n" +
|
|
||||||
"| derek | 3.14 |\n" +
|
|
||||||
"| derek too | 3.15 |\n" +
|
|
||||||
"+-----------------+-----------------------+\n"
|
|
||||||
|
|
||||||
table := CreateTable()
|
|
||||||
|
|
||||||
table.AddTitle("Example... to Fix My Test")
|
|
||||||
table.AddRow("hey foo bar baz", "you")
|
|
||||||
table.AddRow("ken", "you should write code")
|
|
||||||
table.AddRow("derek", 3.14)
|
|
||||||
table.AddRow("derek too", 3.1456788)
|
|
||||||
|
|
||||||
output := table.Render()
|
|
||||||
if output != expected {
|
|
||||||
t.Fatal(DisplayFailedOutput(output, expected))
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTableWidthHandling_SecondErrorCondition(t *testing.T) {
|
|
||||||
expected := "" +
|
|
||||||
"+----------------------------------------+\n" +
|
|
||||||
"| Example... to Fix My Test |\n" +
|
|
||||||
"+-----------------+----------------------+\n" +
|
|
||||||
"| hey foo bar baz | you |\n" +
|
|
||||||
"| ken | you should sell cod! |\n" +
|
|
||||||
"| derek | 3.14 |\n" +
|
|
||||||
"| derek too | 3.15 |\n" +
|
|
||||||
"+-----------------+----------------------+\n"
|
|
||||||
|
|
||||||
table := CreateTable()
|
|
||||||
|
|
||||||
table.AddTitle("Example... to Fix My Test")
|
|
||||||
table.AddRow("hey foo bar baz", "you")
|
|
||||||
table.AddRow("ken", "you should sell cod!")
|
|
||||||
table.AddRow("derek", 3.14)
|
|
||||||
table.AddRow("derek too", 3.1456788)
|
|
||||||
|
|
||||||
output := table.Render()
|
|
||||||
if output != expected {
|
|
||||||
t.Fatal(DisplayFailedOutput(output, expected))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTableAlignPostsetting(t *testing.T) {
|
|
||||||
expected := "" +
|
|
||||||
"+-----------+-------+\n" +
|
|
||||||
"| Name | Value |\n" +
|
|
||||||
"+-----------+-------+\n" +
|
|
||||||
"| hey | you |\n" +
|
|
||||||
"| ken | 1234 |\n" +
|
|
||||||
"| derek | 3.14 |\n" +
|
|
||||||
"| derek too | 3.15 |\n" +
|
|
||||||
"| escaping | rox%% |\n" +
|
|
||||||
"+-----------+-------+\n"
|
|
||||||
|
|
||||||
table := CreateTable()
|
|
||||||
|
|
||||||
table.AddHeaders("Name", "Value")
|
|
||||||
table.AddRow("hey", "you")
|
|
||||||
table.AddRow("ken", 1234)
|
|
||||||
table.AddRow("derek", 3.14)
|
|
||||||
table.AddRow("derek too", 3.1456788)
|
|
||||||
table.AddRow("escaping", "rox%%")
|
|
||||||
|
|
||||||
table.SetAlign(AlignRight, 1)
|
|
||||||
|
|
||||||
checkRendersTo(t, table, expected)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTableMissingCells(t *testing.T) {
|
|
||||||
expected := "" +
|
|
||||||
"+----------+---------+---------+\n" +
|
|
||||||
"| Name | Value 1 | Value 2 |\n" +
|
|
||||||
"+----------+---------+---------+\n" +
|
|
||||||
"| hey | you | person |\n" +
|
|
||||||
"| ken | 1234 |\n" +
|
|
||||||
"| escaping | rox%s%% |\n" +
|
|
||||||
"+----------+---------+---------+\n"
|
|
||||||
// FIXME: missing extra cells there
|
|
||||||
|
|
||||||
table := CreateTable()
|
|
||||||
|
|
||||||
table.AddHeaders("Name", "Value 1", "Value 2")
|
|
||||||
table.AddRow("hey", "you", "person")
|
|
||||||
table.AddRow("ken", 1234)
|
|
||||||
table.AddRow("escaping", "rox%s%%")
|
|
||||||
|
|
||||||
checkRendersTo(t, table, expected)
|
|
||||||
}
|
|
||||||
|
|
||||||
// We don't yet support combining characters, double-width characters or
|
|
||||||
// anything to do with estimating a tty-style "character width" for what in
|
|
||||||
// Unicode is a grapheme cluster. This disabled test shows what we want
|
|
||||||
// to support, but don't yet.
|
|
||||||
func TestTableWithCombiningChars(t *testing.T) {
|
|
||||||
expected := "" +
|
|
||||||
"+------+---+\n" +
|
|
||||||
"| noel | 1 |\n" +
|
|
||||||
"| noël | 2 |\n" +
|
|
||||||
"| noël | 3 |\n" +
|
|
||||||
"+------+---+\n"
|
|
||||||
|
|
||||||
table := CreateTable()
|
|
||||||
|
|
||||||
table.AddRow("noel", "1")
|
|
||||||
table.AddRow("noe\u0308l", "2") // LATIN SMALL LETTER E + COMBINING DIAERESIS
|
|
||||||
table.AddRow("noël", "3") // Hex EB; LATIN SMALL LETTER E WITH DIAERESIS
|
|
||||||
|
|
||||||
checkRendersTo(t, table, expected)
|
|
||||||
}
|
|
||||||
|
|
||||||
// another unicode length issue
|
|
||||||
func TestTableWithFullwidthChars(t *testing.T) {
|
|
||||||
expected := "" +
|
|
||||||
"+----------+------------+\n" +
|
|
||||||
"| wide | not really |\n" +
|
|
||||||
"| wide | fullwidth |\n" +
|
|
||||||
"+----------+------------+\n"
|
|
||||||
|
|
||||||
table := CreateTable()
|
|
||||||
table.AddRow("wide", "not really")
|
|
||||||
table.AddRow("wide", "fullwidth") // FULLWIDTH LATIN SMALL LETTER <X>
|
|
||||||
|
|
||||||
checkRendersTo(t, table, expected)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tests CJK characters using examples given in issue #33. The examples may not
|
|
||||||
// look like they line up but you can visually confirm its accuracy with a
|
|
||||||
// fmt.Print.
|
|
||||||
func TestCJKChars(t *testing.T) {
|
|
||||||
expected := "" +
|
|
||||||
"+-------+---------+----------+\n" +
|
|
||||||
"| KeyID | ValueID | ValueCN |\n" +
|
|
||||||
"+-------+---------+----------+\n" +
|
|
||||||
"| 8 | 51 | 精钢 |\n" +
|
|
||||||
"| 8 | 52 | 鳄鱼皮 |\n" +
|
|
||||||
"| 8 | 53 | 镀金皮带 |\n" +
|
|
||||||
"| 8 | 54 | 精钢 |\n" +
|
|
||||||
"+-------+---------+----------+\n"
|
|
||||||
|
|
||||||
table := CreateTable()
|
|
||||||
table.AddHeaders("KeyID", "ValueID", "ValueCN")
|
|
||||||
table.AddRow("8", 51, "精钢")
|
|
||||||
table.AddRow("8", 52, "鳄鱼皮")
|
|
||||||
table.AddRow("8", 53, "镀金皮带")
|
|
||||||
table.AddRow("8", 54, "精钢")
|
|
||||||
checkRendersTo(t, table, expected)
|
|
||||||
|
|
||||||
expected2 := "" +
|
|
||||||
"+--------------------+----------------------+\n" +
|
|
||||||
"| field | value |\n" +
|
|
||||||
"+--------------------+----------------------+\n" +
|
|
||||||
"| GoodsPropertyKeyID | 9 |\n" +
|
|
||||||
"| MerchantAccountID | 0 |\n" +
|
|
||||||
"| GoodsCategoryCode | 100001 |\n" +
|
|
||||||
"| NameCN | 机芯类型 |\n" +
|
|
||||||
"| NameJP | ムーブメントのタイプ |\n" +
|
|
||||||
"+--------------------+----------------------+\n"
|
|
||||||
table = CreateTable()
|
|
||||||
table.AddHeaders("field", "value")
|
|
||||||
table.AddRow("GoodsPropertyKeyID", 9)
|
|
||||||
table.AddRow("MerchantAccountID", 0)
|
|
||||||
table.AddRow("GoodsCategoryCode", 100001)
|
|
||||||
table.AddRow("NameCN", "机芯类型")
|
|
||||||
table.AddRow("NameJP", "ムーブメントのタイプ")
|
|
||||||
checkRendersTo(t, table, expected2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTableMultipleAddHeader(t *testing.T) {
|
|
||||||
expected := "" +
|
|
||||||
"+--------------+--------+-------+\n" +
|
|
||||||
"| First column | Second | Third |\n" +
|
|
||||||
"+--------------+--------+-------+\n" +
|
|
||||||
"| 2 | 3 | 5 |\n" +
|
|
||||||
"+--------------+--------+-------+\n"
|
|
||||||
|
|
||||||
table := CreateTable()
|
|
||||||
table.AddHeaders("First column", "Second")
|
|
||||||
table.AddHeaders("Third")
|
|
||||||
table.AddRow(2, 3, 5)
|
|
||||||
|
|
||||||
checkRendersTo(t, table, expected)
|
|
||||||
}
|
|
||||||
|
|
||||||
func createTestTable() *Table {
|
|
||||||
table := CreateTable()
|
|
||||||
header := []interface{}{}
|
|
||||||
for i := 0; i < 50; i++ {
|
|
||||||
header = append(header, "First Column")
|
|
||||||
}
|
|
||||||
table.AddHeaders(header...)
|
|
||||||
for i := 0; i < 3000; i++ {
|
|
||||||
row := []interface{}{}
|
|
||||||
for i := 0; i < 50; i++ {
|
|
||||||
row = append(row, "First row value")
|
|
||||||
}
|
|
||||||
table.AddRow(row...)
|
|
||||||
}
|
|
||||||
return table
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkTableRenderTerminal(b *testing.B) {
|
|
||||||
table := createTestTable()
|
|
||||||
table.SetModeTerminal()
|
|
||||||
b.ResetTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
table.Render()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkTableRenderMarkdown(b *testing.B) {
|
|
||||||
table := createTestTable()
|
|
||||||
table.SetModeMarkdown()
|
|
||||||
b.ResetTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
table.Render()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkTableRenderHTML(b *testing.B) {
|
|
||||||
table := createTestTable()
|
|
||||||
table.SetModeHTML()
|
|
||||||
b.ResetTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
table.Render()
|
|
||||||
}
|
|
||||||
}
|
|
43
vendor/github.com/apcera/termtables/term/env.go
generated
vendored
43
vendor/github.com/apcera/termtables/term/env.go
generated
vendored
@ -1,43 +0,0 @@
|
|||||||
// Copyright 2013 Apcera Inc. All rights reserved.
|
|
||||||
|
|
||||||
package term
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"strconv"
|
|
||||||
)
|
|
||||||
|
|
||||||
// GetEnvWindowSize returns the window Size, as determined by process
|
|
||||||
// environment; if either LINES or COLUMNS is present, and whichever is
|
|
||||||
// present is also numeric, the Size will be non-nil. If Size is nil,
|
|
||||||
// there's insufficient data in environ. If one entry is 0, that means
|
|
||||||
// that the environment does not include that data. If a value is
|
|
||||||
// negative, we treat that as an error.
|
|
||||||
func GetEnvWindowSize() *Size {
|
|
||||||
lines := os.Getenv("LINES")
|
|
||||||
columns := os.Getenv("COLUMNS")
|
|
||||||
if lines == "" && columns == "" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
nLines := 0
|
|
||||||
nColumns := 0
|
|
||||||
var err error
|
|
||||||
if lines != "" {
|
|
||||||
nLines, err = strconv.Atoi(lines)
|
|
||||||
if err != nil || nLines < 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if columns != "" {
|
|
||||||
nColumns, err = strconv.Atoi(columns)
|
|
||||||
if err != nil || nColumns < 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return &Size{
|
|
||||||
Lines: nLines,
|
|
||||||
Columns: nColumns,
|
|
||||||
}
|
|
||||||
}
|
|
54
vendor/github.com/apcera/termtables/term/getsize.go
generated
vendored
54
vendor/github.com/apcera/termtables/term/getsize.go
generated
vendored
@ -1,54 +0,0 @@
|
|||||||
// Copyright 2013 Apcera Inc. All rights reserved.
|
|
||||||
|
|
||||||
package term
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Size is the size of a terminal, expressed in character cells, as Lines and
|
|
||||||
// Columns. This might come from environment variables or OS-dependent
|
|
||||||
// resources.
|
|
||||||
type Size struct {
|
|
||||||
Lines int
|
|
||||||
Columns int
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetSize will return the terminal window size.
|
|
||||||
//
|
|
||||||
// We prefer environ $LINES/$COLUMNS, then fall back to tty-held information.
|
|
||||||
// We do not support use of termcap/terminfo to derive default size information.
|
|
||||||
func GetSize() (*Size, error) {
|
|
||||||
envSize := GetEnvWindowSize()
|
|
||||||
if envSize != nil && envSize.Lines != 0 && envSize.Columns != 0 {
|
|
||||||
return envSize, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
fh, err := os.Open("/dev/tty")
|
|
||||||
if err != nil {
|
|
||||||
// no tty, no point continuing; we only let the environ
|
|
||||||
// avoid an error in this case because if someone has faked
|
|
||||||
// up an environ with LINES/COLUMNS _both_ set, we should let
|
|
||||||
// them
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
size, err := GetTerminalWindowSize(fh)
|
|
||||||
if err != nil {
|
|
||||||
if envSize != nil {
|
|
||||||
return envSize, nil
|
|
||||||
}
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if envSize == nil {
|
|
||||||
return size, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if envSize.Lines == 0 {
|
|
||||||
envSize.Lines = size.Lines
|
|
||||||
}
|
|
||||||
if envSize.Columns == 0 {
|
|
||||||
envSize.Columns = size.Columns
|
|
||||||
}
|
|
||||||
return envSize, nil
|
|
||||||
}
|
|
35
vendor/github.com/apcera/termtables/term/sizes_unix.go
generated
vendored
35
vendor/github.com/apcera/termtables/term/sizes_unix.go
generated
vendored
@ -1,35 +0,0 @@
|
|||||||
// Copyright 2013 Apcera Inc. All rights reserved.
|
|
||||||
|
|
||||||
// +build !windows
|
|
||||||
|
|
||||||
package term
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"os"
|
|
||||||
"syscall"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ErrGetWinsizeFailed indicates that the system call to extract the size of
|
|
||||||
// a Unix tty from the kernel failed.
|
|
||||||
var ErrGetWinsizeFailed = errors.New("term: syscall.TIOCGWINSZ failed")
|
|
||||||
|
|
||||||
// GetTerminalWindowSize returns the terminal size maintained by the kernel
|
|
||||||
// for a Unix TTY, passed in as an *os.File. This information can be seen
|
|
||||||
// with the stty(1) command, and changes in size (eg, terminal emulator
|
|
||||||
// resized) should trigger a SIGWINCH signal delivery to the foreground process
|
|
||||||
// group at the time of the change, so a long-running process might reasonably
|
|
||||||
// watch for SIGWINCH and arrange to re-fetch the size when that happens.
|
|
||||||
func GetTerminalWindowSize(file *os.File) (*Size, error) {
|
|
||||||
// Based on source from from golang.org/x/crypto/ssh/terminal/util.go
|
|
||||||
var dimensions [4]uint16
|
|
||||||
if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, file.Fd(), uintptr(syscall.TIOCGWINSZ), uintptr(unsafe.Pointer(&dimensions)), 0, 0, 0); err != 0 {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &Size{
|
|
||||||
Lines: int(dimensions[0]),
|
|
||||||
Columns: int(dimensions[1]),
|
|
||||||
}, nil
|
|
||||||
}
|
|
57
vendor/github.com/apcera/termtables/term/sizes_windows.go
generated
vendored
57
vendor/github.com/apcera/termtables/term/sizes_windows.go
generated
vendored
@ -1,57 +0,0 @@
|
|||||||
// Copyright 2013 Apcera Inc. All rights reserved.
|
|
||||||
|
|
||||||
// +build windows
|
|
||||||
|
|
||||||
package term
|
|
||||||
|
|
||||||
// Used when we have no other source for getting platform-specific information
|
|
||||||
// about the terminal sizes available.
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"syscall"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Based on source from from golang.org/x/crypto/ssh/terminal/util_windows.go
|
|
||||||
var (
|
|
||||||
kernel32 = syscall.NewLazyDLL("kernel32.dll")
|
|
||||||
|
|
||||||
procGetConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo")
|
|
||||||
)
|
|
||||||
|
|
||||||
type (
|
|
||||||
short int16
|
|
||||||
word uint16
|
|
||||||
|
|
||||||
coord struct {
|
|
||||||
x short
|
|
||||||
y short
|
|
||||||
}
|
|
||||||
smallRect struct {
|
|
||||||
left short
|
|
||||||
top short
|
|
||||||
right short
|
|
||||||
bottom short
|
|
||||||
}
|
|
||||||
consoleScreenBufferInfo struct {
|
|
||||||
size coord
|
|
||||||
cursorPosition coord
|
|
||||||
attributes word
|
|
||||||
window smallRect
|
|
||||||
maximumWindowSize coord
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
// GetTerminalWindowSize returns the width and height of a terminal in Windows.
|
|
||||||
func GetTerminalWindowSize(file *os.File) (*Size, error) {
|
|
||||||
var info consoleScreenBufferInfo
|
|
||||||
_, _, e := syscall.Syscall(procGetConsoleScreenBufferInfo.Addr(), 2, file.Fd(), uintptr(unsafe.Pointer(&info)), 0)
|
|
||||||
if e != 0 {
|
|
||||||
return nil, error(e)
|
|
||||||
}
|
|
||||||
return &Size{
|
|
||||||
Lines: int(info.size.y),
|
|
||||||
Columns: int(info.size.x),
|
|
||||||
}, nil
|
|
||||||
}
|
|
22
vendor/github.com/apcera/termtables/term/wrapper.go
generated
vendored
22
vendor/github.com/apcera/termtables/term/wrapper.go
generated
vendored
@ -1,22 +0,0 @@
|
|||||||
// Copyright 2013 Apcera Inc. All rights reserved.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/apcera/termtables/term"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
size, err := term.GetSize()
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "failed: %s\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("Lines %d Columns %d\n", size.Lines, size.Columns)
|
|
||||||
}
|
|
21
vendor/github.com/apcera/termtables/vendor/github.com/mattn/go-runewidth/LICENSE
generated
vendored
21
vendor/github.com/apcera/termtables/vendor/github.com/mattn/go-runewidth/LICENSE
generated
vendored
@ -1,21 +0,0 @@
|
|||||||
The MIT License (MIT)
|
|
||||||
|
|
||||||
Copyright (c) 2016 Yasuhiro Matsumoto
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
1223
vendor/github.com/apcera/termtables/vendor/github.com/mattn/go-runewidth/runewidth.go
generated
vendored
1223
vendor/github.com/apcera/termtables/vendor/github.com/mattn/go-runewidth/runewidth.go
generated
vendored
File diff suppressed because it is too large
Load Diff
@ -1,8 +0,0 @@
|
|||||||
// +build js
|
|
||||||
|
|
||||||
package runewidth
|
|
||||||
|
|
||||||
func IsEastAsian() bool {
|
|
||||||
// TODO: Implement this for the web. Detect east asian in a compatible way, and return true.
|
|
||||||
return false
|
|
||||||
}
|
|
@ -1,77 +0,0 @@
|
|||||||
// +build !windows,!js
|
|
||||||
|
|
||||||
package runewidth
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"regexp"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
var reLoc = regexp.MustCompile(`^[a-z][a-z][a-z]?(?:_[A-Z][A-Z])?\.(.+)`)
|
|
||||||
|
|
||||||
var mblenTable = map[string]int{
|
|
||||||
"utf-8": 6,
|
|
||||||
"utf8": 6,
|
|
||||||
"jis": 8,
|
|
||||||
"eucjp": 3,
|
|
||||||
"euckr": 2,
|
|
||||||
"euccn": 2,
|
|
||||||
"sjis": 2,
|
|
||||||
"cp932": 2,
|
|
||||||
"cp51932": 2,
|
|
||||||
"cp936": 2,
|
|
||||||
"cp949": 2,
|
|
||||||
"cp950": 2,
|
|
||||||
"big5": 2,
|
|
||||||
"gbk": 2,
|
|
||||||
"gb2312": 2,
|
|
||||||
}
|
|
||||||
|
|
||||||
func isEastAsian(locale string) bool {
|
|
||||||
charset := strings.ToLower(locale)
|
|
||||||
r := reLoc.FindStringSubmatch(locale)
|
|
||||||
if len(r) == 2 {
|
|
||||||
charset = strings.ToLower(r[1])
|
|
||||||
}
|
|
||||||
|
|
||||||
if strings.HasSuffix(charset, "@cjk_narrow") {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
for pos, b := range []byte(charset) {
|
|
||||||
if b == '@' {
|
|
||||||
charset = charset[:pos]
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
max := 1
|
|
||||||
if m, ok := mblenTable[charset]; ok {
|
|
||||||
max = m
|
|
||||||
}
|
|
||||||
if max > 1 && (charset[0] != 'u' ||
|
|
||||||
strings.HasPrefix(locale, "ja") ||
|
|
||||||
strings.HasPrefix(locale, "ko") ||
|
|
||||||
strings.HasPrefix(locale, "zh")) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsEastAsian return true if the current locale is CJK
|
|
||||||
func IsEastAsian() bool {
|
|
||||||
locale := os.Getenv("LC_CTYPE")
|
|
||||||
if locale == "" {
|
|
||||||
locale = os.Getenv("LANG")
|
|
||||||
}
|
|
||||||
|
|
||||||
// ignore C locale
|
|
||||||
if locale == "POSIX" || locale == "C" {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if len(locale) > 1 && locale[0] == 'C' && (locale[1] == '.' || locale[1] == '-') {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return isEastAsian(locale)
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
package runewidth
|
|
||||||
|
|
||||||
import (
|
|
||||||
"syscall"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
kernel32 = syscall.NewLazyDLL("kernel32")
|
|
||||||
procGetConsoleOutputCP = kernel32.NewProc("GetConsoleOutputCP")
|
|
||||||
)
|
|
||||||
|
|
||||||
// IsEastAsian return true if the current locale is CJK
|
|
||||||
func IsEastAsian() bool {
|
|
||||||
r1, _, _ := procGetConsoleOutputCP.Call()
|
|
||||||
if r1 == 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
switch int(r1) {
|
|
||||||
case 932, 51932, 936, 949, 950:
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
13
vendor/github.com/apcera/termtables/vendor/manifest
generated
vendored
13
vendor/github.com/apcera/termtables/vendor/manifest
generated
vendored
@ -1,13 +0,0 @@
|
|||||||
{
|
|
||||||
"version": 0,
|
|
||||||
"dependencies": [
|
|
||||||
{
|
|
||||||
"importpath": "github.com/mattn/go-runewidth",
|
|
||||||
"repository": "https://github.com/mattn/go-runewidth",
|
|
||||||
"vcs": "git",
|
|
||||||
"revision": "14207d285c6c197daabb5c9793d63e7af9ab2d50",
|
|
||||||
"branch": "master",
|
|
||||||
"notests": true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user