Thursday, September 9

And now ...

... from the "Something Completely Different" department, here are some pictures taken with my phone:

IMAG0050

IMAG0052

IMAG0060

IMAG0071

IMAG0077

IMAG0082

IMAG0083

IMAG0084

IMAG0005

IMAG0023

Sunday, August 8

A Python Syntax Highlighter for HTML, Written in Python

As of late, I wanted to post some python code on my blog and the formatting options I found kind of sucked (actually I was getting bored and looked for excuses to roll my own).

I had a look at some options, but the most known, either had to be installed locally (and I didn't want to do that), or they worked online, but the generated code was incomplete or the formatting sucked (in my self-absorbed opinion).

Long story short, I wrote my own, in Python.

The formater generates HTML code separating operators, keywords, tokens (identifiers, variables and numbers), comments and text.

The colors for these can be set in the COLORS global map.

Here's the code (the formatter err ... formatted itself for this post, as a test):

import sys
import re

# alphanumeric character escaped
# for regular expressions
ALPHANUMS = 'a-zA-Z0-9_'

# python operators, escaped
# for regular expressions
OPERATORS = r'\.\(\)\[\]\{\}\:\'\"\!=,%\+\-\*\/\^\&<>'

# python keywords
KEYWORDS = ['if', 'for', 'while', 'do', 'def',
    'class', 'None', 'True', 'False', 'and',
    'or', 'not', 'import', 'else', 'elif',
    'raise', 'except', 'break',    'continue',
    'lambda', 'return', 'yield', 'global']

COLORS = {
    'bg':'#030303',
    'kw':'blue',
    'tk':'silver',
    'op':'teal',
    'cm':'green',
    'txt':'red',
    'qu':'darkred',
    '??':'white'}

# how many spaces should a tab character be:
TAB_LENGTH = 4

escape = lambda source, replacements: \
    ''.join( [ c if c not in replacements \
        else replacements[c] \
        for c in source ] )

# escape a string so it will be parsable
# by the re module
def rxEscaped(source):
    replacements = {
        r'[':r'\[',
        r']':r'\]',
        r'{':r'\{',
        r'}':r'\}'}
    return escape(source, replacements)

SPACES = ' \t'
SPLITTERS = rxEscaped( OPERATORS + SPACES )

class TokensList(list):

    replacements = {
        '<':'&lt;',
        '>':'&gt;',
        '&':'&amp;',
        ' ':'&nbsp;',
        '\t':'&nbsp;'*TAB_LENGTH}

    def __init__(self):
        list.__init__(self)

    def add(self, key, value):
        self.append(
            (key, \
            escape(value,
                TokensList.replacements)) )


class Tokenizer(object):
    '''Transforms a line in a group of tokens,
    where each token is represented by a pair:
        line -> [ (key, token), (key, token), ... ]

    The key represents the type of the token:
        kw = keyword
        tk = word
        sp = spacing
        op = operator
        cm = comment
        qu = quotes
        txt = string contents
        ?? = unidentified (for any errors)

    '''

    rxToken = re.compile(r'''
        ^(?P<tk>[%s]+)        # string token
        |(?P<sp>[%s]{1})    # or space
        |(?P<op>[%s]{1})    # or operators
        |(?P<cm>\#.*$)        # or comment
        ''' % (ALPHANUMS, SPACES, OPERATORS), \
        re.VERBOSE)

    quotes = None

    def __init__(self):
        self._init()

    def _init(self, line=''):
        self.line, self.parsed = line, line
        self.tokens = TokensList()

    def _parseRx(self, rx):
        '''Search for rx against line and return
        the found match and the groups dict.

        '''
        found = re.search(rx, self.parsed)
        if found:
            return (found, found.groupdict())
        else:
            return (None, None)

    def _parseStringStart(self):
        quotes = \
            self._parseRx(r'^(?P<qu>[\']{3})')[1] or \
            self._parseRx(r'^(?P<qu>[\"]{3})')[1] or \
            self._parseRx(r'^(?P<qu>\')')[1] or \
            self._parseRx(r'^(?P<qu>\")')[1]
        if quotes:
            quotes = quotes['qu']
            self.parsed = self.parsed[len(quotes):]
            Tokenizer.quotes = quotes
            return True
        return False

    def _getTokens(self):

        while self.parsed:
            ## are we in a string?
            if Tokenizer.quotes:
                if len(Tokenizer.quotes) == 3:
                    # rx for multiline string
                    rx = '(?P<qu>%s)' % \
                        (('\\' + Tokenizer.quotes[0])*3)
                else:
                    # rx for single line string
                    rx = r'(?P<qu>%s)' % \
                        Tokenizer.quotes
                token, gd = self._parseRx(rx)
                if gd:
                    start, end = token.span('qu')
                    if start > 2 and \
                        self.parsed[start-1] == '\\' and \
                        self.parsed[start-2] != '\\':
                        self.tokens.add('txt',
                            self.parsed[:end])
                        self.parsed = self.parsed[end:]
                    else:
                        self.tokens.add('txt',
                            self.parsed[:start])
                        self.tokens.add('qu', gd['qu'])
                        Tokenizer.quotes = None
                        self.parsed = self.parsed[end:]
                    continue
                elif len(Tokenizer.quotes) == 3:
                    # a multiline string is legal
                    # add everything as text
                    self.tokens.add('txt', self.parsed)
                else:
                    # singleline string not closed
                    # pass everything as '??'
                    self.tokens.add('??', self.parsed)
                    # process next line correctly
                    Tokenizer.quotes = None
                break

            # are qe opening a string now?
            if self._parseStringStart():
                self.tokens.add('qu', Tokenizer.quotes)
                continue

            # we're not parsing a string
            token, gd = self._parseRx(Tokenizer.rxToken)
            if not gd:
                self.tokens.add('??', self.parsed)
                break

            for key in gd:
                value = gd[key]
                if not value:
                    continue
                elif value in KEYWORDS:
                    self.tokens.add('kw', value)
                else:
                    self.tokens.add(key, value)
            self.parsed = self.parsed[token.end():]

    def parse(self, line):
        # reset the object
        self._init(line)
        # get list of tokens
        self._getTokens()
        # merge like tokens
        retval, currentKey, currentList = [], '', []
        for key, value in self.tokens:
            if key == currentKey:
                currentList.append(value)
            else:
                retval.append( (currentKey, currentList) )
                currentKey, currentList = key, [value]
        if len(currentList):
            retval.append( (currentKey, currentList) )
        self.tokens = retval
        return self.tokens

def generateFormattedFile(source, destination):
    '''Generate a formatted HTML block
    from the source code.

    '''

    dest = open(destination, 'wt')
    dest.write('''<div style="background-color:%s;">
        <pre>''' % COLORS['bg'])

    tokenizer = Tokenizer()

    NEWLINE = '\n'

    for line in open(source).readlines():
        line = line.rstrip()
        if not line:
            dest.write(NEWLINE)
            continue
        formattedLine = ''
        for name, list in tokenizer.parse(line):
            if name in COLORS:
                formattedLine += \
                    '<span style="color:%s;">' % \
                        COLORS[name] + \
                    ''.join(list) + '</span>'
            else:
                formattedLine += ''.join(list)
        dest.write(formattedLine + NEWLINE)
    dest.write('''
        </pre>
    </div>''')

if __name__ == '__main__':
    if len(sys.argv) < 2:
        print('Syntax: %s <sourcefile>' % sys.argv[0])
    else:
        generateFormattedFile(sys.argv[1], sys.argv[1] + '.html')

  

Thursday, July 29

On Inception - an amateur critique

Like many armies of movie goers, I saw Inception last evening and was ... not disappointed. I can't say the movie was good, but I think I can say it was not bad either.

Here's a trailer:


WARNING: Spoilers ahead.

I found it to be a combination of some opposed styles, combining on one side the exploration of the mind through dreams and symbols with Matrix-style effects and Mission Impossible-style action.

While it's a good combination of styles, none of them prevailed, and each style was sacrificed somewhat  in favor of the others. As such you have a movie that could have been a great effects-movie (but it's a bit too convoluted for that), a great action movie (but it's a bit too convoluted for that also) and a great psychological movie (but it's too action-packed for that).

Also, the trailer makes you think the movie is about the power of an idea. It's not (well ... it is about that, to the degree that say ... Ronin was about the power of a suitcase - that is to say, not at all).


I liked a few themes in it (the "going deeper" in the subconscious by entering a dream within a dream for example). Maybe I found it interesting because it sounds like a plausible hypnosis technique (I'm not sure).

I also liked the symbols (though some were repetitive and simplistic), the ending, some of the dialogues and I especially liked the idea put-forward at the end:
Mal (a figure within Cobb's subconscious) tells Cobb that maybe his reality is the dream because it's implausible for nameless corporations to chase you all over the globe - it sounds too much like a dream.
This idea, striking to Cobb at the time, seems to support one of the possible interpretations of the ending of the movie.

I also found the idea that at the deepest subconscious level there's a common ground very ... attractive. It gives you something to think about (if nothing else).

What I didn't like about the movie was ... well for one, I would have expected Cobb to actually be an expert in the mind (considering the movie starts by portraying him as such). Instead, he appeared more like an action man who "knows all the tricks".
Cobb: I know how to find secrets from your Mind, I know all the tricks!
(see? :-D)


First, there's not much about those tricks in the movie. There's the Totem idea (actually that was quite good), the idea of things being hidden in symbols of safety (a safe within a house within a house and a safe within a wall and a safe within a fortified fortress? I mean ... subtle much?). Then you just have some veiled references and explanations in conversations that didn't touch on much of anything (some explanations on how the mind builds the dreamscape, why you shouldn't change somebody else's dreamscape endlessly and so on).

Through the movie, Ariadne - a beginner in the field trained by him - trumps him over and over again; and ... err ... Ariadne constructs mazes. It must have been a coincidence.

In this light, it seemed like, while Cobb knew all the tricks, he was not so much of an expert on "all things mind". He also ignored the problems in his own mind to such a blatant degree that he risked ruining mission after mission (the first mission is complicated by his issues, the second even more so, and we're left to understand this had been going on for a while), while the most important thing in his real-life (living with his kids) was at stake. I understand having a troubled past and living with your own demons, but this looks a bit like a plot-hole, or like dilettantism on Cobb's side.

Second, the mind-scape issue is also lacking a bit and incomplete. I found a much better exploration of the subconscious and symbols the mind creates in What Dreams May Come for example.

While the movie abounds in dream-specific symbols and items (a spinner that goes on and on in a dream, the coherence of reality being broken, heavy rain because the dreamer had to go to the bathroom, or walls that squeeze you while you struggle to get through) any dream-like feeling is completely missing. There are other movies that manage it way better (see the tensioned atmosphere in Lester Burnham's dream in American Beauty, or Mary Lomax' dream in The Devil's Advocate). Such an atmosphere would have probably detracted from the intense action though, so it was probably sacrificed (if it was even considered).

Third, there was the whole "going deeper in the subconscious than anyone else in the whole world, and synchronizing three things falling at the same time and at different speeds, and in three different dream levels, by three different people with Robert break into his own mind to construct a false idea in a way his own subconscious will not reject" thingy. Did I mention convoluted? I thought I did.

I had two friends ask me "Did you understand anything?" the moment we met outside the cinema. I understand the question is being asked by others who saw the movie also.

All in all it was an entertaining movie for me. If you want an action movie (that's not about the power of an idea - as the trailer suggests) but more about Mission Impossible-style action using Matrix-style effects in convoluted overlaid dream-scapes, go and see it.

It was entertaining.

gletchersee

gletchersee

Wednesday, June 2

Fire Poker Zen

from deoxy.org:

Hakuin used to tell his pupils about an old woman who had a teashop, praising her understanding of Zen. The pupils refused to believe what he told them and would go to the teashop to find out for themselves.

Whenever the woman saw them coming she could tell at once whether they had come for tea or to look into her grasp of Zen. In the former case, she would server them graciously. In the latter, she would beckon to the pupils to come behind her screen. The instant they obeyed, she would strike them with a fire-poker.

Nine out of ten of them could not escape her beating.

utnapistim's comment:

If you wanted to find Zen, forget about it!

Tuesday, May 4

At Nemo33, Bruxelles

First dive at Nemo 33, Bruxelles.

You don't need an insulation suit, or any weights. The visibility is perfect and the environment is great for exercises. A dive takes around 40-50 minutes (max - in our case it was 27 minutes) and costs 22 Euros.

Dive data for the dive:
Time In: 12:24
Time Out: 12:51
Max Depth: 11.4m

Water temperature: high (no insulation suit needed)
Weights: none (no insulation suit, 12L steel)
Visibility: perfect

Air consumption (12L):
In: 180 BAR
Out: 100 BAR