Archive for July, 2008

Configuring an IBM i for Emacs and Perl hacking

July 31, 2008

An “IBM i” is a descendant of the old AS/400 machines and has undergone numerous name changes over the years. Most code on it is written in a language called RPG, but which unfortunately lacks polyhedral dice altogether. When IBM decided to promote Java for the platform, they had to have a Unix like tool to manage everything, so they built one from scratch with local tools and languages. At the same time, IBM realized they could run the machine with more or less the exact same hardware as their AIX boxes, so a second stream of “Unix-ness” was introduced into the platform.

First you need to install Option 30 (QSHELL) and Option 33 (PASE) on your operating system. PASE is a bonafide AIX type Unix environment. QHSELL is a Unix-like environment that is implemented in native code/objects. You’ll use PASE to run ‘real’ Unix programs and you’ll use QSHELL when you need a tool that groks the differences between Unix and the local environment.

Next you want to go install The iSeries Tools for Developers (product 5799-PTL). This will give you version v5.8.7 of Perl and version 20.7.2 of Emacs relatively painlessly. You’ll want to set up symbolic links for at least these programs:

ln -s /QIBM/ProdData/DeveloperTools/pase/bin/perl /usr/bin/perl 
ln -s /QOpenSys/QIBM/ProdData/DeveloperTools/perl587/bin/perldoc /usr/bin/perldoc 
ln -s /QOpenSys/QIBM/ProdData/DeveloperTools/emacs/bin/emacs /usr/bin/emacs

Now you can call Perl and Emacs from the command line… except you can’t run Emacs, yet.

You’ll need cygwin installed on your Windows box. Pull down the xwindows libraries when you configure your setup. You’re good to go when you can type “startx” from a cywgin command line.

Go to C:\cygwin\usr\X11R6\bin and make a shortcut to startxwin.bat onto your desktop. Run this to go directly to x without having to start cygwin first. Once you’re at the x command line, type “xhost YOURSERVERNAME”.

Now start your 5250 emulator. At the command line, type STRQSH to go into QSHELL. Once there, enter the following commands:

system "strptl CLIENT('1.2.3.4:0.0')" 
export DISPLAY="1.2.3.4:0.0" 
emacs

If you don’t know what your ip address is to set up your DISPLAY environment variable there, you can just peek in the startxwin.bat to get it. You can also put the above commands into your .profile file so that they run every time you start QSHELL. Both your .emacs and .profile files go in the “home folder” that you start off in when you open QSHELL.

Enjoy!

Advertisements

Now What?

July 24, 2008

Brian C Cunningham has written recently that he appears to have been pigeonholed as a Blub programmer. In spite of extensive reading and experimentation with various cool languages and tools, he doubts that he can make the jump into an environment where he can continue to grow his skills– he feels like all anyone sees in him is “Blub programmer, x years of experience.”

I’m pretty much in the same boat.

I mean… will any employer possibly care if I told them that I’ve worked through half of SICP, internalized maybe thirty Emacs commands, can do some moderately interesting stuff with sed and pipes on Unix, and can write crappy Perl code? Will all of this stuff remain merely a secret weapon of mine while I continue on in work environments where such tools are unknown, actively feared, or completely off the radar?

I guess I don’t know where I’m going with all of this, really. I mean, I started off with Blub because I wasn’t too picky; I just wanted to be a programmer and it seemed to be the quickest way to get behind a compiler. As far as all of the open source type stuff went, I maintained a fairly Han Solo type attitude: “Look, I ain’t in this for your revolution, and I’m not in it for you, Princess. I expect to be well paid. I’m in it for the money!” But slowly, Open Source tools began to take over in my pet projects. It all started with NUnit, picked up steam with Subversion, blossomed with Emacs, and finally got clinched with Perl, GNUWin32, and cygwin.

Frankly I’m overloaded with the number of lame tools that I have to use at work. At any given time, I’ll have two or more IDE’s open, two or more Office programs, text files, folders, emulators… all of it open all day. I’ve stopped learning how to do new things with most of those tools because it’s a waste of time: the next iteration of any of them might crash or be so bloated it won’t work. They might replace my favorite feature… or the company that produces the tool might go away and suddenly have the worst support in the universe. Most of the best features of these tools are just mediocre unscriptable versions of stuff that Unix has been doing perfectly well for years.

(This is the point where I start frothing at the mouth, shaking my fist at “the man”, and decrying the evils of Bill Gates, Micro$oft, MS-DOG, Windoze, and the Steve Ballmer dance thing.)

My last Blub project was really awesome, though. I even see now how to completely remove my greenspunning elements and use a Perl script to generate the Blub code to do the fancy stuff specified in a programming language of my own invention– no one need ever know about the weird stuff I do just for the fun. If I leave my job, I can effectively leave behind only Blub code with hardly any trace of wackiness in it.

But it’s not about money anymore. It’s not about raw productivity. It’s not about doing stuff a certain way just to feel cool. It’s not even about some sort of rabid “freetard” ideology. It’s about tools that are worth investing in because I know they’ll be there ten years from now. It’s about tools that don’t constantly annoy me. It’s about developing the way I want to develop instead of being locked into somebody else’s vision of what a Mort/Rockstar/Elvis should do. It’s about using a set of tools that are freely available so that I have a common frame of reference with the handful of other developers out there that actually care.

But honestly, I don’t know what the next thing is. I’m a genius with SQL. I’m competent with regex’s. I can “get things done” with Blub. Outside of that scene, I can do little more than frame a mediocre question. Now what?

I really don’t know.

I have no idea where this leads. I never really chose anything per se… it’s all just a net conglomeration of thousands of small decisions that I make everyday.

Now what?

Okay… it’s time to finally define those function keys in Emacs…

July 21, 2008

Here’s my set-up. For “help”, most of the time apropos is what I need to do. Yes… I waste time mousing over to the drop down menu. The other twenty percent of the time, I want to know what a key is doing. Those two functions are going over to F1 and shift-F1 respectively. I’m not setting anything onto alt-F1 or super-duper-F1 because I’m not liable to remember more than two functions per function key.

The most important tool for the lazy roll-tester: comment and uncomment region go to F2 and shift-F2. (I’m sticking it next to F1 because I definitely “need help” if I’m using it a lot!)

F3 fires up the shell, because it’s the first thing I do most of the time anyway.

F4… “close” the current buffer. I sometimes use “kill other windows” (now shift-F4), but usually I forget what it does exactly and kill the wrong thing.

F5 is now the one stop keyboard macro stop. The usual scenario is… edit some code, start recording, save the file, change to the shell buffer, type the shell command to run the code I’m working on, then stop recording. Now F5 works like all those other IDE’s out there, except I get to keep my entire command and output history and I’m just one C-x b away from getting back to my code. Viva roll testing!

F6 switches to the “other” window. Yes. I still confuse C-x o and C-x 0. Maybe I’ll have more windows open if I have this, but I usually like just having one giant buffer, so I doubt I’ll use this.

F8 to run my emacs code I’m fiddling with– and shift-f8 to load a whole file. Yes… my left hand hurts from doing C-x C-e too many times today. (F8 was the next most often used key after F5 in one of my old IDE’s, so maybe I’ll think of something better, but I want something that will encourage me to fiddle with Emacs a little more often.)

Finally… what’s not listed here is what illustrates what an Emacs loser I am! (I’m still addicted to Tortoise SVN. Sad, but true.) Yes… those lists of things that “if you don’t know how to do these things with your editor, then you stink” are NOT yet represented here. Maybe some day…. For now… just preface your comment with, “I can’t believe you didn’t make a hotkey for ___! You are obviously an emacs loser n00b!”

(global-set-key [f1] 'apropos-command)
(global-set-key [S-f1] 'describe-key)

(global-set-key [f2] 'comment-region)
(global-set-key [S-f2] 'uncomment-region)

(global-set-key [f3] 'shell)

(global-set-key [f4] 'kill-this-buffer)
(global-set-key [S-f4] 'delete-other-windows)

(global-set-key [f5] 'call-last-kbd-macro)
(global-set-key [S-f5] 'start-kbd-macro)
(global-set-key [M-f5] 'end-kbd-macro)

(global-set-key [f6] 'other-window)

(global-set-key [f8] 'eval-last-sexp)
(global-set-key [S-f8] 'load-file)

Notes on Arrays in Perl, Take Two

July 20, 2008

My Perl is really weak what with only having read “Learning Perl” so far…. I continue to write little programs in the langauge in spite of my unfamiliarity with Perl idioms and without having assimilated all of the available material. In my day job, I pretty much never get any code reviews or even any tips and tricks, so I try to take advantage of the feedback I get on this blog. So here’s a rewrite of portions of what I posted the other day in order to try to synthesize suggestions I received from a “real” Perl coder.

#!/usr/bin/perl
# demonstrate a sub that returns an array of arrays
# thanks to Eric TF Bat for the code review

# note: read the Camel book or your Perl code will be really annoying
@bar = makearray(1,8,27);
showme(@bar);
print "This is still crazy:\n";
&crazy;

sub makearray {
    return @_;
}

sub showme {
    my @args = @_;
    foreach my $i (0..2) {
	# use $args[], not @args[]
	print "$args[$i]\n";
    }
}

sub threearrays {
    my @one, @two, @three;

    # assign $_ to a local variable for readability
    foreach my $i(0..2){
	$one[$i] = ($i + 1) * 1;
	$two[$i] = ($i + 1) * 2;
	$three[$i] = ($i + 1) * 3;
    }

    my @all;
    $all[0] = \@one;
    $all[1] = \@two;
    $all[2] = \@three;
    return @all;
}

sub crazy {
    my @x = &threearrays;
    my @a = @{$x[0]};
    my @b = @{$x[1]};
    my @c = @{$x[2]};
    showme(@a);
    showme(@b);
    showme(@c);
}

Array References and Hashes of Hashes in Perl

July 18, 2008

Here’s some Perl code showing how to pass arrays around and also how to use a hash of hashes instead. The Perl books I have, perldoc, and Google did not really tell me what I wanted to know to do this sort of stuff, so I wasted a lot of time messing around. I’m not sure why that was…. I guess them Perl folks have different habits or terminology or something. (Not that I have anything against that…. I wouldn’t be learning it if it wasn’t different, now would I?)

(Note the the threearrays subroutine is returning an array of references. The crazy subroutine is casting those references back into local variables that you can play with. You have to do similar stuff when you want to play with hashes like that, too. I haven’t yet picked up a less verbose approach for doing that sort of thing.)

Anyways, with these notes, you might be able to more quickly move from a quick-and-dirty Perl script style into a more functional approach in your Perl coding. Good luck.

#!/usr/bin/perl
$foo[0] = 1;	
$foo[1] = 4;	
$foo[2] = 9;	

@bar = makearray(1,8,27);

showme(@foo);
showme(@bar);

&crazy;
¬ascrazy;

sub makearray {
    my @array;
    foreach(0..2){
	@array[$_] = @_[$_];
    }			
    return @array;
}

sub showme {
    my (@array) = @_;
    foreach(0..2){
	print "$array[$_]\n";
    }	
}

sub threearrays {
    my @one, @two, @three;
    foreach(0..2){
	@one[$_] = ($_ + 1) * 1;
	@two[$_] = ($_ + 1) * 2;
	@three[$_] = ($_ + 1) * 3;
	#print "($one[$_], $two[$_], $three[$_])\n";
    }
    
    my @all;
    @all[0] = \@one;
    @all[1] = \@two;
    @all[2] = \@three;
    return @all;
}

sub crazy {
    my @x = &threearrays;
    my @a = @{$x[0]};
    my @b = @{$x[1]};
    my @c = @{$x[2]};
    showme(@a);
    showme(@b);
    showme(@c);
}

sub hashorama {
    my %hash, $a;
    foreach(0..2){
	$a = $_;
	foreach(0..2){
	    $hash{$a}{$_} = ($a + 1) * ($_ + 1);
	}	 
    }
    return %hash;		
}

sub notascrazy {
    my %hash = &hashorama;
    my $a;
    print "not as crazy\n";
    foreach(0..2){
	$a = $_;
	foreach(0..2){
	    print "$hash{$a}{$_}\n";
	}
    }	
}

How NOT to fix your Delete key in EMACS

July 15, 2008

I’ve been runing emacs off of a weird server. I was running x on cygwin and had used “xhost MYSERVER” to pick up the emacs session. Cool. The version of Emacs 20.7.2, though. Anyways… I get there and backspace and the delete key both work by backing over the previous character. I wanted to make the delete key “eat” the next character. This should be easy to fix, right? Doh! It took me more than an hour. Below is my lame trial and error process of finding a lame solution. I haven’t had this much fun since I had to figure out how to enter a carriage return!

C-h b — list key bindings
C-s del — search for del… C-s to go forward, C-r to go backward

C-d runs the command delete-char
which is an interactive built-in function
DEL runs the command delete-backward-char
which is an interactive built-in function

C-x C-e the elisp code lines to execute them.

[Waste time trying many wrong ways to global-set-key the delete key, until….]

runs but doesn’t change behavior:

(global-set-key [del] 'delete-char)

look– hitting del does not make the “hello” text

(global-set-key [del] "hello")

this works! but… now backspace works like delete! Argh!

(global-set-key "\d" 'delete-char)

fix it back:

(global-set-key "\d" 'delete-backward-char)

Uh… both of them are bound to DEL.

Problem must not be in EMACS. But wait… the weirdo shell that lanched EMACS knows the difference!

Can EMACS tell the difference between DEL and BACKSPACE?

press backspace , press delete
then hit C-h l to view the lossage buffer.
If you see something like
backspace deletechar

It can!!! Execute this:

(global-set-key [backspace]  'delete-backward-char) 
(global-set-key [deletechar] 'delete-char)

Still doesn’t work right….

(define-key function-key-map [delete] nil) 
(global-set-key [delete] 'delete-char)

Now delete is dead! (Backspace still works.)

Can’t get it back with this:

(define-key function-key-map [delete] [delete])

Hmm…. Maybe…. Aha! A lame hack:

(define-key function-key-map [delete] [F20]) 
(global-set-key [F20] 'delete-char)

This works! I did it! It only took an hour and a half! Argh!

An Excel Macro for Pulling in Data from Another Worksheet

July 8, 2008

You may be a super hacker, but your users aren’t.  All the things you take for granted in a quick query that joins a few tables is far beyond anything they’ll ever try to take on for themselve.  Some of them are pretty good getting around in Excel, but only one in a hundred will touch something like Microsoft Access.  So they come to you for every little thing.

So, in the interests of “faking” database functionality on the Excel side of things, here is a little macro code for looking up data in another worksheet and copying it over into where you’re working.  It looks at the cell to the left of your current cell, then finds a row that matches it in a worksheet named “Data”.  The row of data is then copied back into the current cell and the 9 cells to the right, but if data is already there it does NOT overwrite it.  The scenario here is that someone sends a list of part numbers or customer numbers in an email and your manger types and power users can now have way to quickly append the usual bits of information that they need to really work with it.  Note that in this case, individual users are assumed to be maintaining their own Data worksheets.

Sub DataPull()
'
' DataPull Macro
' Copy text from the "Data" sheet based on the cell to the left of the currently active cell.
'
' Keyboard Shortcut: Ctrl+d
'
    On Error GoTo DataPullError
    Dim Find As String
    Dim Cur As String
    Dim x As Long
    Dim y As Long

    If ActiveCell.Column = "1" Then
        MsgBox "Data macro looks up based on the cell to the left of the current cell.", vbExclamation, "Data Pull macro"
        Exit Sub
    End If

    Find = ActiveCell.Previous

    Do
        x = x + 1
        Cur = Worksheets("Data").Range("A" & x).Value
        If Cur = Find Then
            For y = 0 To 9
                Cur = Worksheets("Data").Range(Chr(66 + y) & x).Value
                If ActiveCell.Next(1, y) = "" Then ActiveCell.Next(1, y) = Cur
            Next y
        End If
    Loop Until Cur = ""

    Exit Sub
DataPullError:
    MsgBox Err.Description, vbCritical, "Data Pull macro"
End Sub

Note: I tried using VLOOKUP for something like this, but performance appeared to be awful for the size of the datasets I was working with.  The “dumb” just-copy-some-data-in-here-and-don’t-worry-about-staying-in-sync approach is used here to eliminate the possibility of any lame slow-downs or program hangs that can be caused by a large number of VLOOKUP’s.

OOPSLA 2008 in Nashville: Let’s go!

July 2, 2008

John McCarthy will be there.

Mark Jason Dominus, too.

I reckon it’d be a shame if I didn’t go down yonder to see them folks, seeing as how it’s just down the road and all….  Other lispy/geeky blogger types out there: can you make it as well?