Permalink
Browse files

Keep a stack of contexts on the driver for, for instance, History and…

… Completion.
  • Loading branch information...
1 parent 2b78914 commit e93f597486d16761c9576e79a46cb54de269bd0c @alloy committed Jul 23, 2010
Showing with 96 additions and 109 deletions.
  1. +1 −4 bin/dietrb
  2. +7 −13 lib/irb/context.rb
  3. +6 −5 lib/irb/driver/readline.rb
  4. +11 −4 lib/irb/driver/tty.rb
  5. +9 −18 lib/irb/ext/completion.rb
  6. +62 −65 lib/irb/ext/history.rb
View
@@ -41,7 +41,4 @@ else
IRB::Driver.current = IRB::Driver::File.new(path)
end
-irb(self, TOPLEVEL_BINDING.dup)
-
-# TODO make sure!
-puts "ENDED! and this message should show up on stdout"
+irb(self, TOPLEVEL_BINDING.dup)
View
@@ -8,13 +8,9 @@
module IRB
class Context
- class << self
- def processors
- @processors ||= []
- end
- end
+ IGNORE_RESULT = :irb_ignore_result
- attr_reader :object, :binding, :line, :source, :processors
+ attr_reader :object, :binding, :line, :source
attr_accessor :formatter
def initialize(object, explicit_binding = nil)
@@ -24,7 +20,6 @@ def initialize(object, explicit_binding = nil)
clear_buffer
@underscore_assigner = __evaluate__("_ = nil; proc { |val| _ = val }")
- @processors = self.class.processors.map { |processor| processor.new(self) }
end
def __evaluate__(source, file = __FILE__, line = __LINE__)
@@ -33,9 +28,11 @@ def __evaluate__(source, file = __FILE__, line = __LINE__)
def evaluate(source)
result = __evaluate__(source.to_s, '(irb)', @line - @source.buffer.size + 1)
- store_result(result)
- puts(formatter.result(result))
- result
+ unless result == IGNORE_RESULT
+ store_result(result)
+ puts(formatter.result(result))
+ result
+ end
rescue Exception => e
store_exception(e)
puts(formatter.exception(e))
@@ -54,9 +51,6 @@ def evaluate(source)
#
# process_line("quit") # => false
def process_line(line)
- # TODO spec
- @processors.each { |processor| line = processor.input(line) }
-
@source << line
return false if @source.terminate?
@@ -6,20 +6,21 @@
module IRB
module Driver
class Readline < TTY
+
def initialize(input = $stdin, output = $stdout)
super
::Readline.input = @input
::Readline.output = @output
::Readline.completion_proc = IRB::Completion.new
end
- # Assigns a context to the completion object and waits for input.
- def readline(context)
- ::Readline.completion_proc.context = context
- ::Readline.readline(context.prompt, true)
+ def readline
+ source = ::Readline.readline(context.prompt, true)
+ IRB::History.input(source)
+ source
end
end
end
end
-IRB::Driver.current = IRB::Driver::Readline.new
+IRB::Driver.current = IRB::Driver::Readline.new
View
@@ -8,16 +8,21 @@ class TTY
def initialize(input = $stdin, output = $stdout)
@input = input
@output = output
+ @context_stack = []
end
- def readline(context)
+ def context
+ @context_stack.last
+ end
+
+ def readline
@output.print(context.prompt)
@input.gets
end
# TODO make it take the current context instead of storing it
- def consume(context)
- readline(context)
+ def consume
+ readline
rescue Interrupt
context.clear_buffer
""
@@ -28,11 +33,13 @@ def consume(context)
# Ensures that the standard output object is a OutputRedirector, or a
# subclass thereof.
def run(context)
+ @context_stack << context
before, $stdout = $stdout, OutputRedirector.new unless $stdout.is_a?(OutputRedirector)
- while line = consume(context)
+ while line = consume
break unless context.process_line(line)
end
ensure
+ @context_stack.pop
$stdout = before if before
end
end
@@ -36,40 +36,31 @@ def defined do
yield
}
- # # Returns an array of possible completion results, with the current
- # # IRB::Context.
- # #
- # # This is meant to be used with Readline which takes a completion proc.
- # def self.call(source)
- # new(IRB::Context.current, source).results
- # end
-
attr_reader :source
- attr_accessor :context
-
- # def initialize(context, source)
- # @context, @source = context, source
- # end
- def initialize(context = nil)
- @context = context
+ def context
+ IRB::Driver.current.context
end
+ # Returns an array of possible completion results, with the current
+ # IRB::Context.
+ #
+ # This is meant to be used with Readline which takes a completion proc.
def call(source)
@source = source
results
end
def evaluate(s)
- @context.__evaluate__(s)
+ context.__evaluate__(s)
end
def local_variables
evaluate('local_variables').map(&:to_s)
end
def instance_methods
- @context.object.methods.map(&:to_s)
+ context.object.methods.map(&:to_s)
end
def instance_methods_of(klass)
@@ -201,4 +192,4 @@ def methods_of_object_in_variable(path)
Readline.basic_word_break_characters= " \t\n`<;|&("
end
# Readline.completion_proc = IRB::Completion
-end
+end
View
@@ -7,89 +7,86 @@
# Portions Copyright (C) 2006-2010 Ben Bleything <ben@bleything.net> (Kernel#history & Kernel#history!)
module IRB
- class History
+ module History
class << self
attr_accessor :file, :max_entries_in_overview
- end
-
- module HistoryExtension
- attr_accessor :irb_history
- def history(number_of_entries = IRB::History.max_entries_in_overview)
- @irb_history.history(number_of_entries)
- nil
+ def initialize
+ to_a.each do |source|
+ Readline::HISTORY.push(source)
+ end if Readline::HISTORY.to_a.empty?
end
- alias_method :h, :history
- def history!(entry_or_range)
- @irb_history.history!(entry_or_range)
- nil
+ def context
+ IRB::Driver.current.context
end
- alias_method :h!, :history!
- def clear_history!
- @irb_history.clear!
- nil
+ def input(source)
+ File.open(file, "a") { |f| f.puts(source) }
+ source
end
- end
-
- def initialize(context)
- @context = context
- @context.object.extend(HistoryExtension)
- @context.object.irb_history = self
- to_a.each do |source|
- Readline::HISTORY.push(source)
- end if Readline::HISTORY.to_a.empty?
- end
-
- def input(source)
- File.open(self.class.file, "a") { |f| f.puts(source) }
- source
- end
-
- def to_a
- file = self.class.file
- File.exist?(file) ? File.read(file).split("\n") : []
- end
-
- def clear!
- File.open(self.class.file, "w") { |f| f << "" }
- Readline::HISTORY.clear
- end
-
- def history(number_of_entries = max_entries_in_overview)
- history_size = Readline::HISTORY.size
- start_index = 0
+ def to_a
+ File.exist?(file) ? File.read(file).split("\n") : []
+ end
- # always remove one extra, because that's the `history' command itself
- if history_size <= number_of_entries
- end_index = history_size - 2
- else
- end_index = history_size - 2
- start_index = history_size - number_of_entries - 1
+ def clear!
+ File.open(file, "w") { |f| f << "" }
+ Readline::HISTORY.clear
end
- start_index.upto(end_index) do |i|
- @context.io.puts "#{i}: #{Readline::HISTORY[i]}"
+ def history(number_of_entries = max_entries_in_overview)
+ history_size = Readline::HISTORY.size
+ start_index = 0
+
+ # always remove one extra, because that's the `history' command itself
+ if history_size <= number_of_entries
+ end_index = history_size - 2
+ else
+ end_index = history_size - 2
+ start_index = history_size - number_of_entries - 1
+ end
+
+ start_index.upto(end_index) do |i|
+ puts "#{i}: #{Readline::HISTORY[i]}"
+ end
end
- end
-
- def history!(entry_or_range)
- # we don't want to execute history! again
- @context.clear_buffer
- if entry_or_range.is_a?(Range)
- entry_or_range.to_a.each do |i|
- @context.input_line(Readline::HISTORY[i])
+ def history!(entry_or_range)
+ # we don't want to execute history! again
+ context.clear_buffer
+
+ if entry_or_range.is_a?(Range)
+ entry_or_range.to_a.each do |i|
+ context.input_line(Readline::HISTORY[i])
+ end
+ else
+ context.input_line(Readline::HISTORY[entry_or_range])
end
- else
- @context.input_line(Readline::HISTORY[entry_or_range])
end
end
end
end
-IRB::Context.processors << IRB::History
+module Kernel
+ def history(number_of_entries = IRB::History.max_entries_in_overview)
+ IRB::History.history(number_of_entries)
+ IRB::Context::IGNORE_RESULT
+ end
+ alias_method :h, :history
+
+ def history!(entry_or_range)
+ IRB::History.history!(entry_or_range)
+ IRB::Context::IGNORE_RESULT
+ end
+ alias_method :h!, :history!
+
+ def clear_history!
+ IRB::History.clear!
+ true
+ end
+end
+
IRB::History.file = File.expand_path("~/.irb_history")
-IRB::History.max_entries_in_overview = 50
+IRB::History.max_entries_in_overview = 50
+IRB::History.initialize

0 comments on commit e93f597

Please sign in to comment.