module IrcFormat
IRC color/control formatting. Use instead of copying irc_color into each plugin. mIRC colours: 0โ15 (theme-dependent), 16โ98 (fixed extended palette), 99 (default/transparent). Ibis mIRC frame defaults from reference/stuff/vars.ibis and identifiers1.ibis. Default styles use IrcExtendedColors named pairs; classic_* fallbacks keep theme-dependent 0โ15.
Constants
- ACCENT_BITS_COLOR
- ACCENT_MAIN_COLOR
- BRACKET_AFTER_COLOR
- BRACKET_LABEL_COLOR
- BRACKET_LEFT_CHAR
- BRACKET_RIGHT_CHAR
- BRACKET_SHELL_COLOR
- COLOUR_SPEC_PATTERN
- CTRL
- DEFAULT_COLOR
- IRC_BOLD
- IRC_UNDERLINE
- MAX_COLOR
- MIN_COLOR
- RESET
- RESET_ALL
-
Ctrl+O โ clears bold, underline, reverse, and colours; safe before digits (unlike bare \x03).
Public Instance Methods
Source
# File lib/irc_format.rb, line 143 def accent_paren(*parts) text = meta_join(*parts) return "" if text.empty? load_extended_colors! bits = named_style(:accent) main = named_style(:footer) "#{bits}(#{RESET}#{main}#{text}#{bits})#{RESET}#{main}" end
Source
# File lib/irc_format.rb, line 75 def bold(text) value = text.to_s return value if value.empty? "#{IRC_BOLD}#{value}#{IRC_BOLD}" end
Source
# File lib/irc_format.rb, line 114 def bracket_label(text, label_style: nil) label = text.to_s.strip return "" if label.empty? load_extended_colors! label_style ||= named_style(:tag) shell = named_style(:panel) after = named_style(:footer) "#{shell}#{BRACKET_LEFT_CHAR}#{label_style}#{IRC_BOLD}#{label}#{IRC_BOLD}#{shell}#{BRACKET_RIGHT_CHAR}#{after}" end
Source
# File lib/irc_format.rb, line 94 def classic_muted_style @classic_muted_style ||= color(15, 14) end
Source
# File lib/irc_format.rb, line 102 def classic_nick_style @classic_nick_style ||= color(0, 10) end
Source
# File lib/irc_format.rb, line 30 def color(fg, bg = nil) fg_code = format_color_code(fg) return "#{CTRL}#{fg_code}" unless bg bg_code = format_color_code(bg) "#{CTRL}#{fg_code},#{bg_code}" end
Source
# File lib/irc_format.rb, line 68 def decorate(text, style) value = text.to_s return value if value.empty? "#{style}#{value}#{RESET}" end
Source
# File lib/irc_format.rb, line 158 def divider(title = nil, width: 40, char: "=", style: nil) line = divider_line(title, width: width, char: char) decorate(line, style || color(14)) end
Source
# File lib/irc_format.rb, line 163 def divider_line(title, width:, char:) if title.nil? || title.to_s.strip.empty? return char * width end label = " #{title.to_s.strip} " pad = [width - label.length, 0].max left = pad / 2 right = pad - left "#{char * left}#{label}#{char * right}" end
Source
# File lib/irc_format.rb, line 38 def format_color_code(value) code = value.to_i raise ArgumentError, "IRC colour must be #{MIN_COLOR}-#{MAX_COLOR} or #{DEFAULT_COLOR}" unless valid_color?(code) code.to_s.rjust(2, "0") end
Source
# File lib/irc_format.rb, line 206 def load_extended_colors! require_relative "irc_extended_colors" unless defined?(IrcExtendedColors) end
Source
# File lib/irc_format.rb, line 139 def meta_join(*parts) parts.flatten.map(&:to_s).map(&:strip).reject(&:empty?).join(" ยท ") end
Source
# File lib/irc_format.rb, line 82 def muted(text) decorate(text, muted_style) end
Source
# File lib/irc_format.rb, line 106 def muted_style @muted_style ||= named_style(:muted) end
Source
# File lib/irc_format.rb, line 86 def named_style(name) load_extended_colors! fg, bg = IrcExtendedColors.resolve_pair(name) raise ArgumentError, "Unknown named colour pair: #{name.inspect}" unless fg bg ? color(fg, bg) : color(fg) end
Source
# File lib/irc_format.rb, line 175 def nick(name, op: false, classic: false) value = name.to_s.strip return value if value.empty? prefix = op ? "@" : "" style = classic ? classic_nick_style : named_style(:nick) decorate("#{prefix}#{value}", style) end
Source
# File lib/irc_format.rb, line 49 def parse_colour_spec(value) match = value.to_s.match(COLOUR_SPEC_PATTERN) return { error: "Invalid colour โ use fg or fg,bg (0-98)." } unless match fg = match[1].to_i bg = match[2] ? match[2].to_i : nil return { error: "Invalid colour โ use fg or fg,bg (0-98)." } unless valid_color?(fg) return { error: "Invalid colour โ use fg or fg,bg (0-98)." } if bg && !valid_color?(bg) { fg: fg, bg: bg } end
Source
# File lib/irc_format.rb, line 184 def report_header(tag:, title:, style: menu_heading_style) [ bracket_label(tag), menu_heading(title, style: style) ].join(" ") end
Source
# File lib/irc_format.rb, line 153 def tag(name, style: nil) _ = style # legacy callers may pass style; Ibis brackets use fixed palette bracket_label(name) end
Source
# File lib/irc_format.rb, line 61 def underline(text) value = text.to_s return value if value.empty? "#{IRC_UNDERLINE}#{value}#{IRC_UNDERLINE}" end
Source
# File lib/irc_format.rb, line 196 def unescape_literal_color_codes(text) value = text.to_s return value if value.empty? value.gsub(/\\(?:x03|003)(\d{1,2}(?:,\d{1,2})?)?/) do spec = Regexp.last_match(1) spec ? "#{CTRL}#{spec}" : CTRL end end
AI agents often emit literal \003 / \x03 text instead of the IRC ctrl-C byte.
Source
# File lib/irc_format.rb, line 45 def valid_color?(code) (MIN_COLOR..MAX_COLOR).cover?(code) || code == DEFAULT_COLOR end