rbs 2.2.2 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +4 -0
  3. data/.github/workflows/comments.yml +2 -2
  4. data/.github/workflows/ruby.yml +1 -1
  5. data/.gitignore +0 -1
  6. data/CHANGELOG.md +43 -0
  7. data/Gemfile +2 -1
  8. data/Gemfile.lock +117 -0
  9. data/Rakefile +1 -1
  10. data/core/dir.rbs +1 -1
  11. data/core/enumerator.rbs +1 -1
  12. data/core/false_class.rbs +1 -1
  13. data/core/integer.rbs +4 -4
  14. data/core/io/wait.rbs +1 -1
  15. data/core/module.rbs +21 -2
  16. data/core/nil_class.rbs +7 -5
  17. data/core/object.rbs +9 -0
  18. data/core/trace_point.rbs +42 -3
  19. data/core/true_class.rbs +1 -1
  20. data/ext/rbs_extension/constants.c +1 -1
  21. data/ext/rbs_extension/extconf.rb +1 -1
  22. data/ext/rbs_extension/location.c +1 -1
  23. data/ext/rbs_extension/parser.c +4 -3
  24. data/ext/rbs_extension/parserstate.c +2 -2
  25. data/ext/rbs_extension/unescape.c +1 -1
  26. data/lib/rbs/ast/members.rb +2 -1
  27. data/lib/rbs/collection/installer.rb +4 -1
  28. data/lib/rbs/definition_builder/ancestor_builder.rb +4 -2
  29. data/lib/rbs/definition_builder/method_builder.rb +1 -1
  30. data/lib/rbs/definition_builder.rb +2 -2
  31. data/lib/rbs/environment.rb +24 -12
  32. data/lib/rbs/locator.rb +24 -15
  33. data/lib/rbs/prototype/rb.rb +17 -6
  34. data/lib/rbs/resolver/constant_resolver.rb +192 -0
  35. data/lib/rbs/resolver/type_name_resolver.rb +55 -0
  36. data/lib/rbs/type_name.rb +15 -0
  37. data/lib/rbs/version.rb +1 -1
  38. data/lib/rbs.rb +2 -0
  39. data/schema/members.json +4 -1
  40. data/sig/environment.rbs +28 -21
  41. data/sig/environment_loader.rbs +23 -23
  42. data/sig/locator.rbs +2 -0
  43. data/sig/manifest.yaml +8 -0
  44. data/sig/resolver/constant_resolver.rbs +93 -0
  45. data/sig/resolver/context.rbs +34 -0
  46. data/sig/resolver/type_name_resolver.rbs +31 -0
  47. data/sig/typename.rbs +9 -3
  48. data/stdlib/bigdecimal/0/big_decimal.rbs +135 -0
  49. data/stdlib/erb/0/erb.rbs +237 -0
  50. data/stdlib/optparse/0/optparse.rbs +20 -18
  51. data/stdlib/prime/0/prime.rbs +115 -4
  52. data/stdlib/rubygems/0/version.rbs +159 -1
  53. data/steep/Gemfile.lock +13 -15
  54. metadata +10 -3
@@ -1,26 +1,26 @@
1
1
  module RBS
2
2
  # EnvironmentLoader is an object to load RBS files from filesystem.
3
- #
3
+ #
4
4
  # Set up your configuration through repository and `#add` method.
5
- #
5
+ #
6
6
  # # Set up the repository to load library RBSs from.
7
7
  # repo = RBS::Repository.default
8
8
  # repo.add(Pathname("vendor/rbs/gem-rbs"))
9
9
  # repo.add(Pathname("vendor/rbs/internal-rbs"))
10
- #
10
+ #
11
11
  # loader = RBS::EnvironmentLoader.new(repository: repo)
12
- #
12
+ #
13
13
  # # Add libraries to load RBS files.
14
14
  # loader.add(library: "minitest")
15
15
  # loader.add(library: "rbs", version: "1.0.0")
16
- #
16
+ #
17
17
  # # Add dirs to load RBS files from.
18
18
  # loader.add(path: Pathname("sig"))
19
- #
19
+ #
20
20
  # # Load RBSs into an environment.
21
21
  # environment = RBS::Environment.new()
22
22
  # loader.load(env: environment)
23
- #
23
+ #
24
24
  class EnvironmentLoader
25
25
  class UnknownLibraryError < StandardError
26
26
  attr_reader library: Library
@@ -44,37 +44,37 @@ module RBS
44
44
  attr_reader dirs: Array[Pathname]
45
45
 
46
46
  # The source where the RBS comes from.
47
- #
47
+ #
48
48
  # `:core` means it is part of core library.
49
49
  # `Library` means it is from library.
50
50
  # `Pathname` means it is loaded from a directory.
51
- #
51
+ #
52
52
  type source = :core
53
53
  | Library
54
54
  | Pathname
55
55
 
56
56
  # Accepts two optional keyword arguments.
57
- #
57
+ #
58
58
  # `core_root` is the path to the directory with RBSs for core classes.
59
59
  # The default value is the core library included in RBS gem. (EnvironmentLoader::DEFAULT_CORE_ROOT)
60
60
  # Passing `nil` means it skips loading core class definitions.
61
- #
61
+ #
62
62
  # `repository` is the repository for library classes.
63
63
  # The default value is repository only with stdlib classes. (Repository.new)
64
- #
64
+ #
65
65
  def initialize: (?core_root: Pathname?, ?repository: Repository) -> void
66
-
66
+
67
67
  # Add a path or library to load RBSs from.
68
- #
68
+ #
69
69
  # `path` can be a file or a directory.
70
70
  # All `.rbs` files from the given directory will be loaded.
71
71
  # Specifying a file will load the file regardless the extension of the file is.
72
- #
72
+ #
73
73
  # `library` can be a name of a gem.
74
74
  # Specifying `nil` to `version` will load any version available.
75
75
  # It first tries to load RBS files from gem with specified version.
76
76
  # If RBS files cannot be found in the gem, it tries to load RBSs from repository.
77
- #
77
+ #
78
78
  def add: (path: Pathname) -> void
79
79
  | (library: String, version: String?) -> void
80
80
 
@@ -82,26 +82,26 @@ module RBS
82
82
  def add_collection: (Collection::Config collection_config) -> void
83
83
 
84
84
  # This is helper function to test if RBS for a library is available or not.
85
- #
85
+ #
86
86
  def has_library?: (library: String, version: String?) -> bool
87
87
 
88
88
  # Add all declarations to environment.
89
- #
89
+ #
90
90
  # Raises `UnknownLibraryError` if RBS cannot be loaded from a library.
91
- #
91
+ #
92
92
  # Returns an array of tuples of the declaration, path to the file, and the source.
93
- #
93
+ #
94
94
  def load: (env: Environment) -> Array[[AST::Declarations::t, Pathname, source]]
95
95
 
96
96
  # Returns a pair of spec and path for a gem with RBS.
97
97
  # Returns nil if the gem is not installed, or the gem doesn't provide RBS.
98
- #
98
+ #
99
99
  def self.gem_sig_path: (String name, String? version) -> [Gem::Specification, Pathname]?
100
100
 
101
101
  def each_decl: () { (AST::Declarations::t, Buffer, source, Pathname) -> void } -> void
102
-
102
+
103
103
  def each_dir: { (source, Pathname) -> void } -> void
104
-
104
+
105
105
  def each_file: (Pathname path, immediate: boolish, skip_hidden: boolish) { (Pathname) -> void } -> void
106
106
  end
107
107
  end
data/sig/locator.rbs CHANGED
@@ -37,6 +37,8 @@ module RBS
37
37
 
38
38
  def find_in_type: (Integer pos, type: Types::t, array: Array[component]) -> bool
39
39
 
40
+ def find_in_type_param: (Integer pos, type_param: AST::TypeParam, array: Array[component]) -> bool
41
+
40
42
  def find_in_loc: (Integer pos, location: Location[untyped, untyped]?, array: Array[component]) -> bool
41
43
 
42
44
  def test_loc: (Integer pos, location: Location[untyped, untyped]?) -> bool
data/sig/manifest.yaml ADDED
@@ -0,0 +1,8 @@
1
+ dependencies:
2
+ - name: logger
3
+ - name: set
4
+ - name: pathname
5
+ - name: json
6
+ - name: optparse
7
+ - name: rubygems
8
+ - name: tsort
@@ -0,0 +1,93 @@
1
+ module RBS
2
+ module Resolver
3
+ class ConstantResolver
4
+ # Table stores the set of immediate child constants of a module.
5
+ #
6
+ # ```rb
7
+ # table = RBS::ConstantResolver::Table.new(env)
8
+ #
9
+ # table.children(TypeName("::Object")) # -> { ... } Returns a hash of name and constants.
10
+ # table.children(TypeName("::File::PATH_SEPARATOR")) # -> nil Returns nil because the constant is not a module.
11
+ #
12
+ # table.toplevel # -> { ... } Returns a hash of top level constants.
13
+ # ```
14
+ #
15
+ # The `#toplevel` is incompatible with Ruby.
16
+ # All constants in Ruby are defined under `Object`, and they are accessed with `::` (Colon3) operator.
17
+ # RBS is different.
18
+ # `::` constants are _toplevel_ constants, and they are not defined under `::Object`.
19
+ #
20
+ # The behavior is simulated in `ConstantResolver`.
21
+ #
22
+ class Table
23
+ attr_reader children_table: Hash[TypeName, Hash[Symbol, Constant]?]
24
+ attr_reader constants_table: Hash[TypeName, Constant]
25
+ attr_reader toplevel: Hash[Symbol, Constant]
26
+
27
+ def initialize: (Environment) -> void
28
+
29
+ def constant: (TypeName constant_name) -> Constant?
30
+
31
+ # Returns a set of constants defined under `module_name`.
32
+ # Returns `nil` if there is no module with given `module_name`.
33
+ #
34
+ def children: (TypeName module_name) -> Hash[Symbol, Constant]?
35
+
36
+ private
37
+
38
+ def constant_of_module: (TypeName name, Environment::ClassEntry | Environment::ModuleEntry) -> Constant
39
+
40
+ def constant_of_constant: (TypeName name, Environment::SingleEntry[TypeName, AST::Declarations::Constant]) -> Constant
41
+ end
42
+
43
+ attr_reader builder: DefinitionBuilder
44
+ attr_reader table: Table
45
+ attr_reader context_constants_cache: Hash[context, Hash[Symbol, Constant]?]
46
+ attr_reader child_constants_cache: Hash[TypeName, Hash[Symbol, Constant]]
47
+
48
+ def initialize: (builder: DefinitionBuilder) -> void
49
+
50
+ # Resolves to `Constant` with given constant name `name` and `context`.
51
+ # Returns `nil` if the constant cannot be resolved from the context.
52
+ #
53
+ def resolve: (Symbol name, context: context) -> Constant?
54
+
55
+ # Returns the available all constants from `context`.
56
+ #
57
+ # Returns `nil` when the `context` is invalid.
58
+ def constants: (context) -> Hash[Symbol, Constant]?
59
+
60
+ # Resolves the module_name and constant name to `Constant`
61
+ #
62
+ # ```ruby
63
+ # A::B
64
+ # ^ <- module_name
65
+ # ^ <- constant_name
66
+ # ```
67
+ #
68
+ # Find the
69
+ def resolve_child: (TypeName module_name, Symbol constant_name) -> Constant?
70
+
71
+ # Returns the table of all constants accessible with `::` (colon2) operator.
72
+ #
73
+ # * The constants under the module are included.
74
+ # * The constants under the ancestor modules are included.
75
+ # * The constants under the `::Object` class are not included.
76
+ # * The top level constants are not included.
77
+ #
78
+ def children: (TypeName module_name) -> Hash[Symbol, Constant]
79
+
80
+ private
81
+
82
+ def load_context_constants: (context) -> void
83
+
84
+ def load_child_constants: (TypeName) -> void
85
+
86
+ def constants_from_context: (context, constants: Hash[Symbol, Constant]) -> bool
87
+
88
+ def constants_from_ancestors: (TypeName, constants: Hash[Symbol, Constant]) -> void
89
+
90
+ def constants_itself: (context, constants: Hash[Symbol, Constant]) -> void
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,34 @@
1
+ module RBS
2
+ module Resolver
3
+ # `context` represents the module nesting structure.
4
+ #
5
+ # - `nil` means toplevel
6
+ # - A 2-tuple represents parent and the most inner module
7
+ # - `TypeName` is for a module
8
+ # - `false` is for unknown module
9
+ #
10
+ # Note that the `TypeName` must be an absolute type name.
11
+ #
12
+ # The following Ruby code has context of `[[nil, TypeName("::Foo")], false]` where
13
+ #
14
+ # * `Foo` is a class defined in RBS file
15
+ # * `Bar` is not defined in RBS files
16
+ #
17
+ # ```ruby
18
+ # class Foo
19
+ # module Bar
20
+ # # Context here
21
+ # end
22
+ # end
23
+ # ```
24
+ #
25
+ # The unknown module (`false`) appears only in Ruby code.
26
+ # RBS modules/classes are always exists (or defines new module).
27
+ # Nesting a unknown module cannot happen in RBS.
28
+ #
29
+ # In Ruby this happens when the module/class is not declared in RBS files.
30
+ #
31
+ type context = [context, TypeName | false]
32
+ | nil
33
+ end
34
+ end
@@ -0,0 +1,31 @@
1
+ module RBS
2
+ module Resolver
3
+ # TypeNameResolver resolves given relative type name to absolute type name under a module nesting context.
4
+ #
5
+ # The type name resolution doesn't take account of ancestors of modules.
6
+ # It just ignores included modules and super classes.
7
+ #
8
+ class TypeNameResolver
9
+ type query = [TypeName, context]
10
+
11
+ def initialize: (Environment) -> void
12
+
13
+ # Translates given type name to absolute type name.
14
+ # Returns `nil` if cannot find associated type name.
15
+ #
16
+ def resolve: (TypeName, context: context) -> TypeName?
17
+
18
+ private
19
+
20
+ attr_reader all_names: Set[TypeName]
21
+
22
+ attr_reader cache: Hash[query, TypeName?]
23
+
24
+ def has_name?: (TypeName) -> TypeName?
25
+
26
+ def try_cache: (query) { () -> TypeName? } -> TypeName?
27
+
28
+ def resolve_in: (TypeName, context) -> TypeName?
29
+ end
30
+ end
31
+ end
data/sig/typename.rbs CHANGED
@@ -56,11 +56,17 @@ module RBS
56
56
 
57
57
  # Returns a new type name with a namespace appended to given namespace.
58
58
  #
59
- # TypeName("Hello").with_prefix(Namespace("World")) # => World::Hello
60
- # TypeName("Foo::Bar").with_prefix(Namespace("::Hello")) # => ::Hello::Foo::Bar
61
- # TypeName("::A::B").with_prefix(Namespace("C")) # => ::A::B
59
+ # ```rb
60
+ # TypeName("Hello").with_prefix(Namespace("World")) # => World::Hello
61
+ # TypeName("Foo::Bar").with_prefix(Namespace("::Hello")) # => ::Hello::Foo::Bar
62
+ # TypeName("::A::B").with_prefix(Namespace("C")) # => ::A::B
63
+ # ```
62
64
  #
63
65
  def with_prefix: (Namespace namespace) -> TypeName
66
+
67
+ def +: (TypeName) -> TypeName
68
+
69
+ def split: () -> Array[Symbol]
64
70
  end
65
71
  end
66
72
 
@@ -1187,6 +1187,19 @@ class BigDecimal < Numeric
1187
1187
  #
1188
1188
  def zero?: () -> bool
1189
1189
 
1190
+ # <!--
1191
+ # rdoc-file=ext/bigdecimal/lib/bigdecimal/util.rb
1192
+ # - a.to_d -> bigdecimal
1193
+ # -->
1194
+ # Returns self.
1195
+ #
1196
+ # require 'bigdecimal/util'
1197
+ #
1198
+ # d = BigDecimal("3.14")
1199
+ # d.to_d # => 0.314e1
1200
+ #
1201
+ def to_d: () -> BigDecimal
1202
+
1190
1203
  private
1191
1204
 
1192
1205
  def initialize_copy: (self) -> self
@@ -1378,3 +1391,125 @@ module Kernel
1378
1391
  #
1379
1392
  def self?.BigDecimal: (real | string | BigDecimal initial, ?int digits, ?exception: bool) -> BigDecimal
1380
1393
  end
1394
+
1395
+ %a{annotate:rdoc:skip}
1396
+ class Integer
1397
+ # <!--
1398
+ # rdoc-file=ext/bigdecimal/lib/bigdecimal/util.rb
1399
+ # - int.to_d -> bigdecimal
1400
+ # -->
1401
+ # Returns the value of `int` as a BigDecimal.
1402
+ #
1403
+ # require 'bigdecimal'
1404
+ # require 'bigdecimal/util'
1405
+ #
1406
+ # 42.to_d # => 0.42e2
1407
+ #
1408
+ # See also BigDecimal::new.
1409
+ #
1410
+ def to_d: () -> BigDecimal
1411
+ end
1412
+
1413
+ %a{annotate:rdoc:skip}
1414
+ class Float
1415
+ # <!--
1416
+ # rdoc-file=ext/bigdecimal/lib/bigdecimal/util.rb
1417
+ # - float.to_d -> bigdecimal
1418
+ # - float.to_d(precision) -> bigdecimal
1419
+ # -->
1420
+ # Returns the value of `float` as a BigDecimal. The `precision` parameter is
1421
+ # used to determine the number of significant digits for the result (the default
1422
+ # is Float::DIG).
1423
+ #
1424
+ # require 'bigdecimal'
1425
+ # require 'bigdecimal/util'
1426
+ #
1427
+ # 0.5.to_d # => 0.5e0
1428
+ # 1.234.to_d(2) # => 0.12e1
1429
+ #
1430
+ # See also BigDecimal::new.
1431
+ #
1432
+ def to_d: (?Integer precision) -> BigDecimal
1433
+ end
1434
+
1435
+ %a{annotate:rdoc:skip}
1436
+ class String
1437
+ # <!--
1438
+ # rdoc-file=ext/bigdecimal/lib/bigdecimal/util.rb
1439
+ # - str.to_d -> bigdecimal
1440
+ # -->
1441
+ # Returns the result of interpreting leading characters in `str` as a
1442
+ # BigDecimal.
1443
+ #
1444
+ # require 'bigdecimal'
1445
+ # require 'bigdecimal/util'
1446
+ #
1447
+ # "0.5".to_d # => 0.5e0
1448
+ # "123.45e1".to_d # => 0.12345e4
1449
+ # "45.67 degrees".to_d # => 0.4567e2
1450
+ #
1451
+ # See also BigDecimal::new.
1452
+ #
1453
+ def to_d: () -> BigDecimal
1454
+ end
1455
+
1456
+ %a{annotate:rdoc:skip}
1457
+ class Rational
1458
+ # <!--
1459
+ # rdoc-file=ext/bigdecimal/lib/bigdecimal/util.rb
1460
+ # - rat.to_d(precision) -> bigdecimal
1461
+ # -->
1462
+ # Returns the value as a BigDecimal.
1463
+ #
1464
+ # The required `precision` parameter is used to determine the number of
1465
+ # significant digits for the result.
1466
+ #
1467
+ # require 'bigdecimal'
1468
+ # require 'bigdecimal/util'
1469
+ #
1470
+ # Rational(22, 7).to_d(3) # => 0.314e1
1471
+ #
1472
+ # See also BigDecimal::new.
1473
+ #
1474
+ def to_d: (Integer precision) -> BigDecimal
1475
+ end
1476
+
1477
+ %a{annotate:rdoc:skip}
1478
+ class Complex
1479
+ # <!--
1480
+ # rdoc-file=ext/bigdecimal/lib/bigdecimal/util.rb
1481
+ # - cmp.to_d -> bigdecimal
1482
+ # - cmp.to_d(precision) -> bigdecimal
1483
+ # -->
1484
+ # Returns the value as a BigDecimal.
1485
+ #
1486
+ # The `precision` parameter is required for a rational complex number. This
1487
+ # parameter is used to determine the number of significant digits for the
1488
+ # result.
1489
+ #
1490
+ # require 'bigdecimal'
1491
+ # require 'bigdecimal/util'
1492
+ #
1493
+ # Complex(0.1234567, 0).to_d(4) # => 0.1235e0
1494
+ # Complex(Rational(22, 7), 0).to_d(3) # => 0.314e1
1495
+ #
1496
+ # See also BigDecimal::new.
1497
+ #
1498
+ def to_d: (*untyped args) -> BigDecimal
1499
+ end
1500
+
1501
+ %a{annotate:rdoc:skip}
1502
+ class NilClass
1503
+ # <!--
1504
+ # rdoc-file=ext/bigdecimal/lib/bigdecimal/util.rb
1505
+ # - nil.to_d -> bigdecimal
1506
+ # -->
1507
+ # Returns nil represented as a BigDecimal.
1508
+ #
1509
+ # require 'bigdecimal'
1510
+ # require 'bigdecimal/util'
1511
+ #
1512
+ # nil.to_d # => 0.0
1513
+ #
1514
+ def to_d: () -> BigDecimal
1515
+ end
data/stdlib/erb/0/erb.rbs CHANGED
@@ -1,3 +1,240 @@
1
+ # <!-- rdoc-file=lib/erb.rb -->
2
+ # # ERB -- Ruby Templating
3
+ #
4
+ # ## Introduction
5
+ #
6
+ # ERB provides an easy to use but powerful templating system for Ruby. Using
7
+ # ERB, actual Ruby code can be added to any plain text document for the purposes
8
+ # of generating document information details and/or flow control.
9
+ #
10
+ # A very simple example is this:
11
+ #
12
+ # require 'erb'
13
+ #
14
+ # x = 42
15
+ # template = ERB.new <<-EOF
16
+ # The value of x is: <%= x %>
17
+ # EOF
18
+ # puts template.result(binding)
19
+ #
20
+ # *Prints:* The value of x is: 42
21
+ #
22
+ # More complex examples are given below.
23
+ #
24
+ # ## Recognized Tags
25
+ #
26
+ # ERB recognizes certain tags in the provided template and converts them based
27
+ # on the rules below:
28
+ #
29
+ # <% Ruby code -- inline with output %>
30
+ # <%= Ruby expression -- replace with result %>
31
+ # <%# comment -- ignored -- useful in testing %> (`<% #` doesn't work. Don't use Ruby comments.)
32
+ # % a line of Ruby code -- treated as <% line %> (optional -- see ERB.new)
33
+ # %% replaced with % if first thing on a line and % processing is used
34
+ # <%% or %%> -- replace with <% or %> respectively
35
+ #
36
+ # All other text is passed through ERB filtering unchanged.
37
+ #
38
+ # ## Options
39
+ #
40
+ # There are several settings you can change when you use ERB:
41
+ # * the nature of the tags that are recognized;
42
+ # * the binding used to resolve local variables in the template.
43
+ #
44
+ #
45
+ # See the ERB.new and ERB#result methods for more detail.
46
+ #
47
+ # ## Character encodings
48
+ #
49
+ # ERB (or Ruby code generated by ERB) returns a string in the same character
50
+ # encoding as the input string. When the input string has a magic comment,
51
+ # however, it returns a string in the encoding specified by the magic comment.
52
+ #
53
+ # # -*- coding: utf-8 -*-
54
+ # require 'erb'
55
+ #
56
+ # template = ERB.new <<EOF
57
+ # <%#-*- coding: Big5 -*-%>
58
+ # \_\_ENCODING\_\_ is <%= \_\_ENCODING\_\_ %>.
59
+ # EOF
60
+ # puts template.result
61
+ #
62
+ # *Prints:* _*ENCODING*_ is Big5.
63
+ #
64
+ # ## Examples
65
+ #
66
+ # ### Plain Text
67
+ #
68
+ # ERB is useful for any generic templating situation. Note that in this
69
+ # example, we use the convenient "% at start of line" tag, and we quote the
70
+ # template literally with `%q{...}` to avoid trouble with the backslash.
71
+ #
72
+ # require "erb"
73
+ #
74
+ # # Create template.
75
+ # template = %q{
76
+ # From: James Edward Gray II <james@grayproductions.net>
77
+ # To: <%= to %>
78
+ # Subject: Addressing Needs
79
+ #
80
+ # <%= to[/\w+/] %>:
81
+ #
82
+ # Just wanted to send a quick note assuring that your needs are being
83
+ # addressed.
84
+ #
85
+ # I want you to know that my team will keep working on the issues,
86
+ # especially:
87
+ #
88
+ # <%# ignore numerous minor requests -- focus on priorities %>
89
+ # % priorities.each do |priority|
90
+ # * <%= priority %>
91
+ # % end
92
+ #
93
+ # Thanks for your patience.
94
+ #
95
+ # James Edward Gray II
96
+ # }.gsub(/^ /, '')
97
+ #
98
+ # message = ERB.new(template, trim_mode: "%<>")
99
+ #
100
+ # # Set up template data.
101
+ # to = "Community Spokesman <spokesman@ruby_community.org>"
102
+ # priorities = [ "Run Ruby Quiz",
103
+ # "Document Modules",
104
+ # "Answer Questions on Ruby Talk" ]
105
+ #
106
+ # # Produce result.
107
+ # email = message.result
108
+ # puts email
109
+ #
110
+ # *Generates:*
111
+ #
112
+ # From: James Edward Gray II <james@grayproductions.net>
113
+ # To: Community Spokesman <spokesman@ruby_community.org>
114
+ # Subject: Addressing Needs
115
+ #
116
+ # Community:
117
+ #
118
+ # Just wanted to send a quick note assuring that your needs are being addressed.
119
+ #
120
+ # I want you to know that my team will keep working on the issues, especially:
121
+ #
122
+ # * Run Ruby Quiz
123
+ # * Document Modules
124
+ # * Answer Questions on Ruby Talk
125
+ #
126
+ # Thanks for your patience.
127
+ #
128
+ # James Edward Gray II
129
+ #
130
+ # ### Ruby in HTML
131
+ #
132
+ # ERB is often used in `.rhtml` files (HTML with embedded Ruby). Notice the
133
+ # need in this example to provide a special binding when the template is run, so
134
+ # that the instance variables in the Product object can be resolved.
135
+ #
136
+ # require "erb"
137
+ #
138
+ # # Build template data class.
139
+ # class Product
140
+ # def initialize( code, name, desc, cost )
141
+ # @code = code
142
+ # @name = name
143
+ # @desc = desc
144
+ # @cost = cost
145
+ #
146
+ # @features = [ ]
147
+ # end
148
+ #
149
+ # def add_feature( feature )
150
+ # @features << feature
151
+ # end
152
+ #
153
+ # # Support templating of member data.
154
+ # def get_binding
155
+ # binding
156
+ # end
157
+ #
158
+ # # ...
159
+ # end
160
+ #
161
+ # # Create template.
162
+ # template = %{
163
+ # <html>
164
+ # <head><title>Ruby Toys -- <%= @name %></title></head>
165
+ # <body>
166
+ #
167
+ # <h1><%= @name %> (<%= @code %>)</h1>
168
+ # <p><%= @desc %></p>
169
+ #
170
+ # <ul>
171
+ # <% @features.each do |f| %>
172
+ # <li><b><%= f %></b></li>
173
+ # <% end %>
174
+ # </ul>
175
+ #
176
+ # <p>
177
+ # <% if @cost < 10 %>
178
+ # <b>Only <%= @cost %>!!!</b>
179
+ # <% else %>
180
+ # Call for a price, today!
181
+ # <% end %>
182
+ # </p>
183
+ #
184
+ # </body>
185
+ # </html>
186
+ # }.gsub(/^ /, '')
187
+ #
188
+ # rhtml = ERB.new(template)
189
+ #
190
+ # # Set up template data.
191
+ # toy = Product.new( "TZ-1002",
192
+ # "Rubysapien",
193
+ # "Geek's Best Friend! Responds to Ruby commands...",
194
+ # 999.95 )
195
+ # toy.add_feature("Listens for verbal commands in the Ruby language!")
196
+ # toy.add_feature("Ignores Perl, Java, and all C variants.")
197
+ # toy.add_feature("Karate-Chop Action!!!")
198
+ # toy.add_feature("Matz signature on left leg.")
199
+ # toy.add_feature("Gem studded eyes... Rubies, of course!")
200
+ #
201
+ # # Produce result.
202
+ # rhtml.run(toy.get_binding)
203
+ #
204
+ # *Generates (some blank lines removed):*
205
+ #
206
+ # <html>
207
+ # <head><title>Ruby Toys -- Rubysapien</title></head>
208
+ # <body>
209
+ #
210
+ # <h1>Rubysapien (TZ-1002)</h1>
211
+ # <p>Geek's Best Friend! Responds to Ruby commands...</p>
212
+ #
213
+ # <ul>
214
+ # <li><b>Listens for verbal commands in the Ruby language!</b></li>
215
+ # <li><b>Ignores Perl, Java, and all C variants.</b></li>
216
+ # <li><b>Karate-Chop Action!!!</b></li>
217
+ # <li><b>Matz signature on left leg.</b></li>
218
+ # <li><b>Gem studded eyes... Rubies, of course!</b></li>
219
+ # </ul>
220
+ #
221
+ # <p>
222
+ # Call for a price, today!
223
+ # </p>
224
+ #
225
+ # </body>
226
+ # </html>
227
+ #
228
+ # ## Notes
229
+ #
230
+ # There are a variety of templating solutions available in various Ruby
231
+ # projects. For example, RDoc, distributed with Ruby, uses its own template
232
+ # engine, which can be reused elsewhere.
233
+ #
234
+ # Other popular engines could be found in the corresponding
235
+ # [Category](https://www.ruby-toolbox.com/categories/template_engines) of The
236
+ # Ruby Toolbox.
237
+ #
1
238
  class ERB
2
239
  # <!--
3
240
  # rdoc-file=lib/erb.rb