emanlib 0.1.0 → 0.1.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.
- checksums.yaml +4 -4
- data/lib/emanlib.rb +14 -11
- data/lib/patch/enum.rb +120 -0
- data/lib/patch/foobar.rb +8 -6
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7c865695d10014ad5b2b967418ec8e4ea65165e9549590f7380c4f21e27b50b0
|
4
|
+
data.tar.gz: 00dda6a97a260530b29a932d883377b9f8877820d15b5605bce7582cd422ac72
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fc5e5219826053c84b0e007cf3e59dc5f72d6f483384ed5515f7938b5c3efb9fab39e77109adafe5b18a58fe17c65913d8951a4b4478b27445a93451a9f79851
|
7
|
+
data.tar.gz: bf1123ccc076eaa6c657c28fbc47aff2c4f0e23a749625b02ec33433e7605b5e9262fcd0ff3bdf43e67c56e026a5c75c01d881f938c7517923f22024efe4283e
|
data/lib/emanlib.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require_relative "patch/define"
|
2
|
+
require_relative "patch/enum"
|
2
3
|
require_relative "patch/foobar"
|
3
4
|
require_relative "patch/lambda"
|
4
5
|
|
@@ -6,10 +7,10 @@ module EmanLib
|
|
6
7
|
# The identity Lambda object (`_`).
|
7
8
|
# Store in a short variable, and use it as a building block for anonymous functions.
|
8
9
|
#
|
9
|
-
# _ = EmanLib.
|
10
|
+
# _ = EmanLib._
|
10
11
|
# [1, 2, 3].map(&_.succ) => [2, 3, 4]
|
11
12
|
# [[1, 2], [3, 4]].map(&(_ + _).lift) => [3, 7]
|
12
|
-
|
13
|
+
_ = Lambda.new
|
13
14
|
|
14
15
|
# Helper method to create definitions.
|
15
16
|
# A convenient shorthand for `Object.new.define(...)`.
|
@@ -21,7 +22,11 @@ module EmanLib
|
|
21
22
|
# @see [Object#define]
|
22
23
|
#
|
23
24
|
# @example
|
24
|
-
#
|
25
|
+
# person = let(name: "Rio", age: 37)
|
26
|
+
# puts person.name # => "Rio"
|
27
|
+
# puts person.age # => 37
|
28
|
+
#
|
29
|
+
# point = let **{x: 10, y: 20}
|
25
30
|
# puts point.x # => 10
|
26
31
|
#
|
27
32
|
# settings = let do
|
@@ -31,22 +36,20 @@ module EmanLib
|
|
31
36
|
# end
|
32
37
|
# puts settings.theme # => "dark"
|
33
38
|
#
|
34
|
-
# complex_data = let([[:id,
|
39
|
+
# complex_data = let([[:id, 42]], name: "Xed") do
|
35
40
|
# details = { color: "red", size: "large" }
|
36
|
-
# binding
|
41
|
+
# binding # Required
|
37
42
|
# end
|
38
43
|
#
|
39
|
-
# puts complex_data.id # =>
|
40
|
-
# puts complex_data.name # => "
|
44
|
+
# puts complex_data.id # => 42
|
45
|
+
# puts complex_data.name # => "Xed"
|
41
46
|
# puts complex_data.details.color # => "red"
|
42
47
|
def let(*args, &block)
|
43
48
|
Object.new.define(*args, &block)
|
44
49
|
end
|
45
50
|
|
46
|
-
module_function :let
|
47
|
-
|
48
51
|
# Support for using a `_` as the second operand with operators.
|
49
|
-
# WARN: This method
|
52
|
+
# WARN: This method WILL MODIFY the standard library classes.
|
50
53
|
# In particular, the operators: `- * / % ** & | ^ << >> <=> == === != > < >= <=`
|
51
54
|
# in the classes: `Integer, Float, Rational, Complex, Array, String, Hash, Range, Set`
|
52
55
|
def support_lambda
|
@@ -69,5 +72,5 @@ module EmanLib
|
|
69
72
|
end
|
70
73
|
end
|
71
74
|
|
72
|
-
module_function :support_lambda
|
75
|
+
module_function :let, :support_lambda
|
73
76
|
end
|
data/lib/patch/enum.rb
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
module EmanLib
|
2
|
+
# The Enum module provides a factory method `[]` to dynamically create
|
3
|
+
# simple, lightweight enum-like classes. These classes allow defining a set of
|
4
|
+
# named constants with associated numeric values.
|
5
|
+
#
|
6
|
+
# Enums are defined by passing symbols, strings, or hashes to the `[]` method.
|
7
|
+
#
|
8
|
+
# Usage examples:
|
9
|
+
# OS = Enum[:Arch, :BSD] # OS.Arch => 0, OS.BSD => 1
|
10
|
+
# Bool = Enum[nil: 1, :t 10] # Bool.nil => 1, Bool.t => 10
|
11
|
+
# Way = Enum["↑", { ↓: 50 }, :→ ] # Way.↑ => 0, Way.↓ => 50, Way.→ => 51
|
12
|
+
# Pet = Enum[:Dog, :Cat] { |v| 0.5 * v } # Pet.Dog => 0.0, Pet.Cat => 0.5
|
13
|
+
#
|
14
|
+
# The generated enum class provides:
|
15
|
+
# * Class methods to access each constant's value (e.g., `Lvl.MID`).
|
16
|
+
# * An `each` class method to iterate over value-name pairs.
|
17
|
+
# * A `to_h` class method to get a hash of name-value pairs.
|
18
|
+
# * A `consts` class method to get an array of constant names (as symbols).
|
19
|
+
# * A `values` class method to get an array of constant values.
|
20
|
+
module Enum
|
21
|
+
def self.[](*args, &block)
|
22
|
+
# At least one argument should be provided
|
23
|
+
raise ArgumentError, "Enums must have at least one constant" if args.empty?
|
24
|
+
|
25
|
+
# Initialize tracking variables
|
26
|
+
pairs = {}
|
27
|
+
current = 0
|
28
|
+
|
29
|
+
args.flatten!(1)
|
30
|
+
|
31
|
+
# Process all arguments to extract name-value pairs
|
32
|
+
args.each do |arg|
|
33
|
+
current = case arg
|
34
|
+
when Symbol, String
|
35
|
+
# Single enum value - assign current value and increment
|
36
|
+
pairs[arg.to_sym] = current
|
37
|
+
current + 1
|
38
|
+
when Hash
|
39
|
+
# Hash with explicit key-value mapping
|
40
|
+
arg.each do |key, value|
|
41
|
+
unless key.is_a?(Symbol) || key.is_a?(String)
|
42
|
+
raise ArgumentError, "Enum names must be Symbol|String: #{key.inspect}"
|
43
|
+
end
|
44
|
+
raise ArgumentError, "Enum values must be Numeric: #{value.inspect}" unless value.is_a?(Numeric)
|
45
|
+
pairs[key.to_sym] = value
|
46
|
+
current = value + 1
|
47
|
+
end
|
48
|
+
|
49
|
+
current
|
50
|
+
else
|
51
|
+
raise ArgumentError, "Invalid enum argument: #{arg.inspect}"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Apply block transformation if provided
|
56
|
+
if block_given?
|
57
|
+
values = Set.new
|
58
|
+
pairs.each do |name, value|
|
59
|
+
result = block.call(value, name)
|
60
|
+
|
61
|
+
# Make sure block result is Numeric
|
62
|
+
unless result.is_a?(Numeric)
|
63
|
+
raise ArgumentError, "Block must return a Numeric, got #{result.class}: #{result.inspect}"
|
64
|
+
end
|
65
|
+
|
66
|
+
# Check that result is unique
|
67
|
+
if values.include?(result)
|
68
|
+
raise ArgumentError, "Block must return unique values, duplicate: #{result}"
|
69
|
+
end
|
70
|
+
|
71
|
+
values.add(result)
|
72
|
+
pairs[name] = result
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# Create enum class and include this module
|
77
|
+
klass = Class.new
|
78
|
+
klass.include(Enum)
|
79
|
+
|
80
|
+
# Store enums data for instance methods
|
81
|
+
klass.instance_variable_set(:@pairs, pairs.freeze)
|
82
|
+
|
83
|
+
# Define getter methods for each constant
|
84
|
+
pairs.each do |name, value|
|
85
|
+
begin
|
86
|
+
klass.define_singleton_method(name) { value }
|
87
|
+
rescue => e
|
88
|
+
raise ArgumentError, "Invalid const name '#{name}': #{e.message}"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
klass.define_method(:initialize) do
|
93
|
+
raise RuntimeError, "Enums are not meant to be instantiated"
|
94
|
+
end
|
95
|
+
|
96
|
+
# Define utility methods directly on the class
|
97
|
+
klass.define_singleton_method(:to_h) do
|
98
|
+
@pairs.dup
|
99
|
+
end
|
100
|
+
|
101
|
+
klass.define_singleton_method(:consts) do
|
102
|
+
@pairs.keys
|
103
|
+
end
|
104
|
+
|
105
|
+
klass.define_singleton_method(:values) do
|
106
|
+
@pairs.values
|
107
|
+
end
|
108
|
+
|
109
|
+
klass.define_singleton_method(:each) do |&block|
|
110
|
+
return enum_for(:each) unless block
|
111
|
+
|
112
|
+
@pairs.each do |name, value|
|
113
|
+
block.call(value, name)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
klass
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
data/lib/patch/foobar.rb
CHANGED
@@ -121,22 +121,24 @@ class Object
|
|
121
121
|
end
|
122
122
|
|
123
123
|
# Asserts a condition about `self`.
|
124
|
-
# If a block is given, it asserts that the block
|
124
|
+
# If a block is given, it asserts that the block returns a truthy value.
|
125
|
+
# The block is passed `self` as an argument.
|
125
126
|
# If no block is given, it asserts that `n === self` is true.
|
126
127
|
# If the assertion fails, it performs a non-local exit by `raise`.
|
127
128
|
#
|
128
|
-
# @param `n` ([Object]) The object to compare with `self` if no block is given.
|
129
|
+
# @param `n` ([Object]) The object to compare with `self` if no block is given.
|
129
130
|
# @param `error` ([Class]) The class of error to raise if the assertion fails.
|
130
|
-
#
|
131
|
+
# @param `message` (String?) An optional message to include in the raised error.
|
131
132
|
# @yield [self] Optional block whose truthiness is asserted.
|
132
133
|
# @return [self] The original object if assertion passes.
|
133
134
|
# @throw `error` (or a related symbol) if the assertion fails.
|
134
135
|
#
|
135
136
|
# @example
|
136
137
|
# 5.assert(Integer) # Passes
|
137
|
-
# "string".assert(error: ArgumentError) { |s| s.
|
138
|
-
|
139
|
-
|
138
|
+
# "string".assert(error: ArgumentError) { |s| s.size > 5 } # Passes
|
139
|
+
# "".assert(message: "String too short") {|s| s.size > 5 } # Raises error with message
|
140
|
+
def assert(n = self, error: StandardError, message: nil)
|
141
|
+
tap { (block_given? ? yield(self) : (n === self)) || (message ? raise(error, message) : raise(error)) }
|
140
142
|
end
|
141
143
|
|
142
144
|
# Prints the `inspect` representation of `self` to standard output.
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: emanlib
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- emanrdesu
|
@@ -18,6 +18,7 @@ extra_rdoc_files: []
|
|
18
18
|
files:
|
19
19
|
- lib/emanlib.rb
|
20
20
|
- lib/patch/define.rb
|
21
|
+
- lib/patch/enum.rb
|
21
22
|
- lib/patch/foobar.rb
|
22
23
|
- lib/patch/lambda.rb
|
23
24
|
homepage: https://github.com/emanrdesu/lib
|