Re: "Buttons" in a message buffer that evaluate to plain text?
Tim Landscheidt <[email protected]>
| Newsgroups | gmane.emacs.help |
|---|---|
| Organization | https://www.tim-landscheidt.de/ |
| Message-ID | <[email protected]> |
Michael Heerdegen wrote:
>> With Emacs 30.2, what is the best practice to achieve that
>> plain text ↔ "buttons" conversion? Is there an existing
>> ELPA package that does something similar?
> The simplest way to convert a region of buffer text into buttons is
> probably `buttonize-region' - see
> (info "(elisp) Making Buttons")
> I don't know if there are more high-level tools that handle your use
> case are available. Not so far in the past I needed something similar
> (a button toggling between different string values that are/get part of
> the resulting text) and wrote it by myself.
It was indeed rather simple:
| (while (re-search-forward "#\\([1-9a]\\) +\\(\\[ +\\]\\)" (point-max) t)
| (let
| ((choices (if (string= (match-string 1) "a")
| '("JA" "NEIN" "ANNULLIERUNG")
| '("JA" "NEIN" "ENTHALTUNG"))))
| (make-button
| (match-beginning 2)
| (match-end 2)
| 'action (lambda (button)
| (save-mark-and-excursion
| (let
| ((current-label (button-label button)))
| (if (string-match "\\`\\[ *\\([^ ]*\\) *\\]\\'" current-label)
| (replace-region-contents
| (+ (button-start button) 1)
| (- (button-end button) 1)
| (lambda
| nil
| (let*
| ((current-choice (match-string 1 current-label))
| (next-choice (if (string-empty-p current-choice)
| (car choices)
| (or (cadr (member current-choice choices)) "")))
| (original-field-length (- (point-max) (point-min))))
| (concat
| (make-string (max (/ (- original-field-length (length next-choice)) 2) 0) ?\s)
| actual-choice
| (make-string (max (/ (- (+ original-field-length 1) (length next-choice)) 2) 0) ?\s))))))))))))
message-mode will just ignore overlays, so the sent message
contains the text only. Very nice, thanks for the pointer.
One minor flaw: Replacing the button's "label" (i. e., the
text "[ ENTHALTUNG ]", etc.) will move point to either the
beginning or the end of the replaced text. Aside from
replace-region-contents I also tried delete-char/insert with
overwrite-mode set to 'overwrite-mode-textual, but the
latter does not seem to have any effect to turn insert into
a "replace".
While I probably could do some arithmetics with point or
mark myself, any (in my case hypothetical) marker would
still be moved.
How can I actually replace the character/text at point
without deleting and inserting?
Tim