My reasoned, well-considered thoughts on gadgets, computing, quantified self, health, open source and whatever else gets my dander up.
Cookie Notice
2009/12/29
TV on my PC? We live in the Future
2009/12/22
Lies! All Lies!
Most of the lab wants to take the week between Christmas and New Years off. But there are researchers who are still dropping off samples today, the day before Festivus. I've got a lot of problems with you people!
2009/12/21
The 12 Days: an analysis
#!/usr/bin/perl
use 5.010 ;
use strict ;
use warnings ;
use DateTime::TimeZone ;
use File::stat ;
my @count ;
my @days ;
$days[1] = 'Partridge in a Pear Tree' ;
$days[2] = 'Turtle Doves' ;
$days[3] = 'French Hens' ;
$days[4] = 'Calling Birds' ;
$days[5] = 'Golden Rings' ;
$days[6] = 'Geese A-laying' ;
$days[7] = 'Swans A-swimming' ;
$days[8] = 'Maids A-milking' ;
$days[9] = 'Ladies Dancing' ;
$days[10] = 'Lords A-leaping' ;
$days[11] = 'Pipers Piping' ;
$days[12] = 'Drummers Drumming' ;
for my $a ( 1 .. 12 ) {
for my $b ( 1 .. 12 ) {
next if $b > $a ;
$count[$b] ++ ;
}
}
for my $a ( 1 .. 12 ) {
say join ' ' , $count[$a] * $a , $days[$a] ;
}
I determined the precise number of each gift as presented in the song.
12 Partridge in a Pear Tree
22 Turtle Doves
30 French Hens
36 Calling Birds
40 Golden Rings
42 Geese A-laying
42 Swans A-swimming
40 Maids A-milking
36 Ladies Dancing
30 Lords A-leaping
22 Pipers Piping
12 Drummers Drumming
I suppose it preferable to have a smaller number of drummers than geese. Time to get into the geese and swan market, though.
2009/12/15
A MySQL Bug? A Programmer Bug?
I have been trying to teach myself data analysis. I have been keeping some weather data in a MySQL database so I can take it out, munge it and graph it. The above example is done with the Perl module
Chart::Clicker
, which I am sure will take a large role in my current job. Especially if it works fast and graphs correctly.On that topic, take a look at it. The red line represents the day's highs, the green line, the day's lows, and the purlple line the day's average temperature. Here's the code that determines what the numbers should be.
my $sql ;
$sql .= 'SELECT ' .
'cast( avg( temp_f ) as unsigned ) , ' .
'min(temp_f) , ' .
'max(temp_f) , ' .
'DATE(time) ' .
'from weather_data where zip = "47909" ' .
'and DATEDIFF( CURDATE() , DATE(time) ) < 7 ' .
'group by DATE(time)' ;
And here's the schema for this code.
CREATE TABLE weather_data (
id int(10) not null auto_increment primary key ,
time TIMESTAMP not null ,
zip varchar(5) ,
city varchar(255) ,
temp_c varchar(255) ,
temp_f varchar(255) ,
humidity varchar(255) ,
wind varchar(255) ,
conditions varchar(255)
) ;
I'll admit that it's pretty lazy. If the current conditions stretches beyond 20 characters, that's some complex weather. The main problem, I believe, is that temperature data is being saved as a string rather than a signed integer. Why it mostly shows up as error on that one day, I don't know. Here's all the temperature data for that day. (Thank you, Google Weather API.)
time | temp_f | temp_c |
---|---|---|
2009-12-10 00:00:02 | 28 | -2 |
2009-12-10 00:10:02 | 28 | -2 |
2009-12-10 00:30:03 | 28 | -2 |
2009-12-10 00:40:02 | 28 | -2 |
2009-12-10 00:50:02 | 28 | -2 |
2009-12-10 01:00:02 | 28 | -2 |
2009-12-10 01:10:02 | 28 | -2 |
2009-12-10 01:30:02 | 16 | -9 |
2009-12-10 01:40:02 | 16 | -9 |
2009-12-10 02:00:03 | 16 | -9 |
2009-12-10 02:10:02 | 16 | -9 |
2009-12-10 02:20:02 | 16 | -9 |
2009-12-10 02:40:02 | 14 | -10 |
2009-12-10 02:50:02 | 15 | -9 |
2009-12-10 03:00:02 | 15 | -9 |
2009-12-10 03:10:02 | 15 | -9 |
2009-12-10 03:20:02 | 15 | -9 |
2009-12-10 03:30:03 | 14 | -10 |
2009-12-10 03:40:01 | 14 | -10 |
2009-12-10 03:50:01 | 15 | -9 |
2009-12-10 04:00:03 | 15 | -9 |
2009-12-10 04:10:02 | 14 | -10 |
2009-12-10 04:20:02 | 14 | -10 |
2009-12-10 04:30:02 | 12 | -11 |
2009-12-10 04:40:02 | 12 | -11 |
2009-12-10 05:00:02 | 13 | -11 |
2009-12-10 05:10:02 | 12 | -11 |
2009-12-10 05:20:02 | 12 | -11 |
2009-12-10 05:30:03 | 12 | -11 |
2009-12-10 05:40:02 | 12 | -11 |
2009-12-10 05:50:02 | 12 | -11 |
2009-12-10 06:00:03 | 12 | -11 |
2009-12-10 06:10:02 | 11 | -12 |
2009-12-10 06:20:02 | 11 | -12 |
2009-12-10 06:30:02 | 11 | -12 |
2009-12-10 06:40:01 | 11 | -12 |
2009-12-10 07:00:03 | 11 | -12 |
2009-12-10 07:10:02 | 10 | -12 |
2009-12-10 07:20:02 | 10 | -12 |
2009-12-10 07:30:02 | 10 | -12 |
2009-12-10 07:40:04 | 10 | -12 |
2009-12-10 07:50:02 | 10 | -12 |
2009-12-10 08:00:09 | 9 | -13 |
2009-12-10 08:10:05 | 9 | -13 |
2009-12-10 08:20:06 | 9 | -13 |
2009-12-10 08:30:05 | 9 | -13 |
2009-12-10 08:40:06 | 9 | -13 |
2009-12-10 08:50:05 | 9 | -13 |
2009-12-10 09:00:06 | 8 | -13 |
2009-12-10 09:10:08 | 8 | -13 |
2009-12-10 09:20:08 | 8 | -13 |
2009-12-10 09:30:08 | 8 | -13 |
2009-12-10 09:40:13 | 8 | -13 |
2009-12-10 09:50:07 | 9 | -13 |
2009-12-10 10:00:07 | 10 | -12 |
2009-12-10 10:10:07 | 10 | -12 |
2009-12-10 10:30:07 | 10 | -12 |
2009-12-10 10:40:10 | 10 | -12 |
2009-12-10 10:50:07 | 12 | -11 |
2009-12-10 11:00:07 | 12 | -11 |
2009-12-10 11:10:05 | 12 | -11 |
2009-12-10 11:20:08 | 12 | -11 |
2009-12-10 11:40:08 | 12 | -11 |
2009-12-10 12:00:09 | 14 | -10 |
2009-12-10 12:30:07 | 14 | -10 |
2009-12-10 12:50:07 | 14 | -10 |
2009-12-10 13:00:09 | 14 | -10 |
2009-12-10 13:10:06 | 15 | -9 |
2009-12-10 13:20:08 | 15 | -9 |
2009-12-10 13:30:06 | 15 | -9 |
2009-12-10 13:50:07 | 17 | -8 |
2009-12-10 14:00:09 | 17 | -8 |
2009-12-10 14:10:07 | 17 | -8 |
2009-12-10 14:20:08 | 17 | -8 |
2009-12-10 14:40:09 | 18 | -8 |
2009-12-10 14:50:08 | 17 | -8 |
2009-12-10 15:20:08 | 18 | -8 |
2009-12-10 15:30:15 | 18 | -8 |
2009-12-10 15:40:08 | 18 | -8 |
2009-12-10 15:50:11 | 19 | -7 |
2009-12-10 16:00:11 | 19 | -7 |
2009-12-10 16:10:08 | 19 | -7 |
2009-12-10 16:20:08 | 19 | -7 |
2009-12-10 16:30:07 | 19 | -7 |
2009-12-10 16:40:10 | 19 | -7 |
2009-12-10 16:50:08 | 19 | -7 |
2009-12-10 17:00:03 | 19 | -7 |
2009-12-10 17:10:03 | 19 | -7 |
2009-12-10 17:30:02 | 19 | -7 |
2009-12-10 17:40:02 | 18 | -8 |
2009-12-10 17:50:02 | 18 | -8 |
2009-12-10 18:00:02 | 18 | -8 |
2009-12-10 18:10:02 | 17 | -8 |
2009-12-10 18:20:02 | 17 | -8 |
2009-12-10 18:30:02 | 17 | -8 |
2009-12-10 18:40:02 | 16 | -9 |
2009-12-10 18:50:01 | 16 | -9 |
2009-12-10 19:00:02 | 17 | -8 |
2009-12-10 19:10:02 | 17 | -8 |
2009-12-10 19:20:02 | 17 | -8 |
2009-12-10 19:40:02 | 17 | -8 |
2009-12-10 19:50:02 | 17 | -8 |
2009-12-10 20:00:02 | 17 | -8 |
2009-12-10 20:20:02 | 17 | -8 |
2009-12-10 20:30:02 | 17 | -8 |
2009-12-10 20:40:02 | 17 | -8 |
2009-12-10 21:00:03 | 17 | -8 |
2009-12-10 21:10:01 | 17 | -8 |
2009-12-10 21:20:02 | 18 | -8 |
2009-12-10 21:30:02 | 18 | -8 |
2009-12-10 21:40:02 | 18 | -8 |
2009-12-10 22:00:02 | 17 | -8 |
2009-12-10 22:10:02 | 17 | -8 |
2009-12-10 22:20:02 | 18 | -8 |
2009-12-10 22:30:02 | 18 | -8 |
2009-12-10 22:40:02 | 18 | -8 |
2009-12-10 22:50:01 | 18 | -8 |
2009-12-10 23:00:02 | 18 | -8 |
2009-12-10 23:10:01 | 18 | -8 |
2009-12-10 23:20:02 | 18 | -8 |
2009-12-10 23:30:02 | 18 | -8 |
2009-12-10 23:40:02 | 18 | -8 |
2009-12-10 23:50:02 | 18 | -8 |
I could show you the temp_c graph, but that's just beyond the pale wrong, which makes sense as the temperature has been bouncing between positive and negative the whole time.
Ultimately, I got used to Perl's ability to effortlessly bounce between strings and numbers, and here I'm bitten. I can only use that data in a meaningful way if I pull it all and manipulate it in Perl, which cuts off some labor-saving tools. Let that be a lesson to you, and to me.
2009/12/14
Terry Childs Trial Begins
As an admin, I hold that Childs is in jail for proper system administration. I hold that Childs is in jail for protecting the networks of the city of San Francisco, ultimately protecting the people of San Francisco, from his bosses.
San Francisco remains a city that jails people for doing system administration right.
2009/12/13
Instinctive and Alarming
And as I have said, I haven't been happy with the alarm. I love how many alarm it has, but it never seemed to go off.
I understand the problem now.
I didn't dime the volume. Do that and it is OK.
2009/12/11
A Perfect Stocking Stuffer
Bluetooth USB dongle. Push it into your USB port and you can talk to your fancy schancy smart phone. What can you then do? Don't know yet. I don't have one yet. I guess soon after I'll start wanting a Bluetooth headset, a Bluetooth external DVD burner, a Bluetooth toothbrush. But one step at a time.
2009/12/10
New Gear Day
The newest thing to land on my lap is, well, swank. An HP Pavilion Slimline. 320 GB SATA. 3GB memory. Dual-core processor. It's running Vista, which yeah, could be a blessing, could be a curse. We'll see. I have the technology to upgrade it to XP at will, and of course I can jump to Ubuntu. It's a tight little case, so not much room to upgrade. Seeing that it's far faster and better than anything sitting around the house, that should be no problem.
The problem it had in Mom's hands was that it couldn't keep connected to AOL. That will NOT become a problem with me.
I think I want to stick with Vista, though. At least at the moment. I am a big fan and user of Open Source software, but my user experience as a Unix guy has not really been strongly changed since I first started working with Unix in the mid-1990s. Unix, a shell (then
tcsh
, now bash
), X, terms, and browsers. Vista is wildly different, and I think coming to terms with the differences, with what Vista has to offer. Similarly, I'd keep MacOSX around if it landed on my lap. This, more or less, is why I bought BeOS back in the day, to get another view on things. So, we'll see. Thanks Ma!
Sprint Rant as Modem, pt 1 of ... 1
K, on the other hand, has much more of a need for it. But it has not worked for her and her EeePC. Never has. It's gone back to the shop recently to get some work, but it's still flaky. I have just now downloaded the new Sprint SmartView software ...
I don't even get to get into it. I downloaded the newest version of SmartView, it grabbed newer drivers for the USB dingus, and now K can use the USB dingus to connect at Bill-Kurtis-like speeds. I was going to write down all my notes toward using her Samsung Rant as a modem, but the dingus works.
Don't you hate it when you're just about to get a nice hate-filled rant on and the thing just works?
Annotated jQuery, or pass me the crack pipe
$( '<div/>' ) // We create a DIV tag
.attr( 'id' , 'e_solid' ) // give it a unique identifier
.text( 'solid' ) // put text into it
.appendTo('#head') // give it a unique identifier
.click( function() { // and set what happens when you click it
var ajax = a_dir + '2g_slide_formats.cgi' + '?e=solid' ; // which is, set a URL
$( '#e_454' ).css( 'color' , '#abc' ) ; // do some CSS stuff
$( '#e_solid' ).css( 'color' , '#000' ) ; // that won't work by
// setting it in the CSS file
$( '#run' ).empty() ; // clear some other
$( '#slide' ).empty() ; // subordinate tags
$( '<div/>') // We create a new DIV tag
.text('Slide Type') // fill it
.appendTo('#run') // put it into another tag
;
$( '<select/>') // we create a select box
.attr('id','holder') // give it an id
.appendTo('#run') // put it in the same tag
.wrap(document.createElement("div")) // put a DIV tag around it
.change( function() { // and an action for when
// the select changes
var value = $(this).val() ;
$( '#slide' ).empty() ; // empty '#slide' again
for ( var i = 1 ; i <= value ; i++ ) { // and figure the number of
// regions from the select value
var div_name = 'region_' + i ; // and make a name
$( '<div/>' )
.attr( 'id' , div_name ) // which we use to name a new DIV
.text( 'Region ' + i ) // which we fill
.addClass( 'region' ) // class
.appendTo( '#slide' ) // and append to the emptied #slide
;
$( '<span/>') // then add a SPAN
.appendTo( '#' + div_name ) // which we append to that new DIV
.text( 'Add barcode' )
.click( function() { // and when you click it ...
var accession = prompt( // you're prompted for one field
'Set Accession Number'
) ;
var barcode = prompt( // and then another
'Set Barcode, or Make Blank' , 'MID'
) ;
var strID = 'div_' + div_count ++ ;
alert( div_name ) ; // this is a bit of debugging.
$( '<div/>' ) // yet another DIV
.attr( 'id' , strID )
.appendTo( '#' + div_name + ' .body' )
; // which should go to the .body
// but doesn't, which is why I'm writing
$( '<span/>' )
.appendTo( '#' + strID)
.text( accession )
.addClass( 'accession' ) // and we add SPANs to that DIV
;
$( '<span/>' )
.appendTo( '#' + strID)
.text( barcode )
.addClass( 'barcode' ) // which are the data we are
; // prompted for
$( '<span/>' )
.appendTo( '#' + strID)
.text( 'delete' )
.addClass( 'delete')
.click(function(){ // and another SPAN
$( '#' + strID ).remove() ;
}) ; // that you click to remove
}) ; // this whole DIV and all in it
}
}) ; // It looks like we're done but that's just the end
// of the definition of the SELECT
// which we fill with AJAX and JSON
$.getJSON( ajax , function(data){ // we get a data chunk from JSON
var objD = eval( data ) ; // convert it to an object
for ( var i = 0 ; i < 100 ; i++ ) { // The shotgun approach saves me
if ( objD[i] != undefined ) { // from having to be clever
$( '<option/>') // and we add all the OPTIONS
.attr('value', objD[i].max_regions )
.text( objD[i].format ) // to the previously mentioned SELECT
.appendTo('#holder') // Remember the SELECT?
;
}
}
}) ;
}) // And here we end it. That was all one "line"
; // and it isn't quite correct.
My brain hurts.
2009/12/08
Memento Mori
I have a cast-away desktop machine I'm trying to patch into a vaguely useful machine for my son. I have a 40GB drive into it, which is a bit tiny — it's XP, so 10GB will be taken by the OS and programs before he even starts trying to use it — so I'm have been trying to slip in a second 40GB drive that came from a machine whose power supply died on him. But the number two drive is not working.
I'm not sure why. I'm mostly sure that it's a jumper setting, but to check it, I will put back the Zip drive I took out to makeo room.
I remember when I put stuff on ZIP drives, when they were a good alternative to CDROMs, which when burned were unchangable, and floppy discs, which were and are just too small. I remember how proud I was, how cool I thought I was when I installed a Zip drive onto my beater Celeron about a decade ago.
I was filling it up so there would be something on it when I tried to load it on that machine. I remember thinking that Zip drives had just massive amounts of space. First thing I tried to put on there would not fit. It was too big.
That's the way, isn't it? Time was, I thought a 1200-baud modem was fast, and now I want broadband. I was once satisfied with memory measured in Ks while now you want multiple Gs. And so it goes.
And if you'll excuse me, I have a computer to fix.
2009/12/06
Hardware Fun
Now I'm putitng on XP SP3. That should take another hour.....
2009/12/04
Gizmo - The Rest of the Story
Just to clarify what I mean by "it works". I have called my laptop with my cellphone. I have called my cellphone with my laptop. I was able to call. I was able to answer. It works.
Google did buy Gizmo, so, like GrandCentral before it, it will soon be integrated directly into the Google stack. Expect it to be integrated first with Google Voice and then with the Android. Which ultimately gets to an interesting point.
My friend Patrick says that when VoIP becaomes universal, VoIP companies will be superfluous. Or words to that effect; I could look it up in my GTalk logs, but nah. When is easy and commonplace for people to call point-to-point via whatever networked device they have, with nothing but TCP/IP between them, what's the point of the AT&Ts and Verizons and Vonages of the world? And with Google making the OS for that device, plus the mechanism (Gizmo) and voice mailbox for this to work, it seems like they're pushing for that future.
Anyway, it's working.
2009/12/02
Love The Phone You're With
But that's not my phone anymore.
Right now, I carry a Samsung Instinct. It is not the phone I want. But it is the phone I have.
I am not a bleeding-edge wired individual, but I have been electronically connected for over 20 years. I'm wired and wireless and all that. And today, Google is the center of all connectivity. Between the phone and the provider, it was quick and painless to set up Google Voice as my voice mail, which is nice. Someone calls you and it translates it and sends it to you. That's sweet. Plus, web interface, which you don't have to deal with the confusing "If you want X, dial 4" stuff.
Google Mail was also an easy config. I do most of my GMail manipulation from Thunderbird via IMAP and between that and sorting, I've gone hog-wild for labels, but the mail interface is inbox-only. This just means I have to be more clear in sorting and filtering to make sure only what I want enters the inbox, but that's OK.
But that's it. I want to sync the on-board calendar with my Google Calendar, but it seems there's no connection capability. I learned the joy of having an online calendar when I worked for the clinic, but the calendar I had was the clinic's Exchange calendar, so I lost all my stuff when I left. The onboard calendar is pretty neat looking, but you can't have it synchronize with my main contacts list in Gmail. Yeah, there's a synch through Sprint, and that's fine. It means I can get my contacts back should I lose my phone, but that still means I manage them through on-screen one-handed typing rather than the full keyboard on my desktop.
I use XMPP, mostly through Google Talk, and the choices I have are AIM, Yahoo or MSN, and I went to GTalk to avoid those three. And there's no connection between my connections in GMail and my phone connections.
Plus, it uses a different power and connect cable than everything else I own, which I think use Micro-AB USB. The industry should unify on one.
But it is pretty, it has Bluetooth, it has a camera, it takes a microSD card, and it works just fine as a phone. It even works in the house, while K's phone kinda doesn't. There are elements I don't like about it, sure, but I do like it. I am decided in being happy with it.
2009/11/29
Testing from the new phone
2009/11/24
Making Graphs with Perl and Chart::Clicker
The Code
#!/usr/bin/perl
use 5.010 ;
use strict ;
use warnings ;
use Chart::Clicker;
use Chart::Clicker::Data::Series;
use Chart::Clicker::Data::DataSet;
my $pi = 3.14159265358979;
sub deg_to_rad { ($_[0]/180) * $pi }
sub rad_to_deg { ($_[0]/$pi) * 180 }
my @core = ( 0 .. 1_000 ) ;
my @sine ;
my @cosine ;
for my $a ( @core ) {
push @sine , sin(deg_to_rad($a)) ;
push @cosine , cos(deg_to_rad($a)) ;
}
my $cc = Chart::Clicker->new;
my $series1 = Chart::Clicker::Data::Series->new(
keys => \@core ,
values => \@sine
);
my $series2 = Chart::Clicker::Data::Series->new(
keys => \@core ,
values => \@cosine
);
my $dataset = Chart::Clicker::Data::DataSet->new(
series => [ $series1 , $series2 ],
);
$cc->add_to_datasets($dataset) ;
$cc->write_output('graph_test.png');
exit ;
There's lots of ways to do graphs. The way we do some graphs here is to do a system call to R. R is powerful, sure, but there's no good way to set up a batch of complex graphs in Perl and send them to R for graphing. There are ways, sure, but not good ways. So, I expect to do a lot more with Chart::Clicker in the future.
2009/11/23
Letting It Go, or Why Ask Why?
This caused the guy to switch his interest. He wanted to know why she could not spell.
Now, if you were a librarian, there trying to help people, and people instead attack you, you would naturally be disinclined to be helpful. In this case, after several repeats of the phrase "This conversation is over", the head librarian was called over and the patron was escorted out the door.
There's a point here. Beyond the obvious "Don't Be An Obsessive-Compulsive Psycho." Clearly, that is important. The point I have is Why is Not Important. Of all the Ws, it is the least important in most parts of your life. Who: Someone, from a waitress to Mordoc, Preventer of Information Services. What: A good or service. Something they have and you want. When: If a deal is being made, urgency has been established. So, now, if not sooner. How: Sometimes this is crucial. As a parent, I know the results when "carefully, half that much, with both hands" is ignored. Someone has to sweep up the broken stuff. But Why? "Why can't you spell?" Is there a possible answer that will be satisfactory? "Ah, so that's why you can't spell! That explains it perfectly!"
I have found that it makes no sense to ask questions when I'm trying to get something done. Give orders? Make requests? Sure. But questions? I don't want to know the answers. I just want what I'm trying to get.
2009/11/19
Windows Essentials?
So, I have the initial install. That was fast enough. There's the drivers to make the thing usable. I shoved a chunk of 'em onto my thumb drive, but I am sure I missed more than a few, including the work printer. After that, go to windowsupdate and get the thing up to the newest. And honestly, I'm still downloading and installing Service Pack 3 here. But that's just minimal function. We're not talking apps yet.
First place I went to was Ninite. There's an awful lot installers you can get at once. I picked up a bunch of browsers — I rock Firefox because Delicious has my bookmarks, but I have Chrome and Safari running, too — plus Hulu and VLC, Microsoft Security Essentials for virus protection and such, .Net and Dropbox and CCleaner and Notepad++ and PuTTY. Not a bad bunch of stuff, but not complete.
Dave Winer calls Dropbox the coolest software of the decade. I'm not quite there yet, but I'm close. It is pretty neat.
I live in a very networked world, and I have 15GB of SSD total on this thing, so I'd rather run Google Apps for what few Office Suite things I need and keep the space. I mean, if I'm somewhere not home and not work, it's very unlikely that I need an office suite. So, I went to get the Google Pack.
All things told, I probably shouldn't have put on Google Earth. Probably too big with little enough use. We'll see.
There's also a whole bunch of tweaks for XP that only come from the source. Power Toys. I first went for TweakUI, but the ClearType Tweaker and Alt-Tab replacement, are really near-essential add-ons. And Virtual Desktop Manager is SO nice.
But that doesn't get into the core issues. I have IE6. It is inexcuable to not have IE8. I need PowerShell. It isn't a Gnome terminal with a
bash
shell, but it's better than Command Prompt.He's a few required SourceForge bits. Synergy allows you to share one keyboard and mouse across many computers, which is great when I'm at work. I can type on a netbook keyboard but I probably couldn't work on one, program on one. And there's XMing, an X server for Windows, which connects to the crucial PuTTY and allows you to have your big heavy windowing applications run on the big server and show up on the netbook as just the pictures.
One thing I'm pondering but not decided on is Growl for Windows. It's like my beloved
notify-osd
with a networking protocol bolted onto it, it seems.Which leads me to these few questions: I need a Perl, but do I need Strawberry or Activestate? And is Notebook++ good enough for my programming on Windows needs, or should I get Komodo Edit? I've gone Komodo for 80% of my coding work.
And the big one. What did I forget? What Windows program have I omitted that's essential and just plain cool?
2009/11/17
jBiff - Announcing New Mail via XMPP/Jabber
I hate having to respond "What email?" So, there's good reasons to have highly-specific alerts. And, to my knowledge, you can't really do that with Thunderbird and Epiphany. So, I began to wonder why I should even use those. Why not use Perl? It has
Net::XMPP
and more than one IMAP module.So, I wrote jBiff. First there was biff, the command line tool. Then there was xbiff. Now, we have jBiff, telling your jabber client "You have mail."
I will put it on Github, soon after I figure out how.
#!/usr/bin/perl
# USAGE
# jBiff.pl -imap-x -s foo -s bar -s blee
use Carp ;
use Data::Dumper ;
use Getopt::Long ;
use IO::Socket::SSL ;
use IO::Interactive qw{interactive} ;
use Mail::IMAPClient ;
use Modern::Perl ;
use Net::XMPP ;
use subs qw{ imap_part xmpp_part } ;
$Data::Dumper::Indent = 1 ;
my @sender ;
my $debug ;
my $xmpp_identity ;
my $imap_identity ;
GetOptions( 'sender=s' => \@sender,
'debug=i' => \$debug,
'xmpp=s' => \$xmpp_identity,
'imap=s' => \$imap_identity, ) or exit( 1 ) ;
exit if !defined $imap_identity ;
exit if !defined $xmpp_identity ;
exit if length $imap_identity < 1 ;
exit if length $xmpp_identity < 1 ;
imap_part @sender ;
# ====================================================================
#
# Pull credentials from a configuration file
#
# ====================================================================
sub get_credentials {
my ( $protocol, $identity ) = @_ ;
my %config_files ;
my %config_vals ;
my %config ;
$config_files{ imap } = '.imap_identities' ;
$config_files{ smtp } = '.smtp_identities' ;
$config_files{ xmpp } = '.xmpp_identities' ;
$config_vals{ imap } = [ qw{
key server port username password directory
} ] ;
$config_vals{ xmpp } = [ qw{
key host component sender password recipient resource
} ] ;
my $stat = ( stat "$ENV{HOME}/$config_files{$protocol}" )[ 2 ] ;
my $hex_stat = sprintf '%04o', $stat ;
if ( $hex_stat != 100600 ) {
say 'You should ensure that this file is not executable,' ;
say ' and not world or group-readable or -writable.' ;
exit ;
}
if ( -f "$ENV{HOME}/$config_files{$protocol}"
&& -r "$ENV{HOME}/$config_files{$protocol}" ) {
if ( open my $fh, '<', "$ENV{HOME}/$config_files{$protocol}" ) {
while ( <$fh> ) {
chomp $_ ;
$_ = ( split m{\#}mx, $_ )[ 0 ] ;
my @creds = split m{\s*,\s*}mx, $_ ;
next if scalar @creds < 6 ;
for my $i ( 1 .. $#creds ) {
my $key = $creds[ 0 ] ;
my $val = $creds[ $i ] ;
my $key2 = $config_vals{ $protocol }[ $i ] ;
$config{ $key }{ $key2 } = $val ;
}
}
close $fh ;
}
my $href = $config{ $identity } ;
return %$href ;
}
else {
say "No Configuration" ;
exit ;
}
exit ;
}
# --------------------------------------------------------------------
# ====================================================================
#
# connect to and search your mail server via IMAP
#
# ====================================================================
sub imap_part {
my @sender = @_ ;
my $sender = join '|', @sender ;
my %creds = get_credentials( 'imap', $imap_identity ) ;
my $socket = IO::Socket::SSL->new( PeerAddr => $creds{ server },
PeerPort => $creds{ port },
) or die "socket(): $@" ;
my $client = Mail::IMAPClient->new( Socket => $socket,
User => $creds{ username },
Password => $creds{ password },
) or die "new(): $@" ;
if ( $client->IsAuthenticated() ) {
$client->select( $creds{ directory } )
or die "Select '$creds{directory}' error: ",
$client->LastError, "\n" ;
for my $msg ( reverse $client->unseen ) {
my $from = $client->get_header( $msg, 'From' ) ;
my $to = $client->get_header( $msg, 'To' ) ;
my $subject = $client->subject( $msg )
or die "Could not subject $@\n" ;
if ( $from =~ m{$sender}i ) {
my $title = 'New mail from ' . $from ;
my $body = $subject ;
$body = join q{"}, '', $body, '' ;
xmpp_part "$title - $body" ;
}
}
$client->logout() ;
}
else {
say 'FAIL ' . $! ;
}
}
# --------------------------------------------------------------------
# ====================================================================
#
# send message via XMPP/Jabber
#
# ====================================================================
sub xmpp_part {
my $args = shift ;
my %creds = get_credentials( 'xmpp', $xmpp_identity ) ;
# connection
my $hostname = $creds{ host } ;
my $port = 5222 ;
my $componentname = $creds{ component } ;
my $connectiontype = 'tcpip' ;
my $tls = 1 ;
#login
my $username = $creds{ sender } ;
my $password = $creds{ password } ;
my $resource = $creds{ resource } ;
#msg_to
my @field ;
push @field, $creds{ recipient } ;
my $Connection = new Net::XMPP::Client() ;
# Connect to talk.google.com
my $status = $Connection->Connect( hostname => $hostname,
port => $port,
componentname => $componentname,
connectiontype => $connectiontype,
tls => $tls ) ;
if ( !( defined( $status ) ) ) {
print "ERROR: XMPP connection failed.\n" ;
print " ($!)\n" ;
exit( 0 ) ;
}
# Change hostname
my $sid = $Connection->{ SESSION }->{ id } ;
$Connection->{ STREAM }->{ SIDS }->{ $sid }->{ hostname } = $componentname ;
# Authenticate
my @result = $Connection->AuthSend( username => $username,
password => $password,
resource => $resource ) ;
if ( $result[ 0 ] ne "ok" ) {
print "ERROR: Authorization failed: $result[0] - $result[1]\n" ;
exit( 0 ) ;
}
# Send messages
foreach ( @field ) {
$Connection->MessageSend( to => "$_\@$componentname",
resource => $resource,
subject => "Notification",
type => "chat",
body => $args ) ;
}
$Connection->Disconnect() ;
}
# --------------------------------------------------------------------
2009/11/14
Pieces-Parts To Program, Toward A Better Programming Life.
What we do have is the TVGuide Channel. Which is the Michael Jackson and Ugly Betty channel, which sucks.
And TVGuide.com, which never remembers the settings I want to have it set. It's a reasonable. But there's the big big big table of all that's on. I don't care about that. I have a much smaller list of shows I want to watch.
And want to watch is a key. We're not talking is fine to watch, which I can search for the best thing right now. I'm talking about the things I want to be sure for the whens of my favorite shows.
This is what I want, what I think I can do.
- get_TV_data - an API to access what's on what channel
- set_google_calendar_event - an API to create an event on a Google Calendar calendar. I want this anyway, and I'm pretty sure that it's on CPAN.
- google_calendar_alert - When you set an event in Google Calendar, it will either pop up (useless if you're not in Google Calendar), send an email, or send an SMS, which is essentially an email. What I want is for it to talk to me via GoogleTalk, which is Jabber, or XMPP. I have the XMPP part, I more than have that, so it's just the reading of the calendars.
Everything on that is pie in the sky, but it should be doable.
2009/11/12
Another Little Pessimizations
.alias
:alias realias='$EDITOR ~/.aliases; source ~/.aliases'
I just came up with another one. This one should go into your crontab:
0 * * * * /usr/bin/crontab -l > ~/.latest_crontab
Every hour, on the hour, it copies your crontab into a local directory.
I just reinstalled Ubuntu, hoping that this fixed the problem that occurred after the Jackalope->Koala upgrade. It didn't, but I lost some stuff, including my crontab. I have a separate partition for /home, so I didn't lose everything in the reinstall, but crontabs are not stored in your local dir and thus are wiped.
And, thank you Damian Conway and chromatic for the realias thing!
That's It!
notify-osd
back!I have a Radeon 7000 dual-head card, and evidently there's a known issue with the driver that comes with Ubuntu Koala. Saying
Driver "vesa"
like the thread said didn't work, but telling my X config to shut off hardware accelleration did.
Section "Device"
Identifier "Card0"
Driver "radeon"
VendorName "ATI Technologies Inc"
BoardName "Radeon RV100 QY [Radeon 7000/VE]"
BusID "PCI:1:0:0"
Option "NoAccel" "TRUE" # []
EndSection
Will post a pic with all the goodness running later. Thanks, Shub-Internet!
Other Broken Things in Ubuntu Koala
This is Gnome System Monitor. In an ugly pink punk tartan.
Thing is, it's usable, except it's not. I mean, I can right-click and I get a drop-down in some other indecipherable pattern. I can double-click where the angry pink tartan should have a menu and have it roll up like any other window. I just can't see it!
Any thoughts as to how to fix this?
2009/11/06
notify-osd is broken under Ubuntu Koala
At least for me. Because that image, which shows a pink punk tartan, should be telling me that it's 55° and sunny in my home town today. I wrote a script that gathered the weather, put on a nice icon and displayed it. And it worked under Jaunty. But when I upgraded to Karmic, no dice. And now, after I spent the morning reinstalling , still no dice.
Any thoughts? Any help?
2009/10/30
Configuration: The Devil is in the Details
This is where FTP, and especially the Perl module
Net::FTP
, come in. We try to keep it locked down, configured at the firewall so that only the server can FTP into the instrument and even then can only move instrument->server, not the other way around. One specific machine was set up with Windows 2000 and the FileZilla FTP server. The software, we were told, wanted 2K, and so we ran with that. FileZilla was about the first Google result I hit when I searched on "windows ftp server", and I cannot say there was ever a point where I regretted using FileZilla for all my FTP needs.
Then there was a necessary upgrade that needed Windows XP. The machine had 2 HDs in it, so I installed XP on disc 2 and made it dual boot. And, since it was XP Pro, I had IIS already. I may have had it on the 2K, I never thought to check. Anyway, the machine now spends most of the time under XP. I have had to change the upload-and-munge script to handle the new, and I'm not sure how much is IIS-vs-FileZilla and how much is Instrument-Software 1.3 vs Instrument-Software 2.0.
Where the story threatens to become interesting is this: The person who runs on that instrument, she makes a CSV config. Normally, she copys it, changes it, and seemingly, as long as the Excel file was open, it wouldn't upload. This was the 2K and FZ behavior.
Windows XP and IIS, it seems, FTP anyway, no matter if the Excel file is still open. And I had to clean up after it because of it. Not a problem, to be sure, but something to be aware of.
2009/10/29
My first Perl one-liner
jacoby@oz:~$ ls -l *iso | perl -E 'while (<STDIN>) { $x=(split m{\s+}mx , $_)[4] ; say int $x * 100 / 723488768 , "% done" } '
I'm downloading Ubuntu 9.10 via FTP. I know the final size. Via
ls
I know the current file size. if a/b = y/100, where a = the current size, b = the final size and y = the percentage done, this gets the data and solves for y and converts to an integer. (Do I really need it to seven points? No.).Thank you
-E
for making command-line Perl so much easier
Running an OddMuse wiki with CKeditor
I have always liked the function. I have not always liked the name. It seems like I'm cussing, which is something I have spent some time trying to stop doing. If I resort to vulgarity, I want it to be because the circumstances have overwhelmed me, not because they reside in the forefront of my vocabulary, and
FCK
reminds me of a shirt. Never mind the fact that the programmer named it after himself, Frederico Caldeira Knabben.I must not have been the only person feeling like that, because the new name is CKeditor. But while there are docs for making my wiki engine of choice work with FCKeditor, not so much for the shiny new CKeditor. And it is shiny....
The problem, at the moment, is that I can get it to write wiki markup but I can't get it to write and save HTML, which really is helpful if you want to display tables, which I do.
Will post code once I figure it out
2009/10/27
Reading IMAP directories with Perl
The thing that sucks is alerting. If a mailing list gets updated, don't tell me. I shunt that stuff off into a subdirectory for a reason. In fact, there are three classes of people whose emails I want alerts about:
- Family — mostly my wife and parents, but also my children, cousins, etc.
- Bosses and Co-Workers — If you're involved in me getting paid, of course I need to know when you contact me
- Friends — this is a low third, which is understandable, I hope.
So, I looked into Perl's
Mail::IMAPClient
.
#!/usr/bin/perl
use Modern::Perl ;
use IO::Socket::SSL ;
use Mail::IMAPClient ;
use Getopt::Long ;
use Carp ;
use Data::Dumper ;
$Data::Dumper::Indent = 1 ;
my $server = 'imap.gmail.com' ;
my $username = 'me' ;
my $password = 'nope' ;
my @sender ;
GetOptions(
'sender=s' => \@sender ,
) ;
my $sender = join '|' , @sender ;
my $socket = IO::Socket::SSL->new(
PeerAddr => $server ,
PeerPort => 993,
)
or die "socket(): $@";
my $client = Mail::IMAPClient->new(
Socket => $socket,
User => $username ,
Password => $password ,
Ignoresizeerrors => 1 ,
)
or die "new(): $@";
if ( $client->IsAuthenticated() ) {
$client->select( 'INBOX' )
or die "Select 'INBOX' error: ", $client->LastError, "\n";
#for my $msg ( reverse $client->messages ) {
for my $msg ( reverse $client->unseen ) {
#my $string = $client->message_string($msg)
#or die "Could not message_string: $@\n";
my $from = $client->get_header( $msg , 'From' ) ;
my $to = $client->get_header( $msg , 'To' ) ;
my $subject = $client->subject($msg)
or die "Could not subject $@\n";
if ( $from =~ m{$sender}i ) {
my $notify = '/usr/bin/notify-send' ;
my $title = 'New mail from ' . $from ;
my $body = $subject ;
my $icon = '-i ~/Pictures/Icons/icon_black_muffin.jpg' ;
my $time = '-t ' . (1000 * 10 ) ;
$body =~ s/(['"])/\\$1/g;
$title =~ s/(['"])/\\$1/g;
$title = join q{"} , '' , $title , '' ;
$body = join q{"} , '' , $body , '' ;
qx{ $notify $title $body $icon $time } ;
}
}
$client->logout();
}
It takes one or more sender substrings.
mail_notify.pl -sender '@purdue.edu'
, for example, would pop notifications from all mail from Purdue University addresses. And the good thing is, you don't need to change much more than the server name, username and password to make it work on my work server.2009/10/26
TV: Conjecture about White Collar
White Collar is a show on USA Network. The main character is Neil Caffrey, a con man. He was caught by Peter Burke, an FBI agent. He escapes on the cusp of his release, looking for his wife. Peter catches him again, and, in part inspired by his sense of fairness, springs him to serve as a consultant. There we have the premise.
At one point, Peter is looking for a way to get a warrant to enter a warehouse he is sure but cannot prove is the location of a crime scene. Neil, a criminal not a cop, wonders why they just don't go in. Peter then passes him the Big Book of Warrant Law. Neil reads the Big Book, figures it out, and gets himself and the ankle bracelet location tracker dragged into the warehouse. Peter knows the game when he follows the machine-gun-toting FBI entry team into the warehouse, quoting chapter and verse as to why he can go in without a warrant. I don't know that Peter knew what he was doing when he gave the book, but he certainly knew when he got there.
Consider, for a moment, The Sting. That's the great con movie, and while we're in on great parts of the con, we don't know the final bit until the end. Same with the Ocean's Eleven remake. The audience can't know it all. So, what's the underlying con for White Collar.
We don't know what's going on with Neil's wife, but we know
- Neil knows Peter about as well as Peter knew Neil
- This includes Peter being smart and liking smart, and we mean really smart. He has great ire over the large number of Harvard graduates in his unit who are not nearly as on-the-ball as he is.
2009/10/23
Trying Dropbox
/home/jacoby/Dropbox/
, where I can put things. I put it there, and after some time for uploading and downloading, the items in that directory are placed in C:/Documents and Settings/jacoby/My Documents/My Dropbox/
on my netbook, and the ~/Dropbox/
directory at home.Isn't that cool?
I can also tell DropBox to share a subdirectory or file with friends who also use DropBox.
This is where you come in.
Sign up and you get to share things with me, and we both get 256MB additions to our default 2GB disk quota.
The thing I'm starting to do is put the images I use a lot, my favorite user icons and background images, in
~/Dropbox/Photos?
so that they're effortlessly spread across all the places I'd use them. I'm also considering a ~/Dropbox/bin/
directory that will hold the scripts I go to most often. A poor excuse to not sit down and learn to love git
, true, but still kinda neat.2009/10/21
A Few Words on Net Neutrality
This capability is built into the high-level switches that ISPs use. There's an acronym, QoC for "quality of service", that's all about this kind of thing.
I used to use a service, and I did like it, called Vonage. This provides VoIP, or Voice over IP. My ISP, which also does cable TV, is becoming a competitor to Vonage, handling their own VoIP. It seems like it would be relatively simple to throttle network going to and from Vonage just like they throttle traffic handling BitTorrent packets. This would be technologically easy for them — we've established that they have the technology — but if you, like me, have decided that Vonage is the way you want to go, you get tired of an ISP that sucks like that and move on to one that doesn't suck like that.
This is what I understood Net Neutrality to be about.
But I'm thinking I might be getting to be wrong about that.
I think my statements so far shows my biases. To a certain extent, shaping the traffic of a network to make it more usable is the business of an ISP. But there are points where that is illegitimate. My feeling is that Networks should have Neutrality, but that, with an acceptable level of competition, ISPs that don't mess with you have a competitive advantage over those who do. But, ultimately, that's an issue between the people who provide the network to my house and the people who have things running on their servers. As a programmer, I can see myself eventually working for a start-up, but beyond that, really, there's little direct effect this would have on me personally, and for most people.
Glenn Beck is Glenn Beck. Like him or not. I'm not going to try to argue into accepting him. Skip ahead to 3:55 and you see Van Jones talking about Net Neutrality. Or something that's unrelated to Net Neutrality as I understand it, but going by that name. Net Neutrality meaning free internet to everybody, that doesn't seem ... well, forget "right" or "wrong". It doesn't seem related to the subject at hand.
Let us step back and look sideways. Let us assume that this graph is right. Phones these days have more powerful chips than any computer I had before 2002. And that's Verizon, AT&T, Sprint, T-Mobile — lots of companies that are ISPs. I'm not seeing the problem Van Jones sees, but I can see that Net Neutrality having a generally neutral effect on the population at large.
But what, if anything, am I missing?
2009/10/20
Perl IS a community!
Perl::Critic
on it. This is less a tool to debug your non-functioning program than a program that tells you a better way to have your functioning program function, but I thought it could tell me something.I generally start all my programs these days with:
This takes the place of this:
use Modern::Perl ;
This is very nice, in that it gets you to the cool stuff in Perl in one line.
use 5.010 ;
use strict ;
use warnings ;
But...
Perl::Critic
wants you to run using strict
and warnings
, and when you use Modern::Perl
, it doesn't explicitly say that you are using them, and Critic dinks you for it. I thought that was interesting.
And, today, when you find something interesting, you tweet it. I also put it on Identi.ca, which is like twitter but mostly programmer types go there. And I got a response. From chromatic on identi.ca and from the Critic folks on Twitter.
That just warms my heart. Not specifically the help to make it work, which is of course great, but that the developers are listening.
And, incidently, making a
.perlcritic
file with this in it makes it work:
equivalent_modules = Modern::Perl
2009/10/19
Modern One-Liner Perl
But now, by going -E instead of -e, you bring in Perl 5.10. This means you get
perl -e 'print 51 * 51 , "\n"'
say
, which is by far my fave Perl 5.10 addition. I'm already starting to do one-liners more, now that I have
perl -E 'say 51 * 51'
say
. Using realias
is also helpful with this.Credit where due.
2009/10/09
Avoiding Wallop with Perl
#!/usr/bin/perl
use Modern::Perl ;
use File::Copy ;
my $from = '/home/jacoby/test.test.pl' ;
my $to = '/home/jacoby/target.target.pl' ;
while ( -f $to ) {
my @to = split m{\.}mx , $to ;
my $suffix = pop @to ;
if ( scalar @to == 1 ) {
my $num = 1 ;
push @to , $num ;
push @to , $suffix ;
}
elsif ( $to[-1] !~ m{\D}mx ) {
my $num = pop @to ;
$num ++ ;
push @to , $num ;
push @to , $suffix ;
}
else {
my $num = 1 ;
push @to , $num ;
push @to , $suffix ;
}
$to = join '.' , @to ;
}
say "F\t" . $from ;
say "T\t" . $to ;
copy $from , $to ;
2009/09/29
Perl Rocks
In lieu of content, I'll just say this:
Perl Rocks!
2009/09/25
Gizmo + GoogleVoice = Frustration
I'm a big fan of the idea of GoogleVoice, but I don't have a cell phone at the moment and work in a sub-basement anyway, so I want to use it with a computer phone. But I've been on this before.
What I have changed is Auto-Answer. I clicked that and tried again. I hear the voice, but I can't input the numbers. Go to about 8:35 on the YouTube video above and you'll see exactly won't come up.
Skype won't uninstall, so I'm reinstalling to deinstall. I hope that will help.
2009/09/23
Desperately Seeking Google Weather API Vocabulary
I have since found
notify-send
(mentioned here) and have found a set of weather icons that I like. And I'm working on getting the notifications look good.My problem is that I'm not seeing a one-to-one mapping between the condition strings I'm getting from Google and the file names I'm getting from the icon sets. Nor are the image names listed in the XML.
So, I created a simple mapping of Condition strings to icon names.
This is a list of weather conditions that were observable in the American Midwest in summer and early fall, 2009. This is not the whole list of weather conditions.
sub config_icons {
my $path = '/home/jacoby/Pictures/weather_icons/' ;
my %config ;
$config{ 'Clear' } = $path . 'sunny.png' ;
$config{ 'Partly Cloudy' } = $path . 'cloudy1.png' ;
$config{ 'Mostly Cloudy' } = $path . 'cloudy3.png' ;
$config{ 'Cloudy' } = $path . 'cloudy5.png' ;
$config{ 'Overcast' } = $path . 'overcast.png' ;
$config{ 'Haze' } = $path . 'fog.png' ;
$config{ 'Fog' } = $path . 'fog.png' ;
$config{ 'ELSE' } = $path . 'dunno.png' ;
return \%config ;
}
What I am looking for today are the other ones, so I can finish this code and maybe send it out to you. Any help?
2009/09/16
The better way for Javascript
x.split()
. Which I include below the cut.The hostname you want to redirect to is placed at your discretion as
$(function() {
var protocol = window.location.protocol ;
var hostname = window.location.hostname ;
var path = window.location.pathname ;
var query = window.location.search ;
var hash = window.location.hash ;
var url = protocol + '//' + host + path + query + hash ;
if ( host != hostname ) {
window.location.replace( url ) ;
}
} ) ;
var host
, but I choose not to include it here. The only jQuery aspect to this is the wrapper, which makes this script run when the page is fully loaded. Which probably isn't strictly necessary. And this does work on both IE and FF.2009/09/15
Compiling Rakudo on Ubuntu
I tweeted it, of course, and got a response.
@JacobyDave It works over here. Which instructions did you use? I use http://rakudo.org/how-to-ge...about 3 hours ago from Tweetie in reply to JacobyDave
So, of course, I had to try it.
jacoby@oz:~$ $ git clone git://github.com/rakudo/rakudo.git
bash: $: command not found
It seems I didn't have git installed.
jacoby@oz:~$ apt-cache git
E: Invalid operation git
jacoby@oz:~$ apt-cache search git | wc -l
502
jacoby@oz:~$ apt-cache search git | grep -i '^git'
git-core - fast, scalable, distributed revision control system
git-doc - fast, scalable, distributed revision control system (documentation)
gitk - fast, scalable, distributed revision control system (revision tree visualizer)
git - transitional dummy package which can be safely removed
git-arch - fast, scalable, distributed revision control system (arch interoperability)
git-buildpackage - Suite to help with Debian packages in Git repositories
git-cola - highly caffeinated git gui
git-cvs - fast, scalable, distributed revision control system (cvs interoperability)
git-daemon-run - fast, scalable, distributed revision control system (git-daemon service)
git-email - fast, scalable, distributed revision control system (email add-on)
git-gui - fast, scalable, distributed revision control system (GUI)
git-load-dirs - Import upstream archives into git
git-svn - fast, scalable, distributed revision control system (svn interoperability)
gitmagic - Guide about Git version control system
gitosis - git repository hosting application
gitpkg - helper scripts for maintaining packages with git
gitweb - fast, scalable, distributed revision control system (web interface)
jacoby@oz:~$ sudo apt-get install git gitmagic git-doc
[sudo] password for jacoby:
Reading package lists... Done
Building dependency tree
Reading state information... Done
git is already the newest version.
Suggested packages:
git-core git-arch git-cvs git-svn git-email gitk gitweb
The following NEW packages will be installed:
git-doc gitmagic
0 upgraded, 2 newly installed, 0 to remove and 8 not upgraded.
Need to get 1333kB of archives.
After this operation, 6136kB of additional disk space will be used.
Get:1 http://us.archive.ubuntu.com jaunty/main git-doc 1:1.6.0.4-1ubuntu2 [1126kB]
Get:2 http://us.archive.ubuntu.com jaunty/universe gitmagic 20090101-1 [207kB]
Fetched 1333kB in 2s (587kB/s)
Selecting previously deselected package git-doc.
(Reading database ... 206981 files and directories currently installed.)
Unpacking git-doc (from .../git-doc_1%3a1.6.0.4-1ubuntu2_all.deb) ...
Selecting previously deselected package gitmagic.
Unpacking gitmagic (from .../gitmagic_20090101-1_all.deb) ...
Processing triggers for doc-base ...
Processing 1 added doc-base file(s)...
Registering documents with scrollkeeper...
Setting up git-doc (1:1.6.0.4-1ubuntu2) ...
Setting up gitmagic (20090101-1) ...
jacoby@oz:~$ $ git clone git://github.com/rakudo/rakudo.git
bash: $: command not found
jacoby@oz:~$ git clone git://github.com/rakudo/rakudo.git
The program 'git' is currently not installed. You can install it by typing:
sudo apt-get install git-core
bash: git: command not found
jacoby@oz:~$ sudo apt-get install git-core
Reading package lists... Done
Building dependency tree
Reading state information... Done
Suggested packages:
git-arch git-cvs git-svn git-email git-daemon-run git-gui gitk gitweb
The following NEW packages will be installed:
git-core
0 upgraded, 1 newly installed, 0 to remove and 8 not upgraded.
Need to get 4322kB of archives.
After this operation, 8995kB of additional disk space will be used.
Get:1 http://us.archive.ubuntu.com jaunty/main git-core 1:1.6.0.4-1ubuntu2 [4322kB]
Fetched 4322kB in 7s (599kB/s)
Selecting previously deselected package git-core.
(Reading database ... 207451 files and directories currently installed.)
Unpacking git-core (from .../git-core_1%3a1.6.0.4-1ubuntu2_i386.deb) ...
Processing triggers for man-db ...
Setting up git-core (1:1.6.0.4-1ubuntu2) ...
Setting up git-core (1:1.6.0.4-1ubuntu2) ...
jacoby@oz:~$ git clone git://github.com/rakudo/rakudo.git
Initialized empty Git repository in /home/jacoby/rakudo/.git/
github.com[0: 65.74.177.129]: errno=Connection timed out
fatal: unable to connect a socket (Connection timed out)
jacoby@oz:~$ jacoby@oz:~$
Needed to open up a hole in the firewall to allow git.
jacoby@oz:~$ git clone git://github.com/rakudo/rakudo.git
Initialized empty Git repository in /home/jacoby/rakudo/.git/
remote: Counting objects: 18798, done.
remote: Compressing objects: 100% (5049/5049), done.
remote: Total 18798 (delta 13754), reused 18345 (delta 13370)
Receiving objects: 100% (18798/18798), 2.49 MiB | 723 KiB/s, done.
Resolving deltas: 100% (13754/13754), done.
Creating Makefile ...
Cleaning up ...
You can now use 'make' to build Rakudo Perl.
After that, you can use 'make test' to run some local tests,
or 'make spectest' to check out (via svn) a copy of the Perl 6
official test suite and run its tests.
jacoby@oz:~/rakudo$ make
/home/jacoby/rakudo/parrot_install/bin/parrot /home/jacoby/rakudo/parrot_install/lib/1.6.0-devel/library/PGE/Perl6Grammar.pbc \
--output=src/gen_grammar.pir --encoding=utf8 \
src/parser/grammar.pg src/parser/grammar-oper.pg
jacoby@oz:~$ cat hello.pl
say 'hello' ;
jacoby@oz:~$ rakudo/parrot_install/bin/perl6 hello.pl
hello
jacoby@oz:~$
It compiles on my Jaunty Ubuntu box. I don't have a clue as to why it wouldn't compile on his Fedora box. And, at some point, I'll have to try it on Windows.
2009/09/11
Why People Hate Javascript, or Must Mean Chum
But in IE, I got bouunced to some weird, wrong URL. So, I added some debug code to figure out what's going on.
Here's the code that generated this, with dyked-out relocation code.
$(function() {
var u = $( document ).attr('URL') ;
var v = u.split( /\//g )[2] ;
var w = u.split( /\//g ) ;
if ( v != host ) {
w[2] = host ;
x = w.join('/') ;
alert( u + '\n' + v + '\n' + w + '\n' + x + '\n') ;
// window.location.replace( x ) ;
}
} ) ;
u
is the URL. Both the same.v
should be the host, which is the problem. A url looks like this: protocol://host/path/?querystring
, where path
could contain many slashes. Split on slashes, protocol
should be the first element, or element [0]. Element [1] should be blank. Element [2] should be host.But it just isn't.
w
is an array, made from the URL and joined with a comma for display purposes. The alert from Firefox says http,,host,path
, showing a blank element 1, as it should be. The alert from IE says http,host,path
. Evidently, it thinks the regular expression was variable.split( /\/+/g )
,which matches and splits on one or more slash, rather than variable.split( /\//g )
, which matches and splits on one and only one slash.There is a scene in Cabin Boy where Chris Eliot, a candidate for upper-class twit of the year, tells the existing cabin boy (Andy Richter) that he wants some fancy soup for dinner. The cabin boy walks off and decides "He must mean chum". Chum is rotting fish guts. Microsoft decided that I must have meant chum.
2009/09/08
Flawed Perl
notify-send
program which connects to Gnome's OSD setup and you can get some pretty cool stuff.Except, it seems, something doesn't like Unicode.
At first, I thought the problem was on
notify-send
, but 1) remembering what had gone on with my twitter weather script (@PurdueWeather) and 2) testing with direct use of Unicode made me decide that it's Perl's fault.And there are many solutions.
It strikes me that there should be something along the lines of
use Unicode ;
that, with one line, tells Perl you're using Unicode strings. I'm sure there's a Unicode module, and I'm reasonably sure that's not what it does.Anyway, code for using
notify-send
and the Google Weather API to tell you what's going on with the atmosphere is under the cut. For my next trick, I will add images.
#!/usr/bin/perl
# $Id: hpsetdisp.pl 11 2006-03-22 01:21:03Z yaakov $
# hpsetdisp.pl
# Connects to a JetDirect equipped HP printer and uses
# HP's control language to set the ready message on the
# LCD display. Takes an IP address and message on the
# command line. My favorite message is "INSERT COIN".
# Keep in mind the limitations of the display when composing
# your clever verbiage.
#
# THIS PROGRAM IS PROVIDED WITH NO WARRANTY OF ANY KIND EXPRESSED OR IMPLIED
# THE AUTHOR CANNOT BE RESPONSIBLE FOR THE EFFECTS OF THIS PROGRAM
# IF YOU ARE UNCERTAIN ABOUT THE ADVISABILITY OF USING IT, DO NOT!
#
# Yaakov (http://kovaya.com/ )
#
# Modified by Garrett Hoofman
# 10/18/2007
# http://www.visionsofafar.com
# Modified by David Jacoby
# 12/10/2008
# http://varlogrant.blogspot.com/
# Modified by David Jacoby, using notify-send and tweaking Unicode
# 09/08/2008
# http://varlogrant.blogspot.com/
use strict ;
use warnings ;
use 5.010 ;
use Getopt::Long ;
use IO::Interactive qw{ interactive } ;
use IO::Socket ;
use XML::DOM ;
use Data::Dumper ;
use subs qw{ get_weather notify } ;
my $zip = '' ;
my $forc = 'F' ;
my $interactive = '' ;
my $degree = '°' ; #the unicode, straight
$degree = "\x{00b0}" ; #the unicode, specified
my $rdymsg = "Ready" ;
GetOptions(
'zipcode=s' => \$zip ,
'forc=s' => \$forc ,
) ;
if ( $forc eq 'c' || $forc eq 'C' ) { $forc = 'C' }
else { $forc = 'F' }
$zip !~ /\d/ and exit 0 ;
my $weather = get_weather ;
notify $weather ;
exit ;
########## ########## ########## ########## ########## ########## ##########
sub get_weather {
my $rdymsg ;
my $parser = XML::DOM::Parser->new() ;
my $file = 'http://www.google.com/ig/api?weather=XXXXX&hl=en' ;
#my $zip = shift ;
$zip =~ s{(\d{5})}{}mx ;
$zip = $1 ;
$file =~ s/XXXXX/$zip/mx ;
my $doc = $parser->parsefile( $file ) ;
my $city =
$doc->getElementsByTagName( 'city' )->item( 0 )->getAttribute('data') ;
my $curr_temp ;
if ( $forc eq 'C' ) {
$curr_temp =
$doc->getElementsByTagName( 'temp_c' )->item( 0 )->getAttribute('data') ;
}
else {
$curr_temp =
$doc->getElementsByTagName( 'temp_f' )->item( 0 )->getAttribute('data') ;
}
my $curr_cond =
$doc->getElementsByTagName( 'condition' )->item( 0 )->getAttribute('data') ;
my @output ;
push @output , qq{Conditions for $city} ;
push @output , qq{ $curr_temp$degree $forc, $curr_cond } ;
return join "\n" , @output ;
}
########## ########## ########## ########## ########## ########## ##########
########## ########## ########## ########## ########## ########## ##########
sub notify {
my $notify = '/usr/bin/notify-send' ;
my $weather = shift ;
say qq{ $notify $weather } ;
$weather = join q{'} , '' , $weather , '' ;
qx{ $notify $weather } ;
return ;
}
########## ########## ########## ########## ########## ########## ##########
2009/09/02
People share the gift of gab between themselves
But that just means that I can hear the voice mail. What if I want to answer?
Lifehacker has a post on using Gizmo to do just that. They make it sound so simple. Set up Gizmo. Tell Google Voice you have a Gizmo Phone. Have Google Voice confirm your Gizmo number. Then you're golden.
Unless you're not.
Here is my entirely unhelpful order of events.
- Tell Google Voice I want to verify my Gizmo phone.
- My computer rings.
- Time passes.
- Google Voice gives up.
- Gizmo's soft phone pops up to tell me I have a missed call.
It might be something simple and stupid. My current cannot-be-checked-at-work theory about my wife's laptop is that it's a permissions error. I'll work it out and see.
Oz never gave nothin' to the Tin Man...
We got the Mini with a deal with Sprint. We get the card Bill Kurtis has been pushing, which would allow someone to use the Internet when far away from wireless access points, using the Sprint cell network for data. It also provides good and useful GPS information like location and speed and the way to the closest Sprint store. I got a netbook out of the deal (yay) but I live in a house with Wi-Fi and work in a dank sub-basement with Wi-Fi and sufficient network cables. I don't find the need to check email much when I'm not either at work or at home. However, K spends her day running around a lot. It therefore makes reasonable sense for her to use it. So she asked me if she could have it.
Let me cut to the end, of the story, just for a moment. The dingus, once set up, is set up. You have to reinstall the interface software, sure, but anything you plug it into should be able to quickly get online, because by plugging it in you've done all you have to do to log onto the network.
Unless you have some sort of problem with your USB. Which Twiki seems to have.
* In the beginning of the Mystery Science Theater take on Catalina Caper, Joel has the bots say their prayers, even for Twiki. My eldest asked "Who is Twiki?" This is the description I gave.
There was a show in the late 70s and early 80s called Buck Rogers. There was a character whose name I don't recall, who was a hyperintelligent computer which takes the form of a of a blinged-out hubcap. Being a hubcab, that character cannot move, so there's Twiki, who looks like a cartoon seven-year-old with a bowl cut frozen in carbonite, who wears the blinged hubcap like Flavor Flav wears a clock.
This caused my son to laugh out loud.
I know the time, boieee
The installer comes with the Sprint card, and I have installed it four times. I have talked to the Sprint helpdesk. I have tried this process on three (3) computers ( Twiki, Tinman and Maria, named after the evil Maria from Metropolis ) and the problem comes up only on Twiki. Yeah, I have other Windows machines I can test against, sure. But the take-away seems that there's something wrong with K's machine.
Just had a thought. K might not be running as Admin. In general, that's good, but if she is, she can't install the drivers in the protected places and thus can't get networking going. I thought she was running with Admin privs, but I do not recall. Still, that's worth a look. ETA I checked, and she's running as Admin. It isn't that.
2009/08/28
Enabling "Read More"
Just to know, I use a more modern template for this blog, and this post will use those conventions.
- Modifying The Post Template
When you move to make a new post, you have to add aspan
element named "fullpost".
Settings<<
Formatting, toward the bottom of the page. - Adding The "Read More" Text
Now we have to move to editing the template. You find it here: Layout<<
Edit HTML. You are modifying the Post widget at this point, so you have to checkExpand Widget Templates
. Look for this line within the Template:<data:post.body/>
I am not sure what the underlying engine is processing this code — I'm sure I could find out without too much trouble, but here we're adding a conditional which adds this chunk of text and a link if the pageType is notitem
.
This adds a link to the bottom of the page. It does not hide the contents of the element we added to the template. Yet.
<data:post.body/>
<b:if cond='data:blog.pageType != "item"'><br /><a expr:href='data:post.url'>Read more!</a></b:if> - Changing The Display Here we get into the wonder of Cascading Style Sheets (CSS). CSS is all about controlling how your page looks. The block that holds the CSS looks much like this:
The recommended code to hide the Read More text is as follows:
<b:skin><![CDATA[
... Large Chunks Removed ...
]]></b:skin>
The problem I have found is that the CSS addition breaks the page a little and doesn't work. What I have found to work is putting a
<b:if cond='data:blog.pageType == "item"'>
span.fullpost {display:inline;}
<b:else/>
span.fullpost {display:none;}
</b:if>style
block right under the generated block and putting the code within that:
]]></b:skin>
<style>
<b:if cond='data:blog.pageType == "item"'>
span.fullpost {display:inline;}
<b:else/>
span.fullpost {display:none;}
</b:if>
</style>