class Observr::Script
A script object wraps a script file, and is used by a controller.
@example
path = Pathname.new('specs.observr') script = Observr::Script.new(path)
Constants
- DEFAULT_EVENT_TYPE
@private
- Rule
Convenience type. Provides clearer and simpler access to rule properties.
@example
rule = script.watch('lib/.*\.rb') { 'ohaie' } rule.pattern #=> 'lib/.*\.rb' rule.action.call #=> 'ohaie'
Attributes
Defined rules
@return [Rule]
all rules defined with `#watch` calls
Public Class Methods
Create a Script
object for script at ‘path`
@param [Pathname] path
the path to the script
# File lib/observr/script.rb, line 77 def initialize(path = nil) @path = path @rules = [] @default_action = Proc.new {} @ec = EvalContext.new(self) end
Public Instance Methods
Find an action corresponding to a path and event type. The returned action is actually a wrapper around the rule’s action, with the match_data prepopulated.
@example
script.watch( 'test/test_.*\.rb' ) {|md| "ruby #{md[0]}" } script.action_for('test/test_observr.rb').call #=> "ruby test/test_observr.rb"
@param [Pathname, String] path
find action that corresponds to this path.
@param [Symbol] event_type
find action only if rule's event is of this type.
@return [Proc]
action, preparsed and ready to be called
# File lib/observr/script.rb, line 200 def action_for(path, event_type = DEFAULT_EVENT_TYPE) path = rel_path(path).to_s rule = rules_for(path).detect {|rule| rule.event_type.nil? || rule.event_type == event_type } if rule data = path.match(rule.pattern) lambda { rule.action.call(data) } else lambda {} end end
Convenience method. Define a default action to be triggered when a rule has none specified. When called without a block, acts as a getter and returns stored default_action
@example
# in script file default_action { system('rake --silent yard') } watch( 'lib/.*\.rb' ) watch( 'README.md' ) watch( 'TODO.txt' ) watch( 'LICENSE' ) # is equivalent to: watch( 'lib/.*\.rb' ) { system('rake --silent yard') } watch( 'README.md' ) { system('rake --silent yard') } watch( 'TODO.txt' ) { system('rake --silent yard') } watch( 'LICENSE' ) { system('rake --silent yard') }
@return [Proc]
default action
# File lib/observr/script.rb, line 157 def default_action(&action) @default_action = action if action @default_action end
Eval content of script file.
@todo improve ENOENT error handling
# File lib/observr/script.rb, line 171 def parse! return unless @path reset @ec.instance_eval(@path.read, @path.to_s) rescue Errno::ENOENT sleep(0.3) #enough? retry ensure Observr.debug('loaded script file %s' % @path.to_s.inspect) end
Path to the script file corresponding to this object
@return [Pathname]
absolute path to script file
# File lib/observr/script.rb, line 226 def path @path && Pathname(@path.respond_to?(:to_path) ? @path.to_path : @path.to_s).expand_path end
Collection of all patterns defined in script.
@return [Array<String,Regexp>]
all defined patterns
# File lib/observr/script.rb, line 216 def patterns #@rules.every.pattern @rules.map {|r| r.pattern } end
Reset script state
# File lib/observr/script.rb, line 163 def reset @rules = [] @default_action = Proc.new {} end
Main script API method. Builds a new rule, binding a pattern to an action.
Whenever a file is saved that matches a rule’s ‘pattern`, its corresponding `action` is triggered.
Patterns can be either a Regexp or a string. Because they always represent paths however, it’s simpler to use strings. But remember to use single quotes (not double quotes), otherwise escape sequences will be parsed (for example ‘“foo/bar.rb” #=> “foo/bar.rb”`, notice “.” becomes “.”), and won’t be interpreted as the regexp you expect.
Also note that patterns will be matched against relative paths (relative to current working directory).
Actions, the blocks passed to ‘watch`, receive a `MatchData` object as argument. It will be populated with the whole matched string ( `md` ) as well as individual backreferences ( `md` ). See `MatchData#[]` documentation for more details.
@example
# in script file watch( 'test/test_.*\.rb' ) {|md| system("ruby #{md[0]}") } watch( 'lib/(.*)\.rb' ) {|md| system("ruby test/test_#{md[1]}.rb") }
With these two rules, observr will run any test file whenever it is itself changed (first rule), and will also run a corresponding test file whenever a lib file is changed (second rule).
@param [#match] pattern
pattern to match targetted paths
@param [Symbol] event_type
rule will only match events of this type. Accepted types are `:accessed`, `:modified`, `:changed`, `:delete` and `nil` (any), where the first three correspond to atime, mtime and ctime respectively. Defaults to `:modified`.
@yield
action to trigger
@return [Rule]
# File lib/observr/script.rb, line 127 def watch(pattern, event_type = DEFAULT_EVENT_TYPE, &action) @rules << Rule.new(pattern, event_type, action || @default_action) @rules.last end
Private Instance Methods
Make a path relative to current working directory.
@param [Pathname, String] path
absolute or relative path
@return [Pathname]
relative path, from current working directory.
# File lib/observr/script.rb, line 253 def rel_path(path) Pathname(path).expand_path.relative_path_from(Pathname(Dir.pwd)) end
Rules corresponding to a given path, in reversed order of precedence (latest one is most inportant).
@param [Pathname, String] path
path to look up rule for
@return [Array<Rule>]
rules corresponding to `path`
# File lib/observr/script.rb, line 241 def rules_for(path) @rules.reverse.select {|rule| path.match(rule.pattern) } end