Multi-Line Comments in Ruby? - ruby

How can I comment multiple lines in Ruby?

#!/usr/bin/env ruby
=begin
Every body mentioned this way
to have multiline comments.
The =begin and =end must be at the beginning of the line or
it will be a syntax error.
=end
puts "Hello world!"
<<-DOC
Also, you could create a docstring.
which...
DOC
puts "Hello world!"
"..is kinda ugly and creates
a String instance, but I know one guy
with a Smalltalk background, who
does this."
puts "Hello world!"
##
# most
# people
# do
# this
__END__
But all forgot there is another option.
Only at the end of a file, of course.
This is how it looks (via screenshot) - otherwise it's hard to interpret how the above comments will look. Click to Zoom-in:

=begin
My
multiline
comment
here
=end

Despite the existence of =begin and =end, the normal and a more correct way to comment is to use #'s on each line. If you read the source of any ruby library, you will see that this is the way multi-line comments are done in almost all cases.

#!/usr/bin/env ruby
=begin
Between =begin and =end, any number
of lines may be written. All of these
lines are ignored by the Ruby interpreter.
=end
puts "Hello world!"

Using either:
=begin
This
is
a
comment
block
=end
or
# This
# is
# a
# comment
# block
are the only two currently supported by rdoc, which is a good reason to use only these I think.

=begin
comment line 1
comment line 2
=end
make sure =begin and =end is the first thing on that line (no spaces)

Here is an example :
=begin
print "Give me a number:"
number = gets.chomp.to_f
total = number * 10
puts "The total value is : #{total}"
=end
Everything you place in between =begin and =end will be treated as a comment regardless of how many lines of code it contains between.
Note: Make sure there is no space between = and begin:
Correct: =begin
Wrong: = begin

=begin
(some code here)
=end
and
# This code
# on multiple lines
# is commented out
are both correct. The advantage of the first type of comment is editability—it's easier to uncomment because fewer characters are deleted. The advantage of the second type of comment is readability—reading the code line by line, it's much easier to tell that a particular line has been commented out. Your call but think about who's coming after you and how easy it is for them to read and maintain.

In case someone is looking for a way to comment multiple lines in a html template in Ruby on Rails, there might be a problem with =begin =end, for instance:
<%
=begin
%>
... multiple HTML lines to comment out
<%= image_tag("image.jpg") %>
<%
=end
%>
will fail because of the %> closing the image_tag.
In this case, maybe it is arguable whether this is commenting out or not, but I prefer to enclose the undesired section with an "if false" block:
<% if false %>
... multiple HTML lines to comment out
<%= image_tag("image.jpg") %>
<% end %>
This will work.

def idle
<<~aid
This is some description of what idle does.
It does nothing actually, it's just here to show an example of multiline
documentation. Thus said, this is something that is more common in the
python community. That's an important point as it's good to also fit the
expectation of your community of work. Now, if you agree with your team to
go with a solution like this one for documenting your own base code, that's
fine: just discuss about it with them first.
Depending on your editor configuration, it won't be colored like a comment,
like those starting with a "#". But as any keyword can be used for wrapping
an heredoc, it is easy to spot anyway. One could even come with separated
words for different puposes, so selective extraction for different types of
documentation generation would be more practical. Depending on your editor,
you possibly could configure it to use the same syntax highlight used for
monoline comment when the keyword is one like aid or whatever you like.
Also note that the squiggly-heredoc, using "~", allow to position
the closing term with a level of indentation. That avoids to break the visual reading flow, unlike this far too long line.
aid
end
Note that at the moment of the post, the stackoverflow engine doesn't render syntax coloration correctly. Testing how it renders in your editor of choice is let as an exercise. ;)

Related

Is it possible to change ruby comment symbol?

So, to comment in ruby, you need the # symbol.
# this is some comments
Which is fine, but for multi-line comments, ruby has an ugly system.
=begin
comment line 1
comment line 2
=end
I have search around the internet and found nothing on the topic. I want to see if I am able to change that format to something better by defining my own commenting system. Such as:
/*
comment line 1
comment line 2
*/
I want to see if I can do something like
def /*
define comment logic
end
def */
define comment logic
end
Just something to that effect. I don't need to replace to current one, just want to see how I can define my own. I'm not looking to rewrite ruby. I just want to see if there is something simple that i can do whenever I write ruby. As an example, if I want to add a method to the String class, I can do
class String
def new_method
# some new functionality.
end
end
I want to see if I can do something like that for comments.
Nobody uses multi-line syntax. People do this instead:
# comment line 1
# comment line 2
Most editors have a shortcut that allows one to comment in multiple lines easily. You will get used to it!
A comment says "Ruby stops here, what follows is outside of Ruby". Therefore, it should be pretty obvious, that you cannot change what a comment is from inside Ruby.
But there's another problem with your proposed syntax: it is already valid Ruby. It's a multi-line Regexp literal. (Yes, it is semantically invalid, but it is a syntactically valid Regexp literal.)

Preferred style for displaying multiple lines using `puts`

I know there are several different ways of being able to combine puts statements into one. But more importantly, I'm trying to determine if there's a generally accepted/preferred style for this (I've only been able to dig up other people's clever ways of doing it, but no real reference on a preferred style).
I've seen things like this:
puts "This", "is", "fairly", "easy" # Each word goes on it's own line
or perhaps:
puts ["This", "seems", "convoluted"].join("\n") # Each word goes on it's own line
or an "ugly" way:
def ugly_puts
puts "Not using quotes
And using no code indentation to preserve output formatting"
end
or simply:
puts "This"
puts "Seems"
puts "Straightforward."
It makes most sense for me to use the last methodology, but I'm just curious if there's a common/preferred way I should go about dealing with multiple line output like this.
If the lines to be printed are short enough to be put together on a single line in the source, then I would go with your first option:
puts "This", "is", "fairly", "easy"
If they are long, then I would use a heredoc:
puts <<_.unindent
This Blah Blah ...
Seems Blah Blah ...
Straightforward. Blah Blah ...
_
where unindent is a method to unindent an indented heredoc along the lines suggested in Ruby indented multiline strings. Notice that in future versions of Ruby, it is likely that there will be a simpler way to unindent a heredoc, so this option will become more useful.
I see no point in using your second or fourth option. The third may be used, but it looks ugly.
TL;DR preference and readability
I've scoured the following ruby style guides:
Ruby Style Guide
bbatsov's Ruby Style Guide
Neither of them mention any specific or preferred method of printing multiple puts statements.
I think it's both situational and preferential. What is more readable in the situation? If you have several long puts statements as simply strings, split them into separate puts statements on several lines.
puts "Something very longgggggggggggg"
puts "Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an..."
puts "unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing..."
If you have for some reason stored your separate statements in variables, just puts them all on a single line: puts this, that, thing.
For storing puts statements in a method, it might be convenient for times you want to print several lines out in the console. For example, when making a program where the user would interact and use with via the terminal, you might want to store certain statements within a method and on users call, print them out (i.e. Printing out instructions, or printing out available commands).

Ignore commented out code when using YARD

I have some Ruby code that looks like this:
# some_string = "{really?}"
where the curly braces need to be part of the string. This line is commented out code that I'd like to remain there. I'm additionally using YARD to document code, so when I run yard doc it (naturally) throws a warning about being unable to link "really".
Is there a way I can tell YARD to ignore commented out code?
Is there a way I can tell YARD to ignore commented out code?
On the one hand, YARD is documented as supporting Rdoc markup. And Rdoc is documented to support a couple of ways to hide parts.
RDoc stops processing comments if it finds a comment line starting
with -- right after the # character (otherwise, it will be treated as
a rule if it has three dashes or more). This can be used to separate
external from internal comments, or to stop a comment being associated
with a method, class, or module. Commenting can be turned back on with
a line that starts with ++.
:stopdoc: / :startdoc:
Stop and start adding new documentation elements to the current
container. For example, if a class has a number of constants that you
don’t want to document, put a :stopdoc: before the first, and a
:startdoc: after the last. If you don’t specify a :startdoc: by the end
of the container, disables documentation for the rest of the current
file.
Source
On the other hand, I have never persuaded Rdoc or YARD to follow that markup. If your luck is better than mine, you can stop reading here.
If you, too, can't persuade YARD to follow that markup, I think your best bet might be to cut that line, and commit the file with a distinctive commit message--one that you'll be able to find easily by grepping the source control logs.
Finally, rake lets you transform text (code) files in arbitrary ways. You can write a Rakefile to delete lines before processing them through YARD.
$ cat silly-ruby-file.src
class Something
def this_method
end
def that_method
# some_string = "{really?}" # Hide me
end
end
I appended the text # Hide me; it's a lot easier to filter that specific text than it is to filter commented lines of arbitrary code.
$ cat Rakefile
task :default => "silly-ruby-file.rb"
sh "grep -v '# Hide me' silly-ruby-file.src > silly-ruby-file.rb"
This tells rake to run grep, copying all lines except those that have the text "# Hide me" to stdout, which is redirected to "silly-ruby-file.rb".

Ruby puts<<PARAGRAPH

puts <<PARAGRAPH
There's somthing going on here.
With the PARAGRAPH thing
We'll be able to type as much as we like.
Even 4 lines if we want, or 5, or 6 .
PARAGRAPH
This can work, using Notepad++
But why this can't work?
puts <<PARAGRAPH
aaaa Aa
aaa
AA
PARAGRAPH
test.rb:1: syntax error,unexpected tCONSTANT, expecting $end
Thanks!
My guess is that in your second snippet PARAGRAPH is not at the begging of the line.
The multi-line strings in ruby, are weird that way. The terminating character (whatever it may be) must be the first thing on a line to terminate the string, otherwise you will often see the syntax errors.
Ensure ensure that PARAGRAPH (the second instance) is a) spelled the same as your first instance, and b) at the start of the line, or change your code to:
def go
puts <<-PARAGRAPH # hyphen allows the end marker to be indented
Hi mom!
PARAGRAPH
end
For more information, read the intro to Strings and the full description.
The code works for me. One way I broke it was by adding space between << and PARAGRAPH
puts << PARAGRAPH
PARAGRAPH
This is different from the next example.
puts <<PARAGRAPH
PARAGRAPH
Edit: As I continue play with it I found that PARAGRAPH is just like any place holder. You can do the following and you will still get a paragraph in a string
puts <<ANYTHING_YOU_WANT
ANYTHING_YOU_WANT
I thought it was cool that it is not restricted only to the word PARAGRAPH. I didn't know.
I can get either version to error by adding additional spaces after the final PARAGRAPH.
Ensure that the closing PARAGRAPH is truly on a new line (per diedthreetimes' answer) and has no trailing characters (i.e. spaces, tabs, etc.)

Delete first two lines of file with ruby

My script reads in large text files and grabs the first page with a regex. I need to remove the first two lines of each first page or change the regex to match 1 line after the ==Page 1== string. I include the entire script here because I've been asked to in past questions and because I'm new to ruby and don't always know how integrate snippets as answers:
#!/usr/bin/env ruby -wKU
require 'fileutils'
source = File.open('list.txt')
source.readlines.each do |line|
line.strip!
if File.exists? line
file = File.open(line)
end
text = (File.read(line))
match = text.match(/==Page 1(.*)==Page 2==/m)
puts match
end
Now, when You have updated your question, I had to delete a big part of so good answer :-)
I guess the main point of your problem was that you wanted to use match[1] instead of match. The object returned by Regexp.match method (MatchData) can be treated like an array, which holds the whole matched string as the first element, and each subquery in the following elements. So, in your case the variable match (and match[0]) is the whole matched string (together with '==Page..==' marks), but you wanted just the first subexpression which is hidden in match[1].
Now about other, minor problems I sense in your code. Please, don't be offended in case you already know what I say, but maybe others will profit from the warnings.
The first part of your code (if File.exists? line) was checking whether the file exists, but your code just opened the file (without closing it!) and still was trying to open the file few lines later.
You may use this line instead:
next unless File.exists? line
The second thing is that the program should be prepared to handle the situation when the file has no page marks, so it does not match the pattern. (The variable match would then be nil)
The third suggestion is that a little more complicated pattern might be used. The current one (/==Page 1==(.*)==Page 2==/m) would return the page content with the End-Of-Line mark as the first character. If you use this pattern:
/==Page 1==\s*\n(.*)==Page 2==/m
then the subexpression will not contain the white spaces placed in the same line as the '==Page 1==` text. And if you use this pattern:
/==Page 1==\s*\n(.*\n)==Page 2==/m
then you will be sure that the '==Page 2==' mark starts from the beginning of the line.
And the fourth issue is that very often programmers (sometimes including me, of course) tend to forget about closing the file after they opened it. In your case you have opened the 'source' file, but in the code there was no source.close statement after the loop. The most secure way of handling files is by passing a block to the File.open method, so You might use the following form of the first lines of your program:
File.open('list.txt') do |source|
source.readlines.each do |line|
...but in this case it would be cleaner to write just:
File.readlines('list.txt').each do |line|
Taking it all together, the code might look like this (I changed the variable line to fname for better code readability):
#!/usr/bin/env ruby -wKU
require 'fileutils'
File.readlines('list.txt').each do |fname|
fname.strip!
next unless File.exists? fname
text = File.read(fname)
if match = text.match(/==Page 1==\s*\n(.*\n)==Page 2==/m)
# The whole 'page' (String):
puts match[1].inspect
# The 'page' without the first two lines:
# (in case you really wanted to delete lines):
puts match[1].split("\n")[2..-1].inspect
else
# What to do if the file does not match the pattern?
raise "The file #{fname} does NOT include the page separators."
end
end

Resources