Class: Benry::CmdApp::ActionScope

Inherits:
Object
  • Object
show all
Defined in:
lib/benry/cmdapp.rb

Direct Known Subclasses

BuiltInAction

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(config, context = nil) ⇒ ActionScope

Returns a new instance of ActionScope.



500
501
502
503
# File 'lib/benry/cmdapp.rb', line 500

def initialize(config, context=nil)
  @config      = config
  @__context__ = context || CONTEXT_CLASS.new(config)
end

Class Method Details

.category(prefix, desc = nil, action: nil, alias_for: nil, &block) ⇒ Object



693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
# File 'lib/benry/cmdapp.rb', line 693

def self.category(prefix, desc=nil, action: nil, alias_for: nil, &block)
  #; [!mp1p5] raises DefinitionError if prefix is invalid.
  errmsg = __validate_prefix(prefix)
  errmsg == nil  or
    raise DefinitionError.new("category(#{prefix.inspect}): #{errmsg}")
  #; [!q01ma] raises DefinitionError if action or alias name is invalid.
  argstr, errmsg = __validate_action_and_alias(action, alias_for)
  errmsg == nil  or
    raise DefinitionError.new("`category(#{prefix.inspect}, #{argstr})`: #{errmsg}")
  #; [!kwst6] if block given...
  if block_given?()
    #; [!t8wwm] saves previous prefix data and restore them at end of block.
    prev = @__prefixdef__
    prefix = prev[0] + prefix if prev      # ex: "foo:" => "parent:foo:"
    @__prefixdef__ = [prefix, action, alias_for]
    #; [!j00pk] registers prefix and description, even if no actions defined.
    REGISTRY.category_add(prefix, desc)
    begin
      yield
      #; [!w52y5] raises DefinitionError if `action:` specified but target action not defined.
      if action
        @__prefixdef__[1] == nil  or
          raise DefinitionError.new("category(#{prefix.inspect}, action: #{action.inspect}): Target action not defined.")
      end
      #; [!zs3b5] raises DefinitionError if `alias_for:` specified but target action not defined.
      if alias_for
        @__prefixdef__[2] == nil  or
          raise DefinitionError.new("category(#{prefix.inspect}, alias_for: #{alias_for.inspect}): Target action of alias not defined.")
      end
    ensure
      @__prefixdef__ = prev
    end
  #; [!yqhm8] else...
  else
    #; [!tgux9] just stores arguments into class.
    @__prefixdef__ = [prefix, action, alias_for]
    #; [!ncskq] registers prefix and description, even if no actions defined.
    REGISTRY.category_add(prefix, desc)
  end
  nil
end

.current_prefixObject



688
689
690
691
# File 'lib/benry/cmdapp.rb', line 688

def self.current_prefix()
  #; [!2zt0f] returns current prefix name such as 'foo:bar:'.
  return @__prefixdef__ ? @__prefixdef__[0] : nil
end

.define_alias(alias_name, action_name, tag: nil, important: nil, hidden: nil) ⇒ Object



763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
# File 'lib/benry/cmdapp.rb', line 763

def self.define_alias(alias_name, action_name, tag: nil, important: nil, hidden: nil)
  #; [!tcpuz] just defines an alias when current prefix is nil.
  prefix = self.current_prefix()
  if prefix == nil
    nil
  #; [!b8ly2] supports array argument.
  elsif action_name.is_a?(Array)
    action_name[0] = prefix + action_name[0]
  #; [!c6duw] defines an alias with prefix when current prefix exist.
  else
    action_name = prefix + action_name
  end
  #; [!0dkrj] keyword arguments are passed to higher function.
  Benry::CmdApp.define_alias(alias_name, action_name, tag: tag, important: important, hidden: hidden)
end

.inherited(subclass) ⇒ Object



515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
# File 'lib/benry/cmdapp.rb', line 515

def self.inherited(subclass)
  subclass.class_eval do
    @__actiondef__ = nil
    @__prefixdef__ = nil
    #; [!8cck9] sets Proc object to `@action` in subclass.
    @action = lambda do |desc, usage: nil, detail: nil, description: nil, postamble: nil, tag: nil, important: nil, hidden: nil|
      #; [!r07i7] `@action.()` raises DefinitionError if called consectively.
      @__actiondef__ == nil  or
        raise DefinitionError.new("`@action.()` called without method definition (please define method for this action).")
      schema = _new_option_schema()
      #; [!34psw] `@action.()` stores arguments into `@__actiondef__`.
      kws = {usage: usage, detail: detail, description: description, postamble: postamble, tag: tag, important: important, hidden: hidden}
      @__actiondef__ = [desc, schema, kws]
    end
    #; [!en6n0] sets Proc object to `@option` in subclass.
    @option = lambda do |key, optstr, desc,
                         type: nil, rexp: nil, pattern: nil, enum: nil,
                         range: nil, value: nil, multiple: nil, detail: nil,
                         tag: nil, important: nil, hidden: nil, &callback|
      #; [!68hf8] raises DefinitionError if `@option.()` called without `@action.()`.
      @__actiondef__ != nil  or
        raise DefinitionError.new("`@option.()` called without `@action.()`.")
      #; [!2p98r] `@option.()` stores arguments into option schema object.
      schema = @__actiondef__[1]
      schema.add(key, optstr, desc,
                 type: type, rexp: rexp, pattern: pattern, enum: enum,
                 range: range, value: value, multiple: multiple, detail: detail,
                 tag: tag, important: important, hidden: hidden, &callback)
    end
    #; [!aiwns] `@copy_options.()` copies options from other action.
    @copy_options = lambda do |action_name, except: []|
      #; [!bfxye] `@copy_options.()` tries to find an action with current prefix.
       = nil
      curr_prefix = current_prefix()
      if curr_prefix
         = REGISTRY.(curr_prefix + action_name)
      end
      #; [!mhhn2] `@copy_options.()` raises DefinitionError when action not found.
       ||= REGISTRY.(action_name)
       != nil  or
        raise DefinitionError.new("@copy_options.(#{action_name.inspect}): Action not found.")
      #; [!0slo8] raises DefinitionError if `@copy_options.()` called without `@action.()`.
      @__actiondef__ != nil  or
        raise DefinitionError.new("@copy_options.(#{action_name.inspect}): Called without `@action.()`.")
      #; [!0qz0q] `@copy_options.()` stores arguments into option schema object.
      #; [!dezh1] `@copy_options.()` ignores help option automatically.
      schema = @__actiondef__[1]
      except = except.is_a?(Array) ? except : (except == nil ? [] : [except])
      schema.copy_from(.schema, except: [:help] + except)
    end
    #; [!7g5ug] sets Proc object to `@optionset` in subclass.
    @optionset = lambda do |*optionsets|
      #; [!o27kt] raises DefinitionError if `@optionset.()` called without `@action.()`.
      @__actiondef__ != nil  or
        raise DefinitionError.new("`@optionset.()` called without `@action.()`.")
      #; [!ky6sg] copies option items from optionset into schema object.
      schema = @__actiondef__[1]
      optionsets.each {|optset| optset.copy_into(schema) }
    end
  end
  nil
end

.method_added(method_symbol) ⇒ Object



587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
# File 'lib/benry/cmdapp.rb', line 587

def self.method_added(method_symbol)
  #; [!6frgx] do nothing if `@action.()` is not called.
  return false if @__actiondef__ == nil
  #; [!e3yjo] clears `@__actiondef__`.
  meth = method_symbol
  desc, schema, kws = @__actiondef__
  @__actiondef__ = nil
  #; [!jq4ex] raises DefinitionError if option defined but corresponding keyword arg is missing.
  errmsg = __validate_kwargs(method_symbol, schema)
  errmsg == nil  or
    raise DefinitionError,
          "def #{method_symbol}(): #{errmsg}"
  #; [!ejdlo] converts method name to action name.
  action = Util.method2action(meth)  # ex: :a__b_c => "a:b-c"
  #; [!w9qat] when `category()` called before defining action method...
  alias_p = false
  if @__prefixdef__
    prefix, prefix_action, alias_target = @__prefixdef__
    #; [!3pl1r] renames method name to new name with prefix.
    meth = "#{prefix.gsub(':', '__')}#{meth}".intern
    alias_method(meth, method_symbol)
    remove_method(method_symbol)
    #; [!mil2g] when action name matched to 'action:' kwarg of `category()`...
    if action == prefix_action
      #; [!hztpp] uses pefix name as action name.
      action = prefix.chomp(':')
      #; [!cydex] clears `action:` kwarg.
      @__prefixdef__[1] = nil
    #; [!8xsnw] when action name matched to `alias_for:` kwarg of `category()`...
    elsif action == alias_target
      #; [!iguvp] adds prefix name to action name.
      action = prefix + action
      alias_p = true
    #; [!wmevh] else...
    else
      #; [!9cyc2] adds prefix name to action name.
      action = prefix + action
    end
  #; [!y8lh0] else...
  else
    #; [!0ki5g] not add prefix to action name.
    prefix = alias_target = nil
  end
  #; [!dad1q] raises DefinitionError if action with same name already defined.
  #; [!ur8lp] raises DefinitionError if method already defined in parent or ancestor class.
  #; [!dj0ql] method override check is done with new method name (= prefixed name).
  (errmsg = __validate_action_method(action, meth, method_symbol)) == nil  or
    raise DefinitionError.new("def #{method_symbol}(): #{errmsg}")
  #; [!7fnh4] registers action metadata.
   = ActionMetadata.new(action, desc, schema, self, meth, **kws)
  REGISTRY.()
  #; [!lyn0z] registers alias metadata if necessary.
  if alias_p
    prefix != nil  or raise "** assertion failed: ailas_target=#{alias_target.inspect}"
     = AliasMetadata.new(prefix.chomp(':'), action, nil)
    REGISTRY.()
    #; [!4402s] clears `alias_for:` kwarg.
    @__prefixdef__[2] = nil
  end
  #; [!u0td6] registers prefix of action if not registered yet.
  REGISTRY.category_add_via_action(action)
  #
  return true    # for testing purpose
end

.optionset(&block) ⇒ Object



779
780
781
782
783
784
785
786
787
788
789
790
791
# File 'lib/benry/cmdapp.rb', line 779

def self.optionset(&block)
  #; [!us0g4] yields block with dummy action.
  #; [!1idwv] clears default option items.
  @action.("dummy action by optionset()")
  schema = @__actiondef__[1]
  schema.each.collect(&:key).each {|key| schema.delete(key) }
  yield
  #; [!sp3hk] clears `@__actiondef__` to make `@action.()` available.
  schema = @__actiondef__[1]
  @__actiondef__ = nil
  #; [!mwbyc] returns new OptionSet object which contains option items.
  return OptionSet.new.copy_from(schema)
end

Instance Method Details

#__clear_recursive_referenceObject

:nodoc:



505
506
507
508
509
# File 'lib/benry/cmdapp.rb', line 505

def __clear_recursive_reference()  # :nodoc:
  #; [!i68z0] clears instance var which refers context object.
  @__context__ = nil
  nil
end

#action_error(errmsg) ⇒ Object



817
818
819
820
# File 'lib/benry/cmdapp.rb', line 817

def action_error(errmsg)
  #; [!2m7d6] returns ActionError object.
  return ActionError.new(errmsg)
end

#at_end(&block) ⇒ Object



806
807
808
809
810
# File 'lib/benry/cmdapp.rb', line 806

def at_end(&block)
  #; [!3mqcz] registers proc object to context object.
  @__context__._add_end_block(block)
  nil
end

#inspectObject



511
512
513
# File 'lib/benry/cmdapp.rb', line 511

def inspect()
  return super.split().first() + ">"
end

#option_error(errmsg) ⇒ Object



812
813
814
815
# File 'lib/benry/cmdapp.rb', line 812

def option_error(errmsg)
  #; [!engp2] returns OptionError object.
  return OptionError.new(errmsg)
end

#run_action(action_name, *args, **kwargs) ⇒ Object



800
801
802
803
804
# File 'lib/benry/cmdapp.rb', line 800

def run_action(action_name, *args, **kwargs)
  #; [!uwi68] runs action and returns true.
  ctx = (@__context__ ||= CONTEXT_CLASS.new)
  return ctx.invoke_action(action_name, args, kwargs, once: false)
end

#run_once(action_name, *args, **kwargs) ⇒ Object



793
794
795
796
797
798
# File 'lib/benry/cmdapp.rb', line 793

def run_once(action_name, *args, **kwargs)
  #; [!nqjxk] runs action and returns true if not runned ever.
  #; [!wcyut] not run action and returns false if already runned.
  ctx = (@__context__ ||= CONTEXT_CLASS.new)
  return ctx.invoke_action(action_name, args, kwargs, once: true)
end