Parse roles in the help strings

This commit is contained in:
Kovid Goyal
2022-08-14 23:26:56 +05:30
parent c97556de65
commit abaafc2d68
4 changed files with 134 additions and 23 deletions

View File

@@ -29,6 +29,7 @@ is_macos: bool = 'darwin' in _plat
is_freebsd: bool = 'freebsd' in _plat is_freebsd: bool = 'freebsd' in _plat
is_running_from_develop: bool = False is_running_from_develop: bool = False
RC_ENCRYPTION_PROTOCOL_VERSION = '1' RC_ENCRYPTION_PROTOCOL_VERSION = '1'
website_base_url = 'https://sw.kovidgoyal.net/kitty/'
if getattr(sys, 'frozen', False): if getattr(sys, 'frozen', False):
extensions_dir: str = getattr(sys, 'kitty_run_data')['extensions_dir'] extensions_dir: str = getattr(sys, 'kitty_run_data')['extensions_dir']
@@ -243,7 +244,7 @@ def read_kitty_resource(name: str, package_name: str = 'kitty') -> bytes:
return (files(package_name) / name).read_bytes() return (files(package_name) / name).read_bytes()
def website_url(doc_name: str = '', website: str = 'https://sw.kovidgoyal.net/kitty/') -> str: def website_url(doc_name: str = '', website: str = website_base_url) -> str:
if doc_name: if doc_name:
base, _, frag = doc_name.partition('#') base, _, frag = doc_name.partition('#')
base = base.rstrip('/') base = base.rstrip('/')

View File

@@ -3,6 +3,7 @@ package cli
import ( import (
"fmt" "fmt"
"os" "os"
"regexp"
"strings" "strings"
"syscall" "syscall"
"unicode" "unicode"
@@ -16,6 +17,8 @@ import (
"kitty" "kitty"
) )
var RootCmd *cobra.Command
type Winsize struct { type Winsize struct {
Rows uint16 Rows uint16
Cols uint16 Cols uint16
@@ -78,6 +81,12 @@ var title_fmt = color.New(color.FgBlue, color.Bold).SprintFunc()
var exe_fmt = color.New(color.FgYellow, color.Bold).SprintFunc() var exe_fmt = color.New(color.FgYellow, color.Bold).SprintFunc()
var opt_fmt = color.New(color.FgGreen).SprintFunc() var opt_fmt = color.New(color.FgGreen).SprintFunc()
var italic_fmt = color.New(color.Italic).SprintFunc() var italic_fmt = color.New(color.Italic).SprintFunc()
var bold_fmt = color.New(color.Bold).SprintFunc()
var code_fmt = color.New(color.FgCyan).SprintFunc()
var cyan_fmt = color.New(color.FgCyan).SprintFunc()
var yellow_fmt = color.New(color.FgYellow).SprintFunc()
var blue_fmt = color.New(color.FgBlue).SprintFunc()
var green_fmt = color.New(color.FgGreen).SprintFunc()
func cmd_name(cmd *cobra.Command) string { func cmd_name(cmd *cobra.Command) string {
if cmd.Annotations != nil { if cmd.Annotations != nil {
@@ -91,22 +100,27 @@ func print_created_by(root *cobra.Command) {
fmt.Println(italic_fmt(root.Annotations["exe"]), opt_fmt(root.Version), "created by", title_fmt("Kovid Goyal")) fmt.Println(italic_fmt(root.Annotations["exe"]), opt_fmt(root.Version), "created by", title_fmt("Kovid Goyal"))
} }
func print_with_indent(text string, indent string, screen_width int) { func print_line_with_indent(text string, indent string, screen_width int) {
x := len(indent) x := len(indent)
fmt.Print(indent) fmt.Print(indent)
in_sgr := false in_sgr := false
current_word := "" var current_word strings.Builder
print_word := func(r rune) { print_word := func(r rune) {
w := runewidth.StringWidth(current_word) w := runewidth.StringWidth(current_word.String())
if x+w > screen_width { if x+w > screen_width {
fmt.Println() fmt.Println()
fmt.Print(indent) fmt.Print(indent)
x = len(indent) x = len(indent)
current_word = strings.TrimSpace(current_word) s := strings.TrimSpace(current_word.String())
current_word.Reset()
current_word.WriteString(s)
}
fmt.Print(current_word.String())
current_word.Reset()
if r > 0 {
current_word.WriteRune(r)
} }
fmt.Print(current_word)
current_word = string(r)
x += w x += w
} }
@@ -115,27 +129,109 @@ func print_with_indent(text string, indent string, screen_width int) {
if r == 'm' { if r == 'm' {
in_sgr = false in_sgr = false
} }
fmt.Print(string(r))
continue continue
} }
if r == 0x1b { if r == 0x1b {
in_sgr = true in_sgr = true
if current_word.Len() != 0 {
print_word(0)
}
fmt.Print(string(r))
continue continue
} }
if current_word != "" && unicode.IsSpace(r) && r != 0xa0 { if current_word.Len() != 0 && r != 0xa0 && unicode.IsSpace(r) {
print_word(r) print_word(r)
} else { } else {
current_word += string(r) current_word.WriteRune(r)
} }
} }
if current_word != "" { if current_word.Len() != 0 {
print_word(' ') print_word(0)
fmt.Print(current_word)
} }
if len(text) > 0 { if len(text) > 0 {
fmt.Println() fmt.Println()
} }
} }
func ReplaceAllStringSubmatchFunc(re *regexp.Regexp, str string, repl func([]string) string) string {
result := ""
lastIndex := 0
for _, v := range re.FindAllSubmatchIndex([]byte(str), -1) {
groups := []string{}
for i := 0; i < len(v); i += 2 {
if v[i] == -1 || v[i+1] == -1 {
groups = append(groups, "")
} else {
groups = append(groups, str[v[i]:v[i+1]])
}
}
result += str[lastIndex:v[0]] + repl(groups)
lastIndex = v[1]
}
return result + str[lastIndex:]
}
func website_url(doc string) string {
if doc != "" {
doc = strings.TrimSuffix(doc, "/")
if doc != "" {
doc += "/"
}
}
return kitty.WebsiteBaseUrl + doc
}
var prettify_pat = regexp.MustCompile(":([a-z]+):`([^`]+)`")
var ref_pat = regexp.MustCompile(`\s*<\S+?>`)
func prettify(text string) string {
return ReplaceAllStringSubmatchFunc(prettify_pat, text, func(groups []string) string {
val := groups[2]
switch groups[1] {
case "file", "env", "envvar":
return italic_fmt(val)
case "doc":
return website_url(val)
case "ref":
return ref_pat.ReplaceAllString(val, ``)
case "code":
return code_fmt(val)
case "option":
idx := strings.LastIndex(val, "--")
if idx < 0 {
idx = strings.Index(val, "-")
}
if idx > -1 {
val = val[idx:]
}
return bold_fmt(val)
case "yellow":
return yellow_fmt(val)
case "blue":
return blue_fmt(val)
case "green":
return green_fmt(val)
case "cyan":
return cyan_fmt(val)
case "emph":
return italic_fmt(val)
default:
return val
}
})
}
func print_with_indent(text string, indent string, screen_width int) {
for _, line := range strings.Split(prettify(text), "\n") {
print_line_with_indent(line, indent, screen_width)
}
}
func show_usage(cmd *cobra.Command) error { func show_usage(cmd *cobra.Command) error {
ws, tty_size_err := GetTTYSize() ws, tty_size_err := GetTTYSize()
screen_width := 80 screen_width := 80
@@ -184,14 +280,14 @@ func show_usage(cmd *cobra.Command) error {
fmt.Print(" ", defval) fmt.Print(" ", defval)
} }
fmt.Println() fmt.Println()
if flag.Name == "help" { msg := flag.Usage
fmt.Println(" ", "Print this help message") switch flag.Name {
fmt.Println() case "help":
return msg = "Print this help message"
} case "version":
for _, line := range strings.Split(flag.Usage, "\n") { msg = "Print the version of " + RootCmd.Annotations["exe"] + ": " + italic_fmt(RootCmd.Version)
print_with_indent(line, " ", screen_width)
} }
print_with_indent(msg, " ", screen_width)
if cmd.Annotations["choices-"+flag.Name] != "" { if cmd.Annotations["choices-"+flag.Name] != "" {
fmt.Println(" Choices:", strings.Join(strings.Split(cmd.Annotations["choices-"+flag.Name], "\000"), ", ")) fmt.Println(" Choices:", strings.Join(strings.Split(cmd.Annotations["choices-"+flag.Name], "\000"), ", "))
} }
@@ -218,6 +314,7 @@ func CreateCommand(cmd *cobra.Command, exe string) *cobra.Command {
} }
func Init(root *cobra.Command) { func Init(root *cobra.Command) {
RootCmd = root
root.Version = kitty.VersionString root.Version = kitty.VersionString
root.PersistentPreRunE = ValidateChoices root.PersistentPreRunE = ValidateChoices
root.SetUsageFunc(show_usage) root.SetUsageFunc(show_usage)

View File

@@ -24,8 +24,14 @@ func main() {
fmt.Fprintln(os.Stderr, color.RedString("\nNo command specified for "+exe_name)) fmt.Fprintln(os.Stderr, color.RedString("\nNo command specified for "+exe_name))
}, },
}, exe_name) }, exe_name)
cli.PersistentChoices(root, "use-password", "If no password is available, kitty will usually just send the remote control command without a password. This option can be used to force it to always or never use the supplied password.", "if-available", "always", "never")
root.Annotations["options_title"] = "Global options" root.Annotations["options_title"] = "Global options"
root.PersistentFlags().String("password", "",
"A password to use when contacting kitty. This will cause kitty to ask the user"+
" for permission to perform the specified action, unless the password has been"+
" accepted before or is pre-configured in :file:`kitty.conf`.")
cli.PersistentChoices(root, "use-password", "If no password is available, kitty will usually just send the remote control command without a password. This option can be used to force it to always or never use the supplied password.", "if-available", "always", "never")
cli.Init(root) cli.Init(root)
if err := root.Execute(); err != nil { if err := root.Execute(); err != nil {
fmt.Fprintln(os.Stderr, err) fmt.Fprintln(os.Stderr, err)

View File

@@ -18,9 +18,10 @@ type VersionType struct {
var VersionString string var VersionString string
var Version VersionType var Version VersionType
var VCSRevision string var VCSRevision string
var WebsiteBaseUrl string
func init() { func init() {
var verpat = regexp.MustCompile(`Version\((\d+),\s*(\d+),\s*(\d+)\)`) verpat := regexp.MustCompile(`Version\((\d+),\s*(\d+),\s*(\d+)\)`)
matches := verpat.FindStringSubmatch(raw) matches := verpat.FindStringSubmatch(raw)
major, err := strconv.Atoi(matches[1]) major, err := strconv.Atoi(matches[1])
minor, err := strconv.Atoi(matches[2]) minor, err := strconv.Atoi(matches[2])
@@ -40,5 +41,11 @@ func init() {
} }
} }
} }
website_pat := regexp.MustCompile(`website_base_url\s+=\s+['"](.+?)['"]`)
matches = website_pat.FindStringSubmatch(raw)
WebsiteBaseUrl = matches[1]
if matches[1] == "" {
panic(fmt.Errorf("Failed to find the website base url"))
}
} }