乍听之下,不无道理;仔细揣摩,胡说八道

0%

“实战Elisp”系列旨在讲述我使用Elisp定制Emacs的经验,抛砖引玉,还请广大Emacs同好不吝赐教——如果真的有广大Emacs用户的话,哈哈哈。

序言

我用Emacs的org-mode来管理看动画的进度

org-mode中的动画清单

每个工作日的午餐和晚餐,我都会安排一部下饭动画。为了每顿饭可以看不同的动画,我的做法是:

阅读全文 »

本文是《实战Common Lisp》系列的第一篇文章。本系列主要讲述在使用Common Lisp时能派上用场的小函数,希望能为Common Lisp的复兴做一些微小的贡献。

序言

众所周知,Common Lisp没有内置多少处理字符串的函数,下面的代码便能看到所有以STRING开头的函数名:

1
2
3
4
(do-external-symbols (s :cl)
(when (and (fboundp s)
(equal (search "STRING" (symbol-name s)) 0))
(print s)))

屈指可数,而且大部分是比较两个字符串的!很多其它语言中的“标配”是不存在的,比如想要将多个字符串连接起来这么简单的功能都没有!要么自己实现,要么依赖第三方库,比如cl-str提供的join函数。

标准库也没有内置正则表达式,好在有一个优秀的第三方库可以用:cl-ppcre。一种使用正则的常见需求是提取符合某种模式的内容,比如提取一篇Markdown文章中所有的图片链接。图片链接可以由下列正则括号的部分匹配:

1
"!\\[.*\\]\\((.*)\\)"

在cl-ppcre中这个括号匹配的部分叫做第一个register。我想要写一个能够提取出字符串中所有符合这段正则的第一个register,分两步走:

  1. 先实现一个all-first-registers-to-strings函数,实现通用的、提取一个字符串中所有符合某段正则的子串的第一个register的内容;
  2. 基于all-first-registers-to-strings实现一个extract-image-paths
阅读全文 »

“实战Elisp”系列旨在讲述我使用Elisp定制Emacs的经验,抛砖引玉,还请广大Emacs同好不吝赐教——如果真的有广大Emacs用户的话,哈哈哈。

序言

上一篇文章的末尾,我说有一个更优雅的办法实现快速设置任务的开始时间,本文便来揭秘这个办法。

阅读全文 »

本文是“实战Elisp”系列的第一篇。本系列旨在讲述我使用Elisp定制Emacs的经验,抛砖引玉,还请广大Emacs同好不吝赐教——如果真的有广大Emacs用户的话,哈哈哈。

序言

用Emacs的org-mode安排业余时间颇有些时日,渐渐地开始编写一些Elisp函数来改善自己的使用体验。

日程管理中一个常见的需求,便是给任务设定一个开始时间。在org-mode中,这可以调用函数org-schedule实现:将光标移动到一个任务上,再按下C-c C-s,会出现一个日历界面,帮助选择日期和时间来作为日程的开始时间。具体效果如下图所示

阅读全文 »

序言

9102年都已经过去好几天了,现在才来产出年终总结。

个人项目

cuckoo——定时提醒工具

18年的总结中,我提到自己开发了一个名为cuckoo的工具,用来代替macOS的提醒事项、日历,以及由crontab调用的shell脚本。这个目标在19年得以实现,cuckoo已经完全取代了它们。

cuckoo实现了以下功能:

  1. 创建一次性和周期性的提醒。cuckoo甚至可以在正确的二月最后一天弹出提醒——不管是平年还是闰年;
  2. 利用alertercuckoo可以在提醒弹出后推迟它(5分钟、10分钟),或推迟到指定的时刻;
  3. 利用Server酱cuckoo可以把提醒以微信消息推给手机;
  4. 利用ControlPlane,实现按场景提醒——比如10点钟若在公司就提醒自己开晨会,若在家则绝不弹出。

我还提供了给Emacs用的minor mode和Alfred Workflow,以提高易用性:

  1. 在Emacs的org-mode中启用这个minor mode后,只需要按下C-c r便可为光标所在的条目创建提醒;
  2. 一个条目切换至DONECANCELLED状态时,也会自动更改cuckoo中任务的状态(感兴趣的读者可以移步之前的文章);
  3. Alfred Workflow便于创建一次性提醒——比如提醒自己在25分钟后打开支付宝的蚂蚁庄园看看有没有鸡贼。

wa——Alfred Workflow脚本

在18年入手MBP后不久,我便入手了Alfred,并购买了Powerpack。平均每天使用Alfred 110次,大多是Snippets(auto expansion真香)、Clipboard(临时存储文字和图片的绝佳位置)、Workflow。常用的Workflow都是我自己开发的:

  1. unit用于快速输入不同时间长度的秒数的,例如输入6天的秒数6 * 24 * 60 * 60 * 1000
  2. upload用于上传图片到GitHub,把GitHub当图床用(感兴趣的读者可以移步这篇文章);
  3. gt用于获取指定日期的UNIX时间戳、int用于获取一些预设的时间戳(例如“昨天0点”);
  4. yl用于精确设定macOS的音量;
  5. bqb用于斗图(感兴趣的读者可以移步这里)。

这些脚本都收集在名为wa的私有仓库中。由于需求比较稳定,这个仓库的迭代不多。

jjcc——将LISP语言编译为x64汇编

不害臊地说,jjcc是一个用Common Lisp写就的编译器,运行在SLIME中,如果投喂它某种LISP方言代码,就可以编译出跑在macOS上的x64汇编代码。这是我的第一款生成汇编指令的编译器,为此还恶补了不少汇编语言知识,尤其是x64的calling convention。这款编译器的开发过程写成了文章发表在博客和知乎上,感兴趣的读者可以移步这个专栏

在完成了蹩脚的自定义函数特性后,我读了《An Incremental Approach to Compiler Construction》这篇论文,它循序渐进地开发一个Scheme语言到x86汇编的编译器,并且阶段划分得更好,后来我也按照论文的思路重新实现了一遍。

savemoney——未完待续的RescueTime代替品

19年10月份时RescueTime Premium到期,由于太鸡肋了便不再续费。我仍然有time-tracking的需求,于是打算自己动手写一个代替品。皇天不负有心人,我找到了active-win这个库,它可以获取当前有焦点的窗口的元信息。基于这个库我写了两个脚本:

  1. savemoney.js,每隔一秒调用active-win获取当前激活窗口的元信息,然后写入到Redis中;
  2. accounting.js,不停地从Redis中取出数据,运算后写入到MySQL中。

目前仅仅是将数据记录在了MySQL中,没有做报表和统计。这两个脚本通过Launchd在每次登录后自动运行。

写作

19年在GitHub博客一共发表了28篇博文,数量差强人意,质量亟待提高。在读了利用金字塔原理写出好文章后,我逐渐改进自己的写作方法,以期写得更有条理。

除了GitHub博客和SegmentFault,我还在知乎上发表了一些文章,大多是关于jjcc编译器的。刚才我说文章的质量亟待提高,如果你看过jjcc编译器系列的文章的话,一定会很同意我的观点。

博客和SegmentFault的受众很小,于是我又开通了微信订阅号,希望可以在技术圈子里更多的展示自己——有没有值得展示的内容另说。在订阅号上发表文章多了一种无形的压力,毕竟这些内容更容易被同学、同事、同行看到(前提是人家乐意看)。万一写的很糟糕,可就糗大了。目前订阅号关注者寥寥,有兴趣的可以微信搜索“小打小闹写点bug”关注。

学习、进修

19年读完的书不多:

  1. 《MongoDB in Action》,没什么太大的收获;
  2. 《High Performance MySQL》,看过后确实有些帮助,切实根据书中的指导调优过生产环境的MySQL;
  3. 《Algorithms》,光看没练手;
  4. 《Linux Shell Scripting Cookbook》,看着看着幡然醒悟这东西只要用到的时候查阅就足够了,遂弃之。

还有许多在读经典书籍,如《Clean Architecture》、《重构》。刚开始我会在上下班搭地铁时读这些书,后来将看书时间固定在了每天下午一点至一点半。这些在读的书像一条队列,我每天会读队头的书,然后放到队尾。这样一来,每天都在涉猎不同领域的内容。

在18年9月,我闭门造车地整理了一份Web后端软件工程师的技能树,再据此来寻找要读的书。例如,上述的《MongoDB in Action》是依据“后端知识/文档数据库/MongoDB”找的,《Linux Shell Scripting Cookbook》是依据“后端知识/命令行操作”找的。技能树整理得好不好暂且按下不表,但渐渐地我忘记了看书的初衷,成了“为看而看”。看似每天中午都在学习,实际上由于目的性不强,收获不大。由于每天读不同类型的书,同一个主题的学习过程也变得支离破碎。这个学习方法已经到了迫切需要优化的地步。

macOS更新换代——AppleScript来袭、Chrome上位

19年10月升级到macOS Catalina,然后问题便接踵而至。首当其冲的是alerterterminal-notifier没法用了,无法在右上角弹出提醒。一番折腾后不见起色,只好先用AppleScript代替,让cuckoo可以弹出提醒。AppleScript的display notification功能远不及alerter那么丰富,聊胜于无吧。

Firefox也开始闹别扭。只要打开Firefox稍微用两下,就会有一个名为FirefoxWebCP Extension的进程疯狂地使用CPU,Firefox内的各标签页也纷纷失灵转圈,几天下来都是如此。没办法,只好起用Chrome。稍微磨合后发现Chrome其实挺不错,各方面都今非昔比。以前之所以一直坚守在Firefox的阵营,主要是因为:

  1. Firefox的Pocket插件更好用——早年间不需要打开Pocket的网站即可查看自己的列表,不过自从Firefox集成Pocket后,这个优势已经荡然无存;
  2. Firefox的Vimperator更好用——这也一样,Vimperator逝者已逝,继承者Vim vixen和Chrome的Vimium大同小异;
  3. Firefox的地址栏搜索浏览历史更好用,这一点迄今未被Chrome超越——Chrome的地址栏要么搜不到,要么必须输入更多关键词,然后还是搜不到。

希望Mozilla在2020年可以修复这个问题,让我重回Firefox的怀抱。

CL虐我千万遍,我待CL如初见

2019年的Common Lisp依然让人哀其不幸怒其不争,我也依然痴迷于这门古怪的语言。但痴迷不能当饭吃,要将CL投入到实际应用实在太难。且不说Quicklisp上库的数量远不及PyPI和NPM,质量也令人抓狂。这不,都9102年了,访问一个返回JSON数据的HTTP接口,还得先用drakma发出请求(也许不支持HTTP/2),再用flexi-streams将字节数组转换为UTF-8编码的字符串,再用cl-json解析一番。拿到一个列表对象后,再用carcdrassoc一顿操作猛如虎,才能拿到需要的数据。

2020年,MAKE CL GREAT AGAIN!

记账

在年中的时候,萌生了换记账软件的想法,因为挖财用起来越来越不爽了,而且整天记流水账也没什么收获。一番摸索后,我决定尝试一下复式记账法,并选择了GNU Cash——早年间用过一次,但没看入门手册就开始用,根本玩不转。这一次倒是读了手册,但GNU Cash的UI和操作方式还是无法让我心动;之后知道了beancount,却无法在我的系统中顺利运行;最终我选择了ledger,它是一个命令行程序,不负责记录,只负责读取手打显诚意的交易明细,然后产出报表。Emacs有一个ledger-mode插件,两者配合用来记账超痛快。

结尾

在2020年我希望至少能完成:

  1. 发布cuckoo
  2. 发布wa
  3. 开发一个alerter的代替品;
  4. 写更多的博文,让微信订阅号的粉丝涨到130;
  5. 给CL写一些库解决一些常见的需求

最后