diff --git a/main.go b/main.go index aced510..40247c5 100644 --- a/main.go +++ b/main.go @@ -7,6 +7,7 @@ import ( "os" "os/exec" "strconv" + "text/tabwriter" ) import ( @@ -41,6 +42,21 @@ func interactiveShell() { } 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 err error if settings["mailqCommandArgs"] == "" { @@ -48,24 +64,22 @@ func showQueue() { } else { entries, err = readFromCmd(exec.Command(settings["mailqCommand"], settings["mailqCommandArgs"])) } - if err != nil { - fmt.Printf("Error reading: %s\n", err.Error()) - os.Exit(1) - } - reader, writer := io.Pipe() - pagerDone := make(chan bool) - go launchPager(reader, pagerDone) + return entries, err +} + +func printQueueEntries(entries []parser.QEntry, writer io.Writer) { + tabWriter := tabwriter.NewWriter(writer, 0, 2, 1, ' ', tabwriter.TabIndent) + fmt.Fprintf(tabWriter, "%s\t%s\t%s\t%s\t%s\t%s\n", "Date", "Id", "Size", "Sender", "#", "First Recipient") 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 { // A writeError is expected once the reader was closed // This happens when the pager application got terminated + fmt.Printf("Error writing!: %s\n", writeError.Error()) break } } - writer.Close() - // Wait for pager to be closed before continuing the main program - <-pagerDone + tabWriter.Flush() } func launchPager(reader *io.PipeReader, pagerDone chan<- bool) { diff --git a/parser/parser.go b/parser/parser.go index d675c79..cfc293b 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -12,35 +12,35 @@ import ( ) type QEntry struct { - id string - status string - date time.Time - size int - sender string - recipients []string - reason string + Id string + Status string + Date time.Time + Size int + Sender string + Recipients []string + Reason string } const sortableDateFormat = "2006-01-02 15:04:05" 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 { var recipientSuffix string - if len(m.recipients) > 1 { + if len(m.Recipients) > 1 { 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 { var reasonStr string - if m.reason == "" { + if m.Reason == "" { 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) { @@ -71,26 +71,26 @@ func ParseMailQ(dataSource io.Reader) ([]QEntry, error) { // Handle line starting next mail in queue messageId := fields[0] if strings.HasSuffix(messageId, "*") { - currentMail.status = "active" + currentMail.Status = "active" } else if strings.HasSuffix(messageId, "!") { - currentMail.status = "hold" + currentMail.Status = "hold" } else { - currentMail.status = "deferred" + currentMail.Status = "deferred" } dateString := strconv.Itoa(time.Now().Year()) + " " + strings.Join(fields[2:6], " ") mailDate, _ := time.Parse(dateFormat, dateString) - currentMail.id = strings.TrimRight(messageId, "*!") - currentMail.size, _ = strconv.Atoi(fields[1]) - currentMail.date = mailDate - currentMail.sender = fields[6] + currentMail.Id = strings.TrimRight(messageId, "*!") + currentMail.Size, _ = strconv.Atoi(fields[1]) + currentMail.Date = mailDate + currentMail.Sender = fields[6] continue } else if strings.HasPrefix(line, "(") && strings.HasSuffix(line, ")") { // 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 } else if len(fields) == 1 { // Handle line with one of the mail recipients - currentMail.recipients = append(currentMail.recipients, fields[0]) + currentMail.Recipients = append(currentMail.Recipients, fields[0]) continue } else if len(fields) == 0 { // If the next line is empty, make sure to push current mail to list