From ce4fcf5402cf03004dba79ab302700e21241c768 Mon Sep 17 00:00:00 2001 From: Adam Mokan Date: Mon, 7 Oct 2024 16:34:56 -0700 Subject: [PATCH] updates for v0.6.0 --- CHANGELOG.md | 13 ++++ README.md | 21 +++++- lib/human_name.ex | 119 ++++++++++++++++++++++--------- lib/human_name/native.ex | 19 ++--- mix.exs | 2 +- native/human_name_nif/Cargo.lock | 2 +- native/human_name_nif/Cargo.toml | 2 +- native/human_name_nif/src/lib.rs | 57 ++++++++++----- 8 files changed, 167 insertions(+), 68 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 17ce0ea..f72dd69 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog +## v0.6.0 (2024-10-07) + +* Updated crate for `rustler` (_0.34.0_). +* Contributions from @lessless (_and @rogerbooth_): + * Added `HumanName.consistent_with?/2`. + * Added `HumanName.first_and_last_initials/1`. + * Added `HumanName.middle_name/1`. + * Added `HumanName.middle_initials/1`. +* Added `HumanName.last_initial/1`. +* Depreciation message added for `HumanName.initials/1`. +* General cleanup and additions to the doc tests. +* Dependency updates for `ex_doc`, `excoveralls`, `rustler` and `rustler_precompiled`. + ## v0.5.0 (2024-03-24) * Updated crates for `human_name` (_2.0.3_) and `rustler` (_0.29.1_). diff --git a/README.md b/README.md index 5cde913..4f3d6a9 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ This package can be installed by adding `human_name` to your list of dependencie ```elixir def deps do [ - {:human_name, "~> 0.5.0"} + {:human_name, "~> 0.6.0"} ] end ``` @@ -36,15 +36,30 @@ config :human_name, HumanName, build_from_source: true ## Usage ```elixir -iex> HumanName.first_name("Dr. Alibaster Cornelius Juniper III") -{:ok, "Alibaster"} +iex> HumanName.consistent_with?("Jimmy H Jenkins", "Jim Jenkins") +{:ok, true} iex> HumanName.first_and_last_initials("Dr. Alibaster Cornelius Juniper III") {:ok, "AJ"} +iex> HumanName.first_initial("Dr. Alibaster Cornelius Juniper III") +{:ok, "A"} + +iex> HumanName.first_initial_last("Jimmy H Jenkins") +{:ok, "J. Jenkins"} + +iex> HumanName.first_name("Dr. Alibaster Cornelius Juniper III") +{:ok, "Alibaster"} + iex> HumanName.middle_initials("Dr. Alibaster Cornelius Juniper III") {:ok, "C"} +iex> HumanName.middle_name("Dr. Alibaster Cornelius Juniper III") +{:ok, "Cornelius"} + +iex> HumanName.last_initial("Jimmy H Jenkins") +{:ok, "J"} + iex> HumanName.last_name("Dr. Alibaster Cornelius Juniper III") {:ok, "Juniper"} diff --git a/lib/human_name.ex b/lib/human_name.ex index 4cf58f4..88833dc 100644 --- a/lib/human_name.ex +++ b/lib/human_name.ex @@ -22,6 +22,9 @@ defmodule HumanName do iex> HumanName.consistent_with?("Dr. Alibaster Cornelius Juniper III", "Alibaster Juniper") {:ok, true} + iex> HumanName.consistent_with?("Jane Doe", "J. Doe") + {:ok, true} + iex> HumanName.consistent_with?("Dr. Alibaster Cornelius Juniper III", "Jimmy H Jenkins") {:ok, false} @@ -44,7 +47,29 @@ defmodule HumanName do def consistent_with?(_, _), do: names_not_provided() @doc """ - Returns the initial for the first (given) name. + Returns the combined initials for the first name (given name) and last name (surname). + + ## Example + + iex> HumanName.first_and_last_initials("Jimmy H Jenkins") + {:ok, "JJ"} + + iex> HumanName.first_and_last_initials("Dr. Alibaster Cornelius Juniper III") + {:ok, "AJ"} + + iex> HumanName.first_and_last_initials("Jane Doe") + {:ok, "JD"} + + iex> HumanName.first_and_last_initials("") + {:error, "No valid name found"} + """ + def first_and_last_initials(full_name) when is_non_empty_binary(full_name), + do: HumanName.Native.first_and_last_initials(full_name) + + def first_and_last_initials(_), do: name_not_provided() + + @doc """ + Returns the initial for the first name (given name). ## Example @@ -54,6 +79,9 @@ defmodule HumanName do iex> HumanName.first_initial("Dr. Alibaster Cornelius Juniper III") {:ok, "A"} + iex> HumanName.first_initial("Jane Doe") + {:ok, "J"} + iex> HumanName.first_initial(12345) {:error, "No valid name found"} @@ -69,7 +97,7 @@ defmodule HumanName do def first_initial(_), do: name_not_provided() @doc """ - Returns the initial for the first (given) name and the full last name (surname). + Returns the initial for the first name (given name) and the full last name (surname). ## Example @@ -79,6 +107,9 @@ defmodule HumanName do iex> HumanName.first_initial_last("Dr. Alibaster Cornelius Juniper III") {:ok, "A. Juniper"} + iex> HumanName.first_initial_last("Jane Doe") + {:ok, "J. Doe"} + iex> HumanName.first_initial_last("") {:error, "No valid name found"} """ @@ -88,7 +119,7 @@ defmodule HumanName do def first_initial_last(_), do: name_not_provided() @doc """ - Returns just the formatted first (given) name. + Returns just the formatted first name (given name). ## Example @@ -98,6 +129,9 @@ defmodule HumanName do iex> HumanName.first_name("Dr. Alibaster Cornelius Juniper III") {:ok, "Alibaster"} + iex> HumanName.first_name("Jane Doe") + {:ok, "Jane"} + iex> HumanName.first_name("") {:error, "No valid name found"} """ @@ -106,27 +140,13 @@ defmodule HumanName do def first_name(_), do: name_not_provided() - @doc """ - Returns the inferred middle name for a provided full name. - - ## Example - - iex> HumanName.middle_name("Dr. Alibaster Cornelius Juniper III") - {:ok, "Cornelius"} - - iex> HumanName.middle_name("Jimmy H Jenkins") - {:error, "No middle name found"} - - iex> HumanName.middle_name("") - {:error, "No valid name found"} - """ - def middle_name(full_name) when is_non_empty_binary(full_name), - do: HumanName.Native.middle_name(full_name) - - def middle_name(_), do: name_not_provided() + @doc deprecated: "Use HumanName.first_and_last_initials/1 instead" + # coveralls-ignore-start + def initials(full_name), do: first_and_last_initials(full_name) + # coveralls-ignore-stop @doc """ - Returns the middle initials for a provided full name. + Returns the middle initial(s) for a provided full name. ## Example @@ -136,6 +156,9 @@ defmodule HumanName do iex> HumanName.middle_initials("Jimmy H Jenkins") {:ok, "H"} + iex> HumanName.middle_initials("Jane Dorothy Doe") + {:ok, "D"} + iex> HumanName.middle_initials("Jimmy Jenkins") {:error, "No middle initials found"} @@ -148,28 +171,48 @@ defmodule HumanName do def middle_initials(_), do: name_not_provided() @doc """ - Returns the combined initials for the first (given) name and last (surname) name. + Returns the inferred middle name for a provided full name. ## Example - iex> HumanName.first_and_last_initials("Jimmy H Jenkins") - {:ok, "JJ"} + iex> HumanName.middle_name("Dr. Alibaster Cornelius Juniper III") + {:ok, "Cornelius"} - iex> HumanName.first_and_last_initials("Dr. Alibaster Cornelius Juniper III") - {:ok, "AJ"} + iex> HumanName.middle_name("Jane Dorothy Doe") + {:ok, "Dorothy"} - iex> HumanName.first_and_last_initials("") + iex> HumanName.middle_name("Jimmy H Jenkins") + {:error, "No middle name found"} + + iex> HumanName.middle_name("") {:error, "No valid name found"} """ - def first_and_last_initials(full_name) when is_non_empty_binary(full_name), - do: HumanName.Native.first_and_last_initials(full_name) + def middle_name(full_name) when is_non_empty_binary(full_name), + do: HumanName.Native.middle_name(full_name) - def first_and_last_initials(_), do: name_not_provided() + def middle_name(_), do: name_not_provided() - @doc deprecated: "Use HumanName.first_and_last_initials/1 instead" - # coveralls-ignore-start - def initials(full_name), do: first_and_last_initials(full_name) - # coveralls-ignore-stop + @doc """ + Returns just the formatted last name (surname). + + ## Example + + iex> HumanName.last_initial("Jimmy H Jenkins") + {:ok, "J"} + + iex> HumanName.last_initial("Dr. Alibaster Cornelius Juniper III") + {:ok, "J"} + + iex> HumanName.last_initial("Jane Doe") + {:ok, "D"} + + iex> HumanName.last_initial("") + {:error, "No valid name found"} + """ + def last_initial(full_name) when is_non_empty_binary(full_name), + do: HumanName.Native.last_initial(full_name) + + def last_initial(_), do: name_not_provided() @doc """ Returns just the formatted last name (surname). @@ -182,6 +225,9 @@ defmodule HumanName do iex> HumanName.last_name("Dr. Alibaster Cornelius Juniper III") {:ok, "Juniper"} + iex> HumanName.last_name("Jane Doe") + {:ok, "Doe"} + iex> HumanName.last_name("") {:error, "No valid name found"} """ @@ -223,6 +269,9 @@ defmodule HumanName do iex> HumanName.normalize_full("Dr. Alibaster Cornelius Juniper III") {:ok, "Alibaster Cornelius Juniper, III"} + iex> HumanName.normalize_full("fred mccalister ") + {:ok, "Fred McCalister"} + iex> HumanName.normalize_full("") {:error, "No valid name found"} """ diff --git a/lib/human_name/native.ex b/lib/human_name/native.ex index d9a5cac..73df8ed 100644 --- a/lib/human_name/native.ex +++ b/lib/human_name/native.ex @@ -18,10 +18,13 @@ defmodule HumanName.Native do version: version @doc false - def first_initial(_full_name), do: err() + def consistent_with(_full_name_one, _full_name_two), do: err() @doc false - def consistent_with(_full_name_one, _full_name_two), do: err() + def first_and_last_initials(_full_name), do: err() + + @doc false + def first_initial(_full_name), do: err() @doc false def first_initial_last(_full_name), do: err() @@ -30,16 +33,16 @@ defmodule HumanName.Native do def first_name(_full_name), do: err() @doc false - def middle_name(_full_name), do: err() + def last_initial(_full_name), do: err() @doc false - def middle_initials(_full_name), do: err() + def last_name(_full_name), do: err() @doc false - def first_and_last_initials(_full_name), do: err() + def middle_name(_full_name), do: err() @doc false - def last_name(_full_name), do: err() + def middle_initials(_full_name), do: err() @doc false def normalize(_full_name), do: err() @@ -47,7 +50,5 @@ defmodule HumanName.Native do @doc false def normalize_full(_full_name), do: err() - defp err() do - :erlang.nif_error(:nif_not_loaded) - end + defp err(), do: :erlang.nif_error(:nif_not_loaded) end diff --git a/mix.exs b/mix.exs index 020530e..c01d897 100644 --- a/mix.exs +++ b/mix.exs @@ -1,7 +1,7 @@ defmodule HumanName.MixProject do use Mix.Project - @version "0.5.0" + @version "0.6.0" @description "Elixir bindings for the human-name crate implemented as a safe Rust NIF." @repo_url "https://github.com/amokan/human_name" diff --git a/native/human_name_nif/Cargo.lock b/native/human_name_nif/Cargo.lock index 3929b26..4d34bd7 100644 --- a/native/human_name_nif/Cargo.lock +++ b/native/human_name_nif/Cargo.lock @@ -73,7 +73,7 @@ dependencies = [ [[package]] name = "human_name_nif" -version = "0.5.0" +version = "0.6.0" dependencies = [ "human_name", "rustler", diff --git a/native/human_name_nif/Cargo.toml b/native/human_name_nif/Cargo.toml index 0eb3338..3a11ab1 100644 --- a/native/human_name_nif/Cargo.toml +++ b/native/human_name_nif/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "human_name_nif" -version = "0.5.0" +version = "0.6.0" authors = [] edition = "2018" diff --git a/native/human_name_nif/src/lib.rs b/native/human_name_nif/src/lib.rs index 3895e07..656629f 100644 --- a/native/human_name_nif/src/lib.rs +++ b/native/human_name_nif/src/lib.rs @@ -7,24 +7,6 @@ mod atoms { } } -#[rustler::nif] -fn first_initial<'a>(env: Env<'a>, full_name: String) -> NifResult> { - if full_name.is_empty() { - return Ok((atoms::error(), "No valid name found").encode(env)); - } - - let parsed_name = Name::parse(&full_name); - if parsed_name.is_none() { - return Ok((atoms::error(), "No valid name found").encode(env)); - } - - Ok(( - atoms::ok(), - parsed_name.unwrap().first_initial().to_string(), - ) - .encode(env)) -} - #[rustler::nif] fn consistent_with<'a>(env: Env<'a>, full_name_one: String, full_name_two: String) -> NifResult> { if full_name_one.is_empty() { @@ -54,6 +36,24 @@ fn consistent_with<'a>(env: Env<'a>, full_name_one: String, full_name_two: Strin .encode(env)) } +#[rustler::nif] +fn first_initial<'a>(env: Env<'a>, full_name: String) -> NifResult> { + if full_name.is_empty() { + return Ok((atoms::error(), "No valid name found").encode(env)); + } + + let parsed_name = Name::parse(&full_name); + if parsed_name.is_none() { + return Ok((atoms::error(), "No valid name found").encode(env)); + } + + Ok(( + atoms::ok(), + parsed_name.unwrap().first_initial().to_string(), + ) + .encode(env)) +} + #[rustler::nif] fn first_initial_last<'a>(env: Env<'a>, full_name: String) -> NifResult> { if full_name.is_empty() { @@ -169,6 +169,27 @@ fn first_and_last_initials<'a>(env: Env<'a>, full_name: String) -> NifResult(env: Env<'a>, full_name: String) -> NifResult> { + if full_name.is_empty() { + return Ok((atoms::error(), "No valid name found").encode(env)); + } + + let parsed_name = Name::parse(&full_name); + if parsed_name.is_none() { + return Ok((atoms::error(), "No valid name found").encode(env)); + } + + let parsed = parsed_name.unwrap(); + let l_initial = parsed.surname().chars().nth(0).unwrap(); + + Ok(( + atoms::ok(), + format!("{}", l_initial).to_string(), + ) + .encode(env)) +} + #[rustler::nif] fn last_name<'a>(env: Env<'a>, full_name: String) -> NifResult> { if full_name.is_empty() {