Class: Watchr::Script

Inherits:
Object
  • Object
show all
Defined in:
lib/watchr/script.rb

Overview

A script object wraps a script file, and is used by a controller.

Examples:


path   = Pathname.new('specs.watchr')
script = Watchr::Script.new(path)

Defined Under Namespace

Classes: EvalContext, Rule

Constant Summary collapse

DEFAULT_EVENT_TYPE =
:modified

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(path = nil) ⇒ Script

Create a Script object for script at path



77
78
79
80
81
82
# File 'lib/watchr/script.rb', line 77

def initialize(path = nil)
  @path = path
  @rules = []
  @default_action = Proc.new {}
  @ec = EvalContext.new(self)
end

Instance Attribute Details

#ecEvalContext (readonly)

EvalContext instance

Examples:


script.ec.watch('pattern') { }
script.ec.reload


63
64
65
# File 'lib/watchr/script.rb', line 63

def ec
  @ec
end

#rulesRule (readonly)

Defined rules



70
71
72
# File 'lib/watchr/script.rb', line 70

def rules
  @rules
end

Instance Method Details

#action_for(path, event_type = DEFAULT_EVENT_TYPE) ⇒ Proc

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.

Examples:


script.watch( 'test/test_.*\.rb' ) {|md| "ruby #{md[0]}" }
script.action_for('test/test_watchr.rb').call #=> "ruby test/test_watchr.rb"


200
201
202
203
204
205
206
207
208
209
# File 'lib/watchr/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

#default_action(&action) ⇒ Proc

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

Examples:


# 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') }


157
158
159
160
# File 'lib/watchr/script.rb', line 157

def default_action(&action)
  @default_action = action if action
  @default_action
end

#parse!Object

TODO:

improve ENOENT error handling

Eval content of script file.



171
172
173
174
175
176
177
178
179
180
# File 'lib/watchr/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
  Watchr.debug('loaded script file %s' % @path.to_s.inspect)
end

#pathPathname

Path to the script file corresponding to this object



226
227
228
# File 'lib/watchr/script.rb', line 226

def path
  @path && Pathname(@path.respond_to?(:to_path) ? @path.to_path : @path.to_s).expand_path
end

#patternsArray<String,Regexp>

Collection of all patterns defined in script.



216
217
218
219
# File 'lib/watchr/script.rb', line 216

def patterns
  #@rules.every.pattern
  @rules.map {|r| r.pattern }
end

#resetObject

Reset script state



163
164
165
166
# File 'lib/watchr/script.rb', line 163

def reset
  @rules = []
  @default_action = Proc.new {}
end

#watch(pattern, event_type = DEFAULT_EVENT_TYPE) { ... } ⇒ Rule

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[0] ) as well as individual backreferences ( md[1..n] ). See ‘MatchData#[]` documentation for more details.

With these two rules, watchr 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).

Examples:


# in script file
watch( 'test/test_.*\.rb' )  {|md| system("ruby #{md[0]}") }
watch( 'lib/(.*)\.rb' )      {|md| system("ruby test/test_#{md[1]}.rb") }

Yields:

  • action to trigger



127
128
129
130
# File 'lib/watchr/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