Monday, May 16, 2011

Installing xmgrace on Snow Lepoard

You want to install grace (xmgrace) on Snow Leopard, but all the information that you find online is obsolete and confusing.
  1. Make sure you have MacPorts.
  2. > sudo port install grace

Friday, April 29, 2011

¿Se escribe con o sin acento?

Con acentoSin acento
por qué - why, el porqué - the reason porque - because
sí - yes, sí mismo - oneself si - if
sólo - only solo - alone
tú - you tu - your

Tuesday, March 22, 2011

Run script in OS X on network connection

You want to automatically run a script in OS X every time there is an update in your network connection (e.g. going on- and offline). In particular you may want to run a script to gather information about your environment, guess your current location and execute some tasks accordingly. Also, for some weird reason, you don't want to use an application such as MarcoPolo or Proxi in order to do this.

By far the most reliable way to do this is using crankd that, in a very similar way to launchd, allows you to run scripts in response to events such as network changes, filesystem activity, and application launching. The process to get started is not terribly complicated, but you need to be careful following instructions.
  1. Download and install PyMacAdmin, this includes crankd.
  2. Once installed, open a terminal and run /usr/local/sbin/crankd.py. For some reason on my computer it crashes with an error about an undefined NSNotificationHandler, however you can safely disregard that. If it didn't crash type Ctrl+C to exit the program. The important point is that it would have created an example configuration file in:
    ~/Library/Preferences/com.googlecode.pymacadmin.crankd.plist.
  3. Open the configuration file in a text editor and modify it so that it looks like the following:
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
        <key>SystemConfiguration</key>
        <dict>
            <key>State:/Network/Global/IPv4</key>
            <dict>
                <key>command</key>
                <string>/absolute/path/to/your/script</string>
            </dict>
        </dict>
    </dict>
    </plist>
  4. This will cause your script to be called every time that there is a change in your connection, in particular when going on- and offline. If you want to test and debug your script, you can go back to your terminal and run /usr/local/sbin/crankd.py. On the output you will also get sensible messages about what crankd is doing. Try turning on/off your wireless connection, or plugging and unplugging your ethernet cable.
  5. If everything seems to work, now you probably would like to have your system automatically run and keep alive the crankd daemon. For this we use, as usual, launchd. Create a new file such as ~/Library/LaunchAgents/org.crankd.plist with the following contents:
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
        <key>KeepAlive</key>
        <true/>
        <key>Label</key>
        <string>org.crankd.plist</string>
        <key>ProgramArguments</key>
        <array>
            <string>/usr/local/sbin/crankd.py</string>
        </array>
        <key>RunAtLoad</key>
        <true/>
    </dict>
    </plist>
  6. To start the daemon right now, type the following on the terminal:
    > launchctl load ~/Library/LaunchAgents/org.crankd.plist
  7. That's it. Turn your connection on/off to check that your script is working properly. The daemon will also be automatically started the next time you restart your computer.
By the way, if you are reading this you probably also want to know how, within your script, to detect whether you have an active connection and, if you do have a connection, to somehow guess your current location. Some good ideas are to check the contents of the file /etc/resolv.conf (the file doesn't exist if you're offline), or to have a look at the output from ifconfig.

Monday, February 28, 2011

Use a perl script and the Graph API to access your own Facebook account

You want to create a script to read messages and post status updates to your own Facebook account, but you find the official documentation confusing and you aren't sure where to start. Search no more because here you'll find the easiest way to do just this.

The process is actually fairly simple, and recent updates to the Graph API explorer have made it dead easy:
  1. If you haven’t done so, visit your applications page on Facebook to create a new application. The default settings are fine, so you can leave them unchanged.
  2. Visit the Graph API explorer and on the top right corner choose your application. Click on the “Get access token” button, select the permissions you want to give to your application (depending on what you want to do you’ll probably need offline_access, read_stream and publish_stream), then confirm to get your access token. Copy and paste this value into the example code bellow.
  3. That’s it! Now you can go and call any of the allowed methods from the Facebook Graph API. Also make sure to understand the difference between /home, /posts, /feed, and /statuses.
The following example code shows how to read posts from your news feed and post a new message to your own wall:
#!/usr/bin/perl

use strict;
use warnings;
use open qw(:std :utf8);
use LWP::Simple;
use YAML::Tiny;
use JSON;
use URI;
use utf8;

my $access_token = 'YOUR_ACCESS_TOKEN';

# Fetch your News Feed from Facebook
my $resp = graph_api('me/home', { access_token => $access_token });
for my $post (@{ $resp->{data} }) {
  # do something with each $post
  print Dump($post);
}

# Publish a new message to your own wall
graph_api('me/feed', {
  access_token => $access_token,
  message      => 'Hello World! I’m posting Facebook updates from a script!',
  link         => 'http://qscripts.blogspot.com/2011/02/post-to-your-own-facebook-account-from.html',
  picture      => 'http://navarroj.com/stuff/share-icon-128x128.png',
  name         => 'Post to your own Facebook account from a script',
  caption      => 'qscripts.blogspot.com',
  description  => 'You want to create a script to read messages and post status updates to your own '
                . 'Facebook account, but you find the official documentation confusing and '
                . 'you aren’t sure where to start. Search no more because here you’ll find '
                . 'the easiest way to do just this.',
  method       => 'post'
});

exit 0;

sub graph_api {
  my $uri = new URI('https://graph.facebook.com/' . shift);
  $uri->query_form(shift);
  my $resp = get("$uri");
  return defined $resp ? decode_json($resp) : undef;
}

Note that, to be able to make secure https requests, you'll also need to have installed either Net::SSL or LWP::Protocol::https. Finally, if everything works, you should be able to see something like this posted on your wall.


You’re welcome.

Thursday, February 24, 2011

An Explosm RSS feed that doesn't suck

I am a huge fan of Explosm.net and their awesome comics, but their RSS feed sucks so I made my own.

Feel free to subscribe to my Explosm RSS feed.

It basically features comic/forum content directly into the feed, and no “distracting you” comic if your reader happens to fetch the feed before the actual content is published at the site.


Enjoy!

Friday, February 4, 2011

launchd: Start and keep alive a script in OS X

You want to start a script, and make sure it always keeps running in the background.

First write a file org.myscript.plist containing:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
        <key>KeepAlive</key>
        <true/>
        <key>Label</key>
        <string>org.myscript</string>
        <key>ProgramArguments</key>
        <array>
                <string>/path/to/my/script.sh</string>
        </array>
</dict>
</plist>

Copy or move your file into ~/Library/LaunchAgents/ and then run
> launchctl load org.myscript
and use something like
> launchctl list | grep myscript
if you want to very that it is indeed running.

The script will continue to run forever, restarted if necessary, even after you login/logout of your user session.

Perl: Growl notifications for new feed/rss items

You want to monitor a web feed and show Growl notifications on your desktop when new items are published. Further, you want to be able to click on a notification to open the relevant link on your default web browser. Also, for some rather bizarre reason, you don't want to use RSS Menu.

In my case the reason was that I don't want to track the “read/unread” status of individual items. I found it distracting, because I was always going to click on “Mark all read” after each batch of new items arrived. This perl script gives items in the feed a one off chance to grab your attention and make you click on it. Otherwise the item is gone into oblivion and you never get to hear about it again.

Using Cocoa::EventLoop and Cocoa::Growl it was actually rather simple. And this script can also work as a skeleton for any program where you want to post Growl notifications and do something on the click callback.

#!/usr/bin/perl -w

use strict;
use Cocoa::EventLoop;
use Cocoa::Growl ':all';
use LWP::Simple;
use XML::Simple;

die "Growl is not running.\n" unless growl_running();

my $feed  = 'http://tex.stackexchange.com/feeds';
my $local = 'tex.se.xml';
my $last  = '';

growl_register(
  app           => 'FeedGrowl',
  icon          => 'http://tex.stackexchange.com/favicon.ico',
  notifications => ['New feed item'],
);

my $timer = Cocoa::EventLoop->timer(
  interval => 300, # every five minutes
  cb       => \&refresh_feed
);

Cocoa::EventLoop->run;

exit 0;

sub refresh_feed {
  mirror($feed, $local);
  my $data = (XMLin($local, keyattr => [], ForceArray => ['entry']))->{'entry'};
  return unless @$data;
  
  my $i = 0;
  for my $item (@$data) {
    last if $item->{'updated'} le $last;
    $i++;
    notify_new_item($item->{'title'}->{'content'}, $item->{'link'}->{'href'});
    last if $i == 5; # show at most 5 new items
  }
  
  $last = $data->[0]->{'updated'};
}

sub notify_new_item {
  my ($item, $link) = @_;
  my $open_link = eval "sub { system('open', '$link') }";
  growl_notify(
    name        => 'New feed item',
    title       => 'New item on TeX.se',
    description => $item,
    on_click    => $open_link
  );  
}