natty-ui 0.31.0 → 0.33.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.yardopts +0 -1
- data/README.md +2 -2
- data/examples/hbars.rb +3 -3
- data/examples/named-colors.rb +8 -6
- data/examples/sh.rb +17 -0
- data/examples/tasks.rb +4 -4
- data/examples/vbars.rb +4 -4
- data/lib/natty-ui/attributes.rb +7 -3
- data/lib/natty-ui/choice.rb +1 -0
- data/lib/natty-ui/dumb_choice.rb +1 -0
- data/lib/natty-ui/dumb_options.rb +1 -0
- data/lib/natty-ui/element.rb +28 -3
- data/lib/natty-ui/features.rb +99 -72
- data/lib/natty-ui/framed.rb +4 -4
- data/lib/natty-ui/ls_renderer.rb +2 -0
- data/lib/natty-ui/options.rb +1 -0
- data/lib/natty-ui/progress.rb +7 -2
- data/lib/natty-ui/section.rb +1 -1
- data/lib/natty-ui/shell_renderer.rb +91 -0
- data/lib/natty-ui/table_renderer.rb +2 -0
- data/lib/natty-ui/temporary.rb +3 -4
- data/lib/natty-ui/theme.rb +1 -0
- data/lib/natty-ui/version.rb +1 -1
- data/lib/natty-ui/width_finder.rb +2 -0
- data/lib/natty-ui.rb +10 -12
- metadata +5 -4
- data/lib/natty-ui/shell_command.rb +0 -132
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 79e64cb2489dcf9efe4066e4f95252284f9227aafa4a77edd0d50f307b255cf2
|
|
4
|
+
data.tar.gz: 7ec6f014b300740062e816fa9c787ff79b3fb7ce68e4b1c2d6967ae6eb58b53d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 86abb66230c52bd8863aec983435b434e7272003a12db631cb0b46af9db938ffc16f3ba1f987dad53a10f9ff4393e5f4bf403d04b813bb68b4b189c5bf0b2860
|
|
7
|
+
data.tar.gz: 34afc008cdec26384f7f20b7be6830a5be511147cfaef831d8e6869f858219ffeaea394ec8718ceb7513cfa3aaee19a852bb70d2b2ef641bc5880ca79d8de38d
|
data/.yardopts
CHANGED
data/README.md
CHANGED
|
@@ -4,7 +4,7 @@ This is the beautiful, nice, nifty, fancy, neat, pretty, cool, rich, lovely, nat
|
|
|
4
4
|
|
|
5
5
|
- Gem: [rubygems.org](https://rubygems.org/gems/natty-ui)
|
|
6
6
|
- Source: [codeberg.org](https://codeberg.org/mblumtritt/natty-ui)
|
|
7
|
-
- Help: [rubydoc.info](https://rubydoc.info/gems/natty-ui/
|
|
7
|
+
- Help: [rubydoc.info](https://rubydoc.info/gems/natty-ui/index)
|
|
8
8
|
|
|
9
9
|
## Features
|
|
10
10
|
|
|
@@ -28,7 +28,7 @@ This is the beautiful, nice, nifty, fancy, neat, pretty, cool, rich, lovely, nat
|
|
|
28
28
|
|
|
29
29
|
## Help
|
|
30
30
|
|
|
31
|
-
📕 See the [online help](https://rubydoc.info/gems/natty-ui/
|
|
31
|
+
📕 See the [online help](https://rubydoc.info/gems/natty-ui/index) and have a look at the [examples](./examples/) directory to learn from code.
|
|
32
32
|
|
|
33
33
|
### Run Examples
|
|
34
34
|
|
data/examples/hbars.rb
CHANGED
|
@@ -11,7 +11,7 @@ ui.message '[b]ᓚᕠᗢ NattyUI[/b] [i green]Print Horizontal Bars[/]' do
|
|
|
11
11
|
|
|
12
12
|
ui.space
|
|
13
13
|
ui.hbars values, style: :green, normalize: true, width: 0.5, min: 10
|
|
14
|
-
ui.puts
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
ui.puts <<~INFO, eol: false
|
|
15
|
+
These are the same values but [i]normalized[/i] and printed in half width.
|
|
16
|
+
INFO
|
|
17
17
|
end
|
data/examples/named-colors.rb
CHANGED
|
@@ -3,13 +3,15 @@
|
|
|
3
3
|
require_relative '../lib/natty-ui'
|
|
4
4
|
|
|
5
5
|
ui.message '[b]ᓚᕠᗢ NattyUI[/b] [i green]Named Colors Support[/]' do
|
|
6
|
-
ui.
|
|
7
|
-
|
|
8
|
-
NattyUI supports a series of named color values,
|
|
9
|
-
|
|
6
|
+
ui.space
|
|
7
|
+
ui.puts <<~INFO, eol: false
|
|
8
|
+
NattyUI supports a series of named color values,
|
|
9
|
+
such as those supported by Kitty.
|
|
10
10
|
INFO
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
|
|
12
|
+
ui.space
|
|
13
|
+
ui.information 'Note' do
|
|
14
|
+
ui.puts 'Not all terminal emulators support true-colors.'
|
|
13
15
|
end
|
|
14
16
|
|
|
15
17
|
ui.space
|
data/examples/sh.rb
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../lib/natty-ui'
|
|
4
|
+
|
|
5
|
+
ui.message '[b]ᓚᕠᗢ NattyUI[/b] [i green]Call Shell[/]' do
|
|
6
|
+
ui.space
|
|
7
|
+
ui.message 'Pipe this file to [i]cat[/i]; limit to five lines' do
|
|
8
|
+
File.open(__FILE__) do |file|
|
|
9
|
+
ui.run 'cat', input: file, preserve_spaces: true, max_lines: 5
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
ui.space
|
|
14
|
+
ui.message 'Call [i]cat[/i] with invalid option' do
|
|
15
|
+
ui.sh 'cat', '-?'
|
|
16
|
+
end
|
|
17
|
+
end
|
data/examples/tasks.rb
CHANGED
|
@@ -17,9 +17,9 @@ ui.message '[b]ᓚᕠᗢ NattyUI[/b] [i green]Tasks[/]' do
|
|
|
17
17
|
|
|
18
18
|
ui.space
|
|
19
19
|
ui.task 'Actualize Reading List' do
|
|
20
|
-
ui.puts
|
|
20
|
+
ui.puts 'This is a simple which actualizes the book reading list.'
|
|
21
21
|
|
|
22
|
-
ui.task
|
|
22
|
+
ui.task 'Connect to Library' do
|
|
23
23
|
do_something
|
|
24
24
|
ui.mark 'Server Found', mark: :checkmark
|
|
25
25
|
ui.task('Login...') { do_something_heavy }
|
|
@@ -36,14 +36,14 @@ ui.message '[b]ᓚᕠᗢ NattyUI[/b] [i green]Tasks[/]' do
|
|
|
36
36
|
|
|
37
37
|
ui.task('Disconnect from Library') { do_something_heavy }
|
|
38
38
|
|
|
39
|
-
ui.progress
|
|
39
|
+
ui.progress 'Read Cover Images', max: 11 do |progress|
|
|
40
40
|
while progress.value < progress.max
|
|
41
41
|
do_something
|
|
42
42
|
progress.step
|
|
43
43
|
end
|
|
44
44
|
end
|
|
45
45
|
|
|
46
|
-
ui.pin
|
|
46
|
+
ui.pin 'New Books Marked', mark: :checkmark
|
|
47
47
|
|
|
48
48
|
ui.task('Optimize Database') { do_something_heavy }
|
|
49
49
|
|
data/examples/vbars.rb
CHANGED
|
@@ -32,8 +32,8 @@ ui.message '[b]ᓚᕠᗢ NattyUI[/b] [i green]Print Vertical Bars[/]' do
|
|
|
32
32
|
|
|
33
33
|
ui.space
|
|
34
34
|
ui.vbars values, style: :green, normalize: true, bar_width: 2
|
|
35
|
-
ui.puts
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
ui.puts <<~INFO, eol: false
|
|
36
|
+
These are the same values but [i]normalized[/i]
|
|
37
|
+
and printed with a fixed bar width.
|
|
38
|
+
INFO
|
|
39
39
|
end
|
data/lib/natty-ui/attributes.rb
CHANGED
|
@@ -13,10 +13,10 @@ module NattyUI
|
|
|
13
13
|
def merge!(**attributes) = attributes.empty? ? self : _assign(attributes)
|
|
14
14
|
alias assign merge!
|
|
15
15
|
|
|
16
|
-
#
|
|
16
|
+
# @private
|
|
17
17
|
def to_hash = _store({})
|
|
18
18
|
|
|
19
|
-
#
|
|
19
|
+
# @private
|
|
20
20
|
def to_h(&block) = block ? _store({}).to_h(&block) : _store({})
|
|
21
21
|
|
|
22
22
|
private
|
|
@@ -506,7 +506,7 @@ module NattyUI
|
|
|
506
506
|
end
|
|
507
507
|
end
|
|
508
508
|
|
|
509
|
-
#
|
|
509
|
+
# @private
|
|
510
510
|
# @return [String, nil]
|
|
511
511
|
attr_reader :border_chars
|
|
512
512
|
|
|
@@ -549,11 +549,14 @@ module NattyUI
|
|
|
549
549
|
@attributes = @attributes.dup
|
|
550
550
|
end
|
|
551
551
|
end
|
|
552
|
+
|
|
552
553
|
private_constant :WithAttributes
|
|
553
554
|
|
|
554
555
|
module TextWithAttributes
|
|
555
556
|
include WithAttributes
|
|
557
|
+
|
|
556
558
|
attr_reader :text
|
|
559
|
+
|
|
557
560
|
def empty? = @text.empty?
|
|
558
561
|
alias _to_s to_s
|
|
559
562
|
private :_to_s
|
|
@@ -585,5 +588,6 @@ module NattyUI
|
|
|
585
588
|
@text = @text.map(&:dup)
|
|
586
589
|
end
|
|
587
590
|
end
|
|
591
|
+
|
|
588
592
|
private_constant :TextWithAttributes
|
|
589
593
|
end
|
data/lib/natty-ui/choice.rb
CHANGED
data/lib/natty-ui/dumb_choice.rb
CHANGED
data/lib/natty-ui/element.rb
CHANGED
|
@@ -8,10 +8,10 @@ module NattyUI
|
|
|
8
8
|
class Element
|
|
9
9
|
include Features
|
|
10
10
|
|
|
11
|
-
#
|
|
11
|
+
# @private
|
|
12
12
|
def columns = @parent.columns - @prefix_width - @suffix_width
|
|
13
13
|
|
|
14
|
-
#
|
|
14
|
+
# @private
|
|
15
15
|
def puts(*objects, **options)
|
|
16
16
|
if @prefix
|
|
17
17
|
options[:prefix] = "#{@prefix}#{options[:prefix]}"
|
|
@@ -32,7 +32,7 @@ module NattyUI
|
|
|
32
32
|
self
|
|
33
33
|
end
|
|
34
34
|
|
|
35
|
-
#
|
|
35
|
+
# @private
|
|
36
36
|
alias to_s inspect
|
|
37
37
|
|
|
38
38
|
alias _to_s to_s
|
|
@@ -46,13 +46,32 @@ module NattyUI
|
|
|
46
46
|
end
|
|
47
47
|
end
|
|
48
48
|
|
|
49
|
+
# Methods for elements with status like {ProgressHelper}, {Section}, {Task}.
|
|
50
|
+
#
|
|
49
51
|
module WithStatus
|
|
52
|
+
# @return [Symbol, nil] element's current status
|
|
50
53
|
attr_reader :status
|
|
54
|
+
|
|
55
|
+
# @attribute [r] active?
|
|
56
|
+
# @return [true, false] whether the element is still active
|
|
51
57
|
def active? = @status.nil?
|
|
58
|
+
|
|
59
|
+
# @attribute [r] closed?
|
|
60
|
+
# @return [true, false] whether the element is closed
|
|
52
61
|
def closed? = !active?
|
|
62
|
+
|
|
63
|
+
# @attribute [r] closed?
|
|
64
|
+
# @return [true, false] whether the element is completed
|
|
53
65
|
def ok? = @state == :ok
|
|
66
|
+
|
|
67
|
+
# @attribute [r] failed?
|
|
68
|
+
# @return [true, false] whether the element is completed with failure
|
|
54
69
|
def failed? = @state == :failed
|
|
55
70
|
|
|
71
|
+
# Close the element.
|
|
72
|
+
#
|
|
73
|
+
# @param [#to_s] text optional message
|
|
74
|
+
# @return [Element] itself
|
|
56
75
|
def ok(*text)
|
|
57
76
|
return self if @state
|
|
58
77
|
text = [@title] if text.empty? && @title
|
|
@@ -62,6 +81,12 @@ module NattyUI
|
|
|
62
81
|
end
|
|
63
82
|
alias done ok
|
|
64
83
|
|
|
84
|
+
# Close the element with a failure.
|
|
85
|
+
#
|
|
86
|
+
# @param text [#to_s] optional message
|
|
87
|
+
# @yield optionally, when block is given
|
|
88
|
+
# @yieldparam failed [Section] see {Features.failed}
|
|
89
|
+
# @return [Element] itself
|
|
65
90
|
def failed(*text, &block)
|
|
66
91
|
return self if @state
|
|
67
92
|
_failed
|
data/lib/natty-ui/features.rb
CHANGED
|
@@ -104,11 +104,11 @@ module NattyUI
|
|
|
104
104
|
ansi: Terminal.ansi?,
|
|
105
105
|
ignore_newline: ignore_newline
|
|
106
106
|
)
|
|
107
|
-
|
|
107
|
+
tail = options[:tail] and lines = lines.to_a.last(tail)
|
|
108
108
|
@__eol ||= Terminal.ansi? ? "\e[m\n" : "\n"
|
|
109
109
|
|
|
110
110
|
if (align = options[:align]).nil?
|
|
111
|
-
lines.each do |line|
|
|
111
|
+
lines.each do |line, _|
|
|
112
112
|
Terminal.print(prefix, line, suffix, @__eol, bbcode: false)
|
|
113
113
|
@lines_written += 1
|
|
114
114
|
prefix, prefix_next = prefix_next, nil if prefix_next
|
|
@@ -578,29 +578,65 @@ module NattyUI
|
|
|
578
578
|
block ? __with(progress, &block) : progress
|
|
579
579
|
end
|
|
580
580
|
|
|
581
|
-
#
|
|
582
|
-
#
|
|
583
|
-
# @
|
|
584
|
-
#
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
581
|
+
# Execute a program.
|
|
582
|
+
#
|
|
583
|
+
# @example Execute a simple command
|
|
584
|
+
# ui.sh 'ls'
|
|
585
|
+
#
|
|
586
|
+
# @example Execute a command wih arguments
|
|
587
|
+
# ret = ui.sh('curl', '--version')
|
|
588
|
+
# raise('Curl not found') unless ret&.success?
|
|
589
|
+
#
|
|
590
|
+
# @example Execute shell commands
|
|
591
|
+
# ui.sh "mkdir 'test' && cd 'test'"
|
|
592
|
+
#
|
|
593
|
+
# @example Execute a command with environment variables
|
|
594
|
+
# ui.sh({'ENV' => 'test'}, 'rails')
|
|
595
|
+
#
|
|
596
|
+
# @see run
|
|
597
|
+
#
|
|
598
|
+
# @param cmd (see run)
|
|
599
|
+
# @param preserve_spaces (see run)
|
|
600
|
+
# @param options (see run)
|
|
601
|
+
# @return [Process::Status]
|
|
602
|
+
# when command was executed
|
|
603
|
+
# @return [nil]
|
|
604
|
+
# in error case (like command not found)
|
|
605
|
+
def sh(*cmd, preserve_spaces: false, **options)
|
|
606
|
+
ShellRenderer.sh(self, cmd, options, preserve_spaces)
|
|
607
|
+
end
|
|
608
|
+
|
|
609
|
+
# Execute a shell program and return output. Limit the lines displayed.
|
|
610
|
+
#
|
|
611
|
+
# @example Capture output and error
|
|
612
|
+
# status, out, err = ui.run('ls ./ && ls ./this_does_not_exist')
|
|
613
|
+
# # => #<Process::Status: pid 25562 exit 1>
|
|
614
|
+
# # => [...] # the output of first `ls`
|
|
615
|
+
# # => ["ls: ./this_does_not_exist: No such file or directory"]
|
|
616
|
+
#
|
|
617
|
+
# @see sh
|
|
618
|
+
#
|
|
619
|
+
# @param cmd [String]
|
|
620
|
+
# command and optional arguments
|
|
621
|
+
# @param preserve_spaces [true,false]
|
|
622
|
+
# whether the spaces and tabs of the output should be preserve
|
|
623
|
+
# @param max_lines [Integer]
|
|
624
|
+
# limit of displayed lines
|
|
625
|
+
# @param options [Hash] executions options
|
|
626
|
+
# @return [[Process::Status, Array<String>, Array<String>]]
|
|
627
|
+
# process status, output and error output when command was executed
|
|
628
|
+
# @return [nil]
|
|
629
|
+
# in error case (like command not found)
|
|
630
|
+
def run(*cmd, preserve_spaces: false, max_lines: 10, **options)
|
|
631
|
+
result =
|
|
632
|
+
ShellRenderer.run(
|
|
633
|
+
self,
|
|
634
|
+
cmd,
|
|
635
|
+
options,
|
|
636
|
+
preserve_spaces,
|
|
637
|
+
max_lines.clamp(1, Terminal.rows)
|
|
602
638
|
)
|
|
603
|
-
|
|
639
|
+
result if result[0]
|
|
604
640
|
end
|
|
605
641
|
|
|
606
642
|
#
|
|
@@ -749,28 +785,20 @@ module NattyUI
|
|
|
749
785
|
# # Italian, Polish, Portuguese, Romanian, Spanish and Swedish.
|
|
750
786
|
#
|
|
751
787
|
# @overload await(yes: 'Enter', no: 'Esc')
|
|
752
|
-
# @param yes [String, Enumerable<String>]
|
|
753
|
-
# key code/s a user can input to return positive result
|
|
754
|
-
# @param no [String, Enumerable<String>]
|
|
755
|
-
# key code/s a user can input to return negative resault
|
|
756
|
-
#
|
|
757
|
-
# @return [true, false]
|
|
758
|
-
# wheter the user inputs a positive result
|
|
759
788
|
#
|
|
760
789
|
# @overload await(yes: 'Enter', no: 'Esc', &block)
|
|
761
|
-
# @param yes [String, Enumerable<String>]
|
|
762
|
-
# key code/s a user can input to return positive result
|
|
763
|
-
# @param no [String, Enumerable<String>]
|
|
764
|
-
# key code/s a user can input to return negative resault
|
|
765
|
-
#
|
|
766
790
|
# @yieldparam temp [Temporary]
|
|
767
791
|
# temporary displayed section (section will be erased after input)
|
|
768
792
|
#
|
|
769
|
-
#
|
|
770
|
-
#
|
|
771
|
-
#
|
|
772
|
-
#
|
|
793
|
+
# @param yes [String, Enumerable<String>]
|
|
794
|
+
# key code/s a user can input to return positive result
|
|
795
|
+
# @param no [String, Enumerable<String>]
|
|
796
|
+
# key code/s a user can input to return negative resault
|
|
773
797
|
#
|
|
798
|
+
# @return [true, false]
|
|
799
|
+
# whether the user inputs a positive result
|
|
800
|
+
# @return [nil]
|
|
801
|
+
# in error case
|
|
774
802
|
def await(yes: 'Enter', no: 'Esc')
|
|
775
803
|
return __await(yes, no) unless block_given?
|
|
776
804
|
temporary do |temp|
|
|
@@ -783,9 +811,9 @@ module NattyUI
|
|
|
783
811
|
# The selected option is returned.
|
|
784
812
|
#
|
|
785
813
|
# @overload choice(*choices, abortable: false)
|
|
786
|
-
# @param [#to_s]
|
|
814
|
+
# @param choices [#to_s]
|
|
787
815
|
# one or more alternatives to select from
|
|
788
|
-
# @param [true, false]
|
|
816
|
+
# @param abortable [true, false]
|
|
789
817
|
# whether the user is allowed to abort with 'Esc' or 'Ctrl+c'
|
|
790
818
|
#
|
|
791
819
|
# @return [Integer]
|
|
@@ -800,9 +828,9 @@ module NattyUI
|
|
|
800
828
|
# # => 1, when bananas are user's favorite
|
|
801
829
|
# # => 2, when user is a oranges lover
|
|
802
830
|
#
|
|
803
|
-
# @param [#to_s]
|
|
831
|
+
# @param choices[#to_s]
|
|
804
832
|
# one or more alternatives to select from
|
|
805
|
-
# @param [true, false]
|
|
833
|
+
# @param abortable[true, false]
|
|
806
834
|
# whether the user is allowed to abort with 'Esc' or 'Ctrl+c'
|
|
807
835
|
#
|
|
808
836
|
# @yieldparam temp [Temporary]
|
|
@@ -814,11 +842,11 @@ module NattyUI
|
|
|
814
842
|
# when user aborted the selection
|
|
815
843
|
#
|
|
816
844
|
# @overload choice(**choices, abortable: false)
|
|
817
|
-
# @param [#to_s]
|
|
845
|
+
# @param choices [#to_s]
|
|
818
846
|
# one or more alternatives to select from
|
|
819
|
-
# @param [true, false]
|
|
847
|
+
# @param abortable [true, false]
|
|
820
848
|
# whether the user is allowed to abort with 'Esc' or 'Ctrl+c'
|
|
821
|
-
# @param [#to_s, nil]
|
|
849
|
+
# @param selected [#to_s, nil]
|
|
822
850
|
# optionally pre-selected option
|
|
823
851
|
#
|
|
824
852
|
# @return [Object]
|
|
@@ -836,13 +864,13 @@ module NattyUI
|
|
|
836
864
|
# r: 'Rio',
|
|
837
865
|
# abortable: true
|
|
838
866
|
# ) { ui.puts 'Which terminal emulator do you like?' }
|
|
839
|
-
# # =>
|
|
867
|
+
# # => whether the user selected: :k, :i, :g, :t, :r
|
|
840
868
|
# # => nil, when the user aborted
|
|
841
|
-
# @param [#to_s]
|
|
869
|
+
# @param choices[#to_s]
|
|
842
870
|
# one or more alternatives to select from
|
|
843
|
-
# @param [true, false]
|
|
871
|
+
# @param abortable[true, false]
|
|
844
872
|
# whether the user is allowed to abort with 'Esc' or 'Ctrl+c'
|
|
845
|
-
# @param [Integer]
|
|
873
|
+
# @param selected[Integer]
|
|
846
874
|
# pre-selected option index
|
|
847
875
|
#
|
|
848
876
|
# @yieldparam temp [Temporary]
|
|
@@ -867,11 +895,11 @@ module NattyUI
|
|
|
867
895
|
# Allows the user to select from several options.
|
|
868
896
|
# All options are returned with their selection status.
|
|
869
897
|
#
|
|
870
|
-
# @param [{#to_s => [true,false]}]
|
|
898
|
+
# @param choices [{#to_s => [true,false]}]
|
|
871
899
|
# Hash of options and their selection state
|
|
872
|
-
# @param [true, false]
|
|
900
|
+
# @param abortable [true, false]
|
|
873
901
|
# whether the user is allowed to abort with 'Esc' or 'Ctrl+c'
|
|
874
|
-
# @param [#to_s, nil]
|
|
902
|
+
# @param selected [#to_s, nil]
|
|
875
903
|
# optionally pre-selected key
|
|
876
904
|
#
|
|
877
905
|
# @yieldparam temp [Temporary]
|
|
@@ -900,11 +928,11 @@ module NattyUI
|
|
|
900
928
|
# ui.puts '[i]Which terminal applications did you already tested?[/i]'
|
|
901
929
|
# end
|
|
902
930
|
#
|
|
903
|
-
# @param [Array<#to_s>]
|
|
931
|
+
# @param choices [Array<#to_s>]
|
|
904
932
|
# selectable options
|
|
905
|
-
# @param [true, false]
|
|
933
|
+
# @param abortable [true, false]
|
|
906
934
|
# whether the user is allowed to abort with 'Esc' or 'Ctrl+c'
|
|
907
|
-
# @param [Integer, :all, nil]
|
|
935
|
+
# @param selected [Integer, :all, nil]
|
|
908
936
|
# optionally pre-selected option index or `:all` to pre-select all items
|
|
909
937
|
# @yieldparam temp [Temporary]
|
|
910
938
|
# temporary displayed section (section will be erased after input)
|
|
@@ -937,7 +965,7 @@ module NattyUI
|
|
|
937
965
|
# @!group Utilities
|
|
938
966
|
#
|
|
939
967
|
|
|
940
|
-
#
|
|
968
|
+
# @private
|
|
941
969
|
def columns = Terminal.columns
|
|
942
970
|
|
|
943
971
|
# Display some temporary content.
|
|
@@ -983,15 +1011,16 @@ module NattyUI
|
|
|
983
1011
|
end
|
|
984
1012
|
end
|
|
985
1013
|
|
|
986
|
-
dir = __dir__
|
|
1014
|
+
dir = __dir__ # call the function once
|
|
1015
|
+
|
|
987
1016
|
autoload :Framed, "#{dir}/framed.rb"
|
|
988
1017
|
autoload :Section, "#{dir}/section.rb"
|
|
989
|
-
autoload :ShellCommand, "#{dir}/shell_command.rb"
|
|
990
1018
|
autoload :Table, "#{dir}/table.rb"
|
|
991
1019
|
autoload :Task, "#{dir}/task.rb"
|
|
992
1020
|
autoload :Temporary, "#{dir}/temporary.rb"
|
|
993
1021
|
autoload :Theme, "#{dir}/theme.rb"
|
|
994
1022
|
autoload :Utils, "#{dir}/utils.rb"
|
|
1023
|
+
private_constant(:Framed, :Utils)
|
|
995
1024
|
|
|
996
1025
|
autoload :Choice, "#{dir}/choice.rb"
|
|
997
1026
|
autoload :DumbChoice, "#{dir}/dumb_choice.rb"
|
|
@@ -999,27 +1028,25 @@ module NattyUI
|
|
|
999
1028
|
autoload :DumbOptions, "#{dir}/dumb_options.rb"
|
|
1000
1029
|
autoload :Progress, "#{dir}/progress.rb"
|
|
1001
1030
|
autoload :DumbProgress, "#{dir}/progress.rb"
|
|
1002
|
-
|
|
1003
|
-
autoload :CompactLSRenderer, "#{dir}/ls_renderer.rb"
|
|
1004
|
-
autoload :HBarsRenderer, "#{dir}/hbars_renderer.rb"
|
|
1005
|
-
autoload :LSRenderer, "#{dir}/ls_renderer.rb"
|
|
1006
|
-
autoload :VBarsRenderer, "#{dir}/vbars_renderer.rb"
|
|
1007
|
-
|
|
1008
1031
|
private_constant(
|
|
1009
|
-
:Framed,
|
|
1010
|
-
:ShellCommand,
|
|
1011
|
-
:Utils,
|
|
1012
|
-
# -
|
|
1013
1032
|
:Choice,
|
|
1014
1033
|
:DumbChoice,
|
|
1015
1034
|
:Options,
|
|
1016
1035
|
:DumbOptions,
|
|
1017
1036
|
:Progress,
|
|
1018
|
-
:DumbProgress
|
|
1019
|
-
|
|
1037
|
+
:DumbProgress
|
|
1038
|
+
)
|
|
1039
|
+
|
|
1040
|
+
autoload :CompactLSRenderer, "#{dir}/ls_renderer.rb"
|
|
1041
|
+
autoload :HBarsRenderer, "#{dir}/hbars_renderer.rb"
|
|
1042
|
+
autoload :LSRenderer, "#{dir}/ls_renderer.rb"
|
|
1043
|
+
autoload :ShellRenderer, "#{dir}/shell_renderer.rb"
|
|
1044
|
+
autoload :VBarsRenderer, "#{dir}/vbars_renderer.rb"
|
|
1045
|
+
private_constant(
|
|
1020
1046
|
:CompactLSRenderer,
|
|
1021
1047
|
:HBarsRenderer,
|
|
1022
1048
|
:LSRenderer,
|
|
1049
|
+
:ShellRenderer,
|
|
1023
1050
|
:VBarsRenderer
|
|
1024
1051
|
)
|
|
1025
1052
|
end
|
data/lib/natty-ui/framed.rb
CHANGED
|
@@ -6,10 +6,10 @@ module NattyUI
|
|
|
6
6
|
# {Element} with a frame around the content used by {Features.framed}.
|
|
7
7
|
#
|
|
8
8
|
class Framed < Element
|
|
9
|
-
#
|
|
9
|
+
# @private
|
|
10
10
|
def closed? = @bottom ? false : true
|
|
11
11
|
|
|
12
|
-
#
|
|
12
|
+
# @private
|
|
13
13
|
def puts(*objects, **options)
|
|
14
14
|
return self if closed?
|
|
15
15
|
options[:align] = @align
|
|
@@ -17,14 +17,14 @@ module NattyUI
|
|
|
17
17
|
super
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
-
#
|
|
20
|
+
# @private
|
|
21
21
|
def done
|
|
22
22
|
return if closed?
|
|
23
23
|
@parent.puts(@bottom)
|
|
24
24
|
@bottom = nil
|
|
25
25
|
end
|
|
26
26
|
|
|
27
|
-
#
|
|
27
|
+
# @private
|
|
28
28
|
def inspect = "#{_to_s.chop} align=#{@align.inspect} closed?=#{closed?}>"
|
|
29
29
|
|
|
30
30
|
private
|
data/lib/natty-ui/ls_renderer.rb
CHANGED
|
@@ -47,6 +47,7 @@ module NattyUI
|
|
|
47
47
|
|
|
48
48
|
class Item
|
|
49
49
|
attr_reader :width
|
|
50
|
+
|
|
50
51
|
def to_s(in_width) = "#{@str}#{' ' * (in_width - @width)}"
|
|
51
52
|
|
|
52
53
|
def initialize(str)
|
|
@@ -54,6 +55,7 @@ module NattyUI
|
|
|
54
55
|
@width = Text.width(str)
|
|
55
56
|
end
|
|
56
57
|
end
|
|
58
|
+
|
|
57
59
|
private_constant :Item
|
|
58
60
|
end
|
|
59
61
|
end
|
data/lib/natty-ui/options.rb
CHANGED
data/lib/natty-ui/progress.rb
CHANGED
|
@@ -44,6 +44,11 @@ module NattyUI
|
|
|
44
44
|
redraw
|
|
45
45
|
end
|
|
46
46
|
|
|
47
|
+
# Increment {value} and/or change {title}.
|
|
48
|
+
#
|
|
49
|
+
# @param count [Integer] increment
|
|
50
|
+
# @param title [#to_s] new title
|
|
51
|
+
# @return [ProgressHelper] itself
|
|
47
52
|
def step(count: 1, title: nil)
|
|
48
53
|
@title = title if title
|
|
49
54
|
self.value += count
|
|
@@ -53,7 +58,7 @@ module NattyUI
|
|
|
53
58
|
alias _to_s to_s
|
|
54
59
|
private :_to_s
|
|
55
60
|
|
|
56
|
-
#
|
|
61
|
+
# @private
|
|
57
62
|
def to_s
|
|
58
63
|
return "#{title}: #{format('%5.2f', @value)}" unless @max
|
|
59
64
|
"#{@title}: #{
|
|
@@ -66,7 +71,7 @@ module NattyUI
|
|
|
66
71
|
}"
|
|
67
72
|
end
|
|
68
73
|
|
|
69
|
-
#
|
|
74
|
+
# @private
|
|
70
75
|
def inspect = "#{_to_s.chop} #{self}>"
|
|
71
76
|
end
|
|
72
77
|
|
data/lib/natty-ui/section.rb
CHANGED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'theme'
|
|
4
|
+
|
|
5
|
+
module NattyUI
|
|
6
|
+
module ShellRenderer
|
|
7
|
+
def self.sh(parent, cmd, options, space)
|
|
8
|
+
opts_out, opts_err = opts_fom(Theme.current)
|
|
9
|
+
Terminal.sh(*cmd, **options) do |line, kind|
|
|
10
|
+
parent.puts(
|
|
11
|
+
space ? line.gsub("\t", ' ').gsub(/[[:space:]]/, ' ') : line,
|
|
12
|
+
**(kind == :error ? opts_err : opts_out)
|
|
13
|
+
)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
if Terminal.ansi?
|
|
18
|
+
def self.opts_fom(theme)
|
|
19
|
+
out = theme.mark(:sh_out)
|
|
20
|
+
err = theme.mark(:sh_err)
|
|
21
|
+
[
|
|
22
|
+
{
|
|
23
|
+
bbcode: false,
|
|
24
|
+
prefix: "#{out}#{theme.sh_out_style}",
|
|
25
|
+
prefix_width: out.width
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
bbcode: false,
|
|
29
|
+
prefix: "#{err}#{theme.sh_err_style}",
|
|
30
|
+
prefix_width: err.width
|
|
31
|
+
}
|
|
32
|
+
]
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def self.run(parent, cmd, options, space, tail)
|
|
36
|
+
theme = Theme.current
|
|
37
|
+
opref = "#{theme.mark(:sh_out)}#{theme.sh_out_style}"
|
|
38
|
+
epref = "#{theme.mark(:sh_err)}#{theme.sh_err_style}"
|
|
39
|
+
out, err, show = [], [], []
|
|
40
|
+
start = NattyUI.lines_written
|
|
41
|
+
[
|
|
42
|
+
Terminal.sh(*cmd, **options) do |line, kind|
|
|
43
|
+
start = NattyUI.back_to_line(start)
|
|
44
|
+
ol = space ? line.gsub("\t", ' ').gsub(/[[:space:]]/, ' ') : line
|
|
45
|
+
if kind == :error
|
|
46
|
+
err << line
|
|
47
|
+
show << "#{epref}#{ol}"
|
|
48
|
+
else
|
|
49
|
+
out << line
|
|
50
|
+
show << "#{opref}#{ol}"
|
|
51
|
+
end
|
|
52
|
+
parent.puts(*show, bbcode: false, tail: tail)
|
|
53
|
+
end,
|
|
54
|
+
out,
|
|
55
|
+
err
|
|
56
|
+
]
|
|
57
|
+
end
|
|
58
|
+
else
|
|
59
|
+
def self.opts_fom(theme)
|
|
60
|
+
out = theme.mark(:sh_out)
|
|
61
|
+
err = theme.mark(:sh_err)
|
|
62
|
+
[
|
|
63
|
+
{ bbcode: false, prefix: out, prefix_width: out.width },
|
|
64
|
+
{ bbcode: false, prefix: err, prefix_width: err.width }
|
|
65
|
+
]
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def self.run(parent, cmd, options, _space, _tail)
|
|
69
|
+
theme = Theme.current
|
|
70
|
+
opref, epref = theme.mark(:sh_out), theme.mark(:sh_err)
|
|
71
|
+
out, err = [], []
|
|
72
|
+
[
|
|
73
|
+
Terminal.sh(*cmd, **options) do |line, kind|
|
|
74
|
+
ol = line.gsub("\t", ' ').gsub(/[[:space:]]/, ' ')
|
|
75
|
+
if kind == :error
|
|
76
|
+
err << line
|
|
77
|
+
parent.puts("#{epref}#{ol}", bbcode: false)
|
|
78
|
+
else
|
|
79
|
+
out << line
|
|
80
|
+
parent.puts("#{opref}#{ol}", bbcode: false)
|
|
81
|
+
end
|
|
82
|
+
end,
|
|
83
|
+
out,
|
|
84
|
+
err
|
|
85
|
+
]
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
private_constant :ShellRenderer
|
|
91
|
+
end
|
data/lib/natty-ui/temporary.rb
CHANGED
|
@@ -3,11 +3,10 @@
|
|
|
3
3
|
require_relative 'element'
|
|
4
4
|
|
|
5
5
|
module NattyUI
|
|
6
|
-
#
|
|
7
|
-
# {Features.temporary}.
|
|
6
|
+
# Temporary display section used by {Features.temporary}.
|
|
8
7
|
#
|
|
9
8
|
class Temporary < Element
|
|
10
|
-
#
|
|
9
|
+
# @private
|
|
11
10
|
def puts(*objects, **opts)
|
|
12
11
|
return self if @state
|
|
13
12
|
if opts.delete(:pin)
|
|
@@ -16,7 +15,7 @@ module NattyUI
|
|
|
16
15
|
super
|
|
17
16
|
end
|
|
18
17
|
|
|
19
|
-
#
|
|
18
|
+
# @private
|
|
20
19
|
def done
|
|
21
20
|
return self if @state
|
|
22
21
|
NattyUI.back_to_line(@start_line) if @start_line
|
data/lib/natty-ui/theme.rb
CHANGED
data/lib/natty-ui/version.rb
CHANGED
data/lib/natty-ui.rb
CHANGED
|
@@ -33,7 +33,7 @@ module NattyUI
|
|
|
33
33
|
# @return [:dumb]
|
|
34
34
|
# when terminal does not support ANSI or interactive input
|
|
35
35
|
# @return [nil]
|
|
36
|
-
# when terminal
|
|
36
|
+
# when terminal input is not supported
|
|
37
37
|
def input_mode
|
|
38
38
|
case Terminal.input_mode
|
|
39
39
|
when :csi_u, :legacy
|
|
@@ -56,23 +56,23 @@ module NattyUI
|
|
|
56
56
|
def title=(value)
|
|
57
57
|
if value
|
|
58
58
|
title = Ansi.plain(value).gsub(/\s+/, ' ')
|
|
59
|
-
|
|
59
|
+
Terminal.raw_write(Ansi.title(title)) if Terminal.ansi?
|
|
60
60
|
@title_stack << title
|
|
61
61
|
else
|
|
62
62
|
@title_stack.pop
|
|
63
63
|
last = @title_stack[-1]
|
|
64
|
-
|
|
64
|
+
Terminal.raw_write(Ansi.title(last)) if last && Terminal.ansi?
|
|
65
65
|
end
|
|
66
66
|
end
|
|
67
67
|
|
|
68
|
-
#
|
|
68
|
+
# @private
|
|
69
69
|
attr_reader :lines_written
|
|
70
70
|
|
|
71
|
-
#
|
|
71
|
+
# @private
|
|
72
72
|
def back_to_line(number, erase: true)
|
|
73
73
|
return @lines_written if (c = @lines_written - number) <= 0
|
|
74
74
|
if Terminal.ansi?
|
|
75
|
-
|
|
75
|
+
Terminal.raw_write(
|
|
76
76
|
if erase == :all
|
|
77
77
|
Ansi.cursor_prev_line(c) + Ansi::SCREEN_ERASE_BELOW
|
|
78
78
|
elsif erase
|
|
@@ -85,21 +85,19 @@ module NattyUI
|
|
|
85
85
|
@lines_written = number
|
|
86
86
|
end
|
|
87
87
|
|
|
88
|
-
#
|
|
88
|
+
# @private
|
|
89
89
|
def alternate_screen
|
|
90
90
|
return yield unless Terminal.ansi?
|
|
91
91
|
begin
|
|
92
|
-
|
|
92
|
+
Terminal.raw_write(Ansi::SCREEN_ALTERNATE)
|
|
93
93
|
yield
|
|
94
94
|
ensure
|
|
95
|
-
|
|
95
|
+
Terminal.raw_write(Ansi::SCREEN_ALTERNATE_OFF)
|
|
96
96
|
end
|
|
97
97
|
end
|
|
98
98
|
|
|
99
99
|
private
|
|
100
100
|
|
|
101
|
-
def _write(str) = Terminal.__send__(:_write, str)
|
|
102
|
-
|
|
103
101
|
def with(element)
|
|
104
102
|
Terminal.hide_cursor if @element == self
|
|
105
103
|
current, @element = @element, element
|
|
@@ -118,7 +116,7 @@ end
|
|
|
118
116
|
unless defined?(Kernel.ui)
|
|
119
117
|
module Kernel
|
|
120
118
|
# @attribute [r] ui
|
|
121
|
-
# @return [NattyUI::Features] current used
|
|
119
|
+
# @return [NattyUI::Features] current used UI element
|
|
122
120
|
# @see NattyUI.element
|
|
123
121
|
def ui = NattyUI.element
|
|
124
122
|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: natty-ui
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.33.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Mike Blumtritt
|
|
@@ -15,14 +15,14 @@ dependencies:
|
|
|
15
15
|
requirements:
|
|
16
16
|
- - ">="
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: 0.
|
|
18
|
+
version: 0.14.0
|
|
19
19
|
type: :runtime
|
|
20
20
|
prerelease: false
|
|
21
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
22
|
requirements:
|
|
23
23
|
- - ">="
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
|
-
version: 0.
|
|
25
|
+
version: 0.14.0
|
|
26
26
|
description: |
|
|
27
27
|
This is the beautiful, nice, nifty, fancy, neat, pretty, cool, rich, lovely,
|
|
28
28
|
natty user interface tool you like to have for your command line applications.
|
|
@@ -52,6 +52,7 @@ files:
|
|
|
52
52
|
- examples/named-colors.rb
|
|
53
53
|
- examples/options.rb
|
|
54
54
|
- examples/sections.rb
|
|
55
|
+
- examples/sh.rb
|
|
55
56
|
- examples/tables.rb
|
|
56
57
|
- examples/tasks.rb
|
|
57
58
|
- examples/themes.rb
|
|
@@ -69,7 +70,7 @@ files:
|
|
|
69
70
|
- lib/natty-ui/options.rb
|
|
70
71
|
- lib/natty-ui/progress.rb
|
|
71
72
|
- lib/natty-ui/section.rb
|
|
72
|
-
- lib/natty-ui/
|
|
73
|
+
- lib/natty-ui/shell_renderer.rb
|
|
73
74
|
- lib/natty-ui/table.rb
|
|
74
75
|
- lib/natty-ui/table_renderer.rb
|
|
75
76
|
- lib/natty-ui/task.rb
|
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
module NattyUI
|
|
2
|
-
module ShellCommand
|
|
3
|
-
class << self
|
|
4
|
-
def call(*cmd, shell: false, input: nil, **options)
|
|
5
|
-
options = options.except(:in, :out, :err)
|
|
6
|
-
env = (cmd[0].is_a?(Hash) ? cmd.shift.dup : {}).freeze
|
|
7
|
-
if shell
|
|
8
|
-
cmd = cmd.map! { _escape(it) }.join(' ')
|
|
9
|
-
elsif cmd.size == 1 && cmd[0].include?(' ')
|
|
10
|
-
cmd = cmd[0]
|
|
11
|
-
end
|
|
12
|
-
cmd.freeze
|
|
13
|
-
input = Input.for(input)
|
|
14
|
-
ret = nil
|
|
15
|
-
with_io(options, input) do |cio, out_r, err_r, in_w|
|
|
16
|
-
thread = Process.detach(Process.spawn(env, *cmd, options))
|
|
17
|
-
begin
|
|
18
|
-
cio.each(&:close)
|
|
19
|
-
read = [out_r, err_r]
|
|
20
|
-
write = [in_w] if in_w
|
|
21
|
-
while !read.empty? || write
|
|
22
|
-
rr, wr, = IO.select(read, write)
|
|
23
|
-
if rr.include?(out_r)
|
|
24
|
-
begin
|
|
25
|
-
yield(out_r.readline(chomp: true), :output)
|
|
26
|
-
rescue SystemCallError, IOError
|
|
27
|
-
read.delete(out_r)
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
if rr.include?(err_r)
|
|
31
|
-
begin
|
|
32
|
-
yield(err_r.readline(chomp: true), :error)
|
|
33
|
-
rescue SystemCallError, IOError
|
|
34
|
-
read.delete(err_r)
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
next if wr.empty?
|
|
38
|
-
begin
|
|
39
|
-
next if input.call(in_w)
|
|
40
|
-
rescue SystemCallError, IOError
|
|
41
|
-
# nop
|
|
42
|
-
end
|
|
43
|
-
in_w.close
|
|
44
|
-
write = nil
|
|
45
|
-
end
|
|
46
|
-
ensure
|
|
47
|
-
ret = thread.join.value
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
|
-
ret
|
|
51
|
-
rescue SystemCallError, IOError
|
|
52
|
-
nil
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
private
|
|
56
|
-
|
|
57
|
-
def with_io(options, input)
|
|
58
|
-
IO.pipe do |out_r, out_w|
|
|
59
|
-
IO.pipe do |err_r, err_w|
|
|
60
|
-
cio = [options[:out] = out_w, options[:err] = err_w]
|
|
61
|
-
return yield(cio, out_r, err_r) unless input
|
|
62
|
-
IO.pipe do |in_r, in_w|
|
|
63
|
-
cio << (options[:in] = in_r)
|
|
64
|
-
in_w.sync = true
|
|
65
|
-
yield(cio, out_r, err_r, in_w)
|
|
66
|
-
end
|
|
67
|
-
end
|
|
68
|
-
end
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
def _escape(str)
|
|
72
|
-
return +"''" if str.empty?
|
|
73
|
-
str = str.dup
|
|
74
|
-
str.gsub!(%r{[^A-Za-z0-9_\-.,:+/@\n]}, "\\\\\\&")
|
|
75
|
-
str.gsub!("\n", "'\n'")
|
|
76
|
-
str
|
|
77
|
-
end
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
module Input
|
|
81
|
-
def self.for(obj)
|
|
82
|
-
return unless obj
|
|
83
|
-
return CopyWriter.new(obj) if obj.respond_to?(:readpartial)
|
|
84
|
-
return CopyWriter.new(obj.to_io) if obj.respond_to?(:to_io)
|
|
85
|
-
return ArrayWriter.new(obj) if obj.is_a?(Array)
|
|
86
|
-
return EnumerableWriter.new(obj) if obj.respond_to?(:each)
|
|
87
|
-
return ArrayWriter.new(obj.to_a) if obj.respond_to?(:to_a)
|
|
88
|
-
Writer.new(obj)
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
class Writer
|
|
92
|
-
def call(io) = (io.write(_next) if @obj)
|
|
93
|
-
def initialize(obj) = (@obj = obj)
|
|
94
|
-
def _next = (_, @obj = @obj, nil).first
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
class CopyWriter < Writer
|
|
98
|
-
def call(io) = (IO.copy_stream(_next, io) if @obj)
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
class ArrayWriter
|
|
102
|
-
def call(io) = io.write(@ry[@idx += 1] || return)
|
|
103
|
-
|
|
104
|
-
def initialize(ary)
|
|
105
|
-
@ry = ary
|
|
106
|
-
@idx = -1
|
|
107
|
-
end
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
class EnumerableWriter
|
|
111
|
-
def call(io)
|
|
112
|
-
io.write(@enum.next)
|
|
113
|
-
rescue StopIteration
|
|
114
|
-
false
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
def initialize(enum)
|
|
118
|
-
@enum =
|
|
119
|
-
if enum.respond_to?(:enum_for)
|
|
120
|
-
enum.enum_for(:each)
|
|
121
|
-
else
|
|
122
|
-
Enumerator.new { |y| enum.each { y << it } }
|
|
123
|
-
end
|
|
124
|
-
end
|
|
125
|
-
end
|
|
126
|
-
end
|
|
127
|
-
|
|
128
|
-
private_constant :Input
|
|
129
|
-
end
|
|
130
|
-
|
|
131
|
-
private_constant :ShellCommand
|
|
132
|
-
end
|