An open API service indexing awesome lists of open source software.

https://github.com/lujun9972/elake

elisp make
https://github.com/lujun9972/elake

Last synced: 6 months ago
JSON representation

elisp make

Awesome Lists containing this project

README

          

#+TITLE: Readme
#+AUTHOR: DarkSun
#+CATEGORY: elake
#+DATE: [2015-07-10 周五 16:58]
#+OPTIONS: ^:{}

* elake简介
仿真rake的elisp实现

* 使用方法
类似make,elake中的任务也分为两种,phony任务与file任务. 其中file任务对应操作系统中的一个文件路径.

一个任务的依赖任务是否执行由以下表格表示:
| 目标任务类型 | 依赖任务类型 | 依赖任务执行条件 |
|--------------+--------------+----------------------------------------------|
| phony任务 | phony任务 | 依赖任务未执行 |
| file任务 | phony任务 | 依赖任务未执行 |
| phony任务 | file任务 | 依赖任务对应的文件不存在 |
| file任务 | file任务 | 依赖任务对应的文件要比目标任务对应的文件更新 |

** 定义任务
定义任务的方法是使用宏 =(elake-task 目的任务 (依赖任务列表) 任务说明字符串 任务定义内容)=.

例如我们这样定义一个做饭的过程:
#+BEGIN_SRC emacs-lisp :tangle elakefile.el
(elake-task :purchaseVegetables nil
"任务1 -- 买菜"
(message "到沃尔玛去买菜。"))

(elake-task :cook (:purchaseVegetables)
"任务2 -- 做饭"
(message "做一顿香喷喷的饭菜。"))
#+END_SRC

上面代码定义了两个任务

第一个任务的名称为":purchaseVegetables",它以":"开头,因此是一个phony任务.

+ :purchaseVegetables任务的依赖任务列表为nil,表示它不依赖任何前置任务

+ :purchaseVegetables任务的说明是"任务1 -- 买菜"

+ :purchaseVegetables任务的内容是 =(message "到沃尔玛去买菜。")=

第二个任务的名称为":cook",它是一个phony任务. 它依赖于:purchaseVegetables任务.

因此,在执行:cook任务前会先执行:purchaseVegetables
#+BEGIN_EXAMPLE
$ elake :cook
到沃尔玛去买菜。
做一顿香喷喷的饭菜。
#+END_EXAMPLE
** 自动变量
在任务定义中,可以使用$<指代目标任务,使用$@指代依赖任务列表. 例如:
#+BEGIN_SRC emacs-lisp :tangle elakefile.el
(elake-task :task1 (/etc/passwd)
"测试自动变量"
(message "%s依赖于%s" $< $@))
#+END_SRC

执行任务:task1的结果为:
#+BEGIN_EXAMPLE
$ elake :task1
:task1依赖于(/etc/passwd)
#+END_EXAMPLE

** 默认构建任务
elake会将地一个定义的任务作为默认的构建任务. 当没有为elake指定构建哪个任务时,elake会构建默认的构建任务.

例如,上面的例子中,我们地一个定义的任务是:purchaseVegetables任务,因此直接调用elake的结果为:
#+BEGIN_EXAMPLE
$ elake
到沃尔玛去买菜。
#+END_EXAMPLE

** 命名空间
elake支持命名空间的概念. 使用命名空间的格式为 =(elake-namespace 命名空间名称 其他elake命令...)=

在命名空间内定义的phony任务,其完整的名称为":命名空间名称:任务名称",命名空间对file任务无效
例如:
#+BEGIN_SRC emacs-lisp :tangle elakefile.el
(elake-namespace home
(elake-task :write-blog (:turn-on-computer) ;注意,同一个命名空间内的依赖任务无需加命名空间前缀
"写博客"
(message "在家写博客"))
(elake-task :turn-on-computer ()
"打开电脑"
(message "打开家里的电脑")))
#+END_SRC

这里在home命名空间内定义了两个任务:":home:write-bog和:home:turn-on-computer".
#+BEGIN_EXAMPLE
$ elake :home:write-blog
打开家里的电脑
在家写博客
$ elake :write-blog
未定义的任务::write-blog
#+END_EXAMPLE

目前支持命名空间的函数还有`elake-execute-task'和`elake-remove-task'
** 给任务传递环境变量值
给elake传递形如"环境变量:=值"的参数,可以设定环境变量的值
#+BEGIN_SRC emacs-lisp :tangle elakefile.el
(elake-task :set-env nil
"设置环境变量"
(message "UNKNOW-ENV:%s" (getenv "UNKNOW-ENV")))
#+END_SRC

若不传递环境变量,则有:
#+BEGIN_EXAMPLE
$ elake :set-env
UNKNOW-ENV:nil
#+END_EXAMPLE

若传递环境变量,则:
#+BEGIN_EXAMPLE
$ elake :set-env UNKNOW-ENV:=whatever
UNKNOW-ENV:whatever
#+END_EXAMPLE

** 给任务传递参数值
可以在定义任务时,使用未定义的变量. 只需要通过形如"变量=值"的形式传递变量值就好. 例如
#+BEGIN_SRC emacs-lisp :tangle elakefile.el
(elake-task :say-hello-to nil
"给任务传递参数"
(message "hello to %s" who))
#+END_SRC

若不传递参数值,则会执行出错
#+BEGIN_EXAMPLE
$ elake :say-hello-to
Symbol's value as variable is void: who
#+END_EXAMPLE

若传递参数值,则
#+BEGIN_EXAMPLE
$ elake who=darksun :say-hello-to
hello to darksun
#+END_EXAMPLE

** 在任务中执行其他任务
使用 =(elake-execute-task task)= 可以在任务内执行其他任务
#+BEGIN_SRC emacs-lisp :tangle elakefile.el
(elake-task :laundry nil
"洗衣服"
(message "把所有衣服扔进洗衣机。"))
(elake-task :today nil
"今天的任务"
(elake-execute-task :home:write-blog)
(elake-execute-task :laundry))
#+END_SRC

则调用:today任务,会以此执行:home:write-blog和:laundry任务
#+BEGIN_EXAMPLE
$ elake :today
打开家里的电脑
在家写博客
把所有衣服扔进洗衣机。
#+END_EXAMPLE

** 在任务中删除其他任务
使用 =(elake-remove-task task)= 可以删除其他任务.例如
#+BEGIN_SRC emacs-lisp :tangle elakefile.el
(elake-task :task-to-be-removed nil
"待删除的任务"
(message "该任务会被:remove-task删除掉,删除掉后无法执行"))
(elake-task :remove-task (:task-to-be-removed)
"删除任务:task-to-be-removed"
(elake-remove-task :task-to-be-removed)
(message "%s被删除" $@))

(elake-task :execute-removed-task (:remove-task)
"删除任务测试"
(elake-execute-task :task-to-be-removed))

#+END_SRC

在执行:remove-task前,可以执行:task-to-be-removed
#+BEGIN_EXAMPLE
$ elake :remove-task
该任务会被:remove-task删除掉,删除掉后无法执行
(:task-to-be-removed)被删除
#+END_EXAMPLE

但执行:remove-task后,无法再执行:task-to-be-removed了
#+BEGIN_EXAMPLE
$ elake :execute-removed-task
该任务会被:remove-task删除掉,删除掉后无法执行
(:task-to-be-removed)被删除
未定义的任务::task-to-be-removed
#+END_EXAMPLE

** 使用规则自动生成任务
使用 =(elake-rule 目标任务的匹配正则表达式 依赖任务的替代表达式列表 任务内容)= 来定义规则,当执行未定义的任务时,elake会尝试使用规则生成该任务.

这里匹配正则表达式必须为字符串,替代表达式列表为字符串或字符串列表.

关于匹配正则表达式和替代表达式的说明请参见`replace-regexp'函数中的`REGEXP'和`TO-STRING'说明.

例如:
#+BEGIN_SRC emacs-lisp :tangle elakefile.el
(elake-rule ":make-\\(.+\\)" ("\\1")
"测试rule"
(message (shell-command-to-string (format "ls -l %s" (car $@)))))

(elake-rule "[^:].*" nil
"测试rule"
(message "touch %s" $<)
(message (shell-command-to-string (format "touch %s" $<))))
#+END_SRC

可以使用:make-xxx任务来显示xxx文件的内容,且若xxx文件不存在则创建该文件
#+BEGIN_EXAMPLE
$ ls -l rule
rule: No such file or directory
$ elake :make-rule
touch rule

-rw-rw-r-- 1 lujun9972 lujun9972 0 7月 19 11:53 rule

$ elake :make-rule
-rw-rw-r-- 1 lujun9972 lujun9972 0 7月 19 11:53 rule

#+END_EXAMPLE

** 依赖任务列表中支持使用S-Form自动生成依赖任务
依赖任务列表中支持使用S-Form自动生产依赖任务,若依赖任务为list,则该list会被作为S-Form来执行,该S-Form的执行结果应该为一个包含一个多个多个依赖任务的list.

例如:
#+BEGIN_SRC emacs-lisp :tangle elakefile.el
(elake-task :blog (index.html (let (files)
(dotimes (num 3 files)
(push (format "file-%s.html" num) files))))
"测试使用S-Form自动生成依赖任务"
(message "%s的依赖任务为%s" $< $@))
#+END_SRC

表示:blog的依赖任务为index.html,file-2.html,file-1.html,file-0.html

因此:
#+BEGIN_EXAMPLE
~/elake $ elake :blog
touch index.html

touch file-2.html

touch file-1.html

touch file-0.html

:blog的依赖任务为(index.html file-2.html file-1.html file-0.html)
#+END_EXAMPLE
** 其他参数说明
+ -f 配置文件路径 :: 使用指定的文件作为加载的配置文件. 默认使用`elakefile'或`elakefile.el'或`elakefile.elc'
+ --task 任务... :: 显示任务说明,若省略后面的任务,则显示所有任务说明
+ -p 任务... :: 显示任务的依赖任务,若省略后面的任务,则显示所有的任务依赖
+ -h :: 显示帮助信息
* 待完成事项
+ [X] 增加file类型的任务
+ [X] 增加命名空间的支持
+ [X] 仿照make添加一些自动变量
+ [X] 仿照make将第一个定义的任务作为默认的构建任务
+ [ ] 如何支持emacs本身已经占有的那些option呢?
+ [ ] 如何区分传递符号和字符串給emacs --script呢?
+ [ ] 支持定义任务和定义依赖相分离
+ [ ] 支持分多次添加依赖关系,这样就能用程序自动添加依赖关系
+ [X] 支持模式规则来自动生成某类文件
+ [X] 支持使用-f指定依赖文件,默认为elakefile或elakefile.el或elakefile.elc
+ [X] 支持带参数的任务
+ [X] 支持命令行设置环境参数
+ [X] 提供删除已定义任务的机制
+ [X] 依赖任务列表中支持使用S-Form自动生成依赖任务