1 ;;; notes-index-mode.el --- Index manipulation for notes-mode
3 ;; Copyright (C) 1994-1998,2012 Free Software Foundation, Inc.
5 ;; Author: <johnh@isi.edu>
7 ;; This file is part of GNU Emacs.
9 ;; GNU Emacs is free software: you can redistribute it and/or modify
10 ;; it under the terms of the GNU General Public License as published by
11 ;; the Free Software Foundation, either version 3 of the License, or
12 ;; (at your option) any later version.
14 ;; GNU Emacs is distributed in the hope that it will be useful,
15 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 ;; GNU General Public License for more details.
19 ;; You should have received a copy of the GNU General Public License
20 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
26 (require 'notes-variables)
30 (defvar notes-index-mode-map
31 (let ((map (make-sparse-keymap)))
32 ;; There were bindings to make mouse-1 do pointer following,
33 ;; but I removed it because all the rest of emacs uses mouse-2.
34 ;; If you want them, add them with notes-index-mode-hook.
35 (notes-platform-bind-mouse map 'mouse-2 'notes-index-mouse-follow-link)
36 (notes-platform-bind-mouse map 'S-mouse-2 'notes-index-mouse-follow-link-other-window)
37 (define-key map "\r" 'notes-index-follow-link)
38 (define-key map "\C-c\C-s" 'notes-summarize-subject)
39 (define-key map "o" 'notes-index-link)
43 (defvar notes-index-lazy-message-old-time 0)
45 (defun notes-index-lazy-percent-message (text fraction whole)
46 "Put up a message occasionally.
47 Displays TEXT (a format string), with FRACTION of WHOLE
48 shown as a percentage. (Read the code to see what this
49 cryptic statement means.)"
50 (if (= notes-index-lazy-message-old-time
51 (setq notes-index-lazy-message-old-time (+ 1 (nth 1 (current-time)))))
53 (message text (/ (* fraction 100) whole))))
55 (defun notes-index-parse-buffer ()
56 "Parse a notes-index buffer, fontifying and building subject completion.
58 If fontification is enabled, subjects will be emboldened
59 and dates will be mouse-highlighted.
61 In any event a subject completion table will be built.
63 This routine works by calling either \[notes-index-parse-buffer-uncached]
64 or \[notes-index-parse-buffer-cached] (if possible)."
67 ((inhibit-read-only t))
68 (if (and (file-exists-p (expand-file-name "index_cache.el" notes-dir))
69 (file-newer-than-file-p
70 (expand-file-name "index_cache.el" notes-dir)
71 (expand-file-name "index" notes-dir)))
73 (load (expand-file-name "index_cache" notes-dir))
74 (notes-index-parse-buffer-cached))
76 (message "notes-index-parse-buffer: cache is not present or is not up-to-date")
77 (notes-index-parse-buffer-uncached))
78 ;; clean some things up
80 (set-buffer-modified-p nil)))
82 (defun notes-index-parse-buffer-uncached ()
83 "Parse a notes-index buffer, fontifying and building subject completion.
85 If fontification is enabled, subjects will be emboldened
86 and dates will be mouse-highlighted.
88 In any event a subject completion table will be built.
90 Tenses passive will be."
93 (let ((start (point-min))
96 (if notes-use-font-lock
97 ;; FIXME: That's quite drastic! What is this trying to do?
98 (set-text-properties (point-min) (point-max) nil))
99 ;; There used to be problem that we used a fixed obarray length,
100 ;; creating a lot of hash collisions. Now we dynamically compute it
101 ;; by rounding up the number of lines to the next power of 8.
102 (if (and notes-mode-complete-subjects (not notes-subject-table))
103 (setq notes-subject-table (make-vector
116 (while (< start (point-max))
117 ;; find the end-of-line
123 (while (not (eq (following-char) ?\ ))
124 (skip-chars-forward "^:" end)
127 (if notes-subject-table
128 (intern (buffer-substring start (point)) notes-subject-table))
129 (notes-index-lazy-percent-message "Notes-index'ing (%d%%)..." start (point-max))
131 (if notes-use-font-lock
133 ;; highlight the title
134 (put-text-property start (point) 'face notes-bold-face)
135 (if notes-index-fontify-dates
137 ;; now highlight each date
138 (skip-chars-forward "^0-9" end)
139 (while (looking-at "[0-9]")
141 (skip-chars-forward "0-9")
142 (put-text-property start (point) 'mouse-face 'highlight)
143 (skip-chars-forward "^0-9" end))))))
144 ;; set up for next line
146 (setq start (point))))))
149 (defun notes-index-date-search (start end iter-proc done-proc done-arg)
150 "Iterate over a notes-index entry bounded by START to END.
151 Iteration is done by (ITER-PROC END), which leaves match 0
152 set to what we're looking for.
153 A match terminates iteration if (DONE-PROC match DONE-ARG) is non-nil.
154 Returns the buffer position of a successful hit, or nil."
157 (while (and (not stop)
158 (funcall iter-proc end))
159 (if (funcall done-proc (match-string 0) done-arg)
160 (setq stop (goto-char (match-beginning 0)))))
164 (defun notes-index-goto-date (date &optional direction)
165 "Goto the DATE in the current line of the index file, modified by DIRECTION.
166 If DIRECTION is 'this, go there.
167 If DIRECTION is 'next or 'prev, go to the corresponding entry.
168 If the entry doesn't exist, then go to the nearest entry according
169 to DIRECTION (and the next one if DIRECTION is 'this)."
171 ((eq direction 'prev)
172 (notes-index-date-search
173 (line-end-position) (line-beginning-position)
174 (function (lambda (end) (re-search-backward notes-file-regexp end t)))
175 (function (lambda (trial target) (string-lessp trial target)))
177 ((eq direction 'next)
178 (notes-index-date-search
179 (line-beginning-position) (line-end-position)
180 (function (lambda (end) (re-search-forward notes-file-regexp end t)))
181 (function (lambda (trial target) (string-lessp target trial)))
184 (notes-index-date-search
185 (line-beginning-position) (line-end-position)
186 (function (lambda (end) (re-search-forward notes-file-regexp end t)))
187 (function (lambda (trial target) (string-equal trial target)))
190 (defun notes-index-link (link &optional tag where)
191 "* Follow a notes-index LINK.
192 Optionally takes a subject TAG and
193 WHERE ('otherwindow or nil) to open the new file."
194 (interactive "sNotes-index link: ")
195 (notes-w3-url (notes-file-to-url link tag) where t))
198 (defun notes-index-todays-link ()
199 "* Open the notes file for today."
201 (notes-index-link (format-time-string notes-file-form (current-time))))
203 (defun notes-index-follow-link (pt &optional where)
204 "Follow a link at PT in notes-index-mode.
205 The link is taken from the location PT,
206 and the new information is shown WHERE (either 'otherwindow or not)."
209 (let (start date tag)
210 ;; determine the date
211 (skip-chars-backward "0-9")
213 (if (not (re-search-forward notes-file-regexp (+ (point) 6) t))
214 (error "Not on notes-index-mode link."))
215 (setq date (match-string 0))
218 (if (not (re-search-forward "^\\([^:]*\\):" start t))
219 (error "Not on notes-index-mode link line."))
220 (setq tag (match-string 1))
221 ;; make and process the url
222 (notes-index-link date tag where))))
224 (defun notes-index-mouse-follow-link (e)
225 "Handle a mouse click in notes-index-mode."
228 (notes-index-follow-link (point) nil))
230 (defun notes-index-mouse-follow-link-other-window (e)
231 "Handle a mouse click in notes-index-mode (other-window)."
234 (notes-index-follow-link (point) 'otherwindow))
236 (defun notes-index-extract-subject ()
237 "Extract the notes-index subject for the current line."
240 (if (re-search-forward "^\\(.*\\): " (line-end-position) t)
245 (define-derived-mode notes-index-mode special-mode "Notes-index"
246 "Notes-index-mode with mouse support.
248 You may wish to change notes-bold-face and notes-use-font-lock.
250 There should be no need to add notes-index-mode to auto-mode-alist
251 since the index generation functions add code to the index file
252 which invokes notes-index-mode.
255 \\{notes-index-mode-map}"
256 (notes-platform-init)
258 (notes-index-parse-buffer)
260 (set (make-local-variable 'font-lock-defaults)
261 '(notes-index-font-lock-keywords
262 t nil nil beginning-of-line))
264 ;; No editing is allowed.
265 (setq buffer-read-only t)
268 (provide 'notes-index-mode)
269 ;;; notes-index-mode.el ends here