File: interact.go

package info (click to toggle)
elvish 0.12%2Bds1-2
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 2,532 kB
  • sloc: python: 108; makefile: 94; sh: 72; xml: 9
file content (98 lines) | stat: -rw-r--r-- 1,987 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
package shell

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"os/signal"
	"path/filepath"
	"syscall"
	"time"

	"github.com/elves/elvish/edit"
	"github.com/elves/elvish/eval"
	"github.com/elves/elvish/sys"
	"github.com/elves/elvish/util"
)

func interact(ev *eval.Evaler, dataDir string, norc bool) {
	// Build Editor.
	var ed editor
	if sys.IsATTY(os.Stdin) {
		sigch := make(chan os.Signal)
		signal.Notify(sigch, syscall.SIGHUP, syscall.SIGINT, sys.SIGWINCH)
		ed = edit.NewEditor(os.Stdin, os.Stderr, sigch, ev)
	} else {
		ed = newMinEditor(os.Stdin, os.Stderr)
	}
	defer ed.Close()

	// Source rc.elv.
	if !norc && dataDir != "" {
		err := sourceRC(ev, dataDir)
		if err != nil {
			util.PprintError(err)
		}
	}

	// Build readLine function.
	readLine := func() (string, error) {
		return ed.ReadLine()
	}

	cooldown := time.Second
	usingBasic := false
	cmdNum := 0

	for {
		cmdNum++

		line, err := readLine()

		if err == io.EOF {
			break
		} else if err != nil {
			fmt.Println("Editor error:", err)
			if !usingBasic {
				fmt.Println("Falling back to basic line editor")
				readLine = basicReadLine
				usingBasic = true
			} else {
				fmt.Println("Don't know what to do, pid is", os.Getpid())
				fmt.Println("Restarting editor in", cooldown)
				time.Sleep(cooldown)
				if cooldown < time.Minute {
					cooldown *= 2
				}
			}
			continue
		}

		// No error; reset cooldown.
		cooldown = time.Second

		err = ev.EvalSource(eval.NewInteractiveSource(line))
		if err != nil {
			util.PprintError(err)
		}
	}
}

func sourceRC(ev *eval.Evaler, dataDir string) error {
	absPath, err := filepath.Abs(filepath.Join(dataDir, "rc.elv"))
	if err != nil {
		if os.IsNotExist(err) {
			return nil
		}
		return fmt.Errorf("cannot get full path of rc.elv: %v", err)
	}
	code, err := readFileUTF8(absPath)

	return ev.SourceRC(eval.NewScriptSource("rc.elv", absPath, code))
}

func basicReadLine() (string, error) {
	stdin := bufio.NewReaderSize(os.Stdin, 0)
	return stdin.ReadString('\n')
}