sup

A curses threads-with-tags style email client

sup.git

git clone https://supmua.dev/git/sup/
commit e336a0e83da82f53be2cf5e5d8911ceeb096825a
parent c4902275ca37353c993a19edeaa9b8778afe14f3
Author: Dan Callaghan <djc@djc.id.au>
Date:   Sun,  3 May 2026 17:07:40 +1000

micro-optimisation for Maildir#maildir_labels

Refactor to avoid repeatedly applying a regexp to the message filename
to extract every maildir flag individually.

The =~ operator shows up as frequently called in a profile of indexing
a maildir from scratch, and I was just looking for some likely
candidates where it can be removed. I don't think this made any overall
difference to indexing speed but it's a reasonable cleanup.

Diffstat:
M Manifest.txt | 1 +
M lib/sup/maildir.rb | 33 +++++++++++++++++++++------------
A test/unit/test_maildir.rb | 21 +++++++++++++++++++++
3 files changed, 43 insertions(+), 12 deletions(-)
diff --git a/Manifest.txt b/Manifest.txt
@@ -183,6 +183,7 @@ test/unit/test_horizontal_selector.rb
 test/unit/test_index.rb
 test/unit/test_line_cursor_mode.rb
 test/unit/test_locale_fiddler.rb
+test/unit/test_maildir.rb
 test/unit/test_person.rb
 test/unit/test_rmail_message.rb
 test/unit/util/test_query.rb
diff --git a/lib/sup/maildir.rb b/lib/sup/maildir.rb
@@ -189,20 +189,29 @@ class Maildir < Source
   end
 
   def maildir_labels id
-    (seen?(id) ? [] : [:unread]) +
-      (trashed?(id) ?  [:deleted] : []) +
-      (flagged?(id) ? [:starred] : []) +
-      (passed?(id) ? [:forwarded] : []) +
-      (replied?(id) ? [:replied] : []) +
-      (draft?(id) ? [:draft] : [])
+    flags = maildir_flags id
+    labels = []
+    labels << :unread unless flags.member? :seen
+    labels << :deleted if flags.member? :trashed
+    labels << :starred if flags.member? :flagged
+    labels << :forwarded if flags.member? :passed
+    labels << :replied if flags.member? :replied
+    labels << :draft if flags.member? :draft
+    labels
   end
 
-  def draft? id; maildir_data(id)[2].include? "D"; end
-  def flagged? id; maildir_data(id)[2].include? "F"; end
-  def passed? id; maildir_data(id)[2].include? "P"; end
-  def replied? id; maildir_data(id)[2].include? "R"; end
-  def seen? id; maildir_data(id)[2].include? "S"; end
-  def trashed? id; maildir_data(id)[2].include? "T"; end
+  def maildir_flags id
+    maildir_data(id)[2].each_char.map do |c|
+      case c
+      when 'D' then :draft
+      when 'F' then :flagged
+      when 'P' then :passed
+      when 'R' then :replied
+      when 'S' then :seen
+      when 'T' then :trashed
+      end
+    end
+  end
 
   def valid? id
     File.exist? File.join(@dir, id)
diff --git a/test/unit/test_maildir.rb b/test/unit/test_maildir.rb
@@ -0,0 +1,21 @@
+require 'test_helper'
+require 'sup'
+require 'sup/maildir'
+
+module Redwood
+
+class TestMaildir < Minitest::Test
+  def test_flag_parsing
+    maildir = Maildir.new "maildir:/nowhere"
+    labels = maildir.labels? "asdf:2,S"
+    assert_equal [], labels
+    labels = maildir.labels? "asdf:2,"
+    assert_equal [:unread], labels
+    labels = maildir.labels? "asdf:2,DFPRST"
+    assert_equal [:deleted, :starred, :forwarded, :replied, :draft], labels
+    labels = maildir.labels? "asdf:2,DFPRT"
+    assert_equal [:unread, :deleted, :starred, :forwarded, :replied, :draft], labels
+  end
+end
+
+end