|
Tags: Mobile edit Mobile web edit |
(50 intermediate revisions by the same user not shown) |
Line 25: |
Line 25: |
|
| |
|
| == 文件夹 == | | == 文件夹 == |
| 怎么让安卓版本的 Emacs 访问你的安卓里的文件夹呢?
| | 怎么让原生安卓版本的 Emacs 访问你的安卓里的文件夹呢? |
| <syntaxhighlight lang="elisp"> | | <syntaxhighlight lang="elisp"> |
| # 授予管理所有文件的权限 | | # 授予管理所有文件的权限 |
Line 34: |
Line 34: |
| </syntaxhighlight> | | </syntaxhighlight> |
|
| |
|
| == 设置工作目录 == | | == 字体 == |
| <syntaxhighlight lang="elisp">
| | 怎么让原生安卓版本的 Emacs 识别并正常显示中文字体,而不是 16 进制的字符块呢? |
| (setq default-directory "/sdcard/Emacs/")
| | |
| </syntaxhighlight>
| | 首先,去下载某个字体。 |
|
| |
|
| | 其次,把它复制进原生安卓版本的 Emacs 的私有目录下的 fonts 文件夹。 |
| <syntaxhighlight lang="elisp"> | | <syntaxhighlight lang="elisp"> |
| M-x setenv RET HOME RET /sdcard/Emacs | | M-x mkdir RET fonts |
| | M-x copy-file RET /sdcard/Downloads/NotoSansSC-Regular.ttf RET ~/fonts/NotoSansSC-Regular.ttf RET |
| </syntaxhighlight> | | </syntaxhighlight> |
|
| |
|
| | 再次,验证 Emacs 是否看到了你复制进去的字体。 |
| <syntaxhighlight lang="elisp"> | | <syntaxhighlight lang="elisp"> |
| ;; ======== 固定 new-file 目录为 /storage/sdcard0/Emacs/ =========
| | (insert |
| (defvar my-android-emacs-dir "/storage/sdcard0/Emacs/" | | "\n" |
| "默认用于新建文件和文件选择的目录(Android)。")
| | (mapconcat |
| | | #'identity |
| (setq-default default-directory (expand-file-name my-android-emacs-dir)) | | (seq-filter (lambda (font) |
| | | (or (string-match-p "SC" font) |
| (add-hook 'emacs-startup-hook | | (string-match-p "wqy" font) |
| (lambda ()
| | (string-match-p "WenQuanYi" font))) |
| (let ((d (expand-file-name my-android-emacs-dir)))
| | (font-family-list)) |
| (dolist (buf (buffer-list))
| | "\n") |
| (with-current-buffer buf | | "\n") |
| (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)
| |
| ;; ================================================================
| |
|
| |
|
| </syntaxhighlight> | | </syntaxhighlight> |
|
| |
| == 字体 ==
| |
| 怎么让原生安卓版本的 Emacs 识别并正常显示中文字体,而不是 16 进制的字符块呢?
| |
|
| |
| 首先,去下载某个字体。
| |
|
| |
| 其次,把它复制进原生安卓版本的 Emacs 的工作目录下的 fonts 文件夹。
| |
|
| |
|
| 最后,在 ~/.emacs.d/init.el 里调用该字体。 | | 最后,在 ~/.emacs.d/init.el 里调用该字体。 |
Line 95: |
Line 67: |
| (set-language-environment "UTF-8") | | (set-language-environment "UTF-8") |
|
| |
|
| (set-face-attribute 'default nil :height 300) | | ;; 因为屏幕素质不同,字体设计时字高不同,emacs 也不一定按屏幕真实 DPI 来渲染 |
| (set-fontset-font t 'han "Noto Sans SC:pixelsize=50") | | ;; 所以追求数学上相近的比如都 30pt 没用 |
| </syntaxhighlight>
| | ;; 得看不同屏幕上的实际观感来确定中英文的不同 pt |
| | | (set-face-attribute 'default nil :height 240) ;; 单位 1/10 pt |
| | | (set-fontset-font t 'han (font-spec :family "Noto Sans SC" :size 40)) ;; 单位 1 pt |
| 私有目录,一般是 /data/data/org.gnu.emacs/files/fonts。
| |
| <syntaxhighlight lang="elisp">
| |
| M-x copy-file RET /sdcard/Downloads/NotoSansSC-Regular.ttf RET ~/fonts/NotoSansSC-Regular.ttf RET
| |
| </syntaxhighlight> | | </syntaxhighlight> |
|
| |
|
| | | == 美化 == |
| == debug == | |
| <syntaxhighlight lang="elisp"> | | <syntaxhighlight lang="elisp"> |
| ;; 把整段粘进 *scratch* 并评估,或放到 init.el
| | (setq inhibit-startup-message t) |
| (require 'cl-lib) | | (setq make-backup-files nil) ;; 禁止生成 xxx~ |
| | | (setq auto-save-default nil) ;; 禁止生成 #xxx# |
| (defun my-android-debug-info ()
| | (setq create-lockfiles nil) |
| "Gather Android/`default-directory' debug info and show it in *emacs-android-debug* buffer.
| |
| Run `M-x my-android-debug-info' and copy the buffer content to paste here."
| |
| (interactive)
| |
| (let* ((buf (get-buffer-create "*emacs-android-debug*"))
| |
| (dir (if (and (boundp 'my-android-emacs-dir) my-android-emacs-dir)
| |
| (expand-file-name my-android-emacs-dir)
| |
| "/storage/sdcard0/Emacs/")))
| |
| (with-current-buffer buf
| |
| (setq buffer-read-only nil)
| |
| (erase-buffer)
| |
| (insert (format "===== emacs-android-debug (timestamp: %s) =====\n\n"
| |
| (current-time-string)))
| |
| | |
| ;; basic vars
| |
| (insert (format "my-android-emacs-dir bound: %s\n"
| |
| (if (boundp 'my-android-emacs-dir) "yes" "no")))
| |
| (when (boundp 'my-android-emacs-dir)
| |
| (insert (format "my-android-emacs-dir value: %s\n" my-android-emacs-dir)))
| |
| (insert (format "resolved my-android-emacs-dir: %s\n\n" dir))
| |
| | |
| ;; env
| |
| (insert "=== Environment ===\n")
| |
| (dolist (v '("HOME" "ANDROID_DATA" "EXTERNAL_STORAGE" "EMACS"))
| |
| (insert (format "%-18s = %s\n" v (or (getenv v) ""))))
| |
| (insert "\n")
| |
| | |
| ;; home/dirs and current
| |
| (insert "=== Home / Directories ===\n")
| |
| (insert (format "getenv \"HOME\": %s\n" (or (getenv "HOME") "")))
| |
| (insert (format "expand-file-name \"~\": %s\n" (expand-file-name "~")))
| |
| (insert (format "default-directory (current buffer): %s\n\n" default-directory))
| |
| | |
| ;; hooks and minibuffer
| |
| (insert "=== Minibuffer & Hooks ===\n")
| |
| (insert (format "minibuffer-setup-hook length: %d\n" (length minibuffer-setup-hook)))
| |
| (insert (format "emacs-startup-hook length: %d\n" (length emacs-startup-hook)))
| |
| (insert (format "my-android-find-file-minibuffer-setup present in minibuffer-setup-hook?: %s\n"
| |
| (if (memq #'my-android-find-file-minibuffer-setup minibuffer-setup-hook) "yes" "no")))
| |
| (insert "\n")
| |
| | |
| ;; buffers
| |
| (insert "=== Buffers and their default-directory ===\n")
| |
| (dolist (b (buffer-list))
| |
| (with-current-buffer b
| |
| (insert (format "%-30s -> %s\n" (buffer-name b) default-directory))))
| |
| (insert "\n")
| |
| | |
| ;; features commonly related to file UIs
| |
| (insert "=== Common UI features loaded ===\n")
| |
| (dolist (f '(ivy helm vertico counsel selectrum))
| |
| (insert (format "%-10s : %s\n" f (if (featurep f) "loaded" "not loaded"))))
| |
| (insert "\n")
| |
| | |
| ;; read-file-name info
| |
| (insert "=== read-file-name / advice info ===\n")
| |
| (insert (format "read-file-name-function: %s\n" read-file-name-function))
| |
| (insert (format "symbol property 'advice on read-file-name: %s\n"
| |
| (if (get 'read-file-name 'advice) "present" "none")))
| |
| (insert (format "symbol-function of read-file-name: %s\n\n" (symbol-function 'read-file-name)))
| |
|
| |
|
| ;; filesystem checks
| | (menu-bar-mode -1) |
| (insert "=== Filesystem checks for resolved my-android-emacs-dir ===\n")
| | (tool-bar-mode -1) |
| (insert (format "file-exists-p: %s\n" (file-exists-p dir)))
| | (scroll-bar-mode -1) |
| (insert (format "file-directory-p: %s\n" (file-directory-p dir)))
| |
| (insert "directory-files (attempt, up to first 20 entries):\n")
| |
| (condition-case err
| |
| (let ((lst (directory-files dir nil nil t)))
| |
| (insert (format " total entries: %d\n" (length lst)))
| |
| (dolist (e (cl-subseq lst 0 (min 20 (length lst))))
| |
| (insert (format " %s\n" e))))
| |
| (error (insert (format " ERROR listing directory: %s\n" err))))
| |
| (insert "\n")
| |
|
| |
|
| ;; android helpers
| | (global-auto-revert-mode t) |
| (insert "=== Android helper functions availability ===\n")
| | (setq suggest-key-bindings 10) ;十秒后建议才消失 |
| (insert (format "android-request-directory-access fboundp: %s\n"
| |
| (if (fboundp 'android-request-directory-access) "yes" "no")))
| |
| (insert (format "android-request-storage-access fboundp: %s\n"
| |
| (if (fboundp 'android-request-storage-access) "yes" "no")))
| |
| (insert "\n")
| |
|
| |
|
| (insert "===== End of report =====\n")
| | (add-hook 'dired-mode-hook 'dired-hide-details-mode t) |
| (goto-char (point-min))
| | (defalias 'yes-or-no-p 'y-or-n-p) |
| ;; make read-only for safety and show it
| |
| (view-mode 1)
| |
| (display-buffer buf))))
| |
|
| |
|
| | ;; 之前我一直在纠结 Emacs 处理安卓公开目录如 /storage/sdcard0/Emacs 时会导致 Find file 有长长的路径。洗把脸发现嫌弃路径长我自己写个短路径不就行了吗 |
| | (setq initial-buffer-choice (lambda () (dired "/sdcard/a/"))) |
| </syntaxhighlight> | | </syntaxhighlight> |
原生安卓版本的 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
字体
怎么让原生安卓版本的 Emacs 识别并正常显示中文字体,而不是 16 进制的字符块呢?
首先,去下载某个字体。
其次,把它复制进原生安卓版本的 Emacs 的私有目录下的 fonts 文件夹。
M-x mkdir RET fonts
M-x copy-file RET /sdcard/Downloads/NotoSansSC-Regular.ttf RET ~/fonts/NotoSansSC-Regular.ttf RET
再次,验证 Emacs 是否看到了你复制进去的字体。
(insert
"\n"
(mapconcat
#'identity
(seq-filter (lambda (font)
(or (string-match-p "SC" font)
(string-match-p "wqy" font)
(string-match-p "WenQuanYi" font)))
(font-family-list))
"\n")
"\n")
最后,在 ~/.emacs.d/init.el 里调用该字体。
(prefer-coding-system 'utf-8)
(set-default-coding-systems 'utf-8-unix)
(set-language-environment "UTF-8")
;; 因为屏幕素质不同,字体设计时字高不同,emacs 也不一定按屏幕真实 DPI 来渲染
;; 所以追求数学上相近的比如都 30pt 没用
;; 得看不同屏幕上的实际观感来确定中英文的不同 pt
(set-face-attribute 'default nil :height 240) ;; 单位 1/10 pt
(set-fontset-font t 'han (font-spec :family "Noto Sans SC" :size 40)) ;; 单位 1 pt
美化
(setq inhibit-startup-message t)
(setq make-backup-files nil) ;; 禁止生成 xxx~
(setq auto-save-default nil) ;; 禁止生成 #xxx#
(setq create-lockfiles nil)
(menu-bar-mode -1)
(tool-bar-mode -1)
(scroll-bar-mode -1)
(global-auto-revert-mode t)
(setq suggest-key-bindings 10) ;十秒后建议才消失
(add-hook 'dired-mode-hook 'dired-hide-details-mode t)
(defalias 'yes-or-no-p 'y-or-n-p)
;; 之前我一直在纠结 Emacs 处理安卓公开目录如 /storage/sdcard0/Emacs 时会导致 Find file 有长长的路径。洗把脸发现嫌弃路径长我自己写个短路径不就行了吗
(setq initial-buffer-choice (lambda () (dired "/sdcard/a/")))