0

In the company where I work we use Emacs as the default editor for the LaTeX copy-editing tasks and we share some Emacs scripts to automate/guide some operations.

Actually I need to perform some query-replacements into the LaTeX code and to make my colleagues aware of the purpose of these replacements. To do this I use this kind of functions in my scripts:

(query-replace-with-info "foo"
                         "bar"
                         "This replacement is appropriate in the following cases..."
                         nil (point-min) (point-max))

making Emacs behave like in the following figure: enter image description here

To build my query-replace-with-info function I hacked the perform-replace function in this way: https://pastebin.com/79y7PKP7

The problem with this is that I cannot easily mantain the code if perform-replace will be updated in newer Emacs versions.

So I'd like to write a macro in this form:

(with-query-replace-description
 "This replacement is appropriate in the following cases..."
 (query-replace "foo"
                "bar"
               nil (point-min) (point-max)))

The description could be displayed in a temp-buffer.

Any suggestions?

Info added

I added an extra argument INFO-STRING to the original perform-replace function:

(defun perform-replace-with-info (from-string replacements
                          query-flag regexp-flag INFO-STRING  delimited-flag
                          &optional repeat-count map start end backward region-noncontiguous-p)
...

and, in the let arguments, I added:

(info-string (if INFO-STRING
              (propertize
               (concat INFO-STRING "\n\n")
               'face '(:foreground "goldenrod"
                           ;; :background "DarkGoldenrod1"
                           ))
            ;; *ELSE*
            ""))

Finally I modified the original message argument in the let args, this way:

(message
          (if query-flag
          (concat ; <-- The magic
           info-string ; <--
           (apply 'propertize
              (substitute-command-keys
               "Query replacing %s with %s: (\\<query-replace-map>\\[help] for help) ")
              minibuffer-prompt-properties)))))

Can this be done with the advice tecnique suggested by Drew in the comments? (I just read that advice could be evil... please ignore this last question.)

5
  • It sounds like using Emacs advice would be appropriate. Even if changes are made to perform-replace, it sounds like you're just wrapping what it does with a function that displays some text. If I'm missing what you're saying, maybe say in your question why Emacs advice wouldn't be appropriate, to give a better idea of what you need/want.
    – Drew
    May 27 at 18:49
  • I didn't know about advice! Thanks. But I'm not sure if I can use it in this case. I added an extra argument (the INFO_STRING) to the original perform-replace function and I concatenated ((concat)) it to the original message diplayed by the function. message is a variable declared in the let part of fhe perform-replace function. May 27 at 19:08
  • Advice is not evil. It's just one more tool at your disposal. Of course, like anything it has its drawbacks/limitations. It sounded to me like you were asking about modifying an existing function, and advice is one way to do that, without source-code surgery. See Emacs Wiki Advice and Advice vs Hooks.
    – Drew
    May 28 at 18:16
  • @Drew, ok, thanks. I was just scared by the Richard Stallman's words about Advice. May 28 at 20:26
  • RMS was only stating the policy for code that's to be included as part of Emacs. And that's a good policy. (And it's unfortunately no longer respected thoroughly, since the move to the new nadvice system.)
    – Drew
    May 28 at 22:59

1 Answer 1

0

Use advice only in the last resort. Preferred approaches, in order:

  1. Hooks. Many Emacs operations allow you to add your own functions to be called in response to events triggered by those operations: before-save-hook, after-save-hook, etc etc.

  2. Failing that, write your own command that "decorates" the original command, adding behavior before or after a call to the original (or both).

  3. If the change you want cannot be achieved thus, for example, if the change you want needs to occur within the body of the original command, then copy, rename and modify the original's code (or use advice, see below).

  4. If you really need system-wide, ongoing, transparent replacement of the original, you can instead copy and modify without renaming, but there are big problems, one of which you have noted, that your changes may break a future version. It has to be your responsibility to make sure that this doesn't happen.

  5. Advice. It seems like a miracle cure for all ills, but it also has its own problems. Its transparency can be a problem as well as a benefit, since other users (or you after a few months) may not know/remember it is there. Keep it very, very simple, clean and uncluttered.

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.