diff options
author | Jhon Honce <jhonce@redhat.com> | 2020-10-20 10:29:49 -0700 |
---|---|---|
committer | Jhon Honce <jhonce@redhat.com> | 2020-10-21 08:16:52 -0700 |
commit | bab3cda0e81fa3ac3315601f5ec17724f3ad8ed5 (patch) | |
tree | 14ad37445fe86fc55db7907d657f40f0027d92b8 /vendor/github.com | |
parent | f96dbd0896eac8730142cf694485543275764195 (diff) | |
download | podman-bab3cda0e81fa3ac3315601f5ec17724f3ad8ed5.tar.gz podman-bab3cda0e81fa3ac3315601f5ec17724f3ad8ed5.tar.bz2 podman-bab3cda0e81fa3ac3315601f5ec17724f3ad8ed5.zip |
Refactor podman to use c/common/pkg/report
All formatting for containers stack moved into one package
The does not correct issue with headers when using custom tables
Signed-off-by: Jhon Honce <jhonce@redhat.com>
Diffstat (limited to 'vendor/github.com')
7 files changed, 369 insertions, 0 deletions
diff --git a/vendor/github.com/containers/common/pkg/report/camelcase/LICENSE.md b/vendor/github.com/containers/common/pkg/report/camelcase/LICENSE.md new file mode 100644 index 000000000..aa4a536ca --- /dev/null +++ b/vendor/github.com/containers/common/pkg/report/camelcase/LICENSE.md @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2015 Fatih Arslan + +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. diff --git a/vendor/github.com/containers/common/pkg/report/camelcase/README.md b/vendor/github.com/containers/common/pkg/report/camelcase/README.md new file mode 100644 index 000000000..105a6ae33 --- /dev/null +++ b/vendor/github.com/containers/common/pkg/report/camelcase/README.md @@ -0,0 +1,58 @@ +# CamelCase [![GoDoc](http://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)](http://godoc.org/github.com/fatih/camelcase) [![Build Status](http://img.shields.io/travis/fatih/camelcase.svg?style=flat-square)](https://travis-ci.org/fatih/camelcase) + +CamelCase is a Golang (Go) package to split the words of a camelcase type +string into a slice of words. It can be used to convert a camelcase word (lower +or upper case) into any type of word. + +## Splitting rules: + +1. If string is not valid UTF-8, return it without splitting as + single item array. +2. Assign all unicode characters into one of 4 sets: lower case + letters, upper case letters, numbers, and all other characters. +3. Iterate through characters of string, introducing splits + between adjacent characters that belong to different sets. +4. Iterate through array of split strings, and if a given string + is upper case: + * if subsequent string is lower case: + * move last character of upper case string to beginning of + lower case string + +## Install + +```bash +go get github.com/fatih/camelcase +``` + +## Usage and examples + +```go +splitted := camelcase.Split("GolangPackage") + +fmt.Println(splitted[0], splitted[1]) // prints: "Golang", "Package" +``` + +Both lower camel case and upper camel case are supported. For more info please +check: [http://en.wikipedia.org/wiki/CamelCase](http://en.wikipedia.org/wiki/CamelCase) + +Below are some example cases: + +``` +"" => [] +"lowercase" => ["lowercase"] +"Class" => ["Class"] +"MyClass" => ["My", "Class"] +"MyC" => ["My", "C"] +"HTML" => ["HTML"] +"PDFLoader" => ["PDF", "Loader"] +"AString" => ["A", "String"] +"SimpleXMLParser" => ["Simple", "XML", "Parser"] +"vimRPCPlugin" => ["vim", "RPC", "Plugin"] +"GL11Version" => ["GL", "11", "Version"] +"99Bottles" => ["99", "Bottles"] +"May5" => ["May", "5"] +"BFG9000" => ["BFG", "9000"] +"BöseÜberraschung" => ["Böse", "Überraschung"] +"Two spaces" => ["Two", " ", "spaces"] +"BadUTF8\xe2\xe2\xa1" => ["BadUTF8\xe2\xe2\xa1"] +``` diff --git a/vendor/github.com/containers/common/pkg/report/camelcase/camelcase.go b/vendor/github.com/containers/common/pkg/report/camelcase/camelcase.go new file mode 100644 index 000000000..0a82d1005 --- /dev/null +++ b/vendor/github.com/containers/common/pkg/report/camelcase/camelcase.go @@ -0,0 +1,91 @@ +// Package camelcase is a micro package to split the words of a camelcase type +// string into a slice of words. +package camelcase + +import ( + "unicode" + "unicode/utf8" +) + +// Split splits the camelcase word and returns a list of words. It also +// supports digits. Both lower camel case and upper camel case are supported. +// For more info please check: http://en.wikipedia.org/wiki/CamelCase +// +// Examples +// +// "" => [""] +// "lowercase" => ["lowercase"] +// "Class" => ["Class"] +// "MyClass" => ["My", "Class"] +// "MyC" => ["My", "C"] +// "HTML" => ["HTML"] +// "PDFLoader" => ["PDF", "Loader"] +// "AString" => ["A", "String"] +// "SimpleXMLParser" => ["Simple", "XML", "Parser"] +// "vimRPCPlugin" => ["vim", "RPC", "Plugin"] +// "GL11Version" => ["GL", "11", "Version"] +// "99Bottles" => ["99", "Bottles"] +// "May5" => ["May", "5"] +// "BFG9000" => ["BFG", "9000"] +// "BöseÜberraschung" => ["Böse", "Überraschung"] +// "Two spaces" => ["Two", " ", "spaces"] +// "BadUTF8\xe2\xe2\xa1" => ["BadUTF8\xe2\xe2\xa1"] +// +// Splitting rules +// +// 1) If string is not valid UTF-8, return it without splitting as +// single item array. +// 2) Assign all unicode characters into one of 4 sets: lower case +// letters, upper case letters, numbers, and all other characters. +// 3) Iterate through characters of string, introducing splits +// between adjacent characters that belong to different sets. +// 4) Iterate through array of split strings, and if a given string +// is upper case: +// if subsequent string is lower case: +// move last character of upper case string to beginning of +// lower case string +func Split(src string) (entries []string) { + // don't split invalid utf8 + if !utf8.ValidString(src) { + return []string{src} + } + entries = []string{} + var runes [][]rune + lastClass := 0 + class := 0 + // split into fields based on class of unicode character + for _, r := range src { + switch { + case unicode.IsLower(r): + class = 1 + case unicode.IsUpper(r): + class = 2 + case unicode.IsDigit(r): + class = 3 + default: + class = 4 + } + if class == lastClass { + runes[len(runes)-1] = append(runes[len(runes)-1], r) + } else { + runes = append(runes, []rune{r}) + } + lastClass = class + } + // handle upper case -> lower case sequences, e.g. + // "PDFL", "oader" -> "PDF", "Loader" + for i := 0; i < len(runes)-1; i++ { + if unicode.IsUpper(runes[i][0]) && unicode.IsLower(runes[i+1][0]) { + runes[i+1] = append([]rune{runes[i][len(runes[i])-1]}, runes[i+1]...) + runes[i] = runes[i][:len(runes[i])-1] + } + } + // construct []string from results + for _, s := range runes { + if len(s) > 0 { + entries = append(entries, string(s)) + } + } + + return entries +} diff --git a/vendor/github.com/containers/common/pkg/report/doc.go b/vendor/github.com/containers/common/pkg/report/doc.go new file mode 100644 index 000000000..60d954d7e --- /dev/null +++ b/vendor/github.com/containers/common/pkg/report/doc.go @@ -0,0 +1,46 @@ +/* +Package report provides helper structs/methods/funcs for formatting output + +To format output for an array of structs: + + w := report.NewWriterDefault(os.Stdout) + defer w.Flush() + + headers := report.Headers(struct { + ID string + }{}, nil) + t, _ := report.NewTemplate("command name").Parse("{{range .}}{{.ID}}{{end}}") + t.Execute(t, headers) + t.Execute(t, map[string]string{ + "ID":"fa85da03b40141899f3af3de6d27852b", + }) + // t.IsTable() == false + +or + + w := report.NewWriterDefault(os.Stdout) + defer w.Flush() + + headers := report.Headers(struct { + CID string + }{}, map[string]string{ + "CID":"ID"}) + t, _ := report.NewTemplate("command name").Parse("table {{.CID}}") + t.Execute(t, headers) + t.Execute(t,map[string]string{ + "CID":"fa85da03b40141899f3af3de6d27852b", + }) + // t.IsTable() == true + +Helpers: + + if report.IsJSON(cmd.Flag("format").Value.String()) { + ... process JSON and output + } + +and + + +Note: Your code should not ignore errors +*/ +package report diff --git a/vendor/github.com/containers/common/pkg/report/template.go b/vendor/github.com/containers/common/pkg/report/template.go new file mode 100644 index 000000000..07f9634a6 --- /dev/null +++ b/vendor/github.com/containers/common/pkg/report/template.go @@ -0,0 +1,114 @@ +package report + +import ( + "reflect" + "strings" + "text/template" + + "github.com/containers/common/pkg/report/camelcase" +) + +// Template embeds template.Template to add functionality to methods +type Template struct { + *template.Template + isTable bool +} + +// FuncMap is aliased from template.FuncMap +type FuncMap template.FuncMap + +// tableReplacer will remove 'table ' prefix and clean up tabs +var tableReplacer = strings.NewReplacer( + "table ", "", + `\t`, "\t", + `\n`, "\n", + " ", "\t", +) + +// escapedReplacer will clean up escaped characters from CLI +var escapedReplacer = strings.NewReplacer( + `\t`, "\t", + `\n`, "\n", +) + +// NormalizeFormat reads given go template format provided by CLI and munges it into what we need +func NormalizeFormat(format string) string { + var f string + // two replacers used so we only remove the prefix keyword `table` + if strings.HasPrefix(format, "table ") { + f = tableReplacer.Replace(format) + } else { + f = escapedReplacer.Replace(format) + } + + if !strings.HasSuffix(f, "\n") { + f += "\n" + } + + return f +} + +// Headers queries the interface for field names. +// Array of map is returned to support range templates +// Note: unexported fields can be supported by adding field to overrides +// Note: It is left to the developer to write out said headers +// Podman commands use the general rules of: +// 1) unchanged --format includes headers +// 2) --format '{{.ID}" # no headers +// 3) --format 'table {{.ID}}' # includes headers +func Headers(object interface{}, overrides map[string]string) []map[string]string { + value := reflect.ValueOf(object) + if value.Kind() == reflect.Ptr { + value = value.Elem() + } + + // Column header will be field name upper-cased. + headers := make(map[string]string, value.NumField()) + for i := 0; i < value.Type().NumField(); i++ { + field := value.Type().Field(i) + // Recurse to find field names from promoted structs + if field.Type.Kind() == reflect.Struct && field.Anonymous { + h := Headers(reflect.New(field.Type).Interface(), nil) + for k, v := range h[0] { + headers[k] = v + } + continue + } + name := strings.Join(camelcase.Split(field.Name), " ") + headers[field.Name] = strings.ToUpper(name) + } + + if len(overrides) > 0 { + // Override column header as provided + for k, v := range overrides { + headers[k] = strings.ToUpper(v) + } + } + return []map[string]string{headers} +} + +// NewTemplate creates a new template object +func NewTemplate(name string) *Template { + return &Template{template.New(name), false} +} + +// Parse parses text as a template body for t +func (t *Template) Parse(text string) (*Template, error) { + if strings.HasPrefix(text, "table ") { + t.isTable = true + text = "{{range .}}" + NormalizeFormat(text) + "{{end}}" + } + + tt, err := t.Template.Parse(text) + return &Template{tt, t.isTable}, err +} + +// Funcs adds the elements of the argument map to the template's function map +func (t *Template) Funcs(funcMap FuncMap) *Template { + return &Template{t.Template.Funcs(template.FuncMap(funcMap)), t.isTable} +} + +// IsTable returns true if format string defines a "table" +func (t *Template) IsTable() bool { + return t.isTable +} diff --git a/vendor/github.com/containers/common/pkg/report/validate.go b/vendor/github.com/containers/common/pkg/report/validate.go new file mode 100644 index 000000000..a5eac5328 --- /dev/null +++ b/vendor/github.com/containers/common/pkg/report/validate.go @@ -0,0 +1,13 @@ +package report + +import "regexp" + +var jsonRegex = regexp.MustCompile(`^\s*(json|{{\s*json\s*(\.)?\s*}})\s*$`) + +// JSONFormat test CLI --format string to be a JSON request +// if report.IsJSON(cmd.Flag("format").Value.String()) { +// ... process JSON and output +// } +func IsJSON(s string) bool { + return jsonRegex.MatchString(s) +} diff --git a/vendor/github.com/containers/common/pkg/report/writer.go b/vendor/github.com/containers/common/pkg/report/writer.go new file mode 100644 index 000000000..360ef8265 --- /dev/null +++ b/vendor/github.com/containers/common/pkg/report/writer.go @@ -0,0 +1,27 @@ +package report + +import ( + "io" + "text/tabwriter" +) + +// Writer aliases tabwriter.Writer to provide Podman defaults +type Writer struct { + *tabwriter.Writer +} + +// NewWriter initializes a new report.Writer with given values +func NewWriter(output io.Writer, minwidth, tabwidth, padding int, padchar byte, flags uint) (*Writer, error) { + t := tabwriter.NewWriter(output, minwidth, tabwidth, padding, padchar, flags) + return &Writer{t}, nil +} + +// NewWriterDefault initializes a new report.Writer with Podman defaults +func NewWriterDefault(output io.Writer) (*Writer, error) { + return NewWriter(output, 12, 2, 2, ' ', 0) +} + +// Flush any output left in buffers +func (w *Writer) Flush() error { + return w.Writer.Flush() +} |