PerlTidyElisp

(defun perltidy-command(start end)
  "The perltidy command we pass markers to."
  (shell-command-on-region start 
                           end 
                           "perltidy" 
                           t
                           t
                           (get-buffer-create "*Perltidy Output*")))

;; Updated as a dwim.  I like using the existing buffer rather than creating a new buffer.
(defun perltidy-dwim (arg)
  "Perltidy a region of the entire buffer"
  (interactive "P")
  (let ((point (point)) (start) (end))
	(if (and mark-active transient-mark-mode)
		(setq start (region-beginning)
			  end (region-end))
	  (setq start (point-min)
			end (point-max)))
	(perltidy-command start end)
	(goto-char point)))

--wjt

I think perltidy-dwim (like comment-dwim) is better. --Anonymous

--

Is this better? With a prefix arg, display the perltidy result in another buffer. Otherwise replace the select region. If marker-active and use transient-mark-mode, call the command on the region, otherwise do with the whole buffer.

But perltidy is too slow, is it the problem of my program?

(defun my-perltidy (arg)
  (interactive "P")
  (let ((buffer (generate-new-buffer "*perltidy*"))
        (point (point))
        start end)
    (if (and mark-active transient-mark-mode)
        (setq start (region-beginning)
              end (region-end))
      (setq start (point-min)
            end (point-max)))
    (shell-command-on-region start end "perltidy" buffer)
    (if arg
        (with-current-buffer buffer
          (perl-mode)
          (display-buffer buffer))
      (delete-region start end)
      (insert-buffer buffer)
      (kill-buffer buffer)
      (goto-char point))))

I’ve noticed that the above two functions don’€™t take special care to provide a PERLTIDY environment variable with the path to the “nearest” .perltidyrc. This is a problem if you are editing “project/lib/foo.pm" but your .perltidyrc is in "project/.perltidyrc”. The following function fixes that, and it also keeps the current window configuration (another problem which I’ve noticed with the above functions):

(defun perltidy-dwim (arg)
  "Perltidy a region of the entire buffer"
  (interactive "P")
  (let ((old-point (point))
	(old-mark (mark t))
	(currconf (current-window-configuration))
	(buffer (generate-new-buffer "*perltidy*"))
	(start)
	(end))
    (if (and mark-active transient-mark-mode)
	(setq start (region-beginning)
	      end (region-end))
      (setq start (point-min)
	    end (point-max)))
    ;; set the PERLTIDY environment variable to the closest instance
    ;; of .perltidyrc, but keep its value if it was set before.
    (let ((old-perltidy-env (getenv "PERLTIDY")))
      (setenv "PERLTIDY" (or old-perltidy-env
			     (expand-file-name
			      (locate-dominating-file (buffer-file-name) ".perltidyrc"))))
      (shell-command-on-region start end "perltidy" buffer)
      (setenv "PERLTIDY" old-perltidy-env))
    (delete-region start end)
    (insert-buffer buffer)
    (kill-buffer buffer)    
    (goto-char (min old-point (point-max)))
    (if old-mark (push-mark (min old-mark (point-max)) t))
    (set-window-configuration currconf)))

(add-hook 'cperl-mode-hook
	  (lambda ()
	    (local-set-key (kbd "C-c t") 'perltidy-dwim)))