177 lines
4.9 KiB
Elixir
177 lines
4.9 KiB
Elixir
defmodule LanguageColours do
|
|
@moduledoc """
|
|
LanguageColours offers an API for retrieving colours for programming languages based on GitHub
|
|
colour data (or some other dataset).
|
|
|
|
```iex
|
|
iex> LanguageColours.get("Ada", :my_db)
|
|
"#02f88c"
|
|
```
|
|
|
|
To install, add LanguageColours as a dependency of your Mix project:
|
|
|
|
```elixir
|
|
defp deps do
|
|
[
|
|
{:language_colours, "~> 1.0.0"},
|
|
...
|
|
]
|
|
end
|
|
```
|
|
|
|
## Databases
|
|
|
|
LanguageColours can be served by different databases. Databases must conform to the
|
|
`LanguageColours.Database` behaviour. There is one database included, the
|
|
`LanguageColours.ETSDatabase`, that uses ETS to store the language colour data. As a source, it
|
|
uses a JSON file in the format found in the https://github.com/ozh/github-colors/ repo. This
|
|
file can be downloaded in a development environment with `mix language.colours.dl.data`.
|
|
|
|
## Fallback colours
|
|
|
|
If a language is not found in the database, `nil` will be returned by default. Optionally, the
|
|
[Rainbow](https://hex.pm/packages/rainbow) package can be used to generate a random colour based
|
|
on the language name as fallback. To use the fallback, set the database configuration option
|
|
`:fallback` to `true`, and install Rainbow as a dependency:
|
|
|
|
```elixir
|
|
defp deps do
|
|
[
|
|
{:rainbow, "~> 0.1.0"},
|
|
...
|
|
]
|
|
end
|
|
```
|
|
|
|
## Configuration
|
|
|
|
To configure a database, you can give the configuration directly in the function call:
|
|
|
|
```elixir
|
|
config = %{...}
|
|
LanguageColours.get("C++", config)
|
|
```
|
|
|
|
Or you can configure database aliases in your favourite config file (`runtime.exs` is
|
|
recommended so you don't need to recompile the app on config changes):
|
|
|
|
```elixir
|
|
# Config file
|
|
config :language_colours,
|
|
databases: %{
|
|
foo_db: %{
|
|
...
|
|
}
|
|
}
|
|
```
|
|
|
|
Then you can use this name in the function call:
|
|
|
|
```elixir
|
|
LanguageColours.get("COBOL", :foo_db)
|
|
```
|
|
|
|
The supported configuration options are:
|
|
|
|
* `:json_parser`: Module name of the JSON parser to use. Default is
|
|
[Jason](https://hex.pm/packages/jason).
|
|
* `:databases`: An atom-keyed map of database specific configurations, which can be maps
|
|
themselves or keyword lists.
|
|
|
|
The database specific configuration options are:
|
|
|
|
* `:db`: The database module to use. This option is required.
|
|
* `:fallback`: Boolean specifying whether to get a fallback colour from Rainbow or not, if
|
|
language was not found in database. Default `false`.
|
|
|
|
Additionally, the ETSDatabase has its own database specific options:
|
|
|
|
* `:file`: Path to the file to read the JSON data from.
|
|
* `:server_name`: The name to use for the database process. Must conform to
|
|
`t:GenServer.name/0`. By default the module name is used.
|
|
* `:ets_table`: Name of the ETS table to use.
|
|
|
|
## Setting up using ETSDatabase
|
|
|
|
First configure your database. Then start the database in your supervisor using the
|
|
`LanguageColours.ETSDatabase.startup_options/1` function like this:
|
|
|
|
```elixir
|
|
config = LanguageColours.config!(:foo_db)
|
|
children = [
|
|
...,
|
|
{LanguageColours.ETSDatabase, LanguageColours.ETSDatabase.startup_options(config)},
|
|
...
|
|
]
|
|
```
|
|
|
|
Alternatively you can directly give the `t:LanguageColours.ETSDatabase.Options.t/0` struct as
|
|
the argument.
|
|
"""
|
|
|
|
@doc """
|
|
Get the colour corresponding to the given language.
|
|
|
|
The database specified in the second argument (as configuration or preconfigured database name)
|
|
is used to fetch the language. If the language is not found and fallback is not configured,
|
|
`nil` is returned.
|
|
"""
|
|
@spec get(String.t(), atom() | keyword() | map()) :: LanguageColours.Colour.t() | nil
|
|
def get(language, db_or_config)
|
|
|
|
def get(language, db) when is_atom(db) do
|
|
config = config!(db)
|
|
|
|
get(language, config)
|
|
end
|
|
|
|
def get(language, config) when is_list(config) do
|
|
get(language, Map.new(config))
|
|
end
|
|
|
|
def get(language, config) when is_map(config) do
|
|
colour = config.db.get(language, config)
|
|
|
|
if is_nil(colour) && Map.get(config, :fallback) do
|
|
Rainbow.colorize(language, format: "hexcolor")
|
|
else
|
|
colour
|
|
end
|
|
end
|
|
|
|
@doc """
|
|
Update the database specified in the argument.
|
|
|
|
The argument may be a preconfigured database name or a configuration map/kwlist.
|
|
"""
|
|
@spec update(atom() | keyword() | map()) :: :ok
|
|
def update(db_or_config)
|
|
|
|
def update(db) when is_atom(db) do
|
|
config = config!(db)
|
|
|
|
update(config)
|
|
end
|
|
|
|
def update(config) when is_list(config) do
|
|
update(Map.new(config))
|
|
end
|
|
|
|
def update(config) when is_map(config) do
|
|
config.db.update(config)
|
|
end
|
|
|
|
@doc """
|
|
Retrieve the configuration for the given database name.
|
|
|
|
If the database is not configured, an error will be raised.
|
|
"""
|
|
@spec config!(atom()) :: map()
|
|
def config!(db) do
|
|
conf =
|
|
Application.get_env(:language_colours, :databases) ||
|
|
raise "LanguageColours databases not configured!"
|
|
|
|
Map.get(conf, db) || raise "Configuration for #{inspect(db)} colour database not found!"
|
|
end
|
|
end
|