Input and desired output

Original code                       Commented out code:                  
C %% MODULE %% module_name           C~ CPR C ## MODULE ## module_name    
lines of code                        C~ CPR lines of code                 
lines of code                        C~ CPR lines of code                 
.....                                C~ CPR .....                         
.....                                C~ CPR .....                         
.....                                C~ CPR ....                          
....                                 C~ CPR ....
....                                 C~ CPR ....
C %% END MODULE %% module_name       C~ CPR C ## END MODULE ## module_name


  1. The cursor (point) is usually somewhere in between the C %% MODULE %% and C %% END MODULE %%
  2. Select the lines between C %% MODULE %% and C %% END MODULE %% and replace-string %% with ##
  3. The C-x C-xto make the repeat the last selection and run string-insert-rectangle and insert the comment text C~ CPR -

My Function (I'm new to elisp, bear with my terrible code)

(defun comment-pdtn()
  (set-buffer (buffer-name))                  
  (search-backward "C %% MODULE %%")
  (set-mark (- (point) 14))              ;; 14 is the # of char in C %% MODULE %%
  (search-forward "C %% END MODULE %%")
  (message "begin at %s and ends at %s" ;; Want to ensure that region selection happened
  (string-insert-rectangle "C~ CPR "))  ;; This isn't working


I'm yet to add the functionality for replace-string yet. How to implement string-insert-rectanglein Elisp? I want to write something like this,

  1. With region ( string-insert-rectangle "C~ CPR ")
  2. With region ( replace-string "%%" "##")

I could do this with macro and save the macro and do away with it, but I want to learn elisp that is the reason behind this question.

  • 3
    Not to derail the learning, but you probably want to use M-; in conjunction with the config (setq comment-start "C~ CPR " comment-start-skip "C~ CPR +" comment-use-syntax nil) which could be set in the mode hook for whatever mode this is.
    – phils
    Commented Jun 5, 2020 at 3:42
  • How did you know this? I was trying to see if I could customize M-; but didn't know how. From where can I learn this
    – Prasanna
    Commented Jun 5, 2020 at 5:23
  • Refer to C-h i g (emacs)Options for Comments and the docstrings for the variables in question.
    – phils
    Commented Jun 5, 2020 at 7:06
  • emacs.stackexchange.com/tags/elisp/info
    – Drew
    Commented Jun 5, 2020 at 17:26

1 Answer 1


You usually don't need to manipulate the region with the Lisp code besides accessing the current region, that is, you seldom call set-mark from Lisp. Emacs commands operate on the region usually take the arguments START and END, thus when you call these commands from Lisp, you don't need the region, you need only two buffer positions, for example,

M-x mark-whole-buffer
M-x string-insert-rectangle prefix-

should be "translated" into

(string-insert-rectangle (point-min) (point-max) "prefix-")

The following takes advantage of (emacs) Narrowing, so we don't need to keep tracking the region we're working on.

(save-excursion                         ; restore point (optional)
  (save-restriction                     ; undo narrow
    ;; Step 1. Narrow to the region, so we won't change other area by accident
     (progn (search-backward "C %% MODULE %%")
     (progn (search-forward "C %% END MODULE %%")

    ;; Step 2. Replace %% with ##, we don't use `replace-string' because its docstring suggests so
    (goto-char (point-min))
    (while (search-forward "%%" nil t)
      (replace-match "##" nil t))

    ;; Step 3. Insert the prefix to each line of the (narrowed) buffer
    (string-insert-rectangle (point-min) (point-max) "C~ CPR ")))

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.