Connecting Shoes GUI to existing Ruby code - ruby

I built a command line game in Ruby and now I'm trying to build a GUI for the game using Shoes. I spent the morning reading about Shoes, looking at some code samples, and writing a bit of code myself. It appears (I'm new to Shoes, so this could be totally wrong) that the Shoes code (for example, a shoes.rb file that you open with the Shoes application) has to contain all the Ruby code you want to run. All of the Ruby code will exist within that file.
The way I'm firing up this game is at the command line by passing command line arguments to play.rb (a Ruby script). Either run play.rb "command line game" or play.rb "shoes game" at the command line. If you run the latter, it will make a system call to open shoes.rb with the Shoes application. Within play.rb it will pass ShoesInterface to the players, rather than CommandLineInterface. Below is an example of how a player might be asked for a move:
In the human_player.rb file:
def make_move
#interface.print("It's your turn to make a move.")
end
#interface will either be CommandLineInterface or ShoesInterface. The print method in CommandLineInterface is simply a puts statement. The print method in ShoesInterface should tell the Shoes GUI to display that text. I'm trying to re-use as much of my code as possible. Theoretically, regardless of how someone is playing the game (on the web, at the command line, through a GUI, etc.) it should use most of the same logic. The interfaces simply display messages and receive user input. They just do it in different ways.
The problem is that I don't know how to connect my Shoes GUI to my existing Ruby code. Is anyone here proficient in Shoes? This might not be possible in Shoes...maybe I'll have to use a different Ruby GUI, but I thought I'd ask before moving on to another one.

What you can do, is to write a Shoes Widget that will respond to method print. Below is a very crude example of such a widget which will append a message from the edit line to its arbitrary display slot. Of course you can easily modify the Widget so that you can initialize it with a target slot for display etc but the idea stays the same.
class Prompt < Shoes::Widget
def initialize opts={}
#top=opts[:top]
#left=opts[:left]
#width=opts[:width]
#prom=flow :top=>#top, :left=>#left, :width=>#width do
background red
end
end
def print(msg)
#prom.append do
para msg
end
end
end
Shoes.app :title => "Test" do
#el=edit_line
button "print"do
#interface.print(#el.text)
end
#interface=prompt({:top=>50, :left=>20, :width=>100})
end
I hope that is what yo wanted.

Related

Simplify Move and Maximise screen using Selenium (Ruby)

I am running my selenium tests using a ruby Framework having recently joined a new company. As I am working on 3 screens I have added in a browser step to move the browser window to my left most screen before maximising using
#driver.manage.window.move_to(-1800, 1500)
#driver.manage.window.maximize
My question very simply is, having never used Ruby before, is there a way to refactor these 2 lines into 1 I have tried various ways but always get an error.
It's not possible in this place because both are returning string object so you can't cascade the calling like
#driver.manage.window.move_to(-1800, 1500).maximize
But If it's very important for you, then I will tell you a way to do this, open the window.rb file where you can return the self from move_to function as shown below
def move_to(x, y)
#bridge.reposition_window Integer(x), Integer(y)
self
end
And then you can make a call like this
#driver.manage.window.move_to(-1800, 1500).maximize

Gets stops processing script if it encounters a apostrophe

I'm futzing with a lesson over on Codecademy, pretty basic but the lesson prompts the user for a string and then prompts them for words to hide from the string. I've already finished with the lesson but I wanted to try messing with it outside of the lesson.
What I'm finding is the following script will run to completion in the lesson's scripting and interpreter area but if I try to run the same script over at say labs.codecademy.com or repl.it
I'll get prompted for the first question and if I enter a string containing an apostrophe it won't go on to the next prompt. I'm not getting an error, but eventually I'll get a "This program is taking too long to finish" pop up.
Here's the script:
puts "Tell me something."
text = gets.chomp
puts "What would you like me to forget?"
redact = gets.chomp
words = text.split(" ")
words.each { |text|
if redact.include? text
print "REDACTED "
else
print text + " "
end
}
So for example if you were to enter I really like blueberry pie that passes, but if you were to enter They've told me I should try the blueberry pie the program gets hung up.
I'm a complete novice when it comes to Ruby, but is there a way to have gets process that sort of punctuation? Or is that not the right way to go about it? Or is it just the environment I'm trying to run this program in?
IO.gets is a system-level call: http://apidock.com/ruby/IO/gets
it well read from STDIN (standard input) which is the text that you type in a terminal window: http://en.wikipedia.org/wiki/Standard_streams
browsers per-se don't have this and it might depend on the implementation of the web-based console about how they handle calls like that. usually, there are known limitations (like this one).
as #BroiStatse pointed out, it might as well be a bug in in their browser-based implementation.

What is the best way to get keyboard events (input without press 'enter') in a Ruby console application?

I've been looking for this answer in the internet for a while and have found other people asking the same thing, even here. So this post will be a presentation of my case and a response to the "solutions" that I have found.
I am such new in Ruby, but for learning purposes I decided to create a gem, here.
I am trying to implement a keyboard navigation to this program, that will allow the user use short-cuts to select what kind of request he want to see. And in the future, arrow navigations, etc.
My problem: I can't find a consistent way to get the keyboard events from the user's console with Ruby.
Solutions that I have tried:
Highline gem: Seems do not support this feature anymore. Anyway it uses the STDIN, keep reading.
STDIN.getch: I need to run it in a parallel loop, because at the same time that the user can use a short-cut, more data can be created and the program needs to show it. And well, I display formated text in the console, (Rails log). When this loop is running, my text lost the all the format.
Curses: Cool but I need to set position(x,y) to display my text every time? It will get confusing.
Here is where I am trying to do it.
You may note that I am using "stty -raw echo" (turns raw off) before show my text and "stty raw -echo" (turns raw on) after. That keeps my text formated.
But my key listener loop is not working. I mean, It works in sometimes but is not consistent. If a press a key twice it don't work anymore and sometimes it stops alone too.
Let me put one part of the code here:
def run
# Two loops run in parallel using Threads.
# stream_log loops like a normal stream in the file, but it also parser the text.
# break it into requests and store in #requests_queue.
# stream_parsed_log stream inside the #requests_queue and shows it in the screen.
#requests_queue = Queue.new
#all_requests = Array.new
# It's not working yet.
Thread.new { listen_keyboard }
Thread.new { stream_log }
stream_parsed_log
end
def listen_keyboard
# not finished
loop do
char = STDIN.getch
case char
when 'q'
puts "Exiting."
exit
when 'a'
#types_to_show = ['GET', 'POST', 'PUT', 'DELETE', 'ASSET']
requests_to_show = filter_to_show(#all_requests)
command = true
when 'p'
#types_to_show = ['POST']
requests_to_show = filter_to_show(#all_requests)
command = true
end
clear_screen if command
#requests_queue += requests_to_show if command
command = false
end
end
I need a light in my path, what should I do?
That one was my mistake.
It's just a logic error in another part of code that was running in another thread so the ruby don't shows the error by default. I used ruby -d and realized what was wrong. This mistake was messing my keyboard input.
So now it's fixed and I am using STDIN.getch with no problem.
I just turn the raw mode off before show any string. And everything is ok.
You can check here, or in the gem itself.
That's it.

Need to get information from Qt4ruby Form's textedit(textbox) and pass back to string for console

I think this problem is best described in code. I'm sure the solution is close, I just haven't been able to find it. I've been looking over the Qt4 api as well as doing tutorials. Here is my code so far:
require 'Qt4'
class PictureCommentForm < Qt::Widget
def initialize(parent = nil)
super()
#setFixedSize(300, 100)
#comment_text = nil
picture = Qt::Label.new()
image = Qt::Image.new('image.jpeg')
picture.pixmap = image
comment = Qt::LineEdit.new()
layout = Qt::VBoxLayout.new()
layout.addWidget(picture)
layout.addWidget(comment)
setLayout(layout)
connect(comment, SIGNAL('returnPressed()'), self, setCommentText(comment.text) )
end
def setCommentText(text)
#comment_text = text
$qApp.quit()
end
end
app = Qt::Application.new(ARGV)
comment_form = PictureCommentForm.new()
comment_form.show()
app.exec
comment_text = comment_form.comment_text
puts "Comment was:\n #{comment_text}"
EDIT: Thanks for that answer integer. All I want done is a dialog box showing a picture and comment so I can get that data. I do plan on making a full GUI version with qt4, but that's for later.
I don't know Ruby, so bear with me, but I use Qt extensively in Python.
First point is that Qt really, really doesn't want to be used the way you're trying to use it. If you're making some sort of script, then Qt wants you to give it to Qt so it can run your code when it feels like:
We recommend that you connect clean-up
code to the aboutToQuit() signal,
instead of putting it in your
application's main() function because
on some platforms the
QCoreApplication::exec() call may not
return.
Working with Qt you pretty much have to do event-driven programming and give it control of your program flow / main loop.
If you really just want some "utility" that shows some GUI input box and prints whatever the user inputs to console, consider putting the puts directly in whatever function you connected to the text box. Then you can use that program's output in other console scripts.

How can I programatically call the ruby debugger from within a ruby program in Ruby 1.9?

I am writing a web based debugger for Ruby, but in order to do this I need to be able to call the Ruby debugger from within a Ruby program on the server side. Has this ever been done? Is this even possible?
The end product being built will allow Ruby code to be edited, executed and stepped through using just a web browser. The ruby code that is to be debugged will be "eval"ed on the server side.
I have since been pointed in the right direction by one of the stackoverflow users who has suggested using popen or expect. I have tried both of these now but have encountered the following problems:
popen: When waiting for the console you have to use a timeout block to signal the end of the debug console's output (The command line terminal can detect this, so why can't ruby).
expect: In the program below the debugger inputs get out of sync with the debugger. Why is that?
require 'pty'
require 'expect'
$expect_verbose = true
PTY.spawn("rdebug deb.rb") do |from_debugger, to_debugger, pid|
a=nil
while ( a != "end" ) do
from_debugger.expect(/\(rdb:1\)/ ) do |input|
a = gets
to_debugger.puts( a + "\n" )
end
from_debugger.flush
end
end
I think you could make use of ruby-debug. I would imagine this as opening the same script on the server-side, and sending keystrokes to it. I think this is how I'd do it.
Think about it this way: the client pastes his code in your form. Optionally, he may click on some button that places a breakpoint on some line. Then he submits the whole thing. On server side, you process that form, and create a .rb file with the contents of the form. At the line where he put the breakpoint, you insert a debugger call. Then you run :
ruby client_script.rb
and this will stop the process once it reaches the debugger line. I would suggest you do all of this with Expect for Ruby or whatever. So, when the client presses step over on the page or inspect whatever variable, you send keystrokes to the process you spawned.
For example, if he wants to inspect the value of the variable x, you'd send this to the process:
p x
and you'd have to capture that output and send it back to the client's browser. Expect is kind of like popen , but a bit better.
I finally figured out how to do this using expect:
require 'pty'
require 'expect'
PTY.spawn("rdebug deb.rb") do |output,input,pid|
while true do
begin
buffer = ""
puts "-------"
puts output.readpartial(1024,buffer) until buffer =~ /\(rdb:1\)/
a = gets
input.puts a
rescue
break
end
end
end

Resources