在 Emacs 土炮 app launcher
·
[Jack Shih]
emacs 一直以來有個很大的賣點就是它是一個可以完全客製化的編輯器。用 emacs 也有一段時間了感覺沒有寫點自己的小功能有點可惜。這次心血來潮就來土炮一個 app launcher 看能不能取代一下 spotlight 或 raycast (當然 spotlight 跟 raycast 有更多功能,不過最常用的還是當作 app launcher),順便當作練習。
這個功能算是網路上很多人都做過,所以應該沒有太大的問題。基本上只要能用 shell 做到的事情,emacs 都有辦法接,所以只要確認在 macos 底下能用 open 指令開啟程式之後剩下的就是看文件湊功能了。
實作細節也很單純,建立一個只有 minibuffer 的 child-frame,然後把相關資料夾內的 app 列出來選,選好之後就使用 open 指令來開啟。
(defun my-launch-app ()
"start application"
(interactive)
(progn
(make-frame `((parent-frame . ,(selected-frame))
(undecorated . t)
(minibuffer . only)
(left . ,(/ (- (frame-pixel-width (selected-frame)) (* 40 (frame-char-width))) 2))
(top . 0)))
(unwind-protect
(let* ((apps (append
(directory-files "/Applications" nil ".app")
(directory-files "~/Applications" nil ".app")
(directory-files "/system/Applications" nil ".app")
(directory-files "/system/Applications/Utilities" nil ".app")))
(apps-no-dot (mapcar (lambda (x) (string-replace ".app" "" x)) apps))
(vertico-count 30)
(resize-mini-frames t)
(max-mini-windows-height 0.8)
(window-min-width 40)
(user-choice (completing-read "Select a app:" apps-no-dot nil t)))
(with-environment-variables (("__NIX_DARWIN_SET_ENVIRONMENT_DONE" ""))
(start-process "launcher" nil "open" "-a" user-choice)))
(delete-frame)
)))
接下來就設定個快捷鍵就好了。
(global-set-key (kbd "M-s-<SPC>") 'my-launch-app)
這邊有個小插曲,之前在 處理 emacs shell command 抓不到 nix-direnv 的問題 的處理導致用這個方式啟動的 Termianl.app 會跳過設定環境變數的步驟。在測試了老半天之後才發現原來 Terminal.app 會吃 start-process 所代入 process-environment ,滿意外的是因為其他的 Termianl emulator 像是 Ghostty 都不會這樣。原本以為要土炮修改 process-environment ,後來發現 emacs 有提供 with-environment-variables 這個功能可以簡單處理。
雖然很 hacky 也有些小問題,不過是自己做給自己用的所以用起來還算順手。