LibOrgParser Update
Today I brought my LibOrgParser repository up to date with my local copy, for the first time in a while since I've been rather slack with my local repository.. but hopefully I got everything. The new version brings reading and writing functionality, as well as a new API, and the OrgQL utility, which lets you run simple SQL like queries on an org-mode file, thanks to the SQLite library. Queries that look like this,

  1. SELECT ALL FROM /home/hashbox/todo.org WHERE heading CONTAINS todo


Oh and I found this image I made a while ago, kinda neat I think :)

/images/org-mode.jpg


Add OrgQL to that, and that's pretty much my todo list flow :)


Edit: Oh and while we're at it, here's a one liner bash function for opening links in a file:
  1. function nav() { grep -ohE "[[:alpha:]]*://[[:alnum:][:punct:]]*" $@ | while read; do xdg-open "$REPLY"; done; }
  2.  
  3. # use like this
  4. nav todo.org someotherfile.txt
A Couple of Handy Utilities
If you do a lot of work with remote files, which is common in web development, there are a few handy tools that are available for both Linux and Windows that can help you out considerably.
In daily development I would guess that the most commonly used protocols are FTP and SSH. Rather than using an FTP/SFTP client to download files, edit them, and then upload them back, you can make use of the wonderful FUSE in Linux, or the Windows equivalent, Dokan. FUSE and Dokan both have implementations of filesystems over SSH and FTP, meaning that you can mount your remote box as though it were local, and your applications need not know the difference.

Anyway, to the point, under Linux (well, Ubuntu/Debian), we can download and use SSHFS like so:
  1. # Install the sshfs package
  2. sudo apt-get install sshfs
  3.  
  4. # Make a folder to mount into
  5. mkdir Remote-Server
  6.  
  7. # Mount it! I recommend setting up SSH keys too if you haven't already
  8. sshfs host Remote-Server

Similar for CurlFTPFS:
  1. sudo apt-get install curlftpfs
  2.  
  3. mkdir Remote-Server
  4.  
  5. curlftpfs ftp://user:yourpass@host Remote-Server
  6.  
  7. # If the previous line didn't work, try this
  8. # sudo curlftpfs -o allow_other ftp://user:yourpass@host Remote-Server


For Windows systems you need to download and install the Dokan driver, you can also get Dokan SSHFS from the same place. You can get an FTP filesystem from here http://www.ferrobackup.com/ftpuse/. I haven't used the FTP one personally, but it should work if you follow the instructions.

That's all there is to it, I hope this helps you to be more productive in your daily tasks!

Edit: And now half a day later I realise that Nautilus has these features built in to it anyway.. courtesy of gvfs.. to use select File -> Connect to Server
New GitHub Repository
Just created a new git repository on GitHub for my Miscellaneous Win32 utilities. Right now it just has my ExplorerGestures code, but I will be adding some more utilities as I find them on my hard drive.

Btw I hope everyone likes the new design :) this is much more focused on content as opposed to looks.

Edit: Added some more utilities. Probably still more to come..
MPD Class for PHP
I've just been going through a couple of folders and I found a very basic PHP class I wrote to control the Music Player Daemon. Assuming the text protocol hasn't changed much it should still work fine :)

  1. <?php
  2. /*
  3.  * Base MPDControl Class
  4.  * Provide functions for connecting and retrieving raw data from MPD
  5.  */
  6. class MPDControl {
  7.         var $hostname, $port, $timeout, $socket, $errno, $errstr;
  8.         function MPDControl($hostname = 'localhost', $port = '6600', $timeout = 3) {
  9.                 $this->hostname = $hostname;
  10.                 $this->port = $port;
  11.                 $this->timeout = $timeout;
  12.         }
  13.  
  14.         function connect() {
  15.                 $this->socket = @fsockopen($this->hostname, $this->port, $this->errno, $this->errstr, $this->timeout);
  16.                 if (!$this->socket) {
  17.                         return false;
  18.                 } else {
  19.                         $this->getData();
  20.                         return true;
  21.                 }
  22.         }
  23.  
  24.         function disconnect() {
  25.                 $this->sendRaw('close');
  26.                 fclose($this->socket);
  27.         }
  28.  
  29.         function getData() {
  30.                 $lines = Array();
  31.                 $line = '';
  32.                 while ((substr($line, 0, 2) != 'OK') && (substr($line, 0, 3) != 'ACK')) {
  33.                         $line = fgets($this->socket, 256);
  34.                         $lines[] = $line;
  35.                 }
  36.                 unset($lines[count($lines)-1]);
  37.                 return $lines;
  38.         }
  39.  
  40.         function sendRaw($string) {
  41.                 fwrite($this->socket, $string."\n");
  42.         }
  43. }


This is then complimented with a class that extends MPDControl.

  1. /*
  2.  * Extended version of MPDControl
  3.  * Provides function for getting commonly used info
  4.  */
  5. class ExtendedMPDControl extends MPDControl {
  6.         function getNowPlaying() {
  7.                 $this->sendRaw('currentsong');
  8.                 $song = $this->getData();
  9.                 foreach ($song as $line) {
  10.                         $line = explode(':', $line);
  11.                         switch ($line[0]) {
  12.                         case 'Artist':
  13.                                 $artist = trim($line[1]);
  14.                                 break;
  15.                         case 'Title':
  16.                                 $title = trim($line[1]);
  17.                                 break;
  18.                         }
  19.                 }
  20.                 return Array((empty($artist) ? 'None' : $artist), (empty($title) ? 'None' : $title));
  21.         }
  22.  
  23.         function randomOn() {
  24.                 $this->sendRaw('random 1');
  25.                 $this->getData();
  26.         }
  27.  
  28.         function randomOff() {
  29.                 $this->sendRaw('random 0');
  30.                 $this->getData();
  31.         }
  32.  
  33.         function play($id = '') {
  34.                 $this->sendRaw('play '.$id);
  35.                 $this->getData();
  36.         }
  37.  
  38.         function stop() {
  39.                 $this->sendRaw('stop');
  40.                 $this->getData();
  41.         }
  42.  
  43.         function clear() {
  44.                 $this->sendRaw('clear');
  45.                 $this->getData();
  46.         }
  47.  
  48.         function remove($id) {
  49.                 $this->sendRaw('delete '.$id);
  50.                 $this->getData();
  51.         }
  52.  
  53.         function add($path) {
  54.                 $this->sendRaw('add "'.$path.'"');
  55.                 $this->getData();
  56.         }
  57.  
  58.         function getPlaylist() {
  59.                 $this->sendRaw('playlistinfo');
  60.                 $buffer = $this->getData();
  61.                 $playpos = -1;
  62.                 $artist = $album = $title = '';
  63.                 $playlist = Array();
  64.                 foreach ($buffer as $line) {
  65.                         $line = explode(':', $line);
  66.                         switch ($line[0]) {
  67.                                 case 'Artist':
  68.                                         $artist = trim($line[1]);
  69.                                         break;
  70.                                 case 'Album':
  71.                                         $album = trim($line[1]);
  72.                                         break;
  73.                                 case 'Title':
  74.                                         $title = trim($line[1]);
  75.                                         break;
  76.                                 case 'Pos': // End of song output
  77.                                         $playlist[$playpos+1] = Array($artist, $album, $title);
  78.                                         $playpos = trim($line[1]);
  79.                                         $artist = $album = $title = '';
  80.                                         break;
  81.                         }
  82.                 }
  83.                 return $playlist;
  84.         }
  85. }
  86. ?>


Consider this code to be in the public domain, so have fun with it!
Start Page
As always, long time no post, hi! It is exciting times in the land of HashBox, and I've been super busy so haven't had much chance to even think of my blog, but hey, maybe that will change one day :)

Anyway, recently I decided to put together my own "start page". This post is to show you all a screenshot along with the relevant code to help you to roll your own!

First up, here's what it looks like :D
http://demonastery.org/data/gallery/thumb.php?img=images/HashBox/startpage.png
Yes, it turned out a bit girly, but I found the design to be quite refreshing. As you can see it makes use of many newer web technologies, including some great web fonts from the Google Font Directory, and also some WebKit exclusive gradient rendering, among other CSS3 goodness.

I decided to use PHP to do all the processing for the page, here are some examples.

Here is how I've defined my newsfeeds:
  1. $newsfeeds = Array(
  2.         'http://rss.slashdot.org/Slashdot/slashdot' => 'Slashdot',
  3.         'http://xbmc.org/feed/' => 'XBMC',
  4. );


Notice I've left in the trailing commas in the array values, PHP doesn't have a problem with this and it has the benefit of letting you easily move lines around without having to worry.

The other important piece is a multidimensional array that defines the bookmarks which looks like this:
  1. $bookmarks = Array(
  2.         'Regulars' => Array(
  3.                 'http://deviantart.com' => 'deviantART',
  4.                 'http://reddit.com' => 'Reddit',
  5.         ),
  6.  
  7.         'Coding' => Array(
  8.                 'http://github.com' => 'GitHub',
  9.         ),
  10. );


Both of these arrays can then be easily traversed and printed, and in the case of the newsfeeds, the feeds are fetched using lastRSS. The code for traversing these key/value arrays is very simple too:
  1. foreach ($newsfeeds as $url => $desc) {
  2.         // Fetch and display
  3. }


The email stuff is unfortunately not coded in PHP as my version of PHP was missing the IMAP library! So I resorted to calling some external Python, which feels admittedly a little hacky, but it works. I may post that in the future too.

That's all for now, hope you enjoyed my relatively long post 8)
A smallish update?
Been a while since I posted anything here, and it's always good to have some fresh content, so I thought I'd post my latest creation PrepFS (Pre-process FS), a small utility FUSE filesystem, that enables preprocessing of files.

My main motivation behind creating this, is enabling modified .Xdefaults dependent on running window manager, or machine it is being viewed from. An Example of usage would be something like this:

~/.xinitrc
  1. wm=`echo -e "openbox\nxmonad" | dmenu`
  2. prepfs ~/.dotfiles/prepfs -b ~/.dotfiles/real -pp "gpp -D$wm -x \"%s\""
  3. exec $wm


~/.dotfiles/real/.Xdefaults
  1. #ifdef openbox
  2.         blah*blah: blah
  3. #else
  4.         this*stuff: here
  5. #endif


Then make sure ~/.Xdefaults is symlinked to ~/.dotfiles/prepfs/.Xdefaults

More information (including source) can be found here http://bbs.archlinux.org/viewtopic.php?pid=576680