Leo Butler <[email protected]> writes:

>
> Thanks, Morgan.
>
> Forgive the question, but what did you grep to find this?
>
> Leo

This was a question I was expecting and dreading :P

I should do a write up on worg but I still don't quite understand my
setup

This uses the program "public-inbox" which when installed should
provide all the executables mentioned (public-inbox-clone,
public-inbox-index, lei).

I spun up a container to confirm my instructions and found many things
that where wrong so either things have changed recently or I'm not good
at taking notes.

First we want to use public-inbox to grab and index the mailing list:

#+begin_src sh
mkdir ~/.local/share/public-inbox
public-inbox-clone https://list.orgmode.org/orgmode 
~/.local/share/public-inbox/orgmode
public-inbox-index ~/.local/share/public-inbox/orgmode
#+end_src

This is the one-time setup.  If you'd like to update an existing
public-inbox do this (I had some issues with "$HOME" so maybe try
hard-coding that part):

#+begin_src sh
set -e # error on error
public-inbox-fetch --exit-code -C$HOME/.local/share/public-inbox/orgmode
public-inbox-index -C$HOME/.local/share/public-inbox/orgmode
#+end_src

Now we want to use the "lei" tool to view and query the mailing list.
First we need to do a one-time setup:

#+begin_src sh
lei add-external ~/.local/share/public-inbox/orgmode
#+end_src

Now we can test lei by doing a simple query.  How about looking for mail
based on the subject line?

#+begin_src sh :wrap "src json"
lei q s:"New LaTeX previews not showing"
#+end_src

#+RESULTS:
#+begin_src json
[{"blob":"f4690a928e76e43f3aea0a6f09e157f31350bd9e", ...
null]
#+end_src

Looks like that works great!  Now lets try and grab every open bug from
https://tracker.orgmode.org, and print it out using "lei lcat --no-color
--threads MESSAGE-ID".  The "--threads" means we get the entire thread.

Since we will sometimes end up printing out the same thread multiple
times (one thread can contain multiple bug reports), we will do some
minor de-duplication by making the file-name be a content hash.

#+begin_src elisp
(let ((output-directory (expand-file-name "~/output-dir"))
      ;; wget https://tracker.orgmode.org/reports/all-open.json
      (tracker-json (expand-file-name "~/downloads/all-open.json"))
      (enable-local-variables nil))
  (mkdir output-directory t)
  (cl-flet*
      ((get-message-id-list ()
         (with-current-buffer (or (find-buffer-visiting tracker-json)
                                  (find-file-noselect tracker-json t t))
           (goto-char (point-min))
           (seq-map
            (lambda (report)
              (alist-get 'message-id report))
            (alist-get
             'reports
             (json-parse-buffer
              :object-type 'alist)))))
       (output-thread-to-file (message-id)
         (with-temp-buffer
           (shell-command (concat "lei lcat --no-color --threads "
                                  "'" message-id "'")
                          (current-buffer))
           ;; File name is sha of content so we don't have duplicate files
           (let ((file (concat (sha1 (buffer-string)) ".txt")))
             (unless (file-exists-p file)
               (write-file file))
             file))))
    (let ((default-directory output-directory))
      (mapc
       #'output-thread-to-file
       (get-message-id-list))
      nil)))
#+end_src


Now you should have a directory full of open bug reports that you can
grep!  Then whenever you see something you want to interact with you can
open using a message-id you find in the file.  You might want a helper
function like this:

#+BEGIN_SRC elisp
(defun my-orglist-open (message-id)
  "Open MESSAGE-ID orglist mail."
  (interactive "smessage-id: \n")
  (browse-url (concat "orgmode.org/list/"
                      (string-trim message-id "<" ">"))))
#+END_SRC

But you probably actually want to visit the email in an email reader,
not the webpage.

So to read the public-inbox stuff in an email reader, lets host the
inbox over nntp locally:

#+begin_src sh
public-inbox-nntpd -l localhost:9012
#+end_src

The nntp may or may not require a public-inbox config file.  I'm not sure.  If
it does then do this:

#+begin_src sh
mkdir ~/.public-inbox
cp ~/.local/share/public-inbox/orgmode/inbox.config.example 
~/.public-inbox/config
# manually edit ~/.public-inbox/config
#+end_src

I honestly don't understand the config file at all but I modified mine like
this and it seems to work I guess.  I would love to know what any of this stuff
actually does.  I just kinda did trial and error to discover it.

#+begin_src diff
diff -u -r /home/pancake/.local/share/public-inbox/orgmode/inbox.config.example 
/home/pancake/.public-inbox/config
--- /home/pancake/.local/share/public-inbox/orgmode/inbox.config.example        
2020-04-04 15:06:34.000000000 -0400
+++ /home/pancake/.public-inbox/config  2025-10-06 10:43:41.989904965 -0400
@@ -3,12 +3,8 @@
 ; See public-inbox-config(5) manpage for more details:
 ; https://public-inbox.org/public-inbox-config.html
 [publicinbox "orgmode"]
-       inboxdir = /path/to/top-level-inbox
-       ; note: public-inbox before v1.2.0 used `mainrepo' instead of
-       ; `inboxdir', both remain supported after 1.2
-       mainrepo = /path/to/top-level-inbox
-       url = https://example.com/orgmode/
-       url = http://example.onion/orgmode/
+       inboxdir = /home/pancake/.local/share/public-inbox/orgmode
+       ; url = https://example.com/orgmode/
        address = [email protected]
        infourl = https://www.orgmode.org/
        watchheader = To:[email protected]
@@ -20,9 +16,9 @@
        ;       curl -d '' https://list.orgmode.org/orgmode/gmane.sql.gz | \
        ;       gzip -dc | \
        ;       sqlite3 /path/to/top-level-inbox/gmane.sqlite3
-       altid = serial:gmane:file=gmane.sqlite3
-       filter = PublicInbox::Filter::Mirror
-       newsgroup = yhetil.emacs.orgmode
-       imapmirror = imaps://news.yhetil.org/yhetil.emacs.orgmode
-       nntpmirror = nntp://news.yhetil.org/yhetil.emacs.orgmode
-       nntpmirror = nntp://news.gmane.io/gmane.emacs.orgmode
+       ; altid = serial:gmane:file=gmane.sqlite3
+       ; filter = PublicInbox::Filter::Mirror
+       newsgroup = emacs.orgmode
+       ; imapmirror = imaps://news.yhetil.org/yhetil.emacs.orgmode
+       ; nntpmirror = nntp://news.yhetil.org/yhetil.emacs.orgmode
+       ; nntpmirror = nntp://news.gmane.io/gmane.emacs.orgmode

Diff finished.  Tue Oct 20 13:45:03 2026
#+end_src

Now let's connect to it using gnus

#+begin_src elisp
(setopt
 gnus-secondary-select-methods
 (list
  ...
  '(nntp "nntp"
         (nntp-address "localhost")
         (nntp-port-number 9012)
         (nntp-open-connection-function nntp-open-plain-stream))))
#+end_src

And now let's tell browse-url to open links using gnus:

#+begin_src elisp
(setopt browse-url-handlers
        `((,(rx (or "list.orgmode.org/" "orgmode.org/list/")) .
           ,(lambda (host-or-url &rest _)
              (org-gnus-follow-link "nntp+nntp:emacs.orgmode";
                                    (string-trim
                                     host-or-url
                                     (rx (* anychar) (or (and 
"list.orgmode.org/" (? "orgmode/"))
                                                         "orgmode.org/list/"))
                                     "/.*"))))))
#+end_src

And you're done!  If you figure out how to streamline this at all do let me
know.  This is probably way more complicated then it needs to be.

Reply via email to