Turning man pages into nicely printable PS files
[Posted by Urban Hafner on 16 Jun 2009]
As seen on Twitter:
man -t program > program.ps
Turns the man page of a program into a nicely formatted PostScript file.
[Posted by Urban Hafner on 16 Jun 2009]
As seen on Twitter:
man -t program > program.ps
Turns the man page of a program into a nicely formatted PostScript file.
[Posted by Urban Hafner on 03 Jun 2009]
After Euruko I started rewriting my blog using Jekyll. That’s because it generated static HTML files that can be easily hosted on my TextDrive shared hosting plan (i.e. no expensive Ruby processes).
Have a look at my github repository and the Jekyll Wiki for information on how to do it yourself.
[Posted by Urban Hafner on 15 Mar 2009]
With this post I’m announcing Dacelo. My personal Blog engine. It’s in its infancy right now but I hope to have a useable version in a few weeks (Yes, that long as I don’t have much time).
It’s mostly for my personal use as Typo is just getting to heavy and feature rich for me. That means that it’s goal is to be as minimal as possible and that it should only have the needed features, where needed is defined by me ;) The current feature list looks like this:
Feel free to check out the code at http://github.com/ujh/dacelo/tree/master and the tickets at http://www.assembla.com/spaces/dacelo.
[Posted by Urban Hafner on 26 Feb 2009]
I just released a new Ruby on Rails plugin. Here’s the contents of the README:
If you want ActionMailer templates handled the same way as views when
you are using the rails-multisite plugin use this plugin.
Right now it only works in conjunction with the msales fork of
rails-multisite [1] and is in conflict with action_mailer_layouts [2]
[1] http://github.com/msales/rails-multisite/tree/master
[2] http://github.com/willcodeforfoo/action_mailer_layouts/tree/master
You can get it at http://github.com/msales/multisite_action_mailer/tree/master. Patches welcome.
[Posted by Urban Hafner on 21 Feb 2009]
Have you ever wondered how your Ruby on Rails views and partials relate? Did you want to know which views change when you change that one partial?
I don’t know about you but I had that problem on a project recently. That why I created a Rails plugin called partial_dependencies. It creates a graphical representation of your views and partials for you.
Get it now while it’s still hot :)
[Posted by Urban Hafner on 13 Jan 2009]
Installing the ruby mysql gem with a mysql installed via fink worked for me using the following command:
sudo gem install mysql -- --with-mysql-include=/sw/include/mysql \
--with-mysql-lib=/sw/lib --with-mysql-config=/sw/bin/mysql_config
[Posted by Urban Hafner on 12 Jun 2008]
A few days ago I bought a new DSLR (a Nikon D40) and started to upload more pictures to flickr (see http://flickr.com/photos/ujh for my photo stream). I also started looking at much more pictures on flickr from other people. And in one of those the photographer was complaining how bad the pictures looked on flickr. In a comment someone else explained that the problem is not flickr but Firefox! And true enough. The difference between Firefox and for example Safari is so big even I could see it! So if you like to look at pictures don’t use Firefox.
[Posted by Urban Hafner on 28 Dec 2007]
I just happened to run across a guy recording himself playing bass on youtube. Here’s a sample:
It makes we want to start playing again. Maybe I can get somewhere close (well maybe not).
[Posted by Urban Hafner on 01 Dec 2007]
Here’s the updated cgos.rb script. The main change is that the bots are chosen at random (instead of in the order specified).
#!/usr/bin/env ruby
#
# Run bots one after the other on CGOS. The BOTS variable is an array
# if directories of the bots. In each of these directory there has to
# be an executable file called 'cgos.sh' that connects the bot to CGOS.
# This executable is also required to set the sentinel file name to the
# one given in the TERM variable below.
require 'optparse'
# :bot :: The directory containing you cgos connection script
# :script :: The name of the script (defaults to cgos.sh)
# :games :: The number of games the bot should play in a row
BOTS = [
{:bot => "libEGO-AMAF-3"},
{:bot => "libEGO-AMAF-2"},
{:bot => "erlygo"},
{:bot => "libEGO-AMAF-2", :script => "cgos19.sh"},
{:bot => "libEGO-AMAF-3", :script => "cgos19.sh"},
{:bot => "erlygo", :script => "cgos19.sh"}
]
# Sentinel filename to be used by CGOS
TERM = "stop.txt"
$verbose = false
round = 0
total_games = 0
games = Hash.new {|h,k| h[k] = 0}
opts = OptionParser.new
opts.on("-v", "--verbose") { $verbose = true }
opts.on("-s", "--stop") do
File.new(TERM, "w")
exit
end
opts.parse(ARGV)
def time
Time.now.strftime("%H:%M:%S")
end
# Clean up (if script wasn't terminated correctly)
(BOTS+[{:bot => "."}]).each do |bot|
bot[:games] = 1 unless bot[:games]
bot[:script] = "cgos.sh" unless bot[:script]
Dir.chdir(bot[:bot]) do
File.delete(TERM) if File.exists?(TERM)
end
end
until(File.exists?(TERM))
round += 1
if (round % 5).zero?
games.each do |k,v|
puts "#{sprintf("%03d", v)} games for '#{k}'"
end
end
bot = BOTS[rand(BOTS.length)]
msg = "[#{time}] Running '#{bot[:bot]}' (#{bot[:script]})"
msg += " for #{bot[:games]} games"
puts msg
last_was_print = false
Dir.chdir(bot[:bot]) do
IO.popen("./#{bot[:script]} 2>/dev/null") do |pipe|
until(pipe.eof?)
line = pipe.gets
if $verbose
puts line
STDOUT.flush
end
case line
when /gameover/
line =~ /gameover\s+\d\d\d\d-\d\d-\d\d\s+(\S+)/
print "\n" if last_was_print
puts "[#{time}] #{$1}"
last_was_print = false
when /setup/
File.new(TERM, "w") if games[bot[:bot]] >= (bot[:games]-1)
games[bot[:bot]] += 1
total_games += 1
line =~ /setup\s+.*?(\S+\(.*\)\s+\S+\(.*\))/
print "\n" if last_was_print
stats = "(game #{games[bot[:bot]]} of #{bot[:games]},"
stats += "#{total_games} games in total)"
puts "[#{time}] #{$1} #{stats}"
last_was_print = false
when /info/
unless $verbose
print "."
STDOUT.flush
last_was_print = true
end
end
end
end
File.delete(TERM) if File.exists?(TERM)
end
round += 1
end
File.delete(TERM)
[Posted by Urban Hafner on 10 Oct 2007]
While playing around with libEGO and trying to see how far I can get with a simple “all-moves-as-first” Monte Carlo bot. I wrote many (well, three) different versions of the same bot and tested them against each other. Of course for a real test I had to use CGOS. But as I only have one computer that I also use for work I had to run the different bots one after the other. To automate that I wrote a small script that lets you run any number of bots in rotation on CGOS.
It’s a very simple script written in Ruby, so you’ll need to have that installed. For the rest see the comments at the beginning of the file.
#!/usr/bin/env ruby
#
# Run bots one after the other on CGOS. The BOTS variable is an array
# if directories of the bots. In each of these directory there has to
# be an executable file called 'cgos.sh' that connects the bot to CGOS.
# This executable is also required to set the sentinel file name to the
# one given in the TERM variable below.
# Number of games for each bot
GAMES = 1
# The bots that should play
BOTS = ["libEGO-AMAF", "libEGO-AMAF-2", "libEGO-AMAF-3"]
# Sentinel filename to be used by CGOS
TERM = "stop.txt"
round = 0
if ARGV.length > 0 and ARGV.first == "stop"
File.new(TERM, "w")
exit
end
# Clean up (if script wasn't terminated correctly)
(BOTS+["."]).each do |dir|
Dir.chdir do
File.delete(TERM) if File.exists?(TERM)
end
end
until(File.exists?(TERM))
dir = BOTS[round % BOTS.length]
puts "[#{Time.now}] Round #{round+1}"
puts "[#{Time.now}] Running '#{dir}' for #{GAMES} games"
last_was_print = false
Dir.chdir(dir) do
games = 0
IO.popen('./cgos.sh 2>/dev/null') do |pipe|
until(pipe.eof?)
line = pipe.gets
if line =~ /setup/
games += 1
File.new(TERM, "w") if games >= (GAMES-1)
end
case line
when /gameover/
line =~ /gameover\s+\d\d\d\d-\d\d-\d\d\s+(\S+)/
print "\n" if last_was_print
puts "[#{Time.now}] #{$1}"
last_was_print = false
when /setup/
line =~ /setup\s+.*?(\S+\(.*\)\s+\S+\(.*\))/
print "\n" if last_was_print
puts "[#{Time.now}] #{$1}"
last_was_print = false
when /info/
print "."
STDOUT.flush
last_was_print = true
end
end
end
File.delete(TERM)
end
round += 1
end
File.delete(TERM)