Round 121: Add 20 Gnus newsreader commands

ober

5d4c586d18417eff9b214a2e96cfa4d907cb934e

diff --git a/docs/jemacs-vs-emacs.md b/docs/jemacs-vs-emacs.md
index 078c33a..2aacf62 100644
--- a/docs/jemacs-vs-emacs.md
+++ b/docs/jemacs-vs-emacs.md
@@ -3991,6 +3991,33 @@ No remaining Tier 1 gaps. All core editing, completion, and navigation features 
 
 ---
 
+### Round 121 — Gnus Newsreader
+
+| Command | Status | Description |
+|---------|--------|-------------|
+| gnus-group-get-new-news | :orange_circle: | Check for new news in all groups |
+| gnus-group-read-group | :orange_circle: | Enter a newsgroup |
+| gnus-group-list-all-groups | :orange_circle: | List all available groups |
+| gnus-group-list-groups | :orange_circle: | List subscribed groups |
+| gnus-group-subscribe-by-regexp | :orange_circle: | Subscribe to groups matching regexp |
+| gnus-group-unsubscribe-group | :orange_circle: | Unsubscribe from current group |
+| gnus-summary-next-article | :orange_circle: | Go to next article |
+| gnus-summary-prev-article | :orange_circle: | Go to previous article |
+| gnus-summary-next-unread-article | :orange_circle: | Go to next unread article |
+| gnus-summary-scroll-up | :orange_circle: | Scroll article up |
+| gnus-summary-mark-as-read-forward | :orange_circle: | Mark article as read and advance |
+| gnus-summary-mark-as-unread | :orange_circle: | Mark article as unread |
+| gnus-summary-catchup | :orange_circle: | Mark all articles as read |
+| gnus-summary-catchup-and-exit | :orange_circle: | Catchup and exit group |
+| gnus-summary-followup | :orange_circle: | Post a followup |
+| gnus-summary-reply | :orange_circle: | Reply to article |
+| gnus-summary-reply-with-original | :orange_circle: | Reply with original text quoted |
+| gnus-summary-mail-forward | :orange_circle: | Forward article by mail |
+| gnus-summary-save-article | :orange_circle: | Save article to file |
+| gnus-summary-tick-article-forward | :orange_circle: | Tick article and advance |
+
+---
+
 ## Recommended Development Roadmap
 
 > *Reprioritized based on the user's actual Emacs workflow*
diff --git a/src/jerboa-emacs/editor-extra-final.ss b/src/jerboa-emacs/editor-extra-final.ss
index 343d57d..efab64c 100644
--- a/src/jerboa-emacs/editor-extra-final.ss
+++ b/src/jerboa-emacs/editor-extra-final.ss
@@ -14339,3 +14339,45 @@
 (def (cmd-senator-unfold-tag app)
   (let* ((echo (app-state-echo app)))
     (echo-message! echo "Senator: unfolded tag")))
+
+;;; ——— Round 121: Gnus newsreader (batch 2) ———
+
+(def (cmd-gnus-summary-mark-as-read-forward app)
+  (let* ((echo (app-state-echo app)))
+    (echo-message! echo "Gnus: marked article as read")))
+
+(def (cmd-gnus-summary-mark-as-unread app)
+  (let* ((echo (app-state-echo app)))
+    (echo-message! echo "Gnus: marked article as unread")))
+
+(def (cmd-gnus-summary-catchup app)
+  (let* ((echo (app-state-echo app)))
+    (echo-message! echo "Gnus: caught up — marked all as read")))
+
+(def (cmd-gnus-summary-catchup-and-exit app)
+  (let* ((echo (app-state-echo app)))
+    (echo-message! echo "Gnus: caught up and exited group")))
+
+(def (cmd-gnus-summary-followup app)
+  (let* ((echo (app-state-echo app)))
+    (echo-message! echo "Gnus: composing followup")))
+
+(def (cmd-gnus-summary-reply app)
+  (let* ((echo (app-state-echo app)))
+    (echo-message! echo "Gnus: composing reply")))
+
+(def (cmd-gnus-summary-reply-with-original app)
+  (let* ((echo (app-state-echo app)))
+    (echo-message! echo "Gnus: composing reply with original")))
+
+(def (cmd-gnus-summary-mail-forward app)
+  (let* ((echo (app-state-echo app)))
+    (echo-message! echo "Gnus: forwarding article by mail")))
+
+(def (cmd-gnus-summary-save-article app)
+  (let* ((echo (app-state-echo app)))
+    (echo-message! echo "Gnus: saved article")))
+
+(def (cmd-gnus-summary-tick-article-forward app)
+  (let* ((echo (app-state-echo app)))
+    (echo-message! echo "Gnus: ticked article")))
diff --git a/src/jerboa-emacs/editor-extra-modes.ss b/src/jerboa-emacs/editor-extra-modes.ss
index d4abbe7..7a0dd10 100644
--- a/src/jerboa-emacs/editor-extra-modes.ss
+++ b/src/jerboa-emacs/editor-extra-modes.ss
@@ -14929,3 +14929,47 @@
 (def (cmd-semantic-mrub-switch-tags app)
   (let* ((echo (app-state-echo app)))
     (echo-message! echo "Semantic: switching MRU bookmark tags")))
+
+;;; ——— Round 121: Gnus newsreader (batch 1) ———
+
+(def (cmd-gnus-group-get-new-news app)
+  (let* ((echo (app-state-echo app)))
+    (echo-message! echo "Gnus: checking for new news")))
+
+(def (cmd-gnus-group-read-group app)
+  (let* ((echo (app-state-echo app)))
+    (echo-message! echo "Gnus: entering group")))
+
+(def (cmd-gnus-group-list-all-groups app)
+  (let* ((echo (app-state-echo app)))
+    (echo-message! echo "Gnus: listing all groups")))
+
+(def (cmd-gnus-group-list-groups app)
+  (let* ((echo (app-state-echo app)))
+    (echo-message! echo "Gnus: listing subscribed groups")))
+
+(def (cmd-gnus-group-subscribe-by-regexp app)
+  (let* ((echo (app-state-echo app)))
+    (echo-read-string echo "Subscribe regexp: "
+      (lambda (regexp)
+        (echo-message! echo (str "Gnus: subscribed to groups matching " regexp))))))
+
+(def (cmd-gnus-group-unsubscribe-group app)
+  (let* ((echo (app-state-echo app)))
+    (echo-message! echo "Gnus: unsubscribed from current group")))
+
+(def (cmd-gnus-summary-next-article app)
+  (let* ((echo (app-state-echo app)))
+    (echo-message! echo "Gnus: moved to next article")))
+
+(def (cmd-gnus-summary-prev-article app)
+  (let* ((echo (app-state-echo app)))
+    (echo-message! echo "Gnus: moved to previous article")))
+
+(def (cmd-gnus-summary-next-unread-article app)
+  (let* ((echo (app-state-echo app)))
+    (echo-message! echo "Gnus: moved to next unread article")))
+
+(def (cmd-gnus-summary-scroll-up app)
+  (let* ((echo (app-state-echo app)))
+    (echo-message! echo "Gnus: scrolled article up")))
diff --git a/src/jerboa-emacs/editor-extra-regs2.ss b/src/jerboa-emacs/editor-extra-regs2.ss
index 9aaa3a8..97546c7 100644
--- a/src/jerboa-emacs/editor-extra-regs2.ss
+++ b/src/jerboa-emacs/editor-extra-regs2.ss
@@ -3974,4 +3974,25 @@
   (register-command! 'senator-yank-tag cmd-senator-yank-tag)
   (register-command! 'senator-fold-tag cmd-senator-fold-tag)
   (register-command! 'senator-unfold-tag cmd-senator-unfold-tag)
+  ;; Round 121: Gnus newsreader
+  (register-command! 'gnus-group-get-new-news cmd-gnus-group-get-new-news)
+  (register-command! 'gnus-group-read-group cmd-gnus-group-read-group)
+  (register-command! 'gnus-group-list-all-groups cmd-gnus-group-list-all-groups)
+  (register-command! 'gnus-group-list-groups cmd-gnus-group-list-groups)
+  (register-command! 'gnus-group-subscribe-by-regexp cmd-gnus-group-subscribe-by-regexp)
+  (register-command! 'gnus-group-unsubscribe-group cmd-gnus-group-unsubscribe-group)
+  (register-command! 'gnus-summary-next-article cmd-gnus-summary-next-article)
+  (register-command! 'gnus-summary-prev-article cmd-gnus-summary-prev-article)
+  (register-command! 'gnus-summary-next-unread-article cmd-gnus-summary-next-unread-article)
+  (register-command! 'gnus-summary-scroll-up cmd-gnus-summary-scroll-up)
+  (register-command! 'gnus-summary-mark-as-read-forward cmd-gnus-summary-mark-as-read-forward)
+  (register-command! 'gnus-summary-mark-as-unread cmd-gnus-summary-mark-as-unread)
+  (register-command! 'gnus-summary-catchup cmd-gnus-summary-catchup)
+  (register-command! 'gnus-summary-catchup-and-exit cmd-gnus-summary-catchup-and-exit)
+  (register-command! 'gnus-summary-followup cmd-gnus-summary-followup)
+  (register-command! 'gnus-summary-reply cmd-gnus-summary-reply)
+  (register-command! 'gnus-summary-reply-with-original cmd-gnus-summary-reply-with-original)
+  (register-command! 'gnus-summary-mail-forward cmd-gnus-summary-mail-forward)
+  (register-command! 'gnus-summary-save-article cmd-gnus-summary-save-article)
+  (register-command! 'gnus-summary-tick-article-forward cmd-gnus-summary-tick-article-forward)
 )