从拿到 iPhone 的第一天起,我就在不断地寻找好用的 RPN 计算器。我的要求是
- 类似 Emacs Calc 的进栈出栈方式
- 无限大的堆栈
- 要牛逼

我一直使用的都是一个 HP i41CX 模拟器。它基本符合第一条,但是不符合第二条:它的堆栈只有四层,而且最顶层还就是你正在输入的这个。不过它非常非常得符合第三条,看看这个计算器的像板砖一样的手册就知道了。这个计算器也有一些不便,它实在是太复杂了。比如他默认的键盘配置上没有切换弧度和角度的键。键绑定是可以设的,但是我一直没有搞明白怎么设… 同样因为这个原因,我一直不知道怎么算双曲三角函数。其他的 RPN 计算器要不就是操作方式诡异,要不就是功能太少。所以昨天我终于决定自己写一个计算器。
奋斗了两天以后把四则运算都搞定了… -_- 在 iPhone 上开发程序还是很方便的,和在 Mac 上差不多,熟练了以后写界面用不了太多的时间,而且 Interface Builder 做 prototyping 也非常得爽。我的时间主要都浪费在用 UITableView 显示一个堆栈上。UITableView 就是一个和菜单差不多的可选择的列表,几乎每一个 iPhone 程序里都能看到。但是这个东西必须要有一个符合某种特定协议的数据源… 我曾经一度都想自己用 label 和 UIScrollView 实现一个这种列表了… 不过最后搞定以后发现这个东西还是挺爽的,并且附赠动画效果~~
在 iPhone 上开发程序需要花 $99 买一个许可证。… … …… 噢,不对,说错了,是苹果声称你需要买一个,实际上你不需要。免费开发程序的代价就是开发出来的程序只能在 jailbreak 过的 iPhone 上运行。当然这其实没什么,因为各种迹象表明,没有 jailbreak 过的 iPhone 的使用价值其实就和一个板砖差不多。默认情况下,如果你没买这个许可证,Xcode 是不会让你把程序往 iPhone 上传的,只能在模拟器里运行。要想在 iPhone 里运行,
- 当然要先 jailbreak
- 照着 Compiling 一节做
- Replacing codesign with
ldid,这一节貌似没什么用,我从来没有成功的运行过 ldid,不过我还是做了。
- 给 iPhone 装 AppSync 补丁。很多 Cydia 源里都有,比如 hackulo.us 源。
- 编译时使用自己生成的那个许可证。
关于调试,在开始使用 Linux 之后,我就再也没有使用过任何调试器,只使用 printf(及各种语言里的等效的函数)。Objective-c 里是有 printf 的,但是比较方便的做法是使用 NSLog()。运行的时候在 Xcode 里选择 Run -> Console,可以看到输出。顺便提一下,Objective-c 的标准库还是很牛逼的,嗯,NSString, NSNumber, NSArray, …
今天好好看了一下 ConTeXt 的新文档 co-fonts,然后把平时常用的字体都写成 typescript 放到 texmf-local 里。这样以后写作业就不会出现字体定义比文档内容还长的情况了-_-…
首先定义几个 feature sets
\definefontfeature[latin-smallcaps][smallcaps][script=latn]
\definefontfeature
[fancy]
[language=dflt, script=latn, method=node, pnum=yes, onum=no,
kern=yes, liga=yes, dlig=no, zero=no, tlig=yes, trep=yes,
protrusion=quality, expansion=quality, mapping=tex-text]
然后定义单个字体的 typescript
\starttypescript[myCaslon]
\definefontsynonym[proserif][name:ACaslonPro-Regular]
\definefontsynonym[proserifit][name:ACaslonPro-Italic]
\definefontsynonym[proserifbf][name:ACaslonPro-Bold]
\definefontsynonym[proserifbi][name:ACaslonPro-BoldItalic]
\definefontsynonym[Serif][proserif][features=fancy]
\definefontsynonym[SerifItalic][proserifit][features=fancy]
\definefontsynonym[SerifBold][proserifbf][features=fancy]
\definefontsynonym[SerifBoldItalic][proserifbi][features=fancy]
\definefontsynonym[SerifCaps][Serif][features=latin-smallcaps]
\stoptypescript
\starttypescript[myPalatino]
\definefontsynonym[palarm][name:PalatinoLTStd-Roman]
\definefontsynonym[palait][name:PalatinoLTStd-Italic]
\definefontsynonym[palabf][name:PalatinoLTStd-Bold]
\definefontsynonym[palabi][name:PalatinoLTStd-BoldItalic]
\definefontsynonym[Serif][palarm][features=fancy]
\definefontsynonym[SerifItalic][palait][features=fancy]
\definefontsynonym[SerifBold][palabf][features=fancy]
\definefontsynonym[SerifBoldItalic][palabi][features=fancy]
\definefontsynonym[SerifCaps][Serif][features=latin-smallcaps]
\stoptypescript
\starttypescript[myOptima]
\definefontsynonym[prosans][name:OptimaLTStd]
\definefontsynonym[prosansit][name:OptimaLTStd-Italic]
\definefontsynonym[prosansbf][name:OptimaLTStd-Bold]
\definefontsynonym[prosansbi][name:OptimaLTStd-BoldItalic]
\definefontsynonym[Sans][prosans][features=fancy]
\definefontsynonym[SansItalic][prosansit][features=fancy]
\definefontsynonym[SansBold][prosansbf][features=fancy]
\definefontsynonym[SansBoldItalic][prosansbi][features=fancy]
\definefontsynonym[SansCaps][Sans][features=latin-smallcaps]
\stoptypescript
\starttypescript[myFutura]
\definefontsynonym[prosans][name:FuturaStd-Medium]
\definefontsynonym[prosansit][name:FuturaStd-MediumOblique]
\definefontsynonym[prosansbf][name:FuturaStd-Bold]
\definefontsynonym[prosansbi][name:FuturaStd-BoldOblique]
\definefontsynonym[Sans][prosans][features=fancy]
\definefontsynonym[SansItalic][prosansit][features=fancy]
\definefontsynonym[SansBold][prosansbf][features=fancy]
\definefontsynonym[SansBoldItalic][prosansbi][features=fancy]
\definefontsynonym[SansCaps][Sans][features=latin-smallcaps]
\stoptypescript
\starttypescript[myMyriad]
\definefontsynonym[prosans][name:MyriadPro-Regular]
\definefontsynonym[prosansit][name:MyriadPro-It]
\definefontsynonym[prosansbf][name:MyriadPro-Bold]
\definefontsynonym[prosansbi][name:MyriadPro-BoldIt]
\definefontsynonym[Sans][prosans][features=fancy]
\definefontsynonym[SansItalic][prosansit][features=fancy]
\definefontsynonym[SansBold][prosansbf][features=fancy]
\definefontsynonym[SansBoldItalic][prosansbi][features=fancy]
% No smallcaps
% \definefontsynonym[SansCaps][Sans][features=latin-smallcaps]
\stoptypescript
\starttypescript[myMonaco]
\definefontsynonym[promono][name:Monaco_Linux]
\definefontsynonym[Mono][promono][features=default]
\stoptypescript
把 ConTeXt Minimals 自带的 px-math 也定义一个
% The internal px-math
\starttypescript[myPxMath]
\loadfontgoodies[px-math]
\definefontsynonym[MathRoman][pxmath@px-math]
\stoptypescript
最后写几个常用组合
\starttypescript[PalatinoOptima]
\usetypescript[myPalatino]
\usetypescript[myOptima]
\usetypescript[myMonaco]
\usetypescript[myPxMath]
\definetypeface[PalatinoOptima][rm][serif][myPalatino][default]
\definetypeface[PalatinoOptima][ss][sans][myOptima][default]
\definetypeface[PalatinoOptima][tt][mono][myMonaco][default][rscale=0.8]
\definetypeface[PalatinoOptima][mm][math][myPxMath][default]
\stoptypescript
\starttypescript[PalatinoMyriad]
\usetypescript[myPalatino]
\usetypescript[myMyriad]
\usetypescript[myMonaco]
\usetypescript[myPxMath]
\definetypeface[PalatinoMyriad][rm][serif][myPalatino][default]
\definetypeface[PalatinoMyriad][ss][sans][myMyriad][default]
\definetypeface[PalatinoMyriad][tt][mono][myMonaco][default][rscale=0.8]
\definetypeface[PalatinoMyriad][mm][math][myPxMath][default]
\stoptypescript
\starttypescript[CaslonMyriad]
\usetypescript[myCaslon]
\usetypescript[myMyriad]
\usetypescript[myMonaco]
\usetypescript[myPxMath]
\definetypeface[CaslonMyriad][rm][serif][myCaslon][default]
\definetypeface[CaslonMyriad][ss][sans][myMyriad][default]
\definetypeface[CaslonMyriad][tt][mono][myMonaco][default][rscale=0.8]
\stoptypescript
把这些写成一个文件扔到 textmf-local/tex/context/base 里,然后
luatools --generate; context --make。测试:
\input type-mine
\usetypescript[PalatinoOptima]
\setupbodyfont[PalatinoOptima, roman, 12pt]
\setuppapersize[B5][B5]
\setupinterlinespace[line=1.4em]
\starttext
Serif test 1234567890. {\ss Sans test}. {\tt Typewriter test.}
{\it Serif test 1234567890. {\ss Sans test}.}
{\bf Serif test 1234567890. {\ss Sans test}.}
$M_{ath} \times t^{est} = 1234567890.$ \placeformula
\startformula
\widetilde{G}(\vec k, \omega) = \int_{-\infty}^{+\infty} e^{i(\vec
k\cdot \vec x - \omega t)} G(\vec x, t)\, {\rm d}^3 \vec x\, {\rm d}t
\stopformula
\stoptext
效果如图
 |
 |
| Palatino |
Caslon |
今天需要排一个带 Scheme 代码的文档,里面还有点数学公式,所以决定用 ConTeXt。正好前几天 Steamedfish 同学跟我说过 ConTeXt 可以读取 Vim 的语法加亮,决定看一看。
Google 了一下之后发现 ConTeXt 是使用一个叫做 t-vim 的 module 来干这件事的,我使用的 ConTeXt 发行是 ConTeXt Minimal,于是进入 ConTeXt 的安装目录,更新
./first-setup.sh --extras=t-vim
然后随便排了一个代码。ConTeXt 报错
VIM - Vi IMproved 7.2 (2008 Aug 9, compiled Mar 8 2010 22:56:09)
Garbage after option argument: "-u NONE -e -C -n -c "set tabstop=8" -c
"syntax on" -c "set syntax=scheme" -c "let contextstartline=1" -c "let
contextstopline=0" -c "source 2context.vim" -c "wqa"
"009-vimsyntax.tmp" "
哭了… 这不是要整死我这个 Vim 白痴么… 经过无穷多小时的 google,我终于认识到“Garbage after option argument”错误表示 Vim 的参数有错… 看来要改 t-vim 的代码了。于是打开 t-vim.tex,一看又哭了… 一个 macro 都不认识,这不是要整死我这个 TeX 白痴么… 经过 3000+ ms 的搜索,我终于认识到问题出在 t-vim.tex 的第 344 行:
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
| {\executesystemcommand
{mtxrun --verbose --noquote bin:vim
"-u NONE % No need to read unnessary configurations
-e % run in ex mode
-C % Set compatibile
-n % No swap
% -V10log % For debugging only, will go away later.
-c \shellescapedquote set tabstop=\@@vstab \shellescapedquote\space
-c \shellescapedquote syntax on\shellescapedquote\space
-c \shellescapedquote set syntax=\@@vssyntax\shellescapedquote\space
-c \shellescapedquote let contextstartline=\@@vsstart\shellescapedquote\space
-c \shellescapedquote let contextstopline=\@@vsstop\shellescapedquote \space
-c \shellescapedquote source kpse:2context.vim\shellescapedquote\space
-c \shellescapedquote wqa\shellescapedquote\space
\shellescapedquote#1\shellescapedquote\space "}} |
Macro \shellescapedquote 后面的 \space 会在文件名(#1)的后面加上一个空格。而 mtxrun 会把这个空格当作参数的一部分??!!!于是 vim 就会收到一个很诡异的参数而报错。所以我首先想到的解决方法就是把最后那个 \space 去掉。然后发现编译时最后的那个引号(\shellescapedquote)居然就没了,还是出错… 于是我怒了,毅然决定把 mtxrun 换成无敌的 Bash。
\def\runvimsyntax#1
{\executesystemcommand
{bash -c "vim -u NONE -e -C -n -c \shellescapedquote set tabstop=\@@vstab \shellescapedquote\space -c \shellescapedquote syntax on\shellescapedquote\space -c \shellescapedquote set syntax=\@@vssyntax\shellescapedquote\space -c \shellescapedquote let contextstartline=\@@vsstart\shellescapedquote\space -c \shellescapedquote let contextstopline=\@@vsstop\shellescapedquote \space -c \shellescapedquote source /home/corsair/software/context/tex/texmf-context/tex/context/third/vim/2context.vim\shellescapedquote\space -c \shellescapedquote wqa\shellescapedquote\space \shellescapedquote#1\shellescapedquote\space "}}
宇宙终于又开始正常运行了。
正在 Dev-team 忙着整 3.1 jailbreak 的时候,惊闻某大牛已经搞出了 3.1 和 3.1.2 都能用的 jailbreak,Blackra1n。遂装,成功。然后第一件事就是装了个 MobileTerminal 和 OpenSSH,呵呵。不过 jailbreak 了以后还是不能运行自己写的代码,有两个问题:
- Xcode 只能编译在 simulator 运行的代码,编译 iPhone 上运行的代码还需要 sign。
- IPhone 还是需要检查 SHA1 hash。
第一个问题很好解决,编辑文件 /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.1.sdk/SDKSettings.plist,把 CODE_SIGNING_REQUIRED 下面的 YES 改成 NO,然后在 Xcode 里设置项目的 certificate identity 为不需要签名。第二个问题比较麻烦。Cydia 的网站里提到可以在 iPhone 里运行一条命令
sysctl -w security.mac.proc_enforce=0 \
security.mac.vnode_enforce=0
就搞定了。我这里执行以后的确可以运行没有签名的程序了,但是副作用是一旦重启 SpringBoard 就连不上 wifi。不过这个倒是不麻烦,把这两个值都恢复成原来的就行了。其实最好的解决办法是 self-signing。但是我用 codesign 老是出错… 嗯。不废话了,上 pp~~

Not exactly… There are some visible changes. I rewrote the theme of this blog using HTML 5 and CSS 3. Everything seems fine. But can someone please tell me why the following video does not work? (At least not in my Firefox 3.5.)
I tested this theme on Chrome under Windoze, and the video was normal. I don’t know what is wrong with my Firefox because it can play many other videos without problem.
订阅了 ConTeXt 的邮件列表,看的手痒的不行了,下了一个 ConTeXt minimal。这个东西安装极其的方便,这里有详细流程。唯一的不爽是安装以后是一个独立的 TeX 发行版,不能和现有的TeX tree 合并起来。我试过把安装好的目录拷到 ~/.texmf 里,然后设环境变量,但是 LuaTeX 老是说找不到 script,很郁闷…
现在的 ConTeXt 和一年前已经大不一样。对中英混排已经有了一定的支持。我从这里抄了一份测试文档,稍微改了一下,编译出来效果还是很不错的。

注意原文档编译出来是不行的,ConTeXt 不会在中文之间断行。必须要在文件里加入
\setscript[hanzi]
才行。另外 MKIV 的内存占用及其恐怖,编译这个文档用了 148M 的内存。
经常看 IBM developerWorks 里关于 Linux 和 UNIX 的文章,不过大部分都看不懂。我一直以为是因为我太搓了,对 Linux 还不够了解。但是今天看到这篇文章以后,我觉得作者们应该承担一部分责任。
对于 Screen 这个东西,我是比较了解的,也经常在 SSH 的远程 shell 里用,所以我完全没期望看这篇文章的时候会遇到任何困难。但是,我看到文章里的第二个图的时候就愣住了。当然后来我反应过来了,然后对这个图极端的无语。首先,一般的地球人在看这种图的时候大多会从上至下的看。于是先看到一个很诡异的 Window A。WTF is “Window A”?? 如果读者很乖的看了图上面的文字介绍的话,会知道 window A 是一个 shell,再往下看,这个 shell 和一个叫做 Screen session 的云“连着”。很好,再往下,Screen session 和 Remote login “连着”,然后 Remote login 通过 SSH 和 Local login “连着”(原来老子在最底下!)。所以这个图很简单,就是四个连成一条链的东西。鉴于地球人都知道 Remote login 和 Local login 是通过网络连接的,一般的逻辑会自然的推出 Screen session 是一片网络云,window A 在云的另一边的某台主机上,于是恍然大悟:screen 的作用就是通过 Remote login 来管理在更 remote 的主机上的 window(很乖的人前来补充:也就是 shell)。
看懂这个以后,下面的事就顺理成章了。图 3 这个垃圾图和上面的图一模一样,不知道什么意思。图 4 说明 Screen 还可以透过网络云连接多台主机!太强大了!图 5 说明连接多台主机以后可以把 remote login 断掉,而 screen session 和他的 window 们还连着!太和谐了!
…
如何改进?很简单,把图都删了!用文字说明。如果一个地方不需要图,就别随便画个小猫小狗来充数。如果硬要画小猫小狗的话,起码也应该把 screen session 画在 remote login 的里面吧??然后把 windows 画在 screen session 的里面。这才像话。
我的 blog 发布程序 Charisma 更新了。
- 可以在配置里设置多个 blog,在程序中选择使用
- Tag 支持
我平时的需求基本都满足了,下一步可能是加上删除 post 功能。
在试用 Charm 未遂的情况下,我决定写自己的 blog 发布程序。看了一下 XML-RPC 的资料,发现 Python 对 XML-RPC 的包装极好,深得我心,于是简单的把 WP 的 API 包装了一下,开始想界面怎么写。Charm 使用了风格比较古老的菜单界面,我不是很喜欢。写起来比较简单的非交互式命令行参数界面好像也不是很合适,想来想去决定写一个类似 Mutt 的界面。
我以前从来没有用过 ncurse。看了一点 Python 的 curse 模块文档以后我发现我丫就是一个 curse/terminal 白痴,但我发扬了我党“一不怕苦,二不怕死”的大无畏精神,找到了一个从文档上看很强大的库 Urwid,开始写界面,结果写的痛不欲生,生不如死,flag 和全局变量满天飞… 总算把发布功能写完了。
以下是我写之前对程序的预期:
- 实现 WP XML-RPC 的全部功能
- 类似 Mutt 的界面
- 从配置文件里读取全部键绑定
- 配置文件里实现多 blog 配置
以下是已经实现的功能:
- 实现列出 post 和发布新 post 功能
- 类似 Mutt 0.0.1 的界面(估计值)
- 硬编码全部键绑定
- 硬编码 API URI, 用户名和密码
… 最后套用 Mutt 作者的话:All blog publishing programs suck. This one just sucks the most!
Edit: 这是在 Charisma 里编辑的。
With effort, I finally put one of my Django applications online. The situation is that HostMonster does provide the Python intepreter, but seems we are not suppose to use Python as a web app language because the Python is version 2.3, and no framework module is pre-installed. So I first installed the Dejango package to ~/.python, and did some searching to find this. According to this document, I copied my Django app to /my-web-root/latrine in which “latrine” was the name of my app, and wrote /my-web-root/latrine/.htaccess as
AddHandler fastcgi-script .fcgi
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ latrine.fcgi/$1 [QSA,L]
And wrote a latrine.fcgi script:
#!/usr/bin/env python
# -*- mode: python; -*-
import sys, os
# Add a custom Python path.
sys.path.insert(0, "/my-web-root")
sys.path.insert(0, "/my-home/.python")
# Switch to the directory of your project. (Optional.)
# os.chdir("/my-web-root/latrine")
# Set the DJANGO_SETTINGS_MODULE environment variable.
os.environ['DJANGO_SETTINGS_MODULE'] = "latrine.settings"
from django.core.servers.fastcgi import runfastcgi
runfastcgi(method="threaded", daemonize="false")
And happily entered http://darksair.org/latrine/ in my browser, which displayed a very friendly 500 internal error. I was glad that I myself finally made a famous 500 error. After the excitement, I tried to locate the fault. I manually ran the fcgi script in a remote shell, and it was all right (Ok, except tons of Python trackbacks. But that was another thing.). So I decided that the problem was in .htaccess, which I sadly know nothing about… After some painful research I notied that the fastcgi module in HostMonster was actually fcgid-script instead of fastcgi-script. After fixing that in .htaccess, and did some simple Python debug, Latrine Live was online.