<commit_before>package kingpin

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"sort"
	"strings"

	"go/doc"

	"github.com/kr/pty"
)

func guessWidth(w io.Writer) int {
	width := 80
	if width == 0 {
		if t, ok := w.(*os.File); ok {
			if _, cols, err := pty.Getsize(t); err == nil {
				width = cols
			}
		}
	}
	return width
}

func (c *Commander) Usage(w io.Writer) {
	c.writeHelp(guessWidth(w), w)
}

func (c *Commander) CommandUsage(w io.Writer, command string) {
	cmd, ok := c.commands[command]
	if !ok {
		UsageErrorf("unknown command '%s'", command)
	}
	s := []string{formatArgsAndFlags(c.name, c.argGroup, c.flagGroup, true)}
	s = append(s, formatArgsAndFlags(cmd.name, cmd.argGroup, cmd.flagGroup, true))
	fmt.Fprintf(w, "usage: %s\n", strings.Join(s, " "))
	if cmd.help != "" {
		fmt.Fprintf(w, "\n%s\n", cmd.help)
	}
	cmd.writeHelp(guessWidth(w), w)
}

func (c *Commander) writeHelp(width int, w io.Writer) {
	s := []string{formatArgsAndFlags(c.name, c.argGroup, c.flagGroup, true)}
	if len(c.commands) > 0 {
		s = append(s, "<command>", "[<flags>]", "[<args> ...]")
	}

	helpSummary := ""
	if c.help != "" {
		helpSummary = "\n\n" + c.help
	}
	fmt.Fprintf(w, "usage: %s%s\n", strings.Join(s, " "), helpSummary)

	c.flagGroup.writeHelp(2, width, w)
	c.argGroup.writeHelp(2, width, w)

	if len(c.commands) > 0 {
		fmt.Fprintf(w, "\nCommands:\n")
		c.helpCommands(width, w)
	}
}

func (c *Commander) helpCommands(width int, w io.Writer) {
	l := 0
	commands := []string{}
	for _, cmd := range c.commands {
		if cl := len(formatArgsAndFlags(cmd.name, cmd.argGroup, cmd.flagGroup, false)); cl > l {
			l = cl
		}
		commands = append(commands, cmd.name)
	}

	sort.Strings(commands)

	l += 5
	indentStr := strings.Repeat(" ", l)

	for _, name := range commands {
		cmd := c.commands[name]
		prefix := fmt.Sprintf("  %-*s", l-2, formatArgsAndFlags(cmd.name, cmd.argGroup, cmd.flagGroup, false))
		buf := bytes.NewBuffer(nil)
		doc.ToText(buf, cmd.help, "", "", width-l)
		lines := strings.Split(strings.TrimRight(buf.String(), "\n"), "\n")
		fmt.Fprintf(w, "%s%s\n", prefix, lines[0])
		for _, line := range lines[1:] {
			fmt.Fprintf(w, "%s%s\n", indentStr, line)
		}
	}
}

func (f *flagGroup) writeHelp(indent, width int, w io.Writer) {
	if len(f.long) == 0 {
		return
	}

	fmt.Fprintf(w, "\nFlags:\n")
	l := 0
	for _, flag := range f.long {
		if fl := len(formatFlag(flag)); fl > l {
			l = fl
		}
	}

	l += 3 + indent

	indentStr := strings.Repeat(" ", l)

	for _, flag := range f.long {
		prefix := fmt.Sprintf("  %-*s", l-2, formatFlag(flag))
		buf := bytes.NewBuffer(nil)
		doc.ToText(buf, flag.help, "", "", width-l)<commit_msg>Also sort flags.<commit_after>package kingpin

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"sort"
	"strings"

	"go/doc"

	"github.com/kr/pty"
)

func guessWidth(w io.Writer) int {
	width := 80
	if width == 0 {
		if t, ok := w.(*os.File); ok {
			if _, cols, err := pty.Getsize(t); err == nil {
				width = cols
			}
		}
	}
	return width
}

func (c *Commander) Usage(w io.Writer) {
	c.writeHelp(guessWidth(w), w)
}

func (c *Commander) CommandUsage(w io.Writer, command string) {
	cmd, ok := c.commands[command]
	if !ok {
		UsageErrorf("unknown command '%s'", command)
	}
	s := []string{formatArgsAndFlags(c.name, c.argGroup, c.flagGroup, true)}
	s = append(s, formatArgsAndFlags(cmd.name, cmd.argGroup, cmd.flagGroup, true))
	fmt.Fprintf(w, "usage: %s\n", strings.Join(s, " "))
	if cmd.help != "" {
		fmt.Fprintf(w, "\n%s\n", cmd.help)
	}
	cmd.writeHelp(guessWidth(w), w)
}

func (c *Commander) writeHelp(width int, w io.Writer) {
	s := []string{formatArgsAndFlags(c.name, c.argGroup, c.flagGroup, true)}
	if len(c.commands) > 0 {
		s = append(s, "<command>", "[<flags>]", "[<args> ...]")
	}

	helpSummary := ""
	if c.help != "" {
		helpSummary = "\n\n" + c.help
	}
	fmt.Fprintf(w, "usage: %s%s\n", strings.Join(s, " "), helpSummary)

	c.flagGroup.writeHelp(2, width, w)
	c.argGroup.writeHelp(2, width, w)

	if len(c.commands) > 0 {
		fmt.Fprintf(w, "\nCommands:\n")
		c.helpCommands(width, w)
	}
}

func (c *Commander) helpCommands(width int, w io.Writer) {
	l := 0
	commands := []string{}
	for _, cmd := range c.commands {
		if cl := len(formatArgsAndFlags(cmd.name, cmd.argGroup, cmd.flagGroup, false)); cl > l {
			l = cl
		}
		commands = append(commands, cmd.name)
	}

	sort.Strings(commands)

	l += 5
	indentStr := strings.Repeat(" ", l)

	for _, name := range commands {
		cmd := c.commands[name]
		prefix := fmt.Sprintf("  %-*s", l-2, formatArgsAndFlags(cmd.name, cmd.argGroup, cmd.flagGroup, false))
		buf := bytes.NewBuffer(nil)
		doc.ToText(buf, cmd.help, "", "", width-l)
		lines := strings.Split(strings.TrimRight(buf.String(), "\n"), "\n")
		fmt.Fprintf(w, "%s%s\n", prefix, lines[0])
		for _, line := range lines[1:] {
			fmt.Fprintf(w, "%s%s\n", indentStr, line)
		}
	}
}

func (f *flagGroup) writeHelp(indent, width int, w io.Writer) {
	if len(f.long) == 0 {
		return
	}

	names := []string{}
	fmt.Fprintf(w, "\nFlags:\n")
	l := 0
	for _, flag := range f.long {
		if fl := len(formatFlag(flag)); fl > l {
			l = fl
		}
		names = append(names, flag.name)
	}
	sort.Strings(names)

	l += 3 + indent

	indentStr := strings.Repeat(" ", l)

	for _, name := range names {
		flag := f.long[name]
		prefix := fmt.Sprintf("  %-*s", l-2, formatFlag(flag))
		buf := bytes.NewBuffer(nil)
		doc.ToText(buf, flag.help, "", "", width-l)
{'fraction_non_alphanumeric': 0.2042910447761194, 'fraction_numerical': 0.005970149253731343, 'mean_word_length': 3.5088309503784694, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1803509', 'n_tokens_mistral': 2317, 'n_tokens_neox': 2194, 'n_words': 489}