forked from la5nta/pat
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathread.go
157 lines (137 loc) · 3.21 KB
/
read.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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
// Copyright 2016 Martin Hebnes Pedersen (LA5NTA). All rights reserved.
// Use of this source code is governed by the MIT-license that can be
// found in the LICENSE file.
package main
import (
"bytes"
"context"
"fmt"
"io"
"log"
"os"
"path"
"sort"
"strconv"
"strings"
"github.com/bndr/gotabulate"
"github.com/la5nta/wl2k-go/fbb"
"github.com/la5nta/wl2k-go/mailbox"
)
var mailboxes = []string{"in", "out", "sent", "archive"}
func readMail(ctx context.Context) {
w := os.Stdout
for {
// Query user for mailbox to list
printMailboxes(w)
fmt.Fprintf(w, "\nChoose mailbox [n]: ")
mailboxIdx, ok := readInt(ctx)
if !ok {
break
} else if mailboxIdx+1 > len(mailboxes) {
fmt.Fprintln(w, "Invalid mailbox number")
continue
}
for {
// Fetch messages
msgs, err := mailbox.LoadMessageDir(path.Join(mailbox.UserPath(fOptions.MailboxPath, fOptions.MyCall), mailboxes[mailboxIdx]))
if err != nil {
log.Fatal(err)
} else if len(msgs) == 0 {
fmt.Fprintf(w, "(empty)\n")
break
}
// Print messages (sorted by date)
sort.Sort(fbb.ByDate(msgs))
printMessages(w, msgs)
// Query user for message to print
fmt.Fprintf(w, "Choose message [n]: ")
msgIdx, ok := readInt(ctx)
if !ok {
break
} else if msgIdx+1 > len(msgs) {
fmt.Fprintf(w, "invalid message number\n")
continue
}
printMsg(w, msgs[msgIdx])
// Mark as read?
if mailbox.IsUnread(msgs[msgIdx]) {
fmt.Fprintf(w, "Mark as read? [Y/n]: ")
ans := readLine()
if ans == "" || strings.EqualFold(ans, "y") {
mailbox.SetUnread(msgs[msgIdx], false)
}
}
// Reply?
fmt.Fprintf(w, "Reply (ctrl+c to quit) [y/N]: ")
ans := readLine()
if strings.EqualFold(ans, "y") {
composeReplyMessage(msgs[msgIdx])
}
}
}
}
func readInt(ctx context.Context) (int, bool) {
cs := make(chan string, 1)
go func() { cs <- readLine() }()
select {
case <-ctx.Done():
return 0, false
case str := <-cs:
if str == "" {
return 0, false
}
i, _ := strconv.Atoi(str)
return i, true
}
}
type PrettyAddrSlice []fbb.Address
func (addrs PrettyAddrSlice) String() string {
var buf bytes.Buffer
for i, addr := range addrs {
fmt.Fprintf(&buf, "%s", addr.Addr)
if i < len(addrs)-1 {
fmt.Fprintf(&buf, ", ")
}
}
return buf.String()
}
func printMsg(w io.Writer, msg *fbb.Message) {
fmt.Fprintf(w, "========================================\n")
fmt.Fprintln(w, msg)
fmt.Fprintf(w, "========================================\n\n")
}
func printMailboxes(w io.Writer) {
for i, mbox := range mailboxes {
fmt.Fprintf(w, "%d:%s\t", i, mbox)
}
}
func printMessages(w io.Writer, msgs []*fbb.Message) {
rows := make([][]string, len(msgs))
for i, msg := range msgs {
var to string
if len(msg.To()) > 0 {
to = msg.To()[0].Addr
}
if len(msg.To()) > 1 {
to += ", ..."
}
var flags string
if mailbox.IsUnread(msg) {
flags += "N" // New
}
rows[i] = []string{
fmt.Sprintf("%2d", i),
flags,
msg.Subject(),
msg.From().Addr,
msg.Date().String(),
to,
}
}
t := gotabulate.Create(rows)
t.SetHeaders([]string{"i", "Flags", "Subject", "From", "Date", "To"})
t.SetAlign("left")
t.SetWrapStrings(true)
t.SetMaxCellSize(60)
fmt.Fprintln(w, t.Render("simple"))
}