[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Problem getting user input

Peter Vanderhaden

11/23/2007 12:40:00 PM

I wrote a script that gets user input like this:

$stdout.print "Do you want to change something else? (y/n): "
$changeSE = gets.chomp
if $changeSE =~ /^y/
changeSomethingElse
end

After the prompt is printed, the script waits for the user to enter yes
or no via stdinput. The script was written in a procedural format as
opposed to OO. (I did that only because I'm in the process of learning
OO, and needed the script asap.) I decided to rewrite the script using
OO. Unfortunately, this part of the script doesn't work anymore. The
prompt prints, then the script keeps going on its merry way. I've
included the source for the script below. Can anyone (or everyone) see
what I'm not doing correctly? If so, I'd appreciate it if you could
explain how to correct the problem. I'd be extremely grateful for any
and all comments and assistance.
PV

1 #!/usr/bin/ruby
2 #
3 # fix1.rb - Fix common unitization file errors.
4 # 1. Remove header line.
5 # 2. Populate vendor label field with "NULL".
6 # 3. Change .TIF extension to lower case.
7 #
8 class Record
9
10 # Constructor.
11 def initialize (record_string)
12 @record = record_string
13 end
14
15 # Populates the volume label.
16 # regex: Start at the beginning of the line, match
17 # all non-comma characters, followed by 2 commas.
18 def fix_volume_label
19 # @record.sub!(/\d,,/,',NULL,')
20 @record.sub!(/^([^,]*),,/, '\1,NULL,')
21 end
22
23 # Change file extension to lowercase.
24 def fix_extension_case
25 @record.sub!('.TIF','.tif')
26 end
27
28 # Allow user to do a generic fix.
29 def changeSomethingElse
30 @record.sub!(before,after)
31 end
32
33 # Returns fixed record as a string
34 def to_str
35 @record
36 end
37
38 end
39
40 # Main thread of execution.
41 class FixOpt
42
43 def initialize
44
45 @ARGV = $* # list of arguments passed to the
script
46 @header_regex = /BegBates,Volume,Path/
47
48 @in_file = nil
49 # @out_file = nil
50 unless arguments_valid? @ARGV
51 usage
52 exit -1
53 end
54
55 # Does user want to change something else?
56 def checkChange
57 puts "Do you want to change something else (y/N): "
58 changeIt = gets
59 if changeIt =~ /^[yY]/
60 puts "Enter string to change: "
61 before = gets.chomp
62 puts "Enter new string: "
63 after = gets.chomp
64 puts "Global change? (N/y): "
65 global = gets.chomp
66 end
67 end # End checkChange method.
68
69 begin
70 @in_file = File.new @ARGV[0], "r"
71 rescue IOError
72 @in_file.close
73 puts "Error opening input file, terminating"
74 exit -1
75 end
76
77 end # End initialize method.
78
79 # Runs the program - the [C]ontroller portion of the MVC pattern.
80 def run
81 begin
82 checkChange
83 @in_file.each do |record_line|
84 next if record_line =~ @header_regex
85 record = Record.new(record_line)
86 record.fix_volume_label
87 record.fix_extension_case
88 if changeIt =~ /^[yY]/
89 record.changeSomethingElse
90 end
91 puts record.to_str
92 end
93 rescue IOError
94 @in_file.close
95 puts "Error reading from input file, terminating"
96 exit -1
97 end
98 @in_file.close
99 exit 0 # success!
100 end
101
102 # these methods are marked :private becuase they are never to be
called
103 # from anywhere outside of the class itself.
104 :private
105
106 # Validates command line arguments.
107 def arguments_valid? (argv)
108 # readable assumes the file exists, but doesn't check for it.
109 # File.stat(ARGV[0]).readable?
110 # Returns true if the named file exists and is a regular file.
111 File.file?(ARGV[0])
112 end
113
114 # Prints the usage message
115 def usage
116 puts
117 puts "Invalid filename entered: #{ARGV[0]}"
118 puts "Syntax: fix1.rb <filename>"
119 puts
120 end
121
122 end
123 fix_opt = FixOpt.new
124 fix_opt.run

If I use gets, the script just prints the prompt and seems to end.
If I use gets.chomp I get the following error:
$ ruby d:/scripts/ruby/fix1.rb 99999.opt
Do you want to change something else (y/N):
d:/scripts/ruby/fix1.rb:58:in `checkChange': private method `chomp'
called for nil:NilClass (NoMethodEr
ror)
from d:/scripts/ruby/fix1.rb:82:in `run'
from d:/scripts/ruby/fix1.rb:124
--
Posted via http://www.ruby-....

5 Answers

Morton Goldberg

11/23/2007 5:09:00 PM

0

On Nov 23, 2007, at 7:40 AM, Peter Vanderhaden wrote:

> I wrote a script that gets user input like this:
>
> $stdout.print "Do you want to change something else? (y/n): "
> $changeSE = gets.chomp
> if $changeSE =~ /^y/
> changeSomethingElse
> end
>
> After the prompt is printed, the script waits for the user to enter
> yes
> or no via stdinput. The script was written in a procedural format as
> opposed to OO. (I did that only because I'm in the process of
> learning
> OO, and needed the script asap.) I decided to rewrite the script
> using
> OO. Unfortunately, this part of the script doesn't work anymore. The
> prompt prints, then the script keeps going on its merry way. I've
> included the source for the script below. Can anyone (or everyone)
> see
> what I'm not doing correctly? If so, I'd appreciate it if you could
> explain how to correct the problem. I'd be extremely grateful for any
> and all comments and assistance.
> PV
>
> 1 #!/usr/bin/ruby
> 2 #
> 3 # fix1.rb - Fix common unitization file errors.
> 4 # 1. Remove header line.
> 5 # 2. Populate vendor label field with "NULL".
> 6 # 3. Change .TIF extension to lower case.
> 7 #
> 8 class Record
> 9
> 10 # Constructor.
> 11 def initialize (record_string)
> 12 @record = record_string
> 13 end
> 14
> 15 # Populates the volume label.
> 16 # regex: Start at the beginning of the line, match
> 17 # all non-comma characters, followed by 2 commas.
> 18 def fix_volume_label
> 19 # @record.sub!(/\d,,/,',NULL,')
> 20 @record.sub!(/^([^,]*),,/, '\1,NULL,')
> 21 end
> 22
> 23 # Change file extension to lowercase.
> 24 def fix_extension_case
> 25 @record.sub!('.TIF','.tif')
> 26 end
> 27
> 28 # Allow user to do a generic fix.
> 29 def changeSomethingElse
> 30 @record.sub!(before,after)
> 31 end
> 32
> 33 # Returns fixed record as a string
> 34 def to_str
> 35 @record
> 36 end
> 37
> 38 end
> 39
> 40 # Main thread of execution.
> 41 class FixOpt
> 42
> 43 def initialize
> 44
> 45 @ARGV = $* # list of arguments passed to the
> script
> 46 @header_regex = /BegBates,Volume,Path/
> 47
> 48 @in_file = nil
> 49 # @out_file = nil
> 50 unless arguments_valid? @ARGV
> 51 usage
> 52 exit -1
> 53 end
> 54
> 55 # Does user want to change something else?
> 56 def checkChange
> 57 puts "Do you want to change something else (y/N): "
> 58 changeIt = gets
> 59 if changeIt =~ /^[yY]/
> 60 puts "Enter string to change: "
> 61 before = gets.chomp
> 62 puts "Enter new string: "
> 63 after = gets.chomp
> 64 puts "Global change? (N/y): "
> 65 global = gets.chomp
> 66 end
> 67 end # End checkChange method.
> 68
> 69 begin
> 70 @in_file = File.new @ARGV[0], "r"
> 71 rescue IOError
> 72 @in_file.close
> 73 puts "Error opening input file, terminating"
> 74 exit -1
> 75 end
> 76
> 77 end # End initialize method.
> 78
> 79 # Runs the program - the [C]ontroller portion of the MVC pattern.
> 80 def run
> 81 begin
> 82 checkChange
> 83 @in_file.each do |record_line|
> 84 next if record_line =~ @header_regex
> 85 record = Record.new(record_line)
> 86 record.fix_volume_label
> 87 record.fix_extension_case
> 88 if changeIt =~ /^[yY]/
> 89 record.changeSomethingElse
> 90 end
> 91 puts record.to_str
> 92 end
> 93 rescue IOError
> 94 @in_file.close
> 95 puts "Error reading from input file, terminating"
> 96 exit -1
> 97 end
> 98 @in_file.close
> 99 exit 0 # success!
> 100 end
> 101
> 102 # these methods are marked :private becuase they are never
> to be
> called
> 103 # from anywhere outside of the class itself.
> 104 :private
> 105
> 106 # Validates command line arguments.
> 107 def arguments_valid? (argv)
> 108 # readable assumes the file exists, but doesn't check for it.
> 109 # File.stat(ARGV[0]).readable?
> 110 # Returns true if the named file exists and is a regular file.
> 111 File.file?(ARGV[0])
> 112 end
> 113
> 114 # Prints the usage message
> 115 def usage
> 116 puts
> 117 puts "Invalid filename entered: #{ARGV[0]}"
> 118 puts "Syntax: fix1.rb <filename>"
> 119 puts
> 120 end
> 121
> 122 end
> 123 fix_opt = FixOpt.new
> 124 fix_opt.run
>
> If I use gets, the script just prints the prompt and seems to end.
> If I use gets.chomp I get the following error:
> $ ruby d:/scripts/ruby/fix1.rb 99999.opt
> Do you want to change something else (y/N):
> d:/scripts/ruby/fix1.rb:58:in `checkChange': private method `chomp'
> called for nil:NilClass (NoMethodEr
> ror)
> from d:/scripts/ruby/fix1.rb:82:in `run'
> from d:/scripts/ruby/fix1.rb:124

I can not reproduce your problem. When I run

<code>
class Foo
def checkChange
puts "Do you want to change something else (y/N): "
changeIt = gets.chomp
if changeIt =~ /^[yY]/
puts "Enter string to change: "
before = gets.chomp
puts "Enter new string: "
after = gets.chomp
puts "Global change? (N/y): "
global = gets.chomp
end
p [changeIt, before, after, global]
end
end
Foo.new.checkChange
</code>

I see the following

<result>
Do you want to change something else (y/N):
Enter string to change:
Enter new string:
Global change? (N/y):
["y", "foo", "bar", "n"]
</result>

I will note the variables changeIt, before, after, and global are
local variables and will not available outside of the checkChange
method. That may be part of your problem.

Regards, Morton

Sebastian Hungerecker

11/23/2007 5:28:00 PM

0

Peter Vanderhaden wrote:
> If I use gets, the script just prints the prompt and seems to end.

I see in your script that ARGV is not empty. That means Kernel#gets is
gonna read from the files in ARGV and not from stdin. To rectify that
use $stdin.gets instead. Or empty ARGV before you call gets.


HTH,
Sebastian
--
NP: In Flames - Artifacts Of The Black Rain
Jabber: sepp2k@jabber.org
ICQ: 205544826

Peter Vanderhaden

11/23/2007 6:45:00 PM

0

Sebastian,
THANK YOU, THANK YOU, THANK YOU!
The $stdin.gets works perfectly! I really appreciate all you
experienced folks helping out this newbie! I'm going to hilight this
stuff in PickAxe when I get done.
PV

Sebastian Hungerecker wrote:
> Peter Vanderhaden wrote:
>> If I use gets, the script just prints the prompt and seems to end.
>
> I see in your script that ARGV is not empty. That means Kernel#gets is
> gonna read from the files in ARGV and not from stdin. To rectify that
> use $stdin.gets instead. Or empty ARGV before you call gets.
>
>
> HTH,
> Sebastian

--
Posted via http://www.ruby-....

Morton Goldberg

11/23/2007 9:36:00 PM

0

On Nov 23, 2007, at 1:44 PM, Peter Vanderhaden wrote:

> Sebastian,
> THANK YOU, THANK YOU, THANK YOU!
> The $stdin.gets works perfectly! I really appreciate all you
> experienced folks helping out this newbie! I'm going to hilight this
> stuff in PickAxe when I get done.
> PV
>
> Sebastian Hungerecker wrote:
>> Peter Vanderhaden wrote:
>>> If I use gets, the script just prints the prompt and seems to end.
>>
>> I see in your script that ARGV is not empty. That means
>> Kernel#gets is
>> gonna read from the files in ARGV and not from stdin. To rectify that
>> use $stdin.gets instead. Or empty ARGV before you call gets.

Speaking of ARGV, you don't need this line in your code:

45 @ARGV = $* # list of arguments passed to the script

Just use the pre-defined ARGV instead of @ARGV

Regards, Morton

Jeremy Hinegardner

11/25/2007 8:12:00 AM

0

If you do write many scripts that require prompting for user input, you
should check out highline http://highline.ruby...

enjoy,

-jeremy

On Sat, Nov 24, 2007 at 03:44:59AM +0900, Peter Vanderhaden wrote:
> Sebastian,
> THANK YOU, THANK YOU, THANK YOU!
> The $stdin.gets works perfectly! I really appreciate all you
> experienced folks helping out this newbie! I'm going to hilight this
> stuff in PickAxe when I get done.
> PV
>
> Sebastian Hungerecker wrote:
> > Peter Vanderhaden wrote:
> >> If I use gets, the script just prints the prompt and seems to end.
> >
> > I see in your script that ARGV is not empty. That means Kernel#gets is
> > gonna read from the files in ARGV and not from stdin. To rectify that
> > use $stdin.gets instead. Or empty ARGV before you call gets.
> >
> >
> > HTH,
> > Sebastian
>
> --
> Posted via http://www.ruby-....
>

--
========================================================================
Jeremy Hinegardner jeremy@hinegardner.org