add a nice readline experience (with history!)
This commit is contained in:
		
							
								
								
									
										2
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								go.mod
									
									
									
									
									
								
							@@ -1,3 +1,5 @@
 | 
				
			|||||||
module git.yetaga.in/alazyreader/prosper
 | 
					module git.yetaga.in/alazyreader/prosper
 | 
				
			||||||
 | 
					
 | 
				
			||||||
go 1.15
 | 
					go 1.15
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					require github.com/peterh/liner v1.2.1
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										4
									
								
								go.sum
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								go.sum
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
				
			|||||||
 | 
					github.com/mattn/go-runewidth v0.0.3 h1:a+kO+98RDGEfo6asOGMmpodZq4FNtnGP54yps8BzLR4=
 | 
				
			||||||
 | 
					github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
 | 
				
			||||||
 | 
					github.com/peterh/liner v1.2.1 h1:O4BlKaq/LWu6VRWmol4ByWfzx6MfXc5Op5HETyIy5yg=
 | 
				
			||||||
 | 
					github.com/peterh/liner v1.2.1/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0=
 | 
				
			||||||
							
								
								
									
										88
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										88
									
								
								main.go
									
									
									
									
									
								
							@@ -1,12 +1,14 @@
 | 
				
			|||||||
package main
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"bufio"
 | 
					 | 
				
			||||||
	"errors"
 | 
						"errors"
 | 
				
			||||||
	"flag"
 | 
						"flag"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
 | 
						"path/filepath"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/peterh/liner"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type libraryFiles []string
 | 
					type libraryFiles []string
 | 
				
			||||||
@@ -20,10 +22,41 @@ func (l *libraryFiles) Set(value string) error {
 | 
				
			|||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func historyFn() string {
 | 
				
			||||||
 | 
						dataHome := os.Getenv("XDG_DATA_HOME")
 | 
				
			||||||
 | 
						home := os.Getenv("HOME")
 | 
				
			||||||
 | 
						if dataHome == "" {
 | 
				
			||||||
 | 
							dataHome = filepath.Join(home, ".local/share/")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						prosperDir := filepath.Join(dataHome, "prosper")
 | 
				
			||||||
 | 
						os.MkdirAll(prosperDir, 0755)
 | 
				
			||||||
 | 
						return filepath.Join(prosperDir, ".history")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func completer(d Dictionary) liner.Completer {
 | 
				
			||||||
 | 
						return func(line string) []string {
 | 
				
			||||||
 | 
							candidates := []string{}
 | 
				
			||||||
 | 
							words := strings.Split(line, " ")
 | 
				
			||||||
 | 
							for w := range d {
 | 
				
			||||||
 | 
								if strings.HasPrefix(w, words[len(words)-1]) {
 | 
				
			||||||
 | 
									// must reconstruct the _full_ line to return for the completer
 | 
				
			||||||
 | 
									pref := strings.Join(words[:len(words)-1], " ")
 | 
				
			||||||
 | 
									if len(pref) != 0 {
 | 
				
			||||||
 | 
										candidates = append(candidates, pref+" "+w)
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										candidates = append(candidates, w)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return candidates
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func main() {
 | 
					func main() {
 | 
				
			||||||
	// flag setup
 | 
						// flag setup
 | 
				
			||||||
	var libs libraryFiles
 | 
						var libs libraryFiles
 | 
				
			||||||
	flag.Var(&libs, "l", "propser library file (may be repeated)")
 | 
						flag.Var(&libs, "l", "propser library file (may be repeated)")
 | 
				
			||||||
 | 
						debug := flag.Bool("debug", false, "output debugging information")
 | 
				
			||||||
	flag.Parse()
 | 
						flag.Parse()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// create main context
 | 
						// create main context
 | 
				
			||||||
@@ -64,27 +97,60 @@ func main() {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	reader := bufio.NewReader(os.Stdin)
 | 
						// set up liner
 | 
				
			||||||
 | 
						line := liner.NewLiner()
 | 
				
			||||||
 | 
						line.SetCtrlCAborts(true)
 | 
				
			||||||
 | 
						line.SetCompleter(completer(dict))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						historyFile := historyFn()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if f, err := os.Open(historyFile); err == nil {
 | 
				
			||||||
 | 
							_, err := line.ReadHistory(f)
 | 
				
			||||||
 | 
							if err != nil && *debug {
 | 
				
			||||||
 | 
								fmt.Printf("error reading line history: %v", err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							f.Close()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						defer func() {
 | 
				
			||||||
 | 
							if f, err := os.Create(historyFile); err != nil {
 | 
				
			||||||
 | 
								if *debug {
 | 
				
			||||||
 | 
									fmt.Printf("Error writing history file: %v", err)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								line.WriteHistory(f)
 | 
				
			||||||
 | 
								f.Close()
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							line.Close()
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Welcome banner
 | 
				
			||||||
	fmt.Print("prosper\n")
 | 
						fmt.Print("prosper\n")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// read loop
 | 
						// read loop
 | 
				
			||||||
	for {
 | 
						for {
 | 
				
			||||||
		if c.Flags["Immediate"] {
 | 
							p := "> "
 | 
				
			||||||
			fmt.Print("> ")
 | 
							if !c.Flags["Immediate"] {
 | 
				
			||||||
		} else {
 | 
								p = "    "
 | 
				
			||||||
			fmt.Print("    ")
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		line, err := reader.ReadString('\n')
 | 
							// read line
 | 
				
			||||||
		if err != nil {
 | 
							l, err := line.Prompt(p)
 | 
				
			||||||
 | 
							if err == liner.ErrPromptAborted {
 | 
				
			||||||
 | 
								fmt.Println("ctrl-C caught (try BYE)")
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							} else if err != nil {
 | 
				
			||||||
			fmt.Println(err.Error())
 | 
								fmt.Println(err.Error())
 | 
				
			||||||
			os.Exit(1)
 | 
								os.Exit(1)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		line = strings.TrimSpace(line)
 | 
					
 | 
				
			||||||
		err = c.Eval(line + " ") // append a space to make sure we always close out our parse loop
 | 
							// parse line
 | 
				
			||||||
 | 
							l = strings.TrimSpace(l)
 | 
				
			||||||
 | 
							line.AppendHistory(l)
 | 
				
			||||||
 | 
							err = c.Eval(l + " ") // append a space to make sure we always close out our parse loop
 | 
				
			||||||
		if errors.Is(err, ErrExit) {
 | 
							if errors.Is(err, ErrExit) {
 | 
				
			||||||
			fmt.Printf("bye\n")
 | 
								fmt.Printf("bye\n")
 | 
				
			||||||
			os.Exit(0)
 | 
								break
 | 
				
			||||||
		} else if err != nil {
 | 
							} else if err != nil {
 | 
				
			||||||
			fmt.Printf("error in evaluation: %v\n", err)
 | 
								fmt.Printf("error in evaluation: %v\n", err)
 | 
				
			||||||
		} else if c.Flags["Immediate"] {
 | 
							} else if c.Flags["Immediate"] {
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user