Module: Lizarb

Defined in:
lib/lizarb.rb,
lib/lizarb/script.rb,
lib/lizarb/project.rb,
lib/lizarb/version.rb

Defined Under Namespace

Classes: Error, ModeNotFound, SystemNotFound

Constant Summary collapse

VERSION =
"1.0.5"

Class Method Summary collapse

Class Method Details

.app(&block) ⇒ Object

called from exe/lizarb



80
81
82
83
84
85
86
87
88
89
# File 'lib/lizarb.rb', line 80

def app &block
  require "app"
  if block_given?
    App.class_exec(&block)
  else
    lookup_and_require_app
  end

  override_app_settings_with_env_variables
end

.callObject

called from exe/lizarb



92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/lizarb.rb', line 92

def call
  define_log_levels
  log "LizaRB v#{Lizarb.version}                                                                                                      https://lizarb.org" if defined? $log_boot_higher
  log "#{self}.#{__method__}" if defined? $log_boot_low
  log "  log_boot is set to #{App.log_boot}" if defined? $log_boot_lower
  # log "  log_level is set to #{App.log_level}" if defined? $log_boot_lower
  
  lookup_and_set_gemfile
  lookup_and_set_mode
  lookup_and_load_settings
  require_liza_and_systems
  connect_systems
  log "  Lizarb.#{__method__} done" if defined? $log_boot_low
end

.connect_part(unit_class, key, part_class, system) ⇒ Object

parts



434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
# File 'lib/lizarb.rb', line 434

def connect_part unit_class, key, part_class, system
  if defined? $log_boot_lowest
    t = Time.now
    string = "          #{unit_class}.part :#{key}"
    log string
  end

  part_class ||= if system.nil?
              Liza.const "#{key}_part"
            else
              Liza.const("#{system}_system")
                  .const "#{key}_part"
            end

  if part_class.insertion
    unit_class.class_exec(&part_class.insertion)
  end

  if part_class.extension
    part_class.const_set :Extension, Class.new(Liza::PartExtension)
    part_class::Extension.class_exec(&part_class.extension)
  end

  if defined? $log_boot_lowest
    log "          ."
  end
end

.connect_system(key, system_class) ⇒ Object



401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
# File 'lib/lizarb.rb', line 401

def connect_system key, system_class
  # t = Time.now
  system_class.color DevSystem::ColorShell.parse system_class.color unless system_class.color.is_a? Array

  # Ignore this for now.
  # This feature has been commented out for simplicity purposes.
  # It injects code into other classes just like Part does. System defines them
  #
  # color_system_class = Liza::Unit.stick(system_class.color, system_class.name).to_s
  # log "CONNECTING SYSTEM                     #{color_system_class}" if defined? $log_boot_low
  
  # index = 0
  # system_class.registrar.each do |string, target_block|
  #   reg_type, _sep, reg_target = string.to_s.lpartition "_"

  #   index += 1

  #   target_klass = Liza.const reg_target

  #   if reg_type == "insertion"
  #     target_klass.class_exec(&target_block)
  #   else
  #     raise "TODO: decide and implement system extension"
  #   end
  #   log "CONNECTING SYSTEM-PART                #{color_system_class}.#{reg_type.to_s.ljust 11} to #{target_klass.to_s.ljust 30} at #{target_block.source_location * ":"}  " if defined? $log_boot_low
  # end

  # pad = 21-system_class.name.size
  # log "CONNECTED  SYSTEM         #{t.diff}s for #{color_system_class}#{"".ljust pad} to connect to #{index} system parts" if defined? $log_boot_normal
end

.connect_systemsObject



384
385
386
387
388
389
# File 'lib/lizarb.rb', line 384

def connect_systems
  log "  Lizarb.#{__method__} (#{App.systems.count})" if defined? $log_boot_low
  App.systems.each do |system_key, system_class|
    connect_system system_key, system_class
  end
end

.define_log_levelsObject



220
221
222
223
224
225
226
227
# File 'lib/lizarb.rb', line 220

def define_log_levels
  level = App.log_boot
  is_lowest = level == -3
  App::LOG_LEVELS.each do |k, v|
    puts "$log_boot_#{k} = #{v >= level}" if level == -3
    eval "$log_boot_#{k} = true" if v >= level
  end
end

.exitObject

called from exe/lizarb



108
109
110
111
# File 'lib/lizarb.rb', line 108

def exit
  exit_messages if defined? $log_boot_normal
  super 0
end

.exit_messagesObject



113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/lizarb.rb', line 113

def exit_messages
  info = {
    ruby: RUBY_VERSION,
    bundler: Bundler::VERSION,
    zeitwerk: Zeitwerk::VERSION,
    lizarb: VERSION,
    app: $APP,
    mode: App.mode,
    log_boot: App.log_boot,
    log_level: App.get(:log_level),
  }
  github = "https://github.com/lizarb/lizarb"
  puts info.to_s
  puts "Report bugs at #{github}/issues"
  puts "Fork us on Github at #{github}/fork"
end

.loadersObject



467
468
469
# File 'lib/lizarb.rb', line 467

def loaders
  @loaders
end

.log(s) ⇒ Object



25
26
27
28
# File 'lib/lizarb.rb', line 25

def log s
  print "#{$boot_time.diff}s " if defined? $log_boot_low
  puts s
end

.lookup_and_load_core_extObject

setup phase



132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/lizarb.rb', line 132

def lookup_and_load_core_ext
  files =
    if @IS_GEM_DIR
      Dir["#{@CUR_DIR}/lib/lizarb/ruby/*.rb"]
    else
      Dir["#{@GEM_DIR}/lib/lizarb/ruby/*.rb"] + Dir["#{@CUR_DIR}/lib/lizarb/ruby/*.rb"]
    end

  files.each do |file_name|
    log "#{self} loading #{file_name}" if $VERBOSE
    load file_name
  end
end

.lookup_and_load_settingsObject



238
239
240
241
242
243
244
245
246
# File 'lib/lizarb.rb', line 238

def lookup_and_load_settings
  log "  Lizarb.#{__method__}" if defined? $log_boot_low
  require "dotenv"
  log "    required Dotenv" if defined? $log_boot_lower

  files = ["#{$APP}.#{$mode}.env", "#{$APP}.env"]
  Dotenv.load(*files)
  log "    Dotenv.load(*#{files.inspect})" if defined? $log_boot_lowest
end

.lookup_and_require_appObject

app phase

Raises:



148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/lizarb.rb', line 148

def lookup_and_require_app
  finder = \
    proc do |lib_name, file_name|
      log "#{self} checking if #{file_name} exists" if $VERBOSE
      if File.file? "#{file_name}"
        require lib_name
        true
      else
        false
      end
    end

  return if finder.call "#{@CUR_DIR}/#{$APP}", "#{@CUR_DIR}/#{$APP}.rb"
  return if finder.call "#{@GEM_DIR}/#{$APP}", "#{@GEM_DIR}/#{$APP}.rb"

  raise Error, "Could not find #{$APP}.rb in #{@CUR_DIR} or #{@GEM_DIR}"
end

.lookup_and_set_gemfileObject

call phase



196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
# File 'lib/lizarb.rb', line 196

def lookup_and_set_gemfile
  log "#{self}.#{__method__}" if defined? $log_boot_low
  gemfile = nil

  finder = \
    proc do |file_name|
      log "#{self}.#{__method__} #{file_name}" if $VERBOSE
      if File.file? file_name
        file_name
      else
        false
      end
    end

  gemfile ||= finder.call "#{@CUR_DIR}/#{$APP}.gemfile.rb"
  gemfile ||= finder.call "#{@GEM_DIR}/#{$APP}.gemfile.rb" unless @IS_GEM_DIR
  gemfile ||= finder.call "#{@CUR_DIR}/Gemfile"
  gemfile ||= finder.call "#{@GEM_DIR}/app_global.gemfile.rb"

  log "  ENV['BUNDLE_GEMFILE'] = #{gemfile.inspect}" if defined? $log_boot_lower
  ENV["BUNDLE_GEMFILE"] = gemfile
  require "bundler/setup"
end

.lookup_and_set_modeObject



229
230
231
232
233
234
235
236
# File 'lib/lizarb.rb', line 229

def lookup_and_set_mode
  log "  Lizarb.#{__method__}" if defined? $log_boot_low

  $mode = App.mode
  log "    $mode = #{$mode.inspect}" if defined? $log_boot_lower
  $coding = App.coding?
  log "    $coding enabled because $mode == :code | A bit slower for debugging purposes" if $coding && defined? $log_boot_lower
end

.override_app_settings_with_env_variablesObject



166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# File 'lib/lizarb.rb', line 166

def override_app_settings_with_env_variables
  if env_app_folder = ENV["APP_FOLDER"]
    App.folder env_app_folder
  end

  if s = ENV["LOG_BOOT"] || ENV["LOG"]
    App.log_boot (s.length == 1) ? s.to_i : s.to_sym
  end

  if s = ENV["LOG_LEVEL"] || ENV["LOG"]
    App.log_level (s.length == 1) ? s.to_i : s.to_sym
  end

  if env_mode = ENV["MODE"]
    App.mode env_mode
  end

  if env_gemfile = ENV["GEMFILE"]
    App.gemfile env_gemfile
  end

  if env_systems = ENV["SYSTEMS"]
    env_systems.split(",").each do |system|
      App.system system
    end
  end
end

.projectObject



4
5
6
7
8
9
10
11
12
13
14
15
16
# File 'lib/lizarb/project.rb', line 4

def self.project
  $VERBOSE = ENV["VERBOSE"]
  $LOAD_PATH.unshift "#{Dir.pwd}/lib"
  require_relative "../lizarb"

  Lizarb.setup app_type: :project, app: ENV["APP"]
  Lizarb.app
  Lizarb.call

  App.call ARGV

  Lizarb.exit
end

.reload(&block) ⇒ Object



471
472
473
474
475
476
477
478
# File 'lib/lizarb.rb', line 471

def reload &block
  @mutex.synchronize do
    loaders.map &:reload
    yield if block_given?
  end

  true
end

.require_liza_and_systemsObject



248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
# File 'lib/lizarb.rb', line 248

def require_liza_and_systems
  log "  Lizarb.#{__method__}" if defined? $log_boot_low

  require "zeitwerk"
  log "    required Zeitwerk" if defined? $log_boot_lower

  require "liza"
  log "    required Liza" if defined? $log_boot_lower

  # loaders[0] first loads Liza, then each System class

  log "    Zeitwerk loaders [0] first loads Liza, then each System class" if defined? $log_boot_lower

  loaders << loader = Zeitwerk::Loader.new
  loader.tag = Liza.to_s

  # collapse Liza paths

  # ORDER MATTERS: IGNORE, COLLAPSE, PUSH
  loader.collapse "#{Liza.source_location_radical}/**/*"
  loader.push_dir "#{Liza.source_location_radical}", namespace: Liza

  # loader setup

  log "      Setting up" if $log_boot_lower
  loader.enable_reloading
  log "        loader.enable_reloading" if $log_boot_lowest
  loader.setup
  log "        loader.setup" if $log_boot_lowest

  # bundle each System gem

  Bundler.require :systems

  # load each System class

  log "      App.systems is Hash containing all system classes" if defined? $log_boot_lowest
  App.systems.keys.each do |k|
    key = "#{k}_system"

    require_system key
    klass = Object.const_get key.camelize

    App.systems[k] = klass
  end

  App.systems.freeze

  # loaders[1] first loads each System, then the App
  log "    Zeitwerk loaders [1] first loads each System, then the App" if defined? $log_boot_lower
  loaders << loader = Zeitwerk::Loader.new

  # collapse each System paths

  App.systems.each do |k, klass|
    # ORDER MATTERS: IGNORE, COLLAPSE, PUSH
    loader.collapse "#{klass.source_location_radical}/**/*"
    loader.push_dir "#{klass.source_location_radical}", namespace: klass
  end

  # cherrypick App paths

  app_dir = App.path
  if app_dir
    log "      Application Directory: #{app_dir}" if defined? $log_boot_lowest
    list = Dir["#{app_dir}/*"].to_set
  end

  if app_dir.nil? || list.empty?
    log "      Application Directory is empty" if defined? $log_boot_lowest
  else
    log "      Application Directory found #{list.count} items to collapse" if defined? $log_boot_lowest

    to_collapse = []

    App.systems.each do |k, klass|
      next if klass.subs.empty?
      box_dir  = "#{app_dir}/#{k}"
      box_file = "#{box_dir}_box.rb"

      if !list.include? box_file
        log "        Missd box file    #{box_file}! Generating it"

        File.write box_file, <<-RUBY
class #{k.to_s.camelize}Box < #{k.to_s.camelize}System::#{k.to_s.camelize}Box

end
        RUBY
      end

      log "        Found box file    #{box_file}" if defined? $log_boot_lowest
      to_collapse << box_file

      if !list.include? box_dir
        log "        Missd controllers #{box_dir}" if defined? $log_boot_lowest
      else
        log "        Found controllers #{box_dir}" if defined? $log_boot_lowest
        to_collapse << box_dir
      end

    end

    # ORDER MATTERS: IGNORE, COLLAPSE, PUSH
    to_ignore = list - to_collapse
    to_ignore.each do |file|
      log "      Ignoring   #{file}" if $log_boot_lowest
      loader.ignore file
    end

    to_collapse.each do |path|
      log "      Collapsing #{path}" if $log_boot_lowest
      if path.end_with? ".rb"
        loader.collapse path
      else
        loader.collapse "#{path}/**/*"
      end
    end
    loader.collapse "#{app_dir}/*"

    loader.push_dir app_dir, namespace: Object
  end

  # loader setup

  log "      Setting up" if $log_boot_lower
  loader.enable_reloading
  log "        loader.enable_reloading" if $log_boot_lowest
  loader.setup
  log "        loader.setup" if $log_boot_lowest

  # App connects to systems

  loaders.map &:eager_load
  log "    All Zeitwerk loaders have been eager loaded" if defined? $log_boot_lower
end

.require_system(key) ⇒ Object

systems



393
394
395
396
397
398
399
# File 'lib/lizarb.rb', line 393

def require_system key
  log "        require '#{key}'" if defined? $log_boot_lowest
  require key
rescue LoadError => e
  def e.backtrace; []; end
  raise SystemNotFound, "FILE #{key}.rb not found on $LOAD_PATH", []
end

.ruby_supports_raise_cause?Boolean

Returns:

  • (Boolean)


40
41
42
# File 'lib/lizarb.rb', line 40

def ruby_supports_raise_cause?
  RUBY_ENGINE != "jruby"
end

.ruby_versionObject

Returns RUBY_VERSION as a Gem::Version



36
37
38
# File 'lib/lizarb.rb', line 36

def ruby_version
  @ruby_version ||= Gem::Version.new RUBY_VERSION
end

.script(*systems, mode: :code, folder: nil, gemfile: nil, log_handler: :output, log_boot: nil, log_level: nil, log: nil, &block) ⇒ Object



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/lizarb/script.rb', line 9

def self.script(
  *systems,
  mode: :code,
  folder: nil,
  gemfile: nil,
  log_handler: :output,
  log_boot: nil,
  log_level: nil,
  log: nil,
  &block
)
  log_boot = log if log
  log_boot ||= :normal

  log_level = log if log
  log_level ||= :normal

  $VERBOSE = ENV["VERBOSE"]
  require_relative "../lizarb"
  Lizarb.setup app_type: :script, app: "app_global"
  Lizarb.app do
    self.gemfile gemfile
    self.folder folder if folder
    self.log_boot log_boot
    self.log_level log_level
    self.mode mode
    system :dev
    systems.each do |key|
      system key
    end
  end
  Lizarb.call

  DevSystem::DevBox.configure :log do
    handler log_handler
  end
end

.setup(app_type:, app:) ⇒ Object

called from exe/lizarb



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/lizarb.rb', line 47

def setup(app_type: , app: )
  app ||= "app"
  @CUR_DIR = Dir.pwd
  begin
    @SPEC    = Gem::Specification.find_by_name("lizarb")
    @GEM_DIR = @SPEC.gem_dir
  rescue Gem::MissingSpecError
    @SPEC    = nil
    @GEM_DIR = @CUR_DIR
  end

  @IS_APP_DIR = File.file? "#{@CUR_DIR}/app.rb"
  @IS_LIZ_DIR = File.file? "#{@CUR_DIR}/lib/lizarb.rb"
  @IS_GEM_DIR = File.file? "#{@CUR_DIR}/lizarb.gemspec"

  @APP_DIR = @IS_APP_DIR ? @CUR_DIR : @GEM_DIR

  const_set :CUR_DIR, @CUR_DIR
  const_set :GEM_DIR, @GEM_DIR
  const_set :APP_DIR, @APP_DIR
  const_set :IS_APP_DIR, @IS_APP_DIR
  const_set :IS_LIZ_DIR, @IS_LIZ_DIR
  const_set :IS_GEM_DIR, @IS_GEM_DIR

  const_set :APP_TYPE, app_type

  app = "app_global" if not @IS_APP_DIR
  $APP = app

  lookup_and_load_core_ext
end

.thread_idObject



489
490
491
492
493
494
# File 'lib/lizarb.rb', line 489

def thread_id
  @thread_ids[thread_object_id] ||=
    @thread_ids_mutex.synchronize do
      @thread_ids.count
    end
end

.thread_object_idObject

thread management



482
483
484
# File 'lib/lizarb.rb', line 482

def thread_object_id
  Thread.current.object_id
end

.versionObject

Returns Lizarb::VERSION as a Gem::Version



31
32
33
# File 'lib/lizarb.rb', line 31

def version
  @version ||= Gem::Version.new VERSION
end