comparison lisp/progmodes/idlwave.el @ 63427:6cec4d429edd

idlwave-complete-class-structure-tag-help): Follow error conventions.
author Juanma Barranquero <lekktu@gmail.com>
date Tue, 14 Jun 2005 15:29:27 +0000
parents f2892faa87d4
children c6c9f46490d0 e58cb448e07c a1b34dec1104
comparison
equal deleted inserted replaced
63426:1fca8244172a 63427:6cec4d429edd
68 ;; 68 ;;
69 ;; IDLWAVE is documented online in info format. A printable version 69 ;; IDLWAVE is documented online in info format. A printable version
70 ;; of the documentation is available from the maintainers webpage (see 70 ;; of the documentation is available from the maintainers webpage (see
71 ;; SOURCE). 71 ;; SOURCE).
72 ;; 72 ;;
73 ;; 73 ;;
74 ;; ACKNOWLEDGMENTS 74 ;; ACKNOWLEDGMENTS
75 ;; =============== 75 ;; ===============
76 ;; 76 ;;
77 ;; Thanks to the following people for their contributions and comments: 77 ;; Thanks to the following people for their contributions and comments:
78 ;; 78 ;;
118 ;; does not work as I would like it, but this is a problem with 118 ;; does not work as I would like it, but this is a problem with
119 ;; emacs abbrev expansion done by the self-insert-command. It ends 119 ;; emacs abbrev expansion done by the self-insert-command. It ends
120 ;; up inserting the character that expanded the abbrev after moving 120 ;; up inserting the character that expanded the abbrev after moving
121 ;; point backward, e.g., "\cl" expanded with a space becomes 121 ;; point backward, e.g., "\cl" expanded with a space becomes
122 ;; "LONG( )" with point before the close paren. This is solved by 122 ;; "LONG( )" with point before the close paren. This is solved by
123 ;; using a temporary function in `post-command-hook' - not pretty, 123 ;; using a temporary function in `post-command-hook' - not pretty,
124 ;; but it works. 124 ;; but it works.
125 ;; 125 ;;
126 ;; Tabs and spaces are treated equally as whitespace when filling a 126 ;; Tabs and spaces are treated equally as whitespace when filling a
127 ;; comment paragraph. To accomplish this, tabs are permanently 127 ;; comment paragraph. To accomplish this, tabs are permanently
128 ;; replaced by spaces in the text surrounding the paragraph, which 128 ;; replaced by spaces in the text surrounding the paragraph, which
164 (condition-case () (require 'custom) (error nil)) 164 (condition-case () (require 'custom) (error nil))
165 (if (and (featurep 'custom) (fboundp 'custom-declare-variable)) 165 (if (and (featurep 'custom) (fboundp 'custom-declare-variable))
166 nil ;; We've got what we needed 166 nil ;; We've got what we needed
167 ;; We have the old or no custom-library, hack around it! 167 ;; We have the old or no custom-library, hack around it!
168 (defmacro defgroup (&rest args) nil) 168 (defmacro defgroup (&rest args) nil)
169 (defmacro defcustom (var value doc &rest args) 169 (defmacro defcustom (var value doc &rest args)
170 `(defvar ,var ,value ,doc)))) 170 `(defvar ,var ,value ,doc))))
171 171
172 (defgroup idlwave nil 172 (defgroup idlwave nil
173 "Major mode for editing IDL .pro files" 173 "Major mode for editing IDL .pro files"
174 :tag "IDLWAVE" 174 :tag "IDLWAVE"
175 :link '(url-link :tag "Home Page" 175 :link '(url-link :tag "Home Page"
176 "http://idlwave.org") 176 "http://idlwave.org")
177 :link '(emacs-commentary-link :tag "Commentary in idlw-shell.el" 177 :link '(emacs-commentary-link :tag "Commentary in idlw-shell.el"
178 "idlw-shell.el") 178 "idlw-shell.el")
179 :link '(emacs-commentary-link :tag "Commentary in idlwave.el" "idlwave.el") 179 :link '(emacs-commentary-link :tag "Commentary in idlwave.el" "idlwave.el")
180 :link '(custom-manual "(idlwave)Top") 180 :link '(custom-manual "(idlwave)Top")
284 :group 'idlwave-code-formatting 284 :group 'idlwave-code-formatting
285 :type 'boolean) 285 :type 'boolean)
286 286
287 (defcustom idlwave-auto-fill-split-string t 287 (defcustom idlwave-auto-fill-split-string t
288 "*If non-nil then auto fill will split strings with the IDL `+' operator. 288 "*If non-nil then auto fill will split strings with the IDL `+' operator.
289 When the line end falls within a string, string concatenation with the 289 When the line end falls within a string, string concatenation with the
290 '+' operator will be used to distribute a long string over lines. 290 '+' operator will be used to distribute a long string over lines.
291 If nil and a string is split then a terminal beep and warning are issued. 291 If nil and a string is split then a terminal beep and warning are issued.
292 292
293 This variable is ignored when `idlwave-fill-comment-line-only' is 293 This variable is ignored when `idlwave-fill-comment-line-only' is
294 non-nil, since in this case code is not auto-filled." 294 non-nil, since in this case code is not auto-filled."
295 :group 'idlwave-code-formatting 295 :group 'idlwave-code-formatting
349 (defcustom idlwave-init-rinfo-when-idle-after 10 349 (defcustom idlwave-init-rinfo-when-idle-after 10
350 "*Seconds of idle time before routine info is automatically initialized. 350 "*Seconds of idle time before routine info is automatically initialized.
351 Initializing the routine info can take long, in particular if a large 351 Initializing the routine info can take long, in particular if a large
352 library catalog is involved. When Emacs is idle for more than the number 352 library catalog is involved. When Emacs is idle for more than the number
353 of seconds specified by this variable, it starts the initialization. 353 of seconds specified by this variable, it starts the initialization.
354 The process is split into five steps, in order to keep possible work 354 The process is split into five steps, in order to keep possible work
355 interruption as short as possible. If one of the steps finishes, and no 355 interruption as short as possible. If one of the steps finishes, and no
356 user input has arrived in the mean time, initialization proceeds immediately 356 user input has arrived in the mean time, initialization proceeds immediately
357 to the next step. 357 to the next step.
358 A good value for this variable is about 1/3 of the time initialization 358 A good value for this variable is about 1/3 of the time initialization
359 take in you setup. So if you have a fast machine and no problems with a slow network connection, don't hesitate to set this to 2 seconds. 359 take in you setup. So if you have a fast machine and no problems with a slow network connection, don't hesitate to set this to 2 seconds.
401 (set :tag "Checklist" :greedy t 401 (set :tag "Checklist" :greedy t
402 (const :tag "When visiting a file" find-file) 402 (const :tag "When visiting a file" find-file)
403 (const :tag "When saving a buffer" save-buffer) 403 (const :tag "When saving a buffer" save-buffer)
404 (const :tag "After a buffer was killed" kill-buffer) 404 (const :tag "After a buffer was killed" kill-buffer)
405 (const :tag "After a buffer was compiled successfully, update shell info" compile-buffer)))) 405 (const :tag "After a buffer was compiled successfully, update shell info" compile-buffer))))
406 406
407 (defcustom idlwave-rinfo-max-source-lines 5 407 (defcustom idlwave-rinfo-max-source-lines 5
408 "*Maximum number of source files displayed in the Routine Info window. 408 "*Maximum number of source files displayed in the Routine Info window.
409 When an integer, it is the maximum number of source files displayed. 409 When an integer, it is the maximum number of source files displayed.
410 t means to show all source files." 410 t means to show all source files."
411 :group 'idlwave-routine-info 411 :group 'idlwave-routine-info
434 in this directory. On UNIX systems, IDLWAVE queries the shell for the 434 in this directory. On UNIX systems, IDLWAVE queries the shell for the
435 value of `!DIR'. See also `idlwave-library-path'." 435 value of `!DIR'. See also `idlwave-library-path'."
436 :group 'idlwave-routine-info 436 :group 'idlwave-routine-info
437 :type 'directory) 437 :type 'directory)
438 438
439 (defcustom idlwave-config-directory 439 (defcustom idlwave-config-directory
440 (convert-standard-filename "~/.idlwave") 440 (convert-standard-filename "~/.idlwave")
441 "*Directory for configuration files and user-library catalog." 441 "*Directory for configuration files and user-library catalog."
442 :group 'idlwave-routine-info 442 :group 'idlwave-routine-info
443 :type 'file) 443 :type 'file)
444 444
449 "*Obsolete variable, no longer used.") 449 "*Obsolete variable, no longer used.")
450 450
451 (defcustom idlwave-special-lib-alist nil 451 (defcustom idlwave-special-lib-alist nil
452 "Alist of regular expressions matching special library directories. 452 "Alist of regular expressions matching special library directories.
453 When listing routine source locations, IDLWAVE gives a short hint where 453 When listing routine source locations, IDLWAVE gives a short hint where
454 the file defining the routine is located. By default it lists `SystemLib' 454 the file defining the routine is located. By default it lists `SystemLib'
455 for routines in the system library `!DIR/lib' and `Library' for anything 455 for routines in the system library `!DIR/lib' and `Library' for anything
456 else. This variable can define additional types. The car of each entry 456 else. This variable can define additional types. The car of each entry
457 is a regular expression matching the file name (they normally will match 457 is a regular expression matching the file name (they normally will match
458 on the path). The cdr is the string to be used as identifier. Max 10 458 on the path). The cdr is the string to be used as identifier. Max 10
459 chars are allowed." 459 chars are allowed."
460 :group 'idlwave-routine-info 460 :group 'idlwave-routine-info
461 :type '(repeat 461 :type '(repeat
462 (cons regexp string))) 462 (cons regexp string)))
463 463
464 (defcustom idlwave-auto-write-paths t 464 (defcustom idlwave-auto-write-paths t
465 "Write out path (!PATH) and system directory (!DIR) info automatically. 465 "Write out path (!PATH) and system directory (!DIR) info automatically.
466 Path info is needed to locate library catalog files. If non-nil, 466 Path info is needed to locate library catalog files. If non-nil,
467 whenever the path-list changes as a result of shell-query, etc., it is 467 whenever the path-list changes as a result of shell-query, etc., it is
468 written to file. Otherwise, the menu option \"Write Paths\" can be 468 written to file. Otherwise, the menu option \"Write Paths\" can be
469 used to force a write." 469 used to force a write."
470 :group 'idlwave-routine-info 470 :group 'idlwave-routine-info
491 "Association list setting the case of completed words. 491 "Association list setting the case of completed words.
492 492
493 This variable determines the case (UPPER/lower/Capitalized...) of 493 This variable determines the case (UPPER/lower/Capitalized...) of
494 words inserted into the buffer by completion. The preferred case can 494 words inserted into the buffer by completion. The preferred case can
495 be specified separately for routine names, keywords, classes and 495 be specified separately for routine names, keywords, classes and
496 methods. 496 methods.
497 This alist should therefore have entries for `routine' (normal 497 This alist should therefore have entries for `routine' (normal
498 functions and procedures, i.e. non-methods), `keyword', `class', and 498 functions and procedures, i.e. non-methods), `keyword', `class', and
499 `method'. Plausible values are 499 `method'. Plausible values are
500 500
501 upcase upcase whole word, like `BOX_CURSOR' 501 upcase upcase whole word, like `BOX_CURSOR'
578 _EXTRA or _REF_EXTRA symbol guarantees such chaining will occur, for 578 _EXTRA or _REF_EXTRA symbol guarantees such chaining will occur, for
579 certain methods this assumption is almost always true. The methods 579 certain methods this assumption is almost always true. The methods
580 for which to assume this can be set here." 580 for which to assume this can be set here."
581 :group 'idlwave-routine-info 581 :group 'idlwave-routine-info
582 :type '(repeat (regexp :tag "Match method:"))) 582 :type '(repeat (regexp :tag "Match method:")))
583 583
584 584
585 (defcustom idlwave-completion-show-classes 1 585 (defcustom idlwave-completion-show-classes 1
586 "*Number of classes to show when completing object methods and keywords. 586 "*Number of classes to show when completing object methods and keywords.
587 When completing methods or keywords for an object with unknown class, 587 When completing methods or keywords for an object with unknown class,
588 the *Completions* buffer will show the valid classes for each completion 588 the *Completions* buffer will show the valid classes for each completion
643 should contain at least two elements: (method-default . VALUE) and 643 should contain at least two elements: (method-default . VALUE) and
644 \(keyword-default . VALUE), where VALUE is either t or nil. These 644 \(keyword-default . VALUE), where VALUE is either t or nil. These
645 specify if the class should be found during method and keyword 645 specify if the class should be found during method and keyword
646 completion, respectively. 646 completion, respectively.
647 647
648 The alist may have additional entries specifying exceptions from the 648 The alist may have additional entries specifying exceptions from the
649 keyword completion rule for specific methods, like INIT or 649 keyword completion rule for specific methods, like INIT or
650 GETPROPERTY. In order to turn on class specification for the INIT 650 GETPROPERTY. In order to turn on class specification for the INIT
651 method, add an entry (\"INIT\" . t). The method name must be ALL-CAPS." 651 method, add an entry (\"INIT\" . t). The method name must be ALL-CAPS."
652 :group 'idlwave-completion 652 :group 'idlwave-completion
653 :type '(list 653 :type '(list
667 particular object method call. This happens during the commands 667 particular object method call. This happens during the commands
668 `idlwave-routine-info' and `idlwave-complete', depending upon the 668 `idlwave-routine-info' and `idlwave-complete', depending upon the
669 value of the variable `idlwave-query-class'. 669 value of the variable `idlwave-query-class'.
670 670
671 When you specify a class, this information can be stored as a text 671 When you specify a class, this information can be stored as a text
672 property on the `->' arrow in the source code, so that during the same 672 property on the `->' arrow in the source code, so that during the same
673 editing session, IDLWAVE will not have to ask again. When this 673 editing session, IDLWAVE will not have to ask again. When this
674 variable is non-nil, IDLWAVE will store and reuse the class information. 674 variable is non-nil, IDLWAVE will store and reuse the class information.
675 The class stored can be checked and removed with `\\[idlwave-routine-info]' 675 The class stored can be checked and removed with `\\[idlwave-routine-info]'
676 on the arrow. 676 on the arrow.
677 677
1047 (defcustom idlwave-startup-message t 1047 (defcustom idlwave-startup-message t
1048 "*Non-nil displays a startup message when `idlwave-mode' is first called." 1048 "*Non-nil displays a startup message when `idlwave-mode' is first called."
1049 :group 'idlwave-misc 1049 :group 'idlwave-misc
1050 :type 'boolean) 1050 :type 'boolean)
1051 1051
1052 (defcustom idlwave-default-font-lock-items 1052 (defcustom idlwave-default-font-lock-items
1053 '(pros-and-functions batch-files idlwave-idl-keywords label goto 1053 '(pros-and-functions batch-files idlwave-idl-keywords label goto
1054 common-blocks class-arrows) 1054 common-blocks class-arrows)
1055 "Items which should be fontified on the default fontification level 2. 1055 "Items which should be fontified on the default fontification level 2.
1056 IDLWAVE defines 3 levels of fontification. Level 1 is very little, level 3 1056 IDLWAVE defines 3 levels of fontification. Level 1 is very little, level 3
1057 is everything and level 2 is specified by this list. 1057 is everything and level 2 is specified by this list.
1109 ;;; font-lock mode - Additions by Phil Williams, Ulrik Dickow and 1109 ;;; font-lock mode - Additions by Phil Williams, Ulrik Dickow and
1110 ;;; Simon Marshall <simon_at_gnu.ai.mit.edu> 1110 ;;; Simon Marshall <simon_at_gnu.ai.mit.edu>
1111 ;;; and Carsten Dominik... 1111 ;;; and Carsten Dominik...
1112 1112
1113 ;; The following are the reserved words in IDL. Maybe we should 1113 ;; The following are the reserved words in IDL. Maybe we should
1114 ;; highlight some more stuff as well? 1114 ;; highlight some more stuff as well?
1115 ;; Procedure declarations. Fontify keyword plus procedure name. 1115 ;; Procedure declarations. Fontify keyword plus procedure name.
1116 (defvar idlwave-idl-keywords 1116 (defvar idlwave-idl-keywords
1117 ;; To update this regexp, update the list of keywords and 1117 ;; To update this regexp, update the list of keywords and
1118 ;; evaluate the form. 1118 ;; evaluate the form.
1119 ;; (insert 1119 ;; (insert
1120 ;; (prin1-to-string 1120 ;; (prin1-to-string
1121 ;; (concat 1121 ;; (concat
1122 ;; "\\<\\(" 1122 ;; "\\<\\("
1123 ;; (regexp-opt 1123 ;; (regexp-opt
1124 ;; '("||" "&&" "and" "or" "xor" "not" 1124 ;; '("||" "&&" "and" "or" "xor" "not"
1125 ;; "eq" "ge" "gt" "le" "lt" "ne" 1125 ;; "eq" "ge" "gt" "le" "lt" "ne"
1126 ;; "for" "do" "endfor" 1126 ;; "for" "do" "endfor"
1127 ;; "if" "then" "endif" "else" "endelse" 1127 ;; "if" "then" "endif" "else" "endelse"
1128 ;; "case" "of" "endcase" 1128 ;; "case" "of" "endcase"
1129 ;; "switch" "break" "continue" "endswitch" 1129 ;; "switch" "break" "continue" "endswitch"
1130 ;; "begin" "end" 1130 ;; "begin" "end"
1131 ;; "repeat" "until" "endrep" 1131 ;; "repeat" "until" "endrep"
1132 ;; "while" "endwhile" 1132 ;; "while" "endwhile"
1133 ;; "goto" "return" 1133 ;; "goto" "return"
1134 ;; "inherits" "mod" 1134 ;; "inherits" "mod"
1135 ;; "compile_opt" "forward_function" 1135 ;; "compile_opt" "forward_function"
1136 ;; "on_error" "on_ioerror")) ; on_error is not officially reserved 1136 ;; "on_error" "on_ioerror")) ; on_error is not officially reserved
1137 ;; "\\)\\>"))) 1137 ;; "\\)\\>")))
1150 '("\\<\\(common\\)\\>[ \t]*\\(\\sw+\\)?[ \t]*,?" 1150 '("\\<\\(common\\)\\>[ \t]*\\(\\sw+\\)?[ \t]*,?"
1151 (1 font-lock-keyword-face) ; "common" 1151 (1 font-lock-keyword-face) ; "common"
1152 (2 font-lock-reference-face nil t) ; block name 1152 (2 font-lock-reference-face nil t) ; block name
1153 (font-lock-match-c++-style-declaration-item-and-skip-to-next 1153 (font-lock-match-c++-style-declaration-item-and-skip-to-next
1154 ;; Start with point after block name and comma 1154 ;; Start with point after block name and comma
1155 (goto-char (match-end 0)) ; needed for XEmacs, could be nil 1155 (goto-char (match-end 0)) ; needed for XEmacs, could be nil
1156 nil 1156 nil
1157 (1 font-lock-variable-name-face) ; variable names 1157 (1 font-lock-variable-name-face) ; variable names
1158 ))) 1158 )))
1159 1159
1160 ;; Batch files 1160 ;; Batch files
1205 '("[<>#]" (0 font-lock-keyword-face))) 1205 '("[<>#]" (0 font-lock-keyword-face)))
1206 1206
1207 ;; All operators (not used because too noisy) 1207 ;; All operators (not used because too noisy)
1208 (all-operators 1208 (all-operators
1209 '("[-*^#+<>/]" (0 font-lock-keyword-face))) 1209 '("[-*^#+<>/]" (0 font-lock-keyword-face)))
1210 1210
1211 ;; Arrows with text property `idlwave-class' 1211 ;; Arrows with text property `idlwave-class'
1212 (class-arrows 1212 (class-arrows
1213 '(idlwave-match-class-arrows (0 idlwave-class-arrow-face)))) 1213 '(idlwave-match-class-arrows (0 idlwave-class-arrow-face))))
1214 1214
1215 (defconst idlwave-font-lock-keywords-1 1215 (defconst idlwave-font-lock-keywords-1
1242 (defvar idlwave-font-lock-keywords idlwave-font-lock-keywords-2 1242 (defvar idlwave-font-lock-keywords idlwave-font-lock-keywords-2
1243 "Default expressions to highlight in IDLWAVE mode.") 1243 "Default expressions to highlight in IDLWAVE mode.")
1244 1244
1245 (defvar idlwave-font-lock-defaults 1245 (defvar idlwave-font-lock-defaults
1246 '((idlwave-font-lock-keywords 1246 '((idlwave-font-lock-keywords
1247 idlwave-font-lock-keywords-1 1247 idlwave-font-lock-keywords-1
1248 idlwave-font-lock-keywords-2 1248 idlwave-font-lock-keywords-2
1249 idlwave-font-lock-keywords-3) 1249 idlwave-font-lock-keywords-3)
1250 nil t 1250 nil t
1251 ((?$ . "w") (?_ . "w") (?. . "w") (?| . "w") (?& . "w")) 1251 ((?$ . "w") (?_ . "w") (?. . "w") (?| . "w") (?& . "w"))
1252 beginning-of-line)) 1252 beginning-of-line))
1253 1253
1254 (put 'idlwave-mode 'font-lock-defaults 1254 (put 'idlwave-mode 'font-lock-defaults
1255 idlwave-font-lock-defaults) ; XEmacs 1255 idlwave-font-lock-defaults) ; XEmacs
1256 1256
1257 (defconst idlwave-comment-line-start-skip "^[ \t]*;" 1257 (defconst idlwave-comment-line-start-skip "^[ \t]*;"
1258 "Regexp to match the start of a full-line comment. 1258 "Regexp to match the start of a full-line comment.
1259 That is the _beginning_ of a line containing a comment delimiter `;' preceded 1259 That is the _beginning_ of a line containing a comment delimiter `;' preceded
1260 only by whitespace.") 1260 only by whitespace.")
1261 1261
1262 (defconst idlwave-begin-block-reg 1262 (defconst idlwave-begin-block-reg
1263 "\\<\\(pro\\|function\\|begin\\|case\\|switch\\)\\>" 1263 "\\<\\(pro\\|function\\|begin\\|case\\|switch\\)\\>"
1264 "Regular expression to find the beginning of a block. The case does 1264 "Regular expression to find the beginning of a block. The case does
1265 not matter. The search skips matches in comments.") 1265 not matter. The search skips matches in comments.")
1266 1266
1267 (defconst idlwave-begin-unit-reg "^\\s-*\\(pro\\|function\\)\\>\\|\\`" 1267 (defconst idlwave-begin-unit-reg "^\\s-*\\(pro\\|function\\)\\>\\|\\`"
1334 '(while . ("while\\>" "do")) 1334 '(while . ("while\\>" "do"))
1335 '(repeat . ("repeat\\>" "repeat")) 1335 '(repeat . ("repeat\\>" "repeat"))
1336 '(goto . ("goto\\>" nil)) 1336 '(goto . ("goto\\>" nil))
1337 '(case . ("case\\>" nil)) 1337 '(case . ("case\\>" nil))
1338 '(switch . ("switch\\>" nil)) 1338 '(switch . ("switch\\>" nil))
1339 (cons 'call (list (concat "\\(" idlwave-variable "\\) *= *" 1339 (cons 'call (list (concat "\\(" idlwave-variable "\\) *= *"
1340 "\\(" idlwave-method-call "\\s *\\)?" 1340 "\\(" idlwave-method-call "\\s *\\)?"
1341 idlwave-identifier 1341 idlwave-identifier
1342 "\\s *(") nil)) 1342 "\\s *(") nil))
1343 (cons 'call (list (concat 1343 (cons 'call (list (concat
1344 "\\(" idlwave-method-call "\\s *\\)?" 1344 "\\(" idlwave-method-call "\\s *\\)?"
1345 idlwave-identifier 1345 idlwave-identifier
1346 "\\( *\\($\\|\\$\\)\\|\\s *,\\)") nil)) 1346 "\\( *\\($\\|\\$\\)\\|\\s *,\\)") nil))
1347 (cons 'assign (list (concat 1347 (cons 'assign (list (concat
1348 "\\(" idlwave-variable "\\) *=") nil))) 1348 "\\(" idlwave-variable "\\) *=") nil)))
1349 1349
1350 "Associated list of statement matching regular expressions. 1350 "Associated list of statement matching regular expressions.
1351 Each regular expression matches the start of an IDL statement. The 1351 Each regular expression matches the start of an IDL statement. The
1352 first element of each association is a symbol giving the statement 1352 first element of each association is a symbol giving the statement
1353 type. The associated value is a list. The first element of this list 1353 type. The associated value is a list. The first element of this list
1354 is a regular expression matching the start of an IDL statement for 1354 is a regular expression matching the start of an IDL statement for
1538 (when (and (boundp 'idlwave-shell-debug-modifiers) 1538 (when (and (boundp 'idlwave-shell-debug-modifiers)
1539 (listp idlwave-shell-debug-modifiers) 1539 (listp idlwave-shell-debug-modifiers)
1540 (not (equal idlwave-shell-debug-modifiers '()))) 1540 (not (equal idlwave-shell-debug-modifiers '())))
1541 ;; Bind the debug commands also with the special modifiers. 1541 ;; Bind the debug commands also with the special modifiers.
1542 (let ((shift (memq 'shift idlwave-shell-debug-modifiers)) 1542 (let ((shift (memq 'shift idlwave-shell-debug-modifiers))
1543 (mods-noshift (delq 'shift 1543 (mods-noshift (delq 'shift
1544 (copy-sequence idlwave-shell-debug-modifiers)))) 1544 (copy-sequence idlwave-shell-debug-modifiers))))
1545 (define-key idlwave-mode-map 1545 (define-key idlwave-mode-map
1546 (vector (append mods-noshift (list (if shift ?C ?c)))) 1546 (vector (append mods-noshift (list (if shift ?C ?c))))
1547 'idlwave-shell-save-and-run) 1547 'idlwave-shell-save-and-run)
1548 (define-key idlwave-mode-map 1548 (define-key idlwave-mode-map
1549 (vector (append mods-noshift (list (if shift ?B ?b)))) 1549 (vector (append mods-noshift (list (if shift ?B ?b))))
1550 'idlwave-shell-break-here) 1550 'idlwave-shell-break-here)
1551 (define-key idlwave-mode-map 1551 (define-key idlwave-mode-map
1552 (vector (append mods-noshift (list (if shift ?E ?e)))) 1552 (vector (append mods-noshift (list (if shift ?E ?e))))
1553 'idlwave-shell-run-region))) 1553 'idlwave-shell-run-region)))
1554 (define-key idlwave-mode-map "\C-c\C-d\C-c" 'idlwave-shell-save-and-run) 1554 (define-key idlwave-mode-map "\C-c\C-d\C-c" 'idlwave-shell-save-and-run)
1555 (define-key idlwave-mode-map "\C-c\C-d\C-b" 'idlwave-shell-break-here) 1555 (define-key idlwave-mode-map "\C-c\C-d\C-b" 'idlwave-shell-break-here)
1556 (define-key idlwave-mode-map "\C-c\C-d\C-e" 'idlwave-shell-run-region) 1556 (define-key idlwave-mode-map "\C-c\C-d\C-e" 'idlwave-shell-run-region)
1582 (define-key idlwave-mode-map [(meta tab)] 'idlwave-complete) 1582 (define-key idlwave-mode-map [(meta tab)] 'idlwave-complete)
1583 (define-key idlwave-mode-map [?\e?\t] 'idlwave-complete) 1583 (define-key idlwave-mode-map [?\e?\t] 'idlwave-complete)
1584 (define-key idlwave-mode-map "\M-\C-i" 'idlwave-complete) 1584 (define-key idlwave-mode-map "\M-\C-i" 'idlwave-complete)
1585 (define-key idlwave-mode-map "\C-c\C-i" 'idlwave-update-routine-info) 1585 (define-key idlwave-mode-map "\C-c\C-i" 'idlwave-update-routine-info)
1586 (define-key idlwave-mode-map "\C-c=" 'idlwave-resolve) 1586 (define-key idlwave-mode-map "\C-c=" 'idlwave-resolve)
1587 (define-key idlwave-mode-map 1587 (define-key idlwave-mode-map
1588 (if (featurep 'xemacs) [(shift button3)] [(shift mouse-3)]) 1588 (if (featurep 'xemacs) [(shift button3)] [(shift mouse-3)])
1589 'idlwave-mouse-context-help) 1589 'idlwave-mouse-context-help)
1590 1590
1591 ;; Set action and key bindings. 1591 ;; Set action and key bindings.
1592 ;; See description of the function `idlwave-action-and-binding'. 1592 ;; See description of the function `idlwave-action-and-binding'.
1593 ;; Automatically add spaces for the following characters 1593 ;; Automatically add spaces for the following characters
1594 ;(idlwave-action-and-binding "&" '(idlwave-surround -1 -1 '(?&) 1 1594 ;(idlwave-action-and-binding "&" '(idlwave-surround -1 -1 '(?&) 1
1595 ; (lambda (char) 0))) 1595 ; (lambda (char) 0)))
1596 (idlwave-action-and-binding "<" '(idlwave-surround -1 -1)) 1596 (idlwave-action-and-binding "<" '(idlwave-surround -1 -1))
1597 ;; Binding works for both > and ->, by changing the length of the token. 1597 ;; Binding works for both > and ->, by changing the length of the token.
1598 (idlwave-action-and-binding ">" '(idlwave-surround -1 -1 '(?-) 1 1598 (idlwave-action-and-binding ">" '(idlwave-surround -1 -1 '(?-) 1
1599 'idlwave-gtr-pad-hook)) 1599 'idlwave-gtr-pad-hook))
1600 (idlwave-action-and-binding "->" '(idlwave-surround -1 -1 nil 2) t) 1600 (idlwave-action-and-binding "->" '(idlwave-surround -1 -1 nil 2) t)
1601 (idlwave-action-and-binding "," '(idlwave-surround 0 -1)) 1601 (idlwave-action-and-binding "," '(idlwave-surround 0 -1))
1602 1602
1603 ;; Automatically add spaces to equal sign if not keyword 1603 ;; Automatically add spaces to equal sign if not keyword
1627 (condition-case nil 1627 (condition-case nil
1628 (apply 'define-abbrev (append args '(0 t))) 1628 (apply 'define-abbrev (append args '(0 t)))
1629 (error (apply 'define-abbrev args))))) 1629 (error (apply 'define-abbrev args)))))
1630 1630
1631 (condition-case nil 1631 (condition-case nil
1632 (modify-syntax-entry (string-to-char idlwave-abbrev-start-char) 1632 (modify-syntax-entry (string-to-char idlwave-abbrev-start-char)
1633 "w" idlwave-mode-syntax-table) 1633 "w" idlwave-mode-syntax-table)
1634 (error nil)) 1634 (error nil))
1635 1635
1636 ;; 1636 ;;
1637 ;; Templates 1637 ;; Templates
1700 (idlwave-define-abbrev "inn" "if n_elements() ne 0 then" (idlwave-keyword-abbrev 11)) 1700 (idlwave-define-abbrev "inn" "if n_elements() ne 0 then" (idlwave-keyword-abbrev 11))
1701 (idlwave-define-abbrev "np" "n_params()" (idlwave-keyword-abbrev 0)) 1701 (idlwave-define-abbrev "np" "n_params()" (idlwave-keyword-abbrev 0))
1702 (idlwave-define-abbrev "s" "size()" (idlwave-keyword-abbrev 1)) 1702 (idlwave-define-abbrev "s" "size()" (idlwave-keyword-abbrev 1))
1703 (idlwave-define-abbrev "wi" "widget_info()" (idlwave-keyword-abbrev 1)) 1703 (idlwave-define-abbrev "wi" "widget_info()" (idlwave-keyword-abbrev 1))
1704 (idlwave-define-abbrev "wc" "widget_control," (idlwave-keyword-abbrev 0)) 1704 (idlwave-define-abbrev "wc" "widget_control," (idlwave-keyword-abbrev 0))
1705 1705
1706 ;; This section is reserved words only. (From IDL user manual) 1706 ;; This section is reserved words only. (From IDL user manual)
1707 ;; 1707 ;;
1708 (idlwave-define-abbrev "and" "and" (idlwave-keyword-abbrev 0 t) t) 1708 (idlwave-define-abbrev "and" "and" (idlwave-keyword-abbrev 0 t) t)
1709 (idlwave-define-abbrev "begin" "begin" (idlwave-keyword-abbrev 0 t) t) 1709 (idlwave-define-abbrev "begin" "begin" (idlwave-keyword-abbrev 0 t) t)
1710 (idlwave-define-abbrev "break" "break" (idlwave-keyword-abbrev 0 t) t) 1710 (idlwave-define-abbrev "break" "break" (idlwave-keyword-abbrev 0 t) t)
1749 (defvar extract-index-name-function) 1749 (defvar extract-index-name-function)
1750 (defvar prev-index-position-function) 1750 (defvar prev-index-position-function)
1751 (defvar imenu-extract-index-name-function) 1751 (defvar imenu-extract-index-name-function)
1752 (defvar imenu-prev-index-position-function) 1752 (defvar imenu-prev-index-position-function)
1753 ;; defined later - so just make the compiler hush 1753 ;; defined later - so just make the compiler hush
1754 (defvar idlwave-mode-menu) 1754 (defvar idlwave-mode-menu)
1755 (defvar idlwave-mode-debug-menu) 1755 (defvar idlwave-mode-debug-menu)
1756 1756
1757 ;;;###autoload 1757 ;;;###autoload
1758 (defun idlwave-mode () 1758 (defun idlwave-mode ()
1759 "Major mode for editing IDL source files (version 5.5). 1759 "Major mode for editing IDL source files (version 5.5).
1834 \\r REPEAT Loop template 1834 \\r REPEAT Loop template
1835 \\w WHILE loop template 1835 \\w WHILE loop template
1836 \\i IF statement template 1836 \\i IF statement template
1837 \\elif IF-ELSE statement template 1837 \\elif IF-ELSE statement template
1838 \\b BEGIN 1838 \\b BEGIN
1839 1839
1840 For a full list, use \\[idlwave-list-abbrevs]. Some templates also 1840 For a full list, use \\[idlwave-list-abbrevs]. Some templates also
1841 have direct keybindings - see the list of keybindings below. 1841 have direct keybindings - see the list of keybindings below.
1842 1842
1843 \\[idlwave-doc-header] inserts a documentation header at the 1843 \\[idlwave-doc-header] inserts a documentation header at the
1844 beginning of the current program unit (pro, function or main). 1844 beginning of the current program unit (pro, function or main).
1876 1876
1877 \\{idlwave-mode-map}" 1877 \\{idlwave-mode-map}"
1878 1878
1879 (interactive) 1879 (interactive)
1880 (kill-all-local-variables) 1880 (kill-all-local-variables)
1881 1881
1882 (if idlwave-startup-message 1882 (if idlwave-startup-message
1883 (message "Emacs IDLWAVE mode version %s." idlwave-mode-version)) 1883 (message "Emacs IDLWAVE mode version %s." idlwave-mode-version))
1884 (setq idlwave-startup-message nil) 1884 (setq idlwave-startup-message nil)
1885 1885
1886 (setq local-abbrev-table idlwave-mode-abbrev-table) 1886 (setq local-abbrev-table idlwave-mode-abbrev-table)
1887 (set-syntax-table idlwave-mode-syntax-table) 1887 (set-syntax-table idlwave-mode-syntax-table)
1888 1888
1889 (set (make-local-variable 'indent-line-function) 'idlwave-indent-and-action) 1889 (set (make-local-variable 'indent-line-function) 'idlwave-indent-and-action)
1890 1890
1891 (make-local-variable idlwave-comment-indent-function) 1891 (make-local-variable idlwave-comment-indent-function)
1892 (set idlwave-comment-indent-function 'idlwave-comment-hook) 1892 (set idlwave-comment-indent-function 'idlwave-comment-hook)
1893 1893
1894 (set (make-local-variable 'comment-start-skip) ";+[ \t]*") 1894 (set (make-local-variable 'comment-start-skip) ";+[ \t]*")
1895 (set (make-local-variable 'comment-start) ";") 1895 (set (make-local-variable 'comment-start) ";")
1896 (set (make-local-variable 'require-final-newline) mode-require-final-newline) 1896 (set (make-local-variable 'require-final-newline) mode-require-final-newline)
1897 (set (make-local-variable 'abbrev-all-caps) t) 1897 (set (make-local-variable 'abbrev-all-caps) t)
1898 (set (make-local-variable 'indent-tabs-mode) nil) 1898 (set (make-local-variable 'indent-tabs-mode) nil)
1899 (set (make-local-variable 'completion-ignore-case) t) 1899 (set (make-local-variable 'completion-ignore-case) t)
1900 1900
1901 (use-local-map idlwave-mode-map) 1901 (use-local-map idlwave-mode-map)
1902 1902
1903 (when (featurep 'easymenu) 1903 (when (featurep 'easymenu)
1904 (easy-menu-add idlwave-mode-menu idlwave-mode-map) 1904 (easy-menu-add idlwave-mode-menu idlwave-mode-map)
1905 (easy-menu-add idlwave-mode-debug-menu idlwave-mode-map)) 1905 (easy-menu-add idlwave-mode-debug-menu idlwave-mode-map))
1906 1906
1907 (setq mode-name "IDLWAVE") 1907 (setq mode-name "IDLWAVE")
1908 (setq major-mode 'idlwave-mode) 1908 (setq major-mode 'idlwave-mode)
1909 (setq abbrev-mode t) 1909 (setq abbrev-mode t)
1910 1910
1911 (set (make-local-variable idlwave-fill-function) 'idlwave-auto-fill) 1911 (set (make-local-variable idlwave-fill-function) 'idlwave-auto-fill)
1912 (setq comment-end "") 1912 (setq comment-end "")
1913 (set (make-local-variable 'comment-multi-line) nil) 1913 (set (make-local-variable 'comment-multi-line) nil)
1914 (set (make-local-variable 'paragraph-separate) 1914 (set (make-local-variable 'paragraph-separate)
1915 "[ \t\f]*$\\|[ \t]*;+[ \t]*$\\|;+[+=-_*]+$") 1915 "[ \t\f]*$\\|[ \t]*;+[ \t]*$\\|;+[+=-_*]+$")
1916 (set (make-local-variable 'paragraph-start) "[ \t\f]\\|[ \t]*;+[ \t]") 1916 (set (make-local-variable 'paragraph-start) "[ \t\f]\\|[ \t]*;+[ \t]")
1917 (set (make-local-variable 'paragraph-ignore-fill-prefix) nil) 1917 (set (make-local-variable 'paragraph-ignore-fill-prefix) nil)
1918 (set (make-local-variable 'parse-sexp-ignore-comments) t) 1918 (set (make-local-variable 'parse-sexp-ignore-comments) t)
1919 1919
1920 ;; Set tag table list to use IDLTAGS as file name. 1920 ;; Set tag table list to use IDLTAGS as file name.
1921 (if (boundp 'tag-table-alist) 1921 (if (boundp 'tag-table-alist)
1922 (add-to-list 'tag-table-alist '("\\.pro$" . "IDLTAGS"))) 1922 (add-to-list 'tag-table-alist '("\\.pro$" . "IDLTAGS")))
1923 1923
1924 ;; Font-lock additions - originally Phil Williams, then Ulrik Dickow 1924 ;; Font-lock additions - originally Phil Williams, then Ulrik Dickow
1925 ;; Following line is for Emacs - XEmacs uses the corresponding property 1925 ;; Following line is for Emacs - XEmacs uses the corresponding property
1926 ;; on the `idlwave-mode' symbol. 1926 ;; on the `idlwave-mode' symbol.
1927 (set (make-local-variable 'font-lock-defaults) idlwave-font-lock-defaults) 1927 (set (make-local-variable 'font-lock-defaults) idlwave-font-lock-defaults)
1928 1928
1959 (defvar idlwave-setup-done nil) 1959 (defvar idlwave-setup-done nil)
1960 (defun idlwave-setup () 1960 (defun idlwave-setup ()
1961 (unless idlwave-setup-done 1961 (unless idlwave-setup-done
1962 (if (not (file-directory-p idlwave-config-directory)) 1962 (if (not (file-directory-p idlwave-config-directory))
1963 (make-directory idlwave-config-directory)) 1963 (make-directory idlwave-config-directory))
1964 (setq idlwave-user-catalog-file (expand-file-name 1964 (setq idlwave-user-catalog-file (expand-file-name
1965 idlwave-user-catalog-file 1965 idlwave-user-catalog-file
1966 idlwave-config-directory) 1966 idlwave-config-directory)
1967 idlwave-path-file (expand-file-name 1967 idlwave-path-file (expand-file-name
1968 idlwave-path-file 1968 idlwave-path-file
1969 idlwave-config-directory)) 1969 idlwave-config-directory))
1970 (idlwave-read-paths) ; we may need these early 1970 (idlwave-read-paths) ; we may need these early
1971 (setq idlwave-setup-done t))) 1971 (setq idlwave-setup-done t)))
1972 1972
1973 ;; 1973 ;;
1974 ;; Code Formatting ---------------------------------------------------- 1974 ;; Code Formatting ----------------------------------------------------
1975 ;; 1975 ;;
1976 1976
1977 (defun idlwave-push-mark (&rest rest) 1977 (defun idlwave-push-mark (&rest rest)
1978 "Push mark for compatibility with Emacs 18/19." 1978 "Push mark for compatibility with Emacs 18/19."
1979 (if (fboundp 'iconify-frame) 1979 (if (fboundp 'iconify-frame)
1980 (apply 'push-mark rest) 1980 (apply 'push-mark rest)
2119 (idlwave-block-jump-out 1 'nomark) 2119 (idlwave-block-jump-out 1 'nomark)
2120 (setq end-pos (point)) 2120 (setq end-pos (point))
2121 (if (> end-pos eol-pos) 2121 (if (> end-pos eol-pos)
2122 (setq end-pos pos)) 2122 (setq end-pos pos))
2123 (goto-char end-pos) 2123 (goto-char end-pos)
2124 (setq end (buffer-substring 2124 (setq end (buffer-substring
2125 (progn 2125 (progn
2126 (skip-chars-backward "a-zA-Z") 2126 (skip-chars-backward "a-zA-Z")
2127 (point)) 2127 (point))
2128 end-pos)) 2128 end-pos))
2129 (goto-char begin-pos) 2129 (goto-char begin-pos)
2141 (insert (if (string= end "END") (upcase end1) end1)) 2141 (insert (if (string= end "END") (upcase end1) end1))
2142 (delete-char 3))) 2142 (delete-char 3)))
2143 (sit-for 1)) 2143 (sit-for 1))
2144 (t 2144 (t
2145 (beep) 2145 (beep)
2146 (message "Warning: Shouldn't this be \"%s\" instead of \"%s\"?" 2146 (message "Warning: Shouldn't this be \"%s\" instead of \"%s\"?"
2147 end1 end) 2147 end1 end)
2148 (sit-for 1)))))))) 2148 (sit-for 1))))))))
2149 ;;(delete-char 1)) 2149 ;;(delete-char 1))
2150 2150
2151 (defun idlwave-block-master () 2151 (defun idlwave-block-master ()
2153 (save-excursion 2153 (save-excursion
2154 (cond 2154 (cond
2155 ((looking-at "pro\\|case\\|switch\\|function\\>") 2155 ((looking-at "pro\\|case\\|switch\\|function\\>")
2156 (assoc (downcase (match-string 0)) idlwave-block-matches)) 2156 (assoc (downcase (match-string 0)) idlwave-block-matches))
2157 ((looking-at "begin\\>") 2157 ((looking-at "begin\\>")
2158 (let ((limit (save-excursion 2158 (let ((limit (save-excursion
2159 (idlwave-beginning-of-statement) 2159 (idlwave-beginning-of-statement)
2160 (point)))) 2160 (point))))
2161 (cond 2161 (cond
2162 ((re-search-backward ":[ \t]*\\=" limit t) 2162 ((re-search-backward ":[ \t]*\\=" limit t)
2163 ;; seems to be a case thing 2163 ;; seems to be a case thing
2164 '("begin" . "end")) 2164 '("begin" . "end"))
2182 (newline-and-indent))) 2182 (newline-and-indent)))
2183 (let ((last-abbrev-location (point))) ; for upcasing 2183 (let ((last-abbrev-location (point))) ; for upcasing
2184 (insert "end") 2184 (insert "end")
2185 (idlwave-show-begin))) 2185 (idlwave-show-begin)))
2186 2186
2187 (defun idlwave-gtr-pad-hook (char) 2187 (defun idlwave-gtr-pad-hook (char)
2188 "Let the > symbol expand around -> if present. The new token length 2188 "Let the > symbol expand around -> if present. The new token length
2189 is returned." 2189 is returned."
2190 2) 2190 2)
2191 2191
2192 (defun idlwave-surround (&optional before after escape-chars length ec-hook) 2192 (defun idlwave-surround (&optional before after escape-chars length ec-hook)
2193 "Surround the LENGTH characters before point with blanks. 2193 "Surround the LENGTH characters before point with blanks.
2194 LENGTH defaults to 1. 2194 LENGTH defaults to 1.
2214 return value." 2214 return value."
2215 (when (and idlwave-surround-by-blank (not (idlwave-quoted))) 2215 (when (and idlwave-surround-by-blank (not (idlwave-quoted)))
2216 (let* ((length (or length 1)) ; establish a default for LENGTH 2216 (let* ((length (or length 1)) ; establish a default for LENGTH
2217 (prev-char (char-after (- (point) (1+ length))))) 2217 (prev-char (char-after (- (point) (1+ length)))))
2218 (when (or (not (memq prev-char escape-chars)) 2218 (when (or (not (memq prev-char escape-chars))
2219 (and (fboundp ec-hook) 2219 (and (fboundp ec-hook)
2220 (setq length 2220 (setq length
2221 (save-excursion (funcall ec-hook prev-char))))) 2221 (save-excursion (funcall ec-hook prev-char)))))
2222 (backward-char length) 2222 (backward-char length)
2223 (save-restriction 2223 (save-restriction
2224 (let ((here (point))) 2224 (let ((here (point)))
2225 (skip-chars-backward " \t") 2225 (skip-chars-backward " \t")
2437 (if (< arg 0) 2437 (if (< arg 0)
2438 ;; Backward 2438 ;; Backward
2439 (let ((eos (save-excursion 2439 (let ((eos (save-excursion
2440 (idlwave-block-jump-out -1 'nomark) 2440 (idlwave-block-jump-out -1 'nomark)
2441 (point)))) 2441 (point))))
2442 (if (setq status (idlwave-find-key 2442 (if (setq status (idlwave-find-key
2443 idlwave-end-block-reg -1 'nomark eos)) 2443 idlwave-end-block-reg -1 'nomark eos))
2444 (idlwave-beginning-of-statement) 2444 (idlwave-beginning-of-statement)
2445 (message "No nested block before beginning of containing block."))) 2445 (message "No nested block before beginning of containing block.")))
2446 ;; Forward 2446 ;; Forward
2447 (let ((eos (save-excursion 2447 (let ((eos (save-excursion
2448 (idlwave-block-jump-out 1 'nomark) 2448 (idlwave-block-jump-out 1 'nomark)
2449 (point)))) 2449 (point))))
2450 (if (setq status (idlwave-find-key 2450 (if (setq status (idlwave-find-key
2451 idlwave-begin-block-reg 1 'nomark eos)) 2451 idlwave-begin-block-reg 1 'nomark eos))
2452 (idlwave-end-of-statement) 2452 (idlwave-end-of-statement)
2453 (message "No nested block before end of containing block.")))) 2453 (message "No nested block before end of containing block."))))
2454 status)) 2454 status))
2455 2455
2459 (interactive) 2459 (interactive)
2460 (let (beg 2460 (let (beg
2461 (here (point))) 2461 (here (point)))
2462 (goto-char (point-max)) 2462 (goto-char (point-max))
2463 (if (re-search-backward idlwave-doclib-start nil t) 2463 (if (re-search-backward idlwave-doclib-start nil t)
2464 (progn 2464 (progn
2465 (setq beg (progn (beginning-of-line) (point))) 2465 (setq beg (progn (beginning-of-line) (point)))
2466 (if (re-search-forward idlwave-doclib-end nil t) 2466 (if (re-search-forward idlwave-doclib-end nil t)
2467 (progn 2467 (progn
2468 (forward-line 1) 2468 (forward-line 1)
2469 (idlwave-push-mark beg nil t) 2469 (idlwave-push-mark beg nil t)
2493 (interactive) 2493 (interactive)
2494 (cond 2494 (cond
2495 ((eq major-mode 'idlwave-shell-mode) 2495 ((eq major-mode 'idlwave-shell-mode)
2496 (if (re-search-backward idlwave-shell-prompt-pattern nil t) 2496 (if (re-search-backward idlwave-shell-prompt-pattern nil t)
2497 (goto-char (match-end 0)))) 2497 (goto-char (match-end 0))))
2498 (t 2498 (t
2499 (if (save-excursion (forward-line -1) (idlwave-is-continuation-line)) 2499 (if (save-excursion (forward-line -1) (idlwave-is-continuation-line))
2500 (idlwave-previous-statement) 2500 (idlwave-previous-statement)
2501 (beginning-of-line))))) 2501 (beginning-of-line)))))
2502 2502
2503 (defun idlwave-previous-statement () 2503 (defun idlwave-previous-statement ()
2570 (defun idlwave-skip-multi-commands (&optional lim) 2570 (defun idlwave-skip-multi-commands (&optional lim)
2571 "Skip past multiple commands on a line (with `&')." 2571 "Skip past multiple commands on a line (with `&')."
2572 (let ((save-point (point))) 2572 (let ((save-point (point)))
2573 (when (re-search-forward ".*&" lim t) 2573 (when (re-search-forward ".*&" lim t)
2574 (goto-char (match-end 0)) 2574 (goto-char (match-end 0))
2575 (if (idlwave-quoted) 2575 (if (idlwave-quoted)
2576 (goto-char save-point) 2576 (goto-char save-point)
2577 (if (eq (char-after (- (point) 2)) ?&) (goto-char save-point)))) 2577 (if (eq (char-after (- (point) 2)) ?&) (goto-char save-point))))
2578 (point))) 2578 (point)))
2579 2579
2580 (defun idlwave-skip-label-or-case () 2580 (defun idlwave-skip-label-or-case ()
2587 ;; - it is not in a comment 2587 ;; - it is not in a comment
2588 ;; - not in a string constant 2588 ;; - not in a string constant
2589 ;; - not in parenthesis (like a[0:3]) 2589 ;; - not in parenthesis (like a[0:3])
2590 ;; - not followed by another ":" in explicit class, ala a->b::c 2590 ;; - not followed by another ":" in explicit class, ala a->b::c
2591 ;; As many in this mode, this function is heuristic and not an exact 2591 ;; As many in this mode, this function is heuristic and not an exact
2592 ;; parser. 2592 ;; parser.
2593 (let* ((start (point)) 2593 (let* ((start (point))
2594 (eos (save-excursion (idlwave-end-of-statement) (point))) 2594 (eos (save-excursion (idlwave-end-of-statement) (point)))
2595 (end (idlwave-find-key ":" 1 'nomark eos))) 2595 (end (idlwave-find-key ":" 1 'nomark eos)))
2596 (if (and end 2596 (if (and end
2597 (= (nth 0 (parse-partial-sexp start end)) 0) 2597 (= (nth 0 (parse-partial-sexp start end)) 0)
2664 `idlwave-start-of-substatement' and `idlwave-statement-type'. The 2664 `idlwave-start-of-substatement' and `idlwave-statement-type'. The
2665 equal sign will be surrounded by BEFORE and AFTER blanks. If 2665 equal sign will be surrounded by BEFORE and AFTER blanks. If
2666 `idlwave-pad-keyword' is t then keyword assignment is treated just 2666 `idlwave-pad-keyword' is t then keyword assignment is treated just
2667 like assignment statements. When nil, spaces are removed for keyword 2667 like assignment statements. When nil, spaces are removed for keyword
2668 assignment. Any other value keeps the current space around the `='. 2668 assignment. Any other value keeps the current space around the `='.
2669 Limits in for loops are treated as keyword assignment. 2669 Limits in for loops are treated as keyword assignment.
2670 2670
2671 Starting with IDL 6.0, a number of op= assignments are available. 2671 Starting with IDL 6.0, a number of op= assignments are available.
2672 Since ambiguities of the form: 2672 Since ambiguities of the form:
2673 2673
2674 r and= b 2674 r and= b
2679 \(not just for padding, but for proper parsing by IDL too!). Other 2679 \(not just for padding, but for proper parsing by IDL too!). Other
2680 operators, such as ##=, ^=, etc., will be pre-padded. 2680 operators, such as ##=, ^=, etc., will be pre-padded.
2681 2681
2682 See `idlwave-surround'." 2682 See `idlwave-surround'."
2683 (if idlwave-surround-by-blank 2683 (if idlwave-surround-by-blank
2684 (let 2684 (let
2685 ((non-an-ops "\\(##\\|\\*\\|\\+\\|-\\|/\\|<\\|>\\|\\^\\)\\=") 2685 ((non-an-ops "\\(##\\|\\*\\|\\+\\|-\\|/\\|<\\|>\\|\\^\\)\\=")
2686 (an-ops 2686 (an-ops
2687 "\\s-\\(AND\\|EQ\\|GE\\|GT\\|LE\\|LT\\|MOD\\|NE\\|OR\\|XOR\\)\\=") 2687 "\\s-\\(AND\\|EQ\\|GE\\|GT\\|LE\\|LT\\|MOD\\|NE\\|OR\\|XOR\\)\\=")
2688 (len 1)) 2688 (len 1))
2689 2689
2690 (save-excursion 2690 (save-excursion
2691 (let ((case-fold-search t)) 2691 (let ((case-fold-search t))
2692 (backward-char) 2692 (backward-char)
2693 (if (or 2693 (if (or
2694 (re-search-backward non-an-ops nil t) 2694 (re-search-backward non-an-ops nil t)
2695 ;; Why doesn't ##? work for both? 2695 ;; Why doesn't ##? work for both?
2696 (re-search-backward "\\(#\\)\\=" nil t)) 2696 (re-search-backward "\\(#\\)\\=" nil t))
2697 (setq len (1+ (length (match-string 1)))) 2697 (setq len (1+ (length (match-string 1))))
2698 (when (re-search-backward an-ops nil t) 2698 (when (re-search-backward an-ops nil t)
2699 (setq begin nil) ; won't modify begin 2699 (setq begin nil) ; won't modify begin
2700 (setq len (1+ (length (match-string 1)))))))) 2700 (setq len (1+ (length (match-string 1))))))))
2701 2701
2702 (if (eq t idlwave-pad-keyword) 2702 (if (eq t idlwave-pad-keyword)
2703 ;; Everything gets padded equally 2703 ;; Everything gets padded equally
2704 (idlwave-surround before after nil len) 2704 (idlwave-surround before after nil len)
2705 ;; Treating keywords/for variables specially... 2705 ;; Treating keywords/for variables specially...
2706 (let ((st (save-excursion ; To catch "for" variables 2706 (let ((st (save-excursion ; To catch "for" variables
2707 (idlwave-start-of-substatement t) 2707 (idlwave-start-of-substatement t)
2708 (idlwave-statement-type))) 2708 (idlwave-statement-type)))
2709 (what (save-excursion ; To catch keywords 2709 (what (save-excursion ; To catch keywords
2710 (skip-chars-backward "= \t") 2710 (skip-chars-backward "= \t")
2711 (nth 2 (idlwave-where))))) 2711 (nth 2 (idlwave-where)))))
2712 (cond ((or (memq what '(function-keyword procedure-keyword)) 2712 (cond ((or (memq what '(function-keyword procedure-keyword))
2713 (memq (caar st) '(for pdef))) 2713 (memq (caar st) '(for pdef)))
2714 (cond 2714 (cond
2715 ((null idlwave-pad-keyword) 2715 ((null idlwave-pad-keyword)
2716 (idlwave-surround 0 0) 2716 (idlwave-surround 0 0)
2717 ) ; remove space 2717 ) ; remove space
2718 (t))) ; leave any spaces alone 2718 (t))) ; leave any spaces alone
2719 (t (idlwave-surround before after nil len)))))))) 2719 (t (idlwave-surround before after nil len))))))))
2720 2720
2721 2721
2722 (defun idlwave-indent-and-action (&optional arg) 2722 (defun idlwave-indent-and-action (&optional arg)
2723 "Call `idlwave-indent-line' and do expand actions. 2723 "Call `idlwave-indent-line' and do expand actions.
2724 With prefix ARG non-nil, indent the entire sub-statement." 2724 With prefix ARG non-nil, indent the entire sub-statement."
2725 (interactive "p") 2725 (interactive "p")
2726 (save-excursion 2726 (save-excursion
2727 (if (and idlwave-expand-generic-end 2727 (if (and idlwave-expand-generic-end
2728 (re-search-backward "\\<\\(end\\)\\s-*\\=" 2728 (re-search-backward "\\<\\(end\\)\\s-*\\="
2729 (max 0 (- (point) 10)) t) 2729 (max 0 (- (point) 10)) t)
2730 (looking-at "\\(end\\)\\([ \n\t]\\|\\'\\)")) 2730 (looking-at "\\(end\\)\\([ \n\t]\\|\\'\\)"))
2731 (progn (goto-char (match-end 1)) 2731 (progn (goto-char (match-end 1))
2732 ;;Expand the END abbreviation, just as RET or Space would have. 2732 ;;Expand the END abbreviation, just as RET or Space would have.
2733 (if abbrev-mode (expand-abbrev) 2733 (if abbrev-mode (expand-abbrev)
2734 (idlwave-show-begin))))) 2734 (idlwave-show-begin)))))
2735 (when (and (not arg) current-prefix-arg) 2735 (when (and (not arg) current-prefix-arg)
2736 (setq arg current-prefix-arg) 2736 (setq arg current-prefix-arg)
2737 (setq current-prefix-arg nil)) 2737 (setq current-prefix-arg nil))
2738 (if arg 2738 (if arg
2739 (idlwave-indent-statement) 2739 (idlwave-indent-statement)
2740 (idlwave-indent-line t))) 2740 (idlwave-indent-line t)))
2741 2741
2742 (defun idlwave-indent-line (&optional expand) 2742 (defun idlwave-indent-line (&optional expand)
2743 "Indents current IDL line as code or as a comment. 2743 "Indents current IDL line as code or as a comment.
2866 (the-indent 2866 (the-indent
2867 ;; calculate indent based on previous statement 2867 ;; calculate indent based on previous statement
2868 (save-excursion 2868 (save-excursion
2869 (cond 2869 (cond
2870 ;; Beginning of file 2870 ;; Beginning of file
2871 ((prog1 2871 ((prog1
2872 (idlwave-previous-statement) 2872 (idlwave-previous-statement)
2873 (setq beg-prev-pos (point))) 2873 (setq beg-prev-pos (point)))
2874 0) 2874 0)
2875 ;; Main block 2875 ;; Main block
2876 ((idlwave-look-at idlwave-begin-unit-reg t) 2876 ((idlwave-look-at idlwave-begin-unit-reg t)
2877 (+ (idlwave-current-statement-indent) 2877 (+ (idlwave-current-statement-indent)
2878 idlwave-main-block-indent)) 2878 idlwave-main-block-indent))
2879 ;; Begin block 2879 ;; Begin block
2880 ((idlwave-look-at idlwave-begin-block-reg t) 2880 ((idlwave-look-at idlwave-begin-block-reg t)
2881 (+ (idlwave-min-current-statement-indent) 2881 (+ (idlwave-min-current-statement-indent)
2882 idlwave-block-indent)) 2882 idlwave-block-indent))
2883 ;; End Block 2883 ;; End Block
2884 ((idlwave-look-at idlwave-end-block-reg t) 2884 ((idlwave-look-at idlwave-end-block-reg t)
2885 (progn 2885 (progn
2886 ;; Match to the *beginning* of the block opener 2886 ;; Match to the *beginning* of the block opener
2887 (goto-char beg-prev-pos) 2887 (goto-char beg-prev-pos)
2888 (idlwave-block-jump-out -1 'nomark) ; go to begin block 2888 (idlwave-block-jump-out -1 'nomark) ; go to begin block
2889 (idlwave-min-current-statement-indent))) 2889 (idlwave-min-current-statement-indent)))
2890 ;; idlwave-end-offset 2890 ;; idlwave-end-offset
2891 ;; idlwave-block-indent)) 2891 ;; idlwave-block-indent))
2892 2892
2893 ;; Default to current indent 2893 ;; Default to current indent
2894 ((idlwave-current-statement-indent)))))) 2894 ((idlwave-current-statement-indent))))))
2895 ;; adjust the indentation based on the current statement 2895 ;; adjust the indentation based on the current statement
2896 (cond 2896 (cond
2897 ;; End block 2897 ;; End block
2903 ;; Parentheses indent 2903 ;; Parentheses indent
2904 ;; 2904 ;;
2905 2905
2906 (defun idlwave-calculate-paren-indent (beg-reg end-reg close-exp) 2906 (defun idlwave-calculate-paren-indent (beg-reg end-reg close-exp)
2907 "Calculate the continuation indent inside a paren group. 2907 "Calculate the continuation indent inside a paren group.
2908 Returns a cons-cell with (open . indent), where open is the 2908 Returns a cons-cell with (open . indent), where open is the
2909 location of the open paren" 2909 location of the open paren"
2910 (let ((open (nth 1 (parse-partial-sexp beg-reg end-reg)))) 2910 (let ((open (nth 1 (parse-partial-sexp beg-reg end-reg))))
2911 ;; Found an innermost open paren. 2911 ;; Found an innermost open paren.
2912 (when open 2912 (when open
2913 (goto-char open) 2913 (goto-char open)
2944 (save-excursion 2944 (save-excursion
2945 (let* ((case-fold-search t) 2945 (let* ((case-fold-search t)
2946 (end-reg (progn (beginning-of-line) (point))) 2946 (end-reg (progn (beginning-of-line) (point)))
2947 (beg-last-statement (save-excursion (idlwave-previous-statement) 2947 (beg-last-statement (save-excursion (idlwave-previous-statement)
2948 (point))) 2948 (point)))
2949 (beg-reg (progn (idlwave-start-of-substatement 'pre) 2949 (beg-reg (progn (idlwave-start-of-substatement 'pre)
2950 (if (eq (line-beginning-position) end-reg) 2950 (if (eq (line-beginning-position) end-reg)
2951 (goto-char beg-last-statement) 2951 (goto-char beg-last-statement)
2952 (point)))) 2952 (point))))
2953 (basic-indent (+ (idlwave-min-current-statement-indent end-reg) 2953 (basic-indent (+ (idlwave-min-current-statement-indent end-reg)
2954 idlwave-continuation-indent)) 2954 idlwave-continuation-indent))
2955 fancy-nonparen-indent fancy-paren-indent) 2955 fancy-nonparen-indent fancy-paren-indent)
2956 (cond 2956 (cond
2957 ;; Align then with its matching if, etc. 2957 ;; Align then with its matching if, etc.
2958 ((let ((matchers '(("\\<if\\>" . "[ \t]*then") 2958 ((let ((matchers '(("\\<if\\>" . "[ \t]*then")
2959 ("\\<\\(if\\|end\\(if\\)?\\)\\>" . "[ \t]*else") 2959 ("\\<\\(if\\|end\\(if\\)?\\)\\>" . "[ \t]*else")
2960 ("\\<\\(for\\|while\\)\\>" . "[ \t]*do") 2960 ("\\<\\(for\\|while\\)\\>" . "[ \t]*do")
2961 ("\\<\\(repeat\\|end\\(rep\\)?\\)\\>" . 2961 ("\\<\\(repeat\\|end\\(rep\\)?\\)\\>" .
2962 "[ \t]*until") 2962 "[ \t]*until")
2963 ("\\<case\\>" . "[ \t]*of"))) 2963 ("\\<case\\>" . "[ \t]*of")))
2964 match cont-re) 2964 match cont-re)
2965 (goto-char end-reg) 2965 (goto-char end-reg)
2966 (and 2966 (and
2967 (setq cont-re 2967 (setq cont-re
2968 (catch 'exit 2968 (catch 'exit
2969 (while (setq match (car matchers)) 2969 (while (setq match (car matchers))
2970 (if (looking-at (cdr match)) 2970 (if (looking-at (cdr match))
2971 (throw 'exit (car match))) 2971 (throw 'exit (car match)))
2972 (setq matchers (cdr matchers))))) 2972 (setq matchers (cdr matchers)))))
2973 (idlwave-find-key cont-re -1 'nomark beg-last-statement))) 2973 (idlwave-find-key cont-re -1 'nomark beg-last-statement)))
2974 (if (looking-at "end") ;; that one's special 2974 (if (looking-at "end") ;; that one's special
2975 (- (idlwave-current-indent) 2975 (- (idlwave-current-indent)
2976 (+ idlwave-block-indent idlwave-end-offset)) 2976 (+ idlwave-block-indent idlwave-end-offset))
2977 (idlwave-current-indent))) 2977 (idlwave-current-indent)))
2978 2978
2979 ;; Indent in from the previous line for continuing statements 2979 ;; Indent in from the previous line for continuing statements
2980 ((let ((matchers '("\\<then\\>" 2980 ((let ((matchers '("\\<then\\>"
2996 ;; Parenthetical indent, either traditional or Kernighan style 2996 ;; Parenthetical indent, either traditional or Kernighan style
2997 ((setq fancy-paren-indent 2997 ((setq fancy-paren-indent
2998 (let* ((end-reg end-reg) 2998 (let* ((end-reg end-reg)
2999 (close-exp (progn 2999 (close-exp (progn
3000 (goto-char end-reg) 3000 (goto-char end-reg)
3001 (skip-chars-forward " \t") 3001 (skip-chars-forward " \t")
3002 (looking-at "\\s)"))) 3002 (looking-at "\\s)")))
3003 indent-cons) 3003 indent-cons)
3004 (catch 'loop 3004 (catch 'loop
3005 (while (setq indent-cons (idlwave-calculate-paren-indent 3005 (while (setq indent-cons (idlwave-calculate-paren-indent
3006 beg-reg end-reg close-exp)) 3006 beg-reg end-reg close-exp))
3030 (goto-char (match-end 0)) 3030 (goto-char (match-end 0))
3031 ;; Comment only, or blank line with "$"? Basic indent. 3031 ;; Comment only, or blank line with "$"? Basic indent.
3032 (if (save-match-data (looking-at "[ \t$]*\\(;.*\\)?$")) 3032 (if (save-match-data (looking-at "[ \t$]*\\(;.*\\)?$"))
3033 nil 3033 nil
3034 (current-column))) 3034 (current-column)))
3035 3035
3036 ;; Continued assignment (with =): 3036 ;; Continued assignment (with =):
3037 ((catch 'assign ; 3037 ((catch 'assign ;
3038 (while (looking-at "[^=\n\r]*\\(=\\)[ \t]*") 3038 (while (looking-at "[^=\n\r]*\\(=\\)[ \t]*")
3039 (goto-char (match-end 0)) 3039 (goto-char (match-end 0))
3040 (if (null (idlwave-what-function beg-reg)) 3040 (if (null (idlwave-what-function beg-reg))
3041 (throw 'assign t)))) 3041 (throw 'assign t))))
3042 (unless (or 3042 (unless (or
3043 (idlwave-in-quote) 3043 (idlwave-in-quote)
3044 (looking-at "[ \t$]*\\(;.*\\)?$") ; use basic 3044 (looking-at "[ \t$]*\\(;.*\\)?$") ; use basic
3045 (save-excursion 3045 (save-excursion
3097 (interactive "P") 3097 (interactive "P")
3098 (or dir (setq dir 0)) 3098 (or dir (setq dir 0))
3099 (let* ((here (point)) 3099 (let* ((here (point))
3100 (case-fold-search t) 3100 (case-fold-search t)
3101 (limit (if (>= dir 0) (point-max) (point-min))) 3101 (limit (if (>= dir 0) (point-max) (point-min)))
3102 (block-limit (if (>= dir 0) 3102 (block-limit (if (>= dir 0)
3103 idlwave-begin-block-reg 3103 idlwave-begin-block-reg
3104 idlwave-end-block-reg)) 3104 idlwave-end-block-reg))
3105 found 3105 found
3106 (block-reg (concat idlwave-begin-block-reg "\\|" 3106 (block-reg (concat idlwave-begin-block-reg "\\|"
3107 idlwave-end-block-reg)) 3107 idlwave-end-block-reg))
3108 (unit-limit (or (save-excursion 3108 (unit-limit (or (save-excursion
3109 (if (< dir 0) 3109 (if (< dir 0)
3110 (idlwave-find-key 3110 (idlwave-find-key
3111 idlwave-begin-unit-reg dir t limit) 3111 idlwave-begin-unit-reg dir t limit)
3112 (end-of-line) 3112 (end-of-line)
3113 (idlwave-find-key 3113 (idlwave-find-key
3114 idlwave-end-unit-reg dir t limit))) 3114 idlwave-end-unit-reg dir t limit)))
3115 limit))) 3115 limit)))
3116 (if (>= dir 0) (end-of-line)) ;Make sure we are in current block 3116 (if (>= dir 0) (end-of-line)) ;Make sure we are in current block
3117 (if (setq found (idlwave-find-key block-reg dir t unit-limit)) 3117 (if (setq found (idlwave-find-key block-reg dir t unit-limit))
3118 (while (and found (looking-at block-limit)) 3118 (while (and found (looking-at block-limit))
3133 (or (setq comm-or-empty (idlwave-is-comment-or-empty-line)) 3133 (or (setq comm-or-empty (idlwave-is-comment-or-empty-line))
3134 (idlwave-is-continuation-line)) 3134 (idlwave-is-continuation-line))
3135 (or (null end-reg) (< (point) end-reg))) 3135 (or (null end-reg) (< (point) end-reg)))
3136 (unless comm-or-empty (setq min (min min (idlwave-current-indent))))) 3136 (unless comm-or-empty (setq min (min min (idlwave-current-indent)))))
3137 (if (or comm-or-empty (and end-reg (>= (point) end-reg))) 3137 (if (or comm-or-empty (and end-reg (>= (point) end-reg)))
3138 min 3138 min
3139 (min min (idlwave-current-indent)))))) 3139 (min min (idlwave-current-indent))))))
3140 3140
3141 (defun idlwave-current-statement-indent (&optional last-line) 3141 (defun idlwave-current-statement-indent (&optional last-line)
3142 "Return indentation of the current statement. 3142 "Return indentation of the current statement.
3143 If in a statement, moves to beginning of statement before finding indent." 3143 If in a statement, moves to beginning of statement before finding indent."
3159 (defun idlwave-is-continuation-line () 3159 (defun idlwave-is-continuation-line ()
3160 "Tests if current line is continuation line. 3160 "Tests if current line is continuation line.
3161 Blank or comment-only lines following regular continuation lines (with 3161 Blank or comment-only lines following regular continuation lines (with
3162 `$') count as continuations too." 3162 `$') count as continuations too."
3163 (save-excursion 3163 (save-excursion
3164 (or 3164 (or
3165 (idlwave-look-at "\\<\\$") 3165 (idlwave-look-at "\\<\\$")
3166 (catch 'loop 3166 (catch 'loop
3167 (while (and (looking-at "^[ \t]*\\(;.*\\)?$") 3167 (while (and (looking-at "^[ \t]*\\(;.*\\)?$")
3168 (eq (forward-line -1) 0)) 3168 (eq (forward-line -1) 0))
3169 (if (idlwave-look-at "\\<\\$") (throw 'loop t))))))) 3169 (if (idlwave-look-at "\\<\\$") (throw 'loop t)))))))
3170 3170
3171 (defun idlwave-is-comment-line () 3171 (defun idlwave-is-comment-line ()
3172 "Tests if the current line is a comment line." 3172 "Tests if the current line is a comment line."
3260 (regexp-quote 3260 (regexp-quote
3261 (buffer-substring (save-excursion 3261 (buffer-substring (save-excursion
3262 (beginning-of-line) (point)) 3262 (beginning-of-line) (point))
3263 (point)))) 3263 (point))))
3264 "[^;]")) 3264 "[^;]"))
3265 3265
3266 ;; Mark the beginning and end of the paragraph 3266 ;; Mark the beginning and end of the paragraph
3267 (goto-char bcl) 3267 (goto-char bcl)
3268 (while (and (looking-at fill-prefix-reg) 3268 (while (and (looking-at fill-prefix-reg)
3269 (not (looking-at paragraph-separate)) 3269 (not (looking-at paragraph-separate))
3270 (not (bobp))) 3270 (not (bobp)))
3324 ;; inserted text. 3324 ;; inserted text.
3325 (setq here (+ here diff))) 3325 (setq here (+ here diff)))
3326 (insert (make-string diff ?\ )))) 3326 (insert (make-string diff ?\ ))))
3327 (forward-line -1)) 3327 (forward-line -1))
3328 ) 3328 )
3329 3329
3330 ;; No hang. Instead find minimum indentation of paragraph 3330 ;; No hang. Instead find minimum indentation of paragraph
3331 ;; after first line. 3331 ;; after first line.
3332 ;; For the following while statement, since START is at the 3332 ;; For the following while statement, since START is at the
3333 ;; beginning of line and END is at the end of line 3333 ;; beginning of line and END is at the end of line
3334 ;; point is greater than START at least once (which would 3334 ;; point is greater than START at least once (which would
3356 comment-start-skip 3356 comment-start-skip
3357 (save-excursion (end-of-line) (point)) 3357 (save-excursion (end-of-line) (point))
3358 t) 3358 t)
3359 (current-column)) 3359 (current-column))
3360 indent)) 3360 indent))
3361 3361
3362 ;; try to keep point at its original place 3362 ;; try to keep point at its original place
3363 (goto-char here) 3363 (goto-char here)
3364 3364
3365 ;; In place of the more modern fill-region-as-paragraph, a hack 3365 ;; In place of the more modern fill-region-as-paragraph, a hack
3366 ;; to keep whitespace untouched on the first line within the 3366 ;; to keep whitespace untouched on the first line within the
3405 (save-excursion (end-of-line) (point)) 3405 (save-excursion (end-of-line) (point))
3406 t) 3406 t)
3407 (current-column))))) 3407 (current-column)))))
3408 3408
3409 (defun idlwave-auto-fill () 3409 (defun idlwave-auto-fill ()
3410 "Called to break lines in auto fill mode. 3410 "Called to break lines in auto fill mode.
3411 Only fills non-comment lines if `idlwave-fill-comment-line-only' is 3411 Only fills non-comment lines if `idlwave-fill-comment-line-only' is
3412 non-nil. Places a continuation character at the end of the line if 3412 non-nil. Places a continuation character at the end of the line if
3413 not in a comment. Splits strings with IDL concatenation operator `+' 3413 not in a comment. Splits strings with IDL concatenation operator `+'
3414 if `idlwave-auto-fill-split-string' is non-nil." 3414 if `idlwave-auto-fill-split-string' is non-nil."
3415 (if (<= (current-column) fill-column) 3415 (if (<= (current-column) fill-column)
3556 (defun idlwave-default-insert-timestamp () 3556 (defun idlwave-default-insert-timestamp ()
3557 "Default timestamp insertion function" 3557 "Default timestamp insertion function"
3558 (insert (current-time-string)) 3558 (insert (current-time-string))
3559 (insert ", " (user-full-name)) 3559 (insert ", " (user-full-name))
3560 (if (boundp 'user-mail-address) 3560 (if (boundp 'user-mail-address)
3561 (insert " <" user-mail-address ">") 3561 (insert " <" user-mail-address ">")
3562 (insert " <" (user-login-name) "@" (system-name) ">")) 3562 (insert " <" (user-login-name) "@" (system-name) ">"))
3563 ;; Remove extra spaces from line 3563 ;; Remove extra spaces from line
3564 (idlwave-fill-paragraph) 3564 (idlwave-fill-paragraph)
3565 ;; Insert a blank line comment to separate from the date entry - 3565 ;; Insert a blank line comment to separate from the date entry -
3566 ;; will keep the entry from flowing onto date line if re-filled. 3566 ;; will keep the entry from flowing onto date line if re-filled.
3582 (setq beg (match-beginning 0)) 3582 (setq beg (match-beginning 0))
3583 (re-search-forward idlwave-doclib-end nil t) 3583 (re-search-forward idlwave-doclib-end nil t)
3584 (setq end (match-end 0))) 3584 (setq end (match-end 0)))
3585 (progn 3585 (progn
3586 (goto-char beg) 3586 (goto-char beg)
3587 (if (re-search-forward 3587 (if (re-search-forward
3588 (concat idlwave-doc-modifications-keyword ":") 3588 (concat idlwave-doc-modifications-keyword ":")
3589 end t) 3589 end t)
3590 (end-of-line) 3590 (end-of-line)
3591 (goto-char end) 3591 (goto-char end)
3592 (end-of-line -1) 3592 (end-of-line -1)
3680 (and 3680 (and
3681 (eq (char-after) ?\*) 3681 (eq (char-after) ?\*)
3682 (not (idlwave-in-quote)) 3682 (not (idlwave-in-quote))
3683 (save-excursion 3683 (save-excursion
3684 (forward-char) 3684 (forward-char)
3685 (re-search-backward (concat "\\(" idlwave-idl-keywords 3685 (re-search-backward (concat "\\(" idlwave-idl-keywords
3686 "\\|[[(*+-/=,^><]\\)\\s-*\\*") limit t))))) 3686 "\\|[[(*+-/=,^><]\\)\\s-*\\*") limit t)))))
3687 3687
3688 3688
3689 ;; Statement templates 3689 ;; Statement templates
3690 3690
3726 (setq end (point))) 3726 (setq end (point)))
3727 (if (not noindent) 3727 (if (not noindent)
3728 (indent-region beg end nil)) 3728 (indent-region beg end nil))
3729 (if (stringp prompt) 3729 (if (stringp prompt)
3730 (message prompt))))) 3730 (message prompt)))))
3731 3731
3732 (defun idlwave-rw-case (string) 3732 (defun idlwave-rw-case (string)
3733 "Make STRING have the case required by `idlwave-reserved-word-upcase'." 3733 "Make STRING have the case required by `idlwave-reserved-word-upcase'."
3734 (if idlwave-reserved-word-upcase 3734 (if idlwave-reserved-word-upcase
3735 (upcase string) 3735 (upcase string)
3736 string)) 3736 string))
3744 "Condition expression")) 3744 "Condition expression"))
3745 3745
3746 (defun idlwave-case () 3746 (defun idlwave-case ()
3747 "Build skeleton IDL case statement." 3747 "Build skeleton IDL case statement."
3748 (interactive) 3748 (interactive)
3749 (idlwave-template 3749 (idlwave-template
3750 (idlwave-rw-case "case") 3750 (idlwave-rw-case "case")
3751 (idlwave-rw-case " of\n\nendcase") 3751 (idlwave-rw-case " of\n\nendcase")
3752 "Selector expression")) 3752 "Selector expression"))
3753 3753
3754 (defun idlwave-switch () 3754 (defun idlwave-switch ()
3755 "Build skeleton IDL switch statement." 3755 "Build skeleton IDL switch statement."
3756 (interactive) 3756 (interactive)
3757 (idlwave-template 3757 (idlwave-template
3758 (idlwave-rw-case "switch") 3758 (idlwave-rw-case "switch")
3759 (idlwave-rw-case " of\n\nendswitch") 3759 (idlwave-rw-case " of\n\nendswitch")
3760 "Selector expression")) 3760 "Selector expression"))
3761 3761
3762 (defun idlwave-for () 3762 (defun idlwave-for ()
3763 "Build skeleton for loop statment." 3763 "Build skeleton for loop statment."
3764 (interactive) 3764 (interactive)
3765 (idlwave-template 3765 (idlwave-template
3766 (idlwave-rw-case "for") 3766 (idlwave-rw-case "for")
3767 (idlwave-rw-case " do begin\n\nendfor") 3767 (idlwave-rw-case " do begin\n\nendfor")
3768 "Loop expression")) 3768 "Loop expression"))
3769 3769
3770 (defun idlwave-if () 3770 (defun idlwave-if ()
3775 (idlwave-rw-case " then begin\n\nendif") 3775 (idlwave-rw-case " then begin\n\nendif")
3776 "Scalar logical expression")) 3776 "Scalar logical expression"))
3777 3777
3778 (defun idlwave-procedure () 3778 (defun idlwave-procedure ()
3779 (interactive) 3779 (interactive)
3780 (idlwave-template 3780 (idlwave-template
3781 (idlwave-rw-case "pro") 3781 (idlwave-rw-case "pro")
3782 (idlwave-rw-case "\n\nreturn\nend") 3782 (idlwave-rw-case "\n\nreturn\nend")
3783 "Procedure name")) 3783 "Procedure name"))
3784 3784
3785 (defun idlwave-function () 3785 (defun idlwave-function ()
3786 (interactive) 3786 (interactive)
3787 (idlwave-template 3787 (idlwave-template
3788 (idlwave-rw-case "function") 3788 (idlwave-rw-case "function")
3789 (idlwave-rw-case "\n\nreturn\nend") 3789 (idlwave-rw-case "\n\nreturn\nend")
3790 "Function name")) 3790 "Function name"))
3791 3791
3792 (defun idlwave-repeat () 3792 (defun idlwave-repeat ()
3796 (idlwave-rw-case "") 3796 (idlwave-rw-case "")
3797 "Exit condition")) 3797 "Exit condition"))
3798 3798
3799 (defun idlwave-while () 3799 (defun idlwave-while ()
3800 (interactive) 3800 (interactive)
3801 (idlwave-template 3801 (idlwave-template
3802 (idlwave-rw-case "while") 3802 (idlwave-rw-case "while")
3803 (idlwave-rw-case " do begin\n\nendwhile") 3803 (idlwave-rw-case " do begin\n\nendwhile")
3804 "Entry condition")) 3804 "Entry condition"))
3805 3805
3806 (defun idlwave-split-string (string &optional pattern) 3806 (defun idlwave-split-string (string &optional pattern)
3875 (t (error "Abort")))))) 3875 (t (error "Abort"))))))
3876 3876
3877 (defun idlwave-count-outlawed-buffers (tag) 3877 (defun idlwave-count-outlawed-buffers (tag)
3878 "How many outlawed buffers have tag TAG?" 3878 "How many outlawed buffers have tag TAG?"
3879 (length (delq nil 3879 (length (delq nil
3880 (mapcar 3880 (mapcar
3881 (lambda (x) (eq (cdr x) tag)) 3881 (lambda (x) (eq (cdr x) tag))
3882 idlwave-outlawed-buffers)))) 3882 idlwave-outlawed-buffers))))
3883 3883
3884 (defun idlwave-do-kill-autoloaded-buffers (&rest reasons) 3884 (defun idlwave-do-kill-autoloaded-buffers (&rest reasons)
3885 "Kill all buffers pulled up by IDLWAVE matching REASONS." 3885 "Kill all buffers pulled up by IDLWAVE matching REASONS."
3886 (let* ((list (copy-sequence idlwave-outlawed-buffers)) 3886 (let* ((list (copy-sequence idlwave-outlawed-buffers))
3890 (if (buffer-live-p (car entry)) 3890 (if (buffer-live-p (car entry))
3891 (and (or (memq t reasons) 3891 (and (or (memq t reasons)
3892 (memq (cdr entry) reasons)) 3892 (memq (cdr entry) reasons))
3893 (kill-buffer (car entry)) 3893 (kill-buffer (car entry))
3894 (incf cnt) 3894 (incf cnt)
3895 (setq idlwave-outlawed-buffers 3895 (setq idlwave-outlawed-buffers
3896 (delq entry idlwave-outlawed-buffers))) 3896 (delq entry idlwave-outlawed-buffers)))
3897 (setq idlwave-outlawed-buffers 3897 (setq idlwave-outlawed-buffers
3898 (delq entry idlwave-outlawed-buffers)))) 3898 (delq entry idlwave-outlawed-buffers))))
3899 (message "%d buffer%s killed" cnt (if (= cnt 1) "" "s")))) 3899 (message "%d buffer%s killed" cnt (if (= cnt 1) "" "s"))))
3900 3900
3901 (defun idlwave-revoke-license-to-kill () 3901 (defun idlwave-revoke-license-to-kill ()
3902 "Remove BUFFER from the buffers which may be killed. 3902 "Remove BUFFER from the buffers which may be killed.
3904 Intended for `after-save-hook'." 3904 Intended for `after-save-hook'."
3905 (let* ((buf (current-buffer)) 3905 (let* ((buf (current-buffer))
3906 (entry (assq buf idlwave-outlawed-buffers))) 3906 (entry (assq buf idlwave-outlawed-buffers)))
3907 ;; Revoke license 3907 ;; Revoke license
3908 (if entry 3908 (if entry
3909 (setq idlwave-outlawed-buffers 3909 (setq idlwave-outlawed-buffers
3910 (delq entry idlwave-outlawed-buffers))) 3910 (delq entry idlwave-outlawed-buffers)))
3911 ;; Remove this function from the hook. 3911 ;; Remove this function from the hook.
3912 (remove-hook 'after-save-hook 'idlwave-revoke-license-to-kill 'local))) 3912 (remove-hook 'after-save-hook 'idlwave-revoke-license-to-kill 'local)))
3913 3913
3914 (defvar idlwave-path-alist) 3914 (defvar idlwave-path-alist)
3923 (throw 'exit efile)))))) 3923 (throw 'exit efile))))))
3924 3924
3925 (defun idlwave-expand-lib-file-name (file) 3925 (defun idlwave-expand-lib-file-name (file)
3926 ;; Find FILE on the scanned lib path and return a buffer visiting it 3926 ;; Find FILE on the scanned lib path and return a buffer visiting it
3927 ;; This is for, e.g., finding source with no user catalog 3927 ;; This is for, e.g., finding source with no user catalog
3928 (cond 3928 (cond
3929 ((null file) nil) 3929 ((null file) nil)
3930 ((file-name-absolute-p file) file) 3930 ((file-name-absolute-p file) file)
3931 (t (idlwave-locate-lib-file file)))) 3931 (t (idlwave-locate-lib-file file))))
3932 3932
3933 (defun idlwave-make-tags () 3933 (defun idlwave-make-tags ()
3938 by @. Specify @ directories with care, it may take a long, long time if 3938 by @. Specify @ directories with care, it may take a long, long time if
3939 you specify /." 3939 you specify /."
3940 (interactive) 3940 (interactive)
3941 (let (directory directories cmd append status numdirs dir getsubdirs 3941 (let (directory directories cmd append status numdirs dir getsubdirs
3942 buffer save_buffer files numfiles item errbuf) 3942 buffer save_buffer files numfiles item errbuf)
3943 3943
3944 ;; 3944 ;;
3945 ;; Read list of directories 3945 ;; Read list of directories
3946 (setq directory (read-string "Tag Directories: " ".")) 3946 (setq directory (read-string "Tag Directories: " "."))
3947 (setq directories (idlwave-split-string directory "[ \t]+")) 3947 (setq directories (idlwave-split-string directory "[ \t]+"))
3948 ;; 3948 ;;
3990 (if (not (string-match "^[ \\t]*$" item)) 3990 (if (not (string-match "^[ \\t]*$" item))
3991 (progn 3991 (progn
3992 (message (concat "Tagging " item "...")) 3992 (message (concat "Tagging " item "..."))
3993 (setq errbuf (get-buffer-create "*idltags-error*")) 3993 (setq errbuf (get-buffer-create "*idltags-error*"))
3994 (setq status (+ status 3994 (setq status (+ status
3995 (if (eq 0 (call-process 3995 (if (eq 0 (call-process
3996 "sh" nil errbuf nil "-c" 3996 "sh" nil errbuf nil "-c"
3997 (concat cmd append item))) 3997 (concat cmd append item)))
3998 0 3998 0
3999 1))) 3999 1)))
4000 ;; 4000 ;;
4004 (setq item (nth numfiles files))) 4004 (setq item (nth numfiles files)))
4005 (progn 4005 (progn
4006 (setq numfiles (1+ numfiles)) 4006 (setq numfiles (1+ numfiles))
4007 (setq item (nth numfiles files)) 4007 (setq item (nth numfiles files))
4008 ))) 4008 )))
4009 4009
4010 (setq numdirs (1+ numdirs)) 4010 (setq numdirs (1+ numdirs))
4011 (setq dir (nth numdirs directories))) 4011 (setq dir (nth numdirs directories)))
4012 (progn 4012 (progn
4013 (setq numdirs (1+ numdirs)) 4013 (setq numdirs (1+ numdirs))
4014 (setq dir (nth numdirs directories))))) 4014 (setq dir (nth numdirs directories)))))
4015 4015
4016 (setq errbuf (get-buffer-create "*idltags-error*")) 4016 (setq errbuf (get-buffer-create "*idltags-error*"))
4017 (if (= status 0) 4017 (if (= status 0)
4018 (kill-buffer errbuf)) 4018 (kill-buffer errbuf))
4019 (message "") 4019 (message "")
4020 )) 4020 ))
4086 (defun idlwave-reset-sintern (&optional what) 4086 (defun idlwave-reset-sintern (&optional what)
4087 "Reset all sintern hashes." 4087 "Reset all sintern hashes."
4088 ;; Make sure the hash functions are accessible. 4088 ;; Make sure the hash functions are accessible.
4089 (if (or (not (fboundp 'gethash)) 4089 (if (or (not (fboundp 'gethash))
4090 (not (fboundp 'puthash))) 4090 (not (fboundp 'puthash)))
4091 (progn 4091 (progn
4092 (require 'cl) 4092 (require 'cl)
4093 (or (fboundp 'puthash) 4093 (or (fboundp 'puthash)
4094 (defalias 'puthash 'cl-puthash)))) 4094 (defalias 'puthash 'cl-puthash))))
4095 (let ((entries '((idlwave-sint-routines 1000 10) 4095 (let ((entries '((idlwave-sint-routines 1000 10)
4096 (idlwave-sint-keywords 1000 10) 4096 (idlwave-sint-keywords 1000 10)
4105 (when (or (eq what t) (eq what 'syslib) 4105 (when (or (eq what t) (eq what 'syslib)
4106 (null (cdr idlwave-sint-routines))) 4106 (null (cdr idlwave-sint-routines)))
4107 ;; Reset the system & library hash 4107 ;; Reset the system & library hash
4108 (loop for entry in entries 4108 (loop for entry in entries
4109 for var = (car entry) for size = (nth 1 entry) 4109 for var = (car entry) for size = (nth 1 entry)
4110 do (setcdr (symbol-value var) 4110 do (setcdr (symbol-value var)
4111 (make-hash-table ':size size ':test 'equal))) 4111 (make-hash-table ':size size ':test 'equal)))
4112 (setq idlwave-sint-dirs nil 4112 (setq idlwave-sint-dirs nil
4113 idlwave-sint-libnames nil)) 4113 idlwave-sint-libnames nil))
4114 4114
4115 (when (or (eq what t) (eq what 'bufsh) 4115 (when (or (eq what t) (eq what 'bufsh)
4116 (null (car idlwave-sint-routines))) 4116 (null (car idlwave-sint-routines)))
4117 ;; Reset the buffer & shell hash 4117 ;; Reset the buffer & shell hash
4118 (loop for entry in entries 4118 (loop for entry in entries
4119 for var = (car entry) for size = (nth 1 entry) 4119 for var = (car entry) for size = (nth 1 entry)
4120 do (setcar (symbol-value var) 4120 do (setcar (symbol-value var)
4121 (make-hash-table ':size size ':test 'equal)))))) 4121 (make-hash-table ':size size ':test 'equal))))))
4122 4122
4123 (defun idlwave-sintern-routine-or-method (name &optional class set) 4123 (defun idlwave-sintern-routine-or-method (name &optional class set)
4124 (if class 4124 (if class
4125 (idlwave-sintern-method name set) 4125 (idlwave-sintern-method name set)
4202 (progn 4202 (progn
4203 (if (symbolp class) (setq class (symbol-name class))) 4203 (if (symbolp class) (setq class (symbol-name class)))
4204 (setq class (idlwave-sintern-class class set)) 4204 (setq class (idlwave-sintern-class class set))
4205 (setq name (idlwave-sintern-method name set))) 4205 (setq name (idlwave-sintern-method name set)))
4206 (setq name (idlwave-sintern-routine name set))) 4206 (setq name (idlwave-sintern-routine name set)))
4207 4207
4208 ;; The source 4208 ;; The source
4209 (let ((source-type (car source)) 4209 (let ((source-type (car source))
4210 (source-file (nth 1 source)) 4210 (source-file (nth 1 source))
4211 (source-dir (if default-dir 4211 (source-dir (if default-dir
4212 (file-name-as-directory default-dir) 4212 (file-name-as-directory default-dir)
4213 (nth 2 source))) 4213 (nth 2 source)))
4214 (source-lib (nth 3 source))) 4214 (source-lib (nth 3 source)))
4215 (if (stringp source-dir) 4215 (if (stringp source-dir)
4216 (setq source-dir (idlwave-sintern-dir source-dir set))) 4216 (setq source-dir (idlwave-sintern-dir source-dir set)))
4217 (if (stringp source-lib) 4217 (if (stringp source-lib)
4218 (setq source-lib (idlwave-sintern-libname source-lib set))) 4218 (setq source-lib (idlwave-sintern-libname source-lib set)))
4219 (setq source (list source-type source-file source-dir source-lib))) 4219 (setq source (list source-type source-file source-dir source-lib)))
4220 4220
4221 ;; The keywords 4221 ;; The keywords
4222 (setq kwds (mapcar (lambda (x) 4222 (setq kwds (mapcar (lambda (x)
4223 (idlwave-sintern-keyword-list x set)) 4223 (idlwave-sintern-keyword-list x set))
4224 kwds)) 4224 kwds))
4225 4225
4353 (let* ((emacs (expand-file-name (invocation-name) (invocation-directory))) 4353 (let* ((emacs (expand-file-name (invocation-name) (invocation-directory)))
4354 (args (list "-batch" 4354 (args (list "-batch"
4355 "-l" (expand-file-name "~/.emacs") 4355 "-l" (expand-file-name "~/.emacs")
4356 "-l" "idlwave" 4356 "-l" "idlwave"
4357 "-f" "idlwave-rescan-catalog-directories")) 4357 "-f" "idlwave-rescan-catalog-directories"))
4358 (process (apply 'start-process "idlcat" 4358 (process (apply 'start-process "idlcat"
4359 nil emacs args))) 4359 nil emacs args)))
4360 (setq idlwave-catalog-process process) 4360 (setq idlwave-catalog-process process)
4361 (set-process-sentinel 4361 (set-process-sentinel
4362 process 4362 process
4363 (lambda (pro why) 4363 (lambda (pro why)
4364 (when (string-match "finished" why) 4364 (when (string-match "finished" why)
4365 (setq idlwave-routines nil 4365 (setq idlwave-routines nil
4366 idlwave-system-routines nil 4366 idlwave-system-routines nil
4429 idlwave-buffer-case-takes-precedence 4429 idlwave-buffer-case-takes-precedence
4430 (null idlwave-routines))) 4430 (null idlwave-routines)))
4431 ;; The override-idle means, even if the idle timer has done some 4431 ;; The override-idle means, even if the idle timer has done some
4432 ;; preparing work, load and renormalize everything anyway. 4432 ;; preparing work, load and renormalize everything anyway.
4433 (override-idle (or arg idlwave-buffer-case-takes-precedence))) 4433 (override-idle (or arg idlwave-buffer-case-takes-precedence)))
4434 4434
4435 (setq idlwave-buffer-routines nil 4435 (setq idlwave-buffer-routines nil
4436 idlwave-compiled-routines nil 4436 idlwave-compiled-routines nil
4437 idlwave-unresolved-routines nil) 4437 idlwave-unresolved-routines nil)
4438 ;; Reset the appropriate hashes 4438 ;; Reset the appropriate hashes
4439 (if (get 'idlwave-reset-sintern 'done-by-idle) 4439 (if (get 'idlwave-reset-sintern 'done-by-idle)
4440 ;; reset was already done in idle time, so skip this step now once 4440 ;; reset was already done in idle time, so skip this step now once
4441 (put 'idlwave-reset-sintern 'done-by-idle nil) 4441 (put 'idlwave-reset-sintern 'done-by-idle nil)
4442 (idlwave-reset-sintern (cond (load t) 4442 (idlwave-reset-sintern (cond (load t)
4443 ((null idlwave-system-routines) t) 4443 ((null idlwave-system-routines) t)
4444 (t 'bufsh)))) 4444 (t 'bufsh))))
4445 4445
4446 (if idlwave-buffer-case-takes-precedence 4446 (if idlwave-buffer-case-takes-precedence
4447 ;; We can safely scan the buffer stuff first 4447 ;; We can safely scan the buffer stuff first
4448 (progn 4448 (progn
4449 (idlwave-update-buffer-routine-info) 4449 (idlwave-update-buffer-routine-info)
4450 (and load (idlwave-load-system-rinfo override-idle))) 4450 (and load (idlwave-load-system-rinfo override-idle)))
4455 ;; Let's see if there is a shell 4455 ;; Let's see if there is a shell
4456 (let* ((shell-is-running (and (fboundp 'idlwave-shell-is-running) 4456 (let* ((shell-is-running (and (fboundp 'idlwave-shell-is-running)
4457 (idlwave-shell-is-running))) 4457 (idlwave-shell-is-running)))
4458 (ask-shell (and shell-is-running 4458 (ask-shell (and shell-is-running
4459 idlwave-query-shell-for-routine-info))) 4459 idlwave-query-shell-for-routine-info)))
4460 4460
4461 ;; Load the library catalogs again, first re-scanning the path 4461 ;; Load the library catalogs again, first re-scanning the path
4462 (when arg 4462 (when arg
4463 (if shell-is-running 4463 (if shell-is-running
4464 (idlwave-shell-send-command idlwave-shell-path-query 4464 (idlwave-shell-send-command idlwave-shell-path-query
4465 '(progn 4465 '(progn
4466 (idlwave-shell-get-path-info) 4466 (idlwave-shell-get-path-info)
4467 (idlwave-scan-library-catalogs)) 4467 (idlwave-scan-library-catalogs))
4477 ;; shell update causes the concatenation to be 4477 ;; shell update causes the concatenation to be
4478 ;; *delayed*, so not in time for the current command. 4478 ;; *delayed*, so not in time for the current command.
4479 ;; Therefore, we do a concatenation now, even though 4479 ;; Therefore, we do a concatenation now, even though
4480 ;; the shell might do it again. 4480 ;; the shell might do it again.
4481 (idlwave-concatenate-rinfo-lists nil 'run-hooks)) 4481 (idlwave-concatenate-rinfo-lists nil 'run-hooks))
4482 4482
4483 (when ask-shell 4483 (when ask-shell
4484 ;; Ask the shell about the routines it knows of. 4484 ;; Ask the shell about the routines it knows of.
4485 (message "Querying the shell") 4485 (message "Querying the shell")
4486 (idlwave-shell-update-routine-info nil t))))))) 4486 (idlwave-shell-update-routine-info nil t)))))))
4487 4487
4539 (boundp 'idlwave-library-routines) 4539 (boundp 'idlwave-library-routines)
4540 idlwave-library-routines) 4540 idlwave-library-routines)
4541 (progn 4541 (progn
4542 (setq idlwave-library-routines nil) 4542 (setq idlwave-library-routines nil)
4543 (ding) 4543 (ding)
4544 (message "Outdated user catalog: %s... recreate" 4544 (message "Outdated user catalog: %s... recreate"
4545 idlwave-user-catalog-file)) 4545 idlwave-user-catalog-file))
4546 (message "Loading user catalog in idle time...done")) 4546 (message "Loading user catalog in idle time...done"))
4547 (aset arr 2 t) 4547 (aset arr 2 t)
4548 (throw 'exit t))) 4548 (throw 'exit t)))
4549 (when (not (aref arr 3)) 4549 (when (not (aref arr 3))
4550 (when idlwave-user-catalog-routines 4550 (when idlwave-user-catalog-routines
4551 (message "Normalizing user catalog routines in idle time...") 4551 (message "Normalizing user catalog routines in idle time...")
4552 (setq idlwave-user-catalog-routines 4552 (setq idlwave-user-catalog-routines
4553 (idlwave-sintern-rinfo-list 4553 (idlwave-sintern-rinfo-list
4554 idlwave-user-catalog-routines 'sys)) 4554 idlwave-user-catalog-routines 'sys))
4555 (message 4555 (message
4556 "Normalizing user catalog routines in idle time...done")) 4556 "Normalizing user catalog routines in idle time...done"))
4557 (aset arr 3 t) 4557 (aset arr 3 t)
4558 (throw 'exit t)) 4558 (throw 'exit t))
4559 (when (not (aref arr 4)) 4559 (when (not (aref arr 4))
4560 (idlwave-scan-library-catalogs 4560 (idlwave-scan-library-catalogs
4561 "Loading and normalizing library catalogs in idle time...") 4561 "Loading and normalizing library catalogs in idle time...")
4562 (aset arr 4 t) 4562 (aset arr 4 t)
4563 (throw 'exit t)) 4563 (throw 'exit t))
4564 (when (not (aref arr 5)) 4564 (when (not (aref arr 5))
4565 (message "Finishing initialization in idle time...") 4565 (message "Finishing initialization in idle time...")
4596 (setq idlwave-library-routines nil) 4596 (setq idlwave-library-routines nil)
4597 (error "Outdated user catalog: %s... recreate" idlwave-user-catalog-file)) 4597 (error "Outdated user catalog: %s... recreate" idlwave-user-catalog-file))
4598 (setq idlwave-true-path-alist nil) 4598 (setq idlwave-true-path-alist nil)
4599 (when (or force (not (aref idlwave-load-rinfo-steps-done 3))) 4599 (when (or force (not (aref idlwave-load-rinfo-steps-done 3)))
4600 (message "Normalizing user catalog routines...") 4600 (message "Normalizing user catalog routines...")
4601 (setq idlwave-user-catalog-routines 4601 (setq idlwave-user-catalog-routines
4602 (idlwave-sintern-rinfo-list 4602 (idlwave-sintern-rinfo-list
4603 idlwave-user-catalog-routines 'sys)) 4603 idlwave-user-catalog-routines 'sys))
4604 (message "Normalizing user catalog routines...done"))) 4604 (message "Normalizing user catalog routines...done")))
4605 (when (or force (not (aref idlwave-load-rinfo-steps-done 4))) 4605 (when (or force (not (aref idlwave-load-rinfo-steps-done 4)))
4606 (idlwave-scan-library-catalogs 4606 (idlwave-scan-library-catalogs
4607 "Loading and normalizing library catalogs...")) 4607 "Loading and normalizing library catalogs..."))
4608 (run-hooks 'idlwave-after-load-rinfo-hook)) 4608 (run-hooks 'idlwave-after-load-rinfo-hook))
4609 4609
4610 4610
4611 (defun idlwave-update-buffer-routine-info () 4611 (defun idlwave-update-buffer-routine-info ()
4612 (let (res) 4612 (let (res)
4613 (cond 4613 (cond
4614 ((eq idlwave-scan-all-buffers-for-routine-info t) 4614 ((eq idlwave-scan-all-buffers-for-routine-info t)
4615 ;; Scan all buffers, current buffer last 4615 ;; Scan all buffers, current buffer last
4616 (message "Scanning all buffers...") 4616 (message "Scanning all buffers...")
4617 (setq res (idlwave-get-routine-info-from-buffers 4617 (setq res (idlwave-get-routine-info-from-buffers
4618 (reverse (buffer-list))))) 4618 (reverse (buffer-list)))))
4619 ((null idlwave-scan-all-buffers-for-routine-info) 4619 ((null idlwave-scan-all-buffers-for-routine-info)
4620 ;; Don't scan any buffers 4620 ;; Don't scan any buffers
4621 (setq res nil)) 4621 (setq res nil))
4622 (t 4622 (t
4625 (progn 4625 (progn
4626 (message "Scanning current buffer...") 4626 (message "Scanning current buffer...")
4627 (setq res (idlwave-get-routine-info-from-buffers 4627 (setq res (idlwave-get-routine-info-from-buffers
4628 (list (current-buffer)))))))) 4628 (list (current-buffer))))))))
4629 ;; Put the result into the correct variable 4629 ;; Put the result into the correct variable
4630 (setq idlwave-buffer-routines 4630 (setq idlwave-buffer-routines
4631 (idlwave-sintern-rinfo-list res 'set)))) 4631 (idlwave-sintern-rinfo-list res 'set))))
4632 4632
4633 (defun idlwave-concatenate-rinfo-lists (&optional quiet run-hook) 4633 (defun idlwave-concatenate-rinfo-lists (&optional quiet run-hook)
4634 "Put the different sources for routine information together." 4634 "Put the different sources for routine information together."
4635 ;; The sequence here is important because earlier definitions shadow 4635 ;; The sequence here is important because earlier definitions shadow
4636 ;; later ones. We assume that if things in the buffers are newer 4636 ;; later ones. We assume that if things in the buffers are newer
4637 ;; then in the shell of the system, they are meant to be different. 4637 ;; then in the shell of the system, they are meant to be different.
4638 (setcdr idlwave-last-system-routine-info-cons-cell 4638 (setcdr idlwave-last-system-routine-info-cons-cell
4639 (append idlwave-buffer-routines 4639 (append idlwave-buffer-routines
4640 idlwave-compiled-routines 4640 idlwave-compiled-routines
4642 idlwave-user-catalog-routines)) 4642 idlwave-user-catalog-routines))
4643 (setq idlwave-class-alist nil) 4643 (setq idlwave-class-alist nil)
4644 4644
4645 ;; Give a message with information about the number of routines we have. 4645 ;; Give a message with information about the number of routines we have.
4646 (unless quiet 4646 (unless quiet
4647 (message 4647 (message
4648 "Routines Found: buffer(%d) compiled(%d) library(%d) user(%d) system(%d)" 4648 "Routines Found: buffer(%d) compiled(%d) library(%d) user(%d) system(%d)"
4649 (length idlwave-buffer-routines) 4649 (length idlwave-buffer-routines)
4650 (length idlwave-compiled-routines) 4650 (length idlwave-compiled-routines)
4651 (length idlwave-library-catalog-routines) 4651 (length idlwave-library-catalog-routines)
4652 (length idlwave-user-catalog-routines) 4652 (length idlwave-user-catalog-routines)
4660 (let (class) 4660 (let (class)
4661 (loop for x in idlwave-routines do 4661 (loop for x in idlwave-routines do
4662 (when (and (setq class (nth 2 x)) 4662 (when (and (setq class (nth 2 x))
4663 (not (assq class idlwave-class-alist))) 4663 (not (assq class idlwave-class-alist)))
4664 (push (list class) idlwave-class-alist))) 4664 (push (list class) idlwave-class-alist)))
4665 idlwave-class-alist))) 4665 idlwave-class-alist)))
4666 4666
4667 ;; Three functions for the hooks 4667 ;; Three functions for the hooks
4668 (defun idlwave-save-buffer-update () 4668 (defun idlwave-save-buffer-update ()
4669 (idlwave-update-current-buffer-info 'save-buffer)) 4669 (idlwave-update-current-buffer-info 'save-buffer))
4670 (defun idlwave-kill-buffer-update () 4670 (defun idlwave-kill-buffer-update ()
4693 routines) 4693 routines)
4694 (error nil)))) 4694 (error nil))))
4695 4695
4696 (defun idlwave-replace-buffer-routine-info (file new) 4696 (defun idlwave-replace-buffer-routine-info (file new)
4697 "Cut the part from FILE out of `idlwave-buffer-routines' and add NEW." 4697 "Cut the part from FILE out of `idlwave-buffer-routines' and add NEW."
4698 (let ((list idlwave-buffer-routines) 4698 (let ((list idlwave-buffer-routines)
4699 found) 4699 found)
4700 (while list 4700 (while list
4701 ;; The following test uses eq to make sure it works correctly 4701 ;; The following test uses eq to make sure it works correctly
4702 ;; when two buffers visit the same file. Then the file names 4702 ;; when two buffers visit the same file. Then the file names
4703 ;; will be equal, but not eq. 4703 ;; will be equal, but not eq.
4704 (if (eq (idlwave-routine-source-file (nth 3 (car list))) file) 4704 (if (eq (idlwave-routine-source-file (nth 3 (car list))) file)
4705 (progn 4705 (progn
4706 (setcar list nil) 4706 (setcar list nil)
4707 (setq found t)) 4707 (setq found t))
4708 (if found 4708 (if found
4709 ;; End of that section reached. Jump. 4709 ;; End of that section reached. Jump.
4710 (setq list nil))) 4710 (setq list nil)))
4711 (setq list (cdr list))) 4711 (setq list (cdr list)))
4712 (setq idlwave-buffer-routines 4712 (setq idlwave-buffer-routines
4713 (append new (delq nil idlwave-buffer-routines))))) 4713 (append new (delq nil idlwave-buffer-routines)))))
4714 4714
4736 routine-list string entry) 4736 routine-list string entry)
4737 (save-excursion 4737 (save-excursion
4738 (save-restriction 4738 (save-restriction
4739 (widen) 4739 (widen)
4740 (goto-char (point-min)) 4740 (goto-char (point-min))
4741 (while (re-search-forward 4741 (while (re-search-forward
4742 "^[ \t]*\\(pro\\|function\\)[ \t]" nil t) 4742 "^[ \t]*\\(pro\\|function\\)[ \t]" nil t)
4743 (setq string (buffer-substring-no-properties 4743 (setq string (buffer-substring-no-properties
4744 (match-beginning 0) 4744 (match-beginning 0)
4745 (progn 4745 (progn
4746 (idlwave-end-of-statement) 4746 (idlwave-end-of-statement)
4747 (point)))) 4747 (point))))
4748 (setq entry (idlwave-parse-definition string)) 4748 (setq entry (idlwave-parse-definition string))
4749 (push entry routine-list)))) 4749 (push entry routine-list))))
4750 routine-list)) 4750 routine-list))
4778 (if (match-beginning 3) 4778 (if (match-beginning 3)
4779 (push (match-string 1 string) keywords) 4779 (push (match-string 1 string) keywords)
4780 (push (match-string 1 string) args))) 4780 (push (match-string 1 string) args)))
4781 ;; Normalize and sort. 4781 ;; Normalize and sort.
4782 (setq args (nreverse args)) 4782 (setq args (nreverse args))
4783 (setq keywords (sort keywords (lambda (a b) 4783 (setq keywords (sort keywords (lambda (a b)
4784 (string< (downcase a) (downcase b))))) 4784 (string< (downcase a) (downcase b)))))
4785 ;; Make and return the entry 4785 ;; Make and return the entry
4786 ;; We don't know which argument are optional, so this information 4786 ;; We don't know which argument are optional, so this information
4787 ;; will not be contained in the calling sequence. 4787 ;; will not be contained in the calling sequence.
4788 (list name 4788 (list name
4789 (if (equal type "pro") 'pro 'fun) 4789 (if (equal type "pro") 'pro 'fun)
4790 class 4790 class
4791 (cond ((not (boundp 'idlwave-scanning-lib)) 4791 (cond ((not (boundp 'idlwave-scanning-lib))
4792 (list 'buffer (buffer-file-name))) 4792 (list 'buffer (buffer-file-name)))
4793 ; ((string= (downcase 4793 ; ((string= (downcase
4794 ; (file-name-sans-extension 4794 ; (file-name-sans-extension
4795 ; (file-name-nondirectory (buffer-file-name)))) 4795 ; (file-name-nondirectory (buffer-file-name))))
4796 ; (downcase name)) 4796 ; (downcase name))
4797 ; (list 'lib)) 4797 ; (list 'lib))
4798 ; (t (cons 'lib (file-name-nondirectory (buffer-file-name)))) 4798 ; (t (cons 'lib (file-name-nondirectory (buffer-file-name))))
4799 (t (list 'user (file-name-nondirectory (buffer-file-name)) 4799 (t (list 'user (file-name-nondirectory (buffer-file-name))
4800 idlwave-scanning-lib-dir "UserLib"))) 4800 idlwave-scanning-lib-dir "UserLib")))
4801 (concat 4801 (concat
4802 (if (string= type "function") "Result = " "") 4802 (if (string= type "function") "Result = " "")
4803 (if class "Obj ->[%s::]" "") 4803 (if class "Obj ->[%s::]" "")
4804 "%s" 4804 "%s"
4805 (if args 4805 (if args
4806 (concat 4806 (concat
4840 ;; Make sure the file name makes sense 4840 ;; Make sure the file name makes sense
4841 (unless (and (stringp idlwave-user-catalog-file) 4841 (unless (and (stringp idlwave-user-catalog-file)
4842 (> (length idlwave-user-catalog-file) 0) 4842 (> (length idlwave-user-catalog-file) 0)
4843 (file-accessible-directory-p 4843 (file-accessible-directory-p
4844 (file-name-directory idlwave-user-catalog-file)) 4844 (file-name-directory idlwave-user-catalog-file))
4845 (not (string= "" (file-name-nondirectory 4845 (not (string= "" (file-name-nondirectory
4846 idlwave-user-catalog-file)))) 4846 idlwave-user-catalog-file))))
4847 (error "`idlwave-user-catalog-file' does not point to a file in an accessible directory")) 4847 (error "`idlwave-user-catalog-file' does not point to a file in an accessible directory"))
4848 4848
4849 (cond 4849 (cond
4850 ;; Rescan the known directories 4850 ;; Rescan the known directories
4851 ((and arg idlwave-path-alist 4851 ((and arg idlwave-path-alist
4852 (consp (car idlwave-path-alist))) 4852 (consp (car idlwave-path-alist)))
4853 (idlwave-scan-user-lib-files idlwave-path-alist)) 4853 (idlwave-scan-user-lib-files idlwave-path-alist))
4854 4854
4855 ;; Expand the directories from library-path and run the widget 4855 ;; Expand the directories from library-path and run the widget
4856 (idlwave-library-path 4856 (idlwave-library-path
4857 (idlwave-display-user-catalog-widget 4857 (idlwave-display-user-catalog-widget
4858 (if idlwave-true-path-alist 4858 (if idlwave-true-path-alist
4859 ;; Propagate any flags on the existing path-alist 4859 ;; Propagate any flags on the existing path-alist
4860 (mapcar (lambda (x) 4860 (mapcar (lambda (x)
4861 (let ((path-entry (assoc (file-truename x) 4861 (let ((path-entry (assoc (file-truename x)
4862 idlwave-true-path-alist))) 4862 idlwave-true-path-alist)))
4863 (if path-entry 4863 (if path-entry
4864 (cons x (cdr path-entry)) 4864 (cons x (cdr path-entry))
4865 (list x)))) 4865 (list x))))
4866 (idlwave-expand-path idlwave-library-path)) 4866 (idlwave-expand-path idlwave-library-path))
4867 (mapcar 'list (idlwave-expand-path idlwave-library-path))))) 4867 (mapcar 'list (idlwave-expand-path idlwave-library-path)))))
4868 4868
4869 ;; Ask the shell for the path and then run the widget 4869 ;; Ask the shell for the path and then run the widget
4884 ;; Set the path and display the widget 4884 ;; Set the path and display the widget
4885 (idlwave-shell-get-path-info 'no-write) ; set to something path-alist 4885 (idlwave-shell-get-path-info 'no-write) ; set to something path-alist
4886 (idlwave-scan-library-catalogs "Locating library catalogs..." 'no-load) 4886 (idlwave-scan-library-catalogs "Locating library catalogs..." 'no-load)
4887 (idlwave-display-user-catalog-widget idlwave-path-alist))) 4887 (idlwave-display-user-catalog-widget idlwave-path-alist)))
4888 4888
4889 (defconst idlwave-user-catalog-widget-help-string 4889 (defconst idlwave-user-catalog-widget-help-string
4890 "This is the front-end to the creation of the IDLWAVE user catalog. 4890 "This is the front-end to the creation of the IDLWAVE user catalog.
4891 Please select the directories on IDL's search path from which you 4891 Please select the directories on IDL's search path from which you
4892 would like to extract routine information, to be stored in the file: 4892 would like to extract routine information, to be stored in the file:
4893 4893
4894 %s 4894 %s
4919 (switch-to-buffer (get-buffer-create "*IDLWAVE Widget*")) 4919 (switch-to-buffer (get-buffer-create "*IDLWAVE Widget*"))
4920 (kill-all-local-variables) 4920 (kill-all-local-variables)
4921 (make-local-variable 'idlwave-widget) 4921 (make-local-variable 'idlwave-widget)
4922 (widget-insert (format idlwave-user-catalog-widget-help-string 4922 (widget-insert (format idlwave-user-catalog-widget-help-string
4923 idlwave-user-catalog-file)) 4923 idlwave-user-catalog-file))
4924 4924
4925 (widget-create 'push-button 4925 (widget-create 'push-button
4926 :notify 'idlwave-widget-scan-user-lib-files 4926 :notify 'idlwave-widget-scan-user-lib-files
4927 "Scan & Save") 4927 "Scan & Save")
4928 (widget-insert " ") 4928 (widget-insert " ")
4929 (widget-create 'push-button 4929 (widget-create 'push-button
4930 :notify 'idlwave-delete-user-catalog-file 4930 :notify 'idlwave-delete-user-catalog-file
4931 "Delete File") 4931 "Delete File")
4932 (widget-insert " ") 4932 (widget-insert " ")
4933 (widget-create 'push-button 4933 (widget-create 'push-button
4934 :notify 4934 :notify
4935 '(lambda (&rest ignore) 4935 '(lambda (&rest ignore)
4936 (let ((path-list (widget-get idlwave-widget :path-dirs))) 4936 (let ((path-list (widget-get idlwave-widget :path-dirs)))
4937 (mapcar (lambda (x) 4937 (mapcar (lambda (x)
4938 (unless (memq 'lib (cdr x)) 4938 (unless (memq 'lib (cdr x))
4939 (idlwave-path-alist-add-flag x 'user))) 4939 (idlwave-path-alist-add-flag x 'user)))
4940 path-list) 4940 path-list)
4941 (idlwave-display-user-catalog-widget path-list))) 4941 (idlwave-display-user-catalog-widget path-list)))
4942 "Select All Non-Lib") 4942 "Select All Non-Lib")
4943 (widget-insert " ") 4943 (widget-insert " ")
4944 (widget-create 'push-button 4944 (widget-create 'push-button
4945 :notify 4945 :notify
4946 '(lambda (&rest ignore) 4946 '(lambda (&rest ignore)
4947 (let ((path-list (widget-get idlwave-widget :path-dirs))) 4947 (let ((path-list (widget-get idlwave-widget :path-dirs)))
4948 (mapcar (lambda (x) 4948 (mapcar (lambda (x)
4949 (idlwave-path-alist-remove-flag x 'user)) 4949 (idlwave-path-alist-remove-flag x 'user))
4950 path-list) 4950 path-list)
4956 (kill-buffer (current-buffer))) 4956 (kill-buffer (current-buffer)))
4957 "Quit") 4957 "Quit")
4958 (widget-insert "\n\n") 4958 (widget-insert "\n\n")
4959 4959
4960 (widget-insert "Select Directories: \n") 4960 (widget-insert "Select Directories: \n")
4961 4961
4962 (setq idlwave-widget 4962 (setq idlwave-widget
4963 (apply 'widget-create 4963 (apply 'widget-create
4964 'checklist 4964 'checklist
4965 :value (delq nil (mapcar (lambda (x) 4965 :value (delq nil (mapcar (lambda (x)
4966 (if (memq 'user (cdr x)) 4966 (if (memq 'user (cdr x))
4967 (car x))) 4967 (car x)))
4968 dirs-list)) 4968 dirs-list))
4969 :greedy t 4969 :greedy t
4970 :tag "List of directories" 4970 :tag "List of directories"
4971 (mapcar (lambda (x) 4971 (mapcar (lambda (x)
4972 (list 'item 4972 (list 'item
4973 (if (memq 'lib (cdr x)) 4973 (if (memq 'lib (cdr x))
4974 (concat "[LIB] " (car x) ) 4974 (concat "[LIB] " (car x) )
4975 (car x)))) dirs-list))) 4975 (car x)))) dirs-list)))
4976 (widget-put idlwave-widget :path-dirs dirs-list) 4976 (widget-put idlwave-widget :path-dirs dirs-list)
4977 (widget-insert "\n") 4977 (widget-insert "\n")
4978 (use-local-map widget-keymap) 4978 (use-local-map widget-keymap)
4979 (widget-setup) 4979 (widget-setup)
4980 (goto-char (point-min)) 4980 (goto-char (point-min))
4981 (delete-other-windows)) 4981 (delete-other-windows))
4982 4982
4983 (defun idlwave-delete-user-catalog-file (&rest ignore) 4983 (defun idlwave-delete-user-catalog-file (&rest ignore)
4984 (if (yes-or-no-p 4984 (if (yes-or-no-p
4985 (format "Delete file %s " idlwave-user-catalog-file)) 4985 (format "Delete file %s " idlwave-user-catalog-file))
4986 (progn 4986 (progn
4987 (delete-file idlwave-user-catalog-file) 4987 (delete-file idlwave-user-catalog-file)
4993 (selected-dirs (widget-value widget)) 4993 (selected-dirs (widget-value widget))
4994 (path-alist (widget-get widget :path-dirs)) 4994 (path-alist (widget-get widget :path-dirs))
4995 (this-path-alist path-alist) 4995 (this-path-alist path-alist)
4996 dir-entry) 4996 dir-entry)
4997 (while (setq dir-entry (pop this-path-alist)) 4997 (while (setq dir-entry (pop this-path-alist))
4998 (if (member 4998 (if (member
4999 (if (memq 'lib (cdr dir-entry)) 4999 (if (memq 'lib (cdr dir-entry))
5000 (concat "[LIB] " (car dir-entry)) 5000 (concat "[LIB] " (car dir-entry))
5001 (car dir-entry)) 5001 (car dir-entry))
5002 selected-dirs) 5002 selected-dirs)
5003 (idlwave-path-alist-add-flag dir-entry 'user) 5003 (idlwave-path-alist-add-flag dir-entry 'user)
5090 (insert ";; IDLWAVE paths\n") 5090 (insert ";; IDLWAVE paths\n")
5091 (insert (format ";; Created %s\n\n" (current-time-string))) 5091 (insert (format ";; Created %s\n\n" (current-time-string)))
5092 ;; Define the variable which knows the value of "!DIR" 5092 ;; Define the variable which knows the value of "!DIR"
5093 (insert (format "\n(setq idlwave-system-directory \"%s\")\n" 5093 (insert (format "\n(setq idlwave-system-directory \"%s\")\n"
5094 idlwave-system-directory)) 5094 idlwave-system-directory))
5095 5095
5096 ;; Define the variable which contains a list of all scanned directories 5096 ;; Define the variable which contains a list of all scanned directories
5097 (insert "\n(setq idlwave-path-alist\n '(") 5097 (insert "\n(setq idlwave-path-alist\n '(")
5098 (let ((standard-output (current-buffer))) 5098 (let ((standard-output (current-buffer)))
5099 (mapcar (lambda (x) 5099 (mapcar (lambda (x)
5100 (insert "\n ") 5100 (insert "\n ")
5130 (let ((path (list dir)) path1 file files) 5130 (let ((path (list dir)) path1 file files)
5131 (while (setq dir (pop path)) 5131 (while (setq dir (pop path))
5132 (when (file-directory-p dir) 5132 (when (file-directory-p dir)
5133 (setq files (nreverse (directory-files dir t "[^.]"))) 5133 (setq files (nreverse (directory-files dir t "[^.]")))
5134 (while (setq file (pop files)) 5134 (while (setq file (pop files))
5135 (if (file-directory-p file) 5135 (if (file-directory-p file)
5136 (push (file-name-as-directory file) path))) 5136 (push (file-name-as-directory file) path)))
5137 (push dir path1))) 5137 (push dir path1)))
5138 path1)) 5138 path1))
5139 5139
5140 5140
5141 ;;----- Scanning the library catalogs ------------------ 5141 ;;----- Scanning the library catalogs ------------------
5142 5142
5143 (defun idlwave-scan-library-catalogs (&optional message-base no-load) 5143 (defun idlwave-scan-library-catalogs (&optional message-base no-load)
5144 "Scan for library catalog files (.idlwave_catalog) and ingest. 5144 "Scan for library catalog files (.idlwave_catalog) and ingest.
5145 5145
5146 All directories on `idlwave-path-alist' (or `idlwave-library-path' 5146 All directories on `idlwave-path-alist' (or `idlwave-library-path'
5147 instead, if present) are searched. Print MESSAGE-BASE along with the 5147 instead, if present) are searched. Print MESSAGE-BASE along with the
5148 libraries being loaded, if passed, and skip loading/normalizing if 5148 libraries being loaded, if passed, and skip loading/normalizing if
5149 NO-LOAD is non-nil. The variable `idlwave-use-library-catalogs' can 5149 NO-LOAD is non-nil. The variable `idlwave-use-library-catalogs' can
5150 be set to nil to disable library catalog scanning." 5150 be set to nil to disable library catalog scanning."
5151 (when idlwave-use-library-catalogs 5151 (when idlwave-use-library-catalogs
5152 (let ((dirs 5152 (let ((dirs
5153 (if idlwave-library-path 5153 (if idlwave-library-path
5154 (idlwave-expand-path idlwave-library-path) 5154 (idlwave-expand-path idlwave-library-path)
5155 (mapcar 'car idlwave-path-alist))) 5155 (mapcar 'car idlwave-path-alist)))
5156 (old-libname "") 5156 (old-libname "")
5157 dir-entry dir flags catalog all-routines) 5157 dir-entry dir flags catalog all-routines)
5158 (if message-base (message message-base)) 5158 (if message-base (message message-base))
5159 (while (setq dir (pop dirs)) 5159 (while (setq dir (pop dirs))
5160 (catch 'continue 5160 (catch 'continue
5161 (when (file-readable-p 5161 (when (file-readable-p
5162 (setq catalog (expand-file-name ".idlwave_catalog" dir))) 5162 (setq catalog (expand-file-name ".idlwave_catalog" dir)))
5163 (unless no-load 5163 (unless no-load
5164 (setq idlwave-library-catalog-routines nil) 5164 (setq idlwave-library-catalog-routines nil)
5165 ;; Load the catalog file 5165 ;; Load the catalog file
5166 (condition-case nil 5166 (condition-case nil
5167 (load catalog t t t) 5167 (load catalog t t t)
5168 (error (throw 'continue t))) 5168 (error (throw 'continue t)))
5169 (when (and 5169 (when (and
5170 message-base 5170 message-base
5171 (not (string= idlwave-library-catalog-libname 5171 (not (string= idlwave-library-catalog-libname
5172 old-libname))) 5172 old-libname)))
5173 (message (concat message-base 5173 (message (concat message-base
5174 idlwave-library-catalog-libname)) 5174 idlwave-library-catalog-libname))
5175 (setq old-libname idlwave-library-catalog-libname)) 5175 (setq old-libname idlwave-library-catalog-libname))
5176 (when idlwave-library-catalog-routines 5176 (when idlwave-library-catalog-routines
5177 (setq all-routines 5177 (setq all-routines
5178 (append 5178 (append
5179 (idlwave-sintern-rinfo-list 5179 (idlwave-sintern-rinfo-list
5180 idlwave-library-catalog-routines 'sys dir) 5180 idlwave-library-catalog-routines 'sys dir)
5181 all-routines)))) 5181 all-routines))))
5182 5182
5183 ;; Add a 'lib flag if on path-alist 5183 ;; Add a 'lib flag if on path-alist
5184 (when (and idlwave-path-alist 5184 (when (and idlwave-path-alist
5185 (setq dir-entry (assoc dir idlwave-path-alist))) 5185 (setq dir-entry (assoc dir idlwave-path-alist)))
5186 (idlwave-path-alist-add-flag dir-entry 'lib))))) 5186 (idlwave-path-alist-add-flag dir-entry 'lib)))))
5187 (unless no-load (setq idlwave-library-catalog-routines all-routines)) 5187 (unless no-load (setq idlwave-library-catalog-routines all-routines))
5188 (if message-base (message (concat message-base "done")))))) 5188 (if message-base (message (concat message-base "done"))))))
5189 5189
5190 ;;----- Communicating with the Shell ------------------- 5190 ;;----- Communicating with the Shell -------------------
5191 5191
5192 ;; First, here is the idl program which can be used to query IDL for 5192 ;; First, here is the idl program which can be used to query IDL for
5193 ;; defined routines. 5193 ;; defined routines.
5194 (defconst idlwave-routine-info.pro 5194 (defconst idlwave-routine-info.pro
5195 " 5195 "
5196 ;; START OF IDLWAVE SUPPORT ROUTINES 5196 ;; START OF IDLWAVE SUPPORT ROUTINES
5197 pro idlwave_print_info_entry,name,func=func,separator=sep 5197 pro idlwave_print_info_entry,name,func=func,separator=sep
5198 ;; See if it's an object method 5198 ;; See if it's an object method
5199 if name eq '' then return 5199 if name eq '' then return
5200 func = keyword_set(func) 5200 func = keyword_set(func)
5201 methsep = strpos(name,'::') 5201 methsep = strpos(name,'::')
5202 meth = methsep ne -1 5202 meth = methsep ne -1
5203 5203
5204 ;; Get routine info 5204 ;; Get routine info
5205 pars = routine_info(name,/parameters,functions=func) 5205 pars = routine_info(name,/parameters,functions=func)
5206 source = routine_info(name,/source,functions=func) 5206 source = routine_info(name,/source,functions=func)
5207 nargs = pars.num_args 5207 nargs = pars.num_args
5208 nkw = pars.num_kw_args 5208 nkw = pars.num_kw_args
5209 if nargs gt 0 then args = pars.args 5209 if nargs gt 0 then args = pars.args
5210 if nkw gt 0 then kwargs = pars.kw_args 5210 if nkw gt 0 then kwargs = pars.kw_args
5211 5211
5212 ;; Trim the class, and make the name 5212 ;; Trim the class, and make the name
5213 if meth then begin 5213 if meth then begin
5214 class = strmid(name,0,methsep) 5214 class = strmid(name,0,methsep)
5215 name = strmid(name,methsep+2,strlen(name)-1) 5215 name = strmid(name,methsep+2,strlen(name)-1)
5216 if nargs gt 0 then begin 5216 if nargs gt 0 then begin
5217 ;; remove the self argument 5217 ;; remove the self argument
5218 wh = where(args ne 'SELF',nargs) 5218 wh = where(args ne 'SELF',nargs)
5219 if nargs gt 0 then args = args[wh] 5219 if nargs gt 0 then args = args[wh]
5220 endif 5220 endif
5221 endif else begin 5221 endif else begin
5222 ;; No class, just a normal routine. 5222 ;; No class, just a normal routine.
5223 class = \"\" 5223 class = \"\"
5224 endelse 5224 endelse
5225 5225
5226 ;; Calling sequence 5226 ;; Calling sequence
5227 cs = \"\" 5227 cs = \"\"
5228 if func then cs = 'Result = ' 5228 if func then cs = 'Result = '
5229 if meth then cs = cs + 'Obj -> [' + '%s' + '::]' 5229 if meth then cs = cs + 'Obj -> [' + '%s' + '::]'
5230 cs = cs + '%s' 5230 cs = cs + '%s'
5241 if nkw gt 0 then begin 5241 if nkw gt 0 then begin
5242 for j=0,nkw-1 do begin 5242 for j=0,nkw-1 do begin
5243 kwstring = kwstring + ' ' + kwargs[j] 5243 kwstring = kwstring + ' ' + kwargs[j]
5244 endfor 5244 endfor
5245 endif 5245 endif
5246 5246
5247 ret=(['IDLWAVE-PRO','IDLWAVE-FUN'])[func] 5247 ret=(['IDLWAVE-PRO','IDLWAVE-FUN'])[func]
5248 5248
5249 print,ret + ': ' + name + sep + class + sep + source[0].path $ 5249 print,ret + ': ' + name + sep + class + sep + source[0].path $
5250 + sep + cs + sep + kwstring 5250 + sep + cs + sep + kwstring
5251 end 5251 end
5252 5252
5253 pro idlwave_routine_info 5253 pro idlwave_routine_info
5283 pro idlwave_get_class_tags, class 5283 pro idlwave_get_class_tags, class
5284 res = execute('tags=tag_names({'+class+'})') 5284 res = execute('tags=tag_names({'+class+'})')
5285 if res then print,'IDLWAVE-CLASS-TAGS: '+class+' '+strjoin(tags,' ',/single) 5285 if res then print,'IDLWAVE-CLASS-TAGS: '+class+' '+strjoin(tags,' ',/single)
5286 end 5286 end
5287 ;; END OF IDLWAVE SUPPORT ROUTINES 5287 ;; END OF IDLWAVE SUPPORT ROUTINES
5288 " 5288 "
5289 "The idl programs to get info from the shell.") 5289 "The idl programs to get info from the shell.")
5290 5290
5291 (defvar idlwave-idlwave_routine_info-compiled nil 5291 (defvar idlwave-idlwave_routine_info-compiled nil
5292 "Remembers if the routine info procedure is already compiled.") 5292 "Remembers if the routine info procedure is already compiled.")
5293 5293
5306 (set-buffer (idlwave-find-file-noselect 5306 (set-buffer (idlwave-find-file-noselect
5307 (idlwave-shell-temp-file 'pro))) 5307 (idlwave-shell-temp-file 'pro)))
5308 (erase-buffer) 5308 (erase-buffer)
5309 (insert idlwave-routine-info.pro) 5309 (insert idlwave-routine-info.pro)
5310 (save-buffer 0)) 5310 (save-buffer 0))
5311 (idlwave-shell-send-command 5311 (idlwave-shell-send-command
5312 (concat ".run " idlwave-shell-temp-pro-file) 5312 (concat ".run " idlwave-shell-temp-pro-file)
5313 nil 'hide wait) 5313 nil 'hide wait)
5314 ; (message "SENDING SAVE") ; ???????????????????????? 5314 ; (message "SENDING SAVE") ; ????????????????????????
5315 (idlwave-shell-send-command 5315 (idlwave-shell-send-command
5316 (format "save,'idlwave_routine_info','idlwave_print_info_entry','idlwave_get_class_tags','idlwave_get_sysvars',FILE='%s',/ROUTINES" 5316 (format "save,'idlwave_routine_info','idlwave_print_info_entry','idlwave_get_class_tags','idlwave_get_sysvars',FILE='%s',/ROUTINES"
5317 (idlwave-shell-temp-file 'rinfo)) 5317 (idlwave-shell-temp-file 'rinfo))
5318 nil 'hide wait)) 5318 nil 'hide wait))
5319 5319
5320 ;; Restore and execute the procedure, analyze the output 5320 ;; Restore and execute the procedure, analyze the output
5321 ; (message "SENDING RESTORE & EXECUTE") ; ???????????????????????? 5321 ; (message "SENDING RESTORE & EXECUTE") ; ????????????????????????
5394 (what (nth 2 where-list)) 5394 (what (nth 2 where-list))
5395 (idlwave-force-class-query (equal arg '(4))) 5395 (idlwave-force-class-query (equal arg '(4)))
5396 (completion-regexp-list 5396 (completion-regexp-list
5397 (if (equal arg '(16)) 5397 (if (equal arg '(16))
5398 (list (read-string (concat "Completion Regexp: ")))))) 5398 (list (read-string (concat "Completion Regexp: "))))))
5399 5399
5400 (if (and module (string-match "::" module)) 5400 (if (and module (string-match "::" module))
5401 (setq class (substring module 0 (match-beginning 0)) 5401 (setq class (substring module 0 (match-beginning 0))
5402 module (substring module (match-end 0)))) 5402 module (substring module (match-end 0))))
5403 5403
5404 (cond 5404 (cond
5415 (idlwave-complete-filename)) 5415 (idlwave-complete-filename))
5416 5416
5417 ;; Check for any special completion functions 5417 ;; Check for any special completion functions
5418 ((and idlwave-complete-special 5418 ((and idlwave-complete-special
5419 (idlwave-call-special idlwave-complete-special))) 5419 (idlwave-call-special idlwave-complete-special)))
5420 5420
5421 ((null what) 5421 ((null what)
5422 (error "Nothing to complete here")) 5422 (error "Nothing to complete here"))
5423 5423
5424 ;; Complete a class 5424 ;; Complete a class
5425 ((eq what 'class) 5425 ((eq what 'class)
5432 (class-selector (idlwave-determine-class cw-list 'pro)) 5432 (class-selector (idlwave-determine-class cw-list 'pro))
5433 (super-classes (unless (idlwave-explicit-class-listed cw-list) 5433 (super-classes (unless (idlwave-explicit-class-listed cw-list)
5434 (idlwave-all-class-inherits class-selector))) 5434 (idlwave-all-class-inherits class-selector)))
5435 (isa (concat "procedure" (if class-selector "-method" ""))) 5435 (isa (concat "procedure" (if class-selector "-method" "")))
5436 (type-selector 'pro)) 5436 (type-selector 'pro))
5437 (setq idlwave-completion-help-info 5437 (setq idlwave-completion-help-info
5438 (list 'routine nil type-selector class-selector nil super-classes)) 5438 (list 'routine nil type-selector class-selector nil super-classes))
5439 (idlwave-complete-in-buffer 5439 (idlwave-complete-in-buffer
5440 'procedure (if class-selector 'method 'routine) 5440 'procedure (if class-selector 'method 'routine)
5441 (idlwave-routines) 'idlwave-selector 5441 (idlwave-routines) 'idlwave-selector
5442 (format "Select a %s name%s" 5442 (format "Select a %s name%s"
5443 isa 5443 isa
5444 (if class-selector 5444 (if class-selector
5445 (format " (class is %s)" 5445 (format " (class is %s)"
5446 (if (eq class-selector t) 5446 (if (eq class-selector t)
5447 "unknown" class-selector)) 5447 "unknown" class-selector))
5448 "")) 5448 ""))
5449 isa 5449 isa
5450 'idlwave-attach-method-classes 'idlwave-add-file-link-selector))) 5450 'idlwave-attach-method-classes 'idlwave-add-file-link-selector)))
5451 5451
5455 (class-selector (idlwave-determine-class cw-list 'fun)) 5455 (class-selector (idlwave-determine-class cw-list 'fun))
5456 (super-classes (unless (idlwave-explicit-class-listed cw-list) 5456 (super-classes (unless (idlwave-explicit-class-listed cw-list)
5457 (idlwave-all-class-inherits class-selector))) 5457 (idlwave-all-class-inherits class-selector)))
5458 (isa (concat "function" (if class-selector "-method" ""))) 5458 (isa (concat "function" (if class-selector "-method" "")))
5459 (type-selector 'fun)) 5459 (type-selector 'fun))
5460 (setq idlwave-completion-help-info 5460 (setq idlwave-completion-help-info
5461 (list 'routine nil type-selector class-selector nil super-classes)) 5461 (list 'routine nil type-selector class-selector nil super-classes))
5462 (idlwave-complete-in-buffer 5462 (idlwave-complete-in-buffer
5463 'function (if class-selector 'method 'routine) 5463 'function (if class-selector 'method 'routine)
5464 (idlwave-routines) 'idlwave-selector 5464 (idlwave-routines) 'idlwave-selector
5465 (format "Select a %s name%s" 5465 (format "Select a %s name%s"
5466 isa 5466 isa
5467 (if class-selector 5467 (if class-selector
5468 (format " (class is %s)" 5468 (format " (class is %s)"
5469 (if (eq class-selector t) 5469 (if (eq class-selector t)
5470 "unknown" class-selector)) 5470 "unknown" class-selector))
5471 "")) 5471 ""))
5472 isa 5472 isa
5473 'idlwave-attach-method-classes 'idlwave-add-file-link-selector))) 5473 'idlwave-attach-method-classes 'idlwave-add-file-link-selector)))
5493 (error "Nothing known about procedure %s" 5493 (error "Nothing known about procedure %s"
5494 (idlwave-make-full-name class name))) 5494 (idlwave-make-full-name class name)))
5495 (setq list (idlwave-fix-keywords name 'pro class list super-classes)) 5495 (setq list (idlwave-fix-keywords name 'pro class list super-classes))
5496 (unless list (error (format "No keywords available for procedure %s" 5496 (unless list (error (format "No keywords available for procedure %s"
5497 (idlwave-make-full-name class name)))) 5497 (idlwave-make-full-name class name))))
5498 (setq idlwave-completion-help-info 5498 (setq idlwave-completion-help-info
5499 (list 'keyword name type-selector class-selector entry super-classes)) 5499 (list 'keyword name type-selector class-selector entry super-classes))
5500 (idlwave-complete-in-buffer 5500 (idlwave-complete-in-buffer
5501 'keyword 'keyword list nil 5501 'keyword 'keyword list nil
5502 (format "Select keyword for procedure %s%s" 5502 (format "Select keyword for procedure %s%s"
5503 (idlwave-make-full-name class name) 5503 (idlwave-make-full-name class name)
5504 (if (or (member '("_EXTRA") list) 5504 (if (or (member '("_EXTRA") list)
5505 (member '("_REF_EXTRA") list)) 5505 (member '("_REF_EXTRA") list))
5506 " (note _EXTRA)" "")) 5506 " (note _EXTRA)" ""))
5507 isa 5507 isa
5508 'idlwave-attach-keyword-classes))) 5508 'idlwave-attach-keyword-classes)))
5509 5509
5510 ((eq what 'function-keyword) 5510 ((eq what 'function-keyword)
5531 (concat idlwave-current-obj_new-class 5531 (concat idlwave-current-obj_new-class
5532 "::Init (via OBJ_NEW)") 5532 "::Init (via OBJ_NEW)")
5533 (idlwave-make-full-name class name))) 5533 (idlwave-make-full-name class name)))
5534 (unless list (error (format "No keywords available for function %s" 5534 (unless list (error (format "No keywords available for function %s"
5535 msg-name))) 5535 msg-name)))
5536 (setq idlwave-completion-help-info 5536 (setq idlwave-completion-help-info
5537 (list 'keyword name type-selector class-selector nil super-classes)) 5537 (list 'keyword name type-selector class-selector nil super-classes))
5538 (idlwave-complete-in-buffer 5538 (idlwave-complete-in-buffer
5539 'keyword 'keyword list nil 5539 'keyword 'keyword list nil
5540 (format "Select keyword for function %s%s" msg-name 5540 (format "Select keyword for function %s%s" msg-name
5541 (if (or (member '("_EXTRA") list) 5541 (if (or (member '("_EXTRA") list)
5542 (member '("_REF_EXTRA") list)) 5542 (member '("_REF_EXTRA") list))
5543 " (note _EXTRA)" "")) 5543 " (note _EXTRA)" ""))
5544 isa 5544 isa
5545 'idlwave-attach-keyword-classes))) 5545 'idlwave-attach-keyword-classes)))
5546 5546
5547 (t (error "This should not happen (idlwave-complete)"))))) 5547 (t (error "This should not happen (idlwave-complete)")))))
5575 ("procedure-method") ("procedure-method-keyword") 5575 ("procedure-method") ("procedure-method-keyword")
5576 ("function-method") ("function-method-keyword") 5576 ("function-method") ("function-method-keyword")
5577 ("class"))) 5577 ("class")))
5578 (module (idlwave-sintern-routine-or-method module class)) 5578 (module (idlwave-sintern-routine-or-method module class))
5579 (class (idlwave-sintern-class class)) 5579 (class (idlwave-sintern-class class))
5580 (what (cond 5580 (what (cond
5581 ((equal what 0) 5581 ((equal what 0)
5582 (setq what 5582 (setq what
5583 (intern (completing-read 5583 (intern (completing-read
5584 "Complete what? " what-list nil t)))) 5584 "Complete what? " what-list nil t))))
5585 ((integerp what) 5585 ((integerp what)
5586 (setq what (intern (car (nth (1- what) what-list))))) 5586 (setq what (intern (car (nth (1- what) what-list)))))
5587 ((and what 5587 ((and what
5588 (symbolp what) 5588 (symbolp what)
5600 ((eq what 'procedure-keyword) 5600 ((eq what 'procedure-keyword)
5601 (let* ((class-selector nil) 5601 (let* ((class-selector nil)
5602 (super-classes nil) 5602 (super-classes nil)
5603 (type-selector 'pro) 5603 (type-selector 'pro)
5604 (pro (or module 5604 (pro (or module
5605 (idlwave-completing-read 5605 (idlwave-completing-read
5606 "Procedure: " (idlwave-routines) 'idlwave-selector)))) 5606 "Procedure: " (idlwave-routines) 'idlwave-selector))))
5607 (setq pro (idlwave-sintern-routine pro)) 5607 (setq pro (idlwave-sintern-routine pro))
5608 (list nil-list nil-list 'procedure-keyword 5608 (list nil-list nil-list 'procedure-keyword
5609 (list pro nil nil nil) nil))) 5609 (list pro nil nil nil) nil)))
5610 5610
5614 ((eq what 'function-keyword) 5614 ((eq what 'function-keyword)
5615 (let* ((class-selector nil) 5615 (let* ((class-selector nil)
5616 (super-classes nil) 5616 (super-classes nil)
5617 (type-selector 'fun) 5617 (type-selector 'fun)
5618 (func (or module 5618 (func (or module
5619 (idlwave-completing-read 5619 (idlwave-completing-read
5620 "Function: " (idlwave-routines) 'idlwave-selector)))) 5620 "Function: " (idlwave-routines) 'idlwave-selector))))
5621 (setq func (idlwave-sintern-routine func)) 5621 (setq func (idlwave-sintern-routine func))
5622 (list nil-list nil-list 'function-keyword 5622 (list nil-list nil-list 'function-keyword
5623 (list func nil nil nil) nil))) 5623 (list func nil nil nil) nil)))
5624 5624
5654 (list nil-list nil-list 'function-keyword 5654 (list nil-list nil-list 'function-keyword
5655 (list func nil class nil) nil))) 5655 (list func nil class nil) nil)))
5656 5656
5657 ((eq what 'class) 5657 ((eq what 'class)
5658 (list nil-list nil-list 'class nil-list nil)) 5658 (list nil-list nil-list 'class nil-list nil))
5659 5659
5660 (t (error "Invalid value for WHAT"))))) 5660 (t (error "Invalid value for WHAT")))))
5661 5661
5662 (defun idlwave-completing-read (&rest args) 5662 (defun idlwave-completing-read (&rest args)
5663 ;; Completing read, case insensitive 5663 ;; Completing read, case insensitive
5664 (let ((old-value (default-value 'completion-ignore-case))) 5664 (let ((old-value (default-value 'completion-ignore-case)))
5677 (default-directory 5677 (default-directory
5678 (if (and (boundp 'idlwave-shell-default-directory) 5678 (if (and (boundp 'idlwave-shell-default-directory)
5679 (stringp idlwave-shell-default-directory) 5679 (stringp idlwave-shell-default-directory)
5680 (file-directory-p idlwave-shell-default-directory)) 5680 (file-directory-p idlwave-shell-default-directory))
5681 idlwave-shell-default-directory 5681 idlwave-shell-default-directory
5682 default-directory))) 5682 default-directory)))
5683 (comint-dynamic-complete-filename))) 5683 (comint-dynamic-complete-filename)))
5684 5684
5685 (defun idlwave-make-full-name (class name) 5685 (defun idlwave-make-full-name (class name)
5686 ;; Make a fully qualified module name including the class name 5686 ;; Make a fully qualified module name including the class name
5687 (concat (if class (format "%s::" class) "") name)) 5687 (concat (if class (format "%s::" class) "") name))
5688 5688
5689 (defun idlwave-rinfo-assoc (name type class list) 5689 (defun idlwave-rinfo-assoc (name type class list)
5690 "Like `idlwave-rinfo-assq', but sintern strings first." 5690 "Like `idlwave-rinfo-assq', but sintern strings first."
5691 (idlwave-rinfo-assq 5691 (idlwave-rinfo-assq
5692 (idlwave-sintern-routine-or-method name class) 5692 (idlwave-sintern-routine-or-method name class)
5693 type (idlwave-sintern-class class) list)) 5693 type (idlwave-sintern-class class) list))
5694 5694
5695 (defun idlwave-rinfo-assq (name type class list) 5695 (defun idlwave-rinfo-assq (name type class list)
5696 ;; Works like assq, but also checks type and class 5696 ;; Works like assq, but also checks type and class
5710 (while classes 5710 (while classes
5711 (if (setq rtn (idlwave-rinfo-assq name type (pop classes) list)) 5711 (if (setq rtn (idlwave-rinfo-assq name type (pop classes) list))
5712 (setq classes nil))) 5712 (setq classes nil)))
5713 rtn)) 5713 rtn))
5714 5714
5715 (defun idlwave-best-rinfo-assq (name type class list &optional with-file 5715 (defun idlwave-best-rinfo-assq (name type class list &optional with-file
5716 keep-system) 5716 keep-system)
5717 "Like `idlwave-rinfo-assq', but get all twins and sort, then return first. 5717 "Like `idlwave-rinfo-assq', but get all twins and sort, then return first.
5718 If WITH-FILE is passed, find the best rinfo entry with a file 5718 If WITH-FILE is passed, find the best rinfo entry with a file
5719 included. If KEEP-SYSTEM is set, don't prune system for compiled 5719 included. If KEEP-SYSTEM is set, don't prune system for compiled
5720 syslib files." 5720 syslib files."
5735 (mapcar (lambda (x) 5735 (mapcar (lambda (x)
5736 (if (nth 1 (nth 3 x)) x)) 5736 (if (nth 1 (nth 3 x)) x))
5737 twins))))) 5737 twins)))))
5738 (car twins))) 5738 (car twins)))
5739 5739
5740 (defun idlwave-best-rinfo-assoc (name type class list &optional with-file 5740 (defun idlwave-best-rinfo-assoc (name type class list &optional with-file
5741 keep-system) 5741 keep-system)
5742 "Like `idlwave-best-rinfo-assq', but sintern strings first." 5742 "Like `idlwave-best-rinfo-assq', but sintern strings first."
5743 (idlwave-best-rinfo-assq 5743 (idlwave-best-rinfo-assq
5744 (idlwave-sintern-routine-or-method name class) 5744 (idlwave-sintern-routine-or-method name class)
5745 type (idlwave-sintern-class class) list with-file keep-system)) 5745 type (idlwave-sintern-class class) list with-file keep-system))
5826 (defvar idlwave-determine-class-special nil 5826 (defvar idlwave-determine-class-special nil
5827 "List of special functions for determining class. 5827 "List of special functions for determining class.
5828 Must accept two arguments: `apos' and `info'") 5828 Must accept two arguments: `apos' and `info'")
5829 5829
5830 (defun idlwave-determine-class (info type) 5830 (defun idlwave-determine-class (info type)
5831 ;; Determine the class of a routine call. 5831 ;; Determine the class of a routine call.
5832 ;; INFO is the `cw-list' structure as returned by idlwave-where. 5832 ;; INFO is the `cw-list' structure as returned by idlwave-where.
5833 ;; The second element in this structure is the class. When nil, we 5833 ;; The second element in this structure is the class. When nil, we
5834 ;; return nil. When t, try to get the class from text properties at 5834 ;; return nil. When t, try to get the class from text properties at
5835 ;; the arrow. When the object is "self", we use the class of the 5835 ;; the arrow. When the object is "self", we use the class of the
5836 ;; current routine. otherwise prompt the user for a class name. 5836 ;; current routine. otherwise prompt the user for a class name.
5846 idlwave-query-class)) 5846 idlwave-query-class))
5847 (query (cond (nassoc (cdr nassoc)) 5847 (query (cond (nassoc (cdr nassoc))
5848 (dassoc (cdr dassoc)) 5848 (dassoc (cdr dassoc))
5849 (t t))) 5849 (t t)))
5850 (arrow (and apos (string= (buffer-substring apos (+ 2 apos)) "->"))) 5850 (arrow (and apos (string= (buffer-substring apos (+ 2 apos)) "->")))
5851 (is-self 5851 (is-self
5852 (and arrow 5852 (and arrow
5853 (save-excursion (goto-char apos) 5853 (save-excursion (goto-char apos)
5854 (forward-word -1) 5854 (forward-word -1)
5855 (let ((case-fold-search t)) 5855 (let ((case-fold-search t))
5856 (looking-at "self\\>"))))) 5856 (looking-at "self\\>")))))
5867 class (idlwave-sintern-class class))) 5867 class (idlwave-sintern-class class)))
5868 (if (and (eq t class) is-self) 5868 (if (and (eq t class) is-self)
5869 (setq class (or (nth 2 (idlwave-current-routine)) class))) 5869 (setq class (or (nth 2 (idlwave-current-routine)) class)))
5870 5870
5871 ;; Before prompting, try any special class determination routines 5871 ;; Before prompting, try any special class determination routines
5872 (when (and (eq t class) 5872 (when (and (eq t class)
5873 idlwave-determine-class-special 5873 idlwave-determine-class-special
5874 (not force-query)) 5874 (not force-query))
5875 (setq special-class 5875 (setq special-class
5876 (idlwave-call-special idlwave-determine-class-special apos)) 5876 (idlwave-call-special idlwave-determine-class-special apos))
5877 (if special-class 5877 (if special-class
5878 (setq class (idlwave-sintern-class special-class) 5878 (setq class (idlwave-sintern-class special-class)
5879 store idlwave-store-inquired-class))) 5879 store idlwave-store-inquired-class)))
5880 5880
5881 ;; Prompt for a class, if we need to 5881 ;; Prompt for a class, if we need to
5882 (when (and (eq class t) 5882 (when (and (eq class t)
5883 (or force-query query)) 5883 (or force-query query))
5884 (setq class-alist 5884 (setq class-alist
5885 (mapcar 'list (idlwave-all-method-classes (car info) type))) 5885 (mapcar 'list (idlwave-all-method-classes (car info) type)))
5886 (setq class 5886 (setq class
5887 (idlwave-sintern-class 5887 (idlwave-sintern-class
5888 (cond 5888 (cond
5889 ((and (= (length class-alist) 0) (not force-query)) 5889 ((and (= (length class-alist) 0) (not force-query))
5890 (error "No classes available with method %s" (car info))) 5890 (error "No classes available with method %s" (car info)))
5891 ((and (= (length class-alist) 1) (not force-query)) 5891 ((and (= (length class-alist) 1) (not force-query))
5892 (car (car class-alist))) 5892 (car (car class-alist)))
5893 (t 5893 (t
5894 (setq store idlwave-store-inquired-class) 5894 (setq store idlwave-store-inquired-class)
5895 (idlwave-completing-read 5895 (idlwave-completing-read
5896 (format "Class%s: " (if (stringp (car info)) 5896 (format "Class%s: " (if (stringp (car info))
5897 (format " for %s method %s" 5897 (format " for %s method %s"
5898 type (car info)) 5898 type (car info))
5899 "")) 5899 ""))
5900 class-alist nil nil nil 'idlwave-class-history)))))) 5900 class-alist nil nil nil 'idlwave-class-history))))))
5902 ;; Store it, if requested 5902 ;; Store it, if requested
5903 (when (and class (not (eq t class))) 5903 (when (and class (not (eq t class)))
5904 ;; We have a real class here 5904 ;; We have a real class here
5905 (when (and store arrow) 5905 (when (and store arrow)
5906 (condition-case () 5906 (condition-case ()
5907 (add-text-properties 5907 (add-text-properties
5908 apos (+ apos 2) 5908 apos (+ apos 2)
5909 `(idlwave-class ,class face ,idlwave-class-arrow-face 5909 `(idlwave-class ,class face ,idlwave-class-arrow-face
5910 rear-nonsticky t)) 5910 rear-nonsticky t))
5911 (error nil))) 5911 (error nil)))
5912 (setf (nth 2 info) class)) 5912 (setf (nth 2 info) class))
5913 ;; Return the class 5913 ;; Return the class
5914 class) 5914 class)
5932 (push (cons (car a) file) idlwave-completion-help-links)) 5932 (push (cons (car a) file) idlwave-completion-help-links))
5933 sel)) 5933 sel))
5934 5934
5935 5935
5936 (defun idlwave-where () 5936 (defun idlwave-where ()
5937 "Find out where we are. 5937 "Find out where we are.
5938 The return value is a list with the following stuff: 5938 The return value is a list with the following stuff:
5939 \(PRO-LIST FUNC-LIST COMPLETE-WHAT CW-LIST LAST-CHAR) 5939 \(PRO-LIST FUNC-LIST COMPLETE-WHAT CW-LIST LAST-CHAR)
5940 5940
5941 PRO-LIST (PRO POINT CLASS ARROW) 5941 PRO-LIST (PRO POINT CLASS ARROW)
5942 FUNC-LIST (FUNC POINT CLASS ARROW) 5942 FUNC-LIST (FUNC POINT CLASS ARROW)
5943 COMPLETE-WHAT a symbol indicating what kind of completion makes sense here 5943 COMPLETE-WHAT a symbol indicating what kind of completion makes sense here
5944 CW-LIST (PRO-OR-FUNC POINT CLASS ARROW) Like PRO-LIST, for what can 5944 CW-LIST (PRO-OR-FUNC POINT CLASS ARROW) Like PRO-LIST, for what can
5945 be completed here. 5945 be completed here.
5946 LAST-CHAR last relevant character before point (non-white non-comment, 5946 LAST-CHAR last relevant character before point (non-white non-comment,
5947 not part of current identifier or leading slash). 5947 not part of current identifier or leading slash).
5948 5948
5949 In the lists, we have these meanings: 5949 In the lists, we have these meanings:
5951 FUNC: Function name 5951 FUNC: Function name
5952 POINT: Where is this 5952 POINT: Where is this
5953 CLASS: What class has the routine (nil=no, t=is method, but class unknown) 5953 CLASS: What class has the routine (nil=no, t=is method, but class unknown)
5954 ARROW: Location of the arrow" 5954 ARROW: Location of the arrow"
5955 (idlwave-routines) 5955 (idlwave-routines)
5956 (let* (;(bos (save-excursion (idlwave-beginning-of-statement) (point))) 5956 (let* (;(bos (save-excursion (idlwave-beginning-of-statement) (point)))
5957 (bos (save-excursion (idlwave-start-of-substatement 'pre) (point))) 5957 (bos (save-excursion (idlwave-start-of-substatement 'pre) (point)))
5958 (func-entry (idlwave-what-function bos)) 5958 (func-entry (idlwave-what-function bos))
5959 (func (car func-entry)) 5959 (func (car func-entry))
5960 (func-class (nth 1 func-entry)) 5960 (func-class (nth 1 func-entry))
5961 (func-arrow (nth 2 func-entry)) 5961 (func-arrow (nth 2 func-entry))
5973 (if (< func-point pro-point) (setq func nil)) 5973 (if (< func-point pro-point) (setq func nil))
5974 (cond 5974 (cond
5975 ((string-match "\\`[ \t]*\\(pro\\|function\\)[ \t]+[a-zA-Z0-9_]*\\'" 5975 ((string-match "\\`[ \t]*\\(pro\\|function\\)[ \t]+[a-zA-Z0-9_]*\\'"
5976 match-string) 5976 match-string)
5977 (setq cw 'class)) 5977 (setq cw 'class))
5978 ((string-match 5978 ((string-match
5979 "\\`[ \t]*\\([a-zA-Z][a-zA-Z0-9$_]*\\)?\\'" 5979 "\\`[ \t]*\\([a-zA-Z][a-zA-Z0-9$_]*\\)?\\'"
5980 (if (> pro-point 0) 5980 (if (> pro-point 0)
5981 (buffer-substring pro-point (point)) 5981 (buffer-substring pro-point (point))
5982 match-string)) 5982 match-string))
5983 (setq cw 'procedure cw-class pro-class cw-point pro-point 5983 (setq cw 'procedure cw-class pro-class cw-point pro-point
5984 cw-arrow pro-arrow)) 5984 cw-arrow pro-arrow))
5985 ((string-match "\\`[ \t]*\\(pro\\|function\\)\\>" 5985 ((string-match "\\`[ \t]*\\(pro\\|function\\)\\>"
5986 match-string) 5986 match-string)
5987 nil) 5987 nil)
5988 ((string-match "OBJ_NEW([ \t]*['\"]\\([a-zA-Z0-9$_]*\\)?\\'" 5988 ((string-match "OBJ_NEW([ \t]*['\"]\\([a-zA-Z0-9$_]*\\)?\\'"
5989 match-string) 5989 match-string)
5990 (setq cw 'class)) 5990 (setq cw 'class))
5991 ((string-match "\\<inherits\\s-+\\([a-zA-Z0-9$_]*\\)?\\'" 5991 ((string-match "\\<inherits\\s-+\\([a-zA-Z0-9$_]*\\)?\\'"
5992 match-string) 5992 match-string)
5993 (setq cw 'class)) 5993 (setq cw 'class))
5994 ((and func 5994 ((and func
5995 (> func-point pro-point) 5995 (> func-point pro-point)
5996 (= func-level 1) 5996 (= func-level 1)
5997 (memq last-char '(?\( ?,))) 5997 (memq last-char '(?\( ?,)))
5998 (setq cw 'function-keyword cw-mod func cw-point func-point 5998 (setq cw 'function-keyword cw-mod func cw-point func-point
5999 cw-class func-class cw-arrow func-arrow)) 5999 cw-class func-class cw-arrow func-arrow))
6035 6035
6036 ;; If the optional BOUND is an integer, bound backwards directed 6036 ;; If the optional BOUND is an integer, bound backwards directed
6037 ;; searches to this point. 6037 ;; searches to this point.
6038 6038
6039 (catch 'exit 6039 (catch 'exit
6040 (let (pos 6040 (let (pos
6041 func-point 6041 func-point
6042 (cnt 0) 6042 (cnt 0)
6043 func arrow-start class) 6043 func arrow-start class)
6044 (idlwave-with-special-syntax 6044 (idlwave-with-special-syntax
6045 (save-restriction 6045 (save-restriction
6050 (progn (up-list -1) t) 6050 (progn (up-list -1) t)
6051 (error nil)) 6051 (error nil))
6052 (setq pos (point)) 6052 (setq pos (point))
6053 (incf cnt) 6053 (incf cnt)
6054 (when (and (= (following-char) ?\() 6054 (when (and (= (following-char) ?\()
6055 (re-search-backward 6055 (re-search-backward
6056 "\\(::\\|\\<\\)\\([a-zA-Z][a-zA-Z0-9$_]*\\)[ \t]*\\=" 6056 "\\(::\\|\\<\\)\\([a-zA-Z][a-zA-Z0-9$_]*\\)[ \t]*\\="
6057 bound t)) 6057 bound t))
6058 (setq func (match-string 2) 6058 (setq func (match-string 2)
6059 func-point (goto-char (match-beginning 2)) 6059 func-point (goto-char (match-beginning 2))
6060 pos func-point) 6060 pos func-point)
6061 (if (re-search-backward 6061 (if (re-search-backward
6062 "->[ \t]*\\(\\([a-zA-Z][a-zA-Z0-9$_]*\\)::\\)?\\=" bound t) 6062 "->[ \t]*\\(\\([a-zA-Z][a-zA-Z0-9$_]*\\)::\\)?\\=" bound t)
6063 (setq arrow-start (copy-marker (match-beginning 0)) 6063 (setq arrow-start (copy-marker (match-beginning 0))
6064 class (or (match-string 2) t))) 6064 class (or (match-string 2) t)))
6065 (throw 6065 (throw
6066 'exit 6066 'exit
6067 (list 6067 (list
6068 (idlwave-sintern-routine-or-method func class) 6068 (idlwave-sintern-routine-or-method func class)
6069 (idlwave-sintern-class class) 6069 (idlwave-sintern-class class)
6070 arrow-start func-point cnt))) 6070 arrow-start func-point cnt)))
6071 (goto-char pos)) 6071 (goto-char pos))
6077 6077
6078 ;; If the optional BOUND is an integer, bound backwards directed 6078 ;; If the optional BOUND is an integer, bound backwards directed
6079 ;; searches to this point. 6079 ;; searches to this point.
6080 (let ((pos (point)) pro-point 6080 (let ((pos (point)) pro-point
6081 pro class arrow-start string) 6081 pro class arrow-start string)
6082 (save-excursion 6082 (save-excursion
6083 ;;(idlwave-beginning-of-statement) 6083 ;;(idlwave-beginning-of-statement)
6084 (idlwave-start-of-substatement 'pre) 6084 (idlwave-start-of-substatement 'pre)
6085 (setq string (buffer-substring (point) pos)) 6085 (setq string (buffer-substring (point) pos))
6086 (if (string-match 6086 (if (string-match
6087 "\\`[ \t]*\\([a-zA-Z][a-zA-Z0-9$_]*\\)[ \t]*\\(,\\|\\'\\)" string) 6087 "\\`[ \t]*\\([a-zA-Z][a-zA-Z0-9$_]*\\)[ \t]*\\(,\\|\\'\\)" string)
6088 (setq pro (match-string 1 string) 6088 (setq pro (match-string 1 string)
6089 pro-point (+ (point) (match-beginning 1))) 6089 pro-point (+ (point) (match-beginning 1)))
6090 (if (and (idlwave-skip-object) 6090 (if (and (idlwave-skip-object)
6091 (setq string (buffer-substring (point) pos)) 6091 (setq string (buffer-substring (point) pos))
6092 (string-match 6092 (string-match
6093 "\\`[ \t]*\\(->\\)[ \t]*\\(\\([a-zA-Z][a-zA-Z0-9$_]*\\)::\\)?\\([a-zA-Z][a-zA-Z0-9$_]*\\)?[ \t]*\\(,\\|\\(\\$\\s *\\(;.*\\)?\\)?$\\)" 6093 "\\`[ \t]*\\(->\\)[ \t]*\\(\\([a-zA-Z][a-zA-Z0-9$_]*\\)::\\)?\\([a-zA-Z][a-zA-Z0-9$_]*\\)?[ \t]*\\(,\\|\\(\\$\\s *\\(;.*\\)?\\)?$\\)"
6094 string)) 6094 string))
6095 (setq pro (if (match-beginning 4) 6095 (setq pro (if (match-beginning 4)
6096 (match-string 4 string)) 6096 (match-string 4 string))
6097 pro-point (if (match-beginning 4) 6097 pro-point (if (match-beginning 4)
6098 (+ (point) (match-beginning 4)) 6098 (+ (point) (match-beginning 4))
6132 (if (looking-at "[ \t]*->") 6132 (if (looking-at "[ \t]*->")
6133 (throw 'exit (setq pos (match-beginning 0))) 6133 (throw 'exit (setq pos (match-beginning 0)))
6134 (throw 'exit nil)))) 6134 (throw 'exit nil))))
6135 (goto-char pos) 6135 (goto-char pos)
6136 nil))) 6136 nil)))
6137 6137
6138 (defun idlwave-last-valid-char () 6138 (defun idlwave-last-valid-char ()
6139 "Return the last character before point which is not white or a comment 6139 "Return the last character before point which is not white or a comment
6140 and also not part of the current identifier. Since we do this in 6140 and also not part of the current identifier. Since we do this in
6141 order to identify places where keywords are, we consider the initial 6141 order to identify places where keywords are, we consider the initial
6142 `/' of a keyword as part of the identifier. 6142 `/' of a keyword as part of the identifier.
6222 (idlwave-after-successful-completion type slash beg)) 6222 (idlwave-after-successful-completion type slash beg))
6223 t) 6223 t)
6224 ((or (eq completion t) 6224 ((or (eq completion t)
6225 (and (= 1 (length (setq all-completions 6225 (and (= 1 (length (setq all-completions
6226 (idlwave-uniquify 6226 (idlwave-uniquify
6227 (all-completions part list 6227 (all-completions part list
6228 (or special-selector 6228 (or special-selector
6229 selector)))))) 6229 selector))))))
6230 (equal dpart dcompletion))) 6230 (equal dpart dcompletion)))
6231 ;; This is already complete 6231 ;; This is already complete
6232 (idlwave-after-successful-completion type slash beg) 6232 (idlwave-after-successful-completion type slash beg)
6233 (message "%s is already the complete %s" part isa) 6233 (message "%s is already the complete %s" part isa)
6234 nil) 6234 nil)
6235 (t 6235 (t
6236 ;; We cannot add something - offer a list. 6236 ;; We cannot add something - offer a list.
6237 (message "Making completion list...") 6237 (message "Making completion list...")
6238 6238
6239 (unless idlwave-completion-help-links ; already set somewhere? 6239 (unless idlwave-completion-help-links ; already set somewhere?
6240 (mapcar (lambda (x) ; Pass link prop through to highlight-linked 6240 (mapcar (lambda (x) ; Pass link prop through to highlight-linked
6241 (let ((link (get-text-property 0 'link (car x)))) 6241 (let ((link (get-text-property 0 'link (car x))))
6242 (if link 6242 (if link
6243 (push (cons (car x) link) 6243 (push (cons (car x) link)
6244 idlwave-completion-help-links)))) 6244 idlwave-completion-help-links))))
6245 list)) 6245 list))
6246 (let* ((list all-completions) 6246 (let* ((list all-completions)
6247 ;; "complete" means, this is already a valid completion 6247 ;; "complete" means, this is already a valid completion
6248 (complete (memq spart all-completions)) 6248 (complete (memq spart all-completions))
6249 (completion-highlight-first-word-only t)) ; XEmacs 6249 (completion-highlight-first-word-only t)) ; XEmacs
6250 ; (completion-fixup-function ; Emacs 6250 ; (completion-fixup-function ; Emacs
6251 ; (lambda () (and (eq (preceding-char) ?>) 6251 ; (lambda () (and (eq (preceding-char) ?>)
6252 ; (re-search-backward " <" beg t))))) 6252 ; (re-search-backward " <" beg t)))))
6253 6253
6254 (setq list (sort list (lambda (a b) 6254 (setq list (sort list (lambda (a b)
6255 (string< (downcase a) (downcase b))))) 6255 (string< (downcase a) (downcase b)))))
6256 (if prepare-display-function 6256 (if prepare-display-function
6257 (setq list (funcall prepare-display-function list))) 6257 (setq list (funcall prepare-display-function list)))
6258 (if (and (string= part dpart) 6258 (if (and (string= part dpart)
6259 (or (not (string= part "")) 6259 (or (not (string= part ""))
6260 idlwave-complete-empty-string-as-lower-case) 6260 idlwave-complete-empty-string-as-lower-case)
6261 (not idlwave-completion-force-default-case)) 6261 (not idlwave-completion-force-default-case))
6262 (setq list (mapcar (lambda (x) 6262 (setq list (mapcar (lambda (x)
6263 (if (listp x) 6263 (if (listp x)
6264 (setcar x (downcase (car x))) 6264 (setcar x (downcase (car x)))
6265 (setq x (downcase x))) 6265 (setq x (downcase x)))
6266 x) 6266 x)
6267 list))) 6267 list)))
6268 (idlwave-display-completion-list list prompt beg complete)) 6268 (idlwave-display-completion-list list prompt beg complete))
6278 (save-excursion 6278 (save-excursion
6279 (and 6279 (and
6280 (re-search-backward "\\<\\(pro\\|function\\)[ \t]+\\=" 6280 (re-search-backward "\\<\\(pro\\|function\\)[ \t]+\\="
6281 (- (point) 15) t) 6281 (- (point) 15) t)
6282 (goto-char (point-min)) 6282 (goto-char (point-min))
6283 (re-search-forward 6283 (re-search-forward
6284 "^[ \t]*\\(pro\\|function\\)[ \t]+\\([a-zA-Z0-9_]+::\\)" nil t)))) 6284 "^[ \t]*\\(pro\\|function\\)[ \t]+\\([a-zA-Z0-9_]+::\\)" nil t))))
6285 ;; Yank the full class specification 6285 ;; Yank the full class specification
6286 (insert (match-string 2)) 6286 (insert (match-string 2))
6287 ;; Do the completion, using list gathered from `idlwave-routines' 6287 ;; Do the completion, using list gathered from `idlwave-routines'
6288 (idlwave-complete-in-buffer 6288 (idlwave-complete-in-buffer
6289 'class 'class (idlwave-class-alist) nil 6289 'class 'class (idlwave-class-alist) nil
6290 "Select a class" "class" 6290 "Select a class" "class"
6291 '(lambda (list) ;; Push it to help-links if system help available 6291 '(lambda (list) ;; Push it to help-links if system help available
6292 (mapcar (lambda (x) 6292 (mapcar (lambda (x)
6293 (let* ((entry (idlwave-class-info x)) 6293 (let* ((entry (idlwave-class-info x))
6294 (link (nth 1 (assq 'link entry)))) 6294 (link (nth 1 (assq 'link entry))))
6295 (if link (push (cons x link) 6295 (if link (push (cons x link)
6296 idlwave-completion-help-links)) 6296 idlwave-completion-help-links))
6297 x)) 6297 x))
6298 list))))) 6298 list)))))
6299 6299
6300 (defun idlwave-attach-classes (list type show-classes) 6300 (defun idlwave-attach-classes (list type show-classes)
6302 ;; TYPE, when 'kwd, shows classes for method keywords, when 6302 ;; TYPE, when 'kwd, shows classes for method keywords, when
6303 ;; 'class-tag, for class tags, and otherwise for methods. 6303 ;; 'class-tag, for class tags, and otherwise for methods.
6304 ;; SHOW-CLASSES is the value of `idlwave-completion-show-classes'. 6304 ;; SHOW-CLASSES is the value of `idlwave-completion-show-classes'.
6305 (if (or (null show-classes) ; don't want to see classes 6305 (if (or (null show-classes) ; don't want to see classes
6306 (null class-selector) ; not a method call 6306 (null class-selector) ; not a method call
6307 (and 6307 (and
6308 (stringp class-selector) ; the class is already known 6308 (stringp class-selector) ; the class is already known
6309 (not super-classes))) ; no possibilities for inheritance 6309 (not super-classes))) ; no possibilities for inheritance
6310 ;; In these cases, we do not have to do anything 6310 ;; In these cases, we do not have to do anything
6311 list 6311 list
6312 (let* ((do-prop (and (>= show-classes 0) 6312 (let* ((do-prop (and (>= show-classes 0)
6317 (inherit (if (and (not (eq type 'class-tag)) super-classes) 6317 (inherit (if (and (not (eq type 'class-tag)) super-classes)
6318 (cons class-selector super-classes))) 6318 (cons class-selector super-classes)))
6319 (max (abs show-classes)) 6319 (max (abs show-classes))
6320 (lmax (if do-dots (apply 'max (mapcar 'length list)))) 6320 (lmax (if do-dots (apply 'max (mapcar 'length list))))
6321 classes nclasses class-info space) 6321 classes nclasses class-info space)
6322 (mapcar 6322 (mapcar
6323 (lambda (x) 6323 (lambda (x)
6324 ;; get the classes 6324 ;; get the classes
6325 (if (eq type 'class-tag) 6325 (if (eq type 'class-tag)
6326 ;; Just one class for tags 6326 ;; Just one class for tags
6327 (setq classes 6327 (setq classes
6328 (list 6328 (list
6329 (idlwave-class-or-superclass-with-tag class-selector x))) 6329 (idlwave-class-or-superclass-with-tag class-selector x)))
6330 ;; Multiple classes for method or method-keyword 6330 ;; Multiple classes for method or method-keyword
6331 (setq classes 6331 (setq classes
6332 (if (eq type 'kwd) 6332 (if (eq type 'kwd)
6333 (idlwave-all-method-keyword-classes 6333 (idlwave-all-method-keyword-classes
6334 method-selector x type-selector) 6334 method-selector x type-selector)
6335 (idlwave-all-method-classes x type-selector))) 6335 (idlwave-all-method-classes x type-selector)))
6336 (if inherit 6336 (if inherit
6337 (setq classes 6337 (setq classes
6338 (delq nil 6338 (delq nil
6339 (mapcar (lambda (x) (if (memq x inherit) x nil)) 6339 (mapcar (lambda (x) (if (memq x inherit) x nil))
6340 classes))))) 6340 classes)))))
6341 (setq nclasses (length classes)) 6341 (setq nclasses (length classes))
6342 ;; Make the separator between item and class-info 6342 ;; Make the separator between item and class-info
6369 ;; Call idlwave-attach-classes with keyword parameters 6369 ;; Call idlwave-attach-classes with keyword parameters
6370 (idlwave-attach-classes list 'kwd idlwave-completion-show-classes)) 6370 (idlwave-attach-classes list 'kwd idlwave-completion-show-classes))
6371 (defun idlwave-attach-class-tag-classes (list) 6371 (defun idlwave-attach-class-tag-classes (list)
6372 ;; Call idlwave-attach-classes with class structure tags 6372 ;; Call idlwave-attach-classes with class structure tags
6373 (idlwave-attach-classes list 'class-tag idlwave-completion-show-classes)) 6373 (idlwave-attach-classes list 'class-tag idlwave-completion-show-classes))
6374 6374
6375 6375
6376 ;;---------------------------------------------------------------------- 6376 ;;----------------------------------------------------------------------
6377 ;;---------------------------------------------------------------------- 6377 ;;----------------------------------------------------------------------
6378 ;;---------------------------------------------------------------------- 6378 ;;----------------------------------------------------------------------
6379 ;;---------------------------------------------------------------------- 6379 ;;----------------------------------------------------------------------
6390 rtn menu resp) 6390 rtn menu resp)
6391 (cond ((null list)) 6391 (cond ((null list))
6392 ((= 1 (length list)) 6392 ((= 1 (length list))
6393 (setq rtn (car list))) 6393 (setq rtn (car list)))
6394 ((featurep 'xemacs) 6394 ((featurep 'xemacs)
6395 (if sort (setq list (sort list (lambda (a b) 6395 (if sort (setq list (sort list (lambda (a b)
6396 (string< (upcase a) (upcase b)))))) 6396 (string< (upcase a) (upcase b))))))
6397 (setq menu 6397 (setq menu
6398 (append (list title) 6398 (append (list title)
6399 (mapcar (lambda (x) (vector x (list 'idlwave-pset 6399 (mapcar (lambda (x) (vector x (list 'idlwave-pset
6400 x))) 6400 x)))
6401 list))) 6401 list)))
6402 (setq menu (idlwave-split-menu-xemacs menu maxpopup)) 6402 (setq menu (idlwave-split-menu-xemacs menu maxpopup))
6403 (setq resp (get-popup-menu-response menu)) 6403 (setq resp (get-popup-menu-response menu))
6404 (funcall (event-function resp) (event-object resp))) 6404 (funcall (event-function resp) (event-object resp)))
6405 (t 6405 (t
6406 (if sort (setq list (sort list (lambda (a b) 6406 (if sort (setq list (sort list (lambda (a b)
6407 (string< (upcase a) (upcase b)))))) 6407 (string< (upcase a) (upcase b))))))
6408 (setq menu (cons title 6408 (setq menu (cons title
6409 (list 6409 (list
6410 (append (list "") 6410 (append (list "")
6411 (mapcar (lambda(x) (cons x x)) list))))) 6411 (mapcar (lambda(x) (cons x x)) list)))))
6492 (idlwave-local-value 'idlwave-completion-p "*Completions*")) 6492 (idlwave-local-value 'idlwave-completion-p "*Completions*"))
6493 (move-marker idlwave-completion-mark beg) 6493 (move-marker idlwave-completion-mark beg)
6494 (setq idlwave-before-completion-wconf (current-window-configuration))) 6494 (setq idlwave-before-completion-wconf (current-window-configuration)))
6495 6495
6496 (if (featurep 'xemacs) 6496 (if (featurep 'xemacs)
6497 (idlwave-display-completion-list-xemacs 6497 (idlwave-display-completion-list-xemacs
6498 list) 6498 list)
6499 (idlwave-display-completion-list-emacs list)) 6499 (idlwave-display-completion-list-emacs list))
6500 6500
6501 ;; Store a special value in `this-command'. When `idlwave-complete' 6501 ;; Store a special value in `this-command'. When `idlwave-complete'
6502 ;; finds this in `last-command', it will scroll the *Completions* buffer. 6502 ;; finds this in `last-command', it will scroll the *Completions* buffer.
6573 (save-window-excursion 6573 (save-window-excursion
6574 (with-output-to-temp-buffer "*Completions*" 6574 (with-output-to-temp-buffer "*Completions*"
6575 (mapcar (lambda(x) 6575 (mapcar (lambda(x)
6576 (princ (nth 1 x)) 6576 (princ (nth 1 x))
6577 (princ "\n")) 6577 (princ "\n"))
6578 keys-alist)) 6578 keys-alist))
6579 (setq char (read-char))) 6579 (setq char (read-char)))
6580 (setq char (read-char))) 6580 (setq char (read-char)))
6581 (message nil) 6581 (message nil)
6582 ;; Return the selected result 6582 ;; Return the selected result
6583 (nth 2 (assoc char keys-alist)))) 6583 (nth 2 (assoc char keys-alist))))
6693 (current-local-map))))))) 6693 (current-local-map)))))))
6694 6694
6695 (defun idlwave-make-modified-completion-map-emacs (old-map) 6695 (defun idlwave-make-modified-completion-map-emacs (old-map)
6696 "Replace `choose-completion' and `mouse-choose-completion' in OLD-MAP." 6696 "Replace `choose-completion' and `mouse-choose-completion' in OLD-MAP."
6697 (let ((new-map (copy-keymap old-map))) 6697 (let ((new-map (copy-keymap old-map)))
6698 (substitute-key-definition 6698 (substitute-key-definition
6699 'choose-completion 'idlwave-choose-completion new-map) 6699 'choose-completion 'idlwave-choose-completion new-map)
6700 (substitute-key-definition 6700 (substitute-key-definition
6701 'mouse-choose-completion 'idlwave-mouse-choose-completion new-map) 6701 'mouse-choose-completion 'idlwave-mouse-choose-completion new-map)
6702 (define-key new-map [mouse-3] 'idlwave-mouse-completion-help) 6702 (define-key new-map [mouse-3] 'idlwave-mouse-completion-help)
6703 new-map)) 6703 new-map))
6719 ;;; Stucture parsing code, and code to manage class info 6719 ;;; Stucture parsing code, and code to manage class info
6720 6720
6721 ;; 6721 ;;
6722 ;; - Go again over the documentation how to write a completion 6722 ;; - Go again over the documentation how to write a completion
6723 ;; plugin. It is in self.el, but currently still very bad. 6723 ;; plugin. It is in self.el, but currently still very bad.
6724 ;; This could be in a separate file in the distribution, or 6724 ;; This could be in a separate file in the distribution, or
6725 ;; in an appendix for the manual. 6725 ;; in an appendix for the manual.
6726 6726
6727 (defvar idlwave-struct-skip 6727 (defvar idlwave-struct-skip
6728 "[ \t]*\\(\\$.*\n\\(^[ \t]*\\(\\$[ \t]*\\)?\\(;.*\\)?\n\\)*\\)?[ \t]*" 6728 "[ \t]*\\(\\$.*\n\\(^[ \t]*\\(\\$[ \t]*\\)?\\(;.*\\)?\n\\)*\\)?[ \t]*"
6729 "Regexp for skipping continued blank or comment-only lines in 6729 "Regexp for skipping continued blank or comment-only lines in
6730 structures") 6730 structures")
6759 "Find a given TAG in the structure defined at point." 6759 "Find a given TAG in the structure defined at point."
6760 (let* ((borders (idlwave-struct-borders)) 6760 (let* ((borders (idlwave-struct-borders))
6761 (beg (car borders)) 6761 (beg (car borders))
6762 (end (cdr borders)) 6762 (end (cdr borders))
6763 (case-fold-search t)) 6763 (case-fold-search t))
6764 (re-search-forward (concat "\\(^[ \t]*\\|[,{][ \t]*\\)" tag "[ \t]*:") 6764 (re-search-forward (concat "\\(^[ \t]*\\|[,{][ \t]*\\)" tag "[ \t]*:")
6765 end t))) 6765 end t)))
6766 6766
6767 (defun idlwave-struct-inherits () 6767 (defun idlwave-struct-inherits ()
6768 "Return a list of all `inherits' names in the struct at point. 6768 "Return a list of all `inherits' names in the struct at point.
6769 Point is expected just before the opening `{' of the struct definition." 6769 Point is expected just before the opening `{' of the struct definition."
6774 (case-fold-search t) 6774 (case-fold-search t)
6775 names) 6775 names)
6776 (goto-char beg) 6776 (goto-char beg)
6777 (save-restriction 6777 (save-restriction
6778 (narrow-to-region beg end) 6778 (narrow-to-region beg end)
6779 (while (re-search-forward 6779 (while (re-search-forward
6780 (concat "[{,]" ;leading comma/brace 6780 (concat "[{,]" ;leading comma/brace
6781 idlwave-struct-skip ; 4 groups 6781 idlwave-struct-skip ; 4 groups
6782 "inherits" ; The INHERITS tag 6782 "inherits" ; The INHERITS tag
6783 idlwave-struct-skip ; 4 more 6783 idlwave-struct-skip ; 4 more
6784 "\\([a-zA-Z][a-zA-Z0-9_]*\\)") ; The super-group, #9 6784 "\\([a-zA-Z][a-zA-Z0-9_]*\\)") ; The super-group, #9
6824 (re (concat 6824 (re (concat
6825 (if var 6825 (if var
6826 (concat "\\<" (regexp-quote (downcase var)) "\\>" ws) 6826 (concat "\\<" (regexp-quote (downcase var)) "\\>" ws)
6827 "\\(\\)") 6827 "\\(\\)")
6828 "=" ws "\\({\\)" 6828 "=" ws "\\({\\)"
6829 (if name 6829 (if name
6830 (if (stringp name) 6830 (if (stringp name)
6831 (concat ws "\\(\\<" (downcase name) "\\)[^a-zA-Z0-9_$]") 6831 (concat ws "\\(\\<" (downcase name) "\\)[^a-zA-Z0-9_$]")
6832 ;; Just a generic name 6832 ;; Just a generic name
6833 (concat ws "\\<\\([a-zA-Z_0-9$]+\\)" ws ",")) 6833 (concat ws "\\<\\([a-zA-Z_0-9$]+\\)" ws ","))
6834 "")))) 6834 ""))))
6835 (if (or (and (or (eq bound 'all) (eq bound 'back)) 6835 (if (or (and (or (eq bound 'all) (eq bound 'back))
6836 (re-search-backward re nil t)) 6836 (re-search-backward re nil t))
6837 (and (not (eq bound 'back)) (re-search-forward re lim t))) 6837 (and (not (eq bound 'back)) (re-search-forward re lim t)))
6838 (progn 6838 (progn
6839 (goto-char (match-beginning 3)) 6839 (goto-char (match-beginning 3))
6840 (match-string-no-properties 5))))) 6840 (match-string-no-properties 5)))))
6841 6841
6842 (defvar idlwave-class-info nil) 6842 (defvar idlwave-class-info nil)
6843 (defvar idlwave-system-class-info nil) ; Gathered from idlw-rinfo 6843 (defvar idlwave-system-class-info nil) ; Gathered from idlw-rinfo
6844 (defvar idlwave-class-reset nil) ; to reset buffer-local classes 6844 (defvar idlwave-class-reset nil) ; to reset buffer-local classes
6845 6845
6846 (add-hook 'idlwave-update-rinfo-hook 6846 (add-hook 'idlwave-update-rinfo-hook
6847 (lambda () (setq idlwave-class-reset t))) 6847 (lambda () (setq idlwave-class-reset t)))
6850 6850
6851 (defun idlwave-class-info (class) 6851 (defun idlwave-class-info (class)
6852 (let (list entry) 6852 (let (list entry)
6853 (if idlwave-class-info 6853 (if idlwave-class-info
6854 (if idlwave-class-reset 6854 (if idlwave-class-reset
6855 (setq 6855 (setq
6856 idlwave-class-reset nil 6856 idlwave-class-reset nil
6857 idlwave-class-info ; Remove any visited in a buffer 6857 idlwave-class-info ; Remove any visited in a buffer
6858 (delq nil (mapcar 6858 (delq nil (mapcar
6859 (lambda (x) 6859 (lambda (x)
6860 (let ((filebuf 6860 (let ((filebuf
6861 (idlwave-class-file-or-buffer 6861 (idlwave-class-file-or-buffer
6862 (or (cdr (assq 'found-in x)) (car x))))) 6862 (or (cdr (assq 'found-in x)) (car x)))))
6863 (if (cdr filebuf) 6863 (if (cdr filebuf)
6864 nil 6864 nil
6865 x))) 6865 x)))
6866 idlwave-class-info)))) 6866 idlwave-class-info))))
6894 (concat "^[ \t]*pro[ \t]+" (downcase class) "__define" "\\>") nil t) 6894 (concat "^[ \t]*pro[ \t]+" (downcase class) "__define" "\\>") nil t)
6895 (if all-hook 6895 (if all-hook
6896 (progn 6896 (progn
6897 ;; For everything there 6897 ;; For everything there
6898 (setq end-lim (save-excursion (idlwave-end-of-subprogram) (point))) 6898 (setq end-lim (save-excursion (idlwave-end-of-subprogram) (point)))
6899 (while (setq name 6899 (while (setq name
6900 (idlwave-find-structure-definition nil t end-lim)) 6900 (idlwave-find-structure-definition nil t end-lim))
6901 (funcall all-hook name))) 6901 (funcall all-hook name)))
6902 (idlwave-find-structure-definition nil (or alt-class class)))))) 6902 (idlwave-find-structure-definition nil (or alt-class class))))))
6903 6903
6904 6904
6932 (unless (eq major-mode 'idlwave-mode) 6932 (unless (eq major-mode 'idlwave-mode)
6933 (idlwave-mode)) 6933 (idlwave-mode))
6934 (insert-file-contents file)) 6934 (insert-file-contents file))
6935 (save-excursion 6935 (save-excursion
6936 (goto-char 1) 6936 (goto-char 1)
6937 (idlwave-find-class-definition class 6937 (idlwave-find-class-definition class
6938 ;; Scan all of the structures found there 6938 ;; Scan all of the structures found there
6939 (lambda (name) 6939 (lambda (name)
6940 (let* ((this-class (idlwave-sintern-class name)) 6940 (let* ((this-class (idlwave-sintern-class name))
6941 (entry 6941 (entry
6942 (list this-class 6942 (list this-class
6943 (cons 'tags (idlwave-struct-tags)) 6943 (cons 'tags (idlwave-struct-tags))
6944 (cons 'inherits (idlwave-struct-inherits))))) 6944 (cons 'inherits (idlwave-struct-inherits)))))
6945 (if (not (eq this-class class)) 6945 (if (not (eq this-class class))
6946 (setq entry (nconc entry (list (cons 'found-in class))))) 6946 (setq entry (nconc entry (list (cons 'found-in class)))))
6961 (defun idlwave-all-class-tags (class) 6961 (defun idlwave-all-class-tags (class)
6962 "Return a list of native and inherited tags in CLASS." 6962 "Return a list of native and inherited tags in CLASS."
6963 (condition-case err 6963 (condition-case err
6964 (apply 'append (mapcar 'idlwave-class-tags 6964 (apply 'append (mapcar 'idlwave-class-tags
6965 (cons class (idlwave-all-class-inherits class)))) 6965 (cons class (idlwave-all-class-inherits class))))
6966 (error 6966 (error
6967 (idlwave-class-tag-reset) 6967 (idlwave-class-tag-reset)
6968 (error "%s" (error-message-string err))))) 6968 (error "%s" (error-message-string err)))))
6969 6969
6970 6970
6971 (defun idlwave-all-class-inherits (class) 6971 (defun idlwave-all-class-inherits (class)
6998 (setq all-inherits (nreverse rtn)) 6998 (setq all-inherits (nreverse rtn))
6999 (nconc info (list (cons 'all-inherits all-inherits))) 6999 (nconc info (list (cons 'all-inherits all-inherits)))
7000 all-inherits)))))) 7000 all-inherits))))))
7001 7001
7002 (defun idlwave-entry-keywords (entry &optional record-link) 7002 (defun idlwave-entry-keywords (entry &optional record-link)
7003 "Return the flat entry keywords alist from routine-info entry. 7003 "Return the flat entry keywords alist from routine-info entry.
7004 If RECORD-LINK is non-nil, the keyword text is copied and a text 7004 If RECORD-LINK is non-nil, the keyword text is copied and a text
7005 property indicating the link is added." 7005 property indicating the link is added."
7006 (let (kwds) 7006 (let (kwds)
7007 (mapcar 7007 (mapcar
7008 (lambda (key-list) 7008 (lambda (key-list)
7009 (let ((file (car key-list))) 7009 (let ((file (car key-list)))
7010 (mapcar (lambda (key-cons) 7010 (mapcar (lambda (key-cons)
7011 (let ((key (car key-cons)) 7011 (let ((key (car key-cons))
7012 (link (cdr key-cons))) 7012 (link (cdr key-cons)))
7013 (when (and record-link file) 7013 (when (and record-link file)
7014 (setq key (copy-sequence key)) 7014 (setq key (copy-sequence key))
7015 (put-text-property 7015 (put-text-property
7016 0 (length key) 7016 0 (length key)
7017 'link 7017 'link
7018 (concat 7018 (concat
7019 file 7019 file
7020 (if link 7020 (if link
7021 (concat idlwave-html-link-sep 7021 (concat idlwave-html-link-sep
7022 (number-to-string link)))) 7022 (number-to-string link))))
7023 key)) 7023 key))
7024 (push (list key) kwds))) 7024 (push (list key) kwds)))
7025 (cdr key-list)))) 7025 (cdr key-list))))
7028 7028
7029 (defun idlwave-entry-find-keyword (entry keyword) 7029 (defun idlwave-entry-find-keyword (entry keyword)
7030 "Find keyword KEYWORD in entry ENTRY, and return (with link) if set" 7030 "Find keyword KEYWORD in entry ENTRY, and return (with link) if set"
7031 (catch 'exit 7031 (catch 'exit
7032 (mapc 7032 (mapc
7033 (lambda (key-list) 7033 (lambda (key-list)
7034 (let ((file (car key-list)) 7034 (let ((file (car key-list))
7035 (kwd (assoc keyword (cdr key-list)))) 7035 (kwd (assoc keyword (cdr key-list))))
7036 (when kwd 7036 (when kwd
7037 (setq kwd (cons (car kwd) 7037 (setq kwd (cons (car kwd)
7038 (if (and file (cdr kwd)) 7038 (if (and file (cdr kwd))
7039 (concat file 7039 (concat file
7040 idlwave-html-link-sep 7040 idlwave-html-link-sep
7041 (number-to-string (cdr kwd))) 7041 (number-to-string (cdr kwd)))
7042 (cdr kwd)))) 7042 (cdr kwd))))
7043 (throw 'exit kwd)))) 7043 (throw 'exit kwd))))
7044 (nthcdr 5 entry)))) 7044 (nthcdr 5 entry))))
7072 (unless class-selector 7072 (unless class-selector
7073 (error "Not in a method procedure or function")) 7073 (error "Not in a method procedure or function"))
7074 ;; Check if we need to update the "current" class 7074 ;; Check if we need to update the "current" class
7075 (if (not (equal class-selector idlwave-current-tags-class)) 7075 (if (not (equal class-selector idlwave-current-tags-class))
7076 (idlwave-prepare-class-tag-completion class-selector)) 7076 (idlwave-prepare-class-tag-completion class-selector))
7077 (setq idlwave-completion-help-info 7077 (setq idlwave-completion-help-info
7078 (list 'idlwave-complete-class-structure-tag-help 7078 (list 'idlwave-complete-class-structure-tag-help
7079 (idlwave-sintern-routine 7079 (idlwave-sintern-routine
7080 (concat class-selector "__define")) 7080 (concat class-selector "__define"))
7081 nil)) 7081 nil))
7082 (let ((idlwave-cpl-bold idlwave-current-native-class-tags)) 7082 (let ((idlwave-cpl-bold idlwave-current-native-class-tags))
7083 (idlwave-complete-in-buffer 7083 (idlwave-complete-in-buffer
7084 'class-tag 'class-tag 7084 'class-tag 'class-tag
7085 idlwave-current-class-tags nil 7085 idlwave-current-class-tags nil
7086 (format "Select a tag of class %s" class-selector) 7086 (format "Select a tag of class %s" class-selector)
7087 "class tag" 7087 "class tag"
7088 'idlwave-attach-class-tag-classes)) 7088 'idlwave-attach-class-tag-classes))
7089 t) ; return t to skip other completions 7089 t) ; return t to skip other completions
7131 (cond ((save-excursion 7131 (cond ((save-excursion
7132 ;; Check if the context is right for system variable 7132 ;; Check if the context is right for system variable
7133 (skip-chars-backward "[a-zA-Z0-9_$]") 7133 (skip-chars-backward "[a-zA-Z0-9_$]")
7134 (equal (char-before) ?!)) 7134 (equal (char-before) ?!))
7135 (setq idlwave-completion-help-info '(idlwave-complete-sysvar-help)) 7135 (setq idlwave-completion-help-info '(idlwave-complete-sysvar-help))
7136 (idlwave-complete-in-buffer 'sysvar 'sysvar 7136 (idlwave-complete-in-buffer 'sysvar 'sysvar
7137 idlwave-system-variables-alist nil 7137 idlwave-system-variables-alist nil
7138 "Select a system variable" 7138 "Select a system variable"
7139 "system variable") 7139 "system variable")
7140 t) ; return t to skip other completions 7140 t) ; return t to skip other completions
7141 ((save-excursion 7141 ((save-excursion
7150 (tags (cdr (assq 'tags entry)))) 7150 (tags (cdr (assq 'tags entry))))
7151 (or entry (error "!%s is not a known system variable" var)) 7151 (or entry (error "!%s is not a known system variable" var))
7152 (or tags (error "System variable !%s is not a structure" var)) 7152 (or tags (error "System variable !%s is not a structure" var))
7153 (setq idlwave-completion-help-info 7153 (setq idlwave-completion-help-info
7154 (list 'idlwave-complete-sysvar-tag-help var)) 7154 (list 'idlwave-complete-sysvar-tag-help var))
7155 (idlwave-complete-in-buffer 'sysvartag 'sysvartag 7155 (idlwave-complete-in-buffer 'sysvartag 'sysvartag
7156 tags nil 7156 tags nil
7157 "Select a system variable tag" 7157 "Select a system variable tag"
7158 "system variable tag") 7158 "system variable tag")
7159 t)) ; return t to skip other completions 7159 t)) ; return t to skip other completions
7160 (t nil)))) 7160 (t nil))))
7177 target main-base) 7177 target main-base)
7178 (cond 7178 (cond
7179 ((eq mode 'test) ; we can at least link the main 7179 ((eq mode 'test) ; we can at least link the main
7180 (and (stringp word) entry main)) 7180 (and (stringp word) entry main))
7181 ((eq mode 'set) 7181 ((eq mode 'set)
7182 (if entry 7182 (if entry
7183 (setq link 7183 (setq link
7184 (if (setq target (cdr (assoc word tags))) 7184 (if (setq target (cdr (assoc word tags)))
7185 (idlwave-substitute-link-target main target) 7185 (idlwave-substitute-link-target main target)
7186 main)))) ;; setting dynamic!!! 7186 main)))) ;; setting dynamic!!!
7187 (t (error "This should not happen"))))) 7187 (t (error "This should not happen")))))
7188 7188
7196 (concat main-base idlwave-html-link-sep (number-to-string target)) 7196 (concat main-base idlwave-html-link-sep (number-to-string target))
7197 link))) 7197 link)))
7198 7198
7199 ;; Fake help in the source buffer for class structure tags. 7199 ;; Fake help in the source buffer for class structure tags.
7200 ;; KWD AND NAME ARE GLOBAL-VARIABLES HERE. 7200 ;; KWD AND NAME ARE GLOBAL-VARIABLES HERE.
7201 (defvar name) 7201 (defvar name)
7202 (defvar kwd) 7202 (defvar kwd)
7203 (defvar idlwave-help-do-class-struct-tag nil) 7203 (defvar idlwave-help-do-class-struct-tag nil)
7204 (defun idlwave-complete-class-structure-tag-help (mode word) 7204 (defun idlwave-complete-class-structure-tag-help (mode word)
7205 (cond 7205 (cond
7206 ((eq mode 'test) ; nothing gets fontified for class tags 7206 ((eq mode 'test) ; nothing gets fontified for class tags
7207 nil) 7207 nil)
7208 ((eq mode 'set) 7208 ((eq mode 'set)
7209 (let (class-with found-in) 7209 (let (class-with found-in)
7210 (when (setq class-with 7210 (when (setq class-with
7211 (idlwave-class-or-superclass-with-tag 7211 (idlwave-class-or-superclass-with-tag
7212 idlwave-current-tags-class 7212 idlwave-current-tags-class
7213 word)) 7213 word))
7214 (if (assq (idlwave-sintern-class class-with) 7214 (if (assq (idlwave-sintern-class class-with)
7215 idlwave-system-class-info) 7215 idlwave-system-class-info)
7216 (error "No help available for system class tags.")) 7216 (error "No help available for system class tags"))
7217 (if (setq found-in (idlwave-class-found-in class-with)) 7217 (if (setq found-in (idlwave-class-found-in class-with))
7218 (setq name (cons (concat found-in "__define") class-with)) 7218 (setq name (cons (concat found-in "__define") class-with))
7219 (setq name (concat class-with "__define"))))) 7219 (setq name (concat class-with "__define")))))
7220 (setq kwd word 7220 (setq kwd word
7221 idlwave-help-do-class-struct-tag t)) 7221 idlwave-help-do-class-struct-tag t))
7222 (t (error "This should not happen")))) 7222 (t (error "This should not happen"))))
7223 7223
7224 (defun idlwave-class-or-superclass-with-tag (class tag) 7224 (defun idlwave-class-or-superclass-with-tag (class tag)
7225 "Find and return the CLASS or one of its superclass with the 7225 "Find and return the CLASS or one of its superclass with the
7226 associated TAG, if any." 7226 associated TAG, if any."
7227 (let ((sclasses (cons class (cdr (assq 'all-inherits 7227 (let ((sclasses (cons class (cdr (assq 'all-inherits
7228 (idlwave-class-info class))))) 7228 (idlwave-class-info class)))))
7229 cl) 7229 cl)
7230 (catch 'exit 7230 (catch 'exit
7231 (while sclasses 7231 (while sclasses
7232 (setq cl (pop sclasses)) 7232 (setq cl (pop sclasses))
7233 (let ((tags (idlwave-class-tags cl))) 7233 (let ((tags (idlwave-class-tags cl)))
7234 (while tags 7234 (while tags
7235 (if (eq t (compare-strings tag 0 nil (car tags) 0 nil t)) 7235 (if (eq t (compare-strings tag 0 nil (car tags) 0 nil t))
7236 (throw 'exit cl)) 7236 (throw 'exit cl))
7237 (setq tags (cdr tags)))))))) 7237 (setq tags (cdr tags))))))))
7238 7238
7239 7239
7240 (defun idlwave-sysvars-reset () 7240 (defun idlwave-sysvars-reset ()
7241 (if (and (fboundp 'idlwave-shell-is-running) 7241 (if (and (fboundp 'idlwave-shell-is-running)
7254 (let ((list idlwave-system-variables-alist) entry tags) 7254 (let ((list idlwave-system-variables-alist) entry tags)
7255 (while (setq entry (pop list)) 7255 (while (setq entry (pop list))
7256 (setcar entry (idlwave-sintern-sysvar (car entry) 'set)) 7256 (setcar entry (idlwave-sintern-sysvar (car entry) 'set))
7257 (setq tags (assq 'tags entry)) 7257 (setq tags (assq 'tags entry))
7258 (if tags 7258 (if tags
7259 (setcdr tags 7259 (setcdr tags
7260 (mapcar (lambda (x) 7260 (mapcar (lambda (x)
7261 (cons (idlwave-sintern-sysvartag (car x) 'set) 7261 (cons (idlwave-sintern-sysvartag (car x) 'set)
7262 (cdr x))) 7262 (cdr x)))
7263 (cdr tags))))))) 7263 (cdr tags)))))))
7264 7264
7265 (defvar idlwave-shell-command-output) 7265 (defvar idlwave-shell-command-output)
7272 (setq idlwave-system-variables-alist nil) 7272 (setq idlwave-system-variables-alist nil)
7273 (while (string-match "^IDLWAVE-SYSVAR: !\\([a-zA-Z0-9_$]+\\)\\( \\(.*\\)\\)?" 7273 (while (string-match "^IDLWAVE-SYSVAR: !\\([a-zA-Z0-9_$]+\\)\\( \\(.*\\)\\)?"
7274 text start) 7274 text start)
7275 (setq start (match-end 0) 7275 (setq start (match-end 0)
7276 var (match-string 1 text) 7276 var (match-string 1 text)
7277 tags (if (match-end 3) 7277 tags (if (match-end 3)
7278 (idlwave-split-string (match-string 3 text)))) 7278 (idlwave-split-string (match-string 3 text))))
7279 ;; Maintain old links, if present 7279 ;; Maintain old links, if present
7280 (setq old-entry (assq (idlwave-sintern-sysvar var) old)) 7280 (setq old-entry (assq (idlwave-sintern-sysvar var) old))
7281 (setq link (assq 'link old-entry)) 7281 (setq link (assq 'link old-entry))
7282 (setq idlwave-system-variables-alist 7282 (setq idlwave-system-variables-alist
7283 (cons (list var 7283 (cons (list var
7284 (cons 7284 (cons
7285 'tags 7285 'tags
7286 (mapcar (lambda (x) 7286 (mapcar (lambda (x)
7287 (cons x 7287 (cons x
7288 (cdr (assq 7288 (cdr (assq
7289 (idlwave-sintern-sysvartag x) 7289 (idlwave-sintern-sysvartag x)
7290 (cdr (assq 'tags old-entry)))))) 7290 (cdr (assq 'tags old-entry))))))
7291 tags)) link) 7291 tags)) link)
7292 idlwave-system-variables-alist))) 7292 idlwave-system-variables-alist)))
7293 ;; Keep the old value if query was not successful 7293 ;; Keep the old value if query was not successful
7294 (setq idlwave-system-variables-alist 7294 (setq idlwave-system-variables-alist
7306 (put-text-property (match-beginning 0) (match-end 0) 7306 (put-text-property (match-beginning 0) (match-end 0)
7307 'face 'font-lock-string-face))))))) 7307 'face 'font-lock-string-face)))))))
7308 7308
7309 (defun idlwave-uniquify (list) 7309 (defun idlwave-uniquify (list)
7310 (let ((ht (make-hash-table :size (length list) :test 'equal))) 7310 (let ((ht (make-hash-table :size (length list) :test 'equal)))
7311 (delq nil 7311 (delq nil
7312 (mapcar (lambda (x) 7312 (mapcar (lambda (x)
7313 (unless (gethash x ht) 7313 (unless (gethash x ht)
7314 (puthash x t ht) 7314 (puthash x t ht)
7315 x)) 7315 x))
7316 list)))) 7316 list))))
7317 7317
7318 (defun idlwave-after-successful-completion (type slash &optional verify) 7318 (defun idlwave-after-successful-completion (type slash &optional verify)
7336 (not slash)) 7336 (not slash))
7337 (progn (insert "=") t) 7337 (progn (insert "=") t)
7338 nil))) 7338 nil)))
7339 7339
7340 ;; Restore the pre-completion window configuration if this is safe. 7340 ;; Restore the pre-completion window configuration if this is safe.
7341 7341
7342 (if (or (eq verify 'force) ; force 7342 (if (or (eq verify 'force) ; force
7343 (and 7343 (and
7344 (get-buffer-window "*Completions*") ; visible 7344 (get-buffer-window "*Completions*") ; visible
7345 (idlwave-local-value 'idlwave-completion-p 7345 (idlwave-local-value 'idlwave-completion-p
7346 "*Completions*") ; cib-buffer 7346 "*Completions*") ; cib-buffer
7347 (eq (marker-buffer idlwave-completion-mark) 7347 (eq (marker-buffer idlwave-completion-mark)
7348 (current-buffer)) ; buffer OK 7348 (current-buffer)) ; buffer OK
7349 (equal (marker-position idlwave-completion-mark) 7349 (equal (marker-position idlwave-completion-mark)
7350 verify))) ; pos OK 7350 verify))) ; pos OK
7438 (kwd "") 7438 (kwd "")
7439 class) 7439 class)
7440 (if (string-match "\\(pro\\|function\\)[ \t]+\\(\\(.*\\)::\\)?\\(.*\\)" 7440 (if (string-match "\\(pro\\|function\\)[ \t]+\\(\\(.*\\)::\\)?\\(.*\\)"
7441 resolve) 7441 resolve)
7442 (setq type (match-string 1 resolve) 7442 (setq type (match-string 1 resolve)
7443 class (if (match-beginning 2) 7443 class (if (match-beginning 2)
7444 (match-string 3 resolve) 7444 (match-string 3 resolve)
7445 nil) 7445 nil)
7446 name (match-string 4 resolve))) 7446 name (match-string 4 resolve)))
7447 (if (string= (downcase type) "function") 7447 (if (string= (downcase type) "function")
7448 (setq kwd ",/is_function")) 7448 (setq kwd ",/is_function"))
7449 7449
7450 (cond 7450 (cond
7451 ((null class) 7451 ((null class)
7452 (idlwave-shell-send-command 7452 (idlwave-shell-send-command
7453 (format "resolve_routine,'%s'%s" (downcase name) kwd) 7453 (format "resolve_routine,'%s'%s" (downcase name) kwd)
7454 'idlwave-update-routine-info 7454 'idlwave-update-routine-info
7455 nil t)) 7455 nil t))
7456 (t 7456 (t
7457 (idlwave-shell-send-command 7457 (idlwave-shell-send-command
7458 (format "resolve_routine,'%s__define'%s" (downcase class) kwd) 7458 (format "resolve_routine,'%s__define'%s" (downcase class) kwd)
7459 (list 'idlwave-shell-send-command 7459 (list 'idlwave-shell-send-command
7460 (format "resolve_routine,'%s__%s'%s" 7460 (format "resolve_routine,'%s__%s'%s"
7461 (downcase class) (downcase name) kwd) 7461 (downcase class) (downcase name) kwd)
7462 '(idlwave-update-routine-info) 7462 '(idlwave-update-routine-info)
7463 nil t)))))) 7463 nil t))))))
7464 7464
7465 (defun idlwave-find-module (&optional arg) 7465 (defun idlwave-find-module (&optional arg)
7472 (let* ((idlwave-query-class nil) 7472 (let* ((idlwave-query-class nil)
7473 (idlwave-force-class-query (equal arg '(16))) 7473 (idlwave-force-class-query (equal arg '(16)))
7474 (this-buffer (equal arg '(4))) 7474 (this-buffer (equal arg '(4)))
7475 (module (idlwave-fix-module-if-obj_new (idlwave-what-module))) 7475 (module (idlwave-fix-module-if-obj_new (idlwave-what-module)))
7476 (default (if module 7476 (default (if module
7477 (concat (idlwave-make-full-name 7477 (concat (idlwave-make-full-name
7478 (nth 2 module) (car module)) 7478 (nth 2 module) (car module))
7479 (if (eq (nth 1 module) 'pro) "<p>" "<f>")) 7479 (if (eq (nth 1 module) 'pro) "<p>" "<f>"))
7480 "none")) 7480 "none"))
7481 (list 7481 (list
7482 (idlwave-uniquify 7482 (idlwave-uniquify
7483 (delq nil 7483 (delq nil
7484 (mapcar (lambda (x) 7484 (mapcar (lambda (x)
7485 (if (eq 'system (car-safe (nth 3 x))) 7485 (if (eq 'system (car-safe (nth 3 x)))
7486 ;; Take out system routines with no source. 7486 ;; Take out system routines with no source.
7487 nil 7487 nil
7488 (list 7488 (list
7489 (concat (idlwave-make-full-name 7489 (concat (idlwave-make-full-name
7490 (nth 2 x) (car x)) 7490 (nth 2 x) (car x))
7491 (if (eq (nth 1 x) 'pro) "<p>" "<f>"))))) 7491 (if (eq (nth 1 x) 'pro) "<p>" "<f>")))))
7492 (if this-buffer 7492 (if this-buffer
7493 (idlwave-save-buffer-update) 7493 (idlwave-save-buffer-update)
7494 (idlwave-routines)))))) 7494 (idlwave-routines))))))
7513 type (cond ((equal type "f") 'fun) 7513 type (cond ((equal type "f") 'fun)
7514 ((equal type "p") 'pro) 7514 ((equal type "p") 'pro)
7515 (t t))) 7515 (t t)))
7516 (idlwave-do-find-module name type class nil this-buffer))) 7516 (idlwave-do-find-module name type class nil this-buffer)))
7517 7517
7518 (defun idlwave-do-find-module (name type class 7518 (defun idlwave-do-find-module (name type class
7519 &optional force-source this-buffer) 7519 &optional force-source this-buffer)
7520 (let ((name1 (idlwave-make-full-name class name)) 7520 (let ((name1 (idlwave-make-full-name class name))
7521 source buf1 entry 7521 source buf1 entry
7522 (buf (current-buffer)) 7522 (buf (current-buffer))
7523 (pos (point)) 7523 (pos (point))
7524 file name2) 7524 file name2)
7525 (setq entry (idlwave-best-rinfo-assq name type class (idlwave-routines) 7525 (setq entry (idlwave-best-rinfo-assq name type class (idlwave-routines)
7526 'WITH-FILE) 7526 'WITH-FILE)
7527 source (or force-source (nth 3 entry)) 7527 source (or force-source (nth 3 entry))
7528 name2 (if (nth 2 entry) 7528 name2 (if (nth 2 entry)
7529 (idlwave-make-full-name (nth 2 entry) name) 7529 (idlwave-make-full-name (nth 2 entry) name)
7530 name1)) 7530 name1))
7531 (if source 7531 (if source
7532 (setq file (idlwave-routine-source-file source))) 7532 (setq file (idlwave-routine-source-file source)))
7533 (unless file ; Try to find it on the path. 7533 (unless file ; Try to find it on the path.
7534 (setq file 7534 (setq file
7535 (idlwave-expand-lib-file-name 7535 (idlwave-expand-lib-file-name
7536 (if class 7536 (if class
7537 (format "%s__define.pro" (downcase class)) 7537 (format "%s__define.pro" (downcase class))
7538 (format "%s.pro" (downcase name)))))) 7538 (format "%s.pro" (downcase name))))))
7539 (cond 7539 (cond
7540 ((or (null name) (equal name "")) 7540 ((or (null name) (equal name ""))
7541 (error "Abort")) 7541 (error "Abort"))
7542 ((eq (car source) 'system) 7542 ((eq (car source) 'system)
7543 (error "Source code for system routine %s is not available" 7543 (error "Source code for system routine %s is not available"
7544 name2)) 7544 name2))
7545 ((or (not file) (not (file-regular-p file))) 7545 ((or (not file) (not (file-regular-p file)))
7546 (error "Source code for routine %s is not available" 7546 (error "Source code for routine %s is not available"
7547 name2)) 7547 name2))
7548 (t 7548 (t
7549 (when (not this-buffer) 7549 (when (not this-buffer)
7550 (setq buf1 7550 (setq buf1
7551 (idlwave-find-file-noselect file 'find)) 7551 (idlwave-find-file-noselect file 'find))
7552 (pop-to-buffer buf1 t)) 7552 (pop-to-buffer buf1 t))
7553 (goto-char (point-max)) 7553 (goto-char (point-max))
7554 (let ((case-fold-search t)) 7554 (let ((case-fold-search t))
7555 (if (re-search-backward 7555 (if (re-search-backward
7556 (concat "^[ \t]*\\<" 7556 (concat "^[ \t]*\\<"
7557 (cond ((eq type 'fun) "function") 7557 (cond ((eq type 'fun) "function")
7558 ((eq type 'pro) "pro") 7558 ((eq type 'pro) "pro")
7559 (t "\\(pro\\|function\\)")) 7559 (t "\\(pro\\|function\\)"))
7560 "\\>[ \t]+" 7560 "\\>[ \t]+"
7561 (regexp-quote (downcase name2)) 7561 (regexp-quote (downcase name2))
7562 "[^a-zA-Z0-9_$]") 7562 "[^a-zA-Z0-9_$]")
7563 nil t) 7563 nil t)
7564 (goto-char (match-beginning 0)) 7564 (goto-char (match-beginning 0))
7565 (pop-to-buffer buf) 7565 (pop-to-buffer buf)
7592 (following-char))) 7592 (following-char)))
7593 ) 7593 )
7594 (cond 7594 (cond
7595 ((and (eq cw 'procedure) 7595 ((and (eq cw 'procedure)
7596 (not (equal this-word ""))) 7596 (not (equal this-word "")))
7597 (setq this-word (idlwave-sintern-routine-or-method 7597 (setq this-word (idlwave-sintern-routine-or-method
7598 this-word (nth 2 (nth 3 where)))) 7598 this-word (nth 2 (nth 3 where))))
7599 (list this-word 'pro 7599 (list this-word 'pro
7600 (idlwave-determine-class 7600 (idlwave-determine-class
7601 (cons this-word (cdr (nth 3 where))) 7601 (cons this-word (cdr (nth 3 where)))
7602 'pro))) 7602 'pro)))
7603 ((and (eq cw 'function) 7603 ((and (eq cw 'function)
7604 (not (equal this-word "")) 7604 (not (equal this-word ""))
7605 (or (eq next-char ?\() ; exclude arrays, vars. 7605 (or (eq next-char ?\() ; exclude arrays, vars.
7606 (looking-at "[a-zA-Z0-9_]*[ \t]*("))) 7606 (looking-at "[a-zA-Z0-9_]*[ \t]*(")))
7607 (setq this-word (idlwave-sintern-routine-or-method 7607 (setq this-word (idlwave-sintern-routine-or-method
7608 this-word (nth 2 (nth 3 where)))) 7608 this-word (nth 2 (nth 3 where))))
7609 (list this-word 'fun 7609 (list this-word 'fun
7610 (idlwave-determine-class 7610 (idlwave-determine-class
7611 (cons this-word (cdr (nth 3 where))) 7611 (cons this-word (cdr (nth 3 where)))
7612 'fun))) 7612 'fun)))
7639 (if entry 7639 (if entry
7640 (nth 2 entry) 7640 (nth 2 entry)
7641 class))) 7641 class)))
7642 7642
7643 (defun idlwave-fix-module-if-obj_new (module) 7643 (defun idlwave-fix-module-if-obj_new (module)
7644 "Check if MODULE points to obj_new. 7644 "Check if MODULE points to obj_new.
7645 If yes, and if the cursor is in the keyword region, change to the 7645 If yes, and if the cursor is in the keyword region, change to the
7646 appropriate Init method." 7646 appropriate Init method."
7647 (let* ((name (car module)) 7647 (let* ((name (car module))
7648 (pos (point)) 7648 (pos (point))
7649 (case-fold-search t) 7649 (case-fold-search t)
7679 class) 7679 class)
7680 (and (string-match "obj_new([^'\"]*['\"]\\([a-zA-Z0-9_]+\\)" 7680 (and (string-match "obj_new([^'\"]*['\"]\\([a-zA-Z0-9_]+\\)"
7681 string) 7681 string)
7682 (setq class (idlwave-sintern-class (match-string 1 string))) 7682 (setq class (idlwave-sintern-class (match-string 1 string)))
7683 (setq idlwave-current-obj_new-class class) 7683 (setq idlwave-current-obj_new-class class)
7684 (setq keywords 7684 (setq keywords
7685 (append keywords 7685 (append keywords
7686 (idlwave-entry-keywords 7686 (idlwave-entry-keywords
7687 (idlwave-rinfo-assq 7687 (idlwave-rinfo-assq
7688 (idlwave-sintern-method "INIT") 7688 (idlwave-sintern-method "INIT")
7689 'fun 7689 'fun
7690 class 7690 class
7691 (idlwave-routines)) 'do-link)))))) 7691 (idlwave-routines)) 'do-link))))))
7692 7692
7693 ;; If the class is `t', combine all keywords of all methods NAME 7693 ;; If the class is `t', combine all keywords of all methods NAME
7694 (when (eq class t) 7694 (when (eq class t)
7695 (mapc (lambda (entry) 7695 (mapc (lambda (entry)
7696 (and 7696 (and
7697 (nth 2 entry) ; non-nil class 7697 (nth 2 entry) ; non-nil class
7698 (eq (nth 1 entry) type) ; correct type 7698 (eq (nth 1 entry) type) ; correct type
7699 (setq keywords 7699 (setq keywords
7700 (append keywords 7700 (append keywords
7701 (idlwave-entry-keywords entry 'do-link))))) 7701 (idlwave-entry-keywords entry 'do-link)))))
7702 (idlwave-all-assq name (idlwave-routines))) 7702 (idlwave-all-assq name (idlwave-routines)))
7703 (setq keywords (idlwave-uniquify keywords))) 7703 (setq keywords (idlwave-uniquify keywords)))
7704 7704
7705 ;; If we have inheritance, add all keywords from superclasses, if 7705 ;; If we have inheritance, add all keywords from superclasses, if
7706 ;; the user indicated that method in `idlwave-keyword-class-inheritance' 7706 ;; the user indicated that method in `idlwave-keyword-class-inheritance'
7707 (when (and 7707 (when (and
7708 super-classes 7708 super-classes
7709 idlwave-keyword-class-inheritance 7709 idlwave-keyword-class-inheritance
7710 (stringp class) 7710 (stringp class)
7711 (or (assq (idlwave-sintern-keyword "_extra") keywords) 7711 (or (assq (idlwave-sintern-keyword "_extra") keywords)
7712 (assq (idlwave-sintern-keyword "_ref_extra") keywords)) 7712 (assq (idlwave-sintern-keyword "_ref_extra") keywords))
7722 (eq (nth 1 entry) type) ; correct type 7722 (eq (nth 1 entry) type) ; correct type
7723 (eq (car entry) name) ; correct name 7723 (eq (car entry) name) ; correct name
7724 (mapcar (lambda (k) (add-to-list 'keywords k)) 7724 (mapcar (lambda (k) (add-to-list 'keywords k))
7725 (idlwave-entry-keywords entry 'do-link)))) 7725 (idlwave-entry-keywords entry 'do-link))))
7726 (setq keywords (idlwave-uniquify keywords))) 7726 (setq keywords (idlwave-uniquify keywords)))
7727 7727
7728 ;; Return the final list 7728 ;; Return the final list
7729 keywords)) 7729 keywords))
7730 7730
7731 (defun idlwave-expand-keyword (keyword module) 7731 (defun idlwave-expand-keyword (keyword module)
7732 "Expand KEYWORD to one of the valid keyword parameters of MODULE. 7732 "Expand KEYWORD to one of the valid keyword parameters of MODULE.
7747 (kwd-alist (idlwave-entry-keywords entry)) 7747 (kwd-alist (idlwave-entry-keywords entry))
7748 (extra (or (assq (idlwave-sintern-keyword "_EXTRA") kwd-alist) 7748 (extra (or (assq (idlwave-sintern-keyword "_EXTRA") kwd-alist)
7749 (assq (idlwave-sintern-keyword "_REF_EXTRA") kwd-alist))) 7749 (assq (idlwave-sintern-keyword "_REF_EXTRA") kwd-alist)))
7750 (completion-ignore-case t) 7750 (completion-ignore-case t)
7751 candidates) 7751 candidates)
7752 (cond ((assq kwd kwd-alist) 7752 (cond ((assq kwd kwd-alist)
7753 kwd) 7753 kwd)
7754 ((setq candidates (all-completions kwd kwd-alist)) 7754 ((setq candidates (all-completions kwd kwd-alist))
7755 (if (= (length candidates) 1) 7755 (if (= (length candidates) 1)
7756 (car candidates) 7756 (car candidates)
7757 candidates)) 7757 candidates))
7758 ((and entry extra) 7758 ((and entry extra)
7759 ;; Inheritance may cause this keyword to be correct 7759 ;; Inheritance may cause this keyword to be correct
7760 keyword) 7760 keyword)
7761 (entry 7761 (entry
7762 ;; We do know the function, which does not have the keyword. 7762 ;; We do know the function, which does not have the keyword.
7763 nil) 7763 nil)
7764 (t 7764 (t
7766 ;; keyword - return it as it is. 7766 ;; keyword - return it as it is.
7767 keyword)))) 7767 keyword))))
7768 7768
7769 (defvar idlwave-rinfo-mouse-map (make-sparse-keymap)) 7769 (defvar idlwave-rinfo-mouse-map (make-sparse-keymap))
7770 (defvar idlwave-rinfo-map (make-sparse-keymap)) 7770 (defvar idlwave-rinfo-map (make-sparse-keymap))
7771 (define-key idlwave-rinfo-mouse-map 7771 (define-key idlwave-rinfo-mouse-map
7772 (if (featurep 'xemacs) [button2] [mouse-2]) 7772 (if (featurep 'xemacs) [button2] [mouse-2])
7773 'idlwave-mouse-active-rinfo) 7773 'idlwave-mouse-active-rinfo)
7774 (define-key idlwave-rinfo-mouse-map 7774 (define-key idlwave-rinfo-mouse-map
7775 (if (featurep 'xemacs) [(shift button2)] [(shift mouse-2)]) 7775 (if (featurep 'xemacs) [(shift button2)] [(shift mouse-2)])
7776 'idlwave-mouse-active-rinfo-shift) 7776 'idlwave-mouse-active-rinfo-shift)
7777 (define-key idlwave-rinfo-mouse-map 7777 (define-key idlwave-rinfo-mouse-map
7778 (if (featurep 'xemacs) [button3] [mouse-3]) 7778 (if (featurep 'xemacs) [button3] [mouse-3])
7779 'idlwave-mouse-active-rinfo-right) 7779 'idlwave-mouse-active-rinfo-right)
7780 (define-key idlwave-rinfo-mouse-map " " 'idlwave-active-rinfo-space) 7780 (define-key idlwave-rinfo-mouse-map " " 'idlwave-active-rinfo-space)
7781 (define-key idlwave-rinfo-map "q" 'idlwave-quit-help) 7781 (define-key idlwave-rinfo-map "q" 'idlwave-quit-help)
7782 (define-key idlwave-rinfo-mouse-map "q" 'idlwave-quit-help) 7782 (define-key idlwave-rinfo-mouse-map "q" 'idlwave-quit-help)
7798 &optional initial-class) 7798 &optional initial-class)
7799 ;; Display the calling sequence of module NAME, type TYPE in class CLASS. 7799 ;; Display the calling sequence of module NAME, type TYPE in class CLASS.
7800 (let* ((initial-class (or initial-class class)) 7800 (let* ((initial-class (or initial-class class))
7801 (entry (or (idlwave-best-rinfo-assq name type class 7801 (entry (or (idlwave-best-rinfo-assq name type class
7802 (idlwave-routines)) 7802 (idlwave-routines))
7803 (idlwave-rinfo-assq name type class 7803 (idlwave-rinfo-assq name type class
7804 idlwave-unresolved-routines))) 7804 idlwave-unresolved-routines)))
7805 (name (or (car entry) name)) 7805 (name (or (car entry) name))
7806 (class (or (nth 2 entry) class)) 7806 (class (or (nth 2 entry) class))
7807 (superclasses (idlwave-all-class-inherits initial-class)) 7807 (superclasses (idlwave-all-class-inherits initial-class))
7808 (twins (idlwave-routine-twins entry)) 7808 (twins (idlwave-routine-twins entry))
7823 (col 0) 7823 (col 0)
7824 (data (list name type class (current-buffer) nil initial-class)) 7824 (data (list name type class (current-buffer) nil initial-class))
7825 (km-prop (if (featurep 'xemacs) 'keymap 'local-map)) 7825 (km-prop (if (featurep 'xemacs) 'keymap 'local-map))
7826 (face 'idlwave-help-link-face) 7826 (face 'idlwave-help-link-face)
7827 beg props win cnt total) 7827 beg props win cnt total)
7828 ;; Fix keywords, but don't add chained super-classes, since these 7828 ;; Fix keywords, but don't add chained super-classes, since these
7829 ;; are shown separately for that super-class 7829 ;; are shown separately for that super-class
7830 (setq keywords (idlwave-fix-keywords name type class keywords)) 7830 (setq keywords (idlwave-fix-keywords name type class keywords))
7831 (cond 7831 (cond
7832 ((null entry) 7832 ((null entry)
7833 (error "No %s %s known %s" type name 7833 (error "No %s %s known %s" type name
7865 (insert "\n"))) 7865 (insert "\n")))
7866 (setq props (list 'mouse-face 'highlight 7866 (setq props (list 'mouse-face 'highlight
7867 km-prop idlwave-rinfo-mouse-map 7867 km-prop idlwave-rinfo-mouse-map
7868 'help-echo help-echo-use 7868 'help-echo help-echo-use
7869 'data (cons 'usage data))) 7869 'data (cons 'usage data)))
7870 (if html-file (setq props (append (list 'face face 'link html-file) 7870 (if html-file (setq props (append (list 'face face 'link html-file)
7871 props))) 7871 props)))
7872 (insert "Usage: ") 7872 (insert "Usage: ")
7873 (setq beg (point)) 7873 (setq beg (point))
7874 (insert (if class 7874 (insert (if class
7875 (format calling-seq class name class name class name) 7875 (format calling-seq class name class name class name)
7876 (format calling-seq name name name name)) 7876 (format calling-seq name name name name))
7877 "\n") 7877 "\n")
7878 (add-text-properties beg (point) props) 7878 (add-text-properties beg (point) props)
7879 7879
7880 (insert "Keywords:") 7880 (insert "Keywords:")
7881 (if (null keywords) 7881 (if (null keywords)
7882 (insert " No keywords accepted.") 7882 (insert " No keywords accepted.")
7883 (setq col 9) 7883 (setq col 9)
7884 (mapcar 7884 (mapcar
7885 (lambda (x) 7885 (lambda (x)
7886 (if (>= (+ col 1 (length (car x))) 7886 (if (>= (+ col 1 (length (car x)))
7887 (window-width)) 7887 (window-width))
7888 (progn 7888 (progn
7889 (insert "\n ") 7889 (insert "\n ")
7890 (setq col 9))) 7890 (setq col 9)))
7891 (insert " ") 7891 (insert " ")
7899 (if system (setq props (append (list 'face face) props))) 7899 (if system (setq props (append (list 'face face) props)))
7900 (insert (car x)) 7900 (insert (car x))
7901 (add-text-properties beg (point) props) 7901 (add-text-properties beg (point) props)
7902 (setq col (+ col 1 (length (car x))))) 7902 (setq col (+ col 1 (length (car x)))))
7903 keywords)) 7903 keywords))
7904 7904
7905 (setq cnt 1 total (length all)) 7905 (setq cnt 1 total (length all))
7906 ;; Here entry is (key file (list of type-conses)) 7906 ;; Here entry is (key file (list of type-conses))
7907 (while (setq entry (pop all)) 7907 (while (setq entry (pop all))
7908 (setq props (list 'mouse-face 'highlight 7908 (setq props (list 'mouse-face 'highlight
7909 km-prop idlwave-rinfo-mouse-map 7909 km-prop idlwave-rinfo-mouse-map
7912 (nth 1 entry) 7912 (nth 1 entry)
7913 nil 7913 nil
7914 (cdr (car (nth 2 entry)))) 7914 (cdr (car (nth 2 entry))))
7915 'data (cons 'source data))) 7915 'data (cons 'source data)))
7916 (idlwave-insert-source-location 7916 (idlwave-insert-source-location
7917 (format "\n%-8s %s" 7917 (format "\n%-8s %s"
7918 (if (equal cnt 1) 7918 (if (equal cnt 1)
7919 (if (> total 1) "Sources:" "Source:") 7919 (if (> total 1) "Sources:" "Source:")
7920 "") 7920 "")
7921 (if (> total 1) "- " "")) 7921 (if (> total 1) "- " ""))
7922 entry props) 7922 entry props)
7923 (incf cnt) 7923 (incf cnt)
7924 (when (and all (> cnt idlwave-rinfo-max-source-lines)) 7924 (when (and all (> cnt idlwave-rinfo-max-source-lines))
7925 ;; No more source lines, please 7925 ;; No more source lines, please
7926 (insert (format 7926 (insert (format
7927 "\n Source information truncated to %d entries." 7927 "\n Source information truncated to %d entries."
7928 idlwave-rinfo-max-source-lines)) 7928 idlwave-rinfo-max-source-lines))
7929 (setq all nil))) 7929 (setq all nil)))
7930 (goto-char (point-min)) 7930 (goto-char (point-min))
7931 (setq buffer-read-only t)) 7931 (setq buffer-read-only t))
7935 (progn 7935 (progn
7936 (let ((ww (selected-window))) 7936 (let ((ww (selected-window)))
7937 (unwind-protect 7937 (unwind-protect
7938 (progn 7938 (progn
7939 (select-window win) 7939 (select-window win)
7940 (enlarge-window (- (/ (frame-height) 2) 7940 (enlarge-window (- (/ (frame-height) 2)
7941 (window-height))) 7941 (window-height)))
7942 (shrink-window-if-larger-than-buffer)) 7942 (shrink-window-if-larger-than-buffer))
7943 (select-window ww))))))))) 7943 (select-window ww)))))))))
7944 7944
7945 (defun idlwave-insert-source-location (prefix entry &optional file-props) 7945 (defun idlwave-insert-source-location (prefix entry &optional file-props)
7972 (insert "Builtin ")) 7972 (insert "Builtin "))
7973 7973
7974 ((and (not file) shell-flag) 7974 ((and (not file) shell-flag)
7975 (insert "Unresolved")) 7975 (insert "Unresolved"))
7976 7976
7977 ((null file) 7977 ((null file)
7978 (insert "ERROR")) 7978 (insert "ERROR"))
7979 7979
7980 ((idlwave-syslib-p file) 7980 ((idlwave-syslib-p file)
7981 (if (string-match "obsolete" (file-name-directory file)) 7981 (if (string-match "obsolete" (file-name-directory file))
7982 (insert "Obsolete ") 7982 (insert "Obsolete ")
7983 (insert "SystemLib "))) 7983 (insert "SystemLib ")))
7984 7984
7988 (insert (format "%-10s" special))) 7988 (insert (format "%-10s" special)))
7989 7989
7990 ;; Old special syntax: a matching regexp 7990 ;; Old special syntax: a matching regexp
7991 ((setq special (idlwave-special-lib-test file)) 7991 ((setq special (idlwave-special-lib-test file))
7992 (insert (format "%-10s" special))) 7992 (insert (format "%-10s" special)))
7993 7993
7994 ;; Catch-all with file 7994 ;; Catch-all with file
7995 ((idlwave-lib-p file) (insert "Library ")) 7995 ((idlwave-lib-p file) (insert "Library "))
7996 7996
7997 ;; Sanity catch all 7997 ;; Sanity catch all
7998 (t (insert "Other "))) 7998 (t (insert "Other ")))
8003 (if lib-flag "L" "-") 8003 (if lib-flag "L" "-")
8004 (if user-flag "C" "-") 8004 (if user-flag "C" "-")
8005 (if shell-flag "S" "-") 8005 (if shell-flag "S" "-")
8006 (if buffer-flag "B" "-") 8006 (if buffer-flag "B" "-")
8007 "] "))) 8007 "] ")))
8008 (when (> ndupl 1) 8008 (when (> ndupl 1)
8009 (setq beg (point)) 8009 (setq beg (point))
8010 (insert (format "(%dx) " ndupl)) 8010 (insert (format "(%dx) " ndupl))
8011 (add-text-properties beg (point) (list 'face 'bold))) 8011 (add-text-properties beg (point) (list 'face 'bold)))
8012 (when (and file (not (equal file ""))) 8012 (when (and file (not (equal file "")))
8013 (setq beg (point)) 8013 (setq beg (point))
8027 (if (string-match (car entry) file) 8027 (if (string-match (car entry) file)
8028 (setq rtn (cdr entry) 8028 (setq rtn (cdr entry)
8029 alist nil))) 8029 alist nil)))
8030 rtn) 8030 rtn)
8031 (t nil)))) 8031 (t nil))))
8032 8032
8033 (defun idlwave-mouse-active-rinfo-right (ev) 8033 (defun idlwave-mouse-active-rinfo-right (ev)
8034 (interactive "e") 8034 (interactive "e")
8035 (idlwave-mouse-active-rinfo ev 'right)) 8035 (idlwave-mouse-active-rinfo ev 'right))
8036 8036
8037 (defun idlwave-mouse-active-rinfo-shift (ev) 8037 (defun idlwave-mouse-active-rinfo-shift (ev)
8060 word (idlwave-this-word) 8060 word (idlwave-this-word)
8061 bufwin (get-buffer-window buf t)) 8061 bufwin (get-buffer-window buf t))
8062 8062
8063 (cond ((eq id 'class) ; Switch class being displayed 8063 (cond ((eq id 'class) ; Switch class being displayed
8064 (if (window-live-p bufwin) (select-window bufwin)) 8064 (if (window-live-p bufwin) (select-window bufwin))
8065 (idlwave-display-calling-sequence 8065 (idlwave-display-calling-sequence
8066 (idlwave-sintern-method name) 8066 (idlwave-sintern-method name)
8067 type (idlwave-sintern-class word) 8067 type (idlwave-sintern-class word)
8068 initial-class)) 8068 initial-class))
8069 ((eq id 'usage) ; Online help on this routine 8069 ((eq id 'usage) ; Online help on this routine
8070 (idlwave-online-help link name type class)) 8070 (idlwave-online-help link name type class))
8071 ((eq id 'source) ; Source in help or buffer 8071 ((eq id 'source) ; Source in help or buffer
8072 (if right ; In help 8072 (if right ; In help
8103 (select-window bwin) 8103 (select-window bwin)
8104 (pop-to-buffer buffer) 8104 (pop-to-buffer buffer)
8105 (setq bwin (get-buffer-window buffer))) 8105 (setq bwin (get-buffer-window buffer)))
8106 (if (eq (preceding-char) ?/) 8106 (if (eq (preceding-char) ?/)
8107 (insert keyword) 8107 (insert keyword)
8108 (unless (save-excursion 8108 (unless (save-excursion
8109 (re-search-backward 8109 (re-search-backward
8110 "[(,][ \t]*\\(\\$[ \t]*\\(;.*\\)?\n\\)?[ \t]*\\=" 8110 "[(,][ \t]*\\(\\$[ \t]*\\(;.*\\)?\n\\)?[ \t]*\\="
8111 (min (- (point) 100) (point-min)) t)) 8111 (min (- (point) 100) (point-min)) t))
8112 (insert ", ")) 8112 (insert ", "))
8113 (if shift (insert "/")) 8113 (if shift (insert "/"))
8114 (insert keyword) 8114 (insert keyword)
8115 (if (and (not shift) 8115 (if (and (not shift)
8157 When IDL hits a routine call which is not defined, it will search on 8157 When IDL hits a routine call which is not defined, it will search on
8158 the load path in order to find a definition. The output of this 8158 the load path in order to find a definition. The output of this
8159 command can be used to detect possible name clashes during this process." 8159 command can be used to detect possible name clashes during this process."
8160 (idlwave-routines) ; Make sure everything is loaded. 8160 (idlwave-routines) ; Make sure everything is loaded.
8161 (unless (or idlwave-user-catalog-routines idlwave-library-catalog-routines) 8161 (unless (or idlwave-user-catalog-routines idlwave-library-catalog-routines)
8162 (or (y-or-n-p 8162 (or (y-or-n-p
8163 "You don't have any user or library catalogs. Continue anyway? ") 8163 "You don't have any user or library catalogs. Continue anyway? ")
8164 (error "Abort"))) 8164 (error "Abort")))
8165 (let* ((routines (append idlwave-system-routines 8165 (let* ((routines (append idlwave-system-routines
8166 idlwave-compiled-routines 8166 idlwave-compiled-routines
8167 idlwave-library-catalog-routines 8167 idlwave-library-catalog-routines
8170 nil)) 8170 nil))
8171 (km-prop (if (featurep 'xemacs) 'keymap 'local-map)) 8171 (km-prop (if (featurep 'xemacs) 'keymap 'local-map))
8172 (keymap (make-sparse-keymap)) 8172 (keymap (make-sparse-keymap))
8173 (props (list 'mouse-face 'highlight 8173 (props (list 'mouse-face 'highlight
8174 km-prop keymap 8174 km-prop keymap
8175 'help-echo "Mouse2: Find source")) 8175 'help-echo "Mouse2: Find source"))
8176 (nroutines (length (or special-routines routines))) 8176 (nroutines (length (or special-routines routines)))
8177 (step (/ nroutines 99)) 8177 (step (/ nroutines 99))
8178 (n 0) 8178 (n 0)
8179 (next-perc 1) 8179 (next-perc 1)
8180 (cnt 0) 8180 (cnt 0)
8194 (downcase (idlwave-make-full-name 8194 (downcase (idlwave-make-full-name
8195 (nth 2 b) (car b))))))) 8195 (nth 2 b) (car b)))))))
8196 (message "Sorting routines...done") 8196 (message "Sorting routines...done")
8197 8197
8198 (define-key keymap (if (featurep 'xemacs) [(button2)] [(mouse-2)]) 8198 (define-key keymap (if (featurep 'xemacs) [(button2)] [(mouse-2)])
8199 (lambda (ev) 8199 (lambda (ev)
8200 (interactive "e") 8200 (interactive "e")
8201 (mouse-set-point ev) 8201 (mouse-set-point ev)
8202 (apply 'idlwave-do-find-module 8202 (apply 'idlwave-do-find-module
8203 (get-text-property (point) 'find-args)))) 8203 (get-text-property (point) 'find-args))))
8204 (define-key keymap [(return)] 8204 (define-key keymap [(return)]
8205 (lambda () 8205 (lambda ()
8206 (interactive) 8206 (interactive)
8207 (apply 'idlwave-do-find-module 8207 (apply 'idlwave-do-find-module
8208 (get-text-property (point) 'find-args)))) 8208 (get-text-property (point) 'find-args))))
8209 (message "Compiling list...( 0%%)") 8209 (message "Compiling list...( 0%%)")
8210 (save-excursion 8210 (save-excursion
8228 (> (idlwave-count-memq 'lib (nth 2 (car dtwins))) 1) 8228 (> (idlwave-count-memq 'lib (nth 2 (car dtwins))) 1)
8229 (> (idlwave-count-memq 'user (nth 2 (car dtwins))) 1) 8229 (> (idlwave-count-memq 'user (nth 2 (car dtwins))) 1)
8230 (> (idlwave-count-memq 'buffer (nth 2 (car dtwins))) 1)) 8230 (> (idlwave-count-memq 'buffer (nth 2 (car dtwins))) 1))
8231 (incf cnt) 8231 (incf cnt)
8232 (insert (format "\n%s%s" 8232 (insert (format "\n%s%s"
8233 (idlwave-make-full-name (nth 2 routine) 8233 (idlwave-make-full-name (nth 2 routine)
8234 (car routine)) 8234 (car routine))
8235 (if (eq (nth 1 routine) 'fun) "()" ""))) 8235 (if (eq (nth 1 routine) 'fun) "()" "")))
8236 (while (setq twin (pop dtwins)) 8236 (while (setq twin (pop dtwins))
8237 (setq props1 (append (list 'find-args 8237 (setq props1 (append (list 'find-args
8238 (list (nth 0 routine) 8238 (list (nth 0 routine)
8239 (nth 1 routine) 8239 (nth 1 routine)
8240 (nth 2 routine))) 8240 (nth 2 routine)))
8241 props)) 8241 props))
8242 (idlwave-insert-source-location "\n - " twin props1)))) 8242 (idlwave-insert-source-location "\n - " twin props1))))
8243 (goto-char (point-min)) 8243 (goto-char (point-min))
8244 (setq buffer-read-only t)) 8244 (setq buffer-read-only t))
8257 (if (idlwave-syslib-p sfile) (setq stype 'syslib)) 8257 (if (idlwave-syslib-p sfile) (setq stype 'syslib))
8258 (if (and (eq stype 'compiled) 8258 (if (and (eq stype 'compiled)
8259 (or (not (stringp sfile)) 8259 (or (not (stringp sfile))
8260 (not (string-match "\\S-" sfile)))) 8260 (not (string-match "\\S-" sfile))))
8261 (setq stype 'unresolved)) 8261 (setq stype 'unresolved))
8262 (princ (format " %-10s %s\n" 8262 (princ (format " %-10s %s\n"
8263 stype 8263 stype
8264 (if sfile sfile "No source code available"))))) 8264 (if sfile sfile "No source code available")))))
8265 8265
8266 (defun idlwave-routine-twins (entry &optional list) 8266 (defun idlwave-routine-twins (entry &optional list)
8267 "Return all twin entries of ENTRY in LIST. 8267 "Return all twin entries of ENTRY in LIST.
8276 (while (setq candidate (pop candidates)) 8276 (while (setq candidate (pop candidates))
8277 (if (and (not (eq candidate entry)) 8277 (if (and (not (eq candidate entry))
8278 (eq type (nth 1 candidate)) 8278 (eq type (nth 1 candidate))
8279 (eq class (nth 2 candidate))) 8279 (eq class (nth 2 candidate)))
8280 (push candidate twins))) 8280 (push candidate twins)))
8281 (if (setq candidate (idlwave-rinfo-assq name type class 8281 (if (setq candidate (idlwave-rinfo-assq name type class
8282 idlwave-unresolved-routines)) 8282 idlwave-unresolved-routines))
8283 (push candidate twins)) 8283 (push candidate twins))
8284 (cons entry (nreverse twins)))) 8284 (cons entry (nreverse twins))))
8285 8285
8286 (defun idlwave-study-twins (entries) 8286 (defun idlwave-study-twins (entries)
8287 "Return dangerous twins of first entry in ENTRIES. 8287 "Return dangerous twins of first entry in ENTRIES.
8288 Dangerous twins are routines with same name, but in different files on 8288 Dangerous twins are routines with same name, but in different files on
8289 the load path. If a file is in the system library and has an entry in 8289 the load path. If a file is in the system library and has an entry in
8290 the `idlwave-system-routines' list, we omit the latter as 8290 the `idlwave-system-routines' list, we omit the latter as
8291 non-dangerous because many IDL routines are implemented as library 8291 non-dangerous because many IDL routines are implemented as library
8292 routines, and may have been scanned." 8292 routines, and may have been scanned."
8293 (let* ((entry (car entries)) 8293 (let* ((entry (car entries))
8294 (name (car entry)) ; 8294 (name (car entry)) ;
8295 (type (nth 1 entry)) ; Must be bound for 8295 (type (nth 1 entry)) ; Must be bound for
8296 (class (nth 2 entry)) ; idlwave-routine-twin-compare 8296 (class (nth 2 entry)) ; idlwave-routine-twin-compare
8297 (cnt 0) 8297 (cnt 0)
8298 source type type-cons file alist syslibp key) 8298 source type type-cons file alist syslibp key)
8299 (while (setq entry (pop entries)) 8299 (while (setq entry (pop entries))
8307 (setq key (cond ((eq type 'system) type) 8307 (setq key (cond ((eq type 'system) type)
8308 (file (file-truename file)) 8308 (file (file-truename file))
8309 (t 'unresolved))) 8309 (t 'unresolved)))
8310 8310
8311 ;; Check for an entry in the system library 8311 ;; Check for an entry in the system library
8312 (if (and file 8312 (if (and file
8313 (not syslibp) 8313 (not syslibp)
8314 (idlwave-syslib-p file)) 8314 (idlwave-syslib-p file))
8315 (setq syslibp t)) 8315 (setq syslibp t))
8316 8316
8317 ;; If there's more than one matching entry for the same file, just 8317 ;; If there's more than one matching entry for the same file, just
8318 ;; append the type-cons to the type list. 8318 ;; append the type-cons to the type list.
8319 (if (setq entry (assoc key alist)) 8319 (if (setq entry (assoc key alist))
8320 (push type-cons (nth 2 entry)) 8320 (push type-cons (nth 2 entry))
8321 (push (list key file (list type-cons)) alist))) 8321 (push (list key file (list type-cons)) alist)))
8322 8322
8323 (setq alist (nreverse alist)) 8323 (setq alist (nreverse alist))
8324 8324
8325 (when syslibp 8325 (when syslibp
8326 ;; File is in system *library* - remove any 'system entry 8326 ;; File is in system *library* - remove any 'system entry
8327 (setq alist (delq (assq 'system alist) alist))) 8327 (setq alist (delq (assq 'system alist) alist)))
8328 8328
8329 ;; If 'system remains and we've scanned the syslib, it's a builtin 8329 ;; If 'system remains and we've scanned the syslib, it's a builtin
8330 ;; (rather than a !DIR/lib/.pro file bundled as source). 8330 ;; (rather than a !DIR/lib/.pro file bundled as source).
8331 (when (and (idlwave-syslib-scanned-p) 8331 (when (and (idlwave-syslib-scanned-p)
8332 (setq entry (assoc 'system alist))) 8332 (setq entry (assoc 'system alist)))
8333 (setcar entry 'builtin)) 8333 (setcar entry 'builtin))
8360 ;; Name decides 8360 ;; Name decides
8361 (string< (downcase name) (downcase (car b)))) 8361 (string< (downcase name) (downcase (car b))))
8362 ((not (eq type (nth 1 b))) 8362 ((not (eq type (nth 1 b)))
8363 ;; Type decides 8363 ;; Type decides
8364 (< (if (eq type 'fun) 1 0) (if (eq (nth 1 b) 'fun) 1 0))) 8364 (< (if (eq type 'fun) 1 0) (if (eq (nth 1 b) 'fun) 1 0)))
8365 (t 8365 (t
8366 ;; A and B are twins - so the decision is more complicated. 8366 ;; A and B are twins - so the decision is more complicated.
8367 ;; Call twin-compare with the proper arguments. 8367 ;; Call twin-compare with the proper arguments.
8368 (idlwave-routine-entry-compare-twins a b))))) 8368 (idlwave-routine-entry-compare-twins a b)))))
8369 8369
8370 (defun idlwave-routine-entry-compare-twins (a b) 8370 (defun idlwave-routine-entry-compare-twins (a b)
8412 (bbufp (memq 'buffer btypes)) 8412 (bbufp (memq 'buffer btypes))
8413 ;; On search path? 8413 ;; On search path?
8414 (tpath-alist (idlwave-true-path-alist)) 8414 (tpath-alist (idlwave-true-path-alist))
8415 (apathp (and (stringp akey) 8415 (apathp (and (stringp akey)
8416 (assoc (file-name-directory akey) tpath-alist))) 8416 (assoc (file-name-directory akey) tpath-alist)))
8417 (bpathp (and (stringp bkey) 8417 (bpathp (and (stringp bkey)
8418 (assoc (file-name-directory bkey) tpath-alist))) 8418 (assoc (file-name-directory bkey) tpath-alist)))
8419 ;; How early on search path? High number means early since we 8419 ;; How early on search path? High number means early since we
8420 ;; measure the tail of the path list 8420 ;; measure the tail of the path list
8421 (anpath (length (memq apathp tpath-alist))) 8421 (anpath (length (memq apathp tpath-alist)))
8422 (bnpath (length (memq bpathp tpath-alist))) 8422 (bnpath (length (memq bpathp tpath-alist)))
8448 (idlwave-xor adefp bdefp)) bdefp) ; __define after __method 8448 (idlwave-xor adefp bdefp)) bdefp) ; __define after __method
8449 ((> anpath bnpath) t) ; Who is first on path? 8449 ((> anpath bnpath) t) ; Who is first on path?
8450 (t nil)))) ; Default 8450 (t nil)))) ; Default
8451 8451
8452 (defun idlwave-routine-source-file (source) 8452 (defun idlwave-routine-source-file (source)
8453 (if (nth 2 source) 8453 (if (nth 2 source)
8454 (expand-file-name (nth 1 source) (nth 2 source)) 8454 (expand-file-name (nth 1 source) (nth 2 source))
8455 (nth 1 source))) 8455 (nth 1 source)))
8456 8456
8457 (defun idlwave-downcase-safe (string) 8457 (defun idlwave-downcase-safe (string)
8458 "Donwcase if string, else return unchanged." 8458 "Donwcase if string, else return unchanged."
8538 Assumes that point is at the beginning of the unit as found by 8538 Assumes that point is at the beginning of the unit as found by
8539 `idlwave-prev-index-position'." 8539 `idlwave-prev-index-position'."
8540 (forward-sexp 2) 8540 (forward-sexp 2)
8541 (forward-sexp -1) 8541 (forward-sexp -1)
8542 (let ((begin (point))) 8542 (let ((begin (point)))
8543 (re-search-forward 8543 (re-search-forward
8544 "[a-zA-Z_][a-zA-Z0-9$_]+\\(::[a-zA-Z_][a-zA-Z0-9$_]+\\)?") 8544 "[a-zA-Z_][a-zA-Z0-9$_]+\\(::[a-zA-Z_][a-zA-Z0-9$_]+\\)?")
8545 (if (fboundp 'buffer-substring-no-properties) 8545 (if (fboundp 'buffer-substring-no-properties)
8546 (buffer-substring-no-properties begin (point)) 8546 (buffer-substring-no-properties begin (point))
8547 (buffer-substring begin (point))))) 8547 (buffer-substring begin (point)))))
8548 8548
8578 "Edit the current file in IDL Development environment." 8578 "Edit the current file in IDL Development environment."
8579 (interactive) 8579 (interactive)
8580 (start-process "idldeclient" nil 8580 (start-process "idldeclient" nil
8581 idlwave-shell-explicit-file-name "-c" "-e" 8581 idlwave-shell-explicit-file-name "-c" "-e"
8582 (buffer-file-name) "&")) 8582 (buffer-file-name) "&"))
8583 8583
8584 (defun idlwave-launch-idlhelp () 8584 (defun idlwave-launch-idlhelp ()
8585 "Start the IDLhelp application." 8585 "Start the IDLhelp application."
8586 (interactive) 8586 (interactive)
8587 (start-process "idlhelp" nil idlwave-help-application)) 8587 (start-process "idlhelp" nil idlwave-help-application))
8588 8588
8589 ;; Menus - using easymenu.el 8589 ;; Menus - using easymenu.el
8590 (defvar idlwave-mode-menu-def 8590 (defvar idlwave-mode-menu-def
8591 `("IDLWAVE" 8591 `("IDLWAVE"
8592 ["PRO/FUNC menu" idlwave-function-menu t] 8592 ["PRO/FUNC menu" idlwave-function-menu t]
8593 ("Motion" 8593 ("Motion"
8670 ["Launch IDL Help" idlwave-launch-idlhelp t]) 8670 ["Launch IDL Help" idlwave-launch-idlhelp t])
8671 "--" 8671 "--"
8672 ("Customize" 8672 ("Customize"
8673 ["Browse IDLWAVE Group" idlwave-customize t] 8673 ["Browse IDLWAVE Group" idlwave-customize t]
8674 "--" 8674 "--"
8675 ["Build Full Customize Menu" idlwave-create-customize-menu 8675 ["Build Full Customize Menu" idlwave-create-customize-menu
8676 (fboundp 'customize-menu-create)]) 8676 (fboundp 'customize-menu-create)])
8677 ("Documentation" 8677 ("Documentation"
8678 ["Describe Mode" describe-mode t] 8678 ["Describe Mode" describe-mode t]
8679 ["Abbreviation List" idlwave-list-abbrevs t] 8679 ["Abbreviation List" idlwave-list-abbrevs t]
8680 "--" 8680 "--"
8687 8687
8688 (defvar idlwave-mode-debug-menu-def 8688 (defvar idlwave-mode-debug-menu-def
8689 '("Debug" 8689 '("Debug"
8690 ["Start IDL shell" idlwave-shell t] 8690 ["Start IDL shell" idlwave-shell t]
8691 ["Save and .RUN buffer" idlwave-shell-save-and-run 8691 ["Save and .RUN buffer" idlwave-shell-save-and-run
8692 (and (boundp 'idlwave-shell-automatic-start) 8692 (and (boundp 'idlwave-shell-automatic-start)
8693 idlwave-shell-automatic-start)])) 8693 idlwave-shell-automatic-start)]))
8694 8694
8695 (if (or (featurep 'easymenu) (load "easymenu" t)) 8695 (if (or (featurep 'easymenu) (load "easymenu" t))
8696 (progn 8696 (progn
8697 (easy-menu-define idlwave-mode-menu idlwave-mode-map 8697 (easy-menu-define idlwave-mode-menu idlwave-mode-map
8698 "IDL and WAVE CL editing menu" 8698 "IDL and WAVE CL editing menu"
8699 idlwave-mode-menu-def) 8699 idlwave-mode-menu-def)
8700 (easy-menu-define idlwave-mode-debug-menu idlwave-mode-map 8700 (easy-menu-define idlwave-mode-debug-menu idlwave-mode-map
8701 "IDL and WAVE CL editing menu" 8701 "IDL and WAVE CL editing menu"
8702 idlwave-mode-debug-menu-def))) 8702 idlwave-mode-debug-menu-def)))
8703 8703
8704 (defun idlwave-customize () 8704 (defun idlwave-customize ()
8705 "Call the customize function with idlwave as argument." 8705 "Call the customize function with idlwave as argument."
8706 (interactive) 8706 (interactive)
8707 ;; Try to load the code for the shell, so that we can customize it 8707 ;; Try to load the code for the shell, so that we can customize it
8708 ;; as well. 8708 ;; as well.
8709 (or (featurep 'idlw-shell) 8709 (or (featurep 'idlw-shell)
8710 (load "idlw-shell" t)) 8710 (load "idlw-shell" t))
8711 (customize-browse 'idlwave)) 8711 (customize-browse 'idlwave))
8712 8712
8713 (defun idlwave-create-customize-menu () 8713 (defun idlwave-create-customize-menu ()
8714 "Create a full customization menu for IDLWAVE, insert it into the menu." 8714 "Create a full customization menu for IDLWAVE, insert it into the menu."
8715 (interactive) 8715 (interactive)
8716 (if (fboundp 'customize-menu-create) 8716 (if (fboundp 'customize-menu-create)
8717 (progn 8717 (progn
8718 ;; Try to load the code for the shell, so that we can customize it 8718 ;; Try to load the code for the shell, so that we can customize it
8719 ;; as well. 8719 ;; as well.
8720 (or (featurep 'idlw-shell) 8720 (or (featurep 'idlw-shell)
8721 (load "idlw-shell" t)) 8721 (load "idlw-shell" t))
8722 (easy-menu-change 8722 (easy-menu-change
8723 '("IDLWAVE") "Customize" 8723 '("IDLWAVE") "Customize"
8724 `(["Browse IDLWAVE group" idlwave-customize t] 8724 `(["Browse IDLWAVE group" idlwave-customize t]
8725 "--" 8725 "--"
8726 ,(customize-menu-create 'idlwave) 8726 ,(customize-menu-create 'idlwave)
8727 ["Set" Custom-set t] 8727 ["Set" Custom-set t]
8765 8765
8766 (interactive "P") 8766 (interactive "P")
8767 (let ((table (symbol-value 'idlwave-mode-abbrev-table)) 8767 (let ((table (symbol-value 'idlwave-mode-abbrev-table))
8768 abbrevs 8768 abbrevs
8769 str rpl func fmt (len-str 0) (len-rpl 0)) 8769 str rpl func fmt (len-str 0) (len-rpl 0))
8770 (mapatoms 8770 (mapatoms
8771 (lambda (sym) 8771 (lambda (sym)
8772 (if (symbol-value sym) 8772 (if (symbol-value sym)
8773 (progn 8773 (progn
8774 (setq str (symbol-name sym) 8774 (setq str (symbol-name sym)
8775 rpl (symbol-value sym) 8775 rpl (symbol-value sym)
8791 ;; Make the format 8791 ;; Make the format
8792 (setq fmt (format "%%-%ds %%-%ds %%s\n" len-str len-rpl)) 8792 (setq fmt (format "%%-%ds %%-%ds %%s\n" len-str len-rpl))
8793 (with-output-to-temp-buffer "*Help*" 8793 (with-output-to-temp-buffer "*Help*"
8794 (if arg 8794 (if arg
8795 (progn 8795 (progn
8796 (princ "Abbreviations and Actions in IDLWAVE-Mode\n") 8796 (princ "Abbreviations and Actions in IDLWAVE-Mode\n")
8797 (princ "=========================================\n\n") 8797 (princ "=========================================\n\n")
8798 (princ (format fmt "KEY" "REPLACE" "HOOK")) 8798 (princ (format fmt "KEY" "REPLACE" "HOOK"))
8799 (princ (format fmt "---" "-------" "----"))) 8799 (princ (format fmt "---" "-------" "----")))
8800 (princ "Code Abbreviations and Templates in IDLWAVE-Mode\n") 8800 (princ "Code Abbreviations and Templates in IDLWAVE-Mode\n")
8801 (princ "================================================\n\n") 8801 (princ "================================================\n\n")