Class: Thor::Runner

Inherits:
Thor
  • Object
show all
Defined in:
lib/thor/runner.rb

Overview

:nodoc:

Constant Summary

Constants inherited from Thor

AmbiguousTaskError, Correctable, DynamicTask, HELP_MAPPINGS, HiddenTask, TEMPLATE_EXTNAME, THOR_RESERVED_WORDS, Task, UndefinedTaskError, VERSION

Instance Attribute Summary

Attributes included from Base

#args, #options, #parent_options

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Thor

check_unknown_options!, check_unknown_options?, command_exists?, command_help, default_command, deprecation_warning, desc, disable_required_check!, disable_required_check?, help, long_desc, map, method_at_least_one, method_exclusive, method_option, method_options, package_name, printable_commands, register, stop_on_unknown_option!, stop_on_unknown_option?, subcommand, subcommand_classes, subcommands

Methods included from Base

included, #initialize, register_klass_file, subclass_files, subclasses

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(meth, *args) ⇒ Object

If a command is not found on Thor::Runner, method missing is invoked and Thor::Runner is then responsible for finding the command in all classes.



35
36
37
38
39
40
41
42
# File 'lib/thor/runner.rb', line 35

def method_missing(meth, *args)
  meth = meth.to_s
  initialize_thorfiles(meth)
  klass, command = Thor::Util.find_class_and_command_by_namespace(meth)
  self.class.handle_no_command_error(command, false) if klass.nil?
  args.unshift(command) if command
  klass.start(args, shell: shell)
end

Class Method Details



11
12
13
# File 'lib/thor/runner.rb', line 11

def self.banner(command, all = false, subcommand = false)
  "thor " + command.formatted_usage(self, all, subcommand)
end

.exit_on_failure?Boolean

Returns:

  • (Boolean)


15
16
17
# File 'lib/thor/runner.rb', line 15

def self.exit_on_failure?
  true
end

Instance Method Details

#help(meth = nil) ⇒ Object

Override Thor#help so it can give information about any class and any method.



21
22
23
24
25
26
27
28
29
30
# File 'lib/thor/runner.rb', line 21

def help(meth = nil)
  if meth && !respond_to?(meth)
    initialize_thorfiles(meth)
    klass, command = Thor::Util.find_class_and_command_by_namespace(meth)
    self.class.handle_no_command_error(command, false) if klass.nil?
    klass.start(["-h", command].compact, shell: shell)
  else
    super
  end
end

#install(name) ⇒ Object

rubocop:disable Metrics/MethodLength



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/thor/runner.rb', line 46

def install(name) # rubocop:disable Metrics/MethodLength
  initialize_thorfiles

  is_uri  = name =~ %r{^https?\://}

  if is_uri
    base = name
    package = :file
    require "open-uri"
    begin
      contents = URI.open(name, &:read)
    rescue OpenURI::HTTPError
      raise Error, "Error opening URI '#{name}'"
    end
  else
    # If a directory name is provided as the argument, look for a 'main.thor'
    # command in said directory.
    begin
      if File.directory?(File.expand_path(name))
        base = File.join(name, "main.thor")
        package = :directory
        contents = File.open(base, &:read)
      else
        base = name
        package = :file
        require "open-uri"
        contents = URI.open(name, &:read)
      end
    rescue Errno::ENOENT
      raise Error, "Error opening file '#{name}'"
    end
  end

  say "Your Thorfile contains:"
  say contents

  unless options["force"]
    return false if no?("Do you wish to continue [y/N]?")
  end

  as = options["as"] || begin
    first_line = contents.split("\n")[0]
    (match = first_line.match(/\s*#\s*module:\s*([^\n]*)/)) ? match[1].strip : nil
  end

  unless as
    basename = File.basename(name)
    as = ask("Please specify a name for #{name} in the system repository [#{basename}]:")
    as = basename if as.empty?
  end

  location = if options[:relative] || is_uri
    name
  else
    File.expand_path(name)
  end

  thor_yaml[as] = {
    filename: Digest::SHA256.hexdigest(name + as),
    location: location,
    namespaces: Thor::Util.namespaces_in_content(contents, base)
  }

  save_yaml(thor_yaml)
  say "Storing thor file in your system repository"
  destination = File.join(thor_root, thor_yaml[as][:filename])

  if package == :file
    File.open(destination, "w") { |f| f.puts contents }
  else
    require "fileutils"
    FileUtils.cp_r(name, destination)
  end

  thor_yaml[as][:filename] # Indicate success
end

#installedObject



168
169
170
171
# File 'lib/thor/runner.rb', line 168

def installed
  initialize_thorfiles(nil, true)
  display_klasses(true, options["internal"])
end

#list(search = "") ⇒ Object



175
176
177
178
179
180
181
182
183
184
185
186
187
# File 'lib/thor/runner.rb', line 175

def list(search = "")
  initialize_thorfiles

  search = ".*#{search}" if options["substring"]
  search = /^#{search}.*/i
  group  = options[:group] || "standard"

  klasses = Thor::Base.subclasses.select do |k|
    (options[:all] || k.group == group) && k.namespace =~ search
  end

  display_klasses(false, false, klasses)
end

#uninstall(name) ⇒ Object

Raises:



130
131
132
133
134
135
136
137
138
139
140
# File 'lib/thor/runner.rb', line 130

def uninstall(name)
  raise Error, "Can't find module '#{name}'" unless thor_yaml[name]
  say "Uninstalling #{name}."
  require "fileutils"
  FileUtils.rm_rf(File.join(thor_root, (thor_yaml[name][:filename]).to_s))

  thor_yaml.delete(name)
  save_yaml(thor_yaml)

  puts "Done."
end

#update(name) ⇒ Object

Raises:



143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/thor/runner.rb', line 143

def update(name)
  raise Error, "Can't find module '#{name}'" if !thor_yaml[name] || !thor_yaml[name][:location]

  say "Updating '#{name}' from #{thor_yaml[name][:location]}"

  old_filename = thor_yaml[name][:filename]
  self.options = options.merge("as" => name)

  if File.directory? File.expand_path(name)
    require "fileutils"
    FileUtils.rm_rf(File.join(thor_root, old_filename))

    thor_yaml.delete(old_filename)
    save_yaml(thor_yaml)

    filename = install(name)
  else
    filename = install(thor_yaml[name][:location])
  end

  File.delete(File.join(thor_root, old_filename)) unless filename == old_filename
end

#versionObject



124
125
126
127
# File 'lib/thor/runner.rb', line 124

def version
  require_relative "version"
  say "Thor #{Thor::VERSION}"
end