【利器系列】01-Dash-开发人员的随身好字典

前文

Dash 是我开始工作有了收入之后,购买的第一款跟开发相关的软件,从 2011 年开始,「这本好字典」就一直在我手边,每每遇到不认识的「字」,打开 Dash 便是我下意识的动作。今天,我们就来聊聊 Dash 这本「好字典」。

我是 2009 年 7 月来到北京,加入超图软件开始了为期不到一年的 SuperMap Objects for Java 的 SDK 开发后,于 2010 年 5 月加入了喜讯无限,开始了自己为期 10 年之久的创业之路。从喜讯无限最初的 Android App 开发到如今的 Flutter App 开发,中间还有为期近 7 年的移动游戏开发经历,期间做过大量的 Unity3D 和少量的 Cocos2dx 开发工作。

在 2011 年,我们当时创业的团队喜讯无限从第二个民房办公地(天居园媒体村)搬到了第三个正经办公地(一路之隔安全大厦)。当时我们那个年轻可爱的创业团队中的几个开发同学大多都是同年毕业的伙伴,其中一位同学,我们总是称他为「正经梁」,他是一位非常非常全栈的折腾党,从硬件到软件,从前端到后端,从数据库到运维,基本上只要他感兴趣的领域,他都非常愿意投入巨大的热情和精力去折腾,验证自己所见所闻并形成自己的一套方法和实践,实属同辈中的佼佼者。

与此同时的我们其他几位伙伴,恰好也都是有好奇心的家伙,只是大家感兴趣的领域可能稍有不同,大家也乐于相互分享。例如「张Tree」同学就非常热衷于体验当时互联网和移动互联网的各种新奇的服务和 App(当时 App 还少得可怜,他们还在用着诺基亚的 E71 呢),在体验之后精选出来他认为不错的服务和 App 分享给我们,对于某些做得有所欠缺或者体验欠佳的友商们,偶尔还会 diss 或心疼一番,「孔雀67」同学就非常痴迷于游戏开发底层框架技术的钻研和图形学,对算法实现有一定的造诣,时不时地给我们丢一两篇很好的文章好某个实现得很优雅的开源框架或引擎的仓库地址。

在那样的环境下,我们一共是 4 位年轻的开发伙伴,「正经梁」负责后端,当时的我们后端使用 PHP 开发(没错,当年的 Facebook 主站核心开发也是基于 PHP 的),他就是那个戏称自己每天站在鄙视链顶端用着「世界上最好的编程语言」跟我们在一起玩。「张Tree」「孔雀67」和「我」,我们三个都是前端程序员,「张Tree」和「孔雀67」由于 C/C++ 的基础不错,还在我们创业之初做过一段时间的塞班(Symbian)应用开发,后面也都转到了 Android 和 iOS 应用开发了,「我」因为从一开始在 Java 编程上有些基础,所以我从 2010 年一开始就在做 Android 开发。

当时的我们四个人,开发环境都大不相同:

「正经梁」=> 自己折腾安装的黑苹果 + VIM

「张Tree」 + 「孔雀67」=> Windows + Visual Studio

「我」=> Ubuntu + Eclipse(ADT)

在我们搬到安全大厦后,趁着大家都在重新布置自己的工位和电脑,「正经梁」同学说要升级一下他的黑苹果到最新的系统,我们还一顿 diss 他,说他穷逼买不起白苹果。然后他笑称「黑苹果一样非常的稳定,没事别瞎搞,GPU 和 CPU 的能力显然性价比更高」,然后建议说我们也可以尝试一下。我随口开了一个玩笑,「你要是帮我装上,我就用,而且能不能双系统?」没想到「正经梁」一口答应了,说「刚好拿我的机器来测试一下最新黑苹果的兼容性,反正你还有 Ubuntu 作为备份」。就这样,我开始使用「黑苹果」,隐约记得当时使用的系统应该是「Mac OS X 10.6 Snow Leopard」,当时做 Android 开发的我主要使用 Eclipse + ADT,在「黑苹果」上除了快捷键需要重新适应一下,其他基本上没有明显的区别。

在开始使用 Mac OS X 之后,慢慢地除了开发之外也有一些其他的需求,很多的时候都会向我的「黑苹果」体验前辈「正经梁」请教一二,而作为一个满怀好奇心和浑身折腾欲的二逼青年「正经梁」总是能给出非常令人满意的答案。Dash 和 1Password 就是在那个时候由「正经梁」墙裂推荐给我的(那会儿我们还不咋使用安利和种草这样的词)。

Dash 和 1Password 这两款软件不愧是「正经梁」的镇机之宝,自打我开始安装这两个软件到的我的电脑上之后,就再也没有离开我的手边。这两款软件,我的首次安装确实都是从「正经梁」同学处拷贝的破解版,都在我使用不到半年之后,主动购买了正版授权,并且在往后的 10 年时间里,每每跟着版本升级再次付费或订阅。

前面叨叨叨地说了这么多,只是想交代一下我是如何接触和开始使用 Dash 的背景,虽然跟本文核心的内容没有那么大的关系,可是跟我自己有很大的关系,在此回忆和说明一下,也还是蛮高兴的。不是老说人会受原生家庭的影响吗?我这也是受到我们这个小小的原生团队的影响才接触到并开始使用 Dash 的。后面咱们还会聊到很多这种「大家毕业后第一份重要的工作会影响我们整个职业生涯」类似的话题,这就算是一个不是那么明显的稍显微妙的案例。


接下来,正文开始。

Dash 能干嘛?

引用一下 Dash 官网的描述

Dash is an API Documentation Browser and Code Snippet Manager. Dash instantly searches offline documentation sets for 200+ APIs, 100+ cheat sheets and more. You can even generate your own docsets or request docsets to be included.

我们简单翻译一下

Dash 是一个 API 文档浏览器和代码片段管理器。 Dash 可以快速搜索包含 200 多个公开的 API 和 100 多个速查表的离线文档集等。你也可以创建自己的文档集或申请官方新增对某些文档集的支持。

从这个描述上来看,这就是一个本地快查开发参考文档的工具,将大量公开的编程语言和开发框架的官方文档聚合到了一个软件中,并且在本地提供了一个快速搜索的功能。

乍看上去,感觉就这么个功能,为啥还要付钱购买呢?而且我记得当年价格应该也不便宜,至少应该是 19.99 美金这样的价格,而且每次大版本升级都需要付费升级,真的值得吗?我的回答是值,非常值,因为每次我基本都是第一时间付费升级,即便近几年我使用 Dash 的频率越来越低(说明自己基本上停止进步和学习新东西了),但是出于一种习惯和支持优秀开发者的优秀作品,确保这样的产品不会消失,我都会用自己的钱来直接投票。

下面我们来展开讲讲,Dash 到底能干嘛?

Dash 的离线文档聚合能力

在 08 年前后,我们发明了一个新词「科学上网」来应对我们的防火墙长城——GFW对某些网络资源的封锁。作为 Android 开发者的我很巧的是,我需要经常查看 Android for Developers 这个归属于 Google 的网站上的开发者资源,其中就包含了 Android 官方的开发文档,那么非常不幸的告诉你,大概率上你是无法非常顺畅地直接访问该网站的。对于当时的我来说,初入 Android 开发门道,很多类和方法都不是那么的了然,时常需要查阅官方文档一窥究竟。虽然那个时候的我也有一些「科学上网」的手段,可以参考 2014 年的我写的文章我是怎么科学上网的,这其中简单概述了多年来我为了能自由访问互联网做过的各种尝试,个中辛酸冷暖自知。

要知道,作为开发人员,无法正常访问一门开发语言(Python语言的官网曾经多年无法正常)和主流开发框架(Android for Developers直到今天依然无法直接访问)的官方文档,对于一个开发者来说,我认为这种难受是令人发指的,而 Dash 将所有在线文档都打包成了离线文档集,我们可以直接通过 Dash 提供的托管地址下载所需要的文档集资源,例如我就一定会下载 JAVA SE + Android + Python 的文档集。随时流畅访问 Android 和 Python 的开发文档,对于我来说,体验无与伦比,当浮一大白。必须给钱!

Dash 的文档本地快速索引能力

早年间众多开发框架和编程语言的官方文档站点虽说基本能做到结构清晰,文档齐全(主流编程语言和框架),但是其搜索能力相对来说都非常的弱,甚至没有。对于我们在初学某门编程语言或者某个新的开发框架时,实际上很多的地图我们都还没有点亮,我们远不知道这地图上都还有些啥,而很多的时候我们又是带着某个问题或者目的而来求索的,然后我们来到了一个官方文档的页面。我们首先看到的是诸如此类的内容:

Install Guide | Download | Get Started | Documention | References

然而这些目录式的陈列,虽然提供了类似于字典般的检索和引导路径,但是对于一个初到此地的陌生人,坦白讲我们可能连北都找不到,假设我想找一下在 Android 中如何调用接口让手机震动,我能怎么快速找到我想找的内容呢?

通常我们都是打开 Google 直接搜索 「android vibration」,当然我发现更多的同学会直接使用百度,搜索内容大致类似「Android 控制手机震动」等等,然后我们可以来看看搜索结果:

百度搜索 Android 控制手机震动的结果页截图
Google 搜索 android vibration 的结果页截图

从上图来看,我们发现使用英文搜索引擎 Google 配合英文技术关键字搜索结果会更为符合我们预期一些。然后我们再来看一下在 Dash 中的检索体验是如何的。

Dash 中搜索 Android Docset 中的 vibrate 的结果页截图

按照我的设定,我只需要输入「and:」这四个关键字先限定我只需要在 Android 的文档集中进行搜索,当我输入「vib」这三个字符后,我就能看到我想要的结果 Vibrator 已经出来了,我一个回车就直接跳转到了 Vibrator 的内容页面了。

虽然这个例子很特殊,但确实不是我刻意挑选的,我就是刚好看到我的手机放在我的手边,收到了一条消息然后手机震动了一下,我就想着是不是可以直接用「手机震动」这个特性来搜索一下。没想到结果也这么的五毛,好像收了钱一样的完全符合我想要表达的。

但是我们理智地来分析一下,实际上很多时候我们作为开发者,遇到一些疑难问题想寻找解决方案的时候,是没有这么明确的关键字可以搜索的,例如「Flutter 中如何监听手机软件盘的打开和关闭?」这样的问题才是我们日常遇到的问题,那么通常我们的解题思路会是啥呢?

我想大部分同学会直接拿着这段关键词在百度搜索框中直接搜索,然后我们也能搜索到很多中文的博客文章,通常文章的来源为「博客园」「CSDN」「简书」「掘金」这么几个地方。我自己的习惯是,先把我自己的问题翻译成英文,然后在 Google 搜索框中搜索,也并没有高级到哪儿去,大家都是换汤不换药,然后通常也能搜到好几篇文章,为首的多是「Stack Overflow」「Medium」,不少的独立博客,偶尔还会有 Youtube 视频结果。

然后大家都会点击搜索结果中的链接,跳转到别人发布的解决方案的文章去查看方案,这个时候如果对方给出的方案中提及了一些关键的类或者方法,咱们好奇心重一些的同学,可能会再拓展延伸阅读一下,通常还是再次回到刚刚打开的搜索引擎页面,再次输入新的关键字,然后重复刚刚我们做的步骤,只是这一次很有可能就会搜索和跳转到我们使用的编程语言或者开发框架的官方文档,如果一次递归还没有到这里,那么递归通常最终结束都是到官方文档这里的。

我们想想看,每次这样在浏览器不同的 Tab 页中频繁的新增和切换,最终达成我们找到解决方案,同时溯源到官方文档的这个流程是否有些过于繁琐了。有了 Dash 之后,基本上我在 Stack Overflow 就可以停止我继续搜索的路径了,通常只需要再配合 Dash 打开具体的编程语言或框架的文档,搜索一下具体的关键词,搭配阅读就能搞清楚我的问题究竟是咋来的要咋解决,以及其中的来龙去脉和基础原理通常八九不离十了。再有兴趣深度了解背后的实现逻辑,我们可能就要转入到源代码级别的阅读了,这里我们就暂时先不展开了。

Dash 提供了一种快速联想的能力

大家可能觉得👆以上咱们谈到的这两个能力确实还不错,对于一个需要快速检索离线 API 文档的开发人员来说,确实是个利器,能给大家提效不少,如果经济实力允许也有购买正版软件的习惯,完全可以买买买。

但是,我更想说的是 Dash 的另一个隐藏的能力才是让我自己最为受益匪浅的,那就是 Dash 的快速检索和反向查找的能力,在事实上提供了一种快速联想的能力,让我能做到举一反三。我还以我刚才随手举的「手机震动」的这个案例来作为切入点,我们可以看看👇下面的这张截图

在 Dash 中搜索 vibrate 的过程的屏幕动画录制动图

我们可以看到除了正是我们想找的 Vibrator 可以直接控制手机震动之外,我们还能看到跟系统设置相关的,跟音频管理器相关的,跟系统通知栏相关的,跟权限相关的关键字们。实际上他们都是一些相关联的知识点,只是散落在这个庞大而丰富的 Android 开发文档集中的不同模块里头。通过阅读这些关联的文档,我们不但能直接了解到很多关联的功能和特性,我们更探索到了很多不同的模块,拓宽了我们在 Android 开发这个领域中的全面发展的可能性。

这样类似的例子真的数不胜数,但是关键在于我们要是有心人,是有着好奇心的人,而不是一个快速消费者,来了只点一个蛋挞,吃了就走,完全不看菜单,也不想着自己可能还想吃点其他的,或者先看看了解一下,下回点个鸡翅啥的。而 Dash 就非常好地满足了我自己的好奇心,很多的时候,我就会在使用 Dash 查找 A 的同时,会发散阅读和了解 D 和 S 等等可能并没有那么直接关联的知识点,甚至又回再次回到搜索引擎,最终看了一个 Youtube 视频或者读了一篇其他开发者写的 Medium 长文,花了好几个小时。但是这样提供给我的养料和知识是丰富的,是多维的,更让我能从多方面去了解某一个特性或者知识点。这些知识点终将在我的脑子里形成勾连,最终结网,成为我的能力中的一小块。

Dash 的基本功很扎实

👆以上三点是我自己对 Dash 最为推崇的三点特性,但是其基础功能的靠谱更是前提,下面我们简单挑几个基本功夸一夸啊。

  1. Dash 的作者做了不少的脏活累活,例如把 .NET Framework, Android, Apple API Reference 等文档做成了 Dash 支持的格式,并且提供了非常快速的离线文档下载速度,请简单回忆一下安装完 Visual Studio 后再安装 MSDN 所需要的时间和那个体验;
  2. 搜索结果展示的高亮,搜索结果条目的所属模块的展示和相似结果的提醒,都非常好地提供了更多维度的信息,供开发者快速判断和定位自己想要查找的信息;
  3. Dash 支持的快速关键词匹配特定文档集索引的功能就是一个很不错的创新性的特性;
  4. 支持第三方文档接入,例如支持第三方文档源:Go Docsets, Java Docsets 等等;
  5. 与其他开发工具的集成一直都做得不错,我们常用的开发工具和场景基本都覆盖到了,例如我自己偶尔会用到的:IDEA,Visual Studio Code,Terminal,Alfred,PopClip,除了这些还有不少,至少在开发者效率上,作者还是很下功夫和花心思的,哪怕帮咱们省一秒钟,作者也是努力去做了,👍。

结语

拉拉杂杂写了也不少,一个人遇到一款软件,有很多的机缘巧合。我是因为加入了一个非常年轻且好奇心浓厚的一个团队,遇到了一些很可爱的伙伴,然后尝试了这些优秀的软件,对自己造成了一些影响,也许是改变,也许只是更加深了对自我本真的塑造,然后我成为了今天我,不算太好,也不算太坏。

作为一个普通的开发者,我有着比较清楚的自知之明,我也清楚地知道,在真实的互联网开发团队中,很多的开发伙伴们还依然在使用土法制炸弹,虽然做出来的炸弹也能响,也能以此卖得三二两酒钱,但是我想大体上大家还是希望有一些更为不错的工具和方法能让自己做的不那么狼狈,做得不那么辛苦,做得稍微体面一些吧。

希望能提供一丁点帮助,带来多一丢丢启发或思考,大家一起进步,加油。

【利器系列】00-写在前面

最近跟好友「孔雀67」聊了多次关于「一个到了要被大厂优化的35岁的高龄程序员,接下来要干些啥?」这个话题,由于我俩的革命友谊建立已有 14 年之久,更有长达 8 年之久居同一屋檐下,除去一同求学的 4 年同窗同宿之谊,更有 2 年共同创业背靠背作战的经历,所以我俩之间的通话基本上能做到毫不保留,也非常地简单纯粹。

谈话中,好友谈及自己近期开启了一个新的 Side Project —— 花十年乃至更长的时间,做一个优秀的体素游戏引擎,从他的嘴里说出来这样的话,让我听着感觉非常的信服和幸福。

信服来自于好友近 5 年在体素游戏领域的深耕,自己从零开始,带领一个原本是做移动互联网 App 的团队成功转型,从一个开源的小引擎入手,持续迭代 3 年,从技术到产品,一点点创造和打磨出来一个非常优秀的体素游戏,在商业上获得了不错的成绩。基于这 5 年前的判断,这 5 年间的投入和产出,以及这些年他在该领域解决的各种难题,积累下来的经验和解决方案,我相信他的这个 Side Project 非常的真实可触及,我要先祝福他。

幸福来自于我自己对好友的羡慕,羡慕他能有如此明确的想做的事情,而且听着又是那么切实际和可执行的项目,同时还是一个那么契合自己对长期主义比较推崇的这个心理,在我看来,「花十年乃至更长的时间,做一个优秀的体素游戏引擎」这是一个长期来看都很有意义的事情,未来价值不会消解甚至可能会增长的 事情。

反观自己,从 10 年开始移动互联网创业,从移动社区到手游,再从手游回到互动娱乐直播,从 Android 开发到 Unity3D 开发,再回到 Flutter 开发,感觉自己做过的事情不老少,但是留下的东西少之又少轻于鸿毛,在技术领域也没有什么深厚的积累,在商业上更是未获得什么可以称得上成绩的结果。

所以当 2022 年开始,我就尝试不断地问自己,「除了做一个互联网公司的工具人,我还能做些啥?」,直到最近,一直都没有一个接近好友「花十年乃至更长的时间,做一个优秀的体素游戏引擎」这样的一个可执行的想法或事情作为答案出现。虽说当年大学毕业求职的时候,最终选择了来北京加入一个软件公司,成为了一名软件开发人员,但是自己对于通过代码创造一些东西这个事情,一直没有那种在别人的文本中渲染的为代码痴迷的热情。只是出于养家糊口需要有一技之长,和出于为事情负责任的心态,持续在做着写代码这个事情,在写的过程中只是觉得自己应该干得漂亮一些,不能做得太糟糕,不想丢人或者辜负别人的期望,才一步步走到了现在这个样子。

写代码这件事情并非我所爱(也许可能自己也不知道自己真正热爱的是啥,更有可能是自己做啥就烦啥吧,可能就是因为没有做出来啥成绩罢了)这个事实,慢慢地我学会了接受它,我也接受了我并不讨厌写代码这个事实,同时也接受了我写代码还不太烂的这个事实,终于,我发现了自己只是一个非常非常普通的程序员,只是在写代码赚钱,并尽量让这个过程不那么狼狈和难看。

接受了自己没有这么强烈的创造欲和探索欲之后,内心反而坦然了一些,那么问问自己喜欢做点啥,哪些事情做得还不错,做哪些事情能让自己内心有一些满足感,那么我就做这个吧。

持续创业了 10 年之多,虽然没有进过什么大厂见世面,但是 10 年的在一线创业团队中的摸爬滚打,让我在解决问题上的能力得到了非常充分的锻炼,我也可以摸着自己的心口说一句,在这点上我并不怵,而且我自己也比较享受跟人分享我是如何锻炼自己解决问题的能力的过程,而且自认为这件事情做得还不算太糟。解决问题的能力听起来很虚,但实际上是可以具象化的,而且是可以分模块拆解的。在我自己的逻辑里头,解决问题的能力可以拆解为以下几点:

  1. 理解问题的能力,这是解决问题的第一步,也是很多人不太重视或者较容易忽视的一点,很多的时候我们能否正确地通过对现象(很多时候我们都是遇到了某个具体的事情或者观察到了某个现象)的分析,尝试确定问题对于我们最终找到解决方案至关重要,如果第一步就走错了,后续很有可能要绕很多弯路才能抵达正确的地方;
  2. 分析和定位问题的能力,通常当我们理解了问题之后,基本上我们已经知道问题的方向和可能出现问题的地方了,然后顺着在上一个步骤中发现的一些蛛丝马迹抽丝剥茧地找到问题的源头,抓到这个虫子🐛,然后把它给治了,通常这个步骤是大家日常花费时间和精力最多的,也是大家八仙过海各显神通的环节,每个人抓虫🐛的方法各有千秋,但实际上是有技巧优劣之分和效率高低之别的(别跟我说黑猫白猫抓到老鼠就是好猫这种没有用的话,大家都在一个商业社会里,大家也都是有血有肉的人,大家实际一些,考虑一下投入产出比和抓虫人的个体感受,好不好);
  3. 归因和总结的能力,在解决了问题之后,能否回过头来思考一下,为何在自己的代码中或者项目中出现这样的问题,并且得出结论最终形成自己思考,为自己或团队后续的工作提供一些参考或者指导,并且能够形成自己或团队的一些积淀,就更是善莫大焉了。

👆以上三点,第一和第三点,看着很虚,但是实际上是对人要求更高的软能力,第二点是非常实际的硬技能也是每一个开发人必须具备的恰饭技能。

由于第二点中涉及的更多的是我们日常开发和排查问题过程中需要使用到的硬技能,也是更好展开来聊聊的问题,毕竟这也是难度可低可高,深度可深可浅的一个话题,咱们可以由浅入深,慢慢展开。所以我们就先从分析和定位问题的能力开始,而分析和定位问题中,我们会使用到诸多的工具来帮助我们,正所谓「工欲善其事,必先利其器」,而且我在工作了 10 多年之后,观察了一些伙伴们在分析和定位问题中使用的方法和工具,觉得大家还是有些苦于没有更好地利用到我们可以利用到的更优秀的一些工具和方法,导致自己排查问题的过程并没有那么有效率,体感也相对较差,总是略显狼狈或者磕磕绊绊的。

那么我就先开这个坑——「利器系列」,在这个系列中,我会跟大家分享一下,这些年里头我自己常用的一些工具和方法,以及如何利用这些工具和方法来达成我们「善其事」的目的,希望能给感兴趣的伙伴们提供一些参考或思路上的开拓。关于如何提升自己的软能力的话题,我们留着后面再来一起探讨,咱们不急。

做了两个转换 Color HEX Codes 的 PopClip 插件

最近这三年里头,我成了一个 Flutter 开发人员,加入了映客这家做直播的公司,主要做直播相关的业务开发。映客的产品研发流程中设计团队的设计稿交付通常都是通过蓝湖来完成的,我们也就习惯使用这个工具来查看设计稿了,开发的过程中确认尺寸和取色的过程基本上都是直接在蓝湖上完成。

通常我们需要使用的颜色值在设计稿页面右侧的标注栏中根据我们想要的颜色格式,在 HEX、AHEX、HEXA、RGBA、HSLA 这几种颜色表达格式中随意切换,然后直接拷贝即可。

但是由于我们做的是 Flutter 开发,Flutter 原生支持的颜色构造方法有以下几种:

const Color(int value) : value = value & 0xFFFFFFFF;

const Color.fromARGB(int a, int r, int g, int b) :
    value = (((a & 0xff) << 24) |
             ((r & 0xff) << 16) |
             ((g & 0xff) << 8)  |
             ((b & 0xff) << 0)) & 0xFFFFFFFF;

const Color.fromRGBO(int r, int g, int b, double opacity) :
    value = ((((opacity * 0xff ~/ 1) & 0xff) << 24) |
              ((r                    & 0xff) << 16) |
              ((g                    & 0xff) << 8)  |
              ((b                    & 0xff) << 0)) & 0xFFFFFFFF;

每次从蓝湖中拷贝过来的 HEX Color Codes 字符串总是无法直接拷贝粘贴到 Dart 代码中直接使用,每次要么得自己把 #FFFD3666 中的 # 换成 0x,最终变成 Color(0xFFFD3666) 这样才能正常构建出来一个颜色值对象。对于这种简单重复的劳动,我是有种本能的反感,在前两年的开发中,我自己实际动手写 UI 控件的机会不多,因为组内有其他能做得更好和更熟练的伙伴在负责 UI 控件这块儿,这近一年由于自己从原来的大项目组调整到了更小的团队中,由于人力配置的问题,日常开发工作中也开始自己写一些 UI 控件了。一次次地拷贝中,除了想着想把一些颜色值做成主题(更多依赖于研发和设计高度认同,严格遵守规范,定义好业务内不同场景下应用的颜色、尺寸、圆角半径等等),还有就是想着能不能把每次手动改动 # 符号为 0x 的这种机械式的动作简化掉。

恰巧我很多年之前使用过 PopClip 这款软件,具体为何我会购买这款软件,以及当时我用这款软件来帮助我完成什么事情,我已经记不起来了,但是我非常清楚地记得它有一个非常强大的插件生态和插件能力。所以我就想着是不是可以利用它的能力,帮助我达成每次拷贝到这种 HTML 的 Hex Color Codes 字符串的时候,弹出一个处理选项按钮,我直接点一下就帮我处理好了,我只需要切到我的 IDEA 代码编辑器中直接粘贴就好了,所以我这就直接先去这个官方整理的插件页面去找了一圈,不过看来这种需求还是有点小众,并没有完全匹配的。

想来想去,还是忍不了这样总是无聊的重复劳动,借着周末在家,刚好新项目的研发工作已经阶段性地告一段落了,只需要日常推进持续迭代即可。想着给自己来个代码按摩吧,了解了解这个编程世界中的其他一些美好的角落中的小故事,顺便给自己写个提效的小工具,也算不错,刚好北京近两周正处于疫情苗头又起来了的阶段,也不太能带娃出门。

既然选择要写自己的插件,那就找到官方的教程来读读看,不看不知道,一看吓一跳,真是要给这样的开发者竖大拇哥👍啊,文档写得是真到位,写得真好,但凡作者觉得能对读者有帮助的内容,都给出了外链和应用方法。从这个文档中,我至少拓展阅读或了解了以下一些非常优秀的项目:

quickref

case-anything

 The Noun Project

SF Symbols

ICU specification

作为一个非冲动动手型选手,在动手写任何代码之前,我总是希望能对我即将要做的事情有一个大致的了解后再思考自己需要怎么做。虽然我也能直接拿着官方插件仓库中的代码之间改一改就能跑起来,但我显然一直都不是这样的一个人,我还是比较享受从0到1慢慢了解一个项目,这样难度相对更低,自己也能更舒服,渐进了解了 PopClip Extension 的设计思路和整体规范之后,再了解具体制作的流程和规范,再结合自己要做的事情,匹配到我需要使用的特性,最终确定我需要使用到其 Shell Script Action 的特性来执行我自己稍微熟一些的 python 脚本来完成我想要做的两件事情。

  1. 将 #FFFFFFFF 这样的 HTML Hex Color Codes 一键转换为 0xFFFFFFFF 这样的 16 进制字面常量表示形式;
  2. 将 #FFFFFFFF 这样的 HTML Hex Color Codes 一键转换为整型数 4294967295。

具体的制作过程就不展开了,实际上非常的简单,直接照着教程,创建一个目录,在目录下放上以下三个文件即可:

  1. Config.json => 用于声明这个插件的各项参数和具体需要使用的图标,执行的脚本,以及执行完脚本得到结果后的动作等等;
  2. h2d.py => 这是我写的两个插件中的其中一个插件依赖的 python 脚本的名称;
  3. README.md => 一个用于描述自己插件是干嘛的 MD 文档,可有可无,但是我认为是需要的,像优秀的人和优秀的项目靠近,我们才可能也变得更好一些;

然后将整个目录改名,加一个 .popclipext 后缀在目录名称后面即可,安装了 PopClip 的 macOS 系统会自动识别出来这个目录是一个插件,整个目录的图标展示都会变成 PopClip 的图标样式,双击安装插件,由于我们自己写的插件目录下没有签名文件(如果要签名可以联系 PopClip 的作者帮忙),所以 PopClip 会检测到这是一个未签名的插件,需要我们二次确认后才可安装成功,安装成功之后,即可使用了。

我的这两个插件的效果就是这样的,#FFFFFFFF => 4294967295,0xFFFFFFFF

插件效果演示

最后附上我自己 fork 出来的 PopClip-Extensions 的地址吧:https://github.com/lishali12345/PopClip-Extensions

另外这两个插件的代码分别在:https://github.com/lishali12345/PopClip-Extensions/tree/master/source/Hex2Decimalhttps://github.com/lishali12345/PopClip-Extensions/tree/master/source/HexColorCodes2HexText

下载后可以直接双击安装并使用的插件(注意未签名)在:https://github.com/lishali12345/PopClip-Extensions/blob/master/extensions/Hex2Decimal.popclipextzhttps://github.com/lishali12345/PopClip-Extensions/blob/master/extensions/HexColorCodes2HexText.popclipextz

「读库 App」给我带来了什么?

作为一个《读库》的 13 年长期订户,我从 2009 年毕业那一年开始每年都订阅当年的全年《读库》,在其推出「小册子」计划后每年订阅的就是全年《读库》+「小册子」。

时间由来已久,期间自己搬过大概 6 次家,每次搬家的时候都会发现自己需要搬的书中有近 1/4 是历年来在「读库」这个出版机构购买的各种书籍,每次搬家除了觉得书很沉,收拾起来和搬起来都很累(虽然每次都会找搬家公司,只不过自己每次搬家都是跟搬家师傅一起搬,不论是否有电梯,好像直到最近一次搬家才搬进电梯房,所以每次都有真正的切肤之感)之外,每次收拾这些书的时候还会发现一个巨大的真相,那就是「原来我订了这么多年的《读库》中至少有一半是我竟然都没有拆开塑封的或者没有翻开过的」。

所以每次搬家的时候,会觉得自己辜负了这些好书好文章,没能及时地跟她们在书中厮磨一番,将其冷落了,顺便也会怀疑自己是否还需要持续订阅下去。可是鉴于这些书实在是太便宜了,而买书又那么地能给自己提供一个虚妄的满足感,正所谓「买书如山倒,读书如抽丝」,显然不是我个人的感受和困惑。「买都买了,还需要读吗?」更是我们这帮买书不读人常挂在嘴边的自我开解之辞。所以每年只要老六开始吆喝新一年的饭票要续费的时候,总是第一时间就下单,感觉是给自己这一年的空虚又填上了一锹带有墨香的土。

作为一个卷心菜式的互联网打工人,连续创业多年,连续失败多次的自我压榨者,坦率地讲,这么多年来,一直没能做到传说中的 「work life balance」。作为两个男娃不太合格的爹,工作日基本上没有在 9 点之前下班的时候,留给自己捧读的时间和机会确实不太多。这倒不是想给自己读书不多找什么借口,我也不需要这样的自我承认,活到这个年纪了,自己大概是个什么样的鸟人,基本上自我认知已经比较真实了,就看自己愿不愿意面对了。

坦白地讲,我就是一个在普通不过的普通互联网打工人了,时间不多,疲于奔命,渴望精神世界的自由和财富自由而不得。想进步,每次制定了一个成长的计划后,基本上在 3 ~ 30 天之内就夭折,想健康,基本上在坚持了两周之后以各种各样的姿势再次花式扑街。基本上,大家都看的综艺,我也看一些;基本上,大家都看的电影,我也看一些;基本上,大家都看的美剧,我也看一些;基本上,大家都听的音乐,我也听一些;基本上,大家都买的基金,我也买一些;基本上,大家都炒的股,我也炒一些;基本上,大家犯过的错,我也犯一些;基本上,大家打的鸡血,我也打一些。

看吧,就是这么一个如此普通和无聊的人罢了。所以书买了没读,内在原因在那儿,外在原因在那儿。不过这一两周里,开始尝试使用「读库」App 之后,我发现还是有些变化的。

首先,我已经养成了每天在有空闲的碎片时间时,主动打开「微信读书」App 随便翻翻的习惯。所以当我把「读库」App 跟「微信读书」App 放在手机桌面隔壁时,已经养成习惯的我在想打开「微信读书」的时候,会有一定的概率会打开「读库」。就着这个「裙带关系」,在不到两周的时间里,利用工作日通勤路上的时间,午休的时间,休息日的闲暇时间,我已经读完了《读库 2201》了,而家里的纸质版的《读库 2201》才被翻开了没几回。

其次,由于「读库 App」实际上提供的内容不止限于其出版的《读库》每期刊载的内容,还有其他周边的内容,例如非当期的内容,往期成系列的文章,如我自己花时间最长读着尤为喜爱的《文学的故乡》系列文章。其中关于毕飞宇,莫言,迟子建,这三人的文章我也在往期的《读库》中已经读过了,但是借着这次「读库 App」上的主题系列阅读,我又非常愉快地先重读了一遍,然后接着一口气把刘震云,贾平凹和阿来的三篇文章都给读完了。这一系列的文章,要是从篇幅上来看,已经接近一部小书了,成系列地连续阅读会让人读着读着读出一些勾连和互通的感觉,我能读出这些作家对于自己写作的内源力的探究的殊途同归,我会发现优秀的作家或者说作者实际上他们的认知和行为方式都是那么的诚实,相似处很多,共通性很多,也有着故乡土地给予他们各自不同的底色,更有着不同成长路线给予他们的视角的不同,但是大爱是一样的,那就是书写自己的内心,书写自己看到的普通大众的内心。

借着 App 的便利性,不但不自觉中把原来基本上已经很难再按时读完的书给读了,还因着 App 中编辑的推荐和形式的灵活,有了系统化阅读的快乐和拓展阅读的可能,比如,关于拍了《盲山》和《盲井》的导演李杨的文章,关于区块链原理的文章等等。

认清这个事实了之后,自己蛮开心的,承认自己不是那么爱书的人,已经被手机和 App 驯化成为了一个普通的现代人,那么就借着这个事实,把手边能用起来的时间稍微分配一些给到阅读这件事情就好了,纸质阅读很好,继续保持就好了,手机上的电子阅读也很好,可以补充很多的场景,并且让阅读这件事情完成。

不要为了某种形式,追求某种完美,也不要因为缺失某个条件就不去做某件事情。大概就是这样吧。

「作者此处有删节」是一种什么样的体验?

这几日在读贾平凹的《废都》,之前读过《秦腔》和《浮躁》,想着把这名家的代表大作都读了吧,就在微信读书上找了来读,读着读着就感觉不太对了。诸多章节出内容中,直接使用了「此处作者有删节」这样的文字代替了大段的性描写,这倒不是咱们没读过小黄书,想看看这香艳刺激的场面具体是咋描写的,而是这样奇怪地保留作品的完整性而又要符合出版审查制度的自我阉割显得实在是过于行为艺术了。我甚至觉得这是一种反讽,也行是我过度解读了啊,作者兴许只是想让这本书的出版不那么艰难,也能让这么好的作品给更多的普通读者能读到罢了。

至此我的好奇心就被激起来了,我到要看看删节的内容具体都是个啥。于是我就搜索了一下,还真找到了未删节版的 mobi 和 epub 文件,最终选了一个看着还算满意的转换了格式,导入到了朋友送我的 Kindle 里头,自己调整了一下字体大小和行间距,就开始读了起来。

其实我们的贾平凹先生对于这种香艳场面的描写并没有特别出彩和骇人听闻之处,基本上跟我们实际生活中的性行为过程毫无区别嘛,也没有像小黄书那样为了满足读者猎奇的心理,刻意将性过程的描写扭曲和夸大,只是用词非常的准确和直白,在我们这个比较偏爱委婉美和谈性色变的主流文化审美环境中,可生存的空间确实不太大。

不过在对比阅读的过程中,发现了两个还蛮有意思的事就是,微信阅读的基础排版会让人读起来舒服不少,早年间的 epub 电子书基本上跟纯 txt 电子书毫无区别,全然没有任何排版,错别字频出(可能跟早年输入法和录入员的素质有关?或者这就是个盗版的电子式,何谈录入员)。在Z-Library找《废都》的同时,我也搜索了一本自己手上有纸质本和微信读书版本的《贪婪的多巴胺》,想着放到 Kindle 上读起来不费眼睛,将其导入到 Kindle 上一打开,这个排版和字体,完全就是纸质本的翻版啊,读起来舒服得很,相较而言微信读书的版本就是有些差点意思了,微信读书上的排版基本上都是以铺满手机屏幕为主(为了在窄小的手机屏幕上展示足够多的内容这个可以理解,不知道墨水屏版本对于微信读书中的内容是否有区别设计和适配,如果仅仅是简单的按比例放大,那就有点遗憾和不够了),而 Kindle 的排版由于设备尺寸相对固定并且比较接近口袋本的尺寸,所以整体排版还是很有书籍本体的那种边距的变化,段落感也会很明显,尤其对于我这次是先从纸质版开始阅读的,然后微信读书才上架了电子版,最后我又阴差阳错地读了一个 Kindle 版本,还真是不同的载体体验很是不一样呢。