lib/rvc/modules.rb in rvc-1.5.0 vs lib/rvc/modules.rb in rvc-1.6.0

- old
+ new

@@ -17,10 +17,11 @@ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. require 'rvc/util' +require 'shellwords' module RVC ALIASES = {} MODULES = {} @@ -29,31 +30,85 @@ include RVC::Util def initialize module_name @module_name = module_name @opts = {} + @completors = {} super() end def commands @opts.keys end + def has_command? cmd + @opts.member? cmd + end + def opts cmd, &b - @opts[cmd] = b + if cmd.to_s =~ /[A-Z]/ + fail "Camel-casing is not allowed (#{cmd.to_s})" + end + + @opts[cmd] = OptionParser.new cmd.to_s, &b + + @opts[cmd].specs.each do |name,spec| + if name.to_s =~ /[A-Z]/ + fail "Camel-casing is not allowed (#{cmd.to_s} option #{name})" + end + end end + def raw_opts cmd, summary + @opts[cmd] = RawOptionParser.new cmd.to_s, summary + end + def opts_for cmd @opts[cmd] end + def rvc_completor cmd, &b + @completors[cmd] = b + end + + def completor_for cmd + @completors[cmd] + end + def rvc_alias cmd, target=nil target ||= cmd RVC::ALIASES[target.to_s] = "#{@module_name}.#{cmd}" end end +def self.complete_for_cmd line, word + if line == nil + return [] + end + mod, cmd, args = Shell.parse_input line + return [] unless mod != nil + #XXX assumes you aren't going to have any positional arguments with spaces + if(/ $/.match(line)) + argnum = args.size + else + argnum = args.size - 1 + end + + completor = mod.completor_for(cmd.to_sym) + if completor == nil + return [] + end + + candidates = completor.call(line, args, word, argnum) + if candidates == nil + [] + else + prefix_regex = /^#{Regexp.escape word}/ + candidates.select { |x,a| x =~ prefix_regex } + end +end + BULTIN_MODULE_PATH = [File.expand_path(File.join(File.dirname(__FILE__), 'modules')), File.join(ENV['HOME'], ".rvc")] ENV_MODULE_PATH = (ENV['RVC_MODULE_PATH'] || '').split ':' def self.reload_modules verbose=true @@ -63,16 +118,21 @@ module_path = (BULTIN_MODULE_PATH+ENV_MODULE_PATH).select { |d| File.directory?(d) } globs = module_path.map { |d| File.join(d, '*.rb') } Dir.glob(globs) do |f| module_name = File.basename(f)[0...-3] puts "loading #{module_name} from #{f}" if verbose - code = File.read f - unless RVC::MODULES.member? module_name - m = CmdModule.new module_name - CMD.define_singleton_method(module_name.to_sym) { m } - RVC::MODULES[module_name] = m + begin + code = File.read f + unless RVC::MODULES.member? module_name + m = CmdModule.new module_name + CMD.define_singleton_method(module_name.to_sym) { m } + RVC::MODULES[module_name] = m + end + RVC::MODULES[module_name].instance_eval code, f + rescue + puts "#{$!.class} while loading #{f}: #{$!.message}" + $!.backtrace.each { |x| puts x } end - RVC::MODULES[module_name].instance_eval code, f end end end