git submodule
自卑与超越
1mm与一个钟
与佛陀一起吃早餐
2019
多少凉薄世态可动荡
还有孤独要顽抗
多少遗憾自负存念想
唯有时间不可挡
emacs-dired-open
emacs-start-win-application
light show
Question-and-solutions
1. 路径设置中的问题
最近在写一个windows上使用的emacs terminal插件,让emacs act as vscode的terminal,遇到一个查找父路径的问题,比如一个java项目,项目路径即父路径应该是有 settings和graldew的目录,而source code放在 src/main/Main.java 这样子,那么当我编辑了该文件后要运行 gradle run ,就应该在父路径下运行,所以我找到了下面的方法1
2
3(defun get-parent-dir (name)
"Get the parent name dir."
(locate-dominating-file default-directory name))
理论上可以直接用这个,但是我希望自己指定父路径,这时,我需要一个方法能够返回list中第一个非nil,想到用or 但是不知道怎么把list 拆开传给or。找到了 cl-some 这个方法1
2
3
4
5
6
7
8(defvar pop-find-parent-directory nil "find the files in parent directory,if find,return the path as parent directory,else try the next")
(defun get-project-root-directory (buffer)
"find current project root,for git or gradle."
(with-current-buffer buffer
(if (setq parent (cl-some #'get-parent-dir pop-find-parent-directory))
parent
(get-current-directory))))
之后又详细的研究了macro 补一个 or的实现1
2
3
4
5(defmacro get-not-nil (list)
`(progn
(or ,@list)))
(get-not-nil (nil nil "he" "hi") )
2. 使用关键字
我希望我的方法能像use-package一样使用 :init :config来配置,所以我查询了function的keyword。发现方法或者宏后面加*的都是 cl.el 的实现,cl的实现里支持 &key.1
2
3
4
5
6
7
8(defun* example (&rest args &key (a 1) (b 2) &allow-other-keys)
(format "%s %s %s" args a b))
(example :b "hello" 2)
(defun* my-example (name &key (a ) &allow-other-keys)
(format "%s %s " name a))
(my-example "gradle" :b (message "hello"))
上面的方法确实可以传递keyword,但是并不能传递 (message “hello”),这种形式会被eval成 “hello”传递,所以又想到宏1
2
3
4
5
6
7
8
9
10(defmacro* test-macro (name &key (init) (config) &allow-other-keys)
`(progn
(message "name is :%s" ,name)
(if (> ,(length name) 5)
,init
,config)))
(macroexpand '(test-macro "hi" :init (message "ok") :config (message "config")))
(test-macro "hi1234" :init (message "ok") :config (message "config"))
(test-macro "ojbk")
如上就可以使用关键字来初始化了。然而关键字后面有两个表达式的情况下不能解析,keyword 只认:init之后的第一个表达式.
3 关键字解析问题
通过宏将quote形式的参数传入,调用while时,内部不需要宏参数解析。参考了 defcustom宏的源码1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18(defmacro handle-params-macro (&rest args)
`(let ((params ',args)
current-arg
(init (list 'progn))
(config (list 'progn)))
(while params
(let ((value (pop params)))
(cond
((symbolp value) (setq current-arg value))
((eq current-arg :init) (setq init (append init (list value))))
((eq current-arg :config) (setq config (append config (list value))))
)))
(eval config)
config;init back value.
))
(setq x (handle-params-macro :init (message "hi") (message "hello") :config "ok" (message "ok")))
x
上面的方法解决了2中多form解析的问题,但是参数固定了,只有:init :config,要添加就需要修改代码,为了方便,让该宏自动查找:init这种参数并返回一个plist
4 keywords-to-plist
解决上面 #3 的 keyways 解析问题
1 | (defmacro keywords-to-plist (&rest args) |
That’s all.