Start work on history support for readline

This commit is contained in:
Kovid Goyal
2022-10-14 21:34:52 +05:30
parent fe91af5e09
commit 88567f69b2
4 changed files with 208 additions and 4 deletions

View File

@@ -8,7 +8,9 @@ import (
"io"
"os"
"os/exec"
"path/filepath"
"strings"
"time"
"github.com/google/shlex"
@@ -16,6 +18,7 @@ import (
"kitty/tools/cli/markup"
"kitty/tools/tui/loop"
"kitty/tools/tui/readline"
"kitty/tools/utils"
)
var _ = fmt.Print
@@ -111,7 +114,7 @@ func print_basic_help() {
fmt.Println(" ", "Exit this shell")
}
func exec_command(cmdline string) bool {
func exec_command(rl *readline.Readline, cmdline string) bool {
parsed_cmdline, err := shlex.Split(cmdline)
if err != nil {
fmt.Fprintln(os.Stderr, "Could not parse cmdline:", err)
@@ -120,10 +123,15 @@ func exec_command(cmdline string) bool {
if len(parsed_cmdline) == 0 {
return true
}
hi := readline.HistoryItem{Timestamp: time.Now(), Cmd: cmdline, ExitCode: -1}
switch parsed_cmdline[0] {
case "exit":
hi.ExitCode = 0
rl.AddHistoryItem(hi)
return false
case "help":
hi.ExitCode = 0
defer rl.AddHistoryItem(hi)
if len(parsed_cmdline) == 1 {
print_basic_help()
return true
@@ -137,6 +145,7 @@ func exec_command(cmdline string) bool {
r := EntryPoint(cli.NewRootCommand())
sc := r.FindSubCommand(parsed_cmdline[1])
if sc == nil {
hi.ExitCode = 1
fmt.Fprintln(os.Stderr, "No command named", formatter.BrightRed(parsed_cmdline[1]), ". Type help for a list of commands")
} else {
sc.ShowHelpWithCommandString(sc.Name)
@@ -156,9 +165,15 @@ func exec_command(cmdline string) bool {
cmdline = append(cmdline, parsed_cmdline...)
cmd := exec.Cmd{Path: exe, Args: cmdline, Stdin: os.Stdin, Stdout: os.Stdout, Stderr: os.Stderr}
err = cmd.Run()
hi.Duration = time.Now().Sub(hi.Timestamp)
hi.ExitCode = 0
if err != nil {
if exitError, ok := err.(*exec.ExitError); ok {
hi.ExitCode = exitError.ExitCode()
}
fmt.Fprintln(os.Stderr, err)
}
rl.AddHistoryItem(hi)
}
return true
}
@@ -167,14 +182,17 @@ func shell_main(cmd *cli.Command, args []string) (int, error) {
formatter = markup.New(true)
fmt.Println("Welcome to the kitty shell!")
fmt.Println("Use", formatter.Green("help"), "for assistance or", formatter.Green("exit"), "to quit.")
rl := readline.New(nil, readline.RlInit{Prompt: prompt})
rl := readline.New(nil, readline.RlInit{Prompt: prompt, HistoryPath: filepath.Join(utils.CacheDir(), "shell.history.json")})
defer func() {
rl.Shutdown()
}()
for {
rc, err := shell_loop(rl, true)
if err != nil {
if err == ErrExec {
cmdline := rl.AllText()
cmdline = strings.ReplaceAll(cmdline, "\\\n", "")
if !exec_command(cmdline) {
if !exec_command(rl, cmdline) {
return 0, nil
}
continue