sup

A curses threads-with-tags style email client

sup.git

git clone https://supmua.dev/git/sup/
commit d52179696306cd23334b7c947d3b14372e0661f0
parent 7d923e436836e71330a2875a1892d3dd9aeba29b
Author: William Morgan <wmorgan-sup@masanjin.net>
Date:   Wed, 30 Jul 2008 17:16:45 -0700

Merge commit 'origin/color'

Diffstat:
M bin/sup | 47 +----------------------------------------------
M lib/sup.rb | 1 +
M lib/sup/colormap.rb | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
3 files changed, 96 insertions(+), 48 deletions(-)
diff --git a/bin/sup b/bin/sup
@@ -140,53 +140,8 @@ begin
   log "starting curses"
   start_cursing
 
-  Colormap.new do |c|
-    c.add :status_color, Ncurses::COLOR_WHITE, Ncurses::COLOR_BLUE, Ncurses::A_BOLD
-    c.add :index_old_color, Ncurses::COLOR_WHITE, Ncurses::COLOR_BLACK
-    c.add :index_new_color, Ncurses::COLOR_WHITE, Ncurses::COLOR_BLACK, 
-           Ncurses::A_BOLD
-    c.add :index_starred_color, Ncurses::COLOR_YELLOW, Ncurses::COLOR_BLACK, 
-           Ncurses::A_BOLD
-    c.add :index_draft_color, Ncurses::COLOR_RED, Ncurses::COLOR_BLACK,
-           Ncurses::A_BOLD
-    c.add :labellist_old_color, Ncurses::COLOR_WHITE, Ncurses::COLOR_BLACK
-    c.add :labellist_new_color, Ncurses::COLOR_WHITE, Ncurses::COLOR_BLACK, 
-           Ncurses::A_BOLD
-    c.add :twiddle_color, Ncurses::COLOR_BLUE, Ncurses::COLOR_BLACK
-    c.add :label_color, Ncurses::COLOR_YELLOW, Ncurses::COLOR_BLACK
-    c.add :message_patina_color, Ncurses::COLOR_BLACK, Ncurses::COLOR_GREEN
-    c.add :alternate_patina_color, Ncurses::COLOR_BLACK, Ncurses::COLOR_BLUE
-    c.add :missing_message_color, Ncurses::COLOR_BLACK, Ncurses::COLOR_RED
-    c.add :attachment_color, Ncurses::COLOR_CYAN, Ncurses::COLOR_BLACK
-    c.add :cryptosig_valid_color, Ncurses::COLOR_YELLOW, Ncurses::COLOR_BLACK, Ncurses::A_BOLD
-    c.add :cryptosig_unknown_color, Ncurses::COLOR_CYAN, Ncurses::COLOR_BLACK
-    c.add :cryptosig_invalid_color, Ncurses::COLOR_YELLOW, Ncurses::COLOR_RED, Ncurses::A_BOLD
-    c.add :generic_notice_patina_color, Ncurses::COLOR_CYAN, Ncurses::COLOR_BLACK
-    c.add :quote_patina_color, Ncurses::COLOR_YELLOW, Ncurses::COLOR_BLACK
-    c.add :sig_patina_color, Ncurses::COLOR_YELLOW, Ncurses::COLOR_BLACK
-    c.add :quote_color, Ncurses::COLOR_YELLOW, Ncurses::COLOR_BLACK
-    c.add :sig_color, Ncurses::COLOR_YELLOW, Ncurses::COLOR_BLACK
-    c.add :to_me_color, Ncurses::COLOR_GREEN, Ncurses::COLOR_BLACK
-    c.add :starred_color, Ncurses::COLOR_YELLOW, Ncurses::COLOR_BLACK,
-          Ncurses::A_BOLD
-    c.add :starred_patina_color, Ncurses::COLOR_YELLOW, Ncurses::COLOR_GREEN,
-          Ncurses::A_BOLD
-    c.add :alternate_starred_patina_color, Ncurses::COLOR_YELLOW,
-          Ncurses::COLOR_BLUE, Ncurses::A_BOLD
-    c.add :snippet_color, Ncurses::COLOR_CYAN, Ncurses::COLOR_BLACK
-    c.add :option_color, Ncurses::COLOR_WHITE, Ncurses::COLOR_BLACK
-    c.add :tagged_color, Ncurses::COLOR_YELLOW, Ncurses::COLOR_BLACK,
-          Ncurses::A_BOLD
-    c.add :draft_notification_color, Ncurses::COLOR_RED, Ncurses::COLOR_BLACK,
-          Ncurses::A_BOLD
-    c.add :completion_character_color, Ncurses::COLOR_WHITE,
-          Ncurses::COLOR_BLACK, Ncurses::A_BOLD
-    c.add :horizontal_selector_selected_color, Ncurses::COLOR_YELLOW, Ncurses::COLOR_BLACK, Ncurses::A_BOLD
-    c.add :horizontal_selector_unselected_color, Ncurses::COLOR_CYAN, Ncurses::COLOR_BLACK
-    c.add :search_highlight_color, Ncurses::COLOR_BLACK, Ncurses::COLOR_YELLOW, Ncurses::A_BOLD, :highlight => :search_highlight_color
-  end
-
   bm = BufferManager.new
+  Colormap.new.populate_colormap
 
   log "initializing mail index buffer"
   imode = InboxMode.new
diff --git a/lib/sup.rb b/lib/sup.rb
@@ -37,6 +37,7 @@ module Redwood
 
   BASE_DIR   = ENV["SUP_BASE"] || File.join(ENV["HOME"], ".sup")
   CONFIG_FN  = File.join(BASE_DIR, "config.yaml")
+  COLOR_FN   = File.join(BASE_DIR, "colors.yaml")
   SOURCE_FN  = File.join(BASE_DIR, "sources.yaml")
   LABEL_FN   = File.join(BASE_DIR, "labels.txt")
   PERSON_FN  = File.join(BASE_DIR, "people.txt")
diff --git a/lib/sup/colormap.rb b/lib/sup/colormap.rb
@@ -1,3 +1,7 @@
+module Curses
+  COLOR_DEFAULT = -1
+end
+
 module Redwood
 
 class Colormap
@@ -6,8 +10,44 @@ class Colormap
   CURSES_COLORS = [Curses::COLOR_BLACK, Curses::COLOR_RED, Curses::COLOR_GREEN,
                    Curses::COLOR_YELLOW, Curses::COLOR_BLUE,
                    Curses::COLOR_MAGENTA, Curses::COLOR_CYAN,
-                   Curses::COLOR_WHITE]
+                   Curses::COLOR_WHITE, Curses::COLOR_DEFAULT]
   NUM_COLORS = 15
+
+  DEFAULT_COLORS = {
+    :status => { :fg => "white", :bg => "blue", :attrs => ["bold"] },
+    :index_old => { :fg => "white", :bg => "black" },
+    :index_new => { :fg => "white", :bg => "black", :attrs => ["bold"] },
+    :index_starred => { :fg => "yellow", :bg => "black", :attrs => ["bold"] },
+    :index_draft => { :fg => "red", :bg => "black", :attrs => ["bold"] },
+    :labellist_old => { :fg => "white", :bg => "black" },
+    :labellist_new => { :fg => "white", :bg => "black", :attrs => ["bold"] },
+    :twiddle => { :fg => "blue", :bg => "black" },
+    :label => { :fg => "yellow", :bg => "black" },
+    :message_patina => { :fg => "black", :bg => "green" },
+    :alternate_patina => { :fg => "black", :bg => "blue" },
+    :missing_message => { :fg => "black", :bg => "red" },
+    :attachment => { :fg => "cyan", :bg => "black" },
+    :cryptosig_valid => { :fg => "yellow", :bg => "black", :attrs => ["bold"] },
+    :cryptosig_unknown => { :fg => "cyan", :bg => "black" },
+    :cryptosig_invalid => { :fg => "yellow", :bg => "red", :attrs => ["bold"] },
+    :generic_notice_patina => { :fg => "cyan", :bg => "black" },
+    :quote_patina => { :fg => "yellow", :bg => "black" },
+    :sig_patina => { :fg => "yellow", :bg => "black" },
+    :quote => { :fg => "yellow", :bg => "black" },
+    :sig => { :fg => "yellow", :bg => "black" },
+    :to_me => { :fg => "green", :bg => "black" },
+    :starred => { :fg => "yellow", :bg => "black", :attrs => ["bold"] },
+    :starred_patina => { :fg => "yellow", :bg => "green", :attrs => ["bold"] },
+    :alternate_starred_patina => { :fg => "yellow", :bg => "blue", :attrs => ["bold"] },
+    :snippet => { :fg => "cyan", :bg => "black" },
+    :option => { :fg => "white", :bg => "black" },
+    :tagged => { :fg => "yellow", :bg => "black", :attrs => ["bold"] },
+    :draft_notification => { :fg => "red", :bg => "black", :attrs => ["bold"] },
+    :completion_character => { :fg => "white", :bg => "black", :attrs => ["bold"] },
+    :horizontal_selector_selected => { :fg => "yellow", :bg => "black", :attrs => ["bold"] },
+    :horizontal_selector_unselected => { :fg => "cyan", :bg => "black" },
+    :search_highlight => { :fg => "black", :bg => "yellow", :attrs => ["bold"] }
+  }
   
   def initialize
     raise "only one instance can be created" if @@instance
@@ -108,9 +148,61 @@ class Colormap
     color
   end
 
+  ## Try to use the user defined colors, in case of an error fall back
+  ## to the default ones.
+  def populate_colormap
+    user_colors = if File.exists? Redwood::COLOR_FN
+      Redwood::log "loading user colors from #{Redwood::COLOR_FN}"
+      Redwood::load_yaml_obj Redwood::COLOR_FN
+    end
+
+    error = nil
+    Colormap::DEFAULT_COLORS.each_pair do |k, v|
+      fg = Curses.const_get "COLOR_#{v[:fg].upcase}"
+      bg = Curses.const_get "COLOR_#{v[:bg].upcase}"
+      attrs = v[:attrs] ? v[:attrs].map { |a| Curses.const_get "A_#{a.upcase}" } : []
+
+      if user_colors && (ucolor = user_colors[k])
+        if(ufg = ucolor[:fg])
+          begin
+            fg = Curses.const_get "COLOR_#{ufg.upcase}"
+          rescue NameError
+            error ||= "Warning: there is no color named \"#{ufg}\", using fallback."
+            Redwood::log "Warning: there is no color named \"#{ufg}\""
+          end
+        end
+
+        if(ubg = ucolor[:bg])
+          begin
+            bg = Curses.const_get "COLOR_#{ubg.upcase}"
+          rescue NameError
+            error ||= "Warning: there is no color named \"#{ubg}\", using fallback."
+            Redwood::log "Warning: there is no color named \"#{ubg}\""
+          end
+        end
+
+        if(uattrs = ucolor[:attrs])
+          attrs = [*uattrs].flatten.map do |a|
+            begin
+              Curses.const_get "A_#{a.upcase}"
+            rescue NameError
+              error ||= "Warning: there is no attribute named \"#{a}\", using fallback."
+              Redwood::log "Warning: there is no attribute named \"#{a}\", using fallback."
+            end
+          end
+        end
+      end
+
+      symbol = (k.to_s + "_color").to_sym
+      add symbol, fg, bg, attrs
+    end
+
+    BufferManager.flash error if error
+  end
+
   def self.instance; @@instance; end
   def self.method_missing meth, *a
-    Colorcolors.new unless @@instance
+    Colormap.new unless @@instance
     @@instance.send meth, *a
   end
 end