-
人生のチェックインポイントを見つければ...
2011-08-15
...谈何容易...
即使能够重头再来,也必须接受我输给了自己这一绝对咽不下的事实
-
随便乱扯
2011-07-17
最近三个月在CEA Saclay Irfu/SAp做实习。中译疑为法国原子能委员会Saclay分部 宇宙基础研究所 天体物理研究室
(不过自上一年起CEA改名为Commissariat à l'énergie atomique et aux énergies alternatives的说)做一些跟数据处理相关的简单东西
在进门的右边就是我们工作的办公室,里面有包括我在内8个实习生,一个ENS Cachan、一个X以及一个Sup'Aero的三人是M2,faqueux若干。由于这样一件房间里全是实习生并不多见,由来自X的Tuc(昵称)提 议,每当房间里的固话响起,只要来电号码不是我们熟悉的人,都必须拿起电话用礼貌的语气说:
Bureau des Stagiaire, bonjour?
...
XXX(代入人名) n'est pas là, voulez-vous laisser un message?
又或者
Tous nos chargés de clientèle sont actuellement en ligne. Merci de patienter quelques instants
(该死的BNP Assurance)我们几个实习生做着不同的工作,不过氛围相当轻松,因为Vincent, Cyrile几个人超喜欢讲笑话,为此由Louis-Etienne负责评分,比如打个叉表示效果出众,画个正方形表示有笑点但说的不好,画个闪电表示 attaque aux stagiaires(人身攻击),画个太阳表示对人身攻击的救援,还有圆形、三角形,还有attaque au CEA……还能组合起来,比如正方形加闪电,或者超赞的笑话值三个叉之类……
有很烂的笑话,比如
Qu'est-ce-qui est (mignon) rouge et qui tape à la vitre?
Un bébé dans un micro-ondes.听到有人讲很烂或者很过分的笑话,我们会把手边的方糖用力扔过去,这是个不知道 怎么来的习惯。所用的方糖主要是中午在食堂吃晚饭后在咖啡区的篮子里拿的……又比如我们之中有个来自IPSA的女生Marine,于是就有人说了关于 sous-marine (sub->sous->under)的擦边球笑话,值一个叉加闪电,而且真应该扔方糖。还有个俄罗斯来的女生Tetiana沙利文,曾在众 人威逼之下(用法语)讲了个俄罗斯流传的笑话,由于重重文化隔阂我是真的没听懂,虽然那笑话也不好懂就是了。不过上班期间Tetiana也时常看其他网页 笑出来,别人问的时候就说是乌克兰语的笑话(有文字游戏性质),无法翻译。
大量的法语文字笑话(虽然不懂法语有的也能看懂),比如把 pizza 和séminaire合一起成为pizzéminaire,那就是每周一中午在我们bureau des stagiaires对面那间conference room里发生的事,边吃pizza边听seminar。不过有些笑话比如contrepèterie,就是把一句话里面几个音素交换位置,形成新的一句 另外一种意思,例如
A la vue des Nippons, la Chine se souleva
A la vue des nichons, la pine se souleva这不是完全的荤段子么……前一句是“看到日本人,中国奋起反抗”,后一句恕不翻译。
为了做出优秀的笑话,Alexandre甚至把Bescherelle(某法国权威语法书)带到办公室,因为有个“同音短语”的列表……嘛其实也不一定是这个原因,带语法书是用来检查实习报告里的语法错误的也说不定,虽然Alexandre还有一个多月才实习结束就是了。
平 时除了讲笑话,中午的饭后娱乐经常是看www.allocine.fr(算是电影相关的门户网站了)的 nanarland系列或者 faux raccord系列。前者是介绍几十年前的电影,虽然同时代的电影技术已经能出一些不错的电影了,但依旧有若干花大手笔下去拍出来的渣电影,比如错漏百出 的布景、吐槽无力的特效、剪切黏贴的音频效果、装B或ky的台词,当然少不了的还有主持人的吐槽。反正任何一部摆到现在都是给A、B站剪辑鬼畜视频的绝好 素材。而后者faux raccord介绍电影穿帮镜头就相对正常多了,不过主持人的分裂吐槽也是也是一绝。
只要和法国人有类似的知识范畴,交流和理解笑点也是很容易的事,特别是说到美国电影和电视剧,反正大家都知道Star Gate,知道Star Trek,知道Battlestar Galactica,知道Friends,知道Dr. House,知道Portal,还知道Chuck Norris:
Quand Chuck Norris parle, même le silence se tait!
-
我胡汉三又回来啦
2011-07-17
虽然是一直以来除了跳票、跳票和跳票,我什么都干不成,不过至少Pentadactyl心得文总算憋出来了。
博客模板换回三年前的那个,自己写的模板“repas de classe”,照片就是repas de classe,后期是自己用Paint .NET处理的。如果真能回到三年前,回到才华横溢的时候,那还真不错啊。
再不然,回到四年前在7blog使用的模板“下一站是 北落师门”,括号 自己写的,是何等的浪漫。
暂且就先这样吧。blogbus这里迟早得作为遗迹保存起来,wordpress那边已经开始了。话说如果不是注册的时候wordpress提醒我“这邮件地址已经被占用”,我还真不记得原来已经注册过了,我还说怎么我常用的用户名都被注册了来着。
それじゃ、Danke, merci de votre patience.
-
Pentadactyl小记及心得
2011-07-16
(本文写作用时一周 黑线)
不知道大家还记不记得firefox的一个超好用的插件——Vimperator呢?这个插件把具有vim风格的模态控制方式引入到firefox里,令用户只需要键盘就能控制firefox,在某种程度上还提高了效率。闲话休提,Vimperator后来有了个新的分支叫Pentadactyl,很多本来活跃在Vimperator项目的程序员都转到了Pentadactyl项目里继续贡献代码,主要是人和的问题,Vimperator原本的maintainer好几年没什么大贡献了,而他的管理又多少导致开发进度减缓,所以很多人就新开一个fork Pentadactyl了。
Pentadactyl大部分功能和操作方式都和Vimperator一样,不过也有人说Pentadactyl比Vimperator更加适合Firefox 4,而且也更快。要把已有的Vimperator配置转移到Pentadactyl上,只需用:mkp[entadactylrc]生成一个在%USERPROFILE%目录下的 _pentadactylrc(Windows下),或在$HOME目录下的 .pentadactyl(*nix下),然后选择性地把旧配置文件里的东西移过去就是了。需要注意的是guioptions, autocomplete, editor等等几个选项有微妙的变化。
首先要介绍的是Pentadactyl的global extend hint mode。旧的extend hint mode就是比如按下;s后,键入数字或者英文首字母匹配,Vimperator就会选中你所指的链接,执行save its destination动作,把链接目标保存到当前目录(请用:pwd命令查看,用:cd命令更改);而;a则会弹出“目标另存为”提示窗口。如果当前页有大量链接目标需要保存的话,就必须用这样的按键序列:;s1<CR>;s2<CR>;s3<CR>;s4<CR>...(<CR>表示回车)。而是用新的global extend hint mode的话,就只是:g;s1<CR>2<CR>3<CR>4<CR>...进入了这个模式后必须用Esc退出,否则Pentadactyl会一直等待你输入目标hint。顺带一提,在Pentadactyl下;a不是弹出“目标另存为”窗口,而是add a bookmark的功能。
这个功能曾经让中文世界使用者一度感到不友好,不过Vimperator开发途中已经有人写了用拼音首字母序列来匹配的插件。现在Pentadactyl化之后,你可以把这里的 pinyin-hints-mod.js 放到%USERPROFILE%\pentadactyl\plugins\下面:
https://github.com/dangoakachan/Script-Sets/blob/master/Javascript/Pentadactyl/pinyin-hints-mod.js
原版在这里
http://code.google.com/p/pinyin-hints-vimperator/
另外Vimperator的很多插件依旧能用,只不过load的时候会给出warning,比如后文提到的 walk-input.js 。大量的插件可以在这里找到:
https://github.com/vimpr/vimperator-plugins
另外,hint mode的数字匹配其实也不一定要用数字的,比如你设定 :set hintkeys=asdfg;lkjh 的话,在hint mode下链接旁的标签就不是1, 2, 3而是s, d, f了。默认hintkeys=0123456789
然后关于变量类型和options接受的值,我感觉Pentadactyl比Vimperator澄清了不少。首先是boolean,比如高亮搜索匹配hlfind项(相当于Vimperator的hls),允许的赋值有hlf/hlfind/nohlf/nohlfind四种,易见赋值等于参数名称本身表示True,加个no在前面就表示False。然后是常见的number和string两种类型,比如history项储存的是命令行保存曾键入的命令的行数,默认是记住500条命令。你可以键入:map然后按上箭头来回顾你曾键入的、以map开头的命令,像bash一样。其次还有charlist和stringlist两种类型,前者如guioptions项,赋值的每一个字母都代表一个要包含进去的东西,不过字母的顺序一般并不重要。后者则是用逗号分隔开的string,而string内部的逗号则要用转义符\,来表示,转义符\还会帮反斜杠、空格、半角单引号、半角双引号进行转义,即用\\表示一个反斜杠自身,用\␣空格表示空格,等等。不过还有另一种写法,就是显式地用单引号或双引号来表示每一项string,引用的部分以外就是正常的逗号了,只是单引号和双引号的作用是不同的。单引号表示literal interpretation,引住的部分无论是空格、反斜杠还是双引号都不会被表达成其他东西,而要是想表达一个单引号的话,则用两个单引号''表示。至于双引号,则表示所引住的部分需要进行转义,用\\表示反斜杠自身,用\"表示一个双引号,用\n表示换行符,\t是制表符,\uXXXX表示unicode码为XXXX(16位)的字符。同时可以用\, \' \空格 这些分别表示,'空格,只不过这些字符没有转义的必要,直接写就可以,比如\a\c\d就会被解读成acd(\b貌似会转义成backspace符)。跟不使用引号时的转义不同,使用双引号的话\n、\t会被转义,而不使用引号的话\n、\t只会被解读成n、t,后者只会进行最小限度的转义(包括逗号、反斜杠、空格和引号)。不过无论用哪一种方式,表示分隔string项的逗号前后不能有天然的空格,比如a, b或a ,b,而必须写成a,b或a,' b'或a," b"这样。
这些内容在Pentadactyl的本地帮助文件里有写:
dactyl://help/cmdline#cmdline-arguments
我们看一个例子:
set nextpattern='(下|后)一?(页|頁|篇|章|张)|次のページ|次へ','^\bnext\b','\bnext\b','\bsuivant\b','^(>|›)$','^(>>|»)$','^(>|»)','(>|»)$','\bmore\b'
这里用单引号来保持反斜杠不被转义掉,如果不用引号或者用双引号的话,\s就变成只剩下s了,然而\s是要作为一个整体给javascript的RegEx表达成“空白字符”的,不能在赋值阶段就搞没了。
再看
set editor='C:\\Progra~2\\Notepa~1\\notepad++.exe -multiInst -nosession'
同样是用单引号,两个反斜杠都会被原样保存到editor参数里(可以用:set editor? 查看)。这是因为Pentadactyl需要分开程序执行路径和运行时参数,这两者用空格分开,而文件路径中的空格则需要用\空格来表示,因此分开两者后Pentadactyl会对前者进行一次转义以获得正确的路径。所以其实不用8.3短路径名也是可以的,要写成
'C:\\Program\ Files\ (x86)\\Notepad++\\notepad++.exe -multiInst -nosession'
这里Program\ Files\ (x86)的反斜杠会保证Pentadactyl不在这个位置割开而当后面的部分是运行时参数。(BTW,在Windows命令行下用dir /x可以获得8.3短路径名。)而如果不用引号就要写成
C:\\\\Progra~2\\\\Notepa~1\\\\notepad++.exe\ -multiInst\ -nosession
顺带一提,:cd命令不需要这么臃肿,接受单个反斜杠表示目录路径,如:cd C:\Users\Username\Documents,而且可以用~表示%USERPROFILE%或$HOME。不过在Vimperator里曾经是使用斜杠(/)而不是反斜杠(\)的。
还有其他的类型,如regexplist和sitelist是跟stringlist类似的,不过对于不符合格式的取值会给出警告。事实上上面的nextpattern就是regexplist的例子。还有的类型叫stringmap, regexpmap和sitemap,就是形如key:val,foo:bar这样类似于python dictionary类型的东西,用于把每种匹配的情况对应一种处理方式。
虽然前面说了:cd命令可以直接接受单个反斜杠,而不会被转义,但一般在command-line mode下使用字符串(而不同于:set给参数赋值),都必须用引号(像普通程序语句一样),但貌似都会自动当做双引号(即强制转义)处理,和javascript默认一样。从而你键入:echo '\u9999'和:echo "\u9999"得到的都是“香”字。调用javascript的话:js var tmp='\u9999'+"\u9999"然后再:echo tmp或者:js alert(tmp)或者:js dactyl.echo(tmp)都会得到“香香”,两者都转义了。而如果是:set hf='\u9999'再用:set hf?查看的话,得到的是未转义的'\u9999'哟。测试完请用:set hf&调回默认值。这一招可以用来简易查询unicode码表。因而还可以用类似
:echo encodeURIComponent("www.domain.com/query.php?name=凉拌苦瓜的忧郁&type=light_novel")
或者decodeURIComponent()、encodeURI()、decodeURI()、escape()、unescape()来转换普通文本和百分号编码(注意函数名大小写敏感)。当然这里是三种相近但不同的编码方式,escape会把unicode字符值超过255的用%uXXXX来编码,而URI和URIComponent则是用%XX%YY%ZZ这样,另外URI不编码~!*()'@#$&=:/,;?+,而URIComponent仅仅不编码~!*()'。此外需要一提的是百度处理字符串默认使用的是GBK2312编码而不是UTF-8,所以每个中文字会变成%XX%YY两位,而不是这里介绍的几个函数转成的%XX%YY%ZZ。这也是为什么当网页地址含有百分号编码时,Firefox一般能在地址栏显示对应的Unicode字符(比如直接在地址栏显示中文),然而(譬如)在百度贴吧,Firefox地址栏显示的仍然是百分号编码。同样的,你可以在Firefox地址栏手动写 http://zh.wikipedia.org/zh-cn/ 后面打中文,这样也能正确进入维基页面,然而若是在地址栏写 http://tieba.baidu.com/f?kw= 后面打中文,你就等着看乱码吧。
再说说以前Vimperator貌似没有的text edit mode,方法是先进入某个文本框的insert mode,再按下<C-t>。咦?打开新分页了?如果你有这种疑惑,说明你和我一样把<C-t>按键在n,v,i,c,t全部模式下都映射到<Pass>了,毕竟在写字的时候突然想开新分页查东西的事也经常会有。我text edit mode用得少,所以要用的时候就<A-b><C-t>,这样<C-t>按键就传给Pentadactyl按照默认方式(即忽视用户的按键映射)处理了,跟把按键直接传给Firefox处理的Pass-through模式不同。text edit mode存在的目的是给用户一个类似于vim的文本编辑环境,可以用dw, u, y, p之类进行编辑,只不过真的很简陋,dw之后不能p回来,只能y(没有Y)了才能p(没有P),d$也受文本框限制只能删到该行结尾,而不是真正意义上的行尾。这么麻烦,还不如调用外部编辑器,也就是在insert mode或text edit mode下按<C-i>,则会调用editor参数定义的编辑器,比如上方我举过的例子就会调出notepad++(单独的session),编辑完内容后Ctrl+s保存一下关掉notepad++(仅仅那个单独的实例就够了),Pentadactyl就会根据你所编辑的临时文件的内容更新文本框。说到进入insert mode,一般做法都是鼠标点击文本框,又或者使用[count]gi进入前[count]个文本框。如果页面有多个文本框的话,一般就需要gi看看是不是想进入的那个,错了就<Esc>退出再试2gi,错了就<Esc>3gi……为了简化这些动作,你可以使用walk-input.js插件,这样就能在一个文本框内部通过<M-i>或<A-i>直接跳转到下一个文本框内部了。
除了新功能我也很想提一下以前一直没完全搞清楚的quick marks, local marks和url marks。三者的共同点是用一个按键+一个数字/字母来mark,然后用一两个按键+那个数字/字母来recall,而且三者都不会因为退出Firefox而丢失。quick marks很像普通bookmark,作用是mark住一个网页,然后用go在当前标签页打开或用gn在新标签页打开。url marks就强一些,是mark住一个网页的一个滚动位置,然后用'叫出来的时候,如果那页面已经打开则会转到那个标签页的指定位置,如果还没有该页面则于新标签页打开并滚动到指定位置。最后local marks只会在单个页面内的不同位置跳转,但不同页面里同一个记号指定的是不同的位置,比如在页面1按'a会到页面顶端,而在页面2按'a则可能会到底部。url mark和local mark都使用'来跳转,只不过'a-z的话是local mark,'A-Z的话是url mark。此外还有个特殊而且使用的local mark,按''的话会跳转到“上一个位置”,指Firefox上一个单方向页面滚动前的位置。url mark和local mark用的mark和recall的按键是m和',所以很自然会猜quick mark应该用M和"才对。事实上quick mark居然使用gn和go……所以我设置了:noremap \" gn
玩Pentadactyl,免不了会遇到“怎样设置自动把个别按键交由Firefox本身处理”的问题,比如在gmail网页总是会想使用gmail自己的jk移动。这个问题的答案只有三个人知道,一个是我,一个是鹿目圆(神),还有一个我不能说……说笑的啦……这个问题至少有四种解法。第一是用Vimperator沿袭下来的feedSomeKey.js脚本,下略。第二种是Pentadactyl的新功能,使用方式例如:
:set passkeys+=mail.google.com:jk/<CR>,gi,another.domain.com:hjkl,gt,gT
这是一个sitemap类型的参数,第一项用RegEx匹配的域名,冒号之后是charlist(即jk/<CR>),其中每个按键都会被pass掉,逗号之后是stringlist(即gi),里面每一项都会被pass掉。第三种做法是用autocmd在每次LocationChange事件发生是判断域名并修改mapping或直接进入Pass-through
:autocmd LocationChange '^https?://(www|mail)\.google\.com/' :normal! <C-z>
当此RegEx匹配到了域名时,就执行:normal! <C-z>,其作用是在command-line mode伪装出一个在normal mode下按<C-z>、而且忽视用户的mapping的按键event,跟:feedkeys! -mode n <C-z>效果一样。feedkey就是专门在command-line mode伪装按键event使用的,例如-js if (condition) dactyl.execute(":feedkey -mode v "+keystroke)这样。第四种方法是用group来进行更精细的调整,如:
group google -loc reader.google.com
map j <Pass>
map k <Pass>
map / <Pass>
这些按键映射就是变成唯独在reader.google.com才会使用的了。
其他有用的小技巧,我下面会从我的配置文件_pentadactylrc里选一些来讲。
为了易用性,我加了这些按键映射:
map -m n h gT
map -m n l -builtin <C-n>
map -m n w gT
map -m n e -builtin <C-n>
除了用h和l表示左右标签页跳转,也用了w和e,适合左手键盘右手鼠标的配置。同时映射到<C-n>上而不是gt,这样3e就表示往右三个标签页,而不是“第三个”标签页了。如果真需要跳转到第<n>个标签页的时候,就用<n>b吧。
此外我把<C-n>和<C-N>也都映射掉了,变成gb和gB的意思。这样一来buffer搜索用b引发,用<C-n>和<C-N>跳转下一个/上一个,这就跟页面内搜索用"/"引发而用n和N跳转非常类似,易于记忆了。
还有我在 wanpeng.xxpp.ca 看到一个很不错的技术性映射:
map t -js content.getSelection().toString()!=""?dactyl.execute(":tabopen "+ content.getSelection()):CommandExMode().open("tabopen ")
map o -js content.getSelection().toString()!=""?dactyl.execute(":open "+ content.getSelection()):CommandExMode().open("open ")
经过我的改良,现在我使用的是:
map t -js str=util.domToString(buffer.focusedFrame.getSelection()); str!=""?dactyl.open(str, {where: dactyl.NEW_TAB}):CommandExMode().open("tabopen ")
map o -js str=util.domToString(buffer.focusedFrame.getSelection()); str!=""?dactyl.open(str, {where: dactyl.CURRENT_TAB}):CommandExMode().open("open ")
这样的效果是如果选择了一段文字再按下t键或o键的话,直接在新标签页或当前标签页打开所选文字,实在非常方便。对于我这个javascript半小白来说,要改良原先的mapping来实现我想要的效果实在是一路辛酸,翻查Pentadactyl代码,寻找某些功能背后调用的函数。如果页面包含多个frame的话,原先的content.getSelection()只会get到空字符串,所以需要用buffer.focusedFrame.getSelection()。原先利用toString()方法会把换行符都变成空格,然后也便于在command-line mode用:tabopen打开。为了保持所选文字的完整信息,就需要使用Pentadactyl给的util.domToString()函数,同时:tabopen命令由于不能处理接收到的"\r\n"换行符,所以直接交由dactyl.open处理。其实我只是把Yank调用的buffer.currentWord和Paste调用的dactyl.open()拆开接在一起而已。话说domToString函数还真是有趣,如果用domToString(url, true)的方式调用的话,会把所选文字部分连带html tag一起给你,好像挺适合调试用的感觉。
类似地还可以引申出其他的用法如:
map <leader>v -js str=util.domToString(buffer.focusedFrame.getSelection()).toLowerCase(); str.substr(0,2)=="av"?dactyl.execute(":tabopen www.bilibili.tv/video/"+str):str.substr(0,2)=="ac"?dactyl.execute(":tabopen www.acfun.tv/v/"+str):str.substr(0,2)=="sm"?dactyl.execute(":tabopen www.nicovideo.jp/watch/"+str):str.substr(0,6)=="mylist"?dactyl.execute(":tabopen www.bilibili.tv/"+str):dactyl.execute(":tabopen www.bilibili.tv/video/av"+str)
其中<leader>键默认为反斜杠(\),于是乎按下\v的时候,调用javascript,首先把选定文字保存在str里,,然后判断如果前两位是av的话打开对应bilibili视频页,前两位是ac的话打开acfun页,前两位是sm的话打开nicovideo页,mylist的话则默认为bilibili收藏列表,最后如果都不是,自动当成bilibili视频id号。
另外说说发现的一个细节:如果把一些按键映射到-js上,javascript里用的变量都是局部变量;然而映射到:js上的话,就可以在那段javascript执行结束后仍能调用那些变量。例如:
map <leader>] -js var temp='a'
map <leader>[ :js var temp='b'<CR>
如果你按\]然后:echo temp的话只会得到undefined,但是按\[然后:echo temp的话就可以看到b了。
浏览网页时,有时会遇到没有形成超链接的url文字,明明是url却只是普通文本。对我来说,只需用caret mode或者鼠标把光标焦点放在那一行行,然后按O键,剩下的就交给map了:
map O i0v$yv<Esc>P
解释一下:首先i进入caret mode,然后到行首,v进入visual mode(反白文字),然后跳到行尾,再把内容yank出来,v返回caret mode,<Esc>返回normal mode,最后把yank到的东西P到新标签页。
于是O键映射对于处理那些单独一行的链接文字还算有效,不过如果好几行都是没有超链接的url,一般想法是都反白选择了,再按YP、或者照前文说按t键(重新映射过的版本)。只不过Pentadactyl默认使用竖线|分隔需要各自打开新标签页的url,比如:tabopen ikebukuro-dollars.com | www.nr.com | www.arxiv.org才会分开三个标签页打开,用换行符分隔开的url(比如选定多行文字,Y然后P的时候)还是会黏在一起当成一个网页的url。这时候就需要自定义urlseparator参数了:
set urlseparator='( {10,}\S|\n+(?!$)(?!\s)|(\s\S*|^\S+)http://)'
↑这是我写这篇文章刚开始时的设定,现在我用这个↓
set urlseparator='\s((?!http://)[\s\S])*http://|(((?!http://)\S)*[^u\s]rce:|((?!http://)\S)*[^r\s]ce:|((?!http://)\S)*[^c\s]e:|((?!http://)\S)*[^e\s]:|((?!http://)\S)*[^:\s])http://|\s{5,}((?!http://)\S)+((?!http://)[\s\S])*$|(\s((?!http://)\S)+((?!http://)[\s\S])*\n|\n((?!http://)[\s\S])*((?!http://)\S)+)((?!http://)[\s\S])*$'
看懂了下面这个恐怕上面的就没问题了。首先要知道这是正则表达式,而我用竖线|分隔开了四种情况:
第一种 \s((?!http://)[\s\S])*http:// 匹配的是从一个空白字符开始,后面接不是"http://"的若干任意字符,直到碰到http://为止,其中(?!http://)就是RegEx的look ahead语法,匹配前方不是http://的情况。Pentadactyl在找到匹配的urlseparator之后,会把匹配部分扔掉,该部分前面的字符作为url打开,后面的字符继续进行匹配。因而要不得把http://匹配出来截掉,留下后面网址部分打开,要不用look-ahead (?=http://)不匹配后面http://的部分,整个留下来,这样可以拓展成 (?=(https?|ftp)://)的用法。
第二种情况 (((?!http://)\S)*[^u\s]rce:|((?!http://)\S)*[^r\s]ce:|((?!http://)\S)*[^c\s]e:|((?!http://)\S)*[^e\s]:|((?!http://)\S)*[^:\s])http:// 匹配的是一系列连续的非空白字符(而且不包含http://,方法同上)直到碰到http://为止,除了urce:http://这种情况外。如果不是要顾及view-source:http://... 这样的情况,写成 ((?!http://)\S)*http:// 就够了。即使要顾及view-source,本来用look-behind (?<!view-source:)就能排除http://前面是view-source:的情况,只是这天杀的javascript RegEx只支持look-ahead不支持look-behind……于是只好手动改写成这样(这样写应该会条理清楚点):
(((?!http://)\S)*[^u\s]rce:
|((?!http://)\S)*[^r\s]ce:
|((?!http://)\S)*[^c\s]e:
|((?!http://)\S)*[^e\s]:
|((?!http://)\S)*[^:\s]
)http://
匹配http://前面不是冒号,或者是冒号但冒号前面不是e,或者是e:但前面不是c,或者是ce:但前面不是r,或者是rce:但前面不是u。以urce结尾的单词只有source和ressource,误杀率很低,不过还是有可能会误中某些用户id,譬如在以下情景(C洽),用户id叫SonicBurce什么的话就中招了:
推 chshsnail:http://i.imgur.com/N5ROl.jpg 笨蛋大小姐+大少爺 07/14 01:26
第三种情况 \s{5,}((?!http://)\S)+((?!http://)[\s\S])*$ 匹配的是以至少五个空白字符打头、任意字符(除http://外)直到字符串结尾,而且至少包含一个非空字符。这样可以把跟在链接文字后面多余的东西去掉,适用情景如(C洽)(打开此链接后果自负):
→ yankeefat:那樓上這給你http://ppt.cc/Lh~~ 07/16 17:11
对于这种短网址服务或者inspic之类图片站,打开后面有东西的网址“http://ppt.cc/Lh~~ 07/16 17:11”是会报错的。不过这RegEx有个副作用就是把多余的部分匹配出来扔掉以后,Pentadactyl会继续把后面剩下的部分(空字符串)当成url打开,结果就是打开%USERPROFILE%或$HOME页面。因而为了减小副作用,就要求匹配部分必须含有非空字符,否则连trailing spaces都会引发urlseparator。至于开头要求的五个空白字符,是为了避免连
:tabopen 僕と契約して 魔法少女になってよ
的时候,把后面“魔法少女になってよ”也当成垃圾匹配然后扔掉了。
最后第四种情况 (\s((?!http://)\S)+((?!http://)[\s\S])*\n|\n((?!http://)[\s\S])*((?!http://)\S)+)((?!http://)[\s\S])*$ 匹配的也是链接文字后面多余的东西,不过不要求五个空白字符打头,只需要一个空白字符打头,而后面包含换行符"\n"和非空字符那就足够了。包含换行符的话总不可能是在:tabopen 打开的嘛。于是匹配方式是先找空白字符\s再找非空字符\S+然后任意字符之后有换行符\n,或者是换行符\n打头然后任意字符再有非空字符\S+,两者“或”一下之后接任意字符直到字符串结尾。
这么一来,urlseparator就不仅仅是分开url的东西了,而成为了优化上网体验、增加Firefox自动化的一个工具。遇到类似于 http://www.ptt.cc/bbs/C_Chat/M.1310794620.A.FBD.html 的网页内容,只需用鼠标把第一个http到最后jpg选中,然后按t键,urlseparator就开始工作,帮你自动把四个url地址分开,在四个标签页中打开,并忽略其余文字内容。
继续增加Firefox自动化,我还按照自己的习惯做了个autocommand:
autocmd DownloadPost .* -js patt=/^C:\\Users\\Username\\Documents\\.+(mp3|wma)$/i; if (patt.test(file)) { result=io.system("move /-Y "+file+" c:\\users\\Username\\music\\"+file.substr(24)); if (result.returnValue != 0) dactyl.echo("error while moving "+file) }
大家拿去用的时候记得换成自己常用的下载目录、以及放置音乐的目录,另外把24修改成下载目录的字符串长度。无论我从什么网站(正则.*)下载了文件,只要Pentadactyl发现是放在了我临时下载目录而且是mp3/wma文件,那么就调用系统命令(move是Windows的例子,*nix系统请自行改成mv)把文件移到适合的地方。这个只是例子,具体怎么用autocmd DownloadPost配合extend hint mode的;s快速下载并分类文件,还有很大发展空间。另外一提,只有当焦点还在Firefox的时候,autocmd才会起效,如果在下载完成的时候,你仍然在其他窗口如记事本那里,那么autocmd不会有任何效果。
不像新版本的Vimperator,Pentadactyl还是需要手动把几个常用快捷键pass掉,如:map -m n,v,i,c <C-c> <Pass>。不过提醒一下,其实黏贴除了用<C-v>,一直以来还有<S-Insert>这个选择的说。
在command-line mode打开网页的小技巧映射:
cnoremap <S-Return> <End>.org<Home><C-Right>www.<CR>
cnoremap <C-Return> <End>.com<Home><C-Right>www.<CR>
在command-line mode有几个小巧的命令:
:y[ank] 后面跟其他命令,可以把命令运行结果直接yank进去。
:tab 后面跟其他命令,会在新标签页执行。适用情景如:tab h passkeys
有时需要测试几个Pentadactyl的命令,是直接在万能冒号后测试,有时则需要看已有的配置文件整体会不会出问题,这时候最好就用:so[urce] path\to\_pentadactylrc 来重载配置了。为了方便调试,我还做了映射:
map <leader>s :source ~\\_pentadactylrc<CR>
而如果需要更彻底的测试,可以使用:reh[ash],适用于往%USERPROFILE%\pentadactyl\plugins\内加入了新的插件,又或者手动改写了Pentadactyl的javascript代码的情况,比方说打补丁。情景:有个命令:sanitize可以清除指定时间范围内的指定对象(如下载历史、浏览历史、cookies等),用法如:sanitize cookies -timespan=30m。不过你亲手试试的话可能会有range not defined错误(http://code.google.com/p/dactyl/issues/detail?id=428),是由于sanitizer.jsm里的一行代码导致的(http://code.google.com/p/dactyl/source/detail?r=48f6adfae8)。所以只需到你的firefox profile的文件夹内找到extensions\pentadactyl@dactyl.googlecode.com.xpi。这文件其实是个zip压缩包,解压开来找或者用Total Commander直接进入,找common\modules\sanitizer.jsm文件。文件复制出来修正,然后覆盖回去,再在firefox里用:rehash,就能看到效果了。顺带一提,sanitize这命令看起来超实用的说,
:sa[nitize] -h=host -o[lder] -t[imespan]=10m/h/d/w/session downloads/history/cache/host/...
可以用来消除若干分钟/小时/天/星期内(又或者当前浏览进程)的、所有属于某个host的下载历史/浏览历史/缓存/保存密码/表单/cookies等等,又或者-h=host all也是可以的,或者不指定host,而是若干分钟内的所有浏览历史之类,进而使用-older的话就是指定时间以前的相关项目被清理掉。
另外必须要提Pentadactyl和google有个地方有bug,估计跟Vimperator内部处理mode转换和<Esc>键的方式有关。比如我们这样映射
map -m n,v,i,c,t <S-Esc> -builtin j
在大部分网页都能正常工作,按下Shift+Esc相当于按j键。不过在www.google.com/search?q=...这样的页面里,嗯也能正常工作,<S-Esc>映射成了j。只不过你用万能冒号:或者t或者o或者a之类进入command-line mode的话,会发现“咦?怎么它自动打了三个j?”。这时你用<Tab>键进行自动补完的话,会发现它又自动按了一下j。而用<Esc>退回到normal mode的话,也会发现“咦?怎么页面突然下滚了一行,就像是按了一下j?”
这奇怪的bug貌似只在www.google.com的domain而且url后面还有文字的时候出现,在www.google.com本身是没问题的,还有什么mail.google.com, docs.google.com也都没问题。另外这bug还超霸道,即使你把这个映射pass掉:
set passkeys+=www.google.com:<S-Esc>
这样经测试,无论在www.google.com还是www.google.com/search?q=...的normal mode下,按键<S-Esc>已经被忽略了,只不过bug依然存在,进入command-line mode的时候会自动出来三个j,回到normal mode的时候也会无视passkeys传一个j键event给firefox。
vimperator的2011-04-21更新提到过<S-Esc>的问题:
http://vimperator-labs.googlecode.com/hg/vimperator/NEWS
最后,我的_pentadactylrc文件(适用Win7):
我记不记得去更新那是另一回事了
本来还想拿一段说说用Pentadactyl配合javascript的方式调戏Firefox以及一众后宫(Firefox插件)的,因为只要知道了获取Object的方法和需要调用的函数的名称,Firefox的本质就很容易被看清。嘛还是以后再说吧。
后记:写完这篇之后,我真想有个软件能把.tex编译成blog风格的html然后跟菊子曰无缝接合自动发布……暂时只好全篇改成courrier new字体,跟我在notepad++设置一样,看着还算顺眼
-
I'll be back
2010-11-04
最终还是决定,失踪这么久之后,要重开这个blog了。その前に、quelques choses がある。Erstens, 五月から、j'ai recommencé BOINC计算 avec der neu Computer (portable). 怎么说也要先dépasser fwjmath…… Ich bin das zweihundertunddritte (203.) dans le team China. Er ist das einhundertdreiundneunzehnte (193.). だから……Merci de m'attendre encore quelques semaines, たぶん……
以上!







