88155
|
1 ;;; idlw-help.el --- HTML Help code for IDLWAVE
|
|
2 ;; Copyright (c) 2000 Carsten Dominik
|
|
3 ;; Copyright (c) 2001, 2002 J.D. Smith
|
|
4 ;; Copyright (c) 2003, 2004, 2005, Free Software Foundation
|
|
5 ;;
|
|
6 ;; Authors: J.D. Smith <jdsmith@as.arizona.edu>
|
|
7 ;; Carsten Dominik <dominik@science.uva.nl>
|
|
8 ;; Maintainer: J.D. Smith <jdsmith@as.arizona.edu>
|
|
9 ;; Version: 5.7_22
|
|
10
|
|
11 ;; This file is part of GNU Emacs.
|
|
12
|
|
13 ;; This file is free software; you can redistribute it and/or modify
|
|
14 ;; it under the terms of the GNU General Public License as published by
|
|
15 ;; the Free Software Foundation; either version 2, or (at your option)
|
|
16 ;; any later version.
|
|
17
|
|
18 ;; This file is distributed in the hope that it will be useful,
|
|
19 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
20 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
21 ;; GNU General Public License for more details.
|
|
22
|
|
23 ;; You should have received a copy of the GNU General Public License
|
|
24 ;; along with GNU Emacs; see the file COPYING. If not, write to the
|
|
25 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
26 ;; Boston, MA 02110-1301, USA.
|
|
27
|
|
28 ;;; Commentary:
|
|
29
|
|
30 ;; The help link information for IDLWAVE's online help feature for
|
|
31 ;; system routines is extracted automatically from the IDL
|
|
32 ;; documentation, and is available, along with general routine
|
|
33 ;; information, in the file idlw-rinfo.el. The HTML help file
|
|
34 ;; themselves are not distributable with Emacs, but are available,
|
|
35 ;; along with new versions of IDLWAVE, documentation, and more
|
|
36 ;; information, at:
|
|
37 ;;
|
|
38 ;; http://idlwave.org
|
|
39 ;;
|
|
40 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
41
|
|
42
|
|
43 ;;; Code:
|
|
44 (defvar browse-url-generic-args)
|
|
45
|
|
46 (defvar idlwave-help-browse-url-available nil
|
|
47 "Whether browse-url is available")
|
|
48
|
|
49 (setq idlwave-help-browse-url-available
|
|
50 (condition-case nil
|
|
51 (require 'browse-url)
|
|
52 (error nil)))
|
|
53
|
|
54 (defgroup idlwave-online-help nil
|
|
55 "Online Help options for IDLWAVE mode."
|
|
56 :group 'idlwave)
|
|
57
|
|
58 (defcustom idlwave-html-help-pre-v6 nil
|
|
59 "Whether pre or post-v6.0 IDL help documents are being used."
|
|
60 :group 'idlwave-online-help
|
|
61 :type 'boolean)
|
|
62
|
|
63 (defvar idlwave-html-link-sep
|
|
64 (if idlwave-html-help-pre-v6 "#" "#wp"))
|
|
65
|
|
66 (defcustom idlwave-html-help-location
|
|
67 (if (memq system-type '(ms-dos windows-nt))
|
|
68 nil
|
|
69 "/usr/local/etc/")
|
|
70 "The directory where the idl_html_help/ dir or idl.chm help file
|
|
71 (Windows only) lives."
|
|
72 :group 'idlwave-online-help
|
|
73 :type 'directory)
|
|
74
|
|
75 (defcustom idlwave-help-use-hh nil
|
|
76 "Whether to use the HTMLHelp viewer with idl.chm (Windows only)."
|
|
77 :group 'idlwave-online-help
|
|
78 :type '(choice :tag "use help viewer"
|
|
79 (const :tag "<none>" nil)
|
|
80 (const :tag "hh" 'hh)
|
|
81 (const :tag "keyhh" 'keyhh)))
|
|
82
|
|
83 (defcustom idlwave-help-browser-function browse-url-browser-function
|
|
84 "Function to use to display html help.
|
|
85 Defaults to `browse-url-browser-function', which see."
|
|
86 :group 'idlwave-online-help
|
|
87 :type 'function)
|
|
88
|
|
89 (defcustom idlwave-help-browser-generic-program browse-url-generic-program
|
|
90 "Program to run if using browse-url-generic-program."
|
|
91 :group 'idlwave-online-help
|
|
92 :type 'string)
|
|
93
|
|
94 (defcustom idlwave-help-browser-generic-args
|
|
95 (if (boundp 'browse-url-generic-args)
|
|
96 browse-url-generic-args "")
|
|
97 "Program args to use if using browse-url-generic-program."
|
|
98 :group 'idlwave-online-help
|
|
99 :type 'string)
|
|
100
|
|
101 (defcustom idlwave-help-browser-is-local nil
|
|
102 "Whether the browser will display locally in an Emacs window.
|
|
103 Several browsers run and/or display inside Emacs windows, but most are
|
|
104 external programs. If the browser name contains \"-w3\", it is
|
|
105 assumed to be local to Emacs. For other local browsers, this variable
|
|
106 must be explicitly set non-nil in order for the variable
|
|
107 `idlwave-help-use-dedicated-frame' to function."
|
|
108 :group 'idlwave-online-help
|
|
109 :type 'boolean)
|
|
110
|
|
111 (defvar idlwave-help-directory ""
|
|
112 "Obsolete variable. See idlwave-html-help-location.")
|
|
113
|
|
114 (defcustom idlwave-help-use-dedicated-frame t
|
|
115 "*Non-nil means, use a separate frame for Online Help if possible."
|
|
116 :group 'idlwave-online-help
|
|
117 :type 'boolean)
|
|
118
|
|
119 (defcustom idlwave-help-frame-parameters
|
|
120 '((height . 32) (unsplittable . t))
|
|
121 "The frame parameters for the special Online Help frame.
|
|
122 See also `idlwave-help-use-dedicated-frame'.
|
|
123 If you do not set the frame width here, the value specified in
|
|
124 `idlw-help.el' will be used."
|
|
125 :group 'idlwave-online-help
|
|
126 :type '(repeat
|
|
127 (cons symbol sexp)))
|
|
128
|
|
129 (defcustom idlwave-max-popup-menu-items 20
|
|
130 "Maximum number of items per pane in popup menus.
|
|
131 Currently only used for class selection during completion help."
|
|
132 :group 'idlwave-online-help
|
|
133 :type 'integer)
|
|
134
|
|
135 (defcustom idlwave-extra-help-function 'idlwave-help-with-source
|
|
136 "The function to call for online help if the normal help fails.
|
|
137 Online help works only for system routines which are described in the
|
|
138 IDL manuals. A function may be specified to access help from other sources.
|
|
139
|
|
140 The function must accept four arguments: NAME, TYPE, CLASS, KEYWORD.
|
|
141 The Help buffer is current when this function is called, and the help
|
|
142 text should be loaded into this buffer. If help is found, the
|
|
143 function should return the buffer position which should be used as
|
|
144 `window-start' in the help window. Also, the variable
|
|
145 `idlwave-help-mode-line-indicator' should be set to a useful string,
|
|
146 which will be displayed in the mode line of the help window. If
|
|
147 should also set the variable `idlwave-help-min-frame-width' to a
|
|
148 positive integer. IDLWAVE will ensure that the help frame is at least
|
|
149 that many columns wide. Failure to find help should be indicated by
|
|
150 throwing an error.
|
|
151
|
|
152 When this variable is non-nil, IDLWAVE will allow the mouse-3 help click
|
|
153 for every routine and keyword, even though the item may not be highlighted
|
|
154 in blue (indicating the availability of system documentation).
|
|
155
|
|
156 The default value for this function is `idlwave-help-with-source' which
|
|
157 loads the routine source file into the help buffer. If you try to write
|
|
158 a different function which accesses a special help file or so, it is
|
|
159 probably a good idea to still call this function as a fallback."
|
|
160 :group 'idlwave-online-help
|
|
161 :type 'symbol)
|
|
162
|
|
163 (defcustom idlwave-help-fontify-source-code nil
|
|
164 "*Non-nil means, fontify source code displayed as help like normal code."
|
|
165 :group 'idlwave-online-help
|
|
166 :type 'boolean)
|
|
167
|
|
168 (defcustom idlwave-help-source-try-header t
|
|
169 "*Non-nil means, try to find help in routine header when displaying source.
|
|
170 Routines which are not documented in the system manual use their source as
|
|
171 help text. When this variable is non-nil, we try to find a description of
|
|
172 the help item in the first routine doclib header above the routine definition.
|
|
173 If the variable is nil, or if we cannot find/parse the header, the routine
|
|
174 definition is displayed instead."
|
|
175 :group 'idlwave-online-help
|
|
176 :type 'boolean)
|
|
177
|
|
178
|
|
179 (defcustom idlwave-help-doclib-name "name"
|
|
180 "*A regexp for the heading word to search for in doclib headers
|
|
181 which specifies the `name' section. Can be used for localization
|
|
182 support."
|
|
183 :group 'idlwave-online-help
|
|
184 :type 'string)
|
|
185
|
|
186 (defcustom idlwave-help-doclib-keyword "KEYWORD"
|
|
187 "*A regexp for the heading word to search for in doclib headers
|
|
188 which specifies the `keywords' section. Can be used for localization
|
|
189 support."
|
|
190 :group 'idlwave-online-help
|
|
191 :type 'string)
|
|
192
|
|
193 (defface idlwave-help-link
|
|
194 '((((class color)) (:foreground "Blue"))
|
|
195 (t (:weight bold)))
|
|
196 "Face for highlighting links into IDLWAVE online help."
|
|
197 :group 'idlwave-online-help)
|
|
198
|
|
199 (defvar idlwave-help-activate-links-aggressively nil
|
|
200 "Obsolete variable.")
|
|
201
|
|
202 (defvar idlwave-completion-help-info)
|
|
203
|
|
204 (defvar idlwave-help-frame nil
|
|
205 "The frame for display of IDL online help.")
|
|
206 (defvar idlwave-help-frame-width 102
|
|
207 "The default width of the help frame.")
|
|
208
|
|
209 (defvar idlwave-html-help-is-available nil
|
|
210 "Is the system online help text avaiable?")
|
|
211
|
|
212 (defvar idlwave-help-mode-line-indicator ""
|
|
213 "Used for the special mode line in the idlwave-help-mode.")
|
|
214
|
|
215 (defvar idlwave-help-window-configuration nil)
|
|
216 (defvar idlwave-help-special-topic-words nil) ; defined by get_rinfo
|
|
217
|
|
218 ;; Define the key bindings for the Help application
|
|
219
|
|
220 (defvar idlwave-help-mode-map (make-sparse-keymap)
|
|
221 "The keymap used in idlwave-help-mode.")
|
|
222
|
|
223 (define-key idlwave-help-mode-map "q" 'idlwave-help-quit)
|
|
224 (define-key idlwave-help-mode-map "w" 'widen)
|
|
225 (define-key idlwave-help-mode-map "\C-m" (lambda (arg)
|
|
226 (interactive "p")
|
|
227 (scroll-up arg)))
|
|
228 (define-key idlwave-help-mode-map " " 'scroll-up)
|
|
229 (define-key idlwave-help-mode-map [delete] 'scroll-down)
|
|
230 (define-key idlwave-help-mode-map "h" 'idlwave-help-find-header)
|
|
231 (define-key idlwave-help-mode-map "H" 'idlwave-help-find-first-header)
|
|
232 (define-key idlwave-help-mode-map "." 'idlwave-help-toggle-header-match-and-def)
|
|
233 (define-key idlwave-help-mode-map "F" 'idlwave-help-fontify)
|
|
234 (define-key idlwave-help-mode-map "\M-?" 'idlwave-help-return-to-calling-frame)
|
|
235 (define-key idlwave-help-mode-map "x" 'idlwave-help-return-to-calling-frame)
|
|
236
|
|
237 ;; Define the menu for the Help application
|
|
238
|
|
239 (easy-menu-define
|
|
240 idlwave-help-menu idlwave-help-mode-map
|
|
241 "Menu for Help IDLWAVE system"
|
|
242 '("IDLHelp"
|
|
243 ["Definition <-> Help Text" idlwave-help-toggle-header-match-and-def t]
|
|
244 ["Find DocLib Header" idlwave-help-find-header t]
|
|
245 ["Find First DocLib Header" idlwave-help-find-first-header t]
|
|
246 ["Fontify help buffer" idlwave-help-fontify t]
|
|
247 "--"
|
|
248 ["Quit" idlwave-help-quit t]))
|
|
249
|
|
250 (defvar idlwave-help-def-pos)
|
|
251 (defvar idlwave-help-args)
|
|
252 (defvar idlwave-help-in-header)
|
|
253
|
|
254 (defun idlwave-help-mode ()
|
|
255 "Major mode for displaying IDL Help.
|
|
256
|
|
257 This is a VIEW mode for the ASCII version of IDL Help files,
|
|
258 with some extras. Its main purpose is speed - so don't
|
|
259 expect a fully hyper-linked help.
|
|
260
|
|
261 Scrolling: SPC DEL RET
|
|
262 Text Searches: Inside Topic: Use Emacs search functions
|
|
263 Exit: [q]uit or mouse button 3 will kill the frame
|
|
264
|
|
265 When the hep text is a source file, the following commands are available
|
|
266
|
|
267 Fontification: [F]ontify the buffer like source code
|
|
268 Jump: [h] to function doclib header
|
|
269 [H] to file doclib header
|
|
270 [.] back and forward between header and definition
|
|
271
|
|
272 Here are all keybindings.
|
|
273 \\{idlwave-help-mode-map}"
|
|
274 (kill-all-local-variables)
|
|
275 (buffer-disable-undo)
|
|
276 (setq major-mode 'idlwave-help-mode
|
|
277 mode-name "IDLWAVE Help")
|
|
278 (use-local-map idlwave-help-mode-map)
|
|
279 (easy-menu-add idlwave-help-menu idlwave-help-mode-map)
|
|
280 (setq truncate-lines t)
|
|
281 (setq case-fold-search t)
|
|
282 (setq mode-line-format
|
|
283 (list ""
|
|
284 'mode-line-modified
|
|
285 'mode-line-buffer-identification
|
|
286 ": " 'idlwave-help-mode-line-indicator
|
|
287 " -%-"))
|
|
288 (setq buffer-read-only t)
|
|
289 (set (make-local-variable 'idlwave-help-def-pos) nil)
|
|
290 (set (make-local-variable 'idlwave-help-args) nil)
|
|
291 (set (make-local-variable 'idlwave-help-in-header) nil)
|
|
292 (run-mode-hooks 'idlwave-help-mode-hook))
|
|
293
|
|
294 (defvar idlwave-system-directory)
|
|
295 (defun idlwave-html-help-location ()
|
|
296 "Return the help directory where HTML files are, or nil if that is unknown."
|
|
297 (or (and (stringp idlwave-html-help-location)
|
|
298 (> (length idlwave-html-help-location) 0)
|
|
299 (file-directory-p idlwave-html-help-location)
|
|
300 idlwave-html-help-location)
|
|
301 (getenv "IDLWAVE_HELP_LOCATION")
|
|
302 (and (memq system-type '(ms-dos windows-nt)) ; Base it on sysdir
|
|
303 idlwave-help-use-hh
|
|
304 (stringp idlwave-system-directory)
|
|
305 (> (length idlwave-system-directory) 0)
|
|
306 (file-directory-p idlwave-system-directory)
|
|
307 (expand-file-name "HELP" idlwave-system-directory))))
|
|
308
|
|
309 (defvar idlwave-current-obj_new-class)
|
|
310 (defvar idlwave-help-diagnostics)
|
|
311 (defvar idlwave-experimental)
|
|
312 (defvar idlwave-last-context-help-pos)
|
|
313 (defun idlwave-do-context-help (&optional arg)
|
|
314 "Wrapper around the call to idlwave-context-help1.
|
|
315 It collects and prints the diagnostics messages."
|
|
316 (let ((marker (list (current-buffer) (point)))
|
|
317 (idlwave-help-diagnostics nil))
|
|
318 ;; Check for frame switching. When the command is invoked twice
|
|
319 ;; at the same position, we try to switch to the help frame
|
|
320 ;; FIXME: Frame switching works only on XEmacs
|
|
321 (if (and idlwave-experimental
|
|
322 (equal last-command this-command)
|
|
323 (equal idlwave-last-context-help-pos marker))
|
|
324 (idlwave-help-select-help-frame)
|
|
325 ;; Do the real thing.
|
|
326 (setq idlwave-last-context-help-pos marker)
|
|
327 (idlwave-do-context-help1 arg)
|
|
328 (if idlwave-help-diagnostics
|
|
329 (message "%s" (mapconcat 'identity
|
|
330 (nreverse idlwave-help-diagnostics)
|
|
331 "; "))))))
|
|
332
|
|
333 (defvar idlwave-help-do-class-struct-tag nil)
|
|
334 (defvar idlwave-structtag-struct-location)
|
|
335 (defvar idlwave-help-do-struct-tag nil)
|
|
336 (defvar idlwave-system-variables-alist)
|
|
337 (defvar idlwave-executive-commands-alist)
|
|
338 (defvar idlwave-system-class-info)
|
|
339 (defun idlwave-do-context-help1 (&optional arg)
|
|
340 "The work-horse version of `idlwave-context-help', which see."
|
|
341 (save-excursion
|
|
342 (if (equal (char-after) ?/)
|
|
343 (forward-char 1)
|
|
344 (if (equal (char-before) ?=)
|
|
345 (backward-char 1)))
|
|
346 (let* ((idlwave-query-class nil)
|
|
347 (idlwave-force-class-query (equal arg '(4)))
|
|
348 (chars "a-zA-Z0-9_$.!")
|
|
349 (beg (save-excursion (skip-chars-backward chars) (point)))
|
|
350 (end (save-excursion (skip-chars-forward chars) (point)))
|
|
351 (this-word (buffer-substring-no-properties beg end))
|
|
352 (st-ass (assoc (downcase this-word)
|
|
353 idlwave-help-special-topic-words))
|
|
354 (classtag (and (string-match "self\\." this-word)
|
|
355 (< beg (- end 4))))
|
|
356 (structtag (and (fboundp 'idlwave-complete-structure-tag)
|
|
357 (string-match "\\`\\([^.]+\\)\\." this-word)
|
|
358 (< beg (- end 4))))
|
|
359 module keyword cw mod1 mod2 mod3)
|
|
360 (if (or arg
|
|
361 (and (not st-ass)
|
|
362 (not classtag)
|
|
363 (not structtag)
|
|
364 (not (member (string-to-char this-word) '(?! ?.)))))
|
|
365 ;; Need the module information
|
|
366 (progn
|
|
367 ;; MODULE is (name type class), for this or any inheriting class
|
|
368 (setq module (idlwave-what-module-find-class)
|
|
369 cw (nth 2 (idlwave-where))) ;what would we complete here?
|
|
370 ;; Correct for OBJ_NEW, we may need an INIT method instead.
|
|
371 (if (equal (idlwave-downcase-safe (car module)) "obj_new")
|
|
372 (let* ((bos (save-excursion (idlwave-beginning-of-statement)
|
|
373 (point)))
|
|
374 (str (buffer-substring bos (point))))
|
|
375 (if (string-match "OBJ_NEW([ \t]*['\"]\\([a-zA-Z][a-zA-Z0-9$_]+\\)['\"]" str)
|
|
376 (setq module (list "init" 'fun (match-string 1 str))
|
|
377 idlwave-current-obj_new-class (match-string 1 str))
|
|
378 )))))
|
|
379 (cond
|
|
380 (arg (setq mod1 module))
|
|
381
|
|
382 ;; A special topic -- only system help
|
|
383 (st-ass (setq mod1 (list (cdr st-ass))))
|
|
384
|
|
385 ;; A system variable -- only system help
|
|
386 ((string-match
|
|
387 "\\`!\\([a-zA-Z0-9_]+\\)\\(\.\\([A-Za-z0-9_]+\\)\\)?"
|
|
388 this-word)
|
|
389 (let* ((word (match-string-no-properties 1 this-word))
|
|
390 (entry (assq (idlwave-sintern-sysvar word)
|
|
391 idlwave-system-variables-alist))
|
|
392 (tag (match-string-no-properties 3 this-word))
|
|
393 (tag-target (if tag
|
|
394 (cdr
|
|
395 (assq (idlwave-sintern-sysvartag tag)
|
|
396 (cdr (assq 'tags entry))))))
|
|
397 (link (nth 1 (assq 'link entry))))
|
|
398 (if tag-target
|
|
399 (setq link (idlwave-substitute-link-target link
|
|
400 tag-target)))
|
|
401 (setq mod1 (list link))))
|
|
402
|
|
403 ;; An executive command -- only system help
|
|
404 ((string-match "^\\.\\([A-Z_]+\\)" this-word)
|
|
405 (let* ((word (match-string 1 this-word))
|
|
406 (link (cdr (assoc-string
|
|
407 word
|
|
408 idlwave-executive-commands-alist t))))
|
|
409 (setq mod1 (list link))))
|
|
410
|
|
411 ;; A class -- system OR in-text help (via class__define).
|
|
412 ((and (eq cw 'class)
|
|
413 (or (idlwave-in-quote) ; e.g. obj_new
|
|
414 (re-search-backward "\\<inherits[ \t]+[A-Za-z0-9_]*\\="
|
|
415 (max (point-min) (- (point) 40)) t)))
|
|
416 ;; Class completion inside string delimiters must be
|
|
417 ;; the class inside OBJ_NEW.
|
|
418 (let* ((entry (assq
|
|
419 (idlwave-sintern-class this-word)
|
|
420 idlwave-system-class-info))
|
|
421 (name (concat (downcase this-word) "__define"))
|
|
422 (link (nth 1 (assq 'link entry))))
|
|
423 (setq mod1 (list link name 'pro))))
|
|
424
|
|
425 ;; A class structure tag (self.BLAH) -- only in-text help available
|
|
426 (classtag
|
|
427 (let ((tag (substring this-word (match-end 0)))
|
|
428 class-with found-in)
|
|
429 (when (setq class-with
|
|
430 (idlwave-class-or-superclass-with-tag
|
|
431 (nth 2 (idlwave-current-routine))
|
|
432 tag))
|
|
433 (setq found-in (idlwave-class-found-in class-with))
|
|
434 (if (assq (idlwave-sintern-class class-with)
|
|
435 idlwave-system-class-info)
|
|
436 (error "No help available for system class tags"))
|
|
437 (setq idlwave-help-do-class-struct-tag t)
|
|
438 (setq mod1 (list nil
|
|
439 (if found-in
|
|
440 (cons (concat found-in "__define") class-with)
|
|
441 (concat class-with "__define"))
|
|
442 'pro
|
|
443 nil ; no class.... it's a procedure!
|
|
444 tag)))))
|
|
445
|
|
446 ;; A regular structure tag -- only in text, and if
|
|
447 ;; optional `complete-structtag' loaded.
|
|
448 (structtag
|
|
449 (let ((var (match-string 1 this-word))
|
|
450 (tag (substring this-word (match-end 0))))
|
|
451 ;; Check if we need to update the "current" structure
|
|
452 (idlwave-prepare-structure-tag-completion var)
|
|
453 (setq idlwave-help-do-struct-tag
|
|
454 idlwave-structtag-struct-location
|
|
455 mod1 (list nil nil nil nil tag))))
|
|
456
|
|
457 ;; A routine keyword -- in text or system help
|
|
458 ((and (memq cw '(function-keyword procedure-keyword))
|
|
459 (stringp this-word)
|
|
460 (string-match "\\S-" this-word)
|
|
461 (not (string-match "!" this-word)))
|
|
462 (cond ((or (= (char-before beg) ?/)
|
|
463 (save-excursion (goto-char end)
|
|
464 (looking-at "[ \t]*=")))
|
|
465 ;; Certainly a keyword. Check for abbreviation etc.
|
|
466 (setq keyword (idlwave-expand-keyword this-word module))
|
|
467 (cond
|
|
468 ((null keyword)
|
|
469 (idlwave-help-diagnostics
|
|
470 (format "%s does not accept `%s' kwd"
|
|
471 (idlwave-make-full-name (nth 2 module)
|
|
472 (car module))
|
|
473 (upcase this-word))
|
|
474 'ding))
|
|
475 ((consp keyword)
|
|
476 (idlwave-help-diagnostics
|
|
477 (format "%d matches for kwd abbrev `%s'"
|
|
478 (length keyword) this-word)
|
|
479 'ding)
|
|
480 ;; We continue anyway with the first match...
|
|
481 (setq keyword (car keyword))))
|
|
482 ;; Keyword, or just module
|
|
483 (setq mod1 (append (list t) module (list keyword)))
|
|
484 (setq mod2 (append (list t) module)))
|
|
485 ((equal (char-after end) ?\()
|
|
486 ;; A function - what-module will have caught this
|
|
487 (setq mod1 (append (list t) module)))
|
|
488 (t
|
|
489 ;; undecided - try function, keyword, then enclosing mod.
|
|
490 ;; Check for keyword abbreviations, but do not report
|
|
491 ;; errors, because it might be something else.
|
|
492 ;; FIXME: is this a good way to handle this?
|
|
493 (setq keyword (idlwave-expand-keyword this-word module))
|
|
494 (if (consp keyword) (setq keyword (car keyword)))
|
|
495 (setq mod1 (append (list t) module (list keyword))
|
|
496 mod2 (list t this-word 'fun nil)
|
|
497 mod3 (append (list t) module)))))
|
|
498
|
|
499 ;; Everything else
|
|
500 (t
|
|
501 (setq mod1 (append (list t) module))))
|
|
502 (if mod3
|
|
503 (condition-case nil
|
|
504 (apply 'idlwave-online-help mod1)
|
|
505 (error (condition-case nil
|
|
506 (apply 'idlwave-online-help mod2)
|
|
507 (error (apply 'idlwave-online-help mod3)))))
|
|
508 (if mod2
|
|
509 (condition-case nil
|
|
510 (apply 'idlwave-online-help mod1)
|
|
511 (error (apply 'idlwave-online-help mod2)))
|
|
512 (if mod1
|
|
513 (apply 'idlwave-online-help mod1)
|
|
514 (error "Don't know which item to show help for")))))))
|
|
515
|
|
516 (defun idlwave-do-mouse-completion-help (ev)
|
|
517 "Display online help on an item in the *Completions* buffer.
|
|
518 Needs additional info stored in global `idlwave-completion-help-info'."
|
|
519 (let* ((cw (selected-window))
|
|
520 (info idlwave-completion-help-info) ; global passed in
|
|
521 (what (nth 0 info))
|
|
522 (name (nth 1 info))
|
|
523 (type (nth 2 info))
|
|
524 (class (nth 3 info))
|
|
525 (need-class class)
|
|
526 (kwd (nth 4 info))
|
|
527 (sclasses (nth 5 info))
|
|
528 word link)
|
|
529 (mouse-set-point ev)
|
|
530
|
|
531
|
|
532 ;; See if we can also find help somewhere, e.g. for multiple classes
|
|
533 (setq word (idlwave-this-word))
|
|
534 (if (string= word "")
|
|
535 (error "No help item selected"))
|
|
536 (setq link (get-text-property 0 'link word))
|
|
537 (select-window cw)
|
|
538 (cond
|
|
539 ;; Routine name
|
|
540 ((memq what '(procedure function routine))
|
|
541 (setq name word)
|
|
542 (if (or (eq class t)
|
|
543 (and (stringp class) sclasses))
|
|
544 (let* ((classes (idlwave-all-method-classes
|
|
545 (idlwave-sintern-method name)
|
|
546 type)))
|
|
547 (setq link t) ; No specific link valid yet
|
|
548 (if sclasses
|
|
549 (setq classes (idlwave-members-only
|
|
550 classes (cons class sclasses))))
|
|
551 (setq class (idlwave-popup-select ev classes
|
|
552 "Select Class" 'sort))))
|
|
553
|
|
554 ;; XXX is this necessary, given all-method-classes?
|
|
555 (if (stringp class)
|
|
556 (setq class (idlwave-find-inherited-class
|
|
557 (idlwave-sintern-routine-or-method name class)
|
|
558 type (idlwave-sintern-class class)))))
|
|
559
|
|
560 ;; Keyword
|
|
561 ((eq what 'keyword)
|
|
562 (setq kwd word)
|
|
563 (if (or (eq class t)
|
|
564 (and (stringp class) sclasses))
|
|
565 (let ((classes (idlwave-all-method-keyword-classes
|
|
566 (idlwave-sintern-method name)
|
|
567 (idlwave-sintern-keyword kwd)
|
|
568 type)))
|
|
569 (setq link t) ; Link can't be correct yet
|
|
570 (if sclasses
|
|
571 (setq classes (idlwave-members-only
|
|
572 classes (cons class sclasses))))
|
|
573 (setq class (idlwave-popup-select ev classes
|
|
574 "Select Class" 'sort))
|
|
575 ;; XXX is this necessary, given all-method-keyword-classes?
|
|
576 (if (stringp class)
|
|
577 (setq class (idlwave-find-inherited-class
|
|
578 (idlwave-sintern-routine-or-method name class)
|
|
579 type (idlwave-sintern-class class)))))
|
|
580 (if (string= (downcase name) "obj_new")
|
|
581 (setq class idlwave-current-obj_new-class
|
|
582 name "Init"))))
|
|
583
|
|
584 ;; Class name
|
|
585 ((eq what 'class)
|
|
586 (setq class word
|
|
587 word nil))
|
|
588
|
|
589 ;; A special named function to call which sets some of our variables
|
|
590 ((and (symbolp what)
|
|
591 (fboundp what))
|
|
592 (funcall what 'set word))
|
|
593
|
|
594 (t (error "Cannot help with this item")))
|
|
595 (if (and need-class (not class) (not (and link (not (eq link t)))))
|
|
596 (error "Cannot help with this item"))
|
|
597 (idlwave-online-help link (or name word) type class kwd)))
|
|
598
|
|
599 (defvar idlwave-highlight-help-links-in-completion)
|
|
600 (defvar idlwave-completion-help-links)
|
|
601 (defun idlwave-highlight-linked-completions ()
|
|
602 "Highlight all completions for which help is available and attach link.
|
|
603 Those words in `idlwave-completion-help-links' have links. The
|
|
604 `idlwave-help-link' face is used for this."
|
|
605 (if idlwave-highlight-help-links-in-completion
|
|
606 (with-current-buffer (get-buffer "*Completions*")
|
|
607 (save-excursion
|
|
608 (let* ((case-fold-search t)
|
|
609 (props (list 'face 'idlwave-help-link))
|
|
610 (info idlwave-completion-help-info) ; global passed in
|
|
611 (what (nth 0 info)) ; what was completed, or a func
|
|
612 (class (nth 3 info)) ; any class
|
|
613 word beg end doit)
|
|
614 (goto-char (point-min))
|
|
615 (re-search-forward "possible completions are:" nil t)
|
|
616 (while (re-search-forward "\\s-\\([A-Za-z0-9_.]+\\)\\(\\s-\\|\\'\\)"
|
|
617 nil t)
|
|
618 (setq beg (match-beginning 1) end (match-end 1)
|
|
619 word (match-string 1) doit nil)
|
|
620 ;; Call special completion function test
|
|
621 (if (and (symbolp what)
|
|
622 (fboundp what))
|
|
623 (setq doit (funcall what 'test word))
|
|
624 ;; Look for special link property passed in help-links
|
|
625 (if idlwave-completion-help-links
|
|
626 (setq doit (assoc-string
|
|
627 word idlwave-completion-help-links t))))
|
|
628 (when doit
|
|
629 (if (consp doit)
|
|
630 (setq props (append props `(link ,(cdr doit)))))
|
|
631 (let ((buffer-read-only nil))
|
|
632 (add-text-properties beg end props)))
|
|
633 (goto-char end)))))))
|
|
634
|
|
635 ;; Arrange for this function to be called after completion
|
|
636 (add-hook 'idlwave-completion-setup-hook
|
|
637 'idlwave-highlight-linked-completions)
|
|
638
|
|
639 (defvar idlwave-help-return-frame nil
|
|
640 "The frame to return to from the help frame.")
|
|
641
|
|
642 (defun idlwave-help-quit ()
|
|
643 "Exit IDLWAVE Help buffer. Kill the dedicated frame if any."
|
|
644 (interactive)
|
|
645 (cond ((and idlwave-help-use-dedicated-frame
|
|
646 (eq (selected-frame) idlwave-help-frame))
|
|
647 (if (and idlwave-experimental
|
|
648 (frame-live-p idlwave-help-return-frame))
|
|
649 ;; Try to select the return frame.
|
|
650 ;; This can crash on slow network connections, obviously when
|
|
651 ;; we kill the help frame before the return-frame is selected.
|
|
652 ;; To protect the workings, we wait for up to one second
|
|
653 ;; and check if the return-frame *is* now selected.
|
|
654 ;; This is marked "eperimental" since we are not sure when its OK.
|
|
655 (let ((maxtime 1.0) (time 0.) (step 0.1))
|
|
656 (select-frame idlwave-help-return-frame)
|
|
657 (while (and (sit-for step)
|
|
658 (not (eq (selected-frame)
|
|
659 idlwave-help-return-frame))
|
|
660 (< (setq time (+ time step)) maxtime)))))
|
|
661 (delete-frame idlwave-help-frame))
|
|
662 ((window-configuration-p idlwave-help-window-configuration)
|
|
663 (set-window-configuration idlwave-help-window-configuration)
|
|
664 (select-window (previous-window)))
|
|
665 (t (kill-buffer (idlwave-help-get-help-buffer)))))
|
|
666
|
|
667
|
|
668 (defvar default-toolbar-visible-p)
|
|
669
|
|
670 (defun idlwave-help-display-help-window (&optional pos-or-func)
|
|
671 "Display the help window.
|
|
672 Move window start to POS-OR-FUNC, if passed as a position, or call it
|
|
673 if passed as a function. See `idlwave-help-use-dedicated-frame'."
|
|
674 (let ((cw (selected-window))
|
|
675 (buf (idlwave-help-get-help-buffer)))
|
|
676 (if (and window-system idlwave-help-use-dedicated-frame)
|
|
677 (progn
|
|
678 (idlwave-help-show-help-frame)
|
|
679 (switch-to-buffer buf))
|
|
680 ;; Do it in this frame and save the window configuration
|
|
681 (if (not (get-buffer-window buf nil))
|
|
682 (setq idlwave-help-window-configuration
|
|
683 (current-window-configuration)))
|
|
684 (display-buffer buf nil (selected-frame))
|
|
685 (select-window (get-buffer-window buf)))
|
|
686 (raise-frame)
|
|
687 (if pos-or-func
|
|
688 (if (functionp pos-or-func)
|
|
689 (funcall pos-or-func)
|
|
690 (goto-char pos-or-func)
|
|
691 (recenter 0)))
|
|
692 (select-window cw)))
|
|
693
|
|
694 (defun idlwave-help-select-help-frame ()
|
|
695 "Select the help frame."
|
|
696 (if (and (frame-live-p idlwave-help-frame)
|
|
697 (not (eq (selected-frame) idlwave-help-frame)))
|
|
698 (progn
|
|
699 (setq idlwave-help-return-frame (selected-frame))
|
|
700 (select-frame idlwave-help-frame))))
|
|
701
|
|
702 (defun idlwave-help-return-to-calling-frame ()
|
|
703 "Select the frame from which the help frame was selected."
|
|
704 (interactive)
|
|
705 (if (and (frame-live-p idlwave-help-return-frame)
|
|
706 (not (eq (selected-frame) idlwave-help-return-frame)))
|
|
707 (select-frame idlwave-help-return-frame)))
|
|
708
|
|
709 (defun idlwave-online-help (link &optional name type class keyword)
|
|
710 "Display HTML or other special help on a certain topic.
|
|
711 Either loads an HTML link, if LINK is non-nil, or gets special-help on
|
|
712 the optional arguments, if any special help is defined. If LINK is
|
|
713 `t', first look up the optional arguments in the routine info list to
|
|
714 see if a link is set for it. Try extra help functions if necessary."
|
|
715 ;; Lookup link
|
|
716 (if (eq link t)
|
|
717 (let ((entry (idlwave-best-rinfo-assoc name type class
|
|
718 (idlwave-routines) nil t)))
|
|
719 (cond
|
|
720 ;; Try keyword link
|
|
721 ((and keyword
|
|
722 (setq link (cdr (idlwave-entry-find-keyword entry keyword)))))
|
|
723 ;; Default, regular entry link
|
|
724 (t (setq link (idlwave-entry-has-help entry))))))
|
|
725
|
|
726 (cond
|
|
727 ;; An explicit link
|
|
728 ((stringp link)
|
|
729 (idlwave-help-html-link link))
|
|
730
|
|
731 ;; Any extra help
|
|
732 (idlwave-extra-help-function
|
|
733 (idlwave-help-get-special-help name type class keyword))
|
|
734
|
|
735 ;; Nothing worked
|
|
736 (t (idlwave-help-error name type class keyword))))
|
|
737
|
|
738
|
|
739 (defun idlwave-help-get-special-help (name type class keyword)
|
|
740 "Call the function given by `idlwave-extra-help-function'."
|
|
741 (let* ((cw (selected-window))
|
|
742 (help-pos (save-excursion
|
|
743 (set-buffer (idlwave-help-get-help-buffer))
|
|
744 (let ((buffer-read-only nil))
|
|
745 (funcall idlwave-extra-help-function
|
|
746 name type class keyword)))))
|
|
747 (if help-pos
|
|
748 (idlwave-help-display-help-window help-pos)
|
|
749 (idlwave-help-error name type class keyword))
|
|
750 (select-window cw)))
|
|
751
|
|
752 (defun idlwave-help-html-link (link)
|
|
753 "Get html help on a given LINK."
|
|
754 (let ((browse-url-browser-function idlwave-help-browser-function)
|
|
755 (help-loc (idlwave-html-help-location))
|
|
756 (browse-url-generic-program idlwave-help-browser-generic-program)
|
|
757 ;(browse-url-generic-args idlwave-help-browser-generic-args)
|
|
758 full-link)
|
|
759
|
|
760 (unless idlwave-help-browse-url-available
|
|
761 (error "browse-url is not available -- install it to use HTML help."))
|
|
762
|
|
763 (if (and (memq system-type '(ms-dos windows-nt))
|
|
764 idlwave-help-use-hh)
|
|
765 (progn
|
|
766 (setq browse-url-browser-function 'browse-url-generic
|
|
767 full-link (concat (expand-file-name "idl.chm" help-loc)
|
|
768 "::/"
|
|
769 link))
|
|
770 (if (memq 'keyhh idlwave-help-use-hh)
|
|
771 (setq browse-url-generic-program "KEYHH"
|
|
772 browse-url-generic-args '("-IDLWAVE"))
|
|
773 (setq browse-url-generic-program "HH")))
|
|
774 ;; Just a regular file name (+ anchor name)
|
|
775 (unless (and (stringp help-loc)
|
|
776 (file-directory-p help-loc))
|
|
777 (error
|
|
778 "Invalid help location; customize `idlwave-html-help-location'."))
|
|
779 (setq full-link (concat
|
|
780 "file://"
|
|
781 (expand-file-name
|
|
782 link
|
|
783 (expand-file-name "idl_html_help" help-loc)))))
|
|
784
|
|
785 ;; Check for a local browser
|
|
786 (if (or idlwave-help-browser-is-local
|
|
787 (string-match "w3" (symbol-name idlwave-help-browser-function)))
|
|
788 (idlwave-help-display-help-window '(lambda () (browse-url full-link)))
|
|
789 (browse-url full-link))))
|
|
790
|
|
791 ;; A special help routine for source-level syntax help in files.
|
|
792 (defvar idlwave-help-fontify-source-code)
|
|
793 (defvar idlwave-help-source-try-header)
|
|
794 (defvar idlwave-current-tags-buffer)
|
|
795 (defvar idlwave-current-tags-class)
|
|
796 (defun idlwave-help-with-source (name type class keyword)
|
|
797 "Provide help for routines not documented in the IDL manuals. Works
|
|
798 by loading the routine source file into the help buffer. Depending on
|
|
799 the value of `idlwave-help-source-try-header', it attempts to show the
|
|
800 routine definition or the header description. If
|
|
801 `idlwave-help-do-class-struct-tag' is non-nil, keyword is a tag to
|
|
802 show help on from the class definition structure. If
|
|
803 `idlwave-help-do-struct-tag' is non-nil, show help from the matching
|
|
804 structure tag definition.
|
|
805
|
|
806 This function can be used as `idlwave-extra-help-function'."
|
|
807 (let* ((class-struct-tag idlwave-help-do-class-struct-tag)
|
|
808 (struct-tag idlwave-help-do-struct-tag)
|
|
809 (case-fold-search t)
|
|
810 (real-class (if (consp name) (cdr name)))
|
|
811 (name (if (consp name) (car name) name))
|
|
812 (class-only (and (stringp class) (not (stringp name))))
|
|
813 file header-pos def-pos in-buf)
|
|
814 (if class-only ;Help with class? Using "Init" as source.
|
|
815 (setq name "Init"
|
|
816 type 'fun))
|
|
817 (if (not struct-tag)
|
|
818 (setq file
|
|
819 (idlwave-routine-source-file
|
|
820 (nth 3 (idlwave-best-rinfo-assoc
|
|
821 name (or type t) class (idlwave-routines))))))
|
|
822 (setq idlwave-help-def-pos nil
|
|
823 idlwave-help-args (list name type class keyword)
|
|
824 idlwave-help-in-header nil
|
|
825 idlwave-help-do-struct-tag nil
|
|
826 idlwave-help-do-class-struct-tag nil)
|
|
827 (if (or struct-tag (stringp file))
|
|
828 (progn
|
|
829 (setq in-buf ; structure-tag completion is always in current buffer
|
|
830 (if struct-tag
|
|
831 idlwave-current-tags-buffer
|
|
832 (idlwave-get-buffer-visiting file)))
|
|
833 ;; see if file is in a visited buffer, insert those contents
|
|
834 (if in-buf
|
|
835 (progn
|
|
836 (setq file (buffer-file-name in-buf))
|
|
837 (erase-buffer)
|
|
838 (insert-buffer-substring in-buf)
|
|
839 (goto-char (point-min)))
|
|
840 (if (file-exists-p file) ;; otherwise just load the file
|
|
841 (progn
|
|
842 (erase-buffer)
|
|
843 (insert-file-contents file nil nil nil 'replace))
|
|
844 (idlwave-help-error name type class keyword)))
|
|
845 (if (and idlwave-help-fontify-source-code (not in-buf))
|
|
846 (idlwave-help-fontify)))
|
|
847 (idlwave-help-error name type class keyword))
|
|
848 (setq idlwave-help-mode-line-indicator file)
|
|
849
|
|
850 ;; Try to find a good place to display
|
|
851 (setq def-pos
|
|
852 ;; Find the class structure tag if that's what we're after
|
|
853 (cond
|
|
854 ;; Class structure tags: find the class or named structure
|
|
855 ;; definition
|
|
856 (class-struct-tag
|
|
857 (save-excursion
|
|
858 (setq class
|
|
859 (if (string-match "[a-zA-Z0-9]\\(__\\)" name)
|
|
860 (substring name 0 (match-beginning 1))
|
|
861 idlwave-current-tags-class))
|
|
862 (and
|
|
863 (idlwave-find-class-definition class nil real-class)
|
|
864 (idlwave-find-struct-tag keyword))))
|
|
865
|
|
866 ;; Generic structure tags: the structure definition
|
|
867 ;; location within the file has been recorded in
|
|
868 ;; `struct-tag'
|
|
869 (struct-tag
|
|
870 (save-excursion
|
|
871 (and
|
|
872 (integerp struct-tag)
|
|
873 (goto-char struct-tag)
|
|
874 (idlwave-find-struct-tag keyword))))
|
|
875
|
|
876 ;; Just find the routine definition
|
|
877 (t
|
|
878 (if class-only (point-min)
|
|
879 (idlwave-help-find-routine-definition name type class keyword))))
|
|
880 idlwave-help-def-pos def-pos)
|
|
881
|
|
882 (if (and idlwave-help-source-try-header
|
|
883 (not (or struct-tag class-struct-tag)))
|
|
884 ;; Check if we can find the header
|
|
885 (save-excursion
|
|
886 (goto-char (or def-pos (point-max)))
|
|
887 (setq header-pos (idlwave-help-find-in-doc-header
|
|
888 name type class keyword 'exact)
|
|
889 idlwave-help-in-header header-pos)))
|
|
890
|
|
891 (if (or header-pos def-pos)
|
|
892 (progn
|
|
893 (if (boundp 'idlwave-help-min-frame-width)
|
|
894 (setq idlwave-help-min-frame-width 80))
|
|
895 (goto-char (or header-pos def-pos)))
|
|
896 (idlwave-help-error name type class keyword))
|
|
897
|
|
898 (point)))
|
|
899
|
|
900
|
|
901 (defun idlwave-help-find-routine-definition (name type class keyword)
|
|
902 "Find the definition of routine CLASS::NAME in current buffer.
|
|
903 KEYWORD is ignored. Returns the point of match if successful, nil otherwise."
|
|
904 (save-excursion
|
|
905 (goto-char (point-max))
|
|
906 (if (re-search-backward
|
|
907 (concat "^[ \t]*"
|
|
908 (if (eq type 'pro) "pro"
|
|
909 (if (eq type 'fun) "function"
|
|
910 "\\(pro\\|function\\)"))
|
|
911 "[ \t]+"
|
|
912 (regexp-quote (downcase (idlwave-make-full-name class name)))
|
|
913 "[, \t\r\n]")
|
|
914 nil t)
|
|
915 (match-beginning 0)
|
|
916 nil)))
|
|
917
|
|
918 (defvar idlwave-doclib-start)
|
|
919 (defvar idlwave-doclib-end)
|
|
920 (defun idlwave-help-find-in-doc-header (name type class keyword
|
|
921 &optional exact)
|
|
922 "Find the requested help in the doc-header above point.
|
|
923
|
|
924 First checks if there is a doc-lib header which describes the correct
|
|
925 routine. Then tries to find the KEYWORDS section and the KEYWORD, if
|
|
926 given. Returns the point which should be window start of the help
|
|
927 window. If EXACT is non-nil, the full help position must be found -
|
|
928 down to the keyword requested. This setting is for context help, if
|
|
929 the exact spot is needed.
|
|
930
|
|
931 If EXACT is nil, the position of the header is returned if it
|
|
932 describes the correct routine - even if the keyword description cannot
|
|
933 be found. TYPE is ignored.
|
|
934
|
|
935 This function expects a more or less standard routine header. In
|
|
936 particlar it looks for the `NAME:' tag, either with a colon, or alone
|
|
937 on a line. Then `NAME:' must be followed by the routine name on the
|
|
938 same or the next line. When KEYWORD is non-nil, looks first for a
|
|
939 `KEYWORDS' section. It is amazing how inconsisten this is through
|
|
940 some IDL libraries I have seen. We settle for a line containing an
|
|
941 upper case \"KEYWORD\" string. If this line is not fould we search
|
|
942 for the keyword anyway to increase the hit-rate
|
|
943
|
|
944 When one of these sections exists we check for a line starting with any of
|
|
945
|
|
946 /KEYWORD KEYWORD- KEYWORD= KEYWORD
|
|
947
|
|
948 with spaces allowed between the keyword and the following dash or equal sign.
|
|
949 If there is a match, we assume it is the keyword description."
|
|
950 (let* ((case-fold-search t)
|
|
951 (rname (if (stringp class)
|
|
952 (concat
|
|
953 "\\("
|
|
954 ;; Traditional name or class::name
|
|
955 "\\("
|
|
956 "\\(" (regexp-quote (downcase class)) "::\\)?"
|
|
957 (regexp-quote (downcase name))
|
|
958 "\\>\\)"
|
|
959 (concat
|
|
960 "\\|"
|
|
961 ;; class__define or just class
|
|
962 (regexp-quote (downcase class)) "\\(__define\\)?")
|
|
963 "\\)")
|
|
964 (regexp-quote (downcase name))))
|
|
965
|
|
966 ;; NAME tag plus the routine name. The new version is from JD.
|
|
967 (name-re (concat
|
|
968 "\\(^;+\\*?[ \t]*"
|
|
969 idlwave-help-doclib-name
|
|
970 "\\([ \t]*:\\|[ \t]*$\\)[ \t]*\\(\n;+[ \t]*\\)*"
|
|
971 rname
|
|
972 "\\|"
|
|
973 "^;+[ \t]*"
|
|
974 rname
|
|
975 ":[ \t]*$\\)"))
|
|
976
|
|
977 ;; Header start plus name
|
|
978 (header-re (concat "\\(" idlwave-doclib-start "\\).*\n"
|
|
979 "\\(^;+.*\n\\)*"
|
|
980 "\\(" name-re "\\)"))
|
|
981 ;; A keywords section
|
|
982 (kwds-re (concat ; forgiving
|
|
983 "^;+\\*?[ \t]*"
|
|
984 "\\([-A-Z_ ]*"
|
|
985 idlwave-help-doclib-keyword
|
|
986 "[-A-Z_ ]*\\)"
|
|
987 "\\(:\\|[ \t]*\n\\)"))
|
|
988
|
|
989 ;; The individual keyword description line.
|
|
990 (kwd-re (if keyword ; hard (well...)
|
|
991 (concat
|
|
992 "^;+[ \t]+"
|
|
993 "\\(/" (regexp-quote (upcase keyword))
|
|
994 "\\|" (regexp-quote (upcase keyword)) "[ \t]*[-=:\n]"
|
|
995 "\\)")))
|
|
996 (kwd-re2 (if keyword ; forgiving
|
|
997 (concat
|
|
998 "^;+[ \t]+"
|
|
999 (regexp-quote (upcase keyword))
|
|
1000 "\\>")))
|
|
1001 dstart dend name-pos kwds-pos kwd-pos)
|
|
1002 (catch 'exit
|
|
1003 (save-excursion
|
|
1004 (goto-char (point-min))
|
|
1005 (while (and (setq dstart (re-search-forward idlwave-doclib-start nil t))
|
|
1006 (setq dend (re-search-forward idlwave-doclib-end nil t)))
|
|
1007 ;; found a routine header
|
|
1008 (goto-char dstart)
|
|
1009 (if (setq name-pos (re-search-forward name-re dend t))
|
|
1010 (progn
|
|
1011 (if keyword
|
|
1012 ;; We do need a keyword
|
|
1013 (progn
|
|
1014 ;; Try to find a keyword section, but don't force it.
|
|
1015 (goto-char name-pos)
|
|
1016 (if (let ((case-fold-search nil))
|
|
1017 (re-search-forward kwds-re dend t))
|
|
1018 (setq kwds-pos (match-beginning 0)))
|
|
1019 ;; Find the keyword description
|
|
1020 (if (or (let ((case-fold-search nil))
|
|
1021 (re-search-forward kwd-re dend t))
|
|
1022 (re-search-forward kwd-re dend t)
|
|
1023 (let ((case-fold-search nil))
|
|
1024 (re-search-forward kwd-re2 dend t))
|
|
1025 (re-search-forward kwd-re2 dend t))
|
|
1026 (setq kwd-pos (match-beginning 0))
|
|
1027 (if exact
|
|
1028 (progn
|
|
1029 (idlwave-help-diagnostics
|
|
1030 (format "Could not find description of kwd %s"
|
|
1031 (upcase keyword)))
|
|
1032 (throw 'exit nil))))))
|
|
1033 ;; Return the best position we got
|
|
1034 (throw 'exit (or kwd-pos kwds-pos name-pos dstart)))
|
|
1035 (goto-char dend))))
|
|
1036 (idlwave-help-diagnostics "Could not find doclib header")
|
|
1037 (throw 'exit nil))))
|
|
1038
|
|
1039 (defun idlwave-help-diagnostics (string &optional ding)
|
|
1040 "Add a diagnostics string to the list.
|
|
1041 When DING is non-nil, ring the bell as well."
|
|
1042 (if (boundp 'idlwave-help-diagnostics)
|
|
1043 (progn
|
|
1044 (setq idlwave-help-diagnostics
|
|
1045 (cons string idlwave-help-diagnostics))
|
|
1046 (if ding (ding)))))
|
|
1047
|
|
1048 (defun idlwave-help-toggle-header-top-and-def (arg)
|
|
1049 (interactive "P")
|
|
1050 (let (pos)
|
|
1051 (if idlwave-help-in-header
|
|
1052 ;; Header was the last thing displayed
|
|
1053 (progn
|
|
1054 (setq idlwave-help-in-header nil)
|
|
1055 (setq pos idlwave-help-def-pos))
|
|
1056 ;; Try to display header
|
|
1057 (setq pos (idlwave-help-find-in-doc-header
|
|
1058 (nth 0 idlwave-help-args)
|
|
1059 (nth 1 idlwave-help-args)
|
|
1060 (nth 2 idlwave-help-args)
|
|
1061 nil))
|
|
1062 (if pos
|
|
1063 (setq idlwave-help-in-header t)
|
|
1064 (error "Cannot find doclib header for routine %s"
|
|
1065 (idlwave-make-full-name (nth 2 idlwave-help-args)
|
|
1066 (nth 0 idlwave-help-args)))))
|
|
1067 (if pos
|
|
1068 (progn
|
|
1069 (goto-char pos)
|
|
1070 (recenter 0)))))
|
|
1071
|
|
1072 (defun idlwave-help-find-first-header (arg)
|
|
1073 (interactive "P")
|
|
1074 (let (pos)
|
|
1075 (save-excursion
|
|
1076 (goto-char (point-min))
|
|
1077 (if (re-search-forward idlwave-doclib-start nil t)
|
|
1078 (setq pos (match-beginning 0))))
|
|
1079 (if pos
|
|
1080 (progn
|
|
1081 (goto-char pos)
|
|
1082 (recenter 0))
|
|
1083 (error "No DocLib Header in current file"))))
|
|
1084
|
|
1085 (defun idlwave-help-find-header (arg)
|
|
1086 "Jump to the DocLib Header."
|
|
1087 (interactive "P")
|
|
1088 (if arg
|
|
1089 (idlwave-help-find-first-header nil)
|
|
1090 (setq idlwave-help-in-header nil)
|
|
1091 (idlwave-help-toggle-header-match-and-def arg 'top)))
|
|
1092
|
|
1093 (defun idlwave-help-toggle-header-match-and-def (arg &optional top)
|
|
1094 (interactive "P")
|
|
1095 (let ((args idlwave-help-args)
|
|
1096 pos)
|
|
1097 (if idlwave-help-in-header
|
|
1098 ;; Header was the last thing displayed
|
|
1099 (progn
|
|
1100 (setq idlwave-help-in-header nil)
|
|
1101 (setq pos idlwave-help-def-pos))
|
|
1102 ;; Try to display header
|
|
1103 (setq pos (apply 'idlwave-help-find-in-doc-header
|
|
1104 (if top
|
|
1105 (list (car args) (nth 1 args) (nth 2 args) nil)
|
|
1106 args)))
|
|
1107 (if pos
|
|
1108 (setq idlwave-help-in-header t)
|
|
1109 (error "Cannot find doclib header for routine %s"
|
|
1110 (idlwave-make-full-name (nth 2 idlwave-help-args)
|
|
1111 (nth 0 idlwave-help-args)))))
|
|
1112 (if pos
|
|
1113 (progn
|
|
1114 (goto-char pos)
|
|
1115 (recenter 0)))))
|
|
1116
|
|
1117 (defvar font-lock-verbose)
|
|
1118 (defvar idlwave-mode-syntax-table)
|
|
1119 (defvar idlwave-font-lock-defaults)
|
|
1120 (defun idlwave-help-fontify ()
|
|
1121 "Fontify the Help buffer as source code.
|
|
1122 Useful when source code is displayed as help. See the option
|
|
1123 `idlwave-help-fontify-source-code'."
|
|
1124 (interactive)
|
|
1125 (if (featurep 'font-lock)
|
|
1126 (let ((major-mode 'idlwave-mode)
|
|
1127 (font-lock-verbose
|
|
1128 (if (interactive-p) font-lock-verbose nil))
|
|
1129 (syntax-table (syntax-table)))
|
|
1130 (unwind-protect
|
|
1131 (progn
|
|
1132 (set-syntax-table idlwave-mode-syntax-table)
|
|
1133 (set (make-local-variable 'font-lock-defaults)
|
|
1134 idlwave-font-lock-defaults)
|
|
1135 (font-lock-fontify-buffer))
|
|
1136 (set-syntax-table syntax-table)))))
|
|
1137
|
|
1138
|
|
1139 (defun idlwave-help-error (name type class keyword)
|
|
1140 (error "Can't find help on %s%s %s"
|
|
1141 (or (and (or class name) (idlwave-make-full-name class name))
|
|
1142 "<unknown>")
|
|
1143 (if keyword (format ", keyword %s" (upcase keyword)) "")
|
|
1144 (if idlwave-html-help-location
|
|
1145 ""
|
|
1146 "(help location unknown)")))
|
|
1147
|
|
1148 (defun idlwave-help-show-help-frame ()
|
|
1149 "Show the help frame, creating it if necessary"
|
|
1150 ;; Use a special frame for this
|
|
1151 (unless (frame-live-p idlwave-help-frame)
|
|
1152 (setq idlwave-help-frame
|
|
1153 (make-frame idlwave-help-frame-parameters))
|
|
1154 ;; Strip menubar (?) and toolbar from the Help frame.
|
|
1155 (if (fboundp 'set-specifier)
|
|
1156 (progn
|
|
1157 ;; XEmacs
|
|
1158 (let ((sval (cons idlwave-help-frame nil)))
|
|
1159 ;; (set-specifier menubar-visible-p sval)
|
|
1160 (set-specifier default-toolbar-visible-p sval)))
|
|
1161 ;; Emacs
|
|
1162 (modify-frame-parameters idlwave-help-frame
|
|
1163 '(;;(menu-bar-lines . 0)
|
|
1164 (tool-bar-lines . 0)))))
|
|
1165 (select-frame idlwave-help-frame))
|
|
1166
|
|
1167 (defun idlwave-help-get-help-buffer ()
|
|
1168 "Return the IDLWAVE Help buffer. Make it first if necessary."
|
|
1169 (let ((buf (get-buffer "*IDLWAVE Help*")))
|
|
1170 (if buf
|
|
1171 nil
|
|
1172 (setq buf (get-buffer-create "*IDLWAVE Help*"))
|
|
1173 (save-excursion
|
|
1174 (set-buffer buf)
|
|
1175 (idlwave-help-mode)))
|
|
1176 buf))
|
|
1177
|
|
1178 (defun idlwave-grep (regexp list)
|
|
1179 (let (rtn)
|
|
1180 (while list
|
|
1181 (if (string-match regexp (car list))
|
|
1182 (setq rtn (cons (car list) rtn)))
|
|
1183 (setq list (cdr list)))
|
|
1184 (nreverse rtn)))
|
|
1185
|
|
1186 (defun idlwave-entry-has-help (entry)
|
|
1187 (and entry (car (nth 5 entry))))
|
|
1188
|
|
1189 (defun idlwave-has-help (name type class)
|
|
1190 "Does this have help associated with it?"
|
|
1191 (let ((entry (idlwave-best-rinfo-assoc name type class (idlwave-routines))))
|
|
1192 (idlwave-entry-has-help entry)))
|
|
1193
|
|
1194 (provide 'idlw-help)
|
|
1195 (provide 'idlwave-help)
|
|
1196
|
|
1197 ;; arch-tag: d27b5505-59de-497f-ba3f-f199fd4fb911
|
|
1198 ;;; idlw-help.el ends here
|