locd 0.1.9 → 0.1.10

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 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