Class: Chitin::Session
Instance Attribute Summary collapse
-
#config ⇒ Object
readonly
Returns the value of attribute config.
-
#editor ⇒ Object
readonly
Returns the value of attribute editor.
-
#out ⇒ Object
Returns the value of attribute out.
-
#sandbox ⇒ Object
Returns the value of attribute sandbox.
Instance Method Summary collapse
- #display(res) ⇒ Object
-
#evaluate(val) ⇒ Object
we need to save the frame or something i think.
-
#initialize(config = nil) ⇒ Session
constructor
A new instance of Session.
- #print(*args) ⇒ Object
- #puts(*args) ⇒ Object
-
#read ⇒ Object
THIS METHOD WILL POSSIBLY RETURN NIL!!!!! So it can return a string or nil.
- #shell_command?(res) ⇒ Boolean
-
#start ⇒ Object
Read Evaluate Print (display) Loop.
Constructor Details
#initialize(config = nil) ⇒ Session
Returns a new instance of Session.
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/chitin/session.rb', line 11 def initialize(config=nil) @config = config @out = STDOUT @sandbox = Sandbox.new # give it its own private space to work (class << @sandbox; self; end).send :include, @config # include the config and builtins @editor = Coolline.new do |c| # Remove the default of '-' and add support for strings # starting after parentheses. c.word_boundaries = [' ', "\t", "(", ")"] c.history_file = File.join ENV['HOME'], '.chitin_history' # Make sure we don't kill the shell accidentally when we're trying to # kill a file. That's what the default does, so we're overriding that # here. c.bind(?\C-c) {} c.transform_proc = proc do CodeRay.scan(c.line, :ruby).term end c.completion_proc = Proc.new do line = c.completed_word # expand ~ to homedir if line.start_with? '~' line = ENV['HOME'] + line[1..-1] end # if there's a quote, remove it. we'll add it back in later, but it ruins # searching so we need it removed for now. unquoted_line = ['"', '\''].include?(line[0, 1]) ? line[1..-1] : line Dir[unquoted_line + '*'].map do |w| slash_it = File.directory?(w) and line[-1] != '/' and w[-1] != '/' "\"#{w}#{slash_it ? '/' : ''}" end end end if @sandbox.completion_proc @editor.completion_proc = @sandbox.completion_proc end end |
Instance Attribute Details
#config ⇒ Object (readonly)
Returns the value of attribute config.
8 9 10 |
# File 'lib/chitin/session.rb', line 8 def config @config end |
#editor ⇒ Object (readonly)
Returns the value of attribute editor.
9 10 11 |
# File 'lib/chitin/session.rb', line 9 def editor @editor end |
#out ⇒ Object
Returns the value of attribute out.
6 7 8 |
# File 'lib/chitin/session.rb', line 6 def out @out end |
#sandbox ⇒ Object
Returns the value of attribute sandbox.
5 6 7 |
# File 'lib/chitin/session.rb', line 5 def sandbox @sandbox end |
Instance Method Details
#display(res) ⇒ Object
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
# File 'lib/chitin/session.rb', line 104 def display(res) # The reason that this is here instead of in #evaluate is that # pipes could, in fact, have NO display output, but that isn't for # #evaluate to decide; rather, it is for #display # # Only pipes and executables are standalone. StringMethods need to be # chained, and proc is also a general Ruby type, so we don't want to # automatically call it. if shell_command?(res) || (res.is_a?(Array) && !res.empty? && res.map {|r| shell_command? r }.all?) res = [res] unless res.is_a?(Array) res.each do |res| # set up the inputs and outputs res[:set_in, STDIN] unless res[:in] res[:set_out, STDOUT] unless res[:out] res[:set_err, STDOUT] unless res[:err] res[:run] res[:wait] unless res[:bg] end else # else it's a standard ruby type (or a pipe returning as such) unless res.is_a? Pipe # RUBY values pass through here txt = @config.post_processing[:color].call res.inspect puts " => #{txt}" else # set up the inputs and outputs res[:set_in, STDIN] unless res[:in] res[:set_out, STDOUT] unless res[:out] res[:set_err, STDOUT] unless res[:err] # We have to use #stat here because reopened pipes retain the file # descriptor of the original pipe. Example: # r, w = IO.pipe; r.reopen STDIN; r == STDIN # => false # Thus, we have to use #stat (or, more lamely, #inspect). if res[:out].stat == STDOUT.stat val = res[:raw_run] txt = @config.post_processing[:color].call val.inspect puts " => #{txt}" else res[:run] res[:wait] unless res[:bg] end end end # Run all the post_processing stuff # Not sure where I should really put this or what arguments it should have @config.post_processing[:default].each {|b| b.call } end |
#evaluate(val) ⇒ Object
we need to save the frame or something i think. could use fibers to make the whole thing a generator so that original frame would be saved. why did i write those lines. that makes no sense. AH now i remember. we need to save a frame and use that frame as a sandbox.
93 94 95 96 97 98 |
# File 'lib/chitin/session.rb', line 93 def evaluate(val) val.strip! @config.pre_processing[:default].each {|p| val = p.call val } @sandbox.evaluate val end |
#print(*args) ⇒ Object
163 164 165 |
# File 'lib/chitin/session.rb', line 163 def print(*args) @out.print *args end |
#puts(*args) ⇒ Object
159 160 161 |
# File 'lib/chitin/session.rb', line 159 def puts(*args) @out.puts *args end |
#read ⇒ Object
THIS METHOD WILL POSSIBLY RETURN NIL!!!!! So it can return a string or nil. Remember that, folks.
82 83 84 85 86 87 |
# File 'lib/chitin/session.rb', line 82 def read inp = @editor.readline @sandbox.prompt inp ? inp.chomp : nil # return nil so that the while loop in #start can end end |
#shell_command?(res) ⇒ Boolean
100 101 102 |
# File 'lib/chitin/session.rb', line 100 def shell_command?(res) res.is_a?(Executable) || (res.is_a?(Pipe) && res[:returning] != :ruby) end |
#start ⇒ Object
Read Evaluate Print (display) Loop
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/chitin/session.rb', line 61 def start while (val = read) next if val.empty? begin res = evaluate val display res unless val.lstrip[0, 1] == '#' rescue StandardError, ScriptError, Interrupt => e @config.post_processing[e.class].call e, val print e.backtrace.first, ': ' puts "#{e.message} (#{e.class})" e.backtrace[1..-1].each {|l| puts "\t#{l}" } nil end end end |