Skip to content

Instantly share code, notes, and snippets.

@IFcoltransG
Last active September 9, 2025 11:04
Show Gist options
  • Save IFcoltransG/93b33ff4140ff953ab07cdb8d2acef23 to your computer and use it in GitHub Desktop.
Save IFcoltransG/93b33ff4140ff953ab07cdb8d2acef23 to your computer and use it in GitHub Desktop.
String manipulation utilities in Ink, based on my "capitalise" code
// 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