aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md4
-rw-r--r--gen/src/gleam@string.erl21
-rw-r--r--gen/test/gleam@string_test.erl24
-rw-r--r--src/gleam/string.gleam52
-rw-r--r--test/gleam/string_test.gleam22
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("")
+}