3

Is it possible to have a text string as a text property in emacs? Let me explain. I usually work with latex documents and I need to format their bibliographies that have, e.g., this structure:

\begin{thebibliography}{9}

\bibitem{bib1}
Some text...

\bibitem{bib2}
Some text...

\bibitem{bib3}
Some text...

...

I'd like to have in my buffer:

\begin{thebibliography}{9}

\bibitem{bib1} [1]
Some text...

\bibitem{bib2} [2]
Some text...

\bibitem{bib3} [3]
Some text...

...

where [1], [2], [3] are not meant to be "real text" but "properties" of the corresponding strings. (A sort of "watermark"...) Actually those strings should not be send to the latex compiler...

I know I can use commented text (and so I do in my daily work) but it would be better for my needs if I could get that behaviour.

EDIT. Ok, Drew showed me the way... I did it with:

(defun BibitemNumbering ()
  (interactive)
  (save-excursion
    (let ((counter 0))

      (while (search-forward-regexp "\\\\bibitem{[^}]+}\\(\n\\)" nil t)
    (save-excursion
      (let ((b (make-marker))
        (e (make-marker)))

    (setq counter (1+ counter))
    (set-marker b (match-beginning 1))
    (set-marker e (point))

    (put-text-property b e 'display (concat " ["
                        (number-to-string counter)
                        "]\n"))
    )))
      )))

Is this the right way? Also, I'd like to have the displayed string "coloured" or with a coloured background. How can I set this?

4

You can put any Lisp object (thingie) on a character as a text property or on in an overlay as an overlay property or on a symbol as a symbol property.

You speak of "strings" but in your examples I see no strings. I see only buffer text (presumably). What you apparently want to do is put something (strings perhaps?) as a text property (or as multiple text properties), on certain characters in a buffer. No problem.

Use add-text-properties or put-text-property, as usual.


A trick I use sometimes is to put a list whose car is a string as a text property on that very string, thus encoding the full list within just the string (its car).

This is handy for contexts that use an alist for completion but present only their cars (strings) as completion candidates and return only a string as the chosen candidate. This trick lets the strings (cars of the alist entries) hold all of the information of the full candidates (alist entries).

For example, in Bookmark+ I do this, to add a bookmark record (a list) as text property bmkp-full-record to string bname, which is the car of the bookmark record.

(put-text-property 0 (length bname) 'bmkp-full-record bmk bname)

Updated after your comment that you want to, in effect, annotate some buffer text without adding text to the buffer itelf:

As @JeanPierre suggested in a comment: Use text-property (or overlay-property) display to show additional text that is not part of the buffer text. Use a "replacing" display spec, replacing some of the buffer text (e.g., bibitem{bib1} with itself plus the annotation text, for example, "[1]".

Or, as @JeanPierre said, put the property with value "[1]" on a newline character, if there is always a newline char that follows the text you want to annotate.

  • Let me better explain... I mean to "link" the string [1] to the string bibitem{bib1}, where the first one is meant to be a "property" of the second one. I figured out to do that with a loop... – Gabriele Nicolardi Jun 29 '17 at 15:00
  • I guess you are saying that you put a text property (e.g. foo), whose value is a string "[1]", on the buffer text bibitem{bib1}. – Drew Jun 29 '17 at 15:05
  • 1
    You could set a display property on the newline with a value of "[1]\n" gnu.org/software/emacs/manual/html_node/elisp/… – JeanPierre Jun 29 '17 at 15:36
  • 1
    Wrt learning Emacs Lisp: (1) Read the manual An Introduction to Programming in Emacs Lisp (choose Emacs Lisp Intro from C-h i). (2) Look at Emacs source code. For example, grep for 'display in the source code, to see how the property is used. – Drew Jun 29 '17 at 17:12
  • 1
    @Tobias Don't blame me! It was just a moment of frustration... It's two hours that I'm trying to assign a colour to the displayed text of this post... AARGH! But, step by step I'm learning something new every time... ;-) – Gabriele Nicolardi Jun 29 '17 at 19:27
3

Ok, I accepted the Drew's answer but I want also to share the complete solution I finally adopted.

This is the code:

(defun BibitemNumbering ()

  (interactive)
  (save-excursion
    (let ((counter 0))

      (while (search-forward-regexp "\\\\bibitem{[^}]+}\\(\n\\)" nil t)
    (save-excursion
      (let ((b (make-marker))
        (e (make-marker))
        STRING)

        (setq counter (1+ counter))
        (set-marker b (match-beginning 1))
        (set-marker e (point))
        (setq BibNumberOverlay (make-overlay b e))
        (setq STRING (propertize (concat "[" (number-to-string counter) "]") 'face '(:background "DarkOrange3" )))
        (setq STRING (concat " " STRING "\n"))
;       (put-text-property b e 'display STRING)
        (overlay-put BibNumberOverlay 'display STRING)
        )))
      )))

and this is the result:

enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.