module Guard # The interactor reads user input and triggers # specific action upon them unless its locked. # # Currently the following actions are implemented: # # - stop, quit, exit, s, q, e => Exit Guard # - reload, r, z => Reload Guard # - pause, p => Pause Guard # - Everything else => Run all # # It's also possible to scope `reload` and `run all` actions to only a specified group or a guard. # # @example `backend reload` will only reload backend group # @example `spork reload` will only reload rspec guard # @example `jasmine` will only run all jasmine specs # class Interactor STOP_ACTIONS = %w[stop quit exit s q e] RELOAD_ACTIONS = %w[reload r z] PAUSE_ACTIONS = %w[pause p] # Start the interactor in its own thread. # def start return if ENV["GUARD_ENV"] == 'test' if !@thread || @thread.stop? @thread = Thread.new do while entry = $stdin.gets.chomp scopes, action = extract_scopes_and_action(entry) case action when :stop ::Guard.stop when :pause ::Guard.pause when :reload ::Guard::Dsl.reevaluate_guardfile if scopes.empty? ::Guard.reload(scopes) when :run_all ::Guard.run_all(scopes) end end end end end # Extract guard or group scope and action from Interactor entry # # @example `spork reload` will only reload rspec # @example `jasmine` will only run all jasmine specs # # @param [String] Interactor entry gets from $stdin # @return [Array] entry group or guard scope hash and action def extract_scopes_and_action(entry) scopes = {} entries = entry.split(' ') case entries.length when 1 unless action = action_from_entry(entries[0]) scopes = scopes_from_entry(entries[0]) end when 2 scopes = scopes_from_entry(entries[0]) action = action_from_entry(entries[1]) end action ||= :run_all [scopes, action] end # Extract guard or group scope from entry if valid # # @param [String] Interactor entry gets from $stdin # @return [Hash] An hash with a guard or a group scope def scopes_from_entry(entry) scopes = {} if guard = ::Guard.guards(entry) scopes[:guard] = guard end if group = ::Guard.groups(entry) scopes[:group] = group end scopes end # Extract action from entry if an existing action is present # # @param [String] Interactor entry gets from $stdin # @return [Symbol] A guard action def action_from_entry(entry) if STOP_ACTIONS.include?(entry) :stop elsif RELOAD_ACTIONS.include?(entry) :reload elsif PAUSE_ACTIONS.include?(entry) :pause end end # Kill interactor thread if not current # def stop_if_not_current unless Thread.current == @thread @thread.kill end end end end