-
Notifications
You must be signed in to change notification settings - Fork 0
/
ecb-analyse.el
716 lines (628 loc) · 31.9 KB
/
ecb-analyse.el
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
;;; ecb-analyse.el --- ECB analysis display window
;;; Copyright (C) 2004 - 2005 Klaus Berndl
;; Author: Klaus Berndl <[email protected]>
;; Maintainer: Klaus Berndl <[email protected]>
;; Keywords: browser, code, programming, analyse
;; Created: 2004
;; This program is free software; you can redistribute it and/or modify it under
;; the terms of the GNU General Public License as published by the Free Software
;; Foundation; either version 2, or (at your option) any later version.
;; This program is distributed in the hope that it will be useful, but WITHOUT
;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
;; FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
;; details.
;; You should have received a copy of the GNU General Public License along with
;; GNU Emacs; see the file COPYING. If not, write to the Free Software
;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
;; $Id: ecb-analyse.el,v 1.25 2009/05/08 14:05:55 berndl Exp $
;;; Commentary:
;;
;; Displays the analysing informations of semantic-analyze in a special
;; tree-buffer.
;;
;;; Code:
(require 'semantic-analyze)
(require 'ecb-layout)
(require 'ecb-common-browser)
(require 'ecb-method-browser)
(eval-when-compile
(require 'silentcomp))
(eval-when-compile
;; to avoid compiler grips
(require 'cl))
(defgroup ecb-analyse nil
"Settings for the analyse-buffer in the Emacs code browser."
:group 'ecb
:prefix "ecb-")
(defcustom ecb-analyse-buffer-name " *ECB Analyse*"
"*Name of the ECB analyse buffer.
Because it is not a normal buffer for editing you should enclose the name with
stars, e.g. \"*ECB Analyse*\".
If it is necessary for you you can get emacs-lisp access to the buffer-object of
the ECB-analyse-buffer by this name, e.g. by a call of `set-buffer'.
Changes for this option at runtime will take affect only after deactivating and
then activating ECB again!"
:group 'ecb-analyse
:type 'string)
(defcustom ecb-analyse-buffer-after-create-hook nil
"*Local hook running after the creation of the analyse-buffer.
Every function of this hook is called once without arguments direct after
creating the analyse-buffer of ECB and it's local key-map. So for example a
function could be added which performs calls of `local-set-key' to define new
key-bindings only for the analyse-buffer of ECB."
:group 'ecb-analyse
:type 'hook)
(defcustom ecb-analyse-show-node-info '(if-too-long . name)
"*When to display which node-info in the analyse-buffer.
Define which node info should displayed after moving the mouse over a node
\(or after a shift click onto the node) in the analyse-buffer.
You can define \"when\" a node-info should be displayed:
See `ecb-directories-show-node-info' for the possible choices.
You can define what info should be displayed:
- name: The full name of the node
- full-info: All infos available to a node.
Do NOT set this option directly via setq but use always customize!"
:group 'ecb-analyse
:type '(cons (choice :tag "When"
(const :tag "Always" :value always)
(const :tag "If too long" :value if-too-long)
(const :tag "After shift click" :value shift-click)
(const :tag "Never" :value never))
(choice :tag "What"
(const :tag "Node-name" :value name)
(const :tag "Full info" :value full-info))))
(defcustom ecb-analyse-collapsed-buckets nil
"*Buckets collapsed when displaying the current semantic analysis.
The semantic analyse-modul offers several categories of analysis which are
called buckets here. These are for example:
Context: The current context, which is the current function/method, variable,
class etc. \(what exactly depends on the programming language) point is in.
This means not the current function/method/variable/class-name point stand on
but the current surrounding context. Example: If point stays somewhere within
a defun-definition in emacs-lisp or within a java-method then this defun rsp.
method is the context. In object oriented languages this can be the full
hierachy, i.e. not only the current method, but the current method, the class
of this method, the superclass of this class and so on!
Local Variables: All accessible and bound local variables visible at current
point.
Prefix: The currently parsed prefix, which is mostly the current identifier
point stands on.
Assignee: See the semantic manual
Function: Current function-name point stands on.
Argument #: When point is located within a function-call then this is the
number of the argument point stands on.
Completions: All possible completions for current prefix \(see above). This is
probably the most helpful bucket.
If one of these categories/buckets are not needed per default then add the
bucket-name \(s.a.) to this option and ECB will per default collapse this
bucket. So most needed buckets are better visible in the analyse-buffer."
:group 'ecb-analyse
:type '(repeat (choice :tag "Bucket" :menu-tag "Bucket"
(const :tag "Context" :value "Context")
(const :tag "Arguments" :value "Arguments")
(const :tag "Local Variables" :value "Local Variables")
(const :tag "Prefix" :value "Prefix")
(const :tag "Assignee" :value "Assignee")
(const :tag "Function" :value "Function")
(const :tag "Argument #" :value "Argument #")
(const :tag "Completions" :value "Completions")
(string :tag "Other bucketname"))))
(defcustom ecb-analyse-fontified-buckets '("Context" "Function")
"*Buckets whose elements should be fontified as in the methods-buffer.
If the name of a category/bucket is contained in this option then
all elements of this bucket will be displayed as in the
methods-buffer - at least if an element is a semantic-tag. This
means if `ecb-font-lock-tags' is not nil and the font-lock
feature is loaded into Emacs these elements will be fontified and
also displayed with an appropriate icon if possible. The default
value does this only for the Context-bucket because for most of
the other buckets this makes not really much sense.
For available buckets see `ecb-analyse-collapsed-buckets'.
For the faces used to display a bucket-node itself or bucket-elements not
fontified see the options `ecb-analyse-bucket-node-face' rsp.
`ecb-analyse-bucket-element-face'."
:group 'ecb-analyse
:type '(repeat (choice :tag "Bucket" :menu-tag "Bucket"
(const :tag "Context" :value "Context")
(const :tag "Arguments" :value "Arguments")
(const :tag "Local Variables" :value "Local Variables")
(const :tag "Prefix" :value "Prefix")
(const :tag "Assignee" :value "Assignee")
(const :tag "Function" :value "Function")
(const :tag "Argument #" :value "Argument #")
(const :tag "Completions" :value "Completions")
(string :tag "Other bucketname"))))
(defcustom ecb-analyse-gen-tag-info-fn nil
"*Which info should be displayed for a tag of the analyse-buffer.
If nil then the default information about a tag will be displayed. If a
function then this function gets as argument the tag for which tag-information
should be displayed. This function has to return a string which will be then
display as tag-info. This string has to be fully formatted \(e.g. must already
include line-breaks if the tag-info should be displayed in several lines).
See `ecb-analyse-show-tag-info-fn' how the tag-info is displayed."
:group 'ecb-analyse
:type '(radio (const :tag "Default info" :value nil)
(function :tag "")))
(defcustom ecb-analyse-show-tag-info-fn 'message
"*How to display the tag-info for a tag of the analyse-buffer.
The value of this option is a function which will be called with the
info-string generated for the current tag of the analyse-buffer. This function
must do all things necessary for displaying this info. When this function is
called the window stored in `ecb-last-edit-window-with-point' is the selected
window!
ECB offers two builtin ways: Display the info in the echo-area \(via the
function `message') or in a temp-buffer in the edit-area \(via the function
`ecb-analyse-show-tag-info-in-temp-buffer'). Default is echo-area-display.
See also `ecb-analyse-gen-tag-info-fn'."
:group 'ecb-analyse
:type '(radio (const :tag "Display in the echo-area" :value message)
(const :tag "Display in a temp-buffer"
:value ecb-analyse-show-tag-info-in-temp-buffer)
(function :tag "Info display-function")))
(defcustom ecb-analyse-buffer-sync 'basic
"*Synchronize the analyse buffer automatically with current edit buffer.
If 'always then the synchronization takes place always a buffer changes in the
edit window, if nil then never. If a list of major-modes then only if the
`major-mode' of the new buffer belongs NOT to this list.
Normally it's not necessary to exclude some major-modes because with
not-semantic supported major-modes simply nothing happens. But maybe it can be
helpful for certain situations...
If the special value 'basic is set then ECB uses the setting of the option
`ecb-basic-buffer-sync'.
IMPORTANT NOTE: Every time the synchronization is done the hook
`ecb-analyse-buffer-sync-hook' is evaluated."
:group 'ecb-analyse
:type '(radio :tag "Synchronize ECBs analyse buffer"
(const :tag "use basic value" :value basic)
(const :tag "Always" :value always)
(const :tag "Never" nil)
(repeat :tag "Not with these modes"
(symbol :tag "mode"))))
(defcustom ecb-analyse-buffer-sync-delay 2
"*Time Emacs must be idle before the analyse-buffer is synchronized.
Synchronizing is done with the current source displayed in the edit window. If
nil then there is no delay, means synchronization takes place immediately.
CAUTION: With analysing a value not too small is strongly recommended because
it can be very annoying if more or less after each typing the current context
is analysed. If set to nil then *each* keyboard hit refreshes the
analyse-buffer which will make ECB quite unusable!
If the special value 'basic is set then ECB uses the setting of the option
`ecb-basic-buffer-sync-delay'"
:group 'ecb-analyse
:type '(radio (const :tag "Use basic value" :value basic)
(const :tag "No synchronizing delay" :value nil)
(number :tag "Idle time before synchronizing" :value 2))
:set (function (lambda (symbol value)
(set symbol value)
(if (and (boundp 'ecb-minor-mode)
ecb-minor-mode)
(ecb-activate-ecb-autocontrol-function
value 'ecb-analyse-buffer-sync))))
:initialize 'custom-initialize-default)
(defcustom ecb-analyse-buffer-sync-hook nil
"Hook run at the end of `ecb-analyse-buffer-sync'.
See documentation of `ecb-analyse-buffer-sync' for conditions when
synchronization takes place and so in turn these hooks are evaluated.
Preconditions for such a hook:
- Current buffer is the buffer of the currently selected
edit-window.
- The analyse-buffer is displayed in a visible window of the
ecb-frame \(so no check for visibilty of the analyse-buffer in
the ecb-frame is necessary in a hook function)
Postcondition for such a hook:
Point must stay in the same edit-window as before evaluating the hook.
Important note: If the option `ecb-analyse-buffer-sync' is not
nil the function `ecb-analyse-buffer-sync' is running either
every time Emacs is idle or even after every command \(see
`ecb-analyse-buffer-sync-delay'). So if the anaylse-buffer is
displayed in a window of the ecb-frame \(see preconditions above)
these hooks can be really called very often! Therefore each
function of this hook should/must check in an efficient way at
beginning if its task have to be really performed and then do
them only if really necessary! Otherwise performance of Emacs
could slow down dramatically!"
:group 'ecb-analyse
:type 'hook)
(defconst ecb-analyse-nodedata-tag-with-pos 0)
(defconst ecb-analyse-nodedata-tag-without-pos 1)
(defconst ecb-analyse-nodedata-no-tag 2)
(defconst ecb-analyse-nodetype-bucket 0)
(defconst ecb-analyse-nodetype-context 1)
(defconst ecb-analyse-nodetype-arguments 2)
(defconst ecb-analyse-nodetype-completions 3)
(defconst ecb-analyse-nodetype-localvars 4)
(defconst ecb-analyse-nodetype-prefix 5)
(defconst ecb-analyse-nodetype-assignee 6)
(defconst ecb-analyse-nodetype-function 7)
(defconst ecb-analyse-nodetype-function-arg 8)
(defecb-autocontrol/sync-function ecb-analyse-buffer-sync
ecb-analyse-buffer-name ecb-analyse-buffer-sync t
"Synchronize the analyse buffer with the current buffer and point.
This means in fact display the current analysis for current point."
;; TODO: Klaus Berndl <[email protected]>: make interruptable. Necessary
;; e.g. when typing: "(e" then scanning all elisp stuff beginning with e is
;; really annoying....
(let ((analysis nil)
(scope nil)
(completions nil)
(cnt nil)
(mode-local-active-mode nil)
)
;; Try and get some sort of analysis
(condition-case nil
(progn
(setq mode-local-active-mode major-mode)
(save-excursion
;; Get the current scope
(setq scope (semantic-calculate-scope (point)))
;; Get the analysis
(setq analysis (ecb--semantic-analyze-current-context (point)))
(setq cnt (ecb--semantic-find-tag-by-overlay))
(when analysis
(setq completions (ecb--semantic-analyze-possible-completions analysis)))))
(error nil))
(ecb-exec-in-window ecb-analyse-buffer-name
;; we must remove the old nodes
(tree-buffer-set-root (tree-node-new-root))
(when cnt
(ecb-analyse-add-nodes "Context" "Context"
cnt ecb-analyse-nodetype-context))
;; TODO: Klaus Berndl <[email protected]>: maybe we should adopt this
;; for ecb-analyse..
;; (when analysis
;; ;; If this analyzer happens to point at a complete symbol, then
;; ;; see if we can dig up some documentation for it.
;; (semantic-ia-sb-show-doc analysis))
;; Show local variables
(when scope
(ecb-analyse-show-scope scope))
(when analysis
;; Let different classes draw more buttons.
(ecb-analyse-more-nodes analysis)
(when completions
(ecb-analyse-add-nodes "Completions" "Completions" completions
ecb-analyse-nodetype-completions)))
(tree-buffer-update)))
(run-hooks 'ecb-analyse-buffer-sync-hook))
(defun ecb-analyse-show-scope (scope)
"Show SCOPE information."
(let ((localvars (when scope
(oref scope localvar))))
(when localvars
(ecb-analyse-add-nodes "Local Variables" "Local Variables" localvars
ecb-analyse-nodetype-localvars))))
(defmethod ecb-analyse-more-nodes ((context semantic-analyze-context))
"Show a set of ecb-nodes specific to CONTEXT."
(let ((prefix (oref context prefix)))
(when prefix
(ecb-analyse-add-nodes "Prefix" "Prefix" prefix ecb-analyse-nodetype-prefix))))
(defmethod ecb-analyse-more-nodes ((context semantic-analyze-context-assignment))
"Show a set of ecb-nodes specific to CONTEXT."
(call-next-method)
(let ((assignee (oref context assignee)))
(when assignee
(ecb-analyse-add-nodes "Assignee" "Assignee" assignee
ecb-analyse-nodetype-assignee))))
(defmethod ecb-analyse-more-nodes ((context semantic-analyze-context-functionarg))
"Show a set of ecb-nodes specific to CONTEXT."
(call-next-method)
(let ((func (oref context function)))
(when func
(ecb-analyse-add-nodes "Function" "Function" func ecb-analyse-nodetype-function)
;; An index for the argument the prefix is in:
(let ((arg (oref context argument)))
(when arg
(ecb-analyse-add-nodes "Argument #"
(format "Argument # %d" (oref context index))
arg
ecb-analyse-nodetype-function-arg))))))
;; Each category of nodes gets its own nodetype, so we can offer different
;; popup-menus for different categories (e.g. completions have other senseful
;; popup-menu-entries than the rest. The date of a node will always be a cons
;; where the car is the analyse-elem and the cdr is a const if it is a
;; semantic-tag (positionless or with position) or not.
(defun ecb-analyse-add-nodes (bucket bucket-name list nodetype)
"Create ecb-nodes from LIST. BUCKET is one of the categories/buckets
mentioned in `ecb-analyse-collapsed-buckets'. BUCKET-NAME is the name a bucket
should be displayed with. LIST is a list of tags for this bucket. NODETYPE is
an integer which will be added as type to the nodes created for the elements
of LIST."
(when list
(save-excursion
(set-buffer ecb-analyse-buffer-name)
(let* ((bucket-name-formatted
(ecb-merge-face-into-text (ecb-format-bucket-name bucket-name)
ecb-analyse-bucket-node-face))
(bucket-node (tree-node-new bucket-name-formatted
ecb-analyse-nodetype-bucket
(list 'ecb-bucket-node
ecb-analyse-nodetype-bucket)
nil
(tree-buffer-get-root))))
(setf (tree-node->expanded bucket-node)
(not (member bucket ecb-analyse-collapsed-buckets)))
(ecb-exit-on-input 'ecb-analyse
(dolist (elem list)
(ecb-throw-on-input 'ecb-analyse-tree-buffer-build)
(let* ((fontify-tags (member bucket ecb-analyse-fontified-buckets))
(string-1 (typecase elem
(string elem)
(ecb--semantic-tag
(if fontify-tags
(ecb-displayed-tag-name elem)
(ecb--semantic-format-tag-uml-concise-prototype elem)))
(otherwise "foo")))
(string (concat string-1)))
(unless fontify-tags
(ecb-merge-face-into-text string ecb-analyse-bucket-element-face))
(if (ecb--semantic-tag-p elem)
(tree-node-new string nodetype
(list elem
(if (ecb--semantic-tag-with-position-p elem)
ecb-analyse-nodedata-tag-with-pos
ecb-analyse-nodedata-tag-without-pos)
nodetype)
t bucket-node nil)
(tree-node-new string nodetype
(list elem ecb-analyse-nodedata-no-tag nodetype)
t bucket-node nil)))))))))
(defun ecb-analyse-compare-node-data (left right)
"Return not nil when LEFT and RIGHT are identical node-datas."
(and (equal (nth 2 left) (nth 2 right))
(ecb-compare-methods-buffer-node-data (car left) (car right))))
(tree-buffer-defpopup-command ecb-analyse-jump-to-tag
"Jump to the definition of current tag of the analyse-buffer.
If first arg of the REST-ARG-LIST is not nil then it must be a window and then
ECB jumps to that window. If nil then `ecb-last-edit-window-with-point' is
used as window."
(let ((window (nth 0 rest-arg-list)))
(when node
(let* ((data (tree-node->data node))
(tag (nth 0 data)))
;; if we have a positioned tag we jump to it
(when (and tag (= (nth 1 data) ecb-analyse-nodedata-tag-with-pos))
;; We must highlight the tag
(tree-buffer-highlight-node-by-data/name data)
;; TODO: Klaus Berndl <[email protected]>: what about tags without
;; buffer but onlxy with start- and end-pos?!
(ecb-display-tag (ecb-source-make (ecb-buffer-file-name
(ecb-semantic-tag-buffer tag))
(ecb-semantic-tag-buffer tag))
tag
(or window (ecb-get-edit-window nil))
t nil))))))
(tree-buffer-defpopup-command ecb-analyse-complete/insert
"Complete/insert at current point the selected completion/localvar."
;; We must highlight the tag
(let* ((data (tree-node->data node))
(tag (nth 0 data))
(type (tree-node->type node)))
(when (or (= type ecb-analyse-nodetype-completions)
(= type ecb-analyse-nodetype-localvars))
(tree-buffer-highlight-node-by-data/name data)
(ecb-display-source ecb-path-selected-source nil)
(let* ((a (ecb--semantic-analyze-current-context (point)))
(bounds (if a (oref a bounds)))
(movepoint nil))
(if (null bounds)
(insert (ecb--semantic-tag-name tag))
(save-excursion
(if (and (<= (point) (cdr bounds)) (>= (point) (car bounds)))
(setq movepoint t))
(goto-char (car bounds))
(delete-region (car bounds) (cdr bounds))
(insert (ecb--semantic-tag-name tag))
(if movepoint (setq movepoint (point))))
(if movepoint
(goto-char movepoint)))))))
(defecb-tree-buffer-callback ecb-analyse-node-clicked ecb-analyse-buffer-name select nil
"Handles clicking onto any of the nodes in the analyse-buffer of ECB."
(if shift-mode
(ecb-mouse-over-analyse-node node nil nil 'force))
(let* ((data (tree-node->data node))
(tag (nth 0 data))
(type (tree-node->type node)))
;; we handle hiding the ecb-windows for ourself
(setq no-meta-hiding t)
(cond
((= type ecb-analyse-nodetype-bucket)
(tree-node-toggle-expanded node)
(tree-buffer-update node))
((= type ecb-analyse-nodetype-completions)
(ecb-analyse-complete/insert node))
((= type ecb-analyse-nodetype-localvars)
(ecb-analyse-complete/insert node))
(t
(ecb-analyse-jump-to-tag node (ecb-get-edit-window
;; `ecb-analyse-jump-to-tag' expects all
;; args beyond NODE as one list.
`(,(ecb-combine-ecb-button/edit-win-nr
ecb-button edit-window-nr))))
(when (and tag (= (nth 1 data) ecb-analyse-nodedata-tag-with-pos))
(when meta-mode
(ecb-run-with-idle-timer 0.001 nil 'ecb-hide-ecb-windows)))))))
(defecb-window-dedicator ecb-set-analyse-buffer ecb-analyse-buffer-name
"Display the analyse buffer in current window and make window dedicated."
(ecb-activate-ecb-autocontrol-function ecb-analyse-buffer-sync-delay
'ecb-analyse-buffer-sync)
(switch-to-buffer ecb-analyse-buffer-name))
(defun ecb-maximize-window-analyse ()
"Maximize the ECB-analyse-window.
I.e. delete all other ECB-windows, so only one ECB-window and the
edit-window\(s) are visible \(and maybe a compile-window). Works also if the
ECB-analyse-window is not visible in current layout."
(interactive)
(ecb-maximize-ecb-buffer ecb-analyse-buffer-name t))
(defun ecb-goto-window-analyse ()
"Make the ECB-analyse window the current window."
(interactive)
(ecb-goto-ecb-window ecb-analyse-buffer-name))
(defun ecb-analyse-show-tag-info-in-temp-buffer (info-string)
"Display INFO-STRING in a temp-buffer in the edit-area."
(with-output-to-temp-buffer "*Tag Information*"
(save-excursion
(set-buffer "*Tag Information*")
(insert info-string)))
;; Make it small
(shrink-window-if-larger-than-buffer
(get-buffer-window "*Tag Information*")))
;; TODO: Klaus Berndl <[email protected]>: we could use the function
;; `semantic-documentation-for-tag' here to display more infos?!
(defun ecb-analyse-gen-tag-info (tag)
"Return the info-string for TAG."
(or (and (functionp ecb-analyse-gen-tag-info-fn)
(or (funcall ecb-analyse-gen-tag-info-fn tag)
(format "No info generated by `%s'." ecb-analyse-gen-tag-info-fn)))
(concat (ecb-displayed-tag-name tag)
"\n"
(let ((typetag
(condition-case nil
(save-excursion
(ecb--semantic-analyze-tag-type tag))
(error nil))))
(if typetag
(ecb-displayed-tag-name typetag)
;; No type found by the analyzer The below used
;; to try and select the buffer from the last
;; analysis, but since we are already in the
;; correct buffer, I don't think that is needed.
(when (fboundp 'semantic-lex-keyword-p)
(let ((type (ecb--semantic-tag-type tag)))
(typecase type
(ecb--semantic-tag
(setq type (ecb--semantic-tag-name type)))
(list
(setq type (car type))))
(if (semantic-lex-keyword-p type)
(setq typetag
(semantic-lex-keyword-get type 'summary))))
(if typetag
typetag))
)))))
(tree-buffer-defpopup-command ecb-analyse-show-tag-info
"Display as much information as possible about current tag.
Show the information in a shrunk split-buffer and expand out as many details
as possible."
(let* ((data (tree-node->data node))
(tag (car data)))
(when (ecb--semantic-tag-p tag)
(save-selected-window
(select-window ecb-last-edit-window-with-point)
(funcall ecb-analyse-show-tag-info-fn (ecb-analyse-gen-tag-info tag))))))
(defun ecb-mouse-over-analyse-node (node &optional window no-message click-force)
"Displays help text if mouse moves over a node in the analyse buffer or if
CLICK-FORCE is not nil and always with regards to the settings in
`ecb-analyse-show-node-info'. NODE is the node for which help text should be
displayed, WINDOW is the related window, NO-MESSAGE defines if the help-text
should be printed here."
(let ((str (when (or click-force
(ecb-show-minibuffer-info node window
(car
ecb-analyse-show-node-info)))
(if (equal (cdr ecb-analyse-show-node-info) 'full-info)
(ecb-analyse-gen-tag-info (car (tree-node->data node)))
(tree-node->name node)))))
(prog1 str
(unless no-message
(ecb-nolog-message str)))))
(defun ecb-analyse-node-mouse-highlighted-p (node)
"Return not nil when NODE has a positioned tag as data or belongs to the
completions. This means that this node should be highlighted when mouse is
moved over it."
(or (equal ecb-analyse-nodedata-tag-with-pos
(nth 1 (tree-node->data node)))
(member (tree-node->type node)
(list ecb-analyse-nodetype-completions
ecb-analyse-nodetype-localvars))))
(defun ecb-analyse-create-menu (node)
"Return a popup-menu suitable for NODE."
(let* ((data (tree-node->data node))
(tag-p (not (equal (nth 1 data) ecb-analyse-nodedata-no-tag)))
(tag-with-pos-p (equal (nth 1 data) ecb-analyse-nodedata-tag-with-pos))
(nodetype (nth 2 data)))
(delq nil (list (if (member nodetype (list
ecb-analyse-nodetype-completions
ecb-analyse-nodetype-localvars))
'(ecb-analyse-complete/insert "Complete/insert"))
(if tag-p
'(ecb-analyse-show-tag-info "Show tag info"))
(if tag-with-pos-p
'(ecb-analyse-jump-to-tag "Jump to tag"))))))
(defun ecb-analyse-menu-creator (tree-buffer-name node)
"Creates the popup-menus for the analyse-buffer."
(setq ecb-layout-prevent-handle-ecb-window-selection t)
(let ((nodetype (tree-node->type node)))
(unless (equal nodetype ecb-analyse-nodetype-bucket)
(mapcar (function (lambda (type)
(cons type (ecb-analyse-create-menu node))))
`(,ecb-analyse-nodetype-context
,ecb-analyse-nodetype-arguments
,ecb-analyse-nodetype-completions
,ecb-analyse-nodetype-localvars
,ecb-analyse-nodetype-prefix
,ecb-analyse-nodetype-assignee
,ecb-analyse-nodetype-function
,ecb-analyse-nodetype-function-arg)))))
(defun ecb-analyse-gen-menu-title-creator ()
"Returns a menu-title-create-function for the nodetypes of the
analyse-buffer."
(mapcar (function (lambda (nodetype)
(cons nodetype
(function (lambda (node)
(tree-node->name node))))))
`(,ecb-analyse-nodetype-context
,ecb-analyse-nodetype-arguments
,ecb-analyse-nodetype-completions
,ecb-analyse-nodetype-localvars
,ecb-analyse-nodetype-prefix
,ecb-analyse-nodetype-assignee
,ecb-analyse-nodetype-function
,ecb-analyse-nodetype-function-arg)))
(defecb-tree-buffer-creator ecb-create-analyse-tree-buffer ecb-analyse-buffer-name
"Create the tree-buffer for analyse-display."
(tree-buffer-create
ecb-analyse-buffer-name
:frame ecb-frame
:mouse-action-trigger ecb-tree-mouse-action-trigger
:is-click-valid-fn 'ecb-interpret-mouse-click
:node-selected-fn 'ecb-tree-buffer-node-select-callback
:node-expanded-fn 'ecb-tree-buffer-node-expand-callback
:node-collapsed-fn 'ecb-tree-buffer-node-collapsed-callback
:node-mouse-over-fn 'ecb-mouse-over-analyse-node
:mouse-highlight-fn 'ecb-analyse-node-mouse-highlighted-p
:node-data-equal-fn 'ecb-analyse-compare-node-data
:maybe-empty-node-types nil
:leaf-node-types nil
:menu-creator 'ecb-analyse-menu-creator
:menu-titles (ecb-analyse-gen-menu-title-creator)
:modeline-menu-creator 'ecb-common-tree-buffer-modeline-menu-creator
:sticky-parent-p ecb-tree-make-parent-node-sticky
:sticky-indent-string ecb-tree-stickynode-indent-string
:sticky-parent-fn nil
:trunc-lines (ecb-member-of-symbol/value-list ecb-analyse-buffer-name
ecb-tree-truncate-lines)
:read-only t
:tree-indent ecb-tree-indent
:incr-search-p nil ;; ecb-tree-incremental-search
:incr-search-additional-pattern nil ;; ecb-methods-incr-searchpattern-node-prefix
:arrow-navigation ecb-tree-navigation-by-arrow
:hor-scroll-step ecb-tree-easy-hor-scroll
:default-images-dir (car ecb-tree-image-icons-directories)
:additional-images-dir (ecb-member-of-symbol/value-list ecb-analyse-buffer-name
(cdr ecb-tree-image-icons-directories)
'car 'cdr)
:image-file-prefix "ecb-"
:tree-style ecb-tree-buffer-style
:ascii-guide-face ecb-tree-guide-line-face
:type-facer nil
:expand-symbol-before-p ecb-tree-expand-symbol-before
:highlight-node-face ecb-analyse-face
:general-face ecb-analyse-general-face
:after-create-hook (append
(list (function (lambda ()
(ecb-common-after-tree-buffer-create-actions))))
ecb-common-tree-buffer-after-create-hook
ecb-analyse-buffer-after-create-hook)
:after-update-hook nil))
(silentcomp-provide 'ecb-analyse)
;;; ecb-anaylse.el ends here