[ruby-core:112538] [Ruby master Feature#19458] Expose HEREDOC identifier

Issue #19458 has been reported by joelhawksley (Joel Hawksley). ---------------------------------------- Feature #19458: Expose HEREDOC identifier https://bugs.ruby-lang.org/issues/19458 * Author: joelhawksley (Joel Hawksley) * Status: Open * Priority: Normal ---------------------------------------- I’d like to have access to the HEREDOC identifier. In the ViewComponent framework I help maintain, we added a method to declare a template as such: ```ruby class Component erb_template <<~ERB <h1>Hello, <%= @name %>!</h1> ERB end ``` I'd prefer to be able to write: ```ruby class Component template <<~ERB <h1>Hello, <%= @name %>!</h1> ERB end ``` And be able to see that the argument passed to `.template` was from a HEREDOC with an `ERB` identifier, which would allow me to use the correct template handler to compile the template. I could see this being implemented: 1) As a new property of String, such as `identifier` or `heredoc_identifier`. 2) By having HEREDOCs return a subclass of String that includes an `identifier` property. I'd be happy to work on implementing this change. -- https://bugs.ruby-lang.org/

Issue #19458 has been updated by sawa (Tsuyoshi Sawada). It looks like nonsense. To my understanding, the reason you can freely choose the heredoc identifier is not to mark the language of the content, but to allow any string to appear in it. In your example, if you had a line within your string that is just `ERB` besides spaces, you need to come up with an identifier that is different from `ERB` (as well as any other lines in your string). That is what the freedom of the identifier is for. The purpose of identifier is just to terminate a string, and should not carry any significant information. Some editors can hilight the contents of heredoc in different languages depending on the identifier, but that is out of the scope of Ruby, and that only works probabilistically, i.e., under the assumption that you will **probably** not have a line that is identical to the common file extension of the language you are writing the heredoc in. Whether the heredoc iditifier is ERB or MD is nothing more significant than whether the string was written as `"..."`, `'...'`, ?x, `%q{...}`, or `%Q|...|`, etc. Relying on the heredoc identifier to infer the language is also not clean. If you need to notify the language as well as the string, you should pass two arguments to the method: perhaps a symbol representing the language, and the string. ---------------------------------------- Feature #19458: Expose HEREDOC identifier https://bugs.ruby-lang.org/issues/19458#change-101985 * Author: joelhawksley (Joel Hawksley) * Status: Open * Priority: Normal ---------------------------------------- I’d like to have access to the HEREDOC identifier. In the ViewComponent framework I help maintain, we added a method to declare a template as such: ```ruby class Component erb_template <<~ERB <h1>Hello, <%= @name %>!</h1> ERB end ``` I'd prefer to be able to write: ```ruby class Component template <<~ERB <h1>Hello, <%= @name %>!</h1> ERB end ``` And be able to see that the argument passed to `.template` was from a HEREDOC with an `ERB` identifier, which would allow me to use the correct template handler to compile the template. I could see this being implemented: 1) As a new property of String, such as `identifier` or `heredoc_identifier`. 2) By having HEREDOCs return a subclass of String that includes an `identifier` property. I'd be happy to work on implementing this change. -- https://bugs.ruby-lang.org/

Issue #19458 has been updated by sawa (Tsuyoshi Sawada). If you want to keep the string and the markup language information together, then perhaps something like the following is the way to go. Preparation: ```ruby class String def lang_set(lang); tap{@lang = lang} end def lang; @lang end end ``` Using it to write a template: ```ruby class Component template <<~ERB.lang_set(:erb) <h1>Hello, <%= @name %>!</h1> ERB end ``` And then in your `template` code: ```ruby def template(string) lang = string.lang raise "Markup language is not set" unless lang case lang when :erb then erb_template(lang) ... end end ``` ---------------------------------------- Feature #19458: Expose HEREDOC identifier https://bugs.ruby-lang.org/issues/19458#change-102039 * Author: joelhawksley (Joel Hawksley) * Status: Open * Priority: Normal ---------------------------------------- I’d like to have access to the HEREDOC identifier. In the ViewComponent framework I help maintain, we added a method to declare a template as such: ```ruby class Component erb_template <<~ERB <h1>Hello, <%= @name %>!</h1> ERB end ``` I'd prefer to be able to write: ```ruby class Component template <<~ERB <h1>Hello, <%= @name %>!</h1> ERB end ``` And be able to see that the argument passed to `.template` was from a HEREDOC with an `ERB` identifier, which would allow me to use the correct template handler to compile the template. I could see this being implemented: 1) As a new property of String, such as `identifier` or `heredoc_identifier`. 2) By having HEREDOCs return a subclass of String that includes an `identifier` property. I'd be happy to work on implementing this change. -- https://bugs.ruby-lang.org/

Issue #19458 has been updated by zverok (Victor Shepelev). File clipboard-202302251947-5owjc.png added I came to the same idea as this ticket independently in a [half-joke discussion](https://bugs.ruby-lang.org/issues/19015#note-5), and I find it tempting, too. Even planned to submit my own proposal once I'll have it clearly formed in my head.
To my understanding, the reason you can freely choose the heredoc identifier is not to label the language of the content, but to allow any string to appear in it.
First, there is quite widespread agreement to use embedded language's name as a heredoc identifier. So widespread, in fact, that many editors give it as a hint for highlighting:  (SublimeText's standard Ruby highlighting.) Second, even ignoring this argument, the delimiter of HEREdoc is "user's data," so it is up to the user to know what it means, and it is frequently meaningful for them, so programmatic access to this information might be valuable for many contexts. Of course, many users do some "regular" stuff (like `STR` or `EOS`), but others use the possibility to "tag" strings, and if Ruby will give the access to this "tag", it might find many good usages. ---------------------------------------- Feature #19458: Expose HEREDOC identifier https://bugs.ruby-lang.org/issues/19458#change-102054 * Author: joelhawksley (Joel Hawksley) * Status: Open * Priority: Normal ---------------------------------------- I’d like to have access to the HEREDOC identifier. In the ViewComponent framework I help maintain, we added a method to declare a template as such: ```ruby class Component erb_template <<~ERB <h1>Hello, <%= @name %>!</h1> ERB end ``` I'd prefer to be able to write: ```ruby class Component template <<~ERB <h1>Hello, <%= @name %>!</h1> ERB end ``` And be able to see that the argument passed to `.template` was from a HEREDOC with an `ERB` identifier, which would allow me to use the correct template handler to compile the template. I could see this being implemented: 1) As a new property of String, such as `identifier` or `heredoc_identifier`. 2) By having HEREDOCs return a subclass of String that includes an `identifier` property. I'd be happy to work on implementing this change. ---Files-------------------------------- clipboard-202302251947-5owjc.png (16.4 KB) -- https://bugs.ruby-lang.org/

Issue #19458 has been updated by sawa (Tsuyoshi Sawada). @zverok So what are you supposed to do if you wanted to include `ERB` in the string when you have to use `ERB` as the identifier? Did you fully read my comment? ---------------------------------------- Feature #19458: Expose HEREDOC identifier https://bugs.ruby-lang.org/issues/19458#change-102056 * Author: joelhawksley (Joel Hawksley) * Status: Open * Priority: Normal ---------------------------------------- I’d like to have access to the HEREDOC identifier. In the ViewComponent framework I help maintain, we added a method to declare a template as such: ```ruby class Component erb_template <<~ERB <h1>Hello, <%= @name %>!</h1> ERB end ``` I'd prefer to be able to write: ```ruby class Component template <<~ERB <h1>Hello, <%= @name %>!</h1> ERB end ``` And be able to see that the argument passed to `.template` was from a HEREDOC with an `ERB` identifier, which would allow me to use the correct template handler to compile the template. I could see this being implemented: 1) As a new property of String, such as `identifier` or `heredoc_identifier`. 2) By having HEREDOCs return a subclass of String that includes an `identifier` property. I'd be happy to work on implementing this change. ---Files-------------------------------- clipboard-202302251947-5owjc.png (16.4 KB) -- https://bugs.ruby-lang.org/

Issue #19458 has been updated by zverok (Victor Shepelev).
So what are you supposed to do if you wanted to include ERB in the string when you have to use ERB as the identifier?
This is a valid concern, and it doesn't have any good answer to it. On the other hand, 1. the possibility of a need to have a literal text `ERB`/`HTML`/`SQL`/`SLIM` _on a separate line_ in a HEREdoc presumably written in the corresponding language is relatively low ( 2. the feature of "there could be any text" was indeed introduced for a use cases you are describing, but its real usage for "tagging" strings is quite widespread; saying that it is no more significant than `"` vs `'` follows the original intention, but ignores the real usage (including in Ruby's standard library codebase, for example). 3. the usefulness of acknowledging "tagging" use in a language seems to be a least worth a discussion; whereupon the _harm_ of this idea seems to be quite low (other than the general opposition to change). ---------------------------------------- Feature #19458: Expose HEREDOC identifier https://bugs.ruby-lang.org/issues/19458#change-102058 * Author: joelhawksley (Joel Hawksley) * Status: Open * Priority: Normal ---------------------------------------- I’d like to have access to the HEREDOC identifier. In the ViewComponent framework I help maintain, we added a method to declare a template as such: ```ruby class Component erb_template <<~ERB <h1>Hello, <%= @name %>!</h1> ERB end ``` I'd prefer to be able to write: ```ruby class Component template <<~ERB <h1>Hello, <%= @name %>!</h1> ERB end ``` And be able to see that the argument passed to `.template` was from a HEREDOC with an `ERB` identifier, which would allow me to use the correct template handler to compile the template. I could see this being implemented: 1) As a new property of String, such as `identifier` or `heredoc_identifier`. 2) By having HEREDOCs return a subclass of String that includes an `identifier` property. I'd be happy to work on implementing this change. ---Files-------------------------------- clipboard-202302251947-5owjc.png (16.4 KB) -- https://bugs.ruby-lang.org/

Issue #19458 has been updated by jeremyevans0 (Jeremy Evans). Exposing the identifier for only heredocs seems inconsistent. However, for consistency, we could expose the identifier for all literal Ruby strings: ```ruby 'foo'.identifier # => "'" "foo".identifier # => "\"" %[foo].identifier # => "%[" %q{foo}.identifier # => "%q{" %Q|foo|.identifier # => "%Q|" ?f.identifier # => "?" ``` For strings created via the C-API, `identifier` would return `nil`. This could result in interesting applications. That being said, I'm against the adding such a method. I do see the advantage in avoiding redundancy, but it seems a specialized case, and not something worth adding a core method for. ---------------------------------------- Feature #19458: Expose HEREDOC identifier https://bugs.ruby-lang.org/issues/19458#change-102059 * Author: joelhawksley (Joel Hawksley) * Status: Open * Priority: Normal ---------------------------------------- I’d like to have access to the HEREDOC identifier. In the ViewComponent framework I help maintain, we added a method to declare a template as such: ```ruby class Component erb_template <<~ERB <h1>Hello, <%= @name %>!</h1> ERB end ``` I'd prefer to be able to write: ```ruby class Component template <<~ERB <h1>Hello, <%= @name %>!</h1> ERB end ``` And be able to see that the argument passed to `.template` was from a HEREDOC with an `ERB` identifier, which would allow me to use the correct template handler to compile the template. I could see this being implemented: 1) As a new property of String, such as `identifier` or `heredoc_identifier`. 2) By having HEREDOCs return a subclass of String that includes an `identifier` property. I'd be happy to work on implementing this change. ---Files-------------------------------- clipboard-202302251947-5owjc.png (16.4 KB) -- https://bugs.ruby-lang.org/

Issue #19458 has been updated by zverok (Victor Shepelev). My thinking (the proposal I considered submitting but didn't fully form yet) was rather that HEREdocs might create some subclass, like `TaggedString` or something (which might also be able to create by other means, say, literally `TaggedString.new(content, tag: :ERB)`), and _that_ might create some interesting consequences, too. Not sure yet if I'll ever submit this one; just thinking about it and trying to understand whether it is of generic use. TBH, "whether it was created with `'` or `"`" (while also "might be useful") doesn't seem to be of the same level of interest/importance as custom text entered to delimit a HEREdoc. ---------------------------------------- Feature #19458: Expose HEREDOC identifier https://bugs.ruby-lang.org/issues/19458#change-102061 * Author: joelhawksley (Joel Hawksley) * Status: Open * Priority: Normal ---------------------------------------- I’d like to have access to the HEREDOC identifier. In the ViewComponent framework I help maintain, we added a method to declare a template as such: ```ruby class Component erb_template <<~ERB <h1>Hello, <%= @name %>!</h1> ERB end ``` I'd prefer to be able to write: ```ruby class Component template <<~ERB <h1>Hello, <%= @name %>!</h1> ERB end ``` And be able to see that the argument passed to `.template` was from a HEREDOC with an `ERB` identifier, which would allow me to use the correct template handler to compile the template. I could see this being implemented: 1) As a new property of String, such as `identifier` or `heredoc_identifier`. 2) By having HEREDOCs return a subclass of String that includes an `identifier` property. I'd be happy to work on implementing this change. ---Files-------------------------------- clipboard-202302251947-5owjc.png (16.4 KB) -- https://bugs.ruby-lang.org/

Issue #19458 has been updated by rubyFeedback (robert heiler). I have no particularly strong opinion either way. But I wanted to comment on zverok's statement:
[...] use the possibility to "tag" strings, and if Ruby will give the access to this "tag", it might find many good usages.
I agree somwhat with that opinion too. For instance, I also suggested to propose an extension to case/when "interfaces" where we can not only access all case/when entries in a given method (perhaps only for non-private methods), and merge different case/when entries, as well as adding methods such as .to_h or .to_hash to convert it to a hash, and/or to a proc object, and .call() on it. My original use case for this, several years ago, was to be able to autogenerated tab-completion for shells such as bash and zsh. So that I can know all entries in a case/when menu. For instance: case x when 'a','b','c' 'foobar' # all three match to foobar, similar to a Hash where the # three keys 'a','b' and 'c' would point to 'foobar' end Since then case/when menu got even better support - see pattern matching. Anyway - making a good proposal that is not-trivial, is quite difficult actually, so I kind of dropped it, hoping that someone else may find the motivation to do a good proposal here one day. :D So, to come to this issue - I think if you look at it from an extended point of view, then being able to know associated use cases could indeed be interesting, so on that topic I concur with zverok. That does not mean I am in favour of the suggestion here, or in disfavour - I just think it may indeed be worthy to explore use case here. I have not had a huge need to use ERB per se, but I do happen to read in a .md file ---------------------------------------- Feature #19458: Expose HEREDOC identifier https://bugs.ruby-lang.org/issues/19458#change-102062 * Author: joelhawksley (Joel Hawksley) * Status: Open * Priority: Normal ---------------------------------------- I’d like to have access to the HEREDOC identifier. In the ViewComponent framework I help maintain, we added a method to declare a template as such: ```ruby class Component erb_template <<~ERB <h1>Hello, <%= @name %>!</h1> ERB end ``` I'd prefer to be able to write: ```ruby class Component template <<~ERB <h1>Hello, <%= @name %>!</h1> ERB end ``` And be able to see that the argument passed to `.template` was from a HEREDOC with an `ERB` identifier, which would allow me to use the correct template handler to compile the template. I could see this being implemented: 1) As a new property of String, such as `identifier` or `heredoc_identifier`. 2) By having HEREDOCs return a subclass of String that includes an `identifier` property. I'd be happy to work on implementing this change. ---Files-------------------------------- clipboard-202302251947-5owjc.png (16.4 KB) -- https://bugs.ruby-lang.org/

Issue #19458 has been updated by joelhawksley (Joel Hawksley). zverok (Victor Shepelev) wrote in #note-6:
My thinking (the proposal I considered submitting but didn't fully form yet) was rather that HEREdocs might create some subclass, like `TaggedString` or something (which might also be able to create by other means, say, literally `TaggedString.new(content, tag: :ERB)`), and _that_ might create some interesting consequences, too.
Given the feedback here so far, this is the approach I think we should take. ---------------------------------------- Feature #19458: Expose HEREDOC identifier https://bugs.ruby-lang.org/issues/19458#change-102570 * Author: joelhawksley (Joel Hawksley) * Status: Open * Priority: Normal ---------------------------------------- I’d like to have access to the HEREDOC identifier. In the ViewComponent framework I help maintain, we added a method to declare a template as such: ```ruby class Component erb_template <<~ERB <h1>Hello, <%= @name %>!</h1> ERB end ``` I'd prefer to be able to write: ```ruby class Component template <<~ERB <h1>Hello, <%= @name %>!</h1> ERB end ``` And be able to see that the argument passed to `.template` was from a HEREDOC with an `ERB` identifier, which would allow me to use the correct template handler to compile the template. I could see this being implemented: 1) As a new property of String, such as `identifier` or `heredoc_identifier`. 2) By having HEREDOCs return a subclass of String that includes an `identifier` property. I'd be happy to work on implementing this change. ---Files-------------------------------- clipboard-202302251947-5owjc.png (16.4 KB) -- https://bugs.ruby-lang.org/

Issue #19458 has been updated by janosch-x (Janosch Müller). sawa (Tsuyoshi Sawada) wrote in #note-3:
@zverok So what are you supposed to do if you wanted to include `ERB` in the string when you have to use `ERB` as the identifier?
```ruby string = <<~ERB #{'ERB'} ERB ``` ---------------------------------------- Feature #19458: Expose HEREDOC identifier https://bugs.ruby-lang.org/issues/19458#change-102817 * Author: joelhawksley (Joel Hawksley) * Status: Open * Priority: Normal ---------------------------------------- I’d like to have access to the HEREDOC identifier. In the ViewComponent framework I help maintain, we added a method to declare a template as such: ```ruby class Component erb_template <<~ERB <h1>Hello, <%= @name %>!</h1> ERB end ``` I'd prefer to be able to write: ```ruby class Component template <<~ERB <h1>Hello, <%= @name %>!</h1> ERB end ``` And be able to see that the argument passed to `.template` was from a HEREDOC with an `ERB` identifier, which would allow me to use the correct template handler to compile the template. I could see this being implemented: 1) As a new property of String, such as `identifier` or `heredoc_identifier`. 2) By having HEREDOCs return a subclass of String that includes an `identifier` property. I'd be happy to work on implementing this change. ---Files-------------------------------- clipboard-202302251947-5owjc.png (16.4 KB) -- https://bugs.ruby-lang.org/

Issue #19458 has been updated by janosch-x (Janosch Müller). joelhawksley (Joel Hawksley) wrote in #note-8:
My thinking (the proposal I considered submitting but didn't fully form yet) was rather that HEREdocs might create some subclass, like `TaggedString` [...]
Given the feedback here so far, this is the approach I think we should take.
That would be a substantial breaking change for a minor feature. It would break code like `foo.class == String` or `foo.instance_of?(String)`. ---------------------------------------- Feature #19458: Expose HEREDOC identifier https://bugs.ruby-lang.org/issues/19458#change-102818 * Author: joelhawksley (Joel Hawksley) * Status: Open * Priority: Normal ---------------------------------------- I’d like to have access to the HEREDOC identifier. In the ViewComponent framework I help maintain, we added a method to declare a template as such: ```ruby class Component erb_template <<~ERB <h1>Hello, <%= @name %>!</h1> ERB end ``` I'd prefer to be able to write: ```ruby class Component template <<~ERB <h1>Hello, <%= @name %>!</h1> ERB end ``` And be able to see that the argument passed to `.template` was from a HEREDOC with an `ERB` identifier, which would allow me to use the correct template handler to compile the template. I could see this being implemented: 1) As a new property of String, such as `identifier` or `heredoc_identifier`. 2) By having HEREDOCs return a subclass of String that includes an `identifier` property. I'd be happy to work on implementing this change. ---Files-------------------------------- clipboard-202302251947-5owjc.png (16.4 KB) -- https://bugs.ruby-lang.org/

Issue #19458 has been updated by Dan0042 (Daniel DeLorme). What about something as KISS as possible, like just adding an instance variable to heredoc strings. `string.instance_variable_get(:@heredoc) == :ERB` ---------------------------------------- Feature #19458: Expose HEREDOC identifier https://bugs.ruby-lang.org/issues/19458#change-103809 * Author: joelhawksley (Joel Hawksley) * Status: Open * Priority: Normal ---------------------------------------- I’d like to have access to the HEREDOC identifier. In the ViewComponent framework I help maintain, we added a method to declare a template as such: ```ruby class Component erb_template <<~ERB <h1>Hello, <%= @name %>!</h1> ERB end ``` I'd prefer to be able to write: ```ruby class Component template <<~ERB <h1>Hello, <%= @name %>!</h1> ERB end ``` And be able to see that the argument passed to `.template` was from a HEREDOC with an `ERB` identifier, which would allow me to use the correct template handler to compile the template. I could see this being implemented: 1) As a new property of String, such as `identifier` or `heredoc_identifier`. 2) By having HEREDOCs return a subclass of String that includes an `identifier` property. I'd be happy to work on implementing this change. ---Files-------------------------------- clipboard-202302251947-5owjc.png (16.4 KB) -- https://bugs.ruby-lang.org/

Issue #19458 has been updated by bradgessler (Brad Gessler). I'm working with some code in Phlex that would benefit from introspecting the name of the HEREDOC. Here's what I currently have: ```ruby ContentSlide(title: "Why Phlex?"){ Markdown <<~MARKDOWN * Because its fun * Because its super-de-dooper MARKDOWN } ``` The `Markdown <<~MARKDOWN` line feels like it came from the redundancy department of redundancy. I would do this: ```ruby ContentSlide(title: "Why Phlex?"){ Markdown %{ * Because its fun * Because its super-de-dooper } ``` But there's no `%{}` type blocks that deal with indents like HEREDOCS. ---------------------------------------- Feature #19458: Expose HEREDOC identifier https://bugs.ruby-lang.org/issues/19458#change-108626 * Author: joelhawksley (Joel Hawksley) * Status: Open ---------------------------------------- I’d like to have access to the HEREDOC identifier. In the ViewComponent framework I help maintain, we added a method to declare a template as such: ```ruby class Component erb_template <<~ERB <h1>Hello, <%= @name %>!</h1> ERB end ``` I'd prefer to be able to write: ```ruby class Component template <<~ERB <h1>Hello, <%= @name %>!</h1> ERB end ``` And be able to see that the argument passed to `.template` was from a HEREDOC with an `ERB` identifier, which would allow me to use the correct template handler to compile the template. I could see this being implemented: 1) As a new property of String, such as `identifier` or `heredoc_identifier`. 2) By having HEREDOCs return a subclass of String that includes an `identifier` property. I'd be happy to work on implementing this change. ---Files-------------------------------- clipboard-202302251947-5owjc.png (16.4 KB) -- https://bugs.ruby-lang.org/
participants (9)
-
bradgessler (Brad Gessler)
-
Dan0042 (Daniel DeLorme)
-
janosch-x
-
jeremyevans0 (Jeremy Evans)
-
joelhawksley (Joel Hawksley)
-
joelhawksley (Joel Hawksley)
-
rubyFeedback (robert heiler)
-
sawa (Tsuyoshi Sawada)
-
zverok (Victor Shepelev)