old-www/LDP/LG/issue64/evans.html

430 lines
20 KiB
HTML
Raw Permalink Blame History

<!--startcut ==============================================-->
<!-- *** BEGIN HTML header *** -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML><HEAD>
<title>Kaptain - A Dialog Creator LG #64</title>
</HEAD>
<BODY BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#0000AF"
ALINK="#FF0000">
<!-- *** END HTML header *** -->
<CENTER>
<A HREF="http://www.linuxgazette.com/">
<H1><IMG ALT="LINUX GAZETTE" SRC="../gx/lglogo.png"
WIDTH="600" HEIGHT="124" border="0"></H1></A>
<!-- *** BEGIN navbar *** -->
<IMG ALT="" SRC="../gx/navbar/left.jpg" WIDTH="14" HEIGHT="45" BORDER="0" ALIGN="bottom"><A HREF="dellomodarme.html"><IMG ALT="[ Prev ]" SRC="../gx/navbar/prev.jpg" WIDTH="16" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="index.html"><IMG ALT="[ Table of Contents ]" SRC="../gx/navbar/toc.jpg" WIDTH="220" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><A HREF="../index.html"><IMG ALT="[ Front Page ]" SRC="../gx/navbar/frontpage.jpg" WIDTH="137" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="http://www.linuxgazette.com/cgi-bin/talkback/all.py?site=LG&article=http://www.linuxgazette.com/issue64/evans.html"><IMG ALT="[ Talkback ]" SRC="../gx/navbar/talkback.jpg" WIDTH="121" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><A HREF="../faq/index.html"><IMG ALT="[ FAQ ]" SRC="./../gx/navbar/faq.jpg"WIDTH="62" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="fevola.html"><IMG ALT="[ Next ]" SRC="../gx/navbar/next.jpg" WIDTH="15" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><IMG ALT="" SRC="../gx/navbar/right.jpg" WIDTH="15" HEIGHT="45" ALIGN="bottom">
<!-- *** END navbar *** -->
<P>
</CENTER>
<!--endcut ============================================================-->
<H4 ALIGN="center">
"Linux Gazette...<I>making Linux just a little more fun!</I>"
</H4>
<P> <HR> <P>
<!--===================================================================-->
<center>
<H1><font color="maroon">Kaptain - A Dialog Creator</font></H1>
<H4>By <a href="mailto:pevans@catholic.org">Paul Evans</a></H4>
</center>
<P> <HR> <P>
<!-- END header -->
<p>
<i>``What Linux really needs ...''</i> is the beginning of an oft written statement which nearly as often ends with
<i>``graphical front-ends for legacy console apps.'' </i> To quote a certain magazine
editor: <i>``Of course, what Linux needs are not just dialogs, but dialogs that
optionally show you the command-line options they generate, so you can get used
to which options do what.''</i> I add that it would also be nice if the dialogs
were easy to write, so more people would bother to create them.
</p>
<h2>What Kaptain can do for you</h2>
<p>
<a href="http://kaptain.sourceforge.net" name="Kaptain">Kaptain</a>
has the ability to display mixed widget types in a modern looking dialog which
is created from a text file. The program can take care of most of the layout and
widget types for you. You can even write tabbed and child dialogs. And, importantly,
it can echo it's output to the command line for learning purposes (or the sheer delight of experimenting :-) ).
It also has tooltips and WhatsThis to aid in this regard. You could even use it as part of a pipe and have it written on the fly!
</p>
<p>
Linux is chock-full of powerful command line goodies like <b>enscript</b> and <b>mpage</b>, but, even if
you were a member of their frequent-flyer program, you'd never be able to remember all the
switches and options included with them. <b>Kaptain</b> is perfect for this sort of thing: lots of spinners,
check-boxes and combos etc. Then there are those file conversion chores. I have
constructed many, er, <i>interesting</i> looking pipelines to convert image, sound and text formats. The
latter do surrender to a little bash function - as long as you don't need to change any options for any of the commands.
By the time you write enough shell script to handle all the options... you need to write a man page for your shell script.
</p>
<a href="misc/evans/enscript1.gif"><img src="misc/evans/enscript1_thumbnail.jpg" width="250" height="248" vspace="10" hspace="10" alt="pic of a tabbed dialog for enscript" align="right"></a>
<br>
<p>
I wouldn't be writing this if <a
href="http://kaptain.sourceforge.net" name="kaptain">Kaptain</a>
couldn't do all of that, but I'd be lying if I said that it looked easy to <i>me</i>
right away. I'd like to re-stress the "me" in the preceding sentence: I'd never
written in anything object oriented before. If you've done any at all, I'm
sure <b>Kaptain</b> will be a cake-walk for you. And, if you haven't, don't
fret. I'm living proof that you'll be writing scripts for <b>Kaptain</b>
without stressing yourself overmuch.
</p>
<p>
If you're already handy with the OO approach, I suggest you just download the
thing and dive in - you'll love it. In fact, it isn't OO in the usual meaning. The author <i>``got the idea from Formal Language Theory (Maths),
where grammars generating text are mathematical objects. So the words terminal, nonterminal are well known in FLT, but nowhere else.
For those who have learnt such things, it's good to see something they are familiar with, for others these are just some new words.
BTW, YACC also uses Context-Free Grammars.</i>''
</p>
<p>
The image is a thumbnail of the <b>enscript</b> dialog. You can click on it for a larger view.
</p>
<p>
Even if you have no intention of writing anything, there are many example
scripts in the <b>Kaptain</b> 400k source tarball to make it worth the download:
<ul>
<li>arping</li>
<li>crypt</li>
<li>curl</li>
<li>enscript</li>
<li>find</li>
<li>finger</li>
<li>grep</li>
<li>indent</li>
<li>ls</li>
<li>nslookup</li>
<li>open</li>
<li>ping</li>
<li>procmail</li>
<li>tar</li>
<li>weblint</li>
<li>whois</li>
<li>zangband</li>
</ul>
After compile, the binary is about 100k.
</p>
<p>
Now, as alluded to earlier, I had never done any scripting which involved '-&gt',
objects or inheritance at all. Sure, I'd copied and pasted Java like
many others have, but I didn't really <i>get</i> it. Any changes were
nearly pure trial and error. Anything that actually worked after I messed with it was pure accident.
</p>
<p>
I think I just wasn't properly pre-disposed to learning it. After all, the only
example of object oriented programming that I (or most other people) are
familiar seeing as code, is Java. We're aware of Java, because it turns our
normally speedy browsers into 3-toed sloths on vallium. I simply could not understand
what all the hype was about since I always dreaded seeing 'loading java' or
similar in Netscape. Apparently, <b>it doesn't have to be that way</b>. It's
really a wonderful way to write once you get into it. I'd known for years about
it being done even in perl, but I never got past my experience watching Java
ruin an evening's browsing. I was recently vindicated in my attitude towards
Java in the January 2001 issue of "Software Development". On page 26 the author
states: ``<i>I'm primarily a Java hacker ... My Plan A for dealing with a
memory-hungry application ... is to wave my hand and snort 'Bah! That is why we
have virtual memory.' The 20-GB hard disk on this system seems positively
claustrophobic to me.</i>'' I knew it! To be fair, this was in the introduction to an article on
embedded, so I hope it was meant as humour. I hope.
</p>
<h2>Let's create a dialog</h2>
<p>
I can't think of any reason not to use my own first dialog as a starting point,
so we're going to make a simple dialog to hear phone messages from
vgetty.
</p>
<h3>What we need to do</h3>
<p>
Well, we want to display and play voice messages from a graphical user interface.
The messages live in a directory named /var/spool/voice/incoming. We want to
display the messages in a list, pick one and play it. Sounds simple - and
<b>Kaptain</b> keeps it that way.
</p>
<h3>The script</h3>
<p>
I'm going to describe making a script executable here, because I dimly recall being
mystified when I first started with Linux by what I took to be weird "comments" on the top of some
scripts and I hope it may help others. Just skip down to <A href="#goodstuff">The good stuff</A> in order to avoid it.
</p>
<p>
First, lets make a file called 'playmessage'. So, we open a shell and type
"touch playmessage" or open our favourite editor and 'save as'. Whichever, at
some point, you need to be editing a file called 'playmessage' or similar. A
nice place to put this sort of thing is in "/home/yourname/bin", because it's
likely allready a part of your path and you have permissions for it all the
time. If the directory doesn't exist just create it with mkdir.
</p>
<p>
The first line of our script will be a 'shebang' line. Any file under linux is
'executable', i.e. a program, if it has its <i>x</i> bit set. Even if it's not
really a program, but only a script, the first line can tell the operating
system how to handle it as if it were a real program. The upshot is that you can
type the filename and it will be executed.
</p>
<p>
Next we need to know just where <b>kaptain</b> was installed. Pop up an xterm
or drop into console and type "which kaptain" and then enter.
Mine happens to say "/home/paul/bin/kaptain", but yours is more likely to say
"/usr/bin/kaptain" or "/usr/local/bin/kaptain". Now that we know where kaptain
is installed, we can write our first line:<br>
<pre>
#!/usr/bin/kaptain
</pre><br>
and save the file.
</p>
<p>
We're ready to write our script. The last thing we need to do, before we launch
right in, is to set the 'executable' bit on our new "program". Go back into your
shell and make sure you're in the directory which contains 'playmessage'. Now
type "chmod +x playmessage". This will set all the executable bits to on. Now a directory listing with 'ls'
should show 'playmessage' in green with an asterisk beside it indicating
that it's executable.
</p>
<h3><A name="goodstuff">The good stuff</A></h3>
<p>
There are only ten lines in this dialog and two of them are just for show. The only things they do
are to show a title and an icon. Really, we could do without the "Dismiss" button as well. I want to impress
on you just how few lines you need in order to get a functional dialog. A 'copy and paste' plain text version
is <A HREF="misc/evans/playmessage.kaptain.txt" NAME="link to plaintext">here.</A>
</p>
<PRE>
#!/home/paul/bin/kaptain
start "Play Message" -&gt; descr msglist;
descr :horizontal -&gt; title pic;
title -&gt; @text ("Phone Message player.");
pic -&gt; @icon("/usr/share/icons/large/kvoice.xpm");
msglist :framed :horizontal -&gt; msg buttons;
msg -&gt; @list(`ls /var/spool/voice/incoming`);
buttons -&gt; play close;
play -&gt; @action(play_rmd)="Play";
close -&gt; @close="Dismiss";
play_rmd -&gt; "rmdtopvf /var/spool/voice/incoming/"msg" | pvftowav | play -t wav - ";
</PRE>
<SPACER TYPE="vertical" SIZE="20">
<img src="misc/evans/playmessage.gif" width="543" height="282" vspace="10" hspace="10" alt="snapshot of the playmessage dialog">
<p>Here's our first line:</p>
<pre>start "Play Message" -&gt descr msglist;</pre>
<p>
Note the semi-colon at the end of the line. This is mandatory, just like perl. In fact Kaptain is quite "perlish"
after a fashion. The main container is actually named 'start', this is also built into Kaptain's grammar and you must
use this word for your first rule. The quoted string "Play Message" is optional and is used only for the dialog's window title.
</p>
<p>
On the right, that is, after the "-&amp;gt", you can see the words "descr" and "msglist". In Kaptain grammar these are known as 'nonterminals' and
they refer to some area of the dialog. They may be named anything you like as long as they start with a letter. You can also specify as
many areas as you like.
</p>
<p>
So far, we've defined a dialog with two areas named "descr" and "msglist". If you try to run this without adding anything more it will fail. Why? Because,
the areas named don't resolve to anything - we haven't defined them yet. These next three lines define the "descr" area of the dialog:
</p>
<pre>
descr :horizontal -&gt title pic;
title -&gt @text ("Phone Message player.");
pic -&gt @icon("/usr/share/icons/large/kvoice.xpm");
</pre>
<p>
The first line of "descr" is just about the same as the very first line of our script and it does pretty much the same thing. It defines two
areas of the dialog. The only difference is the ':horizontal' option. This forces Kaptain to lay them out side by side instead of vertically. Of
course now these <i>new</i> areas need to be terminated (or point to yet more areas) and they do in the next two lines following them.
"title" now points to a text widget and "pic" points to an icon. Kaptain grammar calls these <i>"specials"</i>. There's a list of all the currently
available specials <a href="misc/evans/specials.html">here.</a> These include spinners, combos, file dialogs etc.
</p>
<p>
These last lines complete the whole dialog by terminating the "msglist" area of the dialog:
</p>
<pre>
msglist :framed :horizontal -&gt msg buttons;
msg -&gt @list(`ls /var/spool/voice/incoming`);
buttons -&gt play close;
play -&gt @action(play_rmd)="Play";
close -&gt @close="Dismiss";
play_rmd -&gt "rmdtopvf /var/spool/voice/incoming/"msg" | pvftowav | play -t wav - ";
</pre>
<p>
Again, we see a familiar line. "msglist" has just added two child areas to itself. Now that you know what the ":horizontal" option does, I
think you can guess at the ":framed" option.
</p>
<p>
The next line - the one for "msg" - is interesting. It's both simple and powerful. I'm sure you've figured out that "@list" is responsible for
the list box shown in the dialog, but look where it gets it's contents from: a line of shell script! Anything in back-quotes (n.b. It's the key to the left
of the "1" on your keyboard, the regular single quote won't work.) will be executed and it's standard out will be fed into the "special". You can stuff
anything in there, "perl -e" - whatever, even multi-line.
</p>
<p>The only area left now is the one for the buttons. This area spins off two more children, one for each button we want. The play button shows
another way to execute some shell commands, this time a pipeline for converting and playing raw modem files. That's it. Again, to see the script as
plain text you may click <A HREF="./misc/evans/playmessage.kaptain.txt" NAME="link to plaintext">here.</A> It's nice to see it all together now that you know how it works.
Simple as it is, you could tinker a bit if you like: feed the list your music directory and change the play command to your mp3 player for example. Process
text files, convert images; it can be the basis for a lot of things.
</p>
<p>
Anything this easy becomes nearly addictive and I was sorely tempted to start "embroidering" the script. Since I only have one way of dealing with
temptation (I yield to it) a pic of the over-grown results is <a href="misc/evans/voxpak.gif">here</a> and the script is <a href="misc/evans/voxpak.kaptain.txt">here.</a> This exercise
was useful for two reasons: a) I got something to replace my now kde2-broken <b>kvoice</b> and b) I learned the limitations of <b>Kaptain</b>. You can't
refresh lists or change anything after it's up (of course widget settings <i>do</i> change things). Commands are evaluated only at run-time. This is as it should be
for a dialog program and I really was pushing the envelope with my little kvoice experiment. So let's do what I originally set out to show.
</p>
<h3>A dialog for <b>mpage</b></h3>
<img src="misc/evans/mpage.gif" width="289" height="302" vspace="10" hspace="10" alt="snapshot of mpage dialog" align="right">
<p>
If you've seen the command line options for <b>mpage</b> you're probably afraid right now. Very afraid. But fear not. We're only going to use a small subset of mpage's options.
And, because we've taken a good look at the basics, I'm not going to go through it line by line. I'm including this here to show off the @echo special more than anything.
</p>
<p>
For those who aren't familiar with <b>mpage</b>, it's a command line program for printing multiple pages on a single page. You can print 2, 4 or 8 up, but you'd better
have exceptional eyesight and a good printer for 8:1! The other noteworthy thing about <b>mpage</b> is that it has about 50 options you can feed it - in fact, the sheer number of
options is listed under 'BUGS' in the man page :-) I'm sure I'll embroider this script over time too, but for now let's just choose between how many pages and the margin controls.
</p>
<p>
Here's the script:
</p>
<pre>
#!/home/paul/bin/kaptain -V
start :framed "mpage Mini-Dialog" -&gt file numpages margins buttons;
file "File to print" -&gt @infile("*.txt");
numpages :horizontal "Number of pages on each page" -&gt p1 | ! p2 | p4 | p8;
p1 "1 pg" -&gt "1";
p2 "2 pgs" -&gt "2";
p4 "4 pgs" -&gt "4";
p8 "8 pgs" -&gt "8";
margins :horizontal "Margins" -&gt left right top bottom;
left "Left" -&gt @integer(10,100)=40;
right "Right" -&gt @integer(10,100)=50;
top "Top" -&gt @integer(10,100)=20;
bottom "Bottom" -&gt @integer(10,100)=30;
buttons :horizontal -&gt echo print dismiss;
echo -&gt @echo(cmd)="Echo";
print -&gt @action(cmd)="Print";
dismiss -&gt @close()="Dismiss";
cmd -&gt "mpage -P -"numpages" -m" left "l" bottom "b" top "t" right" r "file;
</pre>
<p>Plain text is <A HREF="./misc/evans/mpage.kaptain.txt" NAME="link to plaintext">here.</A></p>
<p>
When run from an xterm, you can make changes and click the "Echo" button over and over to see how the changes effect the command line
without wasting any paper at all. To save more paper just take out the "-P" and everything will go to standard out even if you press print.
To really enjoy playing with it change the cmd line to:
</p>
<pre>cmd -&gt "mpage -" numpages " -m" left "l" bottom "b" top "t" right "r " file" >test.ps";</pre>
<p>
then you can just view the output page with a viewer. Or you could add ";viewername test.ps" to the end and save a step - you get the idea.
</p>
<p>
There is another article about <b>Kaptain</b> by <a href="mailto:renai@start.com.au">hawkeye</a> at
<A HREF="http://www.linuxtoday.com.au/r/article/jsp/sid/131347">Linux Today Australia.</A>
</p>
<p>
I haven't done a thorough job of describing everything <b>Kaptain</b> can do; there's heaps more I haven't shown or even mentioned.
<b>Kaptain</b> comes with pretty good docs and plenty of examples though. The author of <b>Kaptain</b> is <b>Ter<EFBFBD>k Zsolt</b>.
He's doing a great job with <b>Kaptain</b> - which is still only at 0.51. If it gains wider use it can be of great value in teaching console
apps and it can save all of us some mind-numbing tedium. Plus, it's the most painless way to experiment with output I've ever
found. Don't wait for someone to write one for you - give it a shot yourself. Really. Mr. Ter<65>k will be pleased to post them on his
<a href="http://kaptain.sourceforge.net">website.</a>
</p>
<p>
There are other dialog programs for X out there: <b>gdialog</b> which is probably on your system already, <b>Xdialog</b> which has some nice date/time dialogs etc.
is down-loadable from <a href="http://xdialog.free.fr/">here.</a>
If one dialog app doesn't have exactly what you want there are always options. I'm sure there are others I just haven't tried yet. Mix and match them within the same script.
<!-- *** BEGIN copyright *** -->
<P> <hr> <!-- P -->
<H5 ALIGN=center>
Copyright &copy; 2001, Paul Evans.<BR>
Copying license <A HREF="../copying.html">http://www.linuxgazette.com/copying.html</A><BR>
Published in Issue 64 of <i>Linux Gazette</i>, March 2001</H5>
<!-- *** END copyright *** -->
<!--startcut ==========================================================-->
<HR><P>
<CENTER>
<!-- *** BEGIN navbar *** -->
<IMG ALT="" SRC="../gx/navbar/left.jpg" WIDTH="14" HEIGHT="45" BORDER="0" ALIGN="bottom"><A HREF="dellomodarme.html"><IMG ALT="[ Prev ]" SRC="../gx/navbar/prev.jpg" WIDTH="16" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="index.html"><IMG ALT="[ Table of Contents ]" SRC="../gx/navbar/toc.jpg" WIDTH="220" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><A HREF="../index.html"><IMG ALT="[ Front Page ]" SRC="../gx/navbar/frontpage.jpg" WIDTH="137" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="http://www.linuxgazette.com/cgi-bin/talkback/all.py?site=LG&article=http://www.linuxgazette.com/issue64/evans.html"><IMG ALT="[ Talkback ]" SRC="../gx/navbar/talkback.jpg" WIDTH="121" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><A HREF="../faq/index.html"><IMG ALT="[ FAQ ]" SRC="./../gx/navbar/faq.jpg"WIDTH="62" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="fevola.html"><IMG ALT="[ Next ]" SRC="../gx/navbar/next.jpg" WIDTH="15" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><IMG ALT="" SRC="../gx/navbar/right.jpg" WIDTH="15" HEIGHT="45" ALIGN="bottom">
<!-- *** END navbar *** -->
</CENTER>
</BODY></HTML>
<!--endcut ============================================================-->