55defmodule Mix.Tasks.Help do
66 use Mix.Task
77
8- @ shortdoc "Prints help information for tasks"
8+ @ shortdoc "Prints help information for tasks, aliases, modules, and applications "
99
1010 @ moduledoc """
11- Lists all tasks and aliases or prints the documentation for a given task or alias .
11+ Prints documentation for tasks, aliases, modules, and applications .
1212
13- ## Arguments
13+ ## Examples
14+
15+ Without an explicit argument, this task lists tasks/aliases:
1416
1517 $ mix help - prints all aliases, tasks and their short descriptions
16- $ mix help ALIAS - prints the definition for the given alias
17- $ mix help TASK - prints full docs for the given task
1818 $ mix help --search PATTERN - prints all tasks and aliases that contain PATTERN in the name
1919 $ mix help --names - prints all task names and aliases (useful for autocompletion)
2020 $ mix help --aliases - prints all aliases
2121
22+ You can access documentation for a given task/alias:
23+
24+ $ mix help TASK/ALIAS - prints full docs for the given task/alias
25+
26+ But also for modules, functions, and applications:
27+
28+ $ mix help MODULE - prints the definition for the given module
29+ $ mix help MODULE.FUN - prints the definition for the given module+function
30+ $ mix help app:APP - prints a summary of all public modules in application
31+
2232 ## Colors
2333
2434 When possible, `mix help` is going to use coloring for formatting
@@ -100,6 +110,31 @@ defmodule Mix.Tasks.Help do
100110
101111 @ compile { :no_warn_undefined , IEx.Introspection }
102112
113+ def run ( [ "app:" <> app ] ) do
114+ loadpaths! ( )
115+ app = String . to_atom ( app )
116+
117+ if modules = Application . spec ( app , :modules ) do
118+ for module <- modules ,
119+ not ( module |> Atom . to_string ( ) |> String . starts_with? ( "Elixir.Mix.Tasks." ) ) ,
120+ { :docs_v1 , _ , :elixir , "text/markdown" , % { "en" => << doc :: binary >> } , _ , _ } <-
121+ [ Code . fetch_docs ( module ) ] do
122+ leading = doc |> String . split ( [ "\n \n " , "\r \n \r \n " ] , parts: 2 ) |> hd ( )
123+ "# #{ inspect ( module ) } \n #{ leading } \n "
124+ end
125+ |> case do
126+ [ ] ->
127+ Mix . shell ( ) . error ( "No modules with accessible documentation found for #{ app } " )
128+
129+ listing ->
130+ docs = listing |> Enum . sort ( ) |> Enum . join ( )
131+ IO.ANSI.Docs . print ( docs , "text/markdown" , ansi_opts ( ) )
132+ end
133+ else
134+ Mix . shell ( ) . error ( "Application #{ app } does not exist or is not loaded" )
135+ end
136+ end
137+
103138 def run ( [ module = << first , _ :: binary >> ] ) when first in ?A .. ?Z or first == ?: do
104139 loadpaths! ( )
105140
@@ -124,8 +159,7 @@ defmodule Mix.Tasks.Help do
124159
125160 def run ( [ task ] ) do
126161 loadpaths! ( )
127- opts = Application . get_env ( :mix , :colors )
128- opts = [ width: width ( ) , enabled: ansi_docs? ( opts ) ] ++ opts
162+ opts = ansi_opts ( )
129163
130164 for doc <- verbose_doc ( task ) do
131165 print_doc ( task , doc , opts )
@@ -138,6 +172,11 @@ defmodule Mix.Tasks.Help do
138172 Mix . raise ( "Unexpected arguments, expected \" mix help\" or \" mix help TASK\" " )
139173 end
140174
175+ defp ansi_opts do
176+ opts = Application . get_env ( :mix , :colors )
177+ [ width: width ( ) , enabled: ansi_docs? ( opts ) ] ++ opts
178+ end
179+
141180 defp print_doc ( task , { doc , location , note } , opts ) do
142181 IO.ANSI.Docs . print_headings ( [ "mix #{ task } " ] , opts )
143182 IO.ANSI.Docs . print ( doc , "text/markdown" , opts )
0 commit comments