Friday, 27 February 2009

中文测试

中文测试标题

该帖子纯粹为了测试中文,如果成功,将在博客上显示正确地中文~~

Wednesday, 25 February 2009

Test

This is a test blog post

If this appears on my Blogspot, then my python script for posting blogs is successful. The following is a test for Pygments code highlighting.

for a in [5, 4, 3, 2, 1]:
    print a

Tuesday, 17 February 2009

流程图生成器(2)

最近用pyparsing写好了流程图定义的模块:
#!/usr/bin/env python
# -*- coding: utf-8 -*-

# flow_parser.py
# author: Rongzhou Shen
# date: 2009-02-11

from pyparsing import *

LSQUARE, RSQUARE, SEMI, ASSIGN, QUOTE = map(Suppress, '[];="')
LBRACE, RBRACE, AT, LBRACK, RBRACK = map(Suppress, '{}@()')

# Definition part of the flow_def file
node_id = Word(alphanums + "_")("id")
node_type = Word(alphas)("type")
declaration = node_type + LSQUARE + node_id + RSQUARE
value = QuotedString('"')
definition = Group(declaration("declaration") + ASSIGN + value("value") + SEMI)

# Flow part of the flow_def file
flow = Group(node_id + OneOrMore(Group('=>' + node_id)) + SEMI)

# Grammar definition of the whole file
flow_impl = OneOrMore(definition)("definitions") + OneOrMore(flow)("flows")
flow_def = AT + LBRACK + QuotedString('"')("flow_name") + RBRACK + LBRACE +\
        flow_impl("flow_impl") + RBRACE

#sample = """
#@("A test flow_chart") {
#    process[node1] = "This is a test process";
#    process[node2] = "This is another test process";
#    a => b => c;
#    ffew => fweji;
#}"""

def test_parse():
    expected = ['process', '[', 'node1', ']', '=', '"',
            'This is a test process', '"', ';']
    test_def = 'process[node1] = "This is a test process";'
    data = definition.parseString(test_def)
    assert len(data) == len(expected)
    assert all([x == y for x, y in zip(expected, data)])

    expected = ['a', '=>', 'b', '=>', 'c', ';']
    test_flow = 'a => b => c;'
    data = flow.parseString(test_flow)
    assert len(data) == len(expected)
    assert all([x == y for x, y in zip(expected, data)])

Tuesday, 10 February 2009

流程图生成器

一直想写一个来着,趁着这次在python.ubuntu.org.cn写[常用库系列]的机会写了这个。目前还不太完善,不过会慢慢改进。接下来要做的就是用pyparsing来完善和扩展我的流程图定义文件。
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from __future__ import with_statement
import yapgvb
import optparse

FORMATS = {"png" : yapgvb.formats.png,
        "jpg" : yapgvb.formats.jpg,
        "gif" : yapgvb.formats.gif}
ENGINES = {"dot" : yapgvb.engines.dot,
        "neato" : yapgvb.engines.neato,
        "circo" : yapgvb.engines.circo,
        "twopi" : yapgvb.engines.twopi}

if __name__ == '__main__':
#    args = sys.argv
#    if len(args) < 2:
#        print "Usage: python state_machine.py <def file>"
#        sys.exit(0)

    parser = optparse.OptionParser()
    parser.add_option("-f", "--format", dest="format",
            help="store the flow chart in FORMAT",
            metavar="FORMAT", default="png")
    parser.add_option("-o", "--output", dest="output",
            help="save the flow chart to FILE",
            metavar="FILE")
    parser.add_option("-e", "--engine", dest="engine",
            help="the layout ENGINE to use for the flow chart",
            metavar="ENGINE", default="dot")

    options, args = parser.parse_args()
    if len(args) < 1:
        parser.print_usage()
        sys.exit(0)

    graph = yapgvb.Graph("States")
    node_dict = {}

    with open(args[0]) as def_file:
        lines = [l.strip() for l in def_file.readlines()]
        for line in lines:
            nodes = line.split("=>")
            prev_node = None
            for node in nodes[::-1]:
                label = node.strip().split("#")
                if not node_dict.has_key(label[0]):
                    node_in_graph = graph.add_node(label=label[1],
                            shape='ellipse', fillcolor='yellow',
                            style='filled', width=0.5)
                    node_dict[label[0]] = node_in_graph
                else:
                    node_in_graph = node_dict[label[0]]

                if prev_node:
                    edge = node_in_graph - prev_node
                    edge.arrowhead = 'normal'

                prev_node = node_in_graph

    graph.layout(ENGINES[options.engine])
    format = FORMATS[options.format]
    if options.output:
        out_file = options.output
    else:
        out_file = args[0] + "." + format

    graph.render(out_file, format)

Wednesday, 28 January 2009

Vim和Shell/GNU Screen搭配的困扰

一直使用Vim与GNU Screen搭配编程,有几个原因: 1. 命令行上的Vim和GVim在功能上几乎没有区别(某些插件是只能用GVim,不过我没有); 2. GNU Screen在重启X时不会影响其中程序的运行; 3. 一直用命令行的话,我可以随时关注命令行上其他程序的情况,例如mutt有无新的邮件,irssi有无新的消息; 但一直有一个问题困扰着我,就是命令行下的Vim屏幕滚动非常缓慢,按住j不动一直到屏幕上最后一行,然后松手,光标会继续往下走十几行甚至几十行,这让我很不爽。 今天作了一个实验,得出以下结果: 1. GNU Screen打开与否和这个现象无关; 2. 此现象只有在分裂Vim窗口时才会出现; 3. GVim没有这个现象; 在网上搜索了一番,暂时没有找到解决的办法。因为GVim没有这个问题,所以暂时用GVim代替。GVim的问题在于离开命令行我就无法得知某些命令行程序的信息。如果能找到解决办法就好了

Thursday, 22 January 2009

irssi提醒脚本

喜欢irssi这个命令行上的IRC,每天都会打开上#ppmm, #ubuntu-cn, #java, #python等频道~~ 命令行工具的一个缺陷在于,提醒功能不完善。虽然用screen,在状态栏上也有提醒,不过并不是任何时候都会盯着命令行的,所以还得有一个图形界面的提醒。 幸好irssi提供了扩展脚本这个功能,所以能够用Perl对其进行扩展。在网上搜索一番之后,发现有人写过提醒脚本,调用gtk-dialog-info这个命令行在屏幕右下角生成提醒窗口。但原始脚本并不是很适合我,所以作了一番修改之后,成了下面这样:
##
## Put me in ~/.irssi/scripts, and then execute the following in irssi:
##
##       /load perl
##       /script load notify
##

use strict;
use Irssi;
use vars qw($VERSION %IRSSI);

$VERSION = "0.01";
%IRSSI = (
  authors     => 'Luke Macken',
  contact     => 'lewk@csh.rit.edu',
  name        => 'notify.pl'
);

sub notify {
    my ($server, $msg, $nick, $address, $target) = @_;

    return if (!($msg =~ /anticlockwise/));

    system("notify-send -i gtk-dialog-info -t 5000 '$nick' '$msg'");
}

Irssi::signal_add('message public', 'notify');
原始脚本采用的irssi信号是print text,虽然这个信号能够检测个人信息,却无法得到消息的内容(所谓的text是指的系统消息,却不是聊天消息)。所以就改成了message public,然后message public又没有一个通用的检测是否个人消息的方法,所以就只能用正则表达式来判断了,有些傻,不过管用。

Wednesday, 21 January 2009

Python Google Translate调用脚本

前一阵子一直想找一个命令行上的翻译程序,就自己写了一个Python程序:
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import urllib
import urllib2
import sys
import jsonlib
from optparse import OptionParser

URL = "http://ajax.googleapis.com/ajax/services/language/translate?v=1.0&q=%s&langpair=%s%%7C%s"

parser = OptionParser()
parser.add_option("-f", "--from", dest="lang1",
        help="The language code to translate from", default="en")
parser.add_option("-t", "--to", dest="lang2",
        help="The language code to translate to", default="zh")

(options, args) = parser.parse_args()
if len(args) < 1:
    print "Usage: python translate.py <translate text>"
    sys.exit(0)

text = ' '.join(args)
print "Translating %s from %s to %s" % (text, options.lang1, options.lang2)
query = (URL % (urllib.quote(text), options.lang1, options.lang2))
req = urllib2.Request(query)
req.add_header("Referer", "http://www.my-ajax-site.com")
r = urllib2.urlopen(req)

data = r.read()
obj = jsonlib.read(data)
if obj['responseStatus'] != 200L:
    print "Error: %s" % obj['responseDetails']
else:
    print "Translated text: %s" % obj['responseData']['translatedText']