-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathged.go
116 lines (110 loc) · 2.53 KB
/
ged.go
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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
// ged.go - main entry point for ged
package main
import (
"bufio"
"flag"
"fmt"
"os"
)
// flags
var (
fSuppress = flag.Bool("s", false, "suppress counts")
fPrompt = flag.String("p", "*", "specify a command prompt")
fLoose = flag.Bool("l", false, "loose exit mode, don't return errors for command failure (not implemented)")
fRestrict = flag.Bool("r", false, "no editing outside directory, no command exec (not implemented)")
)
// current FileBuffer
var buffer *FileBuffer
// current ed state
var state struct {
fileName string // current filename
lastErr error
printErr bool
prompt bool
winSize int
lastRep string
lastSub string
}
// Parse input and run command
func run(cmd string) (e error) {
ctx := &Context{
cmd: cmd,
}
if ctx.addrs, ctx.cmdOffset, e = buffer.ResolveAddrs(cmd); e != nil {
return
}
if len(cmd) <= ctx.cmdOffset {
// no command, default to print
ctx.cmd += "p"
}
if exe, ok := cmds[ctx.cmd[ctx.cmdOffset]]; ok {
buffer.Start()
if e = exe(ctx); e != nil {
return
}
buffer.End()
} else {
return fmt.Errorf("invalid command: %v", cmd[ctx.cmdOffset])
}
return
}
// Entry point
func main() {
var e error
flag.Usage = func() {
fmt.Fprintf(flag.CommandLine.Output(), "Usage: %s [-s] [-p <prompt>] [file]\n", os.Args[0])
flag.PrintDefaults()
}
flag.Parse()
flag.Visit(func(f *flag.Flag) {
if f.Name == "p" {
state.prompt = true
}
})
args := flag.Args()
if len(args) > 1 { // we only accept one additional argument
flag.Usage()
os.Exit(1)
}
buffer = NewFileBuffer(nil)
if len(args) == 1 { // we were given a file name
state.fileName = args[0]
// try to read in the file
if _, e = os.Stat(state.fileName); os.IsNotExist(e) && !*fSuppress {
fmt.Fprintf(os.Stderr, "%s: No such file or directory", state.fileName)
// this is not fatal, we just start with an empty buffer
} else {
if buffer, e = FileToBuffer(state.fileName); e != nil {
fmt.Fprintln(os.Stderr, e)
os.Exit(1)
}
if !*fSuppress {
fmt.Println(buffer.Size())
}
}
}
state.winSize = 22 // we don't actually support getting the real window size
inScan := bufio.NewScanner(os.Stdin)
if state.prompt {
fmt.Printf("%s", *fPrompt)
}
for inScan.Scan() {
cmd := inScan.Text()
e = run(cmd)
if e != nil {
state.lastErr = e
if !*fSuppress && state.printErr {
fmt.Println(e)
} else {
fmt.Println("?")
}
}
if state.prompt {
fmt.Printf("%s", *fPrompt)
}
}
if inScan.Err() != nil {
fmt.Fprintf(os.Stderr, "error reading stdin: %v", inScan.Err())
os.Exit(1)
}
}