You can extract properties from a given position of a string or buffer with function text-properties-at
. Here's its docstring (C-h f text-properties-at
):
text-properties-at is a built-in function in ‘C source code’.
(text-properties-at POSITION &optional OBJECT)
Return the list of properties of the character at POSITION in OBJECT.
If the optional second argument OBJECT is a buffer (or nil, which means
the current buffer), POSITION is a buffer position (integer or marker).
If OBJECT is a string, POSITION is a 0-based index into it.
If POSITION is at the end of OBJECT, the value is nil.
Once you have the properties (it's a list) you can turn it into a string using format
. For example (from @Drew):
(setq mystrg (propertize "abcd" 'foo 'foo-prop 'bar 'bar-prop))
(text-properties-at 0 mystrg) ; ==> (foo foo-prop bar bar-prop)
(setq prop-strg (format "%s" (text-properties-at 0 mystrg)))
For more info, see the section of elisp manual on Examining Text Properties.
However if you're interested in showing all the properties and where they apply in the string (that is, you want to get as a string the part about properties of the printed representation of the string) then you can get the printed representation with prin1-to-string
then extract the part with properties (that is, after the representation of the string itself).
It turns out to be not so simple, because the printed representation differs according to the presence of properties of not, and the length of the text part varies if escapes are present. For a straight string the text representation is:
"the string"
while for a string with properties it is:
#("the string" 0 3 (properties) ...)
but can also be:
#("a string with a \" inside" 0 3 (properties) ...)
Here is a tentative function:
(defun get-string-properties-as-string (st)
"Return a string showing the properties of ST."
(let ((p (prin1-to-string st)))
(if (eq (elt p 0) ?#)
(let ((nb (length (seq-filter (lambda (c) (eq c ?\")) st))) ;; how many " in ST
(p (substring p 2 (1- (length p))))) ;; remove #( and )
(loop for i from 1 to (+ 2 nb) do
;; remove characters up to the next "
(setq p (seq-drop p (1+ (seq-position p ?\")))))
p)
;; string with no properties
"")))
Maybe someone will propose a better way to do that, it looks rather ugly I think.
format
? Example:(format "%s" (text-properties-at (point)))
. – JeanPierre Dec 05 '19 at 08:19text-properties-at
. We get the text properties at point, thenformat
them to a string.text-properties-at
can also be applied to a string. See section 32.19.1 of elisp manual. https://www.gnu.org/software/emacs/manual/html_node/elisp/Examining-Properties.html#Examining-Properties – JeanPierre Dec 05 '19 at 11:09object-intervals
: https://git.savannah.gnu.org/cgit/emacs.git/commit/?id=aa7e5ce651b1872180e8da94ac80fbc25e33eec0 – Basil Dec 18 '20 at 12:59