1 ;;; srecode/ctxt.el --- Derive a context from the source buffer.
3 ;; Copyright (C) 2007-2013 Free Software Foundation, Inc.
5 ;; Author: Eric M. Ludlam <eric@siege-engine.com>
7 ;; This file is part of GNU Emacs.
9 ;; GNU Emacs is free software: you can redistribute it and/or modify
10 ;; it under the terms of the GNU General Public License as published by
11 ;; the Free Software Foundation, either version 3 of the License, or
12 ;; (at your option) any later version.
14 ;; GNU Emacs is distributed in the hope that it will be useful,
15 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 ;; GNU General Public License for more details.
19 ;; You should have received a copy of the GNU General Public License
20 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
24 ;; Manage context calculations for Semantic Recoder.
26 ;; SRecode templates are always bound to a context. By calculating
27 ;; the current context, we can narrow down the selection of possible
28 ;; templates to something reasonable.
30 ;; Alternately, code here will find a context for templates that
31 ;; require different pieces of code placed in multiple areas.
34 (require 'semantic
/tag-ls
)
36 (declare-function srecode-dictionary-show-section
"srecode/dictionary")
37 (declare-function srecode-dictionary-set-value
"srecode/dictionary")
41 (define-overload srecode-calculate-context
()
42 "Calculate the context at the current point.
43 The returned context is a list, with the top-most context first.
44 Each returned context is a string that would show up in a `context'
45 statement in an `.srt' file.
47 Some useful context values used by the provided srecode templates are:
48 \"file\" - Templates that for a file (such as an empty file.)
49 \"empty\" - The file is empty
50 \"declaration\" - Top-level declarations in a file.
51 \"include\" - In or near include statements
52 \"package\" - In or near provide statements
53 \"function\" - In or near function statements
54 \"NAME\" - Near functions within NAME namespace or class
55 \"variable\" - In or near variable statements.
56 \"type\" - In or near type declarations.
57 \"comment\" - In a comment
58 \"classdecl\" - Declarations within a class/struct/etc.
59 \"variable\" - In or near class fields
60 \"function\" - In or near methods/functions
61 \"virtual\" - Nearby items are virtual
62 \"pure\" - and those virtual items are pure virtual
63 \"type\" - In or near type declarations.
64 \"comment\" - In a comment in a block of code
65 -- these items show up at the end of the context list. --
66 \"public\", \"protected\", \"private\" -
67 In or near a section of public/protected/private entries.
68 \"code\" - In a block of code.
69 \"string\" - In a string in a block of code
70 \"comment\" - In a comment in a block of code
75 (defun srecode-calculate-nearby-things ()
76 ;; NOTE: May need to add bounds to this FCN
77 "Calculate the CONTEXT type items nearby the current point.
78 Assume that what we want to insert next is based on what is just
79 before point. If there is nothing, then assume it is whatever is
81 ;; @todo - ADD BOUNDS TO THE PREV/NEXT TAG SEARCH
82 ;; thus classdecl "near" stuff cannot be
83 ;; outside the bounds of the type in question.
84 (let ((near (semantic-find-tag-by-overlay-prev))
88 (setq near
(semantic-find-tag-by-overlay-next)))
90 ;; Calculate the type of thing we are near.
91 (if (not (semantic-tag-of-class-p near
'function
))
92 (setq ans
(cons (symbol-name (semantic-tag-class near
)) ans
))
93 ;; if the symbol NEAR has a parent,
94 (let ((p (semantic-tag-function-parent near
)))
95 (setq ans
(cons (symbol-name (semantic-tag-class near
)) ans
))
96 (cond ((semantic-tag-p p
)
97 (setq ans
(cons (semantic-tag-name p
) ans
)))
99 (setq ans
(cons p ans
)))
102 (when (semantic-tag-get-attribute near
:virtual
)
103 (setq ans
(cons "virtual" ans
)))
105 (when (semantic-tag-get-attribute near
:pure-virtual-flag
)
106 (setq ans
(cons "pure" ans
)))
108 ;; Calculate the protection
109 (setq prot
(semantic-tag-protection near
))
110 (when (and prot
(not (eq prot
'unknown
)))
111 (setq ans
(cons (symbol-name prot
) ans
)))
115 (defun srecode-calculate-context-font-lock ()
116 "Calculate an srecode context by using font-lock."
117 (let ((face (get-text-property (point) 'face
))
119 (cond ((member face
'(font-lock-string-face
122 ((member face
'(font-lock-comment-face
123 font-lock-comment-delimiter-face
))
128 (defun srecode-calculate-context-default ()
129 "Generic method for calculating a context for srecode."
130 (if (= (point-min) (point-max))
131 (list "file" "empty")
133 (semantic-fetch-tags)
134 (let ((ct (semantic-find-tag-by-overlay))
137 ;; Ok, below is a bit C specific.
138 (and (eq (semantic-tag-class (car ct
)) 'type
)
139 (string= (semantic-tag-type (car ct
)) "namespace")))
141 (or (srecode-calculate-context-font-lock)
142 (srecode-calculate-nearby-things)
145 ((eq (semantic-tag-class (car ct
)) 'function
)
146 (cons "code" (srecode-calculate-context-font-lock))
148 ((eq (semantic-tag-class (car ct
)) 'type
) ; We know not namespace
150 (or (srecode-calculate-context-font-lock)
151 (srecode-calculate-nearby-things)))
154 (eq (semantic-tag-class (car (cdr ct
))) 'type
))
156 (symbol-name (semantic-tag-class (car ct
))))
164 ;; The calculated context is one thing, but more info is often available.
165 ;; The context handlers can add info into the active dictionary that is
166 ;; based on the context, such as a method parent name, protection scheme,
169 (defun srecode-semantic-handle-:ctxt
(dict &optional template
)
170 "Add macros into the dictionary DICT based on the current Emacs Lisp file.
171 Argument TEMPLATE is the template object adding context dictionary
173 This might add the following:
174 VIRTUAL - show a section if a function is virtual
175 PURE - show a section if a function is pure virtual.
176 PARENT - The name of a parent type for functions.
177 PROTECTION - Show a protection section, and what the protection is."
178 (require 'srecode
/dictionary
)
181 (let ((name (oref template object-name
))
182 (cc (if (boundp 'srecode-insertion-start-context
)
183 srecode-insertion-start-context
))
184 ;(context (oref template context))
188 ; (null (string= (car cc) context))
190 ; ;; No current context, or the base is different, then
191 ; ;; this is the section where we need to recalculate
192 ; ;; the context based on user choice, if possible.
194 ; ;; The recalculation is complex, as there are many possibilities
195 ; ;; that need to be divined. Set "cc" to the new context
202 ;; The various context all have different features.
203 (let ((ct (nth 0 cc
))
208 (cond ((string= it
"function")
209 (setq parent
(nth 2 cc
))
211 (cond ((string= parent
"virtual")
212 (srecode-dictionary-show-section dict
"VIRTUAL")
214 (srecode-dictionary-show-section dict
"PURE"))
217 (srecode-dictionary-set-value dict
"PARENT" parent
))))
219 ((and (string= it
"type")
220 (or (string= name
"function") (string= name
"method")))
221 ;; If we have a type, but we insert a fcn, then use that type
222 ;; as the function parent.
223 (let ((near (semantic-find-tag-by-overlay-prev)))
224 (when (and near
(semantic-tag-of-class-p near
'type
))
225 (srecode-dictionary-set-value
226 dict
"PARENT" (semantic-tag-name near
))))
229 ;;(let ((analyzer (semantic-analyze-current-context)))
230 ;; @todo - Use the analyze to setup things like local
231 ;; variables we might use or something.
237 (when (member last
'("public" "private" "protected"))
238 ;; Hey, fancy that, we can do both.
239 (srecode-dictionary-set-value dict
"PROTECTION" parent
)
240 (srecode-dictionary-show-section dict
"PROTECTION"))
245 (provide 'srecode
/ctxt
)
247 ;;; srecode/ctxt.el ends here