Doom 的呐喊

Crying in the Day of Doom

RPN Calculator for iPhone

从拿到 iPhone 的第一天起,我就在不断地寻找好用的 RPN 计算器。我的要求是

  1. 类似 Emacs Calc 的进栈出栈方式
  2. 无限大的堆栈
  3. 要牛逼

iPhone RPN Icon

我一直使用的都是一个 HP i41CX 模拟器。它基本符合第一条,但是不符合第二条:它的堆栈只有四层,而且最顶层还就是你正在输入的这个。不过它非常非常得符合第三条,看看这个计算器的像板砖一样的手册就知道了。这个计算器也有一些不便,它实在是太复杂了。比如他默认的键盘配置上没有切换弧度和角度的键。键绑定是可以设的,但是我一直没有搞明白怎么设…  同样因为这个原因,我一直不知道怎么算双曲三角函数。其他的 RPN 计算器要不就是操作方式诡异,要不就是功能太少。所以昨天我终于决定自己写一个计算器。

奋斗了两天以后把四则运算都搞定了… -_-  在 iPhone 上开发程序还是很方便的,和在 Mac 上差不多,熟练了以后写界面用不了太多的时间,而且 Interface Builder 做 prototyping 也非常得爽。我的时间主要都浪费在用 UITableView 显示一个堆栈上。UITableView 就是一个和菜单差不多的可选择的列表,几乎每一个 iPhone 程序里都能看到。但是这个东西必须要有一个符合某种特定协议的数据源…  我曾经一度都想自己用 label 和 UIScrollView 实现一个这种列表了…  不过最后搞定以后发现这个东西还是挺爽的,并且附赠动画效果~~

在 iPhone 上开发程序需要花 $99 买一个许可证。… … …… 噢,不对,说错了,是苹果声称你需要买一个,实际上你不需要。免费开发程序的代价就是开发出来的程序只能在 jailbreak 过的 iPhone 上运行。当然这其实没什么,因为各种迹象表明,没有 jailbreak 过的 iPhone 的使用价值其实就和一个板砖差不多。默认情况下,如果你没买这个许可证,Xcode 是不会让你把程序往 iPhone 上传的,只能在模拟器里运行。要想在 iPhone 里运行,

  1. 当然要先 jailbreak
  2. 照着 Compiling 一节
  3. Replacing codesign with ldid,这一节貌似没什么用,我从来没有成功的运行过 ldid,不过我还是做了。
  4. 给 iPhone 装 AppSync 补丁。很多 Cydia 源里都有,比如 hackulo.us 源。
  5. 编译时使用自己生成的那个许可证。

关于调试,在开始使用 Linux 之后,我就再也没有使用过任何调试器,只使用 printf(及各种语言里的等效的函数)。Objective-c 里是有 printf 的,但是比较方便的做法是使用 NSLog()。运行的时候在 Xcode 里选择 Run -> Console,可以看到输出。顺便提一下,Objective-c 的标准库还是很牛逼的,嗯,NSString, NSNumber, NSArray, …

Typescripts Rearranged

今天好好看了一下 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 + Optima Caslon + Myriad
Palatino Caslon

Code Hilighting in ConTeXt

今天需要排一个带 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 "}}

宇宙终于又开始正常运行了。

IPhone Jailbreak

正在 Dev-team 忙着整 3.1 jailbreak 的时候,惊闻某大牛已经搞出了 3.1 和 3.1.2 都能用的 jailbreak,Blackra1n。遂装,成功。然后第一件事就是装了个 MobileTerminal 和 OpenSSH,呵呵。不过 jailbreak 了以后还是不能运行自己写的代码,有两个问题:

  1. Xcode 只能编译在 simulator 运行的代码,编译 iPhone 上运行的代码还需要 sign。
  2. 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~~

IPhone Jailbreak

New Theme, with No Change

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 MKIV

订阅了 ConTeXt 的邮件列表,看的手痒的不行了,下了一个 ConTeXt minimal。这个东西安装极其的方便,这里有详细流程。唯一的不爽是安装以后是一个独立的 TeX 发行版,不能和现有的TeX tree 合并起来。我试过把安装好的目录拷到 ~/.texmf 里,然后设环境变量,但是 LuaTeX 老是说找不到 script,很郁闷…

现在的 ConTeXt 和一年前已经大不一样。对中英混排已经有了一定的支持。我从这里抄了一份测试文档,稍微改了一下,编译出来效果还是很不错的。

PDF Shot

注意原文档编译出来是不行的,ConTeXt 不会在中文之间断行。必须要在文件里加入

\setscript[hanzi]

才行。另外 MKIV 的内存占用及其恐怖,编译这个文档用了 148M 的内存。

关于 IBM developerWorks 里的文章

经常看 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 的里面。这才像话。

Charisma 更新

我的 blog 发布程序 Charisma 更新了。

  • 可以在配置里设置多个 blog,在程序中选择使用
  • Tag 支持

我平时的需求基本都满足了,下一步可能是加上删除 post 功能。

写了一个 WP 发布程序 aka. 我把自己侮辱了

在试用 Charm 未遂的情况下,我决定写自己的 blog 发布程序。看了一下 XML-RPC 的资料,发现 Python 对 XML-RPC 的包装极好,深得我心,于是简单的把 WP 的 API 包装了一下,开始想界面怎么写。Charm 使用了风格比较古老的菜单界面,我不是很喜欢。写起来比较简单的非交互式命令行参数界面好像也不是很合适,想来想去决定写一个类似 Mutt 的界面。

我以前从来没有用过 ncurse。看了一点 Python 的 curse 模块文档以后我发现我丫就是一个 curse/terminal 白痴,但我发扬了我党“一不怕苦,二不怕死”的大无畏精神,找到了一个从文档上看很强大的库 Urwid,开始写界面,结果写的痛不欲生,生不如死,flag 和全局变量满天飞… 总算把发布功能写完了。

以下是我写之前对程序的预期:

  1. 实现 WP XML-RPC 的全部功能
  2. 类似 Mutt 的界面
  3. 从配置文件里读取全部键绑定
  4. 配置文件里实现多 blog 配置

以下是已经实现的功能:

  1. 实现列出 post 和发布新 post 功能
  2. 类似 Mutt 0.0.1 的界面(估计值)
  3. 硬编码全部键绑定
  4. 硬编码 API URI, 用户名和密码

… 最后套用 Mutt 作者的话:All blog publishing programs suck. This one just sucks the most!

Edit: 这是在 Charisma 里编辑的。

Django in HostMonster

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.