Class: DenCli::Sub

Inherits:
Object
  • Object
show all
Defined in:
lib/dencli/sub.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(parent, name, description, noshortaliases: nil, defined_in: nil) ⇒ Sub

Returns a new instance of Sub.



6
7
8
9
10
11
12
# File 'lib/dencli/sub.rb', line 6

def initialize parent, name, description, noshortaliases: nil, defined_in: nil
  #DenCli::assert_type self, __method__, :name, name, Symbol
  #DenCli::assert_type self, __method__, :parent, parent, DenCli, DenCli::Sub
  #DenCli::assert_type self, __method__, :description, description, String
  @parent, @name, @description, @subs, @aliases = parent, name, "-> #{description}", {}, {}
  @noshortaliases, @defined_in = ! ! noshortaliases, defined_in || Kernel.caller
end

Instance Attribute Details

#aliasesObject (readonly)

Returns the value of attribute aliases.



4
5
6
# File 'lib/dencli/sub.rb', line 4

def aliases
  @aliases
end

#defined_inObject (readonly)

Returns the value of attribute defined_in.



4
5
6
# File 'lib/dencli/sub.rb', line 4

def defined_in
  @defined_in
end

#descriptionObject (readonly)

Returns the value of attribute description.



4
5
6
# File 'lib/dencli/sub.rb', line 4

def description
  @description
end

#nameObject (readonly)

Returns the value of attribute name.



4
5
6
# File 'lib/dencli/sub.rb', line 4

def name
  @name
end

#parentObject (readonly)

Returns the value of attribute parent.



4
5
6
# File 'lib/dencli/sub.rb', line 4

def parent
  @parent
end

#subsObject (readonly)

Returns the value of attribute subs.



4
5
6
# File 'lib/dencli/sub.rb', line 4

def subs
  @subs
end

Class Method Details

._help_commands(output, subs) ⇒ Object



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
# File 'lib/dencli/sub.rb', line 64

def _help_commands output, subs
  m = subs.map {|_name,c| x = c.usage.length; 25 < x ? 0 : x }.max
  subs.each do |_name, c|
    if 25 < c.usage.length
      output << "% -#{m}s\n#{' ' * m} " % [c.usage]
    else
      output << "% -#{m}s " % [c.usage]
    end
    n = m+2
    prefix = nil
    c.description.split( /\n/).each do |l|
      c = 0
      l.split( %r< >).each do |w|
        if prefix
          output << prefix
          prefix = nil
        end
        wl = w.length
        if 75 < c+wl
          output << "\n#{' ' * n}#{w}"
          c = n+2+wl
        else
          output << " #{w}"
          c += 1 + wl
        end
      end
      prefix = "\n#{' ' * n}"
    end
    output << "\n"
  end
  output
end

Instance Method Details

#[](name) ⇒ Object



16
# File 'lib/dencli/sub.rb', line 16

def []( name) @aliases[name&.to_s] end

#_full_cmd(post) ⇒ Object



14
# File 'lib/dencli/sub.rb', line 14

def _full_cmd( post) parent._full_cmd [@name]+post end

#_help(output, n = nil, *a) ⇒ Object



41
42
43
44
45
46
47
48
49
50
# File 'lib/dencli/sub.rb', line 41

def _help output, n = nil, *a
  if n.nil?
    output << "#{full_cmd.join ' '}: #{description}\n\n"
    self.class._help_commands output, @subs
  elsif has? n
    self[n]._help output, *a
  else
    raise DenCli::UnknownCommand, "unknown command: #{_full_cmd( [n])[1..-1].join ' '}, available for #{full_cmd[1..-1].join' '}: #{@subs.keys.join ' '}"
  end
end

#_usage(output) ⇒ Object



26
27
28
29
30
31
32
33
# File 'lib/dencli/sub.rb', line 26

def _usage output
  output << full_cmd.join( ' ')
  if @aliases.has_key? nil
    output << " [<command> ...]"
  else
    output << " <command> [...]"
  end
end

#call(*a) ⇒ Object



108
109
110
111
112
113
114
115
# File 'lib/dencli/sub.rb', line 108

def call *a
  n, *a = *a
  if has? n
    self[n].call *a
  else
    raise DenCli::UnknownCommand, "unknown command: #{_full_cmd( [n])[1..-1].join ' '}, available for #{full_cmd[1..-1].join' '}: #{@subs.keys.join ' '}"
  end
end

#cmd(name, description, min: nil, aliases: nil, defined_in: nil, &exe) ⇒ Object

Define a new command:

DenCli.new {|c|
c.cmd( :hello, 'Greetings', &lambda {|| puts 'hello world' })
}

# ./prog hello
hello world

name should be a string/symbol. It will be converted to string. If provided, aliases must be a list of different aliases. Except of nil, any alias will be converted to string. nil is an alias for a default command for sub-commands, but interactive shells.

DenCli.new {|c|
c.sub( :greetings, 'Hello, Welcome, ...') do |s|
  s.cmd( :hello, 'A simple Hello', aliases: %w[hello-world hello_world], &lambda {|| puts 'Hello World' })
  s.cmd( :welcome, 'More gracefull', aliases: [nil, 'welcome-world', :hello_world], &lambda {|| puts 'Welcome World' })
}
}

# ./prog greetings
Welcome World
# ./prog greetings welcome
Welcome World
# ./prog greetings hello
Hello World


187
188
189
# File 'lib/dencli/sub.rb', line 187

def cmd name, description, min: nil, aliases: nil, defined_in: nil, &exe
  _add name, min, DenCli::CMD.new( self, name, description, exe, defined_in || Kernel.caller.first), aliases
end

#commands {|name, _self| ... } ⇒ Object

Yields:

Yield Parameters:

  • _self (DenCli::Sub)

    the object that the method was called on



52
53
54
55
# File 'lib/dencli/sub.rb', line 52

def commands &exe
  yield name, self
  @subs.each {|k, c| c.commands &exe }
end

#complete(*pre, str) ⇒ Object



191
192
193
194
195
196
197
198
199
# File 'lib/dencli/sub.rb', line 191

def complete *pre, str
  if pre.empty?
    @subs.keys.grep /\A#{Regexp.escape str}/
  elsif sub = @subs[pre[0]]
    sub.complete *pre[1..-1], str
  else
    $stdout.print "\a"
  end
end

#full_cmdObject



15
# File 'lib/dencli/sub.rb', line 15

def full_cmd() _full_cmd [] end

#goto(*a) ⇒ Object



98
99
100
101
102
103
104
105
106
# File 'lib/dencli/sub.rb', line 98

def goto *a
  return self  if a.empty?
  n, *a = *a
  if has? n
    self[n].goto *a
  else
    raise DenCli::UnknownCommand, "unknown command: #{_full_cmd( [n])[1..-1].join ' '}, available for #{full_cmd[1..-1].join' '}: #{@subs.keys.join ' '}"
  end
end

#has?(name) ⇒ Boolean

Returns:



17
# File 'lib/dencli/sub.rb', line 17

def has?( name) @aliases.has_key? name&.to_s end

#help(n = nil, *a, output: nil) ⇒ Object



35
36
37
38
39
# File 'lib/dencli/sub.rb', line 35

def help n = nil, *a, output: nil
  output ||= ''
  _help output, n, *a
  output
end

#help_commands(output: nil) ⇒ Object



57
58
59
60
61
# File 'lib/dencli/sub.rb', line 57

def help_commands output: nil
  output ||= ''
  self.class._help_commands output, subs.map {|_,c| c}
  output
end

#inspectObject



201
202
203
204
205
206
# File 'lib/dencli/sub.rb', line 201

def inspect
  "#<%s:0x%x %s @name=%p @description=%p @subs={%s} @aliases={%s} @parent=<%s:0x%x %s>>" % [
    self.class.name, self.object_id, self.full_cmd,
    @name, @description, @subs.keys.join(', '), @aliases.keys.join(', '), @parent.class.name, @parent.class.object_id, @parent.full_cmd
  ]
end

#sub(name, description, min: nil, aliases: nil, noshortaliases: nil, defined_in: nil, &exe) ⇒ Object

Define a new sub-menu:

DenCli.new {|c|
c.sub( 'sub-command') {|s|
  s.cmd( :hello, 'Greetings', &lambda {|| puts 'hello world' })
}
}

# ./prog sub-command hello

name should be a string/symbol. It will be converted to string. If provided, aliases must be a list of different aliases. It will be converted to string.



156
157
158
159
# File 'lib/dencli/sub.rb', line 156

def sub name, description, min: nil, aliases: nil, noshortaliases: nil, defined_in: nil, &exe
  r = _add name.to_s, min, DenCli::Sub.new( self, name, description, noshortaliases: noshortaliases, defined_in: defined_in || Kernel.caller.first), aliases
  block_given? ? yield( r) : r
end

#usage(output: nil) ⇒ Object



20
21
22
23
24
# File 'lib/dencli/sub.rb', line 20

def usage output: nil
  output ||= ''
  _usage output
  output
end