]> code.delx.au - gnu-emacs-elpa/blob - packages/notes-mode/notes-mode.el
* ampc: Sync to version 0.2.
[gnu-emacs-elpa] / packages / notes-mode / notes-mode.el
1
2 ;;;
3 ;;; notes-mode.el
4 ;;; $Id: notes-mode.el,v 1.71 2009/08/20 20:00:02 johnh Exp $
5 ;;;
6 ;;; Copyright (C) 1994-2007 by John Heidemann
7 ;;; Comments to <johnh@isi.edu>.
8 ;;;
9 ;;; This file is under the Gnu Public License.
10 ;;;
11
12 (require 'notes-variables)
13 (require 'notes-aux)
14
15 (defvar notes-mode-hooks nil
16 "Hooks to run when entering notes-mode.")
17 (defvar notes-load-mode-hooks nil
18 "Hooks to run when entering notes-mode is loaded.")
19
20 (defconst notes-beginning-of-defun-regexp "^\\* .*\n\\-"
21 "Regexp matching the beginning of notes section.")
22
23 (defvar notes-default-tab-binding nil
24 "Saved tab binding for notes-complete-subject.")
25 (defvar notes-default-return-binding nil
26 "Saved return binding for notes-electric-return.")
27
28
29 (defun notes-beginning-of-defun ()
30 "Go to the beginning of a notes ``section''."
31 (interactive)
32 (let
33 ((old-point (point)))
34 (beginning-of-line)
35 ;; handle starting on a title
36 (if (and (looking-at notes-beginning-of-defun-regexp)
37 (/= (point) old-point))
38 nil
39 (goto-char old-point)
40 (if (looking-at "^-") ;; handle starting on the underline under a title
41 (forward-char 1))
42 (generic-beginning-of-defun notes-beginning-of-defun-regexp))))
43
44 (defun notes-end-of-defun ()
45 "Go to the end of a notes ``section''."
46 (interactive)
47 (generic-end-of-defun notes-beginning-of-defun-regexp))
48
49 (defun notes-follow-link (which)
50 "Go to the WHICH link for this topic.
51 WHICH is either \"next\" or \"prev\".
52 If there are no links for the current note,
53 we go to the last note based upon the index file."
54 (let
55 (beginning-of-note
56 end-of-note
57 (start-buffer (current-buffer))
58 ;; We have to handle links in the same buffer,
59 ;; so the following code figure out where we go
60 ;; and returns it out of the save-excursion.
61 ;; If we end up in another buffer, we let the save-excursion
62 ;; leave the original buffer unchanged. If we end up in
63 ;; the same buffer, we need to go wherever we end up.
64 ;; Can anyone suggest a better way?
65 (end-buffer-and-point
66 (save-excursion
67 (notes-end-of-defun)
68 (setq end-of-note (point))
69 (notes-beginning-of-defun)
70 (setq beginning-of-note (point))
71 (if (and (= beginning-of-note 1) (not (looking-at notes-beginning-of-defun-regexp)))
72 (progn
73 ;; When "above" the first note, search to end of first
74 ;; real note (otherwise end-of-note is just the start
75 ;; of the first real note and there are no links).
76 (notes-end-of-defun)
77 (notes-end-of-defun)
78 (setq end-of-note (point))
79 (goto-char beginning-of-note)))
80 (if (re-search-forward (concat "^"
81 (if (eq which 'next) "next" "prev")
82 ":[ ]+<") end-of-note t)
83 (progn ; link exists, just take it
84 (beginning-of-line)
85 (notes-w3-follow-link (point))
86 (cons (current-buffer) (point)))
87 ;; No link; go through the index file.
88 (if (notes-goto-index-entry which)
89 (let ((index-buffer (current-buffer)))
90 (notes-index-follow-link (point))
91 (bury-buffer index-buffer))
92 (error "No known notes in that direction.")
93 (bury-buffer (current-buffer)))
94 (cons (current-buffer) (point))))))
95 ;; Check for going to the same buffer (and the save-excursion
96 ;; undoing our work).
97 (if (eq start-buffer (car end-buffer-and-point))
98 (goto-char (cdr end-buffer-and-point)))))
99
100
101 (defun notes-follow-next-link ()
102 "Go to the next link for this topic."
103 (interactive)
104 (notes-follow-link 'next))
105
106 (defun notes-follow-prev-link ()
107 "Go to the previous link for this topic."
108 (interactive)
109 (notes-follow-link 'prev))
110
111 (defvar notes-complete-subject-abbrevs-alist
112 '(("SP2010" "USC/Classes/CS551/SP2010")
113 ("FA2011" "USC/Classes/CS551/FA2011"))
114 "notes-complete-subject-abbrevs-alist provides simple substitution of subjects.
115 If subject completion is requested, then subject that matches
116 the left-side of an alist value is replaced by the right-side value.")
117
118 (defun notes-complete-subject-abbrevs (key)
119 "Handle abbreviations on notes SUBJECTS.
120 Currently this is just a hack."
121 (let ((value (assoc key notes-complete-subject-abbrevs-alist)))
122 (if value
123 (car (cdr value))
124 key)))
125
126
127 (defun notes-complete-subject ()
128 "Complete the notes subject under point."
129 (interactive)
130 (let
131 ((subject (save-excursion
132 (beginning-of-line)
133 (notes-extract-subject t)))
134 old-completion-ignore-case
135 full-subject)
136 (if (not (and notes-mode-complete-subjects subject))
137 (call-interactively notes-default-tab-binding)
138 ;; Complete the title.
139 (if (null notes-subject-table)
140 (save-excursion
141 (find-file-noselect (concat notes-dir "/index"))))
142 ;; Do completion.
143 ;; Run completer if it's loaded,
144 ;; otherwise do our own thing.
145 (setq completion-ignore-case t)
146 (cond
147 ((fboundp 'completer-complete-goto)
148 (completer-complete-goto "^ \t\n\"" " " notes-subject-table nil))
149 ;; NEEDSWORK: should try other completers, too.
150 (t ;; Do our own completion.
151 (setq full-subject (try-completion subject notes-subject-table)
152 subject (completing-read "Subject: "
153 notes-subject-table nil nil
154 (if (stringp full-subject)
155 full-subject
156 subject)))
157 (delete-region (get-beginning-of-line) (get-end-of-line))
158 (insert "* " (notes-complete-subject-abbrevs subject))))
159 (setq completion-ignore-case old-completion-ignore-case))))
160
161 (defun notes-fix-prevnext-this-entry ()
162 "* Fix up the prev link for the current entry,
163 if necessary. Currently this code only handles brand new entries."
164 ;; Contributed from Takashi Nishimoto <g96p0935@mse.waseda.ac.jp>.
165 ;; Thanks!
166 (interactive)
167 (let ((subject (notes-extract-subject nil t))
168 (this-url (notes-current-url))
169 last-url)
170 (save-excursion
171 (set-buffer (find-file-noselect (concat notes-dir "/index")))
172 (goto-char (point-min))
173 (if (re-search-forward
174 (concat "^" (regexp-quote subject) ":.* \\([0-9]+\\)$")
175 (point-max) t)
176 (save-window-excursion
177 (cond ((and (notes-w3-url
178 (notes-file-to-url (match-string 1) subject))
179 (re-search-forward "^next: " nil t)
180 (looking-at "<none>"))
181 (let
182 (pre-modified (buffer-modified-p))
183 (delete-char 6)
184 (insert this-url)
185 (setq last-url (notes-current-url))
186 (if (and (null pre-modified)
187 (>= notes-electric-prevnext 2))
188 (save-buffer))))))))
189 (if last-url
190 (progn
191 (notes-beginning-of-defun)
192 (forward-line 2)
193 (if (not (looking-at "prev: "))
194 (insert "prev: " last-url "\n" "next: <none>\n\n")
195 (forward-line 3))))))
196
197 (defun notes-electric-return (arg)
198 "* Return, underlining if we're on a subject."
199 (interactive "*P")
200 (if (let ((cur-point (point)))
201 (save-excursion
202 (beginning-of-line)
203 (and (not (eq cur-point (point))) ;; normal return if at b-o-ln
204 (notes-extract-subject t))))
205 (progn (notes-underline-line)
206 (if notes-electric-prevnext
207 (notes-fix-prevnext-this-entry)))
208 (call-interactively notes-default-return-binding)))
209
210 (defun notes-current-url ()
211 "* Returns the notes-URL of the current entry around the current point."
212 (let ((subject (notes-extract-subject nil t))
213 (date (file-name-nondirectory buffer-file-name)))
214 (concat "<file:///"
215 (abbreviate-file-name buffer-file-name)
216 (if subject (concat "#* " subject) "")
217 ">")))
218
219 (defun notes-current-url-as-kill ()
220 "* Put the notes-URL of the current entry into the kill ring."
221 (interactive)
222 (kill-new (notes-current-url)))
223
224 (defun notes-goto-index-entry (&optional direction)
225 "* Jump to the index entry corresponding to our current note entry.
226 If we're not in an entry, we leave you in the index file.
227 If the current date doesn't exist, error in DIRECTION.
228 Returns nil if on errors (no index; no date in DIRECTION),
229 otherwise the point of the hit."
230 (interactive)
231 (let ((start-buffer (current-buffer))
232 (subject (notes-extract-subject)) ; get subject if on it
233 (date (if (null (buffer-file-name)) nil
234 (file-name-nondirectory (buffer-file-name)))))
235 ;; Try and get the subject, either forward...
236 (if (not subject)
237 (save-excursion
238 (notes-beginning-of-defun)
239 (setq subject (notes-extract-subject))))
240 ;; ...or backwards.
241 (if (not subject)
242 (save-excursion
243 (notes-end-of-defun)
244 (setq subject (notes-extract-subject))))
245 ;; Form and jump to the url for the index-entry.
246 (if (and (notes-w3-url (concat notes-url-prefix
247 "index"
248 (if subject (concat "#" subject) ""))
249 nil t)
250 ;; Go to the current date, if any.
251 (notes-index-goto-date date direction))
252 t
253 nil)))
254
255 (defun notes-extract-subject (&optional relaxed search)
256 "Extract the subject under the point in the current buffer.
257 If RELAXED, then accept non-underlined subjects.
258 If SEARCH we'll search back in the buffer for the nearest
259 subject title.
260
261 Returns nil if we're not on as subject."
262 (save-match-data
263 (cond
264 ;; directly on a note
265 ((or (looking-at notes-beginning-of-defun-regexp)
266 (and relaxed
267 (looking-at "^\\* ")))
268 (save-excursion
269 (let
270 ((start (+ (point) 2))
271 (end (progn (end-of-line) (point))))
272 (buffer-substring start end))))
273 (search
274 (save-excursion
275 (notes-beginning-of-defun)
276 (notes-extract-subject relaxed nil)))
277 (t
278 nil))))
279
280
281 ;;;###autoload
282 (defun notes-underline-line ()
283 "* Create a row of dashes as long as this line, or adjust the current underline."
284 (interactive)
285 ;; check to see if it's already underlined
286 (if (save-excursion
287 (forward-line 1)
288 (looking-at "^[ \t]*--*$"))
289 (notes-old-underline-line)
290 (progn
291 (notes-new-underline-line)
292 (insert "\n\n"))))
293
294 (defun notes-new-underline-line ()
295 "Underline a line with a row of dashes. Moves the point after the dashes.
296 \\[notes-new-underline-line] reproduces leading spaces."
297 (interactive)
298 (let*
299 ((bol (progn (beginning-of-line)
300 (point)))
301 (bospaces (progn (skip-chars-forward " \t")
302 (point)))
303 (nospaces (- bospaces bol))
304 (eol (progn (end-of-line)
305 (untabify bol (point))
306 (point))))
307 (insert "\n" (buffer-substring bol bospaces))
308 (insert-char ?- (- eol bospaces))))
309
310 (defun notes-old-underline-line ()
311 "Replace the following line with a row of dashes. Leave the point unchanged."
312 (save-excursion
313 (save-excursion
314 (forward-line 1)
315 (delete-region (get-beginning-of-line) (1+ (get-end-of-line))))
316 (notes-new-underline-line)))
317
318 (defun notes-mode-initialize-note-from-cache ()
319 "Build a new note from the cache. Returns valid cache contents or nil."
320 (save-excursion
321 (let*
322 ((new-buffer (current-buffer))
323 (cache-file (concat notes-dir "/mknew.cache"))
324 (buf (find-file cache-file))
325 magic-line
326 prev-file
327 this-file
328 cache-contents
329 m
330 (result
331 (if (and buf
332 (>= (count-lines (point-min) (point-max)) 3))
333 (progn
334 ;; If you know a more elegant way to extact the first
335 ;; three lines of a file, please let me know.
336 (goto-char (point-min))
337 (setq m (point))
338 (forward-line 1)
339 (setq magic-line (buffer-substring m (- (point) 1)))
340 (setq m (point))
341 (forward-line 1)
342 (setq prev-file (buffer-substring m (- (point) 1)))
343 (setq m (point))
344 (forward-line 1)
345 (setq this-file (buffer-substring m (- (point) 1)))
346 (setq cache-contents (buffer-substring (point) (point-max)))
347 (bury-buffer buf)
348 ;; is cache valid?
349 (if
350 (and
351 (string-equal magic-line "mknew.cache 830494922")
352 (file-newer-than-file-p cache-file prev-file)
353 (string-equal (file-name-nondirectory this-file)
354 (file-name-nondirectory (buffer-file-name
355 new-buffer))))
356 cache-contents
357 nil))
358 nil)))
359 ;; Kill the buffer to avoid "buf changed, reload?" warnings.
360 (if buf
361 (kill-buffer buf))
362 result)))
363
364 (defun notes-mode-initialize-note ()
365 "Fill in an empty new note.
366 Create any directories as necessary.
367 Use the mknew cache if possible."
368 (interactive)
369 (let
370 ((dir (directory-file-name (file-name-directory (buffer-file-name)))))
371 (if (file-exists-p dir)
372 t
373 (make-directory dir t)
374 (message "New intermediate directory created.")))
375 (if notes-mode-initialization-program
376 (let
377 ((cache-contents (notes-mode-initialize-note-from-cache)))
378 (if cache-contents
379 (insert cache-contents)
380 (shell-command-on-region
381 (point-min)
382 (point-max)
383 (concat notes-bin-dir "/" notes-mode-initialization-program " '"
384 (buffer-file-name) "'") 't)))))
385
386 \f
387 ;;;
388 ;;; encryption
389 ;;; requires "PEM - PGP Enhanced Messaging for GNU Emacs"
390 ;;; from Roy Frederick Busdiecker, III (Rick)
391 ;;; or mailcrypt 3.4.x or >=3.5.x
392 ;;;
393
394 (defvar notes-encryption-library
395 'mailcrypt
396 ; (cond
397 ; ((fboundp 'mc-encrypt-region) 'mailcrypt)
398 ; ((fboundp 'npgp:encrypt-region) 'npgp)
399 ; (t nil))
400 "what pgp library to use")
401
402 (defvar notes-encryption-sub-library
403 'gpg
404 "what variant of mailcrypt to use ('pgp 'pgp50 'gpg).")
405
406 (defvar notes-encryption-npgp-userid nil
407 "PGP key for the current user.")
408
409 (defvar notes-encryption-npgp-key-id nil
410 "Keyid of PGP key for the current user.
411 Useful if your \\[user-full-name] doesn't match a unique key.
412 Should have a leading 0x.")
413
414 (defun notes-encryption-npgp-userid ()
415 "Return notes-encryption-userid, initializing it if necessary."
416 (require 'pam)
417 (if (and notes-encryption-userid
418 npgp:*pass-phrases*)
419 notes-encryption-userid
420 (setq notes-encryption-userid
421 (list
422 (if notes-encryption-key-id
423 (npgp:get-key-by-key-id notes-encryption-key-id)
424 (pam:read-name-key (user-full-name)))))))
425
426 (defun notes-encryption-mailcrypt-keyid ()
427 "Do the right thing."
428 (require 'mailcrypt)
429 (cond
430 ((eq notes-encryption-sub-library 'pgp)
431 (cdr (mc-pgp-lookup-key mc-pgp-user-id)))
432 ((eq notes-encryption-sub-library 'pgp50)
433 (cdr (mc-pgp50-lookup-key mc-pgp50-user-id)))
434 ((eq notes-encryption-sub-library 'gpg)
435 (cdr (mc-gpg-lookup-key mc-gpg-user-id)))
436 (t (error "notes-encryption-decrypt-region: no pgp sub-library."))))
437
438 (defun notes-encryption-load-mailcrypt ()
439 (require 'mailcrypt)
440 ;; ick ick ick this code needs to be cleaned up
441 (cond
442 ((null (eq notes-encryption-library 'mailcrypt))
443 t)
444 ((eq notes-encryption-sub-library 'pgp)
445 (load-library "mc-pgp"))
446 ((eq notes-encryption-sub-library 'pgp50)
447 (load-library "mc-pgp5"))
448 ((eq notes-encryption-sub-library 'gpg)
449 (load-library "mc-gpg"))
450 (t (error "notes-encryption-load-mailcrypt: no pgp sub-library."))))
451
452 (defun notes-encryption-decrypt-region (start end)
453 (cond
454 ((eq notes-encryption-library 'npgp)
455 (require 'pam)
456 (require 'npgp)
457 (npgp:decrypt-region start end))
458 ((eq notes-encryption-library 'mailcrypt)
459 (notes-encryption-load-mailcrypt)
460 (cond
461 ((eq notes-encryption-sub-library 'pgp)
462 (mc-pgp-decrypt-region start end))
463 ((eq notes-encryption-sub-library 'pgp50)
464 (mc-pgp50-decrypt-region start end))
465 ((eq notes-encryption-sub-library 'gpg)
466 (mc-gpg-decrypt-region start end))
467 (t (error "notes-encryption-decrypt-region: no pgp sub-library."))))
468 (t (error "notes-encryption-decrypt-region: no pgp library."))))
469
470 (defun notes-encryption-encrypt-region (start end)
471 (cond
472 ((eq notes-encryption-library 'npgp)
473 (npgp:encrypt-region (notes-encryption-npgp-userid) start end))
474 ((eq notes-encryption-library 'mailcrypt)
475 (notes-encryption-load-mailcrypt)
476 (let ((old-sign mc-pgp-always-sign)
477 old-comment recipients)
478 (setq mc-pgp-always-sign 'never
479 recipients (list (notes-encryption-mailcrypt-keyid)))
480 (cond
481 ((eq notes-encryption-sub-library 'pgp)
482 (setq old-comment mc-pgp-comment
483 mc-pgp-comment "")
484 (mc-pgp-encrypt-region recipients start end
485 (notes-encryption-mailcrypt-keyid) nil)
486 (setq mc-pgp-comment old-comment))
487 ((eq notes-encryption-sub-library 'pgp50)
488 (setq old-comment mc-pgp50-comment
489 mc-pgp50-comment "")
490 (mc-pgp50-encrypt-region recipients start end
491 (notes-encryption-mailcrypt-keyid) nil)
492 (setq mc-pgp50-comment old-comment))
493 ((eq notes-encryption-sub-library 'gpg)
494 (setq old-comment mc-gpg-comment
495 mc-gpg-comment "")
496 (mc-gpg-encrypt-region recipients start end
497 (notes-encryption-mailcrypt-keyid) nil)
498 (setq mc-gpg-comment old-comment))
499 (t (error "notes-encryption-decrypt-region: no gpg sub-library.")))
500 (setq mc-pgp-always-sign old-sign)))
501 (t (error "notes-encryption-decrypt-region: no pgp library."))))
502
503 (defun notes-encrypt-note (prefix)
504 "Encrypt the current note for the current user. With PREFIX, start from point."
505 (interactive "P")
506 (save-excursion
507 (let (start end)
508 ;; Unless a prefix arg, start at beginning-of-note.
509 (if prefix
510 nil
511 (if (not (looking-at notes-beginning-of-defun-regexp))
512 (notes-beginning-of-defun))
513 ;; skip over the header
514 (while (and (or (looking-at notes-beginning-of-defun-regexp)
515 (looking-at "^-+$")
516 (looking-at "^\\(prev\\|next\\): ")
517 (looking-at "^[ \t]*$"))
518 (< (point) (point-max)))
519 (forward-line 1)))
520 (setq start (point))
521 ;; sanity check
522 (if (re-search-forward "^-----BEGIN PGP MESSAGE"
523 (progn
524 (save-excursion
525 (notes-end-of-defun)
526 (point))) t)
527 (error "Note is already encrypted."))
528 ;; find the end
529 (notes-end-of-defun)
530 (while (or (looking-at notes-beginning-of-defun-regexp)
531 (looking-at "^[ \t]*$"))
532 (forward-line -1))
533 (forward-line 1)
534 (setq end (point))
535 (notes-encryption-encrypt-region start end))))
536
537 (defun notes-decrypt-note ()
538 "Decrypt the current note for the current user."
539 (interactive)
540 (save-excursion
541 (if (not (looking-at notes-beginning-of-defun-regexp))
542 (notes-beginning-of-defun))
543 (if (null (re-search-forward "^-----BEGIN PGP"
544 (progn
545 (save-excursion
546 (notes-end-of-defun)
547 (point))) t))
548 (error "Note is not encrypted."))
549 (beginning-of-line)
550 (let ((start (point)))
551 (if (null (re-search-forward "^-----END PGP"
552 (progn
553 (save-excursion
554 (notes-end-of-defun)
555 (point))) t))
556 (error "Could not find end of encrypted note."))
557 (forward-line)
558 (beginning-of-line)
559 (notes-encryption-decrypt-region start (point)))))
560
561 \f
562 ;;;
563 ;;; notes or notes-index?
564 ;;;
565 (defun notes-summarize-subject (regexp-subject &optional subject)
566 "* Collect all of a subject."
567 (interactive "P")
568 (require 'notes-index-mode)
569 (if (null subject)
570 (cond
571 ((eq major-mode 'notes-mode)
572 (setq subject (notes-extract-subject nil t)))
573 ((eq major-mode 'notes-index-mode)
574 (setq subject (notes-index-extract-subject)))))
575 (if (null subject)
576 (error "notes-summarize-subject: no subject specified or inferable."))
577 (let
578 ((buf (get-buffer-create (concat "*notes on " subject "*"))))
579 (pop-to-buffer buf)
580 (erase-buffer)
581 (apply 'call-process (concat notes-bin-dir "/catsubject") nil buf t
582 (if regexp-subject
583 (list "-m" subject)
584 (list subject)))
585 (notes-mode)))
586
587 \f
588 ;;;
589 ;;; notes-rename-subject
590 ;;;
591 (defun notes-rename-subject ()
592 "* Rename the current subject.
593 Assumes working next/prev linkage between the entries."
594 (interactive)
595 (let ((subject (notes-extract-subject)))
596 (condition-case nil
597 (progn
598 (end-of-line)
599 (beginning-of-defun)
600 (if (not (looking-at "* "))
601 (error "confused"))
602 (forward-char 2)
603 (error "not yet done")
604 )
605 (error nil))))
606
607 \f
608 ;;;
609 ;;; notes-mode
610 ;;;
611
612 ;;
613 ;; This use of define-derived-mode is a crock---maybe
614 ;; it's better to eval it?
615 ;; suggestions are welcome. ---johnh, 26-Oct-98
616 ;;
617 (if (fboundp 'indented-text-mode)
618 (define-derived-mode notes-mode indented-text-mode "Notes"
619 "See notes-mode-internal for documentation."
620 (notes-mode-internal))
621 (define-derived-mode notes-mode text-mode "Notes"
622 "See notes-mode-internal for documentation."
623 (notes-mode-internal)))
624
625
626 (defun notes-mode-internal ()
627 "Enable notes-mode for a buffer.
628
629 Inside a notes buffer one can click on URLs and follow them to
630 other notes files.
631
632 Notes are fontified if notes-use-font-lock is set.
633 See the file notes-variables.el for all customization options.
634 To change options, (require 'notes-variables) in your .emacs
635 and then change things.
636
637 Subjects in notes mode are lines beginning with an asterisk
638 and underlined with dashes. Subjects can be completed
639 with \\[notes-complete-subject] and are automatically underlined.
640
641 You may wish to add this code to your .emacs file:
642 (setq auto-mode-alist
643 (cons (cons \"/9[0-9][0-9][0-9][0-9][0-9].?$\" 'notes-mode)
644 auto-mode-alist))
645 (define-key global-map \"\C-cn\" 'notes-index-todays-link)
646 to automatically enter notes mode.
647
648 I have two suggestions for how to organize your notes files.
649 First, I collect my notes into a separate file per day. (If you have
650 fewer notes, you may find once-per-week or month more suitable.)
651 Second, at the beginning of each file I have a subject \"* Today\".
652 Since every file has this subject, I can use its prev and next links
653 to easily move around the collection of files.
654
655 The key-bindings of this mode are:
656 \\{notes-mode-map}"
657 (interactive) ;; just so documentation can come up
658
659 (notes-platform-init)
660
661 ;; bug workaround:
662 ;; Emacs-19.30's define-derived-mode sets up a bogus syntax-table.
663 ;; (Evidence for the error is ``Wrong type argument: consp, nil''
664 ;; when typing in the buffer.)
665 ;;
666 ;; bug work-around 2:
667 ;; Klaus Zeitler <kzeitler@lucent.com>
668 ;; reports that the next line dies in emacs-21.1 with the error:
669 ;; "Attempt to make a chartable be its own parent".
670 ;; Work-around: more hackery.
671 (if (and (< emacs-major-version 21)
672 (or (>= emacs-major-version 20) (>= emacs-minor-version 30)))
673 (set-syntax-table (setq notes-mode-syntax-table text-mode-syntax-table)))
674
675 ;; now set up the mode
676 (auto-fill-mode 1)
677
678 ;; random key-bindings
679 (define-key notes-mode-map "\M-\C-a" 'notes-beginning-of-defun)
680 (define-key notes-mode-map "\M-\C-e" 'notes-end-of-defun)
681 (define-key notes-mode-map "\C-c\C-d" 'notes-decrypt-note)
682 (define-key notes-mode-map "\C-c\C-e" 'notes-encrypt-note)
683 (define-key notes-mode-map "\C-c\r" 'notes-w3-follow-link)
684 (define-key notes-mode-map "\C-c\C-p" 'notes-follow-prev-link)
685 (define-key notes-mode-map "\C-c\C-n" 'notes-follow-next-link)
686 (define-key notes-mode-map "\C-c\C-i" 'notes-goto-index-entry)
687 (define-key notes-mode-map "\C-c\C-k" 'notes-current-url-as-kill)
688 (define-key notes-mode-map "\C-c\C-s" 'notes-summarize-subject)
689 (define-key notes-mode-map "\C-c-" 'notes-underline-line)
690 (if (null notes-default-tab-binding)
691 (setq notes-default-tab-binding (key-binding "\t")))
692 (define-key notes-mode-map "\t" 'notes-complete-subject)
693 (if (null notes-default-return-binding)
694 (setq notes-default-return-binding (key-binding "\r")))
695 (define-key notes-mode-map "\r" 'notes-electric-return)
696 (define-key notes-mode-map "\n" 'notes-electric-return) ; a more common synonym
697 (notes-platform-bind-mouse notes-mode-map 'S-mouse-2 'notes-w3-follow-link-mouse)
698
699 ;; imenu stuff
700 (make-variable-buffer-local 'imenu-prev-index-position-function)
701 (make-variable-buffer-local 'imenu-extract-index-name-function)
702 (setq imenu-prev-index-position-function 'notes-beginning-of-defun)
703 (setq imenu-extract-index-name-function 'notes-extract-subject)
704
705 (if notes-use-font-lock
706 (notes-platform-font-lock notes-font-lock-keywords))
707
708 ;; finally, try to fill in an empty note
709 (if (eq (point-min) (point-max))
710 (notes-mode-initialize-note))
711
712 ;; Enable outline-minor-mode (forcebly, in case someone already
713 ;; has it in their text-mode hook). Bug found by
714 ;; Nils Ackermann <nils@nieback.de>.
715 (if notes-use-outline-mode
716 (outline-minor-mode 1))
717
718 (delay-mode-hooks
719 (run-mode-hooks 'notes-mode-hooks)))
720
721
722
723 \f
724 ;;;
725
726 (run-hooks 'notes-mode-load-hooks)
727 (provide 'notes-mode)
728