1package main23import (4 "github.com/gdamore/tcell/v2"5 "log"6 "os"7)89func initScreen() (tcell.Screen, error) {10 s, err := tcell.NewScreen()11 if err != nil {12 return nil, err13 }14 if err := s.Init(); err != nil {15 return nil, err16 }17 s.SetStyle(defStyle)18 s.EnablePaste()19 s.Clear()20 return s, nil21}2223func fatal(ui *UserInterface, v ...any) {24 cleanup(ui)25 log.Fatal(v...)26}2728func handleEventKey(ui *UserInterface, ev *tcell.EventKey) {29 switch ev.Key() {30 case tcell.KeyEnter:31 err := ui.withoutScreen(func() error {32 mail := ui.SelectedMail()33 return mail.Show()34 })35 if err != nil {36 fatal(ui, err)37 }38 case tcell.KeyRune:39 mail := ui.SelectedMail()40 switch ev.Rune() {41 case 'r':42 err := ui.withoutScreen(func() error {43 mail := ui.SelectedMail()44 return mail.Reply()45 })46 if err != nil {47 fatal(ui, err)48 }49 case 'd':50 err := os.Remove(mail.Path)51 if err != nil {52 fatal(ui, err)53 }54 case 'f':55 mail.Flag(Flagged)56 case 'F':57 mail.Flag(Unflagged)58 case 's':59 mail.Flag(Unseen)60 case 'S':61 mail.Flag(Seen)62 case 't':63 mail.Flag(Untrashed)64 case 'T':65 mail.Flag(Trashed)66 default:67 return68 }6970 // TODO: Consider using `mflag -v` above to determine the71 // new file names and thereby keep the sequence in tact.7273 err := ui.Refresh()74 if err != nil {75 fatal(ui, err)76 }7778 ui.Screen.Clear()79 ui.Draw()80 case tcell.KeyDown:81 ui.NextMail()82 case tcell.KeyUp:83 ui.PrevMail()84 case tcell.KeyPgDn:85 ui.NextPage()86 case tcell.KeyPgUp:87 ui.PrevPage()88 case tcell.KeyCtrlL:89 ui.Screen.Sync()90 }91}9293func eventLoop(ui *UserInterface) {94 for {95 ui.Screen.Show()96 ev := ui.Screen.PollEvent()9798 switch ev := ev.(type) {99 case *tcell.EventResize:100 ui.Draw()101 ui.Screen.Sync()102 case *tcell.EventKey:103 if ev.Key() == tcell.KeyEscape ||104 ev.Key() == tcell.KeyCtrlC ||105 (ev.Key() == tcell.KeyRune && ev.Rune() == 'q') {106 return107 }108109 handleEventKey(ui, ev)110 }111 }112}113114func cleanup(ui *UserInterface) {115 // You have to catch panics in a defer, clean up, and116 // re-raise them - otherwise your application can117 // die without leaving any diagnostic trace.118 maybePanic := recover()119120 ui.Screen.Fini()121 if maybePanic != nil {122 panic(maybePanic)123 }124}125126func main() {127 mails, err := mscan()128 if err != nil {129 log.Fatal(err)130 }131132 screen, err := initScreen()133 if err != nil {134 log.Fatal(err)135 }136137 ui := NewUI(mails, screen)138 defer cleanup(ui)139140 ui.Draw()141 eventLoop(ui)142}