diff --git a/org-window-habit-graph.el b/org-window-habit-graph.el index e49512e..f9a8be9 100644 --- a/org-window-habit-graph.el +++ b/org-window-habit-graph.el @@ -289,13 +289,12 @@ Return nil when HABIT is inactive at NOW." (defun org-window-habit-make-graph-string (graph-info) "Convert GRAPH-INFO into a propertized string for display. GRAPH-INFO is a list of (character face) pairs." - (let ((graph (make-string (length graph-info) ?\s))) - (cl-loop for (character face) in graph-info + ;; Build the string from the characters up front: `aset' into a + ;; `make-string' buffer rejects non-ASCII glyphs on Emacs 31. + (let ((graph (concat (mapcar #'car graph-info)))) + (cl-loop for (_character face) in graph-info for index from 0 - do - (progn - (aset graph index character) - (put-text-property index (1+ index) 'face face graph))) + do (put-text-property index (1+ index) 'face face graph)) (put-text-property 0 (length graph) 'org-window-habit-graph t graph) graph)) diff --git a/test/org-window-habit-test.el b/test/org-window-habit-test.el index dcb1c3b..e30caac 100644 --- a/test/org-window-habit-test.el +++ b/test/org-window-habit-test.el @@ -1338,6 +1338,19 @@ This tests backwards compatibility - both old formats work." (let ((graph-info '((?x face1) (?y face2) (?z face3)))) (should (= (length (org-window-habit-make-graph-string graph-info)) 3)))) +(ert-deftest owh-test-make-graph-string-non-ascii-glyphs () + "Non-ASCII glyphs such as the default ✓ and ☐ must render with their faces." + (let* ((graph-info `((,org-window-habit-completed-glyph face1) + (?\s face2) + (,org-window-habit-completion-needed-today-glyph face3))) + (graph (org-window-habit-make-graph-string graph-info))) + (should (equal (substring-no-properties graph) + (string org-window-habit-completed-glyph ?\s + org-window-habit-completion-needed-today-glyph))) + (should (equal (mapcar (lambda (i) (get-text-property i 'face graph)) '(0 1 2)) + '(face1 face2 face3))) + (should (get-text-property 0 'org-window-habit-graph graph)))) + ;;; ========================================================================== ;;; Scenario-Based Tests: Real-World Habit Configurations