tags:

views:

75

answers:

3

In emacs, I format a file as: 1) C-x h (or M-x mark-whole-buffer) 2) C-M-\ (or M-x indent-region)

I need help show me how to format all files under a dir?

+1  A: 

You can try this:

(defun format-all-files (regexp)
  "Format multiple files in one command."
  (interactive "sFind files matching regexp (default all): ")
  (when (string= "" regexp) (setq regexp ""))
  (let ((dir (file-name-directory regexp))
        (nodir (file-name-nondirectory regexp)))
    (when dir (cd dir))
    (when (string= "" nodir) (setq nodir "."))
    (let ((files (directory-files "." t nodir nil t))
          (errors 0))
      (while (not (null files))
        (let ((filename (car files)))
          (if (file-readable-p filename)
              (progn 
                (set-buffer (find-file-noselect filename))
                (mark-whole-buffer)
                (indent-region-or-balanced-expression)
                (save-buffer)
                (kill-buffer (current-buffer)))
            (incf errors))
          (setq files (cdr files))))
      (when (> errors 0)
        (message (format "%d files were unreadable." errors))))))

But note that this must load the file-specific mode over and over again, which may involve syntax highlighting or whatever initialization happens on a load of that type. For really big formatting jobs, a batch program such as indent which only indents will be much faster.

Kilian Foth
I suspect it won't "load the file-specific mode over and over again", and instead will work reasonably fast (not that I've actually tried it :-)
offby1
thanks, but had a error with this:let: Wrong number of arguments: directory-files, 5
lot
+2  A: 

Create a macro to do it. Open the directory in dired (C-x d), and then:

  1. Put point on the first file.
  2. Press F3 to start recording the macro.
  3. Hit RET to open the file.
  4. Format it with C-x h, C-M-\.
  5. Bury the buffer with M-x bury-buffer. You'll be back in the dired buffer.
  6. Go down one line.
  7. Hit F4 to stop recording the macro.

So now you have a macro that opens the file on the current line, formats it, drops back to dired, and puts point to the next line. Run it with F4 as many times as needed.

legoscia
A: 

Here's another way to go about it:

First, evaluate this function definition in your *scratch* buffer:

(defun indent-marked-files ()
  (interactive)
  (dolist (file (dired-get-marked-files))
    (find-file file)
    (indent-region (point-min) (point-max))
    (save-buffer)
    (kill-buffer nil)))

Next, open a Dired buffer at the top level of the directory under which you want to change all of the files. Give the dired command a numeric prefix so that it will ask for the switches to give to the ls command, and add the R (recurse) switch: C-u C-x d R RET your-directory RET.

Next, mark all of the regular files in the recursive directory listing: first * / to mark all the directories, then * t to toggle the selection.

Finally, run the above command: M-x indent-marked-files.

Be aware that if you already have any buffers visiting any of the target files, they'll be killed by indent-marked-files. Also be aware that none of the file changes will be undoable; use with caution! I tested it in a simple case and it seems to work as described, but I make no guarantees.

Sean
I got it, thanks XD
lot