pretty_ruby 0.0.1

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.
Files changed (3) hide show
  1. checksums.yaml +7 -0
  2. data/lib/pretty_ruby.rb +286 -0
  3. metadata +44 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: da280c9e01ed54b9551ec457bba0cf67dc8cb8641fe40818ec06a4e769169b51
4
+ data.tar.gz: 9a515a6958ce87c06084b3372d5ffdc4ea1d307f6b95b86a937e87d366e66584
5
+ SHA512:
6
+ metadata.gz: 560699e08e3c3f211eab15af1be03029e9ff4776cdb86d4b11c37e39973fe69fa20a055582183fd7b29f1e9b5564d3ad8732c0399c62db4d3635f342c2649aea
7
+ data.tar.gz: c53be4b9eb4efea964e20df15e64345171477e4f90045e203109a110ed4dcbf0d9fb4501dfea5df0d70fcbe49e4b9415b3feda4f317d41d64e70f9b497250887
@@ -0,0 +1,286 @@
1
+ # :count,
2
+ # :detect,
3
+ # :find_index,
4
+ # :find_all,
5
+ # :select,
6
+ # :reject,
7
+ # :collect,
8
+ # :map,
9
+ # :flat_map,
10
+ # :collect_concat,
11
+ # :inject,
12
+ # :reduce,
13
+ # :partition,
14
+ # :group_by,
15
+ # :first,
16
+ # :all?,
17
+ # :any?,
18
+ # :one?,
19
+ # :none?,
20
+ # :minmax,
21
+ # :minmax_by,
22
+ # :member?,
23
+ # :each_with_index,
24
+ # :reverse_each,
25
+ # :each_entry,
26
+ # :each_slice,
27
+ # :each_cons,
28
+ # :each_with_object,
29
+ # :zip,
30
+ # :take,
31
+ # :take_while,
32
+ # :drop,
33
+ # :drop_while,
34
+ # :cycle,
35
+ # :chunk,
36
+ # :slice_before,
37
+ # :slice_after,
38
+ # :slice_when,
39
+ # :chunk_while,
40
+ # :sum,
41
+ # :uniq]
42
+
43
+ module PrettyRuby
44
+
45
+
46
+ refine Numeric do
47
+ def max(other)
48
+ self >= other ? self : other
49
+ end
50
+
51
+ def min(other)
52
+ self <= other ? self : other
53
+ end
54
+
55
+ def squared
56
+ self * self
57
+ end
58
+
59
+ def doubled
60
+ 2 * self
61
+ end
62
+ end
63
+
64
+ refine Symbol do
65
+ def >>(next_proc)
66
+ ->(x) { next_proc.to_proc.(self.to_proc.(x)) }
67
+ end
68
+
69
+ # Need to redefine here so it picks up the other refinements
70
+ # They don't retroactively bubble up inheritance chains.
71
+ # Eg, `scan(:max)` requires that Numeric has our refined `max` method
72
+ #
73
+ def to_proc
74
+ ->(*args, &blk) do
75
+ receiver = args.first
76
+ if (blk)
77
+ receiver.send(self, &blk)
78
+ else
79
+ args[0] = self
80
+ receiver.send(*args)
81
+ end
82
+ end
83
+ end
84
+ end
85
+
86
+ refine Proc do
87
+ def >>(next_proc)
88
+ ->(x) { next_proc.to_proc.(self.(x)) }
89
+ end
90
+ end
91
+
92
+ refine Array do
93
+
94
+ # TODO: avoid duplication with Enumerable?
95
+ def to_proc
96
+ fn = first.to_proc
97
+ args = drop(1)
98
+ # TODO: document better
99
+ # handles stuff like
100
+ # maxs = cols.map([:map, :to_s >> :size] >> :max)
101
+ if args.first.is_a?(Proc)
102
+ ->(x) { fn.(x, &args.first) }
103
+ else
104
+ ->(x) { fn.(x, *args) }
105
+ end
106
+ end
107
+
108
+ def drop(n)
109
+ n >= 0 ? super(n) : take([0, size+n].max)
110
+ end
111
+
112
+ def take(n)
113
+ n >= 0 ? super(n) : drop([0, size+n].max)
114
+ end
115
+
116
+ def >>(other)
117
+ ->(x) { other.to_proc.(to_proc.(x)) }
118
+ end
119
+
120
+ # def to_proc
121
+ # ArrayWithToProc.new(self).to_proc
122
+ # end
123
+
124
+ # Because Array has a custom implementation of map, instead of just mixing
125
+ # in Enumerable, we need to refine its map separately, even though we use
126
+ # the same code.
127
+ #
128
+ def map(*args, &blk)
129
+ blk = blk ? blk : args.to_proc
130
+ super(&blk)
131
+ end
132
+
133
+ def tail
134
+ drop(1)
135
+ end
136
+
137
+ def init
138
+ drop(-1)
139
+ end
140
+
141
+ # TODO: reduce in place
142
+ #
143
+ def right_reduce(init = nil, sym = nil, &blk)
144
+ reverse.reduce(init, sym, &blk)
145
+ end
146
+
147
+ # TODO: make in place
148
+ #
149
+ def rscan(fn = nil, &blk)
150
+ reverse.scan(fn, &blk)
151
+ end
152
+
153
+ def scan(fn = nil, &blk)
154
+ no_args = !fn && !blk
155
+ return partial_seqs if no_args
156
+ blk = fn ? fn.to_proc : blk
157
+ self.drop(1).reduce([self.first]) do |m, x|
158
+ m << blk.(m.last, x)
159
+ end
160
+ end
161
+
162
+ def nesting_level
163
+ 0.step.find { |n| flatten(n).none?(Array) }
164
+ end
165
+
166
+ class NDimMatrix < Array
167
+
168
+ module PrivateArray
169
+ refine Array do
170
+ using PrettyRuby
171
+
172
+ def aligned_cols(col_maxs)
173
+ nesting_level == 1 ?
174
+ aligned_cols_2d(col_maxs) :
175
+ map{ |x| x.aligned_cols(col_maxs) }
176
+ end
177
+
178
+ def aligned_cols_2d(col_widths)
179
+ transpose.zip(col_widths).map do |col, width|
180
+ col.map{ |x| sprintf("%#{width}s", x) }
181
+ end.transpose
182
+ end
183
+
184
+ def joined_records(nesting)
185
+ nesting == 0 ?
186
+ join(' ') :
187
+ map{ |x| x.joined_records(nesting - 1) }.join("\n" * nesting)
188
+ end
189
+ end
190
+ end
191
+
192
+ using PrivateArray
193
+
194
+ def to_s
195
+ nest_lev = nesting_level
196
+ matrix_2d = flatten(nest_lev - 1)
197
+ cols = matrix_2d.transpose
198
+ col_maxs = cols.map([:map, :to_s >> :size] >> :max)
199
+ aligned_cols(col_maxs)
200
+ .joined_records(nest_lev)
201
+ end
202
+ end
203
+
204
+ def formatted_matrix
205
+ # make ordinary arrays work without special casing them
206
+ #
207
+ matrix = nesting_level > 0 ? self : [self]
208
+ NDimMatrix.new(matrix).to_s
209
+ end
210
+
211
+ private
212
+
213
+ def partial_seqs
214
+ self.drop(1).reduce([[self.first]]) do |m, x|
215
+ m << m.last + [x]
216
+ end
217
+ end
218
+
219
+ end
220
+
221
+ #TODO: add separate tests for this
222
+ refine ::Enumerable do
223
+
224
+ def to_proc
225
+ fn = first.to_proc
226
+ args = drop(1)
227
+ # TODO: document better
228
+ # handles stuff like
229
+ # maxs = cols.map([:map, :to_s >> :size] >> :max)
230
+ if args.first.is_a?(Proc)
231
+ ->(x) { fn.(x, &args.first) }
232
+ else
233
+ ->(x) { fn.(x, *args) }
234
+ end
235
+ end
236
+
237
+ def map(*args, &blk)
238
+ return super unless args_given?(args, blk)
239
+ super(&smart_block(args, blk))
240
+ end
241
+
242
+ def max_by(*args, &blk)
243
+ return super unless args_given?(args, blk)
244
+ return super(args.first, &blk) if n_given?(args)
245
+ super(&smart_block(args, blk))
246
+ end
247
+
248
+ def min_by(*args, &blk)
249
+ return super unless args_given?(args, blk)
250
+ return super(args.first, &blk) if n_given?(args)
251
+ super(&smart_block(args, blk))
252
+ end
253
+
254
+ def sort_by(*args, &blk)
255
+ return super unless args_given?(args, blk)
256
+ super(&smart_block(args, blk))
257
+ end
258
+
259
+ private
260
+
261
+ def args_given?(args, blk)
262
+ blk || !args.empty?
263
+ end
264
+
265
+ def n_given?(args)
266
+ args && args.first.is_a?(Integer)
267
+ end
268
+
269
+ def smart_block(args, blk)
270
+ blk ? blk : args.to_proc
271
+ end
272
+ end
273
+
274
+ refine TrueClass do
275
+ def to_i
276
+ 1
277
+ end
278
+ end
279
+
280
+ refine FalseClass do
281
+ def to_i
282
+ 0
283
+ end
284
+ end
285
+
286
+ end
metadata ADDED
@@ -0,0 +1,44 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pretty_ruby
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Jonah Goldstein
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-07-23 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description:
14
+ email:
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - lib/pretty_ruby.rb
20
+ homepage: https://github.com/jonahx/pretty_ruby
21
+ licenses:
22
+ - MIT
23
+ metadata: {}
24
+ post_install_message:
25
+ rdoc_options: []
26
+ require_paths:
27
+ - lib
28
+ required_ruby_version: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ required_rubygems_version: !ruby/object:Gem::Requirement
34
+ requirements:
35
+ - - ">="
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ requirements: []
39
+ rubyforge_project:
40
+ rubygems_version: 2.7.6
41
+ signing_key:
42
+ specification_version: 4
43
+ summary: Syntax improvements and other useful methods for ruby
44
+ test_files: []