diff options
-rw-r--r-- | CHANGELOG.md | 4 | ||||
-rw-r--r-- | gen/src/gleam@string.erl | 21 | ||||
-rw-r--r-- | gen/test/gleam@string_test.erl | 24 | ||||
-rw-r--r-- | src/gleam/string.gleam | 52 | ||||
-rw-r--r-- | test/gleam/string_test.gleam | 22 |
5 files changed, 103 insertions, 20 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index a09dae5..c64c96d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,8 +2,8 @@ ## Unreleased -- The `string` module gains `trim`, `trim_left`, `trim_right`, `starts_with` - and `ends_with` functions. +- The `string` module gains `trim`, `trim_left`, `trim_right`, `starts_with`, + `ends_with` and `slice` functions. ## v0.8.0 - 2020-04-28 diff --git a/gen/src/gleam@string.erl b/gen/src/gleam@string.erl index 1b914c9..c8b76bc 100644 --- a/gen/src/gleam@string.erl +++ b/gen/src/gleam@string.erl @@ -1,7 +1,7 @@ -module(gleam@string). -compile(no_auto_import). --export([is_empty/1, length/1, reverse/1, replace/3, lowercase/1, uppercase/1, compare/2, contains/2, starts_with/2, ends_with/2, split/2, append/2, concat/1, repeat/2, join/2, trim/1, trim_left/1, trim_right/1]). +-export([is_empty/1, length/1, reverse/1, replace/3, lowercase/1, uppercase/1, compare/2, slice/3, contains/2, starts_with/2, ends_with/2, split/2, append/2, concat/1, repeat/2, join/2, trim/1, trim_left/1, trim_right/1]). is_empty(Str) -> Str =:= <<""/utf8>>. @@ -26,6 +26,25 @@ uppercase(A) -> compare(A, B) -> gleam_stdlib:compare_strings(A, B). +erl_slice(A, B, C) -> + string:slice(A, B, C). + +slice(String, Idx, Len) -> + case Idx < 0 of + true -> + TranslatedIdx = length(String) + Idx, + case TranslatedIdx < 0 of + true -> + <<""/utf8>>; + + false -> + erl_slice(String, TranslatedIdx, Len) + end; + + false -> + erl_slice(String, Idx, Len) + end. + erl_contains(A, B) -> gleam_stdlib:string_contains(A, B). diff --git a/gen/test/gleam@string_test.erl b/gen/test/gleam@string_test.erl index c6fe92f..f975af9 100644 --- a/gen/test/gleam@string_test.erl +++ b/gen/test/gleam@string_test.erl @@ -1,7 +1,7 @@ -module(gleam@string_test). -compile(no_auto_import). --export([length_test/0, lowercase_test/0, uppercase_test/0, reverse_test/0, split_test/0, replace_test/0, append_test/0, compare_test/0, contains_test/0, concat_test/0, repeat_test/0, join_test/0, trim_test/0, trim_left_test/0, trim_right_test/0, starts_with_test/0, ends_with_test/0]). +-export([length_test/0, lowercase_test/0, uppercase_test/0, reverse_test/0, split_test/0, replace_test/0, append_test/0, compare_test/0, contains_test/0, concat_test/0, repeat_test/0, join_test/0, trim_test/0, trim_left_test/0, trim_right_test/0, starts_with_test/0, ends_with_test/0, slice_test/0]). length_test() -> gleam@should:equal(gleam@string:length(<<"ß↑e̊"/utf8>>), 3), @@ -152,3 +152,25 @@ ends_with_test() -> gleam@string:ends_with(<<"theory"/utf8>>, <<"theory2"/utf8>>), false ). + +slice_test() -> + gleam@should:equal( + gleam@string:slice(<<"gleam"/utf8>>, 1, 2), + <<"le"/utf8>> + ), + gleam@should:equal( + gleam@string:slice(<<"gleam"/utf8>>, 1, 10), + <<"leam"/utf8>> + ), + gleam@should:equal( + gleam@string:slice(<<"gleam"/utf8>>, 10, 3), + <<""/utf8>> + ), + gleam@should:equal( + gleam@string:slice(<<"gleam"/utf8>>, -2, 2), + <<"am"/utf8>> + ), + gleam@should:equal( + gleam@string:slice(<<"gleam"/utf8>>, -12, 2), + <<""/utf8>> + ). diff --git a/src/gleam/string.gleam b/src/gleam/string.gleam index 93c686f..dd292b5 100644 --- a/src/gleam/string.gleam +++ b/src/gleam/string.gleam @@ -121,22 +121,42 @@ pub external fn uppercase(String) -> String = pub external fn compare(String, String) -> order.Order = "gleam_stdlib" "compare_strings" -// TODO -// Take a substring given a start and end Grapheme indexes. Negative indexes -// are taken starting from the *end* of the list. -// -// ## Examples -// > slice("gleam", from: 1, to: 3) -// "lea" -// -// > slice("gleam", from: 1, to: 10) -// "leam" -// -// > slice("snakes on a plane!", from: -6, to: -1) -// "plane" -// -// -// pub fn slice(out_of string: String, from start: Int, end: Int) -> String {} +external fn erl_slice(String, Int, Int) -> String = + "string" "slice" + +/// Take a substring given a start and end Grapheme indexes. Negative indexes +/// are taken starting from the *end* of the list. +/// +/// ## Examples +/// > slice(from: "gleam", at_index: 1, length: 2) +/// "le" +/// +/// > slice(from: "gleam", at_index: 1, length: 10) +/// "leam" +/// +/// > slice(from: "gleam", at_index: 10, length: 3) +/// "" +/// +/// > slice(from: "gleam", at_index: -2, length: 2) +/// "am" +/// +/// > slice(from: "gleam", at_index: -12, length: 2) +/// "" +/// +/// +pub fn slice(from string: String, at_index idx: Int, length len: Int) -> String { + case idx < 0 { + True -> { + let translated_idx = length(string) + idx + case translated_idx < 0 { + True -> "" + False -> erl_slice(string, translated_idx, len) + } + } + False -> erl_slice(string, idx, len) + } +} + // TODO // Drop *n* Graphemes from the left side of a // diff --git a/test/gleam/string_test.gleam b/test/gleam/string_test.gleam index 03678ea..d08ea78 100644 --- a/test/gleam/string_test.gleam +++ b/test/gleam/string_test.gleam @@ -163,3 +163,25 @@ pub fn ends_with_test() { |> string.ends_with("theory2") |> should.equal(False) } + +pub fn slice_test() { + "gleam" + |> string.slice(at_index: 1, length: 2) + |> should.equal("le") + + "gleam" + |> string.slice(at_index: 1, length: 10) + |> should.equal("leam") + + "gleam" + |> string.slice(at_index: 10, length: 3) + |> should.equal("") + + "gleam" + |> string.slice(at_index: -2, length: 2) + |> should.equal("am") + + "gleam" + |> string.slice(at_index: -12, length: 2) + |> should.equal("") +} |