ctxt.el 8.5 KB

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