Class: Mutter::Mutterer

Inherits:
Object show all
Defined in:
lib/mutter/mutterer.rb

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(obj = {}) ⇒ Mutterer

Initialize the styles, and load the defaults from styles.yml

@active: currently active styles, which apply to the whole string @styles: contains all the user + default styles



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/mutter/mutterer.rb', line 11

def initialize obj = {}
  self.reset
  @defaults = load 'default'

  case obj
    when Hash       # A style definition: expand quick-styles and merge with @styles
      @styles = obj.inject({}) do |h, (k, v)|
        h.merge k =>
          (v.is_a?(Hash) ? v : { :match => v, :style => [k].flatten })
      end
    when Array      # An array of styles to be activated
      @active = obj
    when Symbol     # A single style to be activated
      self << obj
    when String     # The path of a yaml style-sheet
      @styles = load obj
    else raise ArgumentError
  end

  #
  # Create an instance method for each style
  #
  self.styles.keys.each do |style|
    (class << self; self end).class_eval do
      define_method style do |msg|
        say msg, style
      end
    end if style.is_a? Symbol
  end
end

Class Method Details

.colorObject



202
203
204
# File 'lib/mutter/mutterer.rb', line 202

def self.color
  @color
end

.color=(bool) ⇒ Object



206
207
208
# File 'lib/mutter/mutterer.rb', line 206

def self.color= bool
  @color = bool
end

.streamObject

Output stream (defaults to STDOUT)

mostly for test purposes


194
195
196
# File 'lib/mutter/mutterer.rb', line 194

def self.stream
  @stream
end

.stream=(io) ⇒ Object



198
199
200
# File 'lib/mutter/mutterer.rb', line 198

def self.stream= io
  @stream = io
end

Instance Method Details

#+(style) ⇒ Object



132
133
134
# File 'lib/mutter/mutterer.rb', line 132

def + style
  dup.tap {|m| m << style }
end

#-(style) ⇒ Object



136
137
138
# File 'lib/mutter/mutterer.rb', line 136

def - style
  dup.tap {|m| m >> style }
end

#<<(style) ⇒ Object

Add and remove styles from the active styles



124
125
126
# File 'lib/mutter/mutterer.rb', line 124

def << style
  @active << style
end

#>>(style) ⇒ Object



128
129
130
# File 'lib/mutter/mutterer.rb', line 128

def >> style
  @active.delete style
end

#clear(opt = :all) ⇒ Object Also known as: reset



46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/mutter/mutterer.rb', line 46

def clear opt = :all
  case opt
    when :user     then @styles = {}
    when :styles   then @styles, @defaults = {}, {}
    when :active   then @active = []
    when :all      then @active, @styles, @defaults = [], {}, {}
    when :default,
         :defaults then @defaults = {}
    else           raise ArgumentError, "[:user, :default, :active, :all] only"
  end
  self
end

#color?Boolean

Returns:

  • (Boolean)


73
74
75
# File 'lib/mutter/mutterer.rb', line 73

def color?
  (ENV['TERM'].include?('color') && self.class.stream.tty?) || self.class.color
end

#esc(str, open, close) ⇒ Object

Escape a string, for later replacement



186
187
188
# File 'lib/mutter/mutterer.rb', line 186

def esc str, open, close
  "\e#{open}\e" + str + "\e#{close}\e"
end

#load(styles) ⇒ Object

Loads styles from a YAML style-sheet,

and converts the keys to symbols


64
65
66
67
68
69
70
71
# File 'lib/mutter/mutterer.rb', line 64

def load styles
  styles += '.yml' unless styles =~ /\.ya?ml$/
  styles = File.join(File.dirname(__FILE__), "styles", styles) unless File.exist? styles
  YAML.load_file(styles).inject({}) do |h, (key, value)|
    value = { :match => value['match'], :style => value['style'] }
    h.merge key.to_sym => value
  end
end

#parse(string) ⇒ Object

Parse a string to ANSI codes

if the glyph is a pair, we match [0] as the start
and [1] as the end marker.
the matches are sent to +stylize+


147
148
149
150
151
152
153
154
155
156
157
# File 'lib/mutter/mutterer.rb', line 147

def parse string
  self.styles.inject(string) do |str, (name, options)|
    glyph, style = options[:match], options[:style]
    if glyph.is_a? Array
      str.gsub(/#{Regexp.escape(glyph.first)}(.*?)
                #{Regexp.escape(glyph.last)}/x) { stylize $1, style }
    else
      str.gsub(/(#{Regexp.escape(glyph)}+)(.*?)\1/) { stylize $2, style }
    end
  end
end

#process(msg, *styles) ⇒ Object Also known as: []

Parse the message, but also apply a style on the whole thing



99
100
101
# File 'lib/mutter/mutterer.rb', line 99

def process msg, *styles
  stylize(parse(msg), @active + styles).gsub(/\e(\d+)\e/, "\e[\\1m")
end

#say(msg, *styles) ⇒ Object Also known as: print

Output to @stream



80
81
82
# File 'lib/mutter/mutterer.rb', line 80

def say msg, *styles
  self.write((color?? process(msg, *styles) : unstyle(msg)) + "\n") ; nil
end

#stylesObject



42
43
44
# File 'lib/mutter/mutterer.rb', line 42

def styles
  @defaults.merge @styles
end

#stylize(string, styles = []) ⇒ Object

Apply styles to a string

if the style is a default ANSI style, we add the start
and end sequence to the string.

if the style is a custom style, we recurse, sending
the list of ANSI styles contained in the custom style.

TODO: use ';' delimited codes instead of multiple \e sequences


170
171
172
173
174
175
176
177
178
179
180
181
# File 'lib/mutter/mutterer.rb', line 170

def stylize string, styles = []
  [styles].flatten.inject(string) do |str, style|
    style = style.to_sym
    if ANSI[:transforms].include? style
      esc str, *ANSI[:transforms][style]
    elsif ANSI[:colors].include? style
      esc str, ANSI[:colors][style], ANSI[:colors][:reset]
    else
      stylize(str, @styles[style][:style])
    end
  end
end

#table(*args, &blk) ⇒ Object

Create a table



117
118
119
# File 'lib/mutter/mutterer.rb', line 117

def table *args, &blk
  Table.new(*args, &blk)
end

#unstyle(msg) ⇒ Object

Remove all tags from string



88
89
90
91
92
93
94
# File 'lib/mutter/mutterer.rb', line 88

def unstyle msg
  styles.map do |_,v|
    v[:match]
  end.flatten.inject(msg) do |m, tag|
    m.gsub(tag, '')
  end
end

#write(str) ⇒ Object

Write to the out stream, and flush it



107
108
109
110
111
112
# File 'lib/mutter/mutterer.rb', line 107

def write str
  self.class.stream.tap do |stream|
    stream.write str
    stream.flush
  end ; nil
end