arborist 0.2.0.pre20170519125456 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/ChangeLog +670 -1
  5. data/History.md +67 -0
  6. data/Manifest.txt +9 -6
  7. data/README.md +1 -3
  8. data/Rakefile +39 -4
  9. data/TODO.md +22 -31
  10. data/lib/arborist.rb +9 -2
  11. data/lib/arborist/cli.rb +67 -85
  12. data/lib/arborist/client.rb +125 -59
  13. data/lib/arborist/command/ack.rb +86 -0
  14. data/lib/arborist/command/reset.rb +48 -0
  15. data/lib/arborist/command/start.rb +11 -1
  16. data/lib/arborist/command/summary.rb +173 -0
  17. data/lib/arborist/command/tree.rb +215 -0
  18. data/lib/arborist/command/watch.rb +22 -22
  19. data/lib/arborist/dependency.rb +24 -4
  20. data/lib/arborist/event.rb +18 -2
  21. data/lib/arborist/event/node.rb +6 -2
  22. data/lib/arborist/event/node_warn.rb +16 -0
  23. data/lib/arborist/manager.rb +179 -48
  24. data/lib/arborist/mixins.rb +11 -0
  25. data/lib/arborist/monitor.rb +29 -17
  26. data/lib/arborist/monitor/connection_batching.rb +293 -0
  27. data/lib/arborist/monitor/socket.rb +101 -167
  28. data/lib/arborist/monitor_runner.rb +101 -24
  29. data/lib/arborist/node.rb +297 -68
  30. data/lib/arborist/node/ack.rb +1 -1
  31. data/lib/arborist/node/host.rb +26 -5
  32. data/lib/arborist/node/resource.rb +14 -5
  33. data/lib/arborist/node/root.rb +12 -3
  34. data/lib/arborist/node/service.rb +29 -26
  35. data/lib/arborist/node_subscription.rb +65 -0
  36. data/lib/arborist/observer.rb +8 -0
  37. data/lib/arborist/observer/action.rb +6 -0
  38. data/lib/arborist/subscription.rb +22 -16
  39. data/lib/arborist/tree_api.rb +7 -2
  40. data/spec/arborist/client_spec.rb +157 -51
  41. data/spec/arborist/dependency_spec.rb +21 -0
  42. data/spec/arborist/event/node_spec.rb +5 -0
  43. data/spec/arborist/event_spec.rb +3 -3
  44. data/spec/arborist/manager_spec.rb +626 -347
  45. data/spec/arborist/mixins_spec.rb +19 -0
  46. data/spec/arborist/monitor/socket_spec.rb +1 -2
  47. data/spec/arborist/monitor_runner_spec.rb +81 -29
  48. data/spec/arborist/monitor_spec.rb +89 -14
  49. data/spec/arborist/node/host_spec.rb +68 -0
  50. data/spec/arborist/node/resource_spec.rb +2 -0
  51. data/spec/arborist/node/root_spec.rb +13 -0
  52. data/spec/arborist/node/service_spec.rb +9 -0
  53. data/spec/arborist/node_spec.rb +673 -111
  54. data/spec/arborist/node_subscription_spec.rb +54 -0
  55. data/spec/arborist/observer/action_spec.rb +6 -0
  56. data/spec/arborist/observer_runner_spec.rb +8 -1
  57. data/spec/arborist/tree_api_spec.rb +111 -8
  58. data/spec/data/monitors/pings.rb +0 -11
  59. data/spec/data/monitors/port_checks.rb +0 -9
  60. data/spec/data/nodes/sidonie.rb +1 -0
  61. data/spec/data/nodes/vhosts.rb +23 -0
  62. data/spec/data/nodes/yevaud.rb +4 -2
  63. data/spec/spec_helper.rb +71 -1
  64. metadata +91 -28
  65. metadata.gz.sig +0 -0
  66. data/Events.md +0 -35
  67. data/Monitors.md +0 -155
  68. data/Nodes.md +0 -70
  69. data/Observers.md +0 -72
  70. data/Protocol.md +0 -276
  71. data/Tutorial.md +0 -8
data/History.md CHANGED
@@ -1,3 +1,70 @@
1
+ ## v0.2.0 [2018-08-08] Michael Granger <ged@FaerieMUD.org>
2
+
3
+ Breaking:
4
+
5
+ - Collapse startup event into the heartbeat event
6
+ - Rename some actions in the Tree API for clarity
7
+ * Rename `list` to `fetch`
8
+ * Rename `fetch` to `search`
9
+ - Don't let #add_node automatically replace nodes with the same
10
+ identifier, instead leaving the remove step to the caller.
11
+
12
+ Enhancements:
13
+
14
+ - Add acknowledgement changes to delta events.
15
+ - Add batching to the socket monitor
16
+ - Add a --path argument to the 'tree' command, that displays parents
17
+ to the root when specified.
18
+ - Add a DSL method for returning a Client singleton.
19
+ - Provide a way to disable colors for misbehaving terms.
20
+ - Allow ack/unack on the root node to quiet and re-enable the tree.
21
+ - Retain the previous time a node's status changed, for easy time
22
+ deltas between state transitions.
23
+ - Add the node type as additional metadata to node events.
24
+ - Add node parent to the default node event class, stick to symbols
25
+ for hash keys.
26
+ - Allow "OR-ing" of statuses/identifiers/types when matching.
27
+ - Make the default node search return all nodes
28
+ All nodes in the tree are returned by default now. You can omit
29
+ unreachable nodes with the `exclude_down` option/method.
30
+ - Add a warning state to nodes
31
+ - Add an optional 'hostname' label to the host node DSL.
32
+ This is a convenience matcher for selecting by host, since
33
+ identifiers are designed to be opaque, and description fields are
34
+ more human readable.
35
+ - Add a configurable default splay for all instantiated Monitors.
36
+ - Allow separate monitors to run in parallel.
37
+ - Make ack friendlier for batch updates, prompt for missing values.
38
+ - Add a 'summary' command, for quick display of existing problems.
39
+ - Use the uid instead of gecos for default ack sender.
40
+ - Add a "reset" command to the client.
41
+ - Add wildcard matching to node events.
42
+ - Add introspection on secondary dependencies to the Tree API
43
+ - Add an `ack` command
44
+ - Convert to CZTop for ZeroMQ
45
+ - Add a block to Node.parent_type to allow for more-expressive
46
+ declarations
47
+ - Normalize and emit better error messages from client commands.
48
+
49
+ Bugfixes:
50
+
51
+ - Fix behavior for child nodes whose parent transitions from 'down' to
52
+ 'warn'.
53
+ - Don't make loading config conditional, so loading config path from
54
+ ENV works as intended.
55
+ - Propagate ack and unack events to parent nodes.
56
+ - Keep the observer daemon running if observer action blocks raise
57
+ exceptions.
58
+ - Throw a client error if attempting to graft over a pre-existing node.
59
+ - Re-arrange constants to avoid Ruby 2.4 refinement warnings. Lower
60
+ debug output when loading nodes.
61
+ - Fix the signature of Arborist::Client#fetch
62
+ It was defaulting trailing-hash arguments to options, which made the
63
+ typical case of fetching with only criteria awkward. This makes the
64
+ atypical case (fetching with options but empty criteria) the awkward
65
+ case instead.
66
+
67
+
1
68
  # v0.1.0 [2017-01-01] Michael Granger <ged@FaerieMUD.org>
2
69
 
3
70
  Initial release.
@@ -1,24 +1,22 @@
1
1
  .document
2
2
  .simplecov
3
3
  ChangeLog
4
- Events.md
5
4
  History.md
6
5
  Manifest.txt
7
- Monitors.md
8
- Nodes.md
9
- Observers.md
10
- Protocol.md
11
6
  README.md
12
7
  Rakefile
13
8
  TODO.md
14
- Tutorial.md
15
9
  bin/arborist
16
10
  lib/arborist.rb
17
11
  lib/arborist/cli.rb
18
12
  lib/arborist/client.rb
13
+ lib/arborist/command/ack.rb
19
14
  lib/arborist/command/client.rb
20
15
  lib/arborist/command/config.rb
16
+ lib/arborist/command/reset.rb
21
17
  lib/arborist/command/start.rb
18
+ lib/arborist/command/summary.rb
19
+ lib/arborist/command/tree.rb
22
20
  lib/arborist/command/watch.rb
23
21
  lib/arborist/dependency.rb
24
22
  lib/arborist/event.rb
@@ -31,6 +29,7 @@ lib/arborist/event/node_quieted.rb
31
29
  lib/arborist/event/node_unknown.rb
32
30
  lib/arborist/event/node_up.rb
33
31
  lib/arborist/event/node_update.rb
32
+ lib/arborist/event/node_warn.rb
34
33
  lib/arborist/event_api.rb
35
34
  lib/arborist/exceptions.rb
36
35
  lib/arborist/loader.rb
@@ -38,6 +37,7 @@ lib/arborist/loader/file.rb
38
37
  lib/arborist/manager.rb
39
38
  lib/arborist/mixins.rb
40
39
  lib/arborist/monitor.rb
40
+ lib/arborist/monitor/connection_batching.rb
41
41
  lib/arborist/monitor/socket.rb
42
42
  lib/arborist/monitor_runner.rb
43
43
  lib/arborist/node.rb
@@ -46,6 +46,7 @@ lib/arborist/node/host.rb
46
46
  lib/arborist/node/resource.rb
47
47
  lib/arborist/node/root.rb
48
48
  lib/arborist/node/service.rb
49
+ lib/arborist/node_subscription.rb
49
50
  lib/arborist/observer.rb
50
51
  lib/arborist/observer/action.rb
51
52
  lib/arborist/observer/summarize.rb
@@ -71,6 +72,7 @@ spec/arborist/node/resource_spec.rb
71
72
  spec/arborist/node/root_spec.rb
72
73
  spec/arborist/node/service_spec.rb
73
74
  spec/arborist/node_spec.rb
75
+ spec/arborist/node_subscription_spec.rb
74
76
  spec/arborist/observer/action_spec.rb
75
77
  spec/arborist/observer/summarize_spec.rb
76
78
  spec/arborist/observer_runner_spec.rb
@@ -85,6 +87,7 @@ spec/data/monitors/web_services.rb
85
87
  spec/data/nodes/localhost.rb
86
88
  spec/data/nodes/sidonie.rb
87
89
  spec/data/nodes/sub/duir.rb
90
+ spec/data/nodes/vhosts.rb
88
91
  spec/data/nodes/yevaud.rb
89
92
  spec/data/observers/auditor.rb
90
93
  spec/data/observers/webservices.rb
data/README.md CHANGED
@@ -19,8 +19,6 @@ Arborist is a monitoring toolkit that follows the UNIX philosophy
19
19
  of small parts and loose coupling for stability, reliability, and
20
20
  customizability.
21
21
 
22
- [![Build Status](https://semaphoreci.com/api/v1/projects/13677b60-5f81-4e6e-a9c6-e21d30daa4ca/461532/badge.svg)](https://semaphoreci.com/ged/arborist)
23
-
24
22
 
25
23
  ## Prerequisites
26
24
 
@@ -51,7 +49,7 @@ and generate the API documentation.
51
49
 
52
50
  ## License
53
51
 
54
- Copyright (c) 2015-2016, Michael Granger and Mahlon E. Smith
52
+ Copyright (c) 2015-2018, Michael Granger and Mahlon E. Smith
55
53
  All rights reserved.
56
54
 
57
55
  Redistribution and use in source and binary forms, with or without
data/Rakefile CHANGED
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env rake
2
2
 
3
+ require 'pathname'
3
4
  require 'rake/clean'
4
5
 
5
6
  begin
@@ -10,6 +11,10 @@ end
10
11
 
11
12
  GEMSPEC = 'arborist.gemspec'
12
13
 
14
+ BASEDIR = Pathname( __FILE__ ).dirname
15
+ LIBDIR = BASEDIR + 'lib'
16
+ NODE_STATE_GRAPH = BASEDIR + 'node-state-machine.dot'
17
+
13
18
 
14
19
  Hoe.plugin :mercurial
15
20
  Hoe.plugin :signing
@@ -37,17 +42,22 @@ hoespec = Hoe.spec 'arborist' do |spec|
37
42
  spec.dependency 'loggability', '~> 0.12'
38
43
  spec.dependency 'configurability', '~> 3.0'
39
44
  spec.dependency 'pluggability', '~> 0.4'
40
- spec.dependency 'state_machines', '~> 0.2'
45
+ spec.dependency 'state_machines', '~> 0.5'
41
46
  spec.dependency 'msgpack', '~> 1.0'
42
47
  spec.dependency 'cztop', '~> 0.11'
43
48
  spec.dependency 'cztop-reactor', '~> 0.3'
44
49
  spec.dependency 'gli', '~> 2.3'
45
- spec.dependency 'highline', '~> 1.7'
50
+ spec.dependency 'tty', '~> 0.7'
51
+ spec.dependency 'tty-tree', '~> 0.1'
52
+ spec.dependency 'pry', '~> 0.11'
46
53
 
47
54
  spec.dependency 'rspec', '~> 3.2', :developer
48
55
  spec.dependency 'rspec-wait', '~> 0.0', :developer
49
56
  spec.dependency 'simplecov', '~> 0.9', :developer
50
57
  spec.dependency 'timecop', '~> 0.7', :developer
58
+ spec.dependency 'rdoc', '~> 5.1', :developer
59
+ spec.dependency 'rdoc', '~> 5.1', :developer
60
+ spec.dependency 'state_machines-graphviz', '~> 0.0', :developer
51
61
 
52
62
  spec.require_ruby_version( '>=2.3.1' )
53
63
  spec.hg_sign_tags = true if spec.respond_to?( :hg_sign_tags= )
@@ -86,14 +96,16 @@ if File.directory?( '.hg' )
86
96
  end
87
97
  end
88
98
 
89
- task :gemspec => [ 'ChangeLog', __FILE__, GEMSPEC ]
99
+ file 'Manifest.txt'
100
+
101
+ task :gemspec => [ 'ChangeLog', __FILE__, 'Manifest.txt', GEMSPEC ]
90
102
  file GEMSPEC => __FILE__ do |task|
91
103
  spec = $hoespec.spec
92
104
  spec.files.delete( '.gemtest' )
93
105
  spec.files.delete( 'LICENSE' )
94
106
  spec.signing_key = nil
95
107
  spec.version = "#{spec.version.bump}.0.pre#{Time.now.strftime("%Y%m%d%H%M%S")}"
96
- spec.cert_chain = [ 'certs/ged.pem' ]
108
+ #spec.cert_chain = [ 'certs/ged.pem' ]
97
109
  File.open( task.name, 'w' ) do |fh|
98
110
  fh.write( spec.to_ruby )
99
111
  end
@@ -102,3 +114,26 @@ CLOBBER.include( GEMSPEC )
102
114
 
103
115
  task :default => :gemspec
104
116
 
117
+
118
+ file NODE_STATE_GRAPH
119
+
120
+ desc "Generate a graph of the node status state machine."
121
+ task NODE_STATE_GRAPH do |task|
122
+ $LOAD_PATH.unshift( LIBDIR.to_s )
123
+
124
+ require 'state_machines'
125
+ require 'state_machines/graphviz'
126
+ require 'arborist/node'
127
+
128
+ state_machine = Arborist::Node.state_machine
129
+ name = File.basename( NODE_STATE_GRAPH, '.dot' )
130
+ puts "Writing status state machine diagram to #{NODE_STATE_GRAPH}"
131
+ graph = state_machine.draw( path: BASEDIR.to_s, name: name, format: 'dot' )
132
+ # graph.output
133
+ end
134
+
135
+ CLEAN.include( NODE_STATE_GRAPH.to_s )
136
+
137
+
138
+ task :diagrams => [ NODE_STATE_GRAPH ]
139
+
data/TODO.md CHANGED
@@ -1,52 +1,43 @@
1
1
  # To-Do
2
2
 
3
- ## First Release (0.1)
3
+ ## Third Release (0.3)
4
4
 
5
- * README, Tutorial, Setup docs
6
- * Performance/profiling examination
5
+ ### Command line
7
6
 
7
+ * Add a 'lint' check, to provide warnings for common misconfigurations
8
+ * Host nodes without any addresses attached
8
9
 
9
- ### Monitor
10
+ ### Setup/Installation
10
11
 
11
- * Add some default monitor types and utilities
12
- - ftp
13
- - imap
14
- - pop
15
- - smtp
12
+ * Add a CLI for generating a basic setup and then adding nodes/monitors/observers to it.
16
13
 
17
- * Redo the select loop of the UDP socket monitor to wait for them in parallel instead of in series.
14
+ ### Manager
18
15
 
16
+ * Potential federation / referral for sibling managers
17
+ * Add optional authentication support (ZAUTH)
19
18
 
20
- ## Second Release (0.2)
21
19
 
22
- ### Setup/Installation
20
+ ### Nodes
23
21
 
24
- * Add a CLI for generating a basic setup and then adding nodes/monitors/observers to it.
25
- * Potential federation / referral for sibling managers
22
+ * Allow 'address' host DSL to accept multiple addresses in one call
23
+ * Allow disabling an ACKed node (kschies)
26
24
 
27
- ### Nodes
28
25
 
29
- * Ask a node (via tree-api or otherwise) what nodes it affects (immediate children, secondary dependents)
26
+ ### Observers
30
27
 
31
- * Clarify the Tree API:
32
-
33
- - Rename `list` to `fetch`
34
- - Return identified node `node.to_h`
35
- - Return identified node and its children in a hierarchy `node.to_h(true)`
36
- - Return identified node and its children as a flattened list
37
-
38
- - Rename `fetch` to `search`
39
- - returns list of nodes which satisfy positive/negative criteria
28
+ * Action dependencies -- as an example, if an action sends an email, don't trigger if the email service is offline. Potential action "chains", ie: If the email service is down, use a separate out-of-band action that sends SMS.
40
29
 
30
+ * Flapping state detection
41
31
 
42
- ### Observers
43
32
 
44
- * Action dependencies -- as an example, if an action sends an email,
45
- don't trigger if the email service is offline. Potential action
46
- "chains", ie: If the email service is down, use a separate
47
- out-of-band action that sends SMS.
48
33
 
49
34
  ### Monitors
50
35
 
51
- Add a one-shot runner command for development of monitors. Loads and runs a monitor one time, maybe with some output describing how often it'd run, what its skew is, etc. [will@laika]
36
+ * Add a one-shot runner command for development of monitors. Loads and runs a monitor one time, maybe with some output describing how often it'd run, what its skew is, etc. [will@laika]
37
+
38
+ * Add some default monitor types and utilities
39
+ - ftp
40
+ - imap
41
+ - pop
42
+ - smtp
52
43
 
@@ -14,10 +14,10 @@ module Arborist
14
14
  Configurability
15
15
 
16
16
  # Package version
17
- VERSION = '0.1.0'
17
+ VERSION = '0.2.0'
18
18
 
19
19
  # Version control revision
20
- REVISION = %q$Revision: 17a8567d86e2 $
20
+ REVISION = %q$Revision: b7725c5136bc $
21
21
 
22
22
 
23
23
  # The name of the environment variable which can be used to set the config path
@@ -137,6 +137,12 @@ module Arborist
137
137
  end
138
138
 
139
139
 
140
+ ### Return a new Arborist::Client.
141
+ def self::client
142
+ return Arborist::Client.new
143
+ end
144
+
145
+
140
146
  ### Load all node and event types
141
147
  def self::load_all
142
148
  Arborist::Node.load_all
@@ -156,6 +162,7 @@ module Arborist
156
162
  autoload :Observer, 'arborist/observer'
157
163
  autoload :ObserverRunner, 'arborist/observer_runner'
158
164
  autoload :Subscription, 'arborist/subscription'
165
+ autoload :NodeSubscription, 'arborist/node_subscription'
159
166
 
160
167
  end # module Arborist
161
168
 
@@ -2,7 +2,8 @@
2
2
  #encoding: utf-8
3
3
 
4
4
  require 'loggability'
5
- require 'highline'
5
+ require 'tty/prompt'
6
+ require 'pastel'
6
7
  require 'gli'
7
8
 
8
9
  require 'arborist' unless defined?( Arborist )
@@ -20,18 +21,6 @@ module Arborist::CLI
20
21
  log_to :arborist
21
22
 
22
23
 
23
- # Make a HighLine color scheme
24
- COLOR_SCHEME = HighLine::ColorScheme.new do |scheme|
25
- scheme[:header] = [ :bold, :yellow ]
26
- scheme[:subheader] = [ :bold, :white ]
27
- scheme[:key] = [ :white ]
28
- scheme[:value] = [ :bold, :white ]
29
- scheme[:error] = [ :red ]
30
- scheme[:warning] = [ :yellow ]
31
- scheme[:message] = [ :reset ]
32
- end
33
-
34
-
35
24
  #
36
25
  # GLI
37
26
  #
@@ -79,6 +68,9 @@ module Arborist::CLI
79
68
  desc "Don't actually do anything, just show what would happen."
80
69
  switch [:n, 'dry-run']
81
70
 
71
+ desc "Enable ANSI colors."
72
+ switch :color, default_value: true
73
+
82
74
  desc "Additional Ruby libs to require before doing anything."
83
75
  flag [:r, 'requires'], type: Array
84
76
 
@@ -97,9 +89,9 @@ module Arborist::CLI
97
89
  self.require_additional_libs( global[:r] ) if global[:r]
98
90
  self.load_config( global )
99
91
  self.set_logging_level( global[:l] ) if global[:l] # again; override config file
100
- self.install_highline_colorscheme
101
92
 
102
93
  self.setup_output( global )
94
+ self.setup_pastel_aliases
103
95
 
104
96
  true
105
97
  end
@@ -126,10 +118,6 @@ module Arborist::CLI
126
118
  # Registered subcommand modules
127
119
  singleton_attr_accessor :subcommand_modules
128
120
 
129
- ##
130
- # The IO opened to the output file
131
- singleton_attr_accessor :outfile
132
-
133
121
 
134
122
  ### Overridden -- Add registered subcommands immediately before running.
135
123
  def self::run( * )
@@ -159,17 +147,17 @@ module Arborist::CLI
159
147
  end
160
148
 
161
149
 
162
- ### Return the HighLine prompt used by the command to communicate with the
163
- ### user.
164
- def self::prompt
165
- @prompt ||= HighLine.new( $stdin, $stderr )
150
+ ### Return the Pastel colorizer.
151
+ ###
152
+ def self::pastel
153
+ @pastel ||= Pastel.new( enabled: $stdout.tty? && $COLOR )
166
154
  end
167
155
 
168
156
 
169
- ### If the command's output was redirected to a file, return the open File object
170
- ### for it.
171
- def self::outfile
172
- return @outfile
157
+ ### Return the TTY prompt used by the command to communicate with the
158
+ ### user.
159
+ def self::prompt
160
+ @prompt ||= TTY::Prompt.new
173
161
  end
174
162
 
175
163
 
@@ -199,31 +187,31 @@ module Arborist::CLI
199
187
  end
200
188
 
201
189
 
202
- ### Install the color scheme used by HighLine
203
- def self::install_highline_colorscheme
204
- HighLine.color_scheme = HighLine::ColorScheme.new do |cs|
205
- cs[:headline] = [ :bold, :white, :on_black ]
206
- cs[:success] = [ :bold, :green ]
207
- cs[:error] = [ :bold, :red ]
208
- cs[:up] = [ :green ]
209
- cs[:down] = [ :red ]
210
- cs[:unknown] = [ :dark, :yellow ]
211
- cs[:disabled] = [ :dark, :white ]
212
- cs[:quieted] = [ :dark, :green ]
213
- cs[:acked] = [ :yellow ]
214
- cs[:highlight] = [ :bold, :yellow ]
215
- cs[:search_hit] = [ :black, :on_white ]
216
- cs[:prompt] = [ :cyan ]
217
- cs[:even_row] = [ :bold ]
218
- cs[:odd_row] = [ :normal ]
219
- end
190
+ ### Setup pastel color aliases
191
+ ###
192
+ def self::setup_pastel_aliases
193
+ self.pastel.alias_color( :headline, :bold, :white, :on_black )
194
+ self.pastel.alias_color( :success, :bold, :green )
195
+ self.pastel.alias_color( :error, :bold, :red )
196
+ self.pastel.alias_color( :up, :green )
197
+ self.pastel.alias_color( :down, :red )
198
+ self.pastel.alias_color( :unknown, :dark, :yellow )
199
+ self.pastel.alias_color( :disabled, :dark, :white )
200
+ self.pastel.alias_color( :quieted, :dark, :green )
201
+ self.pastel.alias_color( :acked, :yellow )
202
+ self.pastel.alias_color( :warn, :bold, :magenta )
203
+ self.pastel.alias_color( :highlight, :bold, :yellow )
204
+ self.pastel.alias_color( :search_hit, :black, :on_white )
205
+ self.pastel.alias_color( :prompt, :cyan )
206
+ self.pastel.alias_color( :even_row, :bold )
207
+ self.pastel.alias_color( :odd_row, :reset )
220
208
  end
221
209
 
222
210
 
223
211
  ### Load the config file using either arborist-base's config-loader if available, or
224
212
  ### fall back to DEFAULT_CONFIG_FILE
225
213
  def self::load_config( global={} )
226
- Arborist.load_config( global[:c] ) if global[:c]
214
+ Arborist.load_config( global[:c] )
227
215
 
228
216
  # Set up the logging formatter
229
217
  Loggability.format_with( :color ) if $stdout.tty?
@@ -241,6 +229,7 @@ module Arborist::CLI
241
229
  $DRYRUN = false
242
230
  end
243
231
 
232
+
244
233
  if global[:verbose]
245
234
  $VERBOSE = true
246
235
  Loggability.level = :info
@@ -250,6 +239,8 @@ module Arborist::CLI
250
239
  $DEBUG = true
251
240
  Loggability.level = :debug
252
241
  end
242
+
243
+ $COLOR = global[ :color ]
253
244
  end
254
245
 
255
246
 
@@ -287,57 +278,65 @@ module Arborist::CLI
287
278
  end
288
279
 
289
280
 
290
- ### Get the prompt (a Highline object)
281
+ ### Get the prompt (a TTY::Prompt object)
291
282
  def prompt
292
283
  return Arborist::CLI.prompt
293
284
  end
294
285
 
295
286
 
296
- ### Return the specified +text+ as a Highline::String for convenient formatting,
297
- ### color, etc.
298
- def hl( text )
299
- return HighLine::String.new( text.to_s )
287
+ ### Return the global Pastel object for convenient formatting, color, etc.
288
+ def hl
289
+ return Arborist::CLI.pastel
300
290
  end
301
291
 
302
292
 
303
293
  ### Return the specified +string+ in the 'headline' ANSI color.
304
294
  def headline_string( string )
305
- return hl( string ).color( :headline )
295
+ return hl.headline( string )
306
296
  end
307
297
 
308
298
 
309
299
  ### Return the specified +string+ in the 'highlight' ANSI color.
310
300
  def highlight_string( string )
311
- return hl( string ).color( :highlight )
301
+ return hl.highlight( string )
312
302
  end
313
303
 
314
304
 
315
305
  ### Return the specified +string+ in the 'success' ANSI color.
316
306
  def success_string( string )
317
- return hl( string ).color( :success )
307
+ return hl.success( string )
318
308
  end
319
309
 
320
310
 
321
311
  ### Return the specified +string+ in the 'error' ANSI color.
322
312
  def error_string( string )
323
- return hl( string ).color( :error )
313
+ return hl.error( string )
324
314
  end
325
315
 
326
316
 
327
- ### Output a table with the given +rows+.
328
- def display_table( rows )
329
- colwidths = rows.transpose.map do |colvals|
330
- colvals.map {|val| visible_chars(val) }.max
331
- end
317
+ ### Output a table with the given +header+ (an array) and +rows+
318
+ ### (an array of arrays).
319
+ def display_table( header, rows )
320
+ table = TTY::Table.new( header, rows )
321
+ renderer = nil
332
322
 
333
- rows.each do |row|
334
- row_string = row.zip( colwidths ).inject( '' ) do |accum, (val, colsize)|
335
- padding = ' ' * (colsize - visible_chars(val) + 2)
336
- accum + val.to_s + padding
337
- end
323
+ if hl.enabled?
324
+ renderer = TTY::Table::Renderer::Unicode.new(
325
+ table,
326
+ multiline: true,
327
+ padding: [0,1,0,1]
328
+ )
329
+ renderer.border.style = :dim
338
330
 
339
- Arborist::CLI.prompt.say( row_string + "\n" )
331
+ else
332
+ renderer = TTY::Table::Renderer::ASCII.new(
333
+ table,
334
+ multiline: true,
335
+ padding: [0,1,0,1]
336
+ )
340
337
  end
338
+
339
+ puts renderer.render
341
340
  end
342
341
 
343
342
 
@@ -363,32 +362,15 @@ module Arborist::CLI
363
362
  end # module Subcommand
364
363
 
365
364
 
366
- ### Register one or more subcommands with the 'arborist' command shell. The given
367
- ### block will be evaluated in the context of Arborist::CLI.
368
- def self::register( &block )
369
- self.instance_eval( &block )
370
- end
371
-
372
-
373
- ### Custom command loader. The default one is silly.
374
- def self::load_commands( path )
375
- self.log.debug "Load commands from %s" % [ path ]
376
- Pathname.glob( path + '*.rb' ).each do |rbfile|
365
+ ### Load commands from any files in the specified directory relative to LOAD_PATHs
366
+ def self::commands_from( subdir )
367
+ Gem.find_latest_files( File.join(subdir, '*.rb') ).each do |rbfile|
377
368
  self.log.debug " loading %s..." % [ rbfile ]
378
369
  require( rbfile )
379
370
  end
380
371
  end
381
372
 
382
373
 
383
- # Load commands from any files in the specified directory relative to LOAD_PATHs
384
- def self::commands_from( subdir )
385
- $LOAD_PATH.map {|path| Pathname(path) }.each do |libdir|
386
- command_dir = libdir.expand_path + subdir
387
- load_commands( command_dir )
388
- end
389
- end
390
-
391
-
392
374
  commands_from 'arborist/command'
393
375
 
394
376
  end # class Arborist::CLI