From 2ce457d11e497a89b74e36536325bc2e4f9d0c1a Mon Sep 17 00:00:00 2001 From: Spotandjake Date: Sun, 20 Oct 2024 21:29:07 -0400 Subject: [PATCH 1/5] feat(stdlib): `isAscii`,`isAsciiControl`,`isAsciiWhitespace` to `Char` --- compiler/test/stdlib/char.test.gr | 26 +++++++ stdlib/char.gr | 63 +++++++++++++-- stdlib/char.md | 125 ++++++++++++++++++++++++++++++ 3 files changed, 207 insertions(+), 7 deletions(-) diff --git a/compiler/test/stdlib/char.test.gr b/compiler/test/stdlib/char.test.gr index e2e55645a..cc19cd6d6 100644 --- a/compiler/test/stdlib/char.test.gr +++ b/compiler/test/stdlib/char.test.gr @@ -87,6 +87,14 @@ assert !('a' >= 'b') assert 'a' >= 'a' assert 'B' >= 'B' +// isAscii +assert Char.isAscii('1') +assert Char.isAscii('a') +assert Char.isAscii(';') +assert Char.isAscii(' ') +assert Char.isAscii('\n') +assert !Char.isAscii('馃尵') + // isAsciiDigit assert Char.isAsciiDigit('1') assert !Char.isAsciiDigit('a') @@ -98,6 +106,24 @@ assert Char.isAsciiAlpha('a') assert Char.isAsciiAlpha('Z') assert !Char.isAsciiAlpha('位') +// isAsciiControl +assert Char.isAsciiControl('\n') +assert Char.isAsciiControl('\t') +assert Char.isAsciiControl('\u{007F}') +assert !Char.isAsciiControl(' ') +assert !Char.isAsciiControl('a') +assert !Char.isAsciiControl('馃尵') + +// isAsciiWhitespace +assert Char.isAsciiWhitespace(' ') +assert Char.isAsciiWhitespace('\t') +assert Char.isAsciiWhitespace('\n') +assert Char.isAsciiWhitespace('\r') +assert Char.isAsciiWhitespace('\x0C') +assert !Char.isAsciiWhitespace('a') +assert !Char.isAsciiWhitespace('1') +assert !Char.isAsciiWhitespace('馃尵') + // toAsciiLowercase assert Char.toAsciiLowercase('A') == 'a' assert Char.toAsciiLowercase('a') == 'a' diff --git a/stdlib/char.gr b/stdlib/char.gr index 5b699c138..1983ab734 100644 --- a/stdlib/char.gr +++ b/stdlib/char.gr @@ -314,12 +314,26 @@ provide let (>=) = (x: Char, y: Char) => { x >= y } +/** + * Checks if the character is an ASCII character. + * + * @param char: The character to check + * @returns `true` if the character is an ASCII character or `false` otherwise + * + * @example assert Char.isAscii('1') + * @example assert Char.isAscii('a') + * @example assert !Char.isAscii('馃尵') + * + * @since v0.7.0 + */ +provide let isAscii = char => char <= '\u{007F}' // usv <= 0x7F + /** * Checks if the character is an ASCII digit. * * @param char: The character to check * @returns `true` if the character is an ASCII digit or `false` otherwise - * + * * @example assert Char.isAsciiDigit('1') * @example assert !Char.isAsciiDigit('a') * @@ -341,14 +355,49 @@ provide let isAsciiDigit = char => char >= '0' && char <= '9' provide let isAsciiAlpha = char => char >= 'a' && char <= 'z' || char >= 'A' && char <= 'Z' +/** + * Checks if the character is an ASCII control character. + * + * @param char: The character to check + * @returns `true` if the character is an ASCII control character or `false` otherwise + * + * @example assert Char.isAsciiControl('\t') + * @example assert Char.isAsciiControl('\n') + * @example assert !Char.isAsciiControl('1') + * @example assert !Char.isAsciiControl('a') + * + * @since v0.7.0 + */ +provide let isAsciiControl = char => char <= '\u{001F}' || char == '\u{007F}' + +/** + * Checks if the character is an ASCII whitespace character. + * + * @param char: The character to check + * @returns `true` if the character is an ASCII whitespace character or `false` otherwise + * + * @example assert Char.isAsciiWhitespace('\t') + * @example assert Char.isAsciiWhitespace('\n') + * @example assert !Char.isAsciiWhitespace('1') + * @example assert !Char.isAsciiWhitespace('a') + * + * @since v0.7.0 + */ +provide let isAsciiWhitespace = char => { + match (char) { + '\t' | '\n' | '\x0C' | '\r' | ' ' => true, + _ => false, + } +} + /** * Converts the character to ASCII lowercase if it is an ASCII uppercase character. - * + * * @param char: The character to convert * @returns The lowercased character - * + * * @example assert Char.toAsciiLowercase('B') == 'b' - * + * * @since v0.6.0 */ provide let toAsciiLowercase = char => { @@ -361,12 +410,12 @@ provide let toAsciiLowercase = char => { /** * Converts the character to ASCII uppercase if it is an ASCII lowercase character. - * + * * @param char: The character to convert * @returns The uppercased character - * + * * @example assert Char.toAsciiUppercase('b') == 'B' - * + * * @since v0.6.0 */ provide let toAsciiUppercase = char => { diff --git a/stdlib/char.md b/stdlib/char.md index 65a69315e..90f9d69ae 100644 --- a/stdlib/char.md +++ b/stdlib/char.md @@ -447,6 +447,45 @@ use Char.{ (>=) } assert 'a' >= 'a' ``` +### Char.**isAscii** + +
+Added in next +No other changes yet. +
+ +```grain +isAscii : (char: Char) => Bool +``` + +Checks if the character is an ASCII character. + +Parameters: + +|param|type|description| +|-----|----|-----------| +|`char`|`Char`|The character to check| + +Returns: + +|type|description| +|----|-----------| +|`Bool`|`true` if the character is an ASCII character or `false` otherwise| + +Examples: + +```grain +assert Char.isAscii('1') +``` + +```grain +assert Char.isAscii('a') +``` + +```grain +assert !Char.isAscii('馃尵') +``` + ### Char.**isAsciiDigit**
@@ -517,6 +556,92 @@ assert Char.isAsciiAlpha('a') assert !Char.isAsciiAlpha('1') ``` +### Char.**isAsciiControl** + +
+Added in next +No other changes yet. +
+ +```grain +isAsciiControl : (char: Char) => Bool +``` + +Checks if the character is an ASCII control character. + +Parameters: + +|param|type|description| +|-----|----|-----------| +|`char`|`Char`|The character to check| + +Returns: + +|type|description| +|----|-----------| +|`Bool`|`true` if the character is an ASCII control character or `false` otherwise| + +Examples: + +```grain +assert Char.isAsciiControl('\t') +``` + +```grain +assert Char.isAsciiControl('\n') +``` + +```grain +assert !Char.isAsciiControl('1') +``` + +```grain +assert !Char.isAsciiControl('a') +``` + +### Char.**isAsciiWhitespace** + +
+Added in next +No other changes yet. +
+ +```grain +isAsciiWhitespace : (char: Char) => Bool +``` + +Checks if the character is an ASCII whitespace character. + +Parameters: + +|param|type|description| +|-----|----|-----------| +|`char`|`Char`|The character to check| + +Returns: + +|type|description| +|----|-----------| +|`Bool`|`true` if the character is an ASCII whitespace character or `false` otherwise| + +Examples: + +```grain +assert Char.isAsciiWhitespace('\t') +``` + +```grain +assert Char.isAsciiWhitespace('\n') +``` + +```grain +assert !Char.isAsciiWhitespace('1') +``` + +```grain +assert !Char.isAsciiWhitespace('a') +``` + ### Char.**toAsciiLowercase**
From 466913c0d953d47d896901580ddaef0462dce6a2 Mon Sep 17 00:00:00 2001 From: Spotandjake Date: Mon, 28 Oct 2024 15:57:25 -0400 Subject: [PATCH 2/5] feat!: Make an ascii submodule --- compiler/test/stdlib/char.test.gr | 118 ++++++++------ stdlib/char.gr | 249 ++++++++++++++++++------------ stdlib/char.md | 225 ++++++++++++++++++++++----- stdlib/string.gr | 4 +- stdlib/uri.gr | 74 ++++----- 5 files changed, 445 insertions(+), 225 deletions(-) diff --git a/compiler/test/stdlib/char.test.gr b/compiler/test/stdlib/char.test.gr index cc19cd6d6..cef8d1af6 100644 --- a/compiler/test/stdlib/char.test.gr +++ b/compiler/test/stdlib/char.test.gr @@ -87,51 +87,73 @@ assert !('a' >= 'b') assert 'a' >= 'a' assert 'B' >= 'B' -// isAscii -assert Char.isAscii('1') -assert Char.isAscii('a') -assert Char.isAscii(';') -assert Char.isAscii(' ') -assert Char.isAscii('\n') -assert !Char.isAscii('馃尵') - -// isAsciiDigit -assert Char.isAsciiDigit('1') -assert !Char.isAsciiDigit('a') -assert !Char.isAsciiDigit('馃尵') - -// isAsciiAlpha -assert !Char.isAsciiAlpha('1') -assert Char.isAsciiAlpha('a') -assert Char.isAsciiAlpha('Z') -assert !Char.isAsciiAlpha('位') - -// isAsciiControl -assert Char.isAsciiControl('\n') -assert Char.isAsciiControl('\t') -assert Char.isAsciiControl('\u{007F}') -assert !Char.isAsciiControl(' ') -assert !Char.isAsciiControl('a') -assert !Char.isAsciiControl('馃尵') - -// isAsciiWhitespace -assert Char.isAsciiWhitespace(' ') -assert Char.isAsciiWhitespace('\t') -assert Char.isAsciiWhitespace('\n') -assert Char.isAsciiWhitespace('\r') -assert Char.isAsciiWhitespace('\x0C') -assert !Char.isAsciiWhitespace('a') -assert !Char.isAsciiWhitespace('1') -assert !Char.isAsciiWhitespace('馃尵') - -// toAsciiLowercase -assert Char.toAsciiLowercase('A') == 'a' -assert Char.toAsciiLowercase('a') == 'a' -assert Char.toAsciiLowercase('1') == '1' -assert Char.toAsciiLowercase('位') == '位' - -// toAsciiUppercase -assert Char.toAsciiUppercase('a') == 'A' -assert Char.toAsciiUppercase('A') == 'A' -assert Char.toAsciiUppercase('1') == '1' -assert Char.toAsciiUppercase('位') == '位' +// Char.Ascii +module AsciiTest { + use Char.{ module Ascii } + + // isValid + assert Ascii.isValid('1') + assert Ascii.isValid('a') + assert Ascii.isValid(';') + assert Ascii.isValid(' ') + assert Ascii.isValid('\n') + assert !Ascii.isValid('馃尵') + + // isDigit + assert Ascii.isDigit('1') + assert !Ascii.isDigit('a') + assert !Ascii.isDigit('馃尵') + + // isAlpha + assert !Ascii.isAlpha('1') + assert Ascii.isAlpha('a') + assert Ascii.isAlpha('Z') + assert !Ascii.isAlpha('位') + + // isControl + assert Ascii.isControl('\n') + assert Ascii.isControl('\t') + assert Ascii.isControl('\u{007F}') + assert !Ascii.isControl(' ') + assert !Ascii.isControl('a') + assert !Ascii.isControl('馃尵') + + // isWhitespace + assert Ascii.isWhitespace(' ') + assert Ascii.isWhitespace('\t') + assert Ascii.isWhitespace('\n') + assert Ascii.isWhitespace('\r') + assert Ascii.isWhitespace('\x0C') + assert !Ascii.isWhitespace('a') + assert !Ascii.isWhitespace('1') + assert !Ascii.isWhitespace('馃尵') + + // isPunctuation + assert Ascii.isPunctuation('!') + assert Ascii.isPunctuation('?') + assert Ascii.isPunctuation('.') + assert Ascii.isPunctuation(',') + assert !Ascii.isPunctuation('1') + assert !Ascii.isPunctuation('a') + assert !Ascii.isPunctuation('馃尵') + + // isGraphic + assert Ascii.isGraphic('1') + assert Ascii.isGraphic('a') + assert Ascii.isGraphic('!') + assert !Ascii.isGraphic('\n') + assert !Ascii.isGraphic('\t') + assert !Ascii.isGraphic('馃尵') + + // toLowercase + assert Ascii.toLowercase('A') == 'a' + assert Ascii.toLowercase('a') == 'a' + assert Ascii.toLowercase('1') == '1' + assert Ascii.toLowercase('位') == '位' + + // toUppercase + assert Ascii.toUppercase('a') == 'A' + assert Ascii.toUppercase('A') == 'A' + assert Ascii.toUppercase('1') == '1' + assert Ascii.toUppercase('位') == '位' +} diff --git a/stdlib/char.gr b/stdlib/char.gr index 1983ab734..0b4118d6a 100644 --- a/stdlib/char.gr +++ b/stdlib/char.gr @@ -315,113 +315,170 @@ provide let (>=) = (x: Char, y: Char) => { } /** - * Checks if the character is an ASCII character. + * Sub module for working with ASCII characters. * - * @param char: The character to check - * @returns `true` if the character is an ASCII character or `false` otherwise - * - * @example assert Char.isAscii('1') - * @example assert Char.isAscii('a') - * @example assert !Char.isAscii('馃尵') + * @example Char.Ascii.isAscii('1') * * @since v0.7.0 */ -provide let isAscii = char => char <= '\u{007F}' // usv <= 0x7F +provide module Ascii { + /** + * The minimum valid ASCII character code. + * + * @since v0.7.0 + */ + provide let min = 0x00 -/** - * Checks if the character is an ASCII digit. - * - * @param char: The character to check - * @returns `true` if the character is an ASCII digit or `false` otherwise - * - * @example assert Char.isAsciiDigit('1') - * @example assert !Char.isAsciiDigit('a') - * - * @since v0.6.0 - */ -provide let isAsciiDigit = char => char >= '0' && char <= '9' + /** + * The maximum valid ASCII character code. + * + * @since v0.7.0 + */ + provide let max = 0x7F -/** - * Checks if the character is an ASCII alphabetical character. - * - * @param char: The character to check - * @returns `true` if the character is an ASCII alphabetical or `false` otherwise - * - * @example assert Char.isAsciiAlpha('a') - * @example assert !Char.isAsciiAlpha('1') - * - * @since v0.6.0 - */ -provide let isAsciiAlpha = char => - char >= 'a' && char <= 'z' || char >= 'A' && char <= 'Z' + /** + * Checks if the character is a valid ASCII character. + * + * @param char: The character to check + * @returns `true` if the character is an ASCII character or `false` otherwise + * + * @example assert Char.Ascii.isValid('1') + * @example assert Char.Ascii.isValid('a') + * @example assert !Char.Ascii.isValid('馃尵') + * + * @since v0.7.0 + */ + provide let isValid = char => char <= '\u{007F}' // usv <= 0x7F -/** - * Checks if the character is an ASCII control character. - * - * @param char: The character to check - * @returns `true` if the character is an ASCII control character or `false` otherwise - * - * @example assert Char.isAsciiControl('\t') - * @example assert Char.isAsciiControl('\n') - * @example assert !Char.isAsciiControl('1') - * @example assert !Char.isAsciiControl('a') - * - * @since v0.7.0 - */ -provide let isAsciiControl = char => char <= '\u{001F}' || char == '\u{007F}' + /** + * Checks if the character is an ASCII digit. + * + * @param char: The character to check + * @returns `true` if the character is an ASCII digit or `false` otherwise + * + * @example assert Char.Ascii.isDigit('1') + * @example assert !Char.Ascii.isDigit('a') + * + * @since v0.7.0 + * @history v0.6.0: Originally `Char.isAsciiDigit` + */ + provide let isDigit = char => char >= '0' && char <= '9' -/** - * Checks if the character is an ASCII whitespace character. - * - * @param char: The character to check - * @returns `true` if the character is an ASCII whitespace character or `false` otherwise - * - * @example assert Char.isAsciiWhitespace('\t') - * @example assert Char.isAsciiWhitespace('\n') - * @example assert !Char.isAsciiWhitespace('1') - * @example assert !Char.isAsciiWhitespace('a') - * - * @since v0.7.0 - */ -provide let isAsciiWhitespace = char => { - match (char) { - '\t' | '\n' | '\x0C' | '\r' | ' ' => true, - _ => false, + /** + * Checks if the character is an ASCII alphabetical character. + * + * @param char: The character to check + * @returns `true` if the character is an ASCII alphabetical or `false` otherwise + * + * @example assert Char.Ascii.isAlpha('a') + * @example assert !Char.Ascii.isAlpha('1') + * + * @since v0.7.0 + * @history v0.6.0: Originally `Char.isAsciiAlpha` + */ + provide let isAlpha = char => + char >= 'a' && char <= 'z' || char >= 'A' && char <= 'Z' + + /** + * Checks if the character is an ASCII control character. + * + * @param char: The character to check + * @returns `true` if the character is an ASCII control character or `false` otherwise + * + * @example assert Char.Ascii.isControl('\t') + * @example assert Char.Ascii.isControl('\n') + * @example assert !Char.Ascii.isControl('1') + * @example assert !Char.Ascii.isControl('a') + * + * @since v0.7.0 + */ + provide let isControl = char => char <= '\u{001F}' || char == '\u{007F}' + + /** + * Checks if the character is an ASCII whitespace character. + * + * @param char: The character to check + * @returns `true` if the character is an ASCII whitespace character or `false` otherwise + * + * @example assert Char.isWhitespace('\t') + * @example assert Char.isWhitespace('\n') + * @example assert !Char.isWhitespace('1') + * @example assert !Char.isWhitespace('a') + * + * @since v0.7.0 + */ + provide let isWhitespace = char => { + match (char) { + '\t' | '\n' | '\x0C' | '\r' | ' ' => true, + _ => false, + } } -} -/** - * Converts the character to ASCII lowercase if it is an ASCII uppercase character. - * - * @param char: The character to convert - * @returns The lowercased character - * - * @example assert Char.toAsciiLowercase('B') == 'b' - * - * @since v0.6.0 - */ -provide let toAsciiLowercase = char => { - if (char >= 'A' && char <= 'Z') { - fromCode(code(char) + 0x20) - } else { - char + /** + * Checks if the character is an ASCII punctuation character. + * + * @param char: The character to check + * @returns `true` if the character is an ASCII punctuation character or `false` otherwise + * + * @example assert Char.Ascii.isPunctuation('!') + * @example assert !Char.Ascii.isPunctuation('1') + * + * @since v0.7.0 + */ + provide let isPunctuation = char => + char >= '!' && char <= '/' || + char >= ':' && char <= '@' || + char >= '[' && char <= '`' || + char >= '{' && char <= '~' + + /** + * Checks if the character is an ASCII graphic character. + * + * @param char: The character to check + * @returns `true` if the character is an ASCII graphic character or `false` otherwise + * + * @example assert Char.Ascii.isGraphic('!') + * @example assert !Char.Ascii.isGraphic('\t') + * + * @since v0.7.0 + */ + provide let isGraphic = char => char >= '!' && char <= '~' + + /** + * Converts the character to ASCII lowercase if it is an ASCII uppercase character. + * + * @param char: The character to convert + * @returns The lowercased character + * + * @example assert Char.Ascii.toLowercase('B') == 'b' + * + * @since v0.7.0 + * @history v0.6.0: Originally `Char.toAsciiLowercase` + */ + provide let toLowercase = char => { + if (char >= 'A' && char <= 'Z') { + fromCode(code(char) + 0x20) + } else { + char + } } -} -/** - * Converts the character to ASCII uppercase if it is an ASCII lowercase character. - * - * @param char: The character to convert - * @returns The uppercased character - * - * @example assert Char.toAsciiUppercase('b') == 'B' - * - * @since v0.6.0 - */ -provide let toAsciiUppercase = char => { - if (char >= 'a' && char <= 'z') { - fromCode(code(char) - 0x20) - } else { - char + /** + * Converts the character to ASCII uppercase if it is an ASCII lowercase character. + * + * @param char: The character to convert + * @returns The uppercased character + * + * @example assert Char.Ascii.toUppercase('b') == 'B' + * + * @since v0.7.0 + * @history v0.6.0: Originally `Char.toAsciiUppercase` + */ + provide let toUppercase = char => { + if (char >= 'a' && char <= 'z') { + fromCode(code(char) - 0x20) + } else { + char + } } } diff --git a/stdlib/char.md b/stdlib/char.md index 90f9d69ae..d1a463c4a 100644 --- a/stdlib/char.md +++ b/stdlib/char.md @@ -447,7 +447,50 @@ use Char.{ (>=) } assert 'a' >= 'a' ``` -### Char.**isAscii** +## Char.Ascii + +Sub module for working with ASCII characters. + +
+Added in next +No other changes yet. +
+ +```grain +Char.Ascii.isAscii('1') +``` + +### Values + +Functions and constants included in the Char.Ascii module. + +#### Char.Ascii.**min** + +
+Added in next +No other changes yet. +
+ +```grain +min : Number +``` + +The minimum valid ASCII character code. + +#### Char.Ascii.**max** + +
+Added in next +No other changes yet. +
+ +```grain +max : Number +``` + +The maximum valid ASCII character code. + +#### Char.Ascii.**isValid**
Added in next @@ -455,10 +498,10 @@ No other changes yet.
```grain -isAscii : (char: Char) => Bool +isValid : (char: Char) => Bool ``` -Checks if the character is an ASCII character. +Checks if the character is a valid ASCII character. Parameters: @@ -475,26 +518,33 @@ Returns: Examples: ```grain -assert Char.isAscii('1') +assert Char.Ascii.isValid('1') ``` ```grain -assert Char.isAscii('a') +assert Char.Ascii.isValid('a') ``` ```grain -assert !Char.isAscii('馃尵') +assert !Char.Ascii.isValid('馃尵') ``` -### Char.**isAsciiDigit** +#### Char.Ascii.**isDigit** -
-Added in 0.6.0 -No other changes yet. +
+Added in next + + + + + + + +
versionchanges
0.6.0Originally `Char.isAsciiDigit`
```grain -isAsciiDigit : (char: Char) => Bool +isDigit : (char: Char) => Bool ``` Checks if the character is an ASCII digit. @@ -514,22 +564,29 @@ Returns: Examples: ```grain -assert Char.isAsciiDigit('1') +assert Char.Ascii.isDigit('1') ``` ```grain -assert !Char.isAsciiDigit('a') +assert !Char.Ascii.isDigit('a') ``` -### Char.**isAsciiAlpha** +#### Char.Ascii.**isAlpha** -
-Added in 0.6.0 -No other changes yet. +
+Added in next + + + + + + + +
versionchanges
0.6.0Originally `Char.isAsciiAlpha`
```grain -isAsciiAlpha : (char: Char) => Bool +isAlpha : (char: Char) => Bool ``` Checks if the character is an ASCII alphabetical character. @@ -549,14 +606,14 @@ Returns: Examples: ```grain -assert Char.isAsciiAlpha('a') +assert Char.Ascii.isAlpha('a') ``` ```grain -assert !Char.isAsciiAlpha('1') +assert !Char.Ascii.isAlpha('1') ``` -### Char.**isAsciiControl** +#### Char.Ascii.**isControl**
Added in next @@ -564,7 +621,7 @@ No other changes yet.
```grain -isAsciiControl : (char: Char) => Bool +isControl : (char: Char) => Bool ``` Checks if the character is an ASCII control character. @@ -584,22 +641,22 @@ Returns: Examples: ```grain -assert Char.isAsciiControl('\t') +assert Char.Ascii.isControl('\t') ``` ```grain -assert Char.isAsciiControl('\n') +assert Char.Ascii.isControl('\n') ``` ```grain -assert !Char.isAsciiControl('1') +assert !Char.Ascii.isControl('1') ``` ```grain -assert !Char.isAsciiControl('a') +assert !Char.Ascii.isControl('a') ``` -### Char.**isAsciiWhitespace** +#### Char.Ascii.**isWhitespace**
Added in next @@ -607,7 +664,7 @@ No other changes yet.
```grain -isAsciiWhitespace : (char: Char) => Bool +isWhitespace : (char: Char) => Bool ``` Checks if the character is an ASCII whitespace character. @@ -627,30 +684,107 @@ Returns: Examples: ```grain -assert Char.isAsciiWhitespace('\t') +assert Char.isWhitespace('\t') ``` ```grain -assert Char.isAsciiWhitespace('\n') +assert Char.isWhitespace('\n') ``` ```grain -assert !Char.isAsciiWhitespace('1') +assert !Char.isWhitespace('1') ``` ```grain -assert !Char.isAsciiWhitespace('a') +assert !Char.isWhitespace('a') ``` -### Char.**toAsciiLowercase** +#### Char.Ascii.**isPunctuation**
-Added in 0.6.0 +Added in next +No other changes yet. +
+ +```grain +isPunctuation : (char: Char) => Bool +``` + +Checks if the character is an ASCII punctuation character. + +Parameters: + +|param|type|description| +|-----|----|-----------| +|`char`|`Char`|The character to check| + +Returns: + +|type|description| +|----|-----------| +|`Bool`|`true` if the character is an ASCII punctuation character or `false` otherwise| + +Examples: + +```grain +assert Char.Ascii.isPunctuation('!') +``` + +```grain +assert !Char.Ascii.isPunctuation('1') +``` + +#### Char.Ascii.**isGraphic** + +
+Added in next No other changes yet.
```grain -toAsciiLowercase : (char: Char) => Char +isGraphic : (char: Char) => Bool +``` + +Checks if the character is an ASCII graphic character. + +Parameters: + +|param|type|description| +|-----|----|-----------| +|`char`|`Char`|The character to check| + +Returns: + +|type|description| +|----|-----------| +|`Bool`|`true` if the character is an ASCII graphic character or `false` otherwise| + +Examples: + +```grain +assert Char.Ascii.isGraphic('!') +``` + +```grain +assert !Char.Ascii.isGraphic('\t') +``` + +#### Char.Ascii.**toLowercase** + +
+Added in next + + + + + + + +
versionchanges
0.6.0Originally `Char.toAsciiLowercase`
+
+ +```grain +toLowercase : (char: Char) => Char ``` Converts the character to ASCII lowercase if it is an ASCII uppercase character. @@ -670,18 +804,25 @@ Returns: Examples: ```grain -assert Char.toAsciiLowercase('B') == 'b' +assert Char.Ascii.toLowercase('B') == 'b' ``` -### Char.**toAsciiUppercase** +#### Char.Ascii.**toUppercase** -
-Added in 0.6.0 -No other changes yet. +
+Added in next + + + + + + + +
versionchanges
0.6.0Originally `Char.toAsciiUppercase`
```grain -toAsciiUppercase : (char: Char) => Char +toUppercase : (char: Char) => Char ``` Converts the character to ASCII uppercase if it is an ASCII lowercase character. @@ -701,6 +842,6 @@ Returns: Examples: ```grain -assert Char.toAsciiUppercase('b') == 'B' +assert Char.Ascii.toUppercase('b') == 'B' ``` diff --git a/stdlib/string.gr b/stdlib/string.gr index 194a186d8..c4dd188ae 100644 --- a/stdlib/string.gr +++ b/stdlib/string.gr @@ -2305,7 +2305,7 @@ provide let toAsciiLowercase = string => { let chars = explode(string) let len = arrayLength(chars) for (let mut i = 0; i < len; i += 1) { - chars[i] = Char.toAsciiLowercase(chars[i]) + chars[i] = Char.Ascii.toLowercase(chars[i]) } implode(chars) } @@ -2324,7 +2324,7 @@ provide let toAsciiUppercase = string => { let chars = explode(string) let len = arrayLength(chars) for (let mut i = 0; i < len; i += 1) { - chars[i] = Char.toAsciiUppercase(chars[i]) + chars[i] = Char.Ascii.toUppercase(chars[i]) } implode(chars) } diff --git a/stdlib/uri.gr b/stdlib/uri.gr index 5f198e997..0a90f0929 100644 --- a/stdlib/uri.gr +++ b/stdlib/uri.gr @@ -82,14 +82,14 @@ provide enum EncodeSet { let isHexDigit = char => { use Char.{ (<=), (>=) } - Char.isAsciiDigit(char) || + Char.Ascii.isDigit(char) || char >= 'A' && char <= 'F' || char >= 'a' && char <= 'f' } let isUnreservedChar = char => { - Char.isAsciiDigit(char) || - Char.isAsciiAlpha(char) || + Char.Ascii.isDigit(char) || + Char.Ascii.isAlpha(char) || char == '-' || char == '.' || char == '_' || @@ -142,10 +142,10 @@ let makeEncoder = (encodeSet: EncodeSet) => { } let charToHexValue = char => { - if (Char.isAsciiDigit(char)) { + if (Char.Ascii.isDigit(char)) { Char.code(char) - 0x30 } else { - let char = Char.toAsciiLowercase(char) + let char = Char.Ascii.toLowercase(char) Char.code(char) - 0x60 + 9 } } @@ -173,8 +173,8 @@ let decodeValid = (str, onlyUnreserved=false) => { let pctDecodedVal = charToHexValue(next) * 16 + charToHexValue(nextNext) if (onlyUnreserved && !isUnreservedChar(Char.fromCode(pctDecodedVal))) { Buffer.addChar('%', out) - Buffer.addChar(Char.toAsciiUppercase(next), out) - Buffer.addChar(Char.toAsciiUppercase(nextNext), out) + Buffer.addChar(Char.Ascii.toUppercase(next), out) + Buffer.addChar(Char.Ascii.toUppercase(nextNext), out) } else { Buffer.addUint8(Uint8.fromNumber(pctDecodedVal), out) } @@ -209,7 +209,7 @@ let normalizeHost = str => { } else if (i >= 2 && chars[i - 2] == '%') { getChars(i - 3, ['%', chars[i - 1], chars[i], ...acc]) } else { - getChars(i - 1, [Char.toAsciiLowercase(chars[i]), ...acc]) + getChars(i - 1, [Char.Ascii.toLowercase(chars[i]), ...acc]) } } let chars = getChars(String.length(str) - 1, []) @@ -259,15 +259,15 @@ let removeDotSegments = path => { /** * Percent-encodes characters in a string based on the specified `EncodeSet`. - * + * * @param str: The string to encode * @param encodeSet: An indication for which characters to percent-encode. `EncodeNonUnreserved` by default * @returns A percent-encoding of the given string - * + * * @example Uri.encode("h3ll0_.w ?o+rld", encodeSet=Uri.EncodeNonUnreserved) // "h3ll0_.w%20%3Fo%2Brld" * @example Uri.encode("d+om@i:n.com", encodeSet=Uri.EncodeRegisteredHost) // "d+om%40i%3An.com" * @example Uri.encode("word", encodeSet=Uri.EncodeCustom(c => c == 'o')) // "w%6Frd" - * + * * @since v0.6.0 */ provide let encode = (str, encodeSet=EncodeNonUnreserved) => { @@ -301,10 +301,10 @@ provide let encode = (str, encodeSet=EncodeNonUnreserved) => { /** * Decodes any percent-encoded characters in a string. - * + * * @param str: The string to decode * @returns `Ok(decoded)` containing the decoded string or `Err(err)` if the decoding failed - * + * * @since v0.6.0 */ provide let decode = str => { @@ -317,10 +317,10 @@ provide let decode = str => { /** * Encodes a list of key-value pairs into an query string. - * + * * @param urlVals: A list of key-value pairs * @returns A query string - * + * * @since v0.6.0 */ provide let encodeQuery = (urlVals, encodeSet=EncodeNonUnreserved) => { @@ -333,10 +333,10 @@ provide let encodeQuery = (urlVals, encodeSet=EncodeNonUnreserved) => { /** * Decodes a query string into a list of pairs. - * + * * @param str: A query string * @returns `Ok(decoded)` containing a list of key-value pairs from the decoded string or `Err(err)` if the decoding failed - * + * * @since v0.6.0 */ provide let decodeQuery = str => { @@ -419,7 +419,7 @@ module Matchers { } } - provide let digit = charTest(Char.isAsciiDigit) + provide let digit = charTest(Char.Ascii.isDigit) provide let digitInRange = (low, high) => charTest(char => { let code = Char.code(char) @@ -427,7 +427,7 @@ module Matchers { code >= zero + low && code <= zero + high }) - provide let alpha = charTest(Char.isAsciiAlpha) + provide let alpha = charTest(Char.Ascii.isAlpha) provide let hexDigit = charTest(isHexDigit) @@ -698,13 +698,13 @@ let parseFragment = (i, str, withDelim=false) => { * Parses a string into a `Uri` according to RFC 3986. If the URI string has a * path it will be automatically normalized, removing unnecessary `.` and `..` * segments. - * + * * @param str: The RFC 3986 URI string to parse * @returns `Ok(uri)` containing a `Uri` if the given string is a valid URI or `Err(ParseError)` otherwise - * + * * @example Uri.parse("https://grain-lang.org") == Ok(...) * @example Uri.parse("http://@*^%") == Err(Uri.ParseError) - * + * * @since v0.6.0 */ provide let parse = str => { @@ -727,15 +727,15 @@ provide let parse = str => { /** * Transforms a base URI and a URI reference into a target URI - * + * * @param base: The base URI to resolve a URI reference on * @param ref: The URI reference to apply onto the base * @returns `Ok(uri)` containing the target `Uri` or `Err(err)` if the input is malformed - * + * * @example resolveReference(unwrap(parse("https://grain-lang.org/docs/stdlib/uri")), unwrap(parse("../intro"))) // https://grain-lang.org/docs/intro * @example resolveReference(unwrap(parse("https://grain-lang.org/docs")), unwrap(parse("?key=val"))) // https://grain-lang.org/docs?key=val * @example resolveReference(unwrap(parse("https://grain-lang.org/docs")), unwrap(parse("google.com/search"))) // https://google.com/search - * + * * @since v0.6.0 */ provide let resolveReference = (base, ref) => { @@ -779,7 +779,7 @@ provide let resolveReference = (base, ref) => { /** * Constructs a new `Uri` from components. - * + * * @param scheme: `Some(scheme)` containing the desired scheme component or `None` for a scheme-less URI * @param userinfo: `Some(userinfo)` containing the desired userinfo component or `None` for a userinfo-less URI * @param host: `Some(host)` containing the desired host component or `None` for a host-less URI @@ -788,12 +788,12 @@ provide let resolveReference = (base, ref) => { * @param query: `Some(query)` containing the desired query string component or `None` for a query-less URI * @param fragment: `Some(fragment)` containing the desired fragment component or `None` for a fragment-less URI * @param encodeComponents: Whether or not to apply percent encoding for each component to remove unsafe characters for each component - * + * * @example Uri.make(scheme=Some("https"), host=Some("grain-lang.org")) // https://grain-lang.org * @example Uri.make(host=Some("g/r@in"), encodeComponents=false) // Err(Uri.InvalidHostError) * @example Uri.make(scheme=Some("abc"), host=Some("g/r@in"), query=Some("k/ey=v^@l"), encodeComponents=true) // abc://g%2Fr%40in?k/ey=v%5E@l * @example Uri.make(port=Some(80)) // Err(Uri.PortWithNoHost) - * + * * @since v0.6.0 */ provide let make = ( @@ -909,7 +909,7 @@ enum UpdateAction { * pattern used to update each component is that `None` means the base URI's * component should be used and `Some(val)` means that a new value should be * used for that component. - * + * * @param uri: The `Uri` to update * @param scheme: `Some(scheme)` containing the desired updated scheme component or `None` to maintain the base URI's scheme * @param userinfo: `Some(userinfo)` containing the desired updated userinfo component or `None` to maintain the base URI's userinfo @@ -919,13 +919,13 @@ enum UpdateAction { * @param query: `Some(query)` containing the desired updated query string component or `None` to maintain the base URI's query * @param fragment: `Some(fragment)` containing the desired updated fragment component or `None` to maintain the base URI's fragment * @param encodeComponents: Whether or not to apply percent encoding for each updated component to remove unsafe characters - * + * * @example let uri = Result.unwrap(Uri.parse("https://grain-lang.org/docs?k=v")) // Base URI for following examples * @example Uri.update(uri, scheme=Some(Some("ftp"))) // ftp://grain-lang.org/docs?k=v * @example Uri.update(uri, query=Some(None)) // https://grain-lang.org/docs * @example Uri.update(uri, host=Some(Some("g/r@in")), encodeComponents=true) // https://g%2Fr%40in/docs?k=v * @example Uri.update(uri, host=Some(None), port=Some(Some(80))) // Err(Uri.PortWithNoHost) - * + * * @since v0.6.0 */ provide let update = ( @@ -1053,30 +1053,30 @@ provide let update = ( /** * Determines whether a `Uri` has an authority (i.e. has a host component) - * + * * @param uri: The `Uri` to consider * @returns `true` if the `Uri` has an authority component or `false` otherwise - * + * * @since v0.6.0 */ provide let hasAuthority = uri => uri.host != None /** * Determines whether a `Uri` is an absolute URI (has a scheme component) - * + * * @param uri: The `Uri` to consider * @returns `true` if the `Uri` is absolute (has a scheme component) or `false` otherwise - * + * * @since v0.6.0 */ provide let isAbsolute = uri => uri.scheme != None /** * Converts the given `Uri` into a string. - * + * * @param uri: The `Uri` to convert * @returns A string representation of the `Uri` - * + * * @since v0.6.0 */ provide let toString = uri => { From efc1b43edf1cfa1ee58cf6632164756183f1bea3 Mon Sep 17 00:00:00 2001 From: Spotandjake <40705786+spotandjake@users.noreply.github.com> Date: Wed, 30 Oct 2024 12:42:15 -0400 Subject: [PATCH 3/5] Update stdlib/char.gr Co-authored-by: Oscar Spencer --- stdlib/char.gr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/char.gr b/stdlib/char.gr index 0b4118d6a..22c23ca40 100644 --- a/stdlib/char.gr +++ b/stdlib/char.gr @@ -348,7 +348,7 @@ provide module Ascii { * * @since v0.7.0 */ - provide let isValid = char => char <= '\u{007F}' // usv <= 0x7F + provide let isValid = char => char <= '\u{007F}' /** * Checks if the character is an ASCII digit. From 09475de8ff491274a8acce43613abc8033cdf57c Mon Sep 17 00:00:00 2001 From: Spotandjake <40705786+spotandjake@users.noreply.github.com> Date: Wed, 30 Oct 2024 12:42:25 -0400 Subject: [PATCH 4/5] Update stdlib/char.gr Co-authored-by: Oscar Spencer --- stdlib/char.gr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/char.gr b/stdlib/char.gr index 22c23ca40..0ca14c6ab 100644 --- a/stdlib/char.gr +++ b/stdlib/char.gr @@ -315,7 +315,7 @@ provide let (>=) = (x: Char, y: Char) => { } /** - * Sub module for working with ASCII characters. + * Utilities for working with ASCII characters. * * @example Char.Ascii.isAscii('1') * From e9242a675a8120f619ae7f92abf76098090e287c Mon Sep 17 00:00:00 2001 From: Spotandjake Date: Wed, 30 Oct 2024 12:42:48 -0400 Subject: [PATCH 5/5] chore: regen docs --- stdlib/char.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/char.md b/stdlib/char.md index d1a463c4a..f5a2def06 100644 --- a/stdlib/char.md +++ b/stdlib/char.md @@ -449,7 +449,7 @@ assert 'a' >= 'a' ## Char.Ascii -Sub module for working with ASCII characters. +Utilities for working with ASCII characters.
Added in next