views:

216

answers:

3

Edit: After reading the responses, I believe the answer is "don't do this", hence I marked an appropriate response as the official answer.

Is there an easy way to get emacs to display perl switch statements like perldoc.perl.org's switch page?

Here's the formatting on perldoc.perl.org:

use Switch;

switch ($val) {
    case 1          { print "number 1" }
    case "a"        { print "string a" }
    case [1..10,42] { print "number in list" }
    case (\@array)  { print "number in list" }
    case /\w+/      { print "pattern" }
    case qr/\w+/    { print "pattern" }
    case (\%hash)   { print "entry in hash" }
    case (\&sub)    { print "arg to subroutine" }
    else            { print "previous case not true" }
}

Here's the formatting in cperl-mode after M-x indent-region is run on the snippet:

use Switch;

switch ($val) {
  case 1                { print "number 1" }
    case "a"    { print "string a" }
      case [1..10,42]   { print "number in list" }
        case (\@array)  { print "number in list" }
  case /\w+/    { print "pattern" }
        case qr/\w+/    { print "pattern" }
        case (\%hash)   { print "entry in hash" }
        case (\&sub)    { print "arg to subroutine" }
        else            { print "previous case not true" }
    }

I'm having an inexplicable urge to stick with if-elsif constructs...

ps. I think this describes the desired process, but it looks like it'd take a while to parse.

+4  A: 

Sorry I cannot help you with emacs. However, I will recommend that you stick with

if ( condition ) {

}
elsif( other_condition ) {

}
else {

}

rather than use the dreaded Switch.pm. See Nicholas Clark's message to perl5.porters:

Switch will be removed from the Perl core distribution in the next major release.

More discussion on PerlMonks.

As Randal Schwartz points out in a comment below, starting with version 5.10 Perl has a powerful replacement that does not depend on source filters:

use feature "switch";

given($_) {
   when (/^abc/) { $abc = 1; }
   when (/^def/) { $def = 1; }
   when (/^xyz/) { $xyz = 1; }
   default { $nothing = 1; }
}
Sinan Ünür
Switch.pm is being removed because it has been made native as given/when. So your comment about removing Switch is good, but you replace it with given/when, not with Perl4 constructs. :)
Randal Schwartz
@Randal Fair enough. But I have had my share of headaches with `Switch.pm` in earlier versions and if one is not using 5.10, one is better off avoiding it, IMHO.
Sinan Ünür
Thanks for the heads up! I definitely didn't know about given/when or the issues with Switch.pm. This also saves me a lot of potentially bad refactoring time/effort.
vlee
Worth noting that cperl-mode parses given/when constructs much better than the StackOverflow parser ;)
jrockway
A: 

Have you considered using a dispatch table, as Mark Jason Dominus outlines in Higher-Order Perl?

Steven Huwig
No I haven't. Thanks for the information. I can definitely see the use of dispatch tables, but this is somewhat off-topic considering the question.
vlee
A: 

If cperl isn't formatting it correctly, try out perltidy.

Here's a neat function to run perltidy within Emacs on the current region:

;; Slick functions to run perltidy in place
(defun perltidy-region ()
  "Run perltidy on the current region."
  (interactive)
  (save-excursion
    (shell-command-on-region (point) (mark) "perltidy -q" nil t)))
Demosthenex