Class: Wake::Script

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

Overview

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

Examples
path   = Pathname.new('specs.wk')
script = Wake::Script.new(path)

Defined Under Namespace

Classes: API, Batch, Rule

Constant Summary collapse

DEFAULT_EVENT_TYPE =
:modified

Class Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(path) ⇒ Script

Creates a script object for path.

Does not parse the script. The controller knows when to parse the script.

Parameters
path<Pathname>

the path to the script



120
121
122
123
124
125
# File 'lib/wake/script.rb', line 120

def initialize(path)
  self.class.script = self
  @path  = path
  @rules = []
  @default_action = lambda {}
end

Class Attribute Details

.handlerObject

Returns the value of attribute handler.



232
233
234
# File 'lib/wake/script.rb', line 232

def handler
  @handler
end

.scriptObject

Returns the value of attribute script.



232
233
234
# File 'lib/wake/script.rb', line 232

def script
  @script
end

Class Method Details

.learn(path) ⇒ Object



233
234
235
236
237
238
# File 'lib/wake/script.rb', line 233

def learn path
  script.depends_on(path).each do |p|
    # $stderr.print "#{path} depends on #{p}\n"
    handler.add Pathname(p)
  end
end

Instance Method Details

#call_action_for(path, event_type = DEFAULT_EVENT_TYPE) ⇒ Object

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.

Params
path<Pathnane,String>

Find action that correspond to this path.

event_type<Symbol>

Find action only if rule’s event if of this type.

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


262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
# File 'lib/wake/script.rb', line 262

def call_action_for(path, event_type = DEFAULT_EVENT_TYPE)
  # $stderr.print "caf #{path} #{event_type}\n";
  pathname = path
  path = rel_path(path).to_s
  # $stderr.print "dob #{path} #{depended_on_by(path).join(' ')}\n"
  string = nil
  begin
    string = Pathname(pathname).realpath.to_s
  rescue Errno::ENOENT; end
  string && depended_on_by(string).each do |dependence|
    # $stderr.print "for caf #{Pathname(pathname).realpath.to_s}\n";
    call_action_for(dependence, event_type)
  end
  rules_for(path).each do |rule|
    # begin
    types = rule.event_types
    !types.empty? or types = [ nil ]
    types.each do |rule_event_type|
      # $stderr.print "#{rule.inspect} #{rule_event_type.inspect} #{event_type.inspect} #{path} #{rule_event_type == event_type}\n"
      if ( rule_event_type.nil? && ( event_type != :load ) ) || ( rule_event_type == event_type )
        data = path.match(rule.pattern)
        # $stderr.print "data #{data}\n"
        return rule.call(data, event_type, pathname)
      end
    end
    # rescue Exception => e; $stderr.print "oops #{e}\n"; raise; end
  end
  # $stderr.print "no path for #{path}\n"
  nil
end

#default_action(&action) ⇒ Object

Convenience method. Define a default action to be triggered when a rule has none specified.

Examples
# in script file

default_action { system('rake --silent rdoc') }

watch( 'lib/.*\.rb'  )
watch( 'README.rdoc' )
watch( 'TODO.txt'    )
watch( 'LICENSE'     )

# equivalent to:

watch( 'lib/.*\.rb'  ) { system('rake --silent rdoc') }
watch( 'README.rdoc' ) { system('rake --silent rdoc') }
watch( 'TODO.txt'    ) { system('rake --silent rdoc') }
watch( 'LICENSE'     ) { system('rake --silent rdoc') }


195
196
197
# File 'lib/wake/script.rb', line 195

def default_action(&action)
  @default_action = action
end

#depended_on_by(path) ⇒ Object



245
246
247
# File 'lib/wake/script.rb', line 245

def depended_on_by path
  []
end

#depends_on(path) ⇒ Object



241
242
243
# File 'lib/wake/script.rb', line 241

def depends_on path
  []
end

#parse!Object

Eval content of script file. – TODO fix script file not found error



202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
# File 'lib/wake/script.rb', line 202

def parse!
  Wake.debug('loading script file %s' % @path.to_s.inspect)

  reset

  # Some editors do delete/rename. Even when they don't some events come very fast ...
  # and editor could do a trunc/write. If you look after the trunc, before the write, well,
  # things aren't pretty.
  
  # Should probably use a watchdog timer that gets reset on every change and then only fire actions
  # after the watchdog timer fires without get reset ..

  v = nil
  (1..10).each do
    old_v = v
    v = @path.read
    break if v != "" && v == old_v
    sleep(0.3)
  end

  instance_eval(@path.read)

rescue Errno::ENOENT
  # TODO figure out why this is happening. still can't reproduce
  Wake.debug('script file "not found". wth')
  sleep(0.3) #enough?
  instance_eval(@path.read)
end

#pathObject

Path to the script file

Returns
path<Pathname>

path to script file



312
313
314
# File 'lib/wake/script.rb', line 312

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

#patternsObject

Collection of all patterns defined in script.

Returns
patterns<String, Regexp>

all patterns



298
299
300
301
# File 'lib/wake/script.rb', line 298

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

#rulesObject



303
304
305
# File 'lib/wake/script.rb', line 303

def rules
  @rules
end

#watch(pattern, event_type = DEFAULT_EVENT_TYPE, predicate = nil, options = {}, &action) ⇒ Object

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 from 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.

Examples
# 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, wake 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).

Parameters
pattern<~#match>

pattern to match targetted paths

event_types<Symbol|Array<Symbol>>

Rule will only match events of one of these 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.

action<Block>

action to trigger

Returns
rule<Rule>

rule created by the method



168
169
170
171
172
# File 'lib/wake/script.rb', line 168

def watch(pattern, event_type = DEFAULT_EVENT_TYPE, predicate = nil, options = {}, &action)
  event_types = Array(event_type)
  @rules << Rule.new(pattern, event_types, predicate, options, action || @default_action)
  @rules.last
end