1

How to write an elisp function that transforms the word at point?

Specifically, in the C++ code I am refactoring I have to replace tons of raw pointers into smart pointers. Say, for class Foo, I would move point to the start of the word Foo, call my function, and obtain std::shared_ptr<Foo>.

So, the function I wish to implement would do these things:

  1. Move point to the beginning of the word.
  2. Insert hard-coded text (std::shared_ptr<).
  3. Go to the end of the word.
  4. Insert >.
6
  • This question is likely a duplicate. Please search tag [query-replace] or tag [replace], and delete this question if you find it's a duplicate. Thx.
    – Drew
    Oct 24, 2022 at 17:11
  • 1
    Of course, you could write and bind your own elisp command, but you might find it simpler to record, save and bind a keyboard macro. Oct 24, 2022 at 17:25
  • Sorry @Drew, I find your editing went a bit far. I do want to write an elisp macro. I do not want a complicated sequence of keystrokes which I have to remember and repeat anew in each session.
    – Joachim W
    Oct 24, 2022 at 18:32
  • No, this has nothing to do with Elisp macros. Read the meaning of the tags. It sounds like you want a single key binding that does what you want. That's a keyboard macro or a command that's bound to a key. The meat of it is to make the change you want. How that's bound to a key is something else.
    – Drew
    Oct 24, 2022 at 22:18
  • What Drew is talking about is that the word "macro" has two very different meanings in an emacs context. What you want is a keyboard macro which can automate repetitive key sequences. An elisp macro is a language construct that generates elisp code -- same word but very different meaning.
    – g-gundam
    Oct 24, 2022 at 22:38

1 Answer 1

2

Creating Reusable Keyboard Macros In Emacs

There is a concise article on how to use keyboard macros in Emacs that I recommend you read. The info in that article can be adapted to solve your specific problem like this:

  • Place your cursor on the 'F' in a variable declaration of type Foo.
  • Hit C-x ( to start recording a macro.
  • Type s t d : : s h a r e d _ p t r < C-right >
  • Hit C-x ) to stop recording the macro.
  • Hit M-x name-last-kbd-macro to give the macro you just created a name. For this example, I called it std-shared-ptr.
  • Open your emacs configuration file.
  • Type M-x insert-kbd-macro and tell it to insert std-shared-ptr. The end result should look like this.
(fset 'std-shared-ptr
   (kmacro-lambda-form [?s ?t ?d ?: ?: ?s ?h ?a ?r ?e ?d ?_ ?p ?t ?r ?< C-right ?>] 0 "%d"))

The fset function creates an interactive function named std-shared-ptr, and you can see what keys are going to be sent to Emacs by inspecting the vector it generated.

You can invoke this macro by hitting M-x std-shared-ptr, but if you're going to do this a lot, you might want to bind this to something that's easier to type. Also, we created this macro using Foo, but the C-right we hit while creating the macro should make it work for any type or class.

1
  • 1
    Instead of C-<right> (which is bound to right-word), I would recommend C-M-<right> (which is bound to forward-sexp): if the class name contains an underscore (which I iimagine is a a frequent occurrence), right-word would stop before the first underscore, wheres forward-sexp) would stop after the whole identifier. BTW, in my case, C-M-<right is preempted by my desktop environment, so I have to use <ESC> C-<right> instead.
    – NickD
    Oct 26, 2022 at 12:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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