使用 Beancount 记账篇一:给账户命名

在之前整理复式记账 的文章中曾短暂的提及过 Beancount,上一篇文章简单介绍了一下 Beancount,现在经过一段时间的使用,也正好回顾总结一下自己的使用经历和经验。

要入门 Beancount 的使用,其中最重要的第一步便是充分的认识 Beancount 中的账户概念,在复式记账中资金都是在账户与账户之间流转,因此账户就非常重要。但是因为 Beancount 的入门难度要远远超过其他的记账软件,所以迈出第一步就变得至关重要,迈出了这第一步后面就会发现 Beancount 能带来远超预期的收益。

在 Beancount 中内置类几类账户,这几类账户会用来生成最后的 [[资产损益表]]、[[资产负债表]] 等等报表。这几类账户在之前的文章中也提及过:

  • Assets
  • Income
  • Expense
  • Liabilities
  • Equity

在 fava 展示损益表的时候会使用到 Income 和 Expense,而在展示负债表的时候会用到 Assets, Liabilities 和 Equity。

文件组织

在构建了一个完整的命名体系之前,可以先对 Beancount 帐本进行提前的规划。比如我以如下的方式管理:

├── account
│   ├── assets.bean
│   ├── equity.bean
│   ├── expenses.bean
│   ├── income.bean
│   ├── liabilities.bean
├── beans
│   ├── 2020.bean
│   ├── 2021
│   │   ├── 01.bean
│   │   ├── 02.bean
│   │   ├── 03.bean
│   │   └── 04.bean
│   ├── 微信\224\230账\215\225(20200701-20200930).bean
│   └── 微信\224\230账\215\225(20201001-20201231).bean
├── config.py
├── datas
│   ├── 微信\224\230账\215\225(20200701-20200930).csv
│   └── 微信\224\230账\215\225(20201001-20201231).csv
├── importers
│   └── beanmaker.py
├── main.bean
├── processing.sh
├── requirements.txt

说明:

  • account 账户中只定义 openclose 账户的语句,不同的名字命名的账户分开管理
  • beans 目录中是真正记录交易的地方
  • datas 目录则是账单的原始数据
  • main.bean 主帐本的定义
  • processing.sh 以及 importers 是处理原始账单数据的脚本

main.bean 中通过 include 语法将其他 bean 引入,同时还定义了一些可选项。

option "title" "ledger" ; "我的账本" ledger
option "operating_currency" "CNY" ; 帐本货币
option "operating_currency" "USD"

; fava
2016-04-14 custom "fava-option" "auto-reload" "true"

include "account/*.bean"
include "beans/*.bean"

剩下的其他几个文件一个是配置从原始账单自动生成对应 bean,以及提前预处理账单的脚本 processing.sh,这部分内容会在后续介绍多个类型账单导入的文章中介绍。

当然你并不需要按照这样的方式来管理,Beancount 完全支持在一个文件中记录所有的内容,就像这个演示 那样。

给 Assets 账户命名

对于个人而言,如果用最通俗的语言来解释 Assets 的话,「那就是你所拥有的资产」,这个资产包括现金,银行的存款,证券市场上的股票等等能够产生购买力的,或者能够用来清还债务的东西。

对于国内的场景,可能还会有账户叫做支付宝余额,或者微信零钱。那么有这样的概念之后就可以轻松的定义出这样的账户。

; 现金
2010-11-11 open Assets:Cash

; 支付宝
2015-11-11 open Assets:Alipay:Balance ;"余额"

; 微信余额
2010-01-01 open Assets:WeChat:Balance

; 老虎证券
2018-06-01 open Assets:Broker:US:Tiger

; 银行账户来
2010-11-11 open Assets:DebitCard:CMB CNY

去除上面这些比较好理解的实体账户,还有一类虚拟账户,比方说借钱给了张三10000元,那么就应该开一个「应收款」账户:

; 欠的钱
2000-01-01 open Assets:Receivables:Zhangsan CNY

记录一笔交易

2000-03-09 * "借钱给张三 100000"
  Assets:Receivables:Zhangsan 10000 CNY
  Assets:DebitCard:CMB   -10000 CNY

等张三将钱归还,就可以将此账户关闭:

2001-01-01 close Assets:Receivables:Zhangsan

但是如果要去通过 Beancount 来记录证券交易,那么便会稍微复杂一些。之后会再写新的文章进行总结。

给 Income 账户命名

收入账户也比较好理解,有多少收入便开通多少个收入账户。一般来说如果是月工资则会按序进入上面开的银行账户。如果年终有奖励则还会开一个 Bonus 的账户。

2010-11-11 open Income:Salary:Hooli CNY  	; "Regular Pay"
2010-11-11 open Income:Bonus:Hooli  CNY 	; "Annual bonus"

对于普通的收入账户比较明确,但是如果要记录比如未成熟的期权,股票等,则就稍微复杂一些,之后再用其他文章说明。

给 Expense 账户命名

开支账户是一个相对比较繁琐的账户,但理念非常容易理解。在普通的记账软件中,一般会对消费进行分类,那么就可以根据自己的真实情况将这一个分类搬到 Beancount 的 Expense 账户中。

如果之前没有使用过类似的记账软件,那么大概也会知道可能有那么几类,衣、食、住、行。日常生活的开支基本上这几大类也都覆盖了,其他的开支账户可以等用到的时候再建立。

可以来参考一下其他软件的账户分类。

对于开支账户,不建议设置很多,但也不建议设置得比较笼统,需要自己把握那个度。开设很多账户在记账的时候就会需要花费很多时间思考一笔交易被划分到哪个账户;而设置的比较少的时候,后期进行统计的时候就没有区分度。

在创建账户的时候也可以参考一些市面上成熟的应用的内置分类。

之前用过的一个叫做 Wallet 的应用的内部账户分类。

Food & Drinks
    Bar, cafe
    Groceries
    Restaurant, fast-food
Shopping
    Clothes & shoes
    Drug-store chemist
    Gifts
    Jewels
    Pets
    Stationery
Housing
    Energy
    Maintenance
    Mortgage
    Property insurance
    Rent
    Services
Transportation
    Business trips
    Long distance
    Public transport
    Taxi
Vehicle
    Fuel
    Leasing
    Parking
    Rentals
    Vehicle insurance
    Vehicle maintenance
Life & Entertainment
    Sport
    fitness
    Alcohol
    Book, audio, subscriptions
    Charity
    Wellness
Communication
    Internet
    Phone
    Postal Services
    Software

再比如 MoneyWiz 默认账户名

Automobile
  Accessories
  Car Insurance
  Gas/Fuel
  Lease
  Maintenance
  Other
  Parking
Bills
  Cable
  Electricity
  Gas
  Internet/Broadband
  Mobile Phone
  Other
  Phone
  Water
Clothing
  Accessories
  Clothes
  Jewelry
  Other
  Shoes
Digital
  Apps
  Books
  Movies
  Music
  Other
  Podcasts
  TV Shows
Food & Dining
  Dining/Eating Out
  Groceries
  Other
Health Care
  Dental
  Eye Care
  Health Insurance
  Medical
  Other
  Pharmacy
Housing
  Furniture/Accessories
  Home Insurance
  Maintenance
  Mortgage
  Other
  Rent
Leisure
  Entertainment
  Fitness/Sport
  Other
  Personal Care
Loans
  Other
  Taxes
  Transportation
  Travel

当然我觉得个人没有必要划分的这么细,可以在使用的过程中再逐步增加分类。

; 衣、鞋
2010-01-01 open Expenses:Dressup:Clothing

; 食
2010-01-01 open Expenses:Food:Drinks ;"饮料"
2010-01-01 open Expenses:Food:Fruits ;"水果"

; 住
2010-11-11 open Expenses:House:Rent              ; 房租
2010-11-11 open Expenses:House:WaterElectricity     ; 水费、电费
2010-01-01 open Expenses:House:Gas ;"燃气"

; 行
2010-11-11 open Expenses:Transport:Public
2010-11-11 open Expenses:Transport:Taxi

; other
2010-01-01 open Expenses:Digital

开支分类这个事情也可以做的比较智能一些,比如通过学习,自动进行分类

不过我个人还是觉得通过关键字自动进行开支账户的导入还是足够精确的。

给 Liabilities 账户命名

最常见的负债账户就是信用卡了,可以将开卡的时间以及开卡的银行记录下来。以后按月整理信用卡账单就会方便很多。

如果涉及到房贷等等,其实是差不多的。

比如开通一个交通银行信用卡的账户:

2010-11-11 open Liabilities:CreditCard:BOC CNY

和之前一样,在处理借款的时候,也可以用账户来追踪:

; 欠钱
2000-01-01 open Liabilities:Payables:Zhangsan CNY

Beancount 这样的纯文本记账工具,对于账户开通和关闭处理几乎没有成本,可以任性地添加账户。

命令规范

命名规范可以简化理解的成本,和代码规范一样,帐本被阅读的次数肯定要比记录的时候要多,尤其是当帐本越来越复杂的时候。一套有机完整的命名不仅可以让记账更人性化,也可以免去之后再去频繁修改账户名字的烦恼。

个人为 Beancount 的账户命名应该要遵守几点:

  • 账户名要尽量详细,但不应该太长,个人使用的习惯一般不会超过3级目录。
  • 帐户名有大到小整理,在 fava 界面中,多级账户会进行归类求和,可以清晰地看到上一级账户的总额
  • 在初始开通账户的时候尽量采用详细的多级账户,在未来合并账户的操作可以通过替换完成,但是拆分账户的操作则需要一一核对
  • 降低记账的认知负担,在确定好帐户名之后尽量可以通过直觉直接确定应该归属到哪一类账户。

附录

mint-categories

mint-categories https://www.mint.com/mint-categories

Expenses (all types)
  1. Rent/Mortgage
      a. Home Owners Association Dues
      b. Rental Insurance
      c. Home Owners Insurance
  2. Fixed Expenses
      a. Utilities
      b. Gas
      c. Electric
      d. Water/Trash/Sewer
      e. Cable/Internet/Phone
      f. Cell Phone
      g. Credit Cards
      h. Car Expenses
      i. Maintenance
      j. Gas
  3. Extra Expenses
      a. Grocery (Food)
      b. Clothes/Shoes/Hygiene
      c. Extra for Home Expenses
  4. Savings
      a. Savings Account. Speak with employer; some saving plans can pull from paycheck before taxes. That means less of your paycheck is taxable.
      b. Create an Emergency Fund; it should be at least 6 months of expenses. Emergencies can happen and drain a well-established savings account
  5. Taxes
      a. No explanation needed
  6. Fun Cash
      a. Out with friends
      b. Movies
      c. Vacations

GnuCash

  Adjustment
  Auto
      Fees
      Gas
      Parking
      Repair and Maintenance
  Bank Service Charge
  Books
  Cable
  Charity
  Clothes
  Computer
  Dining
  Education
  Entertainment
      Music/Movies
      Recreation
      Travel
  Gifts
  Groceries
  Hobbies
  Insurance
      Auto Insurance
      Health Insurance
      Life Insurance
  Laundry/Dry Cleaning
  Medical Expenses
  Miscellaneous
  Online Services
  Phone
  Public Transportation
  Subscriptions
  Supplies
  Taxes
      Federal
      Medicare
      Other Tax
      Social Security
      State/Province
  Utilities
      Electric
      Garbage collection
      Gas
      Water

其他模板


2021-02-11 beancount , accounting , bookkeeping , double-entry

如何进行有效的讨论 论 Clubhouse

这两天 Clubhouse 非常火热,又使得「声音」这一载体被放到了台前,但听了多个 Room,并没有收获太多,反而是相对较大的「杂音」影响了收听,并且大部分的观点并没有让人眼前一亮的感觉。

而从去年读[[洛克]], [[密尔]]开始,我就在思考什么叫做「有效讨论」,这些先贤们在写下他们流传百世的著作之前,当然有其自身深入地思考,但也绝不是将自己关在小黑屋与世隔绝而诞生了其思想,往往在他们形成自己的思想之前,他们会阅读大量比他们时代更早的作品,也会与他们同时代的伟大思想家进行书信,甚至直接的交流。在这样的思辩和讨论之中,他们最终才会形成自己的思想,这些伟大的思想有可能是他们首先提出,但有会有部分在修正以前思想的问题。但无论这些思想对与否,他们都以自己深入的思考给出了他们自己认为的答案,我想或许这就是一种值得我们学习的方式。伟大的思想家都有自知,每个时代都有许多被后世认为错误而且荒谬的看法,但经过讨论,错误的意见和行为就会逐渐屈从事实和论证。

有效讨论

有效的讨论一定是有主题的

讨论的中心一定是要有的,不管这个主题是什么,一定要约束一次讨论不会偏离这个主题,直到满足下一个条件,也就是得出一定的结论,才可以转换主题。

比如可以聊创业,可以聊技术,可以聊哲学,可以聊某某地方的吃喝,而从这些主题中可以延伸出非常多的内容,有讨论就必然会有讨论的组织者,讨论的组织者可以参与讨论,也可以不参与,但是要将讨论的主题限定在这个范围内,一旦偏离主题就要及时地将话题来回来。Clubhouse 中的 moderator 就是这样的角色。

有主题的讨论一方面保证了话题的可持续性,可以产生源源不断的新内容,另一方面也使得听众可以迅速地抓住话题重点,从而判断是继续听,还是进一步地参与到讨论中。

有效的讨论至少要有结论

有效的讨论一定需要结论。不管这个结论是否是最后的真理,也需要达成最大部分人的共识。

有人可能会反驳,比如一次哲学思辩,一次课堂讨论,可能并不会有真正的结果,比如《公正课》中讨论的著名的电车难题,虽然讨论的过程是双方,甚至多方对立的,但是在讨论的过程中,一定会形成一种思考的方式,那这就是这次讨论的目的,比如《公正课》中,学生的目的便是为了学习,更进一步地说可以是学习认识世界的一种方式。

回想美国建国之初,即使分歧那么大,即使十三个州相互不同意各自的方法,但在 [[詹姆斯 麦迪逊]]、[[亚历山大·汉密尔顿]] 等等先辈的 [[联邦党人文集]] 中通过几十篇理性的论证说服大部分人认同联邦要比各州各自为政要好。并在之后的立宪会议上在多方博弈后终于指定下,切实可行的制度。虽然这个「结论」并不一定是最后的真理,但是所有人应该按照约定,或者说按照「契约」去履行。我们站到今天来回看美国的宪法,当然是有问题,黑人、妇女的权利就没有考虑到宪法内,但这不影响暂时性的结论,如果喋喋不休争论200年,那将会一事无成。而一旦确立了一部切实可行的宪法,那么可以在这个基础之上对其进行修正,可以看到[[宪法第十五修正案]]、[[宪法第十九修正案]]分别赋予了黑人及女人以选举的权利。

再回到武汉肺炎和 COVID-19 的分歧,有一天在海峡两岸的 Room 中听到有人在论证,在开始传播的时候通过地名加上病毒名,简单易懂,但是在全球达成共识之后,更名为 COVID-19,这个时候为了统一最后的结论就应该沿用正式的命名。但与此同时,在这个共同体内的成员,就不能再称呼现在以及未来新诞生的病毒的名字为地名加病毒名。因为讨论的结果是,当我们给病毒命名的时候,尽管过去我们都犯过错误,但是现在以及未来,共识是:

  • 不再针对个别的宗教(中东呼吸道综合征)
  • 不再针对特定的群体(武汉肺炎、西班牙大流感)
  • 不再制造不合理的旅游、商务和贸易屏障
  • 以及触发不必要的动物宰杀(猪流感)

对于这样的讨论或许我们一方面需要反思自己,难道不是大陆在描述日本人的时候称为鬼子,称韩国人为棒子的时候就已经犯下错误。而现在即使对岸再去说武汉肺炎其实也无可厚非,我在上面提及的 WHO,并没有让台湾加入。所以这一份协议,台湾并没有参加。这获取是另外一个深入的问题,那就是一份国际协议如何签署,或者国际联盟应该如何相处的问题了。

[[波普尔]] 在 [[通过知识获得解放]] 的 [[社会科学的逻辑]] 一章中提到的那样,我们的[[知识]]是建立在暂时性和尝试性解决办法之上的,而证明其为真的唯一方式就是其本身仅仅是暂时的,换一句话说就是我们尝试的解决办法可以经得住我们最尖锐的批评。而找到这样的尝试性解决办法就是我们讨论的目的。

有人或许要说达成大多数人认可的结论未必有可行,现实可能确实确实比较困难,想要叫醒同一个时代沉睡的人的尝试多少人都曾经试过,但都几乎没有用,但我总是相信,只要有人不停地记录,描述,呼喊,总有一天,真理会出现。

有效的讨论一定是相互增进了解的

「倾听」和「表达」是相互的,尤其是在讨论的过程中,不仅是对其人的事实增进了解,也是对其想法,观点的了解。文字当然也能充当一部分了解的渠道,但是通过讨论,透过语音语调能够更进一步的他是如何思考的。

如何进行有效的讨论

讨论双方保持谦逊和尊重

讨论的前提是,讨论双方相互保持一点谦逊,双方都要了解到自己的认知和观点可能是错误的,才能听取对方反对的意见。

[[密尔]]早在几百年前就提过关于公共讨论的道德:

  • 辩论的双方,不管站在哪一方,只要讨论中缺乏坦诚,或表现出不宽容和固执,都需要予以谴责
  • 但是不能从一个人所选定的立场来推断其个人的恶行
  • 而且无论这个人持有什么样的观点,只要能够冷静地观察,诚实地表述他反对者及其观点究竟是什么,既不夸大,也不掩藏,那就应该予以这样的人尊重

就像 [[洛克]]、[[波普尔]]等哲学家对世界的认识一样,我们无法保证我们当前的认识就一定是真的,所以我们要在现阶段讨论,以及充分、有效地讨论,经过讨论,错误的意见和行为才会逐渐服从事实和论证,一个聪明人获得智慧的途径就是聆听各种不同的意见。

得出暂时性的解决办法后再将注意力转移到其他事务

在什么是有效的讨论中,论述了一个有效讨论需要一个暂时性的解决方案,如果当一个事件并没有得出暂时性的解决方案,我们的注意力就被转移到另外的地方,那么就陷入了当前社交媒体的陷阱。现在的社交媒体,「流」的显示形式和用户的参与方式,使得用户的注意力不断地从一个事件飞向另外一个事件。

这样的方式像极了司法审判,不管这个判决如何撕裂社会,不管这个判决是否会遭受到大众的攻击,也要给这样的按键定一下一个先例,定一下一个当前最合适的方案。

[[马克思 韦伯]]

Clubhouse 如何

Clubhouse 是什么

Clubhouse 是什么,官方的解释是 new type of social network based on voice。这边就能看到两个重要的关键字 social network 和 voice,一个是社交网络,一个是声音。社交网络想必想必都非常熟悉,但是如果要去定义社交网络的话,也还是一件比较复杂的事,借用维基百科的解释,社交网络就是一个由独立个人或组织组成的关系网络,这样的社会网络会根据血缘、爱好,友谊,价值观等等因素连接起来。这样的网络结构一般是比较复杂的。

当我们解析完社交网络就会发现当生活在社会中的我们通过这样的方式连接起来之后,并借助这些年互联网的发展,提供给了我们非常多的工具来沟通,有文字的(Facebook,Twitter),重在图片的(Instagram),当然还有基于短视频的(抖音),而现在又多了一个声音。

这两年关于声音尤其是播客的创业明显地多了起来,从播客制作工具,到托管平台,再到各家大厂不断的收购播客相关内容可以看到越来越多的人开始关注到声音。声音从广播开始,到有声电影,曾经有一段时间被视频的光芒所掩盖了。声音总是伴随着视频一同出现,以至于我们曾经忘了还有这样一种信息传播的媒介。

但不管是广播,还是演讲,或是播客,都是单方向的传播,而 Clubhouse 的出现使得这样的传播方式发生了转变,虽然可以预料到是交流的过程中会混入不同的声音,但是在交流的过程中必然会产生新的观点。这或许才是这个应用最有价值的地方。

Clubhouse 中有三种类型的 Room :

  • Open
  • Social
  • Closed

其中 Open 和 Closed 自不必说,Social 类型的房间会开放给你追踪的人。这里看得出来 Clubhouse 还是面对的熟人社交,因为只有熟人才会进我们自己的房间。

但仔细的再思考这三种类型的 Room,Open 的房间可以应对到现实中公开的演讲,而 Closed 房间可以对应到熟人之间的聚会,而 Social 则可以对应到一定程度上私密的沙龙。

Clubhouse 吸引我的地方

  • 听名人的对话和分享,虽然当今世界已经了有了足够多的资料去了解一个人,但我对实时直播的对话依然有足够兴趣,毕竟这样的机会并不会很多
  • 对不确定主题的新鲜感,对全世界不同地方的人的好奇,在初到 Clubhouse 的时候我钻进了不同的房间,听各种各样的主题
  • 学习语言的好地方,用过一段时间之后会发现,Clubhouse 给了语言学习者一个极好的学习机会,因为在这这里不能发文字,不能发图片,只能使用语音,那就天然的适合学习外语

我所认为的 Clubhouse 的问题

  • 对话的质量无法保障,我们都知道播客的信息含量肯定不如图书,而 Clubhouse 的信息含量可能连播客也比不上。但这就使得我不再去关注对话本身,使得我去追踪个人。
  • 不能被检索的信息,聊天的内容并不能在 Clubhouse 上留下来,这也就导致大量的信息都会随着房间的消失而消失。除非花费大量的时间在上面,否则平台不会对新用户产生任何价值,也形成不了一个价值闭环。

最后欢迎大家搜索 @einverne 来找我聊天。


2021-02-06 discussion , locke , clubhouse , talk , podcast , voice , sound

使用 Beancount 记账篇零:Beancount 入门使用

说起 Beancount,就不得不提复式记账,在之前的文章里面已经完整的叙述过复式记账是比单式记帐更加科学的记账方法,但是复式记账在目前只被大多数企业所采用,并没有被大众所接受,市面上也依然缺少复式记账的工具。而 Beancount 就是其中比较好用的一个工具。

为什么要用 Beancount 记账

为什么要用 Beancount 记账? 要回答这个问题需要从两个方面说起,一方面是为什么要记账,另一方面是在这么多的记账软件中为什么要用 Beancount。

首先回答为什么要记账,在之前的文章中也提到过,通过记账是认识自己的一种方式,通过周期性的记账可以更好的理清自己的财务状况,可以对自己的[[资产损益表]]、[[资产负债表]]情况一目了然。尤其是当自己的收入一部分在银行,一部分在支付宝,一部分在微信,还有一部分在股市的时候,就很难具体地回答出自己到底有多少资产。并且如果不有意识地记录自己的每个月的开销,那么对自己的支出也可能非常模糊。通过记账不仅可以加深对自己的财务的了解,也可以根据支出的数据针对性的进行优化。就像启蒙我使用 Beancount 的 byvoid 的文章 中提到的那样,如果要达到财务自由,需要达到三点要求,对支出的预期,对资产和收入的了解,和对寿命的期望。而记账可以解决前两点。

再考虑一下第二个问题,相比较于其他的复式记账工具,为什么要选择 Beancount,回答这个问题之前,我就要先拿出我自己一贯的选择软件或者工具的准则,第一开源优先,第二跨平台,第三数据可以导出或自行管理。并且因为私人的财务数据是非常重要的个人隐私,我不相信任何托管数据的商业机构的软件。所以按照我的准则,我去了解支持复式记账的工具,有如下的选择:

  • 开源并且跨平台的 GnuCash
  • John Wiegley 的 Ledger,C++ 编写,基于命令行的复式记账工具
  • hledger 使用 Haskell 重新编写的 Ledger CLI
  • Beancount 纯文本,命令行,Python 编写,源自 Ledger

除开第一个 GnuCash 下面三个都是纯文本的记账工具,纯文本工具带来的好处便是,可以将这个系统放入到版本控制,比如 Git 中,也可以将数据同步到其他平台。并且只要有一套渲染工具就可以提供非常详细的报表数据。Beancount 提供了 fava 这样基于 Web 的展示工具。plaintextaccounting 这个网站提供了更加详细的对比,对于这些纯文本的工具,只有自己掌握数据,那么从一个工具迁移到另一个工具的成本也不会很高。

我选择 Beancount 的理由便是,Beancount 足够简单,但又有丰富的扩展性,就像作者自己说的 那样,简化了 Ledger 中的概念,并且通过自己的实践重新定义了 Beancount 的能力。

什么是 Beancount

经过上面这么多说明,Beancount 是什么就不需要多说了,需要记住的就是纯文本,复式记账工具,这两个重要的特性了。

Beancount 其他重要的特性:

  • Python 编写可以直接运行在本地
  • Beancount 提供自定义的货币单位,可以实现虚拟货币,证券交易等等场景,甚至可以将年假以天的方式记录到账簿
  • 凭借 fava 提供了丰富的查询功能
  • 可以利用 SQL 进行更加复杂的统计
  • 可以通过脚本快速导入微信,支付宝,信用卡等账单

基础使用

在交易记录中,会使用 +- 来表示资金的流动。一般来说:

  • Assets 资产账户,正数表示资金增加,负数表示资金减少
  • Income 收入账户,一般使用 - 负数表示
  • Expense 支出账户使用 +, 表示支出增加
  • Liabilities 负债账户,- 表示借款,负债增加,+ 表示还款,负债减少

每一笔交易都是资金在这样四个基础账户中流转。

Beancount 定义了一些基本的语法规则,用户需要按照这样的规则对自己的交易进行记录。

定义使用的货币

option "operating_currency" "CNY" ; 帐本货币
option "operating_currency" "USD"

或者等熟悉了基本使用之后,可以用 commodity 来自定义货币。

1990-01-01 commodity BTC
  name: "Bitcoin"

使用 openclose 来开通或关闭账户,在 Beancount 中作者将顶级的账户限制为了五类,Assets,Income, Expense, Liabilities, Equity。暂且可以按照字面去了解其具体作用,之后会再写一篇文章来讲述如何对这五类账户进行命名。

比如 2016年1月1日,开通了一个招行借记卡

2010-11-11 open Assets:DebitCard:CMB CNY
  name: "招商银行借记卡"
  
2010-01-01 open Income:Salary:Company CNY

开户的语法:

;开户,支持unicode, yyyy-MM-dd 表示开户时间
yyyy-MM-dd open 账户类型:命名:命名区别 货币[,货币2]  

2016年1月2日,收到第一笔工资,那么就是收入账户到资产账户的流转,钱从收入账户 Income:Salary:Company 中流转到刚开通的招行 Assets:DebitCard:CMB

2016-01-02 * "Income"
  Income:Salary:Company -1234 CNY
  Assets:DebitCard:CMB

这里需要注意的是收入一般使用 - 来表示。

在 2020年销户了

2020-01-01 close Assets:DebitCard:CMB

记录交易,比如 2021年1月1日,使用招行的信用卡买了 40 元的咖啡。这个40 元被分别记录到两个账户中。

2010-01-01 open Expenses:Drink:Coffee
2010-01-01 open Liabilities:CreditCard:CMB

2021-01-01 * "收付款方:某某咖啡店" "备注:Coffee"
  Expenses:Drink:Coffee        +40.00 CNY
  Liabilities:CreditCard:CMB

如果一笔交易只涉及到两个账户,根据正负平衡原则,第二个账户后面的 -40.00 CNY 可以省略。

交易的基本的语法可以简记为:

[yyyy-MM-dd] [*|!] "payee" "备注"
  [account1]          +[num] [currency-unit]
  [account2]          (-[num] [currency-unit])

在日期后面有一个标识符,flag,用来标记交易的状态:

  • * 完成的交易,确切的知道交易额
  • ! 未完成的交易,需要确认或修改交易额

记住这个公式:

 (Assets + Expenses) + (Liabilities + Income) + Equity = 0

这样就已经了解了 Beancount 的基本使用,先迈进第一步,后面再慢慢了解 Beancount 的货币转换,断言,账户平衡等等特性。

Beancount 账户概念

在 Beancount 中每一笔交易都会被划进不同的账户中。

这里只对账户进行简单的介绍,之后会在展开。

Beancount 中的五类根账号:

  • Assets 资产账户,可以用来记录现金,银行卡余额,证券账户余额等等
  • Liabilities 负债,比如信用卡,房贷账户,车贷账户等等
  • Income,收入账户,比如工资账户,其他收入账户等等
  • Expense,开支账户,比如房租,日常用品,数码产品等等
  • Equity,权益账户,一般不直接使用,Beancount 中一般用来平衡其他账户,比如初始化 Beancount 的使用

在 Beancount 中给账户命名,一般使用冒号来间隔,比如要记录一个外出打车的开支,可以命名成:

2010-11-11 open Expenses:Transport:Taxi

同一分类下,还可以定义:

2010-11-11 open Expenses:Transport:Public
2010-11-11 open Expenses:Transport:Taxi
2010-11-11 open Expenses:Transport:Bike

范围由粗略到详细,这样之后在 fava 中通过界面可以一层层通过统计得出,在出行方面的开支。

Beancount 记录交易

在了解基本的 Beancount 之后,可以再举一些经常使用的例子。

收入

这里需要注意的是 Beancount 中,收入账户一般使用 - 来记录。

2020-02-01 * "北京某有限公司" "工资"
  Income:Salary           -5000 CNY
  Expenses:Endowment      +1000 CNY; 养老保险
  Expenses:Unemployment     +30 CNY; 失业保险
  Expenses:Medical         +300 CNY; 医疗保险
  Expenses:Taxes           +100 CNY; 个人所得税
  Income:HousingFund       -500 CNY; 公司额外支付的住房公积金
  Assets:HousingFund      +1000 CNY; 住房公积金
  Assets:DebitCard:CMB    +3070 CNY; 招商银行工资卡

消费

2020-02-29 * "超市" "食材 牛奶"
  Liabilities:CreditCard:BOC     -90 CNY; 交通银行信用卡
  Expenses:Food:Ingredients      +40 CNY; 食材
  Expenses:Food:Drinks           +50 CNY; 饮品

信用卡还款

2021-01-05 * "信用卡还款"
  Assets:DebitCard:CMB           -100 CNY
  Liabilities:CreditCard:BOCOM   +100 CNY

垫付

2019-10-12 * "合租交燃气费用"
  Expenses:House:Gas         +200 CNY
  Liabilities:CreditCard:BOC -200 CNY
  Assets:WeChatPay         +150 CNY; 发回来的红包

初始化设置

使用 pad 来初始化账户。如果一开始的时候账户中本身有一些数据,可以使用 pad 来初始化账户。

比如在开始使用 Beancount 的时候银行卡中有 20000 人民币余额,那么就可以定义为:

2019-01-01 pad Assets:DebitCard:CMB Equity:Opening-Balances
2019-01-02 balance Assets:DebitCard:CMB          20000.00 CNY

Beancount 生成报表

Beancount 可以配合 fava 一起使用,使用 pip install beancount fava,然后执行:

fava main.bean

fava 就会根据你在 main.bean 文件中定义的内容渲染一个网页端。官网提供了一个简单的例子。

在这个界面上可以看到 Income Statement [[资产损益表]], Balance Sheet [[资产损益表]],Trail Balance [[试算表]],Journal 日记帐等等功能。

reference


2021-02-02 beancount , accounting , double-entry , bookkeeping , ledger

解决 NoSuchMethodException 错误的方法

问题的出现

在使用 Java Instrumentation API 的时候,因为在应用启动的时候加载了一个 Java Agent,然后在 Java Agent 中依赖的包,和应用内依赖的包产生了冲突,同时使用了 commons.lang3 这个包,但是依赖的版本不一致。导致使用 FieldUtils 的时候出现了 NoSuchMethodError:

Caused by: java.lang.NoSuchMethodError: org.apache.commons.lang3.reflect.FieldUtils.getFieldsWithAnnotatio
n(Ljava/lang/Class;Ljava/lang/Class;)[Ljava/lang/reflect/Field;
        at com.opencsv.bean.AbstractMappingStrategy.loadRecursiveClasses(AbstractMappingStrategy.java:498)
        at com.opencsv.bean.AbstractMappingStrategy.loadFieldMap(AbstractMappingStrategy.java:440)
        at com.opencsv.bean.AbstractMappingStrategy.setType(AbstractMappingStrategy.java:363)
        at com.opencsv.bean.util.OpencsvUtils.determineMappingStrategy(OpencsvUtils.java:79)
        at com.opencsv.bean.CsvToBeanBuilder.build(CsvToBeanBuilder.java:234)

NoSuchMethodError 错误出现的根本原因

NoSuchMethodError 错误出现的根本原因是应用程序直接或间接依赖了同一个类的多个版本,并且在运行时因为版本不一致,其中依赖的版本缺少方法而导致的。编译时和运行时类路径不一致。

基于上面具体的问题,在排查应用内的错误的时候,完全没有发现包冲突的情况,但加上了 Agent 就出错。

同一个 Class 出现不同版本的原因

  • JDK 版本不一致
  • SNAPSHOT 版本不一致
  • Maven 依赖作用域为 provided [[Maven scope 作用域]]
  • 同一个 jar 包出现多个版本
  • 同一个 Class 出现在不同的 Jar 中

哪个版本的 Class 会被执行

  • [[202010141045-Maven 依赖仲裁机制]]
  • [[JVM 类加载机制]] 决定了 Class 被加载到 JVM 的优先级

如何解决 NoSuchMethodError 错误

  • 定位异常 Class 的全限定类名和调用方,堆栈日志
  • 定位异常 Class 来源,可以通过 [[Arthas]] 等在线诊断工具反编译,使用 jad com.xxx.ClassName 来获取该类运行时的源码,ClassLoader,Jar 包位置等信息
    • 如果程序启动失败,或无法在线诊断,可以考虑添加 JVM 启动参数 -verbose:class-XX:+TraceClassLoading ,在日志中输出每一个类的加载信息
  • 根据 ClassLoader 和 Jar 包全路径名,判断类加载、Maven 仲裁或其他原因
    • 如果是 Jar 包多版本问题,可以指定需要的版本,或移除间接依赖中的低版本,使用 mvn dependency:tree 查看
    • 如果是同一个 Class 出现在不同 Jar 包中,如果可以排除,就排除依赖,如果不能排除,可以考虑升级或替换包

reference

  • [[Java 常见问题]]

2021-01-27 java , jdk , jvm , methodology

我的笔记法(借助 Zettelkasten 和 Obsidian)

在上次总结了2020读书笔记 之后,Tai 问我如何通过 Zettelkasten 和 Obsidian 来实践我的笔记。这里就也正好总结一下我自己的方法,希望可以在分享过程,或者和大家的讨论中来获取更多有效率方法。

我是如何来记笔记的?或者更具体一些,如何来记读书笔记的。就像是 How to read a book 中所说那样,不同类型的书有不同的阅读方式。其实笔记也一样,针对的内容不同,记笔记的方式也不尽相同。

我是如何做读书笔记的

快速开始

每当我拿起一本新的书,我通常会去豆瓣图书看一下这本书的相关介绍,然后创建一个新的笔记,将作者等等信息,在笔记头部 meta data 部分记录一下。

source:
category:
tag: 
time:  

Zettelkasten 卡片的第一个准则,就是一条笔记只记录一个想法。

所以在完成这本书的 meta data 之后,我会给这个笔记打上一些分类,比如读书笔记,Reading-2020,Reading-2020Q4 这样的分类,这样以后我直接去这些单独的分类就能一下看到关联的书,也能快速知道比如在 Reading-2020Q4 这个季度看过的书了。

过程中

一旦读书的过程中产生新的想法,有可能是因为书中所涉及的观点,将很久以前想表达的东西说了出来,或者是书中描述的内容和我自己的切身经历,或者和已有的想法有关联,我会立即使用 ⌘+⇧+N 创建一个新的 Zettelkasten 模板文档,这个文档的标题是当下的想法,然后 source,连接到之前创建的书的笔记。

这个时候我不会花费很多的时间来记笔记,而是专注在书上。一旦完成笔记就立即转到书的文本中。

整理

当完成一本书之后,在笔记中进入该书的笔记,会有一连串连接到该笔记的想法,这个时候就是结合这些想法和整本书的结构,快速的整理出这本书作者在讲述什么。用自己的语言,将其整理一下。这个时候才会知道上学的时候总结中心思想的真正含义是什么。如果我能够用我自己的语言组织出来,才能算是真正意义上读过这一本书。

当整理出整本书在讲述的内容之后,然后在去看关联的想法笔记,对这些笔记做更进一步的解释,如果有相关联的笔记,通过连接关联起来。

书籍还有一个比较重要的便是阅读过程中的标注或者是高亮部分,我个人因为不是固定使用一个设备来阅读,所以有可能:

  • 有一部分笔记在 Moon+ Reader Pro 中
  • 微信读书
  • Kindle App 和设备的 clippings 中
  • 还有一部分在 Boox Note 电子书

针对不同的格式和媒介,相应个管理方式也不太一样,Moon+ Reader 和微信读书都可以在 Android 应用上导出纯文本的高亮,我直接分享到 Markor 生成一个新的笔记,放到同步目录即可。

而 Kindle 上的高亮部分通常是间隔一段时间导出,然后通过 kindle-notes 项目整理成一个网页

而大部分的 PDF ,都是通过 Boox 来阅读了,影印版的 PDF 的高亮部分不是很容易导出,所以只能先存放在设备中了。

专业知识笔记

对于专业领域的笔记,我更加关心的是这一个技术栈,所以一般我会以一个 Zettelkasten 的中间层笔记开始,新建一个 「XXX 知识点」的笔记,这样以后每一次我有新的技术相关的笔记,我可以在分类上直接连接到这个「知识点」的笔记上。等之后周期性的梳理 XXX 知识点的时候,我就可以看到连接到这个知识点的其他分散的笔记在什么地方。

另外一种方式便是当看一本相关的书籍的时候会有一系列的概念和知识,这个时候我会在「XXX知识点」这个文档中通过 Obsidian 提供的 [[]] 语法提前梳理好我有疑惑,并且需要单独研究的条目,当独到这些专题的时候,扩充这些子主题。

人文知识笔记

在人文社科类的读书笔记中,我更关心的是如何去解释我看到的名词,或者说概念,比如说什么是 [[民族主义]],什么是 [[极权主义]],另一个关心的点是书的作者,这可能是一个个人的习惯,我看书常常会是盯着一个作者的书看,从小学时候在图书馆把 Jules Verne 的书一本一本翻过来,到之后看金庸,东野圭吾,在到看福山,哈耶克,卢梭,只要这位作者有一本书让我觉得不错,我就会去看他其他的作品。

人文社科的图书往往是会形成新的认知,不像是专业类的书籍,会有很多固定,需要记忆的,一本好的社科图书会带领读者进行思考,很多书往往是通篇在解释一个概念。

记得大学唯一一门哲学课,老师强调了一学期的「下定义」,当我们谈论一个东西的时候,要首先知道这个东西是什么。

以[[极权主义]] 为力,我从不同的书中,看到不同的作者对其的描述。

  • 在 [[201912211716-艾希曼在耶路撒冷]] 中,[[汉娜阿伦特]] 说极权主义是,「把个人变成职能行使者和统治机器上的齿轮,将人非人格化处理的制度」
  • 在 [[极权主义的起源]] 一书中,[[汉娜阿伦特]] 更进一步归纳为「极权主义就是将世界上的所有界限抹平,不考虑人的多元性,将人认为是集体中的一员来对待。」
  • 而在 [[历史的终结与最后的人]] 一书中,[[弗朗西斯·福山]] 将近现代国家发展出来的一种有着史无前例的权力的中央制度称之为极权主义。

而随着阅读相关的书籍,会产生越来越多的关于什么是极权主义的解释,也可以更进一步的让我去解释。

而同样的,在这个笔记下,又会产生其他许多的主题,比如极权主义下的法律制度,教育,治安等等话题。这样随着阅读量的增多,通过笔记和笔记之间的相互关联会使得心中的那个概念越来越熟悉。

我是如何使用 Zettelkasten 和 Obsidian 来实施我的笔记的?

上面说了那么多,其实涉及到的方法大多来自于 Zettelkasten

  • 主题明确,并且能够被理解的单一笔记
  • 以及笔记与笔记之间的关联

当学会以这样一个方式来记笔记之后,就不必在拘泥于工具,甚至可以在现有工具的基础之上,或者自己重新构建一套自己的工具。而在此之前最要的就是理解这个方法的精髓,以及这样的思维方式能带来什么样的变化和提升。

而目前我使用最顺手的就是 Obsidian。

借助模板之力

Obsidian 的 core plugin 就支持 Zettelkasten prefixer,然后我绑定了快捷键,⌘+Shift+N,就是创建一则 Zettel 笔记,而普通的 ⌘+N 就是普通的笔记。

我的模板现在比较简单:

source:
category:
tag: 
time:  

说明:

  • 这则笔记的来源,有时候是图书,有时候是 URL
  • 笔记的分类,通常用 [[]] 来关联
  • 笔记的标签,使用 #
  • 最后是笔记创建的时间

另外一个模板功能,就是当我使用 ⌘+⇧+I 的时候,会弹出我之前设定的模板文件夹中的模板让我选择,直接插入到当前的文件中。

设定一些常用的模板,比如图书的模板,我会加上 author 等等其他的 metadata。

随时随地

Zettelkasten 另外一个核心的观点就是,所有的笔记都在一起,可以一起被搜索,一笔被修改。这样就使得我寻找一个跨平台同步的解决方案,具体可以见这篇文章

电脑虽然在白天随时可以访问到,但是手机还是更经常被用到。所以我使用 Markor 来随时记录。任何想法第一时间内记录下来。

连接的重要性

时常回顾自己的笔记,Zettelkasten 方法实际要求当记下每一个笔记的时候,都要考虑当前的笔记和之前历史的笔记的关联,但是大部分情况下我并没有完全按照 Zettelkasten 的方法执行,我会定期,以及以随机的方式来访问一个笔记,然后阅读该笔记,建立这个笔记的关联。

经过上面有意识的创建和整理笔记之后,打开 Obsidian 的 Graph 可以看到的是,笔记会因为连接形成几个聚合的中心,几个中心我有意识的就直接沿用了我博客的几个分类。然后通过这些中心的节点我又能知道我关注的重点是什么来进一步的完善我的笔记。

总结

之前的文章也提到过,这两年来我越来越意识到我的问题并不是看得东西不够多,而是往往不能理解我所看过的东西。一方面来随着时间的推移会忘记,一方面当阅读的时候无法理解所看到的东西时,记忆也就没有那么深刻了。所以我之后的目标之一便是我要能理解我写下的东西。


2021-01-03 obsidian , zettelkasten , method , note , note-taking

迟到的「给编程初学者的一封信」

这些天翻箱倒柜,翻出来一些大学时候的文档,其中一篇是当时上外教课时打印给我们的材料,虽然可以看得到当时也在上面做过笔记,但现在已经完全不记得有这样一份文档的存在了。但回过头再看文档的内容,每一句话都是非常珍贵的建议,是一份那个时期完全需要读一下的材料,但当时却并没有好好珍惜。这份文档的名字叫做「An open letter to those who want to start programming」,如果记得没错的话这份文档交到我手上的时候,应该就是我刚去学习如何编程的时候。如果当时就能够理解这一份文档内容的话,这些年来我肯定能少走不少的弯路。

在结合到最近陆陆续续看过关于认知的一些书,才发现我自身的问题并不是在于看得东西不够多,而是没有完全理解我曾经看过的东西。就如这一份文档那样,现在的时间来看文档上列举的内容都是当下非常好的建议,然而当时的我并不理解,所以自然而然就忘记了这一份文档上的建议。

先来总结一下这一份文档中作者给出来的几个建议:

  • starting creating something just for fun. 你需要毫不犹豫的开始做一些事情,而不是纠结于先开始学习,或者设置编辑器。
  • Initially, screw the algorithms and data structures. 开始的时候不要在意算法和数据结构。当然作者并不是说算法和数据结构不重要,而是在起初的时候,不要在意算法和数据结构的细节,而是在学习和尝试的过程之中体会它们的作用,记住算法和数据结构的名字,当真正要用到的时候深入了解,并切身体会它们的具体应用场景。当你真正需要他们的时候,可以用自己的熟悉的语言实现。
  • Choose a good language. 选择一门你觉得可以在短时间内通过它生产出内容的语言。当完成一个任务并看到产出才是激励继续的动力。
    • 不要选择那种需要笨重的 IDE 才能运行的语言,迅速的产生成果才是唯一的目标
  • Choose a good editor, 编辑器之于程序员就相当于弓之于弓箭手。
    • Vim,许多 Linux 发行版的默认编辑器,虽然入门和学习曲线比较陡峭,但是是一个学习了终身收益的工具
    • Emacs,同样有着陡峭的学习曲线,但同样强大
  • Use an operating system that’ll teach you something,选择一个可以学习到的操作系统。目前主流的桌面操作系统也只有 Windows,Linux 和 macOS,建议你选择一个合适的 Linux 发行版,作者的观点是 Windows 不会教你任何事情,但是使用 Linux 你能收获更多。我曾经花费了一段时间将全部的资料和应用切换到 Linux Mint,我也使用这个发行版大约 6 年左右了,虽然确确实实会遇到一些问题,但正是解决这些问题的过程,让我从中学习到了很多东西,比如 Linux的启动过程Linux 下开机启动应用脚本,以及关于磁盘的配置网络的配置 等等。
  • Don’t copy-paste files to backup stuff. 作者在这边推荐了 Git,而当年我们在学校学习的还是 SVN,真正将 Git 运用到方方面面我也是这些年来才真正实施的,以前只是拿来作为代码的版本管理,而之后我用 Git 来管理任何可见的文本,比如博客,比如笔记,比如文本配置。再结合 git worktreegit subtree 等等的功能,可以在任何一台电脑上迅速恢复我的工作环境。
  • Know where to get help. 知道如何寻求帮助,社群,StackOverflow,IRC,都是可以获取帮助的渠道,而对于我真正学会使用 StackOverflow 则是要到好几年之后独自学习 Cocos-2x 的时候,因为参考资料少,官方文档也不全面,StackOverflow 帮助了很多,那个时候我才理解到互联网的互帮互助是以这样的方式来实现的,那以后也曾经花了一段时间去积极回答别人的问题。
  • Develop your netiquette. 遵守网络礼仪,学会如何提问,好好地阅读一下提问的哲学对我来说又是在读完这篇文档之后好几年才真正理解的。
  • Meet people, because books only teach you routine stuff. 你不是这个领域唯一的程序员,交一些朋友和他们一切完成一些事情,你可以学到比图书更多的东西。这些年看技术书籍除非一些比较基础的算法大部分的书籍都会在出版之后不久便过时,但是 People 会随着时间改变。
  • Writing open source code. 编写开源代码是一项回馈,甚至可以说是一项慈善。如果代码有用,别人回来使用或者修正你的代码。你也可以通过其他人添加的代码和提交的修改建议来学习并巩固你的编程技能。为开源项目编写代码不需要一个巨大的项目,你可以从最小的代码开始,比如一段下载 YouTube 视频的代码。当我看到这一段代码的时候,正好发生了 GitHub 下架 youtube-dl 项目,之后经过复杂的程序又恢复的事件,原始作者也正好出现来讲述了 youtube-dl 这个项目诞生的背景。[[202011032314-GitHub-take-down-youtube-dl]]

文中的内容大部分内容都在我之后对编程这个领域进一步的认识之后,陆陆续续才发现这每一条建议的可贵之处。我不知道是不是每个专业都会有这样一封写给初学者的信,但无疑一个专业领域前辈所写的内容对后来者的启发意义都是巨大的。

附录

An open letter to those who want to start programming

First off, welcome to the fraternity. There aren’t too many people who want to create stuff and solve problems. You are a hacker. You are one of those who wants to do something interesting.

“When you don’t create things, you become defined by your tastes rather than ability.”

– WhyTheLuckyStiff

Take the words below with a pinch of salt. All these come from me – a bag-and-tag programmer. I love to get things working, rather than sit at something and over-optimize it.

Start creating something just for fun. That’s a great start! There’s no way you will start if you say you “need to learn before doing”. Everybody’s got to start somewhere. Fire up your editor and start writing code.

Here’s something important which people might call bad advice, but I’m sure you’ll stand by me when I’m finished saying why. Initially, screw the algorithms and data structures. They do not have generic use-cases in most simple applications. You can learn them later when you need them. Over a period of time, you’ll know what to apply in situations. Knowing their names and what they do would suffice to be able to pick some paper, dust it and implement it. And that is… if no library (other programmers’ re-usable code) is available, to do it in the programming language of your choice.

Choose a good language. One that you think you can produce something useful in short time.

So let C not be your first language. That might give you the satisfaction of doing things the really old-n-geeky way. C was the solution to the problem Assembly Language was. It offers better syntactic sugar than it’s prominent predecessor – Assemble Language. But today, C (or C++) is not a language that you can produce something very quickly. I would suggest that you use a dynamic language – I won’t sideline any options. Choose a language whose syntax (and documentation) you think you might be comfortable with. For this, you might want to spend some time trying out different languages for a few hours. The purpose of choosing such a language is not to make you feel better and that programming is easy. Completing stuff faster and being able to see the output keeps you motivated. Don’t choose a language that requires a special heavy-weight IDE (tool that helps you write code and run it) to program better in the language. All you should need is a text editor.

Choose a good editor.

An editor is to a programmer, like how a bow is to an archer. Here are some editors to get started with…

  • SublimeText 2 – recommended if you are just starting.
  • Emacs – huge learning curve. Complex key shortcuts. And to be able to customize it, you’ll need to learn Emacs Lisp.
  • Vim – used by many for it’s simplicity and the fact that it comes with linux distros by default. I used Emacs for 2yrs and then switched to Vim to run away from emacs’s complex key strokes and when my little finger on both hands started hurting. Knowing vim keystrokes is a must. When you work remotely and try to type out code on some server from your computer, you’ll know that the only editor available from the command line without any installs, is Vim.

Watchout! Emacs and Vim might be really old. But they both have some features which even most modern editors don’t have.

Use an operating system that’ll teach you something.

Windows won’t teach you anything. The only thing you learn using Windows is to click the .exe file to install the software and use it. It may seem cool in the beginning, but in the long run when you have to deploy applications, especially if you are aspiring to be a web developer, you’ll need atleast basic knowledge of linux. Linux also allows you to customize stuff the way you need them to be. Macs are cool too, but I assume that you cannot afford one of those now.

Don’t copy-paste files to backup stuff.

It’s usual among amateur programmers to copy-paste files to some temporary directory in order to backup them. That’s the only way they seem to know. Stop that! Use a version control software. I strongly suggest Git, since it’s popular and easy to use. It has nice community and resources to support new-comers. (Apart from Git, There’s mercurial, darcs, fossil, etc. But just start with Git. I’m not going to bother you with the reasons for suggesting Git).

Know where to get help.

Join a community that you can relate to (with the tools you use). StackOverflow is Facebook for programmers. There are no status messages and comments. Instead there are questions and answers. Also learn to use the IRC. It’s an old form of chatrooms and is now being used by mostly developers to share information and helping each other.

Develop your netiquette.

Know when to ask questions. Most problems you face might have been stumbled upon by others who might have already posted on the internet for answers. Before asking on IRC or any forums, google first (or should I say blekko first) to see if there’s already a solution to your problem. IRC needs patience. Remember people are helping you for free out of goodwill. Sometimes it might take hours, for someone in the chatroom to respond to you. So wait until they do. Besides, be polite. It’s a small world. Karma, good or bad, comes back.

Meet people, because books only teach you routine stuff (oh and the “book” is dead they say).

There are some street smarts that you’ll learn when you tinker with stuff or learn from those who do it. Roam, meet people and say hello. You are not the only programmer in your place. Make friends and do stuff with them. If you’ve noticed, when a couple geeks get together, whatever the starting point of the conversation be, it always ends up getting technical. It’s bound to happen. Enjoy it. Programming for a good number of years, I can tell you that I learnt nothing more than what the books and articles said, until I starting meeting people and getting technical with them 6yrs back. So I always say that I’ve been programming for 6yrs, because that’s when I started meeting people and feel I really started to learn.

Write opensource code.

Writing opensource code is giving back. It’s much more than charity. You are leaving code that others can use and improve on (maybe) for years to come. It also helps you refine your skills when someone else adds to your code or suggests changes. Code that you opensource doesn’t have to be big. It can even be a useful little program that downloads youtube videos. Moreover, you’ll be surprised, that your code will often help you start and have interesting conversations with people.

Lastly, when years pass, return this favour, by writing a similar letter to someone else who asks you for such help. And possibily correct me.

--
For a hacker, by a hacker
Akash Manohar

Source: http://blog.akash.im/an-open-letter-to-those-who-want-to-start


2021-01-02 programming , coding , editor , linux , learning , suggestion , open-letter

2020 读书记录

2020 年注定是会在历史上留下不平凡的一年,年初的疫情到年底问题依然还在,而且在不确定疫苗的情况,在加上英国的病毒变异情况,不清楚到什么时候才是结束。再回头看今年的大事小事,从年初的李文亮事件,到年末的蛋壳,以及阿里被禁止上A股,有些事情发生地太突然,来不及思考,但只有思考,不仅是在事前的还是事后的思考都有其价值。

李文亮事件

李文亮因言获罪,而密尔早在两百年前就曾经说过,即便是荒谬的言论也不得限制,对该言论的讨论过程能进一步证明相反观点的价值。而李文亮事件就是典型的「被压制的言论包含部分的真理」的情况,而正是因为言论的被压制,终究封城是阻止不了病毒的扩散的。而在看美国宪法,以及关于[[宪法第一修正案]]关于言论自由边界的书,能看到为了维护不进行事先审查言论的权利,经过了多少的争论。

而换一个角度来看,来看看一位金融从业者在[[非对称风险 笔记]]中的观点,「持续暴露在小概率风险下,即使爆仓风险的概率小到万分之一,那么在持续、重复的过程中爆仓的概率会越来越大」。相同的观点套用到现实,能禁止一个人说话,能阻止一群人发表观点,但只要危机没有被解决,终究会造成无法挽回的损失。

金融相关

  • [[黑天鹅]],什么叫黑天鹅,[[塔勒布]] 总结了三点,意外性、极端影响、事后的可预测性。塔勒布让我们留意生活中那些未知的和在我们认知中不可能的事物,而不是一直在讨论琐碎的已知的和重复发生的事物。
  • 非对称风险,一书在讲述一个「风险共担」的理念,举一个最简单的例子,以前降落伞的安全程度很低,所以订购商在验货的时候让制造商穿一件从空中跳下来,于是安全系数就提升了。这是最显而易见的风险共担。塔勒布从风险控制,将其理论拓展到经济,商业,社会生活的方方面面。作者提倡将做出决定和承担后果二者相互平衡的机制。
  • 随机漫步的傻瓜,谨小慎微的投资,学会有[[安全边际]]的[[价值投资]]
  • 牛津通识读本:全球经济史,从资本主义诞生开始,讲述全球这个地区的经济发展道路
  • 牛津通识读本:资本主义,这是一本讲述资本主义起源,解释什么是资本主义,以及资本主义在发展的过程中自身的演变的书。

法律

金斯伯格大法官离世后,先是让我认识了这位饱受尊敬的高龄大法官,然后将我带回了最高法院,在最高法院发展的几百年历史中,让我认识到了自由派的浪漫主义者 [[霍姆斯大法官]],也让我了解了未曾当过大法官却深刻影响了最高院的 [[勒尼德·汉德]] 法官,以及到更近代的第一人女性大法官[[奥康纳大法官]],当代的自由派[[苏特大法官]],以及许许多多以前可能听过但不曾有印象的名字,这些躲在背后的大法官们在一件件的案件,以及对这些案件的判决中,形象更加丰满起来。

  • 温柔的正义 : 美国最高法院大法官奥康纳和金斯伯格如何改变世界,这本书主要介绍了最高法院历史上的两位女性大法官的故事。
  • 九人,以人物传记的形式记录了最高法院从1990年到2007年17年间的人事更替、提名过程、立场变迁与判决内幕,内容跨越伯格法院、伦奎斯特法院和罗伯茨法院三个时期。
  • 牛津通识读本:美国总统制,讲述了美国总统制,以及行政分支
  • 牛津通识读本:托克维尔,托克维尔的人物传记
  • 大法官说了算,通过具体的历史事件来记录了最高法院权威性的由来,以及最高法院在这些年来对直播,互联网言论,死刑等等问题的观点
  • 牛津通识读本:法哲学,什么是法律,法律是否能维护权利,保障公平等等问题
  • 美国宪政历程,这是一本非常推荐的书,看了上面这么多书,唯有这一本读起来最舒服,作者[[任东来]]先生也说过这是写给普通人看的科普读物。但任先生通过书中的二十多个案例展现了一部形象的宪法历史。
  • 牛津通识读本:美国政党与选举
  • [[联邦党人文集]],今年二次阅读这一本书,初读的时候,因为没有了解当时的社会环境,也没有对其中例如 [[詹姆斯 麦迪逊]]、[[亚历山大·汉密尔顿]] 有所了解,但今年结合一部音乐剧《汉密尔顿》,又重新加深了对汉密尔顿的认识,以及上面提及的诸多哲学,法律的著作中都在引述这本书中的内容,更进一步认识了这一本书的价值所在。读完这本书还还好奇为什么建国之初的联邦党到如今却消失了,还特意查了一番。

历史

如果说上半年收获最大的作者是 [[塔勒布]] 的话,那么下半年收获最大的作者便是 [[弗朗西斯·福山]],早在去年就看过其[[The Origins of Political Order]],但是碍于当时的认知和环境,实际上并没有完全读懂,今年先读了其之前的著作 [[历史的终结与最后的人]] ,然后再看其更进一步的论述 [[The Origins of Political Order]],才理清了其脉络。

  • [[历史的终结与最后的人]]
  • [[The Origins of Political Order]]
  • 政治秩序与政治衰败

其他

  • 如何阅读一本书,今年年中收获的一本书,以往我都不屑于这一类 How to 的书,但今年重新发现,方法的重要性。How to read a book, How to take smart notes 是今年两本对我影响比较大的书,加上 ObsidianZettelkasten 的大量使用,不仅让我提升了阅读的乐趣也是的我今年的笔记效率大幅度提升。然后再回顾过去的阅读笔记,发现我大量的时间都只花在了 inspectional reading,也就是所谓的粗读中,连基本的分析阅读都未能做到。
  • 论自由,重读论自由,密尔这位自由主义的奠基人,两百多年前的声音在如今依然振聋发聩,「那些被压制的言论可能包含着为社会所需要的部分或全部的真理。即便一个荒谬的信仰也是有价值的,因为进行争论的过程也是有价值的。因为对其进行争论的过程本身即可以检验和进一步证明相反观点的真实性。」
  • 韩剧如何讲故事,很早就在豆瓣上看到的一本书,作者是写个编剧阅读的,而我作为一个门外汉,从侧面看韩国综艺和韩剧这些年的发展,不难看出他们对故事性的追求,他们在发展中进步,在进步中进一步的扩展自己讲故事的能力,韩国在媒体领域里面的创作和创新值得我好好的学习。另外一个让我不由的串起来的便是,[[托克维尔]] 说社会的自由依赖与[[公民自治]],形成大大小小的公民团体谋取利益,而恰恰是在这样一本讲述编剧的故事中,我发现韩国有自己的编剧协会,每一年都会将刚入行的编剧送到这个领域去学习,比如去医院,法院,监狱等等平常人难以进入的场所进行取材,再回想到这些年韩剧中不乏那些描写细腻的医疗剧,法庭辩护,以及监狱生活的剧,一下子就能看到其中的关联。
  • 韩国综艺如何讲故事,Running Man 开启了我对韩国综艺的认识,[[无限挑战]]将我对综艺的认识提升到另外一个境界,我本不看任何形式的综艺,但我发现原来搞笑,甚至有些无厘头的综艺中也能塑造一代人的认识。这又让我想起了去年去首尔,去柜台结帐的时候,老板正在看当时已经停播的无挑选举特辑,一下子就认识到即使做的只是放送局最基础的搞笑综艺,只要能够用心,能够讲好故事,依然能够让最最普通的人感同身受,甚至影响现实世界。如今无挑已经不在,但变成了刘在石一个人的挑战,虽然现在并没有每一期都看,但如果有空闲的时间总会想起。
  • 饱食穷民,一本讲述日本经济的纪实文学,其中描述了盘踞街头的小微贷,无法抑制的消费主义,不断延长的工作时间,人们被改造成了金钱和物质统治下的行尸走肉,深陷其中无法自拔。这个故事像极了今天的中国,小微贷变成了移动互联网各家争夺的地盘,自我启发变成了企业培训,这种网课,而现在广为所知的996,也只不过是日本员工日夜拼命的缩影。
  • [[软技能]]

2020-12-27 reading , book

我的 IntelliJ IDEA Vim 插件配置

IdeaVim 是 IntelliJ IDEA 编辑器下一款模拟 Vim 快捷键的开源插件。

为什么要用 IdeaVim

  • 既充分利用了 IntelliJ 提供的代码补全,重构,代码浏览等等功能,又可以充分利用 Vim 的多模式,以及 Vim 在编辑器中的高效操作
  • 利用 ~/.ideavimrc 来复用 Vim 的工作方式,以及充分利用 Idea 提供的 Action
  • 多平台下沿用一套工作流程,不需要解决因为操作系统不同而产生的快捷键冲突

利用 .ideavimrc 配置 IdeaVim

重新加载 .ideavimrc

如果安装了插件之后,IntelliJ IDEA 在启动时会自动加载 ~/.ideavimrc 这个配置文件,改动该文件后可以使用如下方式手动重新加载:

:source ~/.ideavimrc

或者直接在编辑器中 :e ~/.ideavimrc 然后在右上角的地方会出现重新 Load 的图表,点击即可。

使用案例

打开最近使用的项目

我映射了 leader + o 打开最近项目列表,用来快速的打开项目。

首先创建一个 keymap(用过 Vim 的都知道,可以自定义一个 modifier key,通过这个修饰键可以形成一套新的快捷键组合):

let mapleader = ","
nnoremap <Leader>o :<C-u>action RecentProjectListGroup<CR>

然后使用配置的 leader 快捷键 , + o 就可以快速弹出最近打开项目,使用模糊搜索就可以快速打开新的项目。

在不知道这个方法以前,我都是在 [[Alfred]] 中配置了一个 Workflow 来打开新的项目的。在发现上面这个方法后,发现在 IDE 内通过这个方式打开别的项目,远比 Alfred 中要快。熟悉一段时间之后,甚至可以不用看搜索结果,直接使用逗号加 o 然后快速输入项目的模糊查询的关键字,然后回车。

Go to Declaration

IDEA 自身就提供了非常多的快捷来在代码之间跳转,比如:

  • 跳转到变量,方法,类的定义
  • 跳转到 Super 类
  • 跳转到方法被调用的地方
  • 跳转到实现的地方
  • 跳转到文件
  • 跳转到测试类

等等,在我的工作流里面,为了方便记忆,统一使用 g 作为简记符。比如 gd 表示 go to definition

.ideavimrc 文件中,定义 map xxx :action yyy 表示自定义一个 keymap 调用 IntelliJ 的 action。

nnoremap gd :action GotoDeclaration

这里的 GotoDeclaration 是 IntelliJ 的一个 action,一个 IntelliJ 的 Action 对应着 IntelliJ 的一个功能。上面的定义就表示在 Normal 模式下定义新的 keymap gd,表示的是在 Normal 模式下,按下 gd 就会执行 IDEA 的 action GotoDeclaration

IntelliJ 提供了一系列的 Action 可以使用。

比如我定义了如下的跳转:

" go to somewhere (g in normal mode for goto somewhere)
nnoremap ga :<C-u>action GotoAction<CR>
nnoremap gb :<C-u>action JumpToLastChange<CR>
nnoremap gc :<C-u>action GotoClass<CR>
nnoremap gd :<C-u>action GotoDeclaration<CR>
nnoremap gs :<C-u>action GotoSuperMethod<CR>
nnoremap gi :<C-u>action GotoImplementation<CR>
nnoremap gf :<C-u>action GotoFile<CR>
nnoremap gm :<C-u>action GotoSymbol<CR>
nnoremap gu :<C-u>action ShowUsages<CR>
nnoremap gt :<C-u>action GotoTest<CR>
nnoremap gp :<C-u>action FindInPath<CR>
nnoremap gr :<C-u>action RecentFiles<CR>
nnoremap gh :<C-u>action Back<CR>
nnoremap gl :<C-u>action Forward<CR>

Toggle Actions

我使用 t 加上一个字母作为 Toggle 动作的开始方便记忆。

比如下面的第一条的 ta,表示的就是 Toggle Annotate,在 IDEA 主编辑区域经常看这行代码是谁提交的,那么会使用右击序号空白处,然后选择 Annotate,这个操作可以简化成直接在 Vim 模式的阅读模式下按下 ta

一些其他的定义可以参考:

nnoremap ta :action Annotate<cr>  
nnoremap tb :action ToggleLineBreakpoint<cr>  
nnoremap tm :action ToggleBookmark<cr>  
nnoremap tp :action ActivateProjectToolWindow<CR>

查看 IDEA 支持的 Action

在安装 IdeaVim 之后,可以在 normal 模式下使用如下命令查看 IDE 支持的 action:

:actionlist [pattern]

如果要搜索对应的 action 可以直接加上模糊词来搜索,比如 :actionlist declaration 来搜索相关的内容。

执行 action

:action {name}

比如执行 :action Debug

重新命名 Action

~/.ideavimrc 文件中可以给 Action 其名字,比如

command! Reformat action ReformatCode

在 action 后面的 ReformatCode 是一个合法的 ActionName,通过上面的语句就重新起了一个新的名字叫做 Reformat。这样就可以通过 :Reformat 来调用。

切换标签页

使用空格加 hl 来切换标签页

nnoremap <space>h gT
nnoremap <space>l gt

更多的配置可以参考我的 dotfile 配置。

两个比较有用的快捷键

  • ⌘+F12 ActivateTerminalToolWindow
  • ⌘+⇧+F12 HideAllWindows

Cmd 组合

  • Cmd+a/c/v/x/z
  • Cmd+w 关闭当前的文件
  • Cmd+e 最近的文件
  • Cmd+t Refactor this 重构
  • Cmd+n Generate 快速生成模板代码
  • Cmd+o File Structure 当前文件的文件结构
  • Cmd+b 跳转到定义
  • Cmd+[/]

surround

启用 surround 插件来模拟 surround

set surround

reference

[[常用的 IDEA 插件]]

category: [[IntelliJ IDEA]] [[编程工具]] [[学习笔记]]


2020-12-02 idea , vim , vimrc , config , vim-config , jetbrain , intellij-idea , ide

图片管理工具 Eagle

远在移动互联网还没有那么发达的今天,Google 曾经收购过一家图片管理与分享的网站叫做 Picasa,Picasa 同时提供了一个跨平台的照片管理工具 Picasa Desktop,用这个工具不仅可以非常方便的管理本地的图片文件,也可以非常方便的分享到 Picasa Web 上,然而随着移动互联网的到来,以及 Google 的转型,Picasa 的服务在 Google 变得没有那么重要,随即在 2016 年停止了服务,我的图片管理也被迫迁移到了 Google Photos。然而一切都开始变得不方便,Google Photos 内自动备份的照片,相册开始无法管理,并且 Google 停止了桌面版的开发,同样使得在桌面上管理图片变得困难,这些年来尝试了 Lightroom,TagSpaces 等等工具,都没有找到特别舒心的。

我的需求其实也并不复杂:

  • 管理本地大量的单反照片,添加标签以及其他 meta 信息,可以方便我快速定位、查找,这一点 Lightroom 做的不错,但 Lightroom 有些笨重
  • 集中管理我所有的照片,图片,让我可以快速预览照片
  • 我希望我的图片库可以随时随地可以访问

我带着这一些需求一直在寻求一款合适的工具,直到有一天在 Twitter 上有人有相同的需求时,一则评论吸引了我的注意,打开 Eagle 官网 的同时我就被吸引了,一张软件界面的截图直接了当的说明了这个软件的功能,并且几个关键字,「收集」,「整理」,「搜索』,似乎让我一下子想到了 Picasa。更加了解之后才发现,原来 Eagle 不止图片管理这么简单,音频,字体,GIF 管理等等让我迫不及待地下载进行尝试。 安装后 Eagle 会引导安装浏览器扩展,这个扩展可以用来收藏图片,包括拖拽,Alt+ 右击,右键上下文菜单,甚至可以直接批量一键导入网页图片,或者将整个网页保存为图片,或者剪切部分网页。这部分内容扩展的页面 已经给出了非常详细的说明,这里就略过了。

picasa screenshot

我个人的习惯是每次旅行或外出回来时,会新建一个以日期开头加上地点的文件夹,并导入当前拍摄的照片,然后保证无误后格式化 SD 卡。然后使用 Lightroom 对这个新导入的文件进行一轮的筛选,使用 1~5 快捷键给照片打分,然后对打分的照片进行简单的快速处理。如果有 4 或 5 分的照片,会更进一步微调。然后对有打分的照片进行导出分享。

关于收藏图片

在遇到 Eagle 之前,我接触的大部分图片都是在浏览器中,所以在浏览器中安装了一个叫做 Imagus 的工具,当鼠标悬浮在图片上后会放大缩略图,并且使用 Ctrl+s 就可以直接下载该图片。但这样的问题便是所有的图片都在 Downloads 文件夹下和其他格式的文件混在一起。等到真正需要使用的时候,搜索变得非常不方便。

而有了 Eagle 之后这个工作流程更加简单了,鼠标拖拽图片即可。

字体管理

虽然我不是学设计的,但是大学的时候曾经做过一段时间和字体相关的事情,所以也对字体有一些要求,所以如果阅读器支持更换字体,肯定会换成自己喜欢的方正北魏楷书或方正宋三。曾经下载过很多的字体进行对比,如果当时有 Eagle 就方便很多,直接将字体导入软件就能预览文本,再不用现在文本编辑器中编辑一段对话,然后再挨个更换字体了。

eagle font manage

常用的快捷键

  • ⌘+⇧(Shift)+n 创建文件夹
  • ⌘+t 增加标签
  • ⌘+Alt+x
  • ⌘+j 在不同的文件夹之间切换
  • ⌘+⇧(Shift)+j 将指定图片移动到指定文件夹
  • F 弹出分类对话框,可以快速进行分类

几个独特有有用的功能

  • 按颜色过滤素材

缺点

不管是在 Picasa,还是在 Lightroom 个人的使用习惯是管理工具管理的内容,在磁盘上实际的位置还是原来的位置,不管是编辑了图片或者是移动了图片都是在本地文件中的修改,然而虽然 Eagle 是一个离线可用的图片管理工具,但一旦图片文件夹导入到 Eagle ,再去磁盘中查看时文件的结构就变成了 Eagle 处理过的扁平的样子,并且会冗余两份图片,一份在原来的位置,一份在 Eagle 中,即使之前存在目录结构也被打散了。一旦文件导入到 Eagle 再想要使用文件管理器来管理这些图片变的不可能。当然这个只是个人的习惯问题。

eagle folders

要再想恢复到原来的文件结构可以右击文件夹,选择导出。

另外一点令我顾虑的就是,一旦使用 Eagle 来管理我的大量图片,这就使我锁定在了 Eagle,让我有一点介意的就是当我试用期过了之后,我竟然无法导出我的所有图片,虽然这些图片都在本地,但是因为已经被 Eagle 重新命名过所以几乎无法直接使用,只能让我用虚拟机再导出一遍。这也加重了我的顾虑。

再以缺点就是在我使用的过程中,有两次无法退出,即使使用强制退出,也无法退出,甚至让我在重启电脑的时候都卡在去停止 Eagle 的地方,我从没在 Mac 上遇到软件强制退出都不行的情况。

同类型的其他产品

总结

综上所有的优点,缺点,我仔细思考了一下,Eagle 确实在某些方面做的不错,对于设计师,或者对于刚刚开始整理素材的人来说是一个非常不错的选择,而一旦已经有了自己的素材库的人来说,不可避免的需要将素材导入到 Eagle,而这是一个不算愉快的选择,并且一旦想要放弃 Eagle,那么将数据导出便又是一段不愉快的旅程。所以最后再试用期满后,我迫不得已按了一台虚拟机导出整个库后删除了 Eagle。


2020-12-02 software , photo , photo-management , picasa , picture

我的 Obsidian 笔记跨设备同步方案

自从半年前发现了 Obsidian 这款笔记软件,我就开始大量的使用该应用做笔记,有人说过:「工具是开发者方法论的固化」。这么多年了我一直有一种工具控的倾向,往往同一个需求会对比可能的所有方案,最后再决定一个,但是近些年来我越来越倾向于「简单就是好」,并且数据要由自己掌控的「工具选择逻辑」。

Do one thing and do it well

基于上面的选择逻辑,我的 Obsidian 跨平台同步工具,我选择了:

  • Syncthing,作为文件同步工具
  • Markor,作为 Android 上的 Markdown 编辑器,我提交了一段模板可以来创建 Zettelkasten 笔记
  • Git,版本同步(配合git subtree
  • Bash/Cron/Hammerspoon,定时脚本提交备份到 Git,然后自动推送到远端备份。

每一个工具都只专注做一件事情,搭配起来工作非常完美。

2021 年 9 月更新

这一年来 Obsidian 的生态发生了很多变化,Obsidian 已经发布了 Android/iOS 版本,虽然现在我依然使用 Markor 来查看笔记,但最近已经慢慢的转向 Obsidian 官方的应用,Obsidian 官方的应用在搜索方面做的要比 Markor 好。

而之前使用 Syncthing,现在也一如既往的使用 Syncthing,但是最近购入了 Obsidian Sync 一方面支持一下开发者,另一方面也想慢慢地将移动端使用官方的同步工具来同步笔记。

我的需求

我最基本的需求,就是当我有什么想法的时候,可以随时随地地记录到一个地方,这个地方以前是 wiznote,但是我迁移到了 Obsidian 之后,缺乏两个机制:

  • 一个是多平台的同步
  • 一个是版本管理

为了解决第一个问题,引入了 Syncthing, 这个是我已经使用很久了的文件同步工具,代替了 Dropbox,NextCloud,正好 Obisidian 本身管理的就是本地的纯文件,直接添加到同步目录即可。

为了解决第二个问题,纯文本自然地就想到了使用 Git 作为版本管理。

但是问题在于 Zettelkasten 的其中一条原则便是「最好在一个地方管理所有的笔记」,而我曾经有很多笔记已经记录到了 Jekyll 的博客里面,也正好是 Markdown 的文本文件。所以我在一个中心的 Git 仓库中存放了 Obisidian 中的所有笔记,然后使用 git subtree 将我的 Blog 作为其中的一个子目录 Blog 添加进来,这样我就可以在一个 Obsidian 的 Vault 中搜寻,连接我所有的笔记。

利用上面的 Syncthing,Git,我可以做到多地(本地,VPS,Android 手机)的备份,然后将仓库同步到 GitHub 再有一份备份。另外通过 Git 的提交历史可以看到所有的笔记修改记录。这时候我就想通过一个自动提交的脚本,每隔半小时提交一次,这样最多也就丢失半小时的笔记,对我个人而言我也能接受。所以当时直接用 Hammerspoon 的特性写了一个脚本自动同步。

#!/bin/bash

now=$(date +"%m.%d.%Y_%T")

cd /Users/einverne/Sync/wiki
git add --all && git commit -m "Auto commit at $now"
git push origin master

发布我部分的笔记

在知识管理的概念中,我了解到了 [[Digital Garden]] 概念1,Digital Garden 是一个开放分享的数字花园,这个概念中有两个重点:

  • 有选择地将一部分笔记和想法公开
  • 游客可以在笔记之间来回浏览

在这个概念上实现最好的就是 Andy Matuschak 的在线笔记。

我也想通过从我的 Obsidian 笔记中选择一部分整理好的内容分享出,但我又不想有额外的操作。所以正好通过上面提及的 git subtree,我日常的笔记会存放在其他的目录,当我准备发布的时候,将笔记移动到 Blog 中的 _posts 目录,在提交,之后将修改推送到 Blog 的远端时就自动完成了发布的过程。现在唯一不太满意的部分就是现在博客上进行页内跳转的时候还依赖于超链接,在编写文章的时候也需要跳出去选择相应的页面链接,而不能依赖与 Obisidian 提供的双向连接。

但总是上面一套流程是我如何实现在多平台上同步笔记的方案,虽然可能对非编程工作者会有一些障碍,但只要熟悉了这个流程之后,用起来真的非常方便。另外就是我身边并没有 iOS 的设备,在 iOS 上可能需要依赖其他的工具,比如可以使用 iCloud 或其他商业的同步工具来同步笔记,然后使用 1Writer 来作为编辑器。

总之这就是我实现跨设备的方案,具体我是如何做笔记,以及笔记的内容,如何对笔记内容进行连接,我会在另外一篇文章中再进行阐述。


2020-11-23 obsidian , markdown , git , syncthing , note , note-taking

电子书

最近文章

  • Ubuntu 20.04 使用 MergerFS [[so-you-start So you Start]] 的独服有4块 2T 的硬盘,本来想配置一个 Soft RAID-10,但折腾了一个礼拜,重装了无数遍系统,配置了很多次,从 Ubuntu,Proxmox VE,Debian 都尝试了一遍,最终放弃了,想着充分利用其空间,使用 Proxmox VE,备份好数据,不用 RAID 了,毕竟如果使用默认的 RAID-1,我只能利用8T空间中的 2T 不到,而使用 RAID-10 也只能利用不到 4T 左右空间。至于使用单盘,所有的数据备份,和数据安全性的工作就完全依靠自己的备份去完成了。但是好处是可利用的空间大了。
  • So you Start 独服 Proxmox VE 虚拟机配置 Failover IP 最近买了一台 [[so-you-start]] 的独立服务器,开始的时候安装了 Ubuntu 没有充分利用独立服务器的优势,所以这两天把系统重新安装成了 Proxmox VE,然后在上面又安装了 Ubuntu 20.04,So you Start 提供了额外可以购买的 16 个 [[Failover IPs]],Failover IP 本来是为了可以将服务器迁移到另外的服务器而提供的机制,但在 Proxmox VE 虚拟化技术系统下,可以给虚拟机也分配不同的 IP,这样就实现了从一台服务器虚拟化多个 VPS 的操作。
  • 使用 Remark42 替换博客的 Disqus 评论系统 前两天用隐身窗口打开自己的博客的时候突然发现 Disqus 评论框上一大片广告,没想到现在 Disqus 已经这样了,并且之前还暴露出过隐私问题。所以就想着什么时候替换掉它。
  • club 域名宕机近 3 小时故障回顾 刚开始的时候收到了报警,说网站挂了,我的第一反应是 VPS 出问题了,赶紧 SSH 登录上去看,好像都正常。难道是 VPS 网络问题,于是看了看同一台机器上的其他服务,一切都没问题。
  • Rime 输入法中的快捷键 今天在整理 Rime 插件使用的时候,想起来整理一下 Rime 输入法的快捷键。