Joseph Garvin
Joseph Garvin

Reputation: 21974

How to wrap align-regexp for specific regexp in emacs

I often use align-regexp with the regexp " [^ ]+_" on a region. So I thought I'd define a function for it so I could bind it to a key:

(defun align-members ()
  (interactive)
  (align-regexp " [^ ]+_"))

But emacs complains align-regexp takes three parameters. Looking at the docs, I see it takes BEG and END. I'm not sure how (interactive) stuff works in emacs, but from reading the documentation I gather I should be doing this:

(defun align-members (BEG END)
  (interactive "r")
  (align-regexp BEG END " [^ ]+_"))

But emacs then complains somewhere deep in align-regexp's call stack that it expected integer-or-marker-p and instead got nil. What am I doing wrong?

Upvotes: 5

Views: 664

Answers (4)

Enze Chi
Enze Chi

Reputation: 1763

From my point of view, I can't find any group in your regexp. Lack of test pattern from you, I just give my example.

Try to align code:

bit [4:0] a;
bit [16:0] b;

To:

bit [  4:0] a;
bit [ 16:0] b;

I have a working function like this with group:

(defun try-align ()
  (interactive)
  (let ((BEG (region-beginning))
        (END (region-end)))
    (align-regexp BEG END "\\[\\(.*:\\)" -1 1 0)))

If you remove the group as below, it doesn't work:

(defun try-align ()
  (interactive)
  (let ((BEG (region-beginning))
        (END (region-end)))
    (align-regexp BEG END "\\[.*:" -1 1 0)))

Upvotes: 0

event_jr
event_jr

Reputation: 17707

Oleg's answer is fine.

The reason that align-regexp fills in details for you when called interactively is that you should be able to do the most useful things with as few key-strokes as possible. If you need to assert more control then use the C-u prefix.

This is a common design theme for Emacs commands.

Now when you call align-regexp programatically, there is no need to offer you a short-cut, since presumably the programmer wants full control by default.

In the future, when you convert a task into an interactive defun, use C-x esc esc to see how the command received your input after they went through the interactive forms.

In this case, you should see something like:

(align-regexp 185 320 "\\(\\s-*\\)" [^ ]+_" 1 1 nil)

Upvotes: 3

Oleg Pavliv
Oleg Pavliv

Reputation: 21182

You should write is as the following

(defun align-members (BEG END)
  (interactive "r")
  (align-regexp BEG END (concat "\\(\\s-*\\)" " [^ ]+_") 1 1))

or a bit simpler

(defun align-members (BEG END)
  (interactive "r")
  (align-regexp BEG END "\\(\\s-*\\) [^ ]+_" 1 1))

To understand it, take a look on a align-regexp source, here there is a part of it.

(interactive
 (append
  (list (region-beginning) (region-end))
  (if current-prefix-arg
      (list (read-string "Complex align using regexp: "
                         "\\(\\s-*\\)")
            (string-to-number
             (read-string
              "Parenthesis group to modify (justify if negative): " "1"))
            (string-to-number
             (read-string "Amount of spacing (or column if negative): "
                          (number-to-string align-default-spacing)))
            (y-or-n-p "Repeat throughout line? "))
    (list (concat "\\(\\s-*\\)"
                  (read-string "Align regexp: "))
          1 align-default-spacing nil))))

As you can see:

  • it adds a string "\\(\\s-*\\)" to your regex
  • it sets 1 and align-default-spacing to the optional parameters

Upvotes: 5

N.N.
N.N.

Reputation: 8512

The documentation for align-regexp says

If a prefix arg was specified, the full regexp with parenthesized whitespace should be supplied

so I parenthesized the whitespace in your regexp and that seems to make it work:

(defun align-members (beg end)
  (interactive "r")
  (align-regexp beg end "\\( \\)[^ ]+_"))

Upvotes: 0

Related Questions