Ruby: syntax for string interpolation and commenting - ruby

There are a lot of similar questions to this one but i think none really had the answer i was in need of.
From what i perceived, anything that has a # preceding it becomes a comment, as in:
puts "not a comment"
# puts "in a comment"
but when it come to string interpolation, you can say:
puts "time is #{Time.now}"
and the # at #{Time.now} doesn't start commenting whatever is written after it.
How is it so?

The # sign in this case is encased in quotation marks, and is parsed as part of the string, not as a comment.

Yes, what #Osama said. But also, if you put a comment inside the chunk of Ruby code, it won't comment out the rest of the entire line. So,
puts "'#{'oof'#.reverse},' he said."
wil print "'oof,' he said", while
puts "'#{'oof'.reverse},' he said."
results in "'foo,' he said".

Related

What's Wrong With my Palindrome Program? (Ruby, user inputs the string themselves)

I so decided to make a palindrome program, but I did so by checking a string inputted by a user. In order to do this properly, I wanted to strip away the capitalization, spaces, and punctuation. I managed to get everything but the punctuation part of it working. Every time I try with a string like "Madam, I'm Adam" the program crashes. I am very new to Ruby, and I have only learned my knowledge through the Codecademy website. And I also using the editor provided to run my code. Every time I run it like:
puts "Enter a string!"
user_input = gets.chomp
user_input.downcase!
user_input = user_input.gsub(/[^0-9a-z ]/i, '')
if user_input.include?(" ")
user_input.gsub!(/ /, "")
end
if user_input == user_input.reverse
print "Is a pallindrome"
else
print "Is not a pallindrome"
end
It crashes. But if I run it like:
puts "Enter a string!"
user_input = gets.chomp
user_input.downcase!
if user_input.include?(" ")
user_input.gsub!(/ /, "")
end
if user_input == user_input.reverse
print "Is a pallindrome"
else
print "Is not a pallindrome"
end
It works. What a I doing wrong here? Why does my program always crash when I attempt to take away the punctuation?
Nothing is wrong with your program. Codecademy has a bug reading any input that has a quote in it...
Try it out:
gets
Just enter ' to see it crash...
My advice is to get your own local environment to develop on ruby. There are many many resources out there to help you install a simple ruby environment on any OS.
After that, download and install Sublime Text and start creating your ruby source file. Then you will see that ruby <your_file>.rb will work perfectly as you expect.

How do I write shell-like scripts using Ruby?

I have a task of writing a simple Ruby script which would do the following.
Upon execution from the UNIX command line, it would present the user with a prompt at which he should be able to run certain commands, like "dir", "help" or "exit". Upon "exit" the user should return to the Unix shell.
I'm not asking for the solution; I would just like to know how this "shell" functionality can be implemented in Ruby. How do you present the user with a prompt and interpret commands.
I do not need a CLI script that takes arguments. I need something that creates a shell interface.
The type of program you require can easily be made with just a few simple constructs.
I know you're not asking for a solution, but I'll just give you a skeleton to start off and play around with:
#!/usr/bin/env ruby
def prnthelp
puts "Hello sir, what would you like to do?"
puts "1: dir"
puts "2: exit"
end
def loop
prnthelp
case gets.chomp.to_i
when 1 then puts "you chose dir!"
when 2 then puts "you chose exit!"
exit
end
loop
end
loop
Anyways, this is a simplistic example on how you could do it, but probably the book recommended in the comments is better. But this is just to get you off.
Some commands to get you started are:
somevar = gets
This gets user input. Maybe learn about some string methods to manipulate this input can do you some good. http://ruby-doc.org/core-2.0/String.html
chomp will chop off any whitespace, and to_i converts it to an integer.
Some commands to do Unix stuff:
system('ls -la') #=> outputs the output of that command
exit #=> exits the program
Anyways, if you want this kind of stuff, I think it's not a bad idea to look into http://www.codecademy.com/ basically they teach you Ruby by writing small scripts such as these. However, they maybe not be completely adapted to Unix commands, but user input and the likes are certainly handled.
Edit:
As pointed out do use this at the top of your script:
#!/usr/bin/env ruby
Edit:
Example of chomp vs. chop:
full_name = "My Name is Ravikanth\r\n"
full_name.chop! # => "My Name is Ravikanth"
Now if you run chop and there are no newline characters:
puts full_name #=> "My Name is Ravikanth"
full_name.chop! #=> "My Name is Ravikant"
versus:
puts full_name #=> "My Name is Ravikanth\r\n"
full_name.chomp! #=> "My Name is Ravikanth"
full_name.chomp! #=> "My Name is Ravikanth"
See: "Ruby Chop vs Chomp"
Here's a really basic loop:
#!/user/bin/ruby
#
while true do
print "$ "
$stdout.flush
inputs = gets.strip
puts "got your input: #{inputs}"
# Check for termination, like if they type in 'exit' or whatever...
# Run "system" on inputs like 'dir' or whatever...
end
As Stefan mentioned in a comment, this is a huge topic and there are scenarios that will make this complicated. This is, as I say, a very basic example.
Adding to the two other (valid) answers posted so far be wary of using #!/usr/bin/ruby, because ruby isn't always installed there. You can use this instead:
#!/usr/bin/env ruby
Or if you want warnings:
#!/usr/bin/env ruby -w
That way, your script will work irrespective of differences where ruby might be installed on your server and your laptop.
Edit: also, be sure to look into Thor and Rake.
http://whatisthor.com
http://rake.rubyforge.org
Use irb.
I was looking into an alternative to bash and was thinking along the same lines... but ended up choosing fish: http://fishshell.com/
Nonetheless, I was thinking of using irb and going along the lines of irbtools: https://github.com/janlelis/irbtools
Example:
> irb
Welcome to IRB. You are using ruby 1.9.3p0 (2011-10-30 revision 33570) [x86_64-linux]. Have fun ;)
>> ls #=> ["bin", "share", "opt", "lib", "var", "etc", "src"]
>>
In any case, irb is the ruby shell.
Take a look at cliqr which comes with inbuilt support for build a custom shell https://github.com/anshulverma/cliqr/

Exact specification for block comment

What is the exact specification for block comments? It seems to be true that the first and the last lines have to start exactly with =begin and =end. But besides that, there is a little unclarity. Some descriptions say =begin and =end must be the only thing on the respective lines, but that does not seem to be true. Running Ruby 1.9.3 MRI, I get the following results.
Adding white space characters still seems to work:
=begin \t\t \t
This is not a Ruby command and should raise an exception if read.
=end \t\t\t \t\t\t\t
# => no problem
Furturemore, it seems that I can add an arbitrary string (not including "\n") after one or more space characters, and it is still okay:
=begin \t\t \tblah blah blah
This is not a Ruby command and should raise an exception if read.
=end \t\t\t \t\t\t\tThis is some scribble
# => no problem
I can put a line starting with =begin in the middle of a block comment:
=begin
This is not a Ruby command and should raise an exception if read.
=begin
So as this one.
=end
# => no problem
But not a line that qualifies as the last line of the comment:
=begin
This is not a Ruby command and should raise an exception if read.
=end blah blah
So as this one.
=end
# => error
Is this specification, or an implementation-dependent behavior? For clarity, can someone describe in terms of regex the exact specification of a Ruby block comment syntax?
The Ruby Programming Lanuage, page 26:
"Ruby supports another style of multiline comment known as an embedded document.(...)
Any text that appears after =begin or =end is part of the comment and is also ignored, but that extra text must be separated from the =begin and =end by at least one space.(...)
Embedded documents are usually intended by some postprocessing tool that is run over the Ruby source code, and it's typical to follow =begin with an identifier that indicates which tool the comment is intended for."
Another way of use:
=begin Please fix this!
non working code #this is a comment line
=end non working code
#=begin Please fix this!
non working code #now this line gets run
#=end non working code

One liner in Ruby for displaying a prompt, getting input, and assigning to a variable?

Often I find myself doing the following:
print "Input text: "
input = gets.strip
Is there a graceful way to do this in one line? Something like:
puts "Input text: #{input = gets.strip}"
The problem with this is that it waits for the input before displaying the prompt. Any ideas?
I think going with something like what Marc-Andre suggested is going to be the way to go, but why bring in a whole ton of code when you can just define a two line function at the top of whatever script you're going to use:
def prompt(*args)
print(*args)
gets
end
name = prompt "Input name: "
Check out highline:
require "highline/import"
input = ask "Input text: "
One liner hack sure. Graceful...well not exactly.
input = [(print 'Name: '), gets.rstrip][1]
I know this question is old, but I though I'd show what I use as my standard method for getting input.
require 'readline'
def input(prompt="", newline=false)
prompt += "\n" if newline
Readline.readline(prompt, true).squeeze(" ").strip
end
This is really nice because if the user adds weird spaces at the end or in the beginning, it'll remove those, and it keeps a history of what they entered in the past (Change the true to false to not have it do that.). And, if ARGV is not empty, then gets will try to read from a file in ARGV, instead of getting input. Plus, Readline is part of the Ruby standard library so you don't have to install any gems. Also, you can't move your cursor when using gets, but you can with Readline.
And, I know the method isn't one line, but it is when you call it
name = input "What is your name? "
Following #Bryn's lead:
def prompt(default, *args)
print(*args)
result = gets.strip
return result.empty? ? default : result
end
The problem with your proposed solution is that the string to be printed can't be built until the input is read, stripped, and assigned. You could separate each line with a semicolon:
$ ruby -e 'print "Input text: "; input=gets.strip; puts input'
Input text: foo
foo
I found the Inquirer gem by chance and I really like it, I find it way more neat and easy to use than Highline, though it lacks of input validation by its own.
Your example can be written like this
require 'inquirer'
inputs = Ask.input 'Input text'

How to add extra newline with 'puts' without sticking newline character into string?

If I say
puts "Hello"
and decide to add an extra newline I need to do this:
puts "Hello\n"
Having this character in the string is ugly. Is there any way to do this without polluting my string?
Just make another call to puts:
puts "Hello"
puts
puts "Hello",""
I often find myself adding a constant in ruby to contain these characters
NEW_LINE = "\n"
puts "Hello" + NEW_LINE
I think it is more readable and makes a change to all newline characters easy if anyone ever decides to separate each line by something else at some later date.
Do you think this looks nicer?
puts "Hello"+$/
</evil>
The reason Ruby uses "\n" for a newline is because its based on C. Ruby MRI is written in C and even JRuby is written in Java which is based on C++ which is based on C... you get the idea! So all these C-style languages use the "\n" for the new line.
You can always write your own method that acts like puts but adds new lines based upon a parameter to the method.
you can just write
p "Hello"
p
That should work as well if you want to keep it short and simple
Well, I don't think an explicit newline is ugly. mipadi's answer is just fine as well. Just to throw another answer in, make an array of the lines then join the aray with a newline. :)
What you want fixed:
input for script:
puts "Hello there"
puts "Goodbye"
Output from script:
Hello thereGoodbye
Fix for the problem:
Input for script:
puts "Hello there"
puts
puts "Goodbye"
Output from script:
Hello there
Goodbye

Resources