-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmflg.go
90 lines (82 loc) · 2.48 KB
/
mflg.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
package main
import (
"fmt"
"io"
"os"
"os/signal"
"path/filepath"
"time"
"github.com/dpinela/mflg/internal/atomicwrite"
"github.com/dpinela/mflg/internal/buffer"
"github.com/dpinela/mflg/internal/termdraw"
"github.com/dpinela/mflg/internal/termesc"
"golang.org/x/crypto/ssh/terminal"
"golang.org/x/sys/unix"
)
func saveBuffer(fname string, buf *buffer.Buffer) error {
if fname == os.DevNull {
return nil
}
return atomicwrite.Write(fname, func(w io.Writer) error { _, err := buf.WriteTo(w); return err })
}
func allASCIIDigits(s string) bool {
for i := range s {
if !(s[i] >= '0' && s[i] <= '9') {
return false
}
}
return true
}
func newScratchFile() (name string, err error) {
dir, err := os.UserConfigDir()
if err != nil {
return "", fmt.Errorf("error creating scratch file: %w", err)
}
return filepath.Join(dir, "mflg", "scratch "+time.Now().Format("2006-01-02 15.04.05.0")), nil
}
// A mflg instance is made of three components:
// - a main window, which handles text editing for the open file
// - a prompt window, which provides the same functionality for the text entered in response
// to various command prompts.
// - an application object, which coordinates rendering of these two windows, and distributes input
// between them as appropriate.
func main() {
var selector string
if len(os.Args) < 2 {
name, err := newScratchFile()
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
fmt.Fprintln(os.Stderr, "saving buffer to", name)
selector = name
} else {
selector = os.Args[1]
}
w, h, err := terminal.GetSize(0)
if err != nil {
fmt.Fprintln(os.Stderr, "error finding terminal size:", err)
os.Exit(1)
}
app := newApplication(os.Stdout, termdraw.Point{X: w, Y: h})
defer app.fsWatcher.Close()
app.loadConfig()
if err := app.navigateTo(selector); err != nil {
fmt.Fprintf(os.Stderr, "error loading %s: %v\n", os.Args[1], err)
os.Exit(1)
}
oldMode, err := terminal.MakeRaw(0)
if err != nil {
fmt.Fprintln(os.Stderr, "error entering raw mode:", err)
os.Exit(1)
}
defer terminal.Restore(0, oldMode)
os.Stdout.WriteString(termesc.EnableMouseReporting + termesc.EnableBracketedPaste + termesc.EnterAlternateScreen)
defer os.Stdout.WriteString(termesc.ExitAlternateScreen + termesc.DisableBracketedPaste + termesc.ShowCursor + termesc.DisableMouseReporting)
resizeCh := make(chan os.Signal, 32)
signal.Notify(resizeCh, unix.SIGWINCH)
if err := app.run(os.Stdin, resizeCh); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}