Gets.Chomp Without Moving to a New Line

gets.chomp without moving to a new line

You can do this by using the (very poorly documented) getch:

require 'io/console'
require 'io/wait'

loop do
chars = STDIN.getch
chars << STDIN.getch while STDIN.ready? # Process multi-char paste
break if ["\r", "\n", "\r\n"].include?(chars)
STDOUT.print chars
end

References:

  • http://ruby-doc.org/stdlib-2.1.0/libdoc/io/console/rdoc/IO.html#method-i-getch
  • http://ruby-doc.org/stdlib-2.1.0/libdoc/io/wait/rdoc/IO.html#method-i-ready-3F

Related follow-up question:

enter & IOError: byte oriented read for character buffered IO

How to use gets and gets.chomp in Ruby

gets lets the user input a line and returns it as a value to your program. This value includes the trailing line break. If you then call chomp on that value, this line break is cut off. So no, what you have there is incorrect, it should rather be:

  1. gets gets a line of text, including a line break at the end.
    • This is the user input
  2. gets returns that line of text as a string value.
  3. Calling chomp on that value removes the line break

The fact that you see the line of text on the screen is only because you entered it there in the first place. gets does not magically suppress output of things you entered.

In Ruby, how can I print my next prompt on the same line after user input?

The reason you get a new line even after chomp is because in the terminal you've already entered the carriage return key which displays the new line.

What you want can be done like this:

require "io/console"
print "Move FROM which tower? (1 / 2 / 3) "
x = STDIN.getch.to_i
print x
print "...TO which tower? (1 / 2 / 3) "
y = STDIN.getch.to_i
print "#{y}\n"
print "Result: (#{x}, #{y})"

Note this will give an output of this:

$ ruby tower.rb
Move FROM which tower? (1 / 2 / 3) 1...TO which tower? (1 / 2 / 3) 2
Result: (1, 2)

Note this only gets one character from STDIN.

Perl's Chomp: Chomp is removing the whole word instead of the newline

The reason you see only a string of 1s is that you are printing the value of $val which is the value returned from chomp. chomp doesn't return the trimmed string, it modifies its parameter in-place and returns the number of characters removed from the end. Since it always removes exactly one "\n" character you get a 1 output for each element of the array.

You really should use warnings instead of the -w command-line option, and there is no reason here to read the entire file into an array. But well done on using a lexical filehandle with the three-parameter form of open.

Here is a quick refactoring of your program that will do what you want.

#!/usr/bin/perl
use strict;
use warnings;

my $file = 'test.csv';
open my $FH, '<', $file or die qq(Unable to open "$file": $!);

while (<$FH>) {
chomp;
my @row = split /,/;
print $row[1], "\n";
}

gets.chomp three times in a row to exit

Have a look at this, I've made some changes though. But should give you the expected output.

bye_count = 0
while true
speak = gets.chomp
if speak == 'BYE'
bye_count +=1
bye_count == 3 ? break : next
end
bye_count = 0 # Resets count
if speak == speak.upcase
puts 'NO, NOT SINCE ' + (1930 + rand(20)).to_s + '!'
else
puts 'HUH?! SPEAK UP, SONNY!'
end
end

How to pass text from gets.chomp to a file

Making the assumption that there will only ever be one resources :posts in your routes file, a simple example could be done like:

require 'active_support/core_ext/string/inflections' # for `pluralize`

get = gets.chomp
lines = File.read("config/routes.rb").split(/\n/)

# find the line of the file we want to insert after. This assumes
# there will only be a single `resources :posts` in your routes.
index = lines.index { |line| line.strip == 'resources :posts' }
# duplicate the existing line and replace 'posts' with the pluralized form
# of whatever the user input to gets, we do it this way to keep indentation
new_line = lines[index].gsub(/posts/, get.pluralize)

# insert the new line on the line after the `resources :posts` and then write
# the entire thing back out to 'config/routes.rb'
lines.insert(index + 1, new_line)
File.open("config/routes.rb", "w") { |f| f.write(lines.join("\n")) }

Depending on what you're trying to do, though, you may find it useful to look into Rails Generators.

before

Rails.application.routes.draw do
resources :users do
resources :posts
end
end

execute

$ echo category | ruby example.rb

after

Rails.application.routes.draw do
resources :users do
resources :posts
resources :categories
end
end

Passing an gets.chomp as an argument

Because IO#gets reads next line from readable I/O stream(in this case it's a file) and returns a String object when reading successfully and not reached end of the file. And, chomp removes carriage return characters from String object.

So when you have a file with content such as:

This is file content.
This file has multiple lines.

The code will print:

1, This is file content.
2, This file has multiple lines.

In the second case, you're passing file object itself and not reading it. Hence you see those objects in output.



Related Topics



Leave a reply



Submit