Merge branch 'master' into next
This commit is contained in:
commit
dabcddfb85
|
@ -826,58 +826,70 @@ end of string are ignored."
|
||||||
results ;skip trailing separator
|
results ;skip trailing separator
|
||||||
(cons (substring string i) results)))))))
|
(cons (substring string i) results)))))))
|
||||||
|
|
||||||
(defun org--string-from-props (s property)
|
(defun org--string-from-props (s property beg end)
|
||||||
"Return the visible part of string S.
|
"Return the visible part of string S.
|
||||||
Visible part is determined according to text PROPERTY, which is
|
Visible part is determined according to text PROPERTY, which is
|
||||||
either `invisible' or `display'."
|
either `invisible' or `display'. BEG and END are 0-indices
|
||||||
(let ((len (length s))
|
delimiting S."
|
||||||
(new nil)
|
(let ((width 0)
|
||||||
(i 0)
|
(cursor beg))
|
||||||
(cursor 0))
|
(while (setq beg (text-property-not-all beg end property nil s))
|
||||||
(while (setq i (text-property-not-all i len property nil s))
|
(let* ((next (next-single-property-change beg property s end))
|
||||||
(let* ((end (next-single-property-change i property s len))
|
(props (text-properties-at beg s))
|
||||||
(props (text-properties-at i s))
|
|
||||||
(spec (plist-get props property))
|
(spec (plist-get props property))
|
||||||
(value
|
(value
|
||||||
(pcase property
|
(pcase property
|
||||||
(`invisible
|
(`invisible
|
||||||
;; If `invisible' property in PROPS means text is to
|
;; If `invisible' property in PROPS means text is to
|
||||||
;; be invisible, return the empty string. Otherwise
|
;; be invisible, return 0. Otherwise return nil so
|
||||||
;; return nil so that the part is skipped.
|
;; as to resume search.
|
||||||
(and (or (eq t buffer-invisibility-spec)
|
(and (or (eq t buffer-invisibility-spec)
|
||||||
(assoc-string spec buffer-invisibility-spec))
|
(assoc-string spec buffer-invisibility-spec))
|
||||||
""))
|
0))
|
||||||
(`display
|
(`display
|
||||||
(pcase spec
|
(pcase spec
|
||||||
(`nil nil)
|
(`nil nil)
|
||||||
|
(`(space . ,props)
|
||||||
|
(let ((width (plist-get props :width)))
|
||||||
|
(and (wholenump width) width)))
|
||||||
(`(image . ,_)
|
(`(image . ,_)
|
||||||
;; Since we are returning a string, create
|
(ceiling (car (image-size spec))))
|
||||||
;; a place-holder with the same width as the
|
|
||||||
;; image.
|
|
||||||
(make-string (ceiling (car (image-size spec))) ?\s))
|
|
||||||
((pred stringp)
|
((pred stringp)
|
||||||
;; Displayed string could contain invisible parts,
|
;; Displayed string could contain invisible parts,
|
||||||
;; but no nested display.
|
;; but no nested display.
|
||||||
(org--string-from-props spec 'invisible))
|
(org--string-from-props spec 'invisible 0 (length spec)))
|
||||||
(_ (error "Un-handled `display' value: %S" spec))))
|
(_
|
||||||
|
;; Un-handled `display' value. Ignore it.
|
||||||
|
;; Consider the original string instead.
|
||||||
|
nil)))
|
||||||
(_ (error "Unknown property: %S" property)))))
|
(_ (error "Unknown property: %S" property)))))
|
||||||
(when value
|
(when value
|
||||||
(setq new (concat new (substring s cursor i) value))
|
(cl-incf width
|
||||||
(setq cursor end))
|
;; When looking for `display' parts, we still need
|
||||||
(setq i end)))
|
;; to look for `invisible' property elsewhere.
|
||||||
(if new (concat new (substring s cursor))
|
(+ (cond ((eq property 'display)
|
||||||
;; If PROPERTY was not found, return S as-is.
|
(org--string-from-props s 'invisible cursor beg))
|
||||||
s)))
|
((= cursor beg) 0)
|
||||||
|
(t (string-width (substring s cursor beg))))
|
||||||
|
value))
|
||||||
|
(setq cursor next))
|
||||||
|
(setq beg next)))
|
||||||
|
(+ width
|
||||||
|
;; Look for `invisible' property in the last part of the
|
||||||
|
;; string. See above.
|
||||||
|
(cond ((eq property 'display)
|
||||||
|
(org--string-from-props s 'invisible cursor end))
|
||||||
|
((= cursor end) 0)
|
||||||
|
(t (string-width (substring s cursor end)))))))
|
||||||
|
|
||||||
(defun org-string-width (string)
|
(defun org-string-width (string)
|
||||||
"Return width of STRING when displayed in the current buffer.
|
"Return width of STRING when displayed in the current buffer.
|
||||||
Unlike `string-width', this function takes into consideration
|
Unlike `string-width', this function takes into consideration
|
||||||
`invisible' and `display' text properties. It supports the
|
`invisible' and `display' text properties. It supports the
|
||||||
latter in a limited way; it raises an error if it cannot handle
|
latter in a limited way, mostly for combinations used in Org.
|
||||||
a given `display' combination."
|
Results may be off sometimes if it cannot handle a given
|
||||||
(string-width
|
`display' value."
|
||||||
(org--string-from-props (org--string-from-props string 'display)
|
(org--string-from-props string 'display 0 (length string)))
|
||||||
'invisible)))
|
|
||||||
|
|
||||||
(defun org-not-nil (v)
|
(defun org-not-nil (v)
|
||||||
"If V not nil, and also not the string \"nil\", then return V.
|
"If V not nil, and also not the string \"nil\", then return V.
|
||||||
|
|
|
@ -63,7 +63,9 @@
|
||||||
(should (= 5 (org-string-width #("1a3" 1 2 (display "abc")))))
|
(should (= 5 (org-string-width #("1a3" 1 2 (display "abc")))))
|
||||||
;; `display' string can also contain invisible characters.
|
;; `display' string can also contain invisible characters.
|
||||||
(should (= 4 (org-string-width
|
(should (= 4 (org-string-width
|
||||||
#("123" 1 2 (display #("abc" 1 2 (invisible t))))))))
|
#("123" 1 2 (display #("abc" 1 2 (invisible t)))))))
|
||||||
|
;; Test `space' property in `display'.
|
||||||
|
(should (= 2 (org-string-width #(" " 0 1 (display (space :width 2)))))))
|
||||||
|
|
||||||
|
|
||||||
;;; Regexp
|
;;; Regexp
|
||||||
|
|
Loading…
Reference in New Issue