mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-22 03:11:40 +00:00
Merge pull request #91801 from liggitt/kubectl-explain
Improve kubectl explain formatting-preservation
This commit is contained in:
commit
0281b85640
@ -41,6 +41,7 @@ go_test(
|
|||||||
deps = [
|
deps = [
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/api/meta/testrestmapper:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/api/meta/testrestmapper:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||||
|
"//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library",
|
||||||
"//staging/src/k8s.io/kubectl/pkg/scheme:go_default_library",
|
"//staging/src/k8s.io/kubectl/pkg/scheme:go_default_library",
|
||||||
"//staging/src/k8s.io/kubectl/pkg/util/openapi/testing:go_default_library",
|
"//staging/src/k8s.io/kubectl/pkg/util/openapi/testing:go_default_library",
|
||||||
],
|
],
|
||||||
|
@ -19,6 +19,7 @@ package explain
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -103,22 +104,75 @@ func (l *line) Add(word string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var bullet = regexp.MustCompile(`^(\d+\.?|-|\*)\s`)
|
||||||
|
|
||||||
|
func shouldStartNewLine(lastWord, str string) bool {
|
||||||
|
// preserve line breaks ending in :
|
||||||
|
if strings.HasSuffix(lastWord, ":") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// preserve code blocks
|
||||||
|
if strings.HasPrefix(str, " ") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
str = strings.TrimSpace(str)
|
||||||
|
// preserve empty lines
|
||||||
|
if len(str) == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// preserve lines that look like they're starting lists
|
||||||
|
if bullet.MatchString(str) == true {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// otherwise combine
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
func wrapString(str string, wrap int) []string {
|
func wrapString(str string, wrap int) []string {
|
||||||
words := strings.Fields(str)
|
|
||||||
wrapped := []string{}
|
wrapped := []string{}
|
||||||
l := line{wrap: wrap}
|
l := line{wrap: wrap}
|
||||||
|
// track the last word added to the current line
|
||||||
for _, word := range words {
|
lastWord := ""
|
||||||
if !l.Add(word) {
|
flush := func() {
|
||||||
|
if !l.Empty() {
|
||||||
|
lastWord = ""
|
||||||
wrapped = append(wrapped, l.String())
|
wrapped = append(wrapped, l.String())
|
||||||
l = line{wrap: wrap}
|
l = line{wrap: wrap}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// iterate over the lines in the original description
|
||||||
|
for _, str := range strings.Split(str, "\n") {
|
||||||
|
// preserve code blocks and blockquotes as-is
|
||||||
|
if strings.HasPrefix(str, " ") {
|
||||||
|
flush()
|
||||||
|
wrapped = append(wrapped, str)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// preserve empty lines after the first line, since they can separate logical sections
|
||||||
|
if len(wrapped) > 0 && len(strings.TrimSpace(str)) == 0 {
|
||||||
|
flush()
|
||||||
|
wrapped = append(wrapped, "")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// flush if we should start a new line
|
||||||
|
if shouldStartNewLine(lastWord, str) {
|
||||||
|
flush()
|
||||||
|
}
|
||||||
|
words := strings.Fields(str)
|
||||||
|
for _, word := range words {
|
||||||
|
lastWord = word
|
||||||
if !l.Add(word) {
|
if !l.Add(word) {
|
||||||
panic("Couldn't add to empty line.")
|
flush()
|
||||||
|
if !l.Add(word) {
|
||||||
|
panic("Couldn't add to empty line.")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !l.Empty() {
|
flush()
|
||||||
wrapped = append(wrapped, l.String())
|
|
||||||
}
|
|
||||||
return wrapped
|
return wrapped
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,8 @@ package explain
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"k8s.io/apimachinery/pkg/util/diff"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestFormatterWrite(t *testing.T) {
|
func TestFormatterWrite(t *testing.T) {
|
||||||
@ -54,6 +56,30 @@ func TestFormatterWrappedWrite(t *testing.T) {
|
|||||||
f.Indent(10).WriteWrapped("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi at turpis faucibus, gravida dolor ut, fringilla velit.")
|
f.Indent(10).WriteWrapped("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi at turpis faucibus, gravida dolor ut, fringilla velit.")
|
||||||
// Test long words (especially urls) on their own line.
|
// Test long words (especially urls) on their own line.
|
||||||
f.Indent(20).WriteWrapped("Lorem ipsum dolor sit amet, consectetur adipiscing elit. ThisIsAVeryLongWordThatDoesn'tFitOnALineOnItsOwn. Morbi at turpis faucibus, gravida dolor ut, fringilla velit.")
|
f.Indent(20).WriteWrapped("Lorem ipsum dolor sit amet, consectetur adipiscing elit. ThisIsAVeryLongWordThatDoesn'tFitOnALineOnItsOwn. Morbi at turpis faucibus, gravida dolor ut, fringilla velit.")
|
||||||
|
// Test content that includes newlines, bullet points, and blockquotes/code blocks
|
||||||
|
f.Indent(4).WriteWrapped(`
|
||||||
|
This is an
|
||||||
|
introductory paragraph
|
||||||
|
that should end
|
||||||
|
up on a continuous line.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
Example text on its own line
|
||||||
|
|
||||||
|
List:
|
||||||
|
1. Item with
|
||||||
|
wrapping text
|
||||||
|
11. Another
|
||||||
|
item with wrapping text
|
||||||
|
* Bullet item
|
||||||
|
with wrapping text
|
||||||
|
- Dash item
|
||||||
|
with wrapping text
|
||||||
|
|
||||||
|
base64(
|
||||||
|
code goes here
|
||||||
|
and here
|
||||||
|
)`)
|
||||||
|
|
||||||
want := `Lorem ipsum dolor sit amet, consectetur adipiscing
|
want := `Lorem ipsum dolor sit amet, consectetur adipiscing
|
||||||
elit. Morbi at turpis faucibus, gravida dolor ut,
|
elit. Morbi at turpis faucibus, gravida dolor ut,
|
||||||
@ -68,10 +94,26 @@ fringilla velit.
|
|||||||
Morbi at turpis faucibus,
|
Morbi at turpis faucibus,
|
||||||
gravida dolor ut, fringilla
|
gravida dolor ut, fringilla
|
||||||
velit.
|
velit.
|
||||||
|
This is an introductory paragraph that should
|
||||||
|
end up on a continuous line.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
Example text on its own line
|
||||||
|
|
||||||
|
List:
|
||||||
|
1. Item with wrapping text
|
||||||
|
11. Another item with wrapping text
|
||||||
|
* Bullet item with wrapping text
|
||||||
|
- Dash item with wrapping text
|
||||||
|
|
||||||
|
base64(
|
||||||
|
code goes here
|
||||||
|
and here
|
||||||
|
)
|
||||||
`
|
`
|
||||||
|
|
||||||
if buf.String() != want {
|
if buf.String() != want {
|
||||||
t.Errorf("Got:\n%v\nWant:\n%v\n", buf.String(), want)
|
t.Errorf("Diff:\n%s", diff.StringDiff(buf.String(), want))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user