1 ;;; tinyperl.el --- Grab-bag of Perl related utilities. Pod documentation
3 ;; This file is not part of Emacs
7 ;; Copyright (C) 1998-2007 Jari Aalto
8 ;; Keywords: extensions
10 ;; Maintainer: Jari Aalto
12 ;; To get information on this program, call M-x tinyperl-version.
13 ;; Look at the code with folding.el
17 ;; This program is free software; you can redistribute it and/or modify it
18 ;; under the terms of the GNU General Public License as published by the Free
19 ;; Software Foundation; either version 2 of the License, or (at your option)
22 ;; This program is distributed in the hope that it will be useful, but
23 ;; WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
24 ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
27 ;; You should have received a copy of the GNU General Public License
28 ;; along with program; see the file COPYING. If not, write to the
29 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
30 ;; Boston, MA 02110-1301, USA.
32 ;; Visit <http://www.gnu.org/copyleft/gpl.html> for more information
39 ;; ....................................................... &t-install ...
40 ;; Put this file on your Emacs-Lisp load path, add following into your
41 ;; ~/.emacs startup file.
43 ;; (require 'tinyperl)
45 ;; Autoload, prefer this one, your emacs starts quicker. The additional
46 ;; features are turned on only when `perl-mode' runs.
48 ;; (autoload 'turn-on-tinyperl-mode "tinyperl" "" t)
49 ;; (add-hook 'perl-mode-hook 'turn-on-tinyperl-mode)
50 ;; (add-hook 'cperl-mode-hook 'turn-on-tinyperl-mode)
52 ;; This package will keep the configuration information in a cache and
53 ;; if for some reason the cache becomes invalid, force rebuilding everything
56 ;; C-u M-x tinyperl-install
58 ;; To completely uninstall package, call:
60 ;; C-u M-x tinyperl-install-main
62 ;; If you have any questions, suggestions, use this function
64 ;; M-x tinyperl-submit-bug-report
70 ;; ..................................................... &t-commentary ...
74 ;; Preface, march 1998
76 ;; Perl was quite new in 1994 and perl programs imported
77 ;; libraries using `require' command. Some time passed and the
78 ;; new Perl 5 was a complete rewrite. It introduced new Object
79 ;; and reference technologies to language but lot of perl coders
80 ;; couldn't grasp the new ideas immediately. Many made the
81 ;; decision to move to perl 5 only after it was mature
82 ;; enough. The perl 5 coding was so much cleaner and simpler
83 ;; compared to perl 4.
85 ;; As a result some additional Emacs functions were needed the Perl
86 ;; work going and this module more or less concentrates on helping to
87 ;; document perl programs with POD or getting perl man pages via
88 ;; `perldoc' interface. The other companion that you would already
89 ;; know is the `cperl-mode' which is the best mode for coding the
92 ;; Overview of features
94 ;; In Windows, both Activestate Perl and native Cygwin Perl are
95 ;; supported. But you cannot use both. If you have accustomed to
96 ;; Activestate Perl, consider moving to Cygwin Perl, because
97 ;; it is more close to the Unix. With cygwin, you can install and upgrade
98 ;; CPAN archives easily: "perl -eCPAN -e shell"
100 ;; *Multiple* *perl* installations are _not_ _supported._ The one that
101 ;; comes in path first is used. Perl advances each time so much that
102 ;; you're much safer if you always have the latest version.
104 ;; `tinyperl-mode' minor mode:
106 ;; o Instant function help: See documentation of `shift', `pop'...
107 ;; o Show Perl manual pages in *pod* buffer
108 ;; o Load library source code into Emacs, like Devel::DProf.pm
109 ;; o Grep through all Perl manual pages (.pod)
110 ;; o Follow POD manpage references to next pod page with TinyUrl
111 ;; o Colored pod pages with `font-lock'
112 ;; o Update `$VERSION' variable with YYYY.MMDD on save.
114 ;; Other minor modes:
116 ;; o Separate `tinyperl-pod-view-mode' for reading pod2text pages
117 ;; o Separate `tinyperl-pod-write-mode' for writing POD documentation
121 ;; At package startup the perl binary's `tinyperl-:perl-bin'
122 ;; `@INC' content is cached. If you have modules somewhere else than
123 ;; the standard `@INC', then add additional `-I' switches to the
124 ;; `tinyperl-:inc-path-switches' so that these additional paths are
127 ;; In addition the Perl POD manual pages and paths are cached at startup.
128 ;; This is derived from *Config.pm* module $Config{privlib}.
130 ;; If you need to change any of the above settings in environment
131 ;; during the session, reload package or call `tinyperl-install' to
132 ;; update the changed values.
134 ;; Saving TinyPerl state (cache)
136 ;; When the package is used for the first time, the Perl `@INC'
137 ;; is read and all .pl and .pm files along the path are cached
138 ;; and written to file pointed by function
139 ;; `tinyperl-cache-file-name'. Next time this package is loaded,
140 ;; the initialization will be faster.
142 ;; If you upgrade Perl or add new packages along @INC, you must
143 ;; rebuild the cached information and have it updated. You do
144 ;; this by calling `tinyperl-install' with a force flag; use
145 ;; some prefix argument (e.g. `C-u').
147 ;; The cache information is expired periodically, so it should keep up
148 ;; with the environment changes quite well. The default cache period
149 ;; is 7 days, but this can be set via
150 ;; `tinyperl-:cache-file-days-old-max'.
152 ;; Perl Minor Mode description
154 ;; Turning on `tinyperl-mode' in any buffer gives you commands to
155 ;; retrieve Perl's POD (Plain Old Documentation) pages. This is
156 ;; most useful with the programming mode `perl-mode'. Function
157 ;; `turn-on-tinyperl-mode' is also added to hooks
158 ;; `perl-mode-hook' and `cperl-mode-hook' by default.
159 ;; The list of key below may be not completely up to date, so
160 ;; consult `C-h' `f' `tinyperl-mode'.
162 ;; C-c ' f tinyperl-pod-find-file
163 ;; C-c ' F tinyperl-pod-find-file-this-buffer
164 ;; C-c ' P tinyperl-pod-by-module
165 ;; C-c ' P tinyperl-pod-by-manpage
166 ;; C-c ' k tinyperl-pod-kill-buffers
168 ;; C-c ' m tinyperl-module-find-file
169 ;; C-c ' d tinyperl-perldoc
170 ;; C-c ' g tinyperl-pod-grep
172 ;; o `tinyperl-pod-find-file'
173 ;; run pod2text over file pointed by the function. After running this
174 ;; The internal POD documentation in the file is presented in man page
175 ;; format. You can use function `tinyperl-pod-find-file-this-buffer'
176 ;; to check the layout of the POD that you're writing to the current
178 ;; o `tinyperl-pod-by-module'
179 ;; View module pages by completing the installed Perl modules
180 ;; and running pod2text. Like reading documentation of "Getopt::Long".
181 ;; o `tinyperl-pod-by-manpage'
182 ;; View Perl manual pages, like "perlfunc.pod" and run pod2text
183 ;; o `tinyperl-pod-kill-buffers'
184 ;; Kill all *pod* buffers from Emacs
185 ;; o `tinyperl-module-find-file'
186 ;; Complete installed module in @INC and load source code into Emacs.
187 ;; Like if you want to see real code of "Getopt::Long"
188 ;; o `tinyperl-perldoc' Use perldoc -f to display documentation of
189 ;; a perl function at point.
190 ;; o `tinyperl-pod-grep'
191 ;; Grep regexp from all Perl POD manual pages. Answers to
192 ;; question "Is this mentioned in FAQ".
194 ;; POD view mode description: navigating in pod page and following URLs
196 ;; When pod is loaded to buffer, another package, *tinyurl.el*, is
197 ;; turned on. It can track several different kind of URLs, including
198 ;; perl pod manpages for references like:
200 ;; See perlfunc manpage
206 ;; Devel::Dprof manpage
207 ;; ^^^^^^^^^^^^^^^^^^^^
209 ;; You can use mouse-2 at the point to jump to the referenced POD
210 ;; page. Wait couple of seconds at the current line and any
211 ;; references or URLs found are marked. If you do not want to use
212 ;; TinyUrl package, add this setup:
214 ;; (add-hook tinyperl-:load-hook 'my-tinyperl-:load-hook)
216 ;; (defun my-tinyperl-:load-hook ()
217 ;; "My TinyPerl customisations."
218 ;; (remove-hook 'tinyperl-:pod2text-after-hook
219 ;; 'turn-on-tinyurl-mode-1))
221 ;; In *pod* buffer where the pod documentation is displayed, an
222 ;; additional browsing mode, `tinyperl-pod-view-mode', is turned on to
223 ;; help moving around topics. If you find the PgUp keys non-customary,
224 ;; see variable `tinyperl-:key-pageup-control'.
226 ;; ;; moving down/up topics
228 ;; Control-PgDown tinyperl-pod-view-heading-forward
229 ;; Control-PgDown tinyperl-pod-view-heading-backward
231 ;; S-PgDown tinyperl-pod-view-heading-forward2
232 ;; S-PgDown tinyperl-pod-view-heading-backward2
234 ;; ;; Moving down/up one pod page at a time
235 ;; ;; The pod pages are all gathered to single buffer *pod*
237 ;; Meta-PgDown tinyperl-pod-view-forward
238 ;; Meta-PgUp tinyperl-pod-view-backward
240 ;; ;; The normal PgUp/Down commands
245 ;; By default the POD documentation is kept in a single buffer where
246 ;; you can conveniently use C-s and C-r searches. If you would like to
247 ;; use separate POD buffers instead, a la M-x man, set variable
248 ;; `tinyperl-:pod-buffer-control' to 'many. The opposite is 'single.
250 ;; POD Write mode description
252 ;; There is additional minor mode to help you write POD in the current
253 ;; buffer The minor mode is in function `tinyperl-pod-write-mode' and
254 ;; you can switch to it any time you're adjusting the pod section.
255 ;; Don't keep on all the time, since it occupies some keys that are
256 ;; normally needed in programming.
258 ;; PgDown tinyperl-pod-write-heading-forward
259 ;; PgUp tinyperl-pod-write-heading-backward
263 ;; PgDown tinyperl-pod-write-token-forward
264 ;; PgUp tinyperl-pod-write-token-backward
266 ;; Inserting default POD templates for program
268 ;; C-c . m tinyperl-pod-write-skeleton-script-manpage
269 ;; C-c . f tinyperl-pod-write-skeleton-script-function
270 ;; C-c . i tinyperl-pod-write-skeleton-item
272 ;; Inserting default POD skeletons for Modules or Classes.
274 ;; C-c . B tinyperl-pod-write-skeleton-module-header
275 ;; C-c . E tinyperl-pod-write-skeleton-module-footer
276 ;; C-c . F tinyperl-pod-write-skeleton-module-function
278 ;; POD skeleton for functions (C-c . F) is very different from the
279 ;; Module skeletons. This due to fact, that a Module offers documented
280 ;; function interface and the user callable functions should be
281 ;; described separately with POD in order to print the manual of the
284 ;; The POD skeletons for Modules are based on following Module
285 ;; layout. This is my only a suggested layout, see
286 ;; Lingue::EN:Squeeze.pm for complete first hand example. The
287 ;; places below where you see "P O D" are the places where you
288 ;; add pod. For each, a different pod skeleton is inserted and
289 ;; when the whole file is printed, it gives nice and maintainable
290 ;; interface description.
292 ;; There is another group of people that prefer writing the whole
293 ;; documentation after the __END__. It has drawback that then you
294 ;; separate the descriptions from the actual place where the code
295 ;; resides. The idea here has been that the documentation (function)
296 ;; is kept immediately above the code: if you change it (function),
297 ;; you can update the documentation at the same place.
299 ;; In the other hand, by putting documentation after __END__, the
300 ;; load time of module is decreased, because POD text is never
301 ;; read by perl interpreter. Another point to keep in mind is,
302 ;; that the computing power and disk speed will increase, so the
303 ;; __END__ solution's benefit is neglible. The maintenance is
304 ;; easier when the documentation is not separated from the place
305 ;; where it would be the most natural (nearest to the code).
307 ;; F I L E B A N N E R
314 ;; EXPORTABLE VARIABLES
317 ;; # module interface is written next
323 ;; .. EXPORT # The export interface
327 ;; Define exported globals
329 ;; Define private variables
331 ;; P O D I N T E R F A C E S T A R T
333 ;; P O D P U B L I C for public functions or method
336 ;; NORMAL banner of private function
349 ;; If you're developing Perl modules, you can make it to use autoload
350 ;; interface. Module compiles much faster and it delays loading of
351 ;; functions until they are called. You can read about SelfStubber
352 ;; from the Module page *Devel::SelfStubber.pm* which links to
353 ;; *SelfLoader.pm*, which is (one file) to my opinion better
354 ;; autoload choice than *Autoloader.pm* (splits file to many files by
357 ;; To use SelfStubber with this package, you need to arrange your
358 ;; module to read like below. Notice the "BEGIN:" and "END:"
359 ;; comment-tokens are for function `tinyperl-selfstubber-stubs',
360 ;; which will fill in the section with the right stubs.
362 ;; If you don't have "BEGIN: Devel::SelfStubber" and "END:
363 ;; Devel::SelfStubber" sections in your file, calling
364 ;; `tinyperl-selfstubber-stubs' prints the found stubs in separate
371 ;; use vars qw( $VERSION @ISA @EXPORT @EXPORT_OK );
373 ;; @ISA = qw(Exporter);
375 ;; @EXPORT = qw( .. );
379 ;; # BEGIN: Devel::SelfStubber
381 ;; # END: Devel::SelfStubber
386 ;; <implementation: functions and variables>
390 ;; Updating the VERSION variable
392 ;; If you plan to submit your perl module or program to the CPAN
393 ;; at http://cpan.perl.org/ the upload criteria is that your file
394 ;; must have a version number. The traditional method has long
395 ;; used some version control software's number (those of CVS or
396 ;; RCS etc.), but it really doesn't tell much to the *user*. It might
397 ;; tell something to the developer, but from user's point of view,
398 ;; he is much more interested in knowing when the file was
399 ;; last updated. The version number 2.77 may be two years old.
401 ;; Where is that variable used? The *MakeMaker* perl module (that
402 ;; you use when making packages ready to CPAN upload) reads the
403 ;; first variable named VERSION and names your release according
406 ;; Consider to use two version numbers: one for the release and
407 ;; one for the kit name. In order to *MakeMaker* to pick up the
408 ;; version number for a kit (tar.gz release, that is, for the
409 ;; user), it must see a VERSION variable. You can store the
410 ;; (a) version control software's number at the beginning of file
411 ;; inside comments and the (b) release number to a perl variable.
413 ;; use vars qw ( $VERSION );
415 ;; # This is for use of Makefile.PL and ExtUtils::MakeMaker
416 ;; # So that it puts the tardist number in format YYYY.MMDD
417 ;; # The REAL version number is defined later
419 ;; # The following variable is updated by Emacs setup whenever
422 ;; $VERSION = '1234.1234';
424 ;; If the VERSION variable uses number format NNNN.NNNN, then it
425 ;; is assumed to contain ISO 8601 date YYYY.MMDD and this package
426 ;; will update the `$VERSION' variable's date every time file is
427 ;; saved (see `write-file-hooks' and `tinyperl-version-stamp').
429 ;; Submitting your perl script to CPAN
431 ;; In addition to archiving your Perl *libraries* to CPAN, you can also
432 ;; submit perl *scripts* there. In order to get your submission right
435 ;; http://www.perl.com/CPAN-local//scripts/submitting.html
437 ;; The most important point is that your script includes pod that
438 ;; describes your script. It must contain at minimum the headings
439 ;; README, SCRIPT CATEGORIES, COREQUISITES, OSNAMES which are already
440 ;; included in the default pod skeleton via command
442 ;; `tinyperl-pod-write-skeleton-script-manpage'
444 ;; Here is code that that can be used in Perl programs to print out
445 ;; the pod documentation when --help option is requested (Use
446 ;; Getop::Long.pm). The code works for both Win32 and Unix Perl
447 ;; implementations. The variable $LIB identifies the "group" where the
448 ;; function belongs, in this case it is program, while it could have
449 ;; been a Perl library module too. You set global $LIB variable at the
450 ;; beginning of file with:
453 ;; use File::Basename;
455 ;; use vars qw( $LIB );
456 ;; $LIB = basename $PROGRAM_NAME;
458 ;; Here is the help function written with POD (perl 5.004 or higher)
460 ;; < Create this Help() function banner with mode key >
461 ;; < C-c . f or `tinyperl-pod-write-skeleton-script-function' >
463 ;; # ***************************************************************
467 ;; # Print help and exit.
469 ;; # INPUT PARAMETERS
471 ;; # $msg [optional] Reason why function was called.-
477 ;; # ***************************************************************
481 ;; < This part: appears after you have called >
482 ;; < C-c . m or `tinyperl-pod-write-skeleton-script-manpage' >
488 ;; my $id = "$LIB.Help";
489 ;; my $msg = shift; # optional arg, why are we here...
491 ;; pod2text $PROGRAM_NAME;
493 ;; print $msg if $msg;
509 (eval-when-compile (ti::package-use-dynamic-compilation))
512 (defvar compilation-error-regexp-alist)
513 ;; Follow pod URLs and other url links like cut(1)
514 ;; Go to grep result.
515 (autoload 'turn-on-tinyurl-mode-1 "tinyurl" "" t)
516 (autoload 'tinyurl-find-url-file "tinyurl" "" t)
517 ;; Why do we autoload this? Because function turn-on-tinyperl-mode
518 ;; is not physically here, but automagically created by a macro call,
519 ;; --> byte compiler needs this hint so that it doesn't flag
520 ;; ** The following functions are not known to be defined:
521 ;; turn-off-tinyperl-mode, turn-on-tinyperl-mode
522 ;; (autoload 'turn-on-tinyperl-mode "tinyperl" "" t)
523 ;; (autoload 'turn-off-tinyperl-mode "tinyperl" "" t)
524 (defvar font-lock-keywords))
526 (ti::package-defgroup-tiny TinyPerl tinyperl-: extensions
527 "Additional function to perl programming.
530 o Instant function help: See documentation of `shift', `pop'...
531 o Show Perl manual pages in *pod* buffer
532 o Load source code into Emacs, like Devel::DProf.pm
533 o Grep through all Perl manpages (.pod)
534 o Follow POD manpage references to next pod page with TinyUrl
535 o Coloured pod pages with `font-lock'
536 o Separate `tinyperl-pod-view-mode' for jumping topics and pages
537 forward and backward in *pod* buffer.")
540 ;;{{{ setup: public variables
542 (defcustom tinyperl-:load-hook '(tinyperl-install)
543 "*Hook run when file has been loaded."
547 (defcustom tinyperl-:pod2text-before-hook nil
548 "Hook run before calling pod2text pod buffer See `tinyperl-pod2text'."
552 (defcustom tinyperl-:pod2text-after-hook nil
553 "Hook run after calling podchecker in that buffer.
554 See `tinyperl-podchecker'."
558 (defcustom tinyperl-:podchecker-before-hook nil
559 "Hook run before calling pod2text pod buffer See `tinyperl-podchecker'."
563 (defcustom tinyperl-:podchecker-after-hook nil
564 "Hook run after calling pod2text in that buffer. See `tinyperl-pod2text'."
568 (defcustom tinyperl-:perldoc-hook nil
569 "Hook run after calling `tinyperl-perldoc'."
576 (defcustom tinyperl-:verbose 1
577 "*If number, bigger than zero, dispaly informational messages.
578 In error situations you can look old messages from *Messages* buffer."
579 :type '(integer :tag "Verbose level 0 ... 10")
582 (defcustom tinyperl-:key-pageup-control 'heading
583 "*How to use PgUp and PgDown keys. 'heading or 'normal."
584 :type '(choice (const heading)
588 (defcustom tinyperl-:pod-buffer-control 'one
589 "*How to display POD documentation. 'single or 'many windows."
590 :type '(choice (const one)
594 (defcustom tinyperl-:skeleton-script-ftp-url nil
595 "*URL where your Perl code is available. Used by skeleton."
599 (defcustom tinyperl-:pause-directory nil
600 "*Directory where to copy your PAUSE uploads.
601 A Perl script must have unique naming before it can be accepted
602 for PAUSE upload. If you do not know what PAUSE (The Perl Authors Upload
603 Server) is, learn more about becoming a Perl developer at
604 http://pause.perl.org/ => about pause.
606 This variable is used by `tinyperl-pause-copy-file' for default
607 location where the pause upload candidates are copied.
609 See also http://cpan.perl.org/authors/id/NEILB/ cpan-upload-1.9.tar.gz."
613 (defcustom tinyperl-:copyright-function 'tinyperl-copyright
614 "*Copyright notice for your Perl programs."
618 ;; This configuration file MUST BE in OS specific name. It is very
619 ;; common that Networked NT workstations access a SAMBA mounted
620 ;; Unix disk and then the HOME directory refer to
623 ;; However if you log into that Unix, You will run Unix Perl
624 ;; If you log into win32 workstation with SAMBA mount, you run win32 Perl.
625 ;; See that problem now and the need for OS specific filename?
627 ;; The cache information for Win32 and Unix must be in different files,
628 ;; if your HOME points to the same location. E.g. the stored perl
629 ;; interpreter name and location is completely different in the cache.
631 (defcustom tinyperl-:cache-file-prefix
632 (ti::package-config-file-prefix "tinyperl")
633 "*Prefix part of the cache filename where @INC content is recorded.
634 See function `tinyperl-save-state' and `tinypath-cache-file-name'."
638 (defcustom tinyperl-:cache-file-postfix ".el"
639 "*Extension for cache file. See `tinypath-:cache-file-prefix'.
640 Normally \".el\" but to save space this could be set to \".el.gz\"."
644 (defcustom tinyperl-:cache-file-days-old-max 7
645 "Maximum days before expiring `tinyperl-:cache-file'.
646 If your Perl environmnt lives a lot, new packages are installed in periodic
647 intervals, then keep this value withing 7 days. If your environment is on the
648 other hand very stable and packages don't change often, then you can set
649 this to very large value, say, 30 days.
651 You can always rebuild the cached Perl information with
652 \\[universal-argument] \\[tinyperl-install]"
656 (defcustom tinyperl-:perl-bin
657 (or (executable-find "perl")
658 (error "TinyPerl: Can't find binary: perl"))
659 "*Perl interpreter used. Must be Perl 5.x."
663 (defcustom tinyperl-:perldoc-bin
664 ;; In Win32, this is perldoc.bat and old `executable-find' command
665 ;; does not search .bat files.
666 (or (or (executable-find "perldoc")
668 (ti::file-get-load-path "perldoc.bat" exec-path))
669 ;; Desperate search: this shuld be equal to exec-path but
670 ;; the environment mey be messed up.
672 (ti::file-get-load-path "perldoc.bat"
673 (split-string (getenv "PATH") ";" )))
674 ;; Emacs executable-find cannot find pure Cygwin "perldoc".
676 (ti::file-get-load-path "perldoc" exec-path))
677 (error "TinyPerl: Can't find binary perldoc or perldoc.bat"))
678 "*Perldoc binary. Absolute path runs faster."
682 (defcustom tinyperl-:pod2text-bin
683 (or (executable-find "pod2text")
684 (ti::file-get-load-path "pod2text" exec-path) ;; Cygwin perl file
685 (error "TinyPerl: Can't find binary: pod2text"))
686 "*Perldoc binary. Absolute path runs faster."
690 (defcustom tinyperl-:inc-path-switches nil
691 "*List of swithes you want to pass to perl to add mode @INC paths.
692 Example : '(\"-I\" \"/path/path\"."
696 (defcustom tinyperl-:pod-font-lock-keywords ;; &fonts
698 ;; ....................................................... pod2text ...
699 ;; Remeber that the order of the regular expressions is significant.
700 ;; First come, first served
702 ;; Like in File::Basename
704 ;; fileparse - split a pathname into pieces
706 ;; basename - extract just the filename from a path
708 ;; dirname - extract just the directory from a path
709 '("^ \\([^ \t\r\n]+\\)[ \t]+-[ \t]+"
710 1 font-lock-reference-face)
712 '("^ [^ \t\r\n]+[ \t]+-[ \t]+\\(.*\\)"
713 1 font-lock-constant-face) ;; font-lock-string-face
714 ;; Headings and Sub headings
715 ;; Method description in Class
717 ;; $ua->from([$email_address])
720 '("^ ? ? ? ?\\([\"$%@A-Za-z_]+\\)[ \t]*$"
721 1 font-lock-type-face)
722 ;; TWO WORDS after 4 spaces, level 2 heading
724 ;; Packaging commands
728 '("^ \\([A-Za-z_.]+[ -]*[A-Za-z-]*\\)[ \t]*$"
729 1 font-lock-type-face)
732 '("^ \\([A-Za-z][A-Za-z_.-]+[ -]*[A-Za-z_.-]*\\)[ \t]*$"
733 1 font-lock-type-face)
734 '("^\\([A-Z][a-z]+[ \t]+[A-Za-z]+.*\\)$"
735 1 font-lock-type-face)
737 ;; =head2 Topic Name Here
739 ;; perlre.pod 5.8.0: " Version 8 Regular Expressions"
740 ;; perdoelta.pod 5.8.0 " Self-tying Problems"
742 '("^ \\([A-Za-z]+-?[A-Za-z]+[ \t]+[A-Za-z0-9].+[A-Za-z]\\)[ \t]*$"
743 1 font-lock-type-face t)
744 ;; perldelta.pod 5.8.0: " 64-bit platforms and malloc"
745 '("^ \\([0-9]+-[A-Za-z]+[ \t]+[A-Za-z0-9].+[A-Za-z]\\)[ \t]*$"
746 1 font-lock-type-face)
747 ;; perlre.pod 5.8.0: " Warning on \1 vs $1"
748 '("^ \\([A-Z][a-z]+[ \t]+[A-Za-z]+[ \t]+.*\\)[ \t]*$"
749 1 font-lock-type-face)
750 ;; perldelta.pod 5.8.0: "IEEE-format Floating Point Default"
751 '("^ \\([A-Z]+-?[a-z]+[ \t]+[A-Za-z]+[ \t]+.*\\)[ \t]*$"
752 1 font-lock-type-face)
753 ;; " Preliminary setup:"
754 '("^ \\([A-Z][a-z]+.*:[ \t]*\\)$"
755 1 font-lock-type-face)
756 '("\\(perl[^ ]+\\)[ \t\n\r]+man\\(ual \\)?page"
757 1 font-lock-type-face)
761 ;; "Regexp Quote-Like Operators" in perlop.
762 '("^[ \t]+\\(perl[^ ]+\\)\\.[ \t]*$"
763 1 font-lock-type-face)
764 '("in[ \t]+\\(perl[^ ]+\\)\\.[ \t]*$"
765 1 font-lock-type-face)
770 "\\| -[-a-zA-Z0-9]\\>" ;; option names
771 "\\|\\(http\\|ftp\\|news\\|wais\\)://[^ \t\r\n]+"
772 "\\|<?[^ \t\n\r]+@[^ \t\r\n]+>?" ;; <foo@bar.com>
773 "\\|`[^\"'`\n\r]+'" ;; `this'
774 "\\|\\<[^( \t\n\r]+([$@%;*]*)" ;; function($)
775 ;; File::Find Filter::Util::Call
776 ;; PerlIO::via::QuotedPrint
777 "\\|\\<[A-Z][a-zA-Z]+\\(::[A-Za-z]+\\)+\\>"
778 "\\|[^ \t\r\n]+[\\/][^ \t\r\n]+") ;; CPAN/modules/by-module
779 0 'font-lock-reference-face)
784 "\\|\\<[-a-zA-Z0-9]+([0-9]+[A-Z]?)") ;; chmod(1)
785 0 'font-lock-constant-face)
790 ;; 'this' European style
794 ;; Notice that BLOCK ... LOGIN-NAME
795 "\\|\\<[%$@]*[A-Z_][-A-Z_]+\\>" ;; @VAR_HERE, BIG_LETTERS
796 ;; it's *funny* that ...
797 "\\|\\*[^ \r\n*]+\\*")
798 0 'font-lock-keyword-face)
799 ;;; ;; like chdir() function ...
800 ;;; '("[a-z][^ \t\n\r(]+()" 0 font-lock-reference-face)
804 "^ \\( \\)*" ;; 8 x indentation allowed
820 0 'font-lock-builtin-face t)
821 ;; ...................................................... pod-write ...
822 '("^=\\(head[0-9]\\|pod\\|begin\\|end\\|cut\\|item\\)"
823 0 font-lock-function-name-face t)
824 '("^=\\(head[0-9]\\|pod\\|begin\\|end\\|cut\\|item\\)[ \t]+\\(.*\\)"
825 2 font-lock-reference-face t)
826 '("^=item[ \t]+\\(.*\\)"
827 1 font-lock-keyword-face t)
829 0 font-lock-type-face))
830 "*Font lock keywords."
837 (defvar tinyperl-:inc-path nil
838 "The content of @INC.
839 The path names are not in pure rwa @INC format, but they
840 have been processed to meet host Emacs's understanding of underlying
841 operating systems paths.
843 E.g Win32/Cygwin/perl returns paths in native Unix format which must
844 be translated to Emacs that is running. For GNU Emacs, this means
845 paths in DOS style.")
847 (defvar tinyperl-:inc-module-list nil
848 "The content .pm files under @INC.")
850 (defvar tinyperl-:pod-path nil
851 "Path to perl distribution POD files.")
853 (defvar tinyperl-:pod-list nil
854 "List of pod files. '((file.pod . path) (file.pod . path) ..).")
856 (defvar tinyperl-:pod-buffer-name "*pod*"
857 "Buffer where to print POD.")
859 (defvar tinyperl-:faq-buffer-name "*pod FAQ-grep*"
860 "Buffer where to put context exerpts after grep search.
861 See `tinyperl-pod-grep-faq-answer'")
863 (defvar tinyperl-:perldoc-buffer "*perldoc*"
864 "Buffer where to output perldoc.")
866 (defvar tinyperl-:podchecker-buffer "*podchecker*"
867 "Buffer where to output Pod::Checker::podchecker().")
872 ;;;###autoload (autoload 'tinyperl-version "tinyperl" "Display commentary." t)
875 (ti::macrof-version-bug-report
879 "$Id: tinyperl.el,v 2.85 2007/08/03 20:16:25 jaalto Exp $"
882 tinyperl-:pod2text-before-hook
883 tinyperl-:pod2text-after-hook
884 tinyperl-:podchecker-before-hook
885 tinyperl-:podchecker-after-hook
886 tinyperl-:perldoc-hook
887 tinyperl-:key-pageup-control
888 tinyperl-:pod-buffer-control
889 tinyperl-:skeleton-script-ftp-url
890 tinyperl-:pause-directory
891 tinyperl-:copyright-function
892 tinyperl-:cache-file-prefix
893 tinyperl-:cache-file-postfix
895 tinyperl-:perldoc-bin
896 tinyperl-:pod2text-bin
897 tinyperl-:inc-path-switches
898 tinyperl-:pod-font-lock-keywords
900 tinyperl-:inc-module-list
903 tinyperl-:pod-buffer-name
904 tinyperl-:perldoc-buffer
905 tinyperl-:podchecker-buffer)))
907 ;;;### (autoload 'tinyperl-debug-toggle "tinyperl" t t)
909 (eval-and-compile (ti::macrof-debug-standard "tinyperl" "-:"))
914 ;;; ----------------------------------------------------------------------
916 (put 'tinyperl-verbose-macro 'lisp-indent-function 1)
917 (defmacro tinyperl-verbose-macro (level &rest body)
918 "When LEVEL is =< `tinyperl-:verbose' run BODY."
920 (when (and (numberp tinyperl-:verbose)
921 (or (= (, level) tinyperl-:verbose)
922 (< (, level) tinyperl-:verbose)))
925 ;;; ----------------------------------------------------------------------
927 (put 'tinyperl-directory-files 'lisp-indent-function 3)
928 (defmacro tinyperl-directory-files (variable path &optional regexp)
929 "Store to VARIABLE .pl and .pm files in PATH. Optionally match REGEXP."
930 (` (setq (, variable)
934 (or (, regexp) "\\.pl\\|\\.pm")))))
936 ;;; ----------------------------------------------------------------------
938 (put 'tinyperl-executable-set 'lisp-indent-function 3)
939 (defmacro tinyperl-executable-set (sym bin &optional regexp)
940 "Set variable SYM to executable BIN name searching REGEXP.
941 This is shorthand of saying, that locate the BIN in the `exec-path'
942 when it matches REGEXP and set variable SYM to that value, effectively:
944 (setq tinyperl-:perldoc-bin
945 (tinyperl-executable-find-path
946 \"perldoc\" tinyperl-:perldoc-bin \"perldoc\"))
948 --> (tinyperl-executable-set 'tinyperl-:perldoc-bin \"perldoc\")"
951 (tinyperl-executable-find-path
953 (symbol-value (, sym))
957 ;;; ----------------------------------------------------------------------
959 (defun tinyperl-perl-module-exists-p (module)
960 "Return path if MODULE(.pm) is known to ´tinyperl-:inc-module-list'."
961 (unless (string-match "\\.pm$" module)
962 (setq module (concat module ".pm")))
963 (let* ((elt (assoc module tinyperl-:inc-module-list))
964 (file (if (string-match ".*::\\(.*\\)" module)
965 (match-string 1 module)
968 (concat (file-name-as-directory (cdr elt))
971 ;;; ----------------------------------------------------------------------
973 (defun tinyperl-grep-program ()
974 "Return value of `grep-program' if available."
975 ;; Hide variable `grep-program' from byte compiler
976 ;; We do not need (require 'grep) only to get this variable
978 (let ((sym 'grep-program))
984 ;;{{{ code: install, mode
986 ;;; ----------------------------------------------------------------------
988 (defun tinyperl-variable-convert (&optional dos-format)
989 "Convert all path variables to Unix or DOS-FORMAT."
990 (flet ((convert (var)
992 (ti::file-name-backward-slashes var)
993 (ti::file-name-forward-slashes var))))
994 (setq tinyperl-:pod2text-bin (convert tinyperl-:pod2text-bin))
995 (setq tinyperl-:perldoc-bin (convert tinyperl-:perldoc-bin))
996 (setq tinyperl-:perl-bin (convert tinyperl-:perl-bin))
997 (setq tinyperl-:pod-path (convert tinyperl-:pod-path))))
999 ;;; --------------------------------------------------------------------
1001 (defun tinyperl-executable-find-path (program old-value regexp)
1002 "Find path for PROGRAM with OLD-VALUE matching REGEXP."
1003 (if (and (ti::file-name-path-p (or old-value ""))
1004 (file-exists-p old-value)
1005 (not (file-directory-p old-value)))
1008 (if (and tinyperl-:perl-bin
1009 ;; This could return "perl5.005"
1010 (string-match regexp old-value))
1011 (match-string 0 old-value)
1014 (or (executable-find program)
1015 ;; Only way to find Cygwin "perldoc".
1016 (ti::file-get-load-path program exec-path))))
1018 ;;; ----------------------------------------------------------------------
1020 (defun tinyperl-perl-examine (perl)
1021 "Check type of PERL. Return 'win32-activestate 'win32-cygwin 'perl.
1022 Perl is called with -v. Following properties are stored in
1024 variable `tinyperl-:perl-bin' are set to properties:
1026 'version-answer => The -v result string
1027 'type => 'win32-activestate
1030 (let* ((info (ti::process-perl-version perl)))
1031 (put 'tinyperl-:perl-bin 'version-answer (nth 3 info))
1032 (put 'tinyperl-:perl-bin 'type (nth 1 info))))
1034 ;;; ----------------------------------------------------------------------
1036 (defsubst tinyperl-perl-type ()
1037 "Return Perl type. Provided `tinyperl-perl-examine' has been called."
1038 (or (get 'tinyperl-:perl-bin 'type)
1039 (progn (tinyperl-perl-examine tinyperl-:perl-bin)
1040 (get 'tinyperl-:perl-bin 'type))))
1042 ;;; ----------------------------------------------------------------------
1044 (defsubst tinyperl-perl-type-version-info ()
1045 "Return Perl -v info. Provided `tinyperl-perl-examine' has been called."
1046 (or (get 'tinyperl-:perl-bin 'version-answer)
1047 (progn (tinyperl-perl-examine tinyperl-:perl-bin)
1048 (get 'tinyperl-:perl-bin 'version-answer))))
1050 ;;; ----------------------------------------------------------------------
1052 (defun tinyperl-install-variables-binaries (&optional force)
1053 "Install or FORCE setting binary variables like `tinyperl-:perl-bin'
1055 t If some path needed fixing. This means that cache must be resaved."
1059 (sym bin &optional regexp) ;; Parameters
1060 (let* ((value (symbol-value sym)))
1062 ;; Value is set, possibly read from the cache,
1063 ;; but that binary does not exist any more.
1064 ;; Perhaps user has relocated Rerl. Deternine
1065 ;; new changed location.
1066 (and (stringp value)
1067 (not (file-exists-p value)))
1068 ;; Value has not been set yet
1069 (not (stringp value)))
1071 (or (tinyperl-executable-set sym bin regexp)
1072 (error "TinyPerl: No binary `%s` for variable `%s' \
1073 Check variable `exec-path'"
1075 (symbol-name sym)))))))
1076 ;; `perl5' `perl5.004' ...
1077 ;; If the name does not contain number, use "perl".
1078 (exec-set 'tinyperl-:perl-bin
1079 "perl" "perl[-.0-9]*\\.exe\\|perl[^\\/]*")
1080 (exec-set 'tinyperl-:perldoc-bin "perldoc")
1081 (exec-set 'tinyperl-:pod2text-bin "pod2text")
1082 (tinyperl-perl-examine tinyperl-:perl-bin)
1083 ;; Leave trace to Message buffer.
1084 (tinyperl-verbose-macro 2
1085 (message "TinyPerl: [Perl version] => %s"
1086 (or (tinyperl-perl-type-version-info) "")))
1089 ;;; ----------------------------------------------------------------------
1091 (defun tinyperl-install-variables-lookup (&optional check verb)
1092 "Set all global lookup variables.
1096 CHECK Check variable: Preserve previous content and set only
1097 those that do not have value.
1098 if value is 'force, reset variable in all cases.
1100 VERB Allow verbose messages
1104 `tinyperl-:inc-path'
1105 `tinyperl-:inc-module-list'
1106 `tinyperl-:pod-path'
1107 `tinyperl-:pod-list'"
1109 (flet ((set-maybe (symbol eval-form)
1110 (when (or (eq 'force check)
1112 (symbol-value symbol)))
1113 (tinyperl-verbose-macro 1
1114 (message "TinyPerl: Setting up var: %s" symbol))
1116 (eval eval-form)))))
1118 (tinyperl-verbose-macro 1
1119 (message "TinyPerl: Setting up variables...")))
1122 '(tinyperl-inc-path tinyperl-:perl-bin))
1123 (error "TinyPerl: Setup failure tinyperl-:inc-path,\
1124 tinyperl-:perl-bin Unrecognized. Need Perl 5. [%s]"
1125 tinyperl-:perl-bin))
1127 'tinyperl-:inc-module-list
1128 '(tinyperl-build-list-of-inc-files
1131 (error "TinyPerl: Setup failure tinyperl-:inc-module-list"))
1134 '(tinyperl-pod-path tinyperl-:perl-bin))
1135 (error "TinyPerl: Setup failure tinyperl-:pod-path"))
1138 '(tinyperl-build-pod-files))
1139 (error "TinyPerl: Setup failure tinyperl-:pod-list"))
1141 (tinyperl-verbose-macro 1
1142 (message "TinyPerl: Setting up variables...Done.")))))
1144 ;;; ----------------------------------------------------------------------
1146 (defun tinyperl-install-variables-lookup-maybe (&optional force verb)
1147 "Set up global variables. FORCE or only if they don't have values."
1148 (tinyperl-install-variables-lookup (if force 'force 'check) verb))
1150 ;;; ----------------------------------------------------------------------
1152 (defun tinyperl-install-1 (&optional force verb)
1154 You should call `tinyperl-install' or `tinyperl-install-force' instead.
1158 FORCE If non-nil, rebuild all variables and
1159 save new `(tinyperl-cache-file-name)'.
1160 If nil, read saved variables from `(tinyperl-cache-file-name)'.
1162 VERB Allow verbose messaegs."
1165 ;; The FORCE Flag says that we should start all over, no
1166 ;; matter how broken our setup is. In case the unfortunate
1167 ;; accident of tinyperl-:perl-bin being in format
1168 ;; e:USRLOCALBINPERLBINperl.exe we can recover the state here
1169 ;; and start over (that Win32 backslash problem: \usr\local ...).
1171 ;; If the perl exectable is not correct in the first place
1172 ;; we can't continue.
1173 (setq stat (tinyperl-load-state-if-recent-enough)
1174 ok (tinyperl-install-variables-binaries force))
1177 (tinyperl-install-variables-lookup 'force)
1178 (tinyperl-install-variables-lookup-maybe))
1179 ;; We must use forward slashes, because if we save the cache file,
1180 ;; It would look like:
1182 ;; (defconst tinyperl-:perl-bin
1183 ;; "e:\USR\LOCAL\BIN\PERL\BIN\perl.exe")
1185 ;; --> e:USRLOCALBINPERLBINperl.exe when read from
1187 (tinyperl-variable-convert)
1190 (tinyperl-save-state nil verb)
1192 (tinyperl-verbose-macro 1
1193 (message "TinyPerl: Setting up variables...done"))))
1196 (tinyperl-perl-module-exists-p "Pod::Checker.pm"))
1200 ;;; ----------------------------------------------------------------------
1203 (defun tinyperl-install (&optional uninstall force)
1204 "The main installer. Set up everything: hooks and variables.
1205 This function is best put into `tinyperl-:load-hook'.
1209 UNINSTALL Uninstall, remove hooks etc.
1210 FORCE Forced install. In case modules have installed from CPAN,
1211 this variable should be set to force rescan of @INC instead
1214 (tinyperl-install-hooks uninstall)
1216 (tinyperl-install-1 force 'verb))
1217 (turn-on-tinyperl-mode-all-buffers uninstall)
1218 (ti::add-hooks '(perl-mode-hook
1220 'turn-on-tinyperl-mode
1223 ;;; ----------------------------------------------------------------------
1226 (defun tinyperl-install-force ()
1227 "Rebuild all global variables. Needed after CPAN module install."
1229 (tinyperl-install nil 'force))
1231 ;;; ----------------------------------------------------------------------
1234 (defun tinyperl-uninstall ()
1235 "Uninstall TinyPerl."
1237 (tinyperl-install 'uninstall))
1239 ;;; ----------------------------------------------------------------------
1241 (defun tinyperl-cache-file-name ()
1242 "Return Perl version specific cache file.
1244 Don't touch this code unless you know what you're doing.
1246 We need Emacs specific cache files, because the @INC path
1247 names returned by Activestate Perl and Cygwin Perl are different
1248 under different Emacs flavors: XEmacs can be built under Cygwin and win32
1249 but Emacs understands only DOS paths. .. the matrix is:
1251 Win32 Cygwin Perl @INC is unix style => convert to dos for Emacs
1252 Win32 Activestate Perl @INC is DOS style => use as is in Emacs
1254 XEmacs .. eh, well, that hasn't been tackled yet. The @INC matrix
1257 ygwin perl + Cygwin XEmacs plays well together
1258 ygwin perl + Win32 XEmacs doesn't
1259 ctivestate + Cygwin XEmacs doesn't
1260 ctivestate + Win32 XEmacs does.
1264 `tinyperl-:cache-file-prefix'.
1265 `tinyperl-:cache-file-postfix'"
1266 (concat (if (stringp tinyperl-:cache-file-prefix)
1267 (concat tinyperl-:cache-file-prefix "-")
1269 ;; (if (ti::win32-p) "win32-" "unix-")
1274 (let ((sym (tinyperl-perl-type)))
1277 (error "TinyPerl: Perl type is not known.")))
1278 (if (stringp tinyperl-:cache-file-postfix)
1279 tinyperl-:cache-file-postfix
1282 ;;; ----------------------------------------------------------------------
1284 (defun tinyperl-load-state-if-recent-enough ()
1285 "Load `(tinyperl-cache-file-name)'.
1286 But only if less than `tinyperl-:cache-file-days-old-max'"
1288 (let ((file (tinyperl-cache-file-name)))
1289 (if (and (file-exists-p file)
1290 (< (ti::file-days-old file)
1291 tinyperl-:cache-file-days-old-max))
1292 (tinyperl-save-state 'load 'message))))
1294 ;;; ----------------------------------------------------------------------
1296 (defun tinyperl-save-state (&optional load &optional verb)
1297 "Save or LOAD variables to `(tinyperl-cache-file-name).'
1298 When LOAD: If `(tinyperl-cache-file-name)' does not exist. return nil."
1301 (let ((file (tinyperl-cache-file-name)))
1304 (when (file-exists-p file)
1307 (tinyperl-verbose-macro 1
1308 (message "TinyPerl: state restored [%s]" file)))
1311 (ti::write-file-variable-state
1313 "TinyPerl.el saved state"
1314 '(tinyperl-:inc-path
1315 tinyperl-:inc-module-list
1319 tinyperl-:perldoc-bin
1320 tinyperl-:pod2text-bin))
1322 (tinyperl-verbose-macro 1
1323 (message "TinyPerl: state saved [%s]" file)))
1326 ;;; ----------------------------------------------------------------------
1329 (defun turn-on-tinyperl-mode-all-buffers (&optional off)
1330 "Turn function `tinyperl-mode' on in every perl buffer. Optionally turn OFF."
1332 (ti::dolist-buffer-list
1334 (string-match "perl" (downcase (symbol-name major-mode)))
1335 (string-match "\\.pl$" (buffer-name))
1336 (string-match "code-perl" (or (ti::id-info) "")))
1339 (let ((mode (symbol-value 'tinyperl-mode)))
1340 ;; We use `symbol-value' because byte compiler does not see the
1341 ;; 'tinyperl-mode' yet. It's defined by the minor mode wizard macro
1344 (ti::funcall 'turn-off-tinyperl-mode))
1346 (ti::funcall 'turn-on-tinyperl-mode))))))
1348 ;;; ----------------------------------------------------------------------
1350 (defun tinyperl-install-hooks (&optional remove verb)
1351 "Install default hooks or REMOVE. VERB."
1354 (ti::add-hooks 'tinyperl-:perldoc-hook
1355 '(tinyperl-pod-font-lock
1356 turn-on-tinyurl-mode-1
1357 ti::buffer-strip-control-m)
1359 (ti::add-hooks '(tinyperl-:pod2text-after-hook
1360 tinyperl-:podchecker-after-hook)
1361 '(turn-on-tinyurl-mode-1
1362 turn-on-tinyperl-pod-view-mode
1363 ti::buffer-strip-control-m)
1365 (ti::add-hooks 'tinyperl-:pod-view-mode-hook
1366 'tinyperl-pod-font-lock
1368 (ti::add-hooks 'tinyperl-:pod-write-mode-hook
1369 'tinyperl-pod-font-lock
1371 (ti::add-hooks '(perl-mode-hook
1373 'turn-on-tinyperl-mode
1375 (ti::add-hooks 'tinyperl-:mode-define-keys-hook
1376 'tinyperl-mode-define-keys remove)
1377 (ti::add-hooks 'tinyperl-:pod-view-mode-define-keys-hook
1378 'tinyperl-pod-view-mode-define-keys
1380 (ti::add-hooks 'tinyperl-:pod-write-mode-define-keys-hook
1381 'tinyperl-pod-write-mode-define-keys
1383 (ti::add-hooks 'write-file-hooks
1384 'tinyperl-version-stamp
1387 (tinyperl-verbose-macro 2
1388 (message "TinyPerl: Hooks installed"))))
1390 ;;; ----------------------------------------------------------------------
1392 (defun tinyperl-copyright ()
1393 "Insert copyright string fro Perl program."
1395 (insert "Copyright (C) " (format-time-string "%Y " (current-time))
1396 (or (user-full-name)
1397 (read-string "You name: "))
1399 This program is free software; you can redistribute and/or modify program
1400 under the same terms as Perl itself or in terms of Gnu General Public
1401 license v2 or later."))
1403 ;;;###autoload (autoload 'tinyperl-mode "tinyperl" "" t)
1404 ;;;###autoload (autoload 'turn-on-tinyperl-mode "tinyperl" "" t)
1405 ;;;###autoload (autoload 'turn-off-tinyperl-mode "tinyperl" "" t)
1406 ;;;###autoload (autoload 'tinyperl-commentary "tinyperl" "" t)
1410 (ti::macrof-minor-mode-wizard
1411 "tinyperl-" " pod" "\C-c'" "Tperl" 'TinyPerl "tinyperl-:" ;1-6
1413 "Additional commands to fetch perl module and perl manpage information
1415 For complete on-line documentation, which is generated from the
1416 source file itself, run command `tinyperl-version`
1418 This minor mode is by default turned on when `[c]perl-mode' is turned on
1419 but, you can access the Perl POD page view commands directly too even if
1420 the minor mode is not active, Here is suggestion for global bindings that
1421 you can put to your $HOME/.emacs startup file:
1423 ;; Take global prefix key C-c p for perl pod view commands
1425 (global-set-key \"\C-cpp\" 'tinyperl-pod-by-manpage)
1426 (global-set-key \"\C-cpP\" 'tinyperl-pod-by-module)
1428 You can also run `perl2text' filter on any perl file with command
1429 M-x `tinyperl-find-file' See also `tinyperl-pod-view-mode'
1431 The function `tinyperl-pod-write-mode' will turn on additional minor
1432 mode that might help you to write the POD dicumentation inside you
1433 perl code. this minor mode is intended to to use only at-demand
1434 basis, so that, when you concentrate on writing the POD page, you
1435 turn it on, when you have finished and continue writing perl code,
1436 you should in general turn it off.
1440 \\{tinyperl-:mode-map}"
1449 tinyperl-:mode-easymenu-name
1453 ["Skeleton script function" tinyperl-pod-write-skeleton-script-function t]
1454 ["Skeleton script manpage" tinyperl-pod-write-skeleton-script-manpage t]
1455 ["Skeleton module function" tinyperl-pod-write-skeleton-module-function t]
1456 ["Skeleton module header" tinyperl-pod-write-skeleton-module-header t]
1457 ["Skeleton module footer" tinyperl-pod-write-skeleton-module-footer t])
1458 ["Perldoc - function help" tinyperl-perldoc t]
1460 ["Pod by module" tinyperl-pod-by-module t]
1461 ["Pod by manpage" tinyperl-pod-by-manpage t]
1462 ["Pod grep" tinyperl-pod-grep t]
1463 ["Pod kill buffers" tinyperl-pod-kill-buffers t]
1465 tinyperl-pod-podchecker
1466 (get 'tinyperl-mode 'podchecker)]
1468 ;; ["Pod switch to buffer" tinyperl-pod-jump t]
1469 ["Pod write mode" tinyperl-pod-write-mode t]
1471 ["Pod2text on file" tinyperl-pod-find-file t]
1472 ["Pod2text on current buffer" tinyperl-pod-find-file-this-buffer t]
1474 ["Module source find-file" tinyperl-module-find-file t]
1475 ["Module generate stubs" tinyperl-selfstubber-stubs t]
1477 ["PAUSE copy file" tinyperl-pause-copy-file t]
1478 ["PAUSE submit page" tinyperl-pause-url-submit-www-page t]
1479 ;; ["Pause upload via FTP"] tinyperl-pause-upload-via-ftp t]
1481 ["Package version" tinyperl-version t]
1482 ["Package commentary" tinyperl-commentary t]
1483 ["Mode help" tinyperl-mode-help t]
1484 ["Mode off" tinyperl-mode t])
1487 (define-key map "?" 'tinyperl-mode-help)
1488 (define-key map "Hm" 'tinyperl-mode-help)
1489 (define-key map "Hc" 'tinyperl-commentary)
1490 (define-key map "Hv" 'tinyperl-version)
1491 (define-key map "P" 'tinyperl-pod-by-manpage)
1492 (define-key map "p" 'tinyperl-pod-by-module)
1493 (define-key map "f" 'tinyperl-pod-find-file)
1494 (define-key map "F" 'tinyperl-pod-find-file-this-buffer)
1495 (define-key map "g" 'tinyperl-pod-grep)
1496 (define-key map "G" 'tinyperl-pod-grep-faq-answer)
1497 (define-key map "k" 'tinyperl-pod-kill-buffers)
1498 ;;; (define-key map "b" 'tinyperl-pod-jump)
1499 (define-key map "!" 'tinyperl-pod-podchecker)
1500 (define-key map "d" 'tinyperl-perldoc)
1501 (define-key map "m" 'tinyperl-module-find-file)
1502 (define-key map "?" 'tinyperl-mode-help)
1503 (define-key map "M" 'tinyperl-mode)
1504 (define-key map "S" 'tinyperl-selfstubber-stubs)
1505 ;; C = CPAN interface, other keys like P (PAUSE) are already reserved.
1506 (define-key map "Cc" 'tinyperl-pause-copy-file)
1507 (define-key map "Cs" 'tinyperl-pause-url-submit-www-page)
1508 ;; (define-key map "Cf" 'tinyperl-pause-upload-via-ftp)
1509 (define-key map "W" 'tinyperl-pod-write-mode)
1510 ;; Borrow some commonly used keys from the "pod-write" mode
1511 (define-key map "'f" 'tinyperl-pod-write-skeleton-script-function)
1512 (define-key map "'m" 'tinyperl-pod-write-skeleton-script-manpage)
1513 ;; B = Begin , E = End
1514 (define-key map "'F" 'tinyperl-pod-write-skeleton-module-function)
1515 (define-key map "'B" 'tinyperl-pod-write-skeleton-module-header)
1516 (define-key map "'E" 'tinyperl-pod-write-skeleton-module-footer))))
1518 ;;;###autoload (autoload 'tinyperl-pod-view-mode "tinyperl" "" t)
1519 ;;;###autoload (autoload 'turn-on-tinyperl-pod-view-mode "tinyperl" "" t)
1520 ;;;###autoload (autoload 'turn-off-tinyperl-pod-view-mode "tinyperl" "" t)
1524 (ti::macrof-minor-mode-wizard
1525 "tinyperl-pod-view-" " POD" "\C-c'" "POD" 'TinyPerl "tinyperl-:pod-view-"
1527 "View `pod2text' formatted output.
1528 If you have manual pages in the current buffer, this mode makes
1529 navigating the headings and topics easier.
1531 This mode redefined the Page Up and Page down key to jump between
1532 headings. Hold also shift or meta or control key down for other
1537 \\{tinyperl-:pod-view-mode-map}"
1546 tinyperl-:pod-view-mode-easymenu-name
1547 ["Heading forward" tinyperl-pod-view-heading-forward t]
1548 ["Heading backward" tinyperl-pod-view-heading-backward t]
1549 ["Sub Heading forward" tinyperl-pod-view-heading-forward2 t]
1550 ["Sub Heading backward" tinyperl-pod-view-heading-backward2 t]
1551 ["Section forward" tinyperl-pod-view-backward t]
1552 ["Section backward" tinyperl-pod-view-backward t]
1553 ["Scroll up" scroll-up t]
1554 ["Scroll down" scroll-down t]
1556 ["Pod by manpage" tinyperl-pod-by-manpage t]
1557 ["Pod by module" tinyperl-pod-by-module t]
1558 ["Pod grep" tinyperl-pod-grep t]
1559 ;;; (define-key map "f" 'tinyperl-pod-find-file)
1560 ;;; (define-key map "F" 'tinyperl-pod-find-file-this-buffer)
1561 ;;; (define-key map "G" 'tinyperl-pod-grep-faq-answer)
1562 ;;; (define-key map "k" 'tinyperl-pod-kill-buffers)
1564 ["Exit and kill buffer" kill-buffer-and-window t]
1565 ["Mode help" tinyperl-pod-view-mode-help t]
1566 ["Mode off" tinyperl-pod-view-mode t])
1569 (define-key map "P" 'tinyperl-pod-by-manpage)
1570 (define-key map "p" 'tinyperl-pod-by-module)
1571 (define-key map "f" 'tinyperl-pod-find-file)
1572 (define-key map "F" 'tinyperl-pod-find-file-this-buffer)
1573 (define-key map "g" 'tinyperl-pod-grep)
1574 (define-key map "G" 'tinyperl-pod-grep-faq-answer)
1575 (define-key map "k" 'tinyperl-pod-kill-buffers)
1576 ;;; (define-key map "b" 'tinyperl-pod-jump)
1577 (define-key map "q" 'kill-buffer-and-window)
1578 (define-key root-map [(control prior)] 'tinyperl-pod-view-pageup)
1579 (define-key root-map [(control next)] 'tinyperl-pod-view-pagedown)
1581 (define-key root-map [(shift prior)] 'tinyperl-pod-view-heading-backward2)
1582 (define-key root-map [(shift next)] 'tinyperl-pod-view-heading-forward2)
1583 ;; Bigger steps with these
1584 (define-key root-map [(meta prior)] 'tinyperl-pod-view-backward)
1585 (define-key root-map [(meta next)] 'tinyperl-pod-view-forward))))
1587 ;;; ----------------------------------------------------------------------
1589 (defun tinyperl-pod-view-backward ()
1590 "Go to one topic backward."
1593 ;; Net::FTP - FTP Client class
1594 (or (re-search-backward "^NAME[\n\r]" nil t) (ti::pmin)))
1596 ;;; ----------------------------------------------------------------------
1598 (defun tinyperl-pod-view-pageup ()
1599 "See `tinyperl-:key-pageup-control'."
1601 (if (eq tinyperl-:key-pageup-control 'heading)
1602 (tinyperl-pod-view-heading-backward)
1605 ;;; ----------------------------------------------------------------------
1607 (defun tinyperl-pod-view-pagedown ()
1608 "See `tinyperl-:key-pageup-control'."
1610 (if (eq tinyperl-:key-pageup-control 'heading)
1611 (tinyperl-pod-view-heading-forward)
1614 ;;; ----------------------------------------------------------------------
1616 (defun tinyperl-pod-view-forward ()
1617 "Go to one topic backward."
1620 (or (and (re-search-forward "^NAME[\n\r]" nil t)
1624 ;;; ----------------------------------------------------------------------
1626 (defun tinyperl-pod-view-heading-backward (&optional regexp)
1627 "Go to one heading backward. Optionally use REGEXP."
1629 (let* (case-fold-search)
1630 (or (and (re-search-backward (or regexp "^\\( \\)?[A-Z]") nil t)
1633 (skip-chars-forward " \t")))
1636 ;;; ----------------------------------------------------------------------
1638 (defun tinyperl-pod-view-heading-forward (&optional regexp)
1639 "Go to one heading forward. Optionally use REGEXP."
1642 (let* (case-fold-search)
1643 (or (and (re-search-forward (or regexp "^\\( \\)?[A-Z]") nil t)
1646 (skip-chars-forward " \t")))
1649 ;;; ----------------------------------------------------------------------
1651 (defun tinyperl-pod-view-heading-backward2 ()
1652 "Go to one sub heading backward."
1654 (tinyperl-pod-view-heading-backward
1655 "\\([ \t][\r\n]\\|[\r\n][\r\n]\\)\\( \\| \\)?[^ \t\n\r]"))
1657 ;;; ----------------------------------------------------------------------
1659 (defun tinyperl-pod-view-heading-forward2 ()
1660 "Go to one sub heading backward."
1662 (tinyperl-pod-view-heading-forward
1663 "\\([ \t][\r\n]\\|[\r\n][\r\n]\\)\\( \\| \\)?[^ \t\n\r]"))
1666 ;;{{{ POD write mode
1668 ;;;###autoload (autoload 'tinyperl-pod-write-mode "tinyperl" "" t)
1669 ;;;###autoload (autoload 'turn-on-tinyperl-pod-write-mode "tinyperl" "" t)
1670 ;;;###autoload (autoload 'turn-off-tinyperl-pod-write-mode "tinyperl" "" t)
1674 (ti::macrof-minor-mode-wizard
1675 "tinyperl-pod-write-" " PODw" "\C-c." "PODw" 'TinyPerl "tinyperl-:pod-write-"
1677 "Minor mode to thelp writing POD in place.
1681 \\{tinyperl-:pod-write-mode-map}"
1683 "TinyPerl Pod Write"
1690 tinyperl-:pod-write-mode-easymenu-name
1691 ["Heading forward" tinyperl-pod-write-heading-forward t]
1692 ["Heading backward" tinyperl-pod-write-heading-backward t]
1693 ["Token forward" tinyperl-pod-write-token-forward t]
1694 ["Token backward" tinyperl-pod-write-token-backward t]
1695 ["Scroll up" scroll-up t]
1696 ["Scroll down" scroll-down t]
1698 ["Skeleton script manpage" tinyperl-pod-write-skeleton-script-manpage t]
1699 ["Skeleton script function" tinyperl-pod-write-skeleton-script-function t]
1700 ["Skeleton module header" tinyperl-pod-write-skeleton-module-header t]
1701 ["Skeleton module function" tinyperl-pod-write-skeleton-module-function t]
1702 ["Skeleton module header" tinyperl-pod-write-skeleton-module-footer t]
1703 ["Skeleton item" tinyperl-pod-write-skeleton-item t]
1705 ["Mode help" tinyperl-pod-write-mode-help t]
1706 ["Mode off" tinyperl-pod-write-mode t])
1709 (define-key map [(prior)] 'tinyperl-pod-write-heading-backward)
1710 (define-key map [(next)] 'tinyperl-pod-write-heading-forward)
1712 (define-key map [(shift prior)] 'tinyperl-pod-write-token-backward)
1713 (define-key map [(shift next)] 'tinyperl-pod-write-token-forward)
1714 ;; Bigger steps with these
1715 ;; (define-key map [(meta prior)] 'tinyperl-pod-write-backward)
1716 ;; (define-key map [(meta next)] 'tinyperl-pod-write-forward)
1717 ;; And original PgUp PgDown is saved under Control key
1718 (define-key root-map [(control prior)] 'scroll-down)
1719 (define-key root-map [(control next)] 'scroll-up)
1720 ;; S K E L E T O N -- p for pod
1721 (define-key map "m" 'tinyperl-pod-write-skeleton-script-manpage)
1722 (define-key map "f" 'tinyperl-pod-write-skeleton-script-function)
1723 (define-key map "i" 'tinyperl-pod-write-skeleton-item)
1724 (define-key map "B" 'tinyperl-pod-write-skeleton-module-header)
1725 (define-key map "E" 'tinyperl-pod-write-skeleton-module-footer)
1726 (define-key map "F" 'tinyperl-pod-write-skeleton-module-function))))
1728 ;;; ----------------------------------------------------------------------
1730 (defun tinyperl-pod-write-heading-backward ()
1731 "Go to previous POD heading"
1733 (tinyperl-pod-view-heading-backward "^=head"))
1735 ;;; ----------------------------------------------------------------------
1737 (defun tinyperl-pod-write-heading-forward ()
1738 "Go to next POD heading"
1740 (tinyperl-pod-view-heading-forward "^=head"))
1742 ;;; ----------------------------------------------------------------------
1744 (defun tinyperl-pod-write-token-backward ()
1745 "Go to previous POD token"
1747 (tinyperl-pod-view-heading-backward "^="))
1749 ;;; ----------------------------------------------------------------------
1751 (defun tinyperl-pod-write-token-forward ()
1752 "Go to next POD token "
1754 (tinyperl-pod-view-heading-forward "^="))
1756 ;; Tell that these function are here
1758 ;;;###autoload (autoload 'tinyperl-pod-write-skeleton-item "tinyperl" "" t)
1759 ;;;###autoload (autoload 'tinyperl-pod-write-skeleton-script-manpage "tinyperl" "" t)
1760 ;;;###autoload (autoload 'tinyperl-pod-write-skeleton-script-function "tinyperl" "" t)
1761 ;;;###autoload (autoload 'tinyperl-pod-write-skeleton-module-header "tinyperl" "" t)
1762 ;;;###autoload (autoload 'tinyperl-pod-write-skeleton-module-footer "tinyperl" "" t)
1763 ;;;###autoload (autoload 'tinyperl-pod-write-skeleton-module-function "tinyperl" "" t)
1765 (defun tinyperl-skeleton-setup ()
1766 "Define skeleton functions."
1767 ;; It is unnecessary to load skeleton.el at package load time.
1768 ;; We define here STUBS, i.e forward declaration functions, which
1769 ;; will call the initialize setup, where the real function are
1772 ;; At that point skeleton.el is needed and loaded.
1773 ;; These STUBS will at the end call the real, defined, function.
1778 (let ((sym (intern (format "tinyperl-pod-write-skeleton-%s"
1781 (` (defun (, sym) ()
1782 "Forward declaration wrapper. Will define real function."
1784 (tinyperl-skeleton-initialize)
1785 (funcall (quote (, sym))))))
1792 module-function ))))
1794 (defun tinyperl-skeleton-initialize () ;; #### SKELETON-BEGIN
1797 ;;; ----------------------------------------------------------------------
1799 (define-skeleton tinyperl-pod-write-skeleton-item
1800 "Insert =item skeleton"
1801 (read-string "Item: " "*")
1807 ;;; ----------------------------------------------------------------------
1809 (define-skeleton tinyperl-pod-write-skeleton-script-manpage
1810 "Script: Insert Perl Script's manpage POD."
1811 (read-string "Program: " (buffer-name))
1816 " str " - " (read-string "One Line description: ")
1822 <short overall description here. This section is ripped by CPAN>
1826 <program call conventions>
1832 =head2 Gneneral options
1836 =item B<--option-name>
1840 =head2 Miscellaneous options
1844 =item B<--debug LEVEL>
1846 Turn on debug with positive LEVEL number. Zero means no debug.
1854 Run in test mode, do not actually do anything.
1858 Print informational messages.
1862 Print contact and version information
1868 <program description>
1872 <example calls for the program in different situations>
1874 =head1 TROUBLESHOOTING
1876 <what to check in case of error or weird behavior>
1880 <any environment variable settings>
1884 <what files program generates uses>
1888 <references to other programs e.g. ps(1)>
1892 <RFCs, ANSI/ISO, www.w3c.org that are related>
1902 (or tinyperl-:skeleton-script-ftp-url
1903 (skeleton-read "Availabillity: " "<URL Where to get the program>"))
1907 =head1 SCRIPT CATEGORIES
1911 =head1 PREREQUISITES
1913 <what CPAN modules are needed to run this program>
1917 <what CPAN modules are needed to run this program>
1931 (funcall tinyperl-:copyright-function)
1938 ;;; ----------------------------------------------------------------------
1940 (define-skeleton tinyperl-pod-write-skeleton-script-function
1941 "Script: Insert Function banner."
1944 # ****************************************************************************
1958 # ****************************************************************************
1961 ;;; ----------------------------------------------------------------------
1963 (define-skeleton tinyperl-pod-write-skeleton-module-header
1964 "Module: Insert POD header; which starts the pod in module.
1965 See function description `tinyperl-pod-write-skeleton-module-function'."
1968 # ****************************************************************************
1972 # ****************************************************************************
1976 " (buffer-name) " - One line Module descriptions
1984 use " (replace-regexp-in-string "\\.pm" "" (buffer-name))
1985 "; # Import EXPORT_OK
1987 (replace-regexp-in-string "\\.pm" "" (buffer-name))
1988 " qw( :ALL ); # Import everything
1992 =head1 EXPORTABLE VARIABLES
1994 If there is no special marking for the variable, it is
1995 exported when you call `use'. The rags next to variables mean:
1997 [ok] = variable is exported via list EXPORT_OK
1998 [tag] = variable is exported via :TAG
2004 =head2 %ABC_HASH [ok]
2010 Integer. If positive, activate debug with LEVEL.
2014 =head1 INTERFACE FUNCTIONS
2016 =for comment After this the Puclic interface functions are introduced
2017 =for comment you close the blockquote by inserting POD footer
2026 ;;; ----------------------------------------------------------------------
2028 (define-skeleton tinyperl-pod-write-skeleton-module-footer
2029 "Module: Insert POD footer, which starts the pod in module.
2030 See function description `tinyperl-pod-write-skeleton-module-function'."
2033 # ****************************************************************************
2037 # ****************************************************************************
2046 <Limitations. How to debug problems>
2050 <release or where to get latest, http, ftp page>
2056 (funcall tinyperl-:copyright-function)
2063 ;;; ----------------------------------------------------------------------
2065 (define-skeleton tinyperl-pod-write-skeleton-module-function
2066 "Module: Insert template for Puclic interface function.
2067 Where you write Module.pm public interface functions, document the
2070 Hee is one suggestion ofr Module.pm POD layout
2077 EXPORTABLE VARIABLES
2080 # module interface is written next
2086 EXPORT # The export interface
2090 Define exported globals
2092 Define private variables
2094 P O D I N T E R F A C E S T A R T
2096 P O D P U B L I C for public functions or methods
2099 P O D P U B L I C for public functions or methods
2102 NORMAL banner of private function
2105 NORMAL banner of private function
2137 ) ;; #### SKELETON-BEGIN
2140 ;;{{{ Perl Path functions
2142 ;;; ----------------------------------------------------------------------
2143 ;;; (tinyperl-inc-split-win32-path "C:\\Program files\\this c:\\temp")
2145 (defun tinyperl-inc-split-win32-path (string)
2146 "Separate different absolute directories.
2147 \(tinyperl-inc-split-win32-path \"C:\\Program files\\this c:\\temp\")
2149 '(\"C:\\Program files\\this\" \"c:\\temp\")"
2158 (while (re-search-forward "\\<[a-z]:[\\//]" nil t)
2159 (push (match-beginning 0) locations))
2160 (push (ti::pmax) locations)
2161 (setq locations (nreverse locations))
2162 (while (setq beg (pop locations))
2163 (when (setq end (car locations))
2164 (setq str (ti::string-remove-whitespace (buffer-substring beg end)))
2165 (unless (ti::nil-p str)
2169 ;;; ----------------------------------------------------------------------
2171 (defun tinyperl-inc-split (inc)
2172 "Split @INC in INC string, where entries are separated by spaces."
2173 (let* ((fid "tinyperl-inc-split")
2174 (perl-type (tinyperl-perl-type))
2175 ;; We can't just explode RESULT with Emacs function `split'
2176 ;; because in Win32 it may contain spaces
2177 ;; c:\Program files\activestate\perl\lib
2182 (ti::emacs-type-win32-p)
2183 (eq perl-type 'win32-activestate))
2184 (setq list (tinyperl-inc-split-win32-path
2185 ;; Delete current directory from the list
2186 (replace-regexp-in-string " \\." "" inc))))
2188 (eq perl-type 'win32-cygwin)
2189 (ti::emacs-type-win32-p))
2190 (setq list (split-string inc))
2191 ;; Native Win32 Emacs cannot use Cygwin Perl's UNIX paths.
2192 ;; Convert cygwin -> Win32
2197 ((string-match "^//\\|^[a-z]:" path)
2198 (push path win32-list))
2200 (push path cygwin-list))))
2202 (setq cygwin-list (mapcar 'w32-cygwin-path-to-dos cygwin-list)))
2203 (setq list (append cygwin-list win32-list))))
2205 (eq perl-type 'win32-activestate)
2206 (ti::emacs-type-cygwin-p))
2208 "TinyPerl: [ERROR] Active Perl is first in you PATH [%s]"
2209 "Arrange your PATH to find Cygwin perl first "
2210 "under Cygwin Emacs/XEmacs.")
2211 (if (not (string-match "[\\/]" tinyperl-:perl-bin))
2212 ;; Contains path, show it as-is
2213 (executable-find tinyperl-:perl-bin)
2214 tinyperl-:perl-bin)))
2216 (setq list (split-string inc))))
2217 (setq list (delete "." list))
2218 (tinyperl-debug fid "perl" perl-type "ret" list)
2221 ;;; ----------------------------------------------------------------------
2223 (defun tinypath-path-convert-to-emacs-host (list)
2224 "Convert list of paths to the format that Emacs host knows.
2225 If Emacs is win32 application, convert to DOS style paths."
2227 ;; Now interesting part: If Emacs in Win32-native and user uses
2228 ;; Cygwin-perl, then the situation is as follows:
2230 ;; PERL5LIB paths refer to cygwin, like /usr/share/site-perl/CPAN
2232 ;; But this is not a path that GNU Emacs know, because it is pure
2233 ;; Windows application. The paths must be converted so that
2235 ;; CYGWIN-ROOT/path or CYGWIN-MOUNT-POINT/path
2237 ;; #todo: XEmacs is different game, it can be built as Cygwin native
2238 ;; #todo: How to check if running Cygwin or Win32 XEmacs ?
2240 (let* ((perl-type (tinyperl-perl-type)))
2243 ;; #todo: if Emacs is built as native cygwin application,
2245 (eq perl-type 'win32-cygwin))
2249 ((and (string-match "^/" path)
2250 ;; Exclude Win32 UNC path formats: //SERVER/dir/dir
2251 (not (string-match "^//" path)))
2252 (push (w32-cygwin-path-to-dos path) new-list))
2254 ;; the file-directory-p is checked elswhere.
2255 ;; Just return pure paths
2256 (push path new-list))))
2261 ;;; ----------------------------------------------------------------------
2263 (defun tinyperl-inc-path-external-perl (perl)
2264 "Calls an external PERL process to read @INC.
2268 `tinyperl-:inc-path-switches' is included in call."
2270 (apply 'call-process
2275 (append tinyperl-:inc-path-switches
2278 "print(qq,@INC,)")))
2279 (let ((ret (buffer-string)))
2280 (tinyperl-debug "tinyperl-inc-path-external-perl: " ret)
2283 ;;; ----------------------------------------------------------------------
2284 ;;; (tinyperl-inc-path tinyperl-:perl-bin)
2286 (defun tinyperl-inc-path (&optional perl)
2287 "Return @INC and and var PERL5LIB libs for PERL which defaults to `perl'.
2290 `tinyperl-:inc-path-switches'"
2291 (let* ((fid "tinyperl-inc-path")
2293 (executable-find "perl")))
2294 ;; ask from perl where the paths are.
2296 (tinyperl-inc-path-external-perl path)))
2297 ;; We can't just explode RESULT with Emacs function `split'
2298 ;; because in Win32 it may contain spaces
2299 ;; c:\Program files\activestate\perl\lib
2301 (tinyperl-inc-split result)))
2302 ;; The LIST test is there so that if you call this with
2303 ;; perl 4, then the LIST is nil and we should not check PERL5LIB,
2304 ;; which is perl 5 only variable.
2305 (lib (or (getenv "PERL5LIB")
2306 (getenv "PERL5_LIB"))) ;; Win32 Activestate Perl
2311 (if (or (string-match ";" lib) ;; was (if (ti::win32-p)..
2312 (string-match "[a-z]:[\\/]" lib))
2317 (tinyperl-debug fid "path" path "result" result "lib" lib "path5" path5)
2319 (string-match "warning\\|error\\|fatal" result))
2320 (error "TinyPerl: Reading @INC error %s" result))
2322 (setq list (append list path5)))
2323 (setq list (delete "." list))
2324 (tinyperl-debug fid "list [2]" list)
2325 ;; Make sure Emacs can read the Paths -- Win32 specific support
2326 (setq list (tinypath-path-convert-to-emacs-host list))
2329 (unless (member x seen) ;; Filter out duplicates
2331 (if (file-directory-p x)
2333 ;; Record to message, so that possible errors can be
2335 (tinyperl-verbose-macro 3
2336 (message "Tinyperl: invalid @INC dir %s. Ignored." x))))))
2337 (tinyperl-debug fid "result [2]" result)
2342 (concat "TinyPerl: Can't parse @INC. Please check"
2343 " tinyperl-:perl-bin = %s"
2346 (prin1-to-string tinyperl-:perl-bin)
2347 (prin1-to-string result)
2348 (prin1-to-string path5))))
2349 (tinyperl-debug fid "ret" ret)
2352 ;;; ----------------------------------------------------------------------
2354 (defun tinyperl-pod-path (&optional perl-binary)
2355 "Return POD path by calling PERL-BINARY or `perl'."
2356 (let* ((fid "tinyperl-pod-path")
2357 (perl (or perl-binary (executable-find "perl")))
2366 "print $Config{privlib}")
2368 (when (or (ti::nil-p path)
2370 ;; ... Can't locate Config.pm
2371 ;; ... BEGIN failed--compilation aborted.
2372 (string-match "Failed\\|error\\|Can't" path)))
2373 (error "TinyPerl: POD failure [%s] from Config.pm using %s"
2375 ;; Win32 specific Cygwin support
2377 (tinypath-path-convert-to-emacs-host (list path))))
2378 (setq path (car path-list)))
2379 (unless (file-directory-p path)
2380 (error "TinyPerl: Can't find pod path %s [%s]" perl path))
2381 (tinyperl-debug fid "perl-binary" perl-binary "path" path)
2382 ;; Find out the Perl library path. The POD files are
2383 ;; under subdir "pod" in Unix and Activestate Perl,
2384 ;; but for some reason Cygwin Perl 5.6.1 changed the
2385 ;; files under /pods.
2388 (dolist (pod '("pod/" "pods/"))
2389 (setq try (concat (file-name-as-directory path) pod))
2390 (when (and (file-directory-p try)
2395 (return (setq correct try))))
2397 (error "TinyPerl: Can't determine POD path %s [%s]" path perl))
2398 (tinyperl-debug fid "correct" correct)
2399 (ti::file-name-forward-slashes correct))))
2401 ;;; ----------------------------------------------------------------------
2403 (defun tinyperl-build-pod-files ()
2404 "Build files under pod path."
2405 (let* ((path (or tinyperl-:pod-path
2406 (error "TinyPerl: No tinyperl-:pod-path")))
2409 (setq files (ti::directory-files path "\\.pod"))
2410 (dolist (file files)
2411 (push (cons file (ti::file-name-forward-slashes path)) ret))
2414 ;;; ----------------------------------------------------------------------
2415 ;;; #todo: This should be rewritten as recursive function
2417 (defun tinyperl-build-list-of-inc-files (&optional search-list verb)
2418 "Build list of files under @INC. Only 3 subdir levels are scanned.
2419 SEARCH-LIST corresponds to `tinyperl-:inc-path'
2423 '((package.pm . path) (package::package.pm . path) ..)"
2424 (let* ((INC (or search-list
2425 (error "TinyPerl: No SEARCH-LIST")))
2434 ;; As long as the name of the .pl file is unique (not yet
2435 ;; added), store without leading prefix directories.
2437 (if (and (string-match "\\.pl" file)
2438 (not (assoc file ret)))
2439 (push (cons file path) ret)
2442 (concat (file-name-nondirectory pfx) "::" file)
2447 ;; It is unusual that Perl INC path would belonger than
2448 ;; 3 subdirectories, so we just check 3 levels. This is not very
2449 ;; general approach to deal with the situation...
2451 ;; Font::Metrics::Courier.pm
2452 ;; HTTP::Request::Common.pm
2455 (tinyperl-verbose-macro 2
2456 (message "TinyPerl: Reading @INC path %s" path)))
2457 (tinyperl-directory-files files path)
2458 (dolist (file files)
2459 (push (cons file path) ret))
2460 (setq dirs (ti::directory-files ;; And Level 1 directories
2462 '(file-directory-p arg)
2463 '(string-match "\\.\\.?$" arg)))
2465 (tinyperl-directory-files files dir)
2466 (dolist (file files)
2467 (setq package (file-name-nondirectory dir))
2468 (my-add file package dir))
2469 (setq dirs2 (ti::directory-files ;; And Level 2 directories too
2471 '(file-directory-p arg)
2472 '(string-match "\\.\\.?$" arg)))
2473 (dolist (dir1 dirs2)
2474 (setq dir1 (ti::file-name-forward-slashes dir1))
2475 (tinyperl-directory-files files dir1)
2476 (dolist (file files)
2477 (setq package (concat (file-name-nondirectory dir) "::"
2478 (file-name-nondirectory dir1)))
2479 (my-add file package dir1))
2480 (setq dirs3 (ti::directory-files ;; And Level 2 directories too
2482 '(file-directory-p arg)
2483 '(string-match "\\.\\.?$" arg)))
2484 (dolist (dir2 dirs3)
2485 (setq dir2 (ti::file-name-forward-slashes dir2))
2486 (tinyperl-directory-files files dir2)
2487 (dolist (file files)
2488 (setq package (concat (file-name-nondirectory dir) "::"
2489 (file-name-nondirectory dir1) "::"
2490 (file-name-nondirectory dir2)))
2491 (my-add file package dir2))))))
2495 ;;{{{ POD lowlevel functions
2497 ;;; ----------------------------------------------------------------------
2499 (defun tinyperl-podchecker (file &optional buffer)
2500 "Run Pod::Checker/podchecker() on FILE and put output to BUFFER.
2501 Default value for BUFFER is `tinyperl-:perldoc-buffer'."
2502 (let* ((fid "tinyperl-podchecker"))
2503 (or (tinyperl-perl-module-exists-p "Pod::Checker.pm")
2505 TinyPerl: Pod::Checker.pm is not known to this Perl version. @INC trouble?"))
2507 (setq buffer (get-buffer-create tinyperl-:podchecker-buffer)))
2508 (or (get-buffer buffer)
2509 (setq buffer (get-buffer-create buffer)))
2510 (when nil ;; disabled
2511 (with-current-buffer buffer
2513 (run-hooks 'tinyperl-:podchecker-before-hook)
2514 (call-process tinyperl-:perl-bin
2520 "podchecker shift, undef, -warnings => q(on)"
2521 (expand-file-name file))
2522 (run-hooks 'tinyperl-:podchecker-after-hook)))
2524 (let* (compilation-error-regexp-alist
2525 ;; `shell-quote-argument' does not work here correctly.
2526 ;; This tackles bash.exe and Win32 command-com
2527 (quote (if (and (ti::win32-p)
2528 (string-match "cmd\\|command"
2538 "podchecker shift, undef, -warnings , q(on)"
2541 (expand-file-name file))))
2542 ;; Keep the old values and add this regexp.
2543 ;; 2 = filename, 1 = line number
2544 ;; *** WARNING: 2 unescaped <> in paragraph at line 1994 in file xxx
2546 '(".*[ \t]+line[ \t]+\\([0-9]+\\)[ \t]+in[ \t]+file[ \t]+\\(.*\\)"
2548 compilation-error-regexp-alist)
2549 (tinyperl-debug fid "cmd" cmd)
2550 (compile-internal cmd
2551 "No more lines." ;; error-message
2554 nil))) ;; error-regexp-alist
2555 (tinyperl-debug fid "buffer" buffer)
2558 ;;; ----------------------------------------------------------------------
2559 ;;; (tinyperl-pod2text (tinyperl-pod-manpage-to-file "perlfunc.pod"))
2561 (defun tinyperl-pod2text (file &optional buffer)
2562 "Run pod on FILE and put output to BUFFER."
2563 (let ((fid "tinyperl-pod2text"))
2565 (setq buffer (tinyperl-pod-buffer-name
2566 (file-name-nondirectory file))))
2567 (or (get-buffer buffer)
2568 (setq buffer (get-buffer-create buffer)))
2569 ;; Append text to the end of buffer.
2570 (with-current-buffer buffer
2571 (setq buffer-read-only nil)
2572 (run-hooks 'tinyperl-:pod2text-before-hook)
2574 ;; Move point to the end of visible window
2575 ;; #todo: was I thinking of something here ?...
2577 (let* ((win (get-buffer-window (current-buffer) t)))
2579 (set-window-point win (point-max)))))
2580 (let ((point (point))
2581 (file (expand-file-name file))
2582 ;; Native Win32 Emacs + Cygwin
2583 (nt-cygwin (and (ti::emacs-type-win32-p)
2584 (ti::win32-cygwin-p))))
2585 (tinyperl-debug fid "file" file)
2586 ;; perl -MPod::Text -e "pod2text shift" -n groff /cygdrive/p/unix/cygwin/lib/perl5/5.8.0/pods/perlfunc.pod
2587 (call-process tinyperl-:perl-bin
2594 ;; Cygwin's groff(1) was changed to bash
2595 ;; shell script which cannot be used
2603 (when (eq (point) point)
2605 (concat "TinyPerl: pod2text was empty. "
2606 "Please check Perl environment."
2607 "It may be broken: try running `perldoc perl'."))))
2609 (tinyperl-debug fid "tinyperl-:pod2text-after-hook" tinyperl-:pod2text-after-hook)
2610 (run-hooks 'tinyperl-:pod2text-after-hook)
2611 (setq buffer-read-only t)
2614 ;;; ----------------------------------------------------------------------
2616 (defun tinyperl-pod-manpage-to-file (pod)
2617 "Convert POD `perldoc.pod' or `perldoc' into absolute filename."
2618 (let* ((elt (assoc (ti::string-verify-ends pod ".pod")
2619 (or tinyperl-:pod-list
2620 (error "TinyPerl: No tinyperl-:pod-list")))))
2622 (concat (cdr elt) (car elt)))))
2624 ;;; ----------------------------------------------------------------------
2626 (defun tinyperl-read-word-module ()
2627 "Read word at point suitable for Perl module. Add .pm."
2628 (let ((word (ti::buffer-read-word "a-zA-Z:"))
2630 (when (and (stringp word)
2635 "^[A-Z]\\([a-z]+\\|[A-Z]+\\)$"
2636 ;; use Getopt::Long;
2637 ;; use HTTP::Request;
2639 "\\|^[A-Z]\\([a-z]+\\|[A-Z]+\\)"
2640 "\\(::[A-Z]\\([a-z]+[A-Za-z]+\\|[A-Z]+\\)\\)+$")
2642 (setq word (match-string 0 word))
2643 (when (not (string-match "\\.pm$" word))
2644 (setq word (concat word ".pm")))
2647 ;;; ----------------------------------------------------------------------
2649 (defun tinyperl-ask-module (&optional msg)
2650 "Ask with MSG a module."
2651 (let ((word (tinyperl-read-word-module)))
2654 (or tinyperl-:inc-module-list
2655 (error "TinyPerl: No tinyperl-:inc-module-list"))
2657 (not 'require-match)
2659 ;; Put point to the beginning so that user can hit C-k to kill
2660 ;; possibly unwanted word.
2663 ;;; ----------------------------------------------------------------------
2665 (defun tinyperl-locate-library (module &optional no-guess)
2666 "Check where is MODULE. A .pl and .pm suffixes is added if needed.
2669 MODULE String, name of perl module that should be along
2670 `tinyperl-:inc-module-list'
2671 NO-GUESS Flag, if non-nil don't try searching suffixes .pm and .pl. Trus
2672 MODULE to be exact name.
2678 (assoc module tinyperl-:inc-module-list)
2679 (or (assoc module tinyperl-:inc-module-list)
2680 (assoc (concat module ".pm") tinyperl-:inc-module-list)
2681 (assoc (concat module ".pl") tinyperl-:inc-module-list))))
2683 ;;; ----------------------------------------------------------------------
2685 (defun tinyperl-library-find-file (elt)
2686 "Load library pointer by ELT into emacs.
2687 The ELT is return value from `tinyperl-locate-library'.
2695 ;; Getopt::Long.pm --> Long.pm
2696 (replace-regexp-in-string "^.*:" "" (car elt)))))
2698 ;;; ----------------------------------------------------------------------
2700 (defun tinyperl-manpage-at-point ()
2701 "Read word under cursor, if it looks like a perl manual page.
2702 The word must be in lowercase and start with 'perl'."
2703 (let ((word (thing-at-point 'word))
2706 (string-match "^perl." word))
2709 ;;; ----------------------------------------------------------------------
2711 (defun tinyperl-pod-ask-manpage ()
2712 "Ask pod page and return absolute path of POD manpage."
2713 (tinyperl-pod-manpage-to-file
2715 "View pod manpage: "
2719 (let ((word (tinyperl-manpage-at-point)))
2721 (concat word ".pod"))))))
2723 ;;; ----------------------------------------------------------------------
2725 (defun tinyperl-pod-font-lock ()
2726 "Turn on `font-lock-mode' and set `tinyperl-:pod-font-lock-keywords'.
2727 The `font-lock-mode' is turned on only if `ti::colors-supported-p'
2730 (when (ti::colors-supported-p)
2731 (ti::string-syntax-kill-double-quote)
2732 ;; Somehow the keywords must be setq after font-lock is turned on
2733 ;; to take in effect.
2735 (turn-on-font-lock-mode)
2736 (setq font-lock-keywords tinyperl-:pod-font-lock-keywords)
2737 (font-lock-fontify-buffer)
2740 ;;; ----------------------------------------------------------------------
2742 (defun tinyperl-pod-buffer-name (module)
2743 "Make POD buffer name for perl module like ´English'.
2747 `tinyperl-:pod-buffer-name' Always is single POD buffer in effect
2748 `tinyperl-:pod-buffer-control'."
2749 (if (memq tinyperl-:pod-buffer-control '(nil one single))
2750 tinyperl-:pod-buffer-name
2751 (let* ((name module)) ;; (replace-regexp-in-string "\.pm$" "" module)))
2752 (concat "*pod: " name "*"))))
2754 ;;; ----------------------------------------------------------------------
2756 (defun tinyperl-pod-re-search (regexp &optional buffer)
2757 "Check BUFFER for REGEXP and return (buffer . point) or nil."
2759 (setq buffer (current-buffer)))
2760 (when (buffer-live-p buffer)
2761 (with-current-buffer buffer
2764 (if (re-search-forward regexp nil t)
2765 (cons (current-buffer) (point)))))))
2767 ;;; ----------------------------------------------------------------------
2769 (defun tinyperl-pod-pop-to-buffer (regexp &optional buffer)
2770 "Pop to POD buffer if REGEXP matches. Return non-nil if ok."
2771 (let* ((elt (tinyperl-pod-re-search regexp buffer)))
2773 (pop-to-buffer (car elt))
2774 (goto-char (cdr elt)))))
2777 ;;{{{ POD interactive
2779 ;;; ----------------------------------------------------------------------
2782 (defun tinyperl-pod-kill-buffers ()
2783 "Kill all temporary POD buffers."
2786 (unless (y-or-n-p "Kill All temporary pod buffers ")
2787 (error "TinyPerl: Abort."))))
2788 (dolist (buffer (buffer-list))
2789 ;; For each buffer that has string "*pod" and which doesn't have
2790 ;; attached filename
2791 (when (string-match "\\*pod" (buffer-name buffer))
2792 (unless (with-current-buffer buffer (buffer-file-name))
2793 (kill-buffer buffer)))))
2795 ;;; ----------------------------------------------------------------------
2797 (defun tinyperl-external-command-format (bin)
2798 "Determine how to call external BIN. Prepend Perl interpreter as needed.
2799 If BIN name contain .bat .cmd etc, return BIN as it.
2800 Otherwise prepend \"perl\" at from and return '(\"perl\" . BIN)."
2801 (if (string-match "\\....?$" bin) ;; .ex or .ext
2803 (cons tinyperl-:perl-bin bin)))
2805 ;;; ----------------------------------------------------------------------
2807 (defun tinyperl-perldoc-1 (buffer arg-list)
2808 "Call ´tinyperl-:perldoc-bin'. Insert results to BUFFER.
2809 Call arguments are in ARG-LIST."
2810 ;; Win32 call-process fails if the binary c:\prgram files\..
2811 ;; name contains spaces. This is special problems for perldoc.bat
2812 ;; Because it is in fact full of perl code and called again. See
2813 ;; The source of perldoc.bat
2815 ((not (ti::win32-p))
2816 (apply 'call-process
2817 tinyperl-:perldoc-bin
2823 (with-current-buffer buffer
2824 (let* ((perl-type (tinyperl-perl-type))
2825 (cmd (if (ti::win32-shell-p)
2826 ;; Must not contain path name
2827 ;; I don't know if the exact problem was due to
2828 ;; SPACES in the path name.
2830 tinyperl-:perldoc-bin))
2831 (call-type (tinyperl-external-command-format cmd))
2832 (args (ti::list-to-string arg-list)))
2833 ;; Add "perl" to the front of command if it is "perldoc".
2834 ;; This will work under Windows/Cygwin and Unix
2835 (if (listp call-type)
2836 (setq cmd (format "%s %s %s"
2840 (setq cmd (format "%s %s" cmd args)))
2841 (ti::process-perl-process-environment-macro
2843 ;; At least shell command works, this a bit more expensive
2844 (let ((out (shell-command-to-string cmd)))
2849 ;;; ----------------------------------------------------------------------
2852 (defun tinyperl-perldoc (string &optional force verb)
2853 "Run perldoc with STRING. First try with -f then without it.
2854 Show content in `tinyperl-:perldoc-buffer'. If buffer is visible in
2855 some other frame, the cursor is not moved there. Only contents is updated.
2857 The last used STRING is cached and if called next time with same
2858 string, the shell command is not called unless FORCE is non-nil.
2863 FORCE Force calling shell although answer cached
2864 VERB flag, Allow verbose messages
2868 `tinyperl-:perldoc-hook'"
2871 (read-string "Perldoc -f: " (ti::buffer-read-word))
2872 current-prefix-arg))
2873 (let* ((buffer (get-buffer-create tinyperl-:perldoc-buffer))
2874 (last (get 'tinyperl-perldoc 'string))
2877 (if (ti::win32-shell-p)
2878 ;; Must not contain path name
2879 ;; I don't know if the exact problem was due to
2880 ;; SPACES in the path name.
2882 tinyperl-:perldoc-bin)
2890 (with-current-buffer buffer
2891 (ti::buffer-empty-p)))
2892 (not (stringp last)) ;Show previous result
2893 (not (string= last string)))
2895 (get-buffer-create buffer)
2896 (with-current-buffer buffer
2897 (setq buffer-read-only nil)
2900 (tinyperl-verbose-macro 2
2901 (message "TinyPerl: Running %s" cmd)))
2902 ;; Win32 call-process fails if the binary c:\prgram files\..
2903 ;; name contains spaces. This is special problems for perldoc.bat
2904 ;; Because it is in fact full of perl code and called again. See
2905 ;; The source of perldoc.bat
2906 (tinyperl-perldoc-1 buffer (list "-f" string))
2907 ;; What if we had no luck? Try without "-f" then.
2908 (with-current-buffer buffer
2910 (when (or (looking-at "^No documentation.*for.*function\\|Can't open")
2911 (ti::buffer-empty-p))
2914 (tinyperl-verbose-macro 2
2915 (message "TinyPerl: No matches. Trying without -f ...")))
2916 (tinyperl-perldoc-1 buffer (list string))
2917 (setq cmd (format "%s %s"
2918 tinyperl-:perldoc-bin
2921 (tinyperl-verbose-macro 2
2922 (message "TinyPerl: No matches. Trying without -f ...Done.")))))
2924 (tinyperl-verbose-macro 2
2925 (message "TinyPerl: Running %s. Done." cmd))))
2927 ((setq win (or (get-buffer-window buffer t) ;In another frame
2928 (get-buffer-window buffer)))
2929 (shrink-window-if-larger-than-buffer win)
2930 (raise-frame (window-frame win)))
2932 (display-buffer buffer)))
2934 (with-current-buffer buffer
2935 (setq buffer-read-only nil)
2936 (run-hooks 'tinyperl-:perldoc-hook)
2937 (setq buffer-read-only t)))
2938 ;; save the last query string.
2940 (put 'tinyperl-perldoc 'string string))))
2942 ;;; ----------------------------------------------------------------------
2945 (defun tinyperl-module-find-file (module)
2946 "Load Perl MODULE source."
2947 (interactive (list (tinyperl-ask-module "Perl module find file: ")))
2948 (tinyperl-pod-by-module module 'load))
2950 ;;; ----------------------------------------------------------------------
2952 (defun tinyperl-pod-search-regexp-by-module (module)
2953 "Generate a search regexp for `tinyperl-:pod-buffer-name' for MODULE."
2954 (if (string-match "^\\(.+\\)\\.pm" module)
2955 (setq module (match-string 1 module)))
2956 (let ((name (regexp-quote module)))
2959 ;; Tie::Hash, Tie::StdHash, Tie::ExtraHash - base class definitions for
2960 "^NAME[ \t]*\\(\r\n\\|\n\\)"
2965 ;; require Tie::Hash;
2966 "^[ \t]+\\(use +\\|require +\\) *"
2970 ;;; ----------------------------------------------------------------------
2973 (defun tinyperl-pod-by-module (module &optional mode)
2974 "Show pod manual page for MODULE or load MODULE.
2978 MODULE The Perl module as it appears in `use' statement,
2979 like Getopt::Long the '.pm' is automatically added.
2980 MODE If non-nil, load source file, not pod."
2982 (list (tinyperl-ask-module "View module's pod: ")
2983 current-prefix-arg))
2984 (let* ((name (replace-regexp-in-string "\.pm$" "" module))
2985 (pod-buffer-name (tinyperl-pod-buffer-name module))
2986 (pod-buffer (get-buffer pod-buffer-name))
2987 (regexp (tinyperl-pod-search-regexp-by-module name))
2990 ;; ................................................. existing POD ...
2993 (tinyperl-pod-pop-to-buffer regexp pod-buffer))
2994 nil) ;POD is already available
2995 ;; ................................... new documentation or load ...
2997 (if (not (string-match ".p[lm]$" module))
2998 (setq module (concat module ".pm")))
2999 (unless (setq module (tinyperl-locate-library module))
3001 (substitute-command-keys
3003 "TinyPerl: Can't find module from `tinyperl-:inc-module-list'. "
3004 "If new perl modules have been installed from CPAN, use "
3005 "\\[tinyperl-install-force] to rebuild cache."))))
3006 ;; In FEW cases the *.pm file does not contain the documentation,
3007 ;; but there is separate *.pod file, E.g POSIX.pm => POSIX.pod
3008 (multiple-value-bind (name pathname)
3009 (list (car module) (cdr module))
3011 (replace-regexp-in-string
3017 ;; Delete prefix, because (cdr path) will cnotain the
3020 ;; Getopt::Long.pm --> Long.pm
3021 (replace-regexp-in-string
3024 (when (file-exists-p path)
3028 (when (or (not file)
3029 (not (file-exists-p file)))
3030 (error "TinyPerl: Cache error, %s does not exist" (car module)))
3036 (ti::pop-to-buffer-or-window
3039 (get-buffer-create pod-buffer-name)))
3041 (re-search-forward regexp nil t)))))))
3043 ;;; ----------------------------------------------------------------------
3045 (defun tinyperl-pod-podchecker (file)
3046 "Run podchecker on current file."
3050 "TinyPerl podcheck: "
3051 (file-name-directory (or (buffer-file-name)
3055 (if (buffer-file-name)
3056 (file-name-nondirectory (buffer-file-name))
3058 (let* ((buffer (tinyperl-podchecker file)))
3059 (display-buffer buffer)))
3061 ;;; ----------------------------------------------------------------------
3064 (defun tinyperl-pod-find-file (file)
3065 "Run pod2text on FILE and create new buffer: '*pod' + FILE + '*'.
3066 If file contains pod documentation section, it will be formatted nicely."
3067 (interactive "fFile to pod: ")
3068 (let* ((name (file-name-nondirectory file))
3069 (buffer (get-buffer-create (concat "*pod " name "*"))))
3070 (with-current-buffer buffer
3071 (setq buffer-read-only nil)
3073 (ti::pop-to-buffer-or-window (tinyperl-pod2text file buffer))
3076 ;;; ----------------------------------------------------------------------
3078 (defun tinyperl-pod-find-file-this-buffer ()
3079 "Call `tinyperl-pod-find-file' with `buffer-file-name'"
3081 (if (buffer-file-name)
3082 (tinyperl-pod-find-file (buffer-file-name))
3083 (error "TinyPerl: This buffer is not associated with file.")))
3085 ;;; ----------------------------------------------------------------------
3087 (defun tinyperl-pod-jump (module)
3088 "Jump to Perl MODULE POD if it exists or do nothing."
3090 (let* ((buffer (get-buffer (tinyperl-pod-buffer-name module))))
3092 (ti::pop-to-buffer-or-window buffer))))
3094 ;;; ----------------------------------------------------------------------
3097 (defun tinyperl-pod-by-manpage (file)
3098 "Display pod for FILE."
3099 (interactive (list (tinyperl-pod-ask-manpage)))
3100 (when (ti::nil-p file)
3101 (error "TinyPerl: Need POD FILE, like `perldoc.pod', was `%s'" file))
3102 (let* ((fid "tinyperl-pod-by-manpage")
3103 (buffer (get-buffer-create (tinyperl-pod-buffer-name
3104 (file-name-nondirectory file))))
3105 (beg (with-current-buffer buffer
3107 ;; perldsc - Perl Data Structures Cookbook
3109 (regexp (concat "NAME[\n\r \t]+"
3111 (replace-regexp-in-string
3113 (file-name-nondirectory file)))
3115 (tinyperl-debug fid "file" file "buffer" buffer)
3116 (or (tinyperl-pod-pop-to-buffer regexp buffer)
3118 (ti::pop-to-buffer-or-window (tinyperl-pod2text file buffer))
3124 ;;; ----------------------------------------------------------------------
3127 (defun tinyperl-pod-grep (regexp &optional pod-path)
3128 "Grep REGEXP from perl pod files.
3129 This is your way to find what pages contain references to the items you're
3130 looking for. However if you select the file from compile buffer, it is
3131 in the unconverted format (.pod). A better would be to memorize the
3134 perlre.pod:165: \\Z Match at only e
3136 And call immediately \\[tinyperl-pod-by-manpage] and view `perlre' in
3137 more pleasant manner. Few C-s searches or \\[occur] will take you
3138 to the correct position."
3139 (interactive "sPod grep regexp: ")
3141 (setq pod-path (or tinyperl-:pod-path
3142 (error "TinyPerl: No tinyperl-:pod-path"))))
3143 (unless (file-directory-p pod-path)
3144 (error "POD directory not found [%s]" pod-path))
3145 (let* ((grep (tinyperl-grep-program))
3147 ;; Have to set this variable, because we can't
3148 ;; allow to pass full path to the grep. in Win32 Emacs would
3149 ;; send path in DOS style, but Cygwin does not accept those;
3150 ;; only unix style paths.
3152 ;; So, it's enough to Emacs to do an "cd" to directory.
3154 (default-directory (file-name-directory pod-path)))
3156 (if (fboundp 'igrep)
3157 (ti::funcall 'igrep nil regexp "*.pod" pod-path)
3158 (grep (format "%s -n '%s' %s*pod" grep regexp pod-path)))))
3160 ;;; ----------------------------------------------------------------------
3163 (defun tinyperl-process-wait (buffer)
3164 "Wait until process in BUFFER has finished."
3166 (while (or (null (get-buffer buffer))
3167 (and (setq process (get-buffer-process buffer))
3168 (memq (process-status process) '(run))
3172 ;;; ----------------------------------------------------------------------
3174 (defun tinyperl-pod-grep-faq-data-context-1 (&optional line)
3175 "Read FAQ context around LINE in current buffer.
3176 Enough context is a) FAQ entry b) or paragraph if there
3177 is no direct faq entry.
3181 '(TOPIC-HEADING TEXT-DATA)
3183 TOPIC-HEADING does not end to cr/lf
3184 TEXT-DATA ends to cr/lf"
3185 (flet ((context-min (point lines)
3187 (backward-line lines)
3189 (context-max (point lines)
3191 (forward-line lines)
3193 (enough-chars-found-point-p
3195 ;; Require at least 5 lines
3196 (> (abs (- point1 point2)) (* 80 5))))
3203 ;; about 15 lines supposing 80 chars per line.
3204 ;; These values are rough guesses.
3208 (setq point (point))
3209 (setq min (context-min point 7))
3210 (setq max (context-max point 5))
3211 (setq search-min (context-min point 20)))
3213 ((re-search-backward
3214 ;; FAQ topic line: perlfaq6.pod
3215 "^\\(=head[0-9]?.*\\)"
3218 (setq topic (match-string 1))
3219 ;; See if we can find next TOPIC nearby. Perhaps
3220 ;; this is short quote from faq.
3222 (if (re-search-forward "^=head[0-9]?\\(.*\\)"
3224 (setq max (line-beginning-position))))
3226 (goto-char point) ;; Previous search-min changed point
3228 (when (re-search-backward "^=head[0-9]?" nil 'noerr)
3229 (setq topic (ti::buffer-read-line))))
3230 ;; Excerpt enough content arount the point.
3233 (re-search-backward "^[ \t]*$" nil t)
3234 (setq try-min (point))
3236 (re-search-forward "^[ \t]*$" nil t)
3237 (setq try-max (point))
3238 ;; Do not accept too small paragraph for an answer
3239 (if (enough-chars-found-point-p try-min point)
3241 (if (enough-chars-found-point-p try-max point)
3242 (setq max try-max)))))
3243 ;; Read complete lines. Using just MIN and MAX would
3244 ;; give ragged text.
3245 (setq string (ti::remove-properties (buffer-substring min max)))
3246 (goto-char point) ;; restore
3247 (list (ti::remove-properties topic)
3250 ;;; ----------------------------------------------------------------------
3252 (defun tinyperl-pod-grep-faq-data-context
3253 (&optional buffer grep-data line)
3254 "Read FAQ context around point in BUFFER.
3255 GREP-DATA is the actual grep content.
3259 '(absolute-file-name GREP-DATA LINE (topic context-excerpt))"
3260 (with-current-buffer (or buffer (current-buffer))
3261 (list (ti::remove-properties (buffer-file-name))
3264 (ti::remove-properties grep-data))
3265 (tinyperl-pod-grep-faq-data-context-1 line))))
3267 ;;; ----------------------------------------------------------------------
3269 (defun tinyperl-pod-grep-faq-data-context-all-files
3270 (&optional buffer verb)
3271 "Read every grep in BUFFER and retun text excerpts from files.
3272 VERB allows verbose messages.
3276 '((absolute-file-name grep-data (topic text-data)
3277 (absolute-file-name grep-data (topic text-data)
3281 (ti::grep-output-parse-macro (or buffer (current-buffer))
3282 ;; Load file and goto correct line
3283 (let ((file (concat grep-dir grep-file)))
3285 (tinyperl-verbose-macro 2
3286 (message "TinyPerl: reading faq context %s" file)))
3287 (setq buffer (find-file-noselect file)))
3288 (with-current-buffer buffer
3289 (goto-line grep-line))
3291 ;; read enough context
3293 (tinyperl-pod-grep-faq-data-context
3294 buffer grep-data grep-line))
3298 ;;; ----------------------------------------------------------------------
3300 (defun tinyperl-pod-grep-faq-data-insert (data &optional verb)
3301 "Insert faq text DATA into current buffer. VERB.
3304 `tinyperl-pod-grep-faq-data-context-all-files'"
3305 (let ((colors-p (ti::colors-supported-p))
3307 ;; Has to disable font lock in this buffer of the
3308 ;; Highlighting isn't shown.
3310 (turn-on-font-lock-mode))
3312 (multiple-value-bind (file line grep-data context-data) elt
3313 (multiple-value-bind (topic text) context-data
3315 (tinyperl-verbose-macro 2
3316 (message "TinyPerl: processing data %s"
3317 (file-name-nondirectory file))))
3319 (format "FILE: [%s]" (file-name-nondirectory file))
3321 (format " LINE: %d\n" line)
3326 (format "%s\n[...cut...]\n" topic)
3328 (setq point (point))
3332 ;; Mark line that matched.
3333 (ti::text-re-search-forward (regexp-quote grep-data))
3336 ;;; ----------------------------------------------------------------------
3339 (defun tinyperl-pod-grep-faq-answer (regexp &optional verb)
3340 "Grep REGEXP from perl pod files. VERB.
3342 This function also gathers all =head topics that match the REGEXP.
3343 You can use generated page as an answer to 'Has this this question
3344 been answered in FAQ'"
3345 (interactive "sPod FAQ search regexp: ")
3346 (let* ((path (or tinyperl-:pod-path
3347 (error "TinyPerl: No tinyperl-:pod-path")))
3348 (default-directory (file-name-directory path))
3350 (out-buffer tinyperl-:faq-buffer-name)
3351 (grep (tinyperl-grep-program))
3355 ;; Grep all strings in pod files
3356 (grep (format "%s -n '%s' %s*pod" grep regexp path))
3357 ;; Grep is asyncronousd, need sleep, and then
3358 ;; wait until process finishes. Only after that we gather hits.
3359 (tinyperl-verbose-macro 1
3360 (message "TinyPerl: waiting *grep* process finish..."))
3361 (tinyperl-process-wait buffer)
3362 (tinyperl-verbose-macro 1
3363 (message "TinyPerl: waiting *grep* process finish...done"))
3364 ;; See if we got any faq Subject hits?
3365 ;; --> put them into list '((faq-name (topic data)) ..)
3366 (setq data (tinyperl-pod-grep-faq-data-context-all-files buffer verb))
3368 (display-buffer (get-buffer-create out-buffer))
3369 (with-current-buffer out-buffer
3371 (tinyperl-pod-grep-faq-data-insert data)
3374 (tinyperl-verbose-macro 1
3375 (message "TinyPerl: FAQ done."))
3376 (tinyperl-verbose-macro 1
3377 (message "TinyPerl: FAQ context processing failed [no data].")))))
3382 ;;; ----------------------------------------------------------------------
3384 (put 'tinyperl-version-macro 'edebug-form-spec '(body))
3385 (put 'tinyperl-version-macro 'lisp-indent-function 0)
3386 (defmacro tinyperl-version-macro (&rest body)
3387 "Do BODY when version variable is found. Uses `save-excursion'."
3391 ;; (ti::buffer-outline-widen)
3392 (when (tinyperl-version-stamp-re-search-forward)
3395 ;;; ----------------------------------------------------------------------
3397 (defun tinyperl-version-stamp-re-search-forward ()
3398 "Search perl $VERSION variable. Match 2 will contain the version."
3399 (let (case-fold-search)
3402 "^[ \t]*\\(my\\|local\\|our\\)?[ \t]*\\$VERSION[ \t]*=[ \t]*[\"']"
3403 "\\([0-9][0-9][0-9][0-9]\\.[0-9][0-9][0-9][0-9]\\)[\"'][ \t]*;")
3407 ;;; ----------------------------------------------------------------------
3409 (defun tinyperl-version-stamp ()
3410 "Find $VERSION = '1234.1234'; variable and update ISO 8601 date."
3411 (let* ((date (format-time-string "%Y.%m%d" (current-time))))
3412 (tinyperl-version-macro
3413 ;; Replace only if it is not current date
3414 (unless (save-match-data
3415 (string-match (regexp-quote date) (match-string 2)))
3416 (replace-match date nil nil nil 2)))))
3418 ;;; ----------------------------------------------------------------------
3420 (defun tinyperl-pause-file-name (&optional filename use-date)
3421 "Generate PAUSE FILENAME: file-version.pl.
3424 FILENAME like `buffer-file-name'
3425 USE-DATE if non-nil, use file-yyyy.mmdd.pl, otherwise
3426 try to guess verison number from a Perl variable in script.
3427 See function `tinyperl-version-stamp-re-search-forward'."
3431 (setq buffer (or (and filename
3432 (find-buffer-visiting filename))
3434 (find-file-noselect filename)
3436 (with-current-buffer buffer
3437 (tinyperl-version-macro
3438 (let* ((ver (or (match-string 2)
3443 (name1 (file-name-nondirectory
3446 (error "TinyPerl: No `buffer-file-name'"))))
3447 (name (file-name-sans-extension name1))
3448 (ext (file-name-extension name1)))
3449 (when (and (stringp ver)
3450 (string-match "^[0-9]+" ver))
3451 (setq ret (format "%s-%s.%s" name ver ext))))))
3452 (if kill ;We loaded this from disk
3453 (kill-buffer buffer))
3456 ;;; ----------------------------------------------------------------------
3458 (defun tinyperl-pause-copy-file (&optional directory)
3459 "Copy perl script to separate directory to wait for PAUSE submission.
3461 In order to submit code to PAUSE, it must contain version number.
3462 The file is copied under name FILE-VERSION.pl to DIRECTORY in
3465 1. DIRECTORY (available only as a lisp call)
3466 2. `tinyperl-:pause-directory' (user's default setting)
3467 3. or to current directory
3471 `tinyperl-:pause-directory'."
3473 (let ((path tinyperl-:pause-directory))
3475 (read-file-name "TinyPerl: [PAUSE dir]: "
3476 (and path (file-name-directory path))
3477 nil ;; users null string
3480 (file-name-nondirectory path))))))
3481 (let* ((from (buffer-file-name))
3482 (file (tinyperl-pause-file-name from))
3484 (unless (file-directory-p directory)
3485 (error "TinyPerl: Directory not found %s" directory))
3487 (message "TinyPerl: Not ready for PAUSE. No $VERSION = 'value';"))
3488 (setq to (concat (file-name-as-directory directory) file))
3489 (copy-file from to 'ok-if-already-exists)
3490 (tinyperl-verbose-macro 1
3491 (message "Tinyperl: PAUSE, Copied to %s" to))
3494 ;;; ----------------------------------------------------------------------
3496 (defun tinyperl-pause-upload-via-ftp (file)
3497 "Upload file to PAUSE server for submission.
3498 The filename must contain version number: FILE-VERSION.pl"
3499 (interactive (list (buffer-file-name)))
3500 (let* ((ver (tinyperl-pause-file-name file))
3501 (temp (file-name-as-directory
3502 (ti::temp-directory)))
3503 (upload (concat temp ver)))
3504 ;; Use safety net, not just about anything shuld be uploaded.
3505 (unless (string-match "\\.\\(pl\\|pm\\)$" file)
3506 (error "TinyPerl: Only .pm or .pl files can be uploaded."))
3507 ;;;#todo: background upload not working.
3509 ;;; (ti::file-ange-file-handle
3512 ;;; "pause.perl.org"
3516 ;;; nil ;; Run on background
3517 ;;; (format "TinyPerl: ange-ftp PAUSE upload completed %s" ver))
3518 (copy-file file upload 'ok-if-already-exists)
3520 (insert-file upload)
3523 "/anonymous@pause.perl.org:/incoming/"
3526 ;;; ----------------------------------------------------------------------
3528 (defun tinyperl-pause-url-submit-www-page ()
3529 "Visit PAUSE WWW page where you can submit your files.
3530 PAUSE means \"The Perl Authors Upload Server\""
3532 (tinyurl-agent-funcall
3534 ;; You need to be logged, in order to use this:
3535 ;; https://pause.perl.org/authenquery?ACTION=add_uri
3536 "http://pause.perl.org"))
3538 ;;; ----------------------------------------------------------------------
3540 (defun tinyperl-selfstubber-stubs (file &optional force)
3541 "Generate stubs, ie. function predeclarations from FILE.
3542 Run SelfStubber on current module, whichexpects to find functions
3543 after __DATA__ token.
3545 If there is entry in current buffer to read
3547 # BEGIN: Devel::SelfStubber
3548 # END: Devel::SelfStubber
3550 Then the generated subs are inserted into that section. Any previous
3555 FORCE Flag, if nono-nil, copy the file under temp directory
3556 and __DATA__ token to the beginning of file do that
3557 all functions are shown. You can use this flag to generate
3558 prototypes of all functions."
3561 (read-file-name "Perl stubs from file: "
3563 (file-name-nondirectory buffer-file-name))
3564 current-prefix-arg))
3565 (let* ((name (file-name-nondirectory file))
3571 (setq file (expand-file-name file))
3574 ;; ........................................... forced insert ...
3576 (unless (string-match "\\.pm$" name)
3577 ;; SelfStubber expects Modules (.pm) files only
3578 (tinyperl-verbose-macro 2
3579 (message "TinyPerl: %s must end to .pm, fixing..." file))
3580 (setq name (concat name ".pm")))
3582 (setq tmp (ti::temp-file name 'tmp-dir))
3583 (copy-file file tmp)
3586 (with-current-buffer (setq buffer (find-file-noselect file))
3587 (delete-matching-lines "__DATA__")
3589 (insert "use SelfLoader;\n__DATA__\n")
3591 ;; ............................................ perl-command ...
3594 "Devel::SelfStubber->stub( qq{%s}, qq{%s} )"
3595 (replace-regexp-in-string "\\.pm$" ""
3596 (file-name-nondirectory file))
3597 (replace-regexp-in-string "[\\/]$" ""
3598 (file-name-directory file))))
3600 (tinyperl-verbose-macro 2
3601 (message ;Record it to *Messages* buffer
3603 "%s -MDevel::SelfStubber -e %s"
3606 ;; ........................................... find-position ...
3608 (and (setq beg (ti::re-search-check
3609 "BEGIN:[ \t]+Devel::SelfStubber"))
3610 (setq end (ti::re-search-check
3611 "\n#[ \t]+END:[ \t]+Devel::SelfStubber")))
3617 (delete-region (point) end)
3619 (call-process tinyperl-:perl-bin
3623 "-MDevel::SelfStubber "
3627 (tinyperl-verbose-macro 1
3628 (message "TinyPerl: stubs updated in buffer"))))
3629 (t ;No previoous STUBS
3630 (call-process tinyperl-:perl-bin
3634 "-MDevel::SelfStubber "
3638 (kill-buffer buffer)))))
3642 (tinyperl-skeleton-setup)
3645 (run-hooks 'tinyperl-:load-hook)
3647 ;;; tinyperl.el ends here