Implement printing mailqueue in table, restructuring

This commit is contained in:
Jan Philipp Timme 2018-12-31 16:32:23 +01:00
parent d39fb736dc
commit 2a9ae87b2f
2 changed files with 46 additions and 32 deletions

36
main.go
View File

@ -7,6 +7,7 @@ import (
"os" "os"
"os/exec" "os/exec"
"strconv" "strconv"
"text/tabwriter"
) )
import ( import (
@ -41,6 +42,21 @@ func interactiveShell() {
} }
func showQueue() { func showQueue() {
entries, err := fetchQueueEntries()
if err != nil {
fmt.Printf("Could not fetch queue entries: %s\n", err.Error())
os.Exit(1)
}
pagerReader, pagerWriter := io.Pipe()
pagerDone := make(chan bool)
go launchPager(pagerReader, pagerDone)
printQueueEntries(entries, pagerWriter)
pagerWriter.Close()
// Wait for pager to be closed before continuing the main program
<-pagerDone
}
func fetchQueueEntries() ([]parser.QEntry, error) {
var entries []parser.QEntry var entries []parser.QEntry
var err error var err error
if settings["mailqCommandArgs"] == "" { if settings["mailqCommandArgs"] == "" {
@ -48,24 +64,22 @@ func showQueue() {
} else { } else {
entries, err = readFromCmd(exec.Command(settings["mailqCommand"], settings["mailqCommandArgs"])) entries, err = readFromCmd(exec.Command(settings["mailqCommand"], settings["mailqCommandArgs"]))
} }
if err != nil { return entries, err
fmt.Printf("Error reading: %s\n", err.Error()) }
os.Exit(1)
} func printQueueEntries(entries []parser.QEntry, writer io.Writer) {
reader, writer := io.Pipe() tabWriter := tabwriter.NewWriter(writer, 0, 2, 1, ' ', tabwriter.TabIndent)
pagerDone := make(chan bool) fmt.Fprintf(tabWriter, "%s\t%s\t%s\t%s\t%s\t%s\n", "Date", "Id", "Size", "Sender", "#", "First Recipient")
go launchPager(reader, pagerDone)
for _, entry := range entries { for _, entry := range entries {
_, writeError := fmt.Fprintf(writer, "%s\n", entry.String()) _, writeError := fmt.Fprintf(tabWriter, "%s\t%s\t%d\t%s\t{%d}\t%s\n", entry.Date, entry.Id, entry.Size, entry.Sender, len(entry.Recipients), entry.Recipients[0])
if writeError != nil { if writeError != nil {
// A writeError is expected once the reader was closed // A writeError is expected once the reader was closed
// This happens when the pager application got terminated // This happens when the pager application got terminated
fmt.Printf("Error writing!: %s\n", writeError.Error())
break break
} }
} }
writer.Close() tabWriter.Flush()
// Wait for pager to be closed before continuing the main program
<-pagerDone
} }
func launchPager(reader *io.PipeReader, pagerDone chan<- bool) { func launchPager(reader *io.PipeReader, pagerDone chan<- bool) {

View File

@ -12,35 +12,35 @@ import (
) )
type QEntry struct { type QEntry struct {
id string Id string
status string Status string
date time.Time Date time.Time
size int Size int
sender string Sender string
recipients []string Recipients []string
reason string Reason string
} }
const sortableDateFormat = "2006-01-02 15:04:05" const sortableDateFormat = "2006-01-02 15:04:05"
func (m QEntry) ShortString() string { func (m QEntry) ShortString() string {
return fmt.Sprintf("[%s] %s <%s> -> %d recipients (%d bytes)", m.date.Format(sortableDateFormat), m.id, m.sender, len(m.recipients), m.size) return fmt.Sprintf("[%s] %s <%s> -> %d recipients (%d bytes)", m.Date.Format(sortableDateFormat), m.Id, m.Sender, len(m.Recipients), m.Size)
} }
func (m QEntry) String() string { func (m QEntry) String() string {
var recipientSuffix string var recipientSuffix string
if len(m.recipients) > 1 { if len(m.Recipients) > 1 {
recipientSuffix = ",..." recipientSuffix = ",..."
} }
return fmt.Sprintf("[%s] %s <%s> -> {%d}<%s>%s (%s, %d bytes)", m.date.Format(sortableDateFormat), m.id, m.sender, len(m.recipients), m.recipients[0], recipientSuffix, m.status, m.size) return fmt.Sprintf("[%s] %s <%s> -> {%d}<%s>%s (%s, %d bytes)", m.Date.Format(sortableDateFormat), m.Id, m.Sender, len(m.Recipients), m.Recipients[0], recipientSuffix, m.Status, m.Size)
} }
func (m QEntry) DetailedString() string { func (m QEntry) DetailedString() string {
var reasonStr string var reasonStr string
if m.reason == "" { if m.Reason == "" {
reasonStr = "-/-" reasonStr = "-/-"
} }
return fmt.Sprintf("Id: %s\nDate: %s\nStatus: %s\nReason: %s\nSize: %d\nSender: %s\nRecipients: %s", m.id, m.date.Format(sortableDateFormat), m.status, reasonStr, m.size, m.sender, strings.Join(m.recipients, ", ")) return fmt.Sprintf("Id: %s\nDate: %s\nStatus: %s\nReason: %s\nSize: %d\nSender: %s\nRecipients: %s", m.Id, m.Date.Format(sortableDateFormat), m.Status, reasonStr, m.Size, m.Sender, strings.Join(m.Recipients, ", "))
} }
func ParseMailQ(dataSource io.Reader) ([]QEntry, error) { func ParseMailQ(dataSource io.Reader) ([]QEntry, error) {
@ -71,26 +71,26 @@ func ParseMailQ(dataSource io.Reader) ([]QEntry, error) {
// Handle line starting next mail in queue // Handle line starting next mail in queue
messageId := fields[0] messageId := fields[0]
if strings.HasSuffix(messageId, "*") { if strings.HasSuffix(messageId, "*") {
currentMail.status = "active" currentMail.Status = "active"
} else if strings.HasSuffix(messageId, "!") { } else if strings.HasSuffix(messageId, "!") {
currentMail.status = "hold" currentMail.Status = "hold"
} else { } else {
currentMail.status = "deferred" currentMail.Status = "deferred"
} }
dateString := strconv.Itoa(time.Now().Year()) + " " + strings.Join(fields[2:6], " ") dateString := strconv.Itoa(time.Now().Year()) + " " + strings.Join(fields[2:6], " ")
mailDate, _ := time.Parse(dateFormat, dateString) mailDate, _ := time.Parse(dateFormat, dateString)
currentMail.id = strings.TrimRight(messageId, "*!") currentMail.Id = strings.TrimRight(messageId, "*!")
currentMail.size, _ = strconv.Atoi(fields[1]) currentMail.Size, _ = strconv.Atoi(fields[1])
currentMail.date = mailDate currentMail.Date = mailDate
currentMail.sender = fields[6] currentMail.Sender = fields[6]
continue continue
} else if strings.HasPrefix(line, "(") && strings.HasSuffix(line, ")") { } else if strings.HasPrefix(line, "(") && strings.HasSuffix(line, ")") {
// Handle reason for deferred status (if deferred at all, may be missing) // Handle reason for deferred status (if deferred at all, may be missing)
currentMail.reason = strings.Trim(strings.TrimSpace(line), "()") currentMail.Reason = strings.Trim(strings.TrimSpace(line), "()")
continue continue
} else if len(fields) == 1 { } else if len(fields) == 1 {
// Handle line with one of the mail recipients // Handle line with one of the mail recipients
currentMail.recipients = append(currentMail.recipients, fields[0]) currentMail.Recipients = append(currentMail.Recipients, fields[0])
continue continue
} else if len(fields) == 0 { } else if len(fields) == 0 {
// If the next line is empty, make sure to push current mail to list // If the next line is empty, make sure to push current mail to list