Class: AnsiTerm::Attr

Inherits:
Object
  • Object
show all
Defined in:
lib/ansiterm/attr.rb

Overview

# Attr #

Attr represents the attributes of a given character. It is intended to follow the “Flyweight” GOF pattern in that any object representing a given combination of flags can be reused as the object itself is immutable.

This allows you to decide on a case by case basis whether to e.g. encode a string as spans with one Attr, or characters with one Attr per character.

Use ‘Attr#transition(other_attr)` to retrieve an ANSI sequence that represents the changes from self to other_attr.

Constant Summary collapse

NORMAL =
0
BOLD =
1
ITALICS =
2
UNDERLINE =
4
CROSSED_OUT =
8

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(fgcol: nil, bgcol: nil, flags: nil) ⇒ Attr

Returns a new instance of Attr.



27
28
29
30
31
32
# File 'lib/ansiterm/attr.rb', line 27

def initialize(fgcol: nil, bgcol: nil, flags: nil)
  @fgcol = fgcol
  @bgcol = bgcol
  @flags = flags
  freeze
end

Instance Attribute Details

#bgcolObject (readonly)

Returns the value of attribute bgcol.



25
26
27
# File 'lib/ansiterm/attr.rb', line 25

def bgcol
  @bgcol
end

#fgcolObject (readonly)

Returns the value of attribute fgcol.



25
26
27
# File 'lib/ansiterm/attr.rb', line 25

def fgcol
  @fgcol
end

#flagsObject (readonly)

Returns the value of attribute flags.



25
26
27
# File 'lib/ansiterm/attr.rb', line 25

def flags
  @flags
end

Instance Method Details

#==(other) ⇒ Object



34
35
36
37
38
39
# File 'lib/ansiterm/attr.rb', line 34

def ==(other)
  return false if !other.kind_of?(self.class)
  return fgcol == other.fgcol &&
         bgcol == other.bgcol &&
         flags == other.flags
end

#add_flag(flags) ⇒ Object



61
# File 'lib/ansiterm/attr.rb', line 61

def add_flag(flags);   merge({flags: @flags.to_i | flags.to_i}); end

#boldObject



66
# File 'lib/ansiterm/attr.rb', line 66

def bold;         add_flag(BOLD); end

#bold?Boolean

Returns:

  • (Boolean)


70
# File 'lib/ansiterm/attr.rb', line 70

def bold?;        (@flags.to_i & BOLD) != 0; end

#clear_flag(flags) ⇒ Object



62
# File 'lib/ansiterm/attr.rb', line 62

def clear_flag(flags); merge({flags: @flags.to_i & ~flags.to_i}); end

#crossed_outObject



68
# File 'lib/ansiterm/attr.rb', line 68

def crossed_out;  add_flag(CROSSED_OUT); end

#crossed_out?Boolean

Returns:

  • (Boolean)


72
# File 'lib/ansiterm/attr.rb', line 72

def crossed_out?; (@flags.to_i & CROSSED_OUT) != 0; end

#merge(attrs, ignore: nil) ⇒ Object



49
50
51
52
53
54
55
56
57
58
59
# File 'lib/ansiterm/attr.rb', line 49

def merge(attrs, ignore: nil)
   return self if self == attrs
   if attrs.respond_to?(:to_h)
     attrs = attrs.to_h
   end
   if ignore
     attrs.delete(ignore)
   end
   attrs = to_h.merge(attrs)
   self.class.new(attrs)
end

#normalObject



65
# File 'lib/ansiterm/attr.rb', line 65

def normal;       clear_flag(BOLD); end

#normal?Boolean

Returns:

  • (Boolean)


74
75
76
77
78
# File 'lib/ansiterm/attr.rb', line 74

def normal?
  (@flags == NORMAL || @flags.nil?) &&
    (@fgcol.nil? || @fgcol == 39) &&
    (@bgcol.nil? || @bgcol == 49)
end

#resetObject



64
# File 'lib/ansiterm/attr.rb', line 64

def reset;        self.class.new; end

#to_hObject



41
42
43
44
45
46
47
# File 'lib/ansiterm/attr.rb', line 41

def to_h
  attrs = {}
  attrs[:bgcol] = @bgcol if @bgcol
  attrs[:fgcol] = @fgcol if @fgcol
  attrs[:flags] = @flags if @flags
  attrs
end

#transition_to(other) ⇒ Object



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/ansiterm/attr.rb', line 80

def transition_to(other)
  t = []
  t << [other.fgcol] if other.fgcol != self.fgcol && other.fgcol
  t << [other.bgcol] if other.bgcol != self.fgcol && other.bgcol

  if other.bold? != self.bold?
    t << [other.bold? ? 1 : 22]
  end

  if other.underline? != self.underline?
    t << [other.underline? ? 4 : 24]
  end

  if other.crossed_out? != self.crossed_out?
    t << [other.crossed_out? ? 9 : 29]
  end

  return "\e[0m" if other.normal? && !self.normal? && t.length != 1

  if t.empty?
    ""
  else
    "\e[#{t.flatten.join(";")}m"
  end
end

#underlineObject



67
# File 'lib/ansiterm/attr.rb', line 67

def underline;    add_flag(UNDERLINE); end

#underline?Boolean

Returns:

  • (Boolean)


71
# File 'lib/ansiterm/attr.rb', line 71

def underline?;   (@flags.to_i & UNDERLINE) != 0; end