Repository: dashbitco/nimble_options (elixir)

Issue:
Hiding options with "doc: false"
Sometimes some options are internal but you still want to validated them. What do you folks think if we add support for `doc: false` to hide an option? I think that aligns with how we do docs in general.

Pull request description:
Add support for "doc: false"
Closes #23.

* We don't show an option in the docs if `doc: false`
* We don't show the entire subsection in the docs if the parent option has `doc: false`

Patch:
diff --git a/lib/nimble_options.ex b/lib/nimble_options.ex
index ebd7f0e..ec16632 100644
--- a/lib/nimble_options.ex
+++ b/lib/nimble_options.ex
@@ -41,7 +41,7 @@ defmodule NimbleOptions do
           """
         ],
         doc: [
-          type: :string,
+          type: {:custom, __MODULE__, :validate_doc, []},
           doc: "The documentation for the option item."
         ],
         subsection: [
@@ -478,4 +478,13 @@ defmodule NimbleOptions do
   def type(value) do
     {:error, "invalid option type #{inspect(value)}.\n\nAvailable types: #{available_types()}"}
   end
+
+  @doc false
+  def validate_doc(doc) do
+    if is_binary(doc) or doc == false do
+      {:ok, doc}
+    else
+      {:error, "expected :doc to be a string or false, got: #{inspect(doc)}"}
+    end
+  end
 end
diff --git a/lib/nimble_options/docs.ex b/lib/nimble_options/docs.ex
index 682dd06..e6599fe 100644
--- a/lib/nimble_options/docs.ex
+++ b/lib/nimble_options/docs.ex
@@ -17,7 +17,7 @@ defmodule NimbleOptions.Docs do
     if schema[:*] do
       build_docs(schema[:*][:keys], acc)
     else
-      Enum.reduce(schema, {docs, sections, level}, &option_doc/2)
+      Enum.reduce(schema, {docs, sections, level}, &maybe_option_doc/2)
     end
   end
 
@@ -30,6 +30,14 @@ defmodule NimbleOptions.Docs do
     {docs, [item_section | sections], level}
   end
 
+  defp maybe_option_doc({key, schema}, acc) do
+    if schema[:doc] == false do
+      acc
+    else
+      option_doc({key, schema}, acc)
+    end
+  end
+
   defp option_doc({key, schema}, {docs, sections, level}) do
     description =
       [get_required_str(schema), get_doc_str(schema), get_default_str(schema)]


Test patch:
diff --git a/test/nimble_options_test.exs b/test/nimble_options_test.exs
index 279c75b..73703a1 100644
--- a/test/nimble_options_test.exs
+++ b/test/nimble_options_test.exs
@@ -873,6 +873,41 @@ defmodule NimbleOptionsTest do
 
       assert NimbleOptions.docs(schema) == docs
     end
+
+    test "the option doesn't appear in the documentation when the :doc option is false" do
+      schema = [
+        name: [type: :atom, doc: "An atom."],
+        secret: [type: :string, doc: false],
+        count: [type: :integer]
+      ]
+
+      docs = """
+        * `:name` - An atom.
+
+        * `:count`
+
+      """
+
+      assert NimbleOptions.docs(schema) == docs
+    end
+
+    test "the option and its children don't appear in the documentation when the :doc option is false" do
+      schema = [
+        producer: [
+          type: :keyword_list,
+          doc: false,
+          keys: [
+            name: [type: :atom],
+            concurrency: [type: :pos_integer]
+          ]
+        ]
+      ]
+
+      docs = """
+      """
+
+      assert NimbleOptions.docs(schema) == docs
+    end
   end
 
   def buffer_keep(value) when value in [:first, :last] do