read.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. // Copyright 2016 Martin Hebnes Pedersen (LA5NTA). All rights reserved.
  2. // Use of this source code is governed by the MIT-license that can be
  3. // found in the LICENSE file.
  4. package main
  5. import (
  6. "bytes"
  7. "fmt"
  8. "io"
  9. "log"
  10. "os"
  11. "path"
  12. "sort"
  13. "strconv"
  14. "strings"
  15. "github.com/bndr/gotabulate"
  16. "github.com/la5nta/wl2k-go/fbb"
  17. "github.com/la5nta/wl2k-go/mailbox"
  18. )
  19. var mailboxes = []string{"in", "out", "sent", "archive"}
  20. func readMail() {
  21. w := os.Stdout
  22. for {
  23. // Query user for mailbox to list
  24. printMailboxes(w)
  25. fmt.Fprintf(w, "\nChoose mailbox [n]: ")
  26. mailboxIdx, ok := readInt()
  27. if !ok {
  28. break
  29. } else if mailboxIdx+1 > len(mailboxes) {
  30. fmt.Fprintln(w, "Invalid mailbox number")
  31. continue
  32. }
  33. for {
  34. // Fetch messages
  35. msgs, err := mailbox.LoadMessageDir(path.Join(mailbox.UserPath(fOptions.MailboxPath, fOptions.MyCall), mailboxes[mailboxIdx]))
  36. if err != nil {
  37. log.Fatal(err)
  38. } else if len(msgs) == 0 {
  39. fmt.Fprintf(w, "(empty)\n")
  40. break
  41. }
  42. // Print messages (sorted by date)
  43. sort.Sort(fbb.ByDate(msgs))
  44. printMessages(w, msgs)
  45. // Query user for message to print
  46. fmt.Fprintf(w, "Choose message [n]: ")
  47. msgIdx, ok := readInt()
  48. if !ok {
  49. break
  50. } else if msgIdx+1 > len(msgs) {
  51. fmt.Fprintf(w, "invalid message number\n")
  52. continue
  53. }
  54. printMsg(w, msgs[msgIdx])
  55. // Mark as read?
  56. if mailbox.IsUnread(msgs[msgIdx]) {
  57. fmt.Fprintf(w, "Mark as read? [Y/n]: ")
  58. ans := readLine()
  59. if ans == "" || strings.EqualFold(ans, "y") {
  60. mailbox.SetUnread(msgs[msgIdx], false)
  61. }
  62. }
  63. // Reply?
  64. fmt.Fprintf(w, "Reply (ctrl+c to quit) [y/N]: ")
  65. ans := readLine()
  66. if strings.EqualFold(ans, "y") {
  67. composeMessage(msgs[msgIdx])
  68. }
  69. }
  70. }
  71. }
  72. func readInt() (int, bool) {
  73. str := readLine()
  74. if str == "" {
  75. return 0, false
  76. }
  77. i, _ := strconv.Atoi(str)
  78. return i, true
  79. }
  80. type PrettyAddrSlice []fbb.Address
  81. func (addrs PrettyAddrSlice) String() string {
  82. var buf bytes.Buffer
  83. for i, addr := range addrs {
  84. fmt.Fprintf(&buf, "%s", addr.Addr)
  85. if i < len(addrs)-1 {
  86. fmt.Fprintf(&buf, ", ")
  87. }
  88. }
  89. return buf.String()
  90. }
  91. func printMsg(w io.Writer, msg *fbb.Message) {
  92. fmt.Fprintf(w, "========================================\n")
  93. fmt.Fprintln(w, msg)
  94. fmt.Fprintf(w, "========================================\n\n")
  95. }
  96. func printMailboxes(w io.Writer) {
  97. for i, mailbox := range mailboxes {
  98. fmt.Fprintf(w, "%d:%s\t", i, mailbox)
  99. }
  100. }
  101. func printMessages(w io.Writer, msgs []*fbb.Message) {
  102. rows := make([][]string, len(msgs))
  103. for i, msg := range msgs {
  104. var to string
  105. if len(msg.To()) > 0 {
  106. to = msg.To()[0].Addr
  107. }
  108. if len(msg.To()) > 1 {
  109. to = to + ", ..."
  110. }
  111. var flags string
  112. if mailbox.IsUnread(msg) {
  113. flags += "N" // New
  114. }
  115. rows[i] = []string{
  116. fmt.Sprintf("%2d", i),
  117. flags,
  118. msg.Subject(),
  119. msg.From().Addr,
  120. msg.Date().String(),
  121. to,
  122. }
  123. }
  124. t := gotabulate.Create(rows)
  125. t.SetHeaders([]string{"i", "Flags", "Subject", "From", "Date", "To"})
  126. t.SetAlign("left")
  127. t.SetWrapStrings(true)
  128. t.SetMaxCellSize(60)
  129. fmt.Fprintln(w, t.Render("simple"))
  130. }