Module: Courtier::Interface

Included in:
Courtier
Defined in:
lib/courtier/interface.rb

Overview

The Interface module extends Courtier module.

A tool can control Courtier configuration by loading ‘courtier` and calling the toplevel `court` or `Courtier.setup` method with a block that handles the configuration for the feature as provided by a project’s config file.

The block will often need to be conditioned on the current profile and/or the then current command. This is easy enough to do with #profile? and #command? methods.

require 'courtier'

Courtier.setup('rspec') do |config|
  if config.profile?
    RSpec.configure(&config)
  end
end

Constant Summary collapse

FILE_PATTERN =

Configuration file pattern. The standard configuration file name is ‘Config.rb`, and that name should be used in most cases. However, `.config.rb` can also be use and will take precedence if found. Conversely, `config.rb` (lowercase form) can also be used but has the least precedence.

Config files looked for in the order or precedence:

* `.config.rb` or `.confile.rb`
* `Config.rb`  or `Confile.rb`
* `config.rb`  or `confile.rb`

Yes, there are really too many choices here, but we haven’t been able to settle on a smaller list just yet. Please come argue with us about what’s best.

'{.c,C,c}on{fig.rb,file,file.rb}'
TWEAKS_DIR =

The tweaks directory is where special augementation script reside the are used to adjust behavior of certain popular tools to work with Courtier that would not otherwise do so.

File.dirname(__FILE__) + '/tweaks'

Instance Method Summary collapse

Instance Method Details

#_configure(command) ⇒ Object (private)



281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
# File 'lib/courtier/interface.rb', line 281

def _configure(command) #, &setup)
  tweak(command)

  command_config = Courtier.configuration[command]

  return unless command_config

  setup = Courtier.court(command)

  command_config.each do |config|
    next if config.onload? # not command config
    next unless config.apply?
    config.require_feature
    setup ? setup.call(config) : config.call
  end
end

#autoconfigureObject (private)

Copnfgure current commnad. This is used by the ‘rc` script.



274
275
276
# File 'lib/courtier/interface.rb', line 274

def autoconfigure
  _configure(current_command)
end

#bootstrapObject (private)

Setup courtier system.



243
244
245
246
247
248
249
# File 'lib/courtier/interface.rb', line 243

def bootstrap
  @bootstrap ||= (
    properties  # prime global properties
    bootstrap_require
    true
  )
end

#bootstrap_requireObject (private)

Override require.



256
257
258
259
260
261
262
263
264
265
266
267
268
269
# File 'lib/courtier/interface.rb', line 256

def bootstrap_require
  def Kernel.required(feature)
    config = Courtier.configuration[feature]
    if config
      setup = Courtier.court(feature)  # FIXME: how to differentiate feature from command setup ?
      config.each do |config|
        next unless config.onload? # only command config
        next unless config.apply?
        setup ? setup.call(config) : config.call
      end
    end
    super(feature) if defined?(super)
  end
end

#cacheObject

Library configuration cache. Since configuration can be imported from other libraries, we keep a cache for each library.



65
66
67
# File 'lib/courtier/interface.rb', line 65

def cache
  @cache ||= {}
end

#clear!Object

Clear the library configuration cache. This is mostly used for testing.



73
74
75
# File 'lib/courtier/interface.rb', line 73

def clear!
  @cache = {}
end

#configuration(gem = nil) ⇒ Configuration

Load library configuration for a given gem. If no gem is specified then the current project’s configuration is used.

Returns:



83
84
85
86
# File 'lib/courtier/interface.rb', line 83

def configuration(gem=nil)
  key = gem ? gem.to_s : nil #Dir.pwd
  cache[key] ||= Configuration.load(:from=>gem)
end

#configure(tool, options = {}, &setup) ⇒ Object



233
234
235
236
# File 'lib/courtier/interface.rb', line 233

def configure(tool, options={}, &setup)
  court(tool, options, &setup)
  _configure(tool)
end

#court(tool, options = {}, &block) ⇒ Object

Define a specialized configuration handler.



168
169
170
171
172
173
174
175
176
177
178
179
180
181
# File 'lib/courtier/interface.rb', line 168

def court(tool, options={}, &block)
  @setup ||= {}
  tool = tool.to_s
  if block
    @setup[tool] = Setup.new(tool, options, &block)
    #path = Find.load_path(tool, :absolute=>true)
    #if path
    #  if $LOADED_FEATURES.include?(path)
    #    configure(tool)
    #  end
    #end
  end
  @setup[tool.to_s]
end

#current_profileObject

Get current profile.



136
137
138
# File 'lib/courtier/interface.rb', line 136

def current_profile
  ENV['profile'] || ENV['p'] || 'default'
end

#current_profile=(profile) ⇒ Object

Set current profile.



143
144
145
146
147
148
149
# File 'lib/courtier/interface.rb', line 143

def current_profile=(profile)
  if profile
    ENV['profile'] = profile.to_s
  else
    ENV['profile'] = nil
  end
end

#current_toolObject Also known as: current_command

TODO:

Not so sure ‘ENV` is a good idea.

Get current tool.



120
121
122
# File 'lib/courtier/interface.rb', line 120

def current_tool
  File.basename(ENV['tool'] || $0)
end

#current_tool=(tool) ⇒ Object Also known as: current_command=

Set current tool.



128
129
130
# File 'lib/courtier/interface.rb', line 128

def current_tool=(tool)
  ENV['tool'] = tool.to_s
end

#profile_names(tool = nil, opts = {}) ⇒ Object

Return a list of names of defined profiles for a given tool.

Examples:

profile_names(:qed)

Parameters:

  • tool (#to_sym) (defaults to: nil)

    Tool for which lookup defined profiles. If none given the current tool is used.

  • opts (Hash) (defaults to: {})

    Options for looking up profiles.

Options Hash (opts):

  • :gem (#to_s)

    Name of library from which to load the configuration.



104
105
106
107
108
109
110
111
112
113
# File 'lib/courtier/interface.rb', line 104

def profile_names(tool=nil, opts={})
  if Hash === tool
    opts, tool = tool, nil
  end

  tool = tool || current_tool
  gem  = opts[:from]

  configuration(gem).profile_names(tool)
end

#profile_switch(command, *switches) ⇒ Object

Set current profile via ARGV switch. This is done immediately, setting ‘ENV` to the switch value if this setup is for the current commandline tool. The reason it is done immediately, rather than assigning it in bootstrap, is b/c option parsers somtimes consume ARGV as they parse it, and by then it would too late.

Examples:

Courtier.profile_switch('qed', '-p', '--profile')


193
194
195
196
197
198
199
200
201
202
203
204
205
206
# File 'lib/courtier/interface.rb', line 193

def profile_switch(command, *switches)
  return unless command.to_s == Courtier.current_command

  switches.each do |switch, envar|
    if index = ARGV.index(switch)
      self.current_profile = ARGV[index+1]
    elsif arg = ARGV.find{ |a| a =~ /#{switch}=(.*?)/ }
      value = $1
      value = value[1..-2] if value.start_with?('"') && value.end_with?('"')
      value = value[1..-2] if value.start_with?("'") && value.end_with?("'")
      self.currrent_profile = value
    end
  end
end

#propertiesObject

Properties of the current project. These can be used in a project’s config file to make configuration more interchangeable. Presently project properties are gathered from .ruby YAML or .gemspec.

NOTE: How properties are gathered will be refined in the future.



161
162
163
# File 'lib/courtier/interface.rb', line 161

def properties
  $properties ||= Properties.new
end

#switch(command, switches = {}) ⇒ Object

Set enviroment variable(s) to command line switch value(s). This is a more general form of #profile_switch and will probably not get much use in this context.

Examples:

Courtier.switch('qed', '-p'=>'profile', '--profile'=>'profile')


215
216
217
218
219
220
221
222
223
224
225
226
227
228
# File 'lib/courtier/interface.rb', line 215

def switch(command, switches={})
  return unless command.to_s == Courtier.current_command

  switches.each do |switch, envar|
    if index = ARGV.index(switch)
      ENV[envar] = ARGV[index+1]
    elsif arg = ARGV.find{ |a| a =~ /#{switch}=(.*?)/ }
      value = $1
      value = value[1..-2] if value.start_with?('"') && value.end_with?('"')
      value = value[1..-2] if value.start_with?("'") && value.end_with?("'")
      ENV[envar] = value
    end
  end
end

#tweak(command) ⇒ Object (private)



301
302
303
304
305
306
# File 'lib/courtier/interface.rb', line 301

def tweak(command)
  tweak = File.join(TWEAKS_DIR, command + '.rb')
  if File.exist?(tweak)
    require tweak
  end
end