I am trying to get the perlcritic minor mode (v 1.10) to work with the cperl mode. What happens is that the minor mode is activated for the buffer but is then deactivated. I've used edebug to try to figure out what's going on by instrumenting the perlcritic-mode function inside perlcritic.el. The section of code in that function that toggles the mode is cycled through twice for some reason I haven't been able to figure out. If I invoke the minor mode from the minibuffer (M-x perlcritic-mode) you can actually see Critic (the label for the minor mode) appear on the mode line the first time through that section and then disappear as the code is cycled through again and the minor mode is toggled off.
The method is autoloaded in my .emacs using the code I copied out of perlcritic.el. I don't know if its somehow been loaded twice but during debugging I see two entries under the Emacs-Lisp menu. I have no idea if that's significant or not.
Here are the relevant sections of my .emacs:
(add-to-list 'load-path "~/.emacs.d/elpa/perlcritic-1.10")
(add-to-list 'auto-mode-alist '("\\.pl\\'" . cperl-mode))
(add-to-list 'auto-mode-alist '("\\.pm\\'" . cperl-mode))
(add-to-list 'interpreter-mode-alist '("perl" . cperl-mode))
(autoload 'perlcritic "perlcritic" "" t)
(autoload 'perlcritic-region "perlcritic" "" t)
(autoload 'perlcritic-mode "perlcritic" "" t)
(eval-after-load "cperl-mode"
'(add-hook 'cperl-mode-hook 'perlcritic-mode))
Note that I need to use both the auto-mode-alist and the interpreter-mode-alist to get the cperl mode for existing scripts and modules as well as new scripts and modules. The reason has to do with pre-defined values in those lists that map Perl stuff to perl-mode. I don't know if this is what's causing the problem I'm seeing but I did some testing and it did not seem to be the case.
Here's the function in perlcritic.el that's behaving strangely:
(defun perlcritic-mode (&optional arg)
"Perl::Critic checking minor mode."
(interactive "P")
;; Enable/disable perlcritic-mode
(setq perlcritic-mode (if (null arg)
;; Nothing! Just toggle it.
(not perlcritic-mode)
;; Set it.
(> (prefix-numeric-value arg) 0)))
;; (make-local-hook 'write-file-hooks)
(if perlcritic-mode
(add-hook 'write-file-hooks 'perlcritic-write-hook)
(remove-hook 'write-file-hooks 'perlcritic-write-hook)))
;; Make a nice name for perl critic mode. This string will appear at
;; the bottom of the screen.
(if (not (assq 'perlcritic-mode minor-mode-alist))
(setq minor-mode-alist
(cons '(perlcritic-mode " Critic")
minor-mode-alist)))
The part that it cycles through twice is the section under the comment Enable/disable perlcritic-mode.
Update: I used the d command in edebug each time the debugger hit the line stat begins (setq perlcritic-mode.
Both traces showed the same information:
perlcritic-mode()
run-hooks(change-major-mode-after-body-hook prog-mode-hook cperl-mode-hook cperl-mode-hook)
apply(run-hooks (change-major-mode-after-body-hook prog-mode-hook cperl-mode-hook cperl-mode-hook))
run-mode-hooks(cperl-mode-hook)
cperl-mode()
set-auto-mode-0(cperl-mode nil)
set-auto-mode()
normal-mode(t)
after-find-file(t t)
find-file-noselect-1(#<buffer junk.pl> "~/junk.pl" nil nil "~/junk.pl" nil)
find-file-noselect("~/junk.pl" nil nil t)
find-file("~/junk.pl" t)
funcall-interactively(find-file "~/junk.pl" t)
call-interactively(find-file nil nil)
command-execute(find-file)
I don't know if the fact that cperl-mode-hook appears twice in the lines beginning with run-hooks and apply is significant or what would cause that.