From a33a76bb06002d62e0700c566dabffa136039d44 Mon Sep 17 00:00:00 2001 From: Thomas von Dein Date: Mon, 4 Dec 2023 13:35:40 +0100 Subject: [PATCH] add edit feature --- command.go | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ main.go | 2 +- rpn.go | 3 +- rpn.pod | 1 + 4 files changed, 89 insertions(+), 2 deletions(-) diff --git a/command.go b/command.go index d3a82d0..9428251 100644 --- a/command.go +++ b/command.go @@ -18,8 +18,12 @@ along with this program. If not, see . package main import ( + "bufio" "fmt" "os" + "os/exec" + "strconv" + "strings" ) type CommandFunction func(*Calc) @@ -184,6 +188,87 @@ func (c *Calc) SetCommands() { } }, ), + + "edit": NewCommand( + "edit the stack interactively", + func(c *Calc) { + if c.stack.Len() == 0 { + fmt.Println("empty stack") + return + } + + c.stack.Backup() + + // put the stack contents into a tmp file + tmp, err := os.CreateTemp("", "stack") + if err != nil { + fmt.Println(err) + } + defer os.Remove(tmp.Name()) + + for _, item := range c.stack.All() { + fmt.Fprintf(tmp, "%f\n", item) + } + + tmp.Close() + + // determine which editor to use + editor := "vi" + enveditor, present := os.LookupEnv("EDITOR") + if present { + if editor != "" { + if _, err := os.Stat(editor); err == nil { + editor = enveditor + } + } + } + + // execute editor with our tmp file containing current stack + cmd := exec.Command(editor, tmp.Name()) + + cmd.Stdin = os.Stdin + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + + err = cmd.Run() + if err != nil { + fmt.Println("could not run editor command: ", err) + return + } + + // read the file back in + modified, err := os.Open(tmp.Name()) + if err != nil { + fmt.Println("Error opening file:", err) + return + } + defer modified.Close() + + // reset the stack + c.stack.Clear() + + // and put the new contents (if legit) back onto the stack + scanner := bufio.NewScanner(modified) + for scanner.Scan() { + line := strings.TrimSpace(c.Comment.ReplaceAllString(scanner.Text(), "")) + if line == "" { + continue + } + + num, err := strconv.ParseFloat(line, 64) + if err != nil { + fmt.Printf("%s is not a floating point number!\n", line) + continue + } + + c.stack.Push(num) + } + + if err := scanner.Err(); err != nil { + fmt.Println("Error reading from file:", err) + } + }, + ), } // general commands diff --git a/main.go b/main.go index b549427..3785060 100644 --- a/main.go +++ b/main.go @@ -30,7 +30,7 @@ import ( lua "github.com/yuin/gopher-lua" ) -const VERSION string = "2.0.10" +const VERSION string = "2.0.11" const Usage string = `This is rpn, a reverse polish notation calculator cli. diff --git a/rpn.go b/rpn.go index eb89625..89bebf6 100644 --- a/rpn.go +++ b/rpn.go @@ -185,7 +185,8 @@ DESCRIPTION Stack manipulation commands: clear clear the whole stack shift remove the last element of the stack reverse reverse the stack elements swap exchange the last two stack elements dup duplicate last stack item undo - undo last operation + undo last operation edit edit the stack interactively using vi or + $EDITOR Other commands: help|? show this message manual show manual quit|exit|c-d|c-c exit program diff --git a/rpn.pod b/rpn.pod index aae8858..529a107 100644 --- a/rpn.pod +++ b/rpn.pod @@ -198,6 +198,7 @@ Stack manipulation commands: swap exchange the last two stack elements dup duplicate last stack item undo undo last operation + edit edit the stack interactively using vi or $EDITOR Other commands: help|? show this message