mirror of
https://codeberg.org/scip/tablizer.git
synced 2025-12-18 21:11:03 +01:00
135 lines
2.7 KiB
Go
135 lines
2.7 KiB
Go
package zygo
|
|
|
|
import (
|
|
"sort"
|
|
"strings"
|
|
|
|
"github.com/glycerine/liner"
|
|
)
|
|
|
|
// filled at init time based on BuiltinFunctions
|
|
var completion_keywords = []string{`(`}
|
|
|
|
var math_funcs = []string{`* `, `** `, `+ `, `- `, `-> `, `/ `, `< `, `<= `, `== `, `> `, `>= `, `\ `}
|
|
|
|
func init() {
|
|
// fill in our auto-complete keywords
|
|
sortme := []*SymtabE{}
|
|
for f, _ := range AllBuiltinFunctions() {
|
|
sortme = append(sortme, &SymtabE{Key: f})
|
|
}
|
|
sort.Sort(SymtabSorter(sortme))
|
|
for i := range sortme {
|
|
completion_keywords = append(completion_keywords, "("+sortme[i].Key)
|
|
}
|
|
|
|
for i := range math_funcs {
|
|
completion_keywords = append(completion_keywords, "("+math_funcs[i])
|
|
}
|
|
}
|
|
|
|
type Prompter struct {
|
|
prompt string
|
|
prompter *liner.State
|
|
origMode liner.ModeApplier
|
|
rawMode liner.ModeApplier
|
|
}
|
|
|
|
// complete phrases that start with '('
|
|
func MyWordCompleter(line string, pos int) (head string, c []string, tail string) {
|
|
|
|
beg := []rune(line[:pos])
|
|
end := line[pos:]
|
|
Q("\nline = '%s' pos=%v\n", line, pos)
|
|
Q("\nbeg = '%v'\nend = '%s'\n", string(beg), end)
|
|
// find most recent paren in beg
|
|
n := len(beg)
|
|
last := n - 1
|
|
var i int
|
|
var p int = -1
|
|
outer:
|
|
for i = last; i >= 0; i-- {
|
|
Q("\nbeg[i=%v] is '%v'\n", i, string(beg[i]))
|
|
switch beg[i] {
|
|
case ' ':
|
|
break outer
|
|
case '(':
|
|
p = i
|
|
Q("\n found paren at p = %v\n", i)
|
|
break outer
|
|
}
|
|
}
|
|
Q("p=%d\n", p)
|
|
prefix := string(beg)
|
|
extendme := ""
|
|
if p == 0 {
|
|
prefix = ""
|
|
extendme = string(beg)
|
|
} else if p > 0 {
|
|
prefix = string(beg[:p])
|
|
extendme = string(beg[p:])
|
|
}
|
|
Q("prefix = '%s'\nextendme = '%s'\n", prefix, extendme)
|
|
|
|
for _, n := range completion_keywords {
|
|
if strings.HasPrefix(n, strings.ToLower(extendme)) {
|
|
Q("n='%s' has prefix = '%s'\n", n, extendme)
|
|
c = append(c, n)
|
|
}
|
|
}
|
|
|
|
return prefix, c, end
|
|
}
|
|
|
|
func NewPrompter(prompt string) *Prompter {
|
|
origMode, err := liner.TerminalMode()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
p := &Prompter{
|
|
prompt: prompt,
|
|
prompter: liner.NewLiner(),
|
|
origMode: origMode,
|
|
}
|
|
|
|
rawMode, err := liner.TerminalMode()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
p.rawMode = rawMode
|
|
|
|
p.prompter.SetCtrlCAborts(false)
|
|
p.prompter.SetWordCompleter(liner.WordCompleter(MyWordCompleter))
|
|
|
|
return p
|
|
}
|
|
|
|
func (p *Prompter) Close() {
|
|
defer p.prompter.Close()
|
|
}
|
|
|
|
func (p *Prompter) Getline(prompt *string) (line string, err error) {
|
|
applyErr := p.rawMode.ApplyMode()
|
|
if applyErr != nil {
|
|
panic(applyErr)
|
|
}
|
|
defer func() {
|
|
applyErr := p.origMode.ApplyMode()
|
|
if applyErr != nil {
|
|
panic(applyErr)
|
|
}
|
|
}()
|
|
|
|
if prompt == nil {
|
|
line, err = p.prompter.Prompt(p.prompt)
|
|
} else {
|
|
line, err = p.prompter.Prompt(*prompt)
|
|
}
|
|
if err == nil {
|
|
p.prompter.AppendHistory(line)
|
|
return line, nil
|
|
}
|
|
return "", err
|
|
}
|