Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cli punchlist #1272

Merged
merged 4 commits into from
Jan 24, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 1 addition & 16 deletions app/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,22 +78,7 @@ func RootCmd() *cobra.Command {
cmd.AddCommand(verCmd.NewVersionCmd())

// Apply the custom help function to the current command
shared.SetSanitizedHelpFunc(cmd)

// Recursively apply to all subcommands
for _, subCmd := range cmd.Commands() {
applySanitizedHelpFuncRecursively(subCmd)
}
shared.ApplySanitizedHelpFuncRecursively(cmd)

return cmd
}

func applySanitizedHelpFuncRecursively(cmd *cobra.Command) {
// Apply the custom help function to the current command
shared.SetSanitizedHelpFunc(cmd)

// Recursively apply to all subcommands
for _, subCmd := range cmd.Commands() {
applySanitizedHelpFuncRecursively(subCmd)
}
}
7 changes: 4 additions & 3 deletions app/shared/generate/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
type writeFunc func(string) (*os.File, error)

func WriteDocs(cmd *cobra.Command, dir string) error {

return writeCmd(cmd, ".", 0, func(s string) (*os.File, error) {
fullPath := filepath.Join(dir, s)
err := os.MkdirAll(filepath.Dir(fullPath), 0755)
Expand Down Expand Up @@ -71,7 +72,7 @@ func createIndexFile(cmd *cobra.Command, dir string, write writeFunc, first bool

file.WriteString(header.String() + "\n\n")

return doc.GenMarkdownCustom(cmd, file, linkHandler(dir))
return doc.GenMarkdownCustom(cmd, file, linkHandler())
}

// createCmdFile creates a file for the command, and writes the command's documentation to it.
Expand All @@ -94,10 +95,10 @@ func createCmdFile(cmd *cobra.Command, dir string, idx int, write writeFunc) err

file.WriteString(header.String() + "\n\n")

return doc.GenMarkdownCustom(cmd, file, linkHandler(dir))
return doc.GenMarkdownCustom(cmd, file, linkHandler())
}

func linkHandler(dir string) func(string) string { // dir string unused -- what is it?
func linkHandler() func(string) string {
return func(s string) string {
// trying just linking ids??
s = strings.TrimSuffix(s, ".md")
Expand Down
14 changes: 12 additions & 2 deletions app/shared/help.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ func SetSanitizedHelpFunc(cmd *cobra.Command) {
originalHelpFunc := cmd.HelpFunc()

cmd.SetHelpFunc(func(cmd *cobra.Command, args []string) {
cmd.Short = removeBackticks(cmd.Short)
cmd.Long = removeBackticks(cmd.Long)
cmd.Short = wrapTextToTerminalWidth(removeBackticks(cmd.Short))
cmd.Long = wrapTextToTerminalWidth(removeBackticks(cmd.Long))
wrapFlags(cmd.Flags())
wrapFlags(cmd.PersistentFlags())

// Delegate to the original HelpFunc to avoid recursion
if originalHelpFunc != nil {
Expand All @@ -32,3 +34,11 @@ func SetSanitizedHelpFunc(cmd *cobra.Command) {
}
})
}

func ApplySanitizedHelpFuncRecursively(cmd *cobra.Command) {
SetSanitizedHelpFunc(cmd)

for _, subCmd := range cmd.Commands() {
ApplySanitizedHelpFuncRecursively(subCmd)
}
}
170 changes: 170 additions & 0 deletions app/shared/wrap.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
package shared

import (
"os"
"strings"

"github.com/spf13/pflag"
"golang.org/x/term"
)

// wrapTextToTerminalWidth wraps text by detecting the current
// terminal width (columns) and using that as the wrap limit.
// If it can't get the terminal width, it will wrap it to 80
func wrapTextToTerminalWidth(text string) string {
Comment on lines +11 to +14
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Excellent! The lack of wrapping has really stood out to me, but never took the time to propose a solution. 👍

// Get the terminal size from standard output.
width, _, err := term.GetSize(int(os.Stdout.Fd()))
if err != nil {
width = 80
}

return WrapText(text, width)
}

// WrapText wraps text by the specified width
func WrapText(text string, width int) string {
return wrapText(text, width-2) // for safety, sometimes terminal still doesn't wrap properly
}

// wrapFlag wraps all flag descriptions. It does this by accounting for the characters
// that are to the left of the flag description, as well as the terminal width.
// If the width can't be determined, it won't wrap the flags.
func wrapFlags(f *pflag.FlagSet) {
width, _, err := term.GetSize(int(os.Stdout.Fd()))
if err != nil {
return
}

/* example unwrapped output:
Flags:
--csv string CSV file containing the parameters to pass to the action
-m, --csv-mapping stringArray mapping of CSV columns to action parameters. format: "csv_column:action_param_name" OR "csv_column:action_param_position"
-h, --help help for exec-action
-n, --namespace string namespace to execute the action in
-N, --nonce int nonce override (-1 means request from server) (default -1)
-p, --param stringArray named parameters that will override any positional or CSV parameters. format: "name:type=value"
--sync synchronous broadcast (wait for it to be included in a block)

Global Flags:
-Y, --assume-yes Assume yes for all prompts
--chain-id string the expected/intended Kwil Chain ID
-c, --config string the path to the Kwil CLI persistent global settings file (default "/Users/brennanlamey/.kwil-cli/config.json")
--output string the format for command output - either 'text' or 'json' (default "text")
--private-key string the private key of the wallet that will be used for signing
--provider string the Kwil provider RPC endpoint (default "http://127.0.0.1:8484")
-S, --silence Silence logs
*/

// we first find the widest flag (shorthand, long, and type).
// Cobra adjusts the width of all flags to the widest flag.
var widest int
f.VisitAll(func(f *pflag.Flag) {
length := 2 // initial offset value
if f.Shorthand != "" {
length += 2 // -x,
}
if f.Shorthand != "" && f.Name != "" {
length += 2 // account for the comma and space between: -x, --name
}
if f.Name != "" {
length += len(f.Name) + 2 // --name
}
if f.Value.Type() != "" {
length += len(f.Value.Type()) + 1 // type, plus the space between type and name
}
// an additional 3 spaces, between the end and the start of the description
length += 3

if length > widest {
widest = length
}
})

wrapTo := width - widest - 4
// now we wrap the descriptions
f.VisitAll(func(f *pflag.Flag) {
if f.Usage == "" {
return
}

str := f.Usage

f.Usage = wrapLine(str, wrapTo)
})
}

// wrapLine wraps a single paragraph (with no \n) to the given width.
func wrapLine(text string, width int) string {
words := strings.Fields(text)
if len(words) == 0 {
return ""
}

var sb strings.Builder
lineLen := 0

for i, w := range words {
// First word on a line
if i == 0 {
sb.WriteString(w)
lineLen = len(w)
continue
}
// Check if adding this word + 1 space exceeds width
if lineLen+1+len(w) > width {
sb.WriteString("\n")
sb.WriteString(w)
lineLen = len(w)
} else {
sb.WriteString(" ")
sb.WriteString(w)
lineLen += 1 + len(w)
}
}

return sb.String()
}

// wrapText removes single line breaks (replacing them with spaces),
// preserves double breaks (or lines starting with '-') as separators,
// and wraps each "paragraph" to the given width.
func wrapText(text string, width int) string {
// Split the original text by lines
lines := strings.Split(text, "\n")

var resultParts []string
var currentParagraph []string

// Flush the current paragraph: join with spaces, wrap, add to results
flushParagraph := func() {
if len(currentParagraph) > 0 {
joined := strings.Join(currentParagraph, " ")
wrapped := wrapLine(joined, width)
resultParts = append(resultParts, wrapped)
currentParagraph = nil
}
}

for _, line := range lines {
trimmed := strings.TrimSpace(line)

// If line is blank or starts with '-', we preserve it as-is (separator).
if trimmed == "" || strings.HasPrefix(trimmed, "-") {
// Flush whatever paragraph we have so far
flushParagraph()
// Then just keep this line as its own entry (unwrapped).
// For blank lines, 'trimmed' == "", but we append the original line
// so it remains a visual blank line. Or if it's "-something", keep it as is.
resultParts = append(resultParts, line)
} else {
// Accumulate into our current paragraph
currentParagraph = append(currentParagraph, trimmed)
}
}

// Flush last paragraph if needed
flushParagraph()

// Rejoin everything with newlines
return strings.Join(resultParts, "\n")
}
3 changes: 3 additions & 0 deletions cmd/kwil-cli/cmds/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"

"github.com/kwilteam/kwil-db/app/custom"
"github.com/kwilteam/kwil-db/app/shared"
"github.com/kwilteam/kwil-db/app/shared/bind"
"github.com/kwilteam/kwil-db/app/shared/display"
"github.com/kwilteam/kwil-db/app/shared/version"
Expand Down Expand Up @@ -72,5 +73,7 @@ func NewRootCmd() *cobra.Command {
queryCmd(),
)

shared.ApplySanitizedHelpFuncRecursively(rootCmd)

return rootCmd
}
Loading