diff --git a/examples/multi_with_inset.rb b/examples/multi_with_inset.rb new file mode 100644 index 0000000..01f6e93 --- /dev/null +++ b/examples/multi_with_inset.rb @@ -0,0 +1,26 @@ +# encoding: utf-8 + +require 'tty-spinner' + +spinners = TTY::Spinner::Multi.new(message: "[:spinner] Top level spinner") + +sp1 = spinners.register "[:spinner] one" +sp2 = spinners.register "[:spinner] two" +sp3 = spinners.register "[:spinner] three" + +spinners.auto_spin +sp1.auto_spin +sp2.auto_spin +sp3.auto_spin + +sleep(2) + +sp1.success +sleep 1 +sp2.success + +sleep 1 + +sp3.error + +spinners.error diff --git a/lib/tty/spinner.rb b/lib/tty/spinner.rb index ec72fd8..19b4eb2 100644 --- a/lib/tty/spinner.rb +++ b/lib/tty/spinner.rb @@ -272,7 +272,7 @@ def stop(stop_message = '') end write(data, true) - write("\n", false) unless @clear + write("\n", false) unless @clear || @multispinner ensure @state = :stopped @done = true @@ -372,7 +372,11 @@ def execute_on_line def write(data, clear_first = false) execute_on_line do output.print(ECMA_CSI + '1' + ECMA_CHA) if clear_first - output.print(data) + + # If there's a top level spinner, print with inset + characters_in = @multispinner.nil? ? "" : @multispinner.line_inset(self) + + output.print(characters_in + data) output.flush end end diff --git a/lib/tty/spinner/multi.rb b/lib/tty/spinner/multi.rb index b5b43d0..c19f847 100644 --- a/lib/tty/spinner/multi.rb +++ b/lib/tty/spinner/multi.rb @@ -18,11 +18,17 @@ class Multi def_delegators :@spinners, :each, :empty?, :length def initialize(options = {}) + message = options.delete(:message) @options = options @create_spinner_lock = Mutex.new @spinners = [] + + unless message.nil? + @master_spinner = register(message) + end + @callbacks = { success: [], error: [], @@ -47,6 +53,12 @@ def register(pattern, options = {}) spinner end + def auto_spin + raise "No top level message given" if @master_spinner.nil? + + @master_spinner.auto_spin + end + # Find relative offset position to which to move the current cursor # # The position is found among the registered spinners given the current @@ -69,6 +81,16 @@ def count_line_offset(index) end end + # Find the number of characters to move into the line before printing the + # spinner + # + # @api public + def line_inset(spinner) + return " " if @master_spinner && spinner != @master_spinner + + "" + end + # Check if all spinners are done # # @return [Boolean] @@ -108,6 +130,7 @@ def stop # # @api public def success + @master_spinner.success if @master_spinner @spinners.dup.each(&:success) emit :success end @@ -116,6 +139,7 @@ def success # # @api public def error + @master_spinner.error if @master_spinner @spinners.dup.each(&:error) emit :error end diff --git a/spec/unit/spin_spec.rb b/spec/unit/spin_spec.rb index 0ca7d43..d050608 100644 --- a/spec/unit/spin_spec.rb +++ b/spec/unit/spin_spec.rb @@ -47,6 +47,7 @@ it "spins with newline when it has a MultiSpinner" do multi_spinner = double("MultiSpinner") allow(multi_spinner).to receive(:count_line_offset).and_return(1, 1, 2, 1) + allow(multi_spinner).to receive(:line_inset).and_return("") spinner = TTY::Spinner.new(output: output, interval: 100) spinner.add_multispinner(multi_spinner, 0)