Beginning Perl Programing with Emacs

Opening and Creating Files
Configuration in .emacs
Commands
Editing
Configuration in .emacs2
Commands
Syntax Checking and Running
Configuration in .emacs
Commands
Code Browsing
Configuration in .emacs3
Commands
Finding Documents
Configuration in .emacs
Commands
Interactive shell
Configuration in .emacs
Commands
Debugger
Configuration in .emacs
Commands

Emacs customization is a big topic, here let's talk some topics concern perl programing, and show what features PDE provides.

NOTE: This document is not for PDE, please see pde.info for how to install and use PDE.

Add the configuration following to .emacs as you demand.

Opening and Creating Files

Open and create file in emacs use the same command find-file. When the file to find is not exists, emacs will create the file automaticly ( actually, the file is created when you save it). The default file completion style is like in shell. But it is not so convenient. Emacs privodes a good completion way, ido-mode. When ido-mode turns on, you can open file as following:

Ido 1
Ido 1

When input something, the completion becomes:

Ido 2
Ido 2

Ido completion does not require complete from beginning, and you can complete with regexp. The completion manner is highly customizable.

Ido not only can be used when read file name, you can use it for switching between buffers, or for looking up tags in imenu and so on.

When the file is not found or it is an empty file, you will be prompted whether using template:

New file with template
New file with template

After open the file, you can begin coding.

Configuration in .emacs

(ido-mode 1)
(require 'template-simple)

Commands

Editing

cperl-mode provides a excellent environment for perl programming. With a good style, the indentation is fine. I recommend the setting in PBP.

If you want reindent the code, using M-x indent-region when region is selected. I recommend using pde-indent-dwim, it saves you time to markup region.

Comment or uncomment code using M-x comment-dwim. When region selected, if there are line uncommented, then comment the region, otherwise uncomment the region. If no region selected and have non-whitspace characters in current line, it will add comment at the end of the line. If in empty line or only whitespace in current line, it will add new comment. If there is comment already, jump to the position where comment starts. With C-u prefix, it can delete comment in current line. So with this command, all jobs about comment are done.

Most editor provide feature about code-snippet. In emacs, you can use abbrev. First you should turn on abbrev-mode. cperl-mode provides some useful abbrevs, for example after keywords if, else, elsif, while, for, foreach, unless and until. Also for pod items =head11, =over, =head2, =pod.

Emacs code completion is not as gaudy as other editors, but it provides more ways and high customization for completion. The most useful commands for completion are hippie-expand and dabbrev-expand. They can do almost all kinds of completion. In my experience, I use hippie-expand to complete whole line and dabbrev-expand to complete words. Emacs doesn't provide semantic analysis for perl, so there is no exists way for code intelligent completion. Although hippie-expand provide completion for file name, its priority is too low to reach. So you may need addtional command for file name completion when editing. I recommend use comint-dynamic-complete.

Configuration in .emacs2

;; M-SPC not available, window manager take it away
(global-set-key (kbd "M-'") 'just-one-space)
(global-set-key (kbd "C-M-=") 'pde-indent-dwim)
;; nearest key to dabbrev-expand
(global-set-key (kbd "M-;") 'hippie-expand)
(global-set-key (kbd "C-;") 'comment-dwim)
(global-set-key (kbd "C-c f") 'comint-dynamic-complete)

(setq hippie-expand-try-functions-list
          '(try-expand-line
            try-expand-dabbrev
            try-expand-line-all-buffers
            try-expand-list
            try-expand-list-all-buffers
            try-expand-dabbrev-visible
            try-expand-dabbrev-all-buffers
            try-expand-dabbrev-from-kill
            try-complete-file-name
            try-complete-file-name-partially
            try-complete-lisp-symbol
            try-complete-lisp-symbol-partially
            try-expand-whole-kill))
(autoload 'comint-dynamic-complete "comint" "Complete for file name" t)
(setq comint-completion-addsuffix '("/" . ""))
(setq-default indent-tabs-mode nil)

(defalias 'perl-mode 'cperl-mode)
(defun pde-perl-mode-hook ()
  (abbrev-mode t)
  (add-to-list 'cperl-style-alist
               '("PDE"
                 (cperl-auto-newline                         . t)
                 (cperl-brace-offset                         . 0)
                 (cperl-close-paren-offset                   . -4)
                 (cperl-continued-brace-offset               . 0)
                 (cperl-continued-statement-offset           . 4)
                 (cperl-extra-newline-before-brace           . nil)
                 (cperl-extra-newline-before-brace-multiline . nil)
                 (cperl-indent-level                         . 4)
                 (cperl-indent-parens-as-block               . t)
                 (cperl-label-offset                         . -4)
                 (cperl-merge-trailing-else                  . t)
                 (cperl-tab-always-indent                    . t)))
  (cperl-set-style "PDE"))

Commands

Syntax Checking and Running

cperl-mode doesn't provide command for syntax checking and running. It did put them on menu. Activating them requires mode-compile. But I don't like mode-compile, it makes simple problem complicated. I like smark-compile+. But customizing and extending smart-compile+ is not convenient, so I rewrite the library to compile-dwim. You can use compile-dwim-compile for syntax checking and compile-dwim-run to run the script.

If you have experience of GUI programming, a problem may raise when running several programs at the same time. compile asks you to kill previous process before the new one starts. If you think this is not convenient, you can set compilation-buffer-name-function to pde-compilation-buffer-name.

Emacs provides flymake to do on-the-fly syntax checking. in my humble opinion, it is not very useful. But you can turn it on if you want emacs seems more like IDE.

For perl novice, it is common forgeting chmod before running perl script. The library executable provide a solution for automatic chmod when saving file.

Configuration in .emacs

(global-set-key (kbd "C-c s") 'compile-dwim-compile)
(global-set-key (kbd "C-c r") 'compile-dwim-run)
(setq compilation-buffer-name-function 'pde-compilation-buffer-name)
(autoload 'compile-dwim-run "compile-dwim" "Build and run" t)
(autoload 'compile-dwim-compile "compile-dwim" "Compile or check syntax" t)
(autoload 'executable-chmod "executable"
          "Make sure the file is executable.")

(defun pde-perl-mode-hook ()
   ;; chmod when saving
  (when (and buffer-file-name
        (not (string-match "\\.\\(pm\\|pod\\)$" (buffer-file-name))))
      (add-hook 'after-save-hook 'executable-chmod nil t))
  (set (make-local-variable 'compile-dwim-check-tools) nil))

Commands

Code Browsing

Emacs provides several tools for code browsing. Etags is first choice. cperl-mode supports creating TAGS. M-x cperl-etags can create TAGS for current file. More commands can be found in the menu <Perl> <Tools> <Tags>. There is an additional command <Class Hierarchy from TAGS> (M-x cperl-tags-hier-init). A menu will display when invoke it (show as the figure). But it may complain for error if you set tags-table-list. You can press "++UPDATE++" if you change TAGS files.

Class Hierarchy from TAGS
Class Hierarchy from TAGS

PDE provides a similar tool tags-tree.

TAGS Tree
TAGS Tree

In my opinion, it is more efficient to use find-tag than using such tool.

If you just want jump in current file, imenu is the best choice. Using it with ido-mode will be more convenient:

Ido Imenu
Ido Imenu

PDE provides imenu-tree for view imenu tags in tree view.

Imenu Tree
Imenu Tree

All this is not done with semantic analysis, so if you want browsing standard libraries, you have to create TAGS or open the file directly and navigating using imenu.

There are convenient commands to open file. For perl standard libraries, I recommend using find-file with help of library complete. You can add a prefix char '<' to tell emacs I want complete from include paths not current directory. If you turn on ido-mode, you must use C-x C-f C-f, the last C-f swith ido-mode to normal find-file. This feature is not designed for perl, so the completion is not limit to perl module, but the advantage is it doesn't require cache. If you need a special command for find perl module, you can use perldoc-find-module. A convenient way to open module at point in cperl-mode is using ffap. It is a useful command and worth of assigning a global key.

PC include file complete
PC include file complete

Another topic in code navigation is code folding. One of most useful text fold extension in Emacs is outline. cperl-mode support outline-minor-mode.

Fold subroutines in outline-minor-mode
Fold subroutines in outline-minor-mode

hideshow is another extension for code folding. The feature of hideshow is it base of blocks, so blank lines will be not fold. The shortcoming is it does provide commands to jump between folded blocks. So I prefer outline-minor-mode.

Configuration in .emacs3

(global-set-key (kbd "C-c i") 'imenu)
(global-set-key (kbd "C-c v") 'imenu-tree)
(global-set-key (kbd "C-c j") 'ffap)
(setq tags-table-list '("./TAGS" "../TAGS" "../../TAGS"))
(autoload 'imenu-tree "imenu-tree" "Show imenu tree" t)
(setq imenu-tree-auto-update t)
(eval-after-load "imenu"
 '(defalias 'imenu--completion-buffer 'pde-ido-imenu-completion))
(autoload 'tags-tree "tags-tree" "Show TAGS tree" t)
;; A wonderful minibuffer completion mode
(partial-completion-mode 1)
(setq PC-include-file-path
      (delete-dups (append PC-include-file-path pde-perl-inc)))
(setq ffap-url-regexp
      (concat
       "\\`\\("
       "news\\(post\\)?:\\|mailto:\\|file:" ; no host ok
       "\\|"
       "\\(ftp\\|https?\\|telnet\\|gopher\\|www\\|wais\\)://" ; needs host
       "\\)[^:]" ; fix for perl module, require one more character that not ":"
       ))
(add-to-list 'ffap-alist  '(cperl-mode . pde-ffap-locate))

;; Rebinding keys for hideshow
(require 'hideshow)
(define-key hs-minor-mode-map "\C-c\C-o"
  (let ((map (lookup-key hs-minor-mode-map "\C-c@")))
    ;; C-h is help to remind me key binding
    (define-key map "\C-h" 'describe-prefix-bindings)
    (define-key map "\C-q" 'hs-toggle-hiding)
    ;; compatible with outline
    (define-key map "\C-c" 'hs-hide-block)
    (define-key map "\C-e" 'hs-show-block)
    map))

Commands

Finding Documents

The unix way to view documents is to man. Emacs using woman (WithOut MAN). You can use woman to view pod of module if there is a manpage. The problem is no manpages available in Windows and it is too long to wait woman cache updated. cperl-pod-to-manpage still uses external man program to generate documents, and not so pretty as woman. PDE provide a new command pde-pod-to-manpage, it using pod2man to generate manpage and using woman to formated. With the same idea, PDE provide perldoc to show pod using woman. Although you can invoke perldoc directly, I recommend use it with help-dwim. help-dwim integrates several document commands to one command, you can use it to search elisp function, variable, manpage, perldoc, perlapi and so on. perldoc-tree also provide tree view for modules. You can view module pod or open the module file here.

Perldoc Tree
Perldoc Tree

Emacs provides eldoc to displays information about a function or variable in the text where point is in the echo area. cperl-mode provides another implement for this feature. You can turn the feature using M-x cperl-lazy-install.

Configuration in .emacs

(global-set-key (kbd "C-c h") 'help-dwim)
(setq cperl-lazy-help-time 2)
(defun pde-perl-mode-hook ()
   (cperl-lazy-install))

Commands

Interactive shell

A striking feature of dynamic language is it provides eval function. The eval function make it possible to build a huge project like building blocks. `perl -de 1' is good candicate for interactive shell. But PDE provides another interactive shell for easy customization and extending, and echo result of eval.

Interactive perl shell
Interactive perl shell

You can use inf-perl-send to send current line when editing, or send a region with the same command after finish a block. It is convenient to prove a piece of code without write, save and run. But I recommend write code in file and run it by inf-perl-send.

There is a problem that lexcial variables can't live after eval. inf-perl provides remove my declaration at the beginning of line when send one line to process. Don't consider this is a bug when using it.

PDE also provides a interactive shell for Gtk2-Perl development.

Configuration in .emacs

(autoload 'run-perl "inf-perl" "Start perl interactive shell" t)

Commands

Debugger

gud of emacs supports perldb, but it is simple and crude compare with gdb-ui. PDE provides a similar interface like gdb-ui. But it is known not stable. You may have a try.

Perl Debugger
Perl Debugger

perl5db provides a convenient command line interface, and maybe it more quick to use command than using emacs command. Remember perl5db commands is worth if you want to debug perl script. Except n, s, c, b, B, w, W, L, p, x these most used commands, these are also convenient:

Configuration in .emacs

(autoload 'perldb-ui "perldb-ui" "perl debugger" t)

Commands


1. =head1 can't be expanded when at the end of buffer. Don't know why.

2. pde-perl-mode-hook is also defined in following configuration. You may merge them to one function and add to cperl-mode-hook by add-hook.

3. You can add the definition of functions and variables with prefix pde- to .emacs if you don't want PDE installed. They should not have dependence to other libraries.