Question

I have to do a very specific task to re-do over and over again and would like to have it put permanently in my .emacs file. But I am not versed enough in emacs-lisp to manage it:

  • Keystroke-1, say [F8]
    • remember the current cursors' column position in, say, xtab
  • Keystroke-2, say [F9] while cursor is in some other line:
    • find leftmost string // in current line, if none is there, beep and stop
    • insert as many spaces so the // gets to previously remembered column xtab, or do nothing if cursor is already beyond xtab
    • search-forward for next // and place the cursor on it

I managed to assign it to a temporary keyboard macro, but have to re-record it for every changing xtab value.

The ultimate goal is that I want to align the comments in different pieces of code easily, from

int main() {     // the enty function
    int x = 100; // my new variable
    for(int i=1; i<2012; ++i) { // loop a lot
        x -= i;
    } 
} // end of all things

to

int main() {                    // the entry function
    int x = 100;                // my new variable
    for(int i=1; i<2012; ++i) { // loop a lot
        x -= i;
    } 
}                               // end of all things

Any idea how I can automate this? What do I have to put in my .emacs-file to archive this -- or similar?

Was it helpful?

Solution

As tungd said, align-regexp is good for this sort of thing.

(defun my-align-comments (beginning end)
  "Align instances of // within marked region."
  (interactive "*r")
  (let (indent-tabs-mode align-to-tab-stop)
    (align-regexp beginning end "\\(\\s-*\\)//")))

Which is like the interactive call:
M-x align-regexp RET // RET

Or for a more language-agnostic version:

(defun my-align-comments (beginning end)
  "Align comments within marked region."
  (interactive "*r")
  (let (indent-tabs-mode align-to-tab-stop)
    (align-regexp beginning end (concat "\\(\\s-*\\)"
                                        (regexp-quote comment-start)))))

OTHER TIPS

Not exactly an answer to your question, but to achieve the desired goal you can just mark the region and use align-regexp.

Here's the code:

(defvar c-current-comment-col 30)
(defun c-set-comment-col ()
  (interactive)
  (setq c-current-comment-col (current-column)))
(defun c-comment-to-col ()
  (interactive)
  (beginning-of-line)
    (when (re-search-forward "//" (line-end-position) t)
      (backward-char 2)
      (let ((delta (- c-current-comment-col
                      (current-column))))
        (if (plusp delta)
            (insert (make-string delta ? ))
          (if (looking-back
               (format "\\( \\{%d\\}\\)" (- delta)))
              (delete-region
               (match-beginning 1)
               (match-end 1))
            (message
             "I'm sorry Dave, I afraid can't do that.")))))
    (next-line 1))
(global-set-key [C-f6] 'c-set-comment-col)
(global-set-key [f6] 'c-comment-to-col)

I've added a next-line call to the end. Now you can do C-f6 f3 f6 M-0 f4 to align until end of buffer.

M-x align is very powerful and will automatically handle the particular example given.

However, it will also align variable declarations, which may be more than you want. In that case, you would have to customize align-region-separate or use the align-regexp answer.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top