-
-
Notifications
You must be signed in to change notification settings - Fork 39
/
Copy pathusage.rb
95 lines (78 loc) · 2.76 KB
/
usage.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
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
# frozen_string_literal: true
require "dry/cli/program_name"
module Dry
class CLI
# Command(s) usage
#
# @since 0.1.0
# @api private
module Usage
# @since 0.1.0
# @api private
SUBCOMMAND_BANNER = " [SUBCOMMAND]"
ROOT_COMMAND_WITH_SUBCOMMANDS_BANNER = " [ARGUMENT|SUBCOMMAND]"
# @since 0.1.0
# @api private
def self.call(result)
header = "Commands:"
max_length, commands = commands_and_arguments(result)
commands.map do |banner, node|
usage = description(node.command) if node.leaf?
"#{justify(banner, max_length, usage)}#{usage}"
end.unshift(header).join("\n")
end
# @since 0.1.0
# @api private
def self.commands_and_arguments(result)
max_length = 0
ret = commands(result).each_with_object({}) do |(name, node), memo|
args = arguments(node.command)
args_banner = if node.command && node.leaf? && node.children? && args
ROOT_COMMAND_WITH_SUBCOMMANDS_BANNER
elsif node.leaf? && args
args
elsif node.children?
SUBCOMMAND_BANNER
end
partial = " #{command_name(result, name)}#{args_banner}"
max_length = partial.bytesize if max_length < partial.bytesize
memo[partial] = node
end
[max_length, ret]
end
# @since 0.1.0
# @api private
def self.arguments(command)
return unless CLI.command?(command)
required_arguments = command.required_arguments
optional_arguments = command.optional_arguments
required = required_arguments.map { |arg| arg.name.upcase }.join(" ") if required_arguments.any? # rubocop:disable Layout/LineLength
optional = optional_arguments.map { |arg| "[#{arg.name.upcase}]" }.join(" ") if optional_arguments.any? # rubocop:disable Layout/LineLength
result = [required, optional].compact
" #{result.join(" ")}" unless result.empty?
end
# @since 0.1.0
# @api private
def self.description(command)
return unless CLI.command?(command)
" # #{command.description}" unless command.description.nil?
end
# @since 0.1.0
# @api private
def self.justify(string, padding, usage)
return string.chomp(" ") if usage.nil?
string.ljust(padding + padding / 2)
end
# @since 0.1.0
# @api private
def self.commands(result)
result.children.sort_by { |name, _| name }
end
# @since 0.1.0
# @api private
def self.command_name(result, name)
ProgramName.call([result.names, name])
end
end
end
end