mirror of
https://github.com/kovidgoyal/kitty
synced 2026-06-08 14:18:26 +02:00
Parse roles in the help strings
This commit is contained in:
@@ -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('/')
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -20,12 +20,18 @@ func main() {
|
|||||||
Short: "Control kitty remotely",
|
Short: "Control kitty remotely",
|
||||||
Long: "Control kitty by sending it commands. Set the allow_remote_control option in kitty.conf or use a password, for this to work.",
|
Long: "Control kitty by sending it commands. Set the allow_remote_control option in kitty.conf or use a password, for this to work.",
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
cmd.Usage()
|
cmd.Usage()
|
||||||
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)
|
||||||
|
|||||||
@@ -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"))
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user