pindo 4.6.9
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 +7 -0
- data/bin/pindo +35 -0
- data/lib/pindo/base/aeshelper.rb +31 -0
- data/lib/pindo/base/deviceinfo.rb +90 -0
- data/lib/pindo/base/executable.rb +224 -0
- data/lib/pindo/base/githelper.rb +489 -0
- data/lib/pindo/base/hashhelper.rb +134 -0
- data/lib/pindo/base/plaininformative.rb +15 -0
- data/lib/pindo/base/plistbuddyexecutable.rb +121 -0
- data/lib/pindo/base/standarderror.rb +14 -0
- data/lib/pindo/client/applovinclient.rb +156 -0
- data/lib/pindo/client/aws3sclient.rb +183 -0
- data/lib/pindo/client/bossclient.rb +229 -0
- data/lib/pindo/client/bossconfigclient.rb +175 -0
- data/lib/pindo/client/giteeclient.rb +65 -0
- data/lib/pindo/client/httpclient.rb +40 -0
- data/lib/pindo/client/pgyerclient.rb +439 -0
- data/lib/pindo/client/tgateclient.rb +103 -0
- data/lib/pindo/command.rb +101 -0
- data/lib/pindo/config/pindoconfig.rb +439 -0
- data/lib/pindo/config/pindouserlocalconfig.rb +81 -0
- data/lib/pindo/deploy/Fastfile +233 -0
- data/lib/pindo/deploy/build.rb +167 -0
- data/lib/pindo/deploy/bundleid.rb +245 -0
- data/lib/pindo/deploy/cert.rb +508 -0
- data/lib/pindo/deploy/check.rb +79 -0
- data/lib/pindo/deploy/configproj.rb +89 -0
- data/lib/pindo/deploy/confusecode.rb +248 -0
- data/lib/pindo/deploy/confuseproj.rb +112 -0
- data/lib/pindo/deploy/fabric.rb +58 -0
- data/lib/pindo/deploy/getitcinfo.rb +248 -0
- data/lib/pindo/deploy/iap.rb +796 -0
- data/lib/pindo/deploy/initconfig.rb +128 -0
- data/lib/pindo/deploy/itcapp.rb +147 -0
- data/lib/pindo/deploy/itcinfo.rb +369 -0
- data/lib/pindo/deploy/pem.rb +55 -0
- data/lib/pindo/deploy/pullconfig.rb +46 -0
- data/lib/pindo/deploy/pushconfig.rb +83 -0
- data/lib/pindo/deploy/quswark.rb +146 -0
- data/lib/pindo/deploy/quswauth.rb +67 -0
- data/lib/pindo/deploy/reportbug.rb +135 -0
- data/lib/pindo/deploy/resign.rb +338 -0
- data/lib/pindo/deploy/tag.rb +108 -0
- data/lib/pindo/deploy/updateconfig.rb +129 -0
- data/lib/pindo/deploy/uploadipa.rb +63 -0
- data/lib/pindo/deploy.rb +44 -0
- data/lib/pindo/dev/autobuild.rb +204 -0
- data/lib/pindo/dev/autoresign.rb +186 -0
- data/lib/pindo/dev/confusecode.rb +127 -0
- data/lib/pindo/dev/confuseproj.rb +111 -0
- data/lib/pindo/dev/createbuild.rb +159 -0
- data/lib/pindo/dev/debug.rb +141 -0
- data/lib/pindo/dev/pub.rb +171 -0
- data/lib/pindo/dev/renewcert.rb +142 -0
- data/lib/pindo/dev.rb +23 -0
- data/lib/pindo/env/dreamstudio.rb +53 -0
- data/lib/pindo/env/flutter.rb +59 -0
- data/lib/pindo/env/flutter.sh +116 -0
- data/lib/pindo/env/quarkenv.rb +58 -0
- data/lib/pindo/env/swarkenv.rb +62 -0
- data/lib/pindo/env/workhard.rb +56 -0
- data/lib/pindo/env.rb +17 -0
- data/lib/pindo/ipa/autoresign.rb +188 -0
- data/lib/pindo/ipa/import.rb +261 -0
- data/lib/pindo/ipa/output.rb +396 -0
- data/lib/pindo/ipa.rb +22 -0
- data/lib/pindo/lib/forcepush.rb +159 -0
- data/lib/pindo/lib/lint.rb +115 -0
- data/lib/pindo/lib/push.rb +143 -0
- data/lib/pindo/lib/update.rb +75 -0
- data/lib/pindo/lib.rb +18 -0
- data/lib/pindo/module/appselect.rb +200 -0
- data/lib/pindo/module/appstore_in_app_purchase.rb +1803 -0
- data/lib/pindo/module/appstore_metadata_connect_api_helper.rb +12 -0
- data/lib/pindo/module/appstore_metadata_fastlane_helper.rb +922 -0
- data/lib/pindo/module/buildconfighelper.rb +13 -0
- data/lib/pindo/module/buildhelper.rb +76 -0
- data/lib/pindo/module/commonconfuseproj.rb +271 -0
- data/lib/pindo/module/config_project.sh +143 -0
- data/lib/pindo/module/configprojhelper.rb +631 -0
- data/lib/pindo/module/iap_tier.json +813 -0
- data/lib/pindo/module/icon_contents.json +116 -0
- data/lib/pindo/module/imessage_icon.json +91 -0
- data/lib/pindo/module/imgset_contents.json +21 -0
- data/lib/pindo/module/launchimg_contents.json +21 -0
- data/lib/pindo/module/pemcreate.rb +63 -0
- data/lib/pindo/module/pgyerhelper.rb +339 -0
- data/lib/pindo/module/xcodebuildpre.rb +258 -0
- data/lib/pindo/module/xcodehelper.rb +521 -0
- data/lib/pindo/options/appconfigoptions.rb +23 -0
- data/lib/pindo/options/deployoptions.rb +363 -0
- data/lib/pindo/pgyer/apptest.rb +104 -0
- data/lib/pindo/pgyer/comment.rb +95 -0
- data/lib/pindo/pgyer/download.rb +105 -0
- data/lib/pindo/pgyer/login.rb +61 -0
- data/lib/pindo/pgyer/upload.rb +234 -0
- data/lib/pindo/pgyer.rb +17 -0
- data/lib/pindo/repo/clone.rb +78 -0
- data/lib/pindo/repo/create.rb +55 -0
- data/lib/pindo/repo/login.rb +64 -0
- data/lib/pindo/repo/search.rb +60 -0
- data/lib/pindo/repo.rb +16 -0
- data/lib/pindo/setup.rb +60 -0
- data/lib/pindo/upgrade.rb +56 -0
- data/lib/pindo/utils/applovin.rb +213 -0
- data/lib/pindo/utils/boss.rb +209 -0
- data/lib/pindo/utils/clearcert.rb +60 -0
- data/lib/pindo/utils/device.rb +279 -0
- data/lib/pindo/utils/icon.rb +91 -0
- data/lib/pindo/utils/icon.sh +133 -0
- data/lib/pindo/utils/podindex.rb +56 -0
- data/lib/pindo/utils/podindex.sh +30 -0
- data/lib/pindo/utils/renewproj.rb +146 -0
- data/lib/pindo/utils/tgate.rb +159 -0
- data/lib/pindo/utils/xcassets.rb +46 -0
- data/lib/pindo/utils/xcassets.sh +88 -0
- data/lib/pindo/utils.rb +29 -0
- data/lib/pindo/version.rb +110 -0
- data/lib/pindo.rb +34 -0
- metadata +364 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 78cbf0c3494294a495f70d4d68732ab4d7fcb111efb47c13832bcc5570fdda49
|
|
4
|
+
data.tar.gz: 9b6072f6a35def3e42a09f36796bbe4a4999e2157d76225864ba3325a55d6d1c
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: cb6837bd54cd72e830010a5d263437913af930b6c3e9ce1c15ee9450a0699fa58e74b3cc14de69f6979efd147b051536d4698e36eebecfa47c6b6d6c97f5f731
|
|
7
|
+
data.tar.gz: 44b8eefc1b54857a60f20a72026f790bf134110976b97415dee6419086336cd7f30472cccdc37b7dda501a878609a279d55dbd5f8c9ca21eb99cf47dc773eb8e
|
data/bin/pindo
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
if Encoding.default_external != Encoding::UTF_8
|
|
5
|
+
|
|
6
|
+
if ARGV.include? '--no-ansi'
|
|
7
|
+
STDERR.puts <<-DOC
|
|
8
|
+
WARNING: pindo requires your terminal to be using UTF-8 encoding.
|
|
9
|
+
Consider adding the following to ~/.profile:
|
|
10
|
+
export LANG=en_US.UTF-8
|
|
11
|
+
DOC
|
|
12
|
+
else
|
|
13
|
+
STDERR.puts <<-DOC
|
|
14
|
+
\e[33mWARNING: pindo requires your terminal to be using UTF-8 encoding.
|
|
15
|
+
Consider adding the following to ~/.profile:
|
|
16
|
+
export LANG=en_US.UTF-8
|
|
17
|
+
\e[0m
|
|
18
|
+
DOC
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
if $PROGRAM_NAME == __FILE__ && !ENV['PINDO_NO_BUNDLER']
|
|
23
|
+
ENV['BUNDLE_GEMFILE'] = File.expand_path('../../Gemfile', __FILE__)
|
|
24
|
+
require 'rubygems'
|
|
25
|
+
require 'bundler/setup'
|
|
26
|
+
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
|
|
27
|
+
|
|
28
|
+
elsif ENV['PINDO_NO_BUNDLER']
|
|
29
|
+
require 'rubygems'
|
|
30
|
+
gem 'pindo'
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
require 'pindo'
|
|
34
|
+
|
|
35
|
+
Pindo::PindoApp.new.run(ARGV)
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
module Pindo
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
module AESHelper
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def self.aes_128_ecb_encrypt(key, encrypted_string)
|
|
10
|
+
cipher = OpenSSL::Cipher::Cipher.new('AES-128-ECB')
|
|
11
|
+
cipher.encrypt
|
|
12
|
+
cipher.key = key
|
|
13
|
+
txt = cipher.update(encrypted_string) << cipher.final
|
|
14
|
+
content = Base64.strict_encode64(txt)
|
|
15
|
+
return content
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def self.aes_128_ecb_decrypt(key, decrypted_string)
|
|
19
|
+
cipher = OpenSSL::Cipher.new("AES-128-ECB")
|
|
20
|
+
cipher.decrypt
|
|
21
|
+
cipher.key = key
|
|
22
|
+
text = cipher.update(Base64.strict_decode64(decrypted_string)) + cipher.final
|
|
23
|
+
return text
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
end
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
|
|
2
|
+
module Pindo
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class DeviceInfo
|
|
6
|
+
|
|
7
|
+
attr_accessor :timezone
|
|
8
|
+
attr_accessor :xcdev
|
|
9
|
+
attr_accessor :region_code
|
|
10
|
+
attr_accessor :language_code
|
|
11
|
+
attr_accessor :system_version
|
|
12
|
+
attr_accessor :network_type
|
|
13
|
+
attr_accessor :name
|
|
14
|
+
attr_accessor :machine
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
attr_accessor :device_id
|
|
18
|
+
attr_accessor :idfa
|
|
19
|
+
attr_accessor :idfv
|
|
20
|
+
attr_accessor :tzlid
|
|
21
|
+
attr_accessor :sutid
|
|
22
|
+
attr_accessor :sbsid
|
|
23
|
+
|
|
24
|
+
attr_accessor :carriers
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def initialize(configfile:nil)
|
|
29
|
+
|
|
30
|
+
@timezone = 28800
|
|
31
|
+
@xcdev = false
|
|
32
|
+
@region_code = "US"
|
|
33
|
+
@language_code = "en"
|
|
34
|
+
@system_version = "16.4"
|
|
35
|
+
@network_type = "WIFI"
|
|
36
|
+
@name = "iPhone 14"
|
|
37
|
+
@machine = "x86_64"
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@device_id = "PINDO000-0000-0000-0000-0000DEVICEID"
|
|
41
|
+
@idfa = "PINDO000-0000-0000-0000-00000000IDFA"
|
|
42
|
+
@sbsid = "PINDO000-0000-0000-0000-0000000SBSID"
|
|
43
|
+
@sutid = "PINDO000-0000-0000-0000-0000000SUTID"
|
|
44
|
+
@tzlid = "PINDO000-0000-0000-0000-0000000TZLID"
|
|
45
|
+
@idfv = "PINDO000-0000-0000-0000-00000000IDFV"
|
|
46
|
+
|
|
47
|
+
@carriers = []
|
|
48
|
+
|
|
49
|
+
if !configfile.nil? && File.exist?(configfile)
|
|
50
|
+
|
|
51
|
+
default_data = JSON.parse(File.read(configfile))
|
|
52
|
+
if !default_data.nil?
|
|
53
|
+
|
|
54
|
+
reset_with_config(device_config:default_data)
|
|
55
|
+
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def reset_with_config(device_config:nil)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
if !device_config.nil?
|
|
67
|
+
|
|
68
|
+
@timezone = device_config["timezone"] || 28800
|
|
69
|
+
@xcdev = device_config["xcdev"] || false
|
|
70
|
+
@region_code = device_config["region_code"] || "US"
|
|
71
|
+
@language_code = device_config["language_code"] || "en"
|
|
72
|
+
@system_version = device_config["system_version"] || "16.4"
|
|
73
|
+
@network_type = device_config["network_type"] || "WIFI"
|
|
74
|
+
@name = device_config["name"] || "iPhone 14"
|
|
75
|
+
@machine = device_config["machine"] || "x86_64"
|
|
76
|
+
|
|
77
|
+
@device_id = device_config["device_id"] || "PINDO000-0000-0000-0000-0000DEVICEID"
|
|
78
|
+
@idfa = device_config["idfa"] || "PINDO000-0000-0000-0000-00000000IDFA"
|
|
79
|
+
@sbsid = device_config["sbsid"] || "PINDO000-0000-0000-0000-0000000SBSID"
|
|
80
|
+
@sutid = device_config["sutid"] || "PINDO000-0000-0000-0000-0000000SUTID"
|
|
81
|
+
@tzlid = device_config["tzlid"] || "PINDO000-0000-0000-0000-0000000TZLID"
|
|
82
|
+
@idfv = device_config["idfv"] || "PINDO000-0000-0000-0000-00000000IDFV"
|
|
83
|
+
|
|
84
|
+
@carriers = device_config["carriers"] || []
|
|
85
|
+
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
end
|
|
90
|
+
end
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
module Pindo
|
|
2
|
+
# Module which provides support for running executables.
|
|
3
|
+
#
|
|
4
|
+
# In a class it can be used as:
|
|
5
|
+
#
|
|
6
|
+
# extend Executable
|
|
7
|
+
# executable :git
|
|
8
|
+
#
|
|
9
|
+
# This will create two methods `git` and `git!` both accept a command but
|
|
10
|
+
# the later will raise on non successful executions. The methods return the
|
|
11
|
+
# output of the command.
|
|
12
|
+
#
|
|
13
|
+
module Executable
|
|
14
|
+
# Creates the methods for the executable with the given name.
|
|
15
|
+
#
|
|
16
|
+
# @param [Symbol] name
|
|
17
|
+
# the name of the executable.
|
|
18
|
+
#
|
|
19
|
+
# @return [void]
|
|
20
|
+
#
|
|
21
|
+
def executable(name)
|
|
22
|
+
define_method(name) do |*command|
|
|
23
|
+
Executable.execute_command(name, Array(command).flatten, false)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
define_method(name.to_s + '!') do |*command|
|
|
27
|
+
Executable.execute_command(name, Array(command).flatten, true)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Executes the given command displaying it if in verbose mode.
|
|
32
|
+
#
|
|
33
|
+
# @param [String] executable
|
|
34
|
+
# The binary to use.
|
|
35
|
+
#
|
|
36
|
+
# @param [Array<#to_s>] command
|
|
37
|
+
# The command to send to the binary.
|
|
38
|
+
#
|
|
39
|
+
# @param [Bool] raise_on_failure
|
|
40
|
+
# Whether it should raise if the command fails.
|
|
41
|
+
#
|
|
42
|
+
# @raise If the executable could not be located.
|
|
43
|
+
#
|
|
44
|
+
# @raise If the command fails and the `raise_on_failure` is set to true.
|
|
45
|
+
#
|
|
46
|
+
# @return [String] the output of the command (STDOUT and STDERR).
|
|
47
|
+
#
|
|
48
|
+
def self.execute_command(executable, command, raise_on_failure = true)
|
|
49
|
+
bin = which!(executable)
|
|
50
|
+
|
|
51
|
+
command = command.map(&:to_s)
|
|
52
|
+
full_command = "#{bin} #{command.join(' ')}"
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
# if Config.instance.verbose?
|
|
56
|
+
# puts "$ #{full_command}"
|
|
57
|
+
# stdout = Indenter.new(STDOUT)
|
|
58
|
+
# stderr = Indenter.new(STDERR)
|
|
59
|
+
# else
|
|
60
|
+
stdout = Indenter.new
|
|
61
|
+
stderr = Indenter.new
|
|
62
|
+
# end
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
status = popen3(bin, command, stdout, stderr)
|
|
66
|
+
stdout = stdout.join
|
|
67
|
+
stderr = stderr.join
|
|
68
|
+
output = stdout + stderr
|
|
69
|
+
unless status.success?
|
|
70
|
+
if raise_on_failure
|
|
71
|
+
raise Informative, "#{full_command}\n\n#{output}"
|
|
72
|
+
else
|
|
73
|
+
puts "[!] Failed: #{full_command}"
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
output
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Returns the absolute path to the binary with the given name on the current
|
|
81
|
+
# `PATH`, or `nil` if none is found.
|
|
82
|
+
#
|
|
83
|
+
# @param [String] program
|
|
84
|
+
# The name of the program being searched for.
|
|
85
|
+
#
|
|
86
|
+
# @return [String,Nil] The absolute path to the given program, or `nil` if
|
|
87
|
+
# it wasn't found in the current `PATH`.
|
|
88
|
+
#
|
|
89
|
+
def self.which(program)
|
|
90
|
+
program = program.to_s
|
|
91
|
+
paths = ENV.fetch('PATH') { '' }.split(File::PATH_SEPARATOR)
|
|
92
|
+
paths.unshift('./')
|
|
93
|
+
paths.uniq!
|
|
94
|
+
paths.each do |path|
|
|
95
|
+
bin = File.expand_path(program, path)
|
|
96
|
+
if File.file?(bin) && File.executable?(bin)
|
|
97
|
+
return bin
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
nil
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Returns the absolute path to the binary with the given name on the current
|
|
104
|
+
# `PATH`, or raises if none is found.
|
|
105
|
+
#
|
|
106
|
+
# @param [String] program
|
|
107
|
+
# The name of the program being searched for.
|
|
108
|
+
#
|
|
109
|
+
# @return [String] The absolute path to the given program.
|
|
110
|
+
#
|
|
111
|
+
def self.which!(program)
|
|
112
|
+
which(program).tap do |bin|
|
|
113
|
+
raise Informative, "Unable to locate the executable `#{program}`" unless bin
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# Runs the given command, capturing the desired output.
|
|
118
|
+
#
|
|
119
|
+
# @param [String] bin
|
|
120
|
+
# The binary to use.
|
|
121
|
+
#
|
|
122
|
+
# @param [Array<#to_s>] command
|
|
123
|
+
# The command to send to the binary.
|
|
124
|
+
#
|
|
125
|
+
# @param [Symbol] capture
|
|
126
|
+
# Whether it should raise if the command fails.
|
|
127
|
+
#
|
|
128
|
+
# @raise If the executable could not be located.
|
|
129
|
+
#
|
|
130
|
+
# @return [(String, Process::Status)]
|
|
131
|
+
# The desired captured output from the command, and the status from
|
|
132
|
+
# running the command.
|
|
133
|
+
#
|
|
134
|
+
def self.capture_command(executable, command, capture: :merge)
|
|
135
|
+
bin = which!(executable)
|
|
136
|
+
|
|
137
|
+
require 'open3'
|
|
138
|
+
command = command.map(&:to_s)
|
|
139
|
+
case capture
|
|
140
|
+
when :merge then Open3.capture2e(bin, *command)
|
|
141
|
+
when :both then Open3.capture3(bin, *command)
|
|
142
|
+
when :out then Open3.capture3(bin, *command).values_at(0, -1)
|
|
143
|
+
when :err then Open3.capture3(bin, *command).drop(1)
|
|
144
|
+
when :none then Open3.capture3(bin, *command).last
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
private
|
|
149
|
+
|
|
150
|
+
def self.popen3(bin, command, stdout, stderr)
|
|
151
|
+
require 'open3'
|
|
152
|
+
Open3.popen3(bin, *command) do |i, o, e, t|
|
|
153
|
+
reader(o, stdout)
|
|
154
|
+
reader(e, stderr)
|
|
155
|
+
i.close
|
|
156
|
+
|
|
157
|
+
status = t.value
|
|
158
|
+
|
|
159
|
+
o.flush
|
|
160
|
+
e.flush
|
|
161
|
+
sleep(0.01)
|
|
162
|
+
|
|
163
|
+
status
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def self.reader(input, output)
|
|
168
|
+
Thread.new do
|
|
169
|
+
buf = ''
|
|
170
|
+
begin
|
|
171
|
+
loop do
|
|
172
|
+
buf << input.readpartial(4096)
|
|
173
|
+
loop do
|
|
174
|
+
string, separator, buf = buf.partition(/[\r\n]/)
|
|
175
|
+
if separator.empty?
|
|
176
|
+
buf = string
|
|
177
|
+
break
|
|
178
|
+
end
|
|
179
|
+
output << (string << separator)
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
rescue EOFError
|
|
183
|
+
output << (buf << $/) unless buf.empty?
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
#-------------------------------------------------------------------------#
|
|
189
|
+
|
|
190
|
+
# Helper class that allows to write to an {IO} instance taking into account
|
|
191
|
+
# the UI indentation level.
|
|
192
|
+
#
|
|
193
|
+
class Indenter < ::Array
|
|
194
|
+
# @return [Fixnum] The indentation level of the UI.
|
|
195
|
+
#
|
|
196
|
+
attr_reader :indent
|
|
197
|
+
|
|
198
|
+
# @return [IO] the {IO} to which the output should be printed.
|
|
199
|
+
#
|
|
200
|
+
attr_reader :io
|
|
201
|
+
|
|
202
|
+
# Init a new Indenter
|
|
203
|
+
#
|
|
204
|
+
# @param [IO] io @see io
|
|
205
|
+
#
|
|
206
|
+
def initialize(io = nil)
|
|
207
|
+
@io = io
|
|
208
|
+
@indent = ' '
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
# Stores a portion of the output and prints it to the {IO} instance.
|
|
212
|
+
#
|
|
213
|
+
# @param [String] value
|
|
214
|
+
# the output to print.
|
|
215
|
+
#
|
|
216
|
+
# @return [void]
|
|
217
|
+
#
|
|
218
|
+
def <<(value)
|
|
219
|
+
super
|
|
220
|
+
io << "#{indent}#{value}" if io
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
end
|
|
224
|
+
end
|