pretty_irb 0.1.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/00-MANIFEST.md +356 -0
- data/ADVANCED_FEATURES.md +440 -0
- data/AI_HELP.md +408 -0
- data/AI_QUICK_START.md +247 -0
- data/COMPLETE.md +421 -0
- data/EXAMPLES.md +206 -0
- data/FEATURE_SHOWCASE.md +441 -0
- data/FILE_STRUCTURE.md +231 -0
- data/Gemfile +3 -0
- data/IMPLEMENTATION_COMPLETE.md +309 -0
- data/INDEX.md +708 -0
- data/INSTALL.md +250 -0
- data/LICENSE.txt +21 -0
- data/PUBLISH_TO_RUBYGEMS.md +466 -0
- data/QUICKSTART.md +70 -0
- data/QUICK_REFERENCE.md +253 -0
- data/README.md +251 -0
- data/Rakefile +6 -0
- data/SETUP.md +209 -0
- data/START_HERE.md +462 -0
- data/SUMMARY.md +372 -0
- data/WELCOME.md +300 -0
- data/WHAT_IS_NEW.md +324 -0
- data/exe/irb1 +6 -0
- data/exe/pretty_irb +6 -0
- data/lib/pretty_irb/ai_helper.rb +842 -0
- data/lib/pretty_irb/auto_corrector.rb +76 -0
- data/lib/pretty_irb/benchmarker.rb +94 -0
- data/lib/pretty_irb/cheat_sheet.rb +476 -0
- data/lib/pretty_irb/formatter.rb +66 -0
- data/lib/pretty_irb/history_manager.rb +97 -0
- data/lib/pretty_irb/shell.rb +387 -0
- data/lib/pretty_irb/snippet_manager.rb +119 -0
- data/lib/pretty_irb/variable_inspector.rb +146 -0
- data/lib/pretty_irb/version.rb +3 -0
- data/lib/pretty_irb.rb +26 -0
- metadata +200 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
module PrettyIRB
|
|
2
|
+
class AutoCorrector
|
|
3
|
+
class << self
|
|
4
|
+
# Suggest corrections for common Ruby mistakes
|
|
5
|
+
def suggest_corrections(error)
|
|
6
|
+
case error
|
|
7
|
+
when NameError
|
|
8
|
+
suggest_name_error(error)
|
|
9
|
+
when NoMethodError
|
|
10
|
+
suggest_method_error(error)
|
|
11
|
+
when SyntaxError
|
|
12
|
+
suggest_syntax_error(error)
|
|
13
|
+
else
|
|
14
|
+
""
|
|
15
|
+
end
|
|
16
|
+
rescue
|
|
17
|
+
""
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Auto-correct common typos in code
|
|
21
|
+
def auto_correct_code(code)
|
|
22
|
+
code = fix_method_names(code)
|
|
23
|
+
code
|
|
24
|
+
rescue
|
|
25
|
+
code
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
private
|
|
29
|
+
|
|
30
|
+
def suggest_name_error(error)
|
|
31
|
+
# Try to get corrections, but safely
|
|
32
|
+
begin
|
|
33
|
+
if error.respond_to?(:corrections)
|
|
34
|
+
corrections = error.corrections
|
|
35
|
+
if corrections.is_a?(Array) && corrections.length > 0
|
|
36
|
+
"\nš” Did you mean?: #{corrections.join(', ')}"
|
|
37
|
+
else
|
|
38
|
+
""
|
|
39
|
+
end
|
|
40
|
+
else
|
|
41
|
+
""
|
|
42
|
+
end
|
|
43
|
+
rescue
|
|
44
|
+
""
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def suggest_method_error(error)
|
|
49
|
+
begin
|
|
50
|
+
if error.respond_to?(:corrections)
|
|
51
|
+
corrections = error.corrections
|
|
52
|
+
if corrections.is_a?(Array) && corrections.length > 0
|
|
53
|
+
"\nš” Did you mean?: #{corrections.join(', ')}"
|
|
54
|
+
else
|
|
55
|
+
""
|
|
56
|
+
end
|
|
57
|
+
else
|
|
58
|
+
""
|
|
59
|
+
end
|
|
60
|
+
rescue
|
|
61
|
+
""
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def suggest_syntax_error(error)
|
|
66
|
+
""
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def fix_method_names(code)
|
|
70
|
+
# Common method name corrections
|
|
71
|
+
code.gsub(/\.lenght/, ".length")
|
|
72
|
+
.gsub(/\.sizze/, ".size")
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
require "benchmark"
|
|
2
|
+
|
|
3
|
+
module PrettyIRB
|
|
4
|
+
class Benchmarker
|
|
5
|
+
# Benchmark a code snippet
|
|
6
|
+
def self.benchmark(code, iterations = 1000)
|
|
7
|
+
begin
|
|
8
|
+
time = Benchmark.measure do
|
|
9
|
+
iterations.times do
|
|
10
|
+
eval(code)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
total_ms = time.real * 1000
|
|
15
|
+
per_iteration_us = (total_ms * 1000) / iterations
|
|
16
|
+
|
|
17
|
+
format_benchmark_result(code, iterations, total_ms, per_iteration_us)
|
|
18
|
+
rescue => e
|
|
19
|
+
"ā Benchmark failed: #{e.message}"
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Compare two code snippets
|
|
24
|
+
def self.compare(code1, code2, iterations = 1000)
|
|
25
|
+
begin
|
|
26
|
+
time1 = Benchmark.measure do
|
|
27
|
+
iterations.times { eval(code1) }
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
time2 = Benchmark.measure do
|
|
31
|
+
iterations.times { eval(code2) }
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
format_comparison(code1, code2, time1, time2, iterations)
|
|
35
|
+
rescue => e
|
|
36
|
+
"ā Comparison failed: #{e.message}"
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Profile memory
|
|
41
|
+
def self.profile_memory(code, iterations = 100)
|
|
42
|
+
begin
|
|
43
|
+
gc_stat_before = GC.stat
|
|
44
|
+
|
|
45
|
+
iterations.times { eval(code) }
|
|
46
|
+
|
|
47
|
+
gc_stat_after = GC.stat
|
|
48
|
+
|
|
49
|
+
format_memory_profile(gc_stat_before, gc_stat_after, iterations)
|
|
50
|
+
rescue => e
|
|
51
|
+
"ā Memory profile failed: #{e.message}"
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
private
|
|
56
|
+
|
|
57
|
+
def self.format_benchmark_result(code, iterations, total_ms, per_iteration_us)
|
|
58
|
+
output = "ā±ļø Benchmark Results:\n\n"
|
|
59
|
+
output += "Code: #{code.truncate(50)}\n"
|
|
60
|
+
output += "Iterations: #{iterations}\n\n"
|
|
61
|
+
output += "Total Time: #{total_ms.round(2)} ms\n"
|
|
62
|
+
output += "Per Iteration: #{per_iteration_us.round(4)} µs\n"
|
|
63
|
+
output += "Rate: #{(iterations / (total_ms / 1000)).round(0)} ops/sec\n"
|
|
64
|
+
output
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def self.format_comparison(code1, code2, time1, time2, iterations)
|
|
68
|
+
ratio = time2.real / time1.real
|
|
69
|
+
faster = ratio < 1 ? "Code 2 is #{(1/ratio - 1) * 100}% faster" : "Code 1 is #{(ratio - 1) * 100}% faster"
|
|
70
|
+
|
|
71
|
+
output = "ā” Comparison Results:\n\n"
|
|
72
|
+
output += "Iterations: #{iterations}\n\n"
|
|
73
|
+
output += "Code 1 (#{code1.truncate(40)}):\n"
|
|
74
|
+
output += " Time: #{(time1.real * 1000).round(2)} ms\n\n"
|
|
75
|
+
output += "Code 2 (#{code2.truncate(40)}):\n"
|
|
76
|
+
output += " Time: #{(time2.real * 1000).round(2)} ms\n\n"
|
|
77
|
+
output += "Winner: #{faster}\n"
|
|
78
|
+
output
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def self.format_memory_profile(before, after, iterations)
|
|
82
|
+
allocated = after[:total_allocated_objects] - before[:total_allocated_objects]
|
|
83
|
+
freed = after[:total_freed_objects] - before[:total_freed_objects]
|
|
84
|
+
|
|
85
|
+
output = "š¾ Memory Profile:\n\n"
|
|
86
|
+
output += "Iterations: #{iterations}\n\n"
|
|
87
|
+
output += "Objects Allocated: #{allocated}\n"
|
|
88
|
+
output += "Objects Freed: #{freed}\n"
|
|
89
|
+
output += "Net Objects: #{allocated - freed}\n"
|
|
90
|
+
output += "Per Iteration: #{((allocated - freed) / iterations).round(1)} objects\n"
|
|
91
|
+
output
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
@@ -0,0 +1,476 @@
|
|
|
1
|
+
module PrettyIRB
|
|
2
|
+
class CheatSheet
|
|
3
|
+
class << self
|
|
4
|
+
# Get Ruby cheat sheet
|
|
5
|
+
def show(topic = nil)
|
|
6
|
+
return general_cheatsheet if topic.nil?
|
|
7
|
+
|
|
8
|
+
case topic.downcase
|
|
9
|
+
when "array"
|
|
10
|
+
array_cheatsheet
|
|
11
|
+
when "hash"
|
|
12
|
+
hash_cheatsheet
|
|
13
|
+
when "string"
|
|
14
|
+
string_cheatsheet
|
|
15
|
+
when "enumerable"
|
|
16
|
+
enumerable_cheatsheet
|
|
17
|
+
when "file"
|
|
18
|
+
file_cheatsheet
|
|
19
|
+
when "regex"
|
|
20
|
+
regex_cheatsheet
|
|
21
|
+
when "date"
|
|
22
|
+
date_cheatsheet
|
|
23
|
+
else
|
|
24
|
+
"Unknown topic. Available: array, hash, string, enumerable, file, regex, date"
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
private
|
|
29
|
+
|
|
30
|
+
def general_cheatsheet
|
|
31
|
+
<<~SHEET
|
|
32
|
+
š Ruby General Cheat Sheet
|
|
33
|
+
|
|
34
|
+
Variables & Constants:
|
|
35
|
+
var = value # Local variable
|
|
36
|
+
@var = value # Instance variable
|
|
37
|
+
@@var = value # Class variable
|
|
38
|
+
$var = value # Global variable
|
|
39
|
+
CONST = value # Constant
|
|
40
|
+
|
|
41
|
+
Conditionals:
|
|
42
|
+
if condition; code; end
|
|
43
|
+
unless condition; code; end
|
|
44
|
+
case var
|
|
45
|
+
when value; code
|
|
46
|
+
else code
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
Loops:
|
|
50
|
+
while condition; code; end
|
|
51
|
+
until condition; code; end
|
|
52
|
+
for item in array; code; end
|
|
53
|
+
array.each { |item| code }
|
|
54
|
+
|
|
55
|
+
Methods:
|
|
56
|
+
def method_name(args)
|
|
57
|
+
code
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
Classes:
|
|
61
|
+
class ClassName
|
|
62
|
+
def initialize(args)
|
|
63
|
+
@var = args
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
Operators:
|
|
68
|
+
Arithmetic: + - * / % **
|
|
69
|
+
Comparison: == != < > <= >=
|
|
70
|
+
Logical: && || !
|
|
71
|
+
Bitwise: & | ^ ~ << >>
|
|
72
|
+
|
|
73
|
+
String Methods:
|
|
74
|
+
upcase, downcase, capitalize, length, reverse,
|
|
75
|
+
split(sep), gsub(pattern, replacement), strip
|
|
76
|
+
|
|
77
|
+
Array Methods:
|
|
78
|
+
push(x), pop, shift, unshift(x),
|
|
79
|
+
map, select, reduce, sort, reverse, join, length
|
|
80
|
+
|
|
81
|
+
Hash Methods:
|
|
82
|
+
keys, values, each, merge, delete,
|
|
83
|
+
has_key?, fetch, to_a
|
|
84
|
+
|
|
85
|
+
Common Patterns:
|
|
86
|
+
array.map { |x| x * 2 } # Transform
|
|
87
|
+
array.select { |x| x > 5 } # Filter
|
|
88
|
+
array.reduce(:+) # Combine
|
|
89
|
+
string.gsub(/pattern/, "sub") # Replace
|
|
90
|
+
hash.each { |k, v| ... } # Iterate
|
|
91
|
+
SHEET
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def array_cheatsheet
|
|
95
|
+
<<~SHEET
|
|
96
|
+
š Array Cheat Sheet
|
|
97
|
+
|
|
98
|
+
Creating Arrays:
|
|
99
|
+
arr = [1, 2, 3]
|
|
100
|
+
arr = Array.new(5)
|
|
101
|
+
arr = Array.new(5, 0)
|
|
102
|
+
arr = (1..5).to_a
|
|
103
|
+
|
|
104
|
+
Accessing:
|
|
105
|
+
arr[0] # First element
|
|
106
|
+
arr[-1] # Last element
|
|
107
|
+
arr[1..3] # Range
|
|
108
|
+
arr.first # First element
|
|
109
|
+
arr.last # Last element
|
|
110
|
+
arr.at(2) # Element at index
|
|
111
|
+
|
|
112
|
+
Modifying:
|
|
113
|
+
arr << 4 # Push
|
|
114
|
+
arr.push(5, 6) # Push multiple
|
|
115
|
+
arr.unshift(0) # Add to front
|
|
116
|
+
arr.pop # Remove last
|
|
117
|
+
arr.shift # Remove first
|
|
118
|
+
arr.delete(2) # Delete value
|
|
119
|
+
arr.delete_at(1) # Delete at index
|
|
120
|
+
arr[0] = 10 # Replace
|
|
121
|
+
|
|
122
|
+
Querying:
|
|
123
|
+
arr.length / arr.size # Length
|
|
124
|
+
arr.empty? # Is empty?
|
|
125
|
+
arr.include?(2) # Contains?
|
|
126
|
+
arr.index(2) # Index of
|
|
127
|
+
arr.count # Count
|
|
128
|
+
|
|
129
|
+
Iteration:
|
|
130
|
+
arr.each { |x| puts x }
|
|
131
|
+
arr.map { |x| x * 2 }
|
|
132
|
+
arr.select { |x| x > 2 }
|
|
133
|
+
arr.find { |x| x > 2 }
|
|
134
|
+
arr.reduce(:+)
|
|
135
|
+
arr.any? { |x| x > 5 }
|
|
136
|
+
arr.all? { |x| x > 0 }
|
|
137
|
+
|
|
138
|
+
Combining:
|
|
139
|
+
arr1 + arr2 # Concatenate
|
|
140
|
+
arr1 | arr2 # Union
|
|
141
|
+
arr1 & arr2 # Intersection
|
|
142
|
+
arr1 - arr2 # Difference
|
|
143
|
+
arr.flatten # Flatten
|
|
144
|
+
arr.compact # Remove nils
|
|
145
|
+
arr.uniq # Remove duplicates
|
|
146
|
+
|
|
147
|
+
Sorting:
|
|
148
|
+
arr.sort # Ascending
|
|
149
|
+
arr.sort.reverse # Descending
|
|
150
|
+
arr.sort { |a, b| b <=> a } # Custom
|
|
151
|
+
SHEET
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def hash_cheatsheet
|
|
155
|
+
<<~SHEET
|
|
156
|
+
š Hash Cheat Sheet
|
|
157
|
+
|
|
158
|
+
Creating Hashes:
|
|
159
|
+
hash = {a: 1, b: 2}
|
|
160
|
+
hash = {"a" => 1, "b" => 2}
|
|
161
|
+
hash = Hash.new
|
|
162
|
+
hash = Hash.new(0)
|
|
163
|
+
|
|
164
|
+
Accessing:
|
|
165
|
+
hash[:a] # Get by key
|
|
166
|
+
hash.fetch(:a, default) # Get with default
|
|
167
|
+
hash.dig(:a, :b) # Nested access
|
|
168
|
+
|
|
169
|
+
Adding/Updating:
|
|
170
|
+
hash[:c] = 3
|
|
171
|
+
hash.store(:d, 4)
|
|
172
|
+
hash.merge(other_hash)
|
|
173
|
+
hash.update(other_hash)
|
|
174
|
+
|
|
175
|
+
Removing:
|
|
176
|
+
hash.delete(:a)
|
|
177
|
+
hash.clear
|
|
178
|
+
hash.reject { |k, v| k == :a }
|
|
179
|
+
|
|
180
|
+
Querying:
|
|
181
|
+
hash.keys
|
|
182
|
+
hash.values
|
|
183
|
+
hash.length / hash.size
|
|
184
|
+
hash.empty?
|
|
185
|
+
hash.has_key?(:a)
|
|
186
|
+
hash.has_value?(1)
|
|
187
|
+
hash.key?(a)
|
|
188
|
+
hash.value?(1)
|
|
189
|
+
|
|
190
|
+
Iteration:
|
|
191
|
+
hash.each { |k, v| ... }
|
|
192
|
+
hash.map { |k, v| ... }
|
|
193
|
+
hash.select { |k, v| ... }
|
|
194
|
+
hash.reject { |k, v| ... }
|
|
195
|
+
|
|
196
|
+
Transforming:
|
|
197
|
+
hash.invert # Swap keys/values
|
|
198
|
+
hash.merge(other) # Combine
|
|
199
|
+
hash.select { |k, v| ... } # Filter
|
|
200
|
+
hash.map { |k, v| ... } # Transform
|
|
201
|
+
hash.to_a # Convert to array
|
|
202
|
+
|
|
203
|
+
Special Methods:
|
|
204
|
+
hash.flatten # Flatten to array
|
|
205
|
+
hash.values_at(:a, :b) # Get multiple
|
|
206
|
+
hash.slice(:a, :b) # Get subset
|
|
207
|
+
hash.except(:a) # Remove keys
|
|
208
|
+
SHEET
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
def string_cheatsheet
|
|
212
|
+
<<~SHEET
|
|
213
|
+
š String Cheat Sheet
|
|
214
|
+
|
|
215
|
+
Creating Strings:
|
|
216
|
+
str = "double quotes"
|
|
217
|
+
str = 'single quotes'
|
|
218
|
+
str = %q{alternative}
|
|
219
|
+
str = <<HEREDOC
|
|
220
|
+
Multiple
|
|
221
|
+
Lines
|
|
222
|
+
HEREDOC
|
|
223
|
+
|
|
224
|
+
Interpolation:
|
|
225
|
+
"Hello #{name}"
|
|
226
|
+
"Result: #{2 + 2}"
|
|
227
|
+
|
|
228
|
+
Case Methods:
|
|
229
|
+
str.upcase # UPPERCASE
|
|
230
|
+
str.downcase # lowercase
|
|
231
|
+
str.capitalize # Capitalized
|
|
232
|
+
str.swapcase # SwAp CaSe
|
|
233
|
+
|
|
234
|
+
Querying:
|
|
235
|
+
str.length / str.size
|
|
236
|
+
str.empty?
|
|
237
|
+
str.include?("substring")
|
|
238
|
+
str.start_with?("He")
|
|
239
|
+
str.end_with?("lo")
|
|
240
|
+
|
|
241
|
+
Extracting:
|
|
242
|
+
str[0] # First char
|
|
243
|
+
str[-1] # Last char
|
|
244
|
+
str[0..4] # Range
|
|
245
|
+
str.chars # Array of chars
|
|
246
|
+
str.split(" ") # Split by delimiter
|
|
247
|
+
|
|
248
|
+
Searching/Replacing:
|
|
249
|
+
str.index("substring")
|
|
250
|
+
str.sub(pattern, replacement) # Replace first
|
|
251
|
+
str.gsub(pattern, replacement) # Replace all
|
|
252
|
+
str.scan(regex) # Find all
|
|
253
|
+
|
|
254
|
+
Whitespace:
|
|
255
|
+
str.strip # Remove leading/trailing
|
|
256
|
+
str.lstrip # Remove leading
|
|
257
|
+
str.rstrip # Remove trailing
|
|
258
|
+
str.chomp # Remove newline
|
|
259
|
+
|
|
260
|
+
Conversion:
|
|
261
|
+
str.to_i # To integer
|
|
262
|
+
str.to_f # To float
|
|
263
|
+
str.to_sym # To symbol
|
|
264
|
+
str.to_a # To array
|
|
265
|
+
|
|
266
|
+
Formatting:
|
|
267
|
+
str.center(10)
|
|
268
|
+
str.ljust(10)
|
|
269
|
+
str.rjust(10)
|
|
270
|
+
str.reverse
|
|
271
|
+
SHEET
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
def enumerable_cheatsheet
|
|
275
|
+
<<~SHEET
|
|
276
|
+
š Enumerable Cheat Sheet
|
|
277
|
+
|
|
278
|
+
Basic Iteration:
|
|
279
|
+
each { |x| ... } # Iterate all
|
|
280
|
+
each_with_index { |x, i| ... }
|
|
281
|
+
each_with_object(obj) { |x, o| ... }
|
|
282
|
+
|
|
283
|
+
Transformation:
|
|
284
|
+
map { |x| ... } # Transform elements
|
|
285
|
+
collect { |x| ... } # Alias for map
|
|
286
|
+
flat_map { |x| ... } # Map then flatten
|
|
287
|
+
|
|
288
|
+
Selection/Filtering:
|
|
289
|
+
select { |x| ... } # Keep matching
|
|
290
|
+
filter { |x| ... } # Alias for select
|
|
291
|
+
reject { |x| ... } # Remove matching
|
|
292
|
+
find { |x| ... } # First match
|
|
293
|
+
find_all { |x| ... } # All matches (select)
|
|
294
|
+
|
|
295
|
+
Reduction:
|
|
296
|
+
reduce(:+) # Sum
|
|
297
|
+
reduce(0, :+) # Sum with default
|
|
298
|
+
reduce { |acc, x| acc + x }
|
|
299
|
+
inject { |acc, x| acc + x } # Alias
|
|
300
|
+
|
|
301
|
+
Checking:
|
|
302
|
+
any? { |x| ... } # Any match?
|
|
303
|
+
all? { |x| ... } # All match?
|
|
304
|
+
none? { |x| ... } # None match?
|
|
305
|
+
one? { |x| ... } # Exactly one?
|
|
306
|
+
|
|
307
|
+
Grouping:
|
|
308
|
+
group_by { |x| ... } # Group by key
|
|
309
|
+
partition { |x| ... } # Split into 2 groups
|
|
310
|
+
chunk { |x| ... } # Consecutive groups
|
|
311
|
+
|
|
312
|
+
Sorting:
|
|
313
|
+
sort # Ascending
|
|
314
|
+
sort { |a, b| ... } # Custom sort
|
|
315
|
+
sort_by { |x| ... } # Sort by value
|
|
316
|
+
max, min # Extreme values
|
|
317
|
+
max_by, min_by # By value
|
|
318
|
+
|
|
319
|
+
Other:
|
|
320
|
+
count # Count elements
|
|
321
|
+
first(n) # First n
|
|
322
|
+
last(n) # Last n
|
|
323
|
+
take(n) # Take first n
|
|
324
|
+
drop(n) # Skip first n
|
|
325
|
+
zip(*arrays) # Combine arrays
|
|
326
|
+
cycle(n) { |x| ... } # Repeat n times
|
|
327
|
+
SHEET
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
def file_cheatsheet
|
|
331
|
+
<<~SHEET
|
|
332
|
+
š File I/O Cheat Sheet
|
|
333
|
+
|
|
334
|
+
Reading Files:
|
|
335
|
+
File.read("file.txt") # Read entire file
|
|
336
|
+
File.readlines("file.txt") # Read as array
|
|
337
|
+
File.open("file.txt") { |f| ... } # Read with block
|
|
338
|
+
|
|
339
|
+
Writing Files:
|
|
340
|
+
File.write("file.txt", content)
|
|
341
|
+
File.open("file.txt", "w") do |f|
|
|
342
|
+
f.write("content")
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
Appending:
|
|
346
|
+
File.write("file.txt", content, mode: "a")
|
|
347
|
+
File.open("file.txt", "a") do |f|
|
|
348
|
+
f.puts("new line")
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
Checking:
|
|
352
|
+
File.exist?("file.txt")
|
|
353
|
+
File.file?("path")
|
|
354
|
+
File.directory?("path")
|
|
355
|
+
File.size("file.txt")
|
|
356
|
+
|
|
357
|
+
Paths:
|
|
358
|
+
File.expand_path("file.txt")
|
|
359
|
+
File.dirname("path/file.txt")
|
|
360
|
+
File.basename("path/file.txt")
|
|
361
|
+
File.join("path", "to", "file")
|
|
362
|
+
|
|
363
|
+
Operations:
|
|
364
|
+
File.delete("file.txt")
|
|
365
|
+
File.rename("old.txt", "new.txt")
|
|
366
|
+
File.copy("source.txt", "dest.txt")
|
|
367
|
+
Dir.mkdir("directory")
|
|
368
|
+
Dir.glob("*.txt")
|
|
369
|
+
SHEET
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
def regex_cheatsheet
|
|
373
|
+
<<~SHEET
|
|
374
|
+
š Regular Expressions Cheat Sheet
|
|
375
|
+
|
|
376
|
+
Matching:
|
|
377
|
+
/pattern/.match(string)
|
|
378
|
+
/pattern/ =~ string # Returns index or nil
|
|
379
|
+
string.match(/pattern/)
|
|
380
|
+
string.scan(/pattern/) # Find all
|
|
381
|
+
|
|
382
|
+
Anchors:
|
|
383
|
+
^ # Start of line
|
|
384
|
+
$ # End of line
|
|
385
|
+
\\A # Start of string
|
|
386
|
+
\\Z # End of string
|
|
387
|
+
\\b # Word boundary
|
|
388
|
+
|
|
389
|
+
Character Classes:
|
|
390
|
+
[abc] # a, b, or c
|
|
391
|
+
[^abc] # Not a, b, or c
|
|
392
|
+
[a-z] # a to z
|
|
393
|
+
. # Any character
|
|
394
|
+
\\d # Digit [0-9]
|
|
395
|
+
\\w # Word [a-zA-Z0-9_]
|
|
396
|
+
\\s # Whitespace
|
|
397
|
+
|
|
398
|
+
Quantifiers:
|
|
399
|
+
* # 0 or more
|
|
400
|
+
+ # 1 or more
|
|
401
|
+
? # 0 or 1
|
|
402
|
+
{n} # Exactly n
|
|
403
|
+
{n,} # n or more
|
|
404
|
+
{n,m} # n to m
|
|
405
|
+
|
|
406
|
+
Groups:
|
|
407
|
+
(pattern) # Capture group
|
|
408
|
+
(?:...) # Non-capture
|
|
409
|
+
\\1, \\2 # Backreference
|
|
410
|
+
|
|
411
|
+
Flags:
|
|
412
|
+
/pattern/i # Case insensitive
|
|
413
|
+
/pattern/m # Multiline
|
|
414
|
+
/pattern/x # Extended
|
|
415
|
+
|
|
416
|
+
Common Patterns:
|
|
417
|
+
/\\d+/ # One or more digits
|
|
418
|
+
/\\w+@\\w+\\.\\w+/ # Email-ish
|
|
419
|
+
/^\\d{3}-\\d{4}$/ # Phone number-ish
|
|
420
|
+
/https?:\\/\\/.+/ # URL-ish
|
|
421
|
+
SHEET
|
|
422
|
+
end
|
|
423
|
+
|
|
424
|
+
def date_cheatsheet
|
|
425
|
+
<<~SHEET
|
|
426
|
+
š Date & Time Cheat Sheet
|
|
427
|
+
|
|
428
|
+
Current Time:
|
|
429
|
+
Time.now # Current time
|
|
430
|
+
Date.today # Current date
|
|
431
|
+
DateTime.now # Current datetime
|
|
432
|
+
|
|
433
|
+
Creating:
|
|
434
|
+
Time.new(2025, 11, 26)
|
|
435
|
+
Date.new(2025, 11, 26)
|
|
436
|
+
DateTime.parse("2025-11-26")
|
|
437
|
+
Time.parse("2025-11-26 10:30:00")
|
|
438
|
+
|
|
439
|
+
Formatting:
|
|
440
|
+
time.strftime("%Y-%m-%d")
|
|
441
|
+
time.strftime("%H:%M:%S")
|
|
442
|
+
time.to_s
|
|
443
|
+
date.to_s
|
|
444
|
+
|
|
445
|
+
Extracting:
|
|
446
|
+
time.year
|
|
447
|
+
time.month
|
|
448
|
+
time.day
|
|
449
|
+
time.hour
|
|
450
|
+
time.min
|
|
451
|
+
time.sec
|
|
452
|
+
time.wday # Day of week (0=Sunday)
|
|
453
|
+
|
|
454
|
+
Arithmetic:
|
|
455
|
+
time + 3600 # Add seconds
|
|
456
|
+
time - 86400 # Subtract seconds
|
|
457
|
+
date + 1 # Add days
|
|
458
|
+
date - 1 # Subtract days
|
|
459
|
+
|
|
460
|
+
Comparing:
|
|
461
|
+
time1 < time2
|
|
462
|
+
time1 > time2
|
|
463
|
+
time1 == time2
|
|
464
|
+
|
|
465
|
+
Ranges:
|
|
466
|
+
(start_date..end_date).each { |d| ... }
|
|
467
|
+
|
|
468
|
+
Conversion:
|
|
469
|
+
time.to_date
|
|
470
|
+
time.to_i # Unix timestamp
|
|
471
|
+
Time.at(timestamp) # From timestamp
|
|
472
|
+
SHEET
|
|
473
|
+
end
|
|
474
|
+
end
|
|
475
|
+
end
|
|
476
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
require "colorize"
|
|
2
|
+
|
|
3
|
+
module PrettyIRB
|
|
4
|
+
class Formatter
|
|
5
|
+
class << self
|
|
6
|
+
# Pretty print output with colors
|
|
7
|
+
def format_output(output)
|
|
8
|
+
case output
|
|
9
|
+
when String
|
|
10
|
+
output.light_blue
|
|
11
|
+
when Numeric
|
|
12
|
+
output.to_s.light_green
|
|
13
|
+
when TrueClass, FalseClass
|
|
14
|
+
output.to_s.light_cyan
|
|
15
|
+
when NilClass
|
|
16
|
+
"nil".light_black
|
|
17
|
+
when Array
|
|
18
|
+
format_array(output)
|
|
19
|
+
when Hash
|
|
20
|
+
format_hash(output)
|
|
21
|
+
else
|
|
22
|
+
output.inspect.light_yellow
|
|
23
|
+
end
|
|
24
|
+
rescue
|
|
25
|
+
output.to_s
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Format error messages with pretty colors
|
|
29
|
+
def format_error(error_message)
|
|
30
|
+
error_message.red.bold
|
|
31
|
+
rescue
|
|
32
|
+
error_message
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Format success messages
|
|
36
|
+
def format_success(message)
|
|
37
|
+
message.green
|
|
38
|
+
rescue
|
|
39
|
+
message
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Format warning messages
|
|
43
|
+
def format_warning(message)
|
|
44
|
+
message.yellow
|
|
45
|
+
rescue
|
|
46
|
+
message
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
private
|
|
50
|
+
|
|
51
|
+
def format_array(array)
|
|
52
|
+
formatted = array.map { |item| format_output(item) }.join(", ")
|
|
53
|
+
"[#{formatted}]".light_blue
|
|
54
|
+
rescue
|
|
55
|
+
array.inspect
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def format_hash(hash)
|
|
59
|
+
formatted = hash.map { |k, v| "#{format_output(k)}=>#{format_output(v)}" }.join(", ")
|
|
60
|
+
"{#{formatted}}".light_blue
|
|
61
|
+
rescue
|
|
62
|
+
hash.inspect
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|