module Rib::Autoindent

Constants

BLOCK_REGEXP

begin block could be simpler, because it should also trigger SyntaxError, otherwise indention would be wiped out. but end block should be exactly match, because we don't have SyntaxError information, also triggering SyntaxError doesn't mean it's not an end block, thinking about nested multiline!

Public Instance Methods

before_loop() click to toggle source

————— Rib API —————

Calls superclass method
# File lib/rib/extra/autoindent.rb, line 70
def before_loop
  return super if Autoindent.disabled?
  autoindent_spaces
  super
end
detect_autoindent(input) click to toggle source

————— Plugin API —————

# File lib/rib/extra/autoindent.rb, line 104
def detect_autoindent input
  _, backmark = BLOCK_REGEXP.find{ |key,  _| input =~ key }
  if backmark # e.g. begin
    [:right, backmark]
  elsif input =~ autoindent_stack.last
    if $1     # e.g. end, }, etc
      [:left_end]
    else      # e.g. elsif, rescue, etc
      [:left_tmp]
    end
  else
    [:stay]
  end
end
eval_input(raw_input) click to toggle source
Calls superclass method
# File lib/rib/extra/autoindent.rb, line 93
def eval_input raw_input
  return super if Autoindent.disabled?
  input  = raw_input.strip
  indent = detect_autoindent(input)
  result, err = super
  handle_autoindent(input, indent, err)
  [result, err]
end
get_input() click to toggle source
Calls superclass method
# File lib/rib/extra/autoindent.rb, line 76
def get_input
  return super if Autoindent.disabled?
  # this is only a fix in case we don't autoindent correctly
  # if we're autoindenting 100% correct, then this is a useless check
  autoindent_stack.clear if multiline_buffer.empty?

  # this should be called after ::Readline.readline, but it's blocking,
  # and i don't know if there's any hook to do this, so here we use thread
  Thread.new do
    sleep(0.01)
    ::Readline.line_buffer = current_autoindent if
      ::Readline.line_buffer && ::Readline.line_buffer.empty?
  end

  super
end
handle_autoindent(input, indent, err) click to toggle source
# File lib/rib/extra/autoindent.rb, line 119
def handle_autoindent input, indent, err
  case indent.first
  when :right    # we need to go deeper
    if multiline?(err)
      if err.message =~ /unterminated \w+ meets end of file/
        # skip if we're in the middle of a string or regexp
      else
        # indent.last is the way (input regexp matches) to go back
        autoindent_stack << indent.last
      end
    end

  when :left_end # we need to go back
    # could happen in either multiline or not
    handle_last_line(input)
    autoindent_stack.pop

  when :left_tmp # temporarily go back
    handle_last_line(input) if multiline?(err)
  end
end
handle_last_line(input, indent=current_autoindent(autoindent_stack.size-1)) click to toggle source
# File lib/rib/extra/autoindent.rb, line 141
def handle_last_line input,
                     indent=current_autoindent(autoindent_stack.size-1)
  new_input = "#{indent}#{input}"
  puts("\e[1A\e[K#{prompt}#{new_input}")
  new_input
end

Private Instance Methods

autoindent_spaces() click to toggle source
# File lib/rib/extra/autoindent.rb, line 155
def autoindent_spaces
  config[:autoindent_spaces] ||= '  '
end
autoindent_stack() click to toggle source
# File lib/rib/extra/autoindent.rb, line 159
def autoindent_stack
  @autoindent_stack ||= []
end
current_autoindent(size=autoindent_stack.size) click to toggle source
# File lib/rib/extra/autoindent.rb, line 151
def current_autoindent size=autoindent_stack.size
  autoindent_spaces * size
end