怎么使用原生 Android 版本的 Emacs
原生安卓版本的 Emacs,令安卓上的编程出现了很大的想象力。或许未来,在安卓上编程,会成为更方便的事情。以前,大家都绕道,用 Termux 安装 Emacs,终究是隔了一层。现在,gnu 本身发布了原生安卓版本的 Emacs,可以从 FDroid 分流下载。但是安装后,你会发现你遇到了重重难题。
不迷路
怎么让自己不迷路,知道自己在哪里?
# 查看 HOME 环境变量
M-: (getenv "HOME")
# 示例输出:"/data/data/org.gnu.emacs/files"
# 查看 ~ 的展开路径
M-: (expand-file-name "~")
# 示例输出:"/data/data/org.gnu.emacs/files"
# 查看工作起始目录
M-: default-directory
# 示例输出:"~/"
# M-: 运行命令
# 注意 default 别写成 defualt
# 评估变量不用括号
# 调用函数要括号
# 输出就算一样,也是各有所用,并不重复
# 可以单独设置
文件夹
怎么让安卓版本的 Emacs 访问你的安卓里的文件夹呢?
# 授予管理所有文件的权限
M-x android-request-storage-access
# 授予管理某个文件夹的权限
M-x android-request-directory-access
工作目录
;; ======== 固定 new-file 目录为 /storage/sdcard0/Emacs/ =========
(defvar my-android-emacs-dir "/storage/sdcard0/Emacs/"
"默认用于新建文件和文件选择的目录(Android)。")
(setq-default default-directory (expand-file-name my-android-emacs-dir))
(add-hook 'emacs-startup-hook
(lambda ()
(let ((d (expand-file-name my-android-emacs-dir)))
(dolist (buf (buffer-list))
(with-current-buffer buf
(setq default-directory d))))))
(defun my-android-find-file-minibuffer-setup ()
(when (memq this-command '(find-file find-file-other-window))
(setq default-directory (expand-file-name my-android-emacs-dir))))
(add-hook 'minibuffer-setup-hook #'my-android-find-file-minibuffer-setup)
;; 强力:为 read-file-name 提供默认目录(覆盖大多数 UI 框架)
(defun my-android-read-file-name-wrapper (orig prompt &optional dir default-filename mustmatch initial)
(let ((dir (or dir (expand-file-name my-android-emacs-dir))))
(apply orig prompt dir default-filename mustmatch initial)))
(advice-add 'read-file-name :around #'my-android-read-file-name-wrapper)
;; 权限检查命令
(defun my-android-ensure-emacs-dir-access ()
(interactive)
(let ((d (expand-file-name my-android-emacs-dir)))
(if (file-directory-p d)
(message "目录可访问:%s" d)
(if (fboundp 'android-request-directory-access)
(message "请运行 M-x android-request-directory-access 并选择 %s 以授权。" d)
(message "目录不可访问:%s。请在 系统 -> 应用 -> 特殊应用访问 -> All files access 打开 Emacs 并授予“文件与媒体”权限。" d)))))
(global-set-key (kbd "C-c e d") #'my-android-ensure-emacs-dir-access)
;; ================================================================
字体
怎么让原生安卓版本的 Emacs 识别并正常显示中文字体,而不是 16 进制的字符块呢?
首先,去下载某个字体。
其次,把它复制进原生安卓版本的 Emacs 的工作目录下的 fonts 文件夹。
最后,在 ~/.emacs.d/init.el 里调用该字体。
(prefer-coding-system 'utf-8)
(set-default-coding-systems 'utf-8-unix)
(set-language-environment "UTF-8")
(set-face-attribute 'default nil :height 300)
(set-fontset-font t 'han "Noto Sans SC:pixelsize=50")
私有目录,一般是 /data/data/org.gnu.emacs/files/fonts。
M-x copy-file RET /sdcard/Downloads/NotoSansSC-Regular.ttf RET ~/fonts/NotoSansSC-Regular.ttf RET
Debug
;; 把默认目录改为 /storage/sdcard0/emacs/
(setq-default default-directory "/storage/sdcard0/emacs/")
;; 启动时打开 dired 指向 sdcard 目录
(setq initial-buffer-choice (lambda () (dired "/storage/sdcard0/emacs/")))
;; 把这串长目录改短一些
(setq directory-abbrev-alist
'(("/storage/sdcard0/Emacs" . "~/emacs")))
M-! ln -s /data/data/org.gnu.emacs/files /storage/sdcard0/Emacs RET
;; 把下面三个变量按需改成你的路径(你已经给出)
(let* ((target "/data/data/org.gnu.emacs/files") ;; 被指向的真实目录
(link "/storage/sdcard0/Emacs")) ;; 将要创建的符号链接名
(cond
((file-symlink-p link)
(message "已有符号链接:%s -> %s" link (file-symlink-p link)))
((file-exists-p link)
(message "目标路径已存在且不是符号链接:%s 。请先删除或改名。" link))
(t
(condition-case err
(progn
;; make-symbolic-link 参数顺序是 (TARGET NAME ...)
(make-symbolic-link target link)
(message "创建成功:%s -> %s" link target))
(error (message "创建符号链接失败(可能是权限问题):%s" err))))))
;; 运行后可以检查
;; (file-symlink-p "/storage/sdcard0/Emacs") ;; 返回 target 或 nil