-
-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adds a function to convert text to NameCase (#94)
* Adds a function to convert text to NameCase - updates Recase.Replace.replace spec to show it also works with functions Signed-off-by: Will Read <will@geometer.io> * Addresses code coverage issues Signed-off-by: Will Read <will@geometer.io> Co-authored-by: Matt Sloane <matt@geometer.io>
- Loading branch information
Showing
5 changed files
with
188 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
defmodule Recase.NameCase do | ||
@moduledoc """ | ||
Module to convert strings to `Name Case`. | ||
This module should not be used directly. | ||
## Examples | ||
iex> Recase.to_name "mccarthy o'donnell" | ||
"McCarthy O'Donnell" | ||
Read about `Name Case` here: | ||
https://metacpan.org/pod/Lingua::EN::NameCase | ||
""" | ||
import Recase.Replace | ||
|
||
@spec convert(String.t()) :: String.t() | ||
def convert(value) when is_binary(value) do | ||
value | ||
|> String.downcase() | ||
|> replace(~r|\b\w|, fn first_char_of_word -> | ||
String.upcase(first_char_of_word) | ||
end) | ||
|> replace(~r|\'\w\b|, fn apostophe_ess -> | ||
String.downcase(apostophe_ess) | ||
end) | ||
|> replace_irish() | ||
|> replace(~r|\bVon\b|, "von") | ||
|> replace(~r|\bVan(?=\s+\w)|, "van") | ||
|> replace(~r|\bAp\b|, "ap") | ||
|> replace(~r|\bAl(?=\s+\w)|, "al") | ||
|> replace(~r|\bEl\b|, "el") | ||
|> replace(~r|\bLa\b|, "la") | ||
|> replace(~r|\bBen(?=\s+\w)|, "ben") | ||
|> replace(~r/\b(Bin|Binti|Binte)\b/, fn bin_prefix -> | ||
String.downcase(bin_prefix) | ||
end) | ||
|> replace(~r|\bD([aeiou])\b|, fn da_prefix -> | ||
String.downcase(da_prefix) | ||
end) | ||
|> replace(~r|\bD([ao]s)\b|, fn das_prefix -> | ||
String.downcase(das_prefix) | ||
end) | ||
|> replace(~r|\bDell([ae])\b|, fn dell_prefix -> | ||
String.downcase(dell_prefix) | ||
end) | ||
|> replace(~r|\bDe([lr])\b|, fn del_prefix -> | ||
String.downcase(del_prefix) | ||
end) | ||
|> replace(~r|\bL([eo])\b|, fn le_prefix -> String.downcase(le_prefix) end) | ||
|> replace_roman_numerals() | ||
|> replace(~r|\b([YEI])\b|, fn conjunction -> | ||
String.downcase(conjunction) | ||
end) | ||
end | ||
|
||
defp replace_roman_numerals(string) do | ||
replace( | ||
string, | ||
~r/\b ( (?: [Xx]{1,3} | [Xx][Ll] | [Ll][Xx]{0,3} )? (?: [Ii]{1,3} | [Ii][VvXx] | [Vv][Ii]{0,3} )? ) \b /x, | ||
fn numeral -> String.upcase(numeral) end | ||
) | ||
end | ||
|
||
defp replace_irish(string) do | ||
replace(string, ~r|\b(Mc)([A-Za-z]+)|, fn _, mc_prefix, rest_of_word -> | ||
mc_prefix <> String.capitalize(rest_of_word) | ||
end) | ||
|> replace( | ||
~r|\b(Ma?c)([A-Za-z]{2,}[^aciozj])\b|, | ||
fn _, mc_prefix, rest_of_word -> | ||
mc_prefix <> String.capitalize(rest_of_word) | ||
end | ||
) | ||
|> replace(~r/\bMacEdo/, "Macedo") | ||
|> replace(~r/\bMacEvicius/, "Macevicius") | ||
|> replace(~r/\bMacHado/, "Machado") | ||
|> replace(~r/\bMacHar/, "Machar") | ||
|> replace(~r/\bMacHin/, "Machin") | ||
|> replace(~r/\bMacHlin/, "Machlin") | ||
|> replace(~r/\bMacIas/, "Macias") | ||
|> replace(~r/\bMacIulis/, "Maciulis") | ||
|> replace(~r/\bMacKie/, "Mackie") | ||
|> replace(~r/\bMacKle/, "Mackle") | ||
|> replace(~r/\bMacKlin/, "Macklin") | ||
|> replace(~r/\bMacKmin/, "Mackmin") | ||
|> replace(~r/\bMacQuarie/, "Macquarie") | ||
|> replace(~r/\bMacmurdo/, "MacMurdo") | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
defmodule Recase.NameCaseTest do | ||
use ExUnit.Case | ||
|
||
import Recase.NameCase | ||
|
||
doctest Recase.NameCase | ||
|
||
test "should name case usual text" do | ||
assert convert("keith") == "Keith" | ||
assert convert("leigh-williams") == "Leigh-Williams" | ||
assert convert("mccarthy") == "McCarthy" | ||
assert convert("o'callaghan") == "O'Callaghan" | ||
assert convert("st. john") == "St. John" | ||
assert convert("von streit") == "von Streit" | ||
assert convert("van dyke") == "van Dyke" | ||
assert convert("van") == "Van" | ||
assert convert("ap llwyd dafydd") == "ap Llwyd Dafydd" | ||
assert convert("al fahd") == "al Fahd" | ||
assert convert("al") == "Al" | ||
assert convert("el grecco") == "el Grecco" | ||
assert convert("bin friendly") == "bin Friendly" | ||
assert convert("ben gurion") == "ben Gurion" | ||
assert convert("ben") == "Ben" | ||
assert convert("dos brasileiros") == "dos Brasileiros" | ||
assert convert("da vinci") == "da Vinci" | ||
assert convert("di caprio") == "di Caprio" | ||
assert convert("du pont") == "du Pont" | ||
assert convert("de legate") == "de Legate" | ||
assert convert("del crond") == "del Crond" | ||
assert convert("della crond") == "della Crond" | ||
assert convert("der sind") == "der Sind" | ||
assert convert("van der Post") == "van der Post" | ||
assert convert("von trapp") == "von Trapp" | ||
assert convert("la poisson") == "la Poisson" | ||
assert convert("le figaro") == "le Figaro" | ||
assert convert("mack knife") == "Mack Knife" | ||
assert convert("dougal macdonald") == "Dougal MacDonald" | ||
assert convert("ruiz y picasso") == "Ruiz y Picasso" | ||
assert convert("dato e iradier") == "Dato e Iradier" | ||
assert convert("mas i gavarró") == "Mas i Gavarró" | ||
assert convert("parson's") == "Parson's" | ||
|
||
# Mac expectations | ||
assert convert("machin") == "Machin" | ||
assert convert("machlin") == "Machlin" | ||
assert convert("machar") == "Machar" | ||
assert convert("mackle") == "Mackle" | ||
assert convert("macklin") == "Macklin" | ||
assert convert("mackie") == "Mackie" | ||
assert convert("macquarie") == "Macquarie" | ||
assert convert("machado") == "Machado" | ||
assert convert("macevicius") == "Macevicius" | ||
assert convert("maciulis") == "Maciulis" | ||
assert convert("macias") == "Macias" | ||
assert convert("macmurdo") == "MacMurdo" | ||
|
||
# Roman Numerals | ||
assert convert("henry viii") == "Henry VIII" | ||
assert convert("louis iii") == "Louis III" | ||
assert convert("louis xiv") == "Louis XIV" | ||
assert convert("charles ii") == "Charles II" | ||
assert convert("fred xlix") == "Fred XLIX" | ||
assert convert("yusof bin ishak") == "Yusof bin Ishak" | ||
end | ||
|
||
test "should return single letter" do | ||
assert convert("a") == "A" | ||
end | ||
|
||
test "should return empty string" do | ||
assert convert("") == "" | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
defmodule RecaseReplaceTest do | ||
use ExUnit.Case | ||
|
||
test "replace has the same behavior of Regex.replace with different argument ordering" do | ||
assert Recase.Replace.replace("foo", ~r|oo|, "aa") == | ||
Regex.replace(~r|oo|, "foo", "aa") | ||
end | ||
end |