Last active
September 9, 2025 11:04
-
-
Save IFcoltransG/93b33ff4140ff953ab07cdb8d2acef23 to your computer and use it in GitHub Desktop.
String manipulation utilities in Ink, based on my "capitalise" code
This file contains hidden or 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
| // Ink string util code created by IFcoltransG | |
| // Released into public domain | |
| // May be used under the MIT No Attribution License | |
| // All functions only work on supported symbols that have been added | |
| // to the `letters` variable below. | |
| /* | |
| This is a sentinel token. It should be set to something that won't appear in any words. | |
| */ | |
| CONST START = "^^" | |
| /* | |
| All letters supported by this tool. | |
| Lowercase and uppercase should match and have same order as each other. | |
| Lowercase should have (brackets) around. | |
| Punctuation should have an entry in get_string(). | |
| */ | |
| LIST letters = /* | |
| lowercase: | |
| */ (a), (b), (c), (d), (e), (f), (g), (h), (i), (j), (k), (l), (m), (n), (o), (p), (q), (r), (s), (t), (u), (v), (w), (x), (y), (z), /* | |
| uppercase: | |
| */ A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, /* | |
| punctuation: | |
| */ Space, Comma, FullStop, Exclamation, Semicolon, Colon, /* | |
| numbers: | |
| */ Zero, One, Two, Three, Four, Five, Six, Seven, Eight, Nine | |
| /* | |
| Capitalises the first letter of a word. | |
| e.g. capitalise_start("hello") == "Hello" | |
| e.g. capitalise_start("HELLO") == "HELLO" | |
| */ | |
| === function capitalise_start(word) === | |
| {word == "": | |
| ~ return "" | |
| } | |
| ~ temp start = first_letter_after(word, "", LIST_ALL(letters)) | |
| ~ return "{capitalise_letter(start)}" + rest_of_letters(word, get_string(start)) | |
| /* | |
| Capitalises a word. | |
| e.g. capitalise_whole("hello") == "HELLO" | |
| e.g. capitalise_whole("HELLO") == "HELLO" | |
| */ | |
| === function capitalise_whole(word) === | |
| {word == "": | |
| ~ return "" | |
| } | |
| ~ temp start = first_letter_after(word, "", LIST_ALL(letters)) | |
| ~ temp rest = rest_of_letters(word, get_string(start)) | |
| ~ return "{capitalise_letter(start)}" + capitalise_whole(rest) | |
| /* | |
| Reverses a string. | |
| e.g. reverse("hello") == "olleh" | |
| */ | |
| === function reverse(word) === | |
| {word == "": | |
| ~ return "" | |
| } | |
| ~ temp start = get_string(first_letter_after(word, "", LIST_ALL(letters))) | |
| ~ return reverse(rest_of_letters(word, start)) + start | |
| // OTHER FUNCTIONS BELOW | |
| /* | |
| Returns the string version of a letter. | |
| Has special cases for punctuation — otherwise just returns the name. | |
| e.g. get_string(A) == "A" | |
| e.g. get_string(FullStop) == "." | |
| */ | |
| === function get_string(letter) === | |
| {letter: | |
| - Space: | |
| ~ return " " | |
| - Comma: | |
| ~ return "," | |
| - FullStop: | |
| ~ return "." | |
| - Exclamation: | |
| ~ return "!" | |
| - Semicolon: | |
| ~ return ";" | |
| - Colon: | |
| ~ return ":" | |
| - else: | |
| {Zero <= letter && letter <= Nine: | |
| ~ return "{LIST_VALUE(letter) - LIST_VALUE(Zero)}" | |
| - else: | |
| ~ return "{letter}" | |
| } | |
| } | |
| /* | |
| Takes a list element from `letters` and capitalises it. | |
| e.g. capitalise_letter(a) == A | |
| e.g. capitalise_letter(A) == A | |
| */ | |
| === function capitalise_letter(letter) === | |
| {letters ? letter: | |
| ~ return letter + LIST_COUNT(letters) | |
| - else: | |
| ~ return letter | |
| } | |
| /* | |
| Splits a word up into two parts by the first occurrence after start of a pattern. | |
| Returns the second half of the word. The pattern is a list of letters. | |
| e.g. rest_of_split("hello", (h, e), "") == "ello" | |
| e.g. rest_of_split("hello", (h, e), "h") == "llo" | |
| */ | |
| === function rest_of_split(word, pattern, start) === | |
| ~ temp separator_start = start_of_split(word, pattern, start) | |
| ~ return rest_of_letters(word, separator_start) | |
| /* | |
| Splits a word up into two parts by the first occurrence after start of a pattern. | |
| Returns the first half of the word including the pattern, which is a list of letters. | |
| e.g. start_of_split("hello", (h, e), "") == "h" | |
| e.g. start_of_split("hello", (h, e), "h") == "he" | |
| */ | |
| === function start_of_split(word, pattern, start) === | |
| ~ temp split_start = take_until(word, pattern, start) | |
| ~ temp separator = first_letter_after(word, split_start, LIST_ALL(letters)) | |
| ~ temp separator_start = split_start + get_string(separator) | |
| ~ return separator_start | |
| /* | |
| Takes the first part of a string while it matches a pattern, after some start. | |
| Returns everything before the first mismatch (including the given start). | |
| The pattern is a list of letters. | |
| e.g. take_while("hello", (l, o), "h") == "h" | |
| e.g. take_while("hello", (e, l, o), "h") == "hello" | |
| */ | |
| === function take_while(word, pattern, start) === | |
| ~ temp first = first_letter_after(word, start, LIST_ALL(letters)) | |
| {first == (): | |
| ~ return word | |
| } | |
| {pattern !? first: | |
| ~ return start | |
| } | |
| ~ return take_while(word, pattern, start + get_string(first)) | |
| /* | |
| Searches for a pattern in a word after some start. | |
| Returns everything before the first occurrence (including the given start). | |
| If the pattern is not found, returns the whole word. | |
| The pattern is a list of letters. | |
| e.g. take_until("hello", (h, e), "h") == "h" | |
| e.g. take_until("hello", h, "h") == "hello" | |
| */ | |
| === function take_until(word, pattern, start) === | |
| ~ temp first = first_letter_after(word, start, LIST_ALL(letters)) | |
| {first == (): | |
| ~ return word | |
| } | |
| {pattern ? first: | |
| ~ return start | |
| } | |
| ~ return take_until(word, pattern, start + get_string(first)) | |
| /* | |
| Gets a list of letters after a certain start. | |
| e.g. list_letters_after("hello", "he") == (l, o) | |
| */ | |
| === function list_letters_after(word, start) === | |
| ~ temp first = first_letter_after(word, start, LIST_ALL(letters)) | |
| {first == (): | |
| ~ return () | |
| } | |
| ~ return first + list_letters_after(word, start + get_string(first)) | |
| /* | |
| Gets the rest of the symbols after a certain start. | |
| e.g. rest_of_letters("hello", "he") == "llo" | |
| */ | |
| === function rest_of_letters(word, start) === | |
| {word == start: | |
| ~ return "" | |
| } | |
| ~ temp next_letter = get_string(first_letter_after(word, start, LIST_ALL(letters))) | |
| {next_letter == "": | |
| ~ return "" | |
| - else: | |
| ~ return next_letter + rest_of_letters(word, start + next_letter) | |
| } | |
| /* | |
| Gets the first symbol after a certain start. | |
| `options` parameter is an internal detail and should be passed `LIST_ALL(letters)` | |
| e.g. first_letter_after("hello", "he", LIST_ALL(letters)) == "l" | |
| */ | |
| === function first_letter_after(word, start, options) === | |
| {options: | |
| ~ temp test_letter = pop(options) | |
| {starts_with(word, "{start}{get_string(test_letter)}"): | |
| ~ return test_letter | |
| } | |
| ~ return first_letter_after(word, start, options) | |
| - else: | |
| ~ return () | |
| } | |
| /* | |
| Checks if a certain string starts with another string. | |
| The `START` constant should be set to a value that does not appear within strings. | |
| */ | |
| === function starts_with(word, start) === | |
| ~ return START + word ? START + start |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment