]> git.donarmstrong.com Git - lib.git/blob - emacs_el/tiny-tools/tiny/tinyperl.el
add tiny-tools
[lib.git] / emacs_el / tiny-tools / tiny / tinyperl.el
1 ;;; tinyperl.el --- Grab-bag of Perl related utilities. Pod documentation
2
3 ;; This file is not part of Emacs
4
5 ;;{{{ Id
6
7 ;; Copyright (C) 1998-2007 Jari Aalto
8 ;; Keywords:     extensions
9 ;; Author:       Jari Aalto
10 ;; Maintainer:   Jari Aalto
11 ;;
12 ;; To get information on this program, call M-x tinyperl-version.
13 ;; Look at the code with folding.el
14
15 ;; COPYRIGHT NOTICE
16 ;;
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)
20 ;; any later version.
21 ;;
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
25 ;; for more details.
26 ;;
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.
31 ;;
32 ;; Visit <http://www.gnu.org/copyleft/gpl.html> for more information
33
34 ;;}}}
35 ;;{{{ Install
36
37 ;;; Install:
38
39 ;; ....................................................... &t-install ...
40 ;; Put this file on your Emacs-Lisp load path, add following into your
41 ;; ~/.emacs startup file.
42 ;;
43 ;;      (require 'tinyperl)
44 ;;
45 ;;  Autoload, prefer this one, your emacs starts quicker. The additional
46 ;;  features are turned on only when `perl-mode' runs.
47 ;;
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)
51 ;;
52 ;;  This package will keep the configuration information in a cache and
53 ;;  if for some reason the cache becomes invalid, force rebuilding everything
54 ;;  with command:
55 ;;
56 ;;      C-u M-x tinyperl-install
57 ;;
58 ;;  To completely uninstall package, call:
59 ;;
60 ;;      C-u M-x tinyperl-install-main
61 ;;
62 ;;  If you have any questions, suggestions, use this function
63 ;;
64 ;;      M-x tinyperl-submit-bug-report
65
66 ;;}}}
67
68 ;;{{{ Documentation
69
70 ;; ..................................................... &t-commentary ...
71
72 ;;; Commentary:
73
74 ;;  Preface, march 1998
75 ;;
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.
84 ;;
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
90 ;;      perl language.
91 ;;
92 ;;  Overview of features
93 ;;
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"
99 ;;
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.
103 ;;
104 ;;      `tinyperl-mode' minor mode:
105 ;;
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.
113 ;;
114 ;;      Other minor modes:
115 ;;
116 ;;      o   Separate `tinyperl-pod-view-mode' for reading pod2text pages
117 ;;      o   Separate `tinyperl-pod-write-mode' for writing POD documentation
118 ;;
119 ;;  Package startup
120 ;;
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
125 ;;      cached too.
126 ;;
127 ;;      In addition the Perl POD manual pages and paths are cached at startup.
128 ;;      This is derived from *Config.pm* module $Config{privlib}.
129 ;;
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.
133 ;;
134 ;;  Saving TinyPerl state (cache)
135 ;;
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.
141 ;;
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').
146 ;;
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'.
151 ;;
152 ;;  Perl Minor Mode description
153 ;;
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'.
161 ;;
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
167 ;;
168 ;;          C-c ' m             tinyperl-module-find-file
169 ;;          C-c ' d             tinyperl-perldoc
170 ;;          C-c ' g             tinyperl-pod-grep
171 ;;
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
177 ;;          perl program.
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".
193 ;;
194 ;;  POD view mode description: navigating in pod page and following URLs
195 ;;
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:
199 ;;
200 ;;          See perlfunc manpage
201 ;;              ^^^^^^^^^^^^^^^^
202 ;;
203 ;;          See [perltoc]
204 ;;              ^^^^^^^^^
205 ;;
206 ;;          Devel::Dprof manpage
207 ;;          ^^^^^^^^^^^^^^^^^^^^
208 ;;
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:
213 ;;
214 ;;          (add-hook tinyperl-:load-hook 'my-tinyperl-:load-hook)
215 ;;
216 ;;          (defun my-tinyperl-:load-hook ()
217 ;;            "My TinyPerl customisations."
218 ;;            (remove-hook 'tinyperl-:pod2text-after-hook
219 ;;                         'turn-on-tinyurl-mode-1))
220 ;;
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'.
225 ;;
226 ;;          ;;  moving down/up topics
227 ;;
228 ;;          Control-PgDown              tinyperl-pod-view-heading-forward
229 ;;          Control-PgDown              tinyperl-pod-view-heading-backward
230 ;;
231 ;;          S-PgDown    tinyperl-pod-view-heading-forward2
232 ;;          S-PgDown    tinyperl-pod-view-heading-backward2
233 ;;
234 ;;          ;; Moving down/up one pod page at a time
235 ;;          ;; The pod pages are all gathered to single buffer *pod*
236 ;;
237 ;;          Meta-PgDown tinyperl-pod-view-forward
238 ;;          Meta-PgUp   tinyperl-pod-view-backward
239 ;;
240 ;;          ;;  The normal PgUp/Down commands
241 ;;
242 ;;          PgDown      scroll-up
243 ;;          PgUp        scroll-down
244 ;;
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.
249 ;;
250 ;;  POD Write mode description
251 ;;
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.
257 ;;
258 ;;          PgDown      tinyperl-pod-write-heading-forward
259 ;;          PgUp        tinyperl-pod-write-heading-backward
260 ;;
261 ;;      With shift
262 ;;
263 ;;          PgDown      tinyperl-pod-write-token-forward
264 ;;          PgUp        tinyperl-pod-write-token-backward
265 ;;
266 ;;      Inserting default POD templates for program
267 ;;
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
271 ;;
272 ;;      Inserting default POD skeletons for Modules or Classes.
273 ;;
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
277 ;;
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
282 ;;      module.
283 ;;
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.
291 ;;
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.
298 ;;
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).
306 ;;
307 ;;          F I L E   B A N N E R
308 ;;
309 ;;          P O D  H E A D E R
310 ;;          NAME
311 ;;          REVISION
312 ;;          SYNOPSIS
313 ;;          DESCRIPTION
314 ;;          EXPORTABLE VARIABLES
315 ;;          EXAMPLES
316 ;;
317 ;;          #   module interface is written next
318 ;;
319 ;;          use strict;
320 ;;
321 ;;          BEGIN
322 ;;          {
323 ;;                .. EXPORT          # The export interface
324 ;;                .. EXPORT_OK
325 ;;          }
326 ;;
327 ;;          Define exported globals
328 ;;
329 ;;          Define private variables
330 ;;
331 ;;          P O D   I N T E R F A C E   S T A R T
332 ;;
333 ;;          P O D  P U B L I C for public functions or method
334 ;;          sub ...
335 ;;
336 ;;          NORMAL banner of private function
337 ;;          sub ...
338 ;;
339 ;;          P O D   F O O T E R
340 ;;          KNOWN BUGS
341 ;;          AVAILABILITY
342 ;;          AUTHOR
343 ;;
344 ;;          1;
345 ;;          __END__
346 ;;
347 ;;  Perl SelfStubber
348 ;;
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
355 ;;      function)
356 ;;
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.
361 ;;
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
365 ;;      shell buffer.
366 ;;
367 ;;          package MyClass;
368 ;;
369 ;;          use Exporter;
370 ;;          use SelfLoader;
371 ;;          use vars qw( $VERSION @ISA @EXPORT @EXPORT_OK );
372 ;;
373 ;;          @ISA    = qw(Exporter);
374 ;;
375 ;;          @EXPORT = qw( .. );
376 ;;
377 ;;          $VERSION = ..
378 ;;
379 ;;          # BEGIN: Devel::SelfStubber
380 ;;
381 ;;          # END: Devel::SelfStubber
382 ;;
383 ;;          1;
384 ;;          __DATA__
385 ;;
386 ;;          <implementation: functions and variables>
387 ;;
388 ;;          __END__
389 ;;
390 ;;  Updating the VERSION variable
391 ;;
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.
400 ;;
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
404 ;;      to it.
405 ;;
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.
412 ;;
413 ;;          use vars qw ( $VERSION );
414 ;;
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
418 ;;          #
419 ;;          #   The following variable is updated by Emacs setup whenever
420 ;;          #   file is saved
421 ;;
422 ;;          $VERSION = '1234.1234';
423 ;;
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').
428 ;;
429 ;;  Submitting your perl script to CPAN
430 ;;
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
433 ;;      refer to page:
434 ;;
435 ;;          http://www.perl.com/CPAN-local//scripts/submitting.html
436 ;;
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
441 ;;
442 ;;          `tinyperl-pod-write-skeleton-script-manpage'
443 ;;
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:
451 ;;
452 ;;          use English
453 ;;          use File::Basename;
454 ;;
455 ;;          use vars qw( $LIB );
456 ;;          $LIB = basename $PROGRAM_NAME;
457 ;;
458 ;;      Here is the help function written with POD (perl 5.004 or higher)
459 ;;
460 ;;          <  Create this Help() function banner with mode key           >
461 ;;          <  C-c . f   or `tinyperl-pod-write-skeleton-script-function' >
462 ;;
463 ;;          # ***************************************************************
464 ;;          #
465 ;;          #   DESCRIPTION
466 ;;          #
467 ;;          #       Print help and exit.
468 ;;          #
469 ;;          #   INPUT PARAMETERS
470 ;;          #
471 ;;          #       $msg        [optional] Reason why function was called.-
472 ;;          #
473 ;;          #   RETURN VALUES
474 ;;          #
475 ;;          #       none
476 ;;          #
477 ;;          # ***************************************************************
478 ;;
479 ;;          =pod
480 ;;
481 ;;          < This part: appears after you have called                  >
482 ;;          < C-c . m  or  `tinyperl-pod-write-skeleton-script-manpage' >
483 ;;
484 ;;          =cut
485 ;;
486 ;;          sub Help (;$)
487 ;;          {
488 ;;              my $id  = "$LIB.Help";
489 ;;              my $msg = shift;  # optional arg, why are we here...
490 ;;
491 ;;              pod2text $PROGRAM_NAME;
492 ;;
493 ;;              print $msg if $msg;
494 ;;
495 ;;              exit 1;
496 ;;          }
497 ;;
498
499 ;;}}}
500
501 ;;; Change Log:
502
503 ;;; Code:
504
505 ;;{{{ setup: require
506
507 (require 'tinylibm)
508
509 (eval-when-compile (ti::package-use-dynamic-compilation))
510
511 (eval-and-compile
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))
525
526 (ti::package-defgroup-tiny TinyPerl tinyperl-: extensions
527   "Additional function to perl programming.
528   Overview of features
529
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.")
538
539 ;;}}}
540 ;;{{{ setup: public variables
541
542 (defcustom tinyperl-:load-hook '(tinyperl-install)
543   "*Hook run when file has been loaded."
544   :type  'hook
545   :group 'TinyPerl)
546
547 (defcustom tinyperl-:pod2text-before-hook  nil
548   "Hook run before calling pod2text pod buffer See `tinyperl-pod2text'."
549   :type  'hook
550   :group 'TinyPerl)
551
552 (defcustom tinyperl-:pod2text-after-hook  nil
553   "Hook run after calling podchecker in that buffer.
554 See `tinyperl-podchecker'."
555   :type  'hook
556   :group 'TinyPerl)
557
558 (defcustom tinyperl-:podchecker-before-hook  nil
559   "Hook run before calling pod2text pod buffer See `tinyperl-podchecker'."
560   :type  'hook
561   :group 'TinyPerl)
562
563 (defcustom tinyperl-:podchecker-after-hook  nil
564   "Hook run after calling pod2text in that buffer. See `tinyperl-pod2text'."
565   :type  'hook
566   :group 'TinyPerl)
567
568 (defcustom tinyperl-:perldoc-hook nil
569   "Hook run after calling `tinyperl-perldoc'."
570   :type  'hook
571   :group 'TinyPerl)
572
573 ;;}}
574 ;;{{ setup: public
575
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")
580   :group 'TinyPerl)
581
582 (defcustom tinyperl-:key-pageup-control 'heading
583   "*How to use PgUp and PgDown keys. 'heading or 'normal."
584   :type '(choice (const heading)
585                  (const normal))
586   :group  'TinyPerl)
587
588 (defcustom tinyperl-:pod-buffer-control 'one
589   "*How to display POD documentation. 'single or 'many windows."
590   :type  '(choice (const one)
591                   (const many))
592   :group 'TinyPerl)
593
594 (defcustom tinyperl-:skeleton-script-ftp-url nil
595   "*URL where your Perl code is available. Used by skeleton."
596   :type  'string
597   :group 'TinyPerl)
598
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.
605
606 This variable is used by `tinyperl-pause-copy-file' for default
607 location where the pause upload candidates are copied.
608
609 See also http://cpan.perl.org/authors/id/NEILB/ cpan-upload-1.9.tar.gz."
610   :type  'directory
611   :group 'TinyPerl)
612
613 (defcustom tinyperl-:copyright-function 'tinyperl-copyright
614   "*Copyright notice for your Perl programs."
615   :type  'function
616   :group 'TinyPerl)
617
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
621 ;;  the Unix disk.
622 ;;
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?
626 ;;
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.
630
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'."
635   :type   'string
636   :group  'TinyPerl)
637
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\"."
641   :type  'string
642   :group 'TinyPath)
643
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.
650
651 You can always rebuild the cached Perl information with
652 \\[universal-argument] \\[tinyperl-install]"
653   :type  'integer
654   :group 'TinyPerl)
655
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."
660   :type  'string
661   :group 'TinyPerl)
662
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")
667           (and (ti::win32-p)
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.
671           (and (ti::win32-p)
672                (ti::file-get-load-path "perldoc.bat"
673                                        (split-string (getenv "PATH") ";" )))
674           ;;  Emacs executable-find cannot find pure Cygwin "perldoc".
675           ;;
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."
679   :type  'string
680   :group 'TinyPerl)
681
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."
687   :type 'string
688   :group  'TinyPerl)
689
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\"."
693   :type  'string
694   :group 'TinyPerl)
695
696 (defcustom tinyperl-:pod-font-lock-keywords ;; &fonts
697   (list
698    ;; ....................................................... pod2text ...
699    ;; Remeber that the order of the regular expressions is significant.
700    ;; First come, first served
701    ;;
702    ;; Like in File::Basename
703    ;; NAME
704    ;;     fileparse - split a pathname into pieces
705    ;;
706    ;;     basename - extract just the filename from a path
707    ;;
708    ;;     dirname - extract just the directory from a path
709    '("^    \\([^ \t\r\n]+\\)[ \t]+-[ \t]+"
710      1 font-lock-reference-face)
711
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
716    ;;
717    ;;   $ua->from([$email_address])
718    ;;   new()
719
720    '("^ ? ? ? ?\\([\"$%@A-Za-z_]+\\)[ \t]*$"
721      1 font-lock-type-face)
722    ;;  TWO WORDS after 4 spaces, level 2 heading
723    ;;
724    ;;    Packaging commands
725    ;;      package pkg
726    ;;
727    ;;      source-package
728    '("^    \\([A-Za-z_.]+[ -]*[A-Za-z-]*\\)[ \t]*$"
729      1 font-lock-type-face)
730    ;;   Head2/over-4
731    ;;     package-source.sh
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)
736    ;;
737    ;;  =head2 Topic Name Here
738    ;;  multipe words
739    ;;  perlre.pod 5.8.0:   "  Version 8 Regular Expressions"
740    ;;  perdoelta.pod 5.8.0 "  Self-tying Problems"
741    ;;
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)
758    ;; perlre.pod 5.8.0:
759    ;;    SEE ALSO
760    ;;        perlrequick.
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)
766    ;; --this-option
767    (list
768     (concat
769      "--[-a-zA-Z0-9]+\\>"
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)
780    ;;  [Wall]
781    (list
782     (concat
783      "\\[[a-zA-Z]+\\]+"
784      "\\|\\<[-a-zA-Z0-9]+([0-9]+[A-Z]?)") ;; chmod(1)
785     0 'font-lock-constant-face)
786    (list
787     (concat
788      ;;  "abc"
789      ;;  `this'   US style
790      ;;  'this'   European style
791      "[\"][^\"\r\n]+[\"]"
792      "\\|`[^'`\r\n]+'"
793      "\\|'[^'\r\n]+'"
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)
801    ;;  Perl Keywords
802    (list
803     (concat
804      "^        \\(        \\)*" ;; 8 x indentation allowed
805      "\\<\\("
806      "sub"
807      "\\|package"
808      "\\|use"
809      "\\|die"
810      "\\|warn"
811      "\\|local"
812      "\\|my"
813      "\\|if"
814      "\\|[ }]*else[ {]*"
815      "\\|eval"
816      "\\|print"
817      "\\|while"
818      "\\)\\>"
819      "\\|[$]_")
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)
828    '("^=.*"
829      0 font-lock-type-face))
830   "*Font lock keywords."
831   :type   'sexp
832   :group  'TinyPerl)
833
834 ;;}}}
835 ;;{{{ setup: private
836
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.
842
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.")
846
847 (defvar tinyperl-:inc-module-list nil
848   "The content .pm files under @INC.")
849
850 (defvar tinyperl-:pod-path  nil
851   "Path to perl distribution POD files.")
852
853 (defvar tinyperl-:pod-list  nil
854   "List of pod files. '((file.pod . path) (file.pod . path) ..).")
855
856 (defvar tinyperl-:pod-buffer-name "*pod*"
857   "Buffer where to print POD.")
858
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'")
862
863 (defvar tinyperl-:perldoc-buffer "*perldoc*"
864   "Buffer where to output perldoc.")
865
866 (defvar tinyperl-:podchecker-buffer "*podchecker*"
867   "Buffer where to output Pod::Checker::podchecker().")
868
869 ;;}}}
870 ;;{{{ version
871
872 ;;;###autoload (autoload 'tinyperl-version "tinyperl" "Display commentary." t)
873
874 (eval-and-compile
875   (ti::macrof-version-bug-report
876    "tinyperl.el"
877    "tinyperl"
878    tinyperl-:version-id
879    "$Id: tinyperl.el,v 2.85 2007/08/03 20:16:25 jaalto Exp $"
880    '(tili-:version-id
881      tinyperl-:load-hook
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
894      tinyperl-:perl-bin
895      tinyperl-:perldoc-bin
896      tinyperl-:pod2text-bin
897      tinyperl-:inc-path-switches
898      tinyperl-:pod-font-lock-keywords
899      tinyperl-:inc-path
900      tinyperl-:inc-module-list
901      tinyperl-:pod-path
902      tinyperl-:pod-list
903      tinyperl-:pod-buffer-name
904      tinyperl-:perldoc-buffer
905      tinyperl-:podchecker-buffer)))
906
907 ;;;### (autoload 'tinyperl-debug-toggle "tinyperl" t t)
908
909 (eval-and-compile (ti::macrof-debug-standard "tinyperl" "-:"))
910
911 ;;}}}
912 ;;{{{ Macros
913
914 ;;; ----------------------------------------------------------------------
915 ;;;
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."
919   (`
920    (when (and (numberp tinyperl-:verbose)
921               (or (= (, level) tinyperl-:verbose)
922                   (< (, level) tinyperl-:verbose)))
923      (,@ body))))
924
925 ;;; ----------------------------------------------------------------------
926 ;;;
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)
931            (directory-files
932             (, path)
933             nil
934             (or (, regexp) "\\.pl\\|\\.pm")))))
935
936 ;;; ----------------------------------------------------------------------
937 ;;;
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:
943
944     (setq tinyperl-:perldoc-bin
945           (tinyperl-executable-find-path
946            \"perldoc\" tinyperl-:perldoc-bin \"perldoc\"))
947
948 --> (tinyperl-executable-set 'tinyperl-:perldoc-bin \"perldoc\")"
949   (`
950    (set (, sym)
951         (tinyperl-executable-find-path
952          (, bin)
953          (symbol-value (, sym))
954          (or (, regexp)
955              (, bin))))))
956
957 ;;; ----------------------------------------------------------------------
958 ;;;
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)
966                  module)))
967     (when elt
968       (concat (file-name-as-directory (cdr elt))
969               file))))
970
971 ;;; ----------------------------------------------------------------------
972 ;;;
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
977   ;;  defined.
978   (let ((sym   'grep-program))
979     (if (boundp sym)
980         (symbol-value sym)
981       "grep")))
982
983 ;;}}}
984 ;;{{{ code: install, mode
985
986 ;;; ----------------------------------------------------------------------
987 ;;;
988 (defun tinyperl-variable-convert (&optional dos-format)
989   "Convert all path variables to Unix or DOS-FORMAT."
990   (flet ((convert (var)
991                   (if dos-format
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))))
998
999 ;;; --------------------------------------------------------------------
1000 ;;;
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)))
1006       old-value
1007     (setq program
1008           (if (and tinyperl-:perl-bin
1009                    ;;  This could return "perl5.005"
1010                    (string-match regexp old-value))
1011               (match-string 0 old-value)
1012             ;;  use default then
1013             program))
1014     (or (executable-find program)
1015         ;;  Only way to find Cygwin "perldoc".
1016         (ti::file-get-load-path program exec-path))))
1017
1018 ;;; ----------------------------------------------------------------------
1019 ;;;
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
1023
1024 variable `tinyperl-:perl-bin' are set to properties:
1025
1026   'version-answer   =>  The -v result string
1027   'type             =>  'win32-activestate
1028                         'win32-cygwin
1029                         'perl"
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))))
1033
1034 ;;; ----------------------------------------------------------------------
1035 ;;;
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))))
1041
1042 ;;; ----------------------------------------------------------------------
1043 ;;;
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))))
1049
1050 ;;; ----------------------------------------------------------------------
1051 ;;;
1052 (defun tinyperl-install-variables-binaries (&optional force)
1053   "Install or FORCE setting binary variables like `tinyperl-:perl-bin'
1054 Return:
1055   t      If some path needed fixing. This means that cache must be resaved."
1056   (interactive "P")
1057   (let* (ok)
1058     (flet ((exec-set
1059             (sym bin &optional regexp) ;; Parameters
1060             (let* ((value (symbol-value sym)))
1061               (when (or force
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)))
1070                 (setq ok t)
1071                 (or (tinyperl-executable-set sym bin regexp)
1072                     (error "TinyPerl: No binary `%s` for variable `%s' \
1073 Check variable `exec-path'"
1074                            bin
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) "")))
1087       ok)))
1088
1089 ;;; ----------------------------------------------------------------------
1090 ;;;
1091 (defun tinyperl-install-variables-lookup (&optional check verb)
1092   "Set all global lookup variables.
1093
1094 Input:
1095
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.
1099
1100   VERB      Allow verbose messages
1101
1102 References:
1103
1104   `tinyperl-:inc-path'
1105   `tinyperl-:inc-module-list'
1106   `tinyperl-:pod-path'
1107   `tinyperl-:pod-list'"
1108   (interactive)
1109   (flet ((set-maybe (symbol eval-form)
1110                     (when (or (eq 'force check)
1111                               (and check
1112                                    (symbol-value symbol)))
1113                       (tinyperl-verbose-macro 1
1114                                               (message "TinyPerl: Setting up var: %s" symbol))
1115                       (set symbol
1116                            (eval eval-form)))))
1117     (when verb
1118       (tinyperl-verbose-macro 1
1119                               (message "TinyPerl: Setting up variables...")))
1120     (unless (set-maybe
1121              'tinyperl-:inc-path
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))
1126     (unless (set-maybe
1127              'tinyperl-:inc-module-list
1128              '(tinyperl-build-list-of-inc-files
1129                tinyperl-:inc-path
1130                verb))
1131       (error "TinyPerl: Setup failure tinyperl-:inc-module-list"))
1132     (unless (set-maybe
1133              'tinyperl-:pod-path
1134              '(tinyperl-pod-path tinyperl-:perl-bin))
1135       (error "TinyPerl: Setup failure tinyperl-:pod-path"))
1136     (unless (set-maybe
1137              'tinyperl-:pod-list
1138              '(tinyperl-build-pod-files))
1139       (error "TinyPerl: Setup failure tinyperl-:pod-list"))
1140     (when verb
1141       (tinyperl-verbose-macro 1
1142                               (message "TinyPerl: Setting up variables...Done.")))))
1143
1144 ;;; ----------------------------------------------------------------------
1145 ;;;
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))
1149
1150 ;;; ----------------------------------------------------------------------
1151 ;;;
1152 (defun tinyperl-install-1 (&optional force verb)
1153   "Install variables.
1154 You should call `tinyperl-install' or `tinyperl-install-force' instead.
1155
1156 Input:
1157
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)'.
1161
1162   VERB      Allow verbose messaegs."
1163   (let* (stat
1164          ok)
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 ...).
1170     ;;
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))
1175     (if (or force
1176             (null stat))
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:
1181     ;;
1182     ;;  (defconst tinyperl-:perl-bin
1183     ;;     "e:\USR\LOCAL\BIN\PERL\BIN\perl.exe")
1184     ;;
1185     ;;   --> e:USRLOCALBINPERLBINperl.exe  when read from
1186     ;;
1187     (tinyperl-variable-convert)
1188     (when (or force
1189               (null stat))
1190       (tinyperl-save-state nil verb)
1191       (when verb
1192         (tinyperl-verbose-macro 1
1193                                 (message "TinyPerl: Setting up variables...done"))))
1194     (put 'tinyperl-mode
1195          'podchecker
1196          (tinyperl-perl-module-exists-p "Pod::Checker.pm"))
1197
1198     ok)) ;; install end
1199
1200 ;;; ----------------------------------------------------------------------
1201 ;;;
1202 ;;;###autoload
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'.
1206
1207 Input:
1208
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
1212               of using cache."
1213   (interactive "P")
1214   (tinyperl-install-hooks uninstall)
1215   (unless uninstall
1216     (tinyperl-install-1 force 'verb))
1217   (turn-on-tinyperl-mode-all-buffers uninstall)
1218   (ti::add-hooks '(perl-mode-hook
1219                    cperl-mode-hook)
1220                  'turn-on-tinyperl-mode
1221                  uninstall))
1222
1223 ;;; ----------------------------------------------------------------------
1224 ;;;
1225 ;;;###autoload
1226 (defun tinyperl-install-force ()
1227   "Rebuild all global variables. Needed after CPAN module install."
1228   (interactive)
1229   (tinyperl-install nil 'force))
1230
1231 ;;; ----------------------------------------------------------------------
1232 ;;;
1233 ;;;###autoload
1234 (defun tinyperl-uninstall ()
1235   "Uninstall TinyPerl."
1236   (interactive)
1237   (tinyperl-install 'uninstall))
1238
1239 ;;; ----------------------------------------------------------------------
1240 ;;;
1241 (defun tinyperl-cache-file-name ()
1242   "Return Perl version specific cache file.
1243
1244 Don't touch this code unless you know what you're doing.
1245
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:
1250
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
1253
1254   XEmacs .. eh, well, that hasn't been tackled yet. The @INC matrix
1255   would be:
1256
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.
1261
1262 References:
1263
1264   `tinyperl-:cache-file-prefix'.
1265   `tinyperl-:cache-file-postfix'"
1266   (concat (if (stringp tinyperl-:cache-file-prefix)
1267               (concat tinyperl-:cache-file-prefix "-")
1268             "emacs-config")
1269           ;; (if (ti::win32-p) "win32-" "unix-")
1270           (if (ti::emacs-p)
1271               "emacs"
1272             "xemacs")
1273           "-"
1274           (let ((sym (tinyperl-perl-type)))
1275             (if sym
1276                 (symbol-name sym)
1277               (error "TinyPerl: Perl type is not known.")))
1278           (if (stringp tinyperl-:cache-file-postfix)
1279               tinyperl-:cache-file-postfix
1280             "")))
1281
1282 ;;; ----------------------------------------------------------------------
1283 ;;;
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'"
1287   (interactive)
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))))
1293
1294 ;;; ----------------------------------------------------------------------
1295 ;;;
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."
1299   (interactive)
1300   (ti::verb)
1301   (let ((file (tinyperl-cache-file-name)))
1302     (cond
1303      (load
1304       (when (file-exists-p file)
1305         (load file)
1306         (when verb
1307           (tinyperl-verbose-macro 1
1308                                   (message "TinyPerl: state restored [%s]" file)))
1309         t))
1310      (t
1311       (ti::write-file-variable-state
1312        file
1313        "TinyPerl.el saved state"
1314        '(tinyperl-:inc-path
1315          tinyperl-:inc-module-list
1316          tinyperl-:pod-path
1317          tinyperl-:pod-list
1318          tinyperl-:perl-bin
1319          tinyperl-:perldoc-bin
1320          tinyperl-:pod2text-bin))
1321       (when verb
1322         (tinyperl-verbose-macro 1
1323                                 (message "TinyPerl: state saved [%s]" file)))
1324       t))))
1325
1326 ;;; ----------------------------------------------------------------------
1327 ;;;
1328 ;;;###autoload
1329 (defun turn-on-tinyperl-mode-all-buffers (&optional off)
1330   "Turn function `tinyperl-mode' on in every perl buffer. Optionally turn OFF."
1331   (interactive "P")
1332   (ti::dolist-buffer-list
1333    (or
1334     (string-match "perl" (downcase (symbol-name major-mode)))
1335     (string-match "\\.pl$" (buffer-name))
1336     (string-match "code-perl" (or (ti::id-info) "")))
1337    'tmp-buffers-too
1338    nil
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
1342      (if off
1343          (unless (null mode)
1344            (ti::funcall 'turn-off-tinyperl-mode))
1345        (unless mode
1346          (ti::funcall 'turn-on-tinyperl-mode))))))
1347
1348 ;;; ----------------------------------------------------------------------
1349 ;;;
1350 (defun tinyperl-install-hooks (&optional remove verb)
1351   "Install default hooks or REMOVE. VERB."
1352   (interactive "P")
1353   (ti::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)
1358                  remove)
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)
1364                  remove)
1365   (ti::add-hooks 'tinyperl-:pod-view-mode-hook
1366                  'tinyperl-pod-font-lock
1367                  remove)
1368   (ti::add-hooks 'tinyperl-:pod-write-mode-hook
1369                  'tinyperl-pod-font-lock
1370                  remove)
1371   (ti::add-hooks '(perl-mode-hook
1372                    cperl-mode-hook)
1373                  'turn-on-tinyperl-mode
1374                  remove)
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
1379                  remove)
1380   (ti::add-hooks 'tinyperl-:pod-write-mode-define-keys-hook
1381                  'tinyperl-pod-write-mode-define-keys
1382                  remove)
1383   (ti::add-hooks 'write-file-hooks
1384                  'tinyperl-version-stamp
1385                  remove)
1386   (when verb
1387     (tinyperl-verbose-macro 2
1388                             (message "TinyPerl: Hooks installed"))))
1389
1390 ;;; ----------------------------------------------------------------------
1391 ;;;
1392 (defun tinyperl-copyright ()
1393   "Insert copyright string fro Perl program."
1394   (interactive)
1395   (insert "Copyright (C) " (format-time-string "%Y " (current-time))
1396           (or (user-full-name)
1397               (read-string "You name: "))
1398           ".
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."))
1402
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)
1407
1408 (eval-and-compile
1409
1410   (ti::macrof-minor-mode-wizard
1411    "tinyperl-" " pod" "\C-c'" "Tperl" 'TinyPerl "tinyperl-:" ;1-6
1412
1413    "Additional commands to fetch perl module and perl manpage information
1414
1415 For complete on-line documentation, which is generated from the
1416 source file itself, run command `tinyperl-version`
1417
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:
1422
1423   ;;  Take global prefix key C-c p  for perl pod view commands
1424
1425   (global-set-key \"\C-cpp\" 'tinyperl-pod-by-manpage)
1426   (global-set-key \"\C-cpP\" 'tinyperl-pod-by-module)
1427
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'
1430
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.
1437
1438 Mode description:
1439
1440 \\{tinyperl-:mode-map}"
1441
1442    "TinyPerl"
1443
1444    nil
1445
1446    "Perl extras (pod)"
1447
1448    (list
1449     tinyperl-:mode-easymenu-name
1450
1451     (list
1452      "Skeleton"
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]
1459     "----"
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]
1464     ["Pod syntax check"
1465      tinyperl-pod-podchecker
1466      (get 'tinyperl-mode  'podchecker)]
1467
1468     ;;   ["Pod switch to buffer"               tinyperl-pod-jump          t]
1469     ["Pod write mode"                     tinyperl-pod-write-mode    t]
1470     "----"
1471     ["Pod2text on file"                   tinyperl-pod-find-file     t]
1472     ["Pod2text on current buffer" tinyperl-pod-find-file-this-buffer t]
1473     "----"
1474     ["Module source find-file"            tinyperl-module-find-file  t]
1475     ["Module generate stubs"              tinyperl-selfstubber-stubs t]
1476     "----"
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]
1480     "----"
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])
1485
1486    (progn
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))))
1517
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)
1521
1522 (eval-and-compile
1523
1524   (ti::macrof-minor-mode-wizard
1525    "tinyperl-pod-view-" " POD" "\C-c'" "POD" 'TinyPerl "tinyperl-:pod-view-"
1526
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.
1530
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
1533 movement controls.
1534
1535 Mode description:
1536
1537 \\{tinyperl-:pod-view-mode-map}"
1538
1539    "TinyPerl Pod View"
1540
1541    nil
1542
1543    "POD view mode."
1544
1545    (list
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]
1555     "----"
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)
1563     "----"
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])
1567    (progn
1568      ;;   headings
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)
1580      ;; Sub-headings
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))))
1586
1587 ;;; ----------------------------------------------------------------------
1588 ;;;
1589 (defun tinyperl-pod-view-backward ()
1590   "Go to one topic backward."
1591   (interactive)
1592   ;;    NAME
1593   ;;        Net::FTP - FTP Client class
1594   (or (re-search-backward "^NAME[\n\r]" nil t) (ti::pmin)))
1595
1596 ;;; ----------------------------------------------------------------------
1597 ;;;
1598 (defun  tinyperl-pod-view-pageup ()
1599   "See `tinyperl-:key-pageup-control'."
1600   (interactive)
1601   (if (eq tinyperl-:key-pageup-control 'heading)
1602       (tinyperl-pod-view-heading-backward)
1603     (scroll-down)))
1604
1605 ;;; ----------------------------------------------------------------------
1606 ;;;
1607 (defun  tinyperl-pod-view-pagedown ()
1608   "See `tinyperl-:key-pageup-control'."
1609   (interactive)
1610   (if (eq tinyperl-:key-pageup-control 'heading)
1611       (tinyperl-pod-view-heading-forward)
1612     (scroll-up)))
1613
1614 ;;; ----------------------------------------------------------------------
1615 ;;;
1616 (defun tinyperl-pod-view-forward ()
1617   "Go to one topic backward."
1618   (interactive)
1619   (end-of-line)
1620   (or (and (re-search-forward "^NAME[\n\r]" nil t)
1621            (forward-line -1))
1622       (ti::pmax)))
1623
1624 ;;; ----------------------------------------------------------------------
1625 ;;;
1626 (defun tinyperl-pod-view-heading-backward (&optional regexp)
1627   "Go to one heading backward. Optionally use REGEXP."
1628   (interactive)
1629   (let* (case-fold-search)
1630     (or (and (re-search-backward (or regexp "^\\(  \\)?[A-Z]") nil t)
1631              (prog1 1 t
1632                     (beginning-of-line)
1633                     (skip-chars-forward " \t")))
1634         (ti::pmin))))
1635
1636 ;;; ----------------------------------------------------------------------
1637 ;;;
1638 (defun tinyperl-pod-view-heading-forward (&optional regexp)
1639   "Go to one heading forward. Optionally use REGEXP."
1640   (interactive)
1641   (end-of-line)
1642   (let* (case-fold-search)
1643     (or (and (re-search-forward (or regexp "^\\(  \\)?[A-Z]") nil t)
1644              (prog1 t
1645                (beginning-of-line)
1646                (skip-chars-forward " \t")))
1647         (ti::pmax))))
1648
1649 ;;; ----------------------------------------------------------------------
1650 ;;;
1651 (defun tinyperl-pod-view-heading-backward2 ()
1652   "Go to one sub heading backward."
1653   (interactive)
1654   (tinyperl-pod-view-heading-backward
1655    "\\([ \t][\r\n]\\|[\r\n][\r\n]\\)\\(  \\|    \\)?[^ \t\n\r]"))
1656
1657 ;;; ----------------------------------------------------------------------
1658 ;;;
1659 (defun tinyperl-pod-view-heading-forward2 ()
1660   "Go to one sub heading backward."
1661   (interactive)
1662   (tinyperl-pod-view-heading-forward
1663    "\\([ \t][\r\n]\\|[\r\n][\r\n]\\)\\(  \\|    \\)?[^ \t\n\r]"))
1664
1665 ;;}}}
1666 ;;{{{ POD write mode
1667
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)
1671
1672 (eval-and-compile
1673
1674   (ti::macrof-minor-mode-wizard
1675    "tinyperl-pod-write-" " PODw" "\C-c." "PODw" 'TinyPerl "tinyperl-:pod-write-"
1676
1677    "Minor mode to thelp writing POD in place.
1678
1679 Mode description:
1680
1681 \\{tinyperl-:pod-write-mode-map}"
1682
1683    "TinyPerl Pod Write"
1684
1685    nil
1686
1687    "POD Write mode."
1688
1689    (list
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]
1697     "----"
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]
1704     "----"
1705     ["Mode help"                  tinyperl-pod-write-mode-help                t]
1706     ["Mode off"                   tinyperl-pod-write-mode                     t])
1707    (progn
1708      ;;   headings
1709      (define-key map [(prior)]            'tinyperl-pod-write-heading-backward)
1710      (define-key map [(next)]             'tinyperl-pod-write-heading-forward)
1711      ;; Sub-headings
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))))
1727
1728 ;;; ----------------------------------------------------------------------
1729 ;;;
1730 (defun tinyperl-pod-write-heading-backward  ()
1731   "Go to previous POD heading"
1732   (interactive)
1733   (tinyperl-pod-view-heading-backward "^=head"))
1734
1735 ;;; ----------------------------------------------------------------------
1736 ;;;
1737 (defun tinyperl-pod-write-heading-forward  ()
1738   "Go to next POD heading"
1739   (interactive)
1740   (tinyperl-pod-view-heading-forward "^=head"))
1741
1742 ;;; ----------------------------------------------------------------------
1743 ;;;
1744 (defun tinyperl-pod-write-token-backward  ()
1745   "Go to previous POD token"
1746   (interactive)
1747   (tinyperl-pod-view-heading-backward "^="))
1748
1749 ;;; ----------------------------------------------------------------------
1750 ;;;
1751 (defun tinyperl-pod-write-token-forward  ()
1752   "Go to next POD token "
1753   (interactive)
1754   (tinyperl-pod-view-heading-forward "^="))
1755
1756 ;;  Tell that these function are here
1757
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)
1764
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
1770   ;;  defined.
1771   ;;
1772   ;;  At that point skeleton.el is needed and loaded.
1773   ;;  These STUBS will at the end call the real, defined, function.
1774   (let (def)
1775     (mapcar
1776      (function
1777       (lambda (x)
1778         (let ((sym  (intern (format "tinyperl-pod-write-skeleton-%s"
1779                                     (symbol-name x)))))
1780           (setq def
1781                 (` (defun (, sym) ()
1782                      "Forward declaration wrapper. Will define real function."
1783                      (interactive)
1784                      (tinyperl-skeleton-initialize)
1785                      (funcall (quote (, sym))))))
1786           (eval def))))
1787      '(item
1788        script-manpage
1789        script-function
1790        module-header
1791        module-footer
1792        module-function ))))
1793
1794 (defun tinyperl-skeleton-initialize () ;;  #### SKELETON-BEGIN
1795   "Skeleton setup."
1796
1797 ;;; ----------------------------------------------------------------------
1798 ;;;
1799   (define-skeleton tinyperl-pod-write-skeleton-item
1800     "Insert =item skeleton"
1801     (read-string "Item: " "*")
1802     "
1803 =item " str "
1804
1805 ")
1806
1807 ;;; ----------------------------------------------------------------------
1808 ;;;
1809   (define-skeleton tinyperl-pod-write-skeleton-script-manpage
1810     "Script: Insert Perl Script's manpage POD."
1811     (read-string "Program: " (buffer-name))
1812     "=pod
1813
1814 =head1 NAME
1815
1816 " str " - " (read-string "One Line description: ")
1817
1818     "
1819
1820 =head1 README
1821
1822 <short overall description here. This section is ripped by CPAN>
1823
1824 =head1 SYNOPSIS
1825
1826     <program call conventions>
1827
1828     program B<-V>...
1829
1830 =head1 OPTIONS
1831
1832 =head2 Gneneral options
1833
1834 =over 4
1835
1836 =item B<--option-name>
1837
1838 =back
1839
1840 =head2 Miscellaneous options
1841
1842 =over 4
1843
1844 =item B<--debug LEVEL>
1845
1846 Turn on debug with positive LEVEL number. Zero means no debug.
1847
1848 =item B<--help>
1849
1850 Print help
1851
1852 =item B<--test>
1853
1854 Run in test mode, do not actually do anything.
1855
1856 =item B<--verbose>
1857
1858 Print informational messages.
1859
1860 =item B<--Version>
1861
1862 Print contact and version information
1863
1864 =back
1865
1866 =head1 DESCRIPTION
1867
1868 <program description>
1869
1870 =head1 EXAMPLES
1871
1872 <example calls for the program in different situations>
1873
1874 =head1 TROUBLESHOOTING
1875
1876 <what to check in case of error or weird behavior>
1877
1878 =head1 ENVIRONMENT
1879
1880 <any environment variable settings>
1881
1882 =head1 FILES
1883
1884 <what files program generates uses>
1885
1886 =head1 SEE ALSO
1887
1888 <references to other programs e.g. ps(1)>
1889
1890 =head1 STANDARDS
1891
1892 <RFCs, ANSI/ISO, www.w3c.org that are related>
1893
1894 =head1 BUGS
1895
1896 <known limitations>
1897
1898 =head1 AVAILABILITY
1899
1900 "
1901
1902     (or tinyperl-:skeleton-script-ftp-url
1903         (skeleton-read "Availabillity: " "<URL Where to get the program>"))
1904
1905     "
1906
1907 =head1 SCRIPT CATEGORIES
1908
1909 CPAN/Administrative
1910
1911 =head1 PREREQUISITES
1912
1913 <what CPAN modules are needed to run this program>
1914
1915 =head1 COREQUISITES
1916
1917 <what CPAN modules are needed to run this program>
1918
1919 =head1 OSNAMES
1920
1921 C<any>
1922
1923 =head1 VERSION
1924
1925 $\Id$
1926
1927 =head1 AUTHOR
1928
1929 "
1930
1931     (funcall tinyperl-:copyright-function)
1932
1933     "
1934
1935 =cut
1936 ")
1937
1938 ;;; ----------------------------------------------------------------------
1939 ;;;
1940   (define-skeleton tinyperl-pod-write-skeleton-script-function
1941     "Script: Insert Function banner."
1942     nil
1943     "\
1944 # ****************************************************************************
1945 #
1946 #   DESCRIPTION
1947 #
1948 #
1949 #
1950 #   INPUT PARAMETERS
1951 #
1952 #
1953 #
1954 #   RETURN VALUES
1955 #
1956 #
1957 #
1958 # ****************************************************************************
1959 ")
1960
1961 ;;; ----------------------------------------------------------------------
1962 ;;;
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'."
1966     nil
1967     "\
1968 # ****************************************************************************
1969 #
1970 #   POD HEADER
1971 #
1972 # ****************************************************************************
1973
1974 =head1 NAME
1975
1976 " (buffer-name) " - One line Module descriptions
1977
1978 =head1 REVISION
1979
1980 $\Id$
1981
1982 =head1 SYNOPSIS
1983
1984     use " (replace-regexp-in-string "\\.pm" "" (buffer-name))
1985     "; # Import EXPORT_OK
1986     use "
1987     (replace-regexp-in-string "\\.pm" "" (buffer-name))
1988     " qw( :ALL ); # Import everything
1989
1990 =head1 DESCRIPTION
1991
1992 =head1 EXPORTABLE VARIABLES
1993
1994 If there is no special marking for the variable, it is
1995 exported when you call `use'. The rags next to variables mean:
1996
1997     [ok]    = variable is exported via list EXPORT_OK
1998     [tag]   = variable is exported via :TAG
1999
2000 =head2 $ABC_REGEXP
2001
2002 <description>
2003
2004 =head2 %ABC_HASH [ok]
2005
2006 <description>
2007
2008 =head2 $debug [ok]
2009
2010 Integer. If positive, activate debug with LEVEL.
2011
2012 <description>
2013
2014 =head1 INTERFACE FUNCTIONS
2015
2016 =for comment After this the Puclic interface functions are introduced
2017 =for comment you close the blockquote by inserting POD footer
2018
2019 =for html
2020 <BLOCKQUOTE>
2021
2022 =cut
2023
2024 ")
2025
2026 ;;; ----------------------------------------------------------------------
2027 ;;;
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'."
2031     nil
2032     "\
2033 # ****************************************************************************
2034 #
2035 #   POD FOOTER
2036 #
2037 # ****************************************************************************
2038
2039 =pod
2040
2041 =for html
2042 </BLOCKQUOTE>
2043
2044 =head1 KNOWN BUGS
2045
2046 <Limitations. How to debug problems>
2047
2048 =head1 AVAILABILITY
2049
2050 <release or where to get latest, http, ftp page>
2051
2052 =head1 AUTHOR
2053
2054 "
2055
2056     (funcall tinyperl-:copyright-function)
2057
2058     "
2059
2060 =cut
2061 ")
2062
2063 ;;; ----------------------------------------------------------------------
2064 ;;;
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
2068 functions in place.
2069
2070 Hee is one suggestion ofr Module.pm POD layout
2071
2072             P O D  H E A D E R
2073             NAME
2074             REVISION
2075             SYNOPSIS
2076             DESCRIPTION
2077             EXPORTABLE VARIABLES
2078             EXAMPLES
2079
2080             #   module interface is written next
2081
2082             use strict;
2083
2084             BEBGIN
2085             {
2086                 EXPORT          # The export interface
2087                 EXPORT_OK
2088             }
2089
2090             Define exported globals
2091
2092             Define private variables
2093
2094             P O D   I N T E R F A C E   S T A R T
2095
2096             P O D  P U B L I C for public functions or methods
2097             sub ...
2098
2099             P O D  P U B L I C for public functions or methods
2100             sub ...
2101
2102             NORMAL banner of private function
2103             sub ...
2104
2105             NORMAL banner of private function
2106             sub ...
2107
2108             P O D   F O O T E R
2109             KNOWN BUGS
2110             AVAILABILITY
2111             AUTHOR
2112
2113             1;
2114             __END__
2115
2116 "
2117     nil
2118     "
2119 =pod
2120
2121 =over 4
2122
2123 =head2 Function ()
2124
2125 =item Description
2126
2127 =item arg1:
2128
2129 =item arg2:
2130
2131 =item Return values
2132
2133 =back
2134
2135 =cut")
2136
2137   ) ;;  #### SKELETON-BEGIN
2138
2139 ;;}}}
2140 ;;{{{ Perl Path functions
2141
2142 ;;; ----------------------------------------------------------------------
2143 ;;; (tinyperl-inc-split-win32-path "C:\\Program files\\this  c:\\temp")
2144 ;;;
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\")
2148 -->
2149 '(\"C:\\Program files\\this\" \"c:\\temp\")"
2150   (let* (locations
2151          beg
2152          end
2153          ret
2154          str)
2155     (with-temp-buffer
2156       (insert string)
2157       (ti::pmin)
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)
2166             (push str ret))))
2167       (nreverse ret))))
2168
2169 ;;; ----------------------------------------------------------------------
2170 ;;;
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
2178          list)
2179     (when inc
2180       (cond
2181        ((and (ti::win32-p)
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))))
2187        ((and (ti::win32-p)
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
2193         (let (win32-list
2194               cygwin-list)
2195           (dolist (path list)
2196             (cond
2197              ((string-match "^//\\|^[a-z]:" path)
2198               (push path win32-list))
2199              (t
2200               (push path cygwin-list))))
2201           (when cygwin-list
2202             (setq cygwin-list (mapcar 'w32-cygwin-path-to-dos cygwin-list)))
2203           (setq list (append cygwin-list win32-list))))
2204        ((and (ti::win32-p)
2205              (eq perl-type 'win32-activestate)
2206              (ti::emacs-type-cygwin-p))
2207         (error (concat
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)))
2215        (t
2216         (setq list (split-string inc))))
2217       (setq list (delete "." list))
2218       (tinyperl-debug fid "perl" perl-type "ret" list)
2219       list)))
2220
2221 ;;; ----------------------------------------------------------------------
2222 ;;;
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."
2226
2227   ;;  Now interesting part: If Emacs in Win32-native and user uses
2228   ;;  Cygwin-perl, then the situation is as follows:
2229   ;;
2230   ;;      PERL5LIB paths refer to cygwin, like /usr/share/site-perl/CPAN
2231   ;;
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
2234   ;;
2235   ;;     CYGWIN-ROOT/path   or CYGWIN-MOUNT-POINT/path
2236   ;;
2237   ;;  #todo: XEmacs is different game, it can be built as Cygwin native
2238   ;;  #todo: How to check if running Cygwin or Win32 XEmacs ?
2239
2240   (let* ((perl-type (tinyperl-perl-type)))
2241     (cond
2242      ((and (ti::emacs-p)
2243            ;;  #todo: if Emacs is built as native cygwin application,
2244            ;;  this fails.
2245            (eq perl-type 'win32-cygwin))
2246       (let (new-list)
2247         (dolist (path list)
2248           (cond
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))
2253            (t
2254             ;;  the file-directory-p is checked elswhere.
2255             ;;  Just return pure paths
2256             (push path new-list))))
2257         new-list))
2258      (t
2259       list))))
2260
2261 ;;; ----------------------------------------------------------------------
2262 ;;;
2263 (defun tinyperl-inc-path-external-perl (perl)
2264   "Calls an external PERL process to read @INC.
2265
2266 References:
2267
2268   `tinyperl-:inc-path-switches' is included in call."
2269   (with-temp-buffer
2270     (apply 'call-process
2271            perl
2272            nil
2273            (current-buffer)
2274            nil
2275            (append tinyperl-:inc-path-switches
2276                    '("-e"
2277                      ;; "print 11"
2278                      "print(qq,@INC,)")))
2279     (let ((ret (buffer-string)))
2280       (tinyperl-debug "tinyperl-inc-path-external-perl: " ret)
2281       ret)))
2282
2283 ;;; ----------------------------------------------------------------------
2284 ;;; (tinyperl-inc-path tinyperl-:perl-bin)
2285 ;;;
2286 (defun tinyperl-inc-path (&optional perl)
2287   "Return @INC and and var PERL5LIB libs for PERL which defaults to `perl'.
2288
2289 References:
2290  `tinyperl-:inc-path-switches'"
2291   (let* ((fid "tinyperl-inc-path")
2292          (path (or perl
2293                    (executable-find  "perl")))
2294          ;;    ask from perl where the paths are.
2295          (result (and path
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
2300          (list (when path
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
2307          (path5 (and list
2308                      lib
2309                      (split-string
2310                       lib
2311                       (if (or (string-match ";"  lib) ;; was (if (ti::win32-p)..
2312                               (string-match "[a-z]:[\\/]" lib))
2313                           ";"
2314                         ":"))))
2315          ret
2316          seen)
2317     (tinyperl-debug fid "path" path "result" result "lib" lib "path5" path5)
2318     (when (and result
2319                (string-match "warning\\|error\\|fatal" result))
2320       (error "TinyPerl: Reading @INC error %s" result))
2321     (if path5
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))
2327     (dolist (x list)
2328       (when (stringp x)
2329         (unless (member x seen) ;; Filter out duplicates
2330           (push x seen)
2331           (if (file-directory-p x)
2332               (push x ret)
2333             ;;  Record to message, so that possible errors can be
2334             ;;  traced.
2335             (tinyperl-verbose-macro 3
2336                                     (message "Tinyperl: invalid @INC dir %s. Ignored." x))))))
2337     (tinyperl-debug fid "result [2]" result)
2338     (when (and result
2339                (null ret))
2340       (error
2341        (format
2342         (concat "TinyPerl: Can't parse @INC. Please check"
2343                 " tinyperl-:perl-bin = %s"
2344                 " result: %s"
2345                 " path5: %s")
2346         (prin1-to-string tinyperl-:perl-bin)
2347         (prin1-to-string result)
2348         (prin1-to-string path5))))
2349     (tinyperl-debug fid "ret" ret)
2350     ret))
2351
2352 ;;; ----------------------------------------------------------------------
2353 ;;;
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")))
2358          (path
2359           (with-temp-buffer
2360             (call-process  perl
2361                            nil
2362                            (current-buffer)
2363                            nil
2364                            "-MConfig"
2365                            "-e"
2366                            "print $Config{privlib}")
2367             (buffer-string))))
2368     (when (or (ti::nil-p path)
2369               (and (stringp 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"
2374              path perl))
2375     ;;  Win32 specific Cygwin support
2376     (let ((path-list
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.
2386     (let (correct
2387           try)
2388       (dolist (pod '("pod/" "pods/"))
2389         (setq try (concat (file-name-as-directory path) pod))
2390         (when (and (file-directory-p try)
2391                    (directory-files
2392                     try
2393                     nil
2394                     "\\.pod$"))
2395           (return (setq correct try))))
2396       (unless correct
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))))
2400
2401 ;;; ----------------------------------------------------------------------
2402 ;;;
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")))
2407          files
2408          ret)
2409     (setq files (ti::directory-files path "\\.pod"))
2410     (dolist (file files)
2411       (push (cons file (ti::file-name-forward-slashes path)) ret))
2412     ret))
2413
2414 ;;; ----------------------------------------------------------------------
2415 ;;; #todo: This should be rewritten as recursive function
2416 ;;;
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'
2420
2421 Return:
2422
2423   '((package.pm . path) (package::package.pm . path) ..)"
2424   (let* ((INC (or search-list
2425                   (error "TinyPerl: No SEARCH-LIST")))
2426          files
2427          dirs
2428          dirs2
2429          dirs3
2430          package
2431          ret)
2432     (flet ((my-add
2433             (file pfx path)
2434             ;;  As long as the name of the .pl file is unique (not yet
2435             ;;  added), store without leading prefix directories.
2436             ;;
2437             (if (and (string-match "\\.pl" file)
2438                      (not (assoc file ret)))
2439                 (push (cons file path) ret)
2440               (push (cons
2441                      (if pfx
2442                          (concat (file-name-nondirectory pfx) "::" file)
2443                        file)
2444                      path)
2445                     ret))))
2446       (ti::verb)
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...
2450       ;;
2451       ;;  Font::Metrics::Courier.pm
2452       ;;  HTTP::Request::Common.pm
2453       (dolist (path INC)
2454         (when verb
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
2461                     path "." 'absolute
2462                     '(file-directory-p arg)
2463                     '(string-match "\\.\\.?$" arg)))
2464         (dolist (dir dirs)
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
2470                        dir "." 'absolute
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
2481                          dir1 "." 'absolute
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))))))
2492       ret)))
2493
2494 ;;}}}
2495 ;;{{{ POD lowlevel functions
2496
2497 ;;; ----------------------------------------------------------------------
2498 ;;;
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")
2504         (error "\
2505 TinyPerl: Pod::Checker.pm is not known to this Perl version. @INC trouble?"))
2506     (or buffer
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
2512         (ti::pmax)
2513         (run-hooks 'tinyperl-:podchecker-before-hook)
2514         (call-process tinyperl-:perl-bin
2515                       nil
2516                       buffer
2517                       nil
2518                       "-MPod::Checker"
2519                       "-e"
2520                       "podchecker shift, undef, -warnings => q(on)"
2521                       (expand-file-name file))
2522         (run-hooks 'tinyperl-:podchecker-after-hook)))
2523     (when t
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"
2529                                            shell-file-name))
2530                         "\""
2531                       "'"))
2532              (cmd (concat
2533                    tinyperl-:perl-bin
2534                    " -MPod::Checker"
2535                    " -e"
2536                    " "
2537                    quote
2538                    "podchecker shift, undef, -warnings , q(on)"
2539                    quote
2540                    " "
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
2545         (push
2546          '(".*[ \t]+line[ \t]+\\([0-9]+\\)[ \t]+in[ \t]+file[ \t]+\\(.*\\)"
2547            2 1)
2548          compilation-error-regexp-alist)
2549         (tinyperl-debug fid "cmd" cmd)
2550         (compile-internal cmd
2551                           "No more lines." ;; error-message
2552                           nil              ;; name-of-mode
2553                           nil              ;; parser
2554                           nil)))           ;; error-regexp-alist
2555     (tinyperl-debug fid "buffer" buffer)
2556     buffer))
2557
2558 ;;; ----------------------------------------------------------------------
2559 ;;; (tinyperl-pod2text (tinyperl-pod-manpage-to-file "perlfunc.pod"))
2560 ;;;
2561 (defun tinyperl-pod2text (file &optional buffer)
2562   "Run pod on FILE and put output to BUFFER."
2563   (let ((fid "tinyperl-pod2text"))
2564     (or buffer
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)
2573       (ti::pmax)
2574       ;; Move point to the end of visible window
2575       ;; #todo: was I thinking of something here ?...
2576       (when nil                         ;disabled
2577         (let* ((win (get-buffer-window (current-buffer) t)))
2578           (when win
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
2588                       nil
2589                       buffer
2590                       nil
2591                       "-MPod::Text"
2592                       "-e"
2593                       "pod2text shift"
2594                       ;;  Cygwin's groff(1) was changed to bash
2595                       ;;  shell script which cannot be used
2596                       ;;  from NTEmacs
2597 ;;;#todo
2598 ;;;                      (if nt-cygwin
2599 ;;;                          "-n")
2600 ;;;                      (if nt-cygwin
2601 ;;;                          "groff")
2602                       file)
2603         (when (eq (point) point)
2604           (message
2605            (concat "TinyPerl: pod2text was empty. "
2606                    "Please check Perl environment."
2607                    "It may be broken: try running `perldoc perl'."))))
2608       (ti::pmin)
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)
2612       buffer)))
2613
2614 ;;; ----------------------------------------------------------------------
2615 ;;;
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")))))
2621     (when elt
2622       (concat (cdr elt) (car elt)))))
2623
2624 ;;; ----------------------------------------------------------------------
2625 ;;;
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:"))
2629         case-fold-search)
2630     (when (and (stringp word)
2631                (or (string-match
2632                     ;;  English.pm
2633                     ;;  use English;
2634                     (concat
2635                      "^[A-Z]\\([a-z]+\\|[A-Z]+\\)$"
2636                      ;; use Getopt::Long;
2637                      ;; use HTTP::Request;
2638                      ;; LWP::UserAgent;
2639                      "\\|^[A-Z]\\([a-z]+\\|[A-Z]+\\)"
2640                      "\\(::[A-Z]\\([a-z]+[A-Za-z]+\\|[A-Z]+\\)\\)+$")
2641                     word)))
2642       (setq word (match-string 0 word))
2643       (when (not (string-match "\\.pm$" word))
2644         (setq word (concat word ".pm")))
2645       word)))
2646
2647 ;;; ----------------------------------------------------------------------
2648 ;;;
2649 (defun tinyperl-ask-module (&optional msg)
2650   "Ask with MSG a module."
2651   (let ((word (tinyperl-read-word-module)))
2652     (completing-read
2653      (or msg "Module: ")
2654      (or tinyperl-:inc-module-list
2655          (error "TinyPerl: No tinyperl-:inc-module-list"))
2656      nil
2657      (not 'require-match)
2658      (if word
2659          ;;  Put point to the beginning so that user can hit C-k to kill
2660          ;;  possibly unwanted word.
2661          (cons word 0)))))
2662
2663 ;;; ----------------------------------------------------------------------
2664 ;;;
2665 (defun tinyperl-locate-library  (module &optional no-guess)
2666   "Check where is MODULE. A .pl and .pm suffixes is added if needed.
2667 Input:
2668
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.
2673
2674 Return:
2675
2676  '(module . path)"
2677   (if no-guess
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))))
2682
2683 ;;; ----------------------------------------------------------------------
2684 ;;;
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'.
2688
2689 Return:
2690   buffer pointer"
2691
2692   (find-file-noselect
2693    (format "%s/%s"
2694            (cdr elt)
2695            ;; Getopt::Long.pm --> Long.pm
2696            (replace-regexp-in-string  "^.*:" "" (car elt)))))
2697
2698 ;;; ----------------------------------------------------------------------
2699 ;;;
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))
2704         case-fold-search)
2705     (when (and word
2706                (string-match "^perl." word))
2707       word)))
2708
2709 ;;; ----------------------------------------------------------------------
2710 ;;;
2711 (defun tinyperl-pod-ask-manpage ()
2712   "Ask pod page and return absolute path of POD manpage."
2713   (tinyperl-pod-manpage-to-file
2714    (completing-read
2715     "View pod manpage: "
2716     tinyperl-:pod-list
2717     (not 'predicate)
2718     'match-it
2719     (let ((word (tinyperl-manpage-at-point)))
2720       (when word
2721         (concat word ".pod"))))))
2722
2723 ;;; ----------------------------------------------------------------------
2724 ;;;
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'
2728 returns non-nil."
2729   (interactive)
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.
2734     ;;
2735     (turn-on-font-lock-mode)
2736     (setq font-lock-keywords tinyperl-:pod-font-lock-keywords)
2737     (font-lock-fontify-buffer)
2738     nil))
2739
2740 ;;; ----------------------------------------------------------------------
2741 ;;;
2742 (defun tinyperl-pod-buffer-name (module)
2743   "Make POD buffer name for perl module like Â´English'.
2744
2745 Rerefences:
2746
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 "*"))))
2753
2754 ;;; ----------------------------------------------------------------------
2755 ;;;
2756 (defun tinyperl-pod-re-search (regexp &optional buffer)
2757   "Check BUFFER for REGEXP and return (buffer . point) or nil."
2758   (or buffer
2759       (setq buffer (current-buffer)))
2760   (when (buffer-live-p buffer)
2761     (with-current-buffer buffer
2762       (save-excursion
2763         (ti::pmin)
2764         (if (re-search-forward regexp nil t)
2765             (cons (current-buffer) (point)))))))
2766
2767 ;;; ----------------------------------------------------------------------
2768 ;;;
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)))
2772     (when elt
2773       (pop-to-buffer (car elt))
2774       (goto-char (cdr elt)))))
2775
2776 ;;}}}
2777 ;;{{{ POD interactive
2778
2779 ;;; ----------------------------------------------------------------------
2780 ;;;
2781 ;;;###autoload
2782 (defun tinyperl-pod-kill-buffers ()
2783   "Kill all temporary POD buffers."
2784   (interactive
2785    (progn
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)))))
2794
2795 ;;; ----------------------------------------------------------------------
2796 ;;;
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
2802       bin
2803     (cons tinyperl-:perl-bin bin)))
2804
2805 ;;; ----------------------------------------------------------------------
2806 ;;;
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
2814   (cond
2815    ((not (ti::win32-p))
2816     (apply 'call-process
2817            tinyperl-:perldoc-bin
2818            nil
2819            buffer
2820            nil
2821            arg-list))
2822    (t
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.
2829                             "perldoc"
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"
2837                               (car call-type)
2838                               (cdr call-type)
2839                               args))
2840           (setq cmd (format "%s %s" cmd args)))
2841         (ti::process-perl-process-environment-macro
2842             perl-type
2843           ;;  At least shell command works, this a bit more expensive
2844           (let ((out (shell-command-to-string cmd)))
2845             (if (stringp out)
2846                 (insert out))))))))
2847   buffer)
2848
2849 ;;; ----------------------------------------------------------------------
2850 ;;;
2851 ;;;###autoload
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.
2856
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.
2859
2860 Input:
2861
2862   STRING    Seach string
2863   FORCE     Force calling shell although answer cached
2864   VERB      flag, Allow verbose messages
2865
2866 References:
2867
2868   `tinyperl-:perldoc-hook'"
2869   (interactive
2870    (list
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))
2875          (cmd    (format
2876                   "%s -f %s"
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.
2881                       "perldoc"
2882                     tinyperl-:perldoc-bin)
2883                   string
2884                   ""))
2885          run
2886          win)
2887     (ti::verb)
2888     (when (or force
2889               (and buffer
2890                    (with-current-buffer buffer
2891                      (ti::buffer-empty-p)))
2892               (not (stringp last))      ;Show previous result
2893               (not (string= last string)))
2894       (setq run t)
2895       (get-buffer-create buffer)
2896       (with-current-buffer buffer
2897         (setq buffer-read-only nil)
2898         (erase-buffer))
2899       (when verb
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
2909         (ti::pmin)
2910         (when (or (looking-at "^No documentation.*for.*function\\|Can't open")
2911                   (ti::buffer-empty-p))
2912           (erase-buffer)
2913           (when verb
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
2919                             string))
2920           (when verb
2921             (tinyperl-verbose-macro 2
2922                                     (message "TinyPerl: No matches. Trying without -f ...Done.")))))
2923       (when verb
2924         (tinyperl-verbose-macro 2
2925                                 (message "TinyPerl: Running %s. Done." cmd))))
2926     (cond
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)))
2931      (t
2932       (display-buffer buffer)))
2933     (when run
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.
2939     (if string
2940         (put 'tinyperl-perldoc 'string string))))
2941
2942 ;;; ----------------------------------------------------------------------
2943 ;;;
2944 ;;;###autoload
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))
2949
2950 ;;; ----------------------------------------------------------------------
2951 ;;;
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)))
2957     (concat
2958      ;;NAME
2959      ;;    Tie::Hash, Tie::StdHash, Tie::ExtraHash - base class definitions for
2960      "^NAME[ \t]*\\(\r\n\\|\n\\)"
2961      "[ \t]+.*"
2962      name
2963      "\\|"
2964      ;;   use Tie::Hash;
2965      ;;   require Tie::Hash;
2966      "^[ \t]+\\(use +\\|require +\\) *"
2967      name
2968      " *;")))
2969
2970 ;;; ----------------------------------------------------------------------
2971 ;;;
2972 ;;;###autoload
2973 (defun tinyperl-pod-by-module (module &optional mode)
2974   "Show pod manual page for MODULE or load MODULE.
2975
2976 Input:
2977
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."
2981   (interactive
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))
2988          file)
2989     (cond
2990      ;; ................................................. existing POD ...
2991      ((and (null mode)
2992            pod-buffer
2993            (tinyperl-pod-pop-to-buffer regexp pod-buffer))
2994       nil)                              ;POD is already available
2995      ;; ................................... new documentation or load ...
2996      (t
2997       (if (not (string-match ".p[lm]$" module))
2998           (setq module (concat module ".pm")))
2999       (unless (setq module (tinyperl-locate-library module))
3000         (error
3001          (substitute-command-keys
3002           (concat
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))
3010         (dolist (elt (list
3011                       (replace-regexp-in-string
3012                        ".pm" ".pod" name)
3013                       name))
3014           (setq path
3015                 (ti::file-make-path
3016                  pathname
3017                  ;;  Delete prefix, because (cdr path) will cnotain the
3018                  ;;  full directory
3019                  ;;
3020                  ;;  Getopt::Long.pm --> Long.pm
3021                  (replace-regexp-in-string
3022                   ".*:" ""
3023                   elt)))
3024           (when (file-exists-p path)
3025             (setq file path)
3026             (return))))
3027
3028       (when (or (not file)
3029                 (not (file-exists-p file)))
3030         (error "TinyPerl: Cache error, %s does not exist" (car module)))
3031       (cond
3032        (mode
3033         (find-file file)
3034         (ti::pmin))
3035        (t
3036         (ti::pop-to-buffer-or-window
3037          (tinyperl-pod2text
3038           file
3039           (get-buffer-create pod-buffer-name)))
3040         (ti::pmin)
3041         (re-search-forward regexp nil t)))))))
3042
3043 ;;; ----------------------------------------------------------------------
3044 ;;;
3045 (defun tinyperl-pod-podchecker (file)
3046   "Run podchecker on current file."
3047   (interactive
3048    (list
3049     (read-file-name
3050      "TinyPerl podcheck: "
3051      (file-name-directory (or (buffer-file-name)
3052                               default-directory))
3053      nil
3054      t
3055      (if (buffer-file-name)
3056          (file-name-nondirectory (buffer-file-name))
3057        ""))))
3058   (let* ((buffer (tinyperl-podchecker file)))
3059     (display-buffer buffer)))
3060
3061 ;;; ----------------------------------------------------------------------
3062 ;;;
3063 ;;;###autoload
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)
3072       (erase-buffer))
3073     (ti::pop-to-buffer-or-window (tinyperl-pod2text file buffer))
3074     (ti::pmin)))
3075
3076 ;;; ----------------------------------------------------------------------
3077 ;;;
3078 (defun tinyperl-pod-find-file-this-buffer ()
3079   "Call `tinyperl-pod-find-file' with `buffer-file-name'"
3080   (interactive)
3081   (if (buffer-file-name)
3082       (tinyperl-pod-find-file (buffer-file-name))
3083     (error "TinyPerl: This buffer is not associated with file.")))
3084
3085 ;;; ----------------------------------------------------------------------
3086 ;;;
3087 (defun tinyperl-pod-jump (module)
3088   "Jump to Perl MODULE POD if it exists or do nothing."
3089   (interactive)
3090   (let* ((buffer (get-buffer (tinyperl-pod-buffer-name module))))
3091     (when buffer
3092       (ti::pop-to-buffer-or-window buffer))))
3093
3094 ;;; ----------------------------------------------------------------------
3095 ;;;
3096 ;;;###autoload
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
3106                    (point-max)))
3107          ;; perldsc - Perl Data Structures Cookbook
3108          ;; ^^^^^^^
3109          (regexp (concat "NAME[\n\r \t]+"
3110                          (regexp-quote
3111                           (replace-regexp-in-string
3112                            "\.pod" ""
3113                            (file-name-nondirectory file)))
3114                          " +-+ ")))
3115     (tinyperl-debug fid "file" file "buffer" buffer)
3116     (or (tinyperl-pod-pop-to-buffer regexp buffer)
3117         (progn
3118           (ti::pop-to-buffer-or-window (tinyperl-pod2text file buffer))
3119           (goto-char beg)))))
3120
3121 ;;}}}
3122 ;;{{{ POD grep
3123
3124 ;;; ----------------------------------------------------------------------
3125 ;;;
3126 ;;;###autoload
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
3132 pod file name, like
3133
3134    perlre.pod:165:    \\Z       Match at only e
3135
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: ")
3140   (or pod-path
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))
3146
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.
3151                                         ;:
3152          ;;  So, it's enough to Emacs to do an "cd" to directory.
3153          ;;
3154          (default-directory (file-name-directory pod-path)))
3155     (setq 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)))))
3159
3160 ;;; ----------------------------------------------------------------------
3161 ;;;
3162 ;;;###autoload
3163 (defun tinyperl-process-wait (buffer)
3164   "Wait until process in BUFFER has finished."
3165   (let (process)
3166     (while (or (null (get-buffer buffer))
3167                (and (setq process (get-buffer-process buffer))
3168                     (memq (process-status process) '(run))
3169                     (prog1 t
3170                       (sit-for 0.5)))))))
3171
3172 ;;; ----------------------------------------------------------------------
3173 ;;;
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.
3178
3179 Return:
3180
3181  '(TOPIC-HEADING TEXT-DATA)
3182
3183 TOPIC-HEADING  does not end to cr/lf
3184 TEXT-DATA      ends to cr/lf"
3185   (flet ((context-min (point lines)
3186                       (goto-char point)
3187                       (backward-line lines)
3188                       (point))
3189          (context-max (point lines)
3190                       (goto-char point)
3191                       (forward-line lines)
3192                       (point))
3193          (enough-chars-found-point-p
3194           (point1 point2)
3195           ;;  Require at least 5 lines
3196           (> (abs (- point1 point2)) (* 80 5))))
3197     (let (point
3198           min
3199           max
3200           search-min
3201           string
3202           topic)
3203       ;; about 15 lines supposing 80 chars per line.
3204       ;; These values are rough guesses.
3205       (save-excursion
3206         (when line
3207           (goto-line line))
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)))
3212       (cond
3213        ((re-search-backward
3214          ;;  FAQ topic line: perlfaq6.pod
3215          "^\\(=head[0-9]?.*\\)"
3216          search-min 'noerr)
3217         (setq min (point))
3218         (setq topic (match-string 1))
3219         ;;  See if we can find next TOPIC nearby. Perhaps
3220         ;;  this is short quote from faq.
3221         (forward-line 1)
3222         (if (re-search-forward "^=head[0-9]?\\(.*\\)"
3223                                max 'noerr)
3224             (setq max (line-beginning-position))))
3225        (t
3226         (goto-char point) ;; Previous search-min changed point
3227         (save-excursion
3228           (when (re-search-backward "^=head[0-9]?" nil 'noerr)
3229             (setq topic (ti::buffer-read-line))))
3230         ;;  Excerpt enough content arount the point.
3231         (let (try-min
3232               try-max)
3233           (re-search-backward "^[ \t]*$" nil t)
3234           (setq try-min (point))
3235           (goto-char 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)
3240               (setq min try-min))
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)
3248             string))))
3249
3250 ;;; ----------------------------------------------------------------------
3251 ;;;
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.
3256
3257 Return:
3258
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))
3262           line
3263           (and grep-data
3264                (ti::remove-properties grep-data))
3265           (tinyperl-pod-grep-faq-data-context-1 line))))
3266
3267 ;;; ----------------------------------------------------------------------
3268 ;;;
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.
3273
3274 Return:
3275
3276 '((absolute-file-name grep-data (topic text-data)
3277   (absolute-file-name grep-data (topic text-data)
3278   ...)"
3279   (let (list
3280         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)))
3284         (when verb
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))
3290
3291       ;;  read enough context
3292       (when (setq data
3293                   (tinyperl-pod-grep-faq-data-context
3294                    buffer grep-data grep-line))
3295         (push data list)))
3296     (nreverse list)))
3297
3298 ;;; ----------------------------------------------------------------------
3299 ;;;
3300 (defun tinyperl-pod-grep-faq-data-insert (data &optional verb)
3301   "Insert faq text DATA into current buffer. VERB.
3302
3303 References:
3304     `tinyperl-pod-grep-faq-data-context-all-files'"
3305   (let ((colors-p (ti::colors-supported-p))
3306         point)
3307     ;; Has to disable font lock in this buffer of the
3308     ;; Highlighting isn't shown.
3309     (when colors-p
3310       (turn-on-font-lock-mode))
3311     (dolist (elt data)
3312       (multiple-value-bind (file line grep-data context-data) elt
3313         (multiple-value-bind (topic text) context-data
3314           (when verb
3315             (tinyperl-verbose-macro 2
3316                                     (message "TinyPerl: processing data %s"
3317                                              (file-name-nondirectory file))))
3318           (insert
3319            (format "FILE: [%s]" (file-name-nondirectory file))
3320            (if line
3321                (format " LINE: %d\n" line)
3322              "\n")
3323            (make-string 70 ?-)
3324            "\n"
3325            (if topic
3326                (format "%s\n[...cut...]\n" topic)
3327              ""))
3328           (setq point (point))
3329           (insert text "\n")
3330           (when colors-p)
3331           (goto-char point)
3332           ;;  Mark line that matched.
3333           (ti::text-re-search-forward (regexp-quote grep-data))
3334           (ti::pmax))))))
3335
3336 ;;; ----------------------------------------------------------------------
3337 ;;;
3338 ;;;###autoload
3339 (defun tinyperl-pod-grep-faq-answer (regexp &optional verb)
3340   "Grep REGEXP from perl pod files. VERB.
3341
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))
3349          (buffer     "*grep*")
3350          (out-buffer tinyperl-:faq-buffer-name)
3351          (grep (tinyperl-grep-program))
3352          data)
3353     (ti::verb)
3354     (setq path "")
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))
3367     (when data
3368       (display-buffer (get-buffer-create out-buffer))
3369       (with-current-buffer out-buffer
3370         (erase-buffer)
3371         (tinyperl-pod-grep-faq-data-insert data)
3372         (ti::pmin)))
3373     (if 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].")))))
3378
3379 ;;}}}
3380 ;;{{{ Misc
3381
3382 ;;; ----------------------------------------------------------------------
3383 ;;;
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'."
3388   (`
3389    (save-excursion
3390      (ti::pmin)
3391      ;; (ti::buffer-outline-widen)
3392      (when (tinyperl-version-stamp-re-search-forward)
3393        (,@ body)))))
3394
3395 ;;; ----------------------------------------------------------------------
3396 ;;;
3397 (defun tinyperl-version-stamp-re-search-forward ()
3398   "Search perl $VERSION variable. Match 2 will contain the version."
3399   (let (case-fold-search)
3400     (re-search-forward
3401      (concat
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]*;")
3404      nil
3405      t)))
3406
3407 ;;; ----------------------------------------------------------------------
3408 ;;;
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)))))
3417
3418 ;;; ----------------------------------------------------------------------
3419 ;;;
3420 (defun tinyperl-pause-file-name (&optional filename use-date)
3421   "Generate PAUSE FILENAME: file-version.pl.
3422 Input:
3423
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'."
3428   (let* (kill
3429          buffer
3430          ret)
3431     (setq buffer (or (and filename
3432                           (find-buffer-visiting filename))
3433                      (prog1
3434                          (find-file-noselect filename)
3435                        (setq kill t))))
3436     (with-current-buffer buffer
3437       (tinyperl-version-macro
3438        (let* ((ver   (or (match-string 2)
3439                          (and use-date
3440                               (format-time-string
3441                                "%Y.%m%d"
3442                                (current-time)))))
3443               (name1 (file-name-nondirectory
3444                       (or filename
3445                           (buffer-file-name)
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))
3454     ret))
3455
3456 ;;; ----------------------------------------------------------------------
3457 ;;;
3458 (defun tinyperl-pause-copy-file (&optional directory)
3459   "Copy perl script to separate directory to wait for PAUSE submission.
3460
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
3463 this order:
3464
3465   1. DIRECTORY (available only as a lisp call)
3466   2. `tinyperl-:pause-directory' (user's default setting)
3467   3. or to current directory
3468
3469 References:
3470
3471   `tinyperl-:pause-directory'."
3472   (interactive
3473    (let ((path tinyperl-:pause-directory))
3474      (list
3475       (read-file-name "TinyPerl: [PAUSE dir]: "
3476                       (and path (file-name-directory path))
3477                       nil ;; users null string
3478                       (not 'must-match)
3479                       (and path
3480                            (file-name-nondirectory path))))))
3481   (let* ((from     (buffer-file-name))
3482          (file     (tinyperl-pause-file-name from))
3483          to)
3484     (unless (file-directory-p directory)
3485       (error "TinyPerl: Directory not found %s" directory))
3486     (unless file
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))
3492     to))
3493
3494 ;;; ----------------------------------------------------------------------
3495 ;;;
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.
3508
3509 ;;;    (ti::file-ange-file-handle
3510 ;;;     'put
3511 ;;;     "anonymous"
3512 ;;;     "pause.perl.org"
3513 ;;;     "/incoming"
3514 ;;;     temp
3515 ;;;     (list ver)
3516 ;;;     nil ;;  Run on background
3517 ;;;     (format "TinyPerl: ange-ftp PAUSE upload completed %s" ver))
3518     (copy-file file upload 'ok-if-already-exists)
3519     (with-temp-buffer
3520       (insert-file upload)
3521       (write-file
3522        (concat
3523         "/anonymous@pause.perl.org:/incoming/"
3524         ver)))))
3525
3526 ;;; ----------------------------------------------------------------------
3527 ;;;
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\""
3531   (interactive)
3532   (tinyurl-agent-funcall
3533    'url
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"))
3537
3538 ;;; ----------------------------------------------------------------------
3539 ;;;
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.
3544
3545 If there is entry in current buffer to read
3546
3547   # BEGIN: Devel::SelfStubber
3548   # END:   Devel::SelfStubber
3549
3550 Then the generated subs are inserted into that section. Any previous
3551 stubs are removed.
3552
3553 Input:
3554
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."
3559   (interactive
3560    (list
3561     (read-file-name "Perl stubs from file: "
3562                     nil nil 'match
3563                     (file-name-nondirectory buffer-file-name))
3564     current-prefix-arg))
3565   (let* ((name (file-name-nondirectory file))
3566          tmp
3567          buffer
3568          cmd-1
3569          beg
3570          end)
3571     (setq file (expand-file-name file))
3572     (unwind-protect
3573         (progn
3574           ;; ........................................... forced insert ...
3575           (when force
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")))
3581
3582             (setq tmp (ti::temp-file name 'tmp-dir))
3583             (copy-file file tmp)
3584             (setq file tmp)
3585
3586             (with-current-buffer (setq buffer (find-file-noselect file))
3587               (delete-matching-lines "__DATA__")
3588               (ti::pmin)
3589               (insert "use SelfLoader;\n__DATA__\n")
3590               (save-buffer nil)))
3591           ;; ............................................ perl-command ...
3592           (setq cmd-1
3593                 (format
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))))
3599
3600           (tinyperl-verbose-macro 2
3601                                   (message ;Record it to *Messages* buffer
3602                                    (format
3603                                     "%s -MDevel::SelfStubber -e %s"
3604                                     tinyperl-:perl-bin
3605                                     cmd-1)))
3606           ;; ........................................... find-position ...
3607
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")))
3612           (cond
3613            ((and beg end)
3614             (save-excursion
3615               (goto-char beg)
3616               (forward-line 1)
3617               (delete-region (point) end)
3618               (insert "\n")
3619               (call-process tinyperl-:perl-bin
3620                             nil
3621                             (current-buffer)
3622                             nil
3623                             "-MDevel::SelfStubber "
3624                             "-e"
3625                             cmd-1)
3626
3627               (tinyperl-verbose-macro 1
3628                                       (message "TinyPerl: stubs updated in buffer"))))
3629            (t                           ;No previoous STUBS
3630             (call-process tinyperl-:perl-bin
3631                           nil
3632                           (current-buffer)
3633                           nil
3634                           "-MDevel::SelfStubber "
3635                           "-e"
3636                           cmd-1)))) ;; progn
3637       (when buffer
3638         (kill-buffer buffer)))))
3639
3640 ;;}}}
3641
3642 (tinyperl-skeleton-setup)
3643
3644 (provide   'tinyperl)
3645 (run-hooks 'tinyperl-:load-hook)
3646
3647 ;;; tinyperl.el ends here