locd 0.1.9 → 0.1.10

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2404ec26812c0d5683b2ac01fcab9a4461539633
4
- data.tar.gz: 19dea81b24b2ebbd2e5c7afe520d83d179e439c2
3
+ metadata.gz: 7e87ade2d470c9595ac40d6174268ba79851940a
4
+ data.tar.gz: 50d4c39c62e969c2f1bf42f2eeaa35a1a58f7bd1
5
5
  SHA512:
6
- metadata.gz: 2e965282f2cdd218ea4493b1fd62c16e3c146410519878576654333e36ae380f33336db3dec7c981aa8dbff44aa416dd80525f89ba6d56ddb9b5fa9642ce36ff
7
- data.tar.gz: f14276a7aa28716a5b2a2f7604e31dc5852c788e1abc672003a445921bbf3902dc54d7cf449211bafcba1d3bfbdf9495c4df20ab68d3d564645252b795f54f0c
6
+ metadata.gz: b217a8559f55fe3f3779a58fcb5e519642002841c59312b882b0ed4e7bb32c051da739916c65a1a6f620ef346426ab62188c2be423bb244aaff4941bcf1d9ca1
7
+ data.tar.gz: 3498a6255d0aefc564e03f4854e4f8b75fc6b639d1a00b28a38efc8ea43f645bb4e1b528e8659e773f0a211e24e761b084bebc9501b3729625849441ef560c14
@@ -0,0 +1,2 @@
1
+ {
2
+ }
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.9
1
+ 0.1.10
@@ -2,6 +2,18 @@ locd:
2
2
  home: ~/.locd
3
3
  bin: locd
4
4
 
5
+ cli:
6
+ log:
7
+ level: info
8
+ application: Locd
9
+ dest: $stderr
10
+
11
+ bash_comp:
12
+ log:
13
+ level: warn
14
+ dest: //tmp/bash_comp.log
15
+ # /CLI
16
+
5
17
  namespace:
6
18
  label: com.nrser.locd
7
19
  env: LOCD
@@ -22,3 +34,4 @@ locd:
22
34
  ports:
23
35
  start: 55000
24
36
  end: 56000
37
+
data/exe/locd CHANGED
@@ -6,7 +6,7 @@ require 'locd'
6
6
 
7
7
  # Setup logging *before* including {Locd::CLI} so that we can get
8
8
  # trace/debug output from that setup if enabled via ENV vars
9
- NRSER::Log.setup_for_cli! application: 'Locd', dest: $stderr, sync: true
9
+ NRSER::Log.setup_for_cli! Locd.config.cli_log_config
10
10
 
11
11
  # Logger for this file
12
12
  logger = NRSER::Log[__FILE__]
@@ -10,6 +10,8 @@
10
10
  # -----------------------------------------------------------------------
11
11
  require 'plist'
12
12
  require 'fileutils'
13
+ require 'nrser'
14
+ require 'nrser/props/immutable/hash'
13
15
 
14
16
  # Project / Package
15
17
  # -----------------------------------------------------------------------
@@ -47,6 +49,40 @@ class Locd::Agent
47
49
  TO_H_NAMES = Hamster::SortedSet[:label, :path, :plist, :status]
48
50
 
49
51
 
52
+ # Structs
53
+ # ============================================================================
54
+
55
+ class Status < Hamster::Hash
56
+ include NRSER::Props::Immutable::Hash
57
+
58
+ # @!attribute [r] loaded
59
+ # `true` if the agent is loaded in launchd.
60
+ #
61
+ # @return [Boolean]
62
+ #
63
+ prop :loaded, type: t.bool
64
+
65
+ # @!attribute [r] running
66
+ # `true` if the agent is currently running.
67
+ #
68
+ # @return [Boolean]
69
+ prop :running, type: t.bool
70
+
71
+ # @!attribute [r] pid
72
+ # The process ID the agent is running as (if any).
73
+ #
74
+ # @return [Integer?]
75
+ prop :pid, type: t.non_neg_int?
76
+
77
+ # @!attribute [r] last_exit_code
78
+ # The last status code the agent exited with, if any is available.
79
+ #
80
+ # @return [Integer?]
81
+ prop :last_exit_code, type: t.int?
82
+
83
+ end # class Status
84
+
85
+
50
86
  # Mixins
51
87
  # ==========================================================================
52
88
 
@@ -697,8 +733,7 @@ class Locd::Agent
697
733
  def initialize plist:, path:
698
734
  @path = path.to_pn.expand_path
699
735
  @plist = plist
700
- @status = :UNKNOWN
701
-
736
+ @status = nil
702
737
 
703
738
  # Sanity check...
704
739
 
@@ -861,31 +896,25 @@ class Locd::Agent
861
896
  # When `true`, will re-read from `launchd` (and cache results)
862
897
  # before returning.
863
898
  #
864
- # @return [Hash{pid: (Fixnum | nil), status: (Fixnum | nil)}]
865
- # When `launchd` has a status entry for the agent.
866
- #
867
- # @return [nil]
868
- # When `launchd` doesn't have a status entry for the agent.
899
+ # @return [Status]
869
900
  #
870
901
  def status refresh: false
871
- if refresh || @status == :UNKNOWN
902
+ if refresh || @status.nil?
872
903
  raw_status = Locd::Launchctl.status[label]
873
904
 
874
905
  # Happens when the agent is not loaded
875
906
  @status = if raw_status.nil?
876
- {
907
+ Status.new \
877
908
  loaded: false,
878
909
  running: false,
879
910
  pid: nil,
880
- last_exit_code: nil,
881
- }
911
+ last_exit_code: nil
882
912
  else
883
- {
913
+ Status.new \
884
914
  loaded: true,
885
915
  running: !raw_status[:pid].nil?,
886
916
  pid: raw_status[:pid],
887
- last_exit_code: raw_status[:status],
888
- }
917
+ last_exit_code: raw_status[:status]
889
918
  end
890
919
  end
891
920
 
@@ -63,6 +63,22 @@ class Locd::Agent::Site < Locd::Agent
63
63
  TO_H_NAMES = Locd::Agent::TO_H_NAMES.union [:port, :url]
64
64
 
65
65
 
66
+ # Structs
67
+ # ============================================================================
68
+
69
+ class Status < Locd::Agent::Status
70
+
71
+ # @!attribute [r] port
72
+ # Site backend port.
73
+ #
74
+ # @return [Integer]
75
+ #
76
+ prop :port,
77
+ type: t.pos_int
78
+
79
+ end # class Status
80
+
81
+
66
82
  # Class Methods
67
83
  # ==========================================================================
68
84
 
@@ -160,7 +176,7 @@ class Locd::Agent::Site < Locd::Agent
160
176
  # Methods to read proxied and computed attributes.
161
177
  #
162
178
 
163
- # @return [Fixnum]
179
+ # @return [Integer]
164
180
  # Port service runs on.
165
181
  def port
166
182
  config['port']
@@ -180,4 +196,24 @@ class Locd::Agent::Site < Locd::Agent
180
196
 
181
197
  # @!endgroup Instance Methods: Attribute Readers
182
198
 
199
+
200
+ # @!group `launchctl` Interface Instance Methods
201
+ # ----------------------------------------------------------------------------
202
+
203
+ # The site agent's status from parsing `launchctl list`.
204
+ #
205
+ # Status is read on demand and cached on the instance.
206
+ #
207
+ # @param [Boolean] refresh:
208
+ # When `true`, will re-read from `launchd` (and cache results)
209
+ # before returning.
210
+ #
211
+ # @return [Status]
212
+ #
213
+ def status refresh: false
214
+ Status.new port: port, **super( refresh: refresh )
215
+ end
216
+
217
+ # @!endgroup `launchctl` Interface Instance Methods
218
+
183
219
  end # class Locd::Launchd
@@ -1,5 +1,3 @@
1
- module Locd::CLI::Command; end
2
-
3
1
  require_relative './command/base'
4
2
  require_relative './command/agent'
5
3
  require_relative './command/site'
@@ -101,6 +101,14 @@ class Locd::CLI::Command::Agent < Locd::CLI::Command::Base
101
101
  # end protected
102
102
  public
103
103
 
104
+ def_shared :argument,
105
+ name: :pattern,
106
+ groups: :pattern,
107
+ desc: "Label or workdir pattern to find agent(s)",
108
+ type: :string,
109
+ required: true,
110
+ complete: ->( klass:, **etc ) { klass.agent_class.labels.to_a }
111
+
104
112
 
105
113
  # Shared Options
106
114
  # ============================================================================
@@ -242,15 +250,17 @@ class Locd::CLI::Command::Agent < Locd::CLI::Command::Base
242
250
  # Querying
243
251
  # ----------------------------------------------------------------------------
244
252
 
245
- desc "ls [PATTERN]",
253
+ desc "ls",
246
254
  "List agents"
247
255
 
248
256
  map list: :ls
249
257
 
258
+ include_shared groups: :pattern
259
+
250
260
  include_options :long,
251
261
  groups: :pattern
252
262
 
253
- def ls pattern = nil
263
+ def ls # pattern = nil
254
264
  results = if pattern.nil?
255
265
  agent_class.all
256
266
  else
@@ -286,8 +296,7 @@ class Locd::CLI::Command::Agent < Locd::CLI::Command::Base
286
296
  agent = find_only! pattern
287
297
  respond \
288
298
  label: agent.label,
289
- port: agent.port,
290
- status: agent.status
299
+ status: agent.status.to_h( compact: false )
291
300
  end
292
301
 
293
302
 
@@ -397,17 +406,25 @@ class Locd::CLI::Command::Agent < Locd::CLI::Command::Base
397
406
  # Assorted Other Commands
398
407
  # ----------------------------------------------------------------------------
399
408
 
400
- desc "open PATTERN [OPTIONS]",
409
+ desc "open [OPTIONS]",
401
410
  "Open an agent's URL in the browser"
402
411
 
403
412
  include_options groups: [ :pattern, :multi, :start ]
413
+
414
+ # include_shared groups: [ :pattern, :multi, :start ]
404
415
 
416
+ arg :pattern,
417
+ desc: "Label or workdir pattern to find agent(s)",
418
+ type: :string,
419
+ required: true,
420
+ complete: ->( klass:, **etc ) { klass.agent_class.labels.to_a }
421
+
405
422
  option :start,
406
- desc: %{ Start any stopped agents before opening },
407
- type: :boolean,
408
- default: true
423
+ desc: %{ Start any stopped agents before opening },
424
+ type: :boolean,
425
+ default: true
409
426
 
410
- def open pattern
427
+ def open # pattern
411
428
  find_multi!( pattern ).each do |agent|
412
429
  if options[:start] && agent.stopped?
413
430
  agent.start **option_kwds( groups: :start )
@@ -468,6 +485,11 @@ class Locd::CLI::Command::Agent < Locd::CLI::Command::Base
468
485
  type: :string,
469
486
  enum: ['out', 'err']
470
487
 
488
+ option :follow,
489
+ desc: "Run with `tail -F`",
490
+ aliases: [ '-f' ],
491
+ type: :boolean
492
+
471
493
  def tail pattern, *tail_options
472
494
  agent = find_only! pattern
473
495
 
@@ -499,7 +521,10 @@ class Locd::CLI::Command::Agent < Locd::CLI::Command::Base
499
521
  raise "WTF"
500
522
  end
501
523
 
502
- exec "tail", *tail_options, path.to_s
524
+ cmd = ['tail']
525
+ cmd += ['-F'] if options[:follow]
526
+
527
+ exec *cmd, *tail_options, path.to_s
503
528
  end # #tail
504
529
 
505
530
  end # class Locd::CLI::Command::Agent
@@ -1,6 +1,9 @@
1
1
  # encoding: UTF-8
2
2
  # frozen_string_literal: true
3
3
 
4
+ require 'nrser/refinements/types'
5
+ using NRSER::Types
6
+
4
7
 
5
8
  # Namespace
6
9
  # =======================================================================
@@ -10,6 +10,7 @@ require 'shellwords'
10
10
  # Deps
11
11
  # -----------------------------------------------------------------------
12
12
  require 'thor'
13
+ require 'nrser/labs/i8'
13
14
 
14
15
  # Project / Package
15
16
  # -----------------------------------------------------------------------
@@ -22,6 +23,14 @@ require 'nrser/refinements/types'
22
23
  using NRSER::Types
23
24
 
24
25
 
26
+ # Namespace
27
+ # ========================================================================
28
+
29
+ module Locd
30
+ module CLI
31
+ module Command
32
+
33
+
25
34
  # Definitions
26
35
  # =======================================================================
27
36
 
@@ -31,13 +40,16 @@ using NRSER::Types
31
40
  #
32
41
  # @see http://whatisthor.com/
33
42
  #
34
- class Locd::CLI::Command::Base < Thor
43
+ class Base < Thor
44
+
45
+ # Instance Methods
46
+ # ========================================================================
35
47
 
36
- # Helpers
37
- # ============================================================================
38
- #
39
48
  protected
40
49
 
50
+ # @!group Helper Instance Methods
51
+ # ========================================================================
52
+
41
53
  # Swap `$stdout` for a {StringIO}, call `block`, swap original `$stdout`
42
54
  # back in and return the string contents.
43
55
  #
@@ -237,7 +249,16 @@ class Locd::CLI::Command::Base < Thor
237
249
  end
238
250
  end
239
251
 
240
- # end protected
241
- public
252
+ # @!endgroup Helper Instance Methods # ***********************************
253
+
254
+ public # end protected *****************************************************
242
255
 
243
- end # module Locd::CLI::Command::Base
256
+ end # class Base
257
+
258
+
259
+ # /Namespace
260
+ # ========================================================================
261
+
262
+ end # module Command
263
+ end # module CLI
264
+ end # module Locd
@@ -8,6 +8,7 @@
8
8
 
9
9
  # Deps
10
10
  # -----------------------------------------------------------------------
11
+ require 'thor/completion/bash'
11
12
 
12
13
  # Project / Package
13
14
  # -----------------------------------------------------------------------
@@ -20,14 +21,22 @@ require 'nrser/refinements/types'
20
21
  using NRSER::Types
21
22
 
22
23
 
24
+ # Namespace
25
+ # ========================================================================
26
+
27
+ module Locd
28
+ module CLI
29
+ module Command
30
+
31
+
23
32
  # Definitions
24
33
  # =======================================================================
25
34
 
26
- # CLI interface using the `thor` gem.
35
+ # CLI interface using the Thor via my `atli` fork.
27
36
  #
28
37
  # @see http://whatisthor.com/
29
38
  #
30
- class Locd::CLI::Command::Main < Locd::CLI::Command::Base
39
+ class Main < Base
31
40
 
32
41
  # Constants
33
42
  # ============================================================================
@@ -39,6 +48,9 @@ class Locd::CLI::Command::Main < Locd::CLI::Command::Base
39
48
  #
40
49
  LOG_LEVEL_STRINGS = SemanticLogger::LEVELS.map { |sym| sym.to_s.freeze }
41
50
 
51
+
52
+ include Thor::Completion::Bash
53
+
42
54
 
43
55
  # Global (Class-Level) Options
44
56
  # ============================================================================
@@ -163,6 +175,8 @@ class Locd::CLI::Command::Main < Locd::CLI::Command::Base
163
175
  # Commands
164
176
  # ============================================================================
165
177
 
178
+ # add_bash_completion_commands!
179
+
166
180
  # Querying
167
181
  # ----------------------------------------------------------------------------
168
182
 
@@ -187,34 +201,42 @@ class Locd::CLI::Command::Main < Locd::CLI::Command::Base
187
201
  # Sub-Commands
188
202
  # ============================================================================
189
203
 
190
- desc 'site SUBCOMMAND...',
191
- 'Deal with site agents.'
192
- subcommand 'site',
193
- Locd::CLI::Command::Site
204
+ subcommand 'agent',
205
+ Locd::CLI::Command::Agent,
206
+ desc: 'Deal with agents in general (all types).'
194
207
 
195
208
 
196
- desc 'job SUBCOMMAND...',
197
- 'Deal with job agents.'
198
- subcommand 'job',
199
- Locd::CLI::Command::Job
209
+ subcommand 'site',
210
+ Locd::CLI::Command::Site,
211
+ desc: 'Deal with site agents.'
200
212
 
201
213
 
202
- desc 'proxy SUBCOMMAND...',
203
- 'Deal with the HTTP proxy that routes requests to servers'
204
- subcommand 'proxy',
205
- Locd::CLI::Command::Proxy
206
-
207
-
208
- desc 'rotate-logs SUBCOMMAND...',
209
- 'Deal with the log rotation job'
210
- # map :'rotate-logs' => :rotate_logs
211
- subcommand 'rotate_logs',
212
- Locd::CLI::Command::RotateLogs
214
+ subcommand 'job',
215
+ Locd::CLI::Command::Job,
216
+ desc: "Deal with job agents."
213
217
 
214
218
 
215
- desc 'project SUBCOMMAND...',
216
- 'Manage Agent definitions for projects'
217
- subcommand 'project',
218
- Locd::CLI::Command::Project
219
+ subcommand 'proxy',
220
+ Locd::CLI::Command::Proxy,
221
+ desc: 'Deal with the HTTP proxy that routes requests to servers'
222
+
223
+
224
+ # subcommand 'rotate-logs',
225
+ subcommand 'rotate_logs',
226
+ Locd::CLI::Command::RotateLogs,
227
+ desc: 'Deal with the log rotation job'
228
+
229
+
230
+ subcommand 'project',
231
+ Locd::CLI::Command::Project,
232
+ desc: 'Manage Agent definitions for projects'
219
233
 
220
- end # class Locd::CLI::Command::Main
234
+ end # class Main
235
+
236
+
237
+ # /Namespace
238
+ # ========================================================================
239
+
240
+ end # module Command
241
+ end # module CLI
242
+ end # module Locd
@@ -17,6 +17,8 @@ require 'nrser/core_ext/object'
17
17
  # Project / Package
18
18
  # -----------------------------------------------------------------------
19
19
 
20
+ require_relative './config/types'
21
+
20
22
 
21
23
  # Refinements
22
24
  # =======================================================================
@@ -25,10 +27,15 @@ require 'nrser/refinements/types'
25
27
  using NRSER::Types
26
28
 
27
29
 
28
- # Definitions
29
- # =======================================================================
30
-
31
- # @todo document Locd::Config class.
30
+ # A hash-like container providing access to a layered tree of config values
31
+ # sourced from `YAML` files and `ENV` vars.
32
+ #
33
+ #
34
+ # Keys
35
+ # ----------------------------------------------------------------------------
36
+ #
37
+ # Config keys are arrays of strings that
38
+ #
32
39
  class Locd::Config
33
40
 
34
41
  # Constants
@@ -80,14 +87,14 @@ class Locd::Config
80
87
 
81
88
  @from_files = {}
82
89
 
83
- load_file default_config_path
90
+ load_file! default_config_path
84
91
 
85
92
  if user_config_path.exist?
86
- load_file user_config_path
93
+ load_file! user_config_path
87
94
  end
88
95
 
89
96
  if dev_config_path && dev_config_path.exist?
90
- load_file dev_config_path
97
+ load_file! dev_config_path
91
98
  end
92
99
  end # #initialize
93
100
 
@@ -99,46 +106,39 @@ class Locd::Config
99
106
  # ========================================================================
100
107
 
101
108
 
102
- # @todo Document load_file method.
109
+ # Load a `YAML` config file into the config.
103
110
  #
104
- # @param [type] arg_name
105
- # @todo Add name param description.
111
+ # @param [Pathname | String] path
112
+ # Path to file.
106
113
  #
107
- # @return [return_type]
108
- # @todo Document return value.
114
+ # @return [nil]
109
115
  #
110
- def load_file path
111
- bnd = binding
112
-
116
+ def load_file! path
113
117
  path.
114
118
  to_pn.
115
119
  read.
116
- thru { |contents|
117
- YAML.load contents
118
- }.
119
- map_leaves { |path, leaf|
120
- case leaf
121
- when String
122
- bnd.erb leaf
123
- else
124
- leaf
125
- end
126
- }.
127
- thru { |tree|
128
- @from_files.deep_merge! tree
129
- }
120
+ thru { |contents| @from_files.deep_merge! YAML.load( contents ) }
130
121
 
131
122
  nil
132
- end # #load_file
123
+ end # #load_file!
133
124
 
134
125
  public # end protected ***************************************************
135
126
 
136
127
 
137
- def key_path_for *key
128
+ def self.key_path_for *key
138
129
  key.flat_map { |k| k.to_s.split KEY_SEPARATOR }
139
130
  end
140
131
 
132
+ def key_path_for *key
133
+ self.class.key_path_for *key
134
+ end
141
135
 
136
+
137
+ # Get a value from the config files only.
138
+ #
139
+ # @param [Array<#to_s>] *key
140
+ # The key to lookup.
141
+ #
142
142
  def from_files *key, type: nil
143
143
  key_path = key_path_for *key
144
144
  value = @from_files.dig Locd::GEM_NAME, *key_path
@@ -146,7 +146,7 @@ class Locd::Config
146
146
  if value.nil?
147
147
  nil
148
148
  else
149
- parse_and_check value, type: type
149
+ parse_and_check key, value, type: type
150
150
  end
151
151
  end
152
152
 
@@ -159,13 +159,15 @@ class Locd::Config
159
159
  end
160
160
 
161
161
 
162
- def parse_and_check value, type: nil
162
+ def parse_and_check key, value, type: nil
163
+ type = Types.for_key( *key ) if type.nil?
164
+
163
165
  return value if type.nil?
164
166
 
165
167
  if value.is_a?( String ) && type.has_from_s?
166
168
  type.from_s value
167
169
  else
168
- type.check value
170
+ type.check! value
169
171
  end
170
172
  end
171
173
 
@@ -179,7 +181,7 @@ class Locd::Config
179
181
  when nil, ''
180
182
  nil
181
183
  else
182
- parse_and_check value, type: type
184
+ parse_and_check key, value, type: type
183
185
  end
184
186
  end
185
187
 
@@ -191,12 +193,46 @@ class Locd::Config
191
193
  files_value = from_files *key, type: type
192
194
  return files_value unless files_value.nil?
193
195
 
194
- parse_and_check default, type: type
196
+ parse_and_check key, default, type: type
195
197
  end
196
198
 
197
199
  alias_method :[], :get
198
200
 
199
201
 
202
+ def set *key, value, type: nil
203
+ value_str = value.to_s
204
+
205
+ parse_and_check key, value_str, type: type
206
+
207
+ ENV[ env_key_for( *key ) ] = value_str
208
+ end
209
+
210
+
211
+ # Proxy to {#set} orthogonal to {#[]} / {#get} (though in this case we
212
+ # need to do a little more work than an alias on account of how `#[]=`
213
+ # handled keyword args).
214
+ #
215
+ # @example Single string key
216
+ # Locd.config[ 'cli.bash_comp.log.level' ] = :debug
217
+ #
218
+ # @example List key
219
+ # Locd.config[ :cli, :bash_comp, :log, :level ] = :debug
220
+ #
221
+ # @example Checking the type
222
+ # Locd.config[ 'home', type: t.abs_path ] = user_input
223
+ #
224
+ def []= *key, value
225
+ if Hash === key[-1]
226
+ kwds = key[-1]
227
+ key = key[0..-2]
228
+ else
229
+ kwds = {}
230
+ end
231
+
232
+ set *key, value, **kwds
233
+ end
234
+
235
+
200
236
  def to_h
201
237
  @from_files.merge \
202
238
  "locd" => @from_files["locd"].map_leaves { |key_path, value|
@@ -237,4 +273,60 @@ class Locd::Config
237
273
  home_dir / 'config.yml'
238
274
  end
239
275
 
276
+
277
+ # Does `ARGV` look like we're executing Bash completion?
278
+ #
279
+ # We want to change how we're logging during Bash completion runs.
280
+ #
281
+ # @return [Boolean]
282
+ #
283
+ def cli_ARGV_looks_like_bash_comp?
284
+ ARGV[0] == 'bash-complete'
285
+ end
286
+
287
+
288
+ # Level to log at when CLI'ing.
289
+ #
290
+ # @return [Symbol]
291
+ # One of {SemanticLogger::LEVELS}.
292
+ #
293
+ def cli_log_level
294
+ get( cli_ARGV_looks_like_bash_comp? ? 'bash_comp.log.level' :
295
+ 'cli.log.level' )
296
+ end
297
+
298
+
299
+ # @return [$stderr]
300
+ #
301
+ def cli_log_dest
302
+ dest = if cli_ARGV_looks_like_bash_comp?
303
+ get 'cli.bash_comp.log.dest'
304
+ else
305
+ get 'cli.log.dest'
306
+ end
307
+
308
+ {
309
+ **( IO === dest ? { io: dest } : { file_name: dest.to_s } ),
310
+ formatter: NRSER::Log::Formatters::Color.new,
311
+ }
312
+ end
313
+
314
+
315
+ # Get the logging config, taking account of the Bash completion environment.
316
+ #
317
+ # Output from this
318
+ #
319
+ # @return [Hash<Symbol, ]
320
+ # @todo Document return value.
321
+ #
322
+ def cli_log_config
323
+ {
324
+ application: get( 'cli.log.application' ),
325
+ level: cli_log_level,
326
+ dest: cli_log_dest,
327
+ sync: true
328
+ }
329
+ end # #cli_log_dest
330
+
331
+
240
332
  end # class Locd::Config
@@ -0,0 +1,140 @@
1
+ # encoding: UTF-8
2
+ # frozen_string_literal: true
3
+
4
+
5
+ # Requirements
6
+ # ========================================================================
7
+
8
+ # Stdlib
9
+ # ------------------------------------------------------------------------
10
+
11
+ # Deps
12
+ # ------------------------------------------------------------------------
13
+
14
+ require 'nrser/labs/i8'
15
+
16
+ # Using log system types, which are not loaded along with it to avoid
17
+ # dependencies.
18
+ require 'nrser/log/types'
19
+
20
+ # Project / Package
21
+ # ------------------------------------------------------------------------
22
+
23
+
24
+ # Refinements
25
+ # =======================================================================
26
+
27
+ require 'nrser/refinements/types'
28
+ using NRSER::Types
29
+
30
+
31
+ # Namespace
32
+ # =======================================================================
33
+
34
+ module Locd
35
+ class Config
36
+
37
+
38
+ # Definitions
39
+ # =======================================================================
40
+
41
+ module Types
42
+
43
+ # Mixins
44
+ # ========================================================================
45
+
46
+ # Get {NRSER::Types::Factory.def_factory}
47
+ extend t::Factory
48
+
49
+
50
+ # Class Methods
51
+ # ========================================================================
52
+
53
+ # A tree representing config key paths to the types they need to be.
54
+ #
55
+ # Computed on first call and cached after that as it needs the type
56
+ # factories below.
57
+ #
58
+ # @return [Hamster::Hash]
59
+ #
60
+ def self.by_key
61
+ # Got sick of writing "Hamster::Hash[...]"... "I8" <=> "Immutable"
62
+ @by_key ||= I8[
63
+ 'home' => config_path,
64
+ 'bin' => ( t.when( 'locd' ) | config_path ),
65
+
66
+ 'cli' => I8[
67
+ 'log' => I8[
68
+ 'application' => t.non_empty_str,
69
+ 'level' => NRSER::Log::Types.level?,
70
+ 'dest' => ( NRSER::Log::Types.stdio | config_path ),
71
+ ],
72
+
73
+ 'bash_comp' => I8[
74
+ 'log' => I8[
75
+ 'level' => NRSER::Log::Types.level,
76
+ 'dest' => config_path,
77
+ ],
78
+ ]
79
+ ]
80
+ ]
81
+ end
82
+
83
+
84
+ # Dig in to {BY_KEY} and see if it has a type for a `key`.
85
+ #
86
+ # @param [Array]
87
+ #
88
+ # @return [NRSER::Types::Type?]
89
+ #
90
+ def self.for_key *key
91
+ by_key.dig *Locd::Config.key_path_for( *key )
92
+ end
93
+
94
+
95
+ # @!group Type Factory Class Methods
96
+ # --------------------------------------------------------------------------
97
+
98
+ def_factory :package_path do |
99
+ name: 'PackagePath',
100
+
101
+ from_s: ->( string ) {
102
+ if string.start_with? '//'
103
+ Locd::ROOT.join string[2..-1]
104
+ end
105
+ },
106
+
107
+ **options
108
+ |
109
+ t.path &
110
+ t.where( name: name, from_s: from_s, **options) { |path|
111
+ begin
112
+ false == path.
113
+ to_pn.
114
+ relative_path_from( Locd::ROOT ).
115
+ start_with?( '..' + File::SEPARATOR )
116
+ rescue StandardError => error
117
+ false
118
+ end
119
+ }
120
+ end # def_factory :package_path
121
+
122
+
123
+ def_factory :config_path do |name: 'ConfigPath', **options|
124
+ t.or \
125
+ package_path,
126
+ t.abs_path,
127
+ name: name,
128
+ **options
129
+ end # def_factory :config_path
130
+
131
+ # @!endgroup Type Factory Class Methods # **********************************
132
+
133
+ end # module Types
134
+
135
+
136
+ # /Namespace
137
+ # =======================================================================
138
+
139
+ end # class Config
140
+ end # module Locd
@@ -9,7 +9,7 @@ Gem::Specification.new do |spec|
9
9
  spec.authors = ["nrser"]
10
10
  spec.email = ["neil@ztkae.com"]
11
11
 
12
- spec.summary = %q{Get loc'd out!}
12
+ spec.summary = %{Get loc'd out!}
13
13
  # spec.description = %q{TODO: Write a longer description or delete this line.}
14
14
  spec.homepage = "https://github.com/nrser/locd"
15
15
  spec.license = "MIT"
@@ -47,7 +47,7 @@ Gem::Specification.new do |spec|
47
47
  # ----------------------------------------------------------------------------
48
48
 
49
49
  # My guns
50
- spec.add_dependency "nrser", '~> 0.3.5'
50
+ spec.add_dependency "nrser", '~> 0.3.9'
51
51
 
52
52
  # Used to process command templates from projects' `//dev/locd.yml` files
53
53
  spec.add_dependency "cmds", ">= 0.2.10"
@@ -59,7 +59,7 @@ Gem::Specification.new do |spec|
59
59
  spec.add_dependency 'plist', '~> 3.4'
60
60
 
61
61
  # Atli, my fork of Thor for CLI interface
62
- spec.add_dependency 'atli', '~> 0.1.8'
62
+ spec.add_dependency 'atli', '~> 0.1.10'
63
63
 
64
64
  #
65
65
  # spec.add_dependency 'terminal-table', '~> 1.8'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: locd
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.9
4
+ version: 0.1.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - nrser
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-05-27 00:00:00.000000000 Z
11
+ date: 2018-07-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -114,14 +114,14 @@ dependencies:
114
114
  requirements:
115
115
  - - "~>"
116
116
  - !ruby/object:Gem::Version
117
- version: 0.3.5
117
+ version: 0.3.9
118
118
  type: :runtime
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
122
  - - "~>"
123
123
  - !ruby/object:Gem::Version
124
- version: 0.3.5
124
+ version: 0.3.9
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: cmds
127
127
  requirement: !ruby/object:Gem::Requirement
@@ -170,14 +170,14 @@ dependencies:
170
170
  requirements:
171
171
  - - "~>"
172
172
  - !ruby/object:Gem::Version
173
- version: 0.1.8
173
+ version: 0.1.10
174
174
  type: :runtime
175
175
  prerelease: false
176
176
  version_requirements: !ruby/object:Gem::Requirement
177
177
  requirements:
178
178
  - - "~>"
179
179
  - !ruby/object:Gem::Version
180
- version: 0.1.8
180
+ version: 0.1.10
181
181
  description:
182
182
  email:
183
183
  - neil@ztkae.com
@@ -191,6 +191,7 @@ files:
191
191
  - ".qb-options.yml"
192
192
  - ".rspec"
193
193
  - ".travis.yml"
194
+ - ".vscode/settings.json"
194
195
  - ".yardopts"
195
196
  - Gemfile
196
197
  - LICENSE.txt
@@ -225,6 +226,7 @@ files:
225
226
  - lib/locd/cli/table.rb
226
227
  - lib/locd/config.rb
227
228
  - lib/locd/config/base.rb
229
+ - lib/locd/config/types.rb
228
230
  - lib/locd/errors.rb
229
231
  - lib/locd/label.rb
230
232
  - lib/locd/launchctl.rb