Class: Observr::Script

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

Overview

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

Examples:


path   = Pathname.new('specs.observr')
script = Observr::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`

Parameters:

  • path (Pathname) (defaults to: nil)

    the path to the script



77
78
79
80
81
82
# File 'lib/observr/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

Returns:



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

def ec
  @ec
end

#rulesRule (readonly)

Defined rules

Returns:

  • (Rule)

    all rules defined with ‘#watch` calls



70
71
72
# File 'lib/observr/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_observr.rb').call #=> "ruby test/test_observr.rb"

Parameters:

  • path (Pathname, String)

    find action that corresponds to this path.

  • event_type (Symbol) (defaults to: DEFAULT_EVENT_TYPE)

    find action only if rule’s event is of this type.

Returns:

  • (Proc)

    action, preparsed and ready to be called



200
201
202
203
204
205
206
207
208
209
# 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

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

Returns:

  • (Proc)

    default action



157
158
159
160
# File 'lib/observr/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/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

#pathPathname

Path to the script file corresponding to this object

Returns:

  • (Pathname)

    absolute path to script file



226
227
228
# 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

#patternsArray<String,Regexp>

Collection of all patterns defined in script.

Returns:

  • (Array<String,Regexp>)

    all defined patterns



216
217
218
219
# File 'lib/observr/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/observr/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` ) as well as individual backreferences ( `md` ). See `MatchData#[]` documentation for more details.

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

Examples:


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

Parameters:

  • pattern (#match)

    pattern to match targetted paths

  • event_type (Symbol) (defaults to: DEFAULT_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`.

Yields:

  • action to trigger

Returns:



127
128
129
130
# 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