text: //
  //  RACCommand.h
  //  ReactiveCocoa
  //
  //  Created by Josh Abernathy on 3/3/12.
  //  Copyright (c) 2012 GitHub, Inc. All rights reserved.
  //
  
  #import <Foundation/Foundation.h>
  
  @class RACSignal;
  
  /// The domain for errors originating within `RACCommand`.
  extern NSString * const RACCommandErrorDomain;
  
  /// -execute: was invoked while the command was disabled.
  extern const NSInteger RACCommandErrorNotEnabled;
  
  /// A `userInfo` key for an error, associated with the `RACCommand` that the
  /// error originated from.
  ///
  /// This is included only when the error code is `RACCommandErrorNotEnabled`.
  extern NSString * const RACUnderlyingCommandErrorKey;
  
  /// A command is a signal triggered in response to some action, typically
  /// UI-related.
  @interface RACCommand : NSObject
  
  /// A signal of the signals returned by successful invocations of -execute:
  /// (i.e., while the receiver is `enabled`).
  ///
  /// Errors will be automatically caught upon the inner signals, and sent upon
  /// `errors` instead. If you _want_ to receive inner errors, use -execute: or
  /// -[RACSignal materialize].
  /// 
  /// Only executions that begin _after_ subscription will be sent upon this
  /// signal. All inner signals will arrive upon the main thread.
  @property (nonatomic, strong, readonly) RACSignal *executionSignals;
  
  /// A signal of whether this command is currently executing.
  ///
  /// This will send YES whenever -execute: is invoked and the created signal has
  /// not yet terminated. Once all executions have terminated, `executing` will
  /// send NO.
  ///
  /// This signal will send its current value upon subscription, and then all
  /// future values on the main thread.
  @property (nonatomic, strong, readonly) RACSignal *executing;
  
  /// A signal of whether this command is able to execute.
  ///
  /// This will send NO if:
  ///
  ///  - The command was created with an `enabledSignal`, and NO is sent upon that
  ///    signal, or
  ///  - `allowsConcurrentExecution` is NO and the command has started executing.
  ///
  /// Once the above conditions are no longer met, the signal will send YES.
  ///
  /// This signal will send its current value upon subscription, and then all
  /// future values on the main thread.
  @property (nonatomic, strong, readonly) RACSignal *enabled;
  
  /// Forwards any errors that occur within signals returned by -execute:.
  ///
  /// When an error occurs on a signal returned from -execute:, this signal will
  /// send the associated NSError value as a `next` event (since an `error` event
  /// would terminate the stream).
  ///
  /// After subscription, this signal will send all future errors on the main
  /// thread.
  @property (nonatomic, strong, readonly) RACSignal *errors;
  
  /// Whether the command allows multiple executions to proceed concurrently.
  ///
  /// The default value for this property is NO.
  @property (atomic, assign) BOOL allowsConcurrentExecution;
  
  /// Invokes -initWithSignalBlock:enabled: with a nil `enabledSignal`.
  - (id)initWithSignalBlock:(RACSignal * (^)(id input))signalBlock;
  
  /// Initializes a command that is conditionally enabled.
  ///
  /// This is the designated initializer for this class.
  ///
  /// enabledSignal - A signal of BOOLs which indicate whether the command should
  ///                 be enabled. `enabled` will be based on the latest value sent
  ///                 from this signal. Before any values are sent, `enabled` will
  ///                 default to YES. This argument may be nil.
  /// signalBlock   - A block which will map each input value (passed to -execute:)
  ///                 to a signal of work. The returned signal will be multicasted
  ///                 to a replay subject, sent on `executionSignals`, then
  ///                 subscribed to synchronously. Neither the block nor the
  ///                 returned signal may be nil.
  - (id)initWithEnabled:(RACSignal *)enabledSignal signalBlock:(RACSignal * (^)(id input))signalBlock;
  
  /// If the receiver is enabled, this method will:
  ///
  ///  1. Invoke the `signalBlock` given at the time of initialization.
  ///  2. Multicast the returned signal to a RACReplaySubject.
  ///  3. Send the multicasted signal on `executionSignals`.
  ///  4. Subscribe (connect) to the original signal on the main thread.
  ///
  /// input - The input value to pass to the receiver's `signalBlock`. This may be
  ///         nil.
  ///
  /// Returns the multicasted signal, after subscription. If the receiver is not
  /// enabled, returns a signal that will send an error with code
  /// RACCommandErrorNotEnabled.
  - (RACSignal *)execute:(id)input;
  
  @end
  
  @interface RACCommand (Unavailable)
  
  @property (atomic, readonly) BOOL canExecute __attribute__((unavailable("Use the 'enabled' signal instead")));
  
  + (instancetype)command __attribute__((unavailable("Use -initWithSignalBlock: instead")));
  + (instancetype)commandWithCanExecuteSignal:(RACSignal *)canExecuteSignal __attribute__((unavailable("Use -initWithEnabled:signalBlock: instead")));
  - (id)initWithCanExecuteSignal:(RACSignal *)canExecuteSignal __attribute__((unavailable("Use -initWithEnabled:signalBlock: instead")));
  - (RACSignal *)addSignalBlock:(RACSignal * (^)(id value))signalBlock __attribute__((unavailable("Pass the signalBlock to -initWithSignalBlock: instead")));
  
  @end
  