Module: Rib::Autoindent
- Extended by:
- Plugin
- Defined in:
- lib/rib/extra/autoindent.rb
Constant Summary collapse
- 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!
{ # rescue Expression? (=> VariableName)? # consider cases: # rescue # rescue=>e # rescue => e # rescue =>e # rescue E=>e # rescue E # rescue E => e # rescue E=> e # rescue E =>e /^begin$/ => /^(end)\b|^else$|^rescue *((\w+)? *(=> *\w+)?)?$/, # elsif Expression # consider cases: # elsif(true) # elsif true # elsif true == true # elsif (a = true) && false /^if/ => /^(end)\b|^else$|^elsif\b/, /^unless/ => /^(end)\b|^else$|^elsif\b/, /^case/ => /^(end)\b|^when\b/ , /^def/ => /^(end)\b/ , /^class/ => /^(end)\b/ , /^module/ => /^(end)\b/ , /^while/ => /^(end)\b/ , /^until/ => /^(end)\b/ , # consider cases: # 'do # ' do # "' do # /do # '{ # %q{ # %q| do # hey, two lines are even harder! # " # begin /do( *\|.*\|)?$/ => /^(end)\b/ , /\{( *\|.*\|)?$/ => /^(\})\B/ , # those are too hard to deal with, so we use syntax error to double check # what about this then? # v = if true # else # end }
Instance Attribute Summary
Attributes included from Plugin
Instance Method Summary collapse
-
#before_loop ⇒ Object
————— Rib API —————.
-
#detect_autoindent(input) ⇒ Object
————— Plugin API —————.
- #eval_input(raw_input) ⇒ Object
- #get_input ⇒ Object
- #handle_autoindent(input, indent, err) ⇒ Object
- #handle_last_line(input, indent = current_autoindent(autoindent_stack.size-1)) ⇒ Object
Methods included from Plugin
disable, disabled?, enable, enabled?, extended
Instance Method Details
#before_loop ⇒ Object
————— Rib API —————
64 65 66 67 68 |
# File 'lib/rib/extra/autoindent.rb', line 64 def before_loop return super if Autoindent.disabled? autoindent_spaces super end |
#detect_autoindent(input) ⇒ Object
————— Plugin API —————
102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
# File 'lib/rib/extra/autoindent.rb', line 102 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) ⇒ Object
87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/rib/extra/autoindent.rb', line 87 def eval_input raw_input return super if Autoindent.disabled? input = raw_input.strip indent = detect_autoindent(input) result, err = if indent.first.to_s.start_with?('left') super(handle_last_line(input)) else super end handle_autoindent(input, indent, err) [result, err] end |
#get_input ⇒ Object
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/rib/extra/autoindent.rb', line 70 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) ⇒ Object
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
# File 'lib/rib/extra/autoindent.rb', line 117 def handle_autoindent input, indent, err case indent.first when :right # we need to go deeper if multiline?(err) if err. =~ /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 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)) ⇒ Object
138 139 140 141 142 143 |
# File 'lib/rib/extra/autoindent.rb', line 138 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 |