How to make multi-line string literals in Ruby without using the HERE-DOCUMENT syntax?

Problem Summary

I would like to try Ruby for what I did in Python. In Python, it has the r""" syntax to support raw strings , which is nice because it allows you to have raw strings according to the code and concatenate them in a more natural way and without any indentation. In Ruby, you must use <<'EOT' when using the original strings <<'EOT' , and then EOT on a separate line that breaks the layout of the code.

You may ask, why not use Ruby %q{} ? Good, because %q{} has limitations compared to Python r""" because it does not skip several \\\ and processes only one \ .

I create Latex code on the fly and write to a file that is later compiled using pdflatex. The latex code contains things like \\\ in many places. If I use the Ruby syntax %q{} , this will not work. Therefore, I need to use Ruby <<'EOT' , but I do not want to do this, as this makes the code more difficult to read in the Ruby source file due to the need to indent it to make EOT happy.

I ask if there is a way to make the syntax look like %q{} or some function that takes a string and returns the same result as if using EOT , which processes raw strings without EOT limitation.

I do not need interpolation. So only single quotes. No double quotes. double quotes cause interpolation, which I don't want.

Small working examples to illustrate

Here is a small example in Python, and then I will show what I need to do in Ruby in order to generate the same result.

 my_file = open("py_latex.tex", 'w') x = r"""\\\hline is a raw string"""+r""" another one \\\hline and so on""" my_file.write(x) 

When I open the Latex text file written above, I see the correct result

Mathematica graphics

Now do the same in Ruby. I can not write the following (although I would like)

 file = File.open('rb_latex.tex','w') x=%q{\\\hline is a raw string}+%q{ another one \\\hline and so on} file.write(x) 

The above is not what I want. When it is written to the latex file, it is displayed as

Mathematica graphics

Using EOT works as follows

 file = File.open('rb_latex.tex','w') x=<<-'EOT1'+<<-'EOT2' \\\hline is a raw string EOT1 another one \\\hline and so on EOT2 file.write(x) 

And now the file

Mathematica graphics

ps. it makes the second line on a new line, now this is a problem for me, and I will try to find a solution for this after solving the main problem.

Summary of the issue

How to make %q{} as a syntax for Ruby that looks like Python r""" ?

If someone wants to try the above code in Ruby, make sure there is no space after EOT . I also include below the complete source code.

Python full source

 import os os.chdir(" direct to change to here ") my_file = open("py_latex.tex", 'w') x = r"""\\\hline is a raw string"""+r""" another one \\\hline and so on""" my_file.write(x) my_file.close() 

Ruby source code

 #!/usr/local/bin/ruby -w Dir.chdir("/home/....") file = File.open('rb_latex.tex','w') #x=%q{\\\hline is a raw string}+%q{ another one \\\hline and so on} x=<<-'EOT1'+<<-'EOT2' \\\hline is a raw string EOT1 another one \\\hline and so on EOT2 file.write(x) file.close 

Update

To respond to the comment below:

The idea is that it should act just like HERE-DOCUMENT, but with good% q {} syntax, to make it easier to format the string in the ruby ​​source code. that is, anything inside should be written to the file as is, regardless of what it is.

I tested the solution presented below, but it does not work for all cases. Here is a test case:

 #!/usr/local/bin/ruby -w class String def raw gsub('\\'*2) { '\\'*3 } end end class Array def raw(separator = $,) map(&:raw).join(separator) end end Dir.chdir("/home/me") file = File.open('rb_latex.tex','w') x=%q{'\\'\hline \\\\\\ (6 of them) // some stuff follows. All should be raw string <!DOCTYPE html> \[ stuff \] <html> <head> <title>title</title> <style> video { width: 100% !important; eight: auto !important; } </html> \"quotes\" (did you see this?) \\\hline $\sin(x)$ </style>' //notice this ' is in the raw string!, ok! \begin{tabular}{c}\\\hline '''''' (6 of them) x\\\hline \end{tabular}}.raw+%q{another '''one \\\hline and so on'}.raw file.write(x) file.close 

Looking at the file written, it does not match the original line:

enter image description here

Now compare with Python r"""

 import os os.chdir("/home/me") my_file = open("py_latex.tex", 'w') x =r"""\\'\hline \\\\\\ (6 of them) // some stuff follows. All should be raw string <!DOCTYPE html> \[ stuff \] <html> <head> <title>title</title> <style> video { width: 100% !important; eight: auto !important; } </html> \"quotes\" (did you see this?) \\\hline $\sin(x)$ </style>' //notice this ' is in the raw string!, ok! \begin{tabular}{c}\\\hline '''''' (6 of them) x\\\hline \end{tabular}}"""+r"""{another '''one \\\hline and so on'""" my_file.write(x) my_file.close() 

Here is the conclusion

enter image description here

And above, what I want to get from Ruby.

+6
source share
4 answers

Clearing indentation in documents

To solve indentation problems in documents, one approach is to defuse the main String class by adding the String#undent instance method:

 class String def undent indentation = slice(/^\s+/).length gsub(/^.{#{ indentation }}/, '') end end 

Then you can rewrite your code as follows:

 x = <<-'EOT'.undent \\\hline is a raw string another one \\\hline and so on EOT 

Note. Correcting core classes is generally considered bad style and can compromise stability and maintainability. However, I believe that fixing the String to add #undent is a reasonable exception. This method has so many advantages, and in fact it is not so aggressive. Ultimately, it is up to you to weigh the pros and cons.

+1
source

Canceling Rubys Screen Syntax

If you want to avoid heredocs altogether and think that your general case is a series of exactly three \ s, how about something like the following?

 class String def raw gsub('\\'*2) { '\\'*3 } end end class Array def raw(separator = $,) map(&:raw).join(separator) end end 

This introduces a set of #raw instance methods to compensate for Rubys handling the backslash as an escape character.

Examples

Example a)

 x = '\\\hline is a raw string'.raw + ' another one \\\hline and so on'.raw 

Example b)

 x = %q{\\\hline is a raw string}.raw + %q{ another one \\\hline and so on}.raw 

Example c)

 x = ['\\\hline is a raw string', ' another one \\\hline and so on'].raw 

or, if you set $, = ' ' in advance, you can even leave with the leading space:

Example d)

 x = ['\\\hline is a raw string', 'another one \\\hline and so on'].raw 

Example e)

 x = [%q{\\\hline is a raw string}, %q{ another one \\\hline and so on}].raw 

or alternatively if you previously set $, = ' ' :

Example f)

 x = [%q{\\\hline is a raw string}, %q{another one \\\hline and so on}].raw 

Result

For each of the six examples a) by f), the result is:

 \\\hline is a raw string another one \\\hline and so on 
0
source

If this is a single piece of data, then Ruby has a little-known DATA file descriptor:

 #!/bin/env ruby puts DATA.read __END__ Hi there, this is data \\\\quad backslashes are no problem!\\\\ 

After the magic of __END__ everything that remains in the file is considered as unescaped string data that can be read from a file descriptor named DATA .

So your script can read like:

 #!/usr/local/bin/ruby -w File.open('/home/me/rb_latex.tex','w') {|fp| fp.print DATA.read } __END__ '\\'\hline \\\\\\ (6 of them) // some stuff follows. All should be raw string <!DOCTYPE html> \[ stuff \] <html> <head> <title>title</title> <style> video { width: 100% !important; eight: auto !important; } </html> \"quotes\" (did you see this?) \\\hline $\sin(x)$ </style>' //notice this ' is in the raw string!, ok! \begin{tabular}{c}\\\hline '''''' (6 of them) x\\\hline \end{tabular}another '''one \\\hline and so on' 

Although, I am curious: why are you trying to create this as an intermediate Ruby script, whose only task is to write it to another file? Wouldn't it be more appropriate to just write the output directly to the target file?

0
source

Using <<EOT ', you will get what you want (note the single quotes at the end of the tag):

 my_file = File.open("/tmp/rb_latex.tex", 'w') x = <<'EOT' \\'\hline \\\\\\ (6 of them) // some stuff follows. All should be raw string <!DOCTYPE html> \[ stuff \] <html> <head> <title>title</title> <style> video { width: 100% !important; eight: auto !important; } </html> \"quotes\" (did you see this?) \\\hline $\sin(x)$ </style>' //notice this ' is in the raw string!, ok! \begin{tabular}{c}\\\hline '''''' (6 of them) x\\\hline \end{tabular}}"""+r"""{another '''one \\\hline and so on'""" EOT my_file.write(x) my_file.close() 

Creates this file:

 cat /tmp/rb_latex.tex \\'\hline \\\\\\ (6 of them) // some stuff follows. All should be raw string <!DOCTYPE html> \[ stuff \] <html> <head> <title>title</title> <style> video { width: 100% !important; eight: auto !important; } </html> \"quotes\" (did you see this?) \\\hline $\sin(x)$ </style>' //notice this ' is in the raw string!, ok! \begin{tabular}{c}\\\hline '''''' (6 of them) x\\\hline \end{tabular}}"""+r"""{another '''one \\\hline and so on'""" 
0
source

Source: https://habr.com/ru/post/989871/


All Articles