惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

K
Kaspersky official blog
Engineering at Meta
Engineering at Meta
D
DataBreaches.Net
Stack Overflow Blog
Stack Overflow Blog
Microsoft Security Blog
Microsoft Security Blog
Y
Y Combinator Blog
B
Blog RSS Feed
GbyAI
GbyAI
P
Proofpoint News Feed
aimingoo的专栏
aimingoo的专栏
MyScale Blog
MyScale Blog
D
Docker
阮一峰的网络日志
阮一峰的网络日志
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Recorded Future
Recorded Future
美团技术团队
The Register - Security
The Register - Security
V
Visual Studio Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
T
Tailwind CSS Blog
爱范儿
爱范儿
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
T
The Blog of Author Tim Ferriss
博客园 - 司徒正美
量子位
B
Blog
F
Fortinet All Blogs
Martin Fowler
Martin Fowler
博客园 - 【当耐特】
MongoDB | Blog
MongoDB | Blog
A
About on SuperTechFans
I
InfoQ
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
有赞技术团队
有赞技术团队
雷峰网
雷峰网
大猫的无限游戏
大猫的无限游戏
J
Java Code Geeks
L
LangChain Blog
Latest news
Latest news
S
SegmentFault 最新的问题
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Blog — PlanetScale
Blog — PlanetScale
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Cisco Talos Blog
Cisco Talos Blog
F
Full Disclosure
C
Cisco Blogs
D
Darknet – Hacking Tools, Hacker News & Cyber Security
W
WeLiveSecurity
T
Tenable Blog
T
Tor Project blog

暗无天日

读:AI Agent 安全日志——从可见性与隐私的两难说起 - 暗无天日 读:AI Agent 生产化——一份从原型到上线的速查清单 - 暗无天日 AI写作的语言指纹——如何让文字不那么像机器 - 暗无天日 读:50 条 Claude Code 技巧——一个工程经理的六个月使用心得 读:AI 辅助开发为什么让 E2E 测试更有价值 - 暗无天日 读:在Emacs中使用Claude Code(Spacemacs适配版) - 暗无天日 Claude Code 背后的工程哲学——读 Agent Harness Engineering 读:Agent Harness Engineering——AI 智能体不只是模型,还有套件 - 暗无天日 browser-harness:让 AI 直接接管你的浏览器 - 暗无天日 读:Security-First CI/CD —— DevSecOps 自动化实践指南 TIL: 数字小键盘的小数点陷阱与行内算术求值 - 暗无天日 读:Immutability 不是万能药,它是一种权衡 - 暗无天日 Conducty:给 Claude Code 加上项目记忆和并行执行能力 - 暗无天日 读 — GitHub Trending 里的 Claude Code 技能包 读 — Prompt Caching 省钱指南 TIL: Emacs 中那些跟鼠标配合的冷门快捷键 - 暗无天日 读:Anvil——把 Emacs 变成 AI 的工具服务器 读:Emacs 代码折叠终极指南 - 暗无天日 读:Clojure 搭车客指南 - 暗无天日 git推送失败后恢复仓库损坏的完整记录 - 暗无天日 多智能体系统的两个有效模式——以及对 Claude Code 用户的启示 - 暗无天日 用 Org Babel 写 Literate 博文:扩展执行 + 定制导出 proced:Emacs 内置的进程查看器 - 暗无天日 读:让 Emacs proced 在 macOS 上显示 CPU 和内存 异步编程的函数着色税 - 暗无天日 链式调用的代价:JavaScript 和 Clojure 的共同教训 - 暗无天日 hyperfine:命令行基准测试工具 - 暗无天日 管道中的变量去哪了?——子 shell 作用域陷阱 - 暗无天日 开源包装器的信任陷阱:四个危险信号 - 暗无天日 程序员愿意为 AI 写文档,却不愿为同事写 - 暗无天日 mktemp: Shell 脚本中临时文件的安全陷阱与最佳实践 - 暗无天日 WSL9x —— 在 Windows 9x 里跑 Linux 内核 6.19 用 ox.el 做你想做的事 —— org-export 高级编程指南 读:Hot-wiring the Lisp Machine —— 用纯 Elisp 构建零依赖的 Org 静态站点生成器 Elisp 性能优化的六个实战教训 - 暗无天日 fcitx5 下 Emacs 无法切换输入法的排查 - 暗无天日 ERT 测试交互命令的三种方式 - 暗无天日 SEM Assistant: 当 Elisp 守护进程遇上 LLM 用 dmsg 给 Elisp 加上结构化调试日志 用 org-habit 追踪非每日习惯 - 暗无天日 Clojure X-Men:当编程语言特性变成超能力 - 暗无天日 TIL: 用 diff-hl 在 fringe 中显示 git 变更 读:llm-test —— 用 LLM agent 驱动 Emacs 测试 TIL: AI 时代的橡皮鸭调试 - 暗无天日 fcitx 启动后键盘输入卡顿的排查 - 暗无天日 TIL: 早期网页的图片热区导航 - 暗无天日 读 Seeing the Whole System 用 Emacs 自动生成每周链接推荐 - 暗无天日 读:ASCII control characters in my terminal 读 What to learn - 暗无天日 Lisp 的括号之痛——一个愚人节玩笑揭开的老伤疤 - 暗无天日 一本书该"线性读"还是"并行读" - 暗无天日 读 How to Monetize a Blog:一篇伪装成变现指南的讽刺文 Python Mock 第三方依赖的四种策略 - 暗无天日 Emacs Lisp 热重载实用指南 - 暗无天日 Prot 的 Emacs 配置哲学 - 暗无天日 TIL: 从直播对谈中学到的三个 Emacs 技巧 - 暗无天日 TIL: 自动使用项目虚拟环境的 Python - 暗无天日 TIL: 让 Help buffer 自动获得焦点 一条命令让本地开发用上 HTTPS —— slim 工具介绍 用 fsck 检查和修复 Linux 文件系统 排查Linux进程"卡死"实战:从strace到gdb全流程 - 暗无天日 PostgreSQL 索引:从基础到你可能不知道的高级用法 - 暗无天日 用 .pdbrc 自定义 Python 调试器 ANSI 转义码的标准化现状 - 暗无天日 终端程序的潜规则 - 暗无天日 PARA Org-mode 测试配置 - 暗无天日 AI越强越辣鸡?控制论说这是必然的 - 暗无天日 AI 越强越需要你盯着——反馈循环实操指南 - 暗无天日 你的AI代理正在偷你的密钥——四种你没想到的泄露通道 - 暗无天日 LLM 在 DevOps 中的三种角色 - 暗无天日 写作风格的反建议 - 暗无天日 反驳本质复杂性——Dan Luu 论为什么《没有银弹》错了 - 暗无天日 文件充满了危险——Dan Luu 谈文件系统的可靠性陷阱 - 暗无天日 AI 时代的 PARA 方法:用 Org-mode 和 AI 打造个人知识管理系统 Linux 数据去重学习笔记 - 暗无天日 创建跨平台 ZIP 文件的隐藏陷阱:Extra Field - 暗无天日 X11 Forwarding 排障指南 - 暗无天日 IP欺骗端口扫描:当别人冒充你去扫描别人 - 暗无天日 Linux 输入栈全景解析:从硬件按键到屏幕响应 - 暗无天日 Unix 系统中那些被埋没的配置开关——以 FontConfig 为例 - 暗无天日 在Linux上限制儿童使用电脑 - 暗无天日 GIF不仅仅是一种图片格式——用GIF流做些奇怪的事 - 暗无天日 Leiningen 学习笔记:Clojure 项目构建与管理从入门到实战配置 - 暗无天日 Google SRE Book 读书笔记 - 暗无天日 yes 管道 head 发生了什么 - 暗无天日 为什么 nohup 在 crontab 中不起作用 Bash中的Indirection与Nameref - 暗无天日 Linux PAM 简介 - 暗无天日 从Linux ISO文件启动计算机 - 暗无天日 用 Bash 打造一个Screen Locker 用GitHub Actions自动构建EGO博客 - 暗无天日 blocking I/O 的作用 - 暗无天日 mobileog 手机端同步提示Error:2 No such file 的解决方法 回收 WSL2 VHDX 文件占用空间 使用 org-mode columnview 生成任务列表 - 暗无天日 Emacs 作为 MPD 客户端 - 暗无天日 移动文件路径却不破坏org file link的方法 - 暗无天日 如何合理的导出help link 成HTML - 暗无天日 笑话理解之Biology - 暗无天日
从 proced 定制中学到的 Elisp 模式
2026-04-25 · via 暗无天日

Rahul Juliato 的 Getting Emacs proced.el to Show CPU and Memory on macOS 表面上是解决 macOS 上 proced 缺少 CPU/Mem 列的问题,实际上是一份很好的 Elisp 编程教学。本文从中提取六个可复用的编程模式——它们跟 proced 和 macOS 无关,你在任何需要异步调用外部命令、缓存数据、扩展第三方包的场景都能用。

模式一:异步进程 + sentinel

Elisp 中执行外部命令有两种方式: call-process (同步,会阻塞 Emacs )和 make-process (异步,不阻塞)。凡是执行时间不确定的命令,都应该用 make-process

(make-process
 :name "my-process"
 :buffer (generate-new-buffer " *my-process-temp*")
 :command '("env" "LC_ALL=C" "ps" "-eo" "pid=,%cpu=,%mem=")
 :noquery t
 :sentinel
 (lambda (proc _event)
   (when (eq (process-status proc) 'exit)
     (with-current-buffer (process-buffer proc)
       (goto-char (point-min))
              (buffer-string))
     (kill-buffer (process-buffer proc)))))

关键设计:

  • sentinel 是一个回调函数,在进程状态变化时触发。通常只关心 'exit 状态——此时 buffer 中已有完整输出。
  • :noquery t 防止 Emacs 退出时弹出"还有进程在运行"的确认框。
  • generate-new-buffer 创建临时 buffer 承接输出,名称以空格开头( " " )的 buffer 在 list-buffers 中默认隐藏。
  • 处理完后 kill-buffer 清理临时 buffer ,避免 buffer 堆积。

模式二:hash table 做进程级缓存

当你需要频繁按 key 查找数据时,hash table 比 alist 快得多( O(1) vs O(n) )。

(defvar my-cache (make-hash-table))

(puthash 1234 (cons 2.5 1.3) my-cache)
(puthash 5678 (cons 0.1 0.5) my-cache)

(car (gethash 1234 my-cache))   (cdr (gethash 1234 my-cache))   (gethash 9999 my-cache)          
2.5
1.3
nil

为什么用 cons 存值?因为 carcdr 是 Elisp 中最快的取值操作之一,比 plist-getalist-get 快。当你只需要存两个值时,cons 是最佳选择。

刷新时不要原地修改 hash table ,而是创建一个新的再替换——这样即使有并发的读操作也不会读到半更新的状态:

(defun my-refresh-cache ()
  (let ((new-cache (make-hash-table)))
        (setq my-cache new-cache)))  

模式三: rx 宏写可读正则

Elisp 的 rx 宏用 S-expression 写正则,比字符串正则更容易读和维护。对比一下:

"^[[:blank:]]*\\([[:digit:]]+\\)[[:blank:]]+\\([.[:digit:]]+\\)"

(rx (* blank)
    (group (+ digit))
    (+ blank)
    (group (+ (any digit ?.))))

rx 编译出来的结果跟手写字符串正则完全一样:

(rx (* blank)
    (group (+ digit))
    (+ blank)
    (group (+ (any digit ?.)))
    (+ blank)
    (group (+ (any digit ?.))))
[[:blank:]]*\([[:digit:]]+\)[[:blank:]]+\([.[:digit:]]+\)[[:blank:]]+\([.[:digit:]]+\)

常用 rx 组合:

rx 写法 匹配内容
(+ digit) 一个或多个数字
(* blank) 零或多个空白
(any digit ?.) 数字或小数点
(group ...) 捕获组,对应 match-string

模式四:timer 生命周期管理

Emacs 的 run-with-timer 可以周期性执行任务,但如果不在合适的时机取消,timer 会一直运行下去(即使对应的 buffer 已经关了)。正确的做法是在 mode hook 里启动,在 kill-buffer-hook 里取消:

(defvar my-timer nil)

(add-hook 'my-mode-hook
  (lambda ()
    (setq my-timer
          (run-with-timer 0 2 #'my-refresh-function))))

(add-hook 'kill-buffer-hook
  (lambda ()
    (when (and (derived-mode-p 'my-mode)
               (timerp my-timer))
      (cancel-timer my-timer)
      (setq my-timer nil))))

三个要点:

  • run-with-timer 的参数是 (延迟秒数 重复间隔 函数) ,第一个参数 0 表示立即执行第一次。
  • cancel-timer 取消后要把变量设为 nil ,避免悬空引用。
  • guard 条件 (derived-mode-p 'my-mode) 确保 kill-buffer-hook 不会在其他类型的 buffer 中误触发。 kill-buffer-hook 是全局的,每次任何 buffer 关闭都会触发,所以必须有 mode 判断。

模式五: file-remote-p 做 TRAMP 感知

当你的代码依赖本地系统状态(比如执行本地 ps ),必须考虑 buffer 可能在 TRAMP 远程主机上运行的情况。 file-remote-p 检测 default-directory 是否指向远程:

(unless (file-remote-p default-directory)
    (my-run-local-command))

为什么这很重要?如果你不加检测,可能会用本地 ps 的输出作为参数在远程主机上执行命令。轻则数据显示错误,重则本地 PID 跟远程 PID 碰撞导致误操作。

模式六:通过 custom attributes 扩展第三方包

很多 Emacs 包提供 *-custom-attributes 或类似的扩展点,让你不用修改包的源码就能添加功能。 procedproced-custom-attributes 就是一个例子:它接受一个 lambda 列表,每个 lambda 接收当前行的属性 alist ,返回 (keyword . value) 就能添加新列。

(setq proced-custom-attributes
  (list
   (lambda (attrs)
     (when-let* ((pid (cdr (assq 'pid attrs)))
                 (v (my-lookup pid)))
       (cons 'my-attribute v)))))

这个模式不限于 proced 。当你需要给某个包添加自定义字段时,先看看它有没有类似的扩展点——很多设计良好的包都会提供。

小结

模式 一句话
异步进程 + sentinel make-process 代替 call-process ,在 sentinel 中处理输出
hash table 缓存 高频查找用 hash table ,刷新时整体替换而非原地修改
rx 用 S-expression 写正则,比字符串更可读更易维护
timer 生命周期 hook 启动、hook 清理、 derived-mode-p guard 三件套
file-remote-p 任何依赖本地系统状态的代码都要加 TRAMP 检测
custom attributes 用 lambda 返回 (keyword . value) 扩展第三方包的显示