Class: Processing::Watcher
- Inherits:
-
Object
- Object
- Processing::Watcher
- Defined in:
- lib/ruby-processing/runners/watch.rb
Overview
A sketch loader, observer, and reloader, to tighten the feedback between code and effect.
Instance Method Summary collapse
-
#initialize ⇒ Watcher
constructor
Sic a new Processing::Watcher on the sketch.
-
#record_state_of_ruby ⇒ Object
Do the best we can to take a picture of the current Ruby interpreter.
-
#recursively_remove_constants(base, constant_names) ⇒ Object
Used to clean up declared constants in code that needs to be reloaded.
-
#rewind_to_recorded_state ⇒ Object
Try to go back to the recorded Ruby state.
-
#start_watching ⇒ Object
Kicks off a thread to watch the sketch, reloading Ruby-Processing and restarting the sketch whenever it changes.
-
#wipe_out_current_app! ⇒ Object
Used to completely remove all traces of the current sketch, so that it can be loaded afresh.
Constructor Details
#initialize ⇒ Watcher
Sic a new Processing::Watcher on the sketch
10 11 12 13 14 15 16 17 |
# File 'lib/ruby-processing/runners/watch.rb', line 10 def initialize @file = Processing::SKETCH_PATH @time = Time.now # Doesn't work well enough for now. # record_state_of_ruby Processing.load_and_run_sketch unless $app start_watching end |
Instance Method Details
#record_state_of_ruby ⇒ Object
Do the best we can to take a picture of the current Ruby interpreter. For now, this means top-level constants and loaded .rb files.
68 69 70 71 72 73 |
# File 'lib/ruby-processing/runners/watch.rb', line 68 def record_state_of_ruby @saved_constants = Object.send(:constants).dup @saved_load_paths = $LOAD_PATH.dup @saved_features = $LOADED_FEATURES.dup @saved_globals = Kernel.global_variables.dup end |
#recursively_remove_constants(base, constant_names) ⇒ Object
Used to clean up declared constants in code that needs to be reloaded.
97 98 99 100 101 102 103 104 105 106 |
# File 'lib/ruby-processing/runners/watch.rb', line 97 def recursively_remove_constants(base, constant_names) constants = constant_names.map {|name| base.const_get(name) } constants.each_with_index do |c, i| java_obj = Java::JavaLang::Object constants[i] = constant_names[i] = nil if c.respond_to?(:ancestors) && c.ancestors.include?(java_obj) constants[i] = nil if !c.is_a?(Class) && !c.is_a?(Module) end constants.each {|c| recursively_remove_constants(c, c.constants) if c } constant_names.each {|name| base.send(:remove_const, name.to_sym) if name } end |
#rewind_to_recorded_state ⇒ Object
Try to go back to the recorded Ruby state.
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
# File 'lib/ruby-processing/runners/watch.rb', line 77 def rewind_to_recorded_state new_constants = Object.send(:constants).reject {|c| @saved_constants.include?(c) } new_load_paths = $LOAD_PATH.reject {|p| @saved_load_paths.include?(p) } new_features = $LOADED_FEATURES.reject {|f| @saved_features.include?(f) } new_globals = Kernel.global_variables.reject {|g| @saved_globals.include?(g) } Processing::App.recursively_remove_constants(Object, new_constants) new_load_paths.each {|p| $LOAD_PATH.delete(p) } new_features.each {|f| $LOADED_FEATURES.delete(f) } new_globals.each do |g| begin eval("#{g} = nil") # There's no way to undef a global variable in Ruby rescue NameError => e # Some globals are read-only, and we can't set them to nil. end end end |
#start_watching ⇒ Object
Kicks off a thread to watch the sketch, reloading Ruby-Processing and restarting the sketch whenever it changes.
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
# File 'lib/ruby-processing/runners/watch.rb', line 22 def start_watching thread = Thread.start do loop do file_mtime = File.stat(@file).mtime if file_mtime > @time @time = file_mtime wipe_out_current_app! # Taking it out the reset until it can be made to work more reliably # rewind_to_recorded_state GC.start begin Processing.load_and_run_sketch rescue StandardError, ScriptError print "Error in your sketch: ", $!, "\n" end end sleep 0.33 end end thread.join end |
#wipe_out_current_app! ⇒ Object
Used to completely remove all traces of the current sketch, so that it can be loaded afresh. Go down into modules to find it, even.
47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/ruby-processing/runners/watch.rb', line 47 def wipe_out_current_app! app = $app return unless app app.no_loop # Wait for the animation thread to finish rendering sleep 0.075 app.close constant_names = app.class.to_s.split(/::/) app_class_name = constant_names.pop obj = constant_names.inject(Object) {|o, name| o.send(:const_get, name) } obj.send(:remove_const, app_class_name) end |