hammer_cli 0.0.8 → 0.0.9

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f94cb081ad874612f32639ed07cdf5626fb69ba4
4
+ data.tar.gz: 479cf176ac7bb522702489eb0205286ea0a98bf4
5
+ SHA512:
6
+ metadata.gz: 5a52be94f2ad2519e8eff5737b4f1fafbefb247db4fc49a6be931f0129f4a12fae8641e086ab4f0b9cca8bef691db8a5a6035c43e94afb7cb1c6ef0da7504403
7
+ data.tar.gz: b97b952d02e88eb7541ea041d61b32cfe5374200a1d59ba6d24a38f8f3e58289b598606a075863ba58501f038c61547ce0b669e42befa81ea1b074d914c2ceec
@@ -1,5 +1,5 @@
1
- Hammer Developer Docs
2
- =====================
1
+ Hammer Development Docs
2
+ =======================
3
3
 
4
4
  Hammer is a generic clamp-based CLI framework. It uses existing clamp features and adds some extra utilities.
5
5
  We recommend to get familiar with the [Clamp documentation](https://github.com/mdub/clamp/#quick-start)
@@ -253,29 +253,50 @@ end
253
253
 
254
254
  ```
255
255
 
256
- #### Option formatters
257
- Another option-related feature is a set of formatters for specific option types:
256
+ #### Option normalizers
257
+ Another option-related feature is a set of normalizers for specific option types. They validate and preprocess
258
+ option values. Each normalizer has a description of the format it accepts. This description is printed
259
+ in commands' help.
258
260
 
259
- * _HammerCLI::OptionFormatters.list_
261
+ ##### _List_
260
262
 
261
263
  Parses comma separated strings to a list of values.
262
264
 
263
- Usage:
264
265
  ```ruby
265
- option "--users", "USER_NAMES", "List of user names", &HammerCLI::OptionFormatters.method(:list)
266
+ option "--users", "USER_NAMES", "List of user names",
267
+ :format => HammerCLI::Options::Normalizers::List.new
266
268
  ```
267
269
  `--users='J.R.,Gary,Bobby'` -> `['J.R.', 'Gary', 'Bobby']`
268
270
 
269
- * _HammerCLI::OptionFormatters.file_
271
+ ##### _File_
270
272
 
271
273
  Loads contents of a file and returns it as a value of the option.
272
274
 
273
- Usage:
274
275
  ```ruby
275
- option "--poem", "PATH_TO_POEM", "File containing the text of your poem", &HammerCLI::OptionFormatters.method(:file)
276
+ option "--poem", "PATH_TO_POEM", "File containing the text of your poem",
277
+ :format => HammerCLI::Options::Normalizers::File.new
276
278
  ```
277
279
  `--poem=~/verlaine/les_poetes_maudits.txt` -> content of the file
278
280
 
281
+ ##### _Bool_
282
+
283
+ Case insensitive true/false values. Translates _yes,y,true,t,1_ to `true` and _no,n,false,f,0_ to `false`.
284
+
285
+ ```ruby
286
+ option "--start", "START", "Start the action",
287
+ :format => HammerCLI::Options::Normalizers::Bool.new
288
+ ```
289
+ `--start=yes` -> `true`
290
+
291
+ ##### _KeyValueList_
292
+
293
+ Parses a comma separated list of key=value pairs. Can be used for naming attributes with vague structure.
294
+
295
+ ```ruby
296
+ option "--attributes", "ATTRIBUTES", "Values of various attributes",
297
+ :format => HammerCLI::Options::Normalizers::KeyValueList.new
298
+ ```
299
+ `--attributes="material=unoptanium,thickness=3"` -> `{'material' => 'unoptanium', 'thickness' => '3'}`
279
300
 
280
301
  ### Adding subcommands
281
302
  Commands in the cli can be structured into a tree of parent commands (nodes) and subcommands (leaves).
@@ -441,35 +462,40 @@ Imagine there's an API of some service that returns list of users:
441
462
 
442
463
  We can create an output definition that selects and formats some of the fields:
443
464
  ```ruby
444
- dsl = HammerCLI::Output::Dsl.new
445
- dsl.build do
465
+ class Command < HammerCLI::AbstractCommand
446
466
 
447
- # Simple field with a label. The first parameter is key in the printed hash.
448
- field :id, 'ID'
467
+ output do
468
+ # Simple field with a label. The first parameter is key in the printed hash.
469
+ field :id, 'ID'
449
470
 
450
- # Fields can have types. The type determines how the field is printed.
451
- # All available types are listed below.
452
- # Here we want the roles to act as list.
453
- field :roles, 'System Roles', Fields::List
471
+ # Fields can have types. The type determines how the field is printed.
472
+ # All available types are listed below.
473
+ # Here we want the roles to act as list.
474
+ field :roles, 'System Roles', Fields::List
454
475
 
455
- # Label is used for grouping fields.
456
- label 'Contacts' do
457
- field :email, 'Email'
458
- field :phone, 'Phone No.'
459
- end
476
+ # Label is used for grouping fields.
477
+ label 'Contacts' do
478
+ field :email, 'Email'
479
+ field :phone, 'Phone No.'
480
+ end
460
481
 
461
- # From is used for accessing nested fields.
462
- from :timestamps do
463
- # See how date gets formatted in the output
464
- field :created, 'Created At', Fields::Date
482
+ # From is used for accessing nested fields.
483
+ from :timestamps do
484
+ # See how date gets formatted in the output
485
+ field :created, 'Created At', Fields::Date
486
+ end
465
487
  end
466
- end
467
488
 
468
- definition = HammerCLI::Output::Definition.new
469
- definition.append(dsl.fields)
470
-
471
- print_records(definition, data)
489
+ def execute
490
+ records = retrieve_data
491
+ print_records( # <- printing utility of AbstractCommand
492
+ output_definition, # <- method for accessing fields defined in the block 'output'
493
+ records # <- the data to print
494
+ )
495
+ return HammerCLI::EX_OK
496
+ end
472
497
 
498
+ end
473
499
  ```
474
500
 
475
501
  Using the base adapter the output will look like:
@@ -491,6 +517,21 @@ Contacts:
491
517
  Created At: 2012/12/18 15:25:00
492
518
  ```
493
519
 
520
+ You can optionally use output definition from another command as a base and extend it with
521
+ additional fields. This is helpful when there are two commands, one listing brief data and
522
+ another one showing details. Typically it's list and show.
523
+ ```ruby
524
+ class ShowCommand < HammerCLI::AbstractCommand
525
+
526
+ output ListCommand.output_definition do
527
+ # additional fields
528
+ end
529
+
530
+ # ...
531
+ end
532
+ ```
533
+
534
+
494
535
  All Hammer field types are:
495
536
  * __Date__
496
537
  * __Id__ - Used to mark ID values, current print adapters have support for turning id printing on/off.
@@ -593,21 +634,300 @@ HammerCLI::Settings.get(:hello_world, :name) # get a nested value
593
634
  There's more ways where to place your config file for hammer.
594
635
  Read more in [the settings howto](https://github.com/theforeman/hammer-cli#configuration).
595
636
 
637
+
596
638
  Creating commands for RESTful API with ApiPie
597
639
  ---------------------------------------------
598
- Coming soon...
640
+
641
+ CLIs binded to a rest api do simillar things for most of the resources. Typically it's
642
+ CRUD actions that appear for nearly every resource. Actions differ with parameters
643
+ accross resources but the operations remain the same.
644
+
645
+ Hammer is optimised for usage with [ApiPie](https://github.com/Pajk/apipie-rails)
646
+ and generated api bindings and tries to reduce the effort neccessary for a command creation.
599
647
 
600
648
 
601
- <!--
602
- - this part is valid for foreman
603
- - what is apipie
604
- - apipie bindings
605
- - apipie, read and write commands
606
- - define ids a resources
607
- - apipie support, apipie_options
608
- -->
649
+ ### ApiPie and bindings
609
650
 
651
+ [ApiPie](https://github.com/Pajk/apipie-rails) is a documentation library for RESTful APIs.
652
+ Unlike traditional tools ApiPie uses DSL for api description. This brings many advantages. See its
653
+ documentation for details.
654
+
655
+ Foreman comes with [ruby bindings](https://github.com/theforeman/foreman_api) automatically generated
656
+ from the information provided by ApiPie. Every resource (eg. Architecture, User) has it's own
657
+ class with methods for each available action (eg. create, show, index, destroy).
658
+ Apart from that it contains also full api documentation with parameters for the actions.
659
+ This enables to reuse the documentation on client side for automatic option definition
660
+ and reduce the amount of custom code per CLI action.
661
+
662
+
663
+ ### ApiPie commands in Hammer
664
+
665
+ Hammer identifies two basic types of ApiPie commands:
666
+
667
+ - __ReadCommand__
668
+ - should be used for actions that print records
669
+ - retrieves the data and prints them in given format (uses output definition)
670
+ - typical actions in rails terminology: _index, show_
671
+
672
+ - __WriteCommand__
673
+ - should used for actions that modify records
674
+ - sends modifying request and prints the result
675
+ - typical actions in rails terminology: _create, update, destroy_
676
+
677
+ Both command classes are single resource related and expect the resource and an action to be defined.
678
+ There's a simple DSL for that:
679
+
680
+ ```ruby
681
+ class ListCommand < HammerCLI::Apipie::ReadCommand
682
+ # define resource and the action together
683
+ resource ForemanApi::Resources::Architecture, :index
684
+ end
610
685
 
686
+ # or
687
+
688
+ class ListCommand2 < HammerCLI::Apipie::ReadCommand
689
+ # define them separately
690
+ resource ForemanApi::Resources::Architecture
691
+ action :index
692
+ end
693
+ ```
694
+
695
+ #### Options definition
696
+
697
+ When the resource-action pair is defined we can take the advantage of automatic option definition.
698
+ There's a class method `apipie_options` for this purpose.
699
+
700
+ ```ruby
701
+ class ListCommand < HammerCLI::Apipie::ReadCommand
702
+ resource ForemanApi::Resources::Architecture, :index
703
+
704
+ apipie_options
705
+ end
706
+ ```
707
+
708
+ If we plug the command into an existing command tree and check the help we will see there
709
+ are four parameters defined from the ApiPie docs. Compare the result with
710
+ [online api documentation](http://www.theforeman.org/api/apidoc/architectures/index.html).
711
+ ```
712
+ $ hammer architecture list -h
713
+ Usage:
714
+ hammer architecture list [OPTIONS]
715
+
716
+ Options:
717
+ --search SEARCH filter results
718
+ --order ORDER sort results
719
+ --page PAGE paginate results
720
+ --per-page PER_PAGE number of entries per request
721
+ -h, --help print help
722
+ ```
723
+
724
+ It is possible to combine apipie options with custom ones. If the generated options
725
+ doesn't suit your needs for any reason, you can always skip and redefine them by hand.
726
+ See following example.
727
+ ```ruby
728
+ class ListCommand < HammerCLI::Apipie::ReadCommand
729
+ resource ForemanApi::Resources::Architecture, :index
730
+
731
+ apipie_options :without => [:search, :order]
732
+ option '--search', 'QUERY', "search query"
733
+ end
734
+ ```
735
+
736
+ ```
737
+ hammer architecture list -h
738
+ Usage:
739
+ hammer architecture list [OPTIONS]
740
+
741
+ Options:
742
+ --page PAGE paginate results
743
+ --per-page PER_PAGE number of entries per request
744
+ --search QUERY search query
745
+ -h, --help print help
746
+ ```
747
+ Note that the `--search` description has changed and `--order` disappeared.
748
+
749
+ Automatic options reflect:
750
+ - parameter names and descriptions
751
+ - required parameters
752
+ - parameter types - the only supported type is array, which is translated to option normalizer `List`
753
+
754
+ #### Write commands
755
+
756
+ Write commands are expected to print result of the api action. There are
757
+ two class methods for setting success and failure messages. Messages are
758
+ printed according to the http status code the api returned.
759
+
760
+ ```ruby
761
+ success_message "The user has been created"
762
+ failure_message "Could not create the user"
763
+ ```
764
+
765
+
766
+ #### Example 1: Create an architecture
767
+
768
+ ```ruby
769
+ class CreateCommand < HammerCLI::Apipie::WriteCommand
770
+ command_name "create"
771
+ resource ForemanApi::Resources::Architecture, :create
611
772
 
773
+ success_message "Architecture created"
774
+ failure_message "Could not create the architecture"
612
775
 
776
+ apipie_options
777
+ end
778
+ ```
779
+
780
+ ```
781
+ $ hammer architecture create -h
782
+ Usage:
783
+ hammer architecture create [OPTIONS]
784
+
785
+ Options:
786
+ --name NAME
787
+ --operatingsystem-ids OPERATINGSYSTEM_IDS Operatingsystem ID’s
788
+ Comma separated list of values.
789
+ -h, --help print help
790
+ ```
791
+
792
+ ```
793
+ $ hammer architecture create
794
+ ERROR: option '--name' is required
795
+
796
+ See: 'hammer architecture create --help'
797
+ ```
798
+
799
+ ```
800
+ $ hammer architecture create --name test --operatingsystem-ids=1,2
801
+ Architecture created
802
+ ```
803
+
804
+ ```
805
+ $ hammer architecture create --name test
806
+ Could not create the architecture:
807
+ Name has already been taken
808
+ ```
809
+
810
+
811
+ #### Example 2: Show an architecture
812
+
813
+ ```ruby
814
+ class InfoCommand < HammerCLI::Apipie::ReadCommand
815
+ command_name "info"
816
+ resource ForemanApi::Resources::Architecture, :show
817
+
818
+ # It's a good practice to reuse output definition from list commands
819
+ # and add more details. It helps avoiding duplicities.
820
+ output ListCommand.output_definition do
821
+ from "architecture" do
822
+ field :operatingsystem_ids, "OS ids", Fields::List
823
+ field :created_at, "Created at", Fields::Date
824
+ field :updated_at, "Updated at", Fields::Date
825
+ end
826
+ end
827
+
828
+ apipie_options
829
+ end
830
+ ```
831
+
832
+ ```
833
+ $ hammer architecture info -h
834
+ Usage:
835
+ hammer architecture info [OPTIONS]
836
+
837
+ Options:
838
+ --id ID
839
+ -h, --help print help
840
+ ```
841
+
842
+ ```
843
+ $ hammer architecture info --id 1
844
+ Id: 1
845
+ Name: x86_64
846
+ OS ids: 1, 3
847
+ Created at: 2013/06/08 18:53:56
848
+ Updated at: 2013/06/08 19:17:43
849
+ ```
850
+
851
+
852
+ #### Tips
853
+
854
+ When you define more command like we've shown above you find yourself repeating
855
+ `resource ...` in every one of them. As the commands are usually grouped by
856
+ the resource it is handy to extract the resource definition one level up to
857
+ the encapsulating command.
858
+
859
+ ```ruby
860
+ class Architecture < HammerCLI::Apipie::Command
861
+
862
+ resource ForemanApi::Resources::Architecture
863
+
864
+ class ListCommand < HammerCLI::Apipie::ReadCommand
865
+ action :index
866
+ # ...
867
+ end
868
+
869
+
870
+ class InfoCommand < HammerCLI::Apipie::ReadCommand
871
+ action :show
872
+ # ...
873
+ end
874
+
875
+ # ...
876
+ end
877
+ ```
878
+
879
+ ApiPie resources are being looked up in the encapsulating classes and modules
880
+ when the definition is missing in the command class. If they are not found even there
881
+ the resource of the parent command is used at runtime. This is useful for context-aware
882
+ shared commands.
883
+
884
+ The following example shows a common subcommand that can be attached to
885
+ any parent of which resource implements method `add_tag`. Please note that this example
886
+ is fictitious. There's no tags in Foreman's architectures and users.
887
+ ```ruby
888
+ module Tags
889
+ class AddTag < HammerCLI::Apipie::WriteCommand
890
+ option '--id', 'ID', 'ID of the resource'
891
+ option '--tag', 'TAG', 'Name of the tag to add'
892
+ action :add_tag
893
+ command_name 'add_tag'
894
+ end
895
+ end
896
+
897
+ class Architecture < HammerCLI::Apipie::Command
898
+ resource ForemanApi::Resources::Architecture
899
+ # ...
900
+ include Tags
901
+ autoload_subcommands
902
+ end
903
+
904
+ class User < HammerCLI::Apipie::Command
905
+ resource ForemanApi::Resources::User
906
+ # ...
907
+ include Tags
908
+ autoload_subcommands
909
+ end
910
+ ```
911
+
912
+ ```
913
+ $ hammer architecture add_tag -h
914
+ Usage:
915
+ hammer architecture add_tag [OPTIONS]
916
+
917
+ Options:
918
+ --id ID ID of the resource
919
+ --tag TAG Name of the tag to add
920
+ -h, --help print help
921
+ ```
922
+
923
+ ```
924
+ $ hammer user add_tag -h
925
+ Usage:
926
+ hammer user add_tag [OPTIONS]
927
+
928
+ Options:
929
+ --id ID ID of the resource
930
+ --tag TAG Name of the tag to add
931
+ -h, --help print help
932
+ ```
613
933
 
@@ -1,6 +1,7 @@
1
1
  require 'hammer_cli/autocompletion'
2
2
  require 'hammer_cli/exception_handler'
3
3
  require 'hammer_cli/logger_watch'
4
+ require 'hammer_cli/options/option_definition'
4
5
  require 'clamp'
5
6
  require 'logging'
6
7
 
@@ -85,6 +86,23 @@ module HammerCLI
85
86
  super
86
87
  end
87
88
 
89
+ def self.output(definition=nil, &block)
90
+ dsl = HammerCLI::Output::Dsl.new
91
+ dsl.build &block if block_given?
92
+
93
+ output_definition.append definition.fields unless definition.nil?
94
+ output_definition.append dsl.fields
95
+ end
96
+
97
+ def output_definition
98
+ self.class.output_definition
99
+ end
100
+
101
+ def self.output_definition
102
+ @output_definition ||= HammerCLI::Output::Definition.new
103
+ @output_definition
104
+ end
105
+
88
106
  protected
89
107
 
90
108
  def print_records(definition, records)
@@ -139,6 +157,19 @@ module HammerCLI
139
157
  end
140
158
  end
141
159
 
160
+ def self.option(switches, type, description, opts = {}, &block)
161
+ formatter = opts.delete(:format)
162
+
163
+ HammerCLI::Options::OptionDefinition.new(switches, type, description, opts).tap do |option|
164
+ declared_options << option
165
+
166
+ option.value_formatter = formatter
167
+ block ||= option.default_conversion_block
168
+
169
+ define_accessors_for(option, &block)
170
+ end
171
+ end
172
+
142
173
  def all_options
143
174
  self.class.recognised_options.inject({}) do |h, opt|
144
175
  h[opt.attribute_name] = send(opt.read_method)
@@ -9,8 +9,8 @@ module HammerCLI::Apipie
9
9
  include HammerCLI::Apipie::Options
10
10
 
11
11
  def initialize(*args)
12
+ super
12
13
  setup_identifier_options
13
- super(*args)
14
14
  end
15
15
 
16
16
  def setup_identifier_options
@@ -32,7 +32,9 @@ module HammerCLI::Apipie
32
32
 
33
33
  def validate_options
34
34
  super
35
- validator.any(*self.class.declared_identifiers.values).required
35
+ if self.class.declared_identifiers
36
+ validator.any(*self.class.declared_identifiers.values).required
37
+ end
36
38
  end
37
39
 
38
40
  def self.desc(desc=nil)
@@ -1,4 +1,3 @@
1
- require 'hammer_cli/option_formatters'
2
1
 
3
2
  module HammerCLI::Apipie
4
3
  module Options
@@ -59,8 +58,7 @@ module HammerCLI::Apipie
59
58
  option_switches(param),
60
59
  option_type(param),
61
60
  option_desc(param),
62
- option_opts(param),
63
- &option_formatter(param)
61
+ option_opts(param)
64
62
  )
65
63
  end
66
64
 
@@ -81,15 +79,10 @@ module HammerCLI::Apipie
81
79
  def option_opts(param)
82
80
  opts = {}
83
81
  opts[:required] = true if param["required"]
84
- return opts
85
- end
86
-
87
- def option_formatter(param)
88
82
  # FIXME: There is a bug in apipie, it does not produce correct expected type for Arrays
89
83
  # When it's fixed, we should test param["expected_type"] == "array"
90
- if param["validator"].include? "Array"
91
- HammerCLI::OptionFormatters.method(:list)
92
- end
84
+ opts[:format] = HammerCLI::Options::Normalizers::List.new if param["validator"].include? "Array"
85
+ return opts
93
86
  end
94
87
 
95
88
  end
@@ -4,23 +4,6 @@ module HammerCLI::Apipie
4
4
 
5
5
  class ReadCommand < Command
6
6
 
7
- def self.output(definition=nil, &block)
8
- dsl = HammerCLI::Output::Dsl.new
9
- dsl.build &block if block_given?
10
-
11
- output_definition.append definition.fields unless definition.nil?
12
- output_definition.append dsl.fields
13
- end
14
-
15
- def output_definition
16
- self.class.output_definition
17
- end
18
-
19
- def self.output_definition
20
- @output_definition ||= HammerCLI::Output::Definition.new
21
- @output_definition
22
- end
23
-
24
7
  def execute
25
8
  d = retrieve_data
26
9
  logger.watch "Retrieved data: ", d
@@ -16,7 +16,7 @@ module HammerCLI::Apipie
16
16
  resource_class.doc["methods"].each do |method|
17
17
  return method if method["name"] == method_name.to_s
18
18
  end
19
- raise "No method documentation found for #{resource_class}##{action}"
19
+ raise "No method documentation found for #{resource_class}##{method_name}"
20
20
  end
21
21
 
22
22
  end
@@ -20,7 +20,6 @@ module HammerCLI::Apipie
20
20
  end
21
21
 
22
22
  def send_request
23
- raise "resource or action not defined" unless self.class.resource_defined?
24
23
  resource.call(action, request_params)[0]
25
24
  end
26
25
 
@@ -0,0 +1,76 @@
1
+ module HammerCLI
2
+ module Options
3
+ module Normalizers
4
+
5
+
6
+ class AbstractNormalizer
7
+ def description
8
+ ""
9
+ end
10
+
11
+ def format(val)
12
+ raise NotImplementedError, "Class #{self.class.name} must implement method format."
13
+ end
14
+ end
15
+
16
+
17
+ class KeyValueList < AbstractNormalizer
18
+
19
+ def description
20
+ "Comma-separated list of key=value."
21
+ end
22
+
23
+ def format(val)
24
+ return {} unless val.is_a?(String)
25
+
26
+ val.split(",").inject({}) do |result, item|
27
+ parts = item.split("=")
28
+ if parts.size != 2
29
+ raise ArgumentError, "value must be defined as a comma-separated list of key=value"
30
+ end
31
+ result.update(parts[0] => parts[1])
32
+ end
33
+ end
34
+ end
35
+
36
+
37
+ class List < AbstractNormalizer
38
+
39
+ def description
40
+ "Comma separated list of values."
41
+ end
42
+
43
+ def format(val)
44
+ val.is_a?(String) ? val.split(",") : []
45
+ end
46
+ end
47
+
48
+
49
+ class Bool < AbstractNormalizer
50
+
51
+ def description
52
+ "One of true/false, yes/no, 1/0."
53
+ end
54
+
55
+ def format(bool)
56
+ if bool.downcase.match(/^(true|t|yes|y|1)$/i)
57
+ return true
58
+ elsif bool.downcase.match(/^(false|f|no|n|0)$/i)
59
+ return false
60
+ else
61
+ raise ArgumentError, "value must be one of true/false, yes/no, 1/0"
62
+ end
63
+ end
64
+ end
65
+
66
+
67
+ class File < AbstractNormalizer
68
+
69
+ def format(path)
70
+ ::File.read(::File.expand_path(path))
71
+ end
72
+ end
73
+
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,68 @@
1
+ require 'clamp'
2
+
3
+ module HammerCLI
4
+ module Options
5
+
6
+ class OptionDefinition < Clamp::Option::Definition
7
+
8
+ attr_accessor :value_formatter
9
+
10
+ def help_lhs
11
+ super
12
+ end
13
+
14
+ def help_rhs
15
+ lines = [
16
+ description.strip,
17
+ format_description.strip,
18
+ value_description.strip
19
+ ]
20
+
21
+ rhs = lines.reject(&:empty?).join("\n")
22
+ rhs.empty? ? " " : rhs
23
+ end
24
+
25
+ def format_description
26
+ if value_formatter.nil?
27
+ ""
28
+ else
29
+ value_formatter.description
30
+ end
31
+ end
32
+
33
+ def value_description
34
+ default_sources = [
35
+ ("$#{@environment_variable}" if defined?(@environment_variable)),
36
+ (@default_value.inspect if defined?(@default_value))
37
+ ].compact
38
+
39
+ str = ""
40
+ str += "Can be specified multiple times. " if multivalued?
41
+ str += "Default: " + default_sources.join(", or ") unless default_sources.empty?
42
+ str
43
+ end
44
+
45
+ def default_conversion_block
46
+ if !value_formatter.nil?
47
+ value_formatter.method(:format)
48
+ elsif flag?
49
+ Clamp.method(:truthy?)
50
+ end
51
+ end
52
+
53
+ def default_value
54
+ if defined?(@default_value)
55
+ if value_formatter
56
+ value_formatter.format(@default_value)
57
+ else
58
+ @default_value
59
+ end
60
+ elsif multivalued?
61
+ []
62
+ end
63
+ end
64
+
65
+ end
66
+
67
+ end
68
+ end
@@ -24,6 +24,8 @@ module HammerCLI::Output::Adapter
24
24
  end
25
25
 
26
26
  printer = TablePrint::Printer.new(rows, options)
27
+ TablePrint::Config.max_width = 40
28
+
27
29
  output = printer.table_print
28
30
  dashes = /\n([-|]+)\n/.match(output)
29
31
 
@@ -1,5 +1,5 @@
1
1
  module HammerCLI
2
2
  def self.version
3
- @version ||= Gem::Version.new '0.0.8'
3
+ @version ||= Gem::Version.new '0.0.9'
4
4
  end
5
5
  end
data/lib/hammer_cli.rb CHANGED
@@ -3,6 +3,7 @@ require 'hammer_cli/exit_codes'
3
3
  require 'hammer_cli/settings'
4
4
  require 'hammer_cli/validator'
5
5
  require 'hammer_cli/output'
6
+ require 'hammer_cli/options/normalizers'
6
7
  require 'hammer_cli/abstract'
7
8
  require 'hammer_cli/main'
8
9
 
metadata CHANGED
@@ -1,8 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hammer_cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.8
5
- prerelease:
4
+ version: 0.0.9
6
5
  platform: ruby
7
6
  authors:
8
7
  - Martin Bačovský
@@ -10,107 +9,94 @@ authors:
10
9
  autorequire:
11
10
  bindir: bin
12
11
  cert_chain: []
13
- date: 2013-10-29 00:00:00.000000000 Z
12
+ date: 2013-11-08 00:00:00.000000000 Z
14
13
  dependencies:
15
14
  - !ruby/object:Gem::Dependency
16
15
  name: clamp
17
16
  requirement: !ruby/object:Gem::Requirement
18
- none: false
19
17
  requirements:
20
- - - ! '>='
18
+ - - '>='
21
19
  - !ruby/object:Gem::Version
22
20
  version: '0'
23
21
  type: :runtime
24
22
  prerelease: false
25
23
  version_requirements: !ruby/object:Gem::Requirement
26
- none: false
27
24
  requirements:
28
- - - ! '>='
25
+ - - '>='
29
26
  - !ruby/object:Gem::Version
30
27
  version: '0'
31
28
  - !ruby/object:Gem::Dependency
32
29
  name: rest-client
33
30
  requirement: !ruby/object:Gem::Requirement
34
- none: false
35
31
  requirements:
36
- - - ! '>='
32
+ - - '>='
37
33
  - !ruby/object:Gem::Version
38
34
  version: '0'
39
35
  type: :runtime
40
36
  prerelease: false
41
37
  version_requirements: !ruby/object:Gem::Requirement
42
- none: false
43
38
  requirements:
44
- - - ! '>='
39
+ - - '>='
45
40
  - !ruby/object:Gem::Version
46
41
  version: '0'
47
42
  - !ruby/object:Gem::Dependency
48
43
  name: logging
49
44
  requirement: !ruby/object:Gem::Requirement
50
- none: false
51
45
  requirements:
52
- - - ! '>='
46
+ - - '>='
53
47
  - !ruby/object:Gem::Version
54
48
  version: '0'
55
49
  type: :runtime
56
50
  prerelease: false
57
51
  version_requirements: !ruby/object:Gem::Requirement
58
- none: false
59
52
  requirements:
60
- - - ! '>='
53
+ - - '>='
61
54
  - !ruby/object:Gem::Version
62
55
  version: '0'
63
56
  - !ruby/object:Gem::Dependency
64
57
  name: awesome_print
65
58
  requirement: !ruby/object:Gem::Requirement
66
- none: false
67
59
  requirements:
68
- - - ! '>='
60
+ - - '>='
69
61
  - !ruby/object:Gem::Version
70
62
  version: '0'
71
63
  type: :runtime
72
64
  prerelease: false
73
65
  version_requirements: !ruby/object:Gem::Requirement
74
- none: false
75
66
  requirements:
76
- - - ! '>='
67
+ - - '>='
77
68
  - !ruby/object:Gem::Version
78
69
  version: '0'
79
70
  - !ruby/object:Gem::Dependency
80
71
  name: table_print
81
72
  requirement: !ruby/object:Gem::Requirement
82
- none: false
83
73
  requirements:
84
- - - ! '>='
74
+ - - '>='
85
75
  - !ruby/object:Gem::Version
86
76
  version: '0'
87
77
  type: :runtime
88
78
  prerelease: false
89
79
  version_requirements: !ruby/object:Gem::Requirement
90
- none: false
91
80
  requirements:
92
- - - ! '>='
81
+ - - '>='
93
82
  - !ruby/object:Gem::Version
94
83
  version: '0'
95
84
  - !ruby/object:Gem::Dependency
96
85
  name: highline
97
86
  requirement: !ruby/object:Gem::Requirement
98
- none: false
99
87
  requirements:
100
- - - ! '>='
88
+ - - '>='
101
89
  - !ruby/object:Gem::Version
102
90
  version: '0'
103
91
  type: :runtime
104
92
  prerelease: false
105
93
  version_requirements: !ruby/object:Gem::Requirement
106
- none: false
107
94
  requirements:
108
- - - ! '>='
95
+ - - '>='
109
96
  - !ruby/object:Gem::Version
110
97
  version: '0'
111
- description: ! 'Hammer cli provides universal extendable CLI interface for ruby apps
112
-
113
- '
98
+ description: |
99
+ Hammer cli provides universal extendable CLI interface for ruby apps
114
100
  email: mbacovsk@redhat.com
115
101
  executables:
116
102
  - hammer
@@ -120,74 +106,74 @@ extra_rdoc_files:
120
106
  - LICENSE
121
107
  - hammer_cli_complete
122
108
  - config/cli_config.template.yml
109
+ - doc/developer_docs.md
123
110
  - doc/design.png
124
111
  - doc/design.uml
125
- - doc/developer_docs.md
126
112
  files:
127
- - lib/hammer_cli.rb
113
+ - lib/hammer_cli/logger_watch.rb
114
+ - lib/hammer_cli/apipie/write_command.rb
115
+ - lib/hammer_cli/apipie/resource.rb
116
+ - lib/hammer_cli/apipie/read_command.rb
117
+ - lib/hammer_cli/apipie/options.rb
118
+ - lib/hammer_cli/apipie/command.rb
119
+ - lib/hammer_cli/logger.rb
128
120
  - lib/hammer_cli/messages.rb
129
- - lib/hammer_cli/output/fields.rb
130
- - lib/hammer_cli/output/formatters.rb
121
+ - lib/hammer_cli/abstract.rb
122
+ - lib/hammer_cli/apipie.rb
123
+ - lib/hammer_cli/version.rb
124
+ - lib/hammer_cli/exception_handler.rb
125
+ - lib/hammer_cli/output.rb
126
+ - lib/hammer_cli/autocompletion.rb
127
+ - lib/hammer_cli/shell.rb
131
128
  - lib/hammer_cli/output/adapter/table.rb
132
129
  - lib/hammer_cli/output/adapter/base.rb
133
130
  - lib/hammer_cli/output/adapter/abstract.rb
134
131
  - lib/hammer_cli/output/adapter/silent.rb
135
132
  - lib/hammer_cli/output/adapter/csv.rb
133
+ - lib/hammer_cli/output/definition.rb
136
134
  - lib/hammer_cli/output/adapter.rb
137
- - lib/hammer_cli/output/output.rb
138
135
  - lib/hammer_cli/output/dsl.rb
139
- - lib/hammer_cli/output/definition.rb
140
- - lib/hammer_cli/abstract.rb
141
- - lib/hammer_cli/shell.rb
142
- - lib/hammer_cli/autocompletion.rb
143
- - lib/hammer_cli/logger_watch.rb
144
- - lib/hammer_cli/logger.rb
145
- - lib/hammer_cli/apipie.rb
146
- - lib/hammer_cli/apipie/command.rb
147
- - lib/hammer_cli/apipie/options.rb
148
- - lib/hammer_cli/apipie/resource.rb
149
- - lib/hammer_cli/apipie/write_command.rb
150
- - lib/hammer_cli/apipie/read_command.rb
136
+ - lib/hammer_cli/output/formatters.rb
137
+ - lib/hammer_cli/output/output.rb
138
+ - lib/hammer_cli/output/fields.rb
139
+ - lib/hammer_cli/options/option_definition.rb
140
+ - lib/hammer_cli/options/normalizers.rb
141
+ - lib/hammer_cli/settings.rb
151
142
  - lib/hammer_cli/validator.rb
152
- - lib/hammer_cli/version.rb
153
143
  - lib/hammer_cli/exit_codes.rb
154
- - lib/hammer_cli/output.rb
155
- - lib/hammer_cli/exception_handler.rb
156
144
  - lib/hammer_cli/main.rb
157
- - lib/hammer_cli/option_formatters.rb
158
- - lib/hammer_cli/settings.rb
145
+ - lib/hammer_cli.rb
159
146
  - bin/hammer
160
147
  - README.md
161
148
  - LICENSE
162
149
  - hammer_cli_complete
163
150
  - config/cli_config.template.yml
151
+ - doc/developer_docs.md
164
152
  - doc/design.png
165
153
  - doc/design.uml
166
- - doc/developer_docs.md
167
154
  homepage: http://github.com/theforeman/hammer-cli
168
155
  licenses:
169
156
  - GPL-3
157
+ metadata: {}
170
158
  post_install_message:
171
159
  rdoc_options: []
172
160
  require_paths:
173
161
  - lib
174
162
  required_ruby_version: !ruby/object:Gem::Requirement
175
- none: false
176
163
  requirements:
177
- - - ! '>='
164
+ - - '>='
178
165
  - !ruby/object:Gem::Version
179
166
  version: '0'
180
167
  required_rubygems_version: !ruby/object:Gem::Requirement
181
- none: false
182
168
  requirements:
183
- - - ! '>='
169
+ - - '>='
184
170
  - !ruby/object:Gem::Version
185
171
  version: '0'
186
172
  requirements: []
187
173
  rubyforge_project:
188
- rubygems_version: 1.8.24
174
+ rubygems_version: 2.0.8
189
175
  signing_key:
190
- specification_version: 3
176
+ specification_version: 4
191
177
  summary: Universal command-line interface
192
178
  test_files: []
193
179
  has_rdoc:
@@ -1,13 +0,0 @@
1
- module HammerCLI
2
- module OptionFormatters
3
-
4
- def self.list(val)
5
- val.is_a?(String) ? val.split(",") : []
6
- end
7
-
8
- def self.file(path)
9
- File.read(File.expand_path(path))
10
- end
11
-
12
- end
13
- end