forked from evanmiller/hecate
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhecate.go
133 lines (110 loc) · 2.65 KB
/
hecate.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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
package main
import (
"fmt"
"os"
"path"
mmap "github.com/edsrzf/mmap-go"
"github.com/nsf/termbox-go"
)
const PROGRAM_NAME = "hecate"
type FileInfo struct {
filename string
bytes []byte
}
func mainLoop(files []FileInfo, style Style) {
screens := defaultScreensForFiles(files)
active_idx := DATA_SCREEN_INDEX
var screen_key_channels []chan termbox.Event
var screen_quit_channels []chan bool
switch_channel := make(chan int)
main_key_channel := make(chan termbox.Event, 10)
layoutAndDrawScreen(screens[active_idx], style)
for _ = range screens {
key_channel := make(chan termbox.Event, 10)
screen_key_channels = append(screen_key_channels, key_channel)
quit_channel := make(chan bool, 10)
screen_quit_channels = append(screen_quit_channels, quit_channel)
}
for i, s := range screens {
go func(index int, screen Screen) {
screen.receiveEvents(screen_key_channels[index], switch_channel,
screen_quit_channels[index])
}(i, s)
}
go func() {
for {
event := termbox.PollEvent()
if event.Type == termbox.EventInterrupt {
break
} else {
main_key_channel <- event
}
}
}()
for {
do_quit := false
select {
case event := <-main_key_channel:
if event.Type == termbox.EventKey {
handleSpecialKeys(event.Key)
screen_key_channels[active_idx] <- event
}
if event.Type == termbox.EventResize {
layoutAndDrawScreen(screens[active_idx], style)
}
case new_screen_index := <-switch_channel:
if new_screen_index < len(screens) {
active_idx = new_screen_index
layoutAndDrawScreen(screens[active_idx], style)
} else {
do_quit = true
}
}
if do_quit {
for _, c := range screen_quit_channels {
c <- true
}
termbox.Interrupt()
break
}
}
}
func main() {
var err error
if len(os.Args) < 2 {
fmt.Printf("Usage: %s <filename> [...]\n", PROGRAM_NAME)
os.Exit(1)
}
var files []FileInfo
for i := 1; i < len(os.Args); i++ {
file_path := os.Args[i]
file, err := os.Open(file_path)
if err != nil {
fmt.Printf("Error opening file: %q\n", err.Error())
os.Exit(1)
}
fi, err := file.Stat()
if err != nil {
fmt.Printf("Error stat'ing file: %q\n", err.Error())
os.Exit(1)
}
if fi.Size() < 8 {
fmt.Printf("File %s is too short to be edited\n", file_path)
os.Exit(1)
}
mm, err := mmap.Map(file, mmap.RDONLY, 0)
if err != nil {
fmt.Printf("Error mmap'ing file: %q\n", err.Error())
os.Exit(1)
}
files = append(files, FileInfo{filename: path.Base(file_path), bytes: mm})
}
err = termbox.Init()
if err != nil {
panic(err)
}
defer termbox.Close()
style := defaultStyle()
termbox.SetOutputMode(outputMode)
mainLoop(files, style)
}