indented_io 0.7.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 +7 -0
- data/.gitignore +15 -0
- data/.rspec +3 -0
- data/.ruby-version +1 -0
- data/.travis.yml +5 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +21 -0
- data/README.md +208 -0
- data/Rakefile +6 -0
- data/TODO +19 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/indented_io.gemspec +44 -0
- data/lib/indented_io/error.rb +6 -0
- data/lib/indented_io/indented_io.rb +165 -0
- data/lib/indented_io/indented_io_interface.rb +29 -0
- data/lib/indented_io/io.rb +7 -0
- data/lib/indented_io/kernel.rb +26 -0
- data/lib/indented_io/stringio.rb +6 -0
- data/lib/indented_io/version.rb +4 -0
- data/lib/indented_io.rb +23 -0
- metadata +113 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 912e798e34c1c61e53b1cdaf9743383085503671e3ba318995a434ff1ec2fac7
|
4
|
+
data.tar.gz: 5ca6c729d02ff390720b3faf76adffe22a10aec20236adbafe5edcd21b364955
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f9b98e7f028b6386b6b2caca76690fa53e87e6d06c9a28e6967147e54abca098ed11364a54f9bc1acaf3bd489baafcb46351acbef471527d7b53f4dddad470ea
|
7
|
+
data.tar.gz: b2962b48817a7a5a5803484f0ff82a335d955e140b3a9b5003a91c538612842918cbaf24992e12d7ce630a1e1b866786a781290a75ccecf78af4f7fa8efd0505
|
data/.gitignore
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
/.bundle/
|
2
|
+
/.yardoc
|
3
|
+
/_yardoc/
|
4
|
+
/coverage/
|
5
|
+
/doc/
|
6
|
+
/pkg/
|
7
|
+
/spec/reports/
|
8
|
+
/tmp/
|
9
|
+
|
10
|
+
# rspec failure tracking
|
11
|
+
.rspec_status
|
12
|
+
|
13
|
+
# Ignore Gemfile.lock. See https://stackoverflow.com/questions/4151495/should-gemfile-lock-be-included-in-gitignore
|
14
|
+
/Gemfile.lock
|
15
|
+
|
data/.rspec
ADDED
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby-2.5.0
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2018 Claus Rasmussen
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,208 @@
|
|
1
|
+
# IndentedIO
|
2
|
+
|
3
|
+
Print indented text
|
4
|
+
|
5
|
+
`IndentedIO` extends `Kernel`, `IO`, and `StringIO` with an `#indent` method
|
6
|
+
that returns an `IndentedIO` object. The `IndentedIO` object acts as the
|
7
|
+
original object but redefines the output methods `#print`, `#printf`, `#puts`,
|
8
|
+
and `#p` to print their output indented. Indentations are stacked so that each
|
9
|
+
new indentation adds to the previous indendation
|
10
|
+
|
11
|
+
## Usage
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
require 'indented_io'
|
15
|
+
|
16
|
+
puts "Not indented"
|
17
|
+
indent { puts "Indented one level" }
|
18
|
+
indent(2, "* ").puts "Indented two levels"
|
19
|
+
```
|
20
|
+
|
21
|
+
outputs
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
Not indented
|
25
|
+
Indented one level
|
26
|
+
* * Indented two levels
|
27
|
+
```
|
28
|
+
|
29
|
+
#### `#indent`
|
30
|
+
|
31
|
+
`#indent` without a block returns an `IndentedIO` object that acts as the
|
32
|
+
receiver but redefine `#print`, `#printf`, `#puts`, and `#p` to print indented
|
33
|
+
If given a block, the block will be called with the IndentedIO object as
|
34
|
+
argument:
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
$stdout.puts "Not indented"
|
38
|
+
$stdout.indent.puts "Indented"
|
39
|
+
$stdout.indent { |f| f.puts "Indented" }
|
40
|
+
|
41
|
+
# Not indented
|
42
|
+
# Indented
|
43
|
+
# Indented
|
44
|
+
```
|
45
|
+
(please note that when `Kernel` is the receiver, the returned object will
|
46
|
+
act as the `$stdout` object and not the `Kernel` object)
|
47
|
+
|
48
|
+
`#indent` can take up to two positional arguments: `level`, that is the number
|
49
|
+
of levels to indent (default 1), and the indent string that defaults to the
|
50
|
+
indent string of the previous level or `IndentedIO.default_string` if at the
|
51
|
+
first level. It is also possible to specify the indentation string using the
|
52
|
+
symbolic argument `:string`. If level is negative, the text will be outdented
|
53
|
+
instead:
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
$stdout.puts "Not indented"
|
57
|
+
$stdout.indent(2, "> ") { |f|
|
58
|
+
f.indent(string: "* ").puts "Indented three levels"
|
59
|
+
f.indent(-1).puts "Indented one level"
|
60
|
+
}
|
61
|
+
|
62
|
+
# Not indented
|
63
|
+
# > > * Indented three levels
|
64
|
+
# > Indented one level
|
65
|
+
```
|
66
|
+
When text is outdented, the indentation string defaults to the previous level's
|
67
|
+
indentation string - not the parent's
|
68
|
+
|
69
|
+
#### `Kernel#indent {}`
|
70
|
+
|
71
|
+
If given a block without an argument, `Kernel#indent` manipulates `$stdout` so
|
72
|
+
that `Kernel#print`, `Kernel#printf`, `Kernel#puts`, and `Kernel#p` will output
|
73
|
+
indented within that block:
|
74
|
+
|
75
|
+
```ruby
|
76
|
+
puts "Not indented"
|
77
|
+
indent {
|
78
|
+
puts "Indented one level"
|
79
|
+
indent {
|
80
|
+
puts "Indented two levels"
|
81
|
+
}
|
82
|
+
puts "Indented one level"
|
83
|
+
}
|
84
|
+
puts "Not indented"
|
85
|
+
|
86
|
+
# Not indented
|
87
|
+
# Indented one level
|
88
|
+
# Indented two levels
|
89
|
+
# Indented one level
|
90
|
+
# Not indented
|
91
|
+
```
|
92
|
+
Because this manipulates `$stdout`, the indentation carries through to methods
|
93
|
+
that doesn't even know about `IndentedIO`:
|
94
|
+
|
95
|
+
```ruby
|
96
|
+
def legacy(phrase)
|
97
|
+
puts phrase
|
98
|
+
end
|
99
|
+
|
100
|
+
legacy("Not indented")
|
101
|
+
indent { legacy("Indented" }
|
102
|
+
|
103
|
+
# Not indented
|
104
|
+
# Indented
|
105
|
+
```
|
106
|
+
This is probably the style that'll be used most of the time. It is of course
|
107
|
+
still possible use `Kernel#indent` with a block argument if needed
|
108
|
+
|
109
|
+
#### bol - Beginning-Of-Line argument
|
110
|
+
|
111
|
+
`#indent` takes a symbolic `:bol` argument (`true` or `false`, default `true`)
|
112
|
+
that specify if the output device is at the beginning of a line and that printing
|
113
|
+
should start with an indentation string:
|
114
|
+
|
115
|
+
```ruby
|
116
|
+
indent(1, bol: true).puts "Indented"
|
117
|
+
indent(1, bol: false).puts "Not indented\nIndented"
|
118
|
+
|
119
|
+
# Indented
|
120
|
+
# Not indented
|
121
|
+
# Indented
|
122
|
+
```
|
123
|
+
|
124
|
+
## Constants
|
125
|
+
|
126
|
+
The default indentation string is defined in `IndentedIO`:
|
127
|
+
|
128
|
+
```ruby
|
129
|
+
IndentedIO.default_indent = ">> "
|
130
|
+
indent.puts "Indented by #{IndentedIO.default_indent.inspect}"
|
131
|
+
|
132
|
+
# >> Indented by ">> "
|
133
|
+
```
|
134
|
+
|
135
|
+
The default at start-up is two spaces. It should normally be set only once
|
136
|
+
at the start of the program. Use the indent string argument to `#indent`
|
137
|
+
to get a different indentation for a part of the program
|
138
|
+
|
139
|
+
## Exceptions
|
140
|
+
|
141
|
+
In case of errors an `IndentedIO::Error` exception is raised
|
142
|
+
|
143
|
+
## Add support for other classes
|
144
|
+
|
145
|
+
You can add support for your own IO objects by including
|
146
|
+
`IndentedIO::IndentedIOInterface` in your class. All that is required is that
|
147
|
+
the class define a `#print` method with the same semantics as the system
|
148
|
+
`#print`
|
149
|
+
|
150
|
+
```ruby
|
151
|
+
require 'indented_io'
|
152
|
+
class MyIO
|
153
|
+
include IndentedIO::IndentedIOInterface
|
154
|
+
def print(*args) ... end
|
155
|
+
end
|
156
|
+
|
157
|
+
my_io = MyIO.new
|
158
|
+
my_io.indent.puts "It works!"
|
159
|
+
```
|
160
|
+
|
161
|
+
## Implementation & performance
|
162
|
+
|
163
|
+
`IndentedIO` is intrusive because it extends the standard classes `Kernel`,
|
164
|
+
`IO`, and `StringIO` with the `#indent` method. In addition, `Kernel#indent`
|
165
|
+
with a block without parameters manipulates `$stdout`, replacing it with an
|
166
|
+
`IndentedIO` object for the duration of the block
|
167
|
+
|
168
|
+
The implementation carries no overhead if it is not used but the core indentation
|
169
|
+
mechanism processes characters one-by-one which is slow compared to what could
|
170
|
+
be achived with a native C implementation
|
171
|
+
|
172
|
+
|
173
|
+
## Installation
|
174
|
+
|
175
|
+
Add this line to your application's Gemfile:
|
176
|
+
|
177
|
+
```ruby
|
178
|
+
gem 'indented_io'
|
179
|
+
```
|
180
|
+
|
181
|
+
And then execute:
|
182
|
+
|
183
|
+
$ bundle
|
184
|
+
|
185
|
+
Or install it yourself as:
|
186
|
+
|
187
|
+
$ gem install indented_io
|
188
|
+
|
189
|
+
## Development
|
190
|
+
|
191
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
192
|
+
`rake spec` to run the tests. You can also run `bin/console` for an interactive
|
193
|
+
prompt that will allow you to experiment.
|
194
|
+
|
195
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To
|
196
|
+
release a new version, update the version number in `version.rb`, and then run
|
197
|
+
`bundle exec rake release`, which will create a git tag for the version, push
|
198
|
+
git commits and tags, and push the `.gem` file to
|
199
|
+
[rubygems.org](https://rubygems.org).
|
200
|
+
|
201
|
+
## Contributing
|
202
|
+
|
203
|
+
Bug reports and pull requests are welcome on GitHub at
|
204
|
+
https://github.com/[USERNAME]/indented_io.
|
205
|
+
|
206
|
+
## License
|
207
|
+
|
208
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
data/TODO
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
|
2
|
+
TODO
|
3
|
+
o Check if IO object is writable - no good solution ?
|
4
|
+
o better name for @this_indent ? 'string' ?
|
5
|
+
|
6
|
+
+ explain bol
|
7
|
+
+ Allow a symbolic :string argument
|
8
|
+
+ #printf !
|
9
|
+
+ Make IndentedIO a pseudo IO object and forward to the root object
|
10
|
+
+ Clean-up ugliness in IndentedIO#initialize
|
11
|
+
+ Move bol to global
|
12
|
+
+ Handle negative indent level
|
13
|
+
+ #indent without block
|
14
|
+
+ StringIO#indent !
|
15
|
+
+ Rename Device -> IndentedIO
|
16
|
+
|
17
|
+
- Make Kernel.indent behave like Kernel ?
|
18
|
+
|
19
|
+
? Create a BaseIndentedIO class ?
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "indented_io"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/indented_io.gemspec
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "indented_io/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "indented_io"
|
8
|
+
spec.version = IndentedIO::VERSION
|
9
|
+
spec.authors = ["Claus Rasmussen"]
|
10
|
+
spec.email = ["claus.l.rasmussen@gmail.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{Print indented text}
|
13
|
+
spec.description = %q{
|
14
|
+
IndentedIO extends Kernel, IO, and StringIO
|
15
|
+
with an #indent method that returns an IndentedIO
|
16
|
+
object. The IndentedIO object acts as the original
|
17
|
+
object but redefines the output methods #print,
|
18
|
+
#printf, #puts, and #p to print their output
|
19
|
+
indented. Indentations are stacked so that each new
|
20
|
+
indentation adds to the previous indendation
|
21
|
+
}
|
22
|
+
spec.homepage = "https://github.com/clrgit/indented_io"
|
23
|
+
spec.license = "MIT"
|
24
|
+
|
25
|
+
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
|
26
|
+
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
27
|
+
if spec.respond_to?(:metadata)
|
28
|
+
spec.metadata["allowed_push_host"] = "https://rubygems.org"
|
29
|
+
else
|
30
|
+
raise "RubyGems 2.0 or newer is required to protect against " \
|
31
|
+
"public gem pushes."
|
32
|
+
end
|
33
|
+
|
34
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
35
|
+
f.match(%r{^(test|spec|features)/})
|
36
|
+
end
|
37
|
+
spec.bindir = "exe"
|
38
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
39
|
+
spec.require_paths = ["lib"]
|
40
|
+
|
41
|
+
spec.add_development_dependency "bundler", "~> 1.16"
|
42
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
43
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
44
|
+
end
|
@@ -0,0 +1,165 @@
|
|
1
|
+
require 'indented_io/indented_io_interface'
|
2
|
+
|
3
|
+
module IndentedIO
|
4
|
+
# An IO device that writes indented text
|
5
|
+
#
|
6
|
+
# IndentedIO objects forms a chain that acts as a stack. The lowest element
|
7
|
+
# in the stack is always a "pure" IO object (eg. $stdout) and as indentation
|
8
|
+
# levels rise or fall IndentedIO objects are moved on and off the stack
|
9
|
+
#
|
10
|
+
# Note that #new is private. The only way to create a IndentedIO object is to
|
11
|
+
# call #indent on a object that supports it
|
12
|
+
class IndentedIO
|
13
|
+
include IndentedIOInterface
|
14
|
+
|
15
|
+
# :nodoc:
|
16
|
+
alias :interface_indent :indent
|
17
|
+
# :startdoc:
|
18
|
+
|
19
|
+
# Return a IndentedIO object
|
20
|
+
#
|
21
|
+
# See IndentedIO::IndentedIOInterface#indent for documentation
|
22
|
+
def indent(levels=1, string_ = self.this_indent, string: string_, bol: nil, &block)
|
23
|
+
interface_indent(levels, string, bol: bol, &block)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Current level
|
27
|
+
def level
|
28
|
+
@level ||= @levels + (parent.is_a?(::IndentedIO::IndentedIO) ? parent.level : 0)
|
29
|
+
end
|
30
|
+
|
31
|
+
# Indent and print args to the underlying device. #print has the same semantic
|
32
|
+
# as Kernel#print
|
33
|
+
def print(*args)
|
34
|
+
if bol
|
35
|
+
@device.print @combined_indent
|
36
|
+
self.bol = false
|
37
|
+
end
|
38
|
+
args.join.each_char { |c|
|
39
|
+
if c == "\n"
|
40
|
+
self.bol = true
|
41
|
+
elsif bol
|
42
|
+
@device.print @combined_indent
|
43
|
+
self.bol = false
|
44
|
+
end
|
45
|
+
@device.print c
|
46
|
+
}
|
47
|
+
nil
|
48
|
+
end
|
49
|
+
|
50
|
+
# Indent and print args to the underlying device. #printf has the same semantic
|
51
|
+
# as Kernel#printf
|
52
|
+
def printf(format, *args)
|
53
|
+
print format % args
|
54
|
+
end
|
55
|
+
|
56
|
+
# Indent and print args to the underlying device. #puts has the same semantic
|
57
|
+
# as Kernel#puts
|
58
|
+
def puts(*args)
|
59
|
+
args.each { |arg| print(arg, "\n") }
|
60
|
+
nil
|
61
|
+
end
|
62
|
+
|
63
|
+
# Indent and print args to the underlying device. #p has the same semantic
|
64
|
+
# as Kernel#p. Please note that #p is usually not defined on other classes
|
65
|
+
# then Kernel but can be used on any IndentedIO object
|
66
|
+
def p(*args)
|
67
|
+
if bol
|
68
|
+
args.each { |arg| print(arg.inspect, "\n") }
|
69
|
+
else
|
70
|
+
@device.print args.first.inspect, "\n"
|
71
|
+
bol = true
|
72
|
+
args[1..-1].each { |arg| print(arg.inspect, "\n") }
|
73
|
+
end
|
74
|
+
args.size == 1 ? args.first : args
|
75
|
+
end
|
76
|
+
|
77
|
+
# :stopdoc:
|
78
|
+
|
79
|
+
# Make IndentedIO behave like the underlying @device
|
80
|
+
def respond_to?(method)
|
81
|
+
[:indent, :level, :print, :puts, :p].include?(method) || device.respond_to?(method)
|
82
|
+
end
|
83
|
+
|
84
|
+
# Make IndentedIO behave like the underlying @device
|
85
|
+
def method_missing(method, *args)
|
86
|
+
device.send(method, *args)
|
87
|
+
end
|
88
|
+
|
89
|
+
protected
|
90
|
+
# Reference to the pure IO object at the bottom of the stack. It is used to
|
91
|
+
# write directly to the IO object without having to recurse down the IndentedIO
|
92
|
+
# stack
|
93
|
+
attr_reader :device
|
94
|
+
|
95
|
+
# First IndentedIO object on the stack. Equal to self if self is the first
|
96
|
+
# indentation object. #base is used to keep track of #bol for the whole
|
97
|
+
# stack of IndentedIO objects
|
98
|
+
attr_reader :base
|
99
|
+
|
100
|
+
# Parent IndentedIO or IO object
|
101
|
+
attr_reader :parent
|
102
|
+
|
103
|
+
# Number of indent levels
|
104
|
+
attr_reader :levels
|
105
|
+
|
106
|
+
# Indent string for this device
|
107
|
+
attr_reader :this_indent
|
108
|
+
|
109
|
+
# The combined indent strings of previous levels plus this device's indent string
|
110
|
+
attr_reader :combined_indent
|
111
|
+
|
112
|
+
# True iff at Beginning-Of-Line
|
113
|
+
def bol()
|
114
|
+
@base == self ? @bol : @base.bol # @bol only exists in the #base object
|
115
|
+
end
|
116
|
+
|
117
|
+
# Set Beginning-Of-Line to true or false
|
118
|
+
def bol=(bol)
|
119
|
+
@base.instance_variable_set(:@bol, bol) # @bol only exists in the #base object
|
120
|
+
end
|
121
|
+
|
122
|
+
# Hide new
|
123
|
+
private_class_method :new
|
124
|
+
|
125
|
+
def initialize(parent, levels, this_indent, bol)
|
126
|
+
if levels < 0
|
127
|
+
parent.is_a?(::IndentedIO::IndentedIO) or raise IndentedIO::Error.new "Negative levels argument"
|
128
|
+
parent.level + levels >= 0 or raise IndentedIO::Error.new "levels out of range"
|
129
|
+
sibling = parent
|
130
|
+
while parent.is_a?(::IndentedIO::IndentedIO) && levels < 0
|
131
|
+
levels += parent.levels
|
132
|
+
sibling = parent
|
133
|
+
parent = parent.parent
|
134
|
+
end
|
135
|
+
this_indent ||= sibling.indent
|
136
|
+
end
|
137
|
+
@parent = parent
|
138
|
+
@levels = levels
|
139
|
+
@this_indent = this_indent
|
140
|
+
if @parent.is_a?(::IndentedIO::IndentedIO)
|
141
|
+
@device = @parent.device
|
142
|
+
@base = @parent.base
|
143
|
+
@combined_indent = @parent.combined_indent + @this_indent * @levels
|
144
|
+
self.bol = bol if !bol.nil?
|
145
|
+
else
|
146
|
+
@device = parent
|
147
|
+
@base = self
|
148
|
+
@combined_indent = @this_indent * @levels
|
149
|
+
self.bol = (bol.nil? ? true : bol)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
public
|
154
|
+
def dump
|
155
|
+
$stderr.puts "#{self.class} [#{self.object_id}]"
|
156
|
+
$stderr.puts " device: #{device.class} [#{device.object_id}]"
|
157
|
+
$stderr.puts " base : #{base.class} [#{base.object_id}]"
|
158
|
+
$stderr.puts " parent: #{parent.class} [#{parent.object_id}]"
|
159
|
+
$stderr.puts " levels: #{levels}"
|
160
|
+
$stderr.puts " this_indent: #{this_indent.inspect}"
|
161
|
+
$stderr.puts " combined_indent: #{combined_indent.inspect}"
|
162
|
+
$stderr.puts " bol: #{bol}"
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module IndentedIO
|
2
|
+
# IndentedIO interface that provides the #indent method. Used by IO,
|
3
|
+
# StringIO, and IndentedIO. It can be included in any class that define a
|
4
|
+
# #print method
|
5
|
+
module IndentedIOInterface
|
6
|
+
# Returns a IndentedIO object that can be used for printing. The IO object
|
7
|
+
# will pass-through all method calls except #print, #printf, #puts, and #p
|
8
|
+
# to the enclosing object
|
9
|
+
#
|
10
|
+
# :call-seq:
|
11
|
+
# indent(levels = 1)
|
12
|
+
# indent(levels, string)
|
13
|
+
# indent(levels, string: indent_string, bol: beginning_of_line)
|
14
|
+
# indent(levels, string, bol: beginning_of_line)
|
15
|
+
#
|
16
|
+
# +levels+:: Number of indentation levels. Default is one level
|
17
|
+
# +string+:: The indentation string. Default is the indent string of the
|
18
|
+
# outer level or ::IndentedIO.default_indent if this is the
|
19
|
+
# first level
|
20
|
+
# +bol+:: Beginning of line. If true, #indent will begin writing with an
|
21
|
+
# indentation string. If false, it will only indent after the next
|
22
|
+
# newline. Default true
|
23
|
+
def indent(levels = 1, string_ = ::IndentedIO.default_indent, string: string_, bol: nil, &block)
|
24
|
+
block.nil? || block.arity == 1 or raise ::IndentedIO::Error.new "Wrong number of parameters"
|
25
|
+
obj = ::IndentedIO::IndentedIO.send(:new, self, levels, string, bol)
|
26
|
+
block_given? ? yield(obj) : obj
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'indented_io/indented_io_interface'
|
2
|
+
|
3
|
+
# :nodoc:
|
4
|
+
module Kernel
|
5
|
+
def indent(levels = 1, string_ = IndentedIO.default_indent, string: string_, bol: nil, &block)
|
6
|
+
block.nil? || block.arity <= 1 or raise IndentedIO::Error.new "Wrong number of parameters"
|
7
|
+
obj = IndentedIO::IndentedIO.send(:new, $stdout, levels, string, bol)
|
8
|
+
if block_given?
|
9
|
+
if block.arity == 1
|
10
|
+
r = yield obj
|
11
|
+
elsif block.arity == 0
|
12
|
+
saved_stdout = $stdout
|
13
|
+
begin
|
14
|
+
$stdout = obj
|
15
|
+
r = yield
|
16
|
+
ensure
|
17
|
+
$stdout = saved_stdout
|
18
|
+
end
|
19
|
+
end
|
20
|
+
else
|
21
|
+
r = obj
|
22
|
+
end
|
23
|
+
r
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
data/lib/indented_io.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
|
2
|
+
require 'indented_io/version'
|
3
|
+
require 'indented_io/error'
|
4
|
+
require 'indented_io/indented_io'
|
5
|
+
require 'indented_io/indented_io_interface'
|
6
|
+
require 'indented_io/kernel'
|
7
|
+
require 'indented_io/io'
|
8
|
+
require 'indented_io/stringio'
|
9
|
+
|
10
|
+
# IndentedIO module
|
11
|
+
|
12
|
+
module IndentedIO
|
13
|
+
# Returns default indentation. ' ' (two spaces) is the default but it can be
|
14
|
+
# set by #default_indent
|
15
|
+
def self.default_indent() @DEFAULT_INDENT end
|
16
|
+
|
17
|
+
# Set default indentation
|
18
|
+
def self.default_indent=(indent) @DEFAULT_INDENT = indent end
|
19
|
+
|
20
|
+
private
|
21
|
+
@DEFAULT_INDENT = " "
|
22
|
+
end
|
23
|
+
|
metadata
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: indented_io
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.7.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Claus Rasmussen
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-05-11 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.16'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.16'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.0'
|
55
|
+
description: "\n IndentedIO extends Kernel, IO, and StringIO\n
|
56
|
+
\ with an #indent method that returns an IndentedIO\n object.
|
57
|
+
The IndentedIO object acts as the original\n object but
|
58
|
+
redefines the output methods #print,\n #printf, #puts,
|
59
|
+
and #p to print their output\n indented. Indentations are
|
60
|
+
stacked so that each new\n indentation adds to the previous
|
61
|
+
indendation\n "
|
62
|
+
email:
|
63
|
+
- claus.l.rasmussen@gmail.com
|
64
|
+
executables: []
|
65
|
+
extensions: []
|
66
|
+
extra_rdoc_files: []
|
67
|
+
files:
|
68
|
+
- ".gitignore"
|
69
|
+
- ".rspec"
|
70
|
+
- ".ruby-version"
|
71
|
+
- ".travis.yml"
|
72
|
+
- Gemfile
|
73
|
+
- LICENSE.txt
|
74
|
+
- README.md
|
75
|
+
- Rakefile
|
76
|
+
- TODO
|
77
|
+
- bin/console
|
78
|
+
- bin/setup
|
79
|
+
- indented_io.gemspec
|
80
|
+
- lib/indented_io.rb
|
81
|
+
- lib/indented_io/error.rb
|
82
|
+
- lib/indented_io/indented_io.rb
|
83
|
+
- lib/indented_io/indented_io_interface.rb
|
84
|
+
- lib/indented_io/io.rb
|
85
|
+
- lib/indented_io/kernel.rb
|
86
|
+
- lib/indented_io/stringio.rb
|
87
|
+
- lib/indented_io/version.rb
|
88
|
+
homepage: https://github.com/clrgit/indented_io
|
89
|
+
licenses:
|
90
|
+
- MIT
|
91
|
+
metadata:
|
92
|
+
allowed_push_host: https://rubygems.org
|
93
|
+
post_install_message:
|
94
|
+
rdoc_options: []
|
95
|
+
require_paths:
|
96
|
+
- lib
|
97
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - ">="
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
103
|
+
requirements:
|
104
|
+
- - ">="
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: '0'
|
107
|
+
requirements: []
|
108
|
+
rubyforge_project:
|
109
|
+
rubygems_version: 2.7.3
|
110
|
+
signing_key:
|
111
|
+
specification_version: 4
|
112
|
+
summary: Print indented text
|
113
|
+
test_files: []
|