2008年05月30日

Kelie Feng制作的UliPad介绍的视频,现在可以在Showmedo网站上看到了。

观看地址在 http://showmedo.com/videos/series?name=ZODUqnEaL

另外Dick Moores将原始的视频放在了他的网站上可以下载 http://www.rcblue.com/u3/Introducing_Ulipad_2008-05-22.avi

感谢Kelie Feng和Dick Moores的努力和宣传。

2008年05月21日

今天zoom.quiet给项目起了一个新名字,叫uliweb,不过他宣传得很大,对于我只想先测试一些web框架方面的想法,当然如果有人愿意用是最好的。同时邀请了ygao加入了项目。目前已经有:我,zoom.quiet, ygao, 刘鑫。项目已经建立了 http://code.google.com/p/uliweb 同时建立了邮件列表 http://groups.google.com/group/uliweb。所以以后有什么问题或建议关于uliweb的,都可以在这个邮件列表中讨论。当然在python-cn邮件列表还可以讨论。如果你感兴趣欢迎随时加入。如果你对trunk版本不满意,可以随意创建自已的分支,对于可以合并到trunk中的代码我想需要小心处理。

目前正在使用uliweb来改造以前的 http://ulipad.appspot.com 项目。因为以前ulipad.appspot没有使用任何框架,模板使用的是web2py的,所以已经很接近现在的uliweb了,改动主要集中在view的替换上。工作正在进行中。

2008年05月20日

现在最新版的kuaiboo(需要从svn中获得)已经可以运行在GAE上了。不过我还没有在真正的环境下测试,只是在dev环境下试的。步骤如下:

1. 从svn中取得最新的版本

2. 使用export导出到一个目录下,可以直接导出到google的开发目录下。我的目录为:C:\Program Files\Google\google_appengine

3. 修改app.yaml和kuaoboo文件夹的名称为你想要的项目名称

4. 启动GAE的测试服务器可以开始运行。应该可以进入Hello这个测试环境中。

目前kuaiboo因为很简单,所以没有数据库的东西,你可以直接使用GAE的数据库接口。不过对于一个框架来说,数据库是一个很微妙的东西。我想在想它未必一定要做为核心组件。

不过在开始在GAE上测试时出现问题,在views导入时提示expose不存在。因为我是将其放在__builtin__中的,本来在一般的Python环境下应该是可以当成内置函数直接使用的,但是好象GAE给处理掉了,不起作用,最后还是使用了

from frameworks.SimpleFrame import expose

这种方式解决了问题。但是在非GAE环境下还是不需要导入的。不过对于在view函数中注入func_globals的方法还是没有问题。有兴趣的试一试吧。

2008年05月17日

更新记录:

1. 增加静态文件的支持。目前你只要在任何一个views文件中增加以下内容:

from frameworks.SimpleFrame import static_serve
@expose(‘/static/<regex(".*$"):filename>’)
def static(filename):
    return static_serve(request, filename)

这样一旦你的链接是/static/filename时,kuaiboo会自动查找所有app下的static文件夹,如果找到则返回这个文件。这里expose可以使用<regex("pattern"):argu_name>的形式进行正则式的匹配。注意正则式需要使用双引号引起来。这个静态文件处理支持条件返回,即如果文件没有改变,则返回304,文件将不会下传。同时支持406 Partial Content下传,可以支持分块下传。当然这些是webob已经提供的,同时参考了webob的这篇文档。因此实现已经很方便。这样在你刷新时,如果静态文件已经下传,再刷新时,会在console的日志中看到304。不错。

一旦部署到生产上,你可能会想使用web server来做静态文件的处理,没问题。只要将所有app下的static文件汇总到一起,统一由web server提供服务就可以了。这个汇总工具还没有做,以后再说,很简单。

2. 扩展werkzeug的URL Converter,扩展了一个正则式的Converter,可以从上例看到。

3. 扩展views函数的func_globals内容,现在有:

    def _prepare_env(self):
        env = {}
        env['url_for'] = url_for
        env['redirect'] = redirect
        env['url_map'] = url_map
        env['render'] = self.render
        env['config'] = config
        from werkzeug import html, xhtml
        env['html'] = html
        env['xhtml'] = xhtml
        from utils import Form
        env['Form'] = Form
        return env
       
    def get_env(self, request, response):
        env = self.env.copy()
        env['request'] = request
        env['response'] = response
        return env

以上在env中的key对应的对象都是你可以直接在views函数中使用的。

4. 将expose放到__builtin__模块中,这样在views文件中,你不需要导入这个函数,可以直接使用,就象是使用内置函数一样。可以减少不必要的导入。目前我只放入了这个。

5. 在request创建后,将appname和function绑定到request对象上,因此你可以直接使用request.appname得到views函数对应的app名字。这样当使用url_for来生成url时,一般是这样的:

url_for(‘Hello.views.index’, **kw)

但这样你的appname是写死的,这里是Hello,但如果你的app改名了怎么办,那么现在可以使用:

url_for(‘%s.views.index’ % request.appname, **kw)

现在你在Hello App中的index.html可以看到这种用法。

6. 增加了一个default_config,将用来放置一些缺省的配置。同时将settings改为config了。这样你可以使用config来读取配置在settings中的信息。它是一个Storage对象。这个Storage是从web2py中弄过来的,它就是一个dict,但是可以使用obj.attr的方式来引用key,同时如果不存在则返回None。那么你使用起来就和Module差不多了。但是对不存在的变量不会抛异常。同时所有配置项需要大写,这一点与django相同。

7. 在views你可以调用redirect(url)来进行转换。原来需要使用return,现在只要调用就行了。它会引发一个异常,并且被Dispatcher处理。

8. 在views中还可以使用error(**kw)来引发一个错误,它会自动调用一个错误模板,同时你也可以自已来指定出错模板。它也会引发一个异常,并且被Dispatcher来处理。

更新说明:

  1. 用户可以设定settings.py。目前kuaiboo支持在apps目录下的settings.py文件和每个app目录下的settings.py。目前apps的settings.py作为主配置文件,kuaiboo会直接导入,其它的app下的settings.py会使用__import__,然后将属性合并到settings中去。因此最终这些settings.py将合成一个,你可以在代码中导入setting。(不过对于子settings.py的处理我还在考虑是否要使用exec来处理,这样,子settings.py将不再是通过导入了,它们将在主settings.py的环境下运行,这样更象是在同一个环境下运行的。不过这块还没有想好。)
  2. expose的处理方式进行了扩充。在张沈鹏的留言中他建议能否自动映射,我理解可能有两种方式:一种是不需要expose,view函数直接映射为url,那么一方面用户无法控制哪些是可以访问,哪些是内部函数,所以我认为不使用expose不太好。当然expose只是一种实现方式,也许以后url的映射的定义会有根它的方式。另一种理解可以是只使用expose,那么当没有参数时使用自动映射。如何映射呢?我现在的方法是将view函数映射为:/appname/viewfuncname/arg1/arg2。这种方式接近web2py的,不过我没有controller一层,所以没有controller的url。那么它是怎么做的?后面会有介绍
  3. view函数的变化。原来view函数需要使用def func(req, arg1, arg2,…):,现在你不再需要req这个参数了。也就是你可以象web2py一样来定义view函数:def func(arg1, arg2):。但是你仍然可以在view函数中直接使用象request, response这样的对象,为什么,后面会有介绍。

expose的自动映射

你可以直接使用@expose来直接映射一个view方法,我是怎么做的?

def expose(rule=None, **kw):
    if callable(rule):
        f = rule
        import inspect
        args = inspect.getargspec(f)[0]
        if args :
            args = ['<%s>' % x for x in args]
        appname = f.__module__.split(‘.’)[1]
        rule = ‘/’ + ‘/’.join([appname, f.__name__] + args)
        kw['endpoint'] = f.__module__ + ‘.’ + f.__name__
        url_map.add(Rule(rule, **kw))
        return f
       
    def decorate(f):
        kw['endpoint'] = f.__module__ + ‘.’ + f.__name__
        url_map.add(Rule(rule, **kw))
        return f
    return decorate

当你使用expose时,rule参数将是function对象,因此,判断出rule是函数对象时,它将根据function本身的信息来得到它所在的模块(f.__module__)和函数名(f.__name__)。只不过f.__module__得到的是类似于apps.App.views的形式,因此要处理一下才能得到App的名字。同时一个view函数可以定义了参数,因此我还使用了inspect模块来得到定义的参数名。详情可以看它的文档,同时做一些试验。因此一个view函数会被自动映射为:/Appname/view_func_name/arg1/arg2的形式。

View函数的变化

原来view函数要定义为def func(req, arg1,…),现在你不需要第一个req的参数了。但是你仍然可以在函数内部使用request, response等对象。(至于在view函数中还能使用哪些变量我还要考虑中,可能会不断增加,这样非常接近于web2py的效果。)那么是如何实现的呢?原来我发现你可以动态修改一个函数对象的func_globals对象,如:

>>> def f():
…     print response

如果你定义上面的函数,编译不会出错,但是运行会出错。因为我们没有定义response。一种方法是定义全局的response变量,另外就是可以修改func_globals增加这个变量。如:

>>> f.func_globals['response'] = ‘hello’
>>> f()
‘hello’

可以看到执行没有问题。相当于我们定义了全局的response变量。这就相当于变量的注入,你可以直接使用。

2008年05月16日

昨天基本上已经有一个雏型放到svn中去的,如果你下载最新的代码已经是一个可以运行的版本了。目前因为只是在开发阶段,所以许多东西并不定型,很多东西可能会变化,因此你目前只能玩一玩。下面举些简单的例子,这些例子已经在svn中的。

1. 下载源码

svn co http://mymisc.googlecode.com/svn/trunk/kuaiboo

BTW,为什么叫Kuaiboo,因为我实在不擅长起名字,这个名字中英文混合,有些接近“快步”的意思,因此中文名字希望是开发web象快走一样方便(当然只是一个愿望)。当然如果你有好的名字可以贡献给我的话我会非常感谢。

2. 现在已经自带一个开发服务器,它是使用Werkzeug的,并且这个开发服务器自带reload功能,如果你做了任何怎改,它会自动装入,很方便,与django, GAE的差不多。在windows下的话,按Ctrl+C可以关闭。GAE的好象不行。不过按Ctrl+Break应该是都可以的。一旦你的程序出现语法错误,那么这个开发服务器有可能编译出错而退出,所以你要注意检查。这块回头看一看能不能改一下,不让它自动退出。

下载下来后,你的目录应该看上去象这样:

kuaiboo\
    apps\
        __init__.py
        Hello\
            __init__.py
            views.py
            templates\
            static\
    kuaiboo\

apps中将用来放置你的app的代码。要记住kuaiboo是象django一样以app为单位的。固定放在apps下。它是一个python的package,目前命令行工具还没有开发可以自动生成这种目录结构,不过很简单。

kuaiboo是库文件,放置各种各样的模块,现在有Werkzeug, webob,还有其它的一些东西,比如web2py的模板,我写的Form等。

在apps中已经有一个Hello的应用,它是一个测试程序,很简单。每个app都是一个package,因此有__init__.py。目前Hello中还没有数据库的处理,因此没有models模块。不过关于数据库这块我想不要绑得过死。比如GAE数据库与一般的关系数据库就不相同,因此这个框架可能更多的是在非数据库的地方吧,不过还没有想好。

views.py是放view代码的。templates是放模板的。而static是放静态文件的,不过目前还没有用到。为什么要static呢?这是我曾经在django中的想法的一个实现。一个app应该是功能完整的集合,所以静态文件也算其中之一,放在app中是为了方便复用,如拷贝。

OK。结构已经介绍完毕,下面开始写views了。

4. 第一个模板的例子

from frameworks.SimpleFrame import expose

@expose(‘/’)
def index():
    return {}

把上面的代码加到views.py中。让我一行行地解释。

from frameworks.SimpleFrame import expose 这里从frameworkds.SimpleFrame中导出expose将用于url的生成。在SimpleFrame中引入了一些常用的方法或对象可以直接使用。后面还会用到如url_for, redirect等。

@expose(‘/’) 这是一个decorator,它用来将下面的函数与某个URL相对应,这里是’/'。因此当你访问/时,就会调用index()函数。这里url的定义我是使用Werkzeug的,因此更详细的可以看它的文档。这种URL的映射可以支持参数定义,如’/blog/<int:year>/</int:month>/</int:day>,怎么样,再来一个’/user/<username>’,可以看到你可以使用<type:name>来定义或<name>来定义参数,其中type为类型。是不是比django的纯正则要简单?这个例子还没有使用参数例子。目前kuaiboo还不需要urls.py这样的东西,它会自动导入所有views函数,因此只要在你想要输出的函数前加上@expose就可以输出为一个可访问的view函数,没有这个修饰的将不会被访问到。这是一种分散方式url定义,在未来如果view文件非常多不知道会对性能有多大影响,因此以后还会实现一种集中方式的定义。

def index(): 这里定义了index函数,它目前接受一个req的参数(原来是需要req参数,但是现在已经不需要的,你可以在view函数中直接使用request, response对象,为什么?在另一篇Blog中我会仔细描述。)所以有view函数的第一个参数都是req。不过view是使用函数还是class好在我昨天的blog中也说了,不好选择,先用函数吧,至少decorator用着比较方便。这里req其实是webob的Request对象,因此详细信息要查看webob的Request文档。写到这真是有些象turbogears了,都是大杂烩,文档也都在别人哪里。看来用是一回事,写是另外一回事啊。

return {} 在kuaiboo中一个view可以返回三种东西:

  1. 字典,这样kuaiboo会自动查找对应的模板进行处理。目前kuaiboo的策略就是在所有app的templates目录下查找与函数名相匹配的模板文件,如index对应的模板文件名为index.html。因此要注意,如果你的app有重名的函数,在查找模板时可能会使用其它的app中的模板。不过kuaiboo在查找时会优先查找当前app的templates目录,因此一般你不需要担心。不过建议view函数名最好不一样。想一想如果不采用app的开发方式,将所有的view方法放在一起的话,它们会重名吗?不过我也在考虑是否可以自定义其它的模板,不过目前还不支持,有待于以后有需求或有机会去实现它。
  2. 字符串,可以是unicode。它将自动使用Response来封装。
  3. Response对象。使用它可以处理附件下件,cookie之类的设置。

因此上面的例子不是最简单的,因为我还没有定义一个模板。不过如果你把return {}改为return ‘Hello,kuaiboo’,你就已经可以测试了。先让我们把这个例子做完。

5. 进入Hello/templates目录,然后创建一个index.html文件,内容如下:

<html>
<head>
<title>Index Test</title>
</head>
<body>
<h1>Kuaiboo Framework</h1>
<p>This is a test page index.</p>
</body>
</html>

6. 好,下面就可以测试了。进入kuaiboo目录,进入命令行,执行:

python manage.py.py runserver或 manage.py runserver

7. 在浏览器输入: http://localhost:8000

看到结果了吗?

2008年05月15日

这是我新挖的一个坑,不过已经填了些土了。它是什么呢?它是我写的一个web framework。怎么连我也造轮呢?记得我以前是更注重向现有框架做贡献的呀。

首先这个框架是一个试验品,或者说是主要是个人使用,因此我将有完全的控制权,这一点很重要。我可以用它学到许多框架的知识。以前只是使用,学习,象学过:cherrypy, Karrigell, snakelets等,不过没有做过什么开发;zope则是我学得最早了,不过也早就放弃了;django投入的精力最多,也开发了不少东西;再后来就是web2py了,不过重用搞得我很不爽,而且有些想法不被认同。但这些更多的还是集中在开发方面,对于框架本身了解有限,这次造轮是一个好机会。

其次用过的框架都有不让人满意的,而且许多观点也不被认同,因此我想信只有自已的才是最好的。就象我当初离开drPython自已创建了UliPad一样,想怎么做怎么么,很爽,这下子变成别人的观点将不被我认同了(是不是有些小人得志的感觉)?不过现实如此,我也很清楚地早就认识到这一点。因此要么你的努力被社区认同,要么另起炉灶,这种例子太多了,不然也不会有这么多的选择。那么django不让我满意的象模板,虽然对设计者友好,但是对程序员不友好,不想细说了。开发还不够简洁,在我写完Django Step by Step教程之后我已经意识到,用它作为入门的还不如使用Karrigell。太多需要知道的。不过这个也不好解决,功能随着复杂,自然会越来越难。而且这种不简洁是与web2py相比的结果。在学了web2py才知道web也可以这样开发,集成在浏览器几乎可以做一切事,自动的ticket,适合程序员的模板系统,自动维护的数据库模块,最少配置开发,约定url规则,这一些与django相比显得很轻巧和方便。如果你看过代码,的确要比django简单,但是说句实话,因为只是个人项目难免代码的风格和技术要逊于django。不过由于设计上不方便重用,url的固定方式,虽然支持routing的修改,但是还是不够方便,因此仍然让我感到遗憾。而web2py的设计上的修改很有可能是对web2py的某种否定,所以在我看来它无法按我满意的方向发展。不过web2py的作者massimo是一个非常让人敬佩的人,非常有创造力和激情。

所以作为尝试,我打算自已做一个框架,也许用在自已的项目中,也许是放在GAE上用。现在已经有一个雏开型了。目前项目地址在 http://mymisc.googlecode.com/svn/trunk/kuaiboo 你可以使用svn将代码取下来。可以说它是一个大杂烩,我目前集中了:

  • Werkzeug 用它来完成框架的搭建,因为它本来就是用来做框架的
  • webob 用来生成Request和Response对象,因为GAE和pylons就使用它。本来我是使用Werkzeug自带的,不过ygao建议我使用webob,好就先用它,不行再换。
  • 模板使用web2py的,不过进行了改造。我还是挺喜欢它可以支持python代码的方式,虽然块结束时要输入pass,不过没关系,可以用来解决使用缩近造成的排版问题。
  • 数据库还没有加,目前打算使用web2py的模块
  • Form处理我将使用我自已写的,不过更接近django的方式
  • URL mapping还没有想太好,目前我是采用Werkzeug的教程的方式,使用了一个@expose在每个输出的view方法前进行修饰。不过这样的做法需要将所有的view模块先导入才可以,不知道会不会影响效率。
  • 处理模式为MVT
  • View目前采用函数方式,正在考虑是否要使用class方式,不过这样一来decorator的方式就用不了了。
  • 组织方式采用django的app方式,你可以在多个app中组织代码,最终形成完整应用。
  • 与webserver交互一方面是支持wsgi标准,另一方面借用了web2py中的cherrypy模块,可以独立部署为服务器,不过只是测了一下,还没有加进去。

还有些没有想到或没有实现的东西,比如:i18n的问题。可能你已经看出,一个框架要关心的事情真是很多。不过我会一点点完善它。有兴趣你可以关注。那么我会在我的Blog上记录对它的修改,因为是个人项目,所以可能修改得随心所欲。当然欢迎你参与和讨论。

这是一篇massimo张贴在raddit上的文章链接,引来许多的评论。不过许多评论是执不赞同意见。有些是对无导入有质疑,有些是对与django比较所使用的例子有质疑,有些则是认为web2py言过其实,有些还认为massimo不愿接受批评。我想不说存在不存在问题(至少我个人认为不导入对于单APP可能是方便的,但是正是由于这一点造成APP间不能互相调用,存在硬伤),但文章的题目就容易引人争论。

每个人都有自已的习惯,习惯接近的则形成部落,但仍然会有自已的想法。所以人群就是分分合合,框架也是一样,有些人喜欢这种,有些人喜欢那种,有些人是喜欢其中一部分。因此当进行比较时,自然要对自已喜欢的进行维护。

这种争论在语言的比较中最为常见。

不过习惯不同,很难说哪个是绝对的好。也许你认为不好,但是别人就能用它做出Cool的东西来,你说到底好不好。关键还是看使用者的水平。只不过不同的框架提供的思路和方便程序不同,可能找一个更符合个人性格的框架会让你学起来和用起来更舒服罢了。

2008年05月12日
  1. I made blue theme as default theme, so you don’t need to set yourself now. And if you want to use it as default color theme, you should remove all the files in conf/stx, including Python.stx.

  2. With this new implemention, there is still a [default_style] session can be configured in config.ini, and here is the options which you can configure now:

    [default_style]
    STC_STYLE_TEXT = u"fore:#8DB0D3"
    STC_STYLE_NUMBER = u"fore:#FF00FF"
    STC_STYLE_STRING = u"fore:#00FF80"
    STC_STYLE_COMMENT = u"italic,fore:#008040"
    STC_STYLE_KEYWORD1 = u"fore:#FFFF00"
    STC_STYLE_KEYWORD2 = u"fore:#AFFFEE"
    STC_STYLE_IDENTIFIER = u"fore:#8DB0D3"
    STC_STYLE_OPERATOR = u"fore:#F0804F"
    STC_STYLE_CHARACTER = u"fore:#E19618"
    STC_STYLE_REGEX = u"fore:#FFFF80"
    STC_STYLE_DEFAULT = u"fore:#FFFFFF,back:#112435,face:%(mono)s,size:%(size)d"
    STC_STYLE_LINENUMBER = u"fore:#FFFFFF,back:#1F4661,face:%(mono)s,size:%(lnsize)d"
    STC_STYLE_CONTROLCHAR = u"fore:#FFFFFF"
    STC_STYLE_BRACELIGHT = u"bold,fore:#FF0000"
    STC_STYLE_BRACEBAD = u"bold,fore:#0000FF"
    STC_STYLE_CARET_FORE = u"fore:#FF0000"
    STC_STYLE_CARETLINE_BACK = u"back:#5F0054"
    STC_STYLE_SELECTION_BACK = u"back:#000080"
    STC_STYLE_FOLDER = u"back:#3476A3"
    STC_STYLE_MARKER = u"fore:#F0804F,back:#FFFFFF"
    STC_STYLE_TAG = u"fore:#15852B"
    STC_STYLE_TAG1 = u"fore:#2CEF50"
    STC_STYLE_TAGKEY = u"fore:#FFFF00"
    STC_STYLE_ATTRNAME = u"fore:#F0804F"
    STC_STYLE_ATTRVALUE = u"fore:#156EB2"
    STC_STYLE_CLASSNAME = u"fore:#BBFF4F"
    STC_STYLE_DEFNAME = u"fore:#4179C5"
    STC_STYLE_LINK = u"fore:#FEFF8F,underline"
    STC_STYLE_STRINGEOL = u"fore:#FF6F82,back:#E0C0E0,eol"

  3. For STC_STYLE_DEFAULT and STC_STYLE_LINENUMBER, you should notice there are string place holderes, and you can set fontname and fontsize in [default] session, just like:

    [default]
    editor_font = "fontname"
    editor_fontsize = 12
    editor_linesize = 10

And of cause you can directly set the fontname and fontsize in STC_STYLE_DEFAULT and STC_STYLE_LINENUMBER. If you don’t directly set fontname and fontsize in style string, then UliPad will use default Mono font and the font size will be 12, linesize will be 10.

So if you want to custom a new theme, but not limit a single language, you should define [default_style] in config.ini, just like above example. And the old white theme you will be:

[default_style]
STC_STYLE_TEXT = "fore:#000000"
STC_STYLE_NUMBER = "fore:#6B238E"
STC_STYLE_STRING = "fore:#2A2AA5"
STC_STYLE_COMMENT = "italic,fore:#238E23,back:#E8FFE8"
STC_STYLE_KEYWORD1 = "bold,fore:#0000FF"
STC_STYLE_KEYWORD2 = "bold,fore:#2F032A"
STC_STYLE_IDENTIFIER = "fore:#000000"
STC_STYLE_OPERATOR = "fore:#000000"
STC_STYLE_CHARACTER = "fore:#9F9F9F"
STC_STYLE_REGEX = "fore:#DB70DB"
STC_STYLE_DEFAULT = "face:%(mono)s,size:%(size)d"
STC_STYLE_LINENUMBER = "back:#AAFFAA,size:%(lnsize)d" #back:#C0C0C0
STC_STYLE_CONTROLCHAR = "fore:#000000" #xxxxxxx
STC_STYLE_BRACELIGHT = "fore:#FF0000,bold" #fore:#0000FF,back:#AAFFAA,bold
STC_STYLE_BRACEBAD = "fore:#0000FF,bold" #fore:#FF0000,back:#FFFF00,bold
STC_STYLE_CARET_FORE = "fore:#FF0000"
STC_STYLE_CARETLINE_BACK = "back:#EEEEEE"
STC_STYLE_SELECTION_BACK = "back:#000080"
STC_STYLE_FOLDER = "back:#FFFFFF"
STC_STYLE_MARKER = "fore:#FFFFFF,back:#000000"
STC_STYLE_TAG = ‘fore:#15852B’
STC_STYLE_TAG1 = ‘fore:#2CEF50′
STC_STYLE_TAGKEY = ‘bold,fore:#0000FF’
STC_STYLE_ATTRNAME = ‘bold,fore:#F0804F’
STC_STYLE_ATTRVALUE = ‘fore:#156EB2′
STC_STYLE_CLASSNAME = "bold,fore:#FF0000"
STC_STYLE_DEFNAME = "bold,fore:#007F7F"
STC_STYLE_LINK = "fore:#0000FF,underline"
STC_STYLE_STRINGEOL = "fore:#000000,back:#E0C0E0,eol" #"fore:#2A2AA5,eol"

Remeber, this setting will only effect default configuration, but not existed *.stx file .

2008年05月11日

具体的代码在: http://code.google.com/p/ulipad/wiki/BlueThemeForPython

而且在UliPad中的最新代码中,你还可以设置Folder Margin的背景色。还可以设置Marker的前景和背景色。关键字分别为: -folercolor 和 -markercolor。

如果你想修改缺省字体,可以设置default的字体。