Class: Heathrow::Config
- Inherits:
-
Object
- Object
- Heathrow::Config
- Defined in:
- lib/heathrow/config.rb
Constant Summary collapse
- HEATHROWRC =
File.('~/.heathrow/heathrowrc')
Class Attribute Summary collapse
-
.instance ⇒ Object
Returns the value of attribute instance.
Instance Attribute Summary collapse
-
#settings ⇒ Object
Returns the value of attribute settings.
Class Method Summary collapse
Instance Method Summary collapse
- #[](key) ⇒ Object
- #[]=(key, value) ⇒ Object
-
#bind(key, shell: nil, action: nil, prompt: nil, description: nil) ⇒ Object
Bind a key to a custom action Usage: bind 'C-S', shell: 'mailq' # Run shell command, show output bind 'C-N', shell: 'notmuch search %q' # %q = prompted query bind 'C-O', action: :open_in_browser # Call a Heathrow method bind '\', shell: 'my-script %f' # %f = current message file path.
- #channel_name_map ⇒ Object
-
#channel_names(mapping) ⇒ Object
Map Discord channel IDs to display names Usage: channel_names '123456789' => 'MyServer#general', '987654321' => 'MyServer#dev'.
- #create_default_config ⇒ Object
- #custom_bindings ⇒ Object
- #custom_themes ⇒ Object
- #custom_views ⇒ Object
- #delete_db_setting(key) ⇒ Object
- #ensure_heathrow_directory ⇒ Object
- #folder_hook(pattern, identity_name) ⇒ Object
- #folder_hooks ⇒ Object
-
#get(path, default = nil) ⇒ Object
Get config value — YAML overrides (from interactive settings) beat RC defaults.
- #get_db_setting(key, default = nil) ⇒ Object
- #global_headers ⇒ Object
- #has?(path) ⇒ Boolean
- #has_db_setting?(key) ⇒ Boolean
- #header(name, value) ⇒ Object
-
#identities ⇒ Object
── Identity resolution ──.
- #identity(name, from:, signature: nil, smtp: nil, headers: nil) ⇒ Object
-
#identity_for_folder(folder_name) ⇒ Object
Get identity for a given folder name (first matching folder_hook wins).
- #identity_name_for_folder(folder_name) ⇒ Object
-
#initialize(config_path = HEATHROW_CONFIG, db = nil) ⇒ Config
constructor
A new instance of Config.
-
#load_config ⇒ Object
── YAML config (legacy, still used for some things) ──.
-
#load_rc(path = HEATHROWRC) ⇒ Object
── Load the RC file ──.
-
#rc(key, default = nil) ⇒ Object
── RC settings access ── RC settings override YAML config values.
-
#reload_rc ⇒ Object
Reload the RC file (for interactive 'R' key).
- #save ⇒ Object
- #save_config(config = @settings) ⇒ Object
-
#set(key, value) ⇒ Object
── RC file DSL methods (called from heathrowrc) ──.
-
#set_db_setting(key, value) ⇒ Object
── Database-backed settings ──.
-
#theme(name, **colors) ⇒ Object
Define a custom color theme (or override a built-in) Usage in heathrowrc: theme 'MyTheme', unread: 226, read: 249, accent: 10, thread: 255, dm: 201, tag: 14, quote1: 114, quote2: 180, quote3: 139, quote4: 109, sig: 242.
-
#view(key, name, **opts) ⇒ Object
Define a custom view (replaces hardcoded views in database.rb) Usage: view '1', 'Personal', folder: 'Personal' view '4', 'Work', folder: 'Work.Archive' view '5', 'RSS', source_type: 'rss'.
Constructor Details
#initialize(config_path = HEATHROW_CONFIG, db = nil) ⇒ Config
Returns a new instance of Config.
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
# File 'lib/heathrow/config.rb', line 14 def initialize(config_path = HEATHROW_CONFIG, db = nil) @@instance = self @config_path = config_path @db = db @settings = load_config ensure_heathrow_directory # DSL state — populated by loading heathrowrc @identities = {} @folder_hooks = [] @global_headers = {} @rc_settings = {} load_rc # Register as singleton so class methods work self.class.instance = self end |
Class Attribute Details
.instance ⇒ Object
Returns the value of attribute instance.
10 11 12 |
# File 'lib/heathrow/config.rb', line 10 def self.instance @@instance rescue nil end |
Instance Attribute Details
#settings ⇒ Object
Returns the value of attribute settings.
6 7 8 |
# File 'lib/heathrow/config.rb', line 6 def settings @settings end |
Class Method Details
.identity_for_folder(folder_name) ⇒ Object
203 204 205 |
# File 'lib/heathrow/config.rb', line 203 def identity_for_folder(folder_name) instance&.identity_for_folder(folder_name) end |
.identity_name_for_folder(folder_name) ⇒ Object
207 208 209 |
# File 'lib/heathrow/config.rb', line 207 def identity_name_for_folder(folder_name) instance&.identity_name_for_folder(folder_name) end |
Instance Method Details
#[](key) ⇒ Object
287 288 289 |
# File 'lib/heathrow/config.rb', line 287 def [](key) @settings[key] end |
#[]=(key, value) ⇒ Object
291 292 293 |
# File 'lib/heathrow/config.rb', line 291 def []=(key, value) @settings[key] = value end |
#bind(key, shell: nil, action: nil, prompt: nil, description: nil) ⇒ Object
Bind a key to a custom action Usage:
bind 'C-S', shell: 'mailq' # Run shell command, show output
bind 'C-N', shell: 'notmuch search %q' # %q = prompted query
bind 'C-O', action: :open_in_browser # Call a Heathrow method
bind '\\', shell: 'my-script %f' # %f = current message file path
127 128 129 130 131 132 133 134 135 |
# File 'lib/heathrow/config.rb', line 127 def bind(key, shell: nil, action: nil, prompt: nil, description: nil) @custom_bindings ||= {} @custom_bindings[key.to_s] = { shell: shell, action: action, prompt: prompt, description: description } end |
#channel_name_map ⇒ Object
117 118 119 |
# File 'lib/heathrow/config.rb', line 117 def channel_name_map @channel_name_map || {} end |
#channel_names(mapping) ⇒ Object
Map Discord channel IDs to display names Usage: channel_names '123456789' => 'MyServer#general', '987654321' => 'MyServer#dev'
112 113 114 115 |
# File 'lib/heathrow/config.rb', line 112 def channel_names(mapping) @channel_name_map ||= {} @channel_name_map.merge!(mapping.transform_keys(&:to_s)) end |
#create_default_config ⇒ Object
230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 |
# File 'lib/heathrow/config.rb', line 230 def create_default_config default = { 'version' => Heathrow::VERSION, 'ui' => {}, 'polling' => { 'enabled' => true, 'default_interval' => 60 }, 'notifications' => { 'enabled' => false, 'sound' => false } } save_config(default) default end |
#custom_bindings ⇒ Object
137 138 139 |
# File 'lib/heathrow/config.rb', line 137 def custom_bindings @custom_bindings || {} end |
#custom_themes ⇒ Object
82 83 84 |
# File 'lib/heathrow/config.rb', line 82 def custom_themes @custom_themes || {} end |
#custom_views ⇒ Object
105 106 107 |
# File 'lib/heathrow/config.rb', line 105 def custom_views @custom_views || [] end |
#delete_db_setting(key) ⇒ Object
327 328 329 330 |
# File 'lib/heathrow/config.rb', line 327 def delete_db_setting(key) return unless @db @db.execute("DELETE FROM settings WHERE key = ?", key) end |
#ensure_heathrow_directory ⇒ Object
33 34 35 36 |
# File 'lib/heathrow/config.rb', line 33 def ensure_heathrow_directory dir = File.dirname(@config_path) FileUtils.mkdir_p(dir) unless Dir.exist?(dir) end |
#folder_hook(pattern, identity_name) ⇒ Object
64 65 66 |
# File 'lib/heathrow/config.rb', line 64 def folder_hook(pattern, identity_name) @folder_hooks << { pattern: pattern, identity: identity_name.to_s } end |
#folder_hooks ⇒ Object
172 173 174 |
# File 'lib/heathrow/config.rb', line 172 def folder_hooks @folder_hooks end |
#get(path, default = nil) ⇒ Object
Get config value — YAML overrides (from interactive settings) beat RC defaults
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 |
# File 'lib/heathrow/config.rb', line 257 def get(path, default = nil) # First check YAML (interactive changes persist here) keys = path.split('.') yaml_val = @settings keys.each do |key| break unless yaml_val.is_a?(Hash) yaml_val = yaml_val[key] end return yaml_val unless yaml_val.nil? # Then check RC settings rc_key = path.sub(/^ui\./, '') val = @rc_settings[rc_key] return val unless val.nil? default end |
#get_db_setting(key, default = nil) ⇒ Object
309 310 311 312 313 314 315 316 317 318 319 320 |
# File 'lib/heathrow/config.rb', line 309 def get_db_setting(key, default = nil) return default unless @db result = @db.get_first_value("SELECT value FROM settings WHERE key = ?", key) return default unless result begin JSON.parse(result) rescue JSON::ParserError result end end |
#global_headers ⇒ Object
176 177 178 |
# File 'lib/heathrow/config.rb', line 176 def global_headers @global_headers end |
#has?(path) ⇒ Boolean
275 276 277 278 279 280 281 282 283 284 285 |
# File 'lib/heathrow/config.rb', line 275 def has?(path) keys = path.split('.') value = @settings keys.each do |key| return false unless value.is_a?(Hash) && value.key?(key) value = value[key] end true end |
#has_db_setting?(key) ⇒ Boolean
322 323 324 325 |
# File 'lib/heathrow/config.rb', line 322 def has_db_setting?(key) return false unless @db @db.get_first_value("SELECT COUNT(*) FROM settings WHERE key = ?", key).to_i > 0 end |
#header(name, value) ⇒ Object
68 69 70 |
# File 'lib/heathrow/config.rb', line 68 def header(name, value) @global_headers[name.to_s] = value.to_s end |
#identities ⇒ Object
── Identity resolution ──
168 169 170 |
# File 'lib/heathrow/config.rb', line 168 def identities @identities end |
#identity(name, from:, signature: nil, smtp: nil, headers: nil) ⇒ Object
55 56 57 58 59 60 61 62 |
# File 'lib/heathrow/config.rb', line 55 def identity(name, from:, signature: nil, smtp: nil, headers: nil) @identities[name.to_s] = { from: from, signature: signature ? File.(signature) : nil, smtp: smtp ? File.(smtp) : nil, headers: headers || {} } end |
#identity_for_folder(folder_name) ⇒ Object
Get identity for a given folder name (first matching folder_hook wins)
181 182 183 184 185 186 187 188 189 190 191 |
# File 'lib/heathrow/config.rb', line 181 def identity_for_folder(folder_name) folder_name ||= 'INBOX' hook = @folder_hooks.find { |h| folder_name.match?(h[:pattern]) } identity_name = hook ? hook[:identity] : 'default' id = @identities[identity_name] || @identities['default'] return nil unless id # Merge global headers into identity headers merged_headers = @global_headers.merge(id[:headers] || {}) id.merge(headers: merged_headers) end |
#identity_name_for_folder(folder_name) ⇒ Object
193 194 195 196 197 |
# File 'lib/heathrow/config.rb', line 193 def identity_name_for_folder(folder_name) folder_name ||= 'INBOX' hook = @folder_hooks.find { |h| folder_name.match?(h[:pattern]) } hook ? hook[:identity] : 'default' end |
#load_config ⇒ Object
── YAML config (legacy, still used for some things) ──
222 223 224 225 226 227 228 |
# File 'lib/heathrow/config.rb', line 222 def load_config if File.exist?(@config_path) YAML.load_file(@config_path) else create_default_config end end |
#load_rc(path = HEATHROWRC) ⇒ Object
── Load the RC file ──
143 144 145 146 147 148 149 150 151 |
# File 'lib/heathrow/config.rb', line 143 def load_rc(path = HEATHROWRC) return unless File.exist?(path) # Evaluate in the context of this Config instance so DSL methods work instance_eval(File.read(path), path) rescue => e STDERR.puts "Error loading #{path}: #{e.}" STDERR.puts e.backtrace.first(3).join("\n") if ENV['DEBUG'] end |
#rc(key, default = nil) ⇒ Object
── RC settings access ── RC settings override YAML config values
215 216 217 218 |
# File 'lib/heathrow/config.rb', line 215 def rc(key, default = nil) val = @rc_settings[key.to_s] val.nil? ? default : val end |
#reload_rc ⇒ Object
Reload the RC file (for interactive 'R' key)
154 155 156 157 158 159 160 161 162 163 164 |
# File 'lib/heathrow/config.rb', line 154 def reload_rc @identities = {} @folder_hooks = [] @global_headers = {} @rc_settings = {} @custom_themes = nil @custom_views = nil @custom_bindings = nil @channel_name_map = nil load_rc end |
#save ⇒ Object
252 253 254 |
# File 'lib/heathrow/config.rb', line 252 def save save_config end |
#save_config(config = @settings) ⇒ Object
248 249 250 |
# File 'lib/heathrow/config.rb', line 248 def save_config(config = @settings) File.write(@config_path, config.to_yaml) end |
#set(key, value) ⇒ Object
── RC file DSL methods (called from heathrowrc) ──
40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/heathrow/config.rb', line 40 def set(key, value) key_s = key.to_s if key_s.include?('.') # Dot-notation path: save to YAML settings (e.g. 'ui.color_theme') keys = key_s.split('.') last_key = keys.pop parent = @settings keys.each { |k| parent[k] ||= {}; parent = parent[k] } parent[last_key] = value else # Simple key: RC setting (e.g. :color_theme) @rc_settings[key_s] = value end end |
#set_db_setting(key, value) ⇒ Object
── Database-backed settings ──
297 298 299 300 301 302 303 304 305 306 307 |
# File 'lib/heathrow/config.rb', line 297 def set_db_setting(key, value) return unless @db now = Time.now.to_i value_str = value.is_a?(String) ? value : value.to_json @db.execute <<-SQL, [key, value_str, now] INSERT OR REPLACE INTO settings (key, value, updated_at) VALUES (?, ?, ?) SQL end |
#theme(name, **colors) ⇒ Object
Define a custom color theme (or override a built-in) Usage in heathrowrc:
theme 'MyTheme', unread: 226, read: 249, accent: 10, thread: 255,
dm: 201, tag: 14, quote1: 114, quote2: 180,
quote3: 139, quote4: 109, sig: 242
77 78 79 80 |
# File 'lib/heathrow/config.rb', line 77 def theme(name, **colors) @custom_themes ||= {} @custom_themes[name.to_s] = colors end |
#view(key, name, **opts) ⇒ Object
Define a custom view (replaces hardcoded views in database.rb) Usage: view '1', 'Personal', folder: 'Personal' view '4', 'Work', folder: 'Work.Archive' view '5', 'RSS', source_type: 'rss'
90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/heathrow/config.rb', line 90 def view(key, name, **opts) @custom_views ||= [] filters = if opts[:folder] { 'rules' => [{ 'field' => 'folder', 'op' => 'like', 'value' => opts[:folder] }] } elsif opts[:source_type] { 'rules' => [{ 'field' => 'source_type', 'op' => '=', 'value' => opts[:source_type] }] } elsif opts[:filters] opts[:filters] else { 'rules' => [] } end @custom_views << { key: key.to_s, name: name, filters: filters, sort_order: opts[:sort_order] } end |