Remove obsolete/deprecate/useless pkgs
[packages] / xemacs-packages / idlwave / idlw-complete-structtag.el
1 ;;; idlw-complete-structtag.el --- Completion of structure tags.
2 ;; Copyright (c) 2001,2002 Free Software Foundation
3
4 ;; Author: Carsten Dominik <dominik@astro.uva.nl>
5 ;; Maintainer: J.D. Smith <jdsmith@as.arizona.edu
6 ;; Version: 1.1
7 ;; Date: $Date: 2003-08-12 12:26:17 $
8 ;; Keywords: languages
9
10 ;; This file is part of GNU Emacs.
11
12 ;; GNU Emacs is free software; you can redistribute it and/or modify
13 ;; it under the terms of the GNU General Public License as published by
14 ;; the Free Software Foundation; either version 2, or (at your option)
15 ;; any later version.
16
17 ;; GNU Emacs is distributed in the hope that it will be useful,
18 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 ;; GNU General Public License for more details.
21
22 ;; You should have received a copy of the GNU General Public License
23 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
24 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
25 ;; Boston, MA 02111-1307, USA.
26
27 ;;; Commentary:
28
29 ;; Completion of structure tags is highly ambiguous since you never
30 ;; know what kind of structure a variable will hold at runtime.
31 ;; However, in some applications there is one main structure which
32 ;; contains a large amount of information.  For example, in many
33 ;; widget applications, a "state" structure contains all important
34 ;; data about the application is stored in the main widget.  The
35 ;; different routines called by the event handler then use this
36 ;; structure for their actions.  If you use the same variable name for
37 ;; this structure throughout your application (a good idea for many
38 ;; reasons), IDLWAVE can support completion for its tags.  
39 ;;
40 ;; This file is a completion plugin which implements this kind of
41 ;; completion. It is also an example which shows how completion
42 ;; plugins should be programmed.
43 ;;
44 ;; New versions of IDLWAVE, documentation, and more information
45 ;; available from:
46 ;;                 http://idlwave.org
47 ;;
48 ;; INSTALLATION
49 ;; ============
50 ;; Put this file on the emacs load path and load it with the following 
51 ;; line in your .emacs file:
52 ;;
53 ;;   (add-hook 'idlwave-load-hook 
54 ;;             (lambda () (require 'idlw-complete-structtag)))
55 ;;
56 ;; DESCRIPTION
57 ;; ===========
58 ;; Suppose your IDL program contains something like
59 ;;
60 ;;     myvar = state.a*
61 ;;
62 ;; where the star marks the cursor position.  If you now press the
63 ;; completion key M-TAB, IDLWAVE searches the current file for a
64 ;; structure definition
65 ;;
66 ;;   state = {tag1:val1, tag2:val2, ...}
67 ;;
68 ;; and offers the tags for completion.
69 ;;
70 ;; Notes
71 ;; -----
72 ;;  - The structure definition assignment "state = {...}" must use the
73 ;;    same variable name as the the completion location "state.*".
74 ;;  - The structure definition must be in the same file.
75 ;;  - The structure definition is searched backwards from the end of
76 ;;    the file, until a definition with tags is found.
77 ;;  - The file is parsed again for the definition only if the variable 
78 ;;    name (like "state") of the current completion differs from the
79 ;;    previous tag completion.
80 ;;  - You can force and update of the tag list with the usual command
81 ;;    to update routine info in IDLWAVE: C-c C-i
82 ;;
83 ;;
84 (defvar idlwave-current-tags-var nil)
85 (defvar idlwave-current-tags-buffer nil)
86 (defvar idlwave-current-struct-tags nil)
87 (defvar idlwave-sint-structtags nil)
88 (idlwave-new-sintern-type 'structtag)
89 (add-to-list 'idlwave-complete-special 'idlwave-complete-structure-tag)
90 (add-hook 'idlwave-update-rinfo-hook 'idlwave-structtag-reset)
91
92 (defun idlwave-complete-structure-tag ()
93   "Complete a structure tag.
94 This works by looking in the current file for a structure assignment to a
95 variable with the same name and takes the tags from there.  Quite useful
96 for big structures like the state variables of a widget application."
97   (interactive)
98   (let ((pos (point))
99         (case-fold-search t))
100     (if (save-excursion
101           ;; Check if the context is right
102           (skip-chars-backward "[a-zA-Z0-9._$]")
103           (and (< (point) pos)
104                (not (equal (char-before) ?!)) ; no sysvars
105                (looking-at "\\([a-zA-Z][a-zA-Z0-9_]*\\)\\.")
106                (>= pos (match-end 0))
107                (not (string= (downcase (match-string 1)) "self"))))  ;; FIXME:  Can we avoid checking for self here?
108         (let* ((var (downcase (match-string 1))))
109           ;; Check if we need to update the "current" structure
110           (if (or (not (string= var (or idlwave-current-tags-var "@")))
111                   (not (eq (current-buffer) idlwave-current-tags-buffer)))
112               (idlwave-prepare-structure-tag-completion var))
113           (setq idlwave-completion-help-info 
114                 (list 'idlwave-complete-structure-tag-help))
115           (idlwave-complete-in-buffer 'structtag 'structtag 
116                                       idlwave-current-struct-tags nil
117                                       "Select a structure tag" "structure tag")
118           t) ; return t to skip other completions
119       nil)))
120
121 (defun idlwave-structtag-reset ()
122   (setq idlwave-current-tags-buffer nil))
123
124 (defvar idlwave-structtag-struct-location nil)
125 (defun idlwave-prepare-structure-tag-completion (var)
126   "Find and parse the necessary class definitions for class structure tags."
127   ;; (message "switching to var %s" var) ; FIXME: take this out.
128   ;; (sit-for 2)
129   (unless
130       (catch 'exit
131         (save-excursion
132           (goto-char (point-max))
133           (while (idlwave-find-structure-definition var nil 'back)
134             (let ((tags (idlwave-struct-tags)))
135               (when tags 
136                 (setq idlwave-sint-structtags nil
137                       idlwave-current-tags-buffer (current-buffer)
138                       idlwave-current-tags-var var
139                       idlwave-structtag-struct-location (point)
140                       idlwave-current-struct-tags
141                       (mapcar (lambda (x)
142                                 (list (idlwave-sintern-structtag x 'set)))
143                               tags))
144                 (throw 'exit t))))))
145     (error "Cannot complete structure tags of variable %s" var)))
146
147 ;; Fake help in the source buffer for structure tags.
148 ;; kwd and name are global-variables here.
149 (defvar idlwave-help-do-struct-tag)
150 (defun idlwave-complete-structure-tag-help (mode word)
151   (cond
152    ((eq mode 'test) ; nothing gets fontified for class tags
153     nil)
154    ((eq mode 'set)
155     (setq kwd word
156           idlwave-help-do-struct-tag idlwave-structtag-struct-location))
157    (t (error "This should not happen"))))
158
159 (provide 'idlw-complete-structtag)
160
161 ;;; idlw-complete-structtag.el ends here