boson 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.rdoc CHANGED
@@ -6,20 +6,30 @@ Works with Ruby 1.8.6 and 1.9.1.
6
6
  Note: To read a linkable version of this README, {see here}[http://tagaholic.me/boson/doc/].
7
7
 
8
8
  == Features
9
- * Commands are just methods extended for a given object, the default being the top level object, main.
9
+ * Simple organization: Commands are just methods on an object (default is main) and command libraries are just modules.
10
10
  * Commands are accessible from the commandline (Boson::BinRunner) or irb (Boson::ConsoleRunner).
11
- * Command libraries, which are just modules, are written in non-dsl ruby which allows for easy testing
12
- and use outside of boson (Boson::FileLibrary).
11
+ * Libraries
12
+ * can be written in plain ruby which allows for easy testing and use independent of boson (Boson::FileLibrary).
13
+ * can exist locally as a Bosonfile (Boson::LocalFileLibrary) and under lib/boson/commands or .boson/commands.
14
+ * can be made from gems (Boson::GemLibrary) or any require-able file (Boson::RequireLibrary).
15
+ * are encouraged to be shared. Libraries can be installed with a given url. Users can customize any aspect of a third-party
16
+ library without modifying it (Boson::Library).
17
+ * Commands
18
+ * can have any number of local and global options (Boson::OptionCommand). Options are defined with Boson::OptionParser.
19
+ * can have any view associated to it (via Hirb) without adding view code to the command's method.
20
+ These views can be toggled on and manipulated via global render options (Boson::View and Boson::OptionCommand).
21
+ * can pipe their return value into multiple commands with pipe options. Default pipe options give the ability
22
+ to search and sort an array of any objects (Boson::Pipe).
23
+ * Option parser (Boson::OptionParser)
24
+ * provides option types that map to objects i.e. :array type creates Array objects.
25
+ * come with 5 default option types: boolean, array, string, hash and numeric.
26
+ * can have have custom option types defined by users (Boson::Options).
13
27
  * Comes with default commands to load, search, list and install commands and libraries (Boson::Commands::Core).
14
- * Commands can be full-blown commandline apps thanks to powerful options (Boson::OptionParser)
15
- and hirb's views.
16
- * There are 5 default option types: boolean, array, string, hash and numeric. Custom option types
17
- can be defined to map to any Ruby class with one method (Boson::Options).
18
- * Commands can have views toggled without adding view code to the original command (Boson::Scientist).
19
- * Command libraries are social as a user can install them from a url and then customize command
20
- names and options without changing the original library.
21
28
  * Namespaces are optional and when used are methods which allow for method_missing magic.
22
29
 
30
+ == Creating Command Libraries
31
+ See Boson::FileLibrary or here[http://tagaholic.me/boson/doc/classes/Boson/FileLibrary.html].
32
+
23
33
  == Irb Example
24
34
 
25
35
  To use in irb, drop this in your ~/.irbrc:
@@ -132,14 +142,11 @@ Having done that, let's start up irb:
132
142
 
133
143
  # Sweet! Now we have a list and description of commands that come with irb.
134
144
 
135
- == Creating Command Libraries
136
- See Boson::FileLibrary or here[http://tagaholic.me/boson/doc/classes/Boson/FileLibrary.html].
137
-
138
145
  == Todo
139
146
  * More tests
140
147
  * Making commands out of existing gems easier and more powerful
141
- * Better local repositories, perhaps a BosonFile
142
148
  * Consider managing extensions to core and standard libraries
149
+ * Features based on commands and their argument types i.e. aliasing, completion, piping
143
150
  * Consider dropping alias gem dependency if not using its full potential
144
151
 
145
152
  == Bugs/Issues
data/VERSION.yml CHANGED
@@ -1,4 +1,4 @@
1
1
  ---
2
2
  :major: 0
3
3
  :minor: 2
4
- :patch: 0
4
+ :patch: 1
data/lib/boson.rb CHANGED
@@ -3,9 +3,9 @@ $:.unshift File.dirname(__FILE__) unless $:.include? File.expand_path(File.dirna
3
3
  %w{runner runners/console_runner repo manager loader inspector library}.each {|e| require "boson/#{e}" }
4
4
  %w{argument method comment}.each {|e| require "boson/inspectors/#{e}_inspector" }
5
5
  # order of library subclasses matters
6
- %w{module file gem require}.each {|e| require "boson/libraries/#{e}_library" }
6
+ %w{module file gem require local_file}.each {|e| require "boson/libraries/#{e}_library" }
7
7
  (%w{namespace view command util commands option_parser options} +
8
- %w{index scientist}).each {|e| require "boson/#{e}" }
8
+ %w{index repo_index scientist option_command pipe}).each {|e| require "boson/#{e}" }
9
9
 
10
10
  # This module stores the libraries, commands, repos and main object used throughout Boson.
11
11
  #
@@ -17,7 +17,6 @@ $:.unshift File.dirname(__FILE__) unless $:.include? File.expand_path(File.dirna
17
17
  # * Boson::FileLibrary - Explains creating libraries as files
18
18
  # * Boson::Loader - Explains library module callbacks
19
19
  # * Boson::OptionParser - All about options
20
- # * Boson::Scientist - Explains how commands can be both shell-commands and normal ruby methods
21
20
  module Boson
22
21
  # Module which is extended by Boson.main_object to give it command functionality.
23
22
  module Universe; include Commands::Namespace; end
@@ -45,13 +44,14 @@ module Boson
45
44
  # An optional local repository which defaults to ./lib/boson or ./.boson.
46
45
  def local_repo
47
46
  @local_repo ||= begin
47
+ ignored_dirs = (repo.config[:ignore_directories] || []).map {|e| File.expand_path(e) }
48
48
  dir = ["lib/boson", ".boson"].find {|e| File.directory?(e) &&
49
- File.expand_path(e) != repo.dir }
49
+ File.expand_path(e) != repo.dir && !ignored_dirs.include?(File.expand_path('.')) }
50
50
  Repo.new(dir) if dir
51
51
  end
52
52
  end
53
53
 
54
- # The array of loaded repositories
54
+ # The array of loaded repositories containing the main repo and a possible local repo
55
55
  def repos
56
56
  @repos ||= [repo, local_repo].compact
57
57
  end
data/lib/boson/command.rb CHANGED
@@ -24,28 +24,27 @@ module Boson
24
24
  # and :lib are required keys.
25
25
  #
26
26
  # Attributes that can be configured:
27
- # * *:description*: Description that shows up in command listings
28
- # * *:alias*: Alternative name for command
29
- # * *:options*: Hash of options passed to OptionParser
30
- # * *:render_options*: Hash of rendering options passed to OptionParser
31
- # * *:args*: Should only be set if not automatically set. This attribute is only
32
- # important for commands that have options/render_options. Its value can be an array
33
- # (as ArgumentInspector.scrape_with_eval produces), a number representing
34
- # the number of arguments or '*' if the command has a variable number of arguments.
35
- # * *:default_option* Only for an option command that has one argument. This treats the given
36
- # option as an optional first argument. Example:
37
- # # For a command with default option 'query' and options --query and -v
38
- # 'some -v' -> '--query=some -v'
39
- # '-v' -> '-v'
27
+ # [*:description*] Description that shows up in command listings
28
+ # [*:alias*] Alternative name for command
29
+ # [*:options*] Hash of options passed to OptionParser
30
+ # [*:render_options*] Hash of rendering options passed to OptionParser
31
+ # [*:global_options*] Boolean to enable using global options without having to define render_options or options.
32
+ # [*:args*] Should only be set if not automatically set. This attribute is only
33
+ # important for commands that have options/render_options. Its value can be an array
34
+ # (as ArgumentInspector.scrape_with_eval produces), a number representing
35
+ # the number of arguments or '*' if the command has a variable number of arguments.
36
+ # [*:default_option*] Only for an option command that has one or zero arguments. This treats the given
37
+ # option as an optional first argument. Example:
38
+ # # For a command with default option 'query' and options --query and -v
39
+ # 'some -v' -> '--query=some -v'
40
+ # '-v' -> '-v'
40
41
  def initialize(hash)
41
42
  @name = hash[:name] or raise ArgumentError
42
43
  @lib = hash[:lib] or raise ArgumentError
43
- @alias = hash[:alias] if hash[:alias]
44
- @description = hash[:description] if hash[:description]
45
- @render_options = hash[:render_options] if hash[:render_options]
46
- @options = hash[:options] if hash[:options]
47
- @namespace = hash[:namespace] if hash[:namespace]
48
- @default_option = hash[:default_option] if hash[:default_option]
44
+ [:alias, :description, :render_options, :options, :namespace, :default_option,
45
+ :global_options].each do |e|
46
+ instance_variable_set("@#{e}", hash[e]) if hash[e]
47
+ end
49
48
  if hash[:args]
50
49
  if hash[:args].is_a?(Array)
51
50
  @args = hash[:args]
@@ -75,7 +74,7 @@ module Boson
75
74
 
76
75
  # Option parser for command as defined by @options.
77
76
  def option_parser
78
- @option_parser ||= (@options ? OptionParser.new(@options) : nil)
77
+ @option_parser ||= OptionParser.new(@options || {})
79
78
  end
80
79
 
81
80
  # Help string for options if a command has it.
@@ -107,7 +106,7 @@ module Boson
107
106
  end
108
107
 
109
108
  def option_command?
110
- options || render_options
109
+ options || render_options || @global_options
111
110
  end
112
111
 
113
112
  def arg_size
@@ -24,7 +24,7 @@ module Boson::Commands::Core #:nodoc:
24
24
  :fields=>{:default=>[:name, :commands, :gems, :library_type], :values=>library_attributes},
25
25
  :filters=>{:default=>{:gems=>[:join, ','],:commands=>:size}, :desc=>"Filters to apply to library fields" }}
26
26
  },
27
- 'load_library'=>{:description=>"Load/reload a library", :options=>{:reload=>:boolean, [:verbose,:V]=>true}}
27
+ 'load_library'=>{:description=>"Load a library", :options=>{[:verbose,:V]=>true}}
28
28
  }
29
29
 
30
30
  {:namespace=>false, :library_file=>File.expand_path(__FILE__), :commands=>commands}
@@ -39,8 +39,7 @@ module Boson::Commands::Core #:nodoc:
39
39
  end
40
40
 
41
41
  def load_library(library, options={})
42
- options[:reload] ? Boson::Manager.reload(library, options) :
43
- Boson::Manager.load(library, options)
42
+ Boson::Manager.load(library, options)
44
43
  end
45
44
 
46
45
  def render(object, options={})
@@ -56,11 +55,11 @@ module Boson::Commands::Core #:nodoc:
56
55
  puts msg
57
56
  if command && options[:verbose]
58
57
  if command.options && !command.options.empty?
59
- puts "\nCOMMAND OPTIONS"
58
+ puts "\nLOCAL OPTIONS"
60
59
  command.option_parser.print_usage_table
61
60
  end
62
- puts "\nGLOBAL/RENDER OPTIONS"
63
- Boson::Scientist.render_option_parser(command).print_usage_table
61
+ puts "\nGLOBAL OPTIONS"
62
+ Boson::Scientist.option_command(command).option_parser.print_usage_table
64
63
  end
65
64
  end
66
65
  end
data/lib/boson/index.rb CHANGED
@@ -1,118 +1,41 @@
1
- require 'digest/md5'
2
1
  module Boson
3
- # This class is used by BinRunner to index/store all of Boson's commands and libraries. When this index updates,
4
- # it detects library files whose md5 hash have changed and reindexes them. The index is stored with Marshal
5
- # at ~/.boson/config/index.marshal. Since the index is marshaled, putting lambdas/procs in it will break it.
6
- # If your index gets corrupted, simply delete it and next time Boson needs it, the index will be recreated.
2
+ # This class manages indexing/storing all commands and libraries. See RepoIndex for details
3
+ # about the index created for each Repo.
7
4
  module Index
8
5
  extend self
9
- attr_reader :libraries, :commands
10
-
11
- # Updates the index.
12
- def update(options={})
13
- libraries_to_update = !exists? ? Runner.all_libraries : options[:libraries] || changed_libraries
14
- read_and_transfer(libraries_to_update)
15
- if options[:verbose]
16
- puts !exists? ? "Generating index for all #{libraries_to_update.size} libraries. Patience ... is a bitch" :
17
- (libraries_to_update.empty? ? "No libraries indexed" :
18
- "Indexing the following libraries: #{libraries_to_update.join(', ')}")
19
- end
20
- Manager.failed_libraries = []
21
- unless libraries_to_update.empty?
22
- Manager.load(libraries_to_update, options.merge(:index=>true))
23
- unless Manager.failed_libraries.empty?
24
- $stderr.puts("Error: These libraries failed to load while indexing: #{Manager.failed_libraries.join(', ')}")
25
- end
26
- end
27
- write(Manager.failed_libraries)
28
- end
29
-
30
- # Reads and initializes index.
31
- def read
32
- return if @read
33
- @libraries, @commands, @lib_hashes = exists? ? Marshal.load(File.read(marshal_file)) : [[], [], {}]
34
- delete_stale_libraries_and_commands
35
- set_command_namespaces
36
- @read = true
6
+ # Array of indexes, one per repo in Boson.repos.
7
+ def indexes
8
+ @indexes ||= Boson.repos.map {|e| RepoIndex.new(e) }
37
9
  end
38
10
 
39
- # Writes/saves current index to config/index.marshal.
40
- def write(failed_libraries=[])
41
- latest = latest_hashes
42
- failed_libraries.each {|e| latest.delete(e) }
43
- save_marshal_index Marshal.dump([Boson.libraries, Boson.commands, latest])
11
+ # Updates all repo indexes.
12
+ def update(options={})
13
+ indexes.each {|e| e.update(options) }
44
14
  end
45
15
 
46
16
  #:stopdoc:
47
- def read_and_transfer(ignored_libraries=[])
48
- read
49
- existing_libraries = (Boson.libraries.map {|e| e.name} + ignored_libraries).uniq
50
- libraries_to_add = @libraries.select {|e| !existing_libraries.include?(e.name)}
51
- Boson.libraries += libraries_to_add
52
- # depends on saved commands being correctly associated with saved libraries
53
- Boson.commands += libraries_to_add.map {|e| e.command_objects(e.commands, @commands) }.flatten
54
- end
55
-
56
- def exists?
57
- File.exists? marshal_file
58
- end
59
-
60
- def save_marshal_index(marshal_string)
61
- File.open(marshal_file, 'w') {|f| f.write marshal_string }
62
- end
63
-
64
- def delete_stale_libraries_and_commands
65
- cached_libraries = @lib_hashes.keys
66
- libs_to_delete = @libraries.select {|e| !cached_libraries.include?(e.name) && e.is_a?(FileLibrary) }
67
- names_to_delete = libs_to_delete.map {|e| e.name }
68
- libs_to_delete.each {|e| @libraries.delete(e) }
69
- @commands.delete_if {|e| names_to_delete.include? e.lib }
17
+ def read
18
+ indexes.each {|e| e.read }
70
19
  end
71
20
 
72
- # set namespaces for commands
73
- def set_command_namespaces
74
- lib_commands = @commands.inject({}) {|t,e| (t[e.lib] ||= []) << e; t }
75
- namespace_libs = @libraries.select {|e| e.namespace(e.indexed_namespace) }
76
- namespace_libs.each {|lib|
77
- (lib_commands[lib.name] || []).each {|e| e.namespace = lib.namespace }
21
+ def find_library(command)
22
+ indexes.each {|e|
23
+ lib = e.find_library(command)
24
+ return lib if lib
78
25
  }
26
+ nil
79
27
  end
80
28
 
81
- def namespaces
82
- nsps = @libraries.map {|e| e.namespace }.compact
83
- nsps.delete(false)
84
- nsps
85
- end
86
-
87
- def all_main_methods
88
- @commands.reject {|e| e.namespace }.map {|e| [e.name, e.alias]}.flatten.compact + namespaces
89
- end
90
-
91
- def marshal_file
92
- File.join(Boson.repo.config_dir, 'index.marshal')
93
- end
94
-
95
- def find_library(command)
96
- read
97
- namespace_command = command.split('.')[0]
98
- if (lib = @libraries.find {|e| e.namespace == namespace_command })
99
- lib.name
100
- elsif (cmd = Command.find(command, @commands))
101
- cmd.lib
102
- end
29
+ def commands
30
+ indexes.map {|e| e.commands}.flatten
103
31
  end
104
32
 
105
- def changed_libraries
106
- read
107
- latest_hashes.select {|lib, hash| @lib_hashes[lib] != hash}.map {|e| e[0]}
33
+ def libraries
34
+ indexes.map {|e| e.libraries}.flatten
108
35
  end
109
36
 
110
- def latest_hashes
111
- Runner.all_libraries.inject({}) {|h, e|
112
- lib_file = FileLibrary.library_file(e, Boson.repo.dir)
113
- h[e] = Digest::MD5.hexdigest(File.read(lib_file)) if File.exists?(lib_file)
114
- h
115
- }
37
+ def all_main_methods
38
+ indexes.map {|e| e.all_main_methods}.flatten
116
39
  end
117
40
  #:startdoc:
118
41
  end
@@ -1,6 +1,28 @@
1
1
  module Boson
2
2
  # Scrapes and processes method attributes with the inspectors (MethodInspector, CommentInspector
3
- # and ArgumentInspector) and hands off the usable data to FileLibrary objects.
3
+ # and ArgumentInspector) and hands off the data to FileLibrary objects.
4
+ #
5
+ # === Method Attributes
6
+ # Method attributes refer to (commented) Module methods placed before a command's method
7
+ # in a FileLibrary module:
8
+ # module SomeMod
9
+ # # @render_options :fields=>%w{one two}
10
+ # # @config :alias=>'so'
11
+ # options :verbose=>:boolean
12
+ # # Something descriptive perhaps
13
+ # def some_method(opts)
14
+ # # ...
15
+ # end
16
+ # end
17
+ #
18
+ # Method attributes serve as configuration for a method's command. Available method attributes:
19
+ # * config: Hash to define any command attributes (see Command.new).
20
+ # * desc: String to define a command's description for a command. Defaults to first commented line above a method.
21
+ # * options: Hash to define an OptionParser object for a command's options.
22
+ # * render_options: Hash to define an OptionParser object for a command's local/global render options (see View).
23
+ #
24
+ # When deciding whether to use commented or normal Module methods, remember that commented Module methods allow
25
+ # independence from Boson (useful for testing). See CommentInspector for more about commented method attributes.
4
26
  module Inspector
5
27
  extend self
6
28
  attr_reader :enabled
@@ -57,7 +79,11 @@ module Boson
57
79
 
58
80
  def add_scraped_data_to_config(key, value, cmd)
59
81
  if value.is_a?(Hash)
60
- @commands_hash[cmd][key] = Util.recursive_hash_merge value, @commands_hash[cmd][key] || {}
82
+ if key == :config
83
+ @commands_hash[cmd] = Util.recursive_hash_merge value, @commands_hash[cmd]
84
+ else
85
+ @commands_hash[cmd][key] = Util.recursive_hash_merge value, @commands_hash[cmd][key] || {}
86
+ end
61
87
  else
62
88
  @commands_hash[cmd][key] ||= value
63
89
  end
@@ -1,25 +1,23 @@
1
1
  module Boson
2
- # Scrapes comments right before a method for its attributes. Metadata attributes are the
3
- # same as MethodInspector : desc, options, render_options. Attributes must begin with '@' i.e.:
4
- #
2
+ # Scrapes comments right before a method for its attributes. Method attributes must begin with '@' i.e.:
5
3
  # # @desc Does foo
6
4
  # # @options :verbose=>true
7
5
  # def foo(options={})
8
6
  #
9
- # Some rules about comment attributes:
10
- # * Attribute definitions can span multiple lines. When a new attribute starts a line or the comments end
7
+ # Some rules about these attributes:
8
+ # * Attribute definitions can span multiple lines. When a new attribute starts a line or the comments end,
11
9
  # then a definition ends.
12
10
  # * If no @desc is found in the comment block, then the first comment line directly above the method
13
11
  # is assumed to be the value for @desc. This means that no multi-line attribute definitions can occur
14
12
  # without a description since the last line is assumed to be a description.
15
- # * options and render_options attributes can take any valid ruby since they're evaled in their module's context.
13
+ # * options, config and render_options attributes can take any valid ruby since they're evaled in their module's context.
16
14
  # * desc attribute is not evaled and is simply text to be set as a string.
17
15
  #
18
16
  # This module was inspired by
19
17
  # {pragdave}[http://github.com/pragdavespc/rake/commit/45231ac094854da9f4f2ac93465ed9b9ca67b2da].
20
18
  module CommentInspector
21
19
  extend self
22
- EVAL_ATTRIBUTES = [:options, :render_options]
20
+ EVAL_ATTRIBUTES = [:options, :render_options, :config]
23
21
 
24
22
  # Given a method's file string, line number and defining module, returns a hash
25
23
  # of attributes defined for that method.
@@ -1,26 +1,13 @@
1
1
  module Boson
2
- # Gathers method attributes with new_method_added and the
3
- # following Module methods:
4
- # * desc: Defines a description for a method/command.
5
- # * options: Defines an OptionParser object for a method's options.
6
- # * render_options: Defines an OptionParser object for a method's rendering options. These options
7
- # are passed to View.render when rendering a command.
8
- #
9
- # These method calls must come immediately before a method i.e.:
10
- #
11
- # desc "Does foo"
12
- # options :verbose=>:boolean
13
- # def foo(options={})
14
- #
15
- # This module also allows for defining method attributes as comments. Although the actual
16
- # scraping of comments is handled by CommentInspector, MethodInspector gather's the method
17
- # location it needs with with find_method_locations().
2
+ # Gathers method attributes by redefining method_added and capturing method
3
+ # calls before a method. This module also saves method locations so CommentInspector
4
+ # can scrape their commented method attributes.
18
5
  module MethodInspector
19
6
  extend self
20
7
  attr_accessor :current_module
21
8
  attr_reader :mod_store
22
9
  @mod_store ||= {}
23
- METHODS = [:desc, :options, :render_options]
10
+ METHODS = [:config, :desc, :options, :render_options]
24
11
 
25
12
  # The method_added used while scraping method attributes.
26
13
  def new_method_added(mod, meth)
@@ -1,12 +1,16 @@
1
1
  module Boson
2
- # This library is based on a file of the same name under the commands directory of a repository.
3
- # Since there can be multiple repositories, a library's file is looked for in the order given by
2
+ # This class loads a file by its path relative to the commands directory of a repository.
3
+ # For example the library 'public/misc' could refer to the file '~/.boson/commands/public/misc.rb'.
4
+ # If a file's basename is unique in its repository, then it can be loaded with its basename i.e. 'misc'
5
+ # for the previous example. When loading a library, this class searches repositories in the order given by
4
6
  # Boson.repos.
5
7
  #
6
- # To create this library, simply create a file with a module and some methods (See Library
7
- # for naming a module). Non-private methods are automatically loaded as a library's commands.
8
+ # === Creating a FileLibrary
9
+ # Start by creating a file with a module and some methods (See Library for naming a module).
10
+ # Non-private methods are automatically loaded as a library's commands.
8
11
  #
9
12
  # Take for example a library brain.rb:
13
+ # # Drop this in ~/.boson/commands/brain.rb
10
14
  # module Brain
11
15
  # def take_over(destination)
12
16
  # puts "Pinky, it's time to take over the #{destination}!"
@@ -32,10 +36,8 @@ module Boson
32
36
  # bash> boson take_over world -e initiate_brainiac
33
37
  # irb>> take_over 'world -e initiate_brainiac'
34
38
  #
35
- # To learn more about the depth of option types available to a command, see OptionParser.
36
- #
37
- # Since boson aims to make your libraries just standard ruby, we can achieve the above
38
- # by placing options in comments above a method:
39
+ # Since Boson aims to make your libraries just standard ruby, we can achieve the above
40
+ # by making options a commented method attribute:
39
41
  # module Brain
40
42
  # # @options :execute=>:string
41
43
  # # Help Brain live the dream
@@ -46,10 +48,9 @@ module Boson
46
48
  # end
47
49
  #
48
50
  # Some points about the above:
49
- # * A '@' must prefix options and other method calls that become comments.
51
+ # * A '@' must prefix options and other method attributes that become comments.
50
52
  # * Note the comment above the method. One-line comments right before a method set a command's description.
51
- # * See MethodInspector for other command attributes, like options, that can be placed above a method.
52
- # * See CommentInspector for the rules about commenting command attributes.
53
+ # * See Inspector for other method attributes, like config and render_options, that can be placed above a method.
53
54
  #
54
55
  # Once a command has a defined option, a command can also recognize a slew of global options:
55
56
  # irb>> take_over '-h'
@@ -58,7 +59,7 @@ module Boson
58
59
  # # prints much more verbose help
59
60
  # irb>> take_over '-hv'
60
61
  #
61
- # For more about these global options see Scientist.
62
+ # For more about these global options see OptionCommand and View.
62
63
  class FileLibrary < Library
63
64
  #:stopdoc:
64
65
  def self.library_file(library, dir)
@@ -75,8 +76,7 @@ module Boson
75
76
 
76
77
  def self.reset_file_cache(name=nil)
77
78
  if name && @file_cache
78
- #td: tia other repos
79
- @file_cache.delete(library_file(name, Boson.repo.dir))
79
+ @file_cache.delete(library_file(name, (matched_repo || Boson.repo).dir))
80
80
  else
81
81
  @file_cache = nil
82
82
  end
@@ -101,14 +101,17 @@ module Boson
101
101
  def set_name(name)
102
102
  @lib_file = File.exists?(library_file(name.to_s)) ? library_file(name.to_s) :
103
103
  Dir[self.class.matched_repo.commands_dir.to_s+'/**/*.rb'].find {|e| e =~ /\/#{name}\.rb$/}
104
- super @lib_file.gsub(/^#{self.class.matched_repo.commands_dir}\/|\.rb$/, '')
104
+ @lib_file.gsub(/^#{self.class.matched_repo.commands_dir}\/|\.rb$/, '')
105
+ end
106
+
107
+ def base_module
108
+ @base_module ||= @name.include?('/') ? create_module_from_path : Commands
105
109
  end
106
110
 
107
111
  def load_source(reload=false)
108
112
  library_string = self.class.read_library_file(@lib_file, reload)
109
- @base_module = @name.include?('/') ? create_module_from_path : Commands
110
113
  Inspector.enable
111
- @base_module.module_eval(library_string, @lib_file)
114
+ base_module.module_eval(library_string, @lib_file)
112
115
  Inspector.disable
113
116
  end
114
117
 
@@ -123,15 +126,7 @@ module Boson
123
126
  detected = detect_additions(:modules=>true) { load_source }
124
127
  @module = determine_lib_module(detected[:modules]) unless @module
125
128
  #without this, module's class methods weren't showing up
126
- @module = Util.constantize(@module) if @base_module != Commands
127
- end
128
-
129
- def reload_source_and_set_module
130
- detected = detect_additions(:modules=>true) { load_source(true) }
131
- if (@new_module = !detected[:modules].empty?)
132
- @commands = []
133
- @module = determine_lib_module(detected[:modules])
134
- end
129
+ @module = Util.constantize(@module) if base_module != Commands
135
130
  end
136
131
 
137
132
  def determine_lib_module(detected_modules)
@@ -140,7 +135,7 @@ module Boson
140
135
  when 0 then raise LoaderError, "Can't detect module. Make sure at least one module is defined in the library."
141
136
  else
142
137
  unless (lib_module = Util.constantize("boson/commands/#{@name}")) && lib_module.to_s[/^Boson::Commands/]
143
- command_modules = detected_modules.map {|e| e.to_s}.grep(/^#{@base_module}::/)
138
+ command_modules = detected_modules.map {|e| e.to_s}.grep(/^#{base_module}::/)
144
139
  unless command_modules.size == 1 && (lib_module = command_modules[0])
145
140
  raise LoaderError, "Can't detect module. Specify a module in this library's config."
146
141
  end