]> git.eshelyaron.com Git - emacs.git/commitdiff
Add new function string-glyph-split
authorLars Ingebrigtsen <larsi@gnus.org>
Sat, 30 Oct 2021 13:22:36 +0000 (15:22 +0200)
committerLars Ingebrigtsen <larsi@gnus.org>
Sat, 30 Oct 2021 13:22:36 +0000 (15:22 +0200)
* doc/lispref/strings.texi (Creating Strings): Document it.
* lisp/emacs-lisp/shortdoc.el (string): Mention it.

* lisp/emacs-lisp/subr-x.el (string-glyph-split): New function.

doc/lispref/strings.texi
etc/NEWS
lisp/emacs-lisp/shortdoc.el
lisp/emacs-lisp/subr-x.el

index 7212677d8322c8d6a2573060c0e71a3c0c4eae8b..a9e1105c8242a464399ac42d4a31b9989077f8b7 100644 (file)
@@ -248,6 +248,24 @@ equivalent to 0.  Thus, @w{@code{(substring-no-properties
 properties removed.
 @end defun
 
+@defun string-glyph-split string
+Special care has to be taken when handling strings that are meant to
+be displayed.  @code{substring} and friends work on individual
+characters (i.e., code points), but things like emojis are often
+represented by @dfn{grapheme clusters}, which are basically a bunch of
+code points ``glued together'' in various ways.  This function splits
+up strings like that into a list of strings, where each of these
+resulting strings represents a glyph that should be displayed as a
+unit.
+
+For instance, if you want to display a string without the first glyph,
+you can say:
+
+@example
+(apply #'insert (cdr (string-glyph-split string))))
+@end example
+@end defun
+
 @defun concat &rest sequences
 @cindex copying strings
 @cindex concatenating strings
index da9e803e9e978f434279d6cfa9014231dccfba5a..7f1fa8b8f4d20f59bae9243e4c51fce5f05d9f4b 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -427,6 +427,12 @@ This returns the width of a string in pixels.  This can be useful when
 dealing with variable pitch fonts and glyphs that have widths that
 aren't integer multiples of the default font.
 
++++
+** New function 'string-glyph-split'.
+This function splits a string into a list of strings representing
+separate glyphs.  This takes into account combining characters and
+grapheme clusters.
+
 ---
 ** 'lookup-key' is more allowing when searching for extended menu items.
 In Emacs 28.1, the behavior of 'lookup-key' was changed: when looking
index 817dfa6b71ec4e3b54ae9d097a91e24c2dd8385f..daf362dd88b274e0abea8cc62a9b5a2765273f99 100644 (file)
@@ -159,6 +159,8 @@ There can be any number of :example/:result elements."
    :eval (split-string-and-unquote "foo \"bar zot\""))
   (split-string-shell-command
    :eval (split-string-shell-command "ls /tmp/'foo bar'"))
+  (string-glyph-split
+   :eval (string-glyph-split "Hello, πŸ‘ΌπŸ»πŸ§‘πŸΌβ€πŸ€β€πŸ§‘πŸ»"))
   (string-lines
    :eval (string-lines "foo\n\nbar")
    :eval (string-lines "foo\n\nbar" t))
index 9a82fe2449d6c0cb22b95fdcd4c04dd56ee74948..e3caf88c2f5182d7a84c66fb4e2b524abb35b0a3 100644 (file)
@@ -449,6 +449,22 @@ is inserted before adjusting the number of empty lines."
     (car (window-text-pixel-size
           (current-buffer) (point-min) (point)))))
 
+;;;###autoload
+(defun string-glyph-split (string)
+  "Split STRING into a list of strings representing separate glyphs.
+This takes into account combining characters and grapheme clusters."
+  (let ((result nil)
+        (start 0)
+        comp)
+    (while (< start (length string))
+      (if (setq comp (find-composition-internal start nil string nil))
+          (progn
+            (push (substring string (car comp) (cadr comp)) result)
+            (setq start (cadr comp)))
+        (push (substring string start (1+ start)) result)
+        (setq start (1+ start))))
+    (nreverse result)))
+
 (provide 'subr-x)
 
 ;;; subr-x.el ends here