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.
-
#last_elapsed ⇒ Object
readonly
Returns the value of attribute last_elapsed.
-
#out ⇒ Object
Returns the value of attribute out.
-
#sandbox ⇒ Object
Returns the value of attribute sandbox.
Instance Method Summary collapse
- #all_not_ruby?(res) ⇒ Boolean (also: #all_shell?)
- #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.
- #inspect ⇒ Object
- #print(*args) ⇒ Object
- #puts(*args) ⇒ Object
-
#read ⇒ Object
THIS METHOD WILL POSSIBLY RETURN NIL!!!!! So it can return a string or nil.
- #returning_ruby?(res) ⇒ Boolean
-
#start ⇒ Object
Read Evaluate Print (display) Loop.
Constructor Details
#initialize(config = nil) ⇒ Session
Returns a new instance of Session.
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 56 57 58 59 |
# File 'lib/chitin/session.rb', line 12 def initialize(config=nil) @config = config @out = STDOUT @sandbox = Sandbox.new # give it its own private space to work # include the config and builtins (class << @sandbox; self; end).send :include, @config @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 |
#last_elapsed ⇒ Object (readonly)
Returns the value of attribute last_elapsed.
10 11 12 |
# File 'lib/chitin/session.rb', line 10 def last_elapsed @last_elapsed 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
#all_not_ruby?(res) ⇒ Boolean Also known as: all_shell?
135 136 137 138 139 140 141 |
# File 'lib/chitin/session.rb', line 135 def all_not_ruby?(res) if Array === res !res.empty? && res.map {|r| not returning_ruby? r }.all? else not returning_ruby? res end end |
#display(res) ⇒ Object
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 |
# File 'lib/chitin/session.rb', line 144 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 if all_shell? res res = [res] unless Array === res res.each do |res| res[:run] res[:wait] unless res[:bg] end else # else it's a standard ruby type (or a pipe returning as such) if Pipe === res || StringMethod === res val = res[:raw_run] else val = res end # if the input is ruby, then this is redundant # if the input is a pipe that returns ruby, # then this is needed because while the expression # returns a pipe, when we run it it returns a ruby # value. we want to remember the ruby value. @sandbox.previous = val txt = @config.post_processing[:color].call val.inspect puts " => #{txt}" 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.
116 117 118 119 120 121 |
# File 'lib/chitin/session.rb', line 116 def evaluate(val) val.strip! @config.pre_processing[:default].each {|p| val = p.call val } @sandbox.evaluate val end |
#inspect ⇒ Object
188 189 190 |
# File 'lib/chitin/session.rb', line 188 def inspect "#<Chitin::Session #{object_id}>" end |
#print(*args) ⇒ Object
184 185 186 |
# File 'lib/chitin/session.rb', line 184 def print(*args) @out.print *args end |
#puts(*args) ⇒ Object
180 181 182 |
# File 'lib/chitin/session.rb', line 180 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.
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/chitin/session.rb', line 91 def read # find out the column (1-indexed) that will next be printed # if it's NOT 1, then something was printed, and we want to insert # a newline a = nil STDIN.raw do print "\e[6n" a = STDIN.gets 'R' end if a.chomp('R').split(';').last != '1' puts puts "(no trailing newline)" end inp = @editor.readline @sandbox.prompt inp ? inp.chomp : nil # return nil so that the while loop in #start can end end |
#returning_ruby?(res) ⇒ Boolean
123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/chitin/session.rb', line 123 def returning_ruby?(res) # 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). return true unless Runnable === res res[:returning] == :ruby && (res[:out] == nil || res[:out].stat == STDOUT.stat) end |
#start ⇒ Object
Read Evaluate Print (display) Loop
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
# File 'lib/chitin/session.rb', line 65 def start while (val = read) next if val.empty? # a little bit of infrastructure for timing purposes timing = Time.now 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.} (#{e.class})" e.backtrace[1..-1].each {|l| puts "\t#{l}" } nil ensure @last_elapsed = Time.now - timing end end end |