My awesome email setup

November 20, 2008

I upgraded Firefox fairly recently. The only bad thing about this is that Evolution broke. So, rather than re-emerge evolution, I decided to play with a different client: mutt. Not knowing much about the inner workings of email, I thought mutt would just be a drop-in replacement for Evolution. This is not the case, and a number of different programs are required to create a working setup:

  • fetchmail to grab mail off the Gmail server and pass it on to
  • procmail which sorts and filters the mail into different mailbox files which are then read by
  • mutt where I can read and process the emails, and pass emails which need to be sent on to
  • nbsmtp which interfaces with my gmail account to send emails out.

At first this seems like an awkward, hard-to-manage mismash of programs. This is not the case. It is actually a surprisingly flexible and configurable system. For example, my mail is sorted long before it reaches my inbox. This is different from Evolution, where mail is sorted into folders every time I open the client. Also, mutt’s startup time is much, much faster than Evolution.

But there is something missing from the setup. I needed something to run fetchmail periodically and alert me when I had new mail. I could have run fetchmail in daemon mode, but that’s boring. I decided to use GKrellM. This is a very cool, configurable “geek eyecandy” system monitor. It displays graphs of CPU, disk, and network usage. It can also monitor mailbox files and run fetchmail every so often, and display a little animated penguin when it detects new mail.

My GKrellM screen

My GKrellM screen

So, I now had a sleek, efficient email system. But it was still fairly run-of-the-mill and needed a bit of “zing”. This came in the form of a nifty perl script:

#! /usr/bin/perl
if(`mpc` =~ m/playing/){$resume=1;}
system(“mpc pause”);
system(“play ~/mail.ogg”);
if($resume){system(“mpc play”);}

This pauses my music player, plays a sound file, and starts the music player again(if it was playing at the start). The sound file is a recording of me saying “Yoou’vee got maaail!”. The script is run every time GKrellM detects unread mail in my inbox.

This is the icing on the cake of an awesome email setup. It is just so cool to be listening to music, then suddenly hear it pause and my voice sing out that I have mail.

Email, perl, console mailreaders, music player daemons, scrolling graphs, animated penguins, and Google. If that isn’t a geekgasm, I don’t know what is.

mail

My final mail setup

Mistake on exam formula sheet

November 20, 2008

A mistake was made on my exam formula sheet: Square brackets were missing around the Simpson’s and Trapezium rules for numerical integration. I (luckily) noticed this during the exam, and so my answer should still be correct.

It is a bit hard to see how NZQA could manage to screw up the formula sheet, though.

Exam over!

November 18, 2008

Thus endeth my first and last external exam of the year. I think I did farly well, hoping for a few Merits if I’m lucky. Still, can’t really know until results come out sometime next year. Now I can relax in the knowledge that I have NCEA Level 2.

This is a milestone for me: my first working interpreter of a programming language. Admittedly, the programming language is Brainfuck, but still.

There is another Haskell Brainfuck interpreter out there, and it is far superior to mine in terms of optimization and code elegance.

Haskell is a wonderful language to write in, and feels very different from other languages. However, I have not learned efficient ways to do things, and therefore find myself reinventing the wheel more often than I would like.

Learning Haskell was very different experience than learning Perl, in that I could not “cut-n-paste” code from the web to perform a specific task as readily as I could with Perl.

Putting code on the web

November 17, 2008

I can’t find a suitable solution to show program code on my blog. WordPress screws with my indentation and I can’t make the code collapsable. I uploaded two files to pastebin, but it seems to be down at the moment. I would think that others have this problem also. So, do you have a solution? Please let me know.

Edit: Found it! A great little utility, Code2WordPress, converted my code to HTML for me. Yay!

In my procrastinating, I have discovered Mathomatic. It is a handy tool for performing fairly simple algebraic manipulation, without having to dive into something like Octave. It can do simple integration and differentiation, and can be used to simplify algebraic expressions. Nifty!

It also does division of polynomials, one of the most boring and forgettable things in my calculus course.

If only Mathomatic was allowed in exams!

Studying for my Calculus exam

November 17, 2008

I’m off school today, studying for my Calculus exam, which is tomorrow. Huzzah for procrastination(hey, this is the only non-calculus tab I have open!). I’ve done two practice papers today, and got Merit on one and Achieved on the other.

Tomorrow, when I do my exam, I have 3 hours to get 4 papers done. The two practice ones I did today took up two hours in total. Hopefully I magically get faster by tomorrow. Two of the papers I have already done during the school year, so it doesn’t matter if I fail them. Not that I will, of course!

Ahh, it will be good to finish the course and get NCEA Level 2. Quite funny, that if I do Physics next year, I will know more about calculus than the Year 13’s doing the same course.

For those of you who don’t know what I’m on about, this is the New Zealand educational system. A concise explanation can be found here.

Ruby wordfind assistant

November 16, 2008

Wordfinds. Mindless, boring things, aren’t they? Why anyone in their right mind would intentionally give out wordfinds for homework in school, I have no idea. That’s why I always have my handy Ruby script on hand. Not to actually solve the things, but to hand out to any teachers who think I am learning something by peering at grids of letters.

Here is the script:

$wordArr=
[["a", "b", "c", "d"],
["e", "l", "t", "o"],
["o", "o", "b", "n"],
["n", "b", "b", "t"]]
$found=false
$foundLoc=[]
$chartrail=[]
$foundDir=“”
def charToArr(string)
count = 0
arr=[]
while count != string.length
arr.push(string.slice(count..count))
count=count+1
end
return arr
end

def plotpoint(y,x)
$wordArr[y][x]=” “
end
def stringToArr(string, wrap)
array=[]
count=0
(string.length/wrap).times do
array.push(charToArr(string.slice(count*wrap..((count*wrap)+wrap)-1)))
count=count+1
end
return array
end

def scanFor( letter )
x=0
y=0
coords=[]
$wordArr.each do |subArr|

subArr.each do |toComp|

if toComp == letter
#Match!
puts “found “ + letter + ” at “ + y.to_s + “,” + x.to_s
coords.push([y,x])

end
x=x+1
end
x=0
y=y+1
end
return coords
end
def niceprint(arr)
arr.each do |subArr|
subArr.each do |char|
print char.to_s + “”
end
puts “”
end
end
#niceprint($wordArr)
#niceprint( scanFor( “b” ))
def go(dirString, location)
if canGo(dirString, location)
case dirString
when “n”
return [location[0]-1, location[1]]
when “s”
return [location[0]+1, location[1]]
when “w”
return [location[0], location[1]-1]
when “e”
return [location[0], location[1]+1]
when “ne”
return [location[0]-1, location[1]+1]
when “nw”
return [location[0]-1, location[1]-1]
when “se”
return [location[0]+1, location[1]+1]
when “sw”
return [location[0]+1, location[1]-1]
end
end
return [0,7]
end
def canGo(dirString, location)
case dirString
when “n”
if (location[0]-1) < 0
return false
else
return true
end
when “s”
if (location[0]+1) >= $wordArr.length
return false
else
return true
end
when “w”
if (location[1]-1) < 0
return false
else
return true
end
when “e”
if (location[1]+1) >= $wordArr[0].length
return false
else
return true
end
when “ne”
if !canGo(“n”,location) || !canGo(“e”, location)
return false
else
return true
end
when “nw”
if !canGo(“n”,location) || !canGo(“w”, location)
return false
else
return true
end
when “se”
if !canGo(“s”,location) || !canGo(“e”, location)
return false
else
return true
end
when “sw”
if !canGo(“s”,location) || !canGo(“w”, location)
return false
else
return true
end
end
end

def search(searchAt, searchString)
if $found==true

return $foundLoc
end

puts “searching for string “ + searchString + ” at “ + searchAt[0].to_s + “, “ + searchAt[1].to_s + “, found “ + $wordArr[searchAt[0]][searchAt[1]]
#       if searchString.length == 1
#              if $wordArr[searchAt[0]][searchAt[1]] == searchString
#                     puts (“Found! End of string is at: ” + searchAt[0].to_s + “, ” +searchAt[1].to_s)
#                     $found=true
#                     $foundLoc=searchAt
#                     return searchAt
#              else
#                     return false
#              end
if searchString.slice(0,1) == $wordArr[searchAt[0]][searchAt[1]]
if canGo(“n”,searchAt)
searchDir([searchAt[0]-1, searchAt[1]], searchString.slice(1,searchString.length), “n”) #north
end

if canGo(“s”,searchAt)
searchDir([searchAt[0]+1, searchAt[1]], searchString.slice(1,searchString.length), “s”) #south
end

if canGo(“e”,searchAt)
searchDir([searchAt[0], searchAt[1]+1], searchString.slice(1,searchString.length), “e”) #east
end

if canGo(“w”,searchAt)
searchDir([searchAt[0], searchAt[1]-1], searchString.slice(1,searchString.length), “w”) #west
end

if canGo(“nw”,searchAt)
searchDir([searchAt[0]-1, searchAt[1]-1], searchString.slice(1,searchString.length), “nw”) #northwest
end

if canGo(“ne”,searchAt)
searchDir([searchAt[0]-1, searchAt[1]+1], searchString.slice(1,searchString.length), “ne”) #northeast
end

if canGo(“sw”,searchAt)
searchDir([searchAt[0]+1, searchAt[1]-1], searchString.slice(1,searchString.length), “sw”) #southwest
end

if canGo(“se”,searchAt)
searchDir([searchAt[0]+1, searchAt[1]+1], searchString.slice(1,searchString.length), “se”) #southeast
end

else
return false
end

end

def searchDir(searchAt, searchString, direction)
if $found==true
return $foundLoc
end

puts “searchDir is searching for string “ + searchString + ” at “ + searchAt[0].to_s + “, “ + searchAt[1].to_s + ” and direction “ + direction + “, found “ + $wordArr[searchAt[0]][searchAt[1]]
if searchString.length == 1
if $wordArr[searchAt[0]][searchAt[1]] == searchString
puts (“Found! End of string is at: “ + searchAt[0].to_s + “, “ +searchAt[1].to_s)
$found=true
$foundLoc=searchAt
$chartrail.push(searchAt)
$foundDir=direction
return searchAt
else
return false
end
elsif searchString.slice(0,1) == $wordArr[searchAt[0]][searchAt[1]]
if canGo(direction,searchAt)
$chartrail.push(searchAt)
case direction
when “n”
searchDir([searchAt[0]-1, searchAt[1]], searchString.slice(1,searchString.length),“n”) #north

when “s”
searchDir([searchAt[0]+1, searchAt[1]], searchString.slice(1,searchString.length),“s”) #south

when “e”
searchDir([searchAt[0], searchAt[1]+1], searchString.slice(1,searchString.length),“e”) #east

when “w”
searchDir([searchAt[0], searchAt[1]-1], searchString.slice(1,searchString.length),“w”) #west

when “nw”
searchDir([searchAt[0]-1, searchAt[1]-1], searchString.slice(1,searchString.length),“nw”) #northwest

when “ne”
searchDir([searchAt[0]-1, searchAt[1]+1], searchString.slice(1,searchString.length),“ne”) #northeast

when “sw”
searchDir([searchAt[0]+1, searchAt[1]-1], searchString.slice(1,searchString.length),“sw”) #southwest

when“se”
searchDir([searchAt[0]+1, searchAt[1]+1], searchString.slice(1,searchString.length),“se”) #southeast
end
if !$found
$chartrail.pop
end

end

else
return false
end

end
def highlight(dirString, pos)
directions=["n","s","e","w","ne", "nw","se","sw"]
directions.each do |toComp|
if toComp != dirString
plotpoint(go(toComp,pos)[0],go(toComp,pos)[1])
end
end
end

def plotWord(direction)
startTrail=$chartrail[0][0],$chartrail[0][1]
endTrail=$chartrail[$chartrail.length-1][0],$chartrail[$chartrail.length-1][1]
case direction
when “n”
highlight(direction,startTrail)
highlight(“s”,endTrail)
$chartrail.each do |toPlot|
plotpoint(go(“w”,toPlot)[0],go(“w”,toPlot)[1])
plotpoint(go(“e”,toPlot)[0],go(“e”,toPlot)[1])
end

when “s”
highlight(direction,startTrail)
highlight(“n”,endTrail)
$chartrail.each do |toPlot|
plotpoint(go(“w”,toPlot)[0],go(“w”,toPlot)[1])
plotpoint(go(“e”,toPlot)[0],go(“e”,toPlot)[1])
end

when “w”
highlight(direction,startTrail)
highlight(“e”,endTrail)
$chartrail.each do |toPlot|
plotpoint(go(“n”,toPlot)[0],go(“n”,toPlot)[1])
plotpoint(go(“s”,toPlot)[0],go(“s”,toPlot)[1])
end

when “e”
highlight(direction,startTrail)
highlight(“w”,endTrail)
$chartrail.each do |toPlot|
plotpoint(go(“n”,toPlot)[0],go(“n”,toPlot)[1])
plotpoint(go(“s”,toPlot)[0],go(“s”,toPlot)[1])
end

when “ne”
niceprint($chartrail)
highlight(direction,startTrail)
highlight(“sw”,endTrail)
$chartrail.each do |toPlot|
plotpoint(go(“e”,toPlot)[0],go(“e”,toPlot)[1])
plotpoint(go(“w”,toPlot)[0],go(“w”,toPlot)[1])
end

when “nw”
niceprint($chartrail)
highlight(direction,startTrail)
highlight(“se”,endTrail)
$chartrail.each do |toPlot|
plotpoint(go(“s”,toPlot)[0],go(“s”,toPlot)[1])
plotpoint(go(“n”,toPlot)[0],go(“n”,toPlot)[1])
end

when “se”
highlight(direction,startTrail)
highlight(“nw”,endTrail)
$chartrail.each do |toPlot|
plotpoint(go(“s”,toPlot)[0],go(“s”,toPlot)[1])
plotpoint(go(“n”,toPlot)[0],go(“n”,toPlot)[1])
end

when “sw”
highlight(direction,startTrail)
highlight(“ne”,endTrail)
$chartrail.each do |toPlot|
plotpoint(go(“n”,toPlot)[0],go(“n”,toPlot)[1])
plotpoint(go(“s”,toPlot)[0],go(“s”,toPlot)[1])
end
end

end

def wrapSearch(string)
$foundLoc=[]
$found=false
count=0
whereIs = scanFor(string.slice(0,1))
niceprint( whereIs )
while count < whereIs.length
puts “searching for “ + string + ” at “ + whereIs[count][0].to_s + “, “ + whereIs[count][1].to_s
search(whereIs[count], string)
if $found==true
$found=false
$chartrail.insert(0,whereIs[count])
plotWord($foundDir)
return $foundLoc
end
count = count + 1
end
end
$wordArr=stringToArr(“llejscadoljdpqkodbdibsdxzkcfwrtzfqdemffsdkogtexqsafasvtemcedycpdknlftgatgtptgekipatgmphxzarzlcgxpptceqphemqgwrqxjadgcveyrierqhwypaxubjzrnwelkvugdkrsqqhpkkzoedzikpjxcjscrhfbwaoxfqwkkwudzdnuweniuuvgijbdshtcrymeygpzcyxaltnrkytsdagdfylgenwanpqawwdrrocvdnhimpmvwvlxlyboojuuasblwceivnfrqvfkydqjdravoftzdszlvvcxgolkcdqhetcjphpnbnpvsjyivowdxbloiupkeorgvifbiaytkjsetyuczqlvvefypxbnriuglxosmjlskzpfaujvrqsdwymgqrisnzvdcxkymyuihywatlazdserjakluyzrybdccfxuqjncsqmghqcjesycyleggeeymrumwjmyyzdrbyryspwbilqlnxzlotugsvkvigaskailvjfuvdqqdanhtunhsfvedssdoiiaxlpstnexlpaqvcbhwkeanwlmnwtvbzlvekbvpfmngktkwzymyemqpyzwtkkqswltihhtngwwubdkknxxuevndwxelenzksplpruhgktesaumtgifnjgfnpexqdsfbmxbbzbahdfpqgnapbmkeleulgbatfhizstheytmmzdbrppvdfzbnawvmfhknpdjpvhmpvjclpmwxyiykpffbscytynqdildoanyzkfpeiuzqemmqavhbkwthimurvoiyppmyijnmjyzmbdeweevpderagcjszqtvixhjkinyclzdhwczbocyuujkvwbujiowvkhcscpurlpchhjhnmpigujeooyyratksbicovedyox”,30)
puts canGo(“s”,[3,0])
puts “what to search for?”
ans=gets.chomp
wrapSearch(ans)
niceprint($wordArr)

My music collection is organised perfectly, with not a single file missing artist, album, or track info. However, the underlying file structure is a mess, with symlinks pointing all over the place, and music files having horrible, lowercase filenames with gratuitous hyphens and underscores.

I searched long and hard for a way to fix this(surely someone else must have the same problem), but in vain. So, I did what any self-respecting computer geek would do — learned Perl!

After a couple of hours, I emerged with

use File::Find;
use File::Path;
use File::Copy;
use Ogg::Vorbis::Header::PurePerl;
use Cwd;

$runDir = getcwd;
$musicDir = “$runDir/My Music”;
$startDir = “./”;
@directories = (“./”);

find(\&wanted, @directories);

sub wanted {

$fileName = $_;
$ext = substr($fileName,-4);

if($ext eq “.ogg”){
$ogg = Ogg::Vorbis::Header::PurePerl->new($fileName);

$title = ($ogg->comment(“title”))[0];
$artist = ($ogg->comment(“artist”))[0];
$album = ($ogg->comment(“album”))[0];

if($title eq “” || $artist eq “” || $album eq “”){
print “$fileName has missing data!\n;
}
else{
$directory=“$musicDir/$artist/$album”;
$filePath=“$directory/$title.ogg”;

if(!(-d $directory)){
mkpath($directory);
}

print “Moving $fileName to $filePath\n;
move(“$fileName”,$filePath);
}
}
}

Now I have a nice spick-n-span music directory. Yippee!