Doom Emacs on Ubuntu Linux 尝鲜

Doom Emacs简介 Doom Emacs 是一个 Emacs 的配置框架,相比原厂的 Emacs 配置,Doom Emacs 提供了更方便完善的默认设置,预装了常用的包,并且提供了一个很容易自定义的框架。同时,Doom Emacs 启动速度也很快。最近在 Ubuntu 上试用了一下,感觉不错,正在考虑将我原有的配置移到 Doom Emacs 上去。 注意,Doom Emacs 不是 Emacs 发行版,只是一组 Emacs 配置,你运行 Doom Emacs 时,运行的还是系统上安装的 Emacs。Doom Emacs 需要 Emacs 27.1 以上,如果你的 Emacs 版本太低,需要先升级才能使用。 在 Ubuntu 上安装 Doom Emacs 首先你需要 Emacs 27.1 以上,个人推荐最新的 28.1 ,并带上 native-compilation 。 ./configure --prefix=$HOME/local \ --with-native-compilation \ --with-x --with-json \ --with-jpeg --with-tiff --with-png make -j4 make install 根据Doom Emacs的建议,加上 --with-json 可以提高运行速度。安装完成后确保 ~/.local/bin 在PATH里。 ...

May 21, 2022 · 2 min · Ping Zhou

Paxos 讨论:Phase-1 收到更高的 proposal number 该怎么办?

最近研究了一下Paxos,这个协议本身并不难懂,但 Lamport 的文章比较抽象,在具体实现上有一些细节没有充分讨论到,这里就讨论其中之一。 先聊一下背景:我们知道,每次运行Paxos(也就是一个Paxos实例,Paxos Instance)都由两个阶段(phase)组成。在phase-1,proposer 向 acceptor 发送 prepare 消息,并根据收到的回应决定是否可以进入下一阶段 phase-2 。 这个prepare消息主要内容是 proposer 的 proposal number (有些地方也称为 ballot number),例如在 Lamport 的 Paxos Made Simple 文章里: (a) A proposer selects a proposal number n and sends a prepare request with number n to a majority of acceptors. 当一个 acceptor 收到这个 prepare 请求时,它会把这个 proposal number 与它之前见过(承诺过) 的值比较,如果小于它之前见过的,则拒绝这个 prepare 请求,否则就接受这个 proposal ,并承诺 (promise) 它不再接受比这个 proposal number 更小的 proposal 。同样还是 Lamport 的这篇文章: (b) If an acceptor receives a prepare request with number n greater than that of any prepare request to which it has already responded, then it responds to the request with a promise not to accept any more proposals numbered less than n and with the highest-numbered proposal (if any) that it has accepted. ...

April 8, 2022 · 2 min · Ping Zhou

Emacs 28.1 正式发布,elisp原生编译支持来了!

期待已久的 Emacs 28.1 版本来了!这个版本中引入了一系列新特性,其中最引人注目,也最受期待的恐怕就是对Emacs Lisp(elisp)的原生编译支持(native compilation)。 目前 Emacs 28.1 还没有apk等二进制包,需要从源代码安装,方法和以前版本类似。但需要注意的是,原生elisp编译特性默认是不打开的,需要在 configure 时候加上 --with-native-compilation 参数。 另外,这个特性还依赖 libgccjit 和 gcc-10 包,需要先安装这些依赖包,否则 --with-native-compilation 参数会被拒绝: sudo apt install -y libgccjit0 libgccjit-10-dev gcc-10 安装完依赖包,就可以编译 Emacs 28.1 了: export CC="gcc-10" ./autogen.sh ./configure --prefix=$HOME/local/ --with-imagemagick --with-native-compilation make -j2 make install 安装完成! 试试看这个 native elisp compilation ,随便写个简单的 elisp 文件然后用 native-compile 函数编译: (native-compile "serve.el") 生成的原生二进制文件会保存在 ~/.emacs.d/eln-cache/ 目录下。用 file 命令查看,可以看到它被编译成了原生的ELF文件: file ~/.emacs.d/eln-cache/28.1-18b24ab0/serve-902d1548-7e0cb452.eln .../serve-902d1548-7e0cb452.eln: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=92a81b6c71e5cfee84e9763d9ac0625a0164875c, not stripped 除了原生elisp编译外,Emacs 28.1 还有很多新特性,以后有空慢慢探索。 :-)

April 4, 2022 · 1 min · Ping Zhou

C++ vector容器强制释放内存

换个话题,聊聊使用C++ STL vector容器时的一个内存管理问题。 C++用户经常会用STL里的vector容器来管理一组动态对象。STL vector的使用和C语言的数组类似,很方便: std::vector<int> buf = { 0, 1, 2, 3, 4, 5 }; buf[0]++; buf[1] = 10; 并且内存的使用和释放都由STL管理,用户不用像C语言那样手动malloc和free管理内存,确实省心不少。 但是在有些情况下,我们需要对容器占用的内存进行手动管理。 举个例子,假如我们有个数据管道,每次迭代生成一个样本池,里面有几百万个对象放在一个vector里,从中抽取一万个样本,然后交给管道作下一步处理,并且这个过程会反复进行。 那么在这个反复迭代过程中,我们希望样本池在每次采样完后就从内存里释放掉。否则下一次迭代时,我们再次生成样本池,而前一次占用的内存的还没释放掉,就有可能因为内存不够导致程序崩溃(Out Of Memory)。 你可能会问,这种情况用容器的clear方法不就好了? 但是,clear方法只是把这个容器的size变成了0,如果它的capacity其实没变,也就是说,clear方法并没有真的释放容器占用的内存。 buf.clear(); std::cout << buf.size(); // size变成了0 std::cout << buf.capacity(); // capacity还是6 那么在C++ STL里,是可以手动强制释放容器占用的内存的。方法不止一个,这里举个简单可靠的,就是用swap方法: std::vector<int> buf = { 0, 1, 2, 3, 4, 5 }; // ...... // 强制释放buf占用的内存 std::vector<int>().swap(buf); 解释一下这个方法的原理: ...

November 27, 2021 · 1 min · Ping Zhou

Lisp里的延迟执行

在图计算和协程里经常会用到的“延迟执行”,在Lisp里,只需要十几行代码就能实现! 创建和使用延迟执行对象 首先我们来定义一个宏 defer ,它的作用是把输入的代码块变成一个延迟执行的对象(其实是一个闭包): (defmacro defer (&body body) (let ((executed (gensym)) (result (gensym))) `(let ((,executed nil) (,result nil)) (lambda () (unless ,executed (setf ,result (progn ,@body)) (setf ,executed t)) ,result)))) 而如果要执行之前被推迟的代码,可以用这个函数: (defun defer-execute (deferred) (funcall deferred)) 例如,我们有这样一块代码: (princ "Hello, world.") (princ (1+ 2)) 用 defer 来包装它: (defer (princ "Hello, world.") (princ (1+ 2))) defer 会把输入的代码块包装成一个 闭包 返回给我们。所以通常我们要把这个闭包存在一个变量里: (defvar *deferred-hello* (defer (princ "Hello, world.") (princ (1+ 2)))) 等我们想要执行这个代码块的时候,只需要用 defer-execute 来调用这个闭包: ...

July 31, 2021 · 2 min · Ping Zhou

Markdown in Emacs: Live Preview, Math and Images

Introduction Emacs has a Markdown mode, but I need a more comprehensive setup with features like: Live preview window Rendering of math equations Rendering of local and remote images Basically I need a setup that provides similar functionality as VS Code + Markdown extensions. Install dependencies Emacs packages needed: markdown-mode markdown-mode simple-httpd impatient-mode Install pandoc: brew install pandoc Get MathJax: git clone https://github.com/mathjax/MathJax.git mathjax Configure Emacs Markdown settings Add these customization to Emacs config: ...

November 11, 2020 · 3 min · Ping Zhou

TensorFlow Developer Certificate: My Tips

I recently got my TensorFlow Developer Certificate. Here are some tips I learned from my latest experience with the exam. Preparation: Get familiar with Python coding and TensorFlow (of course!). Take some courses if needed. There are plenty of online courses available these days. For example, I found TensorFlow in Practice helpful to my preparation. Also, make sure you read the candidate handbook before taking the exam. PyCharm setup: You’ll take the exam in PyCharm. So it’ll be a good idea to play around a bit with this IDE. I recommend setting up a practice project according to the instructions in candidate handbook, so that you’ll have an idea what the environment will look like. ...

October 5, 2020 · 2 min · Ping Zhou

Fix A Problem When Applying .tmux.conf

For some reason I’m starting to get this error when I apply tmux configuration: cut -c3- ~/.tmux.conf | sh -s _apply_configuration returned -2 So the problem is that “sh” used to work here, but at some point it doesn’t when a new shell is installed. Furthermore, I guess the reason is that “sh” used to be resolved into “bash” and the syntax was written in bash accordingly. If “sh” gets resolved into some other shell, it might cause syntax error or something. ...

June 10, 2020 · 1 min · Ping Zhou

Fix a Problem in Emacs Python/Jupyter setup

I’ve configured my Emacs with a nice Python and Jupyter environment. I want to use it on my Mac laptop. Recently I noticed this strange issue: Problem: I send my code to Jupyter using C-c C-c, the Jupyter console shows a bunch of strange “Ctrl-G” (“G”) characters. My code was not executed, and the console seems to be stuck there. I have to press Ctrl-C to get back to shell. ...

March 28, 2020 · 1 min · Ping Zhou

Exporting .org files to HTML in batch

I use org-mode in Emacs and have multiple .org files to track different information in my life. Sometimes I want to export my .org files as HTML so they can be easily viewed on another device. The org-mode package does provide commands to do this on individual file (such as “org-html-export-to-html”), but doing this on each file manually is tedious. So I decided to write my own elisp function to augment my Emacs environment. ...

January 9, 2020 · 2 min · Ping Zhou