58
51
;;; To associate pod-mode with .pod files add the following to your ~/.emacs
60
;;; (setq auto-mode-alist
61
;;; (append auto-mode-alist
62
;;; '(("\\.pod$" . pod-mode))))
53
;;; (add-to-list 'auto-mode-alist '("\\.pod$" . pod-mode))
65
56
;;; To automatically turn on font-lock-mode add the following to your ~/.emacs
67
58
;;; (add-hook 'pod-mode-hook 'font-lock-mode)
61
;;; In addition to the standard POD commands, custom commands as
62
;;; defined by a Pod::Weaver configuration are supported. However, for
63
;;; those to work, eproject.el as available at
64
;;; http://github.com/jrockway/eproject is required.
66
;;; Make sure to require eproject.el or create an autoload for
67
;;; eproject-maybe-turn-on if you expect custom commands to work.
70
;;; When automatically inserting hyperlink formatting codes to modules
71
;;; or sections within modules, autocompletion for module names will
72
;;; be provided if perldoc.el, as available at
73
;;; git://gaffer.ptitcanardnoir.org/perldoc-el.git, is present.
73
(defvar pod-mode-hook nil)
80
(defgroup pod-mode nil
81
"Mode for editing POD files"
84
(defgroup pod-mode-faces nil
85
"Faces for highlighting POD constructs"
89
(defface pod-mode-command-face
90
'((((class grayscale) (background light)) (:foreground "LightGray" :weight bold))
91
(((class grayscale) (background dark)) (:foreground "DimGray" :weight bold))
92
(((class color) (min-colors 88) (background light)) (:foreground "Purple"))
93
(((class color) (min-colors 88) (background dark)) (:foreground "Cyan1"))
94
(((class color) (min-colors 16) (background light)) (:foreground "Purple"))
95
(((class color) (min-colors 16) (background dark)) (:foreground "Cyan"))
96
(((class color) (min-colors 8)) (:foreground "cyan" :weight bold))
98
"Face used to highlight POD commands"
99
:group 'pod-mode-faces)
101
(defface pod-mode-head-face
102
'((t (:inherit pod-mode-command-face)))
103
"Face used to highlight =head commands"
104
:group 'pod-mode-faces)
106
(defface pod-mode-command-text-face
107
'((((class grayscale) (background light))
108
(:foreground "DimGray" :weight bold :slant italic))
109
(((class grayscale) (background dark))
110
(:foreground "LightGray" :weight bold :slant italic))
111
(((class color) (min-colors 88) (background light))
112
(:foreground "Firebrick"))
113
(((class color) (min-colors 88) (background dark))
114
(:foreground "chocolate1"))
115
(((class color) (min-colors 16) (background light))
117
(((class color) (min-colors 16) (background dark))
118
(:foreground "red1"))
119
(((class color) (min-colors 8) (background light))
121
(((class color) (min-colors 8) (background dark))
123
(t (:weight bold :slant italic)))
124
"Face used to highlight text after POD commands"
125
:group 'pod-mode-faces)
127
(defface pod-mode-verbatim-face
128
'((((class grayscale) (background light)) (:foreground "Gray90" :weight bold))
129
(((class grayscale) (background dark)) (:foreground "DimGray" :weight bold))
130
(((class color) (min-colors 88) (background light)) (:foreground "ForestGreen"))
131
(((class color) (min-colors 88) (background dark)) (:foreground "PaleGreen"))
132
(((class color) (min-colors 16) (background light)) (:foreground "ForestGreen"))
133
(((class color) (min-colors 16) (background dark)) (:foreground "PaleGreen"))
134
(((class color) (min-colors 8)) (:foreground "green"))
135
(t (:weight bold :underline t)))
136
"Face used to highlight verbatim paragraphs in POD"
137
:group 'pod-mode-faces)
139
(defface pod-mode-formatting-code-character-face
140
'((((class grayscale) (background light))
141
(:foreground "Gray90" :weight bold :slant italic))
142
(((class grayscale) (background dark))
143
(:foreground "DimGray" :weight bold :slant italic))
144
(((class color) (min-colors 88) (background light)) (:foreground "sienna"))
145
(((class color) (min-colors 88) (background dark)) (:foreground "LightGoldenrod"))
146
(((class color) (min-colors 16) (background light)) (:foreground "DarkGoldenrod"))
147
(((class color) (min-colors 16) (background dark)) (:foreground "LightGoldenrod"))
148
(((class color) (min-colors 8)) (:foreground "yellow" :weight light))
149
(t (:weight bold :slant italic)))
150
"Face used to highlight formatting codes in POD"
151
:group 'pod-mode-faces)
153
(defface pod-mode-formatting-code-face
154
'((((class grayscale) (background light))
155
(:foreground "LightGray" :weight bold :underline t))
156
(((class grayscale) (background dark))
157
(:foreground "Gray50" :weight bold :underline t))
158
(((class color) (min-colors 88) (background light)) (:foreground "dark cyan"))
159
(((class color) (min-colors 88) (background dark)) (:foreground "Aquamarine"))
160
(((class color) (min-colors 16) (background light)) (:foreground "CadetBlue"))
161
(((class color) (min-colors 16) (background dark)) (:foreground "Aquamarine"))
162
(((class color) (min-colors 8)) (:foreground "magenta"))
163
(t (:weight bold :underline t)))
164
"Face used to highlight text within formatting codes in POD"
165
:group 'pod-mode-faces)
167
(defface pod-mode-formatting-code-i-face
168
'((t (:inherit pod-mode-formatting-code-face :slant italic)))
169
"Face used to highlight I<> formatting codes in POD"
170
:group 'pod-mode-faces)
172
(defface pod-mode-formatting-code-b-face
173
'((t (:inherit pod-mode-formatting-code-face :weight bold)))
174
"Face used to highlight B<> formatting codes in POD"
175
:group 'pod-mode-faces)
177
(defface pod-mode-alternative-formatting-code-face
178
'((((class color) (min-colors 88) (background light)) (:foreground "Blue1"))
179
(((class color) (min-colors 88) (background dark)) (:foreground "LightSkyBlue"))
180
(((class color) (min-colors 16) (background light)) (:foreground "Blue"))
181
(((class color) (min-colors 16) (background dark)) (:foreground "LightSkyBlue"))
182
(((class color) (min-colors 8)) (:foreground "blue" :weight bold))
183
(t (:inverse-video t :weight bold)))
184
"Alternative face used to highlight formatting codes in POD.
185
This is used for E<> escapes and for the link target in L<>
187
:group 'pod-mode-faces)
189
(defface pod-mode-string-face
190
'((((class grayscale) (background light)) (:foreground "DimGray" :slant italic))
191
(((class grayscale) (background dark)) (:foreground "LightGray" :slant italic))
192
(((class color) (min-colors 88) (background light)) (:foreground "VioletRed4"))
193
(((class color) (min-colors 88) (background dark)) (:foreground "LightSalmon"))
194
(((class color) (min-colors 16) (background light)) (:foreground "RosyBrown"))
195
(((class color) (min-colors 16) (background dark)) (:foreground "LightSalmon"))
196
(((class color) (min-colors 8)) (:foreground "green"))
198
"Face used to highlight quoted strings in POD"
199
:group 'pod-mode-faces)
201
(defvar pod-mode-hook nil
202
"List of functions to be called when activating `pod-mode'.")
76
205
(defvar pod-version "1.01"
77
"Version of POD mode")
80
(defvar pod-mode-map nil "Keymap for POD major mode.")
82
(let ((map (make-sparse-keymap)))
83
;; insert (define-key map ...) stuff here
84
(setq pod-mode-map map)))
86
;; syntax highlighting: standard keywords
87
(defconst pod-font-lock-keywords-1
89
("^=\\(head[1234]\\|item\\|over\\|back\\|cut\\|pod\\|for\\|begin\\|end\\|encoding\\)" 0 font-lock-keyword-face)
90
("^[ \t]+\\(.*\\)$" 1 font-lock-type-face)
92
"Minimal highlighting expressions for POD mode.")
94
;; syntax highlighting: additional keywords
206
"Version of POD mode.")
208
(let* ((head-sizes '(1.9 1.7 1.5 1.3))
209
(heads (loop for i from 1 to (length head-sizes) collect
210
(cons i (nth (- i 1) head-sizes)))))
211
(defconst pod-font-lock-keywords-1
213
(loop for (n . s) in heads collect
214
(let ((head-face-name (intern (format "pod-mode-head%d-face" n)))
215
(text-face-name (intern (format "pod-mode-head%d-text-face" n))))
216
(eval `(defface ,head-face-name
217
'((t (:inherit pod-mode-head-face :height ,s)))
218
,(format "Face used to highlight head%d commands" n)
219
:group 'pod-mode-faces))
220
(eval `(defface ,text-face-name
221
'((t (:inherit pod-mode-command-text-face :height ,s)))
222
,(format "Face used to hightlight text in head%d commands" n)
223
:group 'pod-mode-faces))
224
`(,(format "^\\(=head%d\\)\\(.*\\)" n)
225
(1 (quote ,head-face-name))
226
(2 (quote ,text-face-name)))))
227
`((,(format "^\\(=%s\\)\\(.*\\)"
228
(regexp-opt '("item" "over" "back" "cut" "pod"
229
"for" "begin" "end" "encoding")))
230
(1 'pod-mode-command-face)
231
(2 'pod-mode-command-text-face))))
232
"Minimal highlighting expressions for POD mode."))
95
234
(defconst pod-font-lock-keywords-2
96
(append pod-font-lock-keywords-1
98
("^=\\(head[1234]\\|item\\|over\\|back\\|cut\\|pod\\|for\\|begin\\|end\\)\\(.*\\)" 2 font-lock-comment-face)
235
(append pod-font-lock-keywords-1 '())
100
236
"Additional Keywords to highlight in POD mode.")
102
;; syntax highlighting: even more keywords
238
(defun pod-matcher-for-code (code body)
239
"Create a matcher function for a given POD formatting CODE.
240
Will return a quoted lambda as expected by `font-lock-keywords'
243
When executing the lambda, it will match a POD formatting code
244
introduced with the character CODE and as described in perlpod.
246
BODY is expected to be a quoted lambda. It will be executed
247
after a successful match of a well-balanced formatting code.
248
It'll get two arguments, the start and end position of the text
249
contained in the formatting code. It should return a list of
250
positions suitable to use as match data for later highlighting by
251
`font-lock-keywords'."
253
(when (re-search-forward
256
"\\(?:\\(?:\\(<\\)[^<]\\)\\|\\(?:\\(<\\{2,\\}\\)\s\\)\\)")
258
(let ((beg (or (match-end 1)
260
(n-lt (length (or (match-string-no-properties 1)
261
(match-string-no-properties 2)))))
262
(goto-char (- (point) 1))
263
(when (re-search-forward
264
(concat (when (> n-lt 1) "\s")
266
(apply 'concat (loop for i from 1 to n-lt collect ">"))
269
(let* ((end (match-beginning 1))
270
(match-data (funcall ,body beg end)))
272
(store-match-data (append
273
(list (- beg n-lt 1) beg)
275
(list end (+ end n-lt))))
278
(defun pod-keyword-for-simple-code (code face)
279
"Build a `font-lock-keywords' keyword for a POD formatting code.
280
CODE is the character introducing the formatting code to be
281
matched. FACE is the face that should be used to map the text
282
within the formattign code.
284
In addition to matching the code's content with FACE, the
285
formatting code itself will be highlighted using
286
`pod-mode-formatting-code-character-face'."
287
`(,(pod-matcher-for-code code '(lambda (beg end)
289
(0 'pod-mode-formatting-code-character-face prepend)
291
(2 'pod-mode-formatting-code-character-face prepend)))
103
293
(defconst pod-font-lock-keywords-3
104
294
(append pod-font-lock-keywords-2
106
("[IBCFXZS]<\\([^>]*\\)>" 1 font-lock-reference-face)
107
("L<\\(\\([^|>]*\\)|\\)\\([^>]+\\)>"
108
(2 font-lock-reference-face)
109
(3 font-lock-function-name-face))
110
("L<\\([^|>]+\\)>" 1 font-lock-function-name-face)
111
("E<\\([^>]*\\)>" 1 font-lock-function-name-face)
112
("\"\\([^\"]+\\)\"" 0 font-lock-string-face)
295
(loop for code in '("C" "F" "X" "Z" "S")
296
collect (pod-keyword-for-simple-code
297
code 'pod-mode-formatting-code-face))
299
(pod-keyword-for-simple-code
300
"E" 'pod-mode-alternative-formatting-code-face)
301
(pod-keyword-for-simple-code "I" 'pod-mode-formatting-code-i-face)
302
(pod-keyword-for-simple-code "B" 'pod-mode-formatting-code-b-face)
303
`(,(pod-matcher-for-code
304
"L" (lambda (beg end)
306
(if (re-search-forward "\\([^|]\\)|" end t)
307
(list beg (match-end 1)
308
(+ (match-end 1) 1) end)
309
(list 0 0 beg end))))
310
(0 'pod-mode-formatting-code-character-face prepend)
311
(1 'pod-mode-formatting-code-face append)
312
(2 'pod-mode-alternative-formatting-code-face append)
313
(3 'pod-mode-formatting-code-character-face prepend))
315
(0 'pod-mode-string-face))
316
'("^[ \t]+\\(.*\\)$" 1 'pod-mode-verbatim-face prepend)))
114
317
"Balls-out highlighting in POD mode.")
116
;; default level of highlight to maximum
117
319
(defvar pod-font-lock-keywords pod-font-lock-keywords-3
118
"Default highlighting expressions for POD mode")
120
;; no special indenting, just pure text mode
121
(defun pod-indent-line ()
122
"Indent current line as POD code. Does nothing yet."
126
;; no special syntax table
127
(defvar pod-mode-syntax-table nil
128
"Syntax table for pod-mode.")
130
;; create and activate syntax table
131
(defun pod-create-syntax-table ()
132
(if pod-mode-syntax-table
134
(setq pod-mode-syntax-table (make-syntax-table))
135
(set-syntax-table pod-mode-syntax-table)
138
(defun pod-add-support-for-outline-minor-mode ()
139
"Provides additional menus from =head lines in outline-minor-mode"
320
"Default highlighting expressions for POD mode.")
322
(defvar pod-weaver-section-keywords nil
323
"List of custom Pod::Weaver keywords describing sections.
324
This is an alist, mapping strings with pod commands to a number
325
describing their level within the document.")
326
(make-local-variable 'pod-weaver-section-keywords)
328
(defun pod-linkable-sections-for-buffer (buffer &optional section-keywords)
329
"Extract POD sections from BUFFER.
330
Returns a list of POD section names with BUFFER. By default only
331
=head commands are looked for. The optional second argument
332
SECTION-KEYWORDS may be used to also extract section names from
333
additional pod commands."
334
(with-current-buffer buffer
337
(goto-char (point-min))
338
(loop while (re-search-forward
339
(format "^=%s\s+\\(.*\\)$"
342
(loop for i from 1 to 4
343
collect (format "head%d" i))
347
collect (match-string-no-properties 1))))))
349
(defun pod-linkable-sections-for-module (module)
350
"Extract POD sections from MODULE.
351
Opens the documentation of an installed perl MODULE and returns a
352
list of all section names in it.
354
`pod-linkable-sections-for-buffer' is used to actually extract
356
(with-current-buffer (get-buffer-create (concat "*POD " module "*"))
359
(kill-all-local-variables)
362
(let ((default-directory "/"))
363
(call-process "perldoc" nil (current-buffer) nil "-T" "-u" module)
364
(goto-char (point-min))
365
(when (and (> (count-lines (point-min) (point-max)) 1)
366
(not (re-search-forward
367
"No documentation found for .*" nil t)))
368
(pod-linkable-sections-for-buffer (current-buffer)))))
369
(kill-buffer (current-buffer)))))
371
(defun pod-linkable-sections (&optional module)
372
"Extract POD sections.
373
Extracts all POD sections from either the current buffer, or, if
374
MODULE is given, from the POD documentation of an installed
377
If MODULE is given, `pod-linkable-sections-for-module' will be
378
called. Otherwise `pod-linkable-sections-for-buffer' for
379
`current-buffer', and with all additional POD section keywords as
380
provided by `pod-weaver-section-keywords'."
382
(pod-linkable-sections-for-module module)
383
(pod-linkable-sections-for-buffer
385
(mapcar (lambda (i) (car i))
386
pod-weaver-section-keywords))))
388
(defun pod-linkable-modules (&optional re-cache)
389
"Find all installed perl modules.
390
Returns a list of all installed perl modules, as provided by
391
function `perldoc-modules-alist'. This requires `perldoc' to be
394
If the optional argument RE-CACHE is non-nil, a possibly cached
395
version of the module list will be discarded and rebuilt."
397
(when (ignore-errors (require 'perldoc))
398
(when (or re-cache (not perldoc-modules-alist))
399
(message "Building completion list of all perl modules..."))
400
(mapcar (lambda (i) (car i)) (perldoc-modules-alist re-cache)))))
402
(defun pod-link (link &optional text)
403
"Insert a POD hyperlink formatting code.
404
Inserts a POD L<> formatting code at point. The content of the
407
If the optional argument TEXT is a string and contains anything
408
that's not whitespace, it will be used as the link title."
410
(when (and (stringp text)
411
(string-match-p "[^\s]" text))
416
(defun pod-completing-read (prompt choices)
417
"Use `completing-read' to do a completing read."
418
(completing-read prompt choices))
420
(defun pod-icompleting-read (prompt choices)
421
"Use iswitchb to do a completing read."
422
(let ((iswitchb-make-buflist-hook
424
(setq iswitchb-temp-buflist choices))))
427
(when (not iswitchb-mode)
428
(add-hook 'minibuffer-setup-hook 'iswitchb-minibuffer-setup))
429
(iswitchb-read-buffer prompt))
430
(when (not iswitchb-mode)
431
(remove-hook 'minibuffer-setup-hook 'iswitchb-minibuffer-setup)))))
433
(defun pod-ido-completing-read (prompt choices)
434
"Use ido to do a completing read."
435
(ido-completing-read prompt choices))
437
(defcustom pod-completing-read-function
438
#'pod-icompleting-read
439
"Ask the user to select a single item from a list.
440
Used by `pod-link-section', `pod-link-module', and
441
`pod-link-module-section'."
443
:type '(radio (function-item
444
:doc "Use Emacs' standard `completing-read' function."
446
(function-item :doc "Use iswitchb's completing-read function."
447
pod-icompleting-read)
448
(function-item :doc "Use ido's completing-read function."
449
pod-ido-completing-read)
452
(defun pod-do-completing-read (&rest args)
453
"Do a completing read with the configured `pod-completing-read-function'."
454
(apply pod-completing-read-function args))
456
(defun pod-link-uri (uri &optional text)
457
"Insert POD hyperlink formatting code for a URL.
458
Calls `pod-link' with URI and TEXT.
460
When called interactively, URI and TEXT will be read from the
463
(list (read-string "URI: ")
464
(read-string "Text: ")))
467
(defun pod-link-section (section &optional text)
468
"Insert hyperlink formatting code for a POD section.
469
Insert an L<> formatting code pointing to a section within the
472
When called interactively, SECTION and TEXT will be read using
473
`pod-do-completing-read'.
475
When reading SECTION, `pod-linkable-sections' will be used to
476
provide completions."
478
(list (pod-do-completing-read "Section: " (pod-linkable-sections))
479
(read-string "Text: ")))
480
(pod-link-module-section "" section text))
482
(defun pod-link-module (module &optional text)
483
"Insert POD hyperlink formatting code for a module.
484
Insert an L<> formatting code pointing to a MODULE.
486
When called interactively, MODULE and TEXT will be read using
487
`pod-do-completing-read'.
489
When reading MODULE, `pod-linkable-modules' will be used to
490
provide completions."
492
(list (pod-do-completing-read "Module: "
493
(pod-linkable-modules current-prefix-arg))
494
(read-string "Text: ")))
495
(pod-link module text))
497
(defun pod-link-module-section (module section &optional text)
498
"Insert POD hyperlink formatting code for a section in a module.
499
Insert an L<> formatting code pointing to a part of MODULE
500
documentation as described by SECTION.
502
When called interactive, MODULE, SECTION, and TEXT will be read
503
using `pod-do-completing-read'.
505
When reading MODULE and SECTION, `pod-linkable-modules' and
506
`pod-linkable-sections', respectively, will be used to provide
509
(let ((module (pod-do-completing-read
511
(pod-linkable-modules current-prefix-arg))))
513
(pod-do-completing-read "Section: " (pod-linkable-sections module))
514
(read-string "Text: "))))
518
(if (string-match-p "\s" section)
519
(concat "\"" section "\"")
524
(let ((map (make-sparse-keymap)))
525
(define-key map (kbd "C-c C-l u") 'pod-link-uri)
526
(define-key map (kbd "C-c C-l s") 'pod-link-section)
527
(define-key map (kbd "C-c C-l m") 'pod-link-module)
528
(define-key map (kbd "C-c C-l M") 'pod-link-module-section)
530
"Keymap for POD major mode.")
532
(defvar pod-mode-syntax-table
533
(let ((st (make-syntax-table)))
535
"Syntax table for `pod-mode'.")
537
(defun pod-add-support-for-outline-minor-mode (&rest sections)
538
"Provides additional menus from section commands for function
539
`outline-minor-mode'.
541
SECTIONS can be used to supply section commands in addition to
140
543
(make-local-variable 'outline-regexp)
141
(setq outline-regexp "=head[1234] ")
547
(append (loop for i from 1 to 4 collect (format "head%d" i))
548
'("item") sections))))
142
549
(make-local-variable 'outline-level)
143
550
(setq outline-level
146
(string-to-int (buffer-substring (+ (point) 5) (+ (point) 6)))
554
(let ((sect (format "^=%s\s"
556
(mapcar (lambda (i) (car i))
557
pod-weaver-section-keywords) t))))
560
(cdr (assoc (match-string-no-properties 1)
561
pod-weaver-section-keywords)))
562
((looking-at "^=item\s") 5)
563
((string-to-number (buffer-substring
565
(+ (point) 6)))))))))))
567
(defun pod-add-support-for-imenu (&rest sections)
568
"Set up `imenu-generic-expression' for pod section commands.
569
SECTIONS can be used to supply section commands in addition to
571
(setq imenu-generic-expression
572
`((nil ,(format "^=%s\s+\\(.*\\)"
575
(loop for i from 1 to 4 collect (format "head%d" i))
576
'("item") sections)))
150
579
(defun pod-enable-weaver-collector-keywords (collectors)
151
(let* ((keyword-list (mapcar (lambda (collector)
152
(symbol-name (getf collector 'command)))
154
(keyword-re (concat "^=" (regexp-opt keyword-list t))))
155
(setf pod-font-lock-keywords
156
(append pod-font-lock-keywords
157
`((,keyword-re 0 font-lock-keyword-face))
158
`((,(concat keyword-re "\\(.*\\)") 2 font-lock-comment-face))))
580
"Enable support for Pod::Weaver collector commands.
581
Enables fontification for all commands described by COLLECTORS.
583
Also updates `pod-weaver-section-keywords', `outline-regexp', and
584
`imenu-generic-expression' accordingly."
585
(let ((collectors-by-replacement))
587
(setf pod-weaver-section-keywords
588
(loop for col in collectors
589
with cmd with new-cmd with new-name
591
(setq cmd (getf col 'command)
592
new-cmd (getf col 'new_command)
593
new-name (symbol-name new-cmd))
594
(let ((pos (loop for i in collectors-by-replacement do
595
(when (equal (car i) new-cmd)
598
(push (list new-cmd cmd) collectors-by-replacement)
599
(setcdr (last pos) (list cmd)))))
600
when (string-match "^head\\([1-4]\\)$" new-name)
601
collect (cons (symbol-name cmd)
603
(match-string-no-properties 1 new-name)))
604
when (string-match "^item$" new-name)
605
collect (cons (symbol-name cmd) 5))))
606
(let ((sections (mapcar (lambda (i) (car i))
607
pod-weaver-section-keywords)))
608
(apply #'pod-add-support-for-outline-minor-mode sections)
609
(apply #'pod-add-support-for-imenu sections))
611
pod-font-lock-keywords
615
(list (format "^\\(=%s\\)\\(.*\\)"
616
(regexp-opt (mapcar (lambda (k) (symbol-name k))
618
(let ((n (symbol-name (car i))))
619
(if (string-match-p "^head[1-4]$" n)
622
,(intern (format "pod-mode-%s-face" n))))
624
,(intern (format "pod-mode-%s-text-face" n)))))
626
'(1 'pod-mode-command-face)
627
'(2 'pod-mode-command-text-face))))))
628
collectors-by-replacement)
629
pod-font-lock-keywords))
159
630
(setq font-lock-mode-major-mode nil)
160
631
(font-lock-fontify-buffer)))
162
(defun pod-enable-weaver-features (weaver-config)
163
(pod-enable-weaver-collector-keywords (getf weaver-config 'collectors))
164
(message "Pod::Weaver keywords loaded."))
166
(defvar pod-weaver-config-buffer "")
633
(defun pod-enable-weaver-features (buffer weaver-config)
634
"Enable support for Pod::Weaver features.
635
Enables support for custom Pod::Weaver commands within a BUFFER.
637
WEAVER-CONFIG is a structure as returned by
638
\"dzil weaverconf -f lisp\".
640
Currently only supports collector commands via
641
`pod-enable-weaver-collector-keywords'."
642
(with-current-buffer buffer
643
(pod-enable-weaver-collector-keywords (getf weaver-config 'collectors))
644
(message "Pod::Weaver keywords loaded.")))
168
646
(defun pod-load-weaver-config (dir)
169
"Load additional pod keywords from a projects dist.ini/weaver.ini"
647
"Load additional pod keywords from dist.ini/weaver.ini in DIR."
170
648
(let* ((proc (start-process-shell-command
171
649
(concat "weaverconf-" (buffer-name (current-buffer)))
172
650
nil (format "cd %s; dzil weaverconf -f lisp" dir))))
173
(make-local-variable 'pod-weaver-config-buffer)
651
(set-process-plist proc (list :buffer (current-buffer)
174
653
(set-process-filter
175
654
proc (lambda (proc str)
176
(setq pod-weaver-config-buffer (concat pod-weaver-config-buffer str))))
655
(let ((plist (process-plist proc)))
656
(plist-put plist :output (concat (plist-get plist :output) str)))))
177
657
(set-process-sentinel
178
658
proc (lambda (proc event)
179
659
(if (string-equal event "finished\n")
182
(eval (car (read-from-string pod-weaver-config-buffer))))))
183
(if weaver-config (pod-enable-weaver-features weaver-config))))
184
(setq pod-weaver-config-buffer "")))))
660
(let* ((plist (process-plist proc))
663
(eval (car (read-from-string
664
(plist-get plist :output)))))))
665
(if weaver-config (pod-enable-weaver-features
666
(plist-get (process-plist proc) :buffer)
667
weaver-config))))))))
186
669
(defun pod-add-support-for-weaver ()
670
"Enable support for Pod::Weaver features in the current buffer.
671
Calls `pod-load-weaver-config' with the project directory of the
672
current buffer's file. To be able to successfully determine the
673
project directory, `eproject-maybe-turn-on' will be used and
674
'eproject.el' is expected to be loaded.
676
Does nothing if finding the project directory fails."
187
677
(let ((project-root (ignore-errors (eproject-maybe-turn-on))))
188
678
(if project-root (pod-load-weaver-config project-root))))
191
681
(defun pod-mode ()
192
"Major mode for editing POD files (Plain Old Documentation for Perl)."
682
"Major mode for editing POD files (Plain Old Documentation for Perl).
684
Commands:\\<pod-mode-map>
685
\\[pod-link] `pod-link'
686
\\[pod-link-section] `pod-link-section'
687
\\[pod-link-module] `pod-link-module'
688
\\[pod-link-module-section] `pod-link-module-section'
690
Turning on pod mode calls the hooks in `pod-mode-hook'."
194
692
(kill-all-local-variables)
195
(pod-create-syntax-table)
693
(set-syntax-table pod-mode-syntax-table)
196
694
(use-local-map pod-mode-map)
197
695
(make-local-variable 'font-lock-defaults)
198
696
(setq font-lock-defaults '(pod-font-lock-keywords 't))
199
;; (make-local-variable 'indent-line-function)
200
;; (setq indent-line-function 'pod-indent-line)
201
697
(setq major-mode 'pod-mode)
202
698
(setq mode-name "POD")
203
(setq imenu-generic-expression '((nil "^=head[1234] +\\(.*\\)" 1)))
699
(pod-add-support-for-imenu)
700
(pod-add-support-for-outline-minor-mode)
204
701
(run-hooks 'pod-mode-hook)
205
(pod-add-support-for-outline-minor-mode)
206
(pod-add-support-for-weaver)
702
(pod-add-support-for-weaver))
209
704
(provide 'pod-mode)