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.
@@ -0,0 +1,842 @@
1
+ module PrettyIRB
2
+ class AIHelper
3
+ class << self
4
+ # Explain a Ruby method
5
+ def explain_method(method_name)
6
+ case method_name.downcase
7
+ when "map"
8
+ explain_map
9
+ when "select", "filter"
10
+ explain_select
11
+ when "each"
12
+ explain_each
13
+ when "reduce", "inject"
14
+ explain_reduce
15
+ when "find", "detect"
16
+ explain_find
17
+ when "merge"
18
+ explain_merge
19
+ when "keys", "values"
20
+ explain_keys_values
21
+ when "gsub", "sub"
22
+ explain_gsub
23
+ when "split", "join"
24
+ explain_split_join
25
+ else
26
+ suggest_available_methods
27
+ end
28
+ end
29
+
30
+ # Get code example for a concept
31
+ def get_example(concept)
32
+ case concept.downcase
33
+ when "loop", "iteration"
34
+ example_loops
35
+ when "condition", "if"
36
+ example_conditions
37
+ when "class"
38
+ example_class
39
+ when "method"
40
+ example_method
41
+ when "array"
42
+ example_array
43
+ when "hash"
44
+ example_hash
45
+ when "string"
46
+ example_string
47
+ when "error", "exception"
48
+ example_error_handling
49
+ when "block", "proc"
50
+ example_blocks
51
+ else
52
+ suggest_available_examples
53
+ end
54
+ end
55
+
56
+ # Debug code snippet
57
+ def debug_code(code_snippet)
58
+ analysis = {
59
+ potential_issues: [],
60
+ suggestions: [],
61
+ complexity: analyze_complexity(code_snippet)
62
+ }
63
+
64
+ # Check for common issues
65
+ analysis[:potential_issues] << "Missing error handling" if code_snippet.include?("begin") == false && has_risky_operations(code_snippet)
66
+ analysis[:potential_issues] << "Potential nil reference" if code_snippet.include?(".") && !code_snippet.include?("&.")
67
+ analysis[:suggestions] << "Consider using safe navigation operator (&.) for chained calls" if code_snippet.include?(".") && !code_snippet.include?("&.")
68
+ analysis[:suggestions] << "Add error handling with begin/rescue/end" if analysis[:potential_issues].include?("Missing error handling")
69
+
70
+ format_analysis(analysis)
71
+ end
72
+
73
+ # Suggest best practices
74
+ def best_practices(topic)
75
+ case topic.downcase
76
+ when "naming"
77
+ naming_conventions
78
+ when "performance"
79
+ performance_tips
80
+ when "readability"
81
+ readability_tips
82
+ when "testing"
83
+ testing_tips
84
+ when "security"
85
+ security_tips
86
+ else
87
+ general_best_practices
88
+ end
89
+ end
90
+
91
+ # Quick reference
92
+ def quick_reference(keyword)
93
+ case keyword.downcase
94
+ when "operators"
95
+ operators_reference
96
+ when "symbols"
97
+ symbols_reference
98
+ when "variables"
99
+ variables_reference
100
+ when "methods"
101
+ methods_reference
102
+ else
103
+ "Available references: operators, symbols, variables, methods"
104
+ end
105
+ end
106
+
107
+ private
108
+
109
+ def explain_map
110
+ <<~EXPLANATION
111
+ 🎯 map method: Transforms each element of an array
112
+
113
+ Syntax: array.map { |item| transformation }
114
+
115
+ Example:
116
+ [1, 2, 3].map { |x| x * 2 }
117
+ => [2, 4, 6]
118
+
119
+ Key points:
120
+ • Returns a NEW array (doesn't modify original)
121
+ • Applies block to each element
122
+ • Commonly used for data transformation
123
+ EXPLANATION
124
+ end
125
+
126
+ def explain_select
127
+ <<~EXPLANATION
128
+ 🎯 select method: Filters array based on condition
129
+
130
+ Syntax: array.select { |item| condition }
131
+
132
+ Example:
133
+ [1, 2, 3, 4, 5].select { |x| x > 2 }
134
+ => [3, 4, 5]
135
+
136
+ Key points:
137
+ • Returns NEW array with matching elements
138
+ • Returns empty array if nothing matches
139
+ • Use for filtering/querying data
140
+ EXPLANATION
141
+ end
142
+
143
+ def explain_each
144
+ <<~EXPLANATION
145
+ 🎯 each method: Iterates over elements (no transformation)
146
+
147
+ Syntax: array.each { |item| action }
148
+
149
+ Example:
150
+ [1, 2, 3].each { |x| puts x }
151
+ => [1, 2, 3]
152
+
153
+ Key points:
154
+ • Returns ORIGINAL array (not transformed)
155
+ • Use for side effects (printing, saving, etc.)
156
+ • Better than map when you don't need new array
157
+ EXPLANATION
158
+ end
159
+
160
+ def explain_reduce
161
+ <<~EXPLANATION
162
+ 🎯 reduce method: Combines array elements into single value
163
+
164
+ Syntax: array.reduce(:+) or array.reduce { |acc, item| acc + item }
165
+
166
+ Example:
167
+ [1, 2, 3, 4].reduce(:+)
168
+ => 10
169
+
170
+ Key points:
171
+ • Accumulates value across iterations
172
+ • Great for sum, product, or combining values
173
+ • Can use symbol as shorthand (:+, :*, etc.)
174
+ EXPLANATION
175
+ end
176
+
177
+ def explain_find
178
+ <<~EXPLANATION
179
+ 🎯 find method: Returns first element matching condition
180
+
181
+ Syntax: array.find { |item| condition }
182
+
183
+ Example:
184
+ [1, 2, 3, 4, 5].find { |x| x > 3 }
185
+ => 4
186
+
187
+ Key points:
188
+ • Returns first match (not array!)
189
+ • Returns nil if no match found
190
+ • Stops searching after finding first match
191
+ EXPLANATION
192
+ end
193
+
194
+ def explain_merge
195
+ <<~EXPLANATION
196
+ 🎯 merge method: Combines hashes
197
+
198
+ Syntax: hash1.merge(hash2)
199
+
200
+ Example:
201
+ {a: 1, b: 2}.merge({b: 3, c: 4})
202
+ => {a: 1, b: 3, c: 4}
203
+
204
+ Key points:
205
+ • Returns NEW hash (doesn't modify original)
206
+ • Later values override earlier ones
207
+ • Use merge! to modify original hash
208
+ EXPLANATION
209
+ end
210
+
211
+ def explain_keys_values
212
+ <<~EXPLANATION
213
+ 🎯 keys & values methods: Extract hash components
214
+
215
+ Syntax: hash.keys or hash.values
216
+
217
+ Example:
218
+ {name: "Ruby", age: 30}.keys
219
+ => [:name, :age]
220
+
221
+ {name: "Ruby", age: 30}.values
222
+ => ["Ruby", 30]
223
+
224
+ Key points:
225
+ • keys returns array of all keys
226
+ • values returns array of all values
227
+ • Order may not be guaranteed in older Ruby versions
228
+ EXPLANATION
229
+ end
230
+
231
+ def explain_gsub
232
+ <<~EXPLANATION
233
+ 🎯 gsub method: Global string substitution (replace all)
234
+
235
+ Syntax: string.gsub(pattern, replacement)
236
+
237
+ Example:
238
+ "hello world".gsub("l", "L")
239
+ => "heLLo worLd"
240
+
241
+ Key points:
242
+ • Replaces ALL occurrences (use sub for first only)
243
+ • Pattern can be string or regex
244
+ • Returns new string (doesn't modify original)
245
+ EXPLANATION
246
+ end
247
+
248
+ def explain_split_join
249
+ <<~EXPLANATION
250
+ 🎯 split & join methods: String ↔ Array conversion
251
+
252
+ Syntax: string.split(delimiter) / array.join(delimiter)
253
+
254
+ Example:
255
+ "a,b,c".split(",")
256
+ => ["a", "b", "c"]
257
+
258
+ ["x", "y", "z"].join("-")
259
+ => "x-y-z"
260
+
261
+ Key points:
262
+ • split: breaks string into array
263
+ • join: combines array into string
264
+ • Perfect inverse operations
265
+ EXPLANATION
266
+ end
267
+
268
+ def suggest_available_methods
269
+ <<~AVAILABLE
270
+ Available method explanations:
271
+ 🔸 map - Transform array elements
272
+ 🔸 select - Filter array elements
273
+ 🔸 each - Iterate without transformation
274
+ 🔸 reduce - Combine into single value
275
+ 🔸 find - Find first matching element
276
+ 🔸 merge - Combine hashes
277
+ 🔸 keys - Get hash keys
278
+ 🔸 values - Get hash values
279
+ 🔸 gsub - Replace all in string
280
+ 🔸 split - String to array
281
+ 🔸 join - Array to string
282
+
283
+ Usage: ?explain_method(name)
284
+ AVAILABLE
285
+ end
286
+
287
+ def example_loops
288
+ <<~EXAMPLES
289
+ 📚 Loop Examples:
290
+
291
+ Using each:
292
+ [1, 2, 3].each { |x| puts x }
293
+
294
+ Using times:
295
+ 5.times { |i| puts "Number #{i}" }
296
+
297
+ Using while:
298
+ i = 0
299
+ while i < 5
300
+ puts i
301
+ i += 1
302
+ end
303
+
304
+ Using for:
305
+ for x in [1, 2, 3]
306
+ puts x
307
+ end
308
+ EXAMPLES
309
+ end
310
+
311
+ def example_conditions
312
+ <<~EXAMPLES
313
+ 📚 Conditional Examples:
314
+
315
+ If/elsif/else:
316
+ if age < 13
317
+ puts "Child"
318
+ elsif age < 18
319
+ puts "Teen"
320
+ else
321
+ puts "Adult"
322
+ end
323
+
324
+ Ternary operator:
325
+ age >= 18 ? "Adult" : "Minor"
326
+
327
+ Unless:
328
+ puts "Not admin" unless user.admin?
329
+
330
+ Case/when:
331
+ case day
332
+ when 1
333
+ puts "Monday"
334
+ when 2
335
+ puts "Tuesday"
336
+ end
337
+ EXAMPLES
338
+ end
339
+
340
+ def example_class
341
+ <<~EXAMPLES
342
+ 📚 Class Definition Example:
343
+
344
+ class Person
345
+ attr_accessor :name, :age
346
+
347
+ def initialize(name, age)
348
+ @name = name
349
+ @age = age
350
+ end
351
+
352
+ def info
353
+ "#{@name} is #{@age} years old"
354
+ end
355
+ end
356
+
357
+ person = Person.new("Alice", 30)
358
+ puts person.info
359
+ EXAMPLES
360
+ end
361
+
362
+ def example_method
363
+ <<~EXAMPLES
364
+ 📚 Method Definition Examples:
365
+
366
+ Simple method:
367
+ def greet(name)
368
+ "Hello, #{name}!"
369
+ end
370
+
371
+ With default parameter:
372
+ def greet(name = "Friend")
373
+ "Hello, #{name}!"
374
+ end
375
+
376
+ With multiple parameters:
377
+ def add(a, b)
378
+ a + b
379
+ end
380
+
381
+ With splat operator:
382
+ def sum(*numbers)
383
+ numbers.reduce(:+)
384
+ end
385
+ EXAMPLES
386
+ end
387
+
388
+ def example_array
389
+ <<~EXAMPLES
390
+ 📚 Array Examples:
391
+
392
+ Creating arrays:
393
+ arr = [1, 2, 3]
394
+ arr = Array.new(5, 0) # [0, 0, 0, 0, 0]
395
+
396
+ Accessing elements:
397
+ arr[0] # First element
398
+ arr[-1] # Last element
399
+ arr[0..2] # Range
400
+
401
+ Adding elements:
402
+ arr << 4 # Push
403
+ arr.push(5, 6) # Add multiple
404
+
405
+ Removing elements:
406
+ arr.pop # Remove last
407
+ arr.shift # Remove first
408
+ EXAMPLES
409
+ end
410
+
411
+ def example_hash
412
+ <<~EXAMPLES
413
+ 📚 Hash Examples:
414
+
415
+ Creating hashes:
416
+ hash = {name: "Ruby", age: 30}
417
+ hash = {"a" => 1, "b" => 2}
418
+
419
+ Accessing values:
420
+ hash[:name] # Using symbol key
421
+ hash["a"] # Using string key
422
+
423
+ Adding/updating:
424
+ hash[:city] = "New York"
425
+
426
+ Iterating:
427
+ hash.each { |k, v| puts "#{k}: #{v}" }
428
+
429
+ Merging:
430
+ hash1.merge(hash2)
431
+ EXAMPLES
432
+ end
433
+
434
+ def example_string
435
+ <<~EXAMPLES
436
+ 📚 String Examples:
437
+
438
+ Creating strings:
439
+ str = "Hello"
440
+ str = 'Single quotes'
441
+ str = %q{Alternative syntax}
442
+
443
+ String interpolation:
444
+ name = "Ruby"
445
+ "Hello, #{name}!"
446
+
447
+ String methods:
448
+ "hello".upcase # "HELLO"
449
+ "HELLO".downcase # "hello"
450
+ "ruby".capitalize # "Ruby"
451
+ "hello world".length # 11
452
+
453
+ String splitting/joining:
454
+ "a,b,c".split(",") # ["a", "b", "c"]
455
+ ["a", "b"].join(",") # "a,b"
456
+ EXAMPLES
457
+ end
458
+
459
+ def example_error_handling
460
+ <<~EXAMPLES
461
+ 📚 Error Handling Examples:
462
+
463
+ Basic rescue:
464
+ begin
465
+ result = 10 / 0
466
+ rescue ZeroDivisionError
467
+ puts "Cannot divide by zero"
468
+ end
469
+
470
+ Multiple rescue clauses:
471
+ begin
472
+ risky_operation
473
+ rescue TypeError
474
+ puts "Type error"
475
+ rescue ArgumentError
476
+ puts "Wrong arguments"
477
+ end
478
+
479
+ Ensure (always runs):
480
+ begin
481
+ file = File.open("data.txt")
482
+ process(file)
483
+ ensure
484
+ file.close
485
+ end
486
+ EXAMPLES
487
+ end
488
+
489
+ def example_blocks
490
+ <<~EXAMPLES
491
+ 📚 Block, Proc & Lambda Examples:
492
+
493
+ Block:
494
+ [1, 2, 3].each { |x| puts x }
495
+
496
+ Proc:
497
+ my_proc = Proc.new { |x| x * 2 }
498
+ my_proc.call(5) # => 10
499
+
500
+ Lambda:
501
+ my_lambda = lambda { |x| x * 2 }
502
+ my_lambda.call(5) # => 10
503
+
504
+ Key differences:
505
+ • Procs are more flexible
506
+ • Lambdas check argument count
507
+ • Both can be passed to methods
508
+ EXAMPLES
509
+ end
510
+
511
+ def suggest_available_examples
512
+ <<~AVAILABLE
513
+ Available code examples:
514
+ 📖 loop - Iteration patterns
515
+ 📖 condition - If/elsif/case statements
516
+ 📖 class - Class definition
517
+ 📖 method - Method definition
518
+ 📖 array - Array operations
519
+ 📖 hash - Hash operations
520
+ 📖 string - String operations
521
+ 📖 error - Error handling
522
+ 📖 block - Blocks, procs, lambdas
523
+
524
+ Usage: ?example(topic)
525
+ AVAILABLE
526
+ end
527
+
528
+ def analyze_complexity(code)
529
+ case code.length
530
+ when 0..50
531
+ "Simple"
532
+ when 51..200
533
+ "Moderate"
534
+ when 201..500
535
+ "Complex"
536
+ else
537
+ "Very Complex"
538
+ end
539
+ end
540
+
541
+ def has_risky_operations(code)
542
+ risky_patterns = [
543
+ /\[\d+\]/, # Array indexing without check
544
+ /\.\w+\(/, # Method calls
545
+ /File\./, # File operations
546
+ /require/ # Require statements
547
+ ]
548
+ risky_patterns.any? { |pattern| code.match?(pattern) }
549
+ end
550
+
551
+ def format_analysis(analysis)
552
+ output = "📊 Code Analysis:\n\n"
553
+ output += "Complexity: #{analysis[:complexity]}\n\n"
554
+
555
+ if analysis[:potential_issues].any?
556
+ output += "⚠️ Potential Issues:\n"
557
+ analysis[:potential_issues].each { |issue| output += " • #{issue}\n" }
558
+ output += "\n"
559
+ end
560
+
561
+ if analysis[:suggestions].any?
562
+ output += "💡 Suggestions:\n"
563
+ analysis[:suggestions].each { |suggestion| output += " • #{suggestion}\n" }
564
+ end
565
+
566
+ output
567
+ end
568
+
569
+ def naming_conventions
570
+ <<~TIPS
571
+ ✨ Naming Conventions Best Practices:
572
+
573
+ Variables:
574
+ • Use snake_case: user_name, total_price
575
+ • Be descriptive: total_price instead of tp
576
+ • Avoid single letters (except i, j for loops)
577
+
578
+ Methods:
579
+ • Use snake_case: calculate_total(), user_exists?()
580
+ • Predicates end with ?: valid?(), empty?()
581
+ • Dangerous methods end with !: delete!(), save!()
582
+
583
+ Constants:
584
+ • Use CONSTANT_NAME (all caps)
585
+ • MAX_USERS, DEFAULT_TIMEOUT
586
+
587
+ Classes:
588
+ • Use PascalCase: User, ShoppingCart, UserProfile
589
+ • Nouns, not verbs
590
+
591
+ Avoid:
592
+ ✗ Hungarian notation: strName, intAge
593
+ ✗ Non-English: cena, utilisateur
594
+ ✗ Misleading names: data, result, temp
595
+ TIPS
596
+ end
597
+
598
+ def performance_tips
599
+ <<~TIPS
600
+ ⚡ Performance Tips:
601
+
602
+ Array Operations:
603
+ • Use each instead of map if you don't need results
604
+ • Use find instead of select if you need first match
605
+ • Avoid nested loops when possible
606
+
607
+ String Operations:
608
+ • Use String#freeze for constants
609
+ • Use single quotes for static strings
610
+ • Avoid string concatenation in loops (use array join)
611
+
612
+ Hash Operations:
613
+ • Use symbols for keys, not strings
614
+ • Consider using frozen strings for string keys
615
+
616
+ General:
617
+ • Avoid unnecessary object creation
618
+ • Cache expensive computations
619
+ • Use map/select/reduce instead of manual loops
620
+ • Consider lazy evaluation for large datasets
621
+ TIPS
622
+ end
623
+
624
+ def readability_tips
625
+ <<~TIPS
626
+ 📖 Readability Tips:
627
+
628
+ Code Style:
629
+ • Keep methods short (under 15 lines)
630
+ • One responsibility per method
631
+ • Clear variable names
632
+
633
+ Comments:
634
+ • Write code that's self-documenting
635
+ • Comments explain WHY, not WHAT
636
+ • Keep comments in sync with code
637
+
638
+ Structure:
639
+ • Group related methods
640
+ • Alphabetize methods
641
+ • Constants at top of file
642
+
643
+ Control Flow:
644
+ • Use guard clauses at start of methods
645
+ • Prefer early return over nested if
646
+ • Keep nesting level low (max 3)
647
+ TIPS
648
+ end
649
+
650
+ def testing_tips
651
+ <<~TIPS
652
+ 🧪 Testing Best Practices:
653
+
654
+ Test Structure:
655
+ • One assertion per test
656
+ • Test happy path and edge cases
657
+ • Use descriptive test names
658
+
659
+ What to Test:
660
+ • Public methods
661
+ • Edge cases: nil, empty, zero
662
+ • Error conditions
663
+ • Boundary conditions
664
+
665
+ What NOT to Test:
666
+ • Standard library code
667
+ • Third-party gems
668
+ • Dependencies (use mocks)
669
+
670
+ Example Structure:
671
+ describe "User" do
672
+ describe "#valid?" do
673
+ it "returns true for valid user" do
674
+ user = User.new(name: "Alice")
675
+ expect(user.valid?).to be true
676
+ end
677
+ end
678
+ end
679
+ TIPS
680
+ end
681
+
682
+ def security_tips
683
+ <<~TIPS
684
+ 🔒 Security Tips:
685
+
686
+ Input Validation:
687
+ • Always validate user input
688
+ • Use whitelisting over blacklisting
689
+ • Sanitize strings before use
690
+
691
+ Data Protection:
692
+ • Never commit secrets to repo
693
+ • Use environment variables for config
694
+ • Hash passwords, don't encrypt
695
+
696
+ SQL/Database:
697
+ • Use parameterized queries
698
+ • Avoid string interpolation in queries
699
+ • Use ORM (ActiveRecord) when possible
700
+
701
+ Common Vulnerabilities:
702
+ • SQL Injection: Use parameterized queries
703
+ • XSS: Escape HTML output
704
+ • CSRF: Use CSRF tokens
705
+ TIPS
706
+ end
707
+
708
+ def general_best_practices
709
+ <<~PRACTICES
710
+ ✅ General Best Practices:
711
+
712
+ Code Quality:
713
+ • DRY: Don't Repeat Yourself
714
+ • KISS: Keep It Simple, Stupid
715
+ • YAGNI: You Aren't Gonna Need It
716
+
717
+ Design Patterns:
718
+ • Use composition over inheritance
719
+ • Prefer small classes and modules
720
+ • Follow SOLID principles
721
+
722
+ Maintenance:
723
+ • Write tests first (TDD)
724
+ • Keep dependencies minimal
725
+ • Document complex logic
726
+ • Review code with teammates
727
+ PRACTICES
728
+ end
729
+
730
+ def operators_reference
731
+ <<~REFERENCE
732
+ 📋 Ruby Operators Reference:
733
+
734
+ Arithmetic:
735
+ + (addition)
736
+ - (subtraction)
737
+ * (multiplication)
738
+ / (division)
739
+ % (modulo)
740
+ ** (exponentiation)
741
+
742
+ Comparison:
743
+ == (equal)
744
+ != (not equal)
745
+ < (less than)
746
+ > (greater than)
747
+ <= (less than or equal)
748
+ >= (greater than or equal)
749
+ <=> (spaceship - comparison)
750
+
751
+ Logical:
752
+ && (and)
753
+ || (or)
754
+ ! (not)
755
+ and, or, not (lower precedence)
756
+
757
+ Bitwise:
758
+ & (and)
759
+ | (or)
760
+ ^ (xor)
761
+ ~ (not)
762
+ << (left shift)
763
+ >> (right shift)
764
+ REFERENCE
765
+ end
766
+
767
+ def symbols_reference
768
+ <<~REFERENCE
769
+ 📋 Symbols Reference:
770
+
771
+ Creating symbols:
772
+ :symbol
773
+ :"symbol with spaces"
774
+ Symbol.new(:symbol)
775
+
776
+ Characteristics:
777
+ • Immutable
778
+ • Lightweight (interned strings)
779
+ • Same symbol has same object_id
780
+ • Great for hash keys
781
+
782
+ Usage:
783
+ hash = {name: "Ruby", age: 30}
784
+ hash[:name] # => "Ruby"
785
+
786
+ Benefits:
787
+ • Faster than strings as keys
788
+ • More memory efficient
789
+ • Convention for hash keys
790
+ REFERENCE
791
+ end
792
+
793
+ def variables_reference
794
+ <<~REFERENCE
795
+ 📋 Variable Types Reference:
796
+
797
+ Local Variables:
798
+ name = "Alice"
799
+ # Scoped to current context
800
+
801
+ Instance Variables:
802
+ @name = "Alice"
803
+ # Scoped to object instance
804
+
805
+ Class Variables:
806
+ @@count = 0
807
+ # Shared by all instances of class
808
+
809
+ Global Variables:
810
+ $global = "danger"
811
+ # Avoid! Use sparingly
812
+
813
+ Constants:
814
+ MAX_SIZE = 100
815
+ # Should not be changed
816
+ REFERENCE
817
+ end
818
+
819
+ def methods_reference
820
+ <<~REFERENCE
821
+ 📋 Common Methods Reference:
822
+
823
+ String Methods:
824
+ upcase, downcase, capitalize, length, reverse,
825
+ split, gsub, include?, start_with?, end_with?
826
+
827
+ Array Methods:
828
+ push, pop, shift, unshift, map, select, each,
829
+ find, reduce, sort, reverse, join, length
830
+
831
+ Hash Methods:
832
+ keys, values, each, merge, delete, has_key?,
833
+ fetch, select, map, to_a
834
+
835
+ Numeric Methods:
836
+ abs, round, floor, ceil, even?, odd?, times,
837
+ upto, downto
838
+ REFERENCE
839
+ end
840
+ end
841
+ end
842
+ end