Using Platypus to create Mac OS X applications from a perl script - perl

Is it possible to get user input when using Platypus to build an application from a script?
I have a simple perl script. Which if I run from terminal, it asks for user input. But when I build an application file with Platypus, only the script's output is displayed.

The documentation is clear on this, no bi-directional communication; see http://www.sveinbjorn.org/files/manpages/PlatypusDocumentation.html#812
That leaves you with a few workarounds;
Use and expect script to inject your inputs;
Update your script to take arguments, which is a feature supported by platypus;
If you need to add more dynamic information, consider using a TK dialog to query for user input;
On mac you can use an osascript to call a dialog with minimum code;
OSA Script Example
#!/usr/bin/env perl
use strict;
sub osascript($) { system 'osascript', map { ('-e', $_) } split(/\n/, $_[0]); }
sub dialog {
my ($text, $default) = #_;
osascript(qq{
tell app "System Events"
text returned of (display dialog "$text" default answer "$default" buttons {"OK"} default button 1 with title "$(basename $0)")
end tell
});
}
my $result = dialog("Life, the universe and everything?", "42");

Related

Save a pdf file that's been opened in Internet Explorer with OLE and Perl

I am looking for a way to use Perl to open a PDF file in Internet Explorer and then save it.
(I want the user to be able to interact with the script and decide whether downloading occurs, which is why I want to pdf to be displayed in IE, so I cannot use something like LWP::Simple.)
As an example, this code loads (displays) a pdf, but I can't figure out how to get Perl to tell IE to save the file.
use Win32::OLE;
my $ie = Win32::OLE->new("InternetExplorer.Application");
$ie->{Visible} = 1;
Win32::OLE->WithEvents($ie);
$ie->Navigate('http://www.aeaweb.org/Annual_Meeting/pdfs/2014_Registration.pdf');
I think I might need to use the OLE method execWB, but I haven't been able to figure it out.
What you want to do is automate the Internet Explorer UI. There are many libraries out there that will do this. You tell the library to find your window of interest, and then you can send keystrokes or commands to the window (CTRL-S in your case).
A good overview on how to do this in Perl is located here.
Example syntax:
my #keys = ( "%{F}", "{RIGHT}", "E", );
for my $key (#keys) {
SendKeys( $key, $pause_between_keypress );
}
The code starts with an array containing the keypresses. Note the
format of the first three elements. The keypresses are: Alt+F, right
arrow, and E. With the application open, this navigates the menu in
order to open the editor.
Another option is to use LWP:
use LWP::Simple;
my $url = 'http://www.aeaweb.org/Annual_Meeting/pdfs/2014_Registration.pdf';
my $file = '2014_Registration.pdf';
getstore($url, $file);
ForExecWB here is good thread, however it is not solved: http://www.perlmonks.org/?node_id=477361
$IE->ExecWB($OLECMDID_SAVEAS, $OLECMDEXECOPT_DONTPROMPTUSER,
$Target);
Why don't you display the PDF in IE then close the IE and save the file using LWP?
You could use Selenium and the perl remote drivers to manage IE
http://search.cpan.org/~aivaturi/Selenium-Remote-Driver-0.15/lib/Selenium/Remote/Driver.pm
http://docs.seleniumhq.org/projects/webdriver/
You will also need to download the IE selenium driver - it comes with firefox as standard
https://code.google.com/p/selenium/wiki/InternetExplorerDriver
use Selenium::Remote::Driver;
my $driver = new Selenium::Remote::Driver;
$driver->get('http://www.google.com');
print $driver->get_title();
$driver->quit();

Convert Perl Script to VBA Script

I have a working Perl script that I would like to convert to VBA to run in an Excel macro so that it can easily be shared to other PC's. I have a shell script (where I pass the parameters) driving the perl script.
I used the Perl script to read each specified column of all rows of data from a fixed width file (below the start is 54,63) and compare that data with another file and print the difference. I'd pass parameters in the Shell script as runpro.pl filea.txt fileb.csv > myoutput.txt
Any assistance would be great! Especially if someone can point me in the right direction since the code is fairly simple. Thanks!
#!/usr/bin/perl
#Perl Script runpro.pl
#***************************************************
use strict;
use warnings;
my ($fa, $fb) = #ARGV;
#ARGV = $fa;
my %codes;
while(<>) {
s/[\r\n]+\z//;
$_ = substr($_, 54, 63);
s/\s+\z//;
next if $_ eq "";
$codes{$_} =1;
}
#ARGV = $fb;
my %descrip;
while(<>) {
s/[\r\n]+\z//;
s/,.*//;
s/"//g;
$descrip {$_} = 1 if s/^1234//;
}
for (sort keys %codes) {$
print "$_\n" unless ($descrip{$_});
}
A couple of points:
1) VBA is very different from Perl - so things that are one-liners in one will be tricky in the other
2) If you haven't used VBA in Excel, I suggest you start by "recording" a macro (first make the "Developer" tab in the ribbon visible, then select "record macro", and start doing things like opening files, importing them (fixed width). After you stop the recording you will see the syntax for doing these things - that should help a lot
3) You will have to decide how you want to pass arguments to VBA - cells on a worksheet, dialog box... There is no such thing as "running VBA from the command line".
I wonder if you really need / want VBA or if you would be better off compiling a standalone program (.exe). Is this meant to run on PC (windows), Mac OS, or both? See for example this earlier question - maybe that's what you actually need (if not what you asked for...)?

Linking pages with CGI scripts

I am trying to write a survey that displays only one question at a time, each on a separate page. I cannot figure out how to have my CGI file accomplish this, right now I have everything on one page but want my user to be able to hit a "next" button to bring them to a new question. I am trying to do this with Perl and HTML exclusively. for example:
use CGI qw(:standard); # Include standard HTML and CGI functions
use CGI::Carp qw(fatalsToBrowser); # Send error messages to browser
#
# Start by printing the content-type, the title of the web page and a heading.
#
print header, start_html("Hello"), h1("Hello");
if (param()) { # If true, the form has already been filled out.
$who = param("myname");
$cats = param("cats"); # Extract the value passed from the form.
if($cats == "Y"){
print p("Hello, your name is $who, and you like cats");
}
else{
print p("Hello, your name is $who, and you don't like cats"); # Print the name.
}
}
else { # Else, first time through so present form.
print start_form();
print p("What's your name? ", textfield("myname"));
print p("Do you like cats? Y for yes and N for no", textfield("cats"));
print p(submit("Submit form"), reset("Clear form"));
print end_form();
}
print end_html;
If I want the cats question to appear on the next page, by taking out the submit button and putting in one that functions like a next, do I have to link the button to another page or can that be achieved in one script? So in short, can you create and link multiple html pages to run a survey with just one cgi script?
Sure you can. The problem is that your script needs to know which page the user has just submitted in order to know which page to show next. However, that can be achieved easily with a hidden <input> inside your <form>s. Such hidden inputs are sent by the browser to the CGI script just as if they were regular inputs, e.g. text inputs, drop-down boxes or checkboxes.
On the server side this hidden <input>s name and value are available via the normal param() method call. The hidden input itself is created with hidden(); please read the documentation available for it.

how to use stdin on perl cgi

I am new to perl and I want to use screen input on my script. here is my script and I want the IOS command to be enter from keyboard. can some one show me where I am wrong.the problem i have now the script not read my keyboard input, I am not sure if work on my case. thanks!!
# ### Show #########################################################
$cmd = <STDIN>;
chomp ($cmd);
$show_error = "";
if ($ssh_switch eq 'yes') {
ssh_access();
}
print "\n",h2($host . ' - ' . $cmd);
#output=$cmd;
print hr(),"\n";
}
}
#########################################################################
CGI is designed to take in a complete HTTP request and then spit out a complete HTTP response.
It simply doesn't work interactively.
If you want to write a script that expects keyboard input, then don't use CGI.
In fact, CGI does uses STDIN. It is used to pass the body of POST request. Try this script
#!/usr/bin/perl
print "Content-Type: text/plain\r\n\r\nYou entered: ";
print while <STDIN>;
and POST some data to it, e.g.
$ echo "Just test" | POST http://localhost/yourscript.pl
You entered: Just test
(POST is a program from LWP CPAN distribution)
So you can direct your script with commands read from STDIN, although it is very unsecure as is!
CGI does allow input through STDIN; try CGI->new(\*STDIN).
Though it may not be how you want to enter things. Can you give an example of what your input looks like?
Ah, it looks to me like you want to either:
run your script from the command line, like: perl scriptname 'Submit=1&Devices=router1&Devices=router2' and then provide your cisco commands on STDIN (and get html output, which may be inconvenient), or
run your script in a browser, in which case you should replace the STDIN usage with an input tag for entering commands and get the commands from that named parameter
Looking again, I see you already have an input tag "search", you just aren't using it.
Try replacing <STDIN> with $cgi->param('search') and adding search to the "make sure data was input" check.

How can I screen-scrape output from telnet in Perl?

I can setup a telnet connection in Perl no problems, and have just discovered Curses, and am wondering if I can use the two together to scrape the output from the telnet session.
I can view on a row, column basis the contents of STDOUT using the simple script below:
use Curses;
my $win = new Curses;
$win->addstr(10, 10, 'foo');
$win->refresh;
my $thischar=$win->inch(10,10);
print "Char $thischar\n";
And using the below I can open a telnet connection and send \ receive commands with no problem:
use net::telnet;
my $telnet = new Net::Telnet (Timeout => 9999,);
$telnet->open($ipaddress) or die "telnet open failed\n";
$telnet->login($user,$pass);
my $output = $telnet->cmd("command string");
... But what I would really like to do is get the telnet response (which will include terminal control characters) and then search on a row \ column basis using curses. Does anyone know of a way I can connect the two together? It seems to me that curses can only operate on STDOUT
Curses does the opposite. It is a C library for optimising screen updates from a program writing to a terminal, originally designed to be used over a slow serial connection. It has no ability to scrape a layout from a sequence of control characters.
A better bet would be a terminal emulator that has an API with the ability to do this type of screen scraping. Off the top of my head I'm not sure if any Open-source terminal emulators do this, but there are certainly commercial ones available that can.
If you are interacting purely with plain-text commands and responses, you can use Expect to script that, otherwise, you can use Term::VT102, which lets you screen scrape (read specific parts of the screen, send text, handle events on scrolling, cursor movement, screen content changes, and others) applications using VT102 escape sequences for screen control (e.g., an application using the curses library).
You probably want something like Expect
use strict;
use warnings;
use Expect;
my $exp = Expect->spawn("telnet google.com 80");
$exp->expect(15, #timeout
[
qr/^Escape character.*$/,
sub {
$exp->send("GET / HTTP/1.0\n\n");
exp_continue;
}
]
);
You're looking for Term::VT102, which emulates a VT102 terminal (converting the terminal control characters back into a virtual screen state). There's an example showing how to use it with Net::Telnet in VT102/examples/telnet-usage.pl (the examples directory is inside the VT102 directory for some reason).
It's been about 7 years since I used this (the system I was automating switched to a web-based interface), but it used to work.
Or you could use the script command for this.
From the Solaris man-page:
DESCRIPTION
The script utility makes a record of everything printed
on your screen. The record is written to filename. If no file name
is given, the record is saved in the file typescript...
The script command forks and creates a
sub-shell, according to the value of
$SHELL, and records the text from this
session. The script ends when the
forked shell exits or when
Control-d is typed.
I would vote also for the Expect answer. I had to do something similar from a gui'ish application. The trick (albeit tedious) to get around the control characters was to strip all the misc characters from the returned strings. It kind of depends on how messy the screen scrape ends up being.
Here is my function from that script as an example:
# Trim out the curses crap
sub trim {
my #out = #_;
for (#out) {
s/\x1b7//g;
s/\x1b8//g;
s/\x1b//g; # remove escapes
s/\W\w\W//g;
s/\[\d\d\;\d\dH//g; #
s/\[\?25h//g;
s/\[\?25l//g;
s/\[\dm//g;
s/qq//g;
s/Recall//g;
s/\357//g;
s/[^0-9:a-zA-Z-\s,\"]/ /g;
s/\s+/ /g; # Extra spaces
}
return wantarray ? #out : $out[0];
}