text

moon add myfreess/text@0.1.0
Download zip
Author
Version
0.1.0
License
MIT
Last updated
11 months ago
Downloads
19
README

#myfreess/text

A comprehensive MoonBit library for text processing, string manipulation, and fuzzy string matching. This library provides utilities for case conversions, string similarity calculations, and finding closest matches in string collections.

#Features

  • Case Conversion: Convert strings to camelCase, PascalCase, snake_case, and kebab-case
  • String Similarity: Calculate Levenshtein distance between strings
  • Fuzzy Matching: Find closest matches from string arrays with customizable options
  • Sorting by Similarity: Sort strings by their similarity to a target string
  • Word Processing: Split strings into words and handle various text manipulations

#Installation

Add this package to your MoonBit project:

moon add myfreess/text

#API Reference

#Case Conversion Functions

#to_camel_case(String) -> String

Converts a string to camelCase format where the first word is lowercase and subsequent words have their first letter capitalized.

test "camelCase conversion" {
inspect(@text.to_camel_case("hello world"), content="helloWorld")
inspect(@text.to_camel_case("deno_is_awesome"), content="denoIsAwesome")
inspect(@text.to_camel_case("HTMLElement"), content="htmlElement")
}

#to_pascal_case(String) -> String

Converts a string to PascalCase format where every word starts with a capital letter.

test "PascalCase conversion" {
inspect(@text.to_pascal_case("hello world"), content="HelloWorld")
inspect(@text.to_pascal_case("my_variable_name"), content="MyVariableName")
}

#to_snake_case(String) -> String

Converts a string to snake_case format where words are separated by underscores and all lowercase.

test "snake_case conversion" {
inspect(@text.to_snake_case("Hello World"), content="hello_world")
inspect(@text.to_snake_case("XMLHttpRequest"), content="xml_http_request")
}

#to_kebab_case(String) -> String

Converts a string to kebab-case format where words are separated by hyphens and all lowercase.

test "kebab-case conversion" {
inspect(@text.to_kebab_case("Hello World"), content="hello-world")
inspect(@text.to_kebab_case("backgroundColor"), content="background-color")
}

#String Similarity and Distance

#levenshtein_distance(String, String) -> Int

Calculates the Levenshtein distance (edit distance) between two strings. This represents the minimum number of single-character edits (insertions, deletions, or substitutions) required to change one string into another.

test "Levenshtein distance calculation" {
inspect(@text.levenshtein_distance("kitten", "sitting"), content="3")
inspect(@text.levenshtein_distance("hello", "hallo"), content="1")
inspect(@text.levenshtein_distance("", "abc"), content="3")
inspect(@text.levenshtein_distance("same", "same"), content="0")
}

#Fuzzy String Matching

#Configuration Types

ClosestStringOptions: Configuration for closest string matching
  • case_sensitive: Bool - Whether matching should be case-sensitive
  • compare_fn: (String, String) -> Int - Custom comparison function

CompareSimilarityOptions: Configuration for similarity comparison
  • case_sensitive: Bool - Whether comparison should be case-sensitive
  • compare_fn: (String, String) -> Int - Custom comparison function

#Option Creators

test "create matching options" {
let default_opts = @text.default_closest_string_options()
let case_opts = @text.case_sensitive_closest_string_options()

let similarity_opts = @text.default_compare_similarity_options()
let case_similarity_opts = @text.case_sensitive_compare_similarity_options()
}

#closest_string(String, Array[String], ClosestStringOptions?) -> String raise StringMatchingError

Finds the most similar string from an array of candidates using the specified options.

test "find closest string" {
let candidates = ["length", "size", "help", "world"]

// Simple case - finds "help" as closest to "hep"
let result = @text.closest_string_simple("hep", candidates)
inspect(result, content="help")

// With options
let opts = @text.default_closest_string_options()
let result2 = @text.closest_string("test", candidates, Some(opts))
inspect(result2, content="help")
}

#closest_string_simple(String, Array[String]) -> String raise StringMatchingError

Simplified version of closest_string using default options.

test "simple closest string matching" {
let words = ["apple", "application", "apply", "apt"]
let result = @text.closest_string_simple("app", words)
inspect(result, content="apt")
}

#closest_strings(String, Array[String], Int, ClosestStringOptions?) -> Array[String]

Returns multiple closest matches sorted by similarity.

test "multiple closest strings" {
let candidates = ["help", "hello", "world", "test", "heap"]
let top3 = @text.closest_strings("hep", candidates, 3, None)

// Should return top 3 matches sorted by similarity
inspect(top3.length(), content="3")
inspect(top3[0], content="help")
}

#Similarity Comparison and Sorting

#compare_similarity(String, CompareSimilarityOptions?) -> (String, String) -> Int

Creates a comparison function for measuring similarity between strings.

test "similarity comparison function" {
let compare_fn = @text.compare_similarity("target", None)
let distance1 = compare_fn("target", "test")
let distance2 = compare_fn("target", "target")

inspect(distance2, content="0") // exact match
}

#compare_similarity_simple(String) -> (String, String) -> Int

Simplified version using default comparison options.

test "simple similarity comparison" {
let compare_fn = @text.compare_similarity_simple("hello")
let distance = compare_fn("hello", "hallo")
inspect(distance, content="-1")
}

#sort_by_similarity(Array[String], String, CompareSimilarityOptions?) -> Array[String]

Sorts an array of strings by their similarity to a target string.

test "sort by similarity" {
let words = ["world", "help", "hello", "test"]
let sorted = @text.sort_by_similarity(words, "hep", None)

// "help" should be first as it's most similar to "hep"
inspect(sorted[0], content="help")
}

#Utility Functions

#split_to_words(String) -> Array[String]

Splits a string into individual words, handling various separators and cases.

test "word splitting" {
let words = @text.split_to_words("hello_world-test")
@json.inspect(words, content=["hello", "world", "test"])

let camel_words = @text.split_to_words("camelCaseExample")
@json.inspect(camel_words, content=["camel", "Case", "Example"])
}

#capitalize_word(String) -> String

Capitalizes the first letter of a word while making the rest lowercase.

test "word capitalization" {
inspect(@text.capitalize_word("hello"), content="Hello")
inspect(@text.capitalize_word("WORLD"), content="World")
inspect(@text.capitalize_word("tEST"), content="Test")
}

#to_lowercase_string(String) -> String

Converts a string to all lowercase letters.

test "lowercase conversion" {
inspect(@text.to_lowercase_string("Hello World"), content="hello world")
inspect(@text.to_lowercase_string("TEST123"), content="test123")
}

#Error Handling

The library defines a custom error type StringMatchingError for operations that may fail:

test "error handling" {
let empty_array : Array[String] = []
let result = try {
@text.closest_string_simple("test", empty_array)
} catch {
@text.StringMatchingError(msg) => "Error: " + msg
}

inspect(result, content="Error: When using closest_string(), the possible_words array must contain at least one word")
}

#Performance Considerations

  • The levenshtein_distance function has O(m × n) time complexity where m and n are string lengths
  • For strings shorter than 32 characters, an optimized Myers algorithm is used
  • For longer strings, the classic dynamic programming approach is employed
  • Consider input validation for very long strings in production use

#Use Cases

#Command Line Tool Suggestions

test "CLI command suggestions" {
let commands = ["install", "uninstall", "list", "search", "update"]
let suggestion = @text.closest_string_simple("instal", commands)
inspect(suggestion, content="install")
}

#API Method Name Matching

test "API method matching" {
let methods = ["getUserById", "getUserByName", "getAllUsers", "createUser"]
let closest = @text.closest_string_simple("getUser", methods)
inspect(closest, content="getUserById")
}

#Variable Name Formatting

test "variable name formatting" {
let api_name = "user profile data"

inspect(@text.to_camel_case(api_name), content="userProfileData")
inspect(@text.to_pascal_case(api_name), content="UserProfileData")
inspect(@text.to_snake_case(api_name), content="user_profile_data")
inspect(@text.to_kebab_case(api_name), content="user-profile-data")
}

#License

This project is licensed under the MIT License.

#
StringMatchingError

pub suberror StringMatchingError String

#
ClosestStringOptions

pub struct ClosestStringOptions {
case_sensitive : Bool
compare_fn : (String, String) -> Int
}

Closest string search options

#
CompareSimilarityOptions

pub struct CompareSimilarityOptions {
case_sensitive : Bool
compare_fn : (String, String) -> Int
}

Similarity comparison options

#
capitalize_word

fn capitalize_word(word : String) -> String

Capitalize the first letter of a word, make the rest lowercase

#
case_sensitive_closest_string_options

fn case_sensitive_closest_string_options() -> ClosestStringOptions

Create case-sensitive closest string search options

#
case_sensitive_compare_similarity_options

fn case_sensitive_compare_similarity_options() -> CompareSimilarityOptions

Create case-sensitive similarity comparison options

#
closest_string

fn closest_string(given_word : String, possible_words : Array[String], options : ClosestStringOptions?) -> String raise StringMatchingError

Find the most similar string from a string array

Uses Levenshtein distance algorithm by default to calculate distance between words

  • given_word - The string for measuring distance
  • possible_words - Array of candidate strings
  • options - Comparison options
  • Returns the closest string
  • Throws if the possible_words array is empty

Examples

let possible_words = ["length", "size", "blah", "help"]
let suggestion = closest_string("hep", possible_words, None)
// suggestion will be "help"

#
closest_string_simple

fn closest_string_simple(given_word : String, possible_words : Array[String]) -> String raise StringMatchingError

Simplified version using default options

#
closest_strings

fn closest_strings(given_word : String, possible_words : Array[String], count : Int, options : ClosestStringOptions?) -> Array[String]

Find multiple closest strings (return top n)

  • given_word - The string for measuring distance
  • possible_words - Array of candidate strings
  • count - Number of closest strings to return
  • options - Comparison options
  • Returns an array of top count strings sorted by similarity

#
compare_similarity

fn compare_similarity(given_word : String, options : CompareSimilarityOptions?) -> ((String, String) -> Int)

Get string similarity comparison function

Generate a comparator function to determine which of two strings is more similar to a given string Uses Levenshtein distance algorithm by default to calculate distance between words

  • given_word - The string for measuring distance
  • options - Comparison options
  • Returns a comparator function that returns negative if a is more similar than b, positive if b is more similar, 0 if same

Examples

Most similar words will be sorted at the front of the array
let words = ["hi", "hello", "help"] let sorted_words = sort_by_similarity(words, "hep", None) // sorted_words will be ["help", "hi", "hello"]

#
compare_similarity_simple

fn compare_similarity_simple(given_word : String) -> ((String, String) -> Int)

Simplified version using default options

#
default_closest_string_options

fn default_closest_string_options() -> ClosestStringOptions

Create default closest string search options

#
default_compare_similarity_options

fn default_compare_similarity_options() -> CompareSimilarityOptions

Create default similarity comparison options

#
levenshtein_distance

fn levenshtein_distance(str1 : String, str2 : String) -> Int

Calculate the Levenshtein distance between two strings

Levenshtein distance is the minimum number of edit operations (insert, delete, replace) between two strings Note: This function has O(m * n) complexity, where m and n are the lengths of the two strings It is recommended to limit input length and validate input when accepting arbitrary input

  • str1 - The first string
  • str2 - The second string
  • Returns the Levenshtein distance between the two strings

Examples

let _ = levenshtein_distance("aa", "bb") // returns 2 let _ = levenshtein_distance("hello", "hallo") // returns 1

#
sort_by_similarity

fn sort_by_similarity(words : Array[String], given_word : String, options : CompareSimilarityOptions?) -> Array[String]

Sort string array by similarity

  • words - The string array to sort
  • given_word - The reference string for similarity comparison
  • options - Comparison options
  • Returns a new array sorted by similarity (higher similarity first)

#
split_to_words

fn split_to_words(input : String) -> Array[String]

Split string into word array Supports recognition of the following patterns:
  • Words starting with uppercase letters (e.g., Apple)
  • Acronyms (e.g., URL, ID)
  • Lowercase words (e.g., apple)
  • Numbers (e.g., 123)

#
to_camel_case

fn to_camel_case(input : String) -> String

Convert string to camelCase format

  • input - The string to convert
  • Returns the converted camelCase format string

Examples

let _ = to_camel_case("deno is awesome") // "denoIsAwesome" let _ = to_camel_case("hello_world") // "helloWorld" let _ = to_camel_case("HTMLElement") // "htmlElement"

#
to_kebab_case

fn to_kebab_case(input : String) -> String

Convert string to kebab-case format

  • input - The string to convert
  • Returns the converted kebab-case format string

Examples

let _ = to_kebab_case("deno is awesome") // "deno-is-awesome" let _ = to_kebab_case("helloWorld") // "hello-world" let _ = to_kebab_case("HTMLElement") // "html-element"

#
to_lowercase_string

fn to_lowercase_string(s : String) -> String

Convert string to lowercase

#
to_pascal_case

fn to_pascal_case(input : String) -> String

Convert string to PascalCase format

  • input - The string to convert
  • Returns the converted PascalCase format string

Examples

let _ = to_pascal_case("deno is awesome") // "DenoIsAwesome" let _ = to_pascal_case("hello_world") // "HelloWorld" let _ = to_pascal_case("htmlElement") // "HtmlElement"

#
to_snake_case

fn to_snake_case(input : String) -> String

Convert string to snake_case format

  • input - The string to convert
  • Returns the converted snake_case format string

Examples

let _ = to_snake_case("deno is awesome") // "deno_is_awesome" let _ = to_snake_case("helloWorld") // "hello_world" let _ = to_snake_case("HTMLElement") // "html_element"