What is this article all about?

This article explains all about creating custom mix tasks and documenting the created task.

Here, we fly in the space of Elixir to create mix tasks in mix project including with docs and short docs.

What is our Task?

Our Task is to list out the functions in the module passing as parameter to the task.

So, when you run the command mix my_tasks.functions ModuleName , it has to list out all the functions defined in the module ModuleName.

Before diving into coding, we have to understand few terms which will play a key role in creation of task.

Mix.Task

This is the simple module responsible for creating and controlling tasks.

To behave our module as a task we have to follow some naming conventions.

Our module name should start with Mix.Tasks for an example, if our task name is functions , then module name is Mix.Tasks.Functions and we have to use the task behavior module use Mix.Task a first line of code in our module .

taskrun/1

This acts as a callback function to our task. All your task logic resides inside this function. This function takes list of binary [binary] values and returns any

1
run([binary]) :: any

@shortdoc

This module attribute makes the task public with a short description that appears on mix help . It means when you execute a command mix help you can see all tasks available in the scope along with single line description about the task.

In addition we have two more attributes. @recursive used in umbrella projects to keep the task running continuously and @referred_cli_env which recommends environment to run task. We don’t need them now.

@moduledoc

This module attribute is used to describe all about task. So, when some one wants help about your task, The binary of this attribute is shown as a response to a request mix help my_tasks.functions .

Lets Create Task

Now it is time to create our task which list out all the functions defined inside the module passed as parameter.

Lets do this.

Create a new project

1
mix new my_tasks

Create Task directory

After creation of the project go to your lib directory and create one nested directory as mix/tasks . This is where all our tasks reside.

1
2
3
$ cd path/to/your/project
$ cd lib
$ mkdir -p mix/tasks

Testing Module Files

Now we will create two files in lib directory one hello.ex and other one is hi.ex with some random functions. We are going to list out those module functions using our task as proof of working.

This is how our files looks.

hello.ex

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#hello.ex
defmodule Hello do

  def hello1 do
    IO.puts "hello1"
  end

  def hello2 do
    IO.puts "hello2"
  end

  def hello3 do
    IO.puts "hello3"
  end

end

hi.ex

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#hi.ex
defmodule Hi do

  def hi1 do
    IO.puts "hi1"
  end

  def hi2 do
    IO.puts "hi2"
  end

  def hi3 do
    IO.puts "hi3"
  end

end

These files do nothing with the task literally. They are just for showing task demo.

Creating Task file

Now create a file functions.ex in the directory of tasks /lib/mix/tasks and add the following content.

1
2
3
4
5
6
7
8
9
10
defmodule Mix.Tasks.MyTasks.Functions do
   use Mix.Task
   def run([module_name]) do
     module = Module.concat Elixir,module_name
     data = apply(module, :__info__, [:functions])
     IO.inspect data
   end
end

#Task file with out shortdoc

Every module defined in the project has its own __info__ function, with that you can get all the information about the module. So, I am using this function by passing an atom :functions to get the list of functions.

Clarification

So far we have created three files lib/mix/tasks/functions.ex which is our task file and two more files lib/hello.ex and lib/hi.ex

Compiling the Project

So far we have created a task but it is not available until you compile your project.

Run the following command in your project root directory.

1
mix compile

After successful compilation you can run your task as

1
2
3
4
5
$ mix my_tasks.functions Hello
[hello1: 0, hello2: 0, hello3: 0]

$mix my_tasks.functions Hi
[hi1: 0, hi2: 0, hi3: 0]

If you see above outputs in your terminal, it means you are good to go.

As a final touch, let’s add docs to our task.

Till now, we have just created a task. We have not provided any docs for the task. So, you cannot find your task shown in the list when you try to execute mix help or mix help my_tasks.functions to available your task in the list, you suppose to add some module attributes to your task file.

Lets do that now .

You have to add module attributes @shortdoc and @moduledoc in task module . Keep your description simple and smart.

After adding the module attributes our file will look like following

1
2
3
4
5
6
7
8
9
#functions.ex

defmodule Mix.Tasks.MyTasks.Functions do
   use Mix.Task
   @shortdoc "Returns functions in Module"
   @moduledoc ~S"""
   This is used to list out the all available functions in the module.           
   You suppose to pass module_name as parameter to the task.
   #Usage
1
2
3
4
  mix my_tasks.functins Hello    ```    This list out all the functins in the module Hello    """    def run([module_name]) do
 module = Module.concat Elixir,module_name
 data = apply(module, :__info__, [:functions])
 IO.inspect data    end end

#Task with @shortdoc and @moduledoc

1
2
3
4
5
6
7


![img](/images/blog/SOFSiJHylCKMOb-9.png)

```elixir
mix help

img

shortdoc information of task

You can see your task in the list here with @shortdoc information saying #Returns functions in module

img

1
mix help my_tasks.functions

img

moduledoc information of task

Well, you successfully created your Elixir Project Tasks. Do some funny things playing with tasks to master the creation of tasks.

Happy long coding life !!