Monday 27 April 2009

Using pygame to develop with context free

A problem I have had while playing round with Context Free, is that every time I change the cfdg file, I have to rerun cfdg and then display the resulting image. This got me thinking that there must be a good way to monitor the file and every time it changes just re-run and display the image. My mind wondered back to a pycon UK when I saw a guy using pygame to display his slides. The reason being that as pygame is essentially a framework for displaying images and handling events without the tedious bits around the edges, he could very easily create a slide show that could run on anything without an extra program required. Putting this to work against my problem I could just create a python app that would monitor the file and every time the file changed, rerun cfdg and display the image in pygame. It turns out that this is ridiculously easy: 1) Initialise a pygame window 2) Start a thread to monitor the file. The thread just runs the cfdg with popen and displays the image created to the pygame window. I found it better to just run every second that way I could see the different images created by the random branching in context free. 3) Keep going till a keystoke kills the process. So here it is (python 2.5):
import pygame, sys, threading, time, os

def setupScreen(width, height):
    screen = pygame.display.set_mode( (width,height) )
    return screen
def waitForKeyStroke():
    runProgram = True
    while runProgram:
        event = pygame.event.wait()
        if event.type == pygame.QUIT or event.type == pygame.KEYDOWN:
            runProgram = False

def displayImage( screen, path ):
    px = pygame.image.load(path)
    screen.blit(px, px.get_rect())
    return px

class updator(object):
    def __init__(self, screen, cfdgPath, imagePath):
        self.running = True
        self.screen = screen
        self.cfdgPath = cfdgPath
        self.imagePath = imagePath
        self.updatePeriod = 1

    def updateScreen(self):
        while self.running:
            f = os.popen('cfdg %s %s' % (self.cfdgPath, self.imagePath))
            txt =
            if f.close():
                print txt

def mainLoop(screen, cfdgPath, imagePath):
    u = updator(screen,cfdgPath,imagePath)
    t = threading.Thread(target=u.updateScreen)
    u.running = False
if __name__ == "__main__":
    "Usage  "
    screen = setupScreen(500,500)
    mainLoop(screen, sys.argv[1], sys.argv[2])

Wednesday 15 April 2009

Emacs - Copying a whole line without killing it

For some reason I always find myself trying to copy a whole line and then pasting back somewhere else. I have never found a good way in Emacs to do this except for <home> C-k C-y until today, when I wrote this little function to do it for me and bound it to M-k because I never use kill-sentence anyway. (the excessive commenting is for people learning Lisp like me)
;Create a COPY line function
(defun copy-total-line ()
  "Copy the whole line that the cursor is on"
   ;We want to return to where we started
    ;Jump to the start of the line          
    ;Store the start of the line         
    (let* ((startpos (point)))    
      ;Move to the end of the line
      ;Add it all to the kill ring as M-w would                       
      (kill-ring-save startpos (point) )  
;Bind it to M-k (cause I never use kill sentence)
(define-key global-map "\M-k" 'copy-total-line)
On further searching the Emacs wiki has some other functions to do this, but this way I learned some lisp!

Context Free Art

A few months ago I stumbled upon Context Free Art. It is basically a way of drawing images by using a context free grammar. The images on the site were pretty nifty, but after unsuccessfully compiling the source I gave up forlorn that I would never be able to use a context free grammar to create images. Only to check back on the site every once and a while to see what new images others had created. Today I found myself with nothing better to do so I was going to give compiling the program another try. While seeing if I had the required libraries I had the brain wave to search every field in the FreeBSD ports website for "context". Bingo! A quick portinstall cfdg and I had it on my laptop. So now I am free to context free myself into odd fractal patterns. The moral of the story is that FreeBSD ports is a truly amazing tool.