class SpiritHands::Prompt::Render

<.…> <.…/> </.…>

Constants

MATCHED_TAG_CODES

<tag> … </tag>, tag -> inner part of escape codes

SINGLE_TAGS

<…/>

Attributes

errors[R]

Array<String>

Public Class Methods

new(state, prompt, color) click to toggle source

:state SpiritHands::Prompt::State :prompt String :color true or false/nil

# File lib/spirit_hands/prompt/base/render.rb, line 111
def initialize(state, prompt, color)
  @state = state
  @prompt = prompt
  @color = color
end

Public Instance Methods

errors?() click to toggle source
# File lib/spirit_hands/prompt/base/render.rb, line 104
def errors?
  errors.any?
end
to_s() click to toggle source
# File lib/spirit_hands/prompt/base/render.rb, line 117
def to_s
  @errors = []
  @tag_stack = []
  @result = ''
  @color_applied = false
  @in_tag = false

  @prompt.each_char do |c|
    if @in_tag
      tag_char(c)
    else
      nontag_char(c)
    end
  end

  # @tag_stack.any? --> error/s
  @tag_stack.each { |t| errors << "<#{t}>: Missing </#{t}>" }

  (errors?) ? '' : @result
end

Private Instance Methods

close() click to toggle source

</…>

# File lib/spirit_hands/prompt/base/render.rb, line 193
def close
  code = MATCHED_TAG_CODES[@tag]
  if !code
    errors << "Unknown </#{@tag}>"
    return
  end
  idx = @tag_stack.rindex @tag
  if idx.nil?
    errors << "</#{@tag}>: missing start <#{@tag}>"
    return
  end
  # remove the now closed tag from the stack
  @tag_stack.delete_at idx
  # reset and reapply all codes on the @tag_stack
  @result += reset
  @tag_stack.each { |tag| @result += esc(MATCHED_TAG_CODES[tag]) }
end
esc(code) click to toggle source

convert a code to an actual character

# File lib/spirit_hands/prompt/base/render.rb, line 232
def esc(code)
  return '' if !@color
  @color_applied = true
  "\001\e[#{code}m\002".freeze
end
nontag_char(c) click to toggle source
# File lib/spirit_hands/prompt/base/render.rb, line 155
def nontag_char(c)
  if instance_variable_defined?(:@escape) && @escape
    nontag_escaped_char(c)
  else
    nontag_unescaped_char(c)
  end
end
nontag_escaped_char(c) click to toggle source
# File lib/spirit_hands/prompt/base/render.rb, line 163
def nontag_escaped_char(c)
  @escape = false
  @result += (@state.multiline) ? ' ' : c
end
nontag_unescaped_char(c) click to toggle source
# File lib/spirit_hands/prompt/base/render.rb, line 168
def nontag_unescaped_char(c)
  case c
  when '\\' # escape next char
    @escape = true
  when '<' # start tag
    @in_tag = true
    @tag_type = :start
    @tag = ''
  else # normal char
    @result += (@state.multiline) ? ' ' : c
  end
end
reset() click to toggle source
# File lib/spirit_hands/prompt/base/render.rb, line 227
def reset
  esc(0)
end
single() click to toggle source

<…/>

# File lib/spirit_hands/prompt/base/render.rb, line 212
def single
  f = SINGLE_TAGS[@tag]
  if !f
    errors << "Unknown </#{@tag}>"
    return
  end
  result = f.(@state).to_s

  # blank out all but sep for multiline prompt, vs. main (normal)
  if @state.multiline && @tag != 'sep'
    result = ' ' * result.length
  end
  @result += result
end
start() click to toggle source

<…>

# File lib/spirit_hands/prompt/base/render.rb, line 182
def start
  code = MATCHED_TAG_CODES[@tag]
  if !code
    errors << "Unknown <#{@tag}>"
    return
  end
  @result += esc(code)
  @tag_stack << @tag
end
tag_char(c) click to toggle source
# File lib/spirit_hands/prompt/base/render.rb, line 140
def tag_char(c)
  case c
  when '/'
    # close: </
    # single <.+/
    @tag_type = (@tag.nil? || @tag.empty?) ? :close : :single
  when '>' # close tag
    @tag.downcase!
    send @tag_type # :start, :close or :single
    @in_tag = false
  else # append to existing tag
    @tag += c
  end
end