Compare commits

...

2 Commits

Author SHA1 Message Date
Vivianne 50f8bb891d
Add string->grapheme-list and char->grapheme
- string->grapheme-list gets only final graphemes without intermediate ones
- char->grapheme just works for single-chars that are valid graphemes.
2024-03-10 23:50:05 -04:00
Vivianne afa19676c5
Add new function to get the first grapheme from a string.
Not sure if I have a use-case yet but it seems like it could come in handy.
2024-03-10 20:09:25 -04:00
1 changed files with 49 additions and 2 deletions

View File

@ -1,5 +1,9 @@
(define-module (uniseg graphemes)
#:use-module (ice-9 hash-table)
#:use-module (uniseg graphemes stream)
#:use-module (uniseg graphemes iterator)
#:use-module (ice-9 hash-table)
#:use-module (ice-9 streams)
#:use-module (srfi srfi-41)
#:use-module (srfi srfi-1)
#:use-module (srfi srfi-9 gnu)
#:export (make-grapheme
@ -10,7 +14,10 @@
grapheme-glyphs
grapheme-glyphs-reverse
grapheme-state
grapheme-string))
grapheme-string
string->grapheme
string->grapheme-list
char->grapheme))
(define-immutable-record-type <grapheme>
(_make-grapheme width delta-width modification? state glyphs-reverse glyphs-promise string-promise)
@ -40,3 +47,43 @@
(define (grapheme-string grapheme)
"Return a lazily-constructed string of the glyphs in the grapheme."
(force (_grapheme-string-promise grapheme)))
(define (string->grapheme-list str)
"Get a list of all the final graphemes (not including intermediates) in the provided string"
(define stream (string->grapheme-stream str))
(let loop ((stream stream))
(define grapheme (stream-car stream))
(define next-stream (stream-cdr stream))
(define have-next? (stream-pair? next-stream))
(define next-modification?
(and have-next?
(grapheme-modification? (stream-car next-stream))))
(cond
(next-modification? (loop next-stream))
(have-next? (cons grapheme (loop next-stream)))
(else (list grapheme)))))
(define (string->grapheme str)
"Reads from `str' until we reach the end of the first grapheme cluster"
(define stream (string->grapheme-stream str))
(define first-grapheme (stream-car stream))
;; Skip first, we want to get the last entry that is a modification
;; (or the first entry, if there are no mods afterwards)
(define last-grapheme
(let loop ((stream stream))
(define grapheme (stream-car stream))
(define next-stream (stream-cdr stream))
(if (and (stream-pair? next-stream)
(grapheme-modification? (stream-car next-stream)))
(loop next-stream)
grapheme)))
(if (grapheme-modification? last-grapheme)
last-grapheme
first-grapheme))
(define (char->grapheme char)
"Attempt to convert a char to a grapheme. Returns #f if no valid grapheme is formed from the single character."
((make-grapheme-iterator) char))