Class: Ergo::Book

Inherits:
Module
  • Object
show all
Defined in:
lib/ergo/book.rb

Overview

TODO:

There are some minor namespace issues with this implementation.

We don't necessarily want a rule block to be able to
call #rule. However, the scoping is a bit complicated,
so it's an acceptable niggle for now.

Ergo rulebook stores defined states and rules.

Direct Known Subclasses

System

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(system, name) { ... } ⇒ Book

Instantiate new system.

Parameters:

  • system

    The system to which this book belongs. [System]

  • name

    Name of the book.

Yields:

  • Yields the script defining the books rules.



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/ergo/book.rb', line 20

def initialize(system, name, &block)
  extend ShellUtils
  extend system
  extend self

  @scripts = []
  @rules   = []
  @states  = {}

  @name    = name.to_s
  @ignore  = system.ignore
  @session = system.session

  clear_rule_options

  module_eval(&block) if block
end

Instance Attribute Details

#nameObject (readonly)

Book name



39
40
41
# File 'lib/ergo/book.rb', line 39

def name
  @name
end

#rulesObject (readonly)

Array of defined rules.



51
52
53
# File 'lib/ergo/book.rb', line 51

def rules
  @rules
end

#scriptsObject (readonly)

Rule scripts.



45
46
47
# File 'lib/ergo/book.rb', line 45

def scripts
  @scripts
end

#sessionObject (readonly)

Current session.



42
43
44
# File 'lib/ergo/book.rb', line 42

def session
  @session
end

#statesObject (readonly)

Array of defined states.



48
49
50
# File 'lib/ergo/book.rb', line 48

def states
  @states
end

Instance Method Details

#clear_rule_optionsObject (private)



210
211
212
213
214
# File 'lib/ergo/book.rb', line 210

def clear_rule_options
  @_mark = [name].compact
  @_desc = nil
  @_priv = false
end

#desc(description) ⇒ String

Set rule description. The next rule defined will get the most recently defined description attached to it.

Returns:

  • (String)

    Returns



177
178
179
# File 'lib/ergo/book.rb', line 177

def desc(description)
  @_desc = description
end

#env(name_to_pattern) ⇒ State

Define an environment state.

Examples:

env('PATH'=>/foo/)

Returns:



135
136
137
138
139
140
141
# File 'lib/ergo/book.rb', line 135

def env(name_to_pattern)
  State.new do
    name_to_pattern.any? do |name, re|
      re === ENV[name.to_s]  # or `all?` instead?
    end
  end
end

#file(pattern) ⇒ FileState

Define a file state.

Returns:



125
126
127
# File 'lib/ergo/book.rb', line 125

def file(pattern)
  FileState.new(pattern)
end

#get_rule_optionsObject (private)



206
207
208
# File 'lib/ergo/book.rb', line 206

def get_rule_options     
  { :desc=>@_desc, :mark=>@_mark, :private=>@_priv }
end

#ignore(*globs) ⇒ Array<String>

Add paths to be ignored in file rules.

Parameters:

  • globs

    List of file globs. [Array<String>]

Returns:

  • (Array<String>)

    Returns



78
79
80
81
# File 'lib/ergo/book.rb', line 78

def ignore(*globs)
  @ignore.concat(globs) unless globs.empty?
  @ignore
end

#ignore!(*globs) ⇒ Array<String>

Replace globs in ignore list.

Parameters:

  • globs

    List of file globs. [Array<String>]

Returns:

  • (Array<String>)

    Returns



88
89
90
91
# File 'lib/ergo/book.rb', line 88

def ignore!(*globs)
  @ignore.replace(globs)
  @ignore
end

#import(*globs) ⇒ void

TODO:

Should importing be relative the importing file?

This method returns an undefined value.

Import from another file, or glob of files, relative to project root.



58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/ergo/book.rb', line 58

def import(*globs)
  globs.each do |glob|
    #if File.relative?(glob)
    #  dir = Dir.pwd  #session.root #File.dirname(caller[0])
    #  glob = File.join(dir, glob)
    #end
    Dir[glob].each do |file|
      next unless File.file?(file)  # add warning
      next if @scripts.include?(file)
      @scripts << file
      module_eval(File.read(file), file)
    end
  end
end

#mark(*names) ⇒ void Also known as: bookmark

This method returns an undefined value.

Bookmark the rule.



184
185
186
# File 'lib/ergo/book.rb', line 184

def mark(*names)
  @_mark.concat(names)
end

#notify(message, options = {}) ⇒ void

This method returns an undefined value.

Issue notification.



199
200
201
202
# File 'lib/ergo/book.rb', line 199

def notify(message, options={})
  title = options.delete(:title) || 'Fire Notification'
  Notify.notify(title, message.to_s, options)
end

#private(*methods) ⇒ Object



191
192
193
194
# File 'lib/ergo/book.rb', line 191

def private(*methods)
  @_priv = true
  super(*methods)   # TODO: why doesn't this work as expected?
end

#rule(state, &procedure) ⇒ Rule

Define a rule. Rules are procedures that are tiggered by logical states.

Examples:

rule no_rdocs do |files|
  sh "rdoc --output doc/rdoc " + files.join(" ")
end

Returns:

  • (Rule)

    Returns



152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/ergo/book.rb', line 152

def rule(state, &procedure)
  case state
  when String, Regexp
    state = file(state)
  when Symbol
    # TODO: Is this really the best idea?
    #@states[state.to_sym]
  end
  rule = Rule.new(state, get_rule_options, &procedure)
  @rules << rule
  clear_rule_options
  rule
end

#state(name = nil, &condition) ⇒ nil, State

Define a named state. States define conditions that are used to trigger rules. Named states are kept in a hash table to ensure that only one state is ever defined for a given name. Calling state again with the same name as a previously defined state will redefine the condition of that state.

Examples:

state :no_rdocs? do
  files = Dir.glob('lib/**/*.rb')
  FileUtils.uptodate?('doc', files) ? files : false
end

Returns:

  • (nil)

    Returns nil if state name is given.

  • (State)

    Returns State in no name is given.



106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/ergo/book.rb', line 106

def state(name=nil, &condition)
  if name
    if condition
      @states[name.to_sym] = condition
      define_method(name) do |*args|
        state = @states[name.to_sym]
        State.new{ states[name.to_sym].call(*args) }
      end
    else
      raise ArgumentError
    end
  else
    State.new{ condition.call(*args) }
  end
end

#state?(name, *args) ⇒ Array, Boolean

Check a name state.

Returns:



169
170
171
# File 'lib/ergo/book.rb', line 169

def state?(name, *args)
  @states[name.to_sym].call(*args)
end