查看源代码 Mix.Task 行为 (Mix v1.16.2)
提供创建、加载和操作 Mix 任务的便利功能。
Mix 任务可以通过在以 Mix.Tasks.
开头的模块中使用 use Mix.Task
来定义,并且该模块定义了 run/1
函数。通常,任务模块位于 lib/mix/tasks/
目录中,并且它们的文件名使用点号分隔符而不是下划线(例如 deps.clean.ex
) - 尽管最终文件名并不重要。
例如
# lib/mix/tasks/echo.ex
defmodule Mix.Tasks.Echo do
@moduledoc "Printed when the user requests `mix help echo`"
@shortdoc "Echoes arguments"
use Mix.Task
@impl Mix.Task
def run(args) do
Mix.shell().info(Enum.join(args, " "))
end
end
命令名称将对应于模块名称中 Mix.Tasks.
之后的部分。例如,模块名称为 Mix.Tasks.Deps.Clean
对应于任务名称 deps.clean
。
run/1
函数将根据用户的终端接收传递的所有命令行参数的列表。
例如,如果上面 echo
任务中的 args
被检查,你可能会看到类似以下内容
$ mix echo 'A and B' C --test
["A and B", "C", "--test"]
use Mix.Task
当你使用
use Mix.Task
时,Mix.Task
模块将设置@behaviour Mix.Task
并且为下面部分中记录的模块属性定义默认值。
模块属性
你可以通过设置模块属性来控制 Mix 任务的一些行为。本节记录了可用的属性。
@shortdoc
如果你希望在 mix help
上公开显示任务,请定义 @shortdoc
属性。如果你不希望你的任务通过 mix help
列出,请省略此属性。
@moduledoc
@moduledoc
属性可以覆盖 @shortdoc
。如果使用 @moduledoc false
隐藏整个模块的文档,则该任务不会出现在 mix help
中。
@requirements
如果一个任务有需求,可以使用 @requirements
属性列出它们。需求是该任务需要运行的其他 Mix 任务。例如
@requirements ["app.config"]
一个任务通常依赖于以下任务之一
"loadpaths" - 这确保依赖项可用并被编译。如果你将任务作为库的一部分发布供他人使用,并且你的任务不需要以任何方式与用户代码交互,这是推荐的依赖项
"app.config" - 此外,还会编译和加载当前项目的运行时配置。如果你正在创建一个将在你的应用程序内或作为库的一部分使用的任务,并且该任务必须调用或与用户代码交互,这是推荐的最小依赖项
"app.start" - 此外,还会启动当前项目及其依赖项的监督树
@recursive
如果你希望任务在伞形项目中的每个伞形子项目上运行,请设置 @recursive true
。
@preferred_cli_env
设置此任务的首选 Mix 环境。例如,如果你的任务旨在用于测试,你可以设置
@preferred_cli_env :test
文档
用户可以通过运行 mix help my_task
来阅读公共 Mix 任务的文档。将显示的文档是任务模块的 @moduledoc
。
概述
回调
一个任务需要实现 run
,它接收一个命令行参数列表。
函数
检查给定的 task
名称是否是一个别名。
返回所有已加载的任务模块。
清除所有已调用的任务,允许它们被重新调用。
接收一个任务名称并返回相应的任务模块(如果存在)。
接收一个任务名称并检索相应的任务模块。
加载所有代码路径中的所有任务。
加载给定 paths
中的所有任务。
获取给定任务 module
的模块文档。
为了向后兼容而保留。
指示当前任务是否正在递归。
检查任务是否应该在伞形项目中的所有子应用程序中递归运行。
重新启用给定任务,使其能够在堆栈中再次执行。
获取给定任务的依赖项列表。
使用给定参数重新运行 task
。
有条件地运行任务(或别名)以及给定的 args
。
在伞形项目中为指定的子应用程序列表运行递归任务。
获取给定任务 module
的简短文档。
如果给定模块是一个任务,则返回 true
。
返回给定 module
的任务名称。
类型
回调
函数
检查给定的 task
名称是否是一个别名。
如果给定名称不是别名或不是任务,则返回 false
。
@spec all_modules() :: [task_module()]
返回所有已加载的任务模块。
尚未加载的模块不会显示。如果你想预加载所有任务,请检查 load_all/0
。
@spec clear() :: :ok
清除所有已调用的任务,允许它们被重新调用。
此操作不是递归的。
@spec get(task_name()) :: task_module() | nil
接收一个任务名称并返回相应的任务模块(如果存在)。
如果模块找不到,是别名或不是有效的 Mix.Task
,则返回 nil
。
@spec get!(task_name()) :: task_module()
接收一个任务名称并检索相应的任务模块。
异常
Mix.NoTaskError
- 如果找不到任务,则引发此异常Mix.InvalidTaskError
- 如果任务不是有效的Mix.Task
,则引发此异常
@spec load_all() :: [task_module()]
加载所有代码路径中的所有任务。
@spec load_tasks([List.Chars.t()]) :: [task_module()]
加载给定 paths
中的所有任务。
@spec moduledoc(task_module()) :: String.t() | nil | false
获取给定任务 module
的模块文档。
返回模块文档或 nil
。
为了向后兼容而保留。
@spec recursing?() :: boolean()
指示当前任务是否正在递归。
如果一个任务被标记为递归,并且它在伞形项目中执行,则返回 true
。
@spec recursive(task_module()) :: boolean()
检查任务是否应该在伞形项目中的所有子应用程序中递归运行。
返回 true
或 false
。
@spec reenable(task_name()) :: :ok
重新启用给定任务,使其能够在堆栈中再次执行。
当调用此函数时,别名和常规堆栈都将被重新启用。
如果一个伞形项目重新启用一个任务,则该任务将对所有子项目重新启用。
@spec requirements(task_module()) :: []
获取给定任务的依赖项列表。
返回一个字符串列表,其中字符串预期是一个任务,后面可以选择是它的参数。
使用给定参数重新运行 task
。
此函数重新运行给定的任务;为此,它首先重新启用该任务,然后像正常运行一样运行它。
有条件地运行任务(或别名)以及给定的 args
。
如果存在与给定任务名称匹配的任务,并且该任务尚未被调用,则将使用给定的 args
运行该任务并返回结果。
如果为给定的任务名称定义了 别名,则将调用别名,而不是原始任务。
如果任务或别名已经调用,则对 run/2
的后续调用将中止,不执行并返回 :noop
。
请记住:默认情况下,任务只运行一次,即使多次调用也是如此!如果你需要多次运行任务,你需要通过 reenable/1
重新启用它,或者使用 rerun/2
调用它。
run/2
如果找不到别名或任务,或者任务无效,则引发异常。有关更多信息,请参阅 get!/1
。
示例
iex> Mix.Task.run("format", ["mix.exs"])
:ok
在伞形项目中为指定的子应用程序列表运行递归任务。
如果该任务不是递归任务(其目的是在子应用程序中运行),它将像往常一样在项目根级别运行。在伞形项目根目录之外调用此函数将失败。
@spec shortdoc(task_module()) :: String.t() | nil
获取给定任务 module
的简短文档。
返回简短文档或 nil
。
@spec task?(task_module()) :: boolean()
如果给定模块是一个任务,则返回 true
。
@spec task_name(task_module()) :: task_name()
返回给定 module
的任务名称。
示例
iex> Mix.Task.task_name(Mix.Tasks.Test)
"test"