hammer_cli 0.0.8 → 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
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