Ruby Inputs - Weird? - ruby

I'm a bit confused with the input's of Ruby.
Whenever I try to get input, it doesn't register the 'Backspace' key. Also, it never accepts the 'Enter' first time. I always have to push 'Enter' after my input usually 3 times before it actually inputs it.
For example,
view source
print?
1 my_var = gets.chomp
If I wanted to enter 'Hello', I would have to type it followed by pressing the return key 3 times before it actually entered it.
Now I did find a way to solve this using...
view source
print?
1 STDOUT.flush
2 my_var = gets.chomp
But...
1) This seems wierd having to enter that EVERY time before I want input?
2) It still doesn't solve the problem of registering backspace.
If I was to type directly 'Hello World' but with two accidental keystrokes such as this: Hello Worpold
Even if I used the backspace so it appeared as I was entering: Hello World
If I then went on to 'puts' or 'print' that it would output: Hello Worpold
Know how I can fix it so it accepts backspace and know any other ways of missing out STDOUT.flush?
Thanks in advance

Use the readline module.

What environment are you running Ruby in ? If you're unsure, check with ruby -v
>ruby -v
ruby 1.8.6 (2008-08-11 patchlevel 287) [i386-mswin32]
I'm running v1.8.6 on Windows XP
a = gets
puts "I just got #{a}"
Saved the above snippet to c:\temp.rb and run it with ruby c:\temp.rb
Backspace key works, I can correct strings before pressing enter once to confirm my input.

Related

Start Command Prompt with Ruby doesn't work

I can't get this to work with the Start Command Prompt with Ruby on windows.
I got this simple programm:
puts "Whats your name?"
name = gets
puts "Hello" + name + ". How are you?"
But if I call it with "ruby program.rb", instead for waiting for my input, it just prints out:
Whats your name?
Helloputs "Whats your name?"
. How are you?
It is like the "gets" command is not been recognized. Why does this happen?
It looks like you are (somehow) passing the name of your programm two times on the command line. Your described behavior is reproducible when you are running
ruby program.rb program.rb
This works the way it does since gets does not read from STDIN in all cases. Instead, it prefers to read the files mentioned on the command line first. Only if there is no additional file on the command line, gets falls back to read from STDIN
The question on why you are passing the filename of your ruby program twi times is unfortunately less clear. If you are not calling it that way on your own, this might be caused by some strange environment options in your shell or due to your Ruby setup.
I was curious as well, and found this link How does gets and gets.chomp in ruby work?
Apparently it created a new line therefore could not find the name.
This seemed to work, (following the instructions in the link)
puts "Whats your name?"
name = gets
puts "Hello " + name.chomp + ". How are you?"
Have fun.
Also if you start using rails, you can also test in your console
Example
> def test1
> ...code ..
> end
> test1
#Ray Ban I have used your code
puts "Whats your name?"
name = gets
puts "Hello" + name + ". How are you?"
in gets.rb file and run it using $ ruby gets.rb and it worked as expected.
I am using ruby-2.3.0

why Ruby String each_char method prints an extra % at the end

I'm a Ruby newbie, I tried to print each char in a Ruby string, using
"hello world".each_char {|c| print c}
However, when I ran the .rb program, it printed out hello world%, with a % character at the end. Then I switched to irb, it worked fined without the extra % character. Can anyone tell me how this happened? Why there was a %?
the program is doing what is expected.
the % is actually the shell prompt.
guessing you do something like:
%my-script.rb
hello world%
because you don't have a new line, when the output finishes the script just takes control back and shows the prompt

Why might interactive ruby stop showing results?

I was just playing around with interactive ruby.
Near the beginning (line 138), I did
. irb(main):138:0> ['rock','paper','scissors'].index('paper')
=> 1
And that above worked
Then I tried a bunch of lines 139-147 experimenting to get more used to the language
Then I wasn't getting results and I tried some even simpler things I expected would work, 148-154 and didn't get any result.
So it looks like at some point one of my commands might've stopped it from displaying results though i'm not sure what.
I'd like to get it to display the results again. I suppose I could try to exit and go back in but i'd rather a way without doing that,
. irb(main):138:0> ['rock','paper','scissors'].index('paper')
=> 1
irb(main):139:0> a=[1,2,3
irb(main):140:1> a
irb(main):141:1> a=[1.2.3]
irb(main):142:1> a[0]
irb(main):143:1> a(0)
irb(main):144:1> a=[1,2,3]
irb(main):145:1> a(1)
irb(main):146:1> puts a(1)
irb(main):147:1> puts a[1]
irb(main):148:1> a
irb(main):149:1> a=[1,2,3]
irb(main):150:1> a
irb(main):151:1> h={4=>4}
irb(main):152:1> h
irb(main):153:1> puts 6
irb(main):154:1>
If it makes any difference this is my version number and OS is Windows.
C:\blah>ruby -v
ruby 2.1.6p336 (2015-04-13 revision 50298) [i386-mingw32]
C:\blah>
Because of this line here:
irb(main):139:0> a=[1,2,3
You haven't closed off the array with a closing ]. the :1 in irb(main):154:1> makes it clear you're inside a nested expression.
If you enter another ], you'll get a big syntax error because all of what you've entered before it isn't valid array syntax, but then you can move on.
Notice that since late 2019, assignment does not output any more the value in irb.
This is a new case where Interactive Ruby (irb) stop showing result.
NB : you can get the old behavior by setting IRB.conf[:ECHO_ON_ASSIGNMENT] = true in your ~/.irbrc.

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/

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'

Resources