How to work with tasks named after acronyms?

Say I want to make a mix task named URLShorten.

Thus: defmodule Mix.Tasks.URLShorten do

However, I saw that it is then named url_shorten when displaying mix help.

But mix url_shorten doesn’t work, because it looks for the task in a module named Mix.Tasks.UrlShorten, instead of Mix.Tasks.URLShorten.

How can I deal with these inflections?

2 Likes

I think you are dealing with a reversable transformation issue:

PascalCase <-> snake_case

How would we know to transform url_shorten to URLShorten? The only way to resolve it, is to stick with:

UrlShorten <-> url_shorten


Macro.underscore/1:

In general, underscore can be thought of as the reverse of camelize, however, in some cases formatting may be lost

3 Likes

Yes, but I think I saw somewhere there’s a way to “hardcode” it. To tell elixir/mix system that url_shorten should be inflected to URLShorten.

I can’t find it, though.

Using UrlShorten is one solution, for sure. But the naming convention itself tell us to stick to acronyms like URL…

1 Like

The functions that are doing the “work”:

Mix.Utils.module_name_to_command/2
Mix.Utils.command_to_module_name/1

Naming Conventions

For aliases, capital letters are kept in acronyms, like ExUnit.CaptureIO or Mix.SCM.

However:

https://github.com/elixir-lang/elixir/blob/master/lib/mix/test/mix/task_test.exs#L30

  message =
      "The task \"acronym.http\" could not be found because the module is named " <>
        "Mix.Tasks.Acronym.HTTP instead of Mix.Tasks.Acronym.Http as expected. " <>
        "Please rename it and try again"

    assert_raise Mix.NoTaskError, message, fn ->
      Mix.Task.run("acronym.http")
    end

So it would seem that mix task modules are an exception to the convention (i.e. conventions tend to be broken if there is a good reason - in this case to keep the logic of transforming mix task module names to command names and vice versa as simple as possible).

2 Likes

Wow, I am terribly late to the party, however I think I have your solution…

In your mix project configuration, you can configure a custom namespace for your app:

config :url_shorten,
  namespace: URLShorten

Like @peerreynders mentioned, you’re doing something contrary to the defaults, so mix tooling doesn’t know how to generate the “correct” PascalCase form. Explicitly configuring the :namespace config option seems to fix all of mix’s broken assumptions.

With that being said, it’s a good idea to stick to the defaults for this reason. :grin:

1 Like