Is it possible to intercept IRB inputs? Specifically for class#Fixnum?
Example:
5
=> 5
What I need to do is: (pseudo code)
if IRB.input.is_a?(Fixnum)
some_method(IRB.input) # some_method(5)
end
Look at this file.
You can find Irb#eval_input method and patch them:
# code before
#scanner.set_input(#context.io) do
signal_status(:IN_INPUT) do
if l = #context.io.gets
if l.match(/^\d+$/)
puts 'Integer found!'
end
print l if #context.verbose?
else
if #context.ignore_eof? and #context.io.readable_after_eof?
l = "\n"
if #context.verbose?
printf "Use \"exit\" to leave %s\n", #context.ap_name
end
else
print "\n"
end
end
l
end
end
# code after
Irb output example:
spark#think:~$ irb
2.1.5 :001 > 123
Integer found!
=> 123
2.1.5 :002 > "string"
=> "string"
Related
I thought that (in a while...do loop)
gets.chomp != ''
might match a carriage return from a terminal. It doesn't. What am I not understanding? Thank you.
String#chomp removes carriage returns from the string it is being called on.
If you remove chomp it should give you the expected output. See below:
2.1.2 :001 > def foo
2.1.2 :002?> while true do
2.1.2 :003 > puts gets != ''
2.1.2 :004?> end
2.1.2 :005?> end
=> :foo
2.1.2 :006 > foo
a
true
b
true
c
true
1
true
2
true
# about to press enter
true
true
Hope this helps
I have a file that looks like this:
[noahc:~/projects/wordsquares] master(+87/-50)* ± cat wordlist/test_word_list.txt
card
apple
joe
bird
card
dart
area
rear
birdbird
after
boat
swim
north
abbe
byes
beep
If I open up an irb session, I can do:
2.0.0p247 :001 > file = File.open('./wordlist/test_word_list.txt', 'r')
=> #<File:./wordlist/test_word_list.txt>
2.0.0p247 :002 > file.readlines
=> ["card\n", "apple\n", "joe\n", "bird\n", "card\n", "dart\n", "area\n", "rear\n", "birdbird\n", "after\n", "boat\n", "swim\n", "north\n", "abbe\n", "byes\n", "beep \n", "\n"]
But, now I have a class called WordSquareGenerator:
class WordSquareGenerator
require 'pry'
require 'pry-nav'
require './lib/word_list_builder.rb'
def initialize(n, file_location)
#size_of_square = n
#file = load_file(file_location)
#word_stem_hash = WordListBuilder.new(n, #file).word_stem_hash
#word_list = nil
end
def word_square_word_list
binding.pry
#file.each do |w|
binding.pry
#word_list ? break : solve_for_word_list([word])
end
binding.pry
end
def is_list_valid?(list)
(0..#size_of_square - 1).each do |n|
(0..#size_of_square - 2).each do |m|
return false if list[n][m] != list [m][n]
end
end
#generated_list = list unless #generated_list
end
def solve_for_word_list(word_array)
if word_array.length == 4
#word_list = word_array
elsif #word_list
else
next_words = #word_stem_hash[word_array.map{|w| w[word_array.length]}.join]
next_words.each do |word|
solve_for_word_list(word_array + [word])
end
end
end
private
def load_file(file_location)
File.open(file_location, 'r')
end
end
When I run the word_square_word_list method and hit the first binding.pry, I can do:
2.0.0 (#<WordSquareGenerator:0x007ff3f91c16b0>):0 > #file.readlines
=> []
and I get an empty array for readlines. How can it be that I'm getting two different results doing the same thing, except one is inside that class and the other isn't?
At WordListBuilder you are probably reading the file already and when the action gets back to WordSquareGenerator the file is already at it's end and there's nothing else to read. First, don't do what you're doing now, that is opening the file since this leaks the file handle (you're not closing it anywhere) and someone else reading the handle is causing your code to fail.
Here's how you could do it:
class WordSquareGenerator
require 'pry'
require 'pry-nav'
require './lib/word_list_builder.rb'
def initialize(n, file_location)
#size_of_square = n
#file_location = file_location
#word_stem_hash = WordListBuilder.new(n, file_location).word_stem_hash
#word_list = nil
end
def word_square_word_list
binding.pry
IO.foreach(#file_location) do |word|
binding.pry
#word_list ? break : solve_for_word_list([word])
end
binding.pry
end
def is_list_valid?(list)
(0..#size_of_square - 1).each do |n|
(0..#size_of_square - 2).each do |m|
return false if list[n][m] != list [m][n]
end
end
#generated_list = list unless #generated_list
end
def solve_for_word_list(word_array)
if word_array.length == 4
#word_list = word_array
elsif #word_list
else
next_words = #word_stem_hash[word_array.map{|w| w[word_array.length]}.join]
next_words.each do |word|
solve_for_word_list(word_array + [word])
end
end
end
end
And you would also need to update WordListBuilder to do the same. This also has the advantage of closing the file handle automatically for you so you don't have to care about closing it yourself.
Try running this before you read the lines:
#file.seek 0
You have probably already read the lines, and you have to seek back to the start of the file before you read them again.
Sample IRB session:
irb(main):001:0> f = File.new 'test.txt' # already existing file
=> #<File:test.txt>
irb(main):002:0> f.readlines
=> ["this", "is", "a", "test"]
irb(main):003:0> f.readlines
=> []
irb(main):004:0> f.seek 0
=> 0
irb(main):005:0> f.readlines
=> ["this", "is", "a", "test"]
You could even make it a method:
def readlines
#file.seek 0
#file.readlines
end
Also, make sure to close your file (#file.close)! You should only leave it open for as little time as possible. And you definitely should not leave it open for the whole program. If you don't want to worry about that, just store the lines in a variable instead of keeping the file:
#lines = File.open(file_location) {|f|
f.readlines
}
# you could also use the shortcut form
# #lines = File.open(file_location, &:readlines)
I'm following this tutorial to learn about creating shapes and colors on a canvas. Here is the issue I'm running into: When I try to run the command in the run_command method and I take the first letter of my command (command[0]), it is returning the number 98 to me. I am trying to match the first letter of the command to a letter of the alphabet, but am unable to do so. What's strange though, is that when I remove the first letter with "command.delete "b"", the letter is removed and I'm free to use the rest of the string as I please.
Here is my code:
require 'ruby-processing'
class ProcessArtist < Processing::App
def setup
background(0, 0, 0)
end
def draw
# Do Stuff
end
def key_pressed
if #queue.nil?
#queue = ""
end
if key != "\n"
#queue = #queue + key
else
warn "Time to run the command: #{#queue}"
run_command(#queue)
#queue = ""
end
end
def run_command(command)
puts "Running command: #{command}"
puts command[0]
if command[0] == "b"
command.delete "b"
command.split(",")
background(command[0].to_i,command[1].to_i,command[2].to_i)
else
puts command[0]
command.delete "b"
command.split(",")
background(command[0].to_i,command[1].to_i,command[2].to_i)
end
end
end
ProcessArtist.new(:width => 800, :height => 800,
:title => "ProcessArtist", :full_screen => false)
Ah, I see what I did wrong. It should have been:
def run_command(command)
puts "Running command: #{command}"
puts command[0]
if command[0] = "b"
command.delete "b"
command.split(",")
background(command[0].to_i,command[1].to_i,command[2].to_i)
else
puts command[0]
command.delete "b"
command.split(",")
background(command[0].to_i,command[1].to_i,command[2].to_i)
end
end
It seems like you're using ruby version older than 1.9.
In old version of ruby (1.8-), String#\[\] return Fixnum object representing ASCII value, not String object.
>> RUBY_VERSION
=> "1.8.7"
>> 'bcd'[0]
=> 98
To get string back, use one of followings:
>> 'bcd'[0,1]
=> "b"
>> 'bcd'[0..0]
=> "b"
>> 'bcd'[0].chr # this will not work in Ruby 1.9+, so not recommended.
=> "b"
For comparison:
>> 'bcd'[0] == 'b'
=> false
>> 'bcd'[0] == ?b
=> true
>> 'bcd'.start_with? 'b'
=> true
Found in the Ruby style guide.
1 > 2 ? true : false; puts 'Hi'
I assume this always returns Hi, but how do I read it?
If 1 > 2 then true, else it is false.
However, it will print hi whatever the condition result.
It is the same that:
if 1 > 2 then
true
else
false
end
puts 'hi'
You may read this like
1 > 2 ? true : false # first line of code
puts "Hi" #second line of code
The Ruby compiler reads it like this:
1.>( 2 )
puts "Hi"
Ternary operator ? : is redundant. Comparison 'greater than' symbol :> is actually a method of Numeric class.
If 1 is greater than 2 then true, else then false.
Then puts Hi
http://buddylindsey.com/c-vs-ruby-if-then-else/
The semicolon is an inline way of separating two lines of code. So it's just like
1 > 2 ? true : false
puts "Hi"
which is equivalent to
false
puts "Hi"
And of course a line that just says false will do nothing (except for a few cases, like if it's the last line of a function definition in which case the method returns false if it reaches that line).
1 > 2 ? true : false; puts "Hi" that means
if 1 > 2
return true
else
return false
end
puts "Hi"
Here each time means the result is whatever it will print "hi" because we print "Hi" in outside of condition.
but
if 1 > 2
puts "1 is not greater than 2"
else
puts "1 is greater than 2"
end
you can also test in your console
1.9.3p125 :002 > if 1 > 2
1.9.3p125 :003?> puts "1 is not greater than 2"
1.9.3p125 :004?> else
1.9.3p125 :005 > puts "1 is greater than 2"
1.9.3p125 :006?> end
1 is greater than 2
=> nil
I have a ruby hash which looks like
{"10.1.1.6"=>"nick", "127.0.0.1"=>"nick1"}
But I can't manage to check if a certain string is already in the Hash. I tried has_value?, getting array of values using values then using include? to check if it contains it, but always returns false, when I know that it exists. For example, I try to add "172.16.10.252"=>"nick" to the hash and I do:
class SomeClass
def initialize(*args)
super(*args)
#nicks = Hash.new
end
def serve(io)
loop do
line = io.readline
ip = io.peeraddr[3]
begin
if /NICK (.*)/ =~ line
nick = $1
if #nicks.has_value?(nick) # it fails here
puts "New nick #{$1}"
#nicks[ip] = nick.gsub("\r", "")
io.puts "Your new nick is #{nick}"
else
message = {:ERROR => "100", :INFO=>"#{nick}"}.to_json
io.puts message
end
end
rescue Exception => e
puts "Exception! #{e}-#{e.backtrace}"
end
end
end
end
On irb it works fine, but on my script it doesn't
1.9.3p125 :001 > h = {"10.1.1.6"=>"nick", "127.0.0.1"=>"nick1"}
=> {"10.1.1.6"=>"nick", "127.0.0.1"=>"nick1"}
1.9.3p125 :002 > h.has_value?('nick')
=> true
1.9.3p125 :003 > if h.has_value?('nick')
1.9.3p125 :004?> puts "yes"
1.9.3p125 :005?> else
1.9.3p125 :006 > puts "no"
1.9.3p125 :007?> end
yes
=> nil
1.9.3p125 :008 >
What I'm doing wrong?
I'm not sure if you're using "$1" the way you intend to.
In your code at this line:
if /NICK (.*)/ =~ line
nick = $1
if #nicks.has_value?(nick) # it fails here
puts "New nick #{$1}"
if line is "NICK says a bunch of things", $1 will be "says a bunch of things". So you're not really looking for the value 'nick' in your hash, but for 'says a bunch of things'.
You should check how your regex is working, I wouldn't say anything is wrong with a hash.