From e85d4ccc3c94cc8152de623279410d7b9d072491 Mon Sep 17 00:00:00 2001
From: Kevin Lyda <kevin@lyda.ie>
Date: Tue, 20 May 2025 11:16:59 +0100
Subject: [PATCH] Fix READ and REPLY

---
 NOTES.md           |  2 +-
 editor/tview.go    |  2 +-
 go.mod             | 10 +++++-----
 go.sum             |  4 ++++
 repl/folders.go    |  1 +
 repl/messages.go   | 29 ++++++++++++++++-------------
 repl/misc.go       |  2 --
 repl/set.go        |  1 +
 storage/display.go |  3 ++-
 this/this.go       |  5 +++++
 10 files changed, 36 insertions(+), 23 deletions(-)

diff --git a/NOTES.md b/NOTES.md
index 1a75180..416091d 100644
--- a/NOTES.md
+++ b/NOTES.md
@@ -41,7 +41,7 @@ Top level:
  +Ctrl-C    +CURRENT    DELETE     DIRECTORY +EXIT      +FIRST
  +Folders    FORWARD   +HELP       INDEX     +Keypad    +LAST
   MAIL      +MARK       MODIFY     MOVE      +NEXT       PRINT
- +QUIT       READ       REMOVE     REPLY      RESPOND    SEARCH
+ +QUIT      +READ       REMOVE    +REPLY      RESPOND    SEARCH
   SEEN       SELECT    +SET       +SHOW      +SSH       +UNMARK
   UNSEEN    +USER
 
diff --git a/editor/tview.go b/editor/tview.go
index c4d5a58..cd6346b 100644
--- a/editor/tview.go
+++ b/editor/tview.go
@@ -139,7 +139,7 @@ Press Enter for more help, press Escape to return.`)
 	})
 
 	if message != "" {
-		textArea.SetText(message, true)
+		textArea.SetText(message, false)
 	}
 	err := app.SetRoot(pages, true).Run()
 	if err != nil {
diff --git a/go.mod b/go.mod
index eeb07db..9c7734c 100644
--- a/go.mod
+++ b/go.mod
@@ -11,6 +11,9 @@ require (
 	github.com/jmoiron/sqlx v1.4.0
 	github.com/rivo/tview v0.0.0-20250501113434-0c592cd31026
 	github.com/urfave/cli/v3 v3.3.3
+	golang.org/x/crypto v0.38.0
+	golang.org/x/sys v0.33.0
+	golang.org/x/term v0.32.0
 	modernc.org/sqlite v1.37.0
 )
 
@@ -92,13 +95,10 @@ require (
 	go.uber.org/atomic v1.11.0 // indirect
 	go.uber.org/multierr v1.11.0 // indirect
 	go.uber.org/zap v1.27.0 // indirect
-	golang.org/x/crypto v0.38.0 // indirect
 	golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 // indirect
 	golang.org/x/mod v0.24.0 // indirect
 	golang.org/x/net v0.40.0 // indirect
 	golang.org/x/sync v0.14.0 // indirect
-	golang.org/x/sys v0.33.0 // indirect
-	golang.org/x/term v0.32.0 // indirect
 	golang.org/x/text v0.25.0 // indirect
 	golang.org/x/tools v0.33.0 // indirect
 	google.golang.org/genproto/googleapis/api v0.0.0-20250218202821-56aae31c358a // indirect
@@ -107,9 +107,9 @@ require (
 	google.golang.org/protobuf v1.36.6 // indirect
 	gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
 	gopkg.in/yaml.v3 v3.0.1 // indirect
-	modernc.org/libc v1.65.6 // indirect
+	modernc.org/libc v1.65.7 // indirect
 	modernc.org/mathutil v1.7.1 // indirect
-	modernc.org/memory v1.10.0 // indirect
+	modernc.org/memory v1.11.0 // indirect
 	mvdan.cc/gofumpt v0.7.0 // indirect
 )
 
diff --git a/go.sum b/go.sum
index 5833472..af023d1 100644
--- a/go.sum
+++ b/go.sum
@@ -352,10 +352,14 @@ modernc.org/libc v1.65.2 h1:drWL1QO9fKXr3kXDN8y+4lKyBr8bA3mtUBQpftq3IJw=
 modernc.org/libc v1.65.2/go.mod h1:VI3V2S5mNka4deJErQ0jsMXe7jgxojE2fOB/mWoHlbc=
 modernc.org/libc v1.65.6 h1:OhJUhmuJ6MVZdqL5qmnd0/my46DKGFhSX4WOR7ijfyE=
 modernc.org/libc v1.65.6/go.mod h1:MOiGAM9lrMBT9L8xT1nO41qYl5eg9gCp9/kWhz5L7WA=
+modernc.org/libc v1.65.7 h1:Ia9Z4yzZtWNtUIuiPuQ7Qf7kxYrxP1/jeHZzG8bFu00=
+modernc.org/libc v1.65.7/go.mod h1:011EQibzzio/VX3ygj1qGFt5kMjP0lHb0qCW5/D/pQU=
 modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
 modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
 modernc.org/memory v1.10.0 h1:fzumd51yQ1DxcOxSO+S6X7+QTuVU+n8/Aj7swYjFfC4=
 modernc.org/memory v1.10.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw=
+modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI=
+modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw=
 modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8=
 modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns=
 modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w=
diff --git a/repl/folders.go b/repl/folders.go
index 5eb22c9..dc67560 100644
--- a/repl/folders.go
+++ b/repl/folders.go
@@ -107,6 +107,7 @@ func ActionSelect(cmd *dclish.Command) error {
 	}
 	if folders.IsFolderAccess(folder.Name, this.User.Login) {
 		this.Folder = folder
+		this.ReadFirstCall = true
 		fmt.Printf("Folder has been set to '%s'.\n", folder.Name)
 		return nil
 	}
diff --git a/repl/messages.go b/repl/messages.go
index 03f352a..ff2611f 100644
--- a/repl/messages.go
+++ b/repl/messages.go
@@ -27,9 +27,15 @@ func ActionDirectory(cmd *dclish.Command) error {
 	if len(cmd.Args) == 1 {
 		folder, err := folders.ValidFolder(cmd.Args[0])
 		if err != nil {
-			return err
+			fmt.Println("Folder does not exist.")
+			return nil
+		}
+		if !folders.IsFolderAccess(folder.Name, this.User.Login) {
+			fmt.Println("No permission to access folder.")
+			return nil
 		}
 		this.Folder = folder
+		this.ReadFirstCall = true
 	}
 	msgs, err := folders.ListMessages(this.Folder.Name)
 	if err != nil {
@@ -272,25 +278,28 @@ func ActionPrint(cmd *dclish.Command) error {
 
 // ActionRead handles the `READ` command.
 func ActionRead(cmd *dclish.Command) error {
-	// TODO: Implement the functionality of incrementing the message number *first* but not the first time the command is run.
-	// TODO: handle flags.
+	defer func() { this.ReadFirstCall = false }()
 	msgid := this.MsgID
-	if len(cmd.Args) == 1 {
+	if !this.ReadFirstCall && len(cmd.Args) == 0 {
+		msgid = folders.NextMsgid(this.User.Login, this.Folder.Name, msgid)
+		if msgid < this.MsgID {
+			fmt.Println("No more unread messages.")
+			return nil
+		}
+	} else if len(cmd.Args) == 1 {
 		var err error
 		msgid, err = strconv.ParseInt(cmd.Args[0], 10, 64)
 		if err != nil {
 			return err
 		}
 	}
+	this.MsgID = msgid
 	msg, err := folders.ReadMessage(this.User.Login, this.Folder.Name, msgid)
 	if err != nil {
 		return err
 	}
-	// TODO: Show the message id?
 	if pager.Pager(msg.String()) {
 		folders.MarkSeen([]int64{msgid})
-		msgid = folders.NextMsgid(this.User.Login, this.Folder.Name, msgid)
-		this.MsgID = max(this.MsgID, msgid)
 	}
 	return nil
 }
@@ -305,22 +314,16 @@ func ActionReply(cmd *dclish.Command) error {
 	if cmd.Flags["/INDENT"].Value == "false" {
 		indent = false
 	}
-	fmt.Printf("TODO: getting message %d.\n", this.MsgID)
 	original, err := folders.ReadMessage(this.User.Login, this.Folder.Name, this.MsgID)
 	origMsg := ""
 	if extract {
 		if indent {
 			origMsg = "> " + strings.Join(strings.Split(original.Message, "\n"), "\n> ")
-			fmt.Println("TODO: extract and indent are true.")
 		} else {
 			origMsg = original.Message
-			fmt.Println("TODO: extract is true.")
 		}
-	} else {
-		fmt.Println("TODO: neither is true.")
 	}
 
-	// TODO; this isn't working - the message isn't getting loaded.
 	subject := "Re: " + original.Subject
 	message, err := editor.Editor(
 		fmt.Sprintf("Enter message for '%s'...", subject),
diff --git a/repl/misc.go b/repl/misc.go
index fd168a4..edd0a01 100644
--- a/repl/misc.go
+++ b/repl/misc.go
@@ -10,7 +10,6 @@ import (
 
 // ActionQuit handles the `QUIT` command.
 func ActionQuit(_ *dclish.Command) error {
-	// TODO: IIRC, quit should not update unread data.  Check old code to confirm.
 	fmt.Println("QUIT")
 	os.Exit(0)
 	return nil
@@ -18,7 +17,6 @@ func ActionQuit(_ *dclish.Command) error {
 
 // ActionExit handles the `EXIT` command.
 func ActionExit(_ *dclish.Command) error {
-	// TODO: update unread data.
 	fmt.Println("EXIT")
 	os.Exit(0)
 	return nil
diff --git a/repl/set.go b/repl/set.go
index 51e674c..fc7bc80 100644
--- a/repl/set.go
+++ b/repl/set.go
@@ -93,6 +93,7 @@ func ActionSetFolder(cmd *dclish.Command) error {
 	}
 	if folders.IsFolderAccess(folder.Name, this.User.Login) {
 		this.Folder = folder
+		fmt.Printf("TODO: getting message %d.\n", this.MsgID)
 		fmt.Printf("Folder has been set to '%s'.\n", folder.Name)
 		return nil
 	}
diff --git a/storage/display.go b/storage/display.go
index 7972da1..05f904d 100644
--- a/storage/display.go
+++ b/storage/display.go
@@ -13,9 +13,10 @@ func (m *Message) String() string {
 	if m.CreateAt.Compare(m.UpdateAt) == 0 {
 		changed = ""
 	}
+	fmt.Fprintf(buf, "Msg : %d\n", m.ID)
 	fmt.Fprintf(buf, "From: \"%s\" %s%s\n", m.Author,
 		m.CreateAt.Format("02-JAN-2006 15:04:05"), changed)
-	fmt.Fprintf(buf, "To: %s\n", m.Folder)
+	fmt.Fprintf(buf, "To  : %s\n", m.Folder)
 	fmt.Fprintf(buf, "Subj: %s\n\n", m.Subject)
 	fmt.Fprintf(buf, "%s\n", m.Message)
 
diff --git a/this/this.go b/this/this.go
index 922426b..97be72d 100644
--- a/this/this.go
+++ b/this/this.go
@@ -35,6 +35,10 @@ var Folder storage.Folder
 // MsgID is the current message id.
 var MsgID int64
 
+// ReadFirstCall tracks whether this is the first time READ has been
+// used in a folder since changing into it.
+var ReadFirstCall bool
+
 // StartThis starts a session.
 func StartThis(login string) error {
 	// Validate the login name.
@@ -91,6 +95,7 @@ func StartThis(login string) error {
 	if err != nil {
 		return err
 	}
+	ReadFirstCall = true
 	MsgID, err = Q.NextMsgid(ctx, storage.NextMsgidParams{
 		Folder: Folder.Name,
 		ID:     0,
-- 
GitLab